Ports "Adds borg tablets, and RoboTact as a borg self-management app" (#12781)

* Ports borg tablets and Robotact

A very rough port of the two from TG with some code "barrowed" from SandPoot from cit to work around the lighting changes on TG

* Ports dentation button, rearranges the UI, and adds a change I forgot

Should all work

* Should fix the checks

Tgui being stingy

* Expanded Robotact and ports stuff

Adds a button to view alerts, self destruct, adjust light, and take picture to Robotact, ports downloading logs with the Borg Monitor, and allows borgs to use the NTOS downloader.

* Update asset_list_items.dm

* Adds buttons for lamp intensity

The slider is a bit jank, so I added some buttons for those who dont want to deal with it.

* Forgot you can do this

Should fix the checks

* *scream

Why is the linter so strict?

* Tails.dm but again

This is so much fun

* Reorganizes stuff and adds an integrated hardware flag

Reorganizes stuff to fit mod PDA/telescreen's new organization (dedicated files for each device) and added a hardware flag to better determine what can be used in the borg PC, fixing adam's issue.

* Should revert some of the removed buttons/commands

No reason to remove them

* Fixes the check

Forgot about this

* This is probably important

I should really test this

Co-authored-by: Theos <theubernyan@gmail.com>
This commit is contained in:
nmajask
2022-02-02 13:27:05 -05:00
committed by GitHub
parent c116b78d07
commit f216b2c4f6
42 changed files with 1109 additions and 424 deletions

View File

@@ -20,6 +20,12 @@
/datum/computer_file/program/revelation/proc/activate()
if(computer)
if(istype(computer, /obj/item/modular_computer/tablet/integrated)) //If this is a borg's integrated tablet
var/obj/item/modular_computer/tablet/integrated/modularInterface = computer
to_chat(modularInterface.borgo,"<span class='userdanger'>SYSTEM PURGE DETECTED/</span>")
addtimer(CALLBACK(modularInterface.borgo, /mob/living/silicon/robot/.proc/death), 2 SECONDS, TIMER_UNIQUE)
return
computer.visible_message(span_notice("\The [computer]'s screen brightly flashes and loud electrical buzzing is heard."))
computer.enabled = FALSE
computer.update_icon()

View File

@@ -12,6 +12,70 @@
size = 5
tgui_id = "NtosCyborgRemoteMonitor"
program_icon = "project-diagram"
var/emagged = FALSE ///Bool of if this app has already been emagged
var/list/loglist = list() ///A list to copy a borg's IC log list into
var/mob/living/silicon/robot/DL_source ///reference of a borg if we're downloading a log, or null if not.
var/DL_progress = -1 ///Progress of current download, 0 to 100, -1 for no current download
/datum/computer_file/program/borg_monitor/Destroy()
loglist = null
DL_source = null
return ..()
/datum/computer_file/program/borg_monitor/kill_program(forced = FALSE)
loglist = null //Not everything is saved if you close an app
DL_source = null
DL_progress = 0
return ..()
/datum/computer_file/program/borg_monitor/run_emag()
if(emagged)
return FALSE
emagged = TRUE
return TRUE
/datum/computer_file/program/borg_monitor/tap(atom/A, mob/living/user, params)
var/mob/living/silicon/robot/borgo = A
if(!istype(borgo) || !borgo.modularInterface)
return FALSE
DL_source = borgo
DL_progress = 0
var/username = "unknown user"
var/obj/item/card/id/stored_card = computer.GetID()
if(istype(stored_card) && stored_card.registered_name)
username = "user [stored_card.registered_name]"
to_chat(borgo, "<span class='userdanger'>Request received from [username] for the system log file. Upload in progress.</span>")//Damning evidence may be contained, so warn the borg
borgo.logevent("File request by [username]: /var/logs/syslog")
return TRUE
/datum/computer_file/program/borg_monitor/process_tick()
if(!DL_source)
DL_progress = -1
return
var/turf/here = get_turf(computer)
var/turf/there = get_turf(DL_source)
if(!here.Adjacent(there))//If someone walked away, cancel the download
to_chat(DL_source, "<span class='danger'>Log upload failed: general connection error.</span>")//Let the borg know the upload stopped
DL_source = null
DL_progress = -1
return
if(DL_progress == 100)
if(!DL_source || !DL_source.modularInterface) //sanity check, in case the borg or their modular tablet poofs somehow
loglist = list("System log of unit [DL_source.name]")
loglist += "Error -- Download corrupted."
else
loglist = DL_source.modularInterface.borglog.Copy()
loglist.Insert(1,"System log of unit [DL_source.name]")
DL_progress = -1
DL_source = null
for(var/datum/tgui/window in SStgui.open_uis_by_src[REF(src)])
window.send_full_update()
return
DL_progress += 25
/datum/computer_file/program/borg_monitor/ui_data(mob/user)
var/list/data = get_header_data()
@@ -35,6 +99,7 @@
var/list/cyborg_data = list(
name = R.name,
integ = round((R.health + 100) / 2), //mob heath is -100 to 100, we want to scale that to 0 - 100
locked_down = R.lockcharge,
status = R.stat,
shell_discon = shell,
@@ -44,6 +109,12 @@
ref = REF(R)
)
data["cyborgs"] += list(cyborg_data)
data["DL_progress"] = DL_progress
return data
/datum/computer_file/program/borg_monitor/ui_static_data(mob/user)
var/list/data = list()
data["borglog"] = loglist
return data
/datum/computer_file/program/borg_monitor/ui_act(action, params)
@@ -58,10 +129,14 @@
var/ID = checkID()
if(!ID)
return
if(R.stat == DEAD) //Dead borgs will listen to you no longer
to_chat(usr, "<span class='warn'>Error -- Could not open a connection to unit:[R]</span>")
var/message = stripped_input(usr, message = "Enter message to be sent to remote cyborg.", title = "Send Message")
if(!message)
return
to_chat(R, "<br><br>[span_notice("Message from [ID] -- \"[message]\"")]<br>")
to_chat(usr, "Message sent to [R]: [message]")
R.logevent("Message from [ID] -- \"[message]\"")
SEND_SOUND(R, 'sound/machines/twobeep_high.ogg')
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br>[span_notice("Message from [ID] to [R] -- \"[message]\"")]<br>")
@@ -80,6 +155,8 @@
/datum/computer_file/program/borg_monitor/proc/checkID()
var/obj/item/card/id/ID = computer.GetID()
if(!ID)
if(emagged)
return "STDERR:UNDF"
return FALSE
return ID.registered_name
@@ -97,6 +174,9 @@
network_destination = "cyborg remote monitoring"
tgui_id = "NtosCyborgRemoteMonitorSyndicate"
/datum/computer_file/program/borg_monitor/syndicate/run_emag()
return FALSE
/datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R)
if((get_turf(computer)).z != (get_turf(R)).z)
return FALSE

View File

@@ -8,7 +8,7 @@
requires_ntnet = TRUE
transfer_access = ACCESS_MEDICAL
available_on_ntnet = TRUE
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE | PROGRAM_TELESCREEN // For my other PR
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE | PROGRAM_TELESCREEN | PROGRAM_INTEGRATED
network_destination = "tracking program"
size = 5
tgui_id = "NtosCrewMonitor"

View File

@@ -7,7 +7,7 @@
requires_ntnet = TRUE
transfer_access = null
available_on_ntnet = FALSE
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE | PROGRAM_INTEGRATED
network_destination = "tracking program"
size = 5
tgui_id = "NtosRadar"

View File

@@ -0,0 +1,172 @@
/datum/computer_file/program/robotact
filename = "robotact"
filedesc = "RoboTact"
extended_desc = "A built-in app for cyborg self-management and diagnostics."
ui_header = "robotact.gif" //DEBUG -- new icon before PR
program_icon_state = "command"
requires_ntnet = FALSE
transfer_access = null
available_on_ntnet = FALSE
unsendable = TRUE
undeletable = TRUE
usage_flags = PROGRAM_TABLET
size = 5
tgui_id = "NtosRobotact"
///A typed reference to the computer, specifying the borg tablet type
var/obj/item/modular_computer/tablet/integrated/tablet
/datum/computer_file/program/robotact/Destroy()
tablet = null
return ..()
/datum/computer_file/program/robotact/run_program(mob/living/user)
if(!istype(computer, /obj/item/modular_computer/tablet/integrated))
to_chat(user, "<span class='warning'>A warning flashes across \the [computer]: Device Incompatible.</span>")
return FALSE
. = ..()
if(.)
tablet = computer
if(tablet.device_theme == "syndicate")
program_icon_state = "command-syndicate"
return TRUE
return FALSE
/datum/computer_file/program/robotact/ui_data(mob/user)
var/list/data = get_header_data()
if(!iscyborg(user))
return data
var/mob/living/silicon/robot/borgo = tablet.borgo
data["name"] = borgo.name
data["designation"] = borgo.designation //Borgo module type
data["masterAI"] = borgo.connected_ai //Master AI
var/charge = 0
var/maxcharge = 1
if(borgo.cell)
charge = borgo.cell.charge
maxcharge = borgo.cell.maxcharge
data["charge"] = charge //Current cell charge
data["maxcharge"] = maxcharge //Cell max charge
data["integrity"] = ((borgo.health + 100) / 2) //Borgo health, as percentage
data["light_on"] = borgo?.lamp_enabled
data["comp_light_color"] = borgo?.lamp_color
data["lampIntensity"] = borgo.lamp_intensity //Borgo lamp power setting
data["alertLength"] = borgo.robot_alerts_length() //Number of alerts
data["sensors"] = "[borgo.sensors_on?"ACTIVE":"DISABLED"]"
data["printerPictures"] = borgo.aicamera.stored.len //Number of pictures taken
data["printerToner"] = borgo.toner //amount of toner
data["printerTonerMax"] = borgo.tonermax //It's a variable, might as well use it
data["cameraActive"] = borgo.aicamera.in_camera_mode //If the camera is active
data["thrustersInstalled"] = borgo.ionpulse //If we have a thruster uprade
data["thrustersStatus"] = "[borgo.ionpulse_on?"ACTIVE":"DISABLED"]" //Feedback for thruster status
//DEBUG -- Cover, TRUE for locked
data["cover"] = "[borgo.locked? "LOCKED":"UNLOCKED"]"
//Ability to move. FAULT if lockdown wire is cut, DISABLED if borg locked, ENABLED otherwise
data["locomotion"] = "[borgo.wires.is_cut(WIRE_LOCKDOWN)?"FAULT":"[borgo.lockcharge?"DISABLED":"ENABLED"]"]"
//Module wire. FAULT if cut, NOMINAL otherwise
data["wireModule"] = "[borgo.wires.is_cut(WIRE_RESET_MODULE)?"FAULT":"NOMINAL"]"
//DEBUG -- Camera(net) wire. FAULT if cut (or no cameranet camera), DISABLED if pulse-disabled, NOMINAL otherwise
data["wireCamera"] = "[!borgo.builtInCamera || borgo.wires.is_cut(WIRE_CAMERA)?"FAULT":"[borgo.builtInCamera.can_use()?"NOMINAL":"DISABLED"]"]"
//AI wire. FAULT if wire is cut, CONNECTED if connected to AI, READY otherwise
data["wireAI"] = "[borgo.wires.is_cut(WIRE_AI)?"FAULT":"[borgo.connected_ai?"CONNECTED":"READY"]"]"
//Law sync wire. FAULT if cut, NOMINAL otherwise
data["wireLaw"] = "[borgo.wires.is_cut(WIRE_LAWSYNC)?"FAULT":"NOMINAL"]"
return data
/datum/computer_file/program/robotact/ui_static_data(mob/user)
var/list/data = list()
if(!iscyborg(user))
return data
var/mob/living/silicon/robot/borgo = user
data["Laws"] = borgo.laws.get_law_list(TRUE, TRUE, FALSE)
data["borgLog"] = tablet.borglog
data["borgUpgrades"] = borgo.upgrades
return data
/datum/computer_file/program/robotact/ui_act(action, params)
. = ..()
if(.)
return
var/mob/living/silicon/robot/borgo = tablet.borgo
switch(action)
if("viewAlerts")
borgo.robot_alerts()
if("coverunlock")
if(borgo.locked)
borgo.locked = FALSE
borgo.update_icons()
if(borgo.emagged)
borgo.logevent("ChÃ¥vÃis cover lock has been [borgo.locked ? "engaged" : "released"]") //"The cover interface glitches out for a split second"
else
borgo.logevent("Chassis cover lock has been [borgo.locked ? "engaged" : "released"]")
if("lawchannel")
borgo.set_autosay()
if("lawstate")
borgo.checklaws()
if("alertPower")
if(borgo.stat == CONSCIOUS)
if(!borgo.cell || !borgo.cell.charge)
borgo.visible_message("<span class='notice'>The power warning light on <span class='name'>[borgo]</span> flashes urgently.</span>", \
"You announce you are operating in low power mode.")
playsound(borgo, 'sound/machines/buzz-two.ogg', 50, FALSE)
if("toggleSensors")
borgo.toggle_sensors()
if("viewImage")
borgo.aicamera?.viewpictures(usr)
if("printImage")
var/obj/item/camera/siliconcam/robot_camera/borgcam = borgo.aicamera
borgcam?.borgprint(usr)
if("takeImage")
var/obj/item/camera/siliconcam/robot_camera/borgcam = borgo.aicamera
borgcam?.toggle_camera_mode(usr)
if("toggleThrusters")
borgo.toggle_ionpulse()
if("lampIntensity")
borgo.lamp_intensity = params["ref"]
borgo.toggle_headlamp(FALSE, TRUE)
if("selfDestruct")
borgo.self_self_destruct()
if("toggle_light")
borgo.toggle_headlamp()
return TRUE
if("light_color")
var/mob/user = usr
var/new_color
while(!new_color)
new_color = input(user, "Choose a new color for [src]'s flashlight.", "Light Color",holder.light_color) as color|null
if(!new_color || QDELETED(borgo))
return
if(color_hex2num(new_color) < 200) //Colors too dark are rejected
to_chat(user, "<span class='warning'>That color is too dark! Choose a lighter one.</span>")
new_color = null
borgo.lamp_color = new_color
borgo.toggle_headlamp(FALSE, TRUE)
return TRUE
/**
* Forces a full update of the UI, if currently open.
*
* Forces an update that includes refreshing ui_static_data. Called by
* law changes and borg log additions.
*/
/datum/computer_file/program/robotact/proc/force_full_update()
if(tablet)
var/datum/tgui/active_ui = SStgui.get_open_ui(tablet.borgo, src)
if(active_ui)
active_ui.send_full_update()

View File

@@ -8,7 +8,7 @@
extended_desc = "This program allows access to standard security camera networks."
requires_ntnet = TRUE
transfer_access = ACCESS_SECURITY
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_INTEGRATED // Probably not a good idea to let borgs use this, though im curious how it will pan out
size = 10
tgui_id = "NtosSecurEye"
program_icon = "eye"