mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-19 12:05:59 +01:00
Base systems pretty much done.
Still need to convert the id computer program.
This commit is contained in:
@@ -16,12 +16,12 @@ var/global/ntnrc_uid = 0
|
||||
..()
|
||||
|
||||
/datum/ntnet_conversation/proc/add_message(var/message, var/username)
|
||||
message = "[stationtime2text()] [username]: [message]"
|
||||
message = "[worldtime2text()] [username]: [message]"
|
||||
messages.Add(message)
|
||||
trim_message_list()
|
||||
|
||||
/datum/ntnet_conversation/proc/add_status_message(var/message)
|
||||
messages.Add("[stationtime2text()] -!- [message]")
|
||||
messages.Add("[worldtime2text()] -!- [message]")
|
||||
trim_message_list()
|
||||
|
||||
/datum/ntnet_conversation/proc/trim_message_list()
|
||||
|
||||
@@ -7,7 +7,6 @@ var/global/datum/ntnet/ntnet_global = new()
|
||||
var/list/logs = list()
|
||||
var/list/available_station_software = list()
|
||||
var/list/available_antag_software = list()
|
||||
var/list/available_news = list()
|
||||
var/list/chat_channels = list()
|
||||
var/list/fileservers = list()
|
||||
// Amount of logs the system tries to keep in memory. Keep below 999 to prevent byond from acting weirdly.
|
||||
@@ -33,7 +32,6 @@ var/global/datum/ntnet/ntnet_global = new()
|
||||
relays.Add(R)
|
||||
R.NTNet = src
|
||||
build_software_lists()
|
||||
build_news_list()
|
||||
add_log("NTNet logging system activated.")
|
||||
|
||||
// Simplified logging: Adds a log. log_string is mandatory parameter, source is optional.
|
||||
@@ -95,17 +93,6 @@ var/global/datum/ntnet/ntnet_global = new()
|
||||
if(prog.available_on_syndinet)
|
||||
available_antag_software.Add(prog)
|
||||
|
||||
// Builds lists that contain downloadable software.
|
||||
/datum/ntnet/proc/build_news_list()
|
||||
/*
|
||||
available_news = list()
|
||||
for(var/F in typesof(/datum/computer_file/data/news_article/))
|
||||
var/datum/computer_file/data/news_article/news = new F(1)
|
||||
if(news.stored_data)
|
||||
available_news.Add(news)
|
||||
*/
|
||||
return 1
|
||||
|
||||
// Attempts to find a downloadable file according to filename var
|
||||
/datum/ntnet/proc/find_ntnet_file_by_name(var/filename)
|
||||
for(var/datum/computer_file/program/P in available_station_software)
|
||||
@@ -154,8 +141,3 @@ var/global/datum/ntnet/ntnet_global = new()
|
||||
if(NTNET_SYSTEMCONTROL)
|
||||
setting_systemcontrol = !setting_systemcontrol
|
||||
add_log("Configuration Updated. Wireless network firewall now [setting_systemcontrol ? "allows" : "disallows"] remote control of station's systems.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,12 +57,12 @@
|
||||
ntnet_global.add_log("Quantum relay switched from overload recovery mode to normal operation mode.")
|
||||
..()
|
||||
|
||||
/obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 1, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
/obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "nt_relay", name, 300, 150, master_ui, state)
|
||||
ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", 500, 300, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
|
||||
@@ -137,11 +137,11 @@
|
||||
ntnet_global.relays.Remove(src)
|
||||
ntnet_global.add_log("Quantum relay connection severed. Current amount of linked relays: [NTNet.relays.len]")
|
||||
NTNet = null
|
||||
/*
|
||||
|
||||
for(var/datum/computer_file/program/ntnet_dos/D in dos_sources)
|
||||
D.target = null
|
||||
D.error = "Connection to quantum relay severed"
|
||||
*/
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/ntnet_relay/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
@@ -159,7 +159,7 @@
|
||||
|
||||
for(var/atom/movable/A in component_parts)
|
||||
A.forceMove(src.loc)
|
||||
// new/obj/machinery/constructable_frame/machine_frame(src.loc)
|
||||
new/obj/structure/frame/machine(src.loc)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
Program-based computers, designed to replace computer3 project and eventually most consoles on station
|
||||
|
||||
|
||||
1. Basic information
|
||||
Program based computers will allow you to do multiple things from single computer. Each computer will have programs, with more being downloadable from NTNet (stationwide network with wireless coverage)
|
||||
if user has apropriate ID card access. It will be possible to hack the computer by using an emag on it - the emag will have to be completely new and will be consumed on use, but it will
|
||||
lift ALL locks on ALL installed programs, and allow download of programs even if your ID doesn't have access to them. Computers will have hard drives that can store files.
|
||||
Files can be programs (datum/computer_file/program/ subtype) or data files (datum/computer_file/data/ subtypes). Program for sending files will be available that will allow transfer via NTNet.
|
||||
NTNet coverage will be limited to station's Z level, but better network card (=more expensive and higher power use) will allow usage everywhere. Hard drives will have limited capacity for files
|
||||
which will be related to how good hard drive you buy when purchasing the laptop. For storing more files USB-style drives will be buildable with Protolathe in research.
|
||||
|
||||
2. Available devices
|
||||
CONSOLES
|
||||
Consoles will come in various pre-fabricated loadouts, each loadout starting with certain set of programs (aka Engineering console, Medical console, etc.), of course, more software may be downloaded.
|
||||
Consoles won't usually have integrated battery, but the possibility to install one will exist for critical applications. Consoles are considered hardwired into NTNet network which means they
|
||||
will have working coverage on higher speed (Ethernet is faster than Wi-Fi) and won't require wireless coverage to exist.
|
||||
LAPTOPS
|
||||
Laptops are middle ground between actual portable devices and full consoles. They offer certain level of mobility, as they can be closed, moved somewhere else and then opened again.
|
||||
Laptops will by default have internal battery to power them, and may be recharged with rechargers. However, laptops rely on wireless NTNet coverage. Laptop HDDs are also designed with power efficiency
|
||||
in mind, which means they sacrifice some storage space for higher battery life. Laptops may be dispensed from computer vendor machine, and may be customised before vending. For people which don't
|
||||
want to rely on internal battery, tesla link exists that connects to APC, if one exists.
|
||||
TABLETS
|
||||
Tablets are smallest available devices, designed with full mobility in mind. Tablets have only weak CPU which means the software they can run is somewhat limited. They are also designed with high
|
||||
battery life in mind, which means the hardware focuses on power efficiency rather than high performance. This is most visible with hard drives which have quite small storage capacity.
|
||||
Tablets can't be equipped with tesla link, which means they have to be recharged manually.
|
||||
|
||||
|
||||
3. Computer Hardware
|
||||
Computers will come with basic hardware installed, with upgrades being selectable when purchasing the device.
|
||||
Hard Drive: Stores data, mandatory for the computer to work
|
||||
Network Card: Connects to NTNet
|
||||
Battery: Internal power source that ensures the computer operates when not connected to APC.
|
||||
Extras (those won't be installed by default, but can be bought)
|
||||
ID Card Slot: Required for HoP-style programs to work. Access for security record-style programs is read from ID of user [RFID?] without requiring this
|
||||
APC Tesla Relay: Wirelessly powers the device from APC. Consoles have it by default. Laptops can buy it.
|
||||
Disk Drive: Allows usage of portable data disks.
|
||||
Nano Printer: Allows the computer to scan paper contents and save them to file, as well as recycle papers and print stuff on it.
|
||||
|
||||
4. NTNet
|
||||
NTNet is stationwide network that allows users to download programs needed for their work. It will be possible to send any files to other active computers using relevant program (NTN Transfer).
|
||||
NTNet is under jurisdiction of both Engineering and Research. Engineering is responsible for any repairs if necessary and research is responsible for monitoring. It is similar to PDA messaging.
|
||||
Operation requires functional "NTNet Relay" which is by default placed on tcommsat. If the relay is damaged NTNet will be offline until it is replaced. Multiple relays bring extra redundancy,
|
||||
if one is destroyed the second will take over. If all relays are gone it stops working, simple as that. NTNet may be altered via administration console available to Research Director. It is
|
||||
possible to enable/disable Software Downloading, P2P file transfers and Communication (IC version of IRC, PDA messages for more than two people)
|
||||
|
||||
5. Software
|
||||
Software would almost exclusively use NanoUI modules. Few exceptions are text editor (uses similar screen as TCS IDE used for editing and classic HTML for previewing as Nano looks differently)
|
||||
and similar programs which for some reason require HTML UI. Most software will be highly dependent on NTNet to work as laptops are not physically connected to the station's network.
|
||||
What i plan to add:
|
||||
|
||||
Note: XXXXDB programs will use ingame_manuals to display basic help for players, similar to how books, etc. do
|
||||
|
||||
Basic - Software in this bundle is automagically preinstalled in every new computer
|
||||
NTN Transfer - Allows P2P transfer of files to other computers that run this.
|
||||
Configurator - Allows configuration of computer's hardware, basically status screen.
|
||||
File Browser - Allows you to browse all files stored on the computer. Allows renaming/deleting of files.
|
||||
TXT Editor - Allows you editing data files in text editor mode.
|
||||
NanoPrint - Allows you to operate NanoPrinter hardware to print text files.
|
||||
NTNRC Chat - NTNet Relay Chat client. Allows PDA-messaging style messaging for more than two users. Person which created the conversation is Host and has administrative privilegies (kicking, etc.)
|
||||
NTNet News - Allows reading news from newscaster network.
|
||||
|
||||
Engineering - Requires "Engineering" access on ID card (ie. CE, Atmostech, Engineer)
|
||||
Alarm Monitor - Allows monitoring alarms, same as the stationbound one.
|
||||
Power Monitor - Power monitoring computer, connects to sensors in same way as regular one does.
|
||||
Atmospheric Control - Allows access to the Atmospherics Monitor Console that operates air alarms. Requires extra access: "Atmospherics"
|
||||
RCON Remote Control Console - Allows access to the RCON Remote Control Console. Requires extra access: "Power Equipment"
|
||||
EngiDB - Allows accessing NTNet information repository for information about engineering-related things.
|
||||
|
||||
Medical - Requires "Medbay" access on ID card (ie. CMO, Doctor,..)
|
||||
Medical Records Uplink - Allows editing/reading of medical records. Printing requires NanoPrinter hardware.
|
||||
MediDB - Allows accessing NTNet information repository for information about medical procedures
|
||||
ChemDB - Requires extra access: "Chemistry" - Downloads basic information about recipes from NTNet
|
||||
|
||||
Research - Requires "Research and Development" access on ID card (ie. RD, Roboticist, etc.)
|
||||
Research Server Monitor - Allows monitoring of research levels on RnD servers. (read only)
|
||||
Robotics Monitor Console - Allows monitoring of robots and exosuits. Lockdown/Self-Destruct options are unavailable [balance reasons for malf/traitor AIs]. Requires extra access: "Robotics"
|
||||
NTNRC Administration Console - Allows administrative access to NTNRC. This includes bypassing any channel passwords and enabling "invisible" mode for spying on conversations. Requires extra access: "Research Director"
|
||||
NTNet Administration Console - Allows remote configuration of NTNet Relay - CAUTION: If NTNet is turned off it won't be possible to turn it on again from the computer, as operation requires NTNet to work! Requires extra access: "Research Director"
|
||||
NTNet Monitor - Allows monitoring of NTNet and it's various components, including simplified network logs and system status.
|
||||
|
||||
Security - Requires "Security" access on ID card (ie. HOS, Security officer, Detective)
|
||||
Security Records Uplink - Allows editing/reading of security records. Printing requires Nanoprinter hardware.
|
||||
LawDB - Allows accessing NTNet information repository for security information (corporate regulations)
|
||||
Camera Uplink - Allows viewing cameras around the station.
|
||||
|
||||
Command - Requires "Bridge" access on ID card (all heads)
|
||||
Alertcon Access - Allows changing of alert levels. Red requires activation from two computers with two IDs similar to how those wall mounted devices do.
|
||||
Employment Records Access - Allows reading of employment records. Printing requires NanoPrinter hardware.
|
||||
Communication Console - Allows sending emergency messages to Central.
|
||||
Emergency Shuttle Control Console - Allows calling/recalling the emergency shuttle.
|
||||
Shuttle Control Console - Allows control of various shuttles around the station (mining, research, engineering)
|
||||
|
||||
*REDACTED* - Can be downloaded from SyndiCorp servers, only via emagged devices. These files are very large and limited to laptops/consoles only.
|
||||
SYSCRACK - Allows cracking of secure network terminals, such as, NTNet administration. The sysadmin will probably notice this.
|
||||
SYSOVERRIDE - Allows hacking into any device connected to NTNet. User will notice this and may stop the hack by disconnecting from NTNet first. After hacking various options exist, such as stealing/deleting files.
|
||||
SYSKILL - Tricks NTNet to force-disconnect a device. The sysadmin will probably notice this.
|
||||
SYSDOS - Launches a Denial of Service attack on NTNet relay. Can DoS only one relay at once. Requires NTNet connection. After some time the relay crashes until attack stops. The sysadmin will probably notice this.
|
||||
AIHACK - Hacks an AI, allowing you to upload/remove/modify a law even without relevant circuit board. The AI is alerted once the hack starts, and it takes a while for it to complete. Does not work on AIs with zeroth law.
|
||||
COREPURGE - Deletes all files on the hard drive, including the undeletable ones. Something like software self-destruct for computer.
|
||||
|
||||
6. Security
|
||||
Laptops will be password-lockable. If password is set a MD5 hash of it is stored and password is required every time you turn on the laptop.
|
||||
Passwords may be decrypted by using special Decrypter (protolathable, RDs office starts with one) device that will slowly decrypt the password.
|
||||
Decryption time would be length_of_password * 30 seconds, with maximum being 9 minutes (due to battery life limitations, which is 10+ min).
|
||||
If decrypted the password is cleared, so you can keep using your favorite password without people ever actually revealing it (for meta prevention reasons mostly).
|
||||
Emagged laptops will have option to enable "Safe Encryption". If safely encrypted laptop is decrypted it loses it's emag status and 50% of files is deleted (randomly selected).
|
||||
|
||||
7. System Administrator
|
||||
System Administrator will be new job under Research. It's main specifics will be maintaining of computer systems on station, espicially from software side.
|
||||
From IC perspective they'd probably know how to build a console or something given they work with computers, but they are mostly programmers/network experts.
|
||||
They will have office in research, which will probably replace (and contain) the server room and part of the toxins storage which is currently oversized.
|
||||
They will have access to DOWNLOAD (not run) all programs that exist on NTNet. They'll have fairly good amount of available programs, most of them being
|
||||
administrative consoles and other very useful things. They'll also be able to monitor NTNet. There will probably be one or two job slots.
|
||||
|
||||
8. IDS
|
||||
With addition of various antag programs, IDS(Intrusion Detection System) will be added to NTNet. This system can be turned on/off via administration console.
|
||||
If enabled, this system automatically detects any abnormality and triggers a warning that's visible on the NTNet status screen, as well as generating a security log.
|
||||
IDS can be disabled by simple on/off switch in the configuration.
|
||||
|
||||
*/
|
||||
@@ -28,7 +28,6 @@
|
||||
var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen.
|
||||
var/max_hardware_size = 0 // Maximal hardware size. Currently, tablets have 1, laptops 2 and consoles 3. Limits what hardware types can be installed.
|
||||
var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
|
||||
var/light_strength = 0
|
||||
|
||||
// Damage of the chassis. If the chassis takes too much damage it will break apart.
|
||||
var/damage = 0 // Current damage level
|
||||
@@ -47,6 +46,8 @@
|
||||
|
||||
var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with.
|
||||
var/activetemplate = "computer_main"
|
||||
var/obj/physical = null
|
||||
|
||||
|
||||
|
||||
// Eject ID card from computer, if it has ID slot with card inside.
|
||||
@@ -123,7 +124,7 @@
|
||||
if(response == "Yes")
|
||||
turn_on(user)
|
||||
|
||||
/obj/item/modular_computer/emag_act(remaining_charges, mob/user)
|
||||
/obj/item/modular_computer/emag_act(mob/user)
|
||||
if(computer_emagged)
|
||||
user << "\The [src] was already emagged."
|
||||
return 0
|
||||
@@ -143,6 +144,8 @@
|
||||
machines += src
|
||||
START_PROCESSING(SSmachine, src)
|
||||
update_icon()
|
||||
if(!physical)
|
||||
physical = src
|
||||
..()
|
||||
|
||||
/obj/item/modular_computer/Destroy()
|
||||
@@ -172,11 +175,13 @@
|
||||
return 0
|
||||
|
||||
// Operates NanoUI
|
||||
/obj/item/modular_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = always_state)
|
||||
// if(!screen_on || !enabled)
|
||||
// if(ui)
|
||||
// ui.close()
|
||||
// return 0
|
||||
/obj/item/modular_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
|
||||
if(!screen_on || !enabled)
|
||||
if(ui)
|
||||
ui.close()
|
||||
return 0
|
||||
// if((!battery_module || !battery_module.battery.charge) && !check_power_override())
|
||||
// if(ui)
|
||||
// ui.close()
|
||||
@@ -192,7 +197,7 @@
|
||||
// We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it.
|
||||
// This screen simply lists available programs and user may select them.
|
||||
if(!hard_drive || !hard_drive.stored_files || !hard_drive.stored_files.len)
|
||||
visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.")
|
||||
physical.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.
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
@@ -214,8 +219,11 @@
|
||||
data["programs"] = list()
|
||||
// var/list/programs = list()
|
||||
for(var/datum/computer_file/program/P in hard_drive.stored_files)
|
||||
var/running = 0
|
||||
if(P in idle_threads)
|
||||
running = 1
|
||||
|
||||
data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc))
|
||||
data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running))
|
||||
|
||||
// var/list/program = list()
|
||||
|
||||
@@ -235,7 +243,7 @@
|
||||
turn_on(user)
|
||||
|
||||
/obj/item/modular_computer/proc/break_apart()
|
||||
visible_message("\The [src] breaks apart!")
|
||||
physical.visible_message("\The [src] breaks apart!")
|
||||
var/turf/newloc = get_turf(src)
|
||||
new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2))
|
||||
for(var/obj/item/weapon/computer_hardware/H in get_all_components())
|
||||
@@ -383,7 +391,7 @@
|
||||
P.kill_program(1)
|
||||
idle_threads.Remove(P)
|
||||
if(loud)
|
||||
visible_message("\The [src] shuts down.")
|
||||
physical.visible_message("\The [src] shuts down.")
|
||||
enabled = 0
|
||||
update_icon()
|
||||
return
|
||||
@@ -467,7 +475,7 @@
|
||||
// Used in following function to reduce copypaste
|
||||
/obj/item/modular_computer/proc/power_failure(var/malfunction = 0)
|
||||
if(enabled) // Shut down the computer
|
||||
visible_message("<span class='danger'>\The [src]'s screen flickers \"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\" warning as it shuts down unexpectedly.</span>")
|
||||
physical.visible_message("<span class='danger'>\The [src]'s screen flickers \"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\" warning as it shuts down unexpectedly.</span>")
|
||||
if(active_program)
|
||||
active_program.event_powerfailure(0)
|
||||
for(var/datum/computer_file/program/PRG in idle_threads)
|
||||
@@ -527,7 +535,7 @@
|
||||
user << "Remove all components from \the [src] before disassembling it."
|
||||
return
|
||||
new /obj/item/stack/sheet/metal( get_turf(src.loc), steel_sheet_cost )
|
||||
src.visible_message("\The [src] has been disassembled by [user].")
|
||||
physical.visible_message("\The [src] has been disassembled by [user].")
|
||||
relay_qdel()
|
||||
qdel(src)
|
||||
return
|
||||
@@ -670,8 +678,6 @@
|
||||
|
||||
// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
|
||||
/obj/item/modular_computer/proc/find_hardware_by_name(var/name)
|
||||
world <<"ran"
|
||||
world << name
|
||||
if(portable_drive && (portable_drive.name == name))
|
||||
return portable_drive
|
||||
if(hard_drive && (hard_drive.name == name))
|
||||
@@ -790,4 +796,10 @@
|
||||
//if(HALLOSS)
|
||||
// take_damage(Proj.damage, Proj.damage / 3, 0)
|
||||
if(BURN)
|
||||
take_damage(Proj.damage, Proj.damage / 1.5)
|
||||
take_damage(Proj.damage, Proj.damage / 1.5)
|
||||
|
||||
/obj/item/modular_computer/ui_host()
|
||||
if(physical)
|
||||
return physical
|
||||
else
|
||||
return src
|
||||
@@ -7,5 +7,4 @@
|
||||
hardware_flag = PROGRAM_TABLET
|
||||
max_hardware_size = 1
|
||||
w_class = 2
|
||||
light_strength = 2 // Same as PDAs
|
||||
var/use_power = 1
|
||||
var/use_power = 0
|
||||
@@ -21,7 +21,6 @@
|
||||
/obj/machinery/modular_computer/console/preset/proc/install_programs()
|
||||
return
|
||||
|
||||
/*
|
||||
|
||||
// ===== ENGINEERING CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/engineering
|
||||
@@ -31,18 +30,6 @@
|
||||
/obj/machinery/modular_computer/console/preset/engineering/install_programs()
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/power_monitor())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/atmos_control())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/rcon_console())
|
||||
|
||||
|
||||
// ===== MEDICAL CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/medical
|
||||
console_department = "Medical"
|
||||
desc = "A stationary computer. This one comes preloaded with medical programs."
|
||||
|
||||
/obj/machinery/modular_computer/console/preset/medical/install_programs()
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/suit_sensors())
|
||||
|
||||
|
||||
// ===== RESEARCH CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/research
|
||||
@@ -54,34 +41,6 @@
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
|
||||
|
||||
// ===== COMMAND CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/command
|
||||
console_department = "Command"
|
||||
desc = "A stationary computer. This one comes preloaded with command programs."
|
||||
_has_id_slot = 1
|
||||
_has_printer = 1
|
||||
|
||||
/obj/machinery/modular_computer/console/preset/command/install_programs()
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/comm())
|
||||
|
||||
/obj/machinery/modular_computer/console/preset/command/main
|
||||
console_department = "Command"
|
||||
desc = "A stationary computer. This one comes preloaded with essential command programs."
|
||||
_has_id_slot = 1
|
||||
_has_printer = 1
|
||||
|
||||
// ===== SECURITY CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/security
|
||||
console_department = "Security"
|
||||
desc = "A stationary computer. This one comes preloaded with security programs."
|
||||
|
||||
/obj/machinery/modular_computer/console/preset/security/install_programs()
|
||||
return // No security programs exist, yet, but the preset is ready so it may be mapped in.
|
||||
|
||||
|
||||
// ===== CIVILIAN CONSOLE =====
|
||||
/obj/machinery/modular_computer/console/preset/civilian
|
||||
console_department = "Civilian"
|
||||
@@ -90,5 +49,4 @@
|
||||
/obj/machinery/modular_computer/console/preset/civilian/install_programs()
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
|
||||
cpu.hard_drive.store_file(new/datum/computer_file/program/newsbrowser())
|
||||
*/
|
||||
|
||||
|
||||
@@ -38,9 +38,8 @@ var/list/global_modular_computers = list()
|
||||
if(cpu)
|
||||
cpu.attack_ghost(user)
|
||||
|
||||
/obj/machinery/modular_computer/emag_act(remaining_charges, mob/user)
|
||||
// return cpu ? cpu.emag_act(remaining_charges, user) : NO_EMAG_ACT
|
||||
return 1
|
||||
/obj/machinery/modular_computer/emag_act(mob/user)
|
||||
return cpu ? cpu.emag_act(user) : 1
|
||||
|
||||
/obj/machinery/modular_computer/update_icon()
|
||||
icon_state = icon_state_unpowered
|
||||
@@ -78,6 +77,7 @@ var/list/global_modular_computers = list()
|
||||
/obj/machinery/modular_computer/New()
|
||||
..()
|
||||
cpu = new(src)
|
||||
cpu.physical = src
|
||||
global_modular_computers.Add(src)
|
||||
|
||||
/obj/machinery/modular_computer/Destroy()
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// /data/ files store data in string format.
|
||||
// They don't contain other logic for now.
|
||||
/datum/computer_file/data/news_article
|
||||
filetype = "XNML"
|
||||
filename = "Unknown News Entry"
|
||||
block_size = 1000 // Results in smaller files
|
||||
do_not_edit = 1 // Editing the file breaks most formatting due to some HTML tags not being accepted as input from average user.
|
||||
var/server_file_path // File path to HTML file that will be loaded on server start. Example: '/news_articles/space_magazine_1.html'. Use the /news_articles/ folder!
|
||||
|
||||
/datum/computer_file/data/news_article/New(var/load_from_file = 0)
|
||||
..()
|
||||
if(server_file_path && load_from_file)
|
||||
stored_data = file2text(server_file_path)
|
||||
calculate_size()
|
||||
|
||||
|
||||
// NEWS DEFINITIONS BELOW THIS LINE
|
||||
|
||||
/datum/computer_file/data/news_article/space/vol_one
|
||||
filename = "SPACE Magazine vol. 1"
|
||||
server_file_path = 'news_articles/space_magazine_1.html'
|
||||
|
||||
/datum/computer_file/data/news_article/space/vol_two
|
||||
filename = "SPACE Magazine vol. 2"
|
||||
server_file_path = 'news_articles/space_magazine_2.html'
|
||||
|
||||
/datum/computer_file/data/news_article/space/vol_three
|
||||
filename = "SPACE Magazine vol. 3"
|
||||
server_file_path = 'news_articles/space_magazine_3.html'
|
||||
@@ -29,9 +29,6 @@
|
||||
computer = null
|
||||
. = ..()
|
||||
|
||||
//datum/computer_file/program/nano_host()
|
||||
// return computer.nano_host()
|
||||
|
||||
/datum/computer_file/program/clone()
|
||||
var/datum/computer_file/program/temp = ..()
|
||||
temp.required_access = required_access
|
||||
@@ -79,19 +76,19 @@
|
||||
access_to_check = required_access
|
||||
if(!access_to_check) // No required_access, allow it.
|
||||
return 1
|
||||
return 1
|
||||
/*
|
||||
var/obj/item/weapon/card/id/I = user.GetIdCard()
|
||||
|
||||
|
||||
var/obj/item/weapon/card/id/I = user.GetID()
|
||||
if(!I)
|
||||
if(loud)
|
||||
user << "<span class='danger'>\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.</span>"
|
||||
return 0
|
||||
|
||||
if(access_to_check in I.access)
|
||||
if(access_to_check in I.GetAccess)
|
||||
return 1
|
||||
else if(loud)
|
||||
user << "<span class='danger'>\The [computer] flashes an \"Access Denied\" warning.</span>"
|
||||
*/
|
||||
|
||||
// This attempts to retrieve header data for NanoUIs. If implementing completely new device of different type than existing ones
|
||||
// always include the device here in this proc. This proc basically relays the request to whatever is running the program.
|
||||
/datum/computer_file/program/proc/get_header_data()
|
||||
@@ -103,8 +100,6 @@
|
||||
// When implementing new program based device, use this to run the program.
|
||||
/datum/computer_file/program/proc/run_program(mob/living/user)
|
||||
if(can_run(user, 1))
|
||||
if(nanomodule_path)
|
||||
NM = new nanomodule_path(src, new /datum/topic_manager/program(src), src)
|
||||
if(requires_ntnet && network_destination)
|
||||
generate_network_log("Connection opened to [network_destination].")
|
||||
program_state = PROGRAM_STATE_ACTIVE
|
||||
@@ -116,19 +111,12 @@
|
||||
program_state = PROGRAM_STATE_KILLED
|
||||
if(network_destination)
|
||||
generate_network_log("Connection to [network_destination] closed.")
|
||||
if(NM)
|
||||
qdel(NM)
|
||||
NM = null
|
||||
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", datum/tgui/ui = null, force_open = 1, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
/datum/computer_file/program/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
if(program_state != PROGRAM_STATE_ACTIVE) // Our program was closed. Close the ui if it exists.
|
||||
if(!ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(ui)
|
||||
ui.close()
|
||||
return computer.ui_interact(user)
|
||||
return 1
|
||||
|
||||
@@ -138,16 +126,18 @@
|
||||
// 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/ui_act(action,params)
|
||||
/datum/computer_file/program/ui_act(action,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
|
||||
@@ -159,11 +149,19 @@
|
||||
|
||||
computer.active_program = null
|
||||
computer.update_icon()
|
||||
ui.close()
|
||||
|
||||
if(user && istype(user))
|
||||
computer.ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
|
||||
|
||||
|
||||
/datum/computer_file/program/ui_host()
|
||||
if(computer.physical)
|
||||
return computer.physical
|
||||
else
|
||||
return computer
|
||||
|
||||
|
||||
//if(computer)
|
||||
// return computer.ui_act(action,params)
|
||||
/datum/computer_file/program/ui_status(mob/user)
|
||||
if(program_state != PROGRAM_STATE_ACTIVE) // Our program was closed. Close the ui if it exists.
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
// These programs are associated with engineering.
|
||||
|
||||
/datum/computer_file/program/power_monitor
|
||||
filename = "powermonitor"
|
||||
filedesc = "Power Monitoring"
|
||||
nanomodule_path = /datum/nano_module/power_monitor/
|
||||
program_icon_state = "power_monitor"
|
||||
extended_desc = "This program connects to sensors around the station to provide information about electrical systems"
|
||||
ui_header = "power_norm.gif"
|
||||
required_access = access_engine
|
||||
requires_ntnet = 1
|
||||
network_destination = "power monitoring system"
|
||||
size = 9
|
||||
var/has_alert = 0
|
||||
|
||||
/datum/computer_file/program/power_monitor/process_tick()
|
||||
..()
|
||||
var/datum/nano_module/power_monitor/NMA = NM
|
||||
if(istype(NMA) && NMA.has_alarm())
|
||||
if(!has_alert)
|
||||
program_icon_state = "power_monitor_warn"
|
||||
ui_header = "power_warn.gif"
|
||||
update_computer_icon()
|
||||
has_alert = 1
|
||||
else
|
||||
if(has_alert)
|
||||
program_icon_state = "power_monitor"
|
||||
ui_header = "power_norm.gif"
|
||||
update_computer_icon()
|
||||
has_alert = 0
|
||||
|
||||
/datum/computer_file/program/alarm_monitor
|
||||
filename = "alarmmonitor"
|
||||
filedesc = "Alarm Monitoring"
|
||||
nanomodule_path = /datum/nano_module/alarm_monitor/engineering
|
||||
ui_header = "alarm_green.gif"
|
||||
program_icon_state = "alert-green"
|
||||
extended_desc = "This program provides visual interface for station's alarm system."
|
||||
requires_ntnet = 1
|
||||
network_destination = "alarm monitoring network"
|
||||
size = 5
|
||||
var/has_alert = 0
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/process_tick()
|
||||
..()
|
||||
var/datum/nano_module/alarm_monitor/NMA = NM
|
||||
if(istype(NMA) && NMA.has_major_alarms())
|
||||
if(!has_alert)
|
||||
program_icon_state = "alert-red"
|
||||
ui_header = "alarm_red.gif"
|
||||
update_computer_icon()
|
||||
has_alert = 1
|
||||
else
|
||||
if(has_alert)
|
||||
program_icon_state = "alert-green"
|
||||
ui_header = "alarm_green.gif"
|
||||
update_computer_icon()
|
||||
has_alert = 0
|
||||
return 1
|
||||
|
||||
/datum/computer_file/program/atmos_control
|
||||
filename = "atmoscontrol"
|
||||
filedesc = "Atmosphere Control"
|
||||
nanomodule_path = /datum/nano_module/atmos_control
|
||||
program_icon_state = "atmos_control"
|
||||
extended_desc = "This program allows remote control of air alarms around the station. This program can not be run on tablet computers."
|
||||
required_access = access_atmospherics
|
||||
requires_ntnet = 1
|
||||
network_destination = "atmospheric control system"
|
||||
requires_ntnet_feature = NTNET_SYSTEMCONTROL
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
|
||||
size = 17
|
||||
|
||||
/datum/computer_file/program/rcon_console
|
||||
filename = "rconconsole"
|
||||
filedesc = "RCON Remote Control"
|
||||
nanomodule_path = /datum/nano_module/rcon
|
||||
program_icon_state = "generic"
|
||||
extended_desc = "This program allows remote control of power distribution systems around the station. This program can not be run on tablet computers."
|
||||
required_access = access_engine
|
||||
requires_ntnet = 1
|
||||
network_destination = "RCON remote control system"
|
||||
requires_ntnet_feature = NTNET_SYSTEMCONTROL
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
|
||||
size = 19
|
||||
@@ -1,10 +0,0 @@
|
||||
/datum/computer_file/program/suit_sensors
|
||||
filename = "sensormonitor"
|
||||
filedesc = "Suit Sensors Monitoring"
|
||||
nanomodule_path = /datum/nano_module/crew_monitor
|
||||
program_icon_state = "crew"
|
||||
extended_desc = "This program connects to life signs monitoring system to provide basic information on crew health."
|
||||
required_access = access_medical
|
||||
requires_ntnet = 1
|
||||
network_destination = "crew lifesigns monitoring system"
|
||||
size = 11
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
|
||||
/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(host, topic_manager, program)
|
||||
..()
|
||||
src.program = program
|
||||
|
||||
/datum/topic_manager/program
|
||||
var/datum/program
|
||||
|
||||
/datum/topic_manager/program/New(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,106 @@
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/alarm_monitor
|
||||
filename = "alarmmonitor"
|
||||
filedesc = "Alarm Monitoring"
|
||||
ui_header = "alarm_green.gif"
|
||||
program_icon_state = "alert-green"
|
||||
extended_desc = "This program provides visual interface for station's alarm system."
|
||||
requires_ntnet = 1
|
||||
network_destination = "alarm monitoring network"
|
||||
size = 5
|
||||
var/has_alert = 0
|
||||
var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list())
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/process_tick()
|
||||
..()
|
||||
|
||||
if(has_alert)
|
||||
program_icon_state = "alert-red"
|
||||
ui_header = "alarm_red.gif"
|
||||
update_computer_icon()
|
||||
else
|
||||
if(!has_alert)
|
||||
program_icon_state = "alert-green"
|
||||
ui_header = "alarm_green.gif"
|
||||
update_computer_icon()
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "station_alert_prog", "Alarm Monitoring", 300, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["alarms"] = list()
|
||||
for(var/class in alarms)
|
||||
data["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
data["alarms"][class] += area
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
|
||||
var/list/L = alarms[class]
|
||||
for(var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if(O && istype(O, /list))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if(O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C ? C : O), list(source))
|
||||
|
||||
update_alarm_display()
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin)
|
||||
|
||||
|
||||
var/list/L = alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
|
||||
update_alarm_display()
|
||||
return !cleared
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/proc/update_alarm_display()
|
||||
has_alert = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
has_alert = TRUE
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/run_program(mob/user)
|
||||
. = ..(user)
|
||||
alarmdisplay += src
|
||||
|
||||
/datum/computer_file/program/alarm_monitor/kill_program(forced = 0)
|
||||
alarmdisplay -= src
|
||||
..(forced)
|
||||
@@ -29,14 +29,15 @@
|
||||
error = "Connection to destination relay lost."
|
||||
|
||||
/datum/computer_file/program/ntnet_dos/kill_program(var/forced)
|
||||
target.dos_sources.Remove(src)
|
||||
if(target)
|
||||
target.dos_sources.Remove(src)
|
||||
target = null
|
||||
executed = 0
|
||||
|
||||
..(forced)
|
||||
|
||||
|
||||
/datum/computer_file/program/ntnet_dos/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = always_state)
|
||||
/datum/computer_file/program/ntnet_dos/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
@@ -50,10 +51,11 @@
|
||||
/datum/computer_file/program/ntnet_dos/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
world << params
|
||||
switch(action)
|
||||
if("PRG_target_relay")
|
||||
for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays)
|
||||
if("[R.uid]" == params)
|
||||
if("[R.uid]" == params["targid"])
|
||||
target = R
|
||||
return 1
|
||||
if("PRG_reset")
|
||||
@@ -90,18 +92,16 @@
|
||||
// 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 = target.dos_overload * 100 / target.dos_capacity
|
||||
var/list/strings[0]
|
||||
data["dos_strings"] = list()
|
||||
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["dos_strings"] += list(list("nums" = string))
|
||||
else
|
||||
var/list/relays[0]
|
||||
data["relays"] = list()
|
||||
for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays)
|
||||
relays.Add(R.uid)
|
||||
data["relays"] = relays
|
||||
data["relays"] += list(list("id" = R.uid))
|
||||
data["focus"] = target ? target.uid : null
|
||||
|
||||
return data
|
||||
@@ -7,7 +7,6 @@
|
||||
requires_ntnet = 0
|
||||
available_on_ntnet = 0
|
||||
available_on_syndinet = 1
|
||||
nanomodule_path = /datum/nano_module/program/revelation/
|
||||
var/armed = 0
|
||||
|
||||
/datum/computer_file/program/revelation/run_program(var/mob/living/user)
|
||||
@@ -24,56 +23,50 @@
|
||||
if(computer.battery_module && prob(25))
|
||||
qdel(computer.battery_module)
|
||||
computer.visible_message("<span class='notice'>\The [computer]'s battery explodes in rain of sparks.</span>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(10, 1, computer.loc)
|
||||
s.start()
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.start()
|
||||
if(istype(computer, /obj/item/modular_computer/processor))
|
||||
var/obj/item/modular_computer/processor/P = computer
|
||||
if(P.machinery_computer.tesla_link && prob(50))
|
||||
qdel(P.machinery_computer.tesla_link)
|
||||
computer.visible_message("<span class='notice'>\The [computer]'s tesla link explodes in rain of sparks.</span>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(10, 1, computer.loc)
|
||||
s.start()
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.start()
|
||||
|
||||
/datum/computer_file/program/revelation/Topic(href, href_list)
|
||||
/datum/computer_file/program/revelation/ui_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
|
||||
return 1
|
||||
switch(action)
|
||||
if("PRG_arm")
|
||||
armed = !armed
|
||||
if("PRG_activate")
|
||||
activate()
|
||||
if("PRG_obfuscate")
|
||||
var/mob/living/user = usr
|
||||
var/newname = sanitize(input(user, "Enter new program name: "))
|
||||
if(!newname)
|
||||
return
|
||||
filedesc = newname
|
||||
|
||||
|
||||
/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/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_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))
|
||||
return
|
||||
|
||||
data = PRG.get_header_data()
|
||||
|
||||
data["armed"] = PRG.armed
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, 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 = new(user, src, ui_key, "revelation", "Revelation Virus", 400, 250, state = state)
|
||||
ui.set_style("syndicate")
|
||||
ui.set_autoupdate(state = 1)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
|
||||
/datum/computer_file/program/revelation/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["armed"] = armed
|
||||
|
||||
return data
|
||||
@@ -1,417 +0,0 @@
|
||||
#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. This program can not be run on tablet computers."
|
||||
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 ? !!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(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"
|
||||
return TRUE
|
||||
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|text
|
||||
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(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())
|
||||
return 1
|
||||
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>"
|
||||
return 1
|
||||
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())
|
||||
return 1
|
||||
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")
|
||||
. = 1
|
||||
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")
|
||||
. = 1
|
||||
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")
|
||||
. = 1
|
||||
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")
|
||||
. = 1
|
||||
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")
|
||||
. = 1
|
||||
if(is_autenthicated(user) && ntn_comm && l != global_message_listener)
|
||||
l.Remove(current_viewing_message)
|
||||
current_status = STATE_MESSAGELIST
|
||||
if("printmessage")
|
||||
. = 1
|
||||
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>")
|
||||
|
||||
#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)
|
||||
|
||||
for (var/obj/machinery/modular_computer/console/preset/command/main/computer in global_modular_computers)
|
||||
if(!(computer.stat & (BROKEN | NOPOWER)) && computer.cpu)
|
||||
if(computer.cpu.hard_drive)
|
||||
var/datum/computer_file/program/comm/C = locate(/datum/computer_file/program/comm) in computer.cpu.hard_drive.stored_files
|
||||
if(C)
|
||||
var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper(computer.loc)
|
||||
intercept.name = message_title
|
||||
intercept.info = 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)
|
||||
|
||||
/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)
|
||||
|
||||
/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 centcomm
|
||||
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/bluespacerelay/M in machines)
|
||||
if(M.stat == 0)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/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))
|
||||
user << "<span class='notice'>Cannot establish a bluespace connection.</span>"
|
||||
return
|
||||
|
||||
if(deathsquad.deployed)
|
||||
user << "[boss_short] will not allow the shuttle to be called. Consider all contracts terminated."
|
||||
return
|
||||
|
||||
if(emergency_shuttle.deny_shuttle)
|
||||
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
|
||||
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())
|
||||
user << "The emergency shuttle may not be called while returning to [boss_short]."
|
||||
return
|
||||
|
||||
if(emergency_shuttle.online())
|
||||
user << "The emergency shuttle is already on its way."
|
||||
return
|
||||
|
||||
if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic")
|
||||
user << "Under directive 7-10, [station_name()] is quarantined until further notice."
|
||||
return
|
||||
|
||||
if(!emergency_shuttle.call_evac(user))
|
||||
return
|
||||
log_and_message_admins("has called the shuttle.")
|
||||
|
||||
/proc/init_shift_change(var/mob/user, var/force = 0)
|
||||
if ((!( ticker ) || !emergency_shuttle.location()))
|
||||
return
|
||||
|
||||
if(emergency_shuttle.going_to_centcom())
|
||||
user << "The shuttle may not be called while returning to [boss_short]."
|
||||
return
|
||||
|
||||
if(emergency_shuttle.online())
|
||||
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)
|
||||
user << "[boss_short] does not currently have a shuttle available in your sector. Please try again later."
|
||||
return
|
||||
|
||||
if(deathsquad.deployed == 1)
|
||||
user << "[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
|
||||
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")
|
||||
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))
|
||||
event_manager.delay_events(EVENT_LEVEL_MODERATE, 10200) //17 minutes
|
||||
event_manager.delay_events(EVENT_LEVEL_MAJOR, 10200)
|
||||
|
||||
log_game("[user? key_name(user) : "Autotransfer"] has called the shuttle.")
|
||||
message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1)
|
||||
|
||||
return
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
//obj/machinery/vr_sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
/datum/computer_file/program/computerconfig/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = always_state)
|
||||
/datum/computer_file/program/computerconfig/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
@@ -38,7 +38,7 @@
|
||||
var/list/data = list()
|
||||
|
||||
|
||||
data = program.get_header_data()
|
||||
data = get_header_data()
|
||||
|
||||
var/list/hardware = movable.get_all_components()
|
||||
|
||||
|
||||
@@ -7,139 +7,138 @@
|
||||
requires_ntnet = 0
|
||||
available_on_ntnet = 0
|
||||
undeletable = 1
|
||||
nanomodule_path = /datum/nano_module/program/computer_filemanager/
|
||||
var/open_file
|
||||
var/error
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_act(href, href_list)
|
||||
/datum/computer_file/program/filemanager/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
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)
|
||||
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
|
||||
// 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|null), 16384)
|
||||
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:<br><br>[F.stored_data]<br><br>"
|
||||
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(parse_tags(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(.)
|
||||
nanomanager.update_uis(NM)
|
||||
switch(action)
|
||||
if("PRG_openfile")
|
||||
. = 1
|
||||
open_file = params["name"]
|
||||
if("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("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(params["name"])
|
||||
if(!file || file.undeletable)
|
||||
return 1
|
||||
HDD.remove_file(file)
|
||||
if("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(params["name"])
|
||||
if(!file || file.undeletable)
|
||||
return 1
|
||||
RHDD.remove_file(file)
|
||||
if("PRG_closefile")
|
||||
. = 1
|
||||
open_file = null
|
||||
error = null
|
||||
if("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(params["name"])
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
var/datum/computer_file/C = F.clone(1)
|
||||
HDD.store_file(C)
|
||||
if("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(params["name"])
|
||||
if(!file || !istype(file))
|
||||
return 1
|
||||
var/newname = sanitize(input(usr, "Enter new file name:", "File rename", file.filename))
|
||||
if(file && newname)
|
||||
file.filename = newname
|
||||
if("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
|
||||
// 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|null), 16384)
|
||||
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:<br><br>[F.stored_data]<br><br>"
|
||||
HDD.store_file(backup)
|
||||
if("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(parse_tags(F.stored_data)))
|
||||
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
|
||||
return 1
|
||||
if("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(params)
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
var/datum/computer_file/C = F.clone(0)
|
||||
RHDD.store_file(C)
|
||||
if("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(params)
|
||||
if(!F || !istype(F))
|
||||
return 1
|
||||
var/datum/computer_file/C = F.clone(0)
|
||||
HDD.store_file(C)
|
||||
|
||||
|
||||
/datum/computer_file/program/filemanager/proc/parse_tags(var/t)
|
||||
t = replacetext(t, "\[center\]", "<center>")
|
||||
@@ -151,8 +150,8 @@
|
||||
t = replacetext(t, "\[/i\]", "</I>")
|
||||
t = replacetext(t, "\[u\]", "<U>")
|
||||
t = replacetext(t, "\[/u\]", "</U>")
|
||||
t = replacetext(t, "\[time\]", "[stationtime2text()]")
|
||||
t = replacetext(t, "\[date\]", "[stationdate2text()]")
|
||||
t = replacetext(t, "\[time\]", "[worldtime2text()]")
|
||||
t = replacetext(t, "\[date\]", "[time2text(world.realtime, "MMM DD")] [year_integer+540]")
|
||||
t = replacetext(t, "\[large\]", "<font size=\"4\">")
|
||||
t = replacetext(t, "\[/large\]", "</font>")
|
||||
t = replacetext(t, "\[h1\]", "<H1>")
|
||||
@@ -179,37 +178,40 @@
|
||||
return t
|
||||
|
||||
|
||||
/datum/nano_module/program/computer_filemanager
|
||||
name = "NTOS File Manager"
|
||||
/datum/computer_file/program/filemanager/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_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
|
||||
PRG = program
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "file_manager", "NTOS File Manage", 575, 700, state = state)
|
||||
ui.open()
|
||||
ui.set_autoupdate(state = 1)
|
||||
|
||||
/datum/computer_file/program/filemanager/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
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(error)
|
||||
data["error"] = error
|
||||
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)
|
||||
HDD = computer.hard_drive
|
||||
file = HDD.find_file_by_name(open_file)
|
||||
if(!istype(file))
|
||||
data["error"] = "I/O ERROR: Unable to open file."
|
||||
else
|
||||
data["filedata"] = PRG.parse_tags(file.stored_data)
|
||||
data["filedata"] = parse_tags(file.stored_data)
|
||||
data["filename"] = "[file.filename].[file.filetype]"
|
||||
else
|
||||
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
|
||||
RHDD = PRG.computer.portable_drive
|
||||
HDD = computer.hard_drive
|
||||
RHDD = computer.portable_drive
|
||||
var/list/files[0]
|
||||
for(var/datum/computer_file/F in HDD.stored_files)
|
||||
files.Add(list(list(
|
||||
@@ -231,11 +233,4 @@
|
||||
)))
|
||||
data["usbfiles"] = usbfiles
|
||||
|
||||
ui = nanomanager.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()
|
||||
|
||||
|
||||
return data
|
||||
@@ -1,120 +0,0 @@
|
||||
/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 = ""
|
||||
|
||||
/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
|
||||
|
||||
/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(.)
|
||||
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)
|
||||
all_articles.Add(list(list(
|
||||
"name" = F.filename,
|
||||
"size" = F.size,
|
||||
"uid" = F.uid
|
||||
)))
|
||||
data["all_articles"] = all_articles
|
||||
|
||||
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()
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
//datum/nano_module/program/computer_ntnetdownload
|
||||
// name = "Network Downloader"
|
||||
|
||||
/datum/computer_file/program/ntnetdownload/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = always_state)
|
||||
/datum/computer_file/program/ntnetdownload/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
required_access = access_network
|
||||
available_on_ntnet = 1
|
||||
|
||||
//datum/nano_module/computer_ntnetmonitor
|
||||
// name = "NTNet Diagnostics and Monitoring"
|
||||
// available_to_ai = TRUE
|
||||
|
||||
/datum/computer_file/program/ntnetmonitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = always_state)
|
||||
/datum/computer_file/program/ntnetmonitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
@@ -67,12 +63,12 @@
|
||||
. = 1
|
||||
if(!ntnet_global)
|
||||
return 1
|
||||
ntnet_global.toggle_function(params)
|
||||
ntnet_global.toggle_function(text2num(params["id"]))
|
||||
|
||||
/datum/computer_file/program/ntnetmonitor/ui_data(mob/user)
|
||||
if(!ntnet_global)
|
||||
return
|
||||
var/list/data = list()
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["ntnetstatus"] = ntnet_global.check_function()
|
||||
data["ntnetrelays"] = ntnet_global.relays.len
|
||||
@@ -84,7 +80,10 @@
|
||||
data["config_communication"] = ntnet_global.setting_communication
|
||||
data["config_systemcontrol"] = ntnet_global.setting_systemcontrol
|
||||
|
||||
data["ntnetlogs"] = ntnet_global.logs
|
||||
data["ntnetlogs"] = list()
|
||||
|
||||
for(var/i in ntnet_global.logs)
|
||||
data["ntnetlogs"] += list(list("entry" = i))
|
||||
data["ntnetmaxlogs"] = ntnet_global.setting_maxlogcount
|
||||
|
||||
return data
|
||||
@@ -9,7 +9,6 @@
|
||||
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
|
||||
var/username
|
||||
var/datum/ntnet_conversation/channel = null
|
||||
@@ -19,143 +18,144 @@
|
||||
/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/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
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: "))
|
||||
if(!message || !channel)
|
||||
return
|
||||
channel.add_message(message, username)
|
||||
|
||||
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
|
||||
|
||||
if(!C)
|
||||
return 1
|
||||
|
||||
if(netadmin_mode)
|
||||
channel = C // Bypasses normal leave/join and passwords. Technically makes the user invisible to others.
|
||||
return 1
|
||||
|
||||
if(C.password)
|
||||
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 = sanitize(input(user,"Enter channel name or leave blank to cancel:"))
|
||||
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:"))
|
||||
if(!newname)
|
||||
return 1
|
||||
if(channel)
|
||||
channel.add_status_message("[username] is now known as [newname].")
|
||||
username = newname
|
||||
|
||||
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!")
|
||||
switch(action)
|
||||
if("PRG_speak")
|
||||
. = 1
|
||||
if(!channel)
|
||||
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:"))
|
||||
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)
|
||||
var/mob/living/user = usr
|
||||
var/message = sanitize(input(user, "Enter message or leave blank to cancel: "))
|
||||
if(!message || !channel)
|
||||
return
|
||||
channel.add_message(message, username)
|
||||
|
||||
if("PRG_joinchannel")
|
||||
. = 1
|
||||
var/datum/ntnet_conversation/C
|
||||
for(var/datum/ntnet_conversation/chan in ntnet_global.chat_channels)
|
||||
if(chan.id == text2num(params["id"]))
|
||||
C = chan
|
||||
break
|
||||
|
||||
if(!C)
|
||||
return 1
|
||||
|
||||
if(netadmin_mode)
|
||||
channel = C // Bypasses normal leave/join and passwords. Technically makes the user invisible to others.
|
||||
return 1
|
||||
|
||||
if(C.password)
|
||||
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("PRG_leavechannel")
|
||||
. = 1
|
||||
if(channel)
|
||||
channel.remove_client(src)
|
||||
channel = null
|
||||
if(href_list["PRG_setpassword"])
|
||||
. = 1
|
||||
if(!channel || ((channel.operator != src) && !netadmin_mode))
|
||||
return 1
|
||||
if("PRG_newchannel")
|
||||
. = 1
|
||||
var/mob/living/user = usr
|
||||
var/channel_title = sanitize(input(user,"Enter channel name or leave blank to cancel:"))
|
||||
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("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("PRG_changename")
|
||||
. = 1
|
||||
var/mob/living/user = usr
|
||||
var/newname = sanitize(input(user,"Enter new nickname or leave blank to cancel:"))
|
||||
if(!newname)
|
||||
return 1
|
||||
if(channel)
|
||||
channel.add_status_message("[username] is now known as [newname].")
|
||||
username = newname
|
||||
|
||||
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("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("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:"))
|
||||
if(!newname || !channel)
|
||||
return
|
||||
channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
|
||||
channel.title = newname
|
||||
if("PRG_deletechannel")
|
||||
. = 1
|
||||
if(channel && ((channel.operator == src) || netadmin_mode))
|
||||
qdel(channel)
|
||||
channel = null
|
||||
if("PRG_setpassword")
|
||||
. = 1
|
||||
if(!channel || ((channel.operator != src) && !netadmin_mode))
|
||||
return 1
|
||||
|
||||
if(newpassword == "nopassword")
|
||||
channel.password = ""
|
||||
else
|
||||
channel.password = newpassword
|
||||
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
|
||||
|
||||
/datum/computer_file/program/chatclient/process_tick()
|
||||
..()
|
||||
@@ -172,44 +172,47 @@
|
||||
else
|
||||
ui_header = "ntnrc_idle.gif"
|
||||
|
||||
/datum/computer_file/program/chatclient/kill_program(var/forced = 0)
|
||||
/datum/computer_file/program/chatclient/kill_program(forced = 0)
|
||||
if(channel)
|
||||
channel.remove_client(src)
|
||||
channel = null
|
||||
..(forced)
|
||||
|
||||
/datum/nano_module/program/computer_chatclient
|
||||
name = "NTNet Relay Chat Client"
|
||||
/datum/computer_file/program/chatclient/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "ntnet_chat", "NTNet Relay Chat Client", 575, 700, state = state)
|
||||
ui.open()
|
||||
ui.set_autoupdate(state = 1)
|
||||
|
||||
|
||||
/datum/computer_file/program/chatclient/ui_data(mob/user)
|
||||
if(!ntnet_global || !ntnet_global.chat_channels)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
if(program)
|
||||
data = program.get_header_data()
|
||||
|
||||
var/datum/computer_file/program/chatclient/C = program
|
||||
if(!istype(C))
|
||||
return
|
||||
data = get_header_data()
|
||||
|
||||
data["adminmode"] = C.netadmin_mode
|
||||
if(C.channel)
|
||||
data["title"] = C.channel.title
|
||||
|
||||
data["adminmode"] = netadmin_mode
|
||||
if(channel)
|
||||
data["title"] = channel.title
|
||||
var/list/messages[0]
|
||||
for(var/M in C.channel.messages)
|
||||
for(var/M in channel.messages)
|
||||
messages.Add(list(list(
|
||||
"msg" = M
|
||||
)))
|
||||
data["messages"] = messages
|
||||
var/list/clients[0]
|
||||
for(var/datum/computer_file/program/chatclient/cl in C.channel.clients)
|
||||
for(var/datum/computer_file/program/chatclient/cl in channel.clients)
|
||||
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
|
||||
operator_mode = (channel.operator == src) ? 1 : 0
|
||||
data["is_operator"] = operator_mode || netadmin_mode
|
||||
|
||||
else // Channel selection screen
|
||||
var/list/all_channels[0]
|
||||
@@ -221,10 +224,4 @@
|
||||
)))
|
||||
data["all_channels"] = all_channels
|
||||
|
||||
ui = nanomanager.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
|
||||
@@ -10,7 +10,6 @@ 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/
|
||||
|
||||
var/error = "" // Error screen
|
||||
var/server_password = "" // Optional password to download the file.
|
||||
@@ -55,8 +54,6 @@ var/global/nttransfer_uid = 0
|
||||
downloaded_file = null
|
||||
..(forced)
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/nttransfer/proc/update_netspeed()
|
||||
download_netspeed = 0
|
||||
switch(ntnet_status)
|
||||
@@ -87,35 +84,88 @@ var/global/nttransfer_uid = 0
|
||||
download_completion = 0
|
||||
|
||||
|
||||
/datum/nano_module/program/computer_nttransfer
|
||||
name = "NTNet P2P Transfer Client"
|
||||
/datum/computer_file/program/nttransfer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_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
|
||||
if(!istype(PRG))
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "ntnet_transfer", "NTNet P2P Transfer Client", 575, 700, state = state)
|
||||
ui.open()
|
||||
ui.set_autoupdate(state = 1)
|
||||
|
||||
var/list/data = program.get_header_data()
|
||||
/datum/computer_file/program/nttransfer/ui_act(action, params)
|
||||
if(..())
|
||||
return 1
|
||||
switch(action)
|
||||
if("PRG_downloadfile")
|
||||
for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers)
|
||||
if("[P.unique_token]" == params["id"])
|
||||
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
|
||||
downloaded_file = remote.provided_file.clone()
|
||||
remote.connected_clients.Add(src)
|
||||
return 1
|
||||
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 1
|
||||
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
|
||||
if(pass == "none")
|
||||
server_password = ""
|
||||
return
|
||||
server_password = pass
|
||||
return 1
|
||||
if("PRG_uploadfile")
|
||||
for(var/datum/computer_file/F in computer.hard_drive.stored_files)
|
||||
if("[F.uid]" == params["id"])
|
||||
if(F.unsendable)
|
||||
error = "I/O Error: File locked."
|
||||
return
|
||||
provided_file = F
|
||||
ntnet_global.fileservers.Add(src)
|
||||
return
|
||||
error = "I/O Error: Unable to locate file on hard drive."
|
||||
return 1
|
||||
if("PRG_uploadmenu")
|
||||
upload_menu = 1
|
||||
|
||||
if(PRG.error)
|
||||
data["error"] = PRG.error
|
||||
else if(PRG.downloaded_file)
|
||||
|
||||
/datum/computer_file/program/nttransfer/ui_data(mob/user)
|
||||
|
||||
var/list/data = get_header_data()
|
||||
|
||||
if(error)
|
||||
data["error"] = error
|
||||
else if(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["download_size"] = downloaded_file.size
|
||||
data["download_progress"] = download_completion
|
||||
data["download_netspeed"] = actual_netspeed
|
||||
data["download_name"] = "[downloaded_file.filename].[downloaded_file.filetype]"
|
||||
else if (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)
|
||||
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]"
|
||||
else if (upload_menu)
|
||||
var/list/all_files[0]
|
||||
for(var/datum/computer_file/F in PRG.computer.hard_drive.stored_files)
|
||||
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]",
|
||||
@@ -133,62 +183,4 @@ var/global/nttransfer_uid = 0
|
||||
)))
|
||||
data["servers"] = all_servers
|
||||
|
||||
ui = nanomanager.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)
|
||||
|
||||
/datum/computer_file/program/nttransfer/Topic(href, href_list)
|
||||
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
|
||||
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."
|
||||
return
|
||||
provided_file = F
|
||||
ntnet_global.fileservers.Add(src)
|
||||
return
|
||||
error = "I/O Error: Unable to locate file on hard drive."
|
||||
return 1
|
||||
if(href_list["PRG_uploadmenu"])
|
||||
upload_menu = 1
|
||||
return 0
|
||||
return data
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
|
||||
/datum/computer_file/program/power_monitor
|
||||
filename = "powermonitor"
|
||||
filedesc = "Power Monitoring"
|
||||
program_icon_state = "power_monitor"
|
||||
extended_desc = "This program connects to sensors around the station to provide information about electrical systems"
|
||||
ui_header = "power_norm.gif"
|
||||
required_access = access_engine
|
||||
usage_flags = PROGRAM_CONSOLE
|
||||
requires_ntnet = 0
|
||||
network_destination = "power monitoring system"
|
||||
size = 9
|
||||
var/has_alert = 0
|
||||
var/obj/structure/cable/attached
|
||||
var/list/history = list()
|
||||
var/record_size = 60
|
||||
var/record_interval = 50
|
||||
var/next_record = 0
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/power_monitor/run_program(mob/living/user)
|
||||
. = ..(user)
|
||||
search()
|
||||
history["supply"] = list()
|
||||
history["demand"] = list()
|
||||
|
||||
|
||||
/datum/computer_file/program/power_monitor/process_tick()
|
||||
if(!attached)
|
||||
search()
|
||||
else
|
||||
record()
|
||||
|
||||
/datum/computer_file/program/power_monitor/proc/search()
|
||||
var/turf/T = get_turf(computer)
|
||||
attached = locate() in T
|
||||
|
||||
/datum/computer_file/program/power_monitor/proc/record()
|
||||
if(world.time >= next_record)
|
||||
next_record = world.time + record_interval
|
||||
|
||||
var/list/supply = history["supply"]
|
||||
supply += attached.powernet.viewavail
|
||||
if(supply.len > record_size)
|
||||
supply.Cut(1, 2)
|
||||
|
||||
var/list/demand = history["demand"]
|
||||
demand += attached.powernet.viewload
|
||||
if(demand.len > record_size)
|
||||
demand.Cut(1, 2)
|
||||
|
||||
/datum/computer_file/program/power_monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "power_monitor_prog", "Power Monitoring", 1200, 1000, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/computer_file/program/power_monitor/ui_data()
|
||||
var/list/data = get_header_data()
|
||||
data["stored"] = record_size
|
||||
data["interval"] = record_interval / 10
|
||||
data["attached"] = attached ? TRUE : FALSE
|
||||
if(attached)
|
||||
data["supply"] = attached.powernet.viewavail
|
||||
data["demand"] = attached.powernet.viewload
|
||||
data["history"] = history
|
||||
|
||||
data["areas"] = list()
|
||||
if(attached)
|
||||
for(var/obj/machinery/power/terminal/term in attached.powernet.nodes)
|
||||
var/obj/machinery/power/apc/A = term.master
|
||||
if(istype(A))
|
||||
data["areas"] += list(list(
|
||||
"name" = A.area.name,
|
||||
"charge" = A.cell.percent(),
|
||||
"load" = A.lastused_total,
|
||||
"charging" = A.charging,
|
||||
"eqp" = A.equipment,
|
||||
"lgt" = A.lighting,
|
||||
"env" = A.environ
|
||||
))
|
||||
|
||||
return data
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
/obj/item/weapon/computer_hardware/hard_drive/proc/install_default_programs()
|
||||
store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
|
||||
store_file(new/datum/computer_file/program/ntnetdownload(src)) // NTNet Downloader Utility, allows users to download more software from NTNet repository
|
||||
// store_file(new/datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation.
|
||||
store_file(new/datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation.
|
||||
|
||||
|
||||
// Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
return 1
|
||||
// Nanopaste. Repair all damage if present for a single unit.
|
||||
var/obj/item/stack/S = W
|
||||
/*
|
||||
if(istype(S, /obj/item/stack/sheet/glass))
|
||||
if(!damage)
|
||||
user << "\The [src] doesn't seem to require repairs."
|
||||
@@ -30,6 +31,7 @@
|
||||
user << "You apply a bit of \the [W] to \the [src]. It immediately repairs all damage."
|
||||
damage = 0
|
||||
return 1
|
||||
*/
|
||||
// Cable coil. Works as repair method, but will probably require multiple applications and more cable.
|
||||
if(istype(S, /obj/item/stack/cable_coil))
|
||||
if(!damage)
|
||||
|
||||
@@ -76,16 +76,15 @@ var/global/ntnet_card_uid = 1
|
||||
return 0
|
||||
|
||||
if(holder2)
|
||||
return 2
|
||||
/*
|
||||
|
||||
var/turf/T = get_turf(holder2)
|
||||
if((T && istype(T)) && T.z in using_map.station_levels)
|
||||
if((T && istype(T)) && T.z == ZLEVEL_STATION)
|
||||
// Computer is on station. Low/High signal depending on what type of network card you have
|
||||
if(long_range)
|
||||
return 2
|
||||
else
|
||||
return 1
|
||||
*/
|
||||
|
||||
if(long_range) // Computer is not on station, but it has upgraded network card. Low signal.
|
||||
return 1
|
||||
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
// A vendor machine for modular computer portable devices - Laptops and Tablets
|
||||
|
||||
/obj/machinery/lapvend
|
||||
name = "computer vendor"
|
||||
desc = "A vending machine with microfabricator capable of dispensing various NT-branded computers."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "robotics"
|
||||
layer = 2.9
|
||||
anchored = 1
|
||||
density = 1
|
||||
|
||||
// The actual laptop/tablet
|
||||
var/obj/machinery/modular_computer/laptop/fabricated_laptop = null
|
||||
var/obj/item/modular_computer/tablet/fabricated_tablet = null
|
||||
|
||||
// Utility vars
|
||||
var/state = 0 // 0: Select device type, 1: Select loadout, 2: Payment, 3: Thankyou screen
|
||||
var/devtype = 0 // 0: None(unselected), 1: Laptop, 2: Tablet
|
||||
var/total_price = 0 // Price of currently vended device.
|
||||
|
||||
// Device loadout
|
||||
var/dev_cpu = 1 // 1: Default, 2: Upgraded
|
||||
var/dev_battery = 1 // 1: Default, 2: Upgraded, 3: Advanced
|
||||
var/dev_disk = 1 // 1: Default, 2: Upgraded, 3: Advanced
|
||||
var/dev_netcard = 0 // 0: None, 1: Basic, 2: Long-Range
|
||||
var/dev_tesla = 0 // 0: None, 1: Standard (LAPTOP ONLY)
|
||||
var/dev_nanoprint = 0 // 0: None, 1: Standard
|
||||
var/dev_card = 0 // 0: None, 1: Standard
|
||||
|
||||
// Removes all traces of old order and allows you to begin configuration from scratch.
|
||||
/obj/machinery/lapvend/proc/reset_order()
|
||||
state = 0
|
||||
devtype = 0
|
||||
if(fabricated_laptop)
|
||||
qdel(fabricated_laptop)
|
||||
fabricated_laptop = null
|
||||
if(fabricated_tablet)
|
||||
qdel(fabricated_tablet)
|
||||
fabricated_tablet = null
|
||||
dev_cpu = 1
|
||||
dev_battery = 1
|
||||
dev_disk = 1
|
||||
dev_netcard = 0
|
||||
dev_tesla = 0
|
||||
dev_nanoprint = 0
|
||||
dev_card = 0
|
||||
|
||||
// Recalculates the price and optionally even fabricates the device.
|
||||
/obj/machinery/lapvend/proc/fabricate_and_recalc_price(var/fabricate = 0)
|
||||
total_price = 0
|
||||
if(devtype == 1) // Laptop, generally cheaper to make it accessible for most station roles
|
||||
if(fabricate)
|
||||
fabricated_laptop = new(src)
|
||||
total_price = 99
|
||||
switch(dev_cpu)
|
||||
if(1)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_laptop.cpu)
|
||||
if(2)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit(fabricated_laptop.cpu)
|
||||
total_price += 299
|
||||
switch(dev_battery)
|
||||
if(1) // Basic(750C)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_laptop.cpu)
|
||||
if(2) // Upgraded(1100C)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/advanced(fabricated_laptop.cpu)
|
||||
total_price += 199
|
||||
if(3) // Advanced(1500C)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(fabricated_laptop.cpu)
|
||||
total_price += 499
|
||||
switch(dev_disk)
|
||||
if(1) // Basic(128GQ)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive(fabricated_laptop.cpu)
|
||||
if(2) // Upgraded(256GQ)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/advanced(fabricated_laptop.cpu)
|
||||
total_price += 99
|
||||
if(3) // Advanced(512GQ)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/super(fabricated_laptop.cpu)
|
||||
total_price += 299
|
||||
switch(dev_netcard)
|
||||
if(1) // Basic(Short-Range)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.network_card = new/obj/item/weapon/computer_hardware/network_card(fabricated_laptop.cpu)
|
||||
total_price += 99
|
||||
if(2) // Advanced (Long Range)
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.network_card = new/obj/item/weapon/computer_hardware/network_card/advanced(fabricated_laptop.cpu)
|
||||
total_price += 299
|
||||
if(dev_tesla)
|
||||
total_price += 399
|
||||
if(fabricate)
|
||||
fabricated_laptop.tesla_link = new/obj/item/weapon/computer_hardware/tesla_link(fabricated_laptop)
|
||||
if(dev_nanoprint)
|
||||
total_price += 99
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(fabricated_laptop.cpu)
|
||||
if(dev_card)
|
||||
total_price += 199
|
||||
if(fabricate)
|
||||
fabricated_laptop.cpu.card_slot = new/obj/item/weapon/computer_hardware/card_slot(fabricated_laptop.cpu)
|
||||
|
||||
return total_price
|
||||
else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this.
|
||||
if(fabricate)
|
||||
fabricated_tablet = new(src)
|
||||
fabricated_tablet.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_tablet)
|
||||
total_price = 199
|
||||
switch(dev_battery)
|
||||
if(1) // Basic(300C)
|
||||
if(fabricate)
|
||||
fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module/nano(fabricated_tablet)
|
||||
if(2) // Upgraded(500C)
|
||||
if(fabricate)
|
||||
fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module/micro(fabricated_tablet)
|
||||
total_price += 199
|
||||
if(3) // Advanced(750C)
|
||||
if(fabricate)
|
||||
fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_tablet)
|
||||
total_price += 499
|
||||
switch(dev_disk)
|
||||
if(1) // Basic(32GQ)
|
||||
if(fabricate)
|
||||
fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/micro(fabricated_tablet)
|
||||
if(2) // Upgraded(64GQ)
|
||||
if(fabricate)
|
||||
fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/small(fabricated_tablet)
|
||||
total_price += 99
|
||||
if(3) // Advanced(128GQ)
|
||||
if(fabricate)
|
||||
fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive(fabricated_tablet)
|
||||
total_price += 299
|
||||
switch(dev_netcard)
|
||||
if(1) // Basic(Short-Range)
|
||||
if(fabricate)
|
||||
fabricated_tablet.network_card = new/obj/item/weapon/computer_hardware/network_card(fabricated_tablet)
|
||||
total_price += 99
|
||||
if(2) // Advanced (Long Range)
|
||||
if(fabricate)
|
||||
fabricated_tablet.network_card = new/obj/item/weapon/computer_hardware/network_card/advanced(fabricated_tablet)
|
||||
total_price += 299
|
||||
if(dev_nanoprint)
|
||||
total_price += 99
|
||||
if(fabricate)
|
||||
fabricated_tablet.nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(fabricated_tablet)
|
||||
if(dev_card)
|
||||
total_price += 199
|
||||
if(fabricate)
|
||||
fabricated_tablet.card_slot = new/obj/item/weapon/computer_hardware/card_slot(fabricated_tablet)
|
||||
return total_price
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/machinery/lapvend/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["pick_device"])
|
||||
if(state) // We've already picked a device type
|
||||
return 0
|
||||
devtype = text2num(href_list["pick_device"])
|
||||
state = 1
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["clean_order"])
|
||||
reset_order()
|
||||
return 1
|
||||
if((state != 1) && devtype) // Following IFs should only be usable when in the Select Loadout mode
|
||||
return 0
|
||||
if(href_list["confirm_order"])
|
||||
state = 2 // Wait for ID swipe for payment processing
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_cpu"])
|
||||
dev_cpu = text2num(href_list["hw_cpu"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_battery"])
|
||||
dev_battery = text2num(href_list["hw_battery"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_disk"])
|
||||
dev_disk = text2num(href_list["hw_disk"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_netcard"])
|
||||
dev_netcard = text2num(href_list["hw_netcard"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_tesla"])
|
||||
dev_tesla = text2num(href_list["hw_tesla"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_nanoprint"])
|
||||
dev_nanoprint = text2num(href_list["hw_nanoprint"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
if(href_list["hw_card"])
|
||||
dev_card = text2num(href_list["hw_card"])
|
||||
fabricate_and_recalc_price(0)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/machinery/lapvend/attack_hand(var/mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/lapvend/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(stat & (BROKEN | NOPOWER | MAINT))
|
||||
if(ui)
|
||||
ui.close()
|
||||
return 0
|
||||
|
||||
var/list/data[0]
|
||||
data["state"] = state
|
||||
data["devtype"] = devtype
|
||||
data["hw_battery"] = dev_battery
|
||||
data["hw_disk"] = dev_disk
|
||||
data["hw_netcard"] = dev_netcard
|
||||
data["hw_tesla"] = dev_tesla
|
||||
data["hw_nanoprint"] = dev_nanoprint
|
||||
data["hw_card"] = dev_card
|
||||
data["hw_cpu"] = dev_cpu
|
||||
data["totalprice"] = "[total_price]þ"
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "computer_fabricator.tmpl", "Personal Computer Vendor", 500, 400)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
|
||||
obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
var/obj/item/weapon/card/id/I = W.GetID()
|
||||
// Awaiting payment state
|
||||
if(state == 2)
|
||||
if(process_payment(I,W))
|
||||
fabricate_and_recalc_price(1)
|
||||
if((devtype == 1) && fabricated_laptop)
|
||||
fabricated_laptop.cpu.battery_module.charge_to_full()
|
||||
fabricated_laptop.forceMove(src.loc)
|
||||
fabricated_laptop.close_laptop()
|
||||
fabricated_laptop = null
|
||||
else if((devtype == 2) && fabricated_tablet)
|
||||
fabricated_tablet.battery_module.charge_to_full()
|
||||
fabricated_tablet.forceMove(src.loc)
|
||||
fabricated_tablet = null
|
||||
ping("Enjoy your new product!")
|
||||
state = 3
|
||||
return 1
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
// Simplified payment processing, returns 1 on success.
|
||||
/obj/machinery/lapvend/proc/process_payment(var/obj/item/weapon/card/id/I, var/obj/item/ID_container)
|
||||
if(I==ID_container || ID_container == null)
|
||||
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
|
||||
else
|
||||
visible_message("<span class='info'>\The [usr] swipes \the [ID_container] through \the [src].</span>")
|
||||
var/datum/money_account/customer_account = get_account(I.associated_account_number)
|
||||
if (!customer_account || customer_account.suspended)
|
||||
ping("Connection error. Unable to connect to account.")
|
||||
return 0
|
||||
|
||||
if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
customer_account = attempt_account_access(I.associated_account_number, attempt_pin, 2)
|
||||
|
||||
if(!customer_account)
|
||||
ping("Unable to access account: incorrect credentials.")
|
||||
return 0
|
||||
|
||||
if(total_price > customer_account.money)
|
||||
ping("Insufficient funds in account.")
|
||||
return 0
|
||||
else
|
||||
customer_account.money -= total_price
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "Computer Manufacturer (via [src.name])"
|
||||
T.purpose = "Purchase of [(devtype == 1) ? "laptop computer" : "tablet microcomputer"]."
|
||||
T.amount = total_price
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
customer_account.transaction_log.Add(T)
|
||||
return 1
|
||||
Reference in New Issue
Block a user