pAI Computer Piloting (#8842)

pAI can now be put into modular computers to control them. When a pAI is inserted, a new service will be unlocked, which can disable their access to the computer.

The VueUI change wasn't tested, but finding and replacing should leave the functionality unchanged.
This commit is contained in:
Geeves
2020-06-05 20:28:52 +02:00
committed by GitHub
parent d880e89342
commit e7194e7893
15 changed files with 131 additions and 18 deletions

View File

@@ -2080,6 +2080,7 @@
#include "code\modules\modular_computers\file_system\programs\generic\nttransfer.dm" #include "code\modules\modular_computers\file_system\programs\generic\nttransfer.dm"
#include "code\modules\modular_computers\file_system\programs\generic\records.dm" #include "code\modules\modular_computers\file_system\programs\generic\records.dm"
#include "code\modules\modular_computers\file_system\programs\medical\suit_sensors.dm" #include "code\modules\modular_computers\file_system\programs\medical\suit_sensors.dm"
#include "code\modules\modular_computers\file_system\programs\pai\access_lock.dm"
#include "code\modules\modular_computers\file_system\programs\pai\atmospehere.dm" #include "code\modules\modular_computers\file_system\programs\pai\atmospehere.dm"
#include "code\modules\modular_computers\file_system\programs\pai\directives.dm" #include "code\modules\modular_computers\file_system\programs\pai\directives.dm"
#include "code\modules\modular_computers\file_system\programs\pai\doorjack.dm" #include "code\modules\modular_computers\file_system\programs\pai\doorjack.dm"

View File

@@ -52,6 +52,12 @@
computer.attack_self(src) computer.attack_self(src)
/mob/living/silicon/pai/proc/personal_computer_interact()
set name = "Access Local Computer"
set category = "Subsystems"
parent_computer.attack_self(src)
/******************** /********************
* Alarm Monitor * * Alarm Monitor *
********************/ ********************/

View File

@@ -1,3 +1,9 @@
/mob/living/silicon/pai/Destroy()
if(parent_computer?.personal_ai == src)
parent_computer.personal_ai = null
parent_computer = null
return ..()
/mob/living/silicon/pai/death(gibbed) /mob/living/silicon/pai/death(gibbed)
if(card) if(card)
card.removePersonality() card.removePersonality()

View File

@@ -83,6 +83,7 @@
var/subscreen // Which specific function of the main screen is being displayed var/subscreen // Which specific function of the main screen is being displayed
var/obj/item/device/pda/ai/pai/pda = null var/obj/item/device/pda/ai/pai/pda = null
var/obj/item/modular_computer/parent_computer
var/secHUD = 0 // Toggles whether the Security HUD is active or not var/secHUD = 0 // Toggles whether the Security HUD is active or not
var/medHUD = 0 // Toggles whether the Medical HUD is active or not var/medHUD = 0 // Toggles whether the Medical HUD is active or not
@@ -356,7 +357,10 @@
if(istype(card.loc,/obj/item/rig_module)) if(istype(card.loc,/obj/item/rig_module))
to_chat(src, SPAN_WARNING("There is no room to unfold inside this rig module. You're good and stuck.")) to_chat(src, SPAN_WARNING("There is no room to unfold inside this rig module. You're good and stuck."))
return FALSE return FALSE
else if(istype(card.loc, /mob)) else if(istype(card.loc, /obj/item/modular_computer))
to_chat(src, SPAN_WARNING("You are unable to unfold while housed within a computer."))
return FALSE
else if(istype(card.loc,/mob))
var/mob/holder = card.loc var/mob/holder = card.loc
if(ishuman(holder)) if(ishuman(holder))
var/mob/living/carbon/human/H = holder var/mob/living/carbon/human/H = holder

View File

@@ -55,6 +55,17 @@
return return
found = TRUE found = TRUE
tesla_link = H tesla_link = H
else if(istype(H, /obj/item/device/paicard))
if(personal_ai)
to_chat(user, SPAN_WARNING("\The [src]'s personal AI slot is already occupied by \the [personal_ai]."))
return
personal_ai = H
to_chat(user, SPAN_NOTICE("You install \the [H] into \the [src]."))
personal_ai.pai.parent_computer = src
personal_ai.pai.verbs += /mob/living/silicon/pai/proc/personal_computer_interact
to_chat(personal_ai.pai, SPAN_NOTICE("You gain access to \the [src]'s computronics."))
user.drop_from_inventory(H, src)
update_icon()
if(found) if(found)
to_chat(user, SPAN_NOTICE("You install \the [H] into \the [src].")) to_chat(user, SPAN_NOTICE("You install \the [H] into \the [src]."))
H.parent_computer = src H.parent_computer = src
@@ -92,6 +103,17 @@
else if(tesla_link == H) else if(tesla_link == H)
tesla_link = null tesla_link = null
found = TRUE found = TRUE
else if(personal_ai == H)
if(user)
to_chat(user, SPAN_NOTICE("You remove \the [H] from \the [src]."))
H.forceMove(get_turf(src))
if(put_in_hands)
user.put_in_hands(H)
personal_ai.pai.verbs -= /mob/living/silicon/pai/proc/personal_computer_interact
to_chat(personal_ai.pai, SPAN_NOTICE("You lose access to \the [src]'s computronics."))
personal_ai.pai.parent_computer = null
update_icon()
personal_ai = null
if(found) if(found)
if(user) if(user)
@@ -105,7 +127,6 @@
to_chat(user, SPAN_WARNING("\The [src]'s screen freezes for few seconds and then displays, \"HARDWARE ERROR: Critical component disconnected. Please verify component connection and reboot the device. If the problem persists contact technical support for assistance.\".")) to_chat(user, SPAN_WARNING("\The [src]'s screen freezes for few seconds and then displays, \"HARDWARE ERROR: Critical component disconnected. Please verify component connection and reboot the device. If the problem persists contact technical support for assistance.\"."))
shutdown_computer() shutdown_computer()
// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null // 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) /obj/item/modular_computer/proc/find_hardware_by_name(var/name)
if(portable_drive && (initial(portable_drive.name) == name)) if(portable_drive && (initial(portable_drive.name) == name))
@@ -124,6 +145,8 @@
return processor_unit return processor_unit
if(ai_slot && (initial(ai_slot.name) == name)) if(ai_slot && (initial(ai_slot.name) == name))
return ai_slot return ai_slot
if(personal_ai && (initial(personal_ai.name) == name))
return personal_ai
if(tesla_link && (initial(tesla_link.name) == name)) if(tesla_link && (initial(tesla_link.name) == name))
return tesla_link return tesla_link
return null return null
@@ -147,6 +170,8 @@
all_components.Add(processor_unit) all_components.Add(processor_unit)
if(ai_slot) if(ai_slot)
all_components.Add(ai_slot) all_components.Add(ai_slot)
if(personal_ai)
all_components.Add(personal_ai)
if(tesla_link) if(tesla_link)
all_components.Add(tesla_link) all_components.Add(tesla_link)
return all_components return all_components

View File

@@ -30,6 +30,16 @@
proc_eject_ai(usr) proc_eject_ai(usr)
/obj/item/modular_computer/verb/eject_personal_ai()
set name = "Eject Personal AI"
set category = "Object"
set src in view(1)
if(use_check_and_message(usr))
return
proc_eject_personal_ai(usr)
/obj/item/modular_computer/proc/proc_eject_id(mob/user) /obj/item/modular_computer/proc/proc_eject_id(mob/user)
if(!user) if(!user)
user = usr user = usr
@@ -87,6 +97,17 @@
ai_slot.update_power_usage() ai_slot.update_power_usage()
update_uis() update_uis()
/obj/item/modular_computer/proc/proc_eject_personal_ai(mob/user)
if(!personal_ai)
to_chat(user, SPAN_WARNING("There is no personal AI connected to \the [src]."))
return
personal_ai.pai.verbs -= /mob/living/silicon/pai/proc/personal_computer_interact
personal_ai.pai.parent_computer = null
to_chat(personal_ai.pai, SPAN_NOTICE("You lose access to \the [src]'s computronics."))
uninstall_component(user, personal_ai, put_in_hands = TRUE)
update_uis()
/obj/item/modular_computer/attack_ghost(var/mob/abstract/observer/user) /obj/item/modular_computer/attack_ghost(var/mob/abstract/observer/user)
if(enabled) if(enabled)
ui_interact(user) ui_interact(user)
@@ -154,6 +175,8 @@
try_install_component(user, C) try_install_component(user, C)
else else
to_chat(user, SPAN_WARNING("This component is too large for \the [src].")) to_chat(user, SPAN_WARNING("This component is too large for \the [src]."))
if(istype(W, /obj/item/device/paicard))
try_install_component(user, W)
if(W.iswrench()) if(W.iswrench())
var/list/components = get_all_components() var/list/components = get_all_components()
if(components.len) if(components.len)

View File

@@ -47,6 +47,8 @@
var/datum/computer_file/data/autorun = hard_drive.find_file_by_name("autorun") var/datum/computer_file/data/autorun = hard_drive.find_file_by_name("autorun")
VUEUI_SET_CHECK_IFNOTSET(data["programs"], list(), ., data) VUEUI_SET_CHECK_IFNOTSET(data["programs"], list(), ., data)
for(var/datum/computer_file/program/P in hard_drive.stored_files) for(var/datum/computer_file/program/P in hard_drive.stored_files)
if(P.program_hidden())
continue
VUEUI_SET_CHECK_IFNOTSET(data["programs"][P.filename], list(), ., data) VUEUI_SET_CHECK_IFNOTSET(data["programs"][P.filename], list(), ., data)
VUEUI_SET_CHECK(data["programs"][P.filename]["desc"], P.filedesc, ., data) VUEUI_SET_CHECK(data["programs"][P.filename]["desc"], P.filedesc, ., data)
VUEUI_SET_CHECK(data["programs"][P.filename]["autorun"], (istype(autorun) && (autorun.stored_data == P.filename)), ., data) VUEUI_SET_CHECK(data["programs"][P.filename]["autorun"], (istype(autorun) && (autorun.stored_data == P.filename)), ., data)

View File

@@ -20,6 +20,7 @@
var/enrolled = 0 // Weather the computer is enrolled in the company device management or not. 0 - unconfigured 1 - enrolled (work device) 2 - unenrolled (private device) var/enrolled = 0 // Weather the computer is enrolled in the company device management or not. 0 - unconfigured 1 - enrolled (work device) 2 - unenrolled (private device)
var/_app_preset_type // Used for specifying the software preset of the console var/_app_preset_type // Used for specifying the software preset of the console
var/ambience_last_played // Last time sound was played var/ambience_last_played // Last time sound was played
var/pAI_lock = FALSE // Toggles whether pAI can interact with the modular computer while installed in it
// Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..) // Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..)
// must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently // must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently
@@ -62,6 +63,7 @@
var/obj/item/computer_hardware/hard_drive/portable/portable_drive // Portable data storage var/obj/item/computer_hardware/hard_drive/portable/portable_drive // Portable data storage
var/obj/item/computer_hardware/ai_slot/ai_slot // AI slot, an intellicard housing that allows modifications of AIs. var/obj/item/computer_hardware/ai_slot/ai_slot // AI slot, an intellicard housing that allows modifications of AIs.
var/obj/item/computer_hardware/tesla_link/tesla_link // Tesla Link, Allows remote charging from nearest APC. var/obj/item/computer_hardware/tesla_link/tesla_link // Tesla Link, Allows remote charging from nearest APC.
var/obj/item/device/paicard/personal_ai // Personal AI, can control the device via a verb when installed
var/listener/listener //Listener needed for things var/listener/listener //Listener needed for things

View File

@@ -126,6 +126,10 @@
else // Should never happen - So fail silently else // Should never happen - So fail silently
return FALSE return FALSE
// Override to set when a program shouldn't appear in the program list
/datum/computer_file/program/proc/program_hidden()
return FALSE
// Check if the user can run program. Only humans can operate computer. Automatically called in run_program() // Check if the user can run program. Only humans can operate computer. Automatically called in run_program()
// User has to wear their ID or have it inhand for ID Scan to work. // User has to wear their ID or have it inhand for ID Scan to work.
// Can also be called manually, with optional parameter being access_to_check to scan the user's ID // Can also be called manually, with optional parameter being access_to_check to scan the user's ID

View File

@@ -0,0 +1,27 @@
/datum/computer_file/program/pai_access_lock
filename = "pai_access_lock"
filedesc = "pAI Access Lock"
extended_desc = "This service toggles whether a pAI can interface with this device."
size = 0
program_type = PROGRAM_SERVICE
available_on_ntnet = FALSE
unsendable = TRUE
undeletable = TRUE
usage_flags = PROGRAM_ALL
/datum/computer_file/program/pai_access_lock/service_activate()
. = ..()
if(computer.personal_ai)
to_chat(computer.personal_ai.pai, SPAN_WARNING("pAI Access Lock systems engaged."))
computer.pAI_lock = TRUE
/datum/computer_file/program/pai_access_lock/service_deactivate()
. = ..()
if(computer.personal_ai)
to_chat(computer.personal_ai.pai, SPAN_NOTICE("pAI Access Lock systems disabled."))
computer.pAI_lock = FALSE
/datum/computer_file/program/pai_access_lock/program_hidden()
if(!computer.personal_ai)
return TRUE
return FALSE

View File

@@ -50,28 +50,28 @@
VUEUI_SET_CHECK(data["installed"][I.filename]["name"], I.filedesc, ., data) VUEUI_SET_CHECK(data["installed"][I.filename]["name"], I.filedesc, ., data)
VUEUI_SET_CHECK(data["installed"][I.filename]["size"], I.size, ., data) VUEUI_SET_CHECK(data["installed"][I.filename]["size"], I.size, ., data)
// Now lets send all avaivable programs with there status. // Now lets send all available programs with their status.
// Statuses (rest): 0 - ALL OK, 1 - can't download due to access, 2 - unsuported hardware, 3 - sindies only // Statuses (rest): 0 - ALL OK, 1 - can't download due to access, 2 - unsuported hardware, 3 - sindies only
LAZYINITLIST(data["avaivable"]) LAZYINITLIST(data["available"])
for(var/datum/computer_file/program/P in ntnet_global.available_software) for(var/datum/computer_file/program/P in ntnet_global.available_software)
LAZYINITLIST(data["avaivable"][P.filename]) LAZYINITLIST(data["available"][P.filename])
VUEUI_SET_CHECK(data["avaivable"][P.filename]["name"], P.filedesc, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["name"], P.filedesc, ., data)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["desc"], P.extended_desc, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["desc"], P.extended_desc, ., data)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["size"], P.size, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["size"], P.size, ., data)
if(computer_emagged) if(computer_emagged)
if(!P.is_supported_by_hardware(computer.hardware_flag)) if(!P.is_supported_by_hardware(computer.hardware_flag))
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 2, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 2, ., data)
else else
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 0, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 0, ., data)
else else
if(!P.available_on_ntnet) if(!P.available_on_ntnet)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 3, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 3, ., data)
else if(!P.can_download(user) && P.requires_access_to_download) else if(!P.can_download(user) && P.requires_access_to_download)
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 1, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 1, ., data)
else if(!P.is_supported_by_hardware(computer.hardware_flag)) else if(!P.is_supported_by_hardware(computer.hardware_flag))
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 2, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 2, ., data)
else else
VUEUI_SET_CHECK(data["avaivable"][P.filename]["rest"], 0, ., data) VUEUI_SET_CHECK(data["available"][P.filename]["rest"], 0, ., data)
VUEUI_SET_CHECK(data["disk_size"], hard_drive.max_capacity, ., data) VUEUI_SET_CHECK(data["disk_size"], hard_drive.max_capacity, ., data)
VUEUI_SET_CHECK(data["disk_used"], hard_drive.used_capacity, ., data) VUEUI_SET_CHECK(data["disk_used"], hard_drive.used_capacity, ., data)

View File

@@ -85,6 +85,7 @@
/obj/item/computer_hardware/hard_drive/proc/install_default_programs() /obj/item/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/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
store_file(new /datum/computer_file/program/clientmanager(src)) // Client Manager to Enroll the Device store_file(new /datum/computer_file/program/clientmanager(src)) // Client Manager to Enroll the Device
store_file(new /datum/computer_file/program/pai_access_lock(src)) // pAI access control, to stop pesky pAI from messing with computers
// Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks. // Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks.
/obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F) /obj/item/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F)

View File

@@ -17,6 +17,12 @@
return STATUS_UPDATE // Ghosts can view updates return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/default_can_use_topic(var/src_object) /mob/living/silicon/pai/default_can_use_topic(var/src_object)
if(src_object == parent_computer)
if(!parent_computer.pAI_lock)
return STATUS_INTERACTIVE
else
to_chat(src, SPAN_WARNING("Error. pAI Access Lock systems still engaged."))
return ..()
if((src_object == src || src_object == radio) && !stat) if((src_object == src || src_object == radio) && !stat)
return STATUS_INTERACTIVE return STATUS_INTERACTIVE
else else

View File

@@ -0,0 +1,6 @@
author: Geeves
delete-after: True
changes:
- rscadd: "pAI can now be put into modular computers to control them. When a pAI is inserted, a new service will be unlocked, which can disable their access to the computer."

View File

@@ -33,7 +33,7 @@
</tr> </tr>
</table> </table>
</template> </template>
<h2>Avaivable programs</h2> <h2>Available Programs</h2>
<vui-input-search <vui-input-search
style="float: right;" style="float: right;"
:input="unrestrictedPrograms" :input="unrestrictedPrograms"
@@ -75,7 +75,7 @@ export default {
}, },
computed: { computed: {
unrestrictedPrograms() { unrestrictedPrograms() {
var entries = Object.entries(this.s.avaivable) var entries = Object.entries(this.s.available)
.filter( .filter(
([key, value]) => ([key, value]) =>
!(key in this.s.installed) && !value.rest && !(key in this.s.queue) !(key in this.s.installed) && !value.rest && !(key in this.s.queue)
@@ -92,7 +92,7 @@ export default {
}, },
queue() { queue() {
return Object.entries(this.s.queue).map(([name, progress]) => { return Object.entries(this.s.queue).map(([name, progress]) => {
let fp = this.s.avaivable[name] let fp = this.s.available[name]
fp.progress = progress fp.progress = progress
fp.filename = name fp.filename = name
return fp return fp