mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-21 21:10:30 +01:00
8111a8489b
Many, many, many items have inhand sprites in their .dmis but for whatever reasons do not display them in-game. This PR: 1. Updates many item definitions to point to their already-existing inhands correctly. This consists largely of held tools, but also gas tanks and jetpacks mounted in the suit storage slot. 2. Adds a few codersprites made by me for objects with either missing inhands or poorly matching mishands (IE, the tape recorder, which has a black case, reused the white inhand sprites of the health analyzer). The new sprites are modified or recolored variations of other inhand sprites from our repo, except for circuitboards which are new. <img width="444" height="400" alt="image" src="https://github.com/user-attachments/assets/7f107b9a-fe24-4e31-8f16-4d34768ee117" /> 3. Adds inhand sprites for Inflatables and Inflatable Boxes made by Tomixcomics. <img width="424" height="101" alt="image" src="https://github.com/user-attachments/assets/434107c4-8577-49a2-a58e-d6b014c03933" /> 4. Ports inhand sprites for the Hydraulic Rescue Tool from tg's Jaws of Life. <img width="224" height="94" alt="Screenshot 2026-02-07 172931" src="https://github.com/user-attachments/assets/070c7956-f6a8-4fb5-870f-10c64afcc8b3" /> 5. Some additional cleanup while in the area. The 'analyzer' has been renamed the 'gas analyzer' to be consistent with the other analyzer objects, standardized icon_state naming conventions where I saw oddballs, updated code docs to use DMDocs when in the area, etc. ### Asset Licenses The following assets that **have not** been created by myself are included in this PR: | Path | Original Author | License | | --- | --- | --- | | icons/obj/item/hydraulic_rescue_tool.dmi | [SomeAngryMiner (bee station)](https://github.com/BeeStation/BeeStation-Hornet/pull/2487), [maxymax (/tg/station)](https://github.com/tgstation/tgstation/pull/58616) | CC-BY-SA | | icons/obj/item/inflatables.dmi | [Tomixcomics](https://github.com/tomixcomics) | CC-BY-SA |
254 lines
8.0 KiB
Plaintext
254 lines
8.0 KiB
Plaintext
/obj/machinery/computer/robotics
|
|
name = "robotics control console"
|
|
desc = "Used to remotely lockdown or detonate linked cyborgs."
|
|
icon = 'icons/obj/modular_computers/modular_console.dmi'
|
|
|
|
icon_screen = "robot"
|
|
icon_keyboard = "purple_key"
|
|
icon_keyboard_emis = "purple_key_mask"
|
|
light_color = LIGHT_COLOR_PURPLE
|
|
|
|
req_one_access = list(ACCESS_RD, ACCESS_ROBOTICS)
|
|
circuit = /obj/item/circuitboard/robotics
|
|
|
|
var/safety = 1
|
|
|
|
|
|
/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob)
|
|
if(!ai_can_interact(user))
|
|
return
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
|
var/data[0]
|
|
data["robots"] = get_cyborgs(user)
|
|
data["safety"] = safety
|
|
// Also applies for cyborgs. Hides the manual self-destruct button.
|
|
data["is_ai"] = issilicon(user)
|
|
|
|
|
|
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
|
|
if(!ui)
|
|
ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500)
|
|
ui.set_initial_data(data)
|
|
ui.open()
|
|
ui.set_auto_update(1)
|
|
|
|
/obj/machinery/computer/robotics/Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
var/mob/user = usr
|
|
if(!src.allowed(user))
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
|
|
// Destroys the cyborg
|
|
if(href_list["detonate"])
|
|
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["detonate"])
|
|
if(!target || !istype(target))
|
|
return
|
|
if(isAI(user) && (target.connected_ai != user))
|
|
to_chat(user, "Access denied. This robot is not linked to you.")
|
|
return
|
|
// Cyborgs may blow up themselves via the console
|
|
if(isrobot(user) && user != target)
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
var/choice = tgui_alert(usr, "Really detonate [target.name]?", "Robotics Control", list("Yes", "No"))
|
|
if(choice != "Yes")
|
|
return
|
|
if(!target || !istype(target))
|
|
return
|
|
|
|
// Antagonistic cyborgs? Left here for downstream
|
|
if(target.mind && target.mind.special_role && target.emagged)
|
|
to_chat(target, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.")
|
|
target.ResetSecurityCodes()
|
|
return
|
|
|
|
if(target.emagged)
|
|
to_chat(user, "Access denied. Safety protocols are disabled.")
|
|
return
|
|
|
|
else
|
|
message_admins("[key_name_admin(usr)] detonated [target.name]!")
|
|
log_game("[key_name(usr)] detonated [target.name]!")
|
|
to_chat(target, SPAN_DANGER("Self-destruct command received."))
|
|
addtimer(CALLBACK(target, TYPE_PROC_REF(/mob/living/silicon/robot, self_destruct)), 1 SECONDS)
|
|
|
|
|
|
|
|
// Locks or unlocks the cyborg
|
|
else if(href_list["lockdown"])
|
|
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
|
|
if(!target || !istype(target))
|
|
return
|
|
|
|
if(isAI(user) && (target.connected_ai != user))
|
|
to_chat(user, "Access denied. This robot is not linked to you.")
|
|
return
|
|
|
|
if(isrobot(user))
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
|
|
if(target.emagged)
|
|
return
|
|
|
|
var/choice = tgui_alert(usr, "Really [target.lock_charge ? "unlock" : "lockdown"] [target.name] ?", "Robotics Control", list("Yes", "No"))
|
|
if(choice != "Yes")
|
|
return
|
|
|
|
if(!target || !istype(target))
|
|
return
|
|
|
|
target.SetLockdown(!target.lock_charge) // Toggle.
|
|
message_admins("[key_name_admin(usr)] [target.lock_charge ? "locked down" : "released"] [target.name]!")
|
|
log_game("[key_name(usr)] [target.lock_charge ? "locked down" : "released"] [target.name]!")
|
|
to_chat(target, (target.lock_charge ? "You have been locked down!" : "Your lockdown has been lifted!"))
|
|
|
|
// Changes borg's access
|
|
else if(href_list["access"])
|
|
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["access"])
|
|
if(!istype(target))
|
|
return
|
|
|
|
if(isAI(user) && (target.connected_ai != user))
|
|
to_chat(user, "Access denied. This robot is not linked to you.")
|
|
return
|
|
|
|
if(isrobot(user) || target.emagged)
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
|
|
if(!istype(target))
|
|
return
|
|
|
|
if(!target.module)
|
|
to_chat(user, "\The [src]\s access protocols are immutable.")
|
|
return
|
|
|
|
target.module.all_access = !target.module.all_access
|
|
target.update_access()
|
|
|
|
var/log_message = "[key_name_admin(usr)] changed [target.name] access to [target.module.all_access ? "all access" : "role specific"]."
|
|
message_admins(log_message)
|
|
log_game(log_message)
|
|
to_chat(target, ("Your access was changed to: [target.module.all_access ? "all access" : "role specific"]."))
|
|
|
|
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
|
|
else if(href_list["hack"])
|
|
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
|
|
if(!target || !istype(target))
|
|
return
|
|
|
|
// Antag AI checks
|
|
if(!istype(user, /mob/living/silicon/ai) || !(user.mind.special_role && user.mind.original == user))
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
|
|
if(target.emagged)
|
|
to_chat(user, "Robot is already hacked.")
|
|
return
|
|
|
|
var/choice = tgui_alert(usr, "Really hack [target.name]? This cannot be undone.", list("Yes", "No"))
|
|
if(choice != "Yes")
|
|
return
|
|
|
|
if(!target || !istype(target))
|
|
return
|
|
|
|
message_admins("[key_name_admin(usr)] emagged [target.name] using robotic console!")
|
|
log_game("[key_name(usr)] emagged [target.name] using robotic console!")
|
|
target.emagged = 1
|
|
to_chat(target, SPAN_NOTICE("Failsafe protocols overriden. New tools available."))
|
|
|
|
// Arms the emergency self-destruct system
|
|
else if(href_list["arm"])
|
|
if(istype(user, /mob/living/silicon))
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
|
|
safety = !safety
|
|
to_chat(user, "You [safety ? "disarm" : "arm"] the emergency self destruct")
|
|
|
|
// Destroys all accessible cyborgs if safety is disabled
|
|
else if(href_list["nuke"])
|
|
if(istype(user, /mob/living/silicon))
|
|
to_chat(user, "Access denied.")
|
|
return
|
|
if(safety)
|
|
to_chat(user, "Self-destruct aborted - safety active")
|
|
return
|
|
|
|
message_admins("[key_name_admin(usr)] detonated all cyborgs!")
|
|
log_game("[key_name(usr)] detonated all cyborgs!")
|
|
|
|
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
|
if(istype(R, /mob/living/silicon/robot/drone))
|
|
continue
|
|
// Ignore antagonistic cyborgs
|
|
if(R.scrambled_codes)
|
|
continue
|
|
if(R.emagged)
|
|
continue
|
|
to_chat(R, SPAN_DANGER("Self-destruct command received."))
|
|
spawn(10)
|
|
R.self_destruct()
|
|
|
|
|
|
// Proc: get_cyborgs()
|
|
// Parameters: 1 (operator - mob which is operating the console.)
|
|
// Description: Returns NanoUI-friendly list of accessible cyborgs.
|
|
/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
|
|
var/list/robots = list()
|
|
|
|
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
|
// Ignore drones
|
|
if(istype(R, /mob/living/silicon/robot/drone))
|
|
continue
|
|
// Ignore antagonistic cyborgs
|
|
if(R.scrambled_codes)
|
|
continue
|
|
|
|
var/list/robot = list()
|
|
robot["name"] = R.name
|
|
if(R.stat)
|
|
robot["status"] = "Not Responding"
|
|
else if(R.lock_charge) // changed this from !R.canmove to R.lock_charge because of issues with lockdown and chairs
|
|
robot["status"] = "Lockdown"
|
|
else
|
|
robot["status"] = "Operational"
|
|
|
|
if(R.cell)
|
|
robot["cell"] = 1
|
|
robot["cell_capacity"] = R.cell.maxcharge
|
|
robot["cell_current"] = R.cell.charge
|
|
robot["cell_percentage"] = round(R.cell.percent())
|
|
else
|
|
robot["cell"] = 0
|
|
|
|
robot["module"] = R.module ? R.module.name : "None"
|
|
robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
|
|
robot["hackable"] = 0
|
|
robot["access"] = R.module ? R.module.all_access : FALSE
|
|
// Antag AIs know whether linked cyborgs are hacked or not.
|
|
if(operator && istype(operator, /mob/living/silicon/ai) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
|
|
robot["hacked"] = R.emagged ? 1 : 0
|
|
robot["hackable"] = R.emagged? 0 : 1
|
|
robots.Add(list(robot))
|
|
return robots
|
|
|
|
// Proc: get_cyborg_by_name()
|
|
// Parameters: 1 (name - Cyborg we are trying to find)
|
|
// Description: Helper proc for finding cyborg by name
|
|
/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
|
|
if(!name)
|
|
return
|
|
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
|
if(R.name == name)
|
|
return R
|