Adds a Prisoner-VR Cyborg/Mech Control Program (#8057)

Adds a program for security to monitor & control prisoners using mechs/cyborgs via VR.
This commit is contained in:
mikomyazaki
2020-02-05 22:33:19 +01:00
committed by GitHub
parent 611727b2a1
commit 8aa8c0ddca
13 changed files with 294 additions and 8 deletions
+1
View File
@@ -2025,6 +2025,7 @@
#include "code\modules\modular_computers\file_system\programs\research\ntmonitor.dm"
#include "code\modules\modular_computers\file_system\programs\security\camera.dm"
#include "code\modules\modular_computers\file_system\programs\security\digitalwarrant.dm"
#include "code\modules\modular_computers\file_system\programs\security\penalmechs.dm"
#include "code\modules\modular_computers\file_system\programs\system\client_manager.dm"
#include "code\modules\modular_computers\file_system\programs\system\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\system\file_browser.dm"
+1
View File
@@ -45,6 +45,7 @@
#define NETWORK_ENGINEERING_OUTPOST "Engineering Outpost"
#define NETWORK_ERT "ZeEmergencyResponseTeam"
#define NETWORK_STATION "Station"
#define NETWORK_MECHS "Mechs"
#define NETWORK_MEDICAL "Medical"
#define NETWORK_MERCENARY "MercurialNet"
#define NETWORK_MINE "MINE"
@@ -10,7 +10,7 @@
var/list/mechs = list() // A list of lists, containing the mechs and their networks
// IPC BODIES
var/list/robotnetworks = list("remoterobots", "bunkerrobots")
var/list/robotnetworks = list("remoterobots", "bunkerrobots", "prisonrobots")
var/list/robots = list()
/datum/controller/subsystem/virtualreality/New()
@@ -28,9 +28,6 @@
if(!software)
to_chat(user, "<span class='warning'>It is missing a software control module.</span>")
/obj/item/mech_component/sensors/prebuild()
radio = new(src)
camera = new(src)
/obj/item/mech_component/sensors/prebuild()
radio = new(src)
+10 -3
View File
@@ -17,7 +17,7 @@
else . = ..()
/mob/living/heavy_vehicle/MouseDrop_T(src_object, over_object, src_location, over_location, src_control, over_control, params, var/mob/user)
if(!user || incapacitated() || user.incapacitated())
if(!user || incapacitated() || user.incapacitated() || lockdown)
return FALSE
if(!(user in pilots) && user != src)
@@ -30,7 +30,7 @@
/mob/living/heavy_vehicle/ClickOn(var/atom/A, params, var/mob/user)
if(!user || incapacitated() || user.incapacitated())
if(!user || incapacitated() || user.incapacitated() || lockdown)
return
if(!loc) return
@@ -258,7 +258,7 @@
if(world.time < next_move)
return 0
if(!user || incapacitated() || user.incapacitated())
if(!user || incapacitated() || user.incapacitated() || lockdown)
return
if(!legs)
@@ -491,3 +491,10 @@
return TRUE
L.apply_damage(legs.trample_damage, BRUTE)
return TRUE
/mob/living/heavy_vehicle/proc/ToggleLockdown()
lockdown = !lockdown
if(lockdown)
src.visible_message("<span class='warning'>\The [src] beeps loudly as its servos sieze up, and it enters lockdown mode!</span>")
else
src.visible_message("<span class='warning'>\The [src] hums with life as it is released from its lockdown mode!</span>")
+4 -1
View File
@@ -22,7 +22,10 @@
update_pilot_overlay()
if(radio)
radio.on = (head && head.radio && head.radio.is_functional())
radio.on = (head?.radio && head.radio.is_functional())
if(camera)
camera.status = (head?.camera && head.camera.is_functional())
body.update_air(hatch_closed && use_air)
@@ -47,6 +47,10 @@
to_chat(mover, "<span class='warning'>Maintenance protocols are in effect.</span>")
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
if(exosuit.lockdown)
to_chat(mover, span("warning", "You cannot move while the exosuit's lockdown mode is active."))
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
var/obj/item/cell/C = exosuit.get_cell()
if(!C || !C.check_charge(exosuit.legs.power_use * CELLRATE))
to_chat(mover, "<span class='warning'>The power indicator flashes briefly.</span>")
+7
View File
@@ -17,6 +17,7 @@
var/offset_y = 0
var/obj/item/device/radio/exosuit/radio
var/obj/machinery/camera/camera
var/wreckage_path = /obj/structure/mech_wreckage
@@ -49,6 +50,7 @@
var/list/hardpoints = list()
var/hardpoints_locked
var/maintenance_protocols
var/lockdown
// Material
var/material/material
@@ -181,6 +183,11 @@
if(head && head.radio)
radio = new(src)
if(!camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = name
camera.replace_networks(list(NETWORK_MECHS))
// Create HUD.
instantiate_hud()
@@ -177,6 +177,7 @@
new /datum/computer_file/program/comm(TRUE),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/civilian/cargocontrol(),
new /datum/computer_file/program/civilian/cargoorder(),
new /datum/computer_file/program/alarm_monitor(),
@@ -200,6 +201,7 @@
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/comm(),
new /datum/computer_file/program/digitalwarrant(),
new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security()
)
return _prg_list
@@ -216,6 +218,7 @@
new /datum/computer_file/program/chatclient(),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security(),
new /datum/computer_file/program/records/employment(),
new /datum/computer_file/program/records/medical()
@@ -235,6 +238,7 @@
new /datum/computer_file/program/civilian/cargoorder(),
new /datum/computer_file/program/camera_monitor(),
new /datum/computer_file/program/digitalwarrant(),
new /datum/computer_file/program/penal_mechs(),
new /datum/computer_file/program/records/security(),
new /datum/computer_file/program/records/employment()
)
@@ -0,0 +1,172 @@
/datum/computer_file/program/penal_mechs
filename = "penalmechs"
filedesc = "Remote Penal Monitoring"
program_icon_state = "security"
extended_desc = "This program allows monitoring and control of active penal miner mechs."
required_access_run = access_armory
required_access_download = access_armory
requires_ntnet = 1
available_on_ntnet = 1
network_destination = "penal mining mech monitoring system"
size = 11
usage_flags = PROGRAM_ALL_REGULAR
color = LIGHT_COLOR_ORANGE
var/obj/machinery/camera/current_camera = null
/datum/computer_file/program/penal_mechs/ui_interact(mob/user)
var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
if (!ui)
ui = new /datum/vueui/modularcomputer(user, src, "mcomputer-security-penalcontroller", 500, 400, "Penal Mech Monitoring")
ui.auto_update_content = 1
ui.open()
/datum/computer_file/program/penal_mechs/vueui_transfer(oldobj)
for(var/o in SSvueui.transfer_uis(oldobj, src, "mcomputer-security-penalcontroller", 500, 400, "Penal Mech Monitoring"))
var/datum/vueui/ui = o
// Let's ensure our ui's autoupdate after transfer.
// TODO: revert this value on transfer out.
ui.auto_update_content = 1
return TRUE
/datum/computer_file/program/penal_mechs/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
. = ..()
data = . || data || list()
// Gather data for computer header
data["_PC"] = get_header_data(data["_PC"])
var/datum/signal/signal
signal = telecomms_process_active()
var/list/mechs = list()
var/list/robots = list()
if(signal.data["done"])
for(var/mech in SSvirtualreality.mechs["prisonmechs"])
var/mob/living/heavy_vehicle/M = mech
if(!ismech(M))
continue
if(!AreConnectedZLevels(computer.loc.z, M.loc.z))
continue
var/list/mechData = list("location" = null, "name" = null, "pilot" = null, "ref" = "\ref[M]", "camera" = null, "lockdown" = null)
mechData["name"] = M.name
mechData["pilot"] = "[M.old_mob]"
var/turf/mech_turf = get_turf(M)
mechData["location"] = "[mech_turf.x], [mech_turf.y], [mech_turf.z]"
mechData["camera_status"] = M.camera.status
mechData["lockdown"] = M.lockdown
mechs[++mechs.len] = mechData
for(var/robot in SSvirtualreality.robots["prisonrobots"])
var/mob/living/R = robot
if(!ismob(R))
continue
if(!AreConnectedZLevels(computer.loc.z, R.loc.z))
continue
var/list/robotData = list("location" = null, "name" = null, "pilot" = null, "ref" = "\ref[R]")
robotData["name"] = R.name
robotData["pilot"] = "[R.old_mob]"
var/turf/robot_turf = get_turf(R)
robotData["location"] = "[robot_turf.x], [robot_turf.y], [robot_turf.z]"
robots[++robots.len] = robotData
data["mechs"] = sortByKey(mechs, "pilot")
data["robots"] = sortByKey(robots, "pilot")
data["current_cam_loc"] = current_camera ? "\ref[current_camera.loc]" : null
return data // This UI needs to constantly update
/datum/computer_file/program/penal_mechs/Topic(href, href_list)
. = ..()
if(href_list["track_mech"])
if(current_camera)
reset_current()
usr.reset_view()
else
var/mob/living/heavy_vehicle/M = locate(href_list["track_mech"]) in mob_list
if(!istype(M))
return FALSE
var/obj/machinery/camera/C = M.camera
if(C)
switch_to_camera(usr, C)
return TRUE
if(href_list["lockdown_mech"])
var/mob/living/heavy_vehicle/M = locate(href_list["lockdown_mech"]) in mob_list
if(ismob(M))
M.ToggleLockdown()
return TRUE
if(href_list["terminate"])
var/mob/living/M = locate(href_list["terminate"]) in mob_list
if(M?.old_mob && M.vr_mob)
to_chat(M, span("warning", "Your connection to remote-controlled [M] is forcibly severed!"))
M.body_return()
return TRUE
if(href_list["message_pilot"])
var/mob/living/M = locate(href_list["message_pilot"]) in mob_list
if(ismob(M))
var/message = sanitize(input("Message to [M.old_mob]", "Set Message") as text|null)
to_chat(usr, span("notice", "Sending message to [M.old_mob]: [message]"))
to_chat(M, span("warning", "Remote Penal Monitoring: [message]"))
return TRUE
// ToDo - Move this set of camera procs to a general datum when more VueUI programs need cameras
/datum/computer_file/program/penal_mechs/proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C)
//don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras.
if(isAI(user))
var/mob/living/silicon/ai/A = user
// Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise.
if(!A.is_in_chassis())
return FALSE
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
return TRUE
set_current(C)
user.machine = ui_host()
user.reset_view(current_camera)
check_eye(user)
return TRUE
/datum/computer_file/program/penal_mechs/proc/set_current(var/obj/machinery/camera/C)
if(current_camera == C)
return
if(current_camera)
reset_current()
current_camera = C
if(current_camera)
var/mob/living/L = current_camera.loc
if(istype(L))
L.tracking_initiated()
/datum/computer_file/program/penal_mechs/proc/reset_current()
if(current_camera)
var/mob/living/L = current_camera.loc
if(istype(L))
L.tracking_cancelled()
current_camera = null
/datum/computer_file/program/penal_mechs/check_eye(var/mob/user)
if(!current_camera)
return FALSE
var/viewflag = current_camera.check_eye(user)
if ( viewflag < 0 ) //camera doesn't work
reset_current()
return viewflag
+8
View File
@@ -0,0 +1,8 @@
author: mikomyazaki
delete-after: True
changes:
- rscadd: "Mechs now have a lockdown function."
- rscadd: "Mechs can now be linked to cameranet networks."
- rscadd: "Adds a program for security that allows them to monitor & lockdown prisoner-controlled mechs and robots."
+1
View File
@@ -46,6 +46,7 @@
NETWORK_ENGINEERING,
NETWORK_ENGINEERING_OUTPOST,
NETWORK_STATION,
NETWORK_MECHS,
NETWORK_MEDICAL,
NETWORK_MINE,
NETWORK_RESEARCH,
@@ -0,0 +1,81 @@
<template>
<div>
<hr>
<h3>Remote Penal Mechs</h3>
<hr>
<div>
<table>
<tr>
<th>Pilot</th>
<th>Mech Type</th>
<th>Location</th>
<th>Camera</th>
<th>Lockdown</th>
<th>End Connection</th>
</tr>
<tr v-for="mech in mechs" :key="mech.ref">
<td>
<template v-if="mech.pilot"><vui-button :params="{message_pilot: mech.ref}">{{ mech.pilot }}</vui-button></template>
<template v-else><span class="red">n/a</span></template>
</td>
<td>{{ mech.name }}</td>
<td>{{ mech.location }}</td>
<td><vui-button :class="{'selected': current_cam_loc == mech.ref}" :params="{track_mech: mech.ref}" :disabled="!mech.camera_status">Track</vui-button></td>
<td><vui-button :class="{'red': mech.lockdown}" :params="{lockdown_mech: mech.ref}">Lockdown</vui-button></td>
<td><vui-button :params="{terminate: mech.ref}" icon="eject">Terminate</vui-button></td>
</tr>
</table>
</div>
<hr>
<h3>Remote Penal Cyborgs</h3>
<hr>
<table>
<tr>
<th>Pilot</th>
<th>Robot Type</th>
<th>Location</th>
<th>End Connection</th>
</tr>
<tr v-for="robot in robots" :key="robot.ref">
<td>
<template v-if="robot.pilot"><vui-button :params="{message_pilot: robot.ref}">{{ robot.pilot }}</vui-button></template>
<template v-else><span class="red">n/a</span></template>
</td>
<td>{{ robot.name }}</td>
<td>{{ robot.location }}</td>
<td><vui-button :params="{terminate: robot.ref}" icon="eject">Terminate</vui-button></td>
</tr>
</table>
</div>
</template>
<script>
export default {
data() {
return this.$root.$data.state
}
}
</script>
<style lang="scss" scoped>
.table {
display: table;
width: 100%;
.header, .mech, .cyborg {
display: table-row;
font-weight: bold;
width: 20%;
.header-item, .item {
display: table-cell;
padding: 1px;
vertical-align: middle;
font-weight: normal;
}
}
}
.center {
text-align: center;
}
</style>