Gives AI a personal atmospherics control subsystem.

Includes further work on NanoUI interactions.
This commit is contained in:
PsiOmega
2015-04-19 00:24:19 +02:00
parent 05d05732f8
commit 27abc7404d
15 changed files with 153 additions and 92 deletions

View File

@@ -1294,8 +1294,10 @@
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
#include "code\modules\nano\interaction\self.dm"
#include "code\modules\nano\interaction\zlevel.dm"
#include "code\modules\nano\modules\alarm_monitor.dm"
#include "code\modules\nano\modules\atmos_control.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"

View File

@@ -9,11 +9,12 @@
density = 1
anchored = 1.0
circuit = "/obj/item/weapon/circuitboard/atmoscontrol"
var/overridden = 0 //not set yet, can't think of a good way to do it
req_access = list(access_ce)
var/list/monitored_alarm_ids = null
var/list/monitored_alarms = null
var/ui_ref
var/obj/nano_module/atmos_control/atmos_control
/obj/machinery/computer/atmoscontrol/New()
..()
/obj/machinery/computer/atmoscontrol/laptop
name = "Atmospherics Laptop"
@@ -21,77 +22,24 @@
icon_state = "medlaptop"
density = 0
/obj/machinery/computer/atmoscontrol/initialize()
..()
if(!monitored_alarms && monitored_alarm_ids)
monitored_alarms = new
for(var/obj/machinery/alarm/alarm in machines)
if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids)
monitored_alarms += alarm
// machines may not yet be ordered at this point
monitored_alarms = dd_sortedObjectList(monitored_alarms)
/obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob)
return ui_interact(user)
ui_interact(user)
/obj/machinery/computer/atmoscontrol/attack_hand(mob/user)
if(..())
return
return ui_interact(user)
/obj/machinery/computer/atmoscontrol/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/alarms[0]
// TODO: Move these to a cache, similar to cameras
for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : machines))
alarms[++alarms.len] = list("name" = sanitize(alarm.name), "ref"= "\ref[alarm]", "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm))
data["alarms"] = alarms
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
ui_ref = ui
return 1
ui_interact(user)
/obj/machinery/computer/atmoscontrol/attackby(var/obj/item/I as obj, var/mob/user as mob)
if(istype(I, /obj/item/weapon/card/emag) && !emagged)
user.visible_message("\red \The [user] swipes \a [I] through \the [src], causing the screen to flash!",\
"\red You swipe your [I] through \the [src], the screen flashing as you gain full control.",\
"You hear the swipe of a card through a reader, and an electronic warble.")
emagged = 1
overridden = 1
atmos_control.emagged = 1
return
return ..()
//a bunch of this is copied from atmos alarms
/obj/machinery/computer/atmoscontrol/Topic(href, href_list)
if(..())
return 1
if(href_list["alarm"])
if(ui_ref)
var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms ? monitored_alarms : machines)
if(alarm)
var/datum/topic_state/TS = generate_state(alarm)
alarm.ui_interact(usr, master_ui = ui_ref, state = TS)
return 1
/obj/machinery/computer/atmoscontrol/proc/generate_state(var/alarm)
var/datum/topic_state/air_alarm/state = new()
state.atmos_control = src
state.air_alarm = alarm
return state
/datum/topic_state/air_alarm
var/obj/machinery/computer/atmoscontrol/atmos_control = null
var/obj/machinery/alarm/air_alarm = null
/datum/topic_state/air_alarm/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = user && (user.isAI() || atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO))
return extra_href
/obj/machinery/computer/atmoscontrol/ui_interact(var/mob/user)
if(!atmos_control)
atmos_control = new(src, req_access, req_one_access, monitored_alarm_ids)
atmos_control.ui_interact(user)

View File

@@ -72,7 +72,6 @@ var/list/ai_verbs_default = list(
var/mob/living/silicon/ai/parent = null
var/apc_override = 0 //hack for letting the AI use its APC even when visionless
var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through.
var/datum/trackable/track = null
var/last_announcement = ""

View File

@@ -92,7 +92,7 @@
var/area/current_area = get_area(src)
if (((!loc.master.power_equip) && current_area.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item))
if (lacks_power())
//If our area lacks equipment power, and is not magically powered (i.e. centcom), or if we are in space and not carded, lose power.
if (src:aiRestorePowerRoutine==0)
src:aiRestorePowerRoutine = 1
@@ -161,10 +161,9 @@
sleep(50)
src << "Receiving control information from APC."
sleep(2)
//bring up APC dialog
apc_override = 1
theAPC.attack_ai(src)
apc_override = 0
theAPC.operating = 1
theAPC.equipment = 3
theAPC.update()
src:aiRestorePowerRoutine = 3
src << "Here are your current laws:"
src.show_laws()
@@ -179,6 +178,11 @@
if (MED_HUD)
process_med_hud(src,0,src.eyeobj)
/mob/living/silicon/ai/proc/lacks_power()
var/turf/T = get_turf(src)
var/area/A = get_area(src)
return ((!A.master.power_equip) && A.requires_power == 1 || istype(T, /turf/space)) && !istype(src.loc,/obj/item)
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
health = 100

View File

@@ -1,10 +1,12 @@
/mob/living/silicon/ai
var/list/ai_verbs_subsystems = list(
/mob/living/silicon/ai/proc/subsystem_atmos_control,
/mob/living/silicon/ai/proc/subsystem_crew_monitor,
/mob/living/silicon/ai/proc/subsystem_power_monitor,
/mob/living/silicon/ai/proc/subsystem_rcon
)
var/obj/nano_module/atmos_control/atmos_control
var/obj/nano_module/crew_monitor/crew_monitor
var/obj/nano_module/rcon/rcon
var/obj/nano_module/power_monitor/power_monitor
@@ -12,25 +14,32 @@
/mob/living/silicon/ai/init_subsystems()
..()
del(alarm_monitor)
atmos_control = new(src)
alarm_monitor = new/obj/nano_module/alarm_monitor/ai(src)
crew_monitor = new(src)
rcon = new(src)
power_monitor = new(src)
/mob/living/silicon/ai/proc/subsystem_atmos_control()
set category = "Subystems"
set name = "Atmospherics Control"
atmos_control.ui_interact(usr, state = self_state)
/mob/living/silicon/ai/proc/subsystem_crew_monitor()
set category = "Subystems"
set name = "Crew Monitor"
crew_monitor.ui_interact(usr)
crew_monitor.ui_interact(usr, state = self_state)
/mob/living/silicon/ai/proc/subsystem_power_monitor()
set category = "Subystems"
set name = "Power Monitor"
power_monitor.ui_interact(usr)
power_monitor.ui_interact(usr, state = self_state)
/mob/living/silicon/ai/proc/subsystem_rcon()
set category = "Subystems"
set name = "RCON"
rcon.ui_interact(usr)
rcon.ui_interact(usr, state = self_state)

View File

@@ -396,10 +396,10 @@
var/changed_name = ""
if(custom_name)
changed_name = custom_name
notify_ai(ROBOT_NOTIFICATION_NEW_NAME, real_name, changed_name)
else
changed_name = "[modtype] [braintype]-[num2text(ident)]"
notify_ai(ROBOT_NOTIFICATION_NEW_NAME, real_name, changed_name)
real_name = changed_name
name = real_name

View File

@@ -17,10 +17,10 @@
set name = "Alarm Monitor"
set category = "Subystems"
alarm_monitor.ui_interact(usr)
alarm_monitor.ui_interact(usr, state = self_state)
/mob/living/silicon/proc/subsystem_law_manager()
set name = "Law Manager"
set category = "Subystems"
law_manager.ui_interact(usr)
law_manager.ui_interact(usr, state = self_state)

View File

@@ -17,3 +17,17 @@
else if (restrained() || lying || stat || stunned || weakened)
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
/mob/living/silicon/ai/shared_nano_interaction()
if(lacks_power())
return STATUS_CLOSE
if (check_unable(1))
return STATUS_CLOSE
return ..()
/mob/living/silicon/robot/shared_nano_interaction()
if(cell.charge <= 0)
return STATUS_CLOSE
if(lockcharge)
. = STATUS_DISABLED
return min(., ..())

View File

@@ -21,10 +21,10 @@
return ..()
/mob/living/silicon/robot/default_can_use_topic(var/src_object)
if(stat || !client)
return STATUS_CLOSE
if(lockcharge || stunned || weakened)
return STATUS_DISABLED
. = shared_nano_interaction()
if(. <= STATUS_DISABLED)
return
// robots can interact with things they can see within their view range
if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view)
return STATUS_INTERACTIVE // interactive (green visibility)
@@ -46,8 +46,10 @@
return STATUS_UPDATE
/mob/living/silicon/ai/default_can_use_topic(var/src_object)
if(!client || check_unable(1))
return STATUS_CLOSE
. = shared_nano_interaction()
if(. != STATUS_INTERACTIVE)
return
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
@@ -61,9 +63,8 @@
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
return STATUS_CLOSE
return STATUS_INTERACTIVE
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
return STATUS_INTERACTIVE

View File

@@ -0,0 +1,10 @@
/*
This state checks that the src_object is the same the as user
*/
/var/global/datum/topic_state/self_state/self_state = new()
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
if(src_object != user)
return STATUS_CLOSE
return user.shared_nano_interaction()

View File

@@ -63,7 +63,7 @@
usr.switch_to_camera(C)
return 1
/obj/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/data[0]
var/categories[0]
@@ -90,7 +90,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "alarm_monitor.tmpl", "Alarm Monitoring Console", 800, 800)
ui = new(user, src, ui_key, "alarm_monitor.tmpl", "Alarm Monitoring Console", 800, 800, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)

View File

@@ -0,0 +1,74 @@
/obj/nano_module/atmos_control
name = "Atmospherics Control"
var/ui_ref
var/emagged = 0
var/list/monitored_alarms = list()
var/datum/topic_state/atmos_state
/obj/nano_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids)
..()
loc = atmos_computer
src.req_access = req_access
src.req_one_access = req_one_access
atmos_state = default_state
if(monitored_alarm_ids)
for(var/obj/machinery/alarm/alarm in machines)
if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids)
monitored_alarms += alarm
// machines may not yet be ordered at this point
monitored_alarms = dd_sortedObjectList(monitored_alarms)
/obj/nano_module/atmos_control/Topic(href, href_list)
if(..())
return 1
if(href_list["alarm"])
if(ui_ref)
var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines)
if(alarm)
var/datum/topic_state/TS = generate_state(alarm)
alarm.ui_interact(usr, master_ui = ui_ref, state = TS)
return 1
/obj/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
var/data[0]
var/alarms[0]
// TODO: Move these to a cache, similar to cameras
for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines))
alarms[++alarms.len] = list("name" = sanitize(alarm.name), "ref"= "\ref[alarm]", "danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm))
data["alarms"] = alarms
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 625, 625, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
ui_ref = ui
/obj/nano_module/atmos_control/proc/generate_state(air_alarm)
var/datum/topic_state/air_alarm/state = new()
state.atmos_control = src
state.air_alarm = air_alarm
return state
/datum/topic_state/air_alarm
var/obj/nano_module/atmos_control/atmos_control = null
var/obj/machinery/alarm/air_alarm = null
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
if(has_access(user))
return STATUS_INTERACTIVE
return STATUS_UPDATE
/datum/topic_state/air_alarm/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = has_access(user)
return extra_href
/datum/topic_state/air_alarm/proc/has_access(var/mob/user)
return user && (user.isAI() || atmos_control.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO))

View File

@@ -25,7 +25,7 @@
AI.ai_actual_track(H)
return 1
/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
user.set_machine(src)
src.scan()
@@ -74,7 +74,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800, state = state)
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")

View File

@@ -7,7 +7,7 @@
..()
refresh_sensors()
/obj/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/nano_module/power_monitor/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/list/sensors = list()
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
@@ -28,7 +28,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500)
ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)

View File

@@ -8,7 +8,7 @@
var/hide_SMES_details = 0
var/hide_breakers = 0
/obj/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1)
/obj/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1, var/datum/topic_state/state = default_state)
FindDevices() // Update our devices list
var/data[0]
@@ -41,7 +41,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400)
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)