Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AI Remote Control Fixes #20198

Merged
merged 10 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 71 additions & 79 deletions code/__HELPERS/lists.dm

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion code/_onclick/hud/screen_object_types/ai_screen_objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 158,7 @@
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
if(AI.anchored)
AI.remote_control_shell()
AI.remote_control()
else
to_chat(AI, SPAN_WARNING("You are unable to get a good connection while unanchored from the station systems."))

Expand Down
69 changes: 51 additions & 18 deletions code/controllers/subsystems/virtual_reality.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 60,16 @@ SUBSYSTEM_DEF(virtualreality)
var/mob/living/vr_mob = null // In which mob is our mind
var/mob/living/old_mob = null // Which mob is our old mob

// Return to our original body
/// Return to original body
/mob/proc/body_return()
set name = "Return to Body"
set category = "IC"

if(old_mob)
ckey_transfer(old_mob)
languages = list(GLOB.all_languages[LANGUAGE_TCB])
if(old_mob.client)
old_mob.client.init_verbs() // We need to have the stat panel to update, so we call this directly
to_chat(old_mob, SPAN_NOTICE("System exited safely, we hope you enjoyed your stay."))
old_mob = null
else
Expand All @@ -81,6 83,8 @@ SUBSYSTEM_DEF(virtualreality)
if(old_mob)
ckey_transfer(old_mob)
speech_synthesizer_langs = list(GLOB.all_languages[LANGUAGE_TCB])
if(old_mob.client)
old_mob.client.init_verbs()
to_chat(old_mob, SPAN_NOTICE("System exited safely, we hope you enjoyed your stay."))
old_mob = null
else
Expand All @@ -95,6 99,8 @@ SUBSYSTEM_DEF(virtualreality)
ckey_transfer(old_mob)
languages = list(GLOB.all_languages[LANGUAGE_TCB])
internal_id.access = list()
if(old_mob.client)
old_mob.client.init_verbs()
to_chat(old_mob, SPAN_NOTICE("System exited safely, we hope you enjoyed your stay."))
old_mob = null
else
Expand All @@ -108,6 114,8 @@ SUBSYSTEM_DEF(virtualreality)
if(old_mob)
ckey_transfer(old_mob)
languages = list(GLOB.all_languages[LANGUAGE_TCB])
if(old_mob.client)
old_mob.client.init_verbs()
to_chat(old_mob, SPAN_NOTICE("System exited safely, we hope you enjoyed your stay."))
old_mob = null
qdel(src)
Expand Down Expand Up @@ -137,11 145,18 @@ SUBSYSTEM_DEF(virtualreality)
if(target.client)
target.client.screen |= global_hud.vr_control

if(istype(target, /mob/living/simple_animal/spiderbot))
if(istype(target, /mob/living/simple_animal/spiderbot) && !istype(target, /mob/living/simple_animal/spiderbot/ai))
var/mob/living/simple_animal/spiderbot/spider = target
var/obj/item/card/id/original_id = M.GetIdCard()
if(original_id)
var/mob/living/simple_animal/spiderbot/SB = target
SB.internal_id.access = original_id.access
// Update radio
var/obj/item/device/encryptionkey/Key = spider.radio.keyslot
var/obj/item/device/radio/Radio = M.get_radio()
if(Key && Radio)
Key.channels = Radio.channels
spider.radio.recalculateChannels()

target.client.init_verbs()
to_chat(target, SPAN_NOTICE("Connection established, system suite active and calibrated."))
Expand Down Expand Up @@ -173,7 188,8 @@ SUBSYSTEM_DEF(virtualreality)
if(null_vr_mob)
target.vr_mob = null

/datum/controller/subsystem/virtualreality/proc/mech_selection(var/user, var/network)
/// Returns a list with all remote controlable exosuits on the given network
/datum/controller/subsystem/virtualreality/proc/mech_choices(var/user, var/network)
var/list/mech = list()

for(var/mob/living/heavy_vehicle/R in mechs[network])
Expand All @@ -193,19 209,26 @@ SUBSYSTEM_DEF(virtualreality)
continue
mech[R.name] = R

if(!length(mech))
return mech

/// Retrieves a list returned by mech_choices and prompts user to select an option to transfer to
/datum/controller/subsystem/virtualreality/proc/mech_selection(var/user, var/network)
var/list/remote = mech_choices(user, network)
if(!length(remote))
to_chat(user, SPAN_WARNING("No active remote mechs are available."))
return

var/choice = tgui_input_list(usr, "Please select a remote control compatible mech to take over.", "Remote Mech Selection", mech)
var/choice = tgui_input_list(usr, "Please select a remote control compatible mech to take over.", "Remote Mech Selection", remote)
if(!choice)
return

var/mob/living/heavy_vehicle/chosen_mech = mech[choice]
var/mob/living/heavy_vehicle/chosen_mech = remote[choice]
var/mob/living/remote_pilot = chosen_mech.pilots[1] // the first pilot
mind_transfer(user, remote_pilot)

/datum/controller/subsystem/virtualreality/proc/robot_selection(var/user, var/network)

/// Returns a list with all remote controlable robots on the given network
/datum/controller/subsystem/virtualreality/proc/robot_choices(var/user, var/network)
var/list/robot = list()

for(var/mob/living/R in robots[network])
Expand All @@ -220,17 243,22 @@ SUBSYSTEM_DEF(virtualreality)
continue
robot[R.name] = R

if(!length(robot))
to_chat(user, SPAN_WARNING("No active remote robots are available."))
return
return robot

var/choice = tgui_input_list(usr, "Please select a remote control robot to take over.", "Remote Robot Selection", robot)
if(!choice)
/// Retrieves a list returned by robot_choices and prompts user to select an option to transfer to
/datum/controller/subsystem/virtualreality/proc/robot_selection(var/user, var/network)
var/list/remote = robot_choices(user, network)
if(!length(remote))
to_chat(user, SPAN_WARNING("No active remote units are available."))

var/choice = tgui_input_list(usr, "Please select a remote control unit to take over.", "Remote Unit Selection", remote)
if(!(choice in remote))
return

mind_transfer(user, robot[choice])
mind_transfer(user, choice)

/datum/controller/subsystem/virtualreality/proc/bound_selection(var/user, var/network)
/// Returns a list with all remote controlable bound on the given network
/datum/controller/subsystem/virtualreality/proc/bound_choices(var/user, var/network)
var/list/bound = list()

for(var/mob/living/silicon/R in bounded[network])
Expand All @@ -245,16 273,21 @@ SUBSYSTEM_DEF(virtualreality)
continue
bound = R

if(!length(bound))
return bound

/// Retrieves a list returned by bound_choices and prompts user to select an option to transfer to
/datum/controller/subsystem/virtualreality/proc/bound_selection(var/user, var/network)
var/list/remote = bound_choices(user, network)
if(!length(remote))
to_chat(user, SPAN_WARNING("No active remote units are available."))
return

var/choice = tgui_input_list(usr, "Please select a remote control unit to take over.", "Remote Unit Selection", bound)
if(!(choice in bound))
var/choice = tgui_input_list(usr, "Please select a remote control unit to take over.", "Remote Unit Selection", remote)
if(!(choice in remote))
return

mind_transfer(user, choice)


/datum/controller/subsystem/virtualreality/proc/create_virtual_reality_avatar(var/mob/living/carbon/human/user)
if(GLOB.virtual_reality_spawn.len)
var/mob/living/carbon/human/virtual_reality/H = new /mob/living/carbon/human/virtual_reality(pick(GLOB.virtual_reality_spawn))
Expand Down
13 changes: 7 additions & 6 deletions code/game/objects/items/devices/radio/radio.dm
Original file line number Diff line number Diff line change
Expand Up @@ -636,12 636,13 @@ var/global/list/default_interrogation_channels = list(
channels = list(CHANNEL_COMMON = TRUE, CHANNEL_ENTERTAINMENT = TRUE)
syndie = FALSE

var/mob/living/silicon/robot/D = loc
if(D.module)
for(var/ch_name in D.module.channels)
if(ch_name in channels)
continue
channels[ch_name] = D.module.channels[ch_name]
if(isrobot(loc))
var/mob/living/silicon/robot/D = loc
if(D.module)
for(var/ch_name in D.module.channels)
if(ch_name in channels)
continue
channels[ch_name] = D.module.channels[ch_name]
if(keyslot)
for(var/ch_name in keyslot.channels)
if(ch_name in channels)
Expand Down
4 changes: 3 additions & 1 deletion code/modules/heavy_vehicle/mech_interaction.dm
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 233,13 @@
LAZYDISTINCTADD(user.additional_vision_handlers, src)
update_icon()
GLOB.move_manager.stop_looping(src) // stop it from auto moving when the pilot gets in
return 1
return TRUE

/mob/living/heavy_vehicle/proc/eject(var/mob/user, var/silent)
if(!user || !(user in src.contents))
return
if(remote)
usr.body_return()
if(hatch_closed)
if(hatch_locked)
if(!silent) to_chat(user, SPAN_WARNING("The [body.hatch_descriptor] is locked."))
Expand Down
5 changes: 4 additions & 1 deletion code/modules/heavy_vehicle/mecha.dm
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 131,7 @@
. = ..()

/mob/living/heavy_vehicle/IsAdvancedToolUser()
return 1
return TRUE

/mob/living/heavy_vehicle/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
SHOULD_CALL_PARENT(FALSE) //Special snowflake case
Expand Down Expand Up @@ -321,6 321,9 @@
dummy = new dummy_type(get_turf(src))
dummy.real_name = "Remote-Bot"
dummy.name = dummy.real_name
// Give dummy a blank encryption key for later editing if spiderbot
if(istype(dummy, /mob/living/simple_animal/spiderbot) && !istype(dummy, /mob/living/simple_animal/spiderbot/ai))
dummy.radio.keyslot = new /obj/item/device/encryptionkey
remove_verb(dummy, /mob/living/proc/ventcrawl)
remove_verb(dummy, /mob/living/proc/hide)
if(dummy_colour)
Expand Down
29 changes: 24 additions & 5 deletions code/modules/mob/living/silicon/ai/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 21,7 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/core,
/mob/living/silicon/ai/proc/pick_icon,
/mob/living/silicon/ai/proc/sensor_mode,
/mob/living/silicon/ai/proc/remote_control_shell,
/mob/living/silicon/ai/proc/remote_control,
/mob/living/silicon/ai/proc/show_laws_verb,
/mob/living/silicon/ai/proc/toggle_acceleration,
/mob/living/silicon/ai/proc/toggle_camera_light,
Expand Down Expand Up @@ -800,14 800,33 @@ var/list/ai_verbs_default = list(
set desc = "Augment visual feed with internal sensor overlays"
toggle_sensor_mode()

/mob/living/silicon/ai/proc/remote_control_shell()
set name = "Remote Control Shell"
/// Retrieves all mobs assigned to REMOTE_AI_ROBOT or REMOTE_AI_MECH and allows the user to select one to control using SSvirtualreality
/mob/living/silicon/ai/proc/remote_control()
Ben10083 marked this conversation as resolved.
Show resolved Hide resolved
set name = "Remote Control"
set category = "AI Commands"
set desc = "Remotely control any active shells on your AI shell network."
set desc = "Remotely control any active shells or mechs on your AI network."

if(check_unable(AI_CHECK_WIRELESS))
return
SSvirtualreality.bound_selection(src, REMOTE_AI_ROBOT)

// Grab from relevant networks
var/list/remote_shell = SSvirtualreality.bound_choices(src, REMOTE_AI_ROBOT)
var/list/remote_mech = SSvirtualreality.mech_choices(src, REMOTE_AI_MECH)
var/list/remote = flatten_list(list(remote_shell, remote_mech))

if(!length(remote))
to_chat(usr, SPAN_WARNING("No active remote units are available."))
return
var/choice = tgui_input_list(usr, "Please select what to take over.", "Remote Control Selection", remote)
if(!choice)
return

// Transfer
if(choice in remote_mech)
var/mob/living/heavy_vehicle/chosen_mech = remote_mech[choice]
SSvirtualreality.mind_transfer(src, chosen_mech.pilots[1]) // the first pilot
else
SSvirtualreality.mind_transfer(src, choice)

/mob/living/silicon/ai/proc/toggle_hologram_movement()
set name = "Toggle Hologram Movement"
Expand Down
7 changes: 7 additions & 0 deletions code/modules/mob/living/simple_animal/friendly/spiderbot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 332,13 @@
spawn(3)//A slight delay to let us finish walking out from under the door
layer = initial(layer)

/mob/living/simple_animal/spiderbot/zMove(direction)
if(istype(loc, /mob/living/heavy_vehicle))
var/mob/living/heavy_vehicle/mech = loc
mech.zMove(direction)
return
..()

/mob/living/simple_animal/spiderbot/get_bullet_impact_effect_type(var/def_zone)
return BULLET_IMPACT_METAL

Expand Down
5 changes: 5 additions & 0 deletions code/modules/tgui/states/default.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 59,8 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
to_chat(src, SPAN_WARNING("Access denied."))

return min(..(), UI_UPDATE)

/mob/living/simple_animal/spiderbot/default_can_use_topic(src_object)
if(ismech(src_object))
return UI_INTERACTIVE
return ..()
63 changes: 63 additions & 0 deletions html/changelogs/Ben10083 - Remote Fixes.yml
Original file line number Diff line number Diff line change
@@ -0,0 1,63 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# - (fixes bugs)
# wip
# - (work in progress)
# qol
# - (quality of life)
# soundadd
# - (adds a sound)
# sounddel
# - (removes a sound)
# rscadd
# - (adds a feature)
# rscdel
# - (removes a feature)
# imageadd
# - (adds an image or sprite)
# imagedel
# - (removes an image or sprite)
# spellcheck
# - (fixes spelling or grammar)
# experiment
# - (experimental change)
# balance
# - (balance changes)
# code_imp
# - (misc internal code change)
# refactor
# - (refactors code)
# config
# - (makes a change to the config files)
# admin
# - (makes changes to administrator tools)
# server
# - (miscellaneous changes to server)
#################################

# Your name.
author: Ben10083

# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True

# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
changes:
- bugfix: "AI can remote control mechs again."
- bugfix: "Remote controlled exosuits now can travel between zlevels if capable."
- bugfix: "Remote control no longer makes the client lose verbs until restart."
- bugfix: "Remote controlled exosuit radios now will use the channels the user has access to."
- qol: "Pressing eject in a remotely controlled mech now exits remote control."
- code_imp: "DMdoced lists.dm"
Loading