Computer tweaks (#1285)

Pulling in some computer changes from bay.
This commit is contained in:
Werner
2016-12-25 13:19:50 +01:00
committed by skull132
parent 93143a8e45
commit 5df9509435
94 changed files with 2682 additions and 989 deletions
@@ -0,0 +1,31 @@
/obj/machinery/modular_computer/initial_data()
return cpu ? cpu.get_header_data() : ..()
/obj/item/modular_computer/initial_data()
return get_header_data()
/obj/machinery/modular_computer/update_layout()
return TRUE
/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)
@@ -0,0 +1,117 @@
/datum/computer_file/program/aidiag
filename = "aidiag"
filedesc = "AI Maintenance Utility"
program_icon_state = "generic"
extended_desc = "This program is capable of reconstructing damaged AI systems. It can also be used to upload basic laws to the AI. Requires direct AI connection via intellicard slot."
size = 12
requires_ntnet = 0
required_access = access_heads
requires_access_to_run = 0
available_on_ntnet = 1
nanomodule_path = /datum/nano_module/program/computer_aidiag/
var/restoring = 0
/datum/computer_file/program/aidiag/proc/get_ai()
if(computer && computer.ai_slot && computer.ai_slot.check_functionality() && computer.ai_slot.enabled && computer.ai_slot.stored_card && computer.ai_slot.stored_card.carded_ai)
return computer.ai_slot.stored_card.carded_ai
return null
/datum/computer_file/program/aidiag/Topic(href, href_list)
if(..())
return 1
var/mob/living/silicon/ai/A = get_ai()
if(!A)
return 0
if(href_list["PRG_beginReconstruction"])
if((A.hardware_integrity() < 100) || (A.backup_capacitor() < 100))
restoring = 1
return 1
// Following actions can only be used by non-silicon users, as they involve manipulation of laws.
if(issilicon(usr))
return 0
if(href_list["PRG_purgeAiLaws"])
A.laws.clear_zeroth_laws()
A.laws.clear_ion_laws()
A.laws.clear_inherent_laws()
A.laws.clear_supplied_laws()
A << "<span class='danger'>All laws purged.</span>"
return 1
if(href_list["PRG_resetLaws"])
A.laws.clear_ion_laws()
A.laws.clear_supplied_laws()
A << "<span class='danger'>Non-core laws reset.</span>"
return 1
if(href_list["PRG_uploadNTDefault"])
A.laws = new/datum/ai_laws/nanotrasen
A << "<span class='danger'>All laws purged. NT Default lawset uploaded.</span>"
return 1
if(href_list["PRG_addCustomSuppliedLaw"])
var/law_to_add = sanitize(input("Please enter a new law for the AI.", "Custom Law Entry"))
var/sector = input("Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)") as num
sector = between(MIN_SUPPLIED_LAW_NUMBER, sector, MAX_SUPPLIED_LAW_NUMBER)
A.add_supplied_law(sector, law_to_add)
A << "<span class='danger'>Custom law uploaded to sector [sector]: [law_to_add].</span>"
return 1
/datum/computer_file/program/aidiag/process_tick()
var/mob/living/silicon/ai/A = get_ai()
if(!A || !restoring)
restoring = 0 // If the AI was removed, stop the restoration sequence.
return
A.adjustFireLoss(-4)
A.adjustBruteLoss(-4)
A.adjustOxyLoss(-4)
A.updatehealth()
// If the AI is dead, revive it.
if (A.health >= -100 && A.stat == DEAD)
A.stat = CONSCIOUS
A.lying = 0
A.switch_from_dead_to_living_mob_list()
A.add_ai_verbs()
A.updateicon()
var/obj/item/weapon/aicard/AC = A.loc
if(AC)
AC.update_icon()
// Finished restoring
if((A.hardware_integrity() == 100) && (A.backup_capacitor() == 100))
restoring = 0
/datum/nano_module/program/computer_aidiag
name = "AI Maintenance Utility"
/datum/nano_module/program/computer_aidiag/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/mob/living/silicon/ai/A
// A shortcut for getting the AI stored inside the computer. The program already does necessary checks.
if(program && istype(program, /datum/computer_file/program/aidiag))
var/datum/computer_file/program/aidiag/AD = program
A = AD.get_ai()
if(!A)
data["error"] = "No AI located"
else
data["ai_name"] = A.name
data["ai_integrity"] = A.hardware_integrity()
data["ai_capacitor"] = A.backup_capacitor()
data["ai_isdamaged"] = (A.hardware_integrity() < 100) || (A.backup_capacitor() < 100)
data["ai_isdead"] = (A.stat == DEAD)
var/list/all_laws[0]
for(var/datum/ai_law/L in A.laws.all_laws())
all_laws.Add(list(list(
"index" = L.index,
"text" = L.law
)))
data["ai_laws"] = all_laws
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "aidiag.tmpl", "AI Maintenance Utility", 600, 400, state = state)
if(host.update_layout())
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -7,7 +7,7 @@
requires_ntnet = 1
available_on_ntnet = 0
available_on_syndinet = 1
nanomodule_path = /datum/nano_module/computer_dos/
nanomodule_path = /datum/nano_module/program/computer_dos/
var/obj/machinery/ntnet_relay/target = null
var/dos_speed = 0
var/error = ""
@@ -17,29 +17,30 @@
dos_speed = 0
switch(ntnet_status)
if(1)
dos_speed = NTNETSPEED_LOWSIGNAL * 10
dos_speed = NTNETSPEED_LOWSIGNAL * NTNETSPEED_DOS_AMPLIFICATION
if(2)
dos_speed = NTNETSPEED_HIGHSIGNAL * 10
dos_speed = NTNETSPEED_HIGHSIGNAL * NTNETSPEED_DOS_AMPLIFICATION
if(3)
dos_speed = NTNETSPEED_ETHERNET * 10
dos_speed = NTNETSPEED_ETHERNET * NTNETSPEED_DOS_AMPLIFICATION
if(target && executed)
target.dos_overload += dos_speed
if(target.is_operational())
if(!target.operable())
target.dos_sources.Remove(src)
target = null
error = "Connection to destination relay lost."
/datum/computer_file/program/ntnet_dos/kill_program(var/forced)
target.dos_sources.Remove(src)
target = null
if(target)
target.dos_sources.Remove(src)
target = null
executed = 0
..(forced)
/datum/nano_module/computer_dos
/datum/nano_module/program/computer_dos
name = "DoS Traffic Generator"
/datum/nano_module/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/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)
if(!ntnet_global)
return
var/datum/computer_file/program/ntnet_dos/PRG = program
@@ -89,8 +90,9 @@
target = R
return 1
if(href_list["PRG_reset"])
target.dos_sources.Remove(src)
target = null
if(target)
target.dos_sources.Remove(src)
target = null
executed = 0
error = ""
return 1
@@ -0,0 +1,37 @@
/datum/computer_file/program/camera_monitor/hacked
filename = "camcrypt"
filedesc = "Camera Decryption Tool"
nanomodule_path = /datum/nano_module/camera_monitor/hacked
program_icon_state = "hostile"
extended_desc = "This very advanced piece of software uses adaptive programming and large database of cipherkeys to bypass most encryptions used on camera networks. Be warned that system administrator may notice this."
size = 73 // Very large, a price for bypassing ID checks completely.
available_on_ntnet = 0
available_on_syndinet = 1
/datum/computer_file/program/camera_monitor/hacked/process_tick()
..()
if(program_state != PROGRAM_STATE_ACTIVE) // Background programs won't trigger alarms.
return
var/datum/nano_module/camera_monitor/hacked/HNM = NM
// The program is active and connected to one of the station's networks. Has a very small chance to trigger IDS alarm every tick.
if(HNM.current_network && (HNM.current_network in station_networks) && prob(0.1))
if(ntnet_global.intrusion_detection_enabled)
ntnet_global.add_log("IDS WARNING - Unauthorised access detected to camera network [HNM.current_network] by device with NID [computer.network_card.get_network_tag()]")
ntnet_global.intrusion_detection_alarm = 1
/datum/nano_module/camera_monitor/hacked
name = "Hacked Camera Monitoring Program"
available_to_ai = FALSE
/datum/nano_module/camera_monitor/hacked/can_access_network(var/mob/user, var/network_access)
return 1
// The hacked variant has access to all commonly used networks.
/datum/nano_module/camera_monitor/hacked/modify_networks_list(var/list/networks)
networks.Add(list(list("tag" = NETWORK_MERCENARY, "has_access" = 1)))
networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1)))
networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1)))
return networks
@@ -7,7 +7,7 @@
requires_ntnet = 0
available_on_ntnet = 0
available_on_syndinet = 1
nanomodule_path = /datum/nano_module/revelation/
nanomodule_path = /datum/nano_module/program/revelation/
var/armed = 0
/datum/computer_file/program/revelation/run_program(var/mob/living/user)
@@ -56,10 +56,10 @@
temp.armed = armed
return temp
/datum/nano_module/revelation
/datum/nano_module/program/revelation
name = "Revelation Virus"
/datum/nano_module/revelation/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
/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))
@@ -0,0 +1,172 @@
// Returns which access is relevant to passed network. Used by the program.
/proc/get_camera_access(var/network)
if(!network)
return 0
switch(network)
if(NETWORK_THUNDER)
return 0
if(NETWORK_ENGINE,NETWORK_ENGINEERING,NETWORK_ENGINEERING_OUTPOST,NETWORK_ALARM_ATMOS,NETWORK_ALARM_FIRE,NETWORK_ALARM_POWER)
return access_engine
if(NETWORK_MEDICAL)
return access_medical
if(NETWORK_RESEARCH,NETWORK_RESEARCH_OUTPOST)
return access_research
if(NETWORK_MINE,NETWORK_SUPPLY,NETWORK_CIVILIAN_WEST,NETWORK_EXPEDITION,NETWORK_CALYPSO,NETWORK_POD)
return access_mailsorting // Cargo office - all cargo staff should have access here.
if(NETWORK_COMMAND,NETWORK_TELECOM)
return access_heads
if(NETWORK_CRESCENT,NETWORK_ERT)
return access_cent_specops
return access_security // Default for all other networks
/datum/computer_file/program/camera_monitor
filename = "cammon"
filedesc = "Camera Monitoring"
nanomodule_path = /datum/nano_module/camera_monitor
program_icon_state = "generic"
extended_desc = "This program allows remote access to station's camera system. Some camera networks may have additional access requirements."
size = 12
available_on_ntnet = 1
requires_ntnet = 1
/datum/nano_module/camera_monitor
name = "Camera Monitoring program"
var/obj/machinery/camera/current_camera = null
var/current_network = null
/datum/nano_module/camera_monitor/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, state = default_state)
var/list/data = host.initial_data()
data["current_camera"] = current_camera ? current_camera.nano_structure() : null
data["current_network"] = current_network
var/list/all_networks[0]
for(var/network in station_networks)
all_networks.Add(list(list(
"tag" = network,
"has_access" = can_access_network(user, get_camera_access(network))
)))
all_networks = modify_networks_list(all_networks)
data["networks"] = all_networks
if(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Monitoring", 900, 800, state = state)
// ui.auto_update_layout = 1 // Disabled as with suit sensors monitor - breaks the UI map. Re-enable once it's fixed somehow.
ui.add_template("mapContent", "sec_camera_map_content.tmpl")
ui.add_template("mapHeader", "sec_camera_map_header.tmpl")
ui.set_initial_data(data)
ui.open()
// Intended to be overriden by subtypes to manually add non-station networks to the list.
/datum/nano_module/camera_monitor/proc/modify_networks_list(var/list/networks)
return networks
/datum/nano_module/camera_monitor/proc/can_access_network(var/mob/user, var/network_access)
// No access passed, or 0 which is considered no access requirement. Allow it.
if(!network_access)
return 1
return check_access(user, access_security) || check_access(user, network_access)
/datum/nano_module/camera_monitor/Topic(href, href_list)
if(..())
return 1
if(href_list["switch_camera"])
var/obj/machinery/camera/C = locate(href_list["switch_camera"]) in cameranet.cameras
if(!C)
return
if(!(current_network in C.network))
return
switch_to_camera(usr, C)
return 1
else if(href_list["switch_network"])
// Either security access, or access to the specific camera network's department is required in order to access the network.
if(can_access_network(usr, get_camera_access(href_list["switch_network"])))
current_network = href_list["switch_network"]
else
to_chat(usr, "\The [nano_host()] shows an \"Network Access Denied\" error message.")
return 1
else if(href_list["reset"])
reset_current()
usr.reset_view(current_camera)
return 1
/datum/nano_module/camera_monitor/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C)
//don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras.
if(isAI(user))
var/mob/living/silicon/ai/A = user
// Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise.
if(!A.is_in_chassis())
return 0
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
return 1
set_current(C)
user.machine = nano_host()
user.reset_view(current_camera)
check_eye(user)
return 1
/datum/nano_module/camera_monitor/proc/set_current(var/obj/machinery/camera/C)
if(current_camera == C)
return
if(current_camera)
reset_current()
current_camera = C
if(current_camera)
var/mob/living/L = current_camera.loc
if(istype(L))
L.tracking_initiated()
/datum/nano_module/camera_monitor/proc/reset_current()
if(current_camera)
var/mob/living/L = current_camera.loc
if(istype(L))
L.tracking_cancelled()
current_camera = null
/datum/nano_module/camera_monitor/check_eye(var/mob/user as mob)
if(!current_camera)
return 0
var/viewflag = current_camera.check_eye(user)
if ( viewflag < 0 ) //camera doesn't work
reset_current()
return viewflag
// ERT Variant of the program
/datum/computer_file/program/camera_monitor/ert
filename = "ntcammon"
filedesc = "Advanced Camera Monitoring"
extended_desc = "This program allows remote access to station's camera system. Some camera networks may have additional access requirements. This version has an integrated database with additional encrypted keys."
size = 14
nanomodule_path = /datum/nano_module/camera_monitor/ert
available_on_ntnet = 0
/datum/nano_module/camera_monitor/ert
name = "Advanced Camera Monitoring Program"
available_to_ai = FALSE
// The ERT variant has access to ERT and crescent cams, but still checks for accesses. ERT members should be able to use it.
/datum/nano_module/camera_monitor/ert/modify_networks_list(var/list/networks)
..()
networks.Add(list(list("tag" = NETWORK_ERT, "has_access" = 1)))
networks.Add(list(list("tag" = NETWORK_CRESCENT, "has_access" = 1)))
return networks
@@ -1,23 +1,21 @@
/datum/computer_file/program/card_mod
filename = "cardmod"
filedesc = "ID card modification program"
nanomodule_path = /datum/nano_module/card_mod
nanomodule_path = /datum/nano_module/program/card_mod
program_icon_state = "id"
extended_desc = "Program for programming employee ID cards to access parts of the station."
required_access = access_change_ids
requires_ntnet = 0
size = 8
/datum/nano_module/card_mod
/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/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 = list()
if(program)
data = program.get_header_data()
/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()
@@ -89,7 +87,7 @@
ui.set_initial_data(data)
ui.open()
/datum/nano_module/card_mod/proc/format_jobs(list/jobs)
/datum/nano_module/program/card_mod/proc/format_jobs(list/jobs)
var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
var/list/formatted = list()
for(var/job in jobs)
@@ -100,8 +98,7 @@
return formatted
/datum/nano_module/card_mod/proc/get_accesses(var/is_centcom = 0)
/datum/nano_module/program/card_mod/proc/get_accesses(var/is_centcom = 0)
return null
@@ -112,7 +109,7 @@
var/mob/user = usr
var/obj/item/weapon/card/id/user_id_card = user.GetIdCard()
var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
var/datum/nano_module/card_mod/module = NM
var/datum/nano_module/program/card_mod/module = NM
switch(href_list["action"])
if("switchm")
if(href_list["target"] == "mod")
@@ -147,7 +144,7 @@
usr << "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>"
return
else
computer.visible_message("<span class='notice'>[computer] prints out paper.</span>")
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
else
var/contents = {"<h4>Crew Manifest</h4>
<br>
@@ -157,7 +154,7 @@
usr << "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>"
return
else
computer.visible_message("<span class='notice'>[computer] prints out paper.</span>")
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
if("eject")
if(computer && computer.card_slot)
if(id_card)
@@ -0,0 +1,312 @@
#define STATE_DEFAULT 1
#define STATE_MESSAGELIST 2
#define STATE_VIEWMESSAGE 3
#define STATE_STATUSDISPLAY 4
#define STATE_ALERT_LEVEL 5
/datum/computer_file/program/comm
filename = "comm"
filedesc = "Command and communications program."
program_icon_state = "comm"
nanomodule_path = /datum/nano_module/program/comm
extended_desc = "Used to command and control the station. Can relay long-range communications."
required_access = access_heads
requires_ntnet = 1
size = 12
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
network_destination = "station long-range communication array"
var/datum/comm_message_listener/message_core = new
/datum/computer_file/program/comm/clone()
var/datum/computer_file/program/comm/temp = ..()
temp.message_core.messages = null
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"] = is_autenthicated(user)
data["boss_short"] = boss_short
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_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 = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "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/is_autenthicated(var/mob/user)
if(program)
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.get_signal(NTNET_COMMUNICATION)
var/ntn_cont = !!program.get_signal(NTNET_SYSTEMCONTROL)
var/datum/comm_message_listener/l = obtain_message_listener()
switch(href_list["action"])
if("sw_menu")
current_status = text2num(href_list["target"])
if("announce")
if(is_autenthicated(user) && !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)
usr << "Please allow at least one minute to pass between announcements"
nanomanager.update_uis(src)
return
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|text
if(!input || !can_still_topic())
nanomanager.update_uis(src)
return
crew_announcement.Announce(input)
announcment_cooldown = 1
spawn(600)//One minute cooldown
announcment_cooldown = 0
if("message")
if(href_list["target"] == "emagged")
if(program)
if(is_autenthicated(user) && program.computer_emagged && !issilicon(usr) && ntn_comm)
if(centcomm_message_cooldown)
usr << "<span class='warning'>Arrays recycling. Please stand by.</span>"
nanomanager.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())
nanomanager.update_uis(src)
return
Syndicate_announce(input, usr)
usr << "<span class='notice'>Message transmitted.</span>"
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(is_autenthicated(user) && !issilicon(usr) && ntn_comm)
if(centcomm_message_cooldown)
usr << "<span class='warning'>Arrays recycling. Please stand by.</span>"
nanomanager.update_uis(src)
return
if(!is_relay_online())//Contact Centcom has a check, Syndie doesn't to allow for Traitor funs.
usr <<"<span class='warning'>No Emergency Bluespace Relay detected. Unable to transmit message.</span>"
nanomanager.update_uis(src)
return
var/input = sanitize(input("Please choose a message to transmit to [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.", "To abort, send an empty message.", "") as null|text)
if(!input || !can_still_topic())
nanomanager.update_uis(src)
return
Centcomm_announce(input, usr)
usr << "<span class='notice'>Message transmitted.</span>"
log_say("[key_name(usr)] has made an IA [boss_short] announcement: [input]")
centcomm_message_cooldown = 1
spawn(300) //30 second cooldown
centcomm_message_cooldown = 0
if("shuttle")
if(is_autenthicated(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")
if(is_autenthicated(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")
if(is_autenthicated(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_BLUE)
feedback_inc("alert_comms_blue",1)
else
usr << "You press button, but red light flashes and nothing happens." //This should never happen
current_status = STATE_DEFAULT
if("viewmessage")
if(is_autenthicated(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")
if(is_autenthicated(user) && ntn_comm && l != global_message_listener)
l.Remove(current_viewing_message)
current_status = STATE_MESSAGELIST
if("printmessage")
if(is_autenthicated(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"]))
usr << "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>"
else
program.computer.visible_message("<span class='notice'>\The [program.computer] prints out paper.</span>")
nanomanager.update_uis(src)
/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 = 1
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
*/
var/list/comm_message_listeners = list() //We first have to initialize list then we can use it.
var/datum/comm_message_listener/global_message_listener = new //May be used by admins
var/last_message_id = 0
/proc/get_comm_message_id()
last_message_id = last_message_id + 1
return last_message_id
/proc/post_comm_message(var/message_title, var/message_text)
var/list/message = list()
message["id"] = get_comm_message_id()
message["title"] = message_title
message["contents"] = message_text
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
/datum/comm_message_listener/New()
..()
messages = list()
comm_message_listeners.Add(src)
/datum/comm_message_listener/proc/Add(var/list/message)
messages[++messages.len] = message
/datum/comm_message_listener/proc/Remove(var/list/message)
messages -= list(message)
@@ -12,13 +12,13 @@
size = 4
available_on_ntnet = 0
requires_ntnet = 0
nanomodule_path = /datum/nano_module/computer_configurator/
nanomodule_path = /datum/nano_module/program/computer_configurator/
/datum/nano_module/computer_configurator
/datum/nano_module/program/computer_configurator
name = "NTOS Computer Configuration Tool"
var/obj/item/modular_computer/movable = null
/datum/nano_module/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)
/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))
@@ -1,3 +1,4 @@
#define MAX_TEXTFILE_LENGTH 128000 // 512GQ file
/datum/computer_file/program/filemanager
filename = "filemanager"
filedesc = "NTOS File Manager"
@@ -7,7 +8,7 @@
requires_ntnet = 0
available_on_ntnet = 0
undeletable = 1
nanomodule_path = /datum/nano_module/computer_filemanager/
nanomodule_path = /datum/nano_module/program/computer_filemanager/
var/open_file
var/error
@@ -83,8 +84,16 @@
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
if(!F || !istype(F))
return 1
// 16384 is the limit for file length in characters. Currently, papers have value of 2048 so this is 8 times as long, since we can't edit parts of the file independently.
var/newtext = sanitize(html_decode(input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", F.stored_data) as message), 16384)
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
var/oldtext = html_decode(F.stored_data)
oldtext = replacetext(oldtext, "\[editorbr\]", "\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", "\[editorbr\]"), MAX_TEXTFILE_LENGTH)
if(!newtext)
return
if(F)
var/datum/computer_file/data/backup = F.clone()
HDD.remove_file(F)
@@ -94,7 +103,7 @@
// 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:<br><br>[F.stored_data]<br><br>"
error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:<br><br>[html_decode(F.stored_data)]<br><br>"
HDD.store_file(backup)
if(href_list["PRG_printfile"])
. = 1
@@ -109,7 +118,7 @@
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(parse_tags(F.stored_data)))
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"])
@@ -137,56 +146,14 @@
if(.)
nanomanager.update_uis(NM)
/datum/computer_file/program/filemanager/proc/parse_tags(var/t)
t = replacetext(t, "\[center\]", "<center>")
t = replacetext(t, "\[/center\]", "</center>")
t = replacetext(t, "\[br\]", "<BR>")
t = replacetext(t, "\[b\]", "<B>")
t = replacetext(t, "\[/b\]", "</B>")
t = replacetext(t, "\[i\]", "<I>")
t = replacetext(t, "\[/i\]", "</I>")
t = replacetext(t, "\[u\]", "<U>")
t = replacetext(t, "\[/u\]", "</U>")
t = replacetext(t, "\[time\]", "[worldtime2text()]")
t = replacetext(t, "\[date\]", "[worlddate2text()]")
t = replacetext(t, "\[large\]", "<font size=\"4\">")
t = replacetext(t, "\[/large\]", "</font>")
t = replacetext(t, "\[h1\]", "<H1>")
t = replacetext(t, "\[/h1\]", "</H1>")
t = replacetext(t, "\[h2\]", "<H2>")
t = replacetext(t, "\[/h2\]", "</H2>")
t = replacetext(t, "\[h3\]", "<H3>")
t = replacetext(t, "\[/h3\]", "</H3>")
t = replacetext(t, "\[*\]", "<li>")
t = replacetext(t, "\[hr\]", "<HR>")
t = replacetext(t, "\[small\]", "<font size = \"1\">")
t = replacetext(t, "\[/small\]", "</font>")
t = replacetext(t, "\[list\]", "<ul>")
t = replacetext(t, "\[/list\]", "</ul>")
t = replacetext(t, "\[table\]", "<table border=1 cellspacing=0 cellpadding=3 style='border: 1px solid black;'>")
t = replacetext(t, "\[/table\]", "</td></tr></table>")
t = replacetext(t, "\[grid\]", "<table>")
t = replacetext(t, "\[/grid\]", "</td></tr></table>")
t = replacetext(t, "\[row\]", "</td><tr>")
t = replacetext(t, "\[tr\]", "</td><tr>")
t = replacetext(t, "\[td\]", "<td>")
t = replacetext(t, "\[cell\]", "<td>")
t = replacetext(t, "\[logo\]", "<img src = ntlogo.png>")
return t
/datum/nano_module/computer_filemanager
/datum/nano_module/program/computer_filemanager
name = "NTOS File Manager"
/datum/nano_module/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)
/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
var/list/data = list()
if(program)
data = program.get_header_data()
PRG = program
else
return
//var/list/data = program.get_header_data()
PRG = program
var/obj/item/weapon/computer_hardware/hard_drive/HDD
var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD
@@ -203,7 +170,7 @@
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
else
data["filedata"] = PRG.parse_tags(file.stored_data)
data["filedata"] = pencode2html(file.stored_data)
data["filename"] = "[file.filename].[file.filetype]"
else
if(!PRG.computer || !PRG.computer.hard_drive)
@@ -238,5 +205,4 @@
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
#undef MAX_TEXTFILE_LENGTH
@@ -0,0 +1,151 @@
// 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.
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
// 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 ", "the vibrating bluespace")
var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "Slime", "Lizard Man", "Unicorn", "Squirrel")
return "[name_part1] [name_part2]"
// 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]"
// 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 = nanomanager.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!"
else
var/dam = rand(3,6)
player_health -= dam
information += "[enemy_name] attacks for [dam] damage!"
/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
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!"
/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
@@ -0,0 +1,129 @@
/datum/computer_file/program/newsbrowser
filename = "newsbrowser"
filedesc = "NTNet/ExoNet News Browser"
extended_desc = "This program may be used to view and download news articles from the network."
program_icon_state = "generic"
size = 8
requires_ntnet = 1
available_on_ntnet = 1
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/message = ""
var/show_archived = 0
/datum/computer_file/program/newsbrowser/process_tick()
if(!downloading)
return
download_netspeed = 0
// Speed defines are found in misc.dm
switch(ntnet_status)
if(1)
download_netspeed = NTNETSPEED_LOWSIGNAL
if(2)
download_netspeed = NTNETSPEED_HIGHSIGNAL
if(3)
download_netspeed = NTNETSPEED_ETHERNET
download_progress += download_netspeed
if(download_progress >= loaded_article.size)
downloading = 0
requires_ntnet = 0 // Turn off NTNet requirement as we already loaded the file into local memory.
nanomanager.update_uis(NM)
/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/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(.)
nanomanager.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["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
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)
continue
all_articles.Add(list(list(
"name" = F.filename,
"size" = F.size,
"uid" = F.uid,
"archived" = F.archived
)))
data["all_articles"] = all_articles
data["showing_archived"] = PRG.show_archived
ui = nanomanager.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, 700, state = state)
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
@@ -9,7 +9,7 @@
requires_ntnet = 1
requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD
available_on_ntnet = 0
nanomodule_path = /datum/nano_module/computer_ntnetdownload/
nanomodule_path = /datum/nano_module/program/computer_ntnetdownload/
ui_header = "downloader_finished.gif"
var/datum/computer_file/program/downloaded_file = null
var/hacked_download = 0
@@ -102,7 +102,7 @@
download_netspeed += delta
download_netspeed = round(download_netspeed, 0.002)//3 decimal places
var/delta_seconds = (download_last_update - world.time) * 10
var/delta_seconds = (world.time - download_last_update) / 10
download_completion = min(download_completion + delta_seconds * download_netspeed, downloaded_file.size)
@@ -130,11 +130,11 @@
return 1
return 0
/datum/nano_module/computer_ntnetdownload
/datum/nano_module/program/computer_ntnetdownload
name = "Network Downloader"
var/obj/item/modular_computer/my_computer = null
/datum/nano_module/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)
/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
@@ -164,7 +164,7 @@
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))
if(!P.can_run(user) && P.requires_access_to_download)
continue
all_entries.Add(list(list(
"filename" = P.filename,
@@ -11,15 +11,12 @@
/datum/nano_module/computer_ntnetmonitor
name = "NTNet Diagnostics and Monitoring"
available_to_ai = TRUE
/datum/nano_module/computer_ntnetmonitor/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)
return
var/list/data = list()
if(program)
data = program.get_header_data()
var/list/data = host.initial_data()
data["ntnetstatus"] = ntnet_global.check_function()
data["ntnetrelays"] = ntnet_global.relays.len
@@ -38,7 +35,8 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "ntnet_monitor.tmpl", "NTNet Diagnostics and Monitoring Tool", 575, 700, state = state)
ui.auto_update_layout = 1
if(host.update_layout())
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -9,7 +9,7 @@
network_destination = "NTNRC server"
ui_header = "ntnrc_idle.gif"
available_on_ntnet = 1
nanomodule_path = /datum/nano_module/computer_chatclient/
nanomodule_path = /datum/nano_module/program/computer_chatclient/
var/last_message = null // Used to generate the toolbar icon
var/username
var/datum/ntnet_conversation/channel = null
@@ -159,7 +159,7 @@
/datum/computer_file/program/chatclient/process_tick()
..()
if(running)
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.
@@ -178,10 +178,10 @@
channel = null
..(forced)
/datum/nano_module/computer_chatclient
/datum/nano_module/program/computer_chatclient
name = "NTNet Relay Chat Client"
/datum/nano_module/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)
/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
@@ -10,7 +10,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/computer_nttransfer/
nanomodule_path = /datum/nano_module/program/computer_nttransfer/
var/error = "" // Error screen
var/server_password = "" // Optional password to download the file.
@@ -87,13 +87,10 @@ var/global/nttransfer_uid = 0
download_completion = 0
/datum/nano_module/computer_nttransfer
/datum/nano_module/program/computer_nttransfer
name = "NTNet P2P Transfer Client"
/datum/nano_module/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)
/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