mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 19:22:20 +00:00
Ports the Bot Control PDA program to Modular Computers. (#50351)
* Startwork. * Time to break this later * How do I map lists again * So close I can almost TASTE ITTTT I GOTTA GET A MOVE ON WITH MY LIIIIFE * Hey, it almost works! * Finally actually ready to PR * Nothing to see here but documentation and dead code * Take 2. * Revert "Take 2." This reverts commit 0882d96a30ba79ebead4b5dd3e6f32e65bbf2a76. * Cleans up tgui compile errors. * WIP changes, still not happy with this for now. * I am satisified. * Rework that UI Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
@@ -110,6 +110,19 @@
|
||||
else
|
||||
return "<span class='average'>[mode_name[mode]]</span>"
|
||||
|
||||
/**
|
||||
* Returns a status string about the bot's current status, if it's moving, manually controlled, or idle.
|
||||
*/
|
||||
/mob/living/simple_animal/bot/proc/get_mode_ui()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
return paicard ? "pAI Controlled" : "Autonomous"
|
||||
else if(!on)
|
||||
return "Inactive"
|
||||
else if(!mode)
|
||||
return "Idle"
|
||||
else
|
||||
return "[mode_name[mode]]"
|
||||
|
||||
/mob/living/simple_animal/bot/proc/turn_on()
|
||||
if(stat)
|
||||
return FALSE
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
|
||||
hard_drive.store_file(new/datum/computer_file/program/chatclient())
|
||||
hard_drive.store_file(new/datum/computer_file/program/aidiag())
|
||||
hard_drive.store_file(new/datum/computer_file/program/robocontrol())
|
||||
|
||||
|
||||
// ===== COMMAND CONSOLE =====
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
/datum/computer_file/program/robocontrol
|
||||
filename = "robocontrol"
|
||||
filedesc = "Bot Remote Controller"
|
||||
program_icon_state = "robot"
|
||||
extended_desc = "A remote controller used for giving basic commands to non-sentient robots."
|
||||
transfer_access = ACCESS_ROBOTICS
|
||||
requires_ntnet = TRUE
|
||||
network_destination = "robotics control network"
|
||||
size = 12
|
||||
tgui_id = "ntos_robocontrol"
|
||||
ui_x = 550
|
||||
ui_y = 550
|
||||
///Number of simple robots on-station.
|
||||
var/botcount = 0
|
||||
///Used to find the location of the user for the purposes of summoning robots.
|
||||
var/mob/current_user
|
||||
///Access granted by the used to summon robots.
|
||||
var/list/current_access = list()
|
||||
|
||||
/datum/computer_file/program/robocontrol/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
var/turf/current_turf = get_turf(ui_host())
|
||||
var/zlevel = current_turf.z
|
||||
var/list/botlist = list()
|
||||
var/list/mulelist = list()
|
||||
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer ? computer.all_components[MC_CARD] : null
|
||||
data["have_id_slot"] = !!card_slot
|
||||
if(computer)
|
||||
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
|
||||
data["has_id"] = !!id_card
|
||||
data["id_owner"] = id_card ? id_card.registered_name : "No Card Inserted."
|
||||
data["access_on_card"] = id_card ? id_card.access : null
|
||||
|
||||
botcount = 0
|
||||
current_user = user
|
||||
|
||||
for(var/B in GLOB.bots_list)
|
||||
var/mob/living/simple_animal/bot/Bot = B
|
||||
if(!Bot.on || Bot.z != zlevel || Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue //Also, the PDA must have access to the bot type.
|
||||
var/list/newbot = list("name" = Bot.name, "mode" = Bot.get_mode_ui(), "model" = Bot.model, "locat" = get_area(Bot), "bot_ref" = REF(Bot), "mule_check" = FALSE)
|
||||
if(Bot.bot_type == MULE_BOT)
|
||||
var/mob/living/simple_animal/bot/mulebot/MULE = Bot
|
||||
mulelist += list(list("name" = MULE.name, "dest" = MULE.destination, "power" = MULE.cell ? MULE.cell.percent() : 0, "home" = MULE.home_destination, "autoReturn" = MULE.auto_return, "autoPickup" = MULE.auto_pickup, "reportDelivery" = MULE.report_delivery, "mule_ref" = REF(MULE)))
|
||||
if(MULE.load)
|
||||
data["load"] = MULE.load.name
|
||||
newbot["mule_check"] = TRUE
|
||||
botlist += list(newbot)
|
||||
|
||||
data["bots"] = botlist
|
||||
data["mules"] = mulelist
|
||||
data["botcount"] = botlist.len
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/robocontrol/ui_act(action, list/params)
|
||||
if(..())
|
||||
return TRUE
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
var/obj/item/card/id/id_card
|
||||
if(computer)
|
||||
card_slot = computer.all_components[MC_CARD]
|
||||
if(card_slot)
|
||||
id_card = card_slot.stored_card
|
||||
|
||||
var/list/standard_actions = list("patroloff", "patrolon", "ejectpai")
|
||||
var/list/MULE_actions = list("stop", "go", "home", "destination", "setid", "sethome", "unload", "autoret", "autopick", "report", "ejectpai")
|
||||
var/mob/living/simple_animal/bot/Bot = locate(params["robot"]) in GLOB.bots_list
|
||||
if (action in standard_actions)
|
||||
Bot.bot_control(action, current_user, current_access)
|
||||
if (action in MULE_actions)
|
||||
Bot.bot_control(action, current_user, current_access, TRUE)
|
||||
switch(action)
|
||||
if("summon")
|
||||
Bot.bot_control(action, current_user, id_card ? id_card.access : current_access)
|
||||
if("ejectcard")
|
||||
if(!computer || !card_slot)
|
||||
return
|
||||
if(id_card)
|
||||
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment)
|
||||
card_slot.try_eject(TRUE, current_user)
|
||||
else
|
||||
playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
|
||||
return
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -2432,6 +2432,7 @@
|
||||
#include "code\modules\modular_computers\file_system\programs\ntmonitor.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\ntnrc_client.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\powermonitor.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\robocontrol.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\sm_monitor.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\antagonist\contract_uplink.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm"
|
||||
|
||||
@@ -15,6 +15,7 @@ const PROGRAM_ICONS = {
|
||||
powermonitor: 'plug',
|
||||
job_manage: 'address-book',
|
||||
crewmani: 'clipboard-list',
|
||||
robocontrol: 'robot',
|
||||
};
|
||||
|
||||
export const NtosMain = props => {
|
||||
|
||||
206
tgui/packages/tgui/interfaces/NtosRoboControl.js
Normal file
206
tgui/packages/tgui/interfaces/NtosRoboControl.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Flex, LabeledList, ProgressBar, Section } from '../components';
|
||||
|
||||
const getMuleByRef = (mules, ref) => {
|
||||
return mules?.find(mule => mule.mule_ref === ref);
|
||||
};
|
||||
|
||||
export const NtosRoboControl = props => {
|
||||
const { state } = props;
|
||||
const { act, data } = useBackend(props);
|
||||
const {
|
||||
bots,
|
||||
id_owner,
|
||||
has_id,
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Robot Control Console">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Id Card">
|
||||
{id_owner}
|
||||
{!!has_id && (
|
||||
<Button
|
||||
ml={2}
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
onClick={() => act('ejectcard')} />
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Bots in range">
|
||||
{data.botcount}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
{bots?.map(robot => (
|
||||
<RobotInfo
|
||||
key={robot.bot_ref}
|
||||
state={state}
|
||||
robot={robot} />
|
||||
))}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const RobotInfo = props => {
|
||||
const { robot } = props;
|
||||
const { act, data } = useBackend(props);
|
||||
const mules = data.mules || [];
|
||||
// Get a mule object
|
||||
const mule = !!robot.mule_check
|
||||
&& getMuleByRef(mules, robot.bot_ref);
|
||||
// Color based on type of a robot
|
||||
const color = robot.mule_check === 1
|
||||
? 'rgba(110, 75, 14, 1)'
|
||||
: 'rgba(74, 59, 140, 1)';
|
||||
return (
|
||||
<Section
|
||||
title={robot.name}
|
||||
style={{
|
||||
border: `4px solid ${color}`,
|
||||
}}
|
||||
buttons={mule && (
|
||||
<Fragment>
|
||||
<Button
|
||||
icon="play"
|
||||
tooltip="Go to Destination."
|
||||
onClick={() => act('go', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button
|
||||
icon="pause"
|
||||
tooltip="Stop Moving."
|
||||
onClick={() => act('stop', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button
|
||||
icon="home"
|
||||
tooltip="Travel Home."
|
||||
tooltipPosition="bottom-left"
|
||||
onClick={() => act('home', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<Flex spacing={1}>
|
||||
<Flex.Item grow={1} basis={0}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Model">
|
||||
{robot.model}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Location">
|
||||
{robot.locat}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Status">
|
||||
{robot.mode}
|
||||
</LabeledList.Item>
|
||||
{mule && (
|
||||
<Fragment>
|
||||
<LabeledList.Item label="Loaded Cargo">
|
||||
{data.load || "N/A"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Home">
|
||||
{mule.home}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Destination">
|
||||
{mule.dest || "N/A"}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Power">
|
||||
<ProgressBar
|
||||
value={mule.power}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
ranges={{
|
||||
good: [60, Infinity],
|
||||
average: [20, 60],
|
||||
bad: [-Infinity, 20],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
</Fragment>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
<Flex.Item width="150px">
|
||||
{mule && (
|
||||
<Fragment>
|
||||
<Button
|
||||
fluid
|
||||
content="Set Destination"
|
||||
onClick={() => act('destination', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Set ID"
|
||||
onClick={() => act('setid', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Set Home"
|
||||
onClick={() => act('sethome', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Unload Cargo"
|
||||
onClick={() => act('unload', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button.Checkbox
|
||||
fluid
|
||||
content="Auto Return"
|
||||
checked={mule.autoReturn}
|
||||
onClick={() => act('autoret', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button.Checkbox
|
||||
fluid
|
||||
content="Auto Pickup"
|
||||
checked={mule.autoPickup}
|
||||
onClick={() => act('autopick', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
<Button.Checkbox
|
||||
fluid
|
||||
content="Delivery Report"
|
||||
checked={mule.reportDelivery}
|
||||
onClick={() => act('report', {
|
||||
robot: mule.mule_ref,
|
||||
})} />
|
||||
</Fragment>
|
||||
)}
|
||||
{!mule && (
|
||||
<Fragment>
|
||||
<Button
|
||||
fluid
|
||||
content="Stop Patrol"
|
||||
onClick={() => act('patroloff', {
|
||||
robot: robot.bot_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Start Patrol"
|
||||
onClick={() => act('patrolon', {
|
||||
robot: robot.bot_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Summon"
|
||||
onClick={() => act('summon', {
|
||||
robot: robot.bot_ref,
|
||||
})} />
|
||||
<Button
|
||||
fluid
|
||||
content="Eject PAi"
|
||||
onClick={() => act('ejectpai', {
|
||||
robot: robot.bot_ref,
|
||||
})} />
|
||||
</Fragment>
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -91,6 +91,7 @@ import { NtosNetDos } from './interfaces/NtosNetDos';
|
||||
import { NtosNetDownloader } from './interfaces/NtosNetDownloader';
|
||||
import { NtosNetMonitor } from './interfaces/NtosNetMonitor';
|
||||
import { NtosRevelation } from './interfaces/NtosRevelation';
|
||||
import { NtosRoboControl } from './interfaces/NtosRoboControl';
|
||||
import { NtosSupermatterMonitor } from './interfaces/NtosSupermatterMonitor';
|
||||
import { NtosWrapper } from './interfaces/NtosWrapper';
|
||||
import { NuclearBomb } from './interfaces/NuclearBomb';
|
||||
@@ -546,6 +547,12 @@ const ROUTES = {
|
||||
scrollable: false,
|
||||
theme: 'syndicate',
|
||||
},
|
||||
ntos_robocontrol: {
|
||||
component: () => NtosRoboControl,
|
||||
wrapper: () => NtosWrapper,
|
||||
scrollable: true,
|
||||
theme: 'ntos',
|
||||
},
|
||||
ntos_station_alert: {
|
||||
component: () => StationAlertConsole,
|
||||
wrapper: () => NtosWrapper,
|
||||
|
||||
Reference in New Issue
Block a user