diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 1c4a448cee..e85541a55d 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -25,16 +25,7 @@
return list("title" = title, "message" = message)
/datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
- for (var/obj/machinery/computer/communications/C in machines)
- if(! (C.stat & (BROKEN|NOPOWER) ) )
- var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc )
- P.name = "'[command_name()] Update.'"
- P.info = replacetext(args["message"], "\n", "
")
- P.update_space(P.info)
- P.update_icon()
- C.messagetitle.Add(args["title"])
- C.messagetext.Add(P.info)
-
+ post_comm_message(args["title"], replacetext(args["message"], "\n", "
"))
command_announcement.Announce(args["message"], args["title"])
return 1
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 4ee64999fa..b49c41f30f 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -180,7 +180,7 @@
/proc/get_access_by_id(id)
var/list/AS = get_all_access_datums_by_id()
- return AS[id]
+ return AS["[id]"]
/proc/get_all_jobs()
var/list/all_jobs = list()
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 7833a58d72..0f52e67b8c 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -26,7 +26,7 @@
var/list/formatted = list()
for(var/job in jobs)
formatted.Add(list(list(
- "display_name" = replacetext(job, " ", " "),
+ "display_name" = replacetext(job, " ", " "),
"target_rank" = get_target_rank(),
"job" = job)))
@@ -68,7 +68,7 @@
id_card.forceMove(src)
modify = id_card
- SSnanoui.update_uis(src)
+ SStgui.update_uis(src)
attack_hand(user)
/obj/machinery/computer/card/attack_ai(var/mob/user as mob)
@@ -77,20 +77,27 @@
/obj/machinery/computer/card/attack_hand(mob/user as mob)
if(..()) return
if(stat & (NOPOWER|BROKEN)) return
- ui_interact(user)
+ tgui_interact(user)
-/obj/machinery/computer/card/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1)
- user.set_machine(src)
+/obj/machinery/computer/card/tgui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "IdentificationComputer", name)
+ ui.open()
+/obj/machinery/computer/card/tgui_static_data(mob/user)
+ var/list/data = ..()
if(data_core)
data_core.get_manifest_list()
+ data["manifest"] = PDA_Manifest
+ return data
+
+/obj/machinery/computer/card/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
+ var/list/data = ..()
- var/data[0]
- data["src"] = "\ref[src]"
data["station_name"] = station_name()
data["mode"] = mode
data["printing"] = printing
- data["manifest"] = PDA_Manifest
data["target_name"] = modify ? modify.name : "-----"
data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----"
data["target_rank"] = get_target_rank()
@@ -110,27 +117,27 @@
continue
if(dept.centcom_only && !is_centcom())
continue
- departments[++departments.len] = list("department_name" = dept.name, "jobs" = format_jobs(SSjob.get_job_titles_in_department(dept.name)) )
-
+ departments.Add(list(list(
+ "department_name" = dept.name,
+ "jobs" = format_jobs(SSjob.get_job_titles_in_department(dept.name))
+ )))
data["departments"] = departments
- if (modify && is_centcom())
- var/list/all_centcom_access = list()
+ var/list/all_centcom_access = list()
+ var/list/regions = list()
+ if(modify && is_centcom())
for(var/access in get_all_centcom_access())
all_centcom_access.Add(list(list(
- "desc" = replacetext(get_centcom_access_desc(access), " ", " "),
+ "desc" = replacetext(get_centcom_access_desc(access), " ", " "),
"ref" = access,
"allowed" = (access in modify.access) ? 1 : 0)))
-
- data["all_centcom_access"] = all_centcom_access
- else if (modify)
- var/list/regions = list()
- for(var/i = 1; i <= 7; i++)
+ else if(modify)
+ for(var/i in ACCESS_REGION_SECURITY to ACCESS_REGION_SUPPLY)
var/list/accesses = list()
for(var/access in get_region_accesses(i))
if (get_access_desc(access))
accesses.Add(list(list(
- "desc" = replacetext(get_access_desc(access), " ", " "),
+ "desc" = replacetext(get_access_desc(access), " ", " "),
"ref" = access,
"allowed" = (access in modify.access) ? 1 : 0)))
@@ -138,23 +145,20 @@
"name" = get_region_accesses_name(i),
"accesses" = accesses)))
- data["regions"] = regions
+ data["regions"] = regions
+ data["all_centcom_access"] = all_centcom_access
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "identification_computer.tmpl", src.name, 600, 700)
- ui.set_initial_data(data)
- ui.open()
+ return data
-/obj/machinery/computer/card/Topic(href, href_list)
+/obj/machinery/computer/card/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
- return 1
+ return TRUE
- switch(href_list["choice"])
- if ("modify")
- if (modify)
+ switch(action)
+ if("modify")
+ if(modify)
data_core.manifest_modify(modify.registered_name, modify.assignment)
- modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])")
+ modify.name = "[modify.registered_name]'s ID Card ([modify.assignment])"
if(ishuman(usr))
modify.forceMove(get_turf(src))
if(!usr.get_active_hand())
@@ -165,12 +169,13 @@
modify = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
+ if(istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.forceMove(src)
modify = I
+ . = TRUE
- if ("scan")
- if (scan)
+ if("scan")
+ if(scan)
if(ishuman(usr))
scan.forceMove(get_turf(src))
if(!usr.get_active_hand())
@@ -181,25 +186,26 @@
scan = null
else
var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/weapon/card/id))
+ if(istype(I, /obj/item/weapon/card/id))
usr.drop_item()
I.forceMove(src)
scan = I
+ . = TRUE
if("access")
- if(href_list["allowed"])
- if(is_authenticated())
- var/access_type = text2num(href_list["access_target"])
- var/access_allowed = text2num(href_list["allowed"])
- if(access_type in (is_centcom() ? get_all_centcom_access() : get_all_station_access()))
- modify.access -= access_type
- if(!access_allowed)
- modify.access += access_type
- modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
+ if(is_authenticated())
+ var/access_type = text2num(params["access_target"])
+ var/access_allowed = text2num(params["allowed"])
+ if(access_type in (is_centcom() ? get_all_centcom_access() : get_all_station_access()))
+ modify.access -= access_type
+ if(!access_allowed)
+ modify.access += access_type
+ modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
+ . = TRUE
- if ("assign")
- if (is_authenticated() && modify)
- var/t1 = href_list["assign_target"]
+ if("assign")
+ if(is_authenticated() && modify)
+ var/t1 = params["assign_target"]
if(t1 == "Custom")
var/temp_t = sanitize(input("Enter a custom job assignment.","Assignment"), 45)
//let custom jobs function as an impromptu alt title, mainly for sechuds
@@ -222,44 +228,42 @@
modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("reassign_employee", list(modify))
+ . = TRUE
- if ("reg")
- if (is_authenticated())
- var/t2 = modify
- if ((modify == t2 && (in_range(src, usr) || (istype(usr, /mob/living/silicon))) && istype(loc, /turf)))
- var/temp_name = sanitizeName(href_list["reg"])
- if(temp_name)
- modify.registered_name = temp_name
- else
- src.visible_message("[src] buzzes rudely.")
- SSnanoui.update_uis(src)
+ if("reg")
+ if(is_authenticated())
+ var/temp_name = sanitizeName(params["reg"])
+ if(temp_name)
+ modify.registered_name = temp_name
+ else
+ visible_message("[src] buzzes rudely.")
+ . = TRUE
- if ("account")
- if (is_authenticated())
- var/t2 = modify
- if ((modify == t2 && (in_range(src, usr) || (istype(usr, /mob/living/silicon))) && istype(loc, /turf)))
- var/account_num = text2num(href_list["account"])
- modify.associated_account_number = account_num
- SSnanoui.update_uis(src)
+ if("account")
+ if(is_authenticated())
+ var/account_num = text2num(params["account"])
+ modify.associated_account_number = account_num
+ . = TRUE
- if ("mode")
- mode = text2num(href_list["mode_target"])
+ if("mode")
+ mode = text2num(params["mode_target"])
+ . = TRUE
- if ("print")
- if (!printing)
+ if("print")
+ if(!printing)
printing = 1
spawn(50)
printing = null
- SSnanoui.update_uis(src)
+ SStgui.update_uis(src)
var/obj/item/weapon/paper/P = new(loc)
- if (mode)
+ if(mode)
P.name = text("crew manifest ([])", stationtime2text())
P.info = {"
Crew Manifest
[data_core ? data_core.get_manifest(0) : ""]
"}
- else if (modify)
+ else if(modify)
P.name = "access report"
P.info = {"Access Report
Prepared By: [scan.registered_name ? scan.registered_name : "Unknown"]
@@ -273,19 +277,20 @@
for(var/A in modify.access)
P.info += " [get_access_desc(A)]"
+ . = TRUE
- if ("terminate")
- if (is_authenticated())
+ if("terminate")
+ if(is_authenticated())
modify.assignment = "Dismissed" //VOREStation Edit: setting adjustment
modify.access = list()
modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("terminate_employee", list(modify))
- if (modify)
- modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])")
+ . = TRUE
- return 1
+ if(modify)
+ modify.name = "[modify.registered_name]'s ID Card ([modify.assignment])"
/obj/machinery/computer/card/centcom
name = "\improper CentCom ID card modification console"
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 9333e32556..e878aaaf8a 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -9,553 +9,24 @@
light_color = "#0099ff"
req_access = list(access_heads)
circuit = /obj/item/weapon/circuitboard/communications
- var/prints_intercept = 1
- var/authenticated = 0
- var/list/messagetitle = list()
- var/list/messagetext = list()
- var/currmsg = 0
- var/aicurrmsg = 0
- var/state = STATE_DEFAULT
- var/aistate = STATE_DEFAULT
- var/message_cooldown = 0
- var/centcomm_message_cooldown = 0
- var/tmp_alertlevel = 0
- var/const/STATE_DEFAULT = 1
- var/const/STATE_CALLSHUTTLE = 2
- var/const/STATE_CANCELSHUTTLE = 3
- var/const/STATE_MESSAGELIST = 4
- var/const/STATE_VIEWMESSAGE = 5
- var/const/STATE_DELMESSAGE = 6
- var/const/STATE_STATUSDISPLAY = 7
- var/const/STATE_ALERT_LEVEL = 8
- var/const/STATE_CONFIRM_LEVEL = 9
- var/const/STATE_CREWTRANSFER = 10
- var/status_display_freq = "1435"
- var/stat_msg1
- var/stat_msg2
+ var/datum/tgui_module/communications/communications
- var/datum/lore/atc_controller/ATC
- var/datum/announcement/priority/crew_announcement = new
-
-/obj/machinery/computer/communications/New()
- ..()
- ATC = atc
- crew_announcement.newscast = 1
-
-/obj/machinery/computer/communications/process()
- if(..())
- if(state != STATE_STATUSDISPLAY)
- src.updateDialog()
-
-
-/obj/machinery/computer/communications/Topic(href, href_list)
- if(..())
- return 1
- if (using_map && !(src.z in using_map.contact_levels))
- to_chat(usr, "Unable to establish a connection: You're too far away from the station!")
- return
- usr.set_machine(src)
-
- if(!href_list["operation"])
- return
- switch(href_list["operation"])
- // main interface
- if("main")
- src.state = STATE_DEFAULT
- if("login")
- var/mob/M = usr
- var/obj/item/weapon/card/id/I = M.GetIdCard()
- if (I && istype(I))
- if(src.check_access(I))
- authenticated = 1
- if(access_captain in I.access)
- authenticated = 2
- crew_announcement.announcer = GetNameAndAssignmentFromId(I)
- if("logout")
- authenticated = 0
- crew_announcement.announcer = ""
-
- if("swipeidseclevel")
- if(src.authenticated) //Let heads change the alert level.
- var/old_level = security_level
- if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN
- if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this
- set_security_level(tmp_alertlevel)
- if(security_level != old_level)
- //Only notify the admins if an actual change happened
- log_game("[key_name(usr)] has changed the security level to [get_security_level()].")
- message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
- switch(security_level)
- if(SEC_LEVEL_GREEN)
- feedback_inc("alert_comms_green",1)
- if(SEC_LEVEL_YELLOW)
- feedback_inc("alert_comms_yellow",1)
- if(SEC_LEVEL_VIOLET)
- feedback_inc("alert_comms_violet",1)
- if(SEC_LEVEL_ORANGE)
- feedback_inc("alert_comms_orange",1)
- if(SEC_LEVEL_BLUE)
- feedback_inc("alert_comms_blue",1)
- tmp_alertlevel = 0
- state = STATE_DEFAULT
-
- if("announce")
- if(src.authenticated==2)
- if(message_cooldown)
- to_chat(usr, "Please allow at least one minute to pass between announcements")
- return
- var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message
- if(!input || !(usr in view(1,src)))
- return
- crew_announcement.Announce(input)
- message_cooldown = 1
- spawn(600)//One minute cooldown
- message_cooldown = 0
-
- if("callshuttle")
- src.state = STATE_DEFAULT
- if(src.authenticated)
- src.state = STATE_CALLSHUTTLE
- if("callshuttle2")
- if(src.authenticated)
- call_shuttle_proc(usr)
- if(emergency_shuttle.online())
- post_status("shuttle")
- src.state = STATE_DEFAULT
- if("cancelshuttle")
- src.state = STATE_DEFAULT
- if(src.authenticated)
- src.state = STATE_CANCELSHUTTLE
- if("cancelshuttle2")
- if(src.authenticated)
- cancel_call_proc(usr)
- src.state = STATE_DEFAULT
- if("messagelist")
- src.currmsg = 0
- src.state = STATE_MESSAGELIST
- if("toggleatc")
- src.ATC.squelched = !src.ATC.squelched
- if("viewmessage")
- src.state = STATE_VIEWMESSAGE
- if (!src.currmsg)
- if(href_list["message-num"])
- src.currmsg = text2num(href_list["message-num"])
- else
- src.state = STATE_MESSAGELIST
- if("delmessage")
- src.state = (src.currmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST
- if("delmessage2")
- if(src.authenticated)
- if(src.currmsg)
- var/title = src.messagetitle[src.currmsg]
- var/text = src.messagetext[src.currmsg]
- src.messagetitle.Remove(title)
- src.messagetext.Remove(text)
- if(src.currmsg == src.aicurrmsg)
- src.aicurrmsg = 0
- src.currmsg = 0
- src.state = STATE_MESSAGELIST
- else
- src.state = STATE_VIEWMESSAGE
- if("status")
- src.state = STATE_STATUSDISPLAY
-
- // Status display stuff
- if("setstat")
- switch(href_list["statdisp"])
- if("message")
- post_status("message", stat_msg1, stat_msg2)
- if("alert")
- post_status("alert", href_list["alert"])
- else
- post_status(href_list["statdisp"])
-
- if("setmsg1")
- stat_msg1 = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40), 40)
- src.updateDialog()
- if("setmsg2")
- stat_msg2 = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40), 40)
- src.updateDialog()
-
- // OMG CENTCOMM LETTERHEAD
- if("MessageCentCom")
- if(src.authenticated==2)
- if(centcomm_message_cooldown)
- to_chat(usr, "Arrays recycling. Please stand by.")
- return
- var/input = sanitize(input("Please choose a message to transmit to [using_map.boss_short] via quantum entanglement. \
- Please be aware that this process is very expensive, and abuse will lead to... termination. \
- Transmission does not guarantee a response. \
- There is a 30 second delay before you may send another message, be clear, full and concise.", "Central Command Quantum Messaging") as null|message)
- if(!input || !(usr in view(1,src)))
- return
- CentCom_announce(input, usr)
- to_chat(usr, "Message transmitted.")
- log_game("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]")
- centcomm_message_cooldown = 1
- spawn(300)//10 minute cooldown
- centcomm_message_cooldown = 0
-
-
- // OMG SYNDICATE ...LETTERHEAD
- if("MessageSyndicate")
- if((src.authenticated==2) && (src.emagged))
- if(centcomm_message_cooldown)
- to_chat(usr, "Arrays recycling. Please stand by.")
- return
- var/input = sanitize(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. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", ""))
- if(!input || !(usr in view(1,src)))
- return
- Syndicate_announce(input, usr)
- to_chat(usr, "Message transmitted.")
- log_game("[key_name(usr)] has made an illegal announcement: [input]")
- centcomm_message_cooldown = 1
- spawn(300)//10 minute cooldown
- centcomm_message_cooldown = 0
-
- if("RestoreBackup")
- to_chat(usr, "Backup routing data restored!")
- src.emagged = 0
- src.updateDialog()
-
-
-
- // AI interface
- if("ai-main")
- src.aicurrmsg = 0
- src.aistate = STATE_DEFAULT
- if("ai-callshuttle")
- src.aistate = STATE_CALLSHUTTLE
- if("ai-callshuttle2")
- call_shuttle_proc(usr)
- src.aistate = STATE_DEFAULT
- if("ai-messagelist")
- src.aicurrmsg = 0
- src.aistate = STATE_MESSAGELIST
- if("ai-viewmessage")
- src.aistate = STATE_VIEWMESSAGE
- if (!src.aicurrmsg)
- if(href_list["message-num"])
- src.aicurrmsg = text2num(href_list["message-num"])
- else
- src.aistate = STATE_MESSAGELIST
- if("ai-delmessage")
- src.aistate = (src.aicurrmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST
- if("ai-delmessage2")
- if(src.aicurrmsg)
- var/title = src.messagetitle[src.aicurrmsg]
- var/text = src.messagetext[src.aicurrmsg]
- src.messagetitle.Remove(title)
- src.messagetext.Remove(text)
- if(src.currmsg == src.aicurrmsg)
- src.currmsg = 0
- src.aicurrmsg = 0
- src.aistate = STATE_MESSAGELIST
- if("ai-status")
- src.aistate = STATE_STATUSDISPLAY
-
- if("securitylevel")
- src.tmp_alertlevel = text2num( href_list["newalertlevel"] )
- if(!tmp_alertlevel) tmp_alertlevel = 0
- state = STATE_CONFIRM_LEVEL
-
- if("changeseclevel")
- state = STATE_ALERT_LEVEL
-
-
-
- src.updateUsrDialog()
+/obj/machinery/computer/communications/Initialize()
+ . = ..()
+ communications = new(src)
/obj/machinery/computer/communications/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- src.emagged = 1
+ emagged = TRUE
+ communications.emagged = TRUE
to_chat(user, "You scramble the communication routing circuits!")
- return 1
+ return TRUE
-/obj/machinery/computer/communications/attack_ai(var/mob/user as mob)
- return src.attack_hand(user)
+/obj/machinery/computer/communications/attack_ai(mob/user)
+ return attack_hand(user)
-/obj/machinery/computer/communications/attack_hand(var/mob/user as mob)
+/obj/machinery/computer/communications/attack_hand(mob/user)
if(..())
return
- if (using_map && !(src.z in using_map.contact_levels))
- to_chat(user, "Unable to establish a connection: You're too far away from the station!")
- return
-
- user.set_machine(src)
- var/dat = "Communications Console"
- if (emergency_shuttle.has_eta())
- var/timeleft = emergency_shuttle.estimate_arrival_time()
- dat += "Emergency shuttle\n
\nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]
"
-
- if (istype(user, /mob/living/silicon))
- var/dat2 = src.interact_ai(user) // give the AI a different interact proc to limit its access
- if(dat2)
- dat += dat2
- user << browse(dat, "window=communications;size=400x500")
- onclose(user, "communications")
- return
-
- switch(src.state)
- if(STATE_DEFAULT)
- if (src.authenticated)
- dat += "
\[ Log Out \]"
- if (src.authenticated==2)
- dat += "
\[ Make An Announcement \]"
- if(src.emagged == 0)
- dat += "
\[ Send an emergency message to [using_map.boss_short] \]"
- else
- dat += "
\[ Send an emergency message to \[UNKNOWN\] \]"
- dat += "
\[ Restore Backup Routing Data \]"
-
- dat += "
\[ Change alert level \]"
- if(emergency_shuttle.location())
- if (emergency_shuttle.online())
- dat += "
\[ Cancel Shuttle Call \]"
- else
- dat += "
\[ Call Emergency Shuttle \]"
-
- dat += "
\[ Set Status Display \]"
- else
- dat += "
\[ Log In \]"
- dat += "
\[ Message List \]"
- dat += "
\[ [ATC.squelched ? "Enable" : "Disable"] ATC Relay \]"
- if(STATE_CALLSHUTTLE)
- dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]"
- if(STATE_CANCELSHUTTLE)
- dat += "Are you sure you want to cancel the shuttle? \[ OK | Cancel \]"
- if(STATE_MESSAGELIST)
- dat += "Messages:"
- for(var/i = 1; i<=src.messagetitle.len; i++)
- dat += "
[src.messagetitle[i]]"
- if(STATE_VIEWMESSAGE)
- if (src.currmsg)
- dat += "[src.messagetitle[src.currmsg]]
[src.messagetext[src.currmsg]]"
- if (src.authenticated)
- dat += "
\[ Delete \]"
- else
- src.state = STATE_MESSAGELIST
- src.attack_hand(user)
- return
- if(STATE_DELMESSAGE)
- if (src.currmsg)
- dat += "Are you sure you want to delete this message? \[ OK | Cancel \]"
- else
- src.state = STATE_MESSAGELIST
- src.attack_hand(user)
- return
- if(STATE_STATUSDISPLAY)
- dat += "Set Status Displays
"
- dat += "\[ Clear \]
"
- dat += "\[ Station Time \]
"
- dat += "\[ Shuttle ETA \]
"
- dat += "\[ Message \]"
- dat += "
"
- dat += "\[ Alert: None |"
- dat += " Red Alert |"
- dat += " Lockdown |"
- dat += " Biohazard \]
"
- if(STATE_ALERT_LEVEL)
- dat += "Current alert level: [get_security_level()]
"
- if(security_level == SEC_LEVEL_DELTA)
- dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate."
- else
- dat += "Blue
"
- dat += "Orange
"
- dat += "Violet
"
- dat += "Yellow
"
- dat += "Green"
- if(STATE_CONFIRM_LEVEL)
- dat += "Current alert level: [get_security_level()]
"
- dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]
"
- dat += "OK to confirm change.
"
-
- dat += "
\[ [(src.state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]"
- user << browse(dat, "window=communications;size=400x500")
- onclose(user, "communications")
-
-
-
-
-/obj/machinery/computer/communications/proc/interact_ai(var/mob/living/silicon/ai/user as mob)
- var/dat = ""
- switch(src.aistate)
- if(STATE_DEFAULT)
- if(emergency_shuttle.location() && !emergency_shuttle.online())
- dat += "
\[ Call Emergency Shuttle \]"
- dat += "
\[ Message List \]"
- dat += "
\[ Set Status Display \]"
- dat += "
\[ [ATC.squelched ? "Enable" : "Disable"] ATC Relay \]"
- if(STATE_CALLSHUTTLE)
- dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]"
- if(STATE_MESSAGELIST)
- dat += "Messages:"
- for(var/i = 1; i<=src.messagetitle.len; i++)
- dat += "
[src.messagetitle[i]]"
- if(STATE_VIEWMESSAGE)
- if (src.aicurrmsg)
- dat += "[src.messagetitle[src.aicurrmsg]]
[src.messagetext[src.aicurrmsg]]"
- dat += "
\[ Delete \]"
- else
- src.aistate = STATE_MESSAGELIST
- src.attack_hand(user)
- return null
- if(STATE_DELMESSAGE)
- if(src.aicurrmsg)
- dat += "Are you sure you want to delete this message? \[ OK | Cancel \]"
- else
- src.aistate = STATE_MESSAGELIST
- src.attack_hand(user)
- return
-
- if(STATE_STATUSDISPLAY)
- dat += "Set Status Displays
"
- dat += "\[ Clear \]
"
- dat += "\[ Station Time \]
"
- dat += "\[ Shuttle ETA \]
"
- dat += "\[ Message \]"
- dat += "
"
- dat += "\[ Alert: None |"
- dat += " Red Alert |"
- dat += " Lockdown |"
- dat += " Biohazard \]
"
-
-
- dat += "
\[ [(src.aistate != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]"
- return dat
-
-/proc/enable_prison_shuttle(var/mob/user)
- for(var/obj/machinery/computer/prison_shuttle/PS in machines)
- PS.allowedtocall = !(PS.allowedtocall)
-
-/proc/call_shuttle_proc(var/mob/user)
- if ((!( ticker ) || !emergency_shuttle.location()))
- return
-
- if(!universe.OnShuttleCall(usr))
- to_chat(user, "Cannot establish a bluespace connection.")
- return
-
- if(deathsquad.deployed)
- to_chat(user, "[using_map.boss_short] will not allow the shuttle to be called. Consider all contracts terminated.")
- return
-
- if(emergency_shuttle.deny_shuttle)
- to_chat(user, "The emergency shuttle may not be sent at this time. Please try again later.")
- return
-
- if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE
- to_chat(user, "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again.")
- return
-
- if(emergency_shuttle.going_to_centcom())
- to_chat(user, "The emergency shuttle may not be called while returning to [using_map.boss_short].")
- return
-
- if(emergency_shuttle.online())
- to_chat(user, "The emergency shuttle is already on its way.")
- return
-
- if(ticker.mode.name == "blob")
- to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
- return
-
- emergency_shuttle.call_evac()
- log_game("[key_name(user)] has called the shuttle.")
- message_admins("[key_name_admin(user)] has called the shuttle.", 1)
- admin_chat_message(message = "Emergency evac beginning! Called by [key_name(user)]!", color = "#CC2222") //VOREStation Add
-
-
- return
-
-/proc/init_shift_change(var/mob/user, var/force = 0)
- if ((!( ticker ) || !emergency_shuttle.location()))
- return
-
- if(emergency_shuttle.going_to_centcom())
- to_chat(user, "The shuttle may not be called while returning to [using_map.boss_short].")
- return
-
- if(emergency_shuttle.online())
- to_chat(user, "The shuttle is already on its way.")
- return
-
- // if force is 0, some things may stop the shuttle call
- if(!force)
- if(emergency_shuttle.deny_shuttle)
- to_chat(user, "[using_map.boss_short] does not currently have a shuttle available in your sector. Please try again later.")
- return
-
- if(deathsquad.deployed == 1)
- to_chat(user, "[using_map.boss_short] will not allow the shuttle to be called. Consider all contracts terminated.")
- return
-
- if(world.time < 54000) // 30 minute grace period to let the game get going
- to_chat(user, "The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again.")
- return
-
- if(ticker.mode.auto_recall_shuttle)
- //New version pretends to call the shuttle but cause the shuttle to return after a random duration.
- emergency_shuttle.auto_recall = 1
-
- if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic")
- to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
- return
-
- emergency_shuttle.call_transfer()
-
- //delay events in case of an autotransfer
- if (isnull(user))
- SSevents.delay_events(EVENT_LEVEL_MODERATE, 9000) //15 minutes
- SSevents.delay_events(EVENT_LEVEL_MAJOR, 9000)
-
- log_game("[user? key_name(user) : "Autotransfer"] has called the shuttle.")
- message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1)
- admin_chat_message(message = "Autotransfer shuttle dispatched, shift ending soon.", color = "#2277BB") //VOREStation Add
-
- return
-
-/proc/cancel_call_proc(var/mob/user)
- if (!( ticker ) || !emergency_shuttle.can_recall())
- return
- if((ticker.mode.name == "blob")||(ticker.mode.name == "Meteor"))
- return
-
- if(!emergency_shuttle.going_to_centcom()) //check that shuttle isn't already heading to CentCom
- emergency_shuttle.recall()
- log_game("[key_name(user)] has recalled the shuttle.")
- message_admins("[key_name_admin(user)] has recalled the shuttle.", 1)
- return
-
-
-/proc/is_relay_online()
- for(var/obj/machinery/telecomms/relay/M in world)
- if(M.stat == 0)
- return 1
- return 0
-
-/obj/machinery/computer/communications/proc/post_status(var/command, var/data1, var/data2)
-
- var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
-
- if(!frequency) return
-
- var/datum/signal/status_signal = new
- status_signal.source = src
- status_signal.transmission_method = TRANSMISSION_RADIO
- status_signal.data["command"] = command
-
- switch(command)
- if("message")
- status_signal.data["msg1"] = data1
- status_signal.data["msg2"] = data2
- log_admin("STATUS: [src.fingerprintslast] set status screen message with [src]: [data1] [data2]")
- //message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
- if("alert")
- status_signal.data["picture_state"] = data1
-
- frequency.post_signal(src, status_signal)
+ communications.tgui_interact(user)
diff --git a/code/game/objects/items/stacks/tickets.dm b/code/game/objects/items/stacks/tickets.dm
new file mode 100644
index 0000000000..1d9cbf047e
--- /dev/null
+++ b/code/game/objects/items/stacks/tickets.dm
@@ -0,0 +1,32 @@
+/obj/item/stack/arcadeticket
+ name = "arcade tickets"
+ desc = "Wow! With enough of these, you could buy a bike! ...Pssh, yeah right."
+ singular_name = "arcade ticket"
+ icon_state = "arcade-ticket"
+ item_state = "tickets"
+ w_class = ITEMSIZE_TINY
+ max_amount = 30
+
+/obj/item/stack/arcadeticket/New(loc, amount = null)
+ . = ..()
+ update_icon()
+
+/obj/item/stack/arcadeticket/update_icon()
+ var/amount = get_amount()
+ switch(amount)
+ if(12 to INFINITY)
+ icon_state = "arcade-ticket_4"
+ if(6 to 12)
+ icon_state = "arcade-ticket_3"
+ if(2 to 6)
+ icon_state = "arcade-ticket_2"
+ else
+ icon_state = "arcade-ticket"
+
+/obj/item/stack/arcadeticket/proc/pay_tickets()
+ amount -= 2
+ if(amount == 0)
+ qdel(src)
+
+/obj/item/stack/arcadeticket/thirty
+ amount = 30
\ No newline at end of file
diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm
index 384dcbcd9b..df3e695628 100644
--- a/code/modules/asset_cache/asset_list_items.dm
+++ b/code/modules/asset_cache/asset_list_items.dm
@@ -6,36 +6,36 @@
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
)
-// /datum/asset/simple/headers
-// assets = list(
-// "alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
-// "alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
-// "batt_5.gif" = 'icons/program_icons/batt_5.gif',
-// "batt_20.gif" = 'icons/program_icons/batt_20.gif',
-// "batt_40.gif" = 'icons/program_icons/batt_40.gif',
-// "batt_60.gif" = 'icons/program_icons/batt_60.gif',
-// "batt_80.gif" = 'icons/program_icons/batt_80.gif',
-// "batt_100.gif" = 'icons/program_icons/batt_100.gif',
-// "charging.gif" = 'icons/program_icons/charging.gif',
-// "downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
-// "downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
-// "ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
-// "ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
-// "power_norm.gif" = 'icons/program_icons/power_norm.gif',
-// "power_warn.gif" = 'icons/program_icons/power_warn.gif',
-// "sig_high.gif" = 'icons/program_icons/sig_high.gif',
-// "sig_low.gif" = 'icons/program_icons/sig_low.gif',
-// "sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
-// "sig_none.gif" = 'icons/program_icons/sig_none.gif',
-// "smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
-// "smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
-// "smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
-// "smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
-// "smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
-// "smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
-// "smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
-// "borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
-// )
+/datum/asset/simple/headers
+ assets = list(
+ "alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
+ "alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
+ "batt_5.gif" = 'icons/program_icons/batt_5.gif',
+ "batt_20.gif" = 'icons/program_icons/batt_20.gif',
+ "batt_40.gif" = 'icons/program_icons/batt_40.gif',
+ "batt_60.gif" = 'icons/program_icons/batt_60.gif',
+ "batt_80.gif" = 'icons/program_icons/batt_80.gif',
+ "batt_100.gif" = 'icons/program_icons/batt_100.gif',
+ "charging.gif" = 'icons/program_icons/charging.gif',
+ "downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
+ "downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
+ "ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
+ "ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
+ "power_norm.gif" = 'icons/program_icons/power_norm.gif',
+ "power_warn.gif" = 'icons/program_icons/power_warn.gif',
+ "sig_high.gif" = 'icons/program_icons/sig_high.gif',
+ "sig_low.gif" = 'icons/program_icons/sig_low.gif',
+ "sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
+ "sig_none.gif" = 'icons/program_icons/sig_none.gif',
+ "smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
+ "smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
+ "smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
+ "smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
+ "smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
+ "smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
+ "smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
+ // "borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
+ )
// /datum/asset/simple/radar_assets
// assets = list(
@@ -206,15 +206,15 @@
// "none_button.png" = 'html/none_button.png',
// )
-// /datum/asset/simple/arcade
-// assets = list(
-// "boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
-// "boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
-// "boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
-// "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
-// "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
-// "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
-// )
+/datum/asset/simple/arcade
+ assets = list(
+ "boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
+ "boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
+ "boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
+ "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
+ "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
+ "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
+ )
// /datum/asset/spritesheet/simple/achievements
// name ="achievements"
diff --git a/code/modules/events/supply_demand_vr.dm b/code/modules/events/supply_demand_vr.dm
index 6c59145fe5..6447630c9e 100644
--- a/code/modules/events/supply_demand_vr.dm
+++ b/code/modules/events/supply_demand_vr.dm
@@ -84,17 +84,9 @@
var/datum/supply_demand_order/random = pick(required_items)
command_announcement.Announce("What happened? Accounting is here right now and they're already asking where that [random.name] is. Damn, I gotta go", my_department)
var/message = "The delivery deadline was reached with the following needs outstanding:
"
- for (var/datum/supply_demand_order/req in required_items)
+ for(var/datum/supply_demand_order/req in required_items)
message += req.describe() + "
"
- for (var/obj/machinery/computer/communications/C in machines)
- if(C.operable())
- var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc )
- P.name = "'[my_department] Mission Summary'"
- P.info = message
- P.update_space(P.info)
- P.update_icon()
- C.messagetitle.Add("[my_department] Mission Summary")
- C.messagetext.Add(P.info)
+ post_comm_message("'[my_department] Mission Summary'", message)
/**
* Event Handler for responding to the supply shuttle arriving at centcom.
*/
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 60966f6da2..4ee1d8935c 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -399,9 +399,7 @@ var/list/ai_verbs_default = list(
// hack to display shuttle timer
if(emergency_shuttle.online())
- var/obj/machinery/computer/communications/C = locate() in machines
- if(C)
- C.post_status("shuttle")
+ post_status(src, "shuttle", user = src)
/mob/living/silicon/ai/proc/ai_recall_shuttle()
set category = "AI Commands"
diff --git a/code/modules/modular_computers/NTNet/NTNet.dm b/code/modules/modular_computers/NTNet/NTNet.dm
index 8370683522..6479f92a21 100644
--- a/code/modules/modular_computers/NTNet/NTNet.dm
+++ b/code/modules/modular_computers/NTNet/NTNet.dm
@@ -181,5 +181,8 @@ var/global/datum/ntnet/ntnet_global = new()
return 1
return 0
-
+/datum/ntnet/proc/get_chat_channel_by_id(id)
+ for(var/datum/ntnet_conversation/chan in chat_channels)
+ if(chan.id == id)
+ return chan
diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm
index 97b4cfe851..a2749836aa 100644
--- a/code/modules/modular_computers/computers/modular_computer/core.dm
+++ b/code/modules/modular_computers/computers/modular_computer/core.dm
@@ -119,7 +119,7 @@
active_program = null
var/mob/user = usr
if(user && istype(user))
- ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
+ tgui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
update_icon()
// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on)
@@ -154,7 +154,7 @@
run_program(autorun.stored_data)
if(user)
- ui_interact(user)
+ tgui_interact(user)
/obj/item/modular_computer/proc/minimize_program(mob/user)
if(!active_program || !processor_unit)
@@ -162,12 +162,11 @@
idle_threads.Add(active_program)
active_program.program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs
- SSnanoui.close_uis(active_program.NM ? active_program.NM : active_program)
SStgui.close_uis(active_program.TM ? active_program.TM : active_program)
active_program = null
update_icon()
if(istype(user))
- ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
+ tgui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
/obj/item/modular_computer/proc/run_program(prog)
@@ -207,12 +206,12 @@
return 1
/obj/item/modular_computer/proc/update_uis()
- if(active_program) //Should we update program ui or computer ui?
- SSnanoui.update_uis(active_program)
- if(active_program.NM)
- SSnanoui.update_uis(active_program.NM)
+ if(active_program)
+ SStgui.update_uis(active_program)
+ if(active_program.TM)
+ SStgui.update_uis(active_program.TM)
else
- SSnanoui.update_uis(src)
+ SStgui.update_uis(src)
/obj/item/modular_computer/proc/check_update_ui_need()
var/ui_update_needed = 0
diff --git a/code/modules/modular_computers/computers/modular_computer/interaction.dm b/code/modules/modular_computers/computers/modular_computer/interaction.dm
index c9ee11a77e..24c02c1add 100644
--- a/code/modules/modular_computers/computers/modular_computer/interaction.dm
+++ b/code/modules/modular_computers/computers/modular_computer/interaction.dm
@@ -99,7 +99,7 @@
/obj/item/modular_computer/attack_ghost(var/mob/observer/ghost/user)
if(enabled)
- ui_interact(user)
+ tgui_interact(user)
else if(check_rights(R_ADMIN|R_EVENT, 0, user))
var/response = alert(user, "This computer is turned off. Would you like to turn it on?", "Admin Override", "Yes", "No")
if(response == "Yes")
@@ -116,7 +116,7 @@
// On-click handling. Turns on the computer if it's off and opens the GUI.
/obj/item/modular_computer/attack_self(var/mob/user)
if(enabled && screen_on)
- ui_interact(user)
+ tgui_interact(user)
else if(!enabled && screen_on)
turn_on(user)
diff --git a/code/modules/modular_computers/computers/modular_computer/ui.dm b/code/modules/modular_computers/computers/modular_computer/ui.dm
index 81081c0cb1..5166d0d777 100644
--- a/code/modules/modular_computers/computers/modular_computer/ui.dm
+++ b/code/modules/modular_computers/computers/modular_computer/ui.dm
@@ -1,5 +1,10 @@
-// Operates NanoUI
-/obj/item/modular_computer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+// Operates TGUI
+/obj/item/modular_computer/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/simple/headers)
+ )
+
+/obj/item/modular_computer/tgui_interact(mob/user, datum/tgui/ui)
if(!screen_on || !enabled)
if(ui)
ui.close()
@@ -13,7 +18,7 @@
if(active_program)
if(ui) // This is the main laptop screen. Since we are switching to program's UI close it for now.
ui.close()
- active_program.ui_interact(user)
+ active_program.tgui_interact(user)
return
// We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it.
@@ -22,80 +27,100 @@
visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.")
return // No HDD, No HDD files list or no stored files. Something is very broken.
- var/datum/computer_file/data/autorun = hard_drive.find_file_by_name("autorun")
-
- var/list/data = get_header_data()
-
- var/list/programs = list()
- for(var/datum/computer_file/program/P in hard_drive.stored_files)
- var/list/program = list()
- program["name"] = P.filename
- program["desc"] = P.filedesc
- program["icon"] = P.program_menu_icon
- program["autorun"] = (istype(autorun) && (autorun.stored_data == P.filename)) ? 1 : 0
- if(P in idle_threads)
- program["running"] = 1
- programs.Add(list(program))
-
- data["programs"] = programs
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "laptop_mainscreen.tmpl", "NTOS Main Menu", 400, 500)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "NtosMain")
+ ui.set_autoupdate(TRUE)
ui.open()
- ui.set_auto_update(1)
+
+/obj/item/modular_computer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
+ var/list/data = get_header_data()
+ data["device_theme"] = device_theme
+
+ data["login"] = list()
+ var/obj/item/weapon/computer_hardware/card_slot/cardholder = card_slot
+ if(cardholder)
+ var/obj/item/weapon/card/id/stored_card = cardholder.stored_card
+ if(stored_card)
+ var/stored_name = stored_card.registered_name
+ var/stored_title = stored_card.assignment
+ if(!stored_name)
+ stored_name = "Unknown"
+ if(!stored_title)
+ stored_title = "Unknown"
+ data["login"] = list(
+ IDName = stored_name,
+ IDJob = stored_title,
+ )
+
+ data["removable_media"] = list()
+
+ var/datum/computer_file/data/autorun = hard_drive.find_file_by_name("autorun")
+ data["programs"] = list()
+ for(var/datum/computer_file/program/P in hard_drive.stored_files)
+ var/running = FALSE
+ if(P in idle_threads)
+ running = TRUE
+
+ data["programs"] += list(list(
+ "name" = P.filename,
+ "desc" = P.filedesc,
+ "icon" = P.program_menu_icon,
+ "running" = running,
+ "autorun" = (istype(autorun) && (autorun.stored_data == P.filename)) ? 1 : 0
+ ))
+
+ data["has_light"] = FALSE // has_light
+ data["light_on"] = FALSE // light_on
+ data["comp_light_color"] = null // comp_light_color
+
+ return data
// Handles user's GUI input
-/obj/item/modular_computer/Topic(href, href_list)
+/obj/item/modular_computer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
- return 1
- if( href_list["PC_exit"] )
- kill_program()
- return 1
- if( href_list["PC_enable_component"] )
- var/obj/item/weapon/computer_hardware/H = find_hardware_by_name(href_list["PC_enable_component"])
- if(H && istype(H) && !H.enabled)
- H.enabled = 1
- . = 1
- if( href_list["PC_disable_component"] )
- var/obj/item/weapon/computer_hardware/H = find_hardware_by_name(href_list["PC_disable_component"])
- if(H && istype(H) && H.enabled)
- H.enabled = 0
- . = 1
- if( href_list["PC_shutdown"] )
- shutdown_computer()
- return 1
- if( href_list["PC_minimize"] )
- var/mob/user = usr
- minimize_program(user)
+ return TRUE
+
+ switch(action)
+ if("PC_exit")
+ kill_program()
+ return TRUE
+ if("PC_shutdown")
+ shutdown_computer()
+ return TRUE
+ if("PC_minimize")
+ var/mob/user = usr
+ minimize_program(user)
+ if("PC_killprogram")
+ var/prog = params["name"]
+ var/datum/computer_file/program/P = null
+ var/mob/user = usr
+ if(hard_drive)
+ P = hard_drive.find_file_by_name(prog)
- if( href_list["PC_killprogram"] )
- var/prog = href_list["PC_killprogram"]
- var/datum/computer_file/program/P = null
- var/mob/user = usr
- if(hard_drive)
- P = hard_drive.find_file_by_name(prog)
+ if(!istype(P) || P.program_state == PROGRAM_STATE_KILLED)
+ return
- if(!istype(P) || P.program_state == PROGRAM_STATE_KILLED)
+ P.kill_program(1)
+ to_chat(user, "Program [P.filename].[P.filetype] with PID [rand(100,999)] has been killed.")
+ return TRUE
+ if("PC_runprogram")
+ return run_program(params["name"])
+ if("PC_setautorun")
+ if(!hard_drive)
+ return
+ set_autorun(params["name"])
+ return TRUE
+ if("PC_Eject_Disk")
+ var/param = params["name"]
+ switch(param)
+ if("ID")
+ proc_eject_id(usr)
+ return TRUE
+ else
return
- P.kill_program(1)
- update_uis()
- to_chat(user, "Program [P.filename].[P.filetype] with PID [rand(100,999)] has been killed.")
-
- if( href_list["PC_runprogram"] )
- return run_program(href_list["PC_runprogram"])
-
- if( href_list["PC_setautorun"] )
- if(!hard_drive)
- return
- set_autorun(href_list["PC_setautorun"])
-
- if(.)
- update_uis()
-
-// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
+// Function used by TGUI's to obtain data for header. All relevant entries begin with "PC_"
/obj/item/modular_computer/proc/get_header_data()
var/list/data = list()
@@ -152,4 +177,4 @@
data["PC_stationtime"] = stationtime2text()
data["PC_hasheader"] = 1
data["PC_showexitprogram"] = active_program ? 1 : 0 // Hides "Exit Program" button on mainscreen
- return data
\ No newline at end of file
+ return data
diff --git a/code/modules/modular_computers/computers/modular_computer/variables.dm b/code/modules/modular_computers/computers/modular_computer/variables.dm
index 8a1641a125..d89a82a0f3 100644
--- a/code/modules/modular_computers/computers/modular_computer/variables.dm
+++ b/code/modules/modular_computers/computers/modular_computer/variables.dm
@@ -6,6 +6,7 @@
var/enabled = 0 // Whether the computer is turned on.
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
+ var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
var/hardware_flag = 0 // A flag that describes this device type
var/last_power_usage = 0 // Last tick power usage of this computer
diff --git a/code/modules/modular_computers/file_system/news_article.dm b/code/modules/modular_computers/file_system/news_article.dm
index 833ba382e9..dffb978383 100644
--- a/code/modules/modular_computers/file_system/news_article.dm
+++ b/code/modules/modular_computers/file_system/news_article.dm
@@ -17,7 +17,7 @@
// NEWS DEFINITIONS BELOW THIS LINE
-/* KEPT HERE AS AN EXAMPLE
+/*
/datum/computer_file/data/news_article/space/vol_one
filename = "SPACE Magazine vol. 1"
server_file_path = 'news_articles/space_magazine_1.html'
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 08589fb13c..8bc12174bf 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -5,9 +5,6 @@
var/required_access = null // List of required accesses to run/download the program.
var/requires_access_to_run = 1 // Whether the program checks for required_access when run.
var/requires_access_to_download = 1 // Whether the program checks for required_access when downloading.
- // NanoModule
- var/datum/nano_module/NM = null // If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement ui_interact.
- var/nanomodule_path = null // Path to nanomodule, make sure to set this if implementing new program.
// TGUIModule
var/datum/tgui_module/TM = null // If the program uses TGUIModule, put it here and it will be automagically opened. Otherwise implement tgui_interact.
var/tguimodule_path = null // Path to tguimodule, make sure to set this if implementing new program.
@@ -29,6 +26,8 @@
var/computer_emagged = 0 // Set to 1 if computer that's running us was emagged. Computer updates this every Process() tick
var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /nano/images/status_icons. Be careful not to use too large images!
var/ntnet_speed = 0 // GQ/s - current network connectivity transfer rate
+ /// Name of the tgui interface
+ var/tgui_id
/datum/computer_file/program/New(var/obj/item/modular_computer/comp = null)
..()
@@ -39,16 +38,12 @@
computer = null
. = ..()
-/datum/computer_file/program/nano_host()
- return computer.nano_host()
-
/datum/computer_file/program/tgui_host()
return computer.tgui_host()
/datum/computer_file/program/clone()
var/datum/computer_file/program/temp = ..()
temp.required_access = required_access
- temp.nanomodule_path = nanomodule_path
temp.filedesc = filedesc
temp.program_icon_state = program_icon_state
temp.requires_ntnet = requires_ntnet
@@ -134,13 +129,9 @@
/datum/computer_file/program/proc/run_program(var/mob/living/user)
if(can_run(user, 1) || !requires_access_to_run)
computer.active_program = src
- if(nanomodule_path)
- NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src)
- NM.using_access = user.GetAccess()
if(tguimodule_path)
TM = new tguimodule_path(src)
TM.using_access = user.GetAccess()
- TM.tgui_interact(user)
if(requires_ntnet && network_destination)
generate_network_log("Connection opened to [network_destination].")
program_state = PROGRAM_STATE_ACTIVE
@@ -152,26 +143,28 @@
program_state = PROGRAM_STATE_KILLED
if(network_destination)
generate_network_log("Connection to [network_destination] closed.")
- QDEL_NULL(NM)
if(TM)
SStgui.close_uis(TM)
- qdel(TM)
- TM = null
+ QDEL_NULL(TM)
return 1
-// This is called every tick when the program is enabled. Ensure you do parent call if you override it. If parent returns 1 continue with UI initialisation.
-// It returns 0 if it can't run or if NanoModule was used instead. I suggest using NanoModules where applicable.
-/datum/computer_file/program/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(program_state != PROGRAM_STATE_ACTIVE) // Our program was closed. Close the ui if it exists.
+/datum/computer_file/program/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/simple/headers)
+ )
+
+/datum/computer_file/program/tgui_interact(mob/user, datum/tgui/ui)
+ if(program_state != PROGRAM_STATE_ACTIVE)
if(ui)
ui.close()
- return computer.ui_interact(user)
- if(istype(NM))
- NM.ui_interact(user, ui_key, null, force_open)
- return 0
+ return computer.tgui_interact(user)
if(istype(TM))
TM.tgui_interact(user)
return 0
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui && tgui_id)
+ ui = new(user, src, tgui_id, filedesc)
+ ui.open()
return 1
// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
@@ -185,10 +178,43 @@
if(computer)
return computer.Topic(href, href_list)
+// CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC:
+// Topic calls are automagically forwarded from NanoModule this program contains.
+// Calls beginning with "PRG_" are reserved for programs handling.
+// Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program)
+// ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE.
+/datum/computer_file/program/tgui_act(action,list/params, datum/tgui/ui)
+ if(..())
+ return 1
+ if(computer)
+ switch(action)
+ if("PC_exit")
+ computer.kill_program()
+ ui.close()
+ return 1
+ if("PC_shutdown")
+ computer.shutdown_computer()
+ ui.close()
+ return 1
+ if("PC_minimize")
+ var/mob/user = usr
+ if(!computer.active_program)
+ return
+
+ computer.idle_threads.Add(computer.active_program)
+ program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs
+
+ computer.active_program = null
+ computer.update_icon()
+ ui.close()
+
+ if(user && istype(user))
+ computer.tgui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
+
+
+
// Relays the call to nano module, if we have one
/datum/computer_file/program/proc/check_eye(var/mob/user)
- if(NM)
- return NM.check_eye(user)
if(TM)
return TM.check_eye(user)
else
@@ -200,34 +226,14 @@
/obj/item/modular_computer/update_layout()
return TRUE
-/datum/nano_module/program
- //available_to_ai = FALSE
- var/datum/computer_file/program/program = null // Program-Based computer program that runs this nano module. Defaults to null.
-
-/datum/nano_module/program/New(var/host, var/topic_manager, var/program)
- ..()
- src.program = program
-
-/datum/topic_manager/program
- var/datum/program
-
-/datum/topic_manager/program/New(var/datum/program)
- ..()
- src.program = program
-
-// Calls forwarded to PROGRAM itself should begin with "PRG_"
-// Calls forwarded to COMPUTER running the program should begin with "PC_"
-/datum/topic_manager/program/Topic(href, href_list)
- return program && program.Topic(href, href_list)
-
/datum/computer_file/program/apply_visual(mob/M)
- if(NM)
- return NM.apply_visual(M)
+ if(TM)
+ return TM.apply_visual(M)
/datum/computer_file/program/remove_visual(mob/M)
- if(NM)
- return NM.remove_visual(M)
+ if(TM)
+ return TM.remove_visual(M)
/datum/computer_file/program/proc/relaymove(var/mob/M, direction)
- if(NM)
- return NM.relaymove(M, direction)
\ No newline at end of file
+ if(TM)
+ return TM.relaymove(M, direction)
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/access_decrypter.dm b/code/modules/modular_computers/file_system/programs/antagonist/access_decrypter.dm
index 04bf931593..11547e3426 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/access_decrypter.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/access_decrypter.dm
@@ -6,15 +6,17 @@
program_menu_icon = "unlocked"
extended_desc = "This highly advanced script can very slowly decrypt operational codes used in almost any network. These codes can be downloaded to an ID card to expand the available access. The system administrator will probably notice this."
size = 34
- requires_ntnet = 1
- available_on_ntnet = 0
- available_on_syndinet = 1
- nanomodule_path = /datum/nano_module/program/access_decrypter/
+ requires_ntnet = TRUE
+ available_on_ntnet = FALSE
+ available_on_syndinet = TRUE
+ tgui_id = "NtosAccessDecrypter"
+
var/message = ""
var/running = FALSE
var/progress = 0
var/target_progress = 300
var/datum/access/target_access = null
+ var/list/restricted_access_codes = list(access_change_ids, access_network) // access codes that are not hackable due to balance reasons
/datum/computer_file/program/access_decrypter/kill_program(var/forced)
reset()
@@ -48,82 +50,63 @@
message = "Successfully decrypted and saved operational key codes. Downloaded access codes for: [target_access.desc]"
target_access = null
-/datum/computer_file/program/access_decrypter/Topic(href, href_list)
+/datum/computer_file/program/access_decrypter/tgui_act(action, list/params, datum/tgui/ui)
if(..())
- return 1
- if(href_list["PRG_reset"])
- reset()
- return 1
- if(href_list["PRG_execute"])
- if(running)
- return 1
- if(text2num(href_list["allowed"]))
- return 1
- var/obj/item/weapon/computer_hardware/processor_unit/CPU = computer.processor_unit
- var/obj/item/weapon/computer_hardware/card_slot/RFID = computer.card_slot
- if(!istype(CPU) || !CPU.check_functionality() || !istype(RFID) || !RFID.check_functionality())
- message = "A fatal hardware error has been detected."
- return
- if(!istype(RFID.stored_card))
- message = "RFID card is not present in the device. Operation aborted."
- return
- running = TRUE
- target_access = get_access_by_id(href_list["PRG_execute"])
- if(ntnet_global.intrusion_detection_enabled)
- ntnet_global.add_log("IDS WARNING - Unauthorised access attempt to primary keycode database from device: [computer.network_card.get_network_tag()]")
- ntnet_global.intrusion_detection_alarm = 1
- return 1
+ return TRUE
+ switch(action)
+ if("PRG_reset")
+ reset()
+ return TRUE
+ if("PRG_execute")
+ if(running)
+ return TRUE
+ if(text2num(params["allowed"]))
+ return TRUE
+ var/obj/item/weapon/computer_hardware/processor_unit/CPU = computer.processor_unit
+ var/obj/item/weapon/computer_hardware/card_slot/RFID = computer.card_slot
+ if(!istype(CPU) || !CPU.check_functionality() || !istype(RFID) || !RFID.check_functionality())
+ message = "A fatal hardware error has been detected."
+ return
+ if(!istype(RFID.stored_card))
+ message = "RFID card is not present in the device. Operation aborted."
+ return
+ running = TRUE
+ target_access = get_access_by_id("[params["access_target"]]")
+ if(ntnet_global.intrusion_detection_enabled)
+ ntnet_global.add_log("IDS WARNING - Unauthorised access attempt to primary keycode database from device: [computer.network_card.get_network_tag()]")
+ ntnet_global.intrusion_detection_alarm = TRUE
+ return TRUE
-/datum/nano_module/program/access_decrypter
- name = "NTNet Access Decrypter"
- var/list/restricted_access_codes = list(access_change_ids, access_network) // access codes that are not hackable due to balance reasons
-
-/datum/nano_module/program/access_decrypter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
+/datum/computer_file/program/access_decrypter/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
if(!ntnet_global)
return
- var/datum/computer_file/program/access_decrypter/PRG = program
- var/list/data = list()
- if(!istype(PRG))
- return
- data = PRG.get_header_data()
+ var/list/data = get_header_data()
- if(PRG.message)
- data["message"] = PRG.message
- else if(PRG.running)
+ var/list/regions = list()
+ data["message"] = null
+ data["running"] = running
+ if(message)
+ data["message"] = message
+ else if(running)
data["running"] = 1
- data["rate"] = PRG.computer.processor_unit.max_idle_programs
-
- // Stolen from DOS traffic generator, generates strings of 1s and 0s
- var/percentage = (PRG.progress / PRG.target_progress) * 100
- var/list/strings[0]
- for(var/j, j<10, j++)
- var/string = ""
- for(var/i, i<20, i++)
- string = "[string][prob(percentage)]"
- strings.Add(string)
- data["dos_strings"] = strings
- else if(program.computer.card_slot && program.computer.card_slot.stored_card)
- var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
- var/list/regions = list()
+ data["rate"] = computer.processor_unit.max_idle_programs
+ data["factor"] = (progress / target_progress)
+ else if(computer?.card_slot?.stored_card)
+ var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
for(var/i = 1; i <= 7; i++)
var/list/accesses = list()
for(var/access in get_region_accesses(i))
- if (get_access_desc(access))
+ if(get_access_desc(access) && !(access in restricted_access_codes))
accesses.Add(list(list(
- "desc" = replacetext(get_access_desc(access), " ", " "),
+ "desc" = replacetext(get_access_desc(access), " ", " "),
"ref" = access,
- "allowed" = (access in id_card.access) ? 1 : 0,
- "blocked" = (access in restricted_access_codes) ? 1 : 0)))
+ "allowed" = (access in id_card.access) ? 1 : 0
+ )))
regions.Add(list(list(
"name" = get_region_accesses_name(i),
- "accesses" = accesses)))
- data["regions"] = regions
+ "accesses" = accesses
+ )))
+ data["regions"] = regions
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "access_decrypter.tmpl", "NTNet Access Decrypter", 550, 400, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
\ No newline at end of file
+ return data
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
index 0e0a1381bd..e1fa0cfa8a 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
@@ -6,10 +6,11 @@
program_menu_icon = "arrow-4-diag"
extended_desc = "This advanced script can perform denial of service attacks against NTNet quantum relays. The system administrator will probably notice this. Multiple devices can run this program together against same relay for increased effect"
size = 20
- requires_ntnet = 1
- available_on_ntnet = 0
- available_on_syndinet = 1
- nanomodule_path = /datum/nano_module/program/computer_dos/
+ requires_ntnet = TRUE
+ available_on_ntnet = FALSE
+ available_on_syndinet = TRUE
+ tgui_id = "NtosNetDos"
+
var/obj/machinery/ntnet_relay/target = null
var/dos_speed = 0
var/error = ""
@@ -39,70 +40,51 @@
..(forced)
-/datum/nano_module/program/computer_dos
- name = "DoS Traffic Generator"
-
-/datum/nano_module/program/computer_dos/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
+/datum/computer_file/program/ntnet_dos/tgui_data(mob/user)
if(!ntnet_global)
return
- var/datum/computer_file/program/ntnet_dos/PRG = program
- var/list/data = list()
- if(!istype(PRG))
- return
- data = PRG.get_header_data()
- if(PRG.error)
- data["error"] = PRG.error
- else if(PRG.target && PRG.executed)
- data["target"] = 1
- data["speed"] = PRG.dos_speed
+ var/list/data = get_header_data()
- // This is mostly visual, generate some strings of 1s and 0s
- // Probability of 1 is equal of completion percentage of DoS attack on this relay.
- // Combined with UI updates this adds quite nice effect to the UI
- var/percentage = PRG.target.dos_overload * 100 / PRG.target.dos_capacity
- var/list/strings[0]
- for(var/j, j<10, j++)
- var/string = ""
- for(var/i, i<20, i++)
- string = "[string][prob(percentage)]"
- strings.Add(string)
- data["dos_strings"] = strings
+ data["error"] = error
+ if(target && executed)
+ data["target"] = TRUE
+ data["speed"] = dos_speed
+
+ data["overload"] = target.dos_overload
+ data["capacity"] = target.dos_capacity
else
- var/list/relays[0]
+ data["target"] = FALSE
+ data["relays"] = list()
for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays)
- relays.Add(R.uid)
- data["relays"] = relays
- data["focus"] = PRG.target ? PRG.target.uid : null
+ data["relays"] += list(list("id" = R.uid))
+ data["focus"] = target ? target.uid : null
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "ntnet_dos.tmpl", "DoS Traffic Generator", 400, 250, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ return data
-/datum/computer_file/program/ntnet_dos/Topic(href, href_list)
+/datum/computer_file/program/ntnet_dos/tgui_act(action, params)
if(..())
- return 1
- if(href_list["PRG_target_relay"])
- for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays)
- if("[R.uid]" == href_list["PRG_target_relay"])
- target = R
- return 1
- if(href_list["PRG_reset"])
- if(target)
- target.dos_sources.Remove(src)
- target = null
- executed = 0
- error = ""
- return 1
- if(href_list["PRG_execute"])
- if(target)
- executed = 1
- target.dos_sources.Add(src)
- if(ntnet_global.intrusion_detection_enabled)
- ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [computer.network_card.get_network_tag()]")
- ntnet_global.intrusion_detection_alarm = 1
- return 1
+ return TRUE
+ switch(action)
+ if("PRG_target_relay")
+ for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays)
+ if(R.uid == text2num(params["targid"]))
+ target = R
+ break
+ return TRUE
+ if("PRG_reset")
+ if(target)
+ target.dos_sources.Remove(src)
+ target = null
+ executed = FALSE
+ error = ""
+ return TRUE
+ if("PRG_execute")
+ if(target)
+ executed = TRUE
+ target.dos_sources.Add(src)
+ if(ntnet_global.intrusion_detection_enabled)
+ var/obj/item/weapon/computer_hardware/network_card/network_card = computer.network_card
+ ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]")
+ ntnet_global.intrusion_detection_alarm = TRUE
+ return TRUE
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
index 17199c3b18..5d0e291336 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
@@ -6,10 +6,10 @@
program_menu_icon = "home"
extended_desc = "This virus can destroy hard drive of system it is executed on. It may be obfuscated to look like another non-malicious program. Once armed, it will destroy the system upon next execution."
size = 13
- requires_ntnet = 0
- available_on_ntnet = 0
- available_on_syndinet = 1
- nanomodule_path = /datum/nano_module/program/revelation/
+ requires_ntnet = FALSE
+ available_on_ntnet = FALSE
+ available_on_syndinet = TRUE
+ tgui_id = "NtosRevelation"
var/armed = 0
/datum/computer_file/program/revelation/run_program(var/mob/living/user)
@@ -37,48 +37,31 @@
if(computer.tesla_link && prob(50))
qdel(computer.tesla_link)
-/datum/computer_file/program/revelation/Topic(href, href_list)
+/datum/computer_file/program/revelation/tgui_act(action, params)
if(..())
- return 1
- else if(href_list["PRG_arm"])
- armed = !armed
- else if(href_list["PRG_activate"])
- activate()
- else if(href_list["PRG_obfuscate"])
- var/mob/living/user = usr
- var/newname = sanitize(input(user, "Enter new program name: "))
- if(!newname)
- return
- filedesc = newname
- for(var/datum/computer_file/program/P in ntnet_global.available_station_software)
- if(filedesc == P.filedesc)
- program_menu_icon = P.program_menu_icon
- break
- return 1
+ return
+ switch(action)
+ if("PRG_arm")
+ armed = !armed
+ return TRUE
+ if("PRG_activate")
+ activate()
+ return TRUE
+ if("PRG_obfuscate")
+ var/newname = params["new_name"]
+ if(!newname)
+ return
+ filedesc = newname
+ return TRUE
/datum/computer_file/program/revelation/clone()
var/datum/computer_file/program/revelation/temp = ..()
temp.armed = armed
return temp
-/datum/nano_module/program/revelation
- name = "Revelation Virus"
+/datum/computer_file/program/revelation/tgui_data(mob/user)
+ var/list/data = get_header_data()
-/datum/nano_module/program/revelation/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = list()
- var/datum/computer_file/program/revelation/PRG = program
- if(!istype(PRG))
- return
-
- data = PRG.get_header_data()
-
- data["armed"] = PRG.armed
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "revelation.tmpl", "Revelation Virus", 400, 250, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ data["armed"] = armed
+ return data
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm
index aa122c0abf..47fe4ea2b3 100644
--- a/code/modules/modular_computers/file_system/programs/command/card.dm
+++ b/code/modules/modular_computers/file_system/programs/command/card.dm
@@ -1,7 +1,7 @@
/datum/computer_file/program/card_mod
filename = "cardmod"
filedesc = "ID card modification program"
- nanomodule_path = /datum/nano_module/program/card_mod
+ tguimodule_path = /datum/tgui_module/cardmod
program_icon_state = "id"
program_key_state = "id_key"
program_menu_icon = "key"
@@ -9,220 +9,3 @@
required_access = access_change_ids
requires_ntnet = 0
size = 8
-
-/datum/nano_module/program/card_mod
- name = "ID card modification program"
- var/mod_mode = 1
- var/is_centcom = 0
- var/show_assignments = 0
-
-/datum/nano_module/program/card_mod/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = host.initial_data()
-
- data["src"] = "\ref[src]"
- data["station_name"] = station_name()
- data["manifest"] = data_core ? data_core.get_manifest(0) : null
- data["assignments"] = show_assignments
- if(program && program.computer)
- data["have_id_slot"] = !!program.computer.card_slot
- data["have_printer"] = !!program.computer.nano_printer
- data["authenticated"] = program.can_run(user)
- if(!program.computer.card_slot)
- mod_mode = 0 //We can't modify IDs when there is no card reader
- else
- data["have_id_slot"] = 0
- data["have_printer"] = 0
- data["authenticated"] = 0
- data["mmode"] = mod_mode
- data["centcom_access"] = is_centcom
-
- if(program && program.computer && program.computer.card_slot)
- var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
- data["has_id"] = !!id_card
- data["id_account_number"] = id_card ? id_card.associated_account_number : null
- data["id_rank"] = id_card && id_card.assignment ? id_card.assignment : "Unassigned"
- data["id_owner"] = id_card && id_card.registered_name ? id_card.registered_name : "-----"
- data["id_name"] = id_card ? id_card.name : "-----"
-
- var/list/departments = list()
- for(var/D in SSjob.get_all_department_datums())
- var/datum/department/dept = D
- if(!dept.assignable) // No AI ID cards for you.
- continue
- if(dept.centcom_only && !is_centcom)
- continue
- departments[++departments.len] = list("department_name" = dept.name, "jobs" = format_jobs(SSjob.get_job_titles_in_department(dept.name)) )
-
- data["departments"] = departments
-
- data["all_centcom_access"] = is_centcom ? get_accesses(1) : null
- data["regions"] = get_accesses()
-
- if(program.computer.card_slot && program.computer.card_slot.stored_card)
- var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
- if(is_centcom)
- var/list/all_centcom_access = list()
- for(var/access in get_all_centcom_access())
- all_centcom_access.Add(list(list(
- "desc" = replacetext(get_centcom_access_desc(access), " ", " "),
- "ref" = access,
- "allowed" = (access in id_card.access) ? 1 : 0)))
- data["all_centcom_access"] = all_centcom_access
- else
- var/list/regions = list()
- for(var/i = 1; i <= 7; i++)
- var/list/accesses = list()
- for(var/access in get_region_accesses(i))
- if (get_access_desc(access))
- accesses.Add(list(list(
- "desc" = replacetext(get_access_desc(access), " ", " "),
- "ref" = access,
- "allowed" = (access in id_card.access) ? 1 : 0)))
-
- regions.Add(list(list(
- "name" = get_region_accesses_name(i),
- "accesses" = accesses)))
- data["regions"] = regions
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "mod_identification_computer.tmpl", name, 600, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
-
-/datum/nano_module/program/card_mod/proc/format_jobs(list/jobs)
- var/obj/item/weapon/card/id/id_card = program.computer.card_slot ? program.computer.card_slot.stored_card : null
- var/list/formatted = list()
- for(var/job in jobs)
- formatted.Add(list(list(
- "display_name" = replacetext(job, " ", " "),
- "target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned",
- "job" = job)))
-
- return formatted
-
-/datum/nano_module/program/card_mod/proc/get_accesses(var/is_centcom = 0)
- return null
-
-
-/datum/computer_file/program/card_mod/Topic(href, href_list)
- if(..())
- return 1
-
- var/mob/user = usr
- var/obj/item/weapon/card/id/user_id_card = user.GetIdCard()
- var/obj/item/weapon/card/id/id_card
- if (computer.card_slot)
- id_card = computer.card_slot.stored_card
-
- var/datum/nano_module/program/card_mod/module = NM
- switch(href_list["action"])
- if("switchm")
- if(href_list["target"] == "mod")
- module.mod_mode = 1
- else if (href_list["target"] == "manifest")
- module.mod_mode = 0
- if("togglea")
- if(module.show_assignments)
- module.show_assignments = 0
- else
- module.show_assignments = 1
- if("print")
- if(computer && computer.nano_printer) //This option should never be called if there is no printer
- if(module.mod_mode)
- if(can_run(user, 1))
- var/contents = {"Access Report
- Prepared By: [user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]
- For: [id_card.registered_name ? id_card.registered_name : "Unregistered"]
-
- Assignment: [id_card.assignment]
- Account Number: #[id_card.associated_account_number]
- Blood Type: [id_card.blood_type]
- Access:
- "}
-
- var/known_access_rights = get_access_ids(ACCESS_TYPE_STATION|ACCESS_TYPE_CENTCOM)
- for(var/A in id_card.access)
- if(A in known_access_rights)
- contents += " [get_access_desc(A)]"
-
- if(!computer.nano_printer.print_text(contents,"access report"))
- to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.")
- return
- else
- computer.visible_message("\The [computer] prints out paper.")
- else
- var/contents = {"Crew Manifest
-
- [data_core ? data_core.get_manifest(0) : ""]
- "}
- if(!computer.nano_printer.print_text(contents,text("crew manifest ([])", stationtime2text())))
- to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.")
- return
- else
- computer.visible_message("\The [computer] prints out paper.")
- if("eject")
- if(computer && computer.card_slot)
- if(id_card)
- data_core.manifest_modify(id_card.registered_name, id_card.assignment)
- computer.proc_eject_id(user)
- if("terminate")
- if(computer && can_run(user, 1))
- id_card.assignment = "Dismissed" //VOREStation Edit: setting adjustment
- id_card.access = list()
- callHook("terminate_employee", list(id_card))
- if("edit")
- if(computer && can_run(user, 1))
- if(href_list["name"])
- var/temp_name = sanitizeName(input("Enter name.", "Name", id_card.registered_name),allow_numbers=TRUE)
- if(temp_name)
- id_card.registered_name = temp_name
- else
- computer.visible_message("[computer] buzzes rudely.")
- else if(href_list["account"])
- var/account_num = text2num(input("Enter account number.", "Account", id_card.associated_account_number))
- id_card.associated_account_number = account_num
- if("assign")
- if(computer && can_run(user, 1) && id_card)
- var/t1 = href_list["assign_target"]
- if(t1 == "Custom")
- var/temp_t = sanitize(input("Enter a custom job assignment.","Assignment", id_card.assignment), 45)
- //let custom jobs function as an impromptu alt title, mainly for sechuds
- if(temp_t)
- id_card.assignment = temp_t
- else
- var/list/access = list()
- if(module.is_centcom)
- access = get_centcom_access(t1)
- else
- var/datum/job/jobdatum
- for(var/jobtype in typesof(/datum/job))
- var/datum/job/J = new jobtype
- if(ckey(J.title) == ckey(t1))
- jobdatum = J
- break
- if(!jobdatum)
- to_chat(usr, "No log exists for this job: [t1]")
- return
-
- access = jobdatum.get_access()
-
- id_card.access = access
- id_card.assignment = t1
- id_card.rank = t1
-
- callHook("reassign_employee", list(id_card))
- if("access")
- if(href_list["allowed"] && computer && can_run(user, 1))
- var/access_type = text2num(href_list["access_target"])
- var/access_allowed = text2num(href_list["allowed"])
- if(access_type in get_access_ids(ACCESS_TYPE_STATION|ACCESS_TYPE_CENTCOM))
- id_card.access -= access_type
- if(!access_allowed)
- id_card.access += access_type
- if(id_card)
- id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])")
-
- SSnanoui.update_uis(NM)
- return 1
diff --git a/code/modules/modular_computers/file_system/programs/command/comm.dm b/code/modules/modular_computers/file_system/programs/command/comm.dm
index fc2efa8820..a2079ad494 100644
--- a/code/modules/modular_computers/file_system/programs/command/comm.dm
+++ b/code/modules/modular_computers/file_system/programs/command/comm.dm
@@ -9,7 +9,7 @@
program_icon_state = "comm"
program_key_state = "med_key"
program_menu_icon = "flag"
- nanomodule_path = /datum/nano_module/program/comm
+ tguimodule_path = /datum/tgui_module/communications/ntos
extended_desc = "Used to command and control. Can relay long-range communications. This program can not be run on tablet computers."
required_access = access_heads
requires_ntnet = 1
@@ -24,269 +24,6 @@
temp.message_core.messages = message_core.messages.Copy()
return temp
-/datum/nano_module/program/comm
- name = "Command and Communications Program"
- //available_to_ai = TRUE
- var/current_status = STATE_DEFAULT
- var/msg_line1 = ""
- var/msg_line2 = ""
- var/centcomm_message_cooldown = 0
- var/announcment_cooldown = 0
- var/datum/announcement/priority/crew_announcement = new
- var/current_viewing_message_id = 0
- var/current_viewing_message = null
-
-/datum/nano_module/program/comm/New()
- ..()
- crew_announcement.newscast = 1
-
-/datum/nano_module/program/comm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = host.initial_data()
-
- if(program)
- data["emagged"] = program.computer_emagged
- data["net_comms"] = !!program.get_signal(NTNET_COMMUNICATION) //Double !! is needed to get 1 or 0 answer
- data["net_syscont"] = !!program.get_signal(NTNET_SYSTEMCONTROL)
- if(program.computer)
- data["have_printer"] = !!program.computer.nano_printer
- else
- data["have_printer"] = 0
- else
- data["emagged"] = 0
- data["net_comms"] = 1
- data["net_syscont"] = 1
- data["have_printer"] = 0
-
- data["message_line1"] = msg_line1
- data["message_line2"] = msg_line2
- data["state"] = current_status
- data["isAI"] = issilicon(usr)
- data["authenticated"] = get_authentication_level(user)
- data["current_security_level"] = security_level
- data["current_security_level_title"] = num2seclevel(security_level)
-
- data["def_SEC_LEVEL_DELTA"] = SEC_LEVEL_DELTA
- data["def_SEC_LEVEL_YELLOW"] = SEC_LEVEL_YELLOW
- data["def_SEC_LEVEL_ORANGE"] = SEC_LEVEL_ORANGE
- data["def_SEC_LEVEL_VIOLET"] = SEC_LEVEL_VIOLET
- data["def_SEC_LEVEL_BLUE"] = SEC_LEVEL_BLUE
- data["def_SEC_LEVEL_GREEN"] = SEC_LEVEL_GREEN
-
- var/datum/comm_message_listener/l = obtain_message_listener()
- data["messages"] = l.messages
- data["message_deletion_allowed"] = l != global_message_listener
- data["message_current_id"] = current_viewing_message_id
- if(current_viewing_message)
- data["message_current"] = current_viewing_message
-
- if(emergency_shuttle.location())
- data["have_shuttle"] = 1
- if(emergency_shuttle.online())
- data["have_shuttle_called"] = 1
- else
- data["have_shuttle_called"] = 0
- else
- data["have_shuttle"] = 0
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "mod_communication.tmpl", name, 550, 420, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
-
-/datum/nano_module/program/comm/proc/get_authentication_level(var/mob/user)
- if(program)
- if(program.can_run(user, 0, access_captain))
- return 2
- else
- return program.can_run(user)
- return 1
-
-/datum/nano_module/program/comm/proc/obtain_message_listener()
- if(program)
- var/datum/computer_file/program/comm/P = program
- return P.message_core
- return global_message_listener
-
-/datum/nano_module/program/comm/Topic(href, href_list)
- if(..())
- return 1
- var/mob/user = usr
- var/ntn_comm = program ? !!program.get_signal(NTNET_COMMUNICATION) : 1
- var/ntn_cont = program ? !!program.get_signal(NTNET_SYSTEMCONTROL) : 1
- var/datum/comm_message_listener/l = obtain_message_listener()
- switch(href_list["action"])
- if("sw_menu")
- . = 1
- current_status = text2num(href_list["target"])
- if("announce")
- . = 1
- if(get_authentication_level(user) == 2 && !issilicon(usr) && ntn_comm)
- if(user)
- var/obj/item/weapon/card/id/id_card = user.GetIdCard()
- crew_announcement.announcer = GetNameAndAssignmentFromId(id_card)
- else
- crew_announcement.announcer = "Unknown"
- if(announcment_cooldown)
- to_chat(usr, "Please allow at least one minute to pass between announcements")
- return TRUE
- var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message
- if(!input || !can_still_topic())
- return 1
- crew_announcement.Announce(input)
- announcment_cooldown = 1
- spawn(600)//One minute cooldown
- announcment_cooldown = 0
- if("message")
- . = 1
- if(href_list["target"] == "emagged")
- if(program)
- if(get_authentication_level(user) == 2 && program.computer_emagged && !issilicon(usr) && ntn_comm)
- if(centcomm_message_cooldown)
- to_chat(usr, "Arrays recycling. Please stand by.")
- SSnanoui.update_uis(src)
- return
- var/input = sanitize(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. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", "") as null|text)
- if(!input || !can_still_topic())
- return 1
- Syndicate_announce(input, usr)
- to_chat(usr, "Message transmitted.")
- log_say("[key_name(usr)] has made an illegal announcement: [input]")
- centcomm_message_cooldown = 1
- spawn(300)//30 second cooldown
- centcomm_message_cooldown = 0
- else if(href_list["target"] == "regular")
- if(get_authentication_level(user) == 2 && !issilicon(usr) && ntn_comm)
- if(centcomm_message_cooldown)
- to_chat(usr, "Arrays recycling. Please stand by.")
- SSnanoui.update_uis(src)
- return
- if(!is_relay_online())//Contact Centcom has a check, Syndie doesn't to allow for Traitor funs.
- to_chat(usr, "No Emergency Bluespace Relay detected. Unable to transmit message.")
- return 1
- var/input = sanitize(input("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. There is a 30 second delay before you may send another message, \
- be clear, full and concise.", "Central Command Quantum Messaging") as null|message)
- if(!input || !can_still_topic())
- return 1
- CentCom_announce(input, usr)
- to_chat(usr, "Message transmitted.")
- log_say("[key_name(usr)] has made an IA Centcomm announcement: [input]")
- centcomm_message_cooldown = 1
- spawn(300) //30 second cooldown
- centcomm_message_cooldown = 0
- if("shuttle")
- . = 1
- if(get_authentication_level(user) && ntn_cont)
- if(href_list["target"] == "call")
- var/confirm = alert("Are you sure you want to call the shuttle?", name, "No", "Yes")
- if(confirm == "Yes" && can_still_topic())
- call_shuttle_proc(usr)
-
- if(href_list["target"] == "cancel" && !issilicon(usr))
- var/confirm = alert("Are you sure you want to cancel the shuttle?", name, "No", "Yes")
- if(confirm == "Yes" && can_still_topic())
- cancel_call_proc(usr)
- if("setstatus")
- . = 1
- if(get_authentication_level(user) && ntn_cont)
- switch(href_list["target"])
- if("line1")
- var/linput = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", msg_line1) as text|null, 40), 40)
- if(can_still_topic())
- msg_line1 = linput
- if("line2")
- var/linput = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", msg_line2) as text|null, 40), 40)
- if(can_still_topic())
- msg_line2 = linput
- if("message")
- post_status("message", msg_line1, msg_line2)
- if("alert")
- post_status("alert", href_list["alert"])
- else
- post_status(href_list["target"])
- if("setalert")
- . = 1
- if(get_authentication_level(user) && !issilicon(usr) && ntn_cont && ntn_comm)
- var/current_level = text2num(href_list["target"])
- var/confirm = alert("Are you sure you want to change alert level to [num2seclevel(current_level)]?", name, "No", "Yes")
- if(confirm == "Yes" && can_still_topic())
- var/old_level = security_level
- if(!current_level) current_level = SEC_LEVEL_GREEN
- if(current_level < SEC_LEVEL_GREEN) current_level = SEC_LEVEL_GREEN
- if(current_level > SEC_LEVEL_BLUE) current_level = SEC_LEVEL_BLUE //Cannot engage delta with this
- set_security_level(current_level)
- if(security_level != old_level)
- log_game("[key_name(usr)] has changed the security level to [get_security_level()].")
- message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
- switch(security_level)
- if(SEC_LEVEL_GREEN)
- feedback_inc("alert_comms_green",1)
- if(SEC_LEVEL_YELLOW)
- feedback_inc("alert_comms_yellow",1)
- if(SEC_LEVEL_ORANGE)
- feedback_inc("alert_comms_orange",1)
- if(SEC_LEVEL_VIOLET)
- feedback_inc("alert_comms_violet",1)
- if(SEC_LEVEL_BLUE)
- feedback_inc("alert_comms_blue",1)
- else
- to_chat(usr, "You press button, but red light flashes and nothing happens.")//This should never happen
-
- current_status = STATE_DEFAULT
- if("viewmessage")
- . = 1
- if(get_authentication_level(user) && ntn_comm)
- current_viewing_message_id = text2num(href_list["target"])
- for(var/list/m in l.messages)
- if(m["id"] == current_viewing_message_id)
- current_viewing_message = m
- current_status = STATE_VIEWMESSAGE
- if("delmessage")
- . = 1
- if(get_authentication_level(user) && ntn_comm && l != global_message_listener)
- l.Remove(current_viewing_message)
- current_status = STATE_MESSAGELIST
- if("printmessage")
- . = 1
- if(get_authentication_level(user) && ntn_comm)
- if(program && program.computer && program.computer.nano_printer)
- if(!program.computer.nano_printer.print_text(current_viewing_message["contents"],current_viewing_message["title"]))
- to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.")
- else
- program.computer.visible_message("\The [program.computer] prints out paper.")
-
-
-/datum/nano_module/program/comm/proc/post_status(var/command, var/data1, var/data2)
-
- var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
-
- if(!frequency) return
-
-
- var/datum/signal/status_signal = new
- status_signal.source = src
- status_signal.transmission_method = TRANSMISSION_RADIO
- status_signal.data["command"] = command
-
- switch(command)
- if("message")
- status_signal.data["msg1"] = data1
- status_signal.data["msg2"] = data2
- log_admin("STATUS: [key_name(usr)] set status screen message with [src]: [data1] [data2]")
- if("alert")
- status_signal.data["picture_state"] = data1
-
- frequency.post_signal(src, status_signal)
-
-#undef STATE_DEFAULT
-#undef STATE_MESSAGELIST
-#undef STATE_VIEWMESSAGE
-#undef STATE_STATUSDISPLAY
-#undef STATE_ALERT_LEVEL
-
/*
General message handling stuff
*/
@@ -304,19 +41,9 @@ proc/post_comm_message(var/message_title, var/message_text)
message["title"] = message_title
message["contents"] = message_text
- for (var/datum/comm_message_listener/l in comm_message_listeners)
+ for(var/datum/comm_message_listener/l in comm_message_listeners)
l.Add(message)
- //Old console support
- for (var/obj/machinery/computer/communications/comm in machines)
- if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
- var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
- intercept.name = message_title
- intercept.info = message_text
-
- comm.messagetitle.Add(message_title)
- comm.messagetext.Add(message_text)
-
/datum/comm_message_listener
var/list/messages
diff --git a/code/modules/modular_computers/file_system/programs/generic/configurator.dm b/code/modules/modular_computers/file_system/programs/generic/configurator.dm
index c3ce1e358a..2d660c8b7e 100644
--- a/code/modules/modular_computers/file_system/programs/generic/configurator.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/configurator.dm
@@ -14,51 +14,4 @@
size = 4
available_on_ntnet = 0
requires_ntnet = 0
- nanomodule_path = /datum/nano_module/program/computer_configurator/
-
-/datum/nano_module/program/computer_configurator
- name = "NTOS Computer Configuration Tool"
- var/obj/item/modular_computer/movable = null
-
-/datum/nano_module/program/computer_configurator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- if(program)
- movable = program.computer
- if(!istype(movable))
- movable = null
-
- // No computer connection, we can't get data from that.
- if(!movable)
- return 0
-
- var/list/data = list()
-
- if(program)
- data = program.get_header_data()
-
- var/list/hardware = movable.get_all_components()
-
- data["disk_size"] = movable.hard_drive.max_capacity
- data["disk_used"] = movable.hard_drive.used_capacity
- data["power_usage"] = movable.last_power_usage
- data["battery_exists"] = movable.battery_module ? 1 : 0
- if(movable.battery_module)
- data["battery_rating"] = movable.battery_module.battery.maxcharge
- data["battery_percent"] = round(movable.battery_module.battery.percent())
-
- var/list/all_entries[0]
- for(var/obj/item/weapon/computer_hardware/H in hardware)
- all_entries.Add(list(list(
- "name" = H.name,
- "desc" = H.desc,
- "enabled" = H.enabled,
- "critical" = H.critical,
- "powerusage" = H.power_usage
- )))
-
- data["hardware"] = all_entries
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "laptop_configuration.tmpl", "NTOS Configuration Utility", 575, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
\ No newline at end of file
+ tguimodule_path = /datum/tgui_module/computer_configurator
diff --git a/code/modules/modular_computers/file_system/programs/generic/email_client.dm b/code/modules/modular_computers/file_system/programs/generic/email_client.dm
index 3e2f979bb5..32d635fef4 100644
--- a/code/modules/modular_computers/file_system/programs/generic/email_client.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/email_client.dm
@@ -11,15 +11,15 @@
var/stored_login = ""
var/stored_password = ""
- nanomodule_path = /datum/nano_module/email_client
+ tguimodule_path = /datum/tgui_module/email_client
// Persistency. Unless you log out, or unless your password changes, this will pre-fill the login data when restarting the program
/datum/computer_file/program/email_client/kill_program()
- if(NM)
- var/datum/nano_module/email_client/NME = NM
- if(NME.current_account)
- stored_login = NME.stored_login
- stored_password = NME.stored_password
+ if(TM)
+ var/datum/tgui_module/email_client/TME = TM
+ if(TME.current_account)
+ stored_login = TME.stored_login
+ stored_password = TME.stored_password
else
stored_login = ""
stored_password = ""
@@ -27,473 +27,31 @@
/datum/computer_file/program/email_client/run_program()
. = ..()
- if(NM)
- var/datum/nano_module/email_client/NME = NM
- NME.stored_login = stored_login
- NME.stored_password = stored_password
- NME.log_in()
- NME.error = ""
- NME.check_for_new_messages(1)
+ if(TM)
+ var/datum/tgui_module/email_client/TME = TM
+ TME.stored_login = stored_login
+ TME.stored_password = stored_password
+ TME.log_in()
+ TME.error = ""
+ TME.check_for_new_messages(1)
/datum/computer_file/program/email_client/proc/new_mail_notify()
- computer.visible_message("\The [computer] beeps softly, indicating a new email has been received.", 1)
+ var/turf/T = get_turf(computer) // Because visible_message is being a butt
+ if(T)
+ T.visible_message("[computer] beeps softly, indicating a new email has been received.")
+ playsound(computer, 'sound/misc/server-ready.ogg', 100, 0)
/datum/computer_file/program/email_client/process_tick()
..()
- var/datum/nano_module/email_client/NME = NM
- if(!istype(NME))
+ var/datum/tgui_module/email_client/TME = TM
+ if(!istype(TME))
return
- NME.relayed_process(ntnet_speed)
+ TME.relayed_process(ntnet_speed)
- var/check_count = NME.check_for_new_messages()
+ var/check_count = TME.check_for_new_messages()
if(check_count)
if(check_count == 2)
new_mail_notify()
ui_header = "ntnrc_new.gif"
else
ui_header = "ntnrc_idle.gif"
-
-/datum/nano_module/email_client/
- name = "Email Client"
- var/stored_login = ""
- var/stored_password = ""
- var/error = ""
-
- var/msg_title = ""
- var/msg_body = ""
- var/msg_recipient = ""
- var/datum/computer_file/msg_attachment = null
- var/folder = "Inbox"
- var/addressbook = FALSE
- var/new_message = FALSE
-
- var/last_message_count = 0 // How many messages were there during last check.
- var/read_message_count = 0 // How many messages were there when user has last accessed the UI.
-
- var/datum/computer_file/downloading = null
- var/download_progress = 0
- var/download_speed = 0
-
- var/datum/computer_file/data/email_account/current_account = null
- var/datum/computer_file/data/email_message/current_message = null
-
-/datum/nano_module/email_client/proc/log_in()
- for(var/datum/computer_file/data/email_account/account in ntnet_global.email_accounts)
- if(!account.can_login)
- continue
- if(account.login == stored_login)
- if(account.password == stored_password)
- if(account.suspended)
- error = "This account has been suspended. Please contact the system administrator for assistance."
- return 0
- current_account = account
- return 1
- else
- error = "Invalid Password"
- return 0
- error = "Invalid Login"
- return 0
-
-// Returns 0 if no new messages were received, 1 if there is an unread message but notification has already been sent.
-// and 2 if there is a new message that appeared in this tick (and therefore notification should be sent by the program).
-/datum/nano_module/email_client/proc/check_for_new_messages(var/messages_read = FALSE)
- if(!current_account)
- return 0
-
- var/list/allmails = current_account.all_emails()
-
- if(allmails.len > last_message_count)
- . = 2
- else if(allmails.len > read_message_count)
- . = 1
- else
- . = 0
-
- last_message_count = allmails.len
- if(messages_read)
- read_message_count = allmails.len
-
-
-/datum/nano_module/email_client/proc/log_out()
- current_account = null
- downloading = null
- download_progress = 0
- last_message_count = 0
- read_message_count = 0
-
-/datum/nano_module/email_client/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = host.initial_data()
-
- // Password has been changed by other client connected to this email account
- if(current_account)
- if(current_account.password != stored_password)
- log_out()
- error = "Invalid Password"
- // Banned.
- if(current_account.suspended)
- log_out()
- error = "This account has been suspended. Please contact the system administrator for assistance."
-
- if(error)
- data["error"] = error
- else if(downloading)
- data["downloading"] = 1
- data["down_filename"] = "[downloading.filename].[downloading.filetype]"
- data["down_progress"] = download_progress
- data["down_size"] = downloading.size
- data["down_speed"] = download_speed
-
- else if(istype(current_account))
- data["current_account"] = current_account.login
- if(addressbook)
- var/list/all_accounts = list()
- for(var/datum/computer_file/data/email_account/account in ntnet_global.email_accounts)
- if(!account.can_login)
- continue
- all_accounts.Add(list(list(
- "login" = account.login
- )))
- data["addressbook"] = 1
- data["accounts"] = all_accounts
- else if(new_message)
- data["new_message"] = 1
- data["msg_title"] = msg_title
- data["msg_body"] = pencode2html(msg_body)
- data["msg_recipient"] = msg_recipient
- if(msg_attachment)
- data["msg_hasattachment"] = 1
- data["msg_attachment_filename"] = "[msg_attachment.filename].[msg_attachment.filetype]"
- data["msg_attachment_size"] = msg_attachment.size
- else if (current_message)
- data["cur_title"] = current_message.title
- data["cur_body"] = pencode2html(current_message.stored_data)
- data["cur_timestamp"] = current_message.timestamp
- data["cur_source"] = current_message.source
- data["cur_uid"] = current_message.uid
- if(istype(current_message.attachment))
- data["cur_hasattachment"] = 1
- data["cur_attachment_filename"] = "[current_message.attachment.filename].[current_message.attachment.filetype]"
- data["cur_attachment_size"] = current_message.attachment.size
- else
- data["label_inbox"] = "Inbox ([current_account.inbox.len])"
- data["label_spam"] = "Spam ([current_account.spam.len])"
- data["label_deleted"] = "Deleted ([current_account.deleted.len])"
- var/list/message_source
- if(folder == "Inbox")
- message_source = current_account.inbox
- else if(folder == "Spam")
- message_source = current_account.spam
- else if(folder == "Deleted")
- message_source = current_account.deleted
-
- if(message_source)
- data["folder"] = folder
- var/list/all_messages = list()
- for(var/datum/computer_file/data/email_message/message in message_source)
- all_messages.Add(list(list(
- "title" = message.title,
- "body" = pencode2html(message.stored_data),
- "source" = message.source,
- "timestamp" = message.timestamp,
- "uid" = message.uid
- )))
- data["messages"] = all_messages
- data["messagecount"] = all_messages.len
- else
- data["stored_login"] = stored_login
- data["stored_password"] = stars(stored_password, 0)
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "email_client.tmpl", "Email Client", 600, 450, state = state)
- if(host.update_layout())
- ui.auto_update_layout = 1
- ui.set_auto_update(1)
- ui.set_initial_data(data)
- ui.open()
-
-/datum/nano_module/email_client/proc/find_message_by_fuid(var/fuid)
- if(!istype(current_account))
- return
-
- // href_list works with strings, so this makes it a bit easier for us
- if(istext(fuid))
- fuid = text2num(fuid)
-
- for(var/datum/computer_file/data/email_message/message in current_account.all_emails())
- if(message.uid == fuid)
- return message
-
-/datum/nano_module/email_client/proc/clear_message()
- new_message = FALSE
- msg_title = ""
- msg_body = ""
- msg_recipient = ""
- msg_attachment = null
- current_message = null
-
-/datum/nano_module/email_client/proc/relayed_process(var/netspeed)
- download_speed = netspeed
- if(!downloading)
- return
- download_progress = min(download_progress + netspeed, downloading.size)
- if(download_progress >= downloading.size)
- var/obj/item/modular_computer/MC = nano_host()
- if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
- error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
- downloading = null
- download_progress = 0
- return 1
-
- if(MC.hard_drive.store_file(downloading))
- error = "File successfully downloaded to local device."
- else
- error = "Error saving file: I/O Error: The hard drive may be full or nonfunctional."
- downloading = null
- download_progress = 0
- return 1
-
-
-/datum/nano_module/email_client/Topic(href, href_list)
- if(..())
- return 1
- var/mob/living/user = usr
- check_for_new_messages(1) // Any actual interaction (button pressing) is considered as acknowledging received message, for the purpose of notification icons.
- if(href_list["login"])
- log_in()
- return 1
-
- if(href_list["logout"])
- log_out()
- return 1
-
- if(href_list["reset"])
- error = ""
- return 1
-
- if(href_list["new_message"])
- new_message = TRUE
- return 1
-
- if(href_list["cancel"])
- if(addressbook)
- addressbook = FALSE
- else
- clear_message()
- return 1
-
- if(href_list["addressbook"])
- addressbook = TRUE
- return 1
-
- if(href_list["set_recipient"])
- msg_recipient = sanitize(href_list["set_recipient"])
- addressbook = FALSE
- return 1
-
- if(href_list["edit_title"])
- var/newtitle = sanitize(input(user,"Enter title for your message:", "Message title", msg_title), 100)
- if(newtitle)
- msg_title = newtitle
- return 1
-
- // This uses similar editing mechanism as the FileManager program, therefore it supports various paper tags and remembers formatting.
- if(href_list["edit_body"])
- var/oldtext = html_decode(msg_body)
- oldtext = replacetext(oldtext, "\[editorbr\]", "\n")
-
- var/newtext = sanitize(replacetext(input(usr, "Enter your message. You may use most tags from paper formatting", "Message Editor", oldtext) as message|null, "\n", "\[editorbr\]"), 20000)
- if(newtext)
- msg_body = newtext
- return 1
-
- if(href_list["edit_recipient"])
- var/newrecipient = sanitize(input(user,"Enter recipient's email address:", "Recipient", msg_recipient), 100)
- if(newrecipient)
- msg_recipient = newrecipient
- return 1
-
- if(href_list["edit_login"])
- var/newlogin = sanitize(input(user,"Enter login", "Login", stored_login), 100)
- if(newlogin)
- stored_login = newlogin
- return 1
-
- if(href_list["edit_password"])
- var/newpass = sanitize(input(user,"Enter password", "Password"), 100)
- if(newpass)
- stored_password = newpass
- return 1
-
- if(href_list["delete"])
- if(!istype(current_account))
- return 1
- var/datum/computer_file/data/email_message/M = find_message_by_fuid(href_list["delete"])
- if(!istype(M))
- return 1
- if(folder == "Deleted")
- current_account.deleted.Remove(M)
- qdel(M)
- else
- current_account.deleted.Add(M)
- current_account.inbox.Remove(M)
- current_account.spam.Remove(M)
- if(current_message == M)
- current_message = null
- return 1
-
- if(href_list["send"])
- if(!current_account)
- return 1
- if((msg_title == "") || (msg_body == "") || (msg_recipient == ""))
- error = "Error sending mail: Title or message body is empty!"
- return 1
-
- var/datum/computer_file/data/email_message/message = new()
- message.title = msg_title
- message.stored_data = msg_body
- message.source = current_account.login
- message.attachment = msg_attachment
- if(!current_account.send_mail(msg_recipient, message))
- error = "Error sending email: this address doesn't exist."
- return 1
- else
- error = "Email successfully sent."
- clear_message()
- return 1
-
- if(href_list["set_folder"])
- folder = href_list["set_folder"]
- return 1
-
- if(href_list["reply"])
- var/datum/computer_file/data/email_message/M = find_message_by_fuid(href_list["reply"])
- if(!istype(M))
- return 1
-
- new_message = TRUE
- msg_recipient = M.source
- msg_title = "Re: [M.title]"
- msg_body = "\[editorbr\]\[editorbr\]\[editorbr\]\[br\]==============================\[br\]\[editorbr\]"
- msg_body += "Received by [current_account.login] at [M.timestamp]\[br\]\[editorbr\][M.stored_data]"
- return 1
-
- if(href_list["view"])
- var/datum/computer_file/data/email_message/M = find_message_by_fuid(href_list["view"])
- if(istype(M))
- current_message = M
- return 1
-
- if(href_list["changepassword"])
- var/oldpassword = sanitize(input(user,"Please enter your old password:", "Password Change"), 100)
- if(!oldpassword)
- return 1
- var/newpassword1 = sanitize(input(user,"Please enter your new password:", "Password Change"), 100)
- if(!newpassword1)
- return 1
- var/newpassword2 = sanitize(input(user,"Please re-enter your new password:", "Password Change"), 100)
- if(!newpassword2)
- return 1
-
- if(!istype(current_account))
- error = "Please log in before proceeding."
- return 1
-
- if(current_account.password != oldpassword)
- error = "Incorrect original password"
- return 1
-
- if(newpassword1 != newpassword2)
- error = "The entered passwords do not match."
- return 1
-
- current_account.password = newpassword1
- stored_password = newpassword1
- error = "Your password has been successfully changed!"
- return 1
-
- // The following entries are Modular Computer framework only, and therefore won't do anything in other cases (like AI View)
-
- if(href_list["save"])
- // Fully dependant on modular computers here.
- var/obj/item/modular_computer/MC = nano_host()
-
- if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
- error = "Error exporting file. Are you using a functional and NTOS-compliant device?"
- return 1
-
- var/filename = sanitize(input(user,"Please specify file name:", "Message export"), 100)
- if(!filename)
- return 1
-
- var/datum/computer_file/data/email_message/M = find_message_by_fuid(href_list["save"])
- var/datum/computer_file/data/mail = istype(M) ? M.export() : null
- if(!istype(mail))
- return 1
- mail.filename = filename
- if(!MC.hard_drive || !MC.hard_drive.store_file(mail))
- error = "Internal I/O error when writing file, the hard drive may be full."
- else
- error = "Email exported successfully"
- return 1
-
- if(href_list["addattachment"])
- var/obj/item/modular_computer/MC = nano_host()
- msg_attachment = null
-
- if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
- error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
- return 1
-
- var/list/filenames = list()
- for(var/datum/computer_file/CF in MC.hard_drive.stored_files)
- if(CF.unsendable)
- continue
- filenames.Add(CF.filename)
- var/picked_file = input(user, "Please pick a file to send as attachment (max 32GQ)") as null|anything in filenames
-
- if(!picked_file)
- return 1
-
- if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
- error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
- return 1
-
- for(var/datum/computer_file/CF in MC.hard_drive.stored_files)
- if(CF.unsendable)
- continue
- if(CF.filename == picked_file)
- msg_attachment = CF.clone()
- break
- if(!istype(msg_attachment))
- msg_attachment = null
- error = "Unknown error when uploading attachment."
- return 1
-
- if(msg_attachment.size > 32)
- error = "Error uploading attachment: File exceeds maximal permitted file size of 32GQ."
- msg_attachment = null
- else
- error = "File [msg_attachment.filename].[msg_attachment.filetype] has been successfully uploaded."
- return 1
-
- if(href_list["downloadattachment"])
- if(!current_account || !current_message || !current_message.attachment)
- return 1
- var/obj/item/modular_computer/MC = nano_host()
- if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
- error = "Error downloading file. Are you using a functional and NTOSv2-compliant device?"
- return 1
-
- downloading = current_message.attachment.clone()
- download_progress = 0
- return 1
-
- if(href_list["canceldownload"])
- downloading = null
- download_progress = 0
- return 1
-
- if(href_list["remove_attachment"])
- msg_attachment = null
- return 1
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
index 42dfdd622d..13a137993e 100644
--- a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
@@ -6,202 +6,190 @@
program_key_state = "generic_key"
program_menu_icon = "folder-collapsed"
size = 8
- requires_ntnet = 0
- available_on_ntnet = 0
- undeletable = 1
- nanomodule_path = /datum/nano_module/program/computer_filemanager/
+ requires_ntnet = FALSE
+ available_on_ntnet = FALSE
+ undeletable = TRUE
+ tgui_id = "NtosFileManager"
+
var/open_file
var/error
-/datum/computer_file/program/filemanager/Topic(href, href_list)
+/datum/computer_file/program/filemanager/tgui_act(action, list/params, datum/tgui/ui)
if(..())
- return 1
+ return TRUE
- if(href_list["PRG_openfile"])
- . = 1
- open_file = href_list["PRG_openfile"]
- if(href_list["PRG_newtextfile"])
- . = 1
- var/newname = sanitize(input(usr, "Enter file name or leave blank to cancel:", "File rename"))
- if(!newname)
- return 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/data/F = new/datum/computer_file/data()
- F.filename = newname
- F.filetype = "TXT"
- HDD.store_file(F)
- if(href_list["PRG_deletefile"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/file = HDD.find_file_by_name(href_list["PRG_deletefile"])
- if(!file || file.undeletable)
- return 1
- HDD.remove_file(file)
- if(href_list["PRG_usbdeletefile"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.portable_drive
- if(!RHDD)
- return 1
- var/datum/computer_file/file = RHDD.find_file_by_name(href_list["PRG_usbdeletefile"])
- if(!file || file.undeletable)
- return 1
- RHDD.remove_file(file)
- if(href_list["PRG_closefile"])
- . = 1
- open_file = null
- error = null
- if(href_list["PRG_clone"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/F = HDD.find_file_by_name(href_list["PRG_clone"])
- if(!F || !istype(F))
- return 1
- var/datum/computer_file/C = F.clone(1)
- HDD.store_file(C)
- if(href_list["PRG_rename"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/file = HDD.find_file_by_name(href_list["PRG_rename"])
- if(!file || !istype(file))
- return 1
- var/newname = sanitize(input(usr, "Enter new file name:", "File rename", file.filename))
- if(file && newname)
+ var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
+ var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.portable_drive
+
+ switch(action)
+ if("PRG_openfile")
+ open_file = params["name"]
+ return TRUE
+ if("PRG_newtextfile")
+ if(!HDD)
+ return
+ var/newname = sanitize(input(usr, "Enter file name or leave blank to cancel:", "File rename"))
+ if(!newname)
+ return
+ var/datum/computer_file/data/F = new/datum/computer_file/data()
+ F.filename = newname
+ F.filetype = "TXT"
+ HDD.store_file(F)
+ return TRUE
+ if("PRG_closefile")
+ open_file = null
+ error = null
+ return TRUE
+ if("PRG_clone")
+ if(!HDD)
+ return
+ var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
+ if(!F || !istype(F))
+ return
+ var/datum/computer_file/C = F.clone(1)
+ HDD.store_file(C)
+ return TRUE
+ if("PRG_edit")
+ if(!HDD)
+ return
+ if(!open_file)
+ return
+ var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
+ if(!F || !istype(F))
+ return
+ if(F.do_not_edit && (alert("WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", "No", "Yes") == "No"))
+ return
+
+ var/oldtext = html_decode(F.stored_data)
+ oldtext = replacetext(oldtext, "\[br\]", "\n")
+
+ var/newtext = sanitize(replacetext(input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", oldtext) as message|null, "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
+ if(!newtext)
+ return
+
+ if(F)
+ var/datum/computer_file/data/backup = F.clone()
+ HDD.remove_file(F)
+ F.stored_data = newtext
+ F.calculate_size()
+ // We can't store the updated file, it's probably too large. Print an error and restore backed up version.
+ // This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
+ // They will be able to copy-paste the text from error screen and store it in notepad or something.
+ if(!HDD.store_file(F))
+ error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:
[html_decode(F.stored_data)]
"
+ HDD.store_file(backup)
+ return TRUE
+ if("PRG_printfile")
+ if(!HDD)
+ return
+ if(!open_file)
+ return
+ var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
+ if(!F || !istype(F))
+ return
+ if(!computer.nano_printer)
+ error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
+ return
+ if(!computer.nano_printer.print_text(pencode2html(F.stored_data)))
+ error = "Hardware error: Printer was unable to print the file. It may be out of paper."
+ return
+ return TRUE
+ if("PRG_deletefile")
+ if(!HDD)
+ return
+ var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
+ if(!file || file.undeletable)
+ return
+ HDD.remove_file(file)
+ return TRUE
+ if("PRG_usbdeletefile")
+ if(!RHDD)
+ return
+ var/datum/computer_file/file = RHDD.find_file_by_name(params["name"])
+ if(!file || file.undeletable)
+ return
+ RHDD.remove_file(file)
+ return TRUE
+ if("PRG_rename")
+ if(!HDD)
+ return
+ var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
+ if(!file)
+ return
+ var/newname = params["new_name"]
+ if(!newname)
+ return
file.filename = newname
- if(href_list["PRG_edit"])
- . = 1
- if(!open_file)
- return 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
- if(!F || !istype(F))
- return 1
- if(F.do_not_edit && (alert("WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", "No", "Yes") == "No"))
- return 1
+ return TRUE
+ if("PRG_copytousb")
+ if(!HDD || !RHDD)
+ return
+ var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
+ if(!F)
+ return
+ var/datum/computer_file/C = F.clone(FALSE)
+ RHDD.store_file(C)
+ return TRUE
+ if("PRG_copyfromusb")
+ if(!HDD || !RHDD)
+ return
+ var/datum/computer_file/F = RHDD.find_file_by_name(params["name"])
+ if(!F || !istype(F))
+ return
+ var/datum/computer_file/C = F.clone(FALSE)
+ HDD.store_file(C)
+ return TRUE
- var/oldtext = html_decode(F.stored_data)
- oldtext = replacetext(oldtext, "\[br\]", "\n")
+/datum/computer_file/program/filemanager/tgui_data(mob/user)
+ var/list/data = get_header_data()
- var/newtext = sanitize(replacetext(input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", oldtext) as message|null, "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
- if(!newtext)
- return
+ var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.portable_drive
- if(F)
- var/datum/computer_file/data/backup = F.clone()
- HDD.remove_file(F)
- F.stored_data = newtext
- F.calculate_size()
- // We can't store the updated file, it's probably too large. Print an error and restore backed up version.
- // This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
- // They will be able to copy-paste the text from error screen and store it in notepad or something.
- if(!HDD.store_file(F))
- error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:
[html_decode(F.stored_data)]
"
- HDD.store_file(backup)
- if(href_list["PRG_printfile"])
- . = 1
- if(!open_file)
- return 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
- if(!F || !istype(F))
- return 1
- if(!computer.nano_printer)
- error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
- return 1
- if(!computer.nano_printer.print_text(pencode2html(F.stored_data)))
- error = "Hardware error: Printer was unable to print the file. It may be out of paper."
- return 1
- if(href_list["PRG_copytousb"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.portable_drive
- if(!HDD || !RHDD)
- return 1
- var/datum/computer_file/F = HDD.find_file_by_name(href_list["PRG_copytousb"])
- if(!F || !istype(F))
- return 1
- var/datum/computer_file/C = F.clone(0)
- RHDD.store_file(C)
- if(href_list["PRG_copyfromusb"])
- . = 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.portable_drive
- if(!HDD || !RHDD)
- return 1
- var/datum/computer_file/F = RHDD.find_file_by_name(href_list["PRG_copyfromusb"])
- if(!F || !istype(F))
- return 1
- var/datum/computer_file/C = F.clone(0)
- HDD.store_file(C)
- if(.)
- SSnanoui.update_uis(NM)
+ data["error"] = null
+ if(error)
+ data["error"] = error
+ if(!computer || !HDD)
+ data["error"] = "I/O ERROR: Unable to access hard drive."
+
+ data["filedata"] = null
+ data["filename"] = null
+ data["files"] = list()
+ data["usbconnected"] = FALSE
+ data["usbfiles"] = list()
-/datum/nano_module/program/computer_filemanager
- name = "NTOS File Manager"
-
-/datum/nano_module/program/computer_filemanager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = host.initial_data()
- var/datum/computer_file/program/filemanager/PRG
- PRG = program
-
- var/obj/item/weapon/computer_hardware/hard_drive/HDD
- var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD
- if(PRG.error)
- data["error"] = PRG.error
- if(PRG.open_file)
+ if(open_file)
var/datum/computer_file/data/file
- if(!PRG.computer || !PRG.computer.hard_drive)
+ if(!computer || !computer.hard_drive)
data["error"] = "I/O ERROR: Unable to access hard drive."
else
- HDD = PRG.computer.hard_drive
- file = HDD.find_file_by_name(PRG.open_file)
+ file = HDD.find_file_by_name(open_file)
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
else
data["filedata"] = pencode2html(file.stored_data)
data["filename"] = "[file.filename].[file.filetype]"
else
- if(!PRG.computer || !PRG.computer.hard_drive)
- data["error"] = "I/O ERROR: Unable to access hard drive."
- else
- HDD = PRG.computer.hard_drive
- RHDD = PRG.computer.portable_drive
- var/list/files[0]
- for(var/datum/computer_file/F in HDD.stored_files)
- files.Add(list(list(
+ var/list/files = list()
+ for(var/datum/computer_file/F in HDD.stored_files)
+ files += list(list(
+ "name" = F.filename,
+ "type" = F.filetype,
+ "size" = F.size,
+ "undeletable" = F.undeletable
+ ))
+ data["files"] = files
+ if(RHDD)
+ data["usbconnected"] = TRUE
+ var/list/usbfiles = list()
+ for(var/datum/computer_file/F in RHDD.stored_files)
+ usbfiles += list(list(
"name" = F.filename,
"type" = F.filetype,
"size" = F.size,
"undeletable" = F.undeletable
- )))
- data["files"] = files
- if(RHDD)
- data["usbconnected"] = 1
- var/list/usbfiles[0]
- for(var/datum/computer_file/F in RHDD.stored_files)
- usbfiles.Add(list(list(
- "name" = F.filename,
- "type" = F.filetype,
- "size" = F.size,
- "undeletable" = F.undeletable
- )))
- data["usbfiles"] = usbfiles
+ ))
+ data["usbfiles"] = usbfiles
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "file_manager.tmpl", "NTOS File Manager", 575, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
\ No newline at end of file
+ return data
diff --git a/code/modules/modular_computers/file_system/programs/generic/game.dm b/code/modules/modular_computers/file_system/programs/generic/game.dm
index b4c0688c29..4d21095f9d 100644
--- a/code/modules/modular_computers/file_system/programs/generic/game.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/game.dm
@@ -1,152 +1,188 @@
// This file is used as a reference for Modular Computers Development guide on the wiki. It contains a lot of excess comments, as it is intended as explanation
// for someone who may not be as experienced in coding. When making changes, please try to keep it this way.
-// An actual program definition.
/datum/computer_file/program/game
- filename = "arcadec" // File name, as shown in the file browser program.
- filedesc = "Unknown Game" // User-Friendly name. In this case, we will generate a random name in constructor.
- program_icon_state = "game" // Icon state of this program's screen.
- program_menu_icon = "script"
- extended_desc = "Fun for the whole family! Probably not an AAA title, but at least you can download it on the corporate network.." // A nice description.
- size = 5 // Size in GQ. Integers only. Smaller sizes should be used for utility/low use programs (like this one), while large sizes are for important programs.
- requires_ntnet = 0 // This particular program does not require NTNet network conectivity...
- available_on_ntnet = 1 // ... but we want it to be available for download.
- nanomodule_path = /datum/nano_module/arcade_classic/ // Path of relevant nano module. The nano module is defined further in the file.
- var/picked_enemy_name
+ filename = "dsarcade" // File name, as shown in the file browser program.
+ filedesc = "Donksoft Micro Arcade" // User-Friendly name.
+ program_icon_state = "arcade" // Icon state of this program's screen.
+ extended_desc = "This is a port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets; Now with thrilling graphics and chilling storytelling." // A nice description.
+ size = 6 // Size in GQ. Integers only. Smaller sizes should be used for utility/low use programs (like this one), while large sizes are for important programs.
+ requires_ntnet = FALSE // This particular program does not require NTNet network conectivity...
+ available_on_ntnet = TRUE // ... but we want it to be available for download.
+ tgui_id = "NtosArcade" // Path of relevant tgui template.js file.
-// Blatantly stolen and shortened version from arcade machines. Generates a random enemy name
-/datum/computer_file/program/game/proc/random_enemy_name()
- var/name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
- var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "Slime", "Lizard Man", "Unicorn")
- return "[name_part1] [name_part2]"
+ ///Returns TRUE if the game is being played.
+ var/game_active = TRUE
+ ///This disables buttom actions from having any impact if TRUE. Resets to FALSE when the player is allowed to make an action again.
+ var/pause_state = FALSE
+ var/boss_hp = 45
+ var/boss_mp = 15
+ var/player_hp = 30
+ var/player_mp = 10
+ var/ticket_count = 0
+ ///Shows what text is shown on the app, usually showing the log of combat actions taken by the player.
+ var/heads_up = "Nanotrasen says, winners make us money."
+ var/boss_name = "Cuban Pete's Minion"
+ ///Determines which boss image to use on the UI.
+ var/boss_id = 1
-// When the program is first created, we generate a new enemy name and name ourselves accordingly.
-/datum/computer_file/program/game/New()
- ..()
- picked_enemy_name = random_enemy_name()
- filedesc = "Defeat [picked_enemy_name]"
+// This is the primary game loop, which handles the logic of being defeated or winning.
+/datum/computer_file/program/game/proc/game_check(mob/user)
+ sleep(5)
+ if(boss_hp <= 0)
+ heads_up = "You have crushed [boss_name]! Rejoice!"
+ playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ game_active = FALSE
+ program_icon_state = "arcade_off"
+ if(istype(computer))
+ computer.update_icon()
+ ticket_count += 1
+ // user?.mind?.adjust_experience(/datum/skill/gaming, 50)
+ sleep(10)
+ else if(player_hp <= 0 || player_mp <= 0)
+ heads_up = "You have been defeated... how will the station survive?"
+ playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ game_active = FALSE
+ program_icon_state = "arcade_off"
+ if(istype(computer))
+ computer.update_icon()
+ // user?.mind?.adjust_experience(/datum/skill/gaming, 10)
+ sleep(10)
-// Important in order to ensure that copied versions will have the same enemy name.
-/datum/computer_file/program/game/clone()
- var/datum/computer_file/program/game/G = ..()
- G.picked_enemy_name = picked_enemy_name
- return G
-
-// When running the program, we also want to pass our enemy name to the nano module.
-/datum/computer_file/program/game/run_program()
- . = ..()
- if(. && NM)
- var/datum/nano_module/arcade_classic/NMC = NM
- NMC.enemy_name = picked_enemy_name
-
-
-// Nano module the program uses.
-// This can be either /datum/nano_module/ or /datum/nano_module/program. The latter is intended for nano modules that are suposed to be exclusively used with modular computers,
-// and should generally not be used, as such nano modules are hard to use on other places.
-/datum/nano_module/arcade_classic/
- name = "Classic Arcade"
- var/player_mana // Various variables specific to the nano module. In this case, the nano module is a simple arcade game, so the variables store health and other stats.
- var/player_health
- var/enemy_mana
- var/enemy_health
- var/enemy_name = "Greytide Horde"
- var/gameover
- var/information
-
-/datum/nano_module/arcade_classic/New()
- ..()
- new_game()
-
-// ui_interact handles transfer of data to NanoUI. Keep in mind that data you pass from here is actually sent to the client. In other words, don't send anything you don't want a client
-// to see, and don't send unnecessarily large amounts of data (due to laginess).
-/datum/nano_module/arcade_classic/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- var/list/data = host.initial_data()
-
- data["player_health"] = player_health
- data["player_mana"] = player_mana
- data["enemy_health"] = enemy_health
- data["enemy_mana"] = enemy_mana
- data["enemy_name"] = enemy_name
- data["gameover"] = gameover
- data["information"] = information
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "arcade_classic.tmpl", "Defeat [enemy_name]", 500, 350, state = state)
- if(host.update_layout())
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
-
-// Three helper procs i've created. These are unique to this particular nano module. If you are creating your own nano module, you'll most likely create similar procs too.
-/datum/nano_module/arcade_classic/proc/enemy_play()
- if((enemy_mana < 5) && prob(60))
- var/steal = rand(2, 3)
- player_mana -= steal
- enemy_mana += steal
- information += "[enemy_name] steals [steal] of your power!"
- else if((enemy_health < 15) && (enemy_mana > 3) && prob(80))
- var/healamt = min(rand(3, 5), enemy_mana)
- enemy_mana -= healamt
- enemy_health += healamt
- information += "[enemy_name] heals for [healamt] health!"
+// This handles the boss "AI".
+/datum/computer_file/program/game/proc/enemy_check(mob/user)
+ var/boss_attackamt = 0 //Spam protection from boss attacks as well.
+ var/boss_mpamt = 0
+ var/bossheal = 0
+ if(pause_state == TRUE)
+ boss_attackamt = rand(3,6)
+ boss_mpamt = rand (2,4)
+ bossheal = rand (4,6)
+ if(game_active == FALSE)
+ return
+ if(boss_mp <= 5)
+ heads_up = "[boss_mpamt] magic power has been stolen from you!"
+ playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ player_mp -= boss_mpamt
+ boss_mp += boss_mpamt
+ else if(boss_mp > 5 && boss_hp <12)
+ heads_up = "[boss_name] heals for [bossheal] health!"
+ playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ boss_hp += bossheal
+ boss_mp -= boss_mpamt
else
- var/dam = rand(3,6)
- player_health -= dam
- information += "[enemy_name] attacks for [dam] damage!"
+ heads_up = "[boss_name] attacks you for [boss_attackamt] damage!"
+ playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ player_hp -= boss_attackamt
-/datum/nano_module/arcade_classic/proc/check_gameover()
- if((player_health <= 0) || player_mana <= 0)
- if(enemy_health <= 0)
- information += "You have defeated [enemy_name], but you have died in the fight!"
- else
- information += "You have been defeated by [enemy_name]!"
- gameover = 1
+ pause_state = FALSE
+ game_check()
+
+/**
+ * UI assets define a list of asset datums to be sent with the UI.
+ * In this case, it's a bunch of cute enemy sprites.
+ */
+/datum/computer_file/program/game/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/simple/arcade),
+ )
+
+/**
+ * This provides all of the relevant data to the UI in a list().
+ */
+/datum/computer_file/program/game/tgui_data(mob/user)
+ var/list/data = get_header_data()
+ data["Hitpoints"] = boss_hp
+ data["PlayerHitpoints"] = player_hp
+ data["PlayerMP"] = player_mp
+ data["TicketCount"] = ticket_count
+ data["GameActive"] = game_active
+ data["PauseState"] = pause_state
+ data["Status"] = heads_up
+ data["BossID"] = "boss[boss_id].gif"
+ return data
+
+/**
+ * This is tgui's replacement for Topic(). It handles any user input from the UI.
+ */
+/datum/computer_file/program/game/tgui_act(action, list/params)
+ if(..()) // Always call parent in tgui_act, it handles making sure the user is allowed to interact with the UI.
return TRUE
- else if(enemy_health <= 0)
- gameover = 1
- information += "Congratulations! You have defeated [enemy_name]!"
- return TRUE
- return FALSE
-/datum/nano_module/arcade_classic/proc/new_game()
- player_mana = 10
- player_health = 30
- enemy_mana = 20
- enemy_health = 45
- gameover = FALSE
- information = "A new game has started!"
+ var/obj/item/weapon/computer_hardware/nano_printer/printer
+ if(computer)
+ printer = computer.nano_printer
-
-
-/datum/nano_module/arcade_classic/Topic(href, href_list)
- if(..()) // Always begin your Topic() calls with a parent call!
- return 1
- if(href_list["new_game"])
- new_game()
- return 1 // Returning 1 (TRUE) in Topic automatically handles UI updates.
- if(gameover) // If the game has already ended, we don't want the following three topic calls to be processed at all.
- return 1 // Instead of adding checks into each of those three, we can easily add this one check here to reduce on code copy-paste.
- if(href_list["attack"])
- var/damage = rand(2, 6)
- information = "You attack for [damage] damage."
- enemy_health -= damage
- enemy_play()
- check_gameover()
- return 1
- if(href_list["heal"])
- var/healfor = rand(6, 8)
- var/cost = rand(1, 3)
- information = "You heal yourself for [healfor] damage, using [cost] energy in the process."
- player_health += healfor
- player_mana -= cost
- enemy_play()
- check_gameover()
- return 1
- if(href_list["regain_mana"])
- var/regen = rand(4, 7)
- information = "You rest of a while, regaining [regen] energy."
- player_mana += regen
- enemy_play()
- check_gameover()
- return 1
\ No newline at end of file
+ // var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming)
+ // var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
+ switch(action)
+ if("Attack")
+ var/attackamt = 0 //Spam prevention.
+ if(pause_state == FALSE)
+ attackamt = rand(2,6) // + rand(0, gamerSkill)
+ pause_state = TRUE
+ heads_up = "You attack for [attackamt] damage."
+ playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ boss_hp -= attackamt
+ sleep(10)
+ game_check()
+ enemy_check()
+ return TRUE
+ if("Heal")
+ var/healamt = 0 //More Spam Prevention.
+ var/healcost = 0
+ if(pause_state == FALSE)
+ healamt = rand(6,8) // + rand(0, gamerSkill)
+ var/maxPointCost = 3
+ // if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN)
+ // maxPointCost = 2
+ healcost = rand(1, maxPointCost)
+ pause_state = TRUE
+ heads_up = "You heal for [healamt] damage."
+ playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ player_hp += healamt
+ player_mp -= healcost
+ sleep(10)
+ game_check()
+ enemy_check()
+ return TRUE
+ if("Recharge_Power")
+ var/rechargeamt = 0 //As above.
+ if(pause_state == FALSE)
+ rechargeamt = rand(4,7) // + rand(0, gamerSkill)
+ pause_state = TRUE
+ heads_up = "You regain [rechargeamt] magic power."
+ playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10)
+ player_mp += rechargeamt
+ sleep(10)
+ game_check()
+ enemy_check()
+ return TRUE
+ if("Dispense_Tickets")
+ if(!printer)
+ to_chat(usr, "Hardware error: A printer is required to redeem tickets.")
+ return
+ if(printer.stored_paper <= 0)
+ to_chat(usr, "Hardware error: Printer is out of paper.")
+ return
+ else
+ computer.visible_message("\The [computer] prints out paper.")
+ if(ticket_count >= 1)
+ new /obj/item/stack/arcadeticket((get_turf(computer)), 1)
+ to_chat(usr, "[src] dispenses a ticket!")
+ ticket_count -= 1
+ printer.stored_paper -= 1
+ else
+ to_chat(usr, "You don't have any stored tickets!")
+ return TRUE
+ if("Start_Game")
+ game_active = TRUE
+ boss_hp = 45
+ player_hp = 30
+ player_mp = 10
+ heads_up = "You stand before [boss_name]! Prepare for battle!"
+ program_icon_state = "arcade"
+ boss_id = rand(1,6)
+ pause_state = FALSE
+ if(istype(computer))
+ computer.update_icon()
diff --git a/code/modules/modular_computers/file_system/programs/generic/news_browser.dm b/code/modules/modular_computers/file_system/programs/generic/news_browser.dm
index 1d4da6d4d5..e72e30fd38 100644
--- a/code/modules/modular_computers/file_system/programs/generic/news_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/news_browser.dm
@@ -6,16 +6,17 @@
program_key_state = "generic_key"
program_menu_icon = "contact"
size = 4
- requires_ntnet = 1
- available_on_ntnet = 1
+ requires_ntnet = TRUE
+ available_on_ntnet = TRUE
+
+ tgui_id = "NtosNewsBrowser"
- nanomodule_path = /datum/nano_module/program/computer_newsbrowser/
var/datum/computer_file/data/news_article/loaded_article
var/download_progress = 0
var/download_netspeed = 0
- var/downloading = 0
+ var/downloading = FALSE
var/message = ""
- var/show_archived = 0
+ var/show_archived = FALSE
/datum/computer_file/program/newsbrowser/process_tick()
if(!downloading)
@@ -33,86 +34,31 @@
if(download_progress >= loaded_article.size)
downloading = 0
requires_ntnet = 0 // Turn off NTNet requirement as we already loaded the file into local memory.
- SSnanoui.update_uis(NM)
+ SStgui.update_uis(src)
-/datum/computer_file/program/newsbrowser/kill_program()
- ..()
- requires_ntnet = 1
- loaded_article = null
- download_progress = 0
- downloading = 0
- show_archived = 0
+/datum/computer_file/program/newsbrowser/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
+ var/list/data = get_header_data()
-/datum/computer_file/program/newsbrowser/Topic(href, href_list)
- if(..())
- return 1
- if(href_list["PRG_openarticle"])
- . = 1
- if(downloading || loaded_article)
- return 1
-
- for(var/datum/computer_file/data/news_article/N in ntnet_global.available_news)
- if(N.uid == text2num(href_list["PRG_openarticle"]))
- loaded_article = N.clone()
- downloading = 1
- break
- if(href_list["PRG_reset"])
- . = 1
- downloading = 0
- download_progress = 0
- requires_ntnet = 1
- loaded_article = null
- if(href_list["PRG_clearmessage"])
- . = 1
- message = ""
- if(href_list["PRG_savearticle"])
- . = 1
- if(downloading || !loaded_article)
- return
-
- var/savename = sanitize(input(usr, "Enter file name or leave blank to cancel:", "Save article", loaded_article.filename))
- if(!savename)
- return 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- if(!HDD)
- return 1
- var/datum/computer_file/data/news_article/N = loaded_article.clone()
- N.filename = savename
- HDD.store_file(N)
- if(href_list["PRG_toggle_archived"])
- . = 1
- show_archived = !show_archived
- if(.)
- SSnanoui.update_uis(NM)
-
-
-/datum/nano_module/program/computer_newsbrowser
- name = "NTNet/ExoNet News Browser"
-
-/datum/nano_module/program/computer_newsbrowser/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
-
- var/datum/computer_file/program/newsbrowser/PRG
- var/list/data = list()
- if(program)
- data = program.get_header_data()
- PRG = program
- else
- return
-
- data["message"] = PRG.message
- if(PRG.loaded_article && !PRG.downloading) // Viewing an article.
- data["title"] = PRG.loaded_article.filename
- data["cover"] = PRG.loaded_article.cover
- data["article"] = PRG.loaded_article.stored_data
- else if(PRG.downloading) // Downloading an article.
- data["download_running"] = 1
- data["download_progress"] = PRG.download_progress
- data["download_maxprogress"] = PRG.loaded_article.size
- data["download_rate"] = PRG.download_netspeed
+ var/list/all_articles = list()
+ data["message"] = message
+ data["showing_archived"] = show_archived
+ data["download"] = null
+ data["article"] = null
+ if(loaded_article && !downloading) // Viewing an article.
+ data["article"] = list(
+ "title" = loaded_article.filename,
+ "cover" = loaded_article.cover,
+ "content" = loaded_article.stored_data,
+ )
+ else if(downloading) // Downloading an article.
+ data["download"] = list(
+ "download_progress" = download_progress,
+ "download_maxprogress" = loaded_article.size,
+ "download_rate" = download_netspeed
+ )
else // Viewing list of articles
- var/list/all_articles[0]
for(var/datum/computer_file/data/news_article/F in ntnet_global.available_news)
- if(!PRG.show_archived && F.archived)
+ if(!show_archived && F.archived)
continue
all_articles.Add(list(list(
"name" = F.filename,
@@ -120,12 +66,56 @@
"uid" = F.uid,
"archived" = F.archived
)))
- data["all_articles"] = all_articles
- data["showing_archived"] = PRG.show_archived
+ data["all_articles"] = all_articles
+
+ return data
+
+/datum/computer_file/program/newsbrowser/kill_program()
+ ..()
+ requires_ntnet = TRUE
+ loaded_article = null
+ download_progress = 0
+ downloading = FALSE
+ show_archived = FALSE
+
+/datum/computer_file/program/newsbrowser/tgui_act(action, list/params, datum/tgui/ui)
+ if(..())
+ return TRUE
+ switch(action)
+ if("PRG_openarticle")
+ . = TRUE
+ if(downloading || loaded_article)
+ return TRUE
+
+ for(var/datum/computer_file/data/news_article/N in ntnet_global.available_news)
+ if(N.uid == text2num(params["uid"]))
+ loaded_article = N.clone()
+ downloading = 1
+ break
+ if("PRG_reset")
+ . = TRUE
+ downloading = 0
+ download_progress = 0
+ requires_ntnet = 1
+ loaded_article = null
+ if("PRG_clearmessage")
+ . = TRUE
+ message = ""
+ if("PRG_savearticle")
+ . = TRUE
+ if(downloading || !loaded_article)
+ return
+
+ var/savename = sanitize(input(usr, "Enter file name or leave blank to cancel:", "Save article", loaded_article.filename))
+ if(!savename)
+ return TRUE
+ var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
+ if(!HDD)
+ return TRUE
+ var/datum/computer_file/data/news_article/N = loaded_article.clone()
+ N.filename = savename
+ HDD.store_file(N)
+ if("PRG_toggle_archived")
+ . = TRUE
+ show_archived = !show_archived
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "news_browser.tmpl", "NTNet/ExoNet News Browser", 575, 750, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
diff --git a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm
index a0b2194168..14e2343e66 100644
--- a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm
@@ -5,29 +5,26 @@
program_key_state = "generic_key"
program_menu_icon = "arrowthickstop-1-s"
extended_desc = "This program allows downloads of software from official NT repositories"
- unsendable = 1
- undeletable = 1
+ unsendable = TRUE
+ undeletable = TRUE
size = 4
- requires_ntnet = 1
+ requires_ntnet = TRUE
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
- available_on_ntnet = 0
- nanomodule_path = /datum/nano_module/program/computer_ntnetdownload/
+ available_on_ntnet = FALSE
ui_header = "downloader_finished.gif"
+ tgui_id = "NtosNetDownloader"
+
var/datum/computer_file/program/downloaded_file = null
var/hacked_download = 0
var/download_completion = 0 //GQ of downloaded data.
var/download_netspeed = 0
var/downloaderror = ""
+ var/obj/item/modular_computer/my_computer = null
var/list/downloads_queue[0]
/datum/computer_file/program/ntnetdownload/kill_program()
..()
- downloaded_file = null
- download_completion = 0
- download_netspeed = 0
- downloaderror = ""
- ui_header = "downloader_finished.gif"
-
+ abort_file_download()
/datum/computer_file/program/ntnetdownload/proc/begin_file_download(var/filename)
if(downloaded_file)
@@ -108,93 +105,85 @@
download_netspeed = NTNETSPEED_ETHERNET
download_completion += download_netspeed
-/datum/computer_file/program/ntnetdownload/Topic(href, href_list)
+/datum/computer_file/program/ntnetdownload/tgui_act(action, params)
if(..())
- return 1
- if(href_list["PRG_downloadfile"])
- if(!downloaded_file)
- begin_file_download(href_list["PRG_downloadfile"])
- else if(check_file_download(href_list["PRG_downloadfile"]) && !downloads_queue.Find(href_list["PRG_downloadfile"]) && downloaded_file.filename != href_list["PRG_downloadfile"])
- downloads_queue += href_list["PRG_downloadfile"]
- return 1
- if(href_list["PRG_removequeued"])
- downloads_queue.Remove(href_list["PRG_removequeued"])
- return 1
- if(href_list["PRG_reseterror"])
- if(downloaderror)
- download_completion = 0
- download_netspeed = 0
- downloaded_file = null
- downloaderror = ""
- return 1
- return 0
-
-/datum/nano_module/program/computer_ntnetdownload
- name = "Network Downloader"
- var/obj/item/modular_computer/my_computer = null
-
-/datum/nano_module/program/computer_ntnetdownload/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- if(program)
- my_computer = program.computer
+ return TRUE
+ switch(action)
+ if("PRG_downloadfile")
+ if(!downloaded_file)
+ begin_file_download(params["filename"])
+ else if(check_file_download(params["filename"]) && !downloads_queue.Find(params["filename"]) && downloaded_file.filename != params["filename"])
+ downloads_queue += params["filename"]
+ return TRUE
+ if("PRG_removequeued")
+ downloads_queue.Remove(params["filename"])
+ return TRUE
+ if("PRG_reseterror")
+ if(downloaderror)
+ download_completion = 0
+ download_netspeed = 0
+ downloaded_file = null
+ downloaderror = ""
+ return TRUE
+ return FALSE
+/datum/computer_file/program/ntnetdownload/tgui_data(mob/user)
+ my_computer = computer
if(!istype(my_computer))
return
- var/list/data = list()
- var/datum/computer_file/program/ntnetdownload/prog = program
- // For now limited to execution by the downloader program
- if(!prog || !istype(prog))
- return
- if(program)
- data = program.get_header_data()
+ var/list/data = get_header_data()
- // This IF cuts on data transferred to client, so i guess it's worth it.
- if(prog.downloaderror) // Download errored. Wait until user resets the program.
- data["error"] = prog.downloaderror
- if(prog.downloaded_file) // Download running. Wait please..
- data["downloadname"] = prog.downloaded_file.filename
- data["downloaddesc"] = prog.downloaded_file.filedesc
- data["downloadsize"] = prog.downloaded_file.size
- data["downloadspeed"] = prog.download_netspeed
- data["downloadcompletion"] = round(prog.download_completion, 0.1)
+ data["downloading"] = !!downloaded_file
+ data["error"] = downloaderror || FALSE
+
+ if(downloaded_file) // Download running. Wait please..
+ data["downloadname"] = downloaded_file.filename
+ data["downloaddesc"] = downloaded_file.filedesc
+ data["downloadsize"] = downloaded_file.size
+ data["downloadspeed"] = download_netspeed
+ data["downloadcompletion"] = round(download_completion, 0.1)
data["disk_size"] = my_computer.hard_drive.max_capacity
data["disk_used"] = my_computer.hard_drive.used_capacity
var/list/all_entries[0]
for(var/datum/computer_file/program/P in ntnet_global.available_station_software)
// Only those programs our user can run will show in the list
- if(!P.can_run(user) && P.requires_access_to_download)
+ if(!P.can_run(user) && P.requires_access_to_download || my_computer.hard_drive.find_file_by_name(P.filename))
continue
all_entries.Add(list(list(
- "filename" = P.filename,
- "filedesc" = P.filedesc,
- "fileinfo" = P.extended_desc,
- "size" = P.size,
- "icon" = P.program_menu_icon
- )))
- data["hackedavailable"] = 0
- if(prog.computer_emagged) // If we are running on emagged computer we have access to some "bonus" software
- var/list/hacked_programs[0]
- for(var/datum/computer_file/program/P in ntnet_global.available_antag_software)
- data["hackedavailable"] = 1
- hacked_programs.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
+ "compatibility" = check_compatibility(P),
"size" = P.size,
"icon" = P.program_menu_icon
+ )))
+ data["hackedavailable"] = FALSE
+ if(computer_emagged) // If we are running on emagged computer we have access to some "bonus" software
+ var/list/hacked_programs[0]
+ for(var/datum/computer_file/program/P in ntnet_global.available_antag_software)
+ if(my_computer.hard_drive.find_file_by_name(P.filename))
+ continue
+ data["hackedavailable"] = TRUE
+ hacked_programs.Add(list(list(
+ "filename" = P.filename,
+ "filedesc" = P.filedesc,
+ "fileinfo" = P.extended_desc,
+ "compatibility" = check_compatibility(P),
+ "size" = P.size,
+ "icon" = P.program_menu_icon
)))
data["hacked_programs"] = hacked_programs
data["downloadable_programs"] = all_entries
+ data["downloads_queue"] = downloads_queue
- if(prog.downloads_queue.len > 0)
- data["downloads_queue"] = prog.downloads_queue
+ return data
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "ntnet_downloader.tmpl", "NTNet Download Program", 575, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+/datum/computer_file/program/ntnetdownload/proc/check_compatibility(datum/computer_file/program/P)
+ var/hardflag = computer.hardware_flag
+
+ if(P && P.is_supported_by_hardware(hardflag,0))
+ return "Compatible"
+ return "Incompatible!"
diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
index 6c67c02c0d..f2466213f3 100644
--- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm
@@ -11,222 +11,220 @@
network_destination = "NTNRC server"
ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1
- nanomodule_path = /datum/nano_module/program/computer_chatclient/
- var/last_message = null // Used to generate the toolbar icon
+ tgui_id = "NtosNetChat"
+ var/last_message // Used to generate the toolbar icon
var/username
- var/datum/ntnet_conversation/channel = null
- var/operator_mode = 0 // Channel operator mode
- var/netadmin_mode = 0 // Administrator mode (invisible to other users + bypasses passwords)
+ var/active_channel
+ var/list/channel_history = list()
+ var/operator_mode = FALSE // Channel operator mode
+ var/netadmin_mode = FALSE // Administrator mode (invisible to other users + bypasses passwords)
/datum/computer_file/program/chatclient/New()
username = "DefaultUser[rand(100, 999)]"
-/datum/computer_file/program/chatclient/Topic(href, href_list)
+/datum/computer_file/program/chatclient/tgui_act(action, params)
if(..())
- return 1
+ return
- if(href_list["PRG_speak"])
- . = 1
- if(!channel)
- return 1
- var/mob/living/user = usr
- var/message = sanitize(input(user, "Enter message or leave blank to cancel: "), 512)
- if(!message || !channel)
- return
- channel.add_message(message, username)
+ var/datum/ntnet_conversation/channel = ntnet_global.get_chat_channel_by_id(active_channel)
+ var/authed = FALSE
+ if(channel && ((channel.operator == src) || netadmin_mode))
+ authed = TRUE
+ switch(action)
+ if("PRG_speak")
+ if(!channel || isnull(active_channel))
+ return
+ var/message = reject_bad_text(params["message"])
+ if(!message)
+ return
+ if(channel.password && !(src in channel.clients))
+ if(channel.password == message)
+ channel.add_client(src)
+ return TRUE
- if(href_list["PRG_joinchannel"])
- . = 1
- var/datum/ntnet_conversation/C
- for(var/datum/ntnet_conversation/chan in ntnet_global.chat_channels)
- if(chan.id == text2num(href_list["PRG_joinchannel"]))
- C = chan
- break
+ channel.add_message(message, username)
+ // var/mob/living/user = usr
+ // user.log_talk(message, LOG_CHAT, tag="as [username] to channel [channel.title]")
+ return TRUE
+ if("PRG_joinchannel")
+ var/new_target = text2num(params["id"])
+ if(isnull(new_target) || new_target == active_channel)
+ return
- if(!C)
- return 1
+ if(netadmin_mode)
+ active_channel = new_target // Bypasses normal leave/join and passwords. Technically makes the user invisible to others.
+ return TRUE
- if(netadmin_mode)
- channel = C // Bypasses normal leave/join and passwords. Technically makes the user invisible to others.
- return 1
-
- if(C.password)
+ active_channel = new_target
+ channel = ntnet_global.get_chat_channel_by_id(new_target)
+ if(!(src in channel.clients) && !channel.password)
+ channel.add_client(src)
+ return TRUE
+ if("PRG_leavechannel")
+ if(channel)
+ channel.remove_client(src)
+ active_channel = null
+ return TRUE
+ if("PRG_newchannel")
+ var/channel_title = reject_bad_text(params["new_channel_name"])
+ if(!channel_title)
+ return
+ var/datum/ntnet_conversation/C = new /datum/ntnet_conversation()
+ C.add_client(src)
+ C.operator = src
+ C.title = channel_title
+ active_channel = C.id
+ return TRUE
+ if("PRG_toggleadmin")
+ if(netadmin_mode)
+ netadmin_mode = FALSE
+ if(channel)
+ channel.remove_client(src) // We shouldn't be in channel's user list, but just in case...
+ return TRUE
var/mob/living/user = usr
- var/password = sanitize(input(user,"Access Denied. Enter password:"))
- if(C && (password == C.password))
- C.add_client(src)
- channel = C
- return 1
- C.add_client(src)
- channel = C
- if(href_list["PRG_leavechannel"])
- . = 1
- if(channel)
- channel.remove_client(src)
- channel = null
- if(href_list["PRG_newchannel"])
- . = 1
- var/mob/living/user = usr
- var/channel_title = sanitizeSafe(input(user,"Enter channel name or leave blank to cancel:"), 64)
- if(!channel_title)
- return
- var/datum/ntnet_conversation/C = new/datum/ntnet_conversation()
- C.add_client(src)
- C.operator = src
- channel = C
- C.title = channel_title
- if(href_list["PRG_toggleadmin"])
- . = 1
- if(netadmin_mode)
- netadmin_mode = 0
- if(channel)
- channel.remove_client(src) // We shouldn't be in channel's user list, but just in case...
- channel = null
- return 1
- var/mob/living/user = usr
- if(can_run(usr, 1, access_network))
- if(channel)
- var/response = alert(user, "Really engage admin-mode? You will be disconnected from your current channel!", "NTNRC Admin mode", "Yes", "No")
- if(response == "Yes")
- if(channel)
- channel.remove_client(src)
- channel = null
- else
- return
- netadmin_mode = 1
- if(href_list["PRG_changename"])
- . = 1
- var/mob/living/user = usr
- var/newname = sanitize(input(user,"Enter new nickname or leave blank to cancel:"), 20)
- if(!newname)
- return 1
- if(channel)
- channel.add_status_message("[username] is now known as [newname].")
- username = newname
+ if(can_run(user, TRUE, access_network))
+ for(var/C in ntnet_global.chat_channels)
+ var/datum/ntnet_conversation/chan = C
+ chan.remove_client(src)
+ netadmin_mode = TRUE
+ return TRUE
+ if("PRG_changename")
+ var/newname = sanitize(params["new_name"])
+ if(!newname)
+ return
+ for(var/C in ntnet_global.chat_channels)
+ var/datum/ntnet_conversation/chan = C
+ if(src in chan.clients)
+ chan.add_status_message("[username] is now known as [newname].")
+ username = newname
+ return TRUE
+ if("PRG_savelog")
+ if(!channel)
+ return
+ var/logname = stripped_input(params["log_name"])
+ if(!logname)
+ return
+ var/datum/computer_file/data/logfile = new /datum/computer_file/data/logfile()
+ // Now we will generate HTML-compliant file that can actually be viewed/printed.
+ logfile.filename = logname
+ logfile.stored_data = "\[b\]Logfile dump from NTNRC channel [channel.title]\[/b\]\[BR\]"
+ for(var/logstring in channel.messages)
+ logfile.stored_data = "[logfile.stored_data][logstring]\[BR\]"
+ logfile.stored_data = "[logfile.stored_data]\[b\]Logfile dump completed.\[/b\]"
+ logfile.calculate_size()
+ if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(logfile))
+ if(!computer)
+ // This program shouldn't even be runnable without computer.
+ CRASH("Var computer is null!")
+ if(!computer.hard_drive)
+ computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.")
+ else // In 99.9% cases this will mean our HDD is full
+ computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.")
+ return TRUE
+ if("PRG_renamechannel")
+ if(!authed)
+ return
+ var/newname = reject_bad_text(params["new_name"])
+ if(!newname || !channel)
+ return
+ channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
+ channel.title = newname
+ return TRUE
+ if("PRG_deletechannel")
+ if(authed)
+ qdel(channel)
+ active_channel = null
+ return TRUE
+ if("PRG_setpassword")
+ if(!authed)
+ return
- if(href_list["PRG_savelog"])
- . = 1
- if(!channel)
- return
- var/mob/living/user = usr
- var/logname = input(user,"Enter desired logfile name (.log) or leave blank to cancel:")
- if(!logname || !channel)
- return 1
- var/datum/computer_file/data/logfile = new/datum/computer_file/data/logfile()
- // Now we will generate HTML-compliant file that can actually be viewed/printed.
- logfile.filename = logname
- logfile.stored_data = "\[b\]Logfile dump from NTNRC channel [channel.title]\[/b\]\[BR\]"
- for(var/logstring in channel.messages)
- logfile.stored_data += "[logstring]\[BR\]"
- logfile.stored_data += "\[b\]Logfile dump completed.\[/b\]"
- logfile.calculate_size()
- if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(logfile))
- if(!computer)
- // This program shouldn't even be runnable without computer.
- CRASH("Var computer is null!")
- return 1
- if(!computer.hard_drive)
- computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.")
- else // In 99.9% cases this will mean our HDD is full
- computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.")
- if(href_list["PRG_renamechannel"])
- . = 1
- if(!operator_mode || !channel)
- return 1
- var/mob/living/user = usr
- var/newname = sanitize(input(user, "Enter new channel name or leave blank to cancel:"), 64)
- if(!newname || !channel)
- return
- channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
- channel.title = newname
- if(href_list["PRG_deletechannel"])
- . = 1
- if(channel && ((channel.operator == src) || netadmin_mode))
- qdel(channel)
- channel = null
- if(href_list["PRG_setpassword"])
- . = 1
- if(!channel || ((channel.operator != src) && !netadmin_mode))
- return 1
+ var/new_password = sanitize(params["new_password"])
+ if(!authed)
+ return
- var/mob/living/user = usr
- var/newpassword = sanitize(input(user, "Enter new password for this channel. Leave blank to cancel, enter 'nopassword' to remove password completely:"))
- if(!channel || !newpassword || ((channel.operator != src) && !netadmin_mode))
- return 1
-
- if(newpassword == "nopassword")
- channel.password = ""
- else
- channel.password = newpassword
+ channel.password = new_password
+ return TRUE
/datum/computer_file/program/chatclient/process_tick()
..()
+ var/datum/ntnet_conversation/channel = ntnet_global.get_chat_channel_by_id(active_channel)
if(program_state != PROGRAM_STATE_KILLED)
ui_header = "ntnrc_idle.gif"
if(channel)
// Remember the last message. If there is no message in the channel remember null.
- last_message = channel.messages.len ? channel.messages[channel.messages.len - 1] : null
+ last_message = length(channel.messages) ? channel.messages[channel.messages.len - 1] : null
else
last_message = null
return 1
- if(channel && channel.messages && channel.messages.len)
+ if(channel?.messages?.len)
ui_header = last_message == channel.messages[channel.messages.len - 1] ? "ntnrc_idle.gif" : "ntnrc_new.gif"
else
ui_header = "ntnrc_idle.gif"
-/datum/computer_file/program/chatclient/kill_program(var/forced = 0)
- if(channel)
+/datum/computer_file/program/chatclient/kill_program(forced = FALSE)
+ for(var/C in ntnet_global.chat_channels)
+ var/datum/ntnet_conversation/channel = C
channel.remove_client(src)
- channel = null
- ..(forced)
-
-/datum/nano_module/program/computer_chatclient
- name = "NTNet Relay Chat Client"
-
-/datum/nano_module/program/computer_chatclient/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- if(!ntnet_global || !ntnet_global.chat_channels)
- return
+ ..()
+/datum/computer_file/program/chatclient/tgui_static_data(mob/user)
var/list/data = list()
- if(program)
- data = program.get_header_data()
+ data["can_admin"] = can_run(user, FALSE, access_network)
+ return data
+
+/datum/computer_file/program/chatclient/tgui_data(mob/user)
+ if(!ntnet_global || !ntnet_global.chat_channels)
+ return list()
- var/datum/computer_file/program/chatclient/C = program
- if(!istype(C))
- return
+ var/list/data = get_header_data()
- data["adminmode"] = C.netadmin_mode
- if(C.channel)
- data["title"] = C.channel.title
- var/list/messages[0]
- for(var/M in C.channel.messages)
- messages.Add(list(list(
- "msg" = M
+ var/list/all_channels = list()
+ for(var/C in ntnet_global.chat_channels)
+ var/datum/ntnet_conversation/conv = C
+ if(conv && conv.title)
+ all_channels.Add(list(list(
+ "chan" = conv.title,
+ "id" = conv.id
)))
- data["messages"] = messages
- var/list/clients[0]
- for(var/datum/computer_file/program/chatclient/cl in C.channel.clients)
+ data["all_channels"] = all_channels
+
+ data["active_channel"] = active_channel
+ data["username"] = username
+ data["adminmode"] = netadmin_mode
+ var/datum/ntnet_conversation/channel = ntnet_global.get_chat_channel_by_id(active_channel)
+ if(channel)
+ data["title"] = channel.title
+ var/authed = FALSE
+ if(!channel.password)
+ authed = TRUE
+ if(netadmin_mode)
+ authed = TRUE
+ var/list/clients = list()
+ for(var/C in channel.clients)
+ if(C == src)
+ authed = TRUE
+ var/datum/computer_file/program/chatclient/cl = C
clients.Add(list(list(
"name" = cl.username
)))
- data["clients"] = clients
- C.operator_mode = (C.channel.operator == C) ? 1 : 0
- data["is_operator"] = C.operator_mode || C.netadmin_mode
-
- else // Channel selection screen
- var/list/all_channels[0]
- for(var/datum/ntnet_conversation/conv in ntnet_global.chat_channels)
- if(conv && conv.title)
- all_channels.Add(list(list(
- "chan" = conv.title,
- "id" = conv.id
+ data["authed"] = authed
+ //no fishing for ui data allowed
+ if(authed)
+ data["clients"] = clients
+ var/list/messages = list()
+ for(var/M in channel.messages)
+ messages.Add(list(list(
+ "msg" = M
)))
- data["all_channels"] = all_channels
+ data["messages"] = messages
+ data["is_operator"] = (channel.operator == src) || netadmin_mode
+ else
+ data["clients"] = list()
+ data["messages"] = list()
+ else
+ data["clients"] = list()
+ data["authed"] = FALSE
+ data["messages"] = list()
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "ntnet_chat.tmpl", "NTNet Relay Chat Client", 575, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ return data
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm b/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm
index 0efed986ae..ea88d3597e 100644
--- a/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm
@@ -12,7 +12,7 @@ var/global/nttransfer_uid = 0
requires_ntnet_feature = NTNET_PEERTOPEER
network_destination = "other device via P2P tunnel"
available_on_ntnet = 1
- nanomodule_path = /datum/nano_module/program/computer_nttransfer/
+ tgui_id = "NtosNetTransfer"
var/error = "" // Error screen
var/server_password = "" // Optional password to download the file.
@@ -75,111 +75,101 @@ var/global/nttransfer_uid = 0
remote = null
download_completion = 0
+/datum/computer_file/program/nttransfer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
+ var/list/data = get_header_data()
-/datum/nano_module/program/computer_nttransfer
- name = "NTNet P2P Transfer Client"
+ data["error"] = error
-/datum/nano_module/program/computer_nttransfer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
- if(!program)
- return
- var/datum/computer_file/program/nttransfer/PRG = program
- if(!istype(PRG))
- return
-
- var/list/data = program.get_header_data()
-
- if(PRG.error)
- data["error"] = PRG.error
- else if(PRG.downloaded_file)
- data["downloading"] = 1
- data["download_size"] = PRG.downloaded_file.size
- data["download_progress"] = PRG.download_completion
- data["download_netspeed"] = PRG.actual_netspeed
- data["download_name"] = "[PRG.downloaded_file.filename].[PRG.downloaded_file.filetype]"
- else if (PRG.provided_file)
- data["uploading"] = 1
- data["upload_uid"] = PRG.unique_token
- data["upload_clients"] = PRG.connected_clients.len
- data["upload_haspassword"] = PRG.server_password ? 1 : 0
- data["upload_filename"] = "[PRG.provided_file.filename].[PRG.provided_file.filetype]"
- else if (PRG.upload_menu)
- var/list/all_files[0]
- for(var/datum/computer_file/F in PRG.computer.hard_drive.stored_files)
+ data["downloading"] = !!downloaded_file
+ if(downloaded_file)
+ data["download_size"] = downloaded_file.size
+ data["download_progress"] = download_completion
+ data["download_netspeed"] = actual_netspeed
+ data["download_name"] = "[downloaded_file.filename].[downloaded_file.filetype]"
+
+ data["uploading"] = !!provided_file
+ if(provided_file)
+ data["upload_uid"] = unique_token
+ data["upload_clients"] = connected_clients.len
+ data["upload_haspassword"] = server_password ? 1 : 0
+ data["upload_filename"] = "[provided_file.filename].[provided_file.filetype]"
+
+ data["upload_filelist"] = list()
+ if(upload_menu)
+ var/list/all_files = list()
+ for(var/datum/computer_file/F in computer.hard_drive.stored_files)
all_files.Add(list(list(
"uid" = F.uid,
"filename" = "[F.filename].[F.filetype]",
"size" = F.size
)))
data["upload_filelist"] = all_files
- else
- var/list/all_servers[0]
+
+ data["servers"] = list()
+ if(!(downloaded_file || provided_file || upload_menu))
+ var/list/all_servers = list()
for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers)
if(!P.provided_file)
continue
all_servers.Add(list(list(
- "uid" = P.unique_token,
- "filename" = "[P.provided_file.filename].[P.provided_file.filetype]",
- "size" = P.provided_file.size,
- "haspassword" = P.server_password ? 1 : 0
+ "uid" = P.unique_token,
+ "filename" = "[P.provided_file.filename].[P.provided_file.filetype]",
+ "size" = P.provided_file.size,
+ "haspassword" = P.server_password ? 1 : 0
)))
data["servers"] = all_servers
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "ntnet_transfer.tmpl", "NTNet P2P Transfer Client", 575, 700, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ return data
-/datum/computer_file/program/nttransfer/Topic(href, href_list)
+/datum/computer_file/program/nttransfer/tgui_act(action, list/params, datum/tgui/ui)
if(..())
- return 1
- if(href_list["PRG_downloadfile"])
- for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers)
- if("[P.unique_token]" == href_list["PRG_downloadfile"])
- remote = P
- break
- if(!remote || !remote.provided_file)
- return
- if(remote.server_password)
- var/pass = sanitize(input(usr, "Code 401 Unauthorized. Please enter password:", "Password required"))
- if(pass != remote.server_password)
- error = "Incorrect Password"
+ return TRUE
+ switch(action)
+ if("PRG_downloadfile")
+ for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers)
+ if(P.unique_token == text2num(params["uid"]))
+ remote = P
+ break
+ if(!remote || !remote.provided_file)
return
- downloaded_file = remote.provided_file.clone()
- remote.connected_clients.Add(src)
- return 1
- if(href_list["PRG_reset"])
- error = ""
- upload_menu = 0
- finalize_download()
- if(src in ntnet_global.fileservers)
- ntnet_global.fileservers.Remove(src)
- for(var/datum/computer_file/program/nttransfer/T in connected_clients)
- T.crash_download("Remote server has forcibly closed the connection")
- provided_file = null
- return 1
- if(href_list["PRG_setpassword"])
- var/pass = sanitize(input(usr, "Enter new server password. Leave blank to cancel, input 'none' to disable password.", "Server security", "none"))
- if(!pass)
- return
- if(pass == "none")
- server_password = ""
- return
- server_password = pass
- return 1
- if(href_list["PRG_uploadfile"])
- for(var/datum/computer_file/F in computer.hard_drive.stored_files)
- if("[F.uid]" == href_list["PRG_uploadfile"])
- if(F.unsendable)
- error = "I/O Error: File locked."
+ if(remote.server_password)
+ var/pass = sanitize(input(usr, "Code 401 Unauthorized. Please enter password:", "Password required"))
+ if(pass != remote.server_password)
+ error = "Incorrect Password"
return
- provided_file = F
- ntnet_global.fileservers.Add(src)
+ downloaded_file = remote.provided_file.clone()
+ remote.connected_clients.Add(src)
+ return TRUE
+ if("PRG_reset")
+ error = ""
+ upload_menu = 0
+ finalize_download()
+ if(src in ntnet_global.fileservers)
+ ntnet_global.fileservers.Remove(src)
+ for(var/datum/computer_file/program/nttransfer/T in connected_clients)
+ T.crash_download("Remote server has forcibly closed the connection")
+ provided_file = null
+ return TRUE
+ if("PRG_setpassword")
+ var/pass = sanitize(input(usr, "Enter new server password. Leave blank to cancel, input 'none' to disable password.", "Server security", "none"))
+ if(!pass)
return
- error = "I/O Error: Unable to locate file on hard drive."
- return 1
- if(href_list["PRG_uploadmenu"])
- upload_menu = 1
- return 0
+ if(pass == "none")
+ server_password = ""
+ return
+ server_password = pass
+ return TRUE
+ if("PRG_uploadfile")
+ for(var/datum/computer_file/F in computer.hard_drive.stored_files)
+ if(F.uid == text2num(params["uid"]))
+ if(F.unsendable)
+ error = "I/O Error: File locked."
+ return
+ provided_file = F
+ ntnet_global.fileservers |= src
+ return
+ error = "I/O Error: Unable to locate file on hard drive."
+ return TRUE
+ if("PRG_uploadmenu")
+ upload_menu = 1
+ return TRUE
diff --git a/code/modules/modular_computers/file_system/programs/generic/uav.dm b/code/modules/modular_computers/file_system/programs/generic/uav.dm
index 0e98d0e0ea..24d677b679 100644
--- a/code/modules/modular_computers/file_system/programs/generic/uav.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/uav.dm
@@ -4,7 +4,7 @@
/datum/computer_file/program/uav
filename = "rigger"
filedesc = "UAV Control"
- nanomodule_path = /datum/nano_module/uav
+ tguimodule_path = /datum/tgui_module/uav
program_icon_state = "comm_monitor"
program_key_state = "generic_key"
program_menu_icon = "link"
@@ -12,255 +12,3 @@
size = 12
available_on_ntnet = 1
//requires_ntnet = 1
-
-/datum/nano_module/uav
- name = "UAV Control program"
- var/obj/item/device/uav/current_uav = null //The UAV we're watching
- var/signal_strength = 0 //Our last signal strength report (cached for a few seconds)
- var/signal_test_counter = 0 //How long until next signal strength check
- var/list/viewers //Who's viewing a UAV through us
- var/adhoc_range = 30 //How far we can operate on a UAV without NTnet
-
-/datum/nano_module/uav/Destroy()
- if(LAZYLEN(viewers))
- for(var/weakref/W in viewers)
- var/M = W.resolve()
- if(M)
- unlook(M)
- . = ..()
-
-/datum/nano_module/uav/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, state = default_state)
- var/list/data = host.initial_data()
-
- if(current_uav)
- if(QDELETED(current_uav))
- set_current(null)
- else if(signal_test_counter-- <= 0)
- signal_strength = get_signal_to(current_uav)
- if(!signal_strength)
- set_current(null)
- else // Don't reset counter until we find a UAV that's actually in range we can stay connected to
- signal_test_counter = 20
-
- data["current_uav"] = null
- if(current_uav)
- data["current_uav"] = list("status" = current_uav.get_status_string(), "power" = current_uav.state == 1 ? 1 : null)
- data["signal_strength"] = signal_strength ? signal_strength >= 2 ? "High" : "Low" : "None"
- data["in_use"] = LAZYLEN(viewers)
-
- var/list/paired_map = list()
- var/obj/item/modular_computer/mc_host = nano_host()
- if(istype(mc_host))
- for(var/puav in mc_host.paired_uavs)
- var/weakref/wr = puav
- var/obj/item/device/uav/U = wr.resolve()
- paired_map[++paired_map.len] = list("name" = "[U ? U.nickname : "!!Missing!!"]", "uavref" = "\ref[U]")
-
- data["paired_uavs"] = paired_map
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "mod_uav.tmpl", "UAV Control", 600, 500, state = state)
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
-
-/datum/nano_module/uav/Topic(var/href, var/href_list = list(), var/datum/topic_state/state)
- if((. = ..()))
- return
- state = state || DefaultTopicState() || global.default_state
- if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
- CouldUseTopic(usr)
- return OnTopic(usr, href_list, state)
- CouldNotUseTopic(usr)
- return TRUE
-
-/datum/nano_module/uav/proc/OnTopic(var/mob/user, var/list/href_list)
- if(href_list["switch_uav"])
- var/obj/item/device/uav/U = locate(href_list["switch_uav"]) //This is a \ref to the UAV itself
- if(!istype(U))
- to_chat(usr,"Something is blocking the connection to that UAV. In-person investigation is required.")
- return TOPIC_NOACTION
-
- if(!get_signal_to(U))
- to_chat(usr,"The screen freezes for a moment, before returning to the UAV selection menu. It's not able to connect to that UAV.")
- return TOPIC_NOACTION
-
- set_current(U)
- return TOPIC_REFRESH
-
- if(href_list["del_uav"])
- var/refstring = href_list["del_uav"] //This is a \ref to the UAV itself
- var/obj/item/modular_computer/mc_host = nano_host()
- //This is so we can really scrape up any weakrefs that can't resolve
- for(var/weakref/wr in mc_host.paired_uavs)
- if(wr.ref == refstring)
- if(current_uav?.weakref == wr)
- set_current(null)
- LAZYREMOVE(mc_host.paired_uavs, wr)
-
- else if(href_list["view_uav"])
- if(!current_uav)
- return TOPIC_NOACTION
-
- if(current_uav.check_eye(user) < 0)
- to_chat(usr,"The screen freezes for a moment, before returning to the UAV selection menu. It's not able to connect to that UAV.")
- else
- viewing_uav(user) ? unlook(user) : look(user)
- return TOPIC_NOACTION
-
- else if(href_list["power_uav"])
- if(!current_uav)
- return TOPIC_NOACTION
- else if(current_uav.toggle_power())
- //Clean up viewers faster
- if(LAZYLEN(viewers))
- for(var/weakref/W in viewers)
- var/M = W.resolve()
- if(M)
- unlook(M)
- return TOPIC_REFRESH
-
-/datum/nano_module/uav/proc/DefaultTopicState()
- return global.default_state
-
-/datum/nano_module/uav/proc/CouldNotUseTopic(mob/user)
- . = ..()
- unlook(user)
-
-/datum/nano_module/uav/proc/CouldUseTopic(mob/user)
- . = ..()
- if(viewing_uav(user))
- look(user)
-
-/datum/nano_module/uav/proc/set_current(var/obj/item/device/uav/U)
- if(current_uav == U)
- return
-
- signal_strength = 0
- current_uav = U
-
- if(LAZYLEN(viewers))
- for(var/weakref/W in viewers)
- var/M = W.resolve()
- if(M)
- if(current_uav)
- to_chat(M, "You're disconnected from the UAV's camera!")
- unlook(M)
- else
- look(M)
-
-////
-//// Finding signal strength between us and the UAV
-////
-/datum/nano_module/uav/proc/get_signal_to(var/atom/movable/AM)
- // Following roughly the ntnet signal levels
- // 0 is none
- // 1 is weak
- // 2 is strong
- var/obj/item/modular_computer/host = nano_host() //Better not add this to anything other than modular computers.
- if(!istype(host))
- return
- var/our_signal = host.get_ntnet_status() //1 low, 2 good, 3 wired, 0 none
- var/their_z = get_z(AM)
-
- //If we have no NTnet connection don't bother getting theirs
- if(!our_signal)
- if(get_z(host) == their_z && (get_dist(host, AM) < adhoc_range))
- return 1 //We can connect (with weak signal) in same z without ntnet, within 30 turfs
- else
- return 0
-
- var/list/zlevels_in_range = using_map.get_map_levels(their_z, FALSE)
- var/list/zlevels_in_long_range = using_map.get_map_levels(their_z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) - zlevels_in_range
- var/their_signal = 0
- for(var/relay in ntnet_global.relays)
- var/obj/machinery/ntnet_relay/R = relay
- if(!R.operable())
- continue
- if(R.z == their_z)
- their_signal = 2
- break
- if(R.z in zlevels_in_range)
- their_signal = 2
- break
- if(R.z in zlevels_in_long_range)
- their_signal = 1
- break
-
- if(!their_signal) //They have no NTnet at all
- if(get_z(host) == their_z && (get_dist(host, AM) < adhoc_range))
- return 1 //We can connect (with weak signal) in same z without ntnet, within 30 turfs
- else
- return 0
- else
- return max(our_signal, their_signal)
-
-////
-//// UAV viewer handling
-////
-/datum/nano_module/uav/proc/viewing_uav(mob/user)
- return (weakref(user) in viewers)
-
-/datum/nano_module/uav/proc/look(var/mob/user)
- if(issilicon(user)) //Too complicated for me to want to mess with at the moment
- to_chat(user, "Regulations prevent you from controlling several corporeal forms at the same time!")
- return
-
- if(!current_uav)
- return
-
- user.set_machine(nano_host())
- user.reset_view(current_uav)
- current_uav.add_master(user)
- LAZYDISTINCTADD(viewers, weakref(user))
-
-/datum/nano_module/uav/proc/unlook(var/mob/user)
- user.unset_machine()
- user.reset_view()
- if(current_uav)
- current_uav.remove_master(user)
- LAZYREMOVE(viewers, weakref(user))
-
-/datum/nano_module/uav/check_eye(var/mob/user)
- if(get_dist(user, nano_host()) > 1 || user.blinded || !current_uav)
- unlook(user)
- return -1
-
- var/viewflag = current_uav.check_eye(user)
- if (viewflag < 0) //camera doesn't work
- unlook(user)
- return -1
-
- return viewflag
-
-////
-//// Relaying movements to the UAV
-////
-/datum/nano_module/uav/relaymove(var/mob/user, direction)
- if(current_uav)
- return current_uav.relaymove(user, direction, signal_strength)
-
-////
-//// The effects when looking through a UAV
-////
-/datum/nano_module/uav/apply_visual(var/mob/M)
- if(!M.client)
- return
- if(weakref(M) in viewers)
- M.overlay_fullscreen("fishbed",/obj/screen/fullscreen/fishbed)
- M.overlay_fullscreen("scanlines",/obj/screen/fullscreen/scanline)
-
- if(signal_strength <= 1)
- M.overlay_fullscreen("whitenoise",/obj/screen/fullscreen/noise)
- else
- M.clear_fullscreen("whitenoise", 0)
- else
- remove_visual(M)
-
-/datum/nano_module/uav/remove_visual(mob/M)
- if(!M.client)
- return
- M.clear_fullscreen("fishbed",0)
- M.clear_fullscreen("scanlines",0)
- M.clear_fullscreen("whitenoise",0)
diff --git a/code/modules/modular_computers/file_system/programs/generic/wordprocessor.dm b/code/modules/modular_computers/file_system/programs/generic/wordprocessor.dm
index 1a4d7a1871..61f3b43da8 100644
--- a/code/modules/modular_computers/file_system/programs/generic/wordprocessor.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/wordprocessor.dm
@@ -5,9 +5,10 @@
program_icon_state = "word"
program_key_state = "atmos_key"
size = 4
- requires_ntnet = 0
- available_on_ntnet = 1
- nanomodule_path = /datum/nano_module/program/computer_wordprocessor/
+ requires_ntnet = FALSE
+ available_on_ntnet = TRUE
+ tgui_id = "NtosWordProcessor"
+
var/browsing
var/open_file
var/loaded_data
@@ -28,7 +29,7 @@
if(F)
open_file = F.filename
loaded_data = F.stored_data
- return 1
+ return TRUE
/datum/computer_file/program/wordprocessor/proc/save_file(var/filename)
var/datum/computer_file/data/F = get_file(filename)
@@ -46,7 +47,7 @@
HDD.store_file(backup)
return 0
is_edited = 0
- return 1
+ return TRUE
/datum/computer_file/program/wordprocessor/proc/create_file(var/newname, var/data = "")
if(!newname)
@@ -64,142 +65,144 @@
if(HDD.store_file(F))
return F
-/datum/computer_file/program/wordprocessor/Topic(href, href_list)
+/datum/computer_file/program/wordprocessor/tgui_act(action, list/params, datum/tgui/ui)
if(..())
- return 1
+ return TRUE
- if(href_list["PRG_txtrpeview"])
- show_browser(usr,"[open_file][pencode2html(loaded_data)]", "window=[open_file]")
- return 1
+ switch(action)
+ if("PRG_txtrpeview")
+ show_browser(usr,"[open_file][pencode2html(loaded_data)]