mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-14 08:34:16 +01:00
[TGUI] Drone Control Console (#15222)
* Drone UI V1 * Bigger button And admin log clarification * Review 1 Also commented out the drone 'rebooting' action, since it didn't work. * Spacing Seemed a bit too cluttered. * Review 2 Co-Authored-By: dearmochi <shenesis@gmail.com> Co-authored-by: dearmochi <shenesis@gmail.com>
This commit is contained in:
@@ -214,6 +214,7 @@
|
||||
#define issilicon(A) (istype((A), /mob/living/silicon))
|
||||
#define isAI(A) (istype((A), /mob/living/silicon/ai))
|
||||
#define isrobot(A) (istype((A), /mob/living/silicon/robot))
|
||||
#define isdrone(A) (istype((A), /mob/living/silicon/robot/drone))
|
||||
#define ispAI(A) (istype((A), /mob/living/silicon/pai))
|
||||
|
||||
// For the tcomms monitor
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define EMAG_TIMER 3000
|
||||
#define EMAG_TIMER 5 MINUTES
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "drone"
|
||||
real_name = "drone"
|
||||
@@ -7,21 +7,19 @@
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
bubble_icon = "machine"
|
||||
universal_speak = 0
|
||||
universal_understand = 1
|
||||
gender = NEUTER
|
||||
pass_flags = PASSTABLE
|
||||
braintype = "Robot"
|
||||
lawupdate = 0
|
||||
density = 0
|
||||
lawupdate = FALSE
|
||||
density = FALSE
|
||||
has_camera = FALSE
|
||||
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
|
||||
ventcrawler = 2
|
||||
magpulse = 1
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
magpulse = TRUE
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
pull_force = MOVE_FORCE_VERY_WEAK // Can only drag small items
|
||||
|
||||
modules_break = FALSE
|
||||
/// Cooldown for law syncs
|
||||
var/sync_cooldown = 0
|
||||
|
||||
// We need to keep track of a few module items so we don't need to do list operations
|
||||
// every time we need them. These get set in New() after the module is chosen.
|
||||
@@ -37,7 +35,7 @@
|
||||
|
||||
//Used for self-mailing.
|
||||
var/mail_destination = 0
|
||||
var/reboot_cooldown = 60 // one minute
|
||||
var/reboot_cooldown = 1 MINUTES
|
||||
var/last_reboot
|
||||
var/list/pullable_drone_items = list(
|
||||
/obj/item/pipe,
|
||||
@@ -57,8 +55,8 @@
|
||||
|
||||
remove_language("Robot Talk")
|
||||
remove_language("Galactic Common")
|
||||
add_language("Drone Talk", 1)
|
||||
add_language("Drone", 1)
|
||||
add_language("Drone Talk", TRUE)
|
||||
add_language("Drone", TRUE)
|
||||
|
||||
// Disable the microphone wire on Drones
|
||||
if(radio)
|
||||
@@ -86,13 +84,13 @@
|
||||
radio.recalculateChannels()
|
||||
|
||||
//Grab stacks.
|
||||
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
|
||||
stack_wood = locate(/obj/item/stack/sheet/wood) in src.module
|
||||
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in src.module
|
||||
stack_plastic = locate(/obj/item/stack/sheet/plastic) in src.module
|
||||
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in module
|
||||
stack_wood = locate(/obj/item/stack/sheet/wood) in module
|
||||
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in module
|
||||
stack_plastic = locate(/obj/item/stack/sheet/plastic) in module
|
||||
|
||||
//Grab decompiler.
|
||||
decompiler = locate(/obj/item/matter_decompiler) in src.module
|
||||
decompiler = locate(/obj/item/matter_decompiler) in module
|
||||
|
||||
//Some tidying-up.
|
||||
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT logo and the subscript: 'Nanotrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
|
||||
@@ -103,10 +101,10 @@
|
||||
laws = new /datum/ai_laws/drone()
|
||||
connected_ai = null
|
||||
|
||||
aiCamera = new/obj/item/camera/siliconcam/drone_camera(src)
|
||||
aiCamera = new /obj/item/camera/siliconcam/drone_camera(src)
|
||||
additional_law_channels["Drone"] = ";"
|
||||
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50)
|
||||
|
||||
//Redefining some robot procs...
|
||||
/mob/living/silicon/robot/drone/rename_character(oldname, newname)
|
||||
@@ -114,7 +112,7 @@
|
||||
return ..(newname, newname)
|
||||
|
||||
/mob/living/silicon/robot/drone/get_default_name()
|
||||
return "maintenance drone ([rand(100,999)])"
|
||||
return "maintenance drone ([rand(100, 999)])"
|
||||
|
||||
/mob/living/silicon/robot/drone/update_icons()
|
||||
overlays.Cut()
|
||||
@@ -126,7 +124,6 @@
|
||||
/mob/living/silicon/robot/drone/choose_icon()
|
||||
return
|
||||
|
||||
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
return
|
||||
|
||||
@@ -136,25 +133,23 @@
|
||||
return FALSE
|
||||
|
||||
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
|
||||
if(istype(W, /obj/item/borg/upgrade/))
|
||||
to_chat(user, "<span class='warning'>The maintenance drone chassis not compatible with \the [W].</span>")
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/borg/upgrade))
|
||||
to_chat(user, "<span class='warning'>The maintenance drone chassis is not compatible with [I].</span>")
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/crowbar))
|
||||
to_chat(user, "The machine is hermetically sealed. You can't open the case.")
|
||||
else if(istype(I, /obj/item/crowbar))
|
||||
to_chat(user, "<span class='warning'>The machine is hermetically sealed. You can't open the case.</span>")
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda))
|
||||
|
||||
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
|
||||
if(stat == DEAD)
|
||||
|
||||
if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
|
||||
// Currently not functional, so commenting out until it's fixed to avoid confusion
|
||||
/*if(!config.allow_drone_spawn || emagged || health < -35) //It's dead, Dave.
|
||||
to_chat(user, "<span class='warning'>The interface is fried, and a distressing burned smell wafts from the robot's interior. You're not rebooting this one.</span>")
|
||||
return
|
||||
|
||||
if(!allowed(W))
|
||||
if(!allowed(I))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
@@ -164,25 +159,26 @@
|
||||
to_chat(usr, "<span class='warning'>The reboot system is currently offline. Please wait another [cooldown_time] seconds.</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.</span>", "<span class='warning'>You swipe your ID card through [src], attempting to reboot it.</span>")
|
||||
user.visible_message("<span class='warning'>[user] swipes [user.p_their()] ID card through [src], attempting to reboot it.</span>",
|
||||
"<span class='warning'>You swipe your ID card through [src], attempting to reboot it.</span>")
|
||||
last_reboot = world.time / 10
|
||||
var/drones = 0
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.key && D.client)
|
||||
drones++
|
||||
if(drones < config.max_maint_drones)
|
||||
request_player()
|
||||
request_player()*/
|
||||
return
|
||||
|
||||
else
|
||||
var/confirm = alert("Using your ID on a Maintenance Drone will shut it down, are you sure you want to do this?", "Disable Drone", "Yes", "No")
|
||||
if(confirm == ("Yes") && (user in range(3, src)))
|
||||
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>", "<span class='warning'>You swipe your ID card through \the [src], attempting to shut it down.</span>")
|
||||
user.visible_message("<span class='warning'>[user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>",
|
||||
"<span class='warning'>You swipe your ID card through [src], attempting to shut it down.</span>")
|
||||
|
||||
if(emagged)
|
||||
return
|
||||
|
||||
if(allowed(W))
|
||||
if(allowed(I))
|
||||
shut_down()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
@@ -191,7 +187,7 @@
|
||||
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/drone/emag_act(user as mob)
|
||||
/mob/living/silicon/robot/drone/emag_act(mob/user)
|
||||
if(!client || stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>There's not much point subverting this heap of junk.</span>")
|
||||
return
|
||||
@@ -210,7 +206,7 @@
|
||||
if(jobban_isbanned(src, ROLE_SYNDICATE))
|
||||
SSticker.mode.replace_jobbanned_player(src, ROLE_SYNDICATE)
|
||||
|
||||
to_chat(src, "<span class='warning'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script. You sense you have five minutes before the drone server detects this and automatically shuts you down.</span>")
|
||||
to_chat(src, "<span class='warning'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script. You sense you have <b>five minutes</b> before the drone server detects this and automatically shuts you down.</span>")
|
||||
|
||||
message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
|
||||
@@ -218,13 +214,12 @@
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [H.name]([H.key]) emagged [name]([key])")
|
||||
addtimer(CALLBACK(src, .proc/shut_down, TRUE), EMAG_TIMER)
|
||||
|
||||
emagged = 1
|
||||
density = 1
|
||||
emagged = TRUE
|
||||
density = TRUE
|
||||
pass_flags = 0
|
||||
icon_state = "repairbot-emagged"
|
||||
holder_type = /obj/item/holder/drone/emagged
|
||||
update_icons()
|
||||
lawupdate = 0
|
||||
connected_ai = null
|
||||
clear_supplied_laws()
|
||||
clear_inherent_laws()
|
||||
@@ -234,7 +229,6 @@
|
||||
to_chat(src, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(src)
|
||||
to_chat(src, "<span class='boldwarning'>ALERT: [H.real_name] is your new master. Obey your new laws and [H.real_name]'s commands.</span>")
|
||||
return
|
||||
|
||||
//DRONE LIFE/DEATH
|
||||
|
||||
@@ -262,7 +256,7 @@
|
||||
full_law_reset()
|
||||
show_laws()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/shut_down(force=FALSE)
|
||||
/mob/living/silicon/robot/drone/proc/shut_down(force = FALSE)
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
@@ -285,32 +279,32 @@
|
||||
for(var/mob/dead/observer/O in GLOB.player_list)
|
||||
if(cannotPossess(O))
|
||||
continue
|
||||
if(jobban_isbanned(O,"nonhumandept") || jobban_isbanned(O,"Drone"))
|
||||
if(jobban_isbanned(O, "nonhumandept") || jobban_isbanned(O, "Drone"))
|
||||
continue
|
||||
if(O.client)
|
||||
if(ROLE_PAI in O.client.prefs.be_special)
|
||||
question(O.client,O)
|
||||
question(O.client, O)
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/question(var/client/C,var/mob/M)
|
||||
/mob/living/silicon/robot/drone/proc/question(client/C, mob/M)
|
||||
spawn(0)
|
||||
if(!C || !M || jobban_isbanned(M,"nonhumandept") || jobban_isbanned(M,"Drone")) return
|
||||
if(!C || !M || jobban_isbanned(M, "nonhumandept") || jobban_isbanned(M, "Drone"))
|
||||
return
|
||||
var/response = alert(C, "Someone is attempting to reboot a maintenance drone. Would you like to play as one?", "Maintenance drone reboot", "Yes", "No")
|
||||
if(!C || ckey)
|
||||
return
|
||||
if(response == "Yes")
|
||||
transfer_personality(C)
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player)
|
||||
/mob/living/silicon/robot/drone/proc/transfer_personality(client/player)
|
||||
if(!player)
|
||||
return
|
||||
|
||||
if(!player) return
|
||||
|
||||
if(player.mob && player.mob.mind)
|
||||
if(player.mob?.mind)
|
||||
player.mob.mind.transfer_to(src)
|
||||
player.mob.mind.assigned_role = "Drone"
|
||||
else
|
||||
ckey = player.ckey
|
||||
|
||||
lawupdate = 0
|
||||
to_chat(src, "<b>Systems rebooted</b>. Loading base pattern maintenance protocol... <b>loaded</b>.")
|
||||
full_law_reset()
|
||||
to_chat(src, "<br><b>You are a maintenance drone, a tiny-brained robotic repair machine</b>.")
|
||||
@@ -358,21 +352,21 @@
|
||||
to_chat(src, "<span class='warning'>You are too small to pull that.</span>")
|
||||
|
||||
/mob/living/silicon/robot/drone/add_robot_verbs()
|
||||
src.verbs |= silicon_subsystems
|
||||
verbs |= silicon_subsystems
|
||||
|
||||
/mob/living/silicon/robot/drone/remove_robot_verbs()
|
||||
src.verbs -= silicon_subsystems
|
||||
verbs -= silicon_subsystems
|
||||
|
||||
/mob/living/silicon/robot/drone/update_canmove(delay_action_updates = 0)
|
||||
/mob/living/silicon/robot/drone/update_canmove(delay_action_updates = FALSE)
|
||||
. = ..()
|
||||
density = emagged //this is reset every canmove update otherwise
|
||||
|
||||
/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
|
||||
/mob/living/silicon/robot/drone/flash_eyes(intensity = 1, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE)
|
||||
if(affect_silicon)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/drone/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(!client && istype(user, /mob/living/silicon/robot/drone))
|
||||
if(!client && isdrone(user))
|
||||
to_chat(user, "<span class='warning'>You begin decompiling the other drone.</span>")
|
||||
if(!do_after(user, 5 SECONDS, target = loc))
|
||||
to_chat(user, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
|
||||
@@ -380,7 +374,7 @@
|
||||
if(QDELETED(src) || QDELETED(user))
|
||||
return ..()
|
||||
to_chat(user, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
|
||||
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
new /obj/effect/decal/cleanable/blood/oil(get_turf(src))
|
||||
C.stored_comms["metal"] += 15
|
||||
C.stored_comms["glass"] += 15
|
||||
C.stored_comms["wood"] += 5
|
||||
|
||||
@@ -6,16 +6,18 @@
|
||||
req_access = list(ACCESS_ENGINE_EQUIP)
|
||||
circuit = /obj/item/circuitboard/drone_control
|
||||
|
||||
//Used when pinging drones.
|
||||
var/drone_call_area = "Engineering"
|
||||
//Used to enable or disable drone fabrication.
|
||||
/// The linked fabricator
|
||||
var/obj/machinery/drone_fabricator/dronefab
|
||||
/// Used when pinging drones
|
||||
var/drone_call_area = "Engineering"
|
||||
/// Cooldown for area pings
|
||||
var/ping_cooldown = 0
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
/obj/machinery/computer/drone_control/Initialize(mapload)
|
||||
. = ..()
|
||||
find_fab()
|
||||
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_hand(var/mob/user as mob)
|
||||
/obj/machinery/computer/drone_control/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -23,105 +25,112 @@
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/attack_ghost(mob/user as mob)
|
||||
interact(user)
|
||||
/obj/machinery/computer/drone_control/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/drone_control/interact(mob/user)
|
||||
// tgui\packages\tgui\interfaces\DroneConsole.js
|
||||
/obj/machinery/computer/drone_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "DroneConsole", "Drone Control Console", 420, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
dat += "<B>Maintenance Units</B><BR>"
|
||||
/obj/machinery/computer/drone_control/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["drone_fab"] = FALSE
|
||||
data["fab_power"] = null
|
||||
data["drone_prod"] = null
|
||||
data["drone_progress"] = null
|
||||
if(dronefab)
|
||||
data["drone_fab"] = TRUE
|
||||
data["fab_power"] = dronefab.stat & NOPOWER ? FALSE : TRUE
|
||||
data["drone_prod"] = dronefab.produce_drones
|
||||
data["drone_progress"] = dronefab.drone_progress
|
||||
data["selected_area"] = drone_call_area
|
||||
data["ping_cd"] = ping_cooldown > world.time ? TRUE : FALSE
|
||||
|
||||
data["drones"] = list()
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE" : "<font color='green'>ACTIVE"]</FONT>)"
|
||||
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
|
||||
dat += "<BR>Currently located in: [get_area(D)]."
|
||||
dat += "<BR><A href='?src=[UID()];resync=\ref[D]'>Resync</A> | <A href='?src=[UID()];shutdown=\ref[D]'>Shutdown</A></font>"
|
||||
var/area/A = get_area(D)
|
||||
var/turf/T = get_turf(D)
|
||||
var/list/drone_data = list(
|
||||
name = D.real_name,
|
||||
uid = D.UID(),
|
||||
stat = D.stat,
|
||||
client = D.client ? TRUE : FALSE,
|
||||
health = round(D.health / D.maxHealth, 0.1),
|
||||
charge = round(D.cell.charge / D.cell.maxcharge, 0.1),
|
||||
location = "[A] ([T.x], [T.y])",
|
||||
sync_cd = D.sync_cooldown > world.time ? TRUE : FALSE
|
||||
)
|
||||
data["drones"] += list(drone_data)
|
||||
return data
|
||||
|
||||
dat += "<BR><BR><B>Request drone presence in area:</B> <A href='?src=[UID()];setarea=1'>[drone_call_area]</A> (<A href='?src=[UID()];ping=1'>Send ping</A>)"
|
||||
/obj/machinery/computer/drone_control/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["area_list"] = GLOB.TAGGERLOCATIONS
|
||||
return data
|
||||
|
||||
dat += "<BR><BR><B>Drone fabricator</B>: "
|
||||
dat += "[dronefab ? "<A href='?src=[UID()];toggle_fab=1'>[(dronefab.produce_drones && !(dronefab.stat & NOPOWER)) ? "ACTIVE" : "INACTIVE"]</A>" : "<font color='red'><b>FABRICATOR NOT DETECTED.</b></font> (<A href='?src=[UID()];search_fab=1'>search</a>)"]"
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
onclose(user, "computer")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/drone_control/Topic(href, href_list)
|
||||
/obj/machinery/computer/drone_control/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
|
||||
if(!allowed(usr) && !usr.can_admin_interact())
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
switch(action)
|
||||
if("find_fab")
|
||||
find_fab(usr)
|
||||
|
||||
if("toggle_fab")
|
||||
if(QDELETED(dronefab))
|
||||
dronefab = null
|
||||
return
|
||||
|
||||
dronefab.produce_drones = !dronefab.produce_drones
|
||||
var/toggle = dronefab.produce_drones ? "enable" : "disable"
|
||||
to_chat(usr, "<span class='notice'>You [toggle] drone production in the nearby fabricator.</span>")
|
||||
message_admins("[key_name_admin(usr)] [toggle]d maintenance drone production from the control console.")
|
||||
log_game("[key_name(usr)] [toggle]d maintenance drone production from the control console.")
|
||||
|
||||
if("set_area")
|
||||
drone_call_area = params["area"]
|
||||
|
||||
if("ping")
|
||||
ping_cooldown = world.time + 1 MINUTES // One minute cooldown to prevent chat spam
|
||||
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.client && D.stat == CONSCIOUS)
|
||||
to_chat(D, "<span class='boldnotice'>-- Maintenance drone presence requested in: [drone_call_area].</span>")
|
||||
|
||||
if("resync")
|
||||
var/mob/living/silicon/robot/drone/D = locateUID(params["uid"])
|
||||
if(D)
|
||||
D.sync_cooldown = world.time + 1 MINUTES // One minute cooldown to prevent chat spam
|
||||
to_chat(usr, "<span class='notice'>You issue a law synchronization directive for the drone.</span>")
|
||||
D.law_resync()
|
||||
|
||||
if("shutdown")
|
||||
var/mob/living/silicon/robot/drone/D = locateUID(params["uid"])
|
||||
if(D)
|
||||
to_chat(usr, "<span class='warning'>You issue a kill command for the unfortunate drone.</span>")
|
||||
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
|
||||
log_game("[key_name(usr)] issued kill order for [key_name(D)] from control console.")
|
||||
D.shut_down()
|
||||
|
||||
/obj/machinery/computer/drone_control/proc/find_fab(mob/user)
|
||||
if(dronefab)
|
||||
return
|
||||
|
||||
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
for(var/obj/machinery/drone_fabricator/fab in get_area(src))
|
||||
|
||||
if(href_list["setarea"])
|
||||
if(fab.stat & NOPOWER)
|
||||
continue
|
||||
|
||||
//Probably should consider using another list, but this one will do.
|
||||
var/t_area = input("Select the area to ping.", "Set Target Area", null) as null|anything in GLOB.TAGGERLOCATIONS
|
||||
dronefab = fab
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Drone fabricator located.</span>")
|
||||
return
|
||||
|
||||
if(!t_area || GLOB.TAGGERLOCATIONS[t_area])
|
||||
return
|
||||
|
||||
drone_call_area = t_area
|
||||
to_chat(usr, "<span class='notice'>You set the area selector to [drone_call_area].</span>")
|
||||
|
||||
else if(href_list["ping"])
|
||||
|
||||
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
|
||||
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
|
||||
if(D.client && D.stat == 0)
|
||||
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
|
||||
|
||||
else if(href_list["resync"])
|
||||
|
||||
var/mob/living/silicon/robot/drone/D = locate(href_list["resync"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='warning'>You issue a law synchronization directive for the drone.</span>")
|
||||
D.law_resync()
|
||||
|
||||
else if(href_list["shutdown"])
|
||||
|
||||
var/mob/living/silicon/robot/drone/D = locate(href_list["shutdown"])
|
||||
|
||||
if(D.stat != 2)
|
||||
to_chat(usr, "<span class='warning'>You issue a kill command for the unfortunate drone.</span>")
|
||||
message_admins("[key_name_admin(usr)] issued kill order for drone [key_name_admin(D)] from control console.")
|
||||
log_game("[key_name(usr)] issued kill order for [key_name(src)] from control console.")
|
||||
D.shut_down()
|
||||
|
||||
else if(href_list["search_fab"])
|
||||
if(dronefab)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/drone_fabricator/fab in get_area(src))
|
||||
|
||||
if(fab.stat & NOPOWER)
|
||||
continue
|
||||
|
||||
dronefab = fab
|
||||
to_chat(usr, "<span class='notice'>Drone fabricator located.</span>")
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
|
||||
else if(href_list["toggle_fab"])
|
||||
|
||||
if(!dronefab)
|
||||
return
|
||||
|
||||
if(get_dist(src,dronefab) > 3)
|
||||
dronefab = null
|
||||
to_chat(usr, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
return
|
||||
|
||||
dronefab.produce_drones = !dronefab.produce_drones
|
||||
to_chat(usr, "<span class='notice'>You [dronefab.produce_drones ? "enable" : "disable"] drone production in the nearby fabricator.</span>")
|
||||
|
||||
src.updateUsrDialog()
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>Unable to locate drone fabricator.</span>")
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
/obj/machinery/drone_fabricator
|
||||
name = "drone fabricator"
|
||||
desc = "A large automated factory for producing maintenance drones."
|
||||
icon = 'icons/obj/machines/drone_fab.dmi'
|
||||
icon_state = "drone_fab_idle"
|
||||
|
||||
density = 1
|
||||
anchored = 1
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 5000
|
||||
|
||||
var/drone_progress = 0
|
||||
var/produce_drones = 1
|
||||
var/time_last_drone = 500
|
||||
|
||||
icon = 'icons/obj/machines/drone_fab.dmi'
|
||||
icon_state = "drone_fab_idle"
|
||||
|
||||
/obj/machinery/drone_fabricator/New()
|
||||
..()
|
||||
var/produce_drones = TRUE
|
||||
var/drone_progress = 100
|
||||
var/time_last_drone = 0
|
||||
|
||||
/obj/machinery/drone_fabricator/power_change()
|
||||
if(powered())
|
||||
@@ -31,7 +27,8 @@
|
||||
return
|
||||
|
||||
if(stat & NOPOWER || !produce_drones)
|
||||
if(icon_state != "drone_fab_nopower") icon_state = "drone_fab_nopower"
|
||||
if(icon_state != "drone_fab_nopower")
|
||||
icon_state = "drone_fab_nopower"
|
||||
return
|
||||
|
||||
if(drone_progress >= 100)
|
||||
@@ -40,14 +37,14 @@
|
||||
|
||||
icon_state = "drone_fab_active"
|
||||
var/elapsed = world.time - time_last_drone
|
||||
drone_progress = round((elapsed/config.drone_build_time)*100)
|
||||
drone_progress = round((elapsed / config.drone_build_time) * 100)
|
||||
|
||||
if(drone_progress >= 100)
|
||||
visible_message("\The [src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
visible_message("[src] voices a strident beep, indicating a drone chassis is prepared.")
|
||||
|
||||
/obj/machinery/drone_fabricator/examine(mob/user)
|
||||
. = ..()
|
||||
if(produce_drones && drone_progress >= 100 && istype(user,/mob/dead) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
if(produce_drones && drone_progress >= 100 && isobserver(user) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
|
||||
. += "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>"
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/count_drones()
|
||||
@@ -57,18 +54,17 @@
|
||||
drones++
|
||||
return drones
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
|
||||
|
||||
/obj/machinery/drone_fabricator/proc/create_drone(client/player)
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
return
|
||||
|
||||
if(!player || !istype(player.mob,/mob/dead))
|
||||
if(!player || !isobserver(player.mob))
|
||||
return
|
||||
|
||||
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
visible_message("[src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
flick("h_lathe_leave",src)
|
||||
|
||||
time_last_drone = world.time
|
||||
@@ -88,41 +84,40 @@
|
||||
to_chat(src, "<span class='warning'>That verb is not currently permitted.</span>")
|
||||
return
|
||||
|
||||
if(!src.stat)
|
||||
if(stat != DEAD)
|
||||
return
|
||||
|
||||
if(usr != src)
|
||||
return 0 //something is terribly wrong
|
||||
return FALSE //something is terribly wrong
|
||||
|
||||
if(jobban_isbanned(src,"nonhumandept") || jobban_isbanned(src,"Drone"))
|
||||
to_chat(usr, "<span class='warning'>You are banned from playing drones and cannot spawn as a drone.</span>")
|
||||
if(jobban_isbanned(src, "nonhumandept") || jobban_isbanned(src, "Drone"))
|
||||
to_chat(usr, "<span class='warning'>You are banned from playing drones, and cannot spawn as one.</span>")
|
||||
return
|
||||
|
||||
if(!SSticker || SSticker.current_state < 3)
|
||||
if(!SSticker || SSticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='warning'>You can't join as a drone before the game starts!</span>")
|
||||
return
|
||||
|
||||
var/drone_age = 14 // 14 days to play as a drone
|
||||
var/player_age_check = check_client_age(usr.client, drone_age)
|
||||
var/player_age_check = check_client_age(usr.client, 14) // 14 days to play as a drone
|
||||
if(player_age_check && config.use_age_restriction_for_antags)
|
||||
to_chat(usr, "<span class='warning'>This role is not yet available to you. You need to wait another [player_age_check] days.</span>")
|
||||
return
|
||||
|
||||
var/pt_req = role_available_in_playtime(client, ROLE_DRONE)
|
||||
var/pt_req = role_available_in_playtime(client, "Drone")
|
||||
if(pt_req)
|
||||
var/pt_req_string = get_exp_format(pt_req)
|
||||
to_chat(usr, "<span class='warning'>This role is not yet available to you. Play another [pt_req_string] to unlock it.</span>")
|
||||
return
|
||||
|
||||
var/deathtime = world.time - src.timeofdeath
|
||||
var/joinedasobserver = 0
|
||||
if(istype(src,/mob/dead/observer))
|
||||
var/deathtime = world.time - timeofdeath
|
||||
var/joinedasobserver = FALSE
|
||||
if(isobserver(src))
|
||||
var/mob/dead/observer/G = src
|
||||
if(cannotPossess(G))
|
||||
to_chat(usr, "<span class='warning'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
|
||||
return
|
||||
if(G.started_as_observer == 1)
|
||||
joinedasobserver = 1
|
||||
if(G.started_as_observer == TRUE)
|
||||
joinedasobserver = TRUE
|
||||
|
||||
var/deathtimeminutes = round(deathtime / 600)
|
||||
var/pluralcheck = "minute"
|
||||
@@ -132,7 +127,7 @@
|
||||
pluralcheck = " [deathtimeminutes] minute and"
|
||||
else if(deathtimeminutes > 1)
|
||||
pluralcheck = " [deathtimeminutes] minutes and"
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10, 1)
|
||||
|
||||
if(deathtime < 6000 && joinedasobserver == 0)
|
||||
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
|
||||
@@ -151,7 +146,7 @@
|
||||
return
|
||||
|
||||
if(DF.drone_progress >= 100)
|
||||
DF.create_drone(src.client)
|
||||
DF.create_drone(client)
|
||||
return
|
||||
|
||||
to_chat(src, "<span class='warning'>There are no available drone spawn points, sorry.</span>")
|
||||
|
||||
@@ -21,6 +21,3 @@ GLOBAL_DATUM_INIT(notcontained_state, /datum/ui_state/notcontained_state, new)
|
||||
|
||||
/mob/living/silicon/notcontained_can_use_topic(src_object)
|
||||
return default_can_use_topic(src_object) // Silicons use default bevhavior.
|
||||
|
||||
/mob/living/simple_animal/drone/notcontained_can_use_topic(src_object)
|
||||
return default_can_use_topic(src_object) // Drones use default bevhavior.
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
// code\modules\mob\living\silicon\robot\drone\drone_console.dm
|
||||
import { toTitleCase } from 'common/string';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Divider, Dropdown, Flex, LabeledList, NoticeBox, ProgressBar, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const DroneConsole = (props, context) => {
|
||||
return (
|
||||
<Window>
|
||||
<Window.Content scrollable>
|
||||
<Fabricator />
|
||||
<DroneList />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const Fabricator = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
drone_fab,
|
||||
fab_power,
|
||||
drone_prod,
|
||||
drone_progress,
|
||||
} = data;
|
||||
|
||||
let FabDetected = () => {
|
||||
if (drone_fab) {
|
||||
return (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="External Power">
|
||||
<Box color={fab_power ? "good" : "bad"}>
|
||||
[ {fab_power ? "Online" : "Offline"} ]
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Drone Production">
|
||||
<ProgressBar
|
||||
value={drone_progress / 100}
|
||||
ranges={{
|
||||
good: [0.7, Infinity],
|
||||
average: [0.4, 0.7],
|
||||
bad: [-Infinity, 0.4],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<NoticeBox textAlign="center" danger={1}>
|
||||
<Flex inline={1} direction="column">
|
||||
<Flex.Item>
|
||||
FABRICATOR NOT DETECTED.
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
icon="search"
|
||||
content="Search"
|
||||
onClick={() => act('find_fab')} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</NoticeBox>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Drone Fabricator"
|
||||
buttons={
|
||||
<Button
|
||||
icon="power-off"
|
||||
content={drone_prod ? "Online" : "Offline"}
|
||||
color={drone_prod ? "green" : "red"}
|
||||
onClick={() => act('toggle_fab')} />
|
||||
}>
|
||||
{FabDetected()}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const DroneList = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
drones,
|
||||
area_list,
|
||||
selected_area,
|
||||
ping_cd,
|
||||
} = data;
|
||||
|
||||
let status = (stat, client) => {
|
||||
let box_color;
|
||||
let text;
|
||||
if (stat === 2) { // Dead
|
||||
box_color='bad';
|
||||
text="Disabled";
|
||||
} else if ((stat === 1) || !client) { // Unconscious or SSD
|
||||
box_color='average';
|
||||
text="Inactive";
|
||||
} else { // Alive
|
||||
box_color='good';
|
||||
text="Active";
|
||||
}
|
||||
return (
|
||||
<Box color={box_color}>
|
||||
{text}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const Divide = () => {
|
||||
if (drones.length) {
|
||||
return (
|
||||
<Box py={0.2}>
|
||||
<Divider />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Section title="Maintenance Units">
|
||||
<Flex>
|
||||
<Flex.Item>
|
||||
Request Drone presence in area:
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Dropdown
|
||||
options={area_list}
|
||||
selected={selected_area}
|
||||
width="125px"
|
||||
onSelected={value => act('set_area', {
|
||||
area: value,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
<Button
|
||||
content="Send Ping"
|
||||
icon="broadcast-tower"
|
||||
disabled={ping_cd || !drones.length}
|
||||
title={drones.length ? null : "No active drones!"}
|
||||
fluid={1}
|
||||
textAlign="center"
|
||||
py={0.4}
|
||||
mt={0.6}
|
||||
onClick={() => act('ping')} />
|
||||
|
||||
<Divide />
|
||||
|
||||
{drones.map(drone => (
|
||||
<Section key={drone.name}
|
||||
title={toTitleCase(drone.name)}
|
||||
buttons={(
|
||||
<Flex>
|
||||
<Button
|
||||
icon="sync"
|
||||
content="Resync"
|
||||
disabled={drone.stat === 2 || drone.sync_cd}
|
||||
onClick={() => act('resync', {
|
||||
uid: drone.uid,
|
||||
})} />
|
||||
<Button.Confirm
|
||||
icon="power-off"
|
||||
content="Shutdown"
|
||||
disabled={drone.stat === 2}
|
||||
color="bad"
|
||||
onClick={() => act('shutdown', {
|
||||
uid: drone.uid,
|
||||
})} />
|
||||
</Flex>
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Status">
|
||||
{status(drone.stat, drone.client)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Integrity">
|
||||
<ProgressBar
|
||||
value={drone.health}
|
||||
ranges={{
|
||||
good: [0.7, Infinity],
|
||||
average: [0.4, 0.7],
|
||||
bad: [-Infinity, 0.4],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Charge">
|
||||
<ProgressBar
|
||||
value={drone.charge}
|
||||
ranges={{
|
||||
good: [0.7, Infinity],
|
||||
average: [0.4, 0.7],
|
||||
bad: [-Infinity, 0.4],
|
||||
}} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Location">
|
||||
{drone.location}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
))}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user