pAIs, Computers and ntIRC (#8757)

#8005 just revived.

Tasks to acomplish while here:

Fix merge conflicts

    Add ntIRC direct messaging

Things I migth consider adding in future PR:

    Porting IRC to VueUI
    Porting File Manager to VueUI.
This commit is contained in:
Karolis
2020-05-08 13:58:34 +03:00
committed by GitHub
parent 691a11cf00
commit 1c00ae02d3
72 changed files with 6149 additions and 4768 deletions

View File

@@ -1,6 +1,9 @@
/obj/item/modular_computer/initial_data()
return list("_PC" = get_header_data())
/datum/computer_file/program/initial_data()
return list("_PC" = get_header_data())
/obj/item/modular_computer/update_layout()
return TRUE

View File

@@ -21,8 +21,7 @@
return
computer.visible_message(SPAN_NOTICE("\The [computer]'s screen brightly flashes and emits a loud electrical buzzing."))
computer.enabled = FALSE
computer.update_icon()
computer.shutdown_computer(0)
spark(get_turf(src), 10, alldirs)
if(computer.hard_drive)

View File

@@ -72,7 +72,7 @@
requires_ntnet = TRUE
network_destination = "atmospheric control system"
requires_ntnet_feature = NTNET_SYSTEMCONTROL
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_SILICON
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_STATIONBOUND
size = 17
color = LIGHT_COLOR_CYAN
@@ -87,7 +87,7 @@
requires_ntnet = TRUE
network_destination = "RCON remote control system"
requires_ntnet_feature = NTNET_SYSTEMCONTROL
usage_flags = PROGRAM_CONSOLE | PROGRAM_SILICON
usage_flags = PROGRAM_CONSOLE | PROGRAM_STATIONBOUND
size = 19
color = LIGHT_COLOR_GREEN
@@ -103,6 +103,6 @@
requires_ntnet = TRUE
network_destination = "APC Coordinator"
requires_ntnet_feature = NTNET_SYSTEMCONTROL
usage_flags = PROGRAM_CONSOLE | PROGRAM_SILICON
usage_flags = PROGRAM_CONSOLE | PROGRAM_STATIONBOUND
size = 9
color = LIGHT_COLOR_GREEN

View File

@@ -0,0 +1,44 @@
/datum/computer_file/program/manifest
filename = "manifest"
filedesc = "Crew Manifest"
program_icon_state = "generic"
extended_desc = "This program is used for viewing the crew manifest."
size = 3
requires_ntnet = 1
available_on_ntnet = 1
/datum/computer_file/program/manifest/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "manifest", 450, 600, "Crew Manifest")
ui.open()
/datum/computer_file/program/manifest/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "manifest", 450, 600, "Crew Manifest")
return TRUE
// Gaters data for ui
/datum/computer_file/program/manifest/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
VUEUI_SET_CHECK(data["manifest"], SSrecords.get_manifest_list(), ., data)
/datum/computer_file/program/manifest/Topic(href, href_list)
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.radio.Topic(href, href_list)

View File

@@ -15,6 +15,7 @@
var/datum/ntnet_conversation/channel
var/operator_mode = FALSE // Channel operator mode
var/netadmin_mode = FALSE // Administrator mode (invisible to other users + bypasses passwords)
var/list/directmessagechannels = list()
color = LIGHT_COLOR_GREEN
/datum/computer_file/program/chatclient/New()
@@ -60,9 +61,12 @@
channel = C
if(href_list["PRG_leavechannel"])
. = TRUE
if(channel)
if(channel && !channel.direct)
channel.remove_client(src)
channel = null
if(href_list["PRG_backtomain"])
. = TRUE
channel = null
if(href_list["PRG_newchannel"])
. = TRUE
var/mob/living/user = usr
@@ -98,10 +102,16 @@
var/new_name = sanitize(input(user, "Enter new nickname or leave blank to cancel:"))
if(!new_name)
return TRUE
if(channel)
channel.add_status_message("[username] is now known as [new_name].")
var/comp_name = ckey(new_name)
for(var/cl in ntnet_global.chat_clients)
var/datum/computer_file/program/chatclient/C = cl
if(ckey(C.username) == comp_name || comp_name == "cancel")
alert(user, "This nickname is already taken.")
return TRUE
for(var/datum/ntnet_conversation/channel in ntnet_global.chat_channels)
if(src in channel.clients)
channel.add_status_message("[username] is now known as [new_name].")
username = new_name
if(href_list["PRG_savelog"])
. = TRUE
if(!channel)
@@ -156,6 +166,30 @@
channel.password = ""
else
channel.password = newpassword
if(href_list["PRG_directmessage"])
. = TRUE
var/clients = list()
var/names = list()
for(var/cl in ntnet_global.chat_clients)
var/datum/computer_file/program/chatclient/C = cl
clients[C.username] = C
names += C.username
names -= username // Remove ourselves
names += "== Cancel =="
var/picked = input(usr, "Select with whom you would like to start a conversation.") in names
if(picked == "== Cancel ==")
return
var/datum/computer_file/program/chatclient/otherClient = clients[picked]
if(picked)
if(directmessagechannels[otherClient])
channel = directmessagechannels[otherClient]
return
var/datum/ntnet_conversation/C = new /datum/ntnet_conversation("", TRUE)
C.begin_direct(src, otherClient)
channel = C
directmessagechannels[otherClient] = C
otherClient.directmessagechannels[src] = C
/datum/computer_file/program/chatclient/process_tick()
..()
@@ -176,11 +210,14 @@
ui_header = "ntnrc_idle.gif"
/datum/computer_file/program/chatclient/kill_program(var/forced = FALSE)
if(channel)
channel.remove_client(src)
channel = null
channel = null
ntnet_global.chat_clients -= src
..(forced)
/datum/computer_file/program/chatclient/run_program(var/mob/user)
ntnet_global.chat_clients += src
return ..(user)
/datum/nano_module/program/computer_chatclient
name = "NTNet Relay Chat Client"
@@ -198,7 +235,7 @@
data["adminmode"] = C.netadmin_mode
if(C.channel)
data["title"] = C.channel.title
data["title"] = C.channel.get_title(C)
var/list/messages[0]
for(var/M in C.channel.messages)
messages.Add(list(list(
@@ -208,19 +245,21 @@
var/list/clients[0]
for(var/datum/computer_file/program/chatclient/cl in C.channel.clients)
clients.Add(list(list(
"name" = cl.username
"name" = cl.username,
"active" = cl.program_state > PROGRAM_STATE_KILLED
)))
data["clients"] = clients
C.operator_mode = (C.channel.operator == C) ? 1 : 0
data["is_operator"] = C.operator_mode || C.netadmin_mode
data["is_direct"] = C.channel.direct
else // Channel selection screen
var/list/all_channels[0]
for(var/datum/ntnet_conversation/conv in ntnet_global.chat_channels)
if(conv && conv.title)
if(conv && conv.title && conv.can_see(program))
all_channels.Add(list(list(
"chan" = conv.title,
"id" = conv.id
"chan" = conv.get_title(C),
"id" = conv.id,
"con" = (program in conv.clients)
)))
data["all_channels"] = all_channels

View File

@@ -11,6 +11,7 @@
requires_ntnet = TRUE
requires_ntnet_feature = NTNET_SYSTEMCONTROL
requires_access_to_run = PROGRAM_ACCESS_LIST_ONE
usage_flags = PROGRAM_ALL_REGULAR | PROGRAM_STATIONBOUND
var/records_type = RECORD_GENERAL | RECORD_MEDICAL | RECORD_SECURITY | RECORD_VIRUS | RECORD_WARRANT | RECORD_LOCKED
var/edit_type = RECORD_GENERAL | RECORD_MEDICAL | RECORD_SECURITY | RECORD_VIRUS | RECORD_WARRANT | RECORD_LOCKED
@@ -77,6 +78,12 @@
program_icon_state = "employment_record"
color = LIGHT_COLOR_BLUE
/datum/computer_file/program/records/pai
available_on_ntnet = 1
extended_desc = "This program is used to view crew records."
usage_flags = PROGRAM_SILICON_PAI
edit_type = 0
/datum/computer_file/program/records/New()
. = ..()
listener = new(src)
@@ -339,4 +346,4 @@
var/datum/computer_file/program/records/t = target
if(istype(t) && !t.isEditing)
if(t.active == r || t.active_virus == r)
SSvueui.check_uis_for_change(t)
SSvueui.check_uis_for_change(t)

View File

@@ -8,7 +8,7 @@
requires_ntnet = TRUE
network_destination = "crew lifesigns monitoring system"
size = 11
usage_flags = PROGRAM_ALL_REGULAR
usage_flags = PROGRAM_ALL_REGULAR | PROGRAM_STATIONBOUND
color = LIGHT_COLOR_CYAN
/datum/computer_file/program/suit_sensors/ui_interact(mob/user)

View File

@@ -0,0 +1,59 @@
/datum/computer_file/program/pai_atmos
filename = "pai_atmos"
filedesc = "Atmosphere Sensor"
program_icon_state = "generic"
extended_desc = "This program is for viewing local atmospheric data."
size = 0
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_atmos/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-pai-atmosphere", 400, 200, "pAI Atmosphere Sensor")
ui.open()
/datum/computer_file/program/pai_atmos/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "mcomputer-pai-atmosphere", 400, 200, "pAI Atmosphere Sensor")
return TRUE
// Gaters data for ui
/datum/computer_file/program/pai_atmos/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
var/turf/T = get_turf_or_move(host.loc)
if(T)
var/datum/gas_mixture/env = T.return_air()
VUEUI_SET_CHECK(data["read"], TRUE, ., data)
VUEUI_SET_CHECK(data["press"], env.return_pressure(), ., data)
VUEUI_SET_CHECK(data["temp"], env.temperature, ., data)
VUEUI_SET_CHECK(data["tempC"], env.temperature-T0C, ., data)
VUEUI_SET_CHECK_IFNOTSET(data["gas"], list("_" = "_"), ., data)
for(var/g in gas_data.gases)
if(!(g in env.gas))
VUEUI_SET_CHECK(data["gas"][g], null, ., data)
else
VUEUI_SET_CHECK(data["gas"][g], env.gas[g], ., data)
else
VUEUI_SET_CHECK(data["read"], FALSE, ., data)
VUEUI_SET_CHECK(data["press"], 0, ., data)
VUEUI_SET_CHECK(data["temp"], T0C, ., data)
VUEUI_SET_CHECK(data["tempC"], 0, ., data)
VUEUI_SET_CHECK_IFNOTSET(data["gas"], list("_" = "_"), ., data)
for(var/g in gas_data.gases)
VUEUI_SET_CHECK(data["gas"][g], null, ., data)

View File

@@ -0,0 +1,79 @@
/datum/computer_file/program/pai_directives
filename = "pai_directives"
filedesc = "pAI Directives"
program_icon_state = "generic"
extended_desc = "This program is for viewing currently assigned directives."
size = 0
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_directives/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-pai-directives", 450, 500, "pAI directives")
ui.open()
/datum/computer_file/program/pai_directives/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "mcomputer-pai-directives", 450, 500, "pAI directives")
return TRUE
// Gaters data for ui
/datum/computer_file/program/pai_directives/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
VUEUI_SET_CHECK(data["master"], host.master, ., data)
VUEUI_SET_CHECK(data["dna"], host.master_dna, ., data)
VUEUI_SET_CHECK(data["prime"], host.pai_law0, ., data)
VUEUI_SET_CHECK(data["supplemental"], host.pai_laws, ., data)
/datum/computer_file/program/pai_directives/Topic(href, href_list)
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
if(href_list["getdna"])
var/mob/living/M = host.loc
var/count = 0
// Find the carrier
while(!istype(M, /mob/living))
if(!M || !M.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
to_chat(src, SPAN_WARNING("You are not being carried by anyone!"))
return 0
M = M.loc
count++
// Check the carrier
var/answer = input(M, "[host] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[host] Check DNA", "No") in list("Yes", "No")
if(answer == "Yes")
var/turf/T = get_turf_or_move(host.loc)
for (var/mob/v in viewers(T))
v.show_message(SPAN_NOTICE("[M] presses \his thumb against [host]."), 3, SPAN_NOTICE("[host] makes a sharp clicking sound as it extracts DNA material from [M]."), 2)
var/datum/dna/dna = M.dna
to_chat(host, "<font color = red><h3>[M]'s UE string : [dna.unique_enzymes]</h3></font>")
if(dna.unique_enzymes == host.master_dna)
to_chat(host, SPAN_NOTICE("<b>Provided DNA is a match to stored Master DNA.</b>"))
else
to_chat(host, SPAN_WARNING("<b>Provided DNA does not match stored Master DNA.</b>"))
else
to_chat(host, SPAN_WARNING("[M] does not seem like \he [gender_datums[M.gender].is] going to provide a DNA sample willingly."))
return 1

View File

@@ -0,0 +1,106 @@
/datum/computer_file/program/pai_doorjack
filename = "doorjack"
filedesc = "Door Jack"
program_icon_state = "generic"
extended_desc = "This program is used to access standard-issue pAI door jack systems."
size = 12
available_on_ntnet = 1
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_doorjack/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-pai-doorjack", 400, 150, "Door Jack")
ui.auto_update_content = TRUE
ui.open()
/datum/computer_file/program/pai_doorjack/vueui_transfer(oldobj)
var/uis = SSvueui.transfer_uis(oldobj, src, "mcomputer-pai-doorjack", 400, 150, "Door Jack")
for(var/i in uis)
var/datum/vueui/ui = i
ui.auto_update_content = TRUE
return TRUE
/datum/computer_file/program/pai_doorjack/vueui_on_transfer(datum/vueui/ui)
. = ..()
ui.auto_update_content = FALSE
// Gaters data for ui
/datum/computer_file/program/pai_doorjack/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
VUEUI_SET_CHECK(data["extended"], !!host.cable, ., data)
VUEUI_SET_CHECK(data["connected"], !!host.cable?.machine , ., data)
VUEUI_SET_CHECK(data["ishacking"], !!host.hackdoor, ., data)
VUEUI_SET_CHECK(data["progress"], host.hackprogress, ., data)
VUEUI_SET_CHECK(data["aborted"], host.hack_aborted, ., data)
/datum/computer_file/program/pai_doorjack/Topic(href, href_list)
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
if(href_list["hack"])
if(host.cable && host.cable.machine)
host.hackdoor = host.cable.machine
host.hackloop()
return 1
if(href_list["cancel"])
host.hackdoor = null
return 1
if(href_list["extend"])
var/turf/T = get_turf_or_move(host.loc)
host.hack_aborted = 0
host.cable = new /obj/item/pai_cable(T)
T.visible_message(SPAN_WARNING("A port on [host] opens to reveal [host.cable], which promptly falls to the floor."),
SPAN_WARNING("You hear the soft click of something light and hard falling to the ground."))
return 1
/mob/living/silicon/pai/proc/hackloop()
var/turf/T = get_turf_or_move(src.loc)
for(var/mob/living/silicon/ai/AI in player_list)
if(T.loc)
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
else
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.</b></font>")
var/obj/machinery/door/airlock/D = cable.machine
if(!istype(D))
hack_aborted = 1
hackprogress = 0
cable.machine = null
hackdoor = null
return
while(hackprogress < 1000)
if(cable && cable.machine == D && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1)
hackprogress = min(hackprogress+rand(1, 20), 1000)
else
hack_aborted = 1
hackprogress = 0
hackdoor = null
return
if(hackprogress >= 1000)
hackprogress = 0
D.unlock() //unbolts door as long as bolt wires aren't cut
D.open()
cable.machine = null
return
sleep(10) // Update every second

View File

@@ -0,0 +1,57 @@
/datum/computer_file/program/pai_sechud
filename = "sechud"
filedesc = "pAI Security HUD"
extended_desc = "This service enables the integrated security HUD."
size = 10
program_type = PROGRAM_SERVICE
available_on_ntnet = 1
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_sechud/service_activate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.secHUD = TRUE
/datum/computer_file/program/pai_sechud/service_deactivate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.secHUD = FALSE
/datum/computer_file/program/pai_medhud
filename = "medhud"
filedesc = "pAI Medical HUD"
extended_desc = "This service enables the integrated medical HUD."
size = 10
program_type = PROGRAM_SERVICE
available_on_ntnet = 1
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_medhud/service_activate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.medHUD = TRUE
/datum/computer_file/program/pai_medhud/service_deactivate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.medHUD = FALSE

View File

@@ -0,0 +1,56 @@
/datum/computer_file/program/pai_radio
filename = "pai_radio"
filedesc = "Radio Configuration"
program_icon_state = "generic"
extended_desc = "This program is used to configure the integrated pAI radio."
size = 0
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_radio/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-pai-radio", 400, 150, "pAI Radio Configuration")
ui.open()
/datum/computer_file/program/pai_radio/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "mcomputer-pai-radio", 400, 150, "pAI Radio Configuration")
return TRUE
// Gaters data for ui
/datum/computer_file/program/pai_radio/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
VUEUI_SET_CHECK(data["listening"], host.radio.broadcasting, ., data)
VUEUI_SET_CHECK(data["frequency"], format_frequency(host.radio.frequency), ., data)
LAZYINITLIST(data["channels"])
for(var/ch_name in host.radio.channels)
var/ch_stat = host.radio.channels[ch_name]
VUEUI_SET_CHECK(data["channels"][ch_name], !!(ch_stat & host.radio.FREQ_LISTENING), ., data)
/datum/computer_file/program/pai_radio/Topic(href, href_list)
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
host.radio.Topic(href, href_list)
SSvueui.check_uis_for_change(src)

View File

@@ -0,0 +1,69 @@
/datum/computer_file/program/pai_signaler
filename = "signaler"
filedesc = "Remote Signaller"
program_icon_state = "generic"
extended_desc = "This program can be used to send wide-range signals of various frequencies."
size = 3
available_on_ntnet = 1
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_signaler/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-pai-signaler", 400, 150, "pAI Signaller")
ui.open()
/datum/computer_file/program/pai_signaler/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "mcomputer-pai-signaler", 400, 150, "pAI Signaller")
return TRUE
// Gaters data for ui
/datum/computer_file/program/pai_signaler/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
VUEUI_SET_CHECK(data["code"], host.sradio.code, ., data)
VUEUI_SET_CHECK(data["frequency"], format_frequency(host.sradio.frequency), ., data)
/datum/computer_file/program/pai_signaler/Topic(href, href_list)
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
if(href_list["send"])
host.sradio.send_signal("ACTIVATE")
for(var/mob/O in hearers(1, host.loc))
O.show_message(text("\icon[] *beep* *beep*", host), 3, "*beep* *beep*", 2)
return 1
else if(href_list["freq"])
var/new_frequency = (host.sradio.frequency + href_list["freq"])
if(new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ)
new_frequency = sanitize_frequency(new_frequency)
host.sradio.set_frequency(new_frequency)
return 1
else if(href_list["code"])
host.sradio.code += href_list["code"]
host.sradio.code = round(host.sradio.code)
host.sradio.code = min(100, host.sradio.code)
host.sradio.code = max(1, host.sradio.code)
return 1

View File

@@ -0,0 +1,40 @@
/datum/computer_file/program/pai_translator
filename = "translator"
filedesc = "pAI Universal Translator"
extended_desc = "This service enables the integrated universal translation systems."
size = 12
program_type = PROGRAM_SERVICE
available_on_ntnet = 1
usage_flags = PROGRAM_SILICON_PAI
/datum/computer_file/program/pai_translator/service_activate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
if(!host.translator_on)
host.add_language(LANGUAGE_UNATHI)
host.add_language(LANGUAGE_SIIK_MAAS)
host.add_language(LANGUAGE_SKRELLIAN)
host.add_language(LANGUAGE_ROOTSONG)
host.translator_on = TRUE
/datum/computer_file/program/pai_translator/service_deactivate()
. = ..()
if(!istype(computer, /obj/item/modular_computer/silicon))
return
var/obj/item/modular_computer/silicon/true_computer = computer
if(!istype(true_computer.computer_host, /mob/living/silicon/pai))
return
var/mob/living/silicon/pai/host = true_computer.computer_host
if(host.translator_on)
host.remove_language(LANGUAGE_UNATHI)
host.remove_language(LANGUAGE_SIIK_MAAS)
host.remove_language(LANGUAGE_SKRELLIAN)
host.remove_language(LANGUAGE_ROOTSONG)
host.translator_on = FALSE

View File

@@ -7,7 +7,7 @@
requires_ntnet = TRUE
required_access_run = access_network
required_access_download = access_heads
usage_flags = PROGRAM_CONSOLE
usage_flags = PROGRAM_CONSOLE | PROGRAM_SILICON_AI
color = LIGHT_COLOR_GREEN
available_on_ntnet = TRUE

View File

@@ -10,6 +10,7 @@
required_access_download = access_hos
required_access_run = access_security
nanomodule_path = /datum/nano_module/program/digitalwarrant
usage_flags = PROGRAM_ALL_REGULAR | PROGRAM_STATIONBOUND
/datum/nano_module/program/digitalwarrant
name = "Warrant Assistant"

View File

@@ -9,231 +9,224 @@
size = 4
requires_ntnet = TRUE
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
available_on_ntnet = FALSE
nanomodule_path = /datum/nano_module/program/computer_ntnetdownload
available_on_ntnet = 0
ui_header = "downloader_finished.gif"
var/datum/computer_file/program/downloaded_file
var/hacked_download = FALSE
var/download_completion = 0 //GQ of downloaded data.
var/download_netspeed = 0
var/download_last_update = 0 // For tracking download rates and completion.
var/downloaderror = ""
var/downstream_variance = 0.1
var/list/download_queue = list()
var/list/download_files = list()
var/queue_size = 0
var/active_download = null
var/last_update = 0
var/speed = 0
/datum/computer_file/program/ntnetdownload/proc/begin_file_download(var/filename, var/user)
if(downloaded_file)
return FALSE
var/datum/computer_file/program/PRG = ntnet_global.find_ntnet_file_by_name(filename)
/datum/computer_file/program/ntnetdownload/ui_interact(mob/user, var/datum/topic_state/state = default_state)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-system-downloader", 575, 700, "NTNet Download Program", state = state)
ui.open()
if(!PRG || !istype(PRG))
return FALSE
/datum/computer_file/program/ntnetdownload/vueui_transfer(oldobj)
SSvueui.transfer_uis(oldobj, src, "mcomputer-system-downloader", 575, 700, "NTNet Download Program")
return TRUE
// Gaters data for ui
/datum/computer_file/program/ntnetdownload/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list("queue" = download_queue)
if(!istype(computer))
return
// Gather data for computer header
var/headerdata = get_header_data(data["_PC"])
if(headerdata)
data["_PC"] = headerdata
. = data
// Let's send all installed programs
LAZYINITLIST(data["installed"])
for(var/datum/computer_file/program/I in hard_drive.stored_files)
LAZYINITLIST(data["installed"][I.filename])
VUEUI_SET_CHECK(data["installed"][I.filename]["name"], I.filedesc, ., data)
VUEUI_SET_CHECK(data["installed"][I.filename]["size"], I.size, ., data)
// Now lets send all avaivable programs with there status.
// Statuses (rest): 0 - ALL OK, 1 - can't download due to access, 2 - unsuported hardware, 3 - sindies only
LAZYINITLIST(data["avaivable"])
for(var/datum/computer_file/program/P in ntnet_global.available_software)
LAZYINITLIST(data["avaivable"][P.filename])
VUEUI_SET_CHECK(data["avaivable"][P.filename]["name"], P.filedesc, ., data)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["desc"], P.extended_desc, ., data)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["size"], P.size, ., data)
if(computer_emagged)
if(!P.is_supported_by_hardware(computer.hardware_flag))
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 2, ., data)
else
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 0, ., data)
else
if(!P.available_on_ntnet)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 3, ., data)
else if(!P.can_download(user) && P.requires_access_to_download)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 1, ., data)
else if(!P.is_supported_by_hardware(computer.hardware_flag))
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 2, ., data)
else
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 0, ., data)
VUEUI_SET_CHECK(data["disk_size"], hard_drive.max_capacity, ., data)
VUEUI_SET_CHECK(data["disk_used"], hard_drive.used_capacity, ., data)
VUEUI_SET_CHECK(data["queue_size"], queue_size, ., data)
VUEUI_SET_CHECK(data["speed"], speed, ., data)
for(var/name in download_queue)
VUEUI_SET_CHECK(data["queue"][name], download_queue[name], ., data)
/datum/computer_file/program/ntnetdownload/Topic(href, href_list)
if(..())
return 1
var/datum/vueui/ui = href_list["vueui"]
if(!istype(ui))
return
if(href_list["download"])
var/datum/computer_file/program/PRG = ntnet_global.find_ntnet_file_by_name(href_list["download"])
if(!istype(PRG))
return 1
return add_to_queue(PRG, ui.user)
if(href_list["cancel"])
return cancel_from_queue(href_list["cancel"])
/datum/computer_file/program/ntnetdownload/proc/add_to_queue(var/datum/computer_file/program/PRG, var/mob/user)
// Attempting to download antag only program, but without having emagged computer. No.
if(PRG.available_on_syndinet && !computer_emagged)
return FALSE
if(!hard_drive.can_store_file(queue_size + PRG.size))
to_chat(user, SPAN_WARNING("You can't download this program as queued items exceed hard drive capacity."))
return TRUE
if(!computer?.hard_drive?.try_store_file(PRG))
return FALSE
if(computer.enrolled == TRUE && !computer_emagged)
if(!computer_emagged && !PRG.can_download(user) && PRG.requires_access_to_download)
return TRUE
if(!PRG.is_supported_by_hardware(computer.hardware_flag))
return FALSE
ui_header = "downloader_running.gif"
if(PRG in ntnet_global.available_station_software)
if(PRG.available_on_ntnet)
generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from NTNet Software Repository.")
hacked_download = FALSE
else if(PRG in ntnet_global.available_antag_software)
else if (PRG.available_on_syndinet)
generate_network_log("Began downloading file **ENCRYPTED**.[PRG.filetype] from unspecified server.")
hacked_download = TRUE
else
generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from unspecified server.")
hacked_download = FALSE
downloaded_file = PRG.clone()
if(user)
spawn()
ui_interact(user)
/datum/computer_file/program/ntnetdownload/proc/abort_file_download()
if(!downloaded_file)
download_files[PRG.filename] = PRG.clone()
queue_size += PRG.size
download_queue[PRG.filename] = 0
for(var/i in SSvueui.get_open_uis(src))
var/datum/vueui/ui = i
ui.data["queue"][PRG.filename] = 0
ui.push_change()
return TRUE
/datum/computer_file/program/ntnetdownload/proc/cancel_from_queue(var/name)
if(!download_files[name])
return
generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : downloaded_file.filename].[downloaded_file.filetype].")
downloaded_file = null
download_completion = 0
download_last_update = 0
ui_header = "downloader_finished.gif"
var/datum/computer_file/program/PRG = download_files[name]
var/hacked_download = PRG.available_on_syndinet && !PRG.available_on_ntnet
generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : PRG.filename].[PRG.filetype].")
download_queue -= name
download_files -= name
queue_size -= PRG.size
for(var/i in SSvueui.get_open_uis(src))
var/datum/vueui/ui = i
ui.data["queue"] -= name
ui.push_change()
/datum/computer_file/program/ntnetdownload/proc/complete_file_download()
if(!downloaded_file)
/datum/computer_file/program/ntnetdownload/proc/finish_from_queue(var/name)
if(!download_files[name])
return
generate_network_log("Completed download of file [hacked_download ? "**ENCRYPTED**" : downloaded_file.filename].[downloaded_file.filetype].")
if(!computer?.hard_drive?.store_file(downloaded_file))
// The download failed
downloaderror = "I/O ERROR - Unable to save file. Check whether you have enough free space on your hard drive and whether your hard drive is properly connected. If the issue persists contact your system administrator for assistance."
else
playsound(get_turf(computer), 'sound/machines/ping.ogg', 40, 0)
computer.output_message("\icon[computer] <b>[capitalize_first_letters(computer)]</b> pings, \"Software download completed successfully!\"", 1)
downloaded_file = null
download_completion = 0
download_last_update = 0
ui_header = "downloader_finished.gif"
var/datum/computer_file/program/PRG = download_files[name]
var/hacked_download = PRG.available_on_syndinet && !PRG.available_on_ntnet
generate_network_log("Completed download of file [hacked_download ? "**ENCRYPTED**" : PRG.filename].[PRG.filetype].")
if(!computer?.hard_drive?.store_file(PRG))
download_queue[name] = -1
for(var/i in SSvueui.get_open_uis(src))
var/datum/vueui/ui = i
ui.data["queue"] = -1
ui.push_change()
return
download_queue -= name
download_files -= name
queue_size -= PRG.size
for(var/i in SSvueui.get_open_uis(src))
var/datum/vueui/ui = i
ui.data["queue"] -= name
ui.push_change()
/datum/computer_file/program/ntnetdownload/process_tick()
if(!downloaded_file)
if(!queue_size)
ui_header = "downloader_finished.gif"
return
if(download_completion >= downloaded_file.size)
complete_file_download()
return
// Download speed according to connectivity state. NTNet server is assumed to be on unlimited speed so we're limited by our local connectivity
download_netspeed = 0
// Speed defines are found in misc.dm
switch(ntnet_status)
if(1)
download_netspeed = NTNETSPEED_LOWSIGNAL
downstream_variance = 0.3
if(2)
download_netspeed = NTNETSPEED_HIGHSIGNAL
downstream_variance = 0.2
if(3)
download_netspeed = NTNETSPEED_ETHERNET
ui_header = "downloader_running.gif"
// We recovered connection or started a new download.
// So we don't have any bytes yet. We'll get them next time!
if (!download_last_update)
download_last_update = world.time
return
var/delta = ((rand() - 0.5) * 2) * downstream_variance * download_netspeed
//Download speed varies +/- 10% each proc. Adds a more realistic feel
download_netspeed += delta
download_netspeed = round(download_netspeed, 0.002)//3 decimal places
var/delta_seconds = (world.time - download_last_update) / 10
download_completion = min(download_completion + delta_seconds * download_netspeed, downloaded_file.size)
// No connection, so cancel the download.
// This is done at the end because of logic reasons.
// Trust me, it's fine. - Skull132
if (!download_netspeed)
download_last_update = 0
else
download_last_update = world.time
/datum/computer_file/program/ntnetdownload/Topic(href, href_list)
if(..())
return TRUE
if(href_list["PRG_downloadfile"])
if(!downloaded_file)
begin_file_download(href_list["PRG_downloadfile"], usr)
return TRUE
if(href_list["PRG_reseterror"])
if(downloaderror)
download_completion = 0
download_netspeed = 0
downloaded_file = null
downloaderror = ""
return TRUE
return FALSE
/datum/nano_module/program/computer_ntnetdownload
name = "Network Downloader"
var/obj/item/modular_computer/my_computer
/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
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 = list("_PC" = program.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
else if(prog.downloaded_file) // Download running. Wait please..
if (ui)
ui.set_auto_update(TRUE)
data["downloadname"] = prog.downloaded_file.filename
data["downloaddesc"] = prog.downloaded_file.filedesc
data["downloadsize"] = prog.downloaded_file.size
data["downloadspeed"] = prog.download_netspeed //Even if it does update every 2 seconds, this is bad coding on everyone's count. :ree:
data["downloadcompletion"] = round(prog.download_completion, 0.01)
else // No download running, pick file.
if (ui)
ui.set_auto_update(FALSE)//No need for auto updating on the software menu
data["disk_size"] = my_computer.hard_drive.max_capacity
data["disk_used"] = my_computer.hard_drive.used_capacity
if(my_computer.enrolled == 2) //To lock installation of software on work computers until the IT Department is properly implemented - Then check for access on enrolled computers
data += get_programlist(user)
else
data["downloadable_programs"] = list()
data["locked"] = TRUE
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 = TRUE
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(TRUE)
/datum/nano_module/program/computer_ntnetdownload/proc/get_programlist(var/mob/user)
var/list/all_entries[0]
var/datum/computer_file/program/ntnetdownload/prog = program
var/list/data = list()
data["hackedavailable"] = FALSE
for(var/datum/computer_file/program/P in ntnet_global.available_station_software)
var/installed = FALSE
for(var/datum/computer_file/program/Q in program.hard_drive.stored_files)
if(istype(P, Q.type))
installed = TRUE
if(download_queue[active_download] == null)
for(var/name in download_queue)
if(download_queue[name] >= 0)
active_download = name
break
if(download_queue[active_download] == null)
return
if(!installed)
// Only those programs our user can run will show in the list
if(!P.can_download(user) && P.requires_access_to_download)
continue
var/datum/computer_file/active_download_file = download_files[active_download]
if(download_queue[active_download] >= 0)
if (!last_update)
last_update = world.time
return
speed = 0
var/variance = 0.1
switch(ntnet_status)
if(1)
speed = NTNETSPEED_LOWSIGNAL
variance = 0.3
if(2)
speed = NTNETSPEED_HIGHSIGNAL
variance = 0.2
if(3)
speed = NTNETSPEED_ETHERNET
if(!P.is_supported_by_hardware(program.computer.hardware_flag))
continue
var/delta = ((rand() - 0.5) * 2) * variance * speed
//Download speed varies +/- 10% each proc. Adds a more realistic feels
speed += delta
speed = round(speed, 0.002)//3 decimal places
all_entries.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
"size" = P.size
)))
var/delta_seconds = (world.time - last_update) / 10
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)
var/installed = FALSE
for(var/datum/computer_file/program/Q in program.hard_drive.stored_files)
if(istype(P, Q.type))
installed = TRUE
break
download_queue[active_download] = min(download_queue[active_download] + delta_seconds * speed, active_download_file.size)
if(!installed)
data["hackedavailable"] = TRUE
hacked_programs.Add(list(list(
"filename" = P.filename,
"filedesc" = P.filedesc,
"fileinfo" = P.extended_desc,
"size" = P.size
)))
data["hacked_programs"] = hacked_programs
// No connection, so cancel the download.
// This is done at the end because of logic reasons.
// Trust me, it's fine. - Skull132
if (!speed)
last_update = 0
else
last_update = world.time
data["downloadable_programs"] = all_entries
return data
if(download_queue[active_download] >= active_download_file.size)
finish_from_queue(active_download)
active_download = null
playsound(get_turf(computer), 'sound/machines/ping.ogg', 40, 0)
computer.output_message("\icon[computer] <b>[capitalize_first_letters(computer)]</b> pings, \"Software download completed successfully!\"", 1)
SSvueui.check_uis_for_change(src)