mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2025-12-10 20:17:54 +00:00
I'VE FUCKING HAD IT
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#define show_browser(target, browser_content, browser_name) target << browse(browser_content, browser_name)
|
#define show_browser(target, browser_content, browser_name) target << browse(browser_content, browser_name)
|
||||||
|
|
||||||
#define CanInteract(user, state) (CanUseTopic(user, state) == STATUS_INTERACTIVE)
|
#define CanInteract(user, state) (CanUseTopic(user, state) == UI_INTERACTIVE)
|
||||||
|
|
||||||
|
|
||||||
#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
|
#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ var/datum/uplink/uplink = new()
|
|||||||
if(!can_buy(U))
|
if(!can_buy(U))
|
||||||
return
|
return
|
||||||
|
|
||||||
if(U.CanUseTopic(user, inventory_state) != STATUS_INTERACTIVE)
|
if(U.CanUseTopic(user, inventory_state) != UI_INTERACTIVE)
|
||||||
return
|
return
|
||||||
|
|
||||||
var/cost = cost(U.uses, U)
|
var/cost = cost(U.uses, U)
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
S.inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"]))
|
S.inject_chemical(usr, href_list["chemical"], text2num(href_list["amount"]))
|
||||||
if(href_list["change_stasis"])
|
if(href_list["change_stasis"])
|
||||||
var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in S.stasis_choices
|
var/new_stasis = input("Levels deeper than 50% stasis level will render the patient unconscious.","Stasis Level") as null|anything in S.stasis_choices
|
||||||
if(new_stasis && CanUseTopic(usr, default_state) == STATUS_INTERACTIVE)
|
if(new_stasis && CanUseTopic(usr, default_state) == UI_INTERACTIVE)
|
||||||
S.stasis_level = S.stasis_choices[new_stasis]
|
S.stasis_level = S.stasis_choices[new_stasis]
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ Class Procs:
|
|||||||
|
|
||||||
/obj/machinery/CanUseTopic(var/mob/user)
|
/obj/machinery/CanUseTopic(var/mob/user)
|
||||||
if(!interact_offline && (stat & (NOPOWER | BROKEN)))
|
if(!interact_offline && (stat & (NOPOWER | BROKEN)))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/CouldUseTopic(var/mob/user)
|
/obj/machinery/CouldUseTopic(var/mob/user)
|
||||||
|
|||||||
@@ -606,15 +606,15 @@
|
|||||||
/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
|
/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
|
||||||
if(aidisabled && isAI(user))
|
if(aidisabled && isAI(user))
|
||||||
to_chat(user, "<span class='warning'>AI control for \the [src] interface has been disabled.</span>")
|
to_chat(user, "<span class='warning'>AI control for \the [src] interface has been disabled.</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
. = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE
|
. = shorted ? UI_DISABLED : UI_INTERACTIVE
|
||||||
|
|
||||||
if(. == STATUS_INTERACTIVE)
|
if(. == UI_INTERACTIVE)
|
||||||
var/extra_href = state.href_list(usr)
|
var/extra_href = state.href_list(usr)
|
||||||
// Prevent remote users from altering RCON settings unless they already have access
|
// Prevent remote users from altering RCON settings unless they already have access
|
||||||
if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"])
|
if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"])
|
||||||
. = STATUS_UPDATE
|
. = UI_UPDATE
|
||||||
|
|
||||||
return min(..(), .)
|
return min(..(), .)
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
QDEL_NULL(camera)
|
QDEL_NULL(camera)
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/computer/security/tgui_interact(mob/user, datum/tgui/ui = null)
|
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui = null)
|
||||||
camera.tgui_interact(user, ui)
|
camera.tgui_interact(user, ui)
|
||||||
|
|
||||||
/obj/machinery/computer/security/attack_hand(mob/user)
|
/obj/machinery/computer/security/attack_hand(mob/user)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
return
|
return
|
||||||
tgui_interact(user)
|
tgui_interact(user)
|
||||||
|
|
||||||
/obj/machinery/computer/crew/tgui_interact(mob/user, datum/tgui/ui = null)
|
/obj/machinery/computer/crew/ui_interact(mob/user, datum/tgui/ui = null)
|
||||||
crew_monitor.tgui_interact(user, ui)
|
crew_monitor.tgui_interact(user, ui)
|
||||||
|
|
||||||
/obj/machinery/computer/crew/interact(mob/user)
|
/obj/machinery/computer/crew/interact(mob/user)
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ About the new airlock wires panel:
|
|||||||
/obj/machinery/door/airlock/CanUseTopic(var/mob/user)
|
/obj/machinery/door/airlock/CanUseTopic(var/mob/user)
|
||||||
if(operating < 0) //emagged
|
if(operating < 0) //emagged
|
||||||
to_chat(user, "<span class='warning'>Unable to interface: Internal error.</span>")
|
to_chat(user, "<span class='warning'>Unable to interface: Internal error.</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
if(issilicon(user) && !src.canAIControl())
|
if(issilicon(user) && !src.canAIControl())
|
||||||
if(src.canAIHack(user))
|
if(src.canAIHack(user))
|
||||||
src.hack(user)
|
src.hack(user)
|
||||||
@@ -931,7 +931,7 @@ About the new airlock wires panel:
|
|||||||
to_chat(user, "<span class='warning'>Unable to interface: Connection timed out.</span>")
|
to_chat(user, "<span class='warning'>Unable to interface: Connection timed out.</span>")
|
||||||
else
|
else
|
||||||
to_chat(user, "<span class='warning'>Unable to interface: Connection refused.</span>")
|
to_chat(user, "<span class='warning'>Unable to interface: Connection refused.</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user)
|
/obj/machinery/embedded_controller/radio/airlock/CanUseTopic(var/mob/user)
|
||||||
if(!allowed(user))
|
if(!allowed(user))
|
||||||
return min(STATUS_UPDATE, ..())
|
return min(UI_UPDATE, ..())
|
||||||
else
|
else
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -458,14 +458,14 @@
|
|||||||
/obj/machinery/porta_turret/CanUseTopic(var/mob/user)
|
/obj/machinery/porta_turret/CanUseTopic(var/mob/user)
|
||||||
if(HasController())
|
if(HasController())
|
||||||
to_chat(user, "<span class='notice'>Turrets can only be controlled using the assigned turret controller.</span>")
|
to_chat(user, "<span class='notice'>Turrets can only be controlled using the assigned turret controller.</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
if(isLocked(user))
|
if(isLocked(user))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
if(!anchored)
|
if(!anchored)
|
||||||
to_chat(user, "<span class='notice'>\The [src] has to be secured first!</span>")
|
to_chat(user, "<span class='notice'>\The [src] has to be secured first!</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
/obj/machinery/turretid/CanUseTopic(mob/user)
|
/obj/machinery/turretid/CanUseTopic(mob/user)
|
||||||
if(isLocked(user))
|
if(isLocked(user))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -422,16 +422,16 @@
|
|||||||
|
|
||||||
/obj/mecha/contents_nano_distance(var/src_object, var/mob/living/user)
|
/obj/mecha/contents_nano_distance(var/src_object, var/mob/living/user)
|
||||||
. = user.shared_living_nano_distance(src_object) //allow them to interact with anything they can interact with normally.
|
. = user.shared_living_nano_distance(src_object) //allow them to interact with anything they can interact with normally.
|
||||||
if(. != STATUS_INTERACTIVE)
|
if(. != UI_INTERACTIVE)
|
||||||
//Allow interaction with the mecha or anything that is part of the mecha
|
//Allow interaction with the mecha or anything that is part of the mecha
|
||||||
if(src_object == src || (src_object in src))
|
if(src_object == src || (src_object in src))
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
if(src.Adjacent(src_object))
|
if(src.Adjacent(src_object))
|
||||||
src.occupant_message("<span class='notice'>Interfacing with [src_object]...</span>")
|
src.occupant_message("<span class='notice'>Interfacing with [src_object]...</span>")
|
||||||
src.log_message("Interfaced with [src_object].")
|
src.log_message("Interfaced with [src_object].")
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
if(src_object in view(2, src))
|
if(src_object in view(2, src))
|
||||||
return STATUS_UPDATE //if they're close enough, allow the occupant to see the screen through the viewport or whatever.
|
return UI_UPDATE //if they're close enough, allow the occupant to see the screen through the viewport or whatever.
|
||||||
|
|
||||||
/obj/mecha/proc/melee_action(atom/target)
|
/obj/mecha/proc/melee_action(atom/target)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
var/user = usr
|
var/user = usr
|
||||||
if (href_list["wipe"])
|
if (href_list["wipe"])
|
||||||
var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "No", "Yes")
|
var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "No", "Yes")
|
||||||
if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE))
|
if(confirm == "Yes" && (CanUseTopic(user, state) == UI_INTERACTIVE))
|
||||||
add_attack_logs(user,carded_ai,"Purged from AI Card")
|
add_attack_logs(user,carded_ai,"Purged from AI Card")
|
||||||
flush = 1
|
flush = 1
|
||||||
carded_ai.suiciding = 1
|
carded_ai.suiciding = 1
|
||||||
|
|||||||
@@ -96,5 +96,5 @@
|
|||||||
|
|
||||||
/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
|
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
|
|||||||
|
|
||||||
/obj/item/radio/CanUseTopic()
|
/obj/item/radio/CanUseTopic()
|
||||||
if(!on)
|
if(!on)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/item/radio/Topic(href, href_list)
|
/obj/item/radio/Topic(href, href_list)
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
|
|
||||||
/obj/item/uplink/hidden/CanUseTopic()
|
/obj/item/uplink/hidden/CanUseTopic()
|
||||||
if(!active)
|
if(!active)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
// The purchasing code.
|
// The purchasing code.
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
/obj/item/card/id/syndicate/CanUseTopic(mob/user)
|
/obj/item/card/id/syndicate/CanUseTopic(mob/user)
|
||||||
if(user != registered_user)
|
if(user != registered_user)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/item/card/id/syndicate/Topic(href, href_list, var/datum/topic_state/state)
|
/obj/item/card/id/syndicate/Topic(href, href_list, var/datum/topic_state/state)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
|
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
|
||||||
// Instead any such checks are made in CanUseTopic()
|
// Instead any such checks are made in CanUseTopic()
|
||||||
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
|
if(CanUseTopic(usr, state, href_list) == UI_INTERACTIVE)
|
||||||
CouldUseTopic(usr)
|
CouldUseTopic(usr)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
if(user.CanUseObjTopic(src))
|
if(user.CanUseObjTopic(src))
|
||||||
return ..()
|
return ..()
|
||||||
to_chat(user, "<span class='danger'>[icon2html(thing = src, target = user)] Access Denied!</span>")
|
to_chat(user, "<span class='danger'>[icon2html(thing = src, target = user)] Access Denied!</span>")
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/mob/living/silicon/CanUseObjTopic(var/obj/O)
|
/mob/living/silicon/CanUseObjTopic(var/obj/O)
|
||||||
var/id = src.GetIdCard()
|
var/id = src.GetIdCard()
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
/obj/structure/undies_wardrobe/CanUseTopic(var/user)
|
/obj/structure/undies_wardrobe/CanUseTopic(var/user)
|
||||||
if(!human_who_can_use_underwear(user))
|
if(!human_who_can_use_underwear(user))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
return TRUE
|
return TRUE
|
||||||
if(!user)
|
if(!user)
|
||||||
return FALSE
|
return FALSE
|
||||||
return (usr.default_can_use_topic(src) < STATUS_UPDATE) //can play with TK and while resting because fun.
|
return (usr.default_can_use_topic(src) < UI_UPDATE) //can play with TK and while resting because fun.
|
||||||
|
|
||||||
/// CITRP EDIT UNTIL INTERACTION REFACTOR PORT!
|
/// CITRP EDIT UNTIL INTERACTION REFACTOR PORT!
|
||||||
/obj/structure/musician/attack_hand(mob/user)
|
/obj/structure/musician/attack_hand(mob/user)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
updateDialog(usr) // make sure updates when complete
|
updateDialog(usr) // make sure updates when complete
|
||||||
|
|
||||||
/datum/song/Topic(href, href_list)
|
/datum/song/Topic(href, href_list)
|
||||||
if(usr.default_can_use_topic(parent) < STATUS_UPDATE)
|
if(usr.default_can_use_topic(parent) < UI_UPDATE)
|
||||||
usr << browse(null, "window=instrument")
|
usr << browse(null, "window=instrument")
|
||||||
usr.unset_machine()
|
usr.unset_machine()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
adjustToxLoss(-(rads))
|
adjustToxLoss(-(rads))
|
||||||
return
|
return
|
||||||
|
|
||||||
/mob/living/carbon/alien/handle_regular_status_updates()
|
/mob/living/carbon/alien/handle_regular_UI_updates()
|
||||||
|
|
||||||
if(status_flags & GODMODE) return 0
|
if(status_flags & GODMODE) return 0
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
return //TODO: DEFERRED
|
return //TODO: DEFERRED
|
||||||
|
|
||||||
/mob/living/carbon/brain/handle_regular_status_updates() //TODO: comment out the unused bits >_>
|
/mob/living/carbon/brain/handle_regular_UI_updates() //TODO: comment out the unused bits >_>
|
||||||
updatehealth()
|
updatehealth()
|
||||||
|
|
||||||
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
|
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
|
||||||
|
|||||||
@@ -982,7 +982,7 @@
|
|||||||
return //TODO: DEFERRED
|
return //TODO: DEFERRED
|
||||||
|
|
||||||
//DO NOT CALL handle_statuses() from this proc, it's called from living/Life() as long as this returns a true value.
|
//DO NOT CALL handle_statuses() from this proc, it's called from living/Life() as long as this returns a true value.
|
||||||
/mob/living/carbon/human/handle_regular_status_updates()
|
/mob/living/carbon/human/handle_regular_UI_updates()
|
||||||
if(!handle_some_updates())
|
if(!handle_some_updates())
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
return //TODO: DEFERRED
|
return //TODO: DEFERRED
|
||||||
|
|
||||||
/mob/living/carbon/slime/handle_regular_status_updates()
|
/mob/living/carbon/slime/handle_regular_UI_updates()
|
||||||
|
|
||||||
src.blinded = null
|
src.blinded = null
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
for(var/obj/item/grab/G in src)
|
for(var/obj/item/grab/G in src)
|
||||||
G.process(2)
|
G.process(2)
|
||||||
|
|
||||||
if(handle_regular_status_updates()) // Status & health update, are we dead or alive etc.
|
if(handle_regular_UI_updates()) // Status & health update, are we dead or alive etc.
|
||||||
handle_disabilities() // eye, ear, brain damages
|
handle_disabilities() // eye, ear, brain damages
|
||||||
handle_statuses() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
|
handle_statuses() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
stop_pulling()
|
stop_pulling()
|
||||||
|
|
||||||
//This updates the health and status of the mob (conscious, unconscious, dead)
|
//This updates the health and status of the mob (conscious, unconscious, dead)
|
||||||
/mob/living/proc/handle_regular_status_updates()
|
/mob/living/proc/handle_regular_UI_updates()
|
||||||
updatehealth()
|
updatehealth()
|
||||||
if(stat != DEAD)
|
if(stat != DEAD)
|
||||||
if(paralysis)
|
if(paralysis)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ var/global/list/default_pai_software = list()
|
|||||||
|
|
||||||
/mob/living/silicon/pai/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
/mob/living/silicon/pai/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||||
if(user != src)
|
if(user != src)
|
||||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
if(ui) ui.set_status(UI_CLOSE, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(ui_key != "main")
|
if(ui_key != "main")
|
||||||
@@ -53,7 +53,7 @@ var/global/list/default_pai_software = list()
|
|||||||
if(S && !S.toggle)
|
if(S && !S.toggle)
|
||||||
S.on_nano_ui_interact(src, ui, force_open)
|
S.on_nano_ui_interact(src, ui, force_open)
|
||||||
else
|
else
|
||||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
if(ui) ui.set_status(UI_CLOSE, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
var/data[0]
|
var/data[0]
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ var/list/mob_hat_cache = list()
|
|||||||
//Easiest to check this here, then check again in the robot proc.
|
//Easiest to check this here, then check again in the robot proc.
|
||||||
//Standard robots use config for crit, which is somewhat excessive for these guys.
|
//Standard robots use config for crit, which is somewhat excessive for these guys.
|
||||||
//Drones killed by damage will gib.
|
//Drones killed by damage will gib.
|
||||||
/mob/living/silicon/robot/drone/handle_regular_status_updates()
|
/mob/living/silicon/robot/drone/handle_regular_UI_updates()
|
||||||
var/turf/T = get_turf(src)
|
var/turf/T = get_turf(src)
|
||||||
if(!T || health <= -35 )
|
if(!T || health <= -35 )
|
||||||
timeofdeath = world.time
|
timeofdeath = world.time
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
//Status updates, death etc.
|
//Status updates, death etc.
|
||||||
clamp_values()
|
clamp_values()
|
||||||
handle_regular_status_updates()
|
handle_regular_UI_updates()
|
||||||
handle_actions()
|
handle_actions()
|
||||||
handle_instability()
|
handle_instability()
|
||||||
// For some reason borg Life() doesn't call ..()
|
// For some reason borg Life() doesn't call ..()
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
lights_on = 0
|
lights_on = 0
|
||||||
set_light(0)
|
set_light(0)
|
||||||
|
|
||||||
/mob/living/silicon/robot/handle_regular_status_updates()
|
/mob/living/silicon/robot/handle_regular_UI_updates()
|
||||||
|
|
||||||
if(src.camera && !scrambledcodes)
|
if(src.camera && !scrambledcodes)
|
||||||
if(src.stat == 2 || wires.IsIndexCut(BORG_WIRE_CAMERA))
|
if(src.stat == 2 || wires.IsIndexCut(BORG_WIRE_CAMERA))
|
||||||
|
|||||||
@@ -89,8 +89,8 @@
|
|||||||
|
|
||||||
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(has_access(user))
|
if(has_access(user))
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
return STATUS_UPDATE
|
return UI_UPDATE
|
||||||
|
|
||||||
/datum/topic_state/air_alarm/href_list(var/mob/user)
|
/datum/topic_state/air_alarm/href_list(var/mob/user)
|
||||||
var/list/extra_href = list()
|
var/list/extra_href = list()
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
/var/global/datum/topic_state/admin_state/admin_state = new()
|
/var/global/datum/topic_state/admin_state/admin_state = new()
|
||||||
|
|
||||||
/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
return check_rights(R_ADMIN, 0, user) ? STATUS_INTERACTIVE : STATUS_CLOSE
|
return check_rights(R_ADMIN, 0, user) ? UI_INTERACTIVE : UI_CLOSE
|
||||||
|
|||||||
@@ -7,33 +7,33 @@
|
|||||||
/datum/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state)
|
/datum/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state)
|
||||||
var/src_object = nano_host()
|
var/src_object = nano_host()
|
||||||
if(IsAdminGhost(user))
|
if(IsAdminGhost(user))
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
return state.can_use_topic(src_object, user)
|
return state.can_use_topic(src_object, user)
|
||||||
|
|
||||||
/datum/topic_state/proc/href_list(var/mob/user)
|
/datum/topic_state/proc/href_list(var/mob/user)
|
||||||
return list()
|
return list()
|
||||||
|
|
||||||
/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/mob/proc/shared_nano_interaction()
|
/mob/proc/shared_nano_interaction()
|
||||||
if (src.stat || !client)
|
if (src.stat || !client)
|
||||||
return STATUS_CLOSE // no updates, close the interface
|
return UI_CLOSE // no updates, close the interface
|
||||||
else if (incapacitated())
|
else if (incapacitated())
|
||||||
return STATUS_UPDATE // update only (orange visibility)
|
return UI_UPDATE // update only (orange visibility)
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
|
|
||||||
/mob/living/silicon/ai/shared_nano_interaction()
|
/mob/living/silicon/ai/shared_nano_interaction()
|
||||||
if(lacks_power())
|
if(lacks_power())
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
if (check_unable(1, 0))
|
if (check_unable(1, 0))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/mob/living/silicon/robot/shared_nano_interaction()
|
/mob/living/silicon/robot/shared_nano_interaction()
|
||||||
. = STATUS_INTERACTIVE
|
. = UI_INTERACTIVE
|
||||||
if(!has_power)
|
if(!has_power)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
if(lockdown)
|
if(lockdown)
|
||||||
. = STATUS_DISABLED
|
. = UI_DISABLED
|
||||||
return min(., ..())
|
return min(., ..())
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
/var/global/datum/topic_state/conscious_state/conscious_state = new()
|
/var/global/datum/topic_state/conscious_state/conscious_state = new()
|
||||||
|
|
||||||
/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE
|
return user.stat == CONSCIOUS ? UI_INTERACTIVE : UI_CLOSE
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user)
|
/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user)
|
||||||
if(!src_object.contains(user))
|
if(!src_object.contains(user))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|
||||||
|
|||||||
@@ -7,56 +7,56 @@
|
|||||||
return user.nano_default_can_use_topic(src_object)
|
return user.nano_default_can_use_topic(src_object)
|
||||||
|
|
||||||
/mob/proc/nano_default_can_use_topic(var/src_object)
|
/mob/proc/nano_default_can_use_topic(var/src_object)
|
||||||
return STATUS_CLOSE // By default no mob can do anything with NanoUI
|
return UI_CLOSE // By default no mob can do anything with NanoUI
|
||||||
|
|
||||||
/mob/observer/dead/nano_default_can_use_topic(var/src_object)
|
/mob/observer/dead/nano_default_can_use_topic(var/src_object)
|
||||||
if(can_admin_interact())
|
if(can_admin_interact())
|
||||||
return STATUS_INTERACTIVE // Admins are more equal
|
return UI_INTERACTIVE // Admins are more equal
|
||||||
if(!client || get_dist(src_object, src) > client.view) // Preventing ghosts from having a million windows open by limiting to objects in range
|
if(!client || get_dist(src_object, src) > client.view) // Preventing ghosts from having a million windows open by limiting to objects in range
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return STATUS_UPDATE // Ghosts can view updates
|
return UI_UPDATE // Ghosts can view updates
|
||||||
|
|
||||||
/mob/living/silicon/pai/nano_default_can_use_topic(var/src_object)
|
/mob/living/silicon/pai/nano_default_can_use_topic(var/src_object)
|
||||||
if((src_object == src || src_object == radio || src_object == communicator) && !stat)
|
if((src_object == src || src_object == radio || src_object == communicator) && !stat)
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
else
|
else
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/mob/living/silicon/robot/nano_default_can_use_topic(var/src_object)
|
/mob/living/silicon/robot/nano_default_can_use_topic(var/src_object)
|
||||||
. = shared_nano_interaction()
|
. = shared_nano_interaction()
|
||||||
if(. <= STATUS_DISABLED)
|
if(. <= UI_DISABLED)
|
||||||
return
|
return
|
||||||
|
|
||||||
// robots can interact with things they can see within their view range
|
// 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)
|
if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view)
|
||||||
return STATUS_INTERACTIVE // interactive (green visibility)
|
return UI_INTERACTIVE // interactive (green visibility)
|
||||||
return STATUS_DISABLED // no updates, completely disabled (red visibility)
|
return UI_DISABLED // no updates, completely disabled (red visibility)
|
||||||
|
|
||||||
/mob/living/silicon/ai/nano_default_can_use_topic(var/src_object)
|
/mob/living/silicon/ai/nano_default_can_use_topic(var/src_object)
|
||||||
. = shared_nano_interaction()
|
. = shared_nano_interaction()
|
||||||
if(. != STATUS_INTERACTIVE)
|
if(. != UI_INTERACTIVE)
|
||||||
return
|
return
|
||||||
|
|
||||||
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
|
// 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.
|
// unless it's on the same level as the object it's interacting with.
|
||||||
var/turf/T = get_turf(src_object)
|
var/turf/T = get_turf(src_object)
|
||||||
if(!T || !(z == T.z || (T.z in GLOB.using_map.player_levels)))
|
if(!T || !(z == T.z || (T.z in GLOB.using_map.player_levels)))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
// If an object is in view then we can interact with it
|
// If an object is in view then we can interact with it
|
||||||
if(src_object in view(client.view, src))
|
if(src_object in view(client.view, src))
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
|
|
||||||
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
|
// 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())
|
if(is_in_chassis())
|
||||||
//stop AIs from leaving windows open and using then after they lose vision
|
//stop AIs from leaving windows open and using then after they lose vision
|
||||||
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
|
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard
|
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
|
return UI_INTERACTIVE
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI.
|
//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI.
|
||||||
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
|
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
|
||||||
@@ -64,30 +64,30 @@
|
|||||||
|
|
||||||
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
|
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
|
||||||
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
|
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
var/dist = get_dist(src_object, src)
|
var/dist = get_dist(src_object, src)
|
||||||
if (dist <= 1)
|
if (dist <= 1)
|
||||||
return STATUS_INTERACTIVE // interactive (green visibility)
|
return UI_INTERACTIVE // interactive (green visibility)
|
||||||
else if (dist <= 2)
|
else if (dist <= 2)
|
||||||
return STATUS_UPDATE // update only (orange visibility)
|
return UI_UPDATE // update only (orange visibility)
|
||||||
else if (dist <= 4)
|
else if (dist <= 4)
|
||||||
return STATUS_DISABLED // no updates, completely disabled (red visibility)
|
return UI_DISABLED // no updates, completely disabled (red visibility)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/mob/living/nano_default_can_use_topic(var/src_object)
|
/mob/living/nano_default_can_use_topic(var/src_object)
|
||||||
. = shared_nano_interaction(src_object)
|
. = shared_nano_interaction(src_object)
|
||||||
if(. != STATUS_CLOSE)
|
if(. != UI_CLOSE)
|
||||||
if(loc)
|
if(loc)
|
||||||
. = min(., loc.contents_nano_distance(src_object, src))
|
. = min(., loc.contents_nano_distance(src_object, src))
|
||||||
/*
|
/*
|
||||||
if(STATUS_INTERACTIVE)
|
if(UI_INTERACTIVE)
|
||||||
return STATUS_UPDATE
|
return UI_UPDATE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/mob/living/carbon/human/nano_default_can_use_topic(var/src_object)
|
/mob/living/carbon/human/nano_default_can_use_topic(var/src_object)
|
||||||
. = shared_nano_interaction(src_object)
|
. = shared_nano_interaction(src_object)
|
||||||
if(. != STATUS_CLOSE)
|
if(. != UI_CLOSE)
|
||||||
. = min(., shared_living_nano_distance(src_object))
|
. = min(., shared_living_nano_distance(src_object))
|
||||||
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
|
if(. == UI_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This state always returns STATUS_INTERACTIVE
|
This state always returns UI_INTERACTIVE
|
||||||
*/
|
*/
|
||||||
/var/global/datum/topic_state/interactive/interactive_state = new()
|
/var/global/datum/topic_state/interactive/interactive_state = new()
|
||||||
|
|
||||||
/datum/topic_state/interactive/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/interactive/can_use_topic(var/src_object, var/mob/user)
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(!(src_object in user))
|
if(!(src_object in user))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
|
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|||||||
@@ -5,6 +5,6 @@
|
|||||||
|
|
||||||
/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(!user.contains(src_object))
|
if(!user.contains(src_object))
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
if(H.glasses == src_object)
|
if(H.glasses == src_object)
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/var/global/datum/topic_state/nif_state/nif_state = new()
|
/var/global/datum/topic_state/nif_state/nif_state = new()
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
|
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/var/global/datum/topic_state/commlink_state/commlink_state = new()
|
/var/global/datum/topic_state/commlink_state/commlink_state = new()
|
||||||
|
|
||||||
@@ -29,4 +29,4 @@
|
|||||||
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
|
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
/datum/topic_state/default/outside/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/default/outside/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(user in src_object)
|
if(user in src_object)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return ..()
|
return ..()
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
|
||||||
. = user.shared_nano_interaction(src_object)
|
. = user.shared_nano_interaction(src_object)
|
||||||
if(. > STATUS_CLOSE)
|
if(. > UI_CLOSE)
|
||||||
return min(., user.check_physical_distance(src_object))
|
return min(., user.check_physical_distance(src_object))
|
||||||
|
|
||||||
/mob/proc/check_physical_distance(var/src_object)
|
/mob/proc/check_physical_distance(var/src_object)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
/mob/observer/dead/check_physical_distance(var/src_object)
|
/mob/observer/dead/check_physical_distance(var/src_object)
|
||||||
return default_can_use_topic(src_object)
|
return default_can_use_topic(src_object)
|
||||||
@@ -15,4 +15,4 @@
|
|||||||
return shared_living_nano_distance(src_object)
|
return shared_living_nano_distance(src_object)
|
||||||
|
|
||||||
/mob/living/silicon/check_physical_distance(var/src_object)
|
/mob/living/silicon/check_physical_distance(var/src_object)
|
||||||
return max(STATUS_UPDATE, shared_living_nano_distance(src_object))
|
return max(UI_UPDATE, shared_living_nano_distance(src_object))
|
||||||
|
|||||||
@@ -24,15 +24,15 @@
|
|||||||
|
|
||||||
/datum/topic_state/remote/can_use_topic(var/datum/src_object, var/mob/user)
|
/datum/topic_state/remote/can_use_topic(var/datum/src_object, var/mob/user)
|
||||||
if(!(remoter && remoter_state)) // The remoter is gone, let us leave
|
if(!(remoter && remoter_state)) // The remoter is gone, let us leave
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
if(src_object != remote_target)
|
if(src_object != remote_target)
|
||||||
log_world("remote - Unexpected src_object: Expected '[remote_target]'/[remote_target.type], was '[src_object]'/[src_object.type]")
|
log_world("remote - Unexpected src_object: Expected '[remote_target]'/[remote_target.type], was '[src_object]'/[src_object.type]")
|
||||||
|
|
||||||
// This checks if src_object is powered, etc.
|
// This checks if src_object is powered, etc.
|
||||||
// The interactive state is otherwise simplistic and only returns STATUS_INTERACTIVE and never checks distances, etc.
|
// The interactive state is otherwise simplistic and only returns UI_INTERACTIVE and never checks distances, etc.
|
||||||
. = src_object.CanUseTopic(user, interactive_state)
|
. = src_object.CanUseTopic(user, interactive_state)
|
||||||
if(. == STATUS_CLOSE)
|
if(. == UI_CLOSE)
|
||||||
return
|
return
|
||||||
|
|
||||||
// This is the (generally) heavy checking, making sure the user is capable, within range of the remoter source, etc.
|
// This is the (generally) heavy checking, making sure the user is capable, within range of the remoter source, etc.
|
||||||
|
|||||||
@@ -5,5 +5,5 @@
|
|||||||
|
|
||||||
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(src_object != user)
|
if(src_object != user)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
return user.shared_nano_interaction()
|
return user.shared_nano_interaction()
|
||||||
|
|||||||
@@ -8,6 +8,6 @@
|
|||||||
var/turf/turf_obj = get_turf(src_object)
|
var/turf/turf_obj = get_turf(src_object)
|
||||||
var/turf/turf_usr = get_turf(user)
|
var/turf/turf_usr = get_turf(user)
|
||||||
if(!turf_obj || !turf_usr)
|
if(!turf_obj || !turf_usr)
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
return turf_obj.z == turf_usr.z ? STATUS_INTERACTIVE : STATUS_CLOSE
|
return turf_obj.z == turf_usr.z ? UI_INTERACTIVE : UI_CLOSE
|
||||||
|
|||||||
@@ -72,8 +72,8 @@
|
|||||||
|
|
||||||
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
|
/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user)
|
||||||
if(has_access(user))
|
if(has_access(user))
|
||||||
return STATUS_INTERACTIVE
|
return UI_INTERACTIVE
|
||||||
return STATUS_UPDATE
|
return UI_UPDATE
|
||||||
|
|
||||||
/datum/topic_state/air_alarm/href_list(var/mob/user)
|
/datum/topic_state/air_alarm/href_list(var/mob/user)
|
||||||
var/list/extra_href = list()
|
var/list/extra_href = list()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
return host ? host : src
|
return host ? host : src
|
||||||
|
|
||||||
/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state)
|
/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state)
|
||||||
return CanUseTopic(usr, state) == STATUS_INTERACTIVE
|
return CanUseTopic(usr, state) == UI_INTERACTIVE
|
||||||
|
|
||||||
/datum/nano_module/proc/check_eye(var/mob/user)
|
/datum/nano_module/proc/check_eye(var/mob/user)
|
||||||
return -1
|
return -1
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ nanoui is used to open and update nano browser uis
|
|||||||
// set to 1 to update the ui automatically every master_controller tick
|
// set to 1 to update the ui automatically every master_controller tick
|
||||||
var/is_auto_updating = 0
|
var/is_auto_updating = 0
|
||||||
// the current status/visibility of the ui
|
// the current status/visibility of the ui
|
||||||
var/status = STATUS_INTERACTIVE
|
var/status = UI_INTERACTIVE
|
||||||
|
|
||||||
// Relationship between a master interface and its children. Used in update_status
|
// Relationship between a master interface and its children. Used in update_status
|
||||||
var/datum/nanoui/master_ui
|
var/datum/nanoui/master_ui
|
||||||
@@ -130,7 +130,7 @@ nanoui is used to open and update nano browser uis
|
|||||||
*/
|
*/
|
||||||
/datum/nanoui/proc/set_status(state, push_update)
|
/datum/nanoui/proc/set_status(state, push_update)
|
||||||
if (state != status) // Only update if it is different
|
if (state != status) // Only update if it is different
|
||||||
if (status == STATUS_DISABLED)
|
if (status == UI_DISABLED)
|
||||||
status = state
|
status = state
|
||||||
if (push_update)
|
if (push_update)
|
||||||
update()
|
update()
|
||||||
@@ -153,7 +153,7 @@ nanoui is used to open and update nano browser uis
|
|||||||
new_status = min(new_status, master_ui.status)
|
new_status = min(new_status, master_ui.status)
|
||||||
|
|
||||||
set_status(new_status, push_update)
|
set_status(new_status, push_update)
|
||||||
if(new_status == STATUS_CLOSE)
|
if(new_status == UI_CLOSE)
|
||||||
close()
|
close()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,7 +414,7 @@ nanoui is used to open and update nano browser uis
|
|||||||
if (width && height)
|
if (width && height)
|
||||||
window_size = "size=[width]x[height];"
|
window_size = "size=[width]x[height];"
|
||||||
update_status(0)
|
update_status(0)
|
||||||
if(status == STATUS_CLOSE)
|
if(status == UI_CLOSE)
|
||||||
return
|
return
|
||||||
|
|
||||||
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
|
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
|
||||||
@@ -470,7 +470,7 @@ nanoui is used to open and update nano browser uis
|
|||||||
*/
|
*/
|
||||||
/datum/nanoui/proc/push_data(data, force_push = 0)
|
/datum/nanoui/proc/push_data(data, force_push = 0)
|
||||||
update_status(0)
|
update_status(0)
|
||||||
if (status == STATUS_DISABLED && !force_push)
|
if (status == UI_DISABLED && !force_push)
|
||||||
return // Cannot update UI, no visibility
|
return // Cannot update UI, no visibility
|
||||||
|
|
||||||
var/list/send_data = get_send_data(data)
|
var/list/send_data = get_send_data(data)
|
||||||
@@ -480,14 +480,14 @@ nanoui is used to open and update nano browser uis
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
|
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
|
||||||
* If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic()
|
* If the UI status is currently UI_INTERACTIVE then call the src_object Topic()
|
||||||
* If the src_object Topic() returns 1 (true) then update all UIs attached to src_object
|
* If the src_object Topic() returns 1 (true) then update all UIs attached to src_object
|
||||||
*
|
*
|
||||||
* @return nothing
|
* @return nothing
|
||||||
*/
|
*/
|
||||||
/datum/nanoui/Topic(href, href_list)
|
/datum/nanoui/Topic(href, href_list)
|
||||||
update_status(0) // update the status
|
update_status(0) // update the status
|
||||||
if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
|
if (status != UI_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
|
||||||
return
|
return
|
||||||
|
|
||||||
// This is used to toggle the nano map ui
|
// This is used to toggle the nano map ui
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
if((. = ..()))
|
if((. = ..()))
|
||||||
return
|
return
|
||||||
state = state || DefaultTopicState() || global.default_state
|
state = state || DefaultTopicState() || global.default_state
|
||||||
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
|
if(CanUseTopic(usr, state, href_list) == UI_INTERACTIVE)
|
||||||
CouldUseTopic(usr)
|
CouldUseTopic(usr)
|
||||||
return OnTopic(usr, href_list, state)
|
return OnTopic(usr, href_list, state)
|
||||||
CouldNotUseTopic(usr)
|
CouldNotUseTopic(usr)
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/computer/ship/attack_ai(mob/user)
|
/obj/machinery/computer/ship/attack_ai(mob/user)
|
||||||
if(CanUseTopic(user, DefaultTopicState()) > STATUS_CLOSE)
|
if(CanUseTopic(user, DefaultTopicState()) > UI_CLOSE)
|
||||||
return interface_interact(user)
|
return interface_interact(user)
|
||||||
|
|
||||||
// After a recent rework this should mostly be safe.
|
// After a recent rework this should mostly be safe.
|
||||||
@@ -100,5 +100,5 @@
|
|||||||
/obj/machinery/computer/ship/attack_hand(mob/user)
|
/obj/machinery/computer/ship/attack_hand(mob/user)
|
||||||
if((. = ..()))
|
if((. = ..()))
|
||||||
return
|
return
|
||||||
if(CanUseTopic(user, DefaultTopicState()) > STATUS_CLOSE)
|
if(CanUseTopic(user, DefaultTopicState()) > UI_CLOSE)
|
||||||
return interface_interact(user)
|
return interface_interact(user)
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ var/global/list/default_infomorph_software = list()
|
|||||||
|
|
||||||
/mob/living/silicon/infomorph/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, key_state = self_state)
|
/mob/living/silicon/infomorph/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, key_state = self_state)
|
||||||
if(user != src)
|
if(user != src)
|
||||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
if(ui) ui.set_status(UI_CLOSE, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(ui_key != "main")
|
if(ui_key != "main")
|
||||||
@@ -469,7 +469,7 @@ var/global/list/default_infomorph_software = list()
|
|||||||
if(S && !S.toggle)
|
if(S && !S.toggle)
|
||||||
S.on_nano_ui_interact(src, ui, force_open)
|
S.on_nano_ui_interact(src, ui, force_open)
|
||||||
else
|
else
|
||||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
if(ui) ui.set_status(UI_CLOSE, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
var/data[0]
|
var/data[0]
|
||||||
|
|||||||
370
code/modules/tgui/modal.dm
Normal file
370
code/modules/tgui/modal.dm
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
/**
|
||||||
|
* tgui modals
|
||||||
|
*
|
||||||
|
* Allows creation of modals within tgui.
|
||||||
|
*/
|
||||||
|
|
||||||
|
GLOBAL_LIST(tgui_modals)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this from a proc that is called in tgui_act() to process modal actions
|
||||||
|
*
|
||||||
|
* Example: /obj/machinery/chem_master/proc/ui_act_modal
|
||||||
|
* You can then switch based on the return value and show different
|
||||||
|
* modals depending on the answer.
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * action - The called action
|
||||||
|
* * params - The params to the action
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_act(datum/source = src, action = "", params)
|
||||||
|
ASSERT(istype(source))
|
||||||
|
|
||||||
|
. = null
|
||||||
|
switch(action)
|
||||||
|
if("modal_open") // Params: id, arguments
|
||||||
|
return TGUI_MODAL_OPEN
|
||||||
|
if("modal_answer") // Params: id, answer, arguments
|
||||||
|
params["answer"] = tgui_modal_preprocess_answer(source, params["answer"])
|
||||||
|
if(tgui_modal_answer(source, params["id"], params["answer"])) // If there's a current modal with a delegate that returned TRUE, no need to continue
|
||||||
|
. = TGUI_MODAL_DELEGATE
|
||||||
|
else
|
||||||
|
. = TGUI_MODAL_ANSWER
|
||||||
|
tgui_modal_clear(source)
|
||||||
|
if("modal_close") // Params: id
|
||||||
|
tgui_modal_clear(source)
|
||||||
|
return TGUI_MODAL_CLOSE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this from tgui_data() to return modal information if needed
|
||||||
|
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_data(datum/source = src)
|
||||||
|
ASSERT(istype(source))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||||
|
if(!current)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return current.to_data()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the current modal for a given datum
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_clear(datum/source = src)
|
||||||
|
ASSERT(istype(source))
|
||||||
|
|
||||||
|
LAZYINITLIST(GLOB.tgui_modals)
|
||||||
|
var/datum/tgui_modal/previous = GLOB.tgui_modals[REF(source)]
|
||||||
|
if(!previous)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
for(var/i in 1 to length(GLOB.tgui_modals))
|
||||||
|
var/key = GLOB.tgui_modals[i]
|
||||||
|
if(previous == GLOB.tgui_modals[key])
|
||||||
|
GLOB.tgui_modals.Cut(i, i + 1)
|
||||||
|
break
|
||||||
|
|
||||||
|
SStgui.update_uis(source)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a message TGUI modal
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * text - The text to display above the answers
|
||||||
|
* * delegate - The proc to call when closed
|
||||||
|
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_message(datum/source = src, id, text = "Default modal message", delegate, arguments)
|
||||||
|
ASSERT(length(id))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/modal = new(id, text, delegate, arguments)
|
||||||
|
return tgui_modal_new(source, modal)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a text input TGUI modal
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * text - The text to display above the answers
|
||||||
|
* * delegate - The proc to call when submitted
|
||||||
|
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||||
|
* * value - The default value of the input
|
||||||
|
* * max_length - The maximum char length of the input
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_input(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", max_length = TGUI_MODAL_INPUT_MAX_LENGTH)
|
||||||
|
ASSERT(length(id))
|
||||||
|
ASSERT(max_length > 0)
|
||||||
|
|
||||||
|
var/datum/tgui_modal/input/modal = new(id, text, delegate, arguments, value, max_length)
|
||||||
|
return tgui_modal_new(source, modal)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a dropdown input TGUI modal
|
||||||
|
*
|
||||||
|
* Internally checks if the answer is in the list of choices.
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * text - The text to display above the answers
|
||||||
|
* * delegate - The proc to call when submitted
|
||||||
|
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||||
|
* * value - The default value of the dropdown
|
||||||
|
* * choices - The list of available choices in the dropdown
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_choice(datum/source = src, id, text = "Default modal message", delegate, arguments, value = "", choices)
|
||||||
|
ASSERT(length(id))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/input/choice/modal = new(id, text, delegate, arguments, value, choices)
|
||||||
|
return tgui_modal_new(source, modal)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a bento input TGUI modal
|
||||||
|
*
|
||||||
|
* Internally checks if the answer is in the list of choices.
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * text - The text to display above the answers
|
||||||
|
* * delegate - The proc to call when submitted
|
||||||
|
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||||
|
* * value - The default value of the bento
|
||||||
|
* * choices - The list of available choices in the bento
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_bento(datum/source = src, id, text = "Default modal message", delegate, arguments, value, choices)
|
||||||
|
ASSERT(length(id))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/input/bento/modal = new(id, text, delegate, arguments, value, choices)
|
||||||
|
return tgui_modal_new(source, modal)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a yes/no TGUI modal
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * text - The text to display above the answers
|
||||||
|
* * delegate - The proc to call when "Yes" is pressed
|
||||||
|
* * delegate_no - The proc to call when "No" is pressed
|
||||||
|
* * arguments - List of arguments passed to and from JS (mostly useful for chaining modals)
|
||||||
|
* * yes_text - The text to show in the "Yes" button
|
||||||
|
* * no_text - The text to show in the "No" button
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_boolean(datum/source = src, id, text = "Default modal message", delegate, delegate_no, arguments, yes_text = "Yes", no_text = "No")
|
||||||
|
ASSERT(length(id))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/boolean/modal = new(id, text, delegate, delegate_no, arguments, yes_text, no_text)
|
||||||
|
return tgui_modal_new(source, modal)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a given modal to a source. Private.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * modal - The datum/tgui_modal to register
|
||||||
|
* * replace_previous - Whether any modal currently assigned to source should be replaced
|
||||||
|
* * instant_update - Whether the changes should reflect immediately
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_new(datum/source = src, datum/tgui_modal/modal = null, replace_previous = TRUE, instant_update = TRUE)
|
||||||
|
ASSERT(istype(source))
|
||||||
|
ASSERT(istype(modal))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/previous = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||||
|
if(previous && !replace_previous)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
modal.owning_source = source
|
||||||
|
|
||||||
|
// Previous one should get GC'd
|
||||||
|
LAZYSET(GLOB.tgui_modals, REF(source), modal)
|
||||||
|
if(instant_update)
|
||||||
|
SStgui.update_uis(source)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the source's currently assigned modal's (if there is one) on_answer() proc. Private.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * id - The ID of the modal
|
||||||
|
* * answer - The provided answer
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_answer(datum/source = src, id, answer = "")
|
||||||
|
ASSERT(istype(source))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||||
|
if(!current)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
return current.on_answer(answer)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes an answer from JS through the modal's proc.
|
||||||
|
*
|
||||||
|
* Used namely for cutting the text short if it's longer
|
||||||
|
* than an input modal's max_length.
|
||||||
|
* Arguments:
|
||||||
|
* * source - The source datum
|
||||||
|
* * answer - The provided answer
|
||||||
|
*/
|
||||||
|
/datum/proc/tgui_modal_preprocess_answer(datum/source = src, answer = "")
|
||||||
|
ASSERT(istype(source))
|
||||||
|
|
||||||
|
var/datum/tgui_modal/current = LAZYACCESS(GLOB.tgui_modals, REF(source))
|
||||||
|
if(!current)
|
||||||
|
return answer
|
||||||
|
|
||||||
|
return current.preprocess_answer(answer)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modal datum (contains base information for a modal)
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal
|
||||||
|
var/datum/owning_source
|
||||||
|
var/id
|
||||||
|
var/text
|
||||||
|
var/delegate
|
||||||
|
var/list/arguments
|
||||||
|
var/modal_type = "message"
|
||||||
|
|
||||||
|
/datum/tgui_modal/New(id, text, delegate, list/arguments)
|
||||||
|
src.id = id
|
||||||
|
src.text = text
|
||||||
|
src.delegate = delegate
|
||||||
|
src.arguments = arguments
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when it's time to pre-process the answer before using it
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * answer - The answer, a nullable text
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/proc/preprocess_answer(answer)
|
||||||
|
return reject_bad_text(answer, TGUI_MODAL_INPUT_MAX_LENGTH) // bleh
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a modal receives an answer
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * answer - The answer, a nullable text
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/proc/on_answer(answer)
|
||||||
|
if(delegate)
|
||||||
|
return call(owning_source, delegate)(answer, arguments)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list that describes a modal visually to be passed to JS
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/proc/to_data()
|
||||||
|
. = list()
|
||||||
|
.["id"] = id
|
||||||
|
.["text"] = text
|
||||||
|
.["args"] = arguments || list()
|
||||||
|
.["type"] = modal_type
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input modal - has a text entry that can be used to enter an answer
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/input
|
||||||
|
modal_type = "input"
|
||||||
|
var/value
|
||||||
|
var/max_length
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/New(id, text, delegate, list/arguments, value, max_length)
|
||||||
|
..(id, text, delegate, arguments)
|
||||||
|
src.value = value
|
||||||
|
src.max_length = max_length
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/preprocess_answer(answer)
|
||||||
|
. = ..(answer)
|
||||||
|
if(length(answer) > max_length)
|
||||||
|
. = copytext(., 1, max_length + 1)
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/to_data()
|
||||||
|
. = ..()
|
||||||
|
.["value"] = value
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Choice modal - has a dropdown menu that can be used to select an answer
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/input/choice
|
||||||
|
modal_type = "choice"
|
||||||
|
var/choices
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/choice/New(id, text, delegate, list/arguments, value, choices)
|
||||||
|
..(id, text, delegate, arguments, value, TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in dropdowns, but whatever
|
||||||
|
src.choices = choices
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/choice/on_answer(answer)
|
||||||
|
if(answer in choices) // Make sure the answer is actually in our choices!
|
||||||
|
return ..(answer, arguments)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/choice/to_data()
|
||||||
|
. = ..()
|
||||||
|
.["choices"] = choices
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bento modal - Similar to choice, it displays the choices in a grid of images
|
||||||
|
*
|
||||||
|
* The returned answer is the index of the choice.
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/input/bento
|
||||||
|
modal_type = "bento"
|
||||||
|
var/choices
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/bento/New(id, text, delegate, list/arguments, value, choices)
|
||||||
|
..(id, text, delegate, arguments, text2num(value), TGUI_MODAL_INPUT_MAX_LENGTH) // Max length doesn't really matter in here, but whatever
|
||||||
|
src.choices = choices
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/bento/preprocess_answer(answer)
|
||||||
|
return text2num(answer) || 0
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/bento/on_answer(answer)
|
||||||
|
if(answer >= 1 && answer <= length(choices)) // Make sure the answer index is actually in our indexes!
|
||||||
|
return ..(answer, arguments)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/datum/tgui_modal/input/bento/to_data()
|
||||||
|
. = ..()
|
||||||
|
.["choices"] = choices
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean modal - has yes/no buttons that do different actions depending on which is pressed
|
||||||
|
*/
|
||||||
|
/datum/tgui_modal/boolean
|
||||||
|
modal_type = "boolean"
|
||||||
|
var/delegate_no
|
||||||
|
var/yes_text
|
||||||
|
var/no_text
|
||||||
|
|
||||||
|
/datum/tgui_modal/boolean/New(id, text, delegate, delegate_no, list/arguments, yes_text, no_text)
|
||||||
|
..(id, text, delegate, arguments)
|
||||||
|
src.delegate_no = delegate_no
|
||||||
|
src.yes_text = yes_text
|
||||||
|
src.no_text = no_text
|
||||||
|
|
||||||
|
/datum/tgui_modal/boolean/preprocess_answer(answer)
|
||||||
|
return text2num(answer) || FALSE
|
||||||
|
|
||||||
|
/datum/tgui_modal/boolean/on_answer(answer)
|
||||||
|
if(answer)
|
||||||
|
return ..(answer, arguments)
|
||||||
|
else if(delegate_no)
|
||||||
|
return call(owning_source, delegate_no)(arguments)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/datum/tgui_modal/boolean/to_data()
|
||||||
|
. = ..()
|
||||||
|
.["yes_text"] = yes_text
|
||||||
|
.["no_text"] = no_text
|
||||||
@@ -12,16 +12,25 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
|||||||
var/list/using_access
|
var/list/using_access
|
||||||
|
|
||||||
var/tgui_id
|
var/tgui_id
|
||||||
|
var/ntos = FALSE
|
||||||
|
|
||||||
/datum/tgui_module/New(var/host)
|
/datum/tgui_module/New(var/host)
|
||||||
src.host = host
|
src.host = host
|
||||||
|
if(ntos)
|
||||||
|
tgui_id = "Ntos" + tgui_id
|
||||||
|
|
||||||
/datum/tgui_module/ui_host()
|
/datum/tgui_module/tgui_host()
|
||||||
return host ? host : src
|
return host ? host.tgui_host() : src
|
||||||
|
|
||||||
/datum/tgui_module/ui_close(mob/user)
|
/datum/tgui_module/tgui_close(mob/user)
|
||||||
if(host)
|
if(host)
|
||||||
host.ui_close(user)
|
host.tgui_close(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/proc/check_eye(mob/user)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
/datum/tgui_module/proc/can_still_topic(mob/user, datum/tgui_state/state)
|
||||||
|
return (tgui_status(user, state) == UI_INTERACTIVE)
|
||||||
|
|
||||||
/datum/tgui_module/proc/check_access(mob/user, access)
|
/datum/tgui_module/proc/check_access(mob/user, access)
|
||||||
if(!access)
|
if(!access)
|
||||||
@@ -36,7 +45,7 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
|||||||
if(!istype(user))
|
if(!istype(user))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
var/obj/item/card/id/I = user.GetIdCard()
|
var/obj/item/weapon/card/id/I = user.GetIdCard()
|
||||||
if(!I)
|
if(!I)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -44,3 +53,36 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
/datum/tgui_module/tgui_static_data()
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
var/obj/item/modular_computer/host = tgui_host()
|
||||||
|
if(istype(host))
|
||||||
|
. += host.get_header_data()
|
||||||
|
|
||||||
|
/datum/tgui_module/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/obj/item/modular_computer/host = tgui_host()
|
||||||
|
if(istype(host))
|
||||||
|
if(action == "PC_exit")
|
||||||
|
host.kill_program()
|
||||||
|
return TRUE
|
||||||
|
if(action == "PC_shutdown")
|
||||||
|
host.shutdown_computer()
|
||||||
|
return TRUE
|
||||||
|
if(action == "PC_minimize")
|
||||||
|
host.minimize_program(usr)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
// Just a nice little default interact in case the subtypes don't need any special behavior here
|
||||||
|
/datum/tgui_module/ui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if(!ui)
|
||||||
|
ui = new(user, src, tgui_id, name, parent_ui)
|
||||||
|
ui.open()
|
||||||
|
|
||||||
|
/datum/tgui_module/proc/relaymove(mob/user, direction)
|
||||||
|
return FALSE
|
||||||
|
|||||||
102
code/modules/tgui/modules/admin_shuttle_controller.dm
Normal file
102
code/modules/tgui/modules/admin_shuttle_controller.dm
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/* This is an admin tool to control all shuttles, including overmap & classic. */
|
||||||
|
|
||||||
|
/datum/tgui_module/admin_shuttle_controller
|
||||||
|
name = "Admin Shuttle Controller"
|
||||||
|
tgui_id = "AdminShuttleController"
|
||||||
|
|
||||||
|
/datum/tgui_module/admin_shuttle_controller/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
var/list/shuttles = list()
|
||||||
|
for(var/shuttle_name in SSshuttles.shuttles)
|
||||||
|
var/datum/shuttle/S = SSshuttles.shuttles[shuttle_name]
|
||||||
|
shuttles.Add(list(list(
|
||||||
|
"name" = shuttle_name,
|
||||||
|
"ref" = REF(S),
|
||||||
|
"current_location" = S.get_location_name(),
|
||||||
|
"status" = S.moving_status,
|
||||||
|
)))
|
||||||
|
data["shuttles"] = shuttles
|
||||||
|
|
||||||
|
var/list/overmap_ships = list()
|
||||||
|
for(var/ship in SSshuttles.ships)
|
||||||
|
var/obj/effect/overmap/visitable/ship/S = ship
|
||||||
|
overmap_ships.Add(list(list(
|
||||||
|
"name" = S.scanner_name || S.name,
|
||||||
|
"ref" = REF(S),
|
||||||
|
)))
|
||||||
|
data["overmap_ships"] = overmap_ships
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/admin_shuttle_controller/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_admin_state
|
||||||
|
|
||||||
|
/datum/tgui_module/admin_shuttle_controller/ui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("adminobserve")
|
||||||
|
var/datum/shuttle/S = locate(params["ref"])
|
||||||
|
if(istype(S))
|
||||||
|
var/client/C = usr.client
|
||||||
|
if(!isobserver(usr))
|
||||||
|
C.admin_ghost()
|
||||||
|
spawn(2)
|
||||||
|
C.jumptoturf(get_turf(S.current_location))
|
||||||
|
else if(istype(S, /obj/effect/overmap/visitable))
|
||||||
|
var/obj/effect/overmap/visitable/V = S
|
||||||
|
var/client/C = usr.client
|
||||||
|
if(!isobserver(usr))
|
||||||
|
C.admin_ghost()
|
||||||
|
spawn(2)
|
||||||
|
var/atom/target
|
||||||
|
if(LAZYLEN(V.generic_waypoints))
|
||||||
|
target = V.generic_waypoints[1]
|
||||||
|
else if(LAZYLEN(V.restricted_waypoints))
|
||||||
|
target = V.restricted_waypoints[1]
|
||||||
|
else
|
||||||
|
to_chat(C, "<span class='warning'>Unable to jump to [V].</span>")
|
||||||
|
return FALSE
|
||||||
|
var/turf/T = get_turf(target)
|
||||||
|
if(!istype(T))
|
||||||
|
to_chat(C, "<span class='warning'>Unable to jump to [V].</span>")
|
||||||
|
return FALSE
|
||||||
|
C.jumptoturf(T)
|
||||||
|
return TRUE
|
||||||
|
if("classicmove")
|
||||||
|
var/datum/shuttle/S = locate(params["ref"])
|
||||||
|
if(istype(S, /datum/shuttle/autodock/multi))
|
||||||
|
var/datum/shuttle/autodock/multi/shuttle = S
|
||||||
|
var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations()
|
||||||
|
if(dest_key)
|
||||||
|
shuttle.set_destination(dest_key, usr)
|
||||||
|
shuttle.launch(src)
|
||||||
|
else if(istype(S, /datum/shuttle/autodock/overmap))
|
||||||
|
var/datum/shuttle/autodock/overmap/shuttle = S
|
||||||
|
var/list/possible_d = shuttle.get_possible_destinations()
|
||||||
|
var/D
|
||||||
|
if(!LAZYLEN(possible_d))
|
||||||
|
to_chat(usr, "<span class='warning'>There are no possible destinations for [shuttle] ([shuttle.type])</span>")
|
||||||
|
return FALSE
|
||||||
|
D = input("Choose shuttle destination", "Shuttle Destination") as null|anything in possible_d
|
||||||
|
if(D)
|
||||||
|
shuttle.set_destination(possible_d[D])
|
||||||
|
shuttle.launch()
|
||||||
|
else if(istype(S, /datum/shuttle/autodock))
|
||||||
|
var/datum/shuttle/autodock/shuttle = S
|
||||||
|
if(alert(usr, "Are you sure you want to launch [shuttle]?", "Launching Shuttle", "Yes", "No") == "Yes")
|
||||||
|
shuttle.launch(src)
|
||||||
|
else
|
||||||
|
to_chat(usr, "<span class='notice'>The shuttle control panel isn't quite sure how to move [S] ([S?.type]).</span>")
|
||||||
|
return FALSE
|
||||||
|
to_chat(usr, "<span class='notice'>Launching shuttle [S].</span>")
|
||||||
|
return TRUE
|
||||||
|
if("overmap_control")
|
||||||
|
var/obj/effect/overmap/visitable/ship/V = locate(params["ref"])
|
||||||
|
if(istype(V))
|
||||||
|
var/datum/tgui_module/ship/fullmonty/F = new(src, V)
|
||||||
|
F.tgui_interact(usr, null, ui)
|
||||||
|
|
||||||
|
return TRUE
|
||||||
135
code/modules/tgui/modules/agentcard.dm
Normal file
135
code/modules/tgui/modules/agentcard.dm
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/datum/tgui_module/agentcard
|
||||||
|
name = "Agent Card"
|
||||||
|
tgui_id = "AgentCard"
|
||||||
|
|
||||||
|
/datum/tgui_module/agentcard/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
|
||||||
|
if(!istype(S))
|
||||||
|
return list()
|
||||||
|
|
||||||
|
var/list/entries = list()
|
||||||
|
entries += list(list("name" = "Age", "value" = S.age))
|
||||||
|
entries += list(list("name" = "Appearance", "value" = "Set"))
|
||||||
|
entries += list(list("name" = "Assignment", "value" = S.assignment))
|
||||||
|
entries += list(list("name" = "Blood Type", "value" = S.blood_type))
|
||||||
|
entries += list(list("name" = "DNA Hash", "value" = S.dna_hash))
|
||||||
|
entries += list(list("name" = "Fingerprint Hash", "value" = S.fingerprint_hash))
|
||||||
|
entries += list(list("name" = "Name", "value" = S.registered_name))
|
||||||
|
entries += list(list("name" = "Photo", "value" = "Update"))
|
||||||
|
entries += list(list("name" = "Sex", "value" = S.sex))
|
||||||
|
entries += list(list("name" = "Factory Reset", "value" = "Use With Care"))
|
||||||
|
data["entries"] = entries
|
||||||
|
|
||||||
|
data["electronic_warfare"] = S.electronic_warfare
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/agentcard/tgui_status(mob/user, datum/tgui_state/state)
|
||||||
|
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
|
||||||
|
if(!istype(S))
|
||||||
|
return UI_CLOSE
|
||||||
|
if(user != S.registered_user)
|
||||||
|
return UI_CLOSE
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/agentcard/ui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/obj/item/weapon/card/id/syndicate/S = tgui_host()
|
||||||
|
switch(action)
|
||||||
|
if("electronic_warfare")
|
||||||
|
S.electronic_warfare = !S.electronic_warfare
|
||||||
|
to_chat(usr, "<span class='notice'>Electronic warfare [S.electronic_warfare ? "enabled" : "disabled"].</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("age")
|
||||||
|
var/new_age = input(usr,"What age would you like to put on this card?","Agent Card Age", S.age) as null|num
|
||||||
|
if(!isnull(new_age) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
if(new_age < 0)
|
||||||
|
S.age = initial(S.age)
|
||||||
|
else
|
||||||
|
S.age = new_age
|
||||||
|
to_chat(usr, "<span class='notice'>Age has been set to '[S.age]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("appearance")
|
||||||
|
var/datum/card_state/choice = input(usr, "Select the appearance for this card.", "Agent Card Appearance") as null|anything in id_card_states()
|
||||||
|
if(choice && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.icon_state = choice.icon_state
|
||||||
|
S.item_state = choice.item_state
|
||||||
|
to_chat(usr, "<span class='notice'>Appearance changed to [choice].</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("assignment")
|
||||||
|
var/new_job = sanitize(input(usr,"What assignment would you like to put on this card?\nChanging assignment will not grant or remove any access levels.","Agent Card Assignment", S.assignment) as null|text)
|
||||||
|
if(!isnull(new_job) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.assignment = new_job
|
||||||
|
to_chat(usr, "<span class='notice'>Occupation changed to '[new_job]'.</span>")
|
||||||
|
S.update_name()
|
||||||
|
. = TRUE
|
||||||
|
if("bloodtype")
|
||||||
|
var/default = S.blood_type
|
||||||
|
if(default == initial(S.blood_type) && ishuman(usr))
|
||||||
|
var/mob/living/carbon/human/H = usr
|
||||||
|
if(H.dna)
|
||||||
|
default = H.dna.b_type
|
||||||
|
var/new_blood_type = sanitize(input(usr,"What blood type would you like to be written on this card?","Agent Card Blood Type",default) as null|text)
|
||||||
|
if(!isnull(new_blood_type) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.blood_type = new_blood_type
|
||||||
|
to_chat(usr, "<span class='notice'>Blood type changed to '[new_blood_type]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("dnahash")
|
||||||
|
var/default = S.dna_hash
|
||||||
|
if(default == initial(S.dna_hash) && ishuman(usr))
|
||||||
|
var/mob/living/carbon/human/H = usr
|
||||||
|
if(H.dna)
|
||||||
|
default = H.dna.unique_enzymes
|
||||||
|
var/new_dna_hash = sanitize(input(usr,"What DNA hash would you like to be written on this card?","Agent Card DNA Hash",default) as null|text)
|
||||||
|
if(!isnull(new_dna_hash) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.dna_hash = new_dna_hash
|
||||||
|
to_chat(usr, "<span class='notice'>DNA hash changed to '[new_dna_hash]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("fingerprinthash")
|
||||||
|
var/default = S.fingerprint_hash
|
||||||
|
if(default == initial(S.fingerprint_hash) && ishuman(usr))
|
||||||
|
var/mob/living/carbon/human/H = usr
|
||||||
|
if(H.dna)
|
||||||
|
default = md5(H.dna.uni_identity)
|
||||||
|
var/new_fingerprint_hash = sanitize(input(usr,"What fingerprint hash would you like to be written on this card?","Agent Card Fingerprint Hash",default) as null|text)
|
||||||
|
if(!isnull(new_fingerprint_hash) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.fingerprint_hash = new_fingerprint_hash
|
||||||
|
to_chat(usr, "<span class='notice'>Fingerprint hash changed to '[new_fingerprint_hash]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("name")
|
||||||
|
var/new_name = sanitizeName(input(usr,"What name would you like to put on this card?","Agent Card Name", S.registered_name) as null|text)
|
||||||
|
if(!isnull(new_name) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.registered_name = new_name
|
||||||
|
S.update_name()
|
||||||
|
to_chat(usr, "<span class='notice'>Name changed to '[new_name]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("photo")
|
||||||
|
S.set_id_photo(usr)
|
||||||
|
to_chat(usr, "<span class='notice'>Photo changed.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("sex")
|
||||||
|
var/new_sex = sanitize(input(usr,"What sex would you like to put on this card?","Agent Card Sex", S.sex) as null|text)
|
||||||
|
if(!isnull(new_sex) && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.sex = new_sex
|
||||||
|
to_chat(usr, "<span class='notice'>Sex changed to '[new_sex]'.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("factoryreset")
|
||||||
|
if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && tgui_status(usr, state) == UI_INTERACTIVE)
|
||||||
|
S.age = initial(S.age)
|
||||||
|
S.access = syndicate_access.Copy()
|
||||||
|
S.assignment = initial(S.assignment)
|
||||||
|
S.blood_type = initial(S.blood_type)
|
||||||
|
S.dna_hash = initial(S.dna_hash)
|
||||||
|
S.electronic_warfare = initial(S.electronic_warfare)
|
||||||
|
S.fingerprint_hash = initial(S.fingerprint_hash)
|
||||||
|
S.icon_state = initial(S.icon_state)
|
||||||
|
S.name = initial(S.name)
|
||||||
|
S.registered_name = initial(S.registered_name)
|
||||||
|
S.unset_registered_user()
|
||||||
|
S.sex = initial(S.sex)
|
||||||
|
to_chat(usr, "<span class='notice'>All information has been deleted from \the [src].</span>")
|
||||||
|
. = TRUE
|
||||||
143
code/modules/tgui/modules/alarm.dm
Normal file
143
code/modules/tgui/modules/alarm.dm
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/datum/tgui_module/alarm_monitor
|
||||||
|
name = "Alarm monitor"
|
||||||
|
tgui_id = "StationAlertConsole"
|
||||||
|
var/list_cameras = 0 // Whether or not to list camera references. A future goal would be to merge this with the enginering/security camera console. Currently really only for AI-use.
|
||||||
|
var/list/datum/alarm_handler/alarm_handlers // The particular list of alarm handlers this alarm monitor should present to the user.
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/New()
|
||||||
|
..()
|
||||||
|
alarm_handlers = list()
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/all
|
||||||
|
/datum/tgui_module/alarm_monitor/all/New()
|
||||||
|
..()
|
||||||
|
alarm_handlers = SSalarm.all_handlers
|
||||||
|
|
||||||
|
// Subtype for glasses_state
|
||||||
|
/datum/tgui_module/alarm_monitor/all/glasses
|
||||||
|
/datum/tgui_module/alarm_monitor/all/glasses/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_glasses_state
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/all/robot
|
||||||
|
/datum/tgui_module/alarm_monitor/all/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/New()
|
||||||
|
..()
|
||||||
|
alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm)
|
||||||
|
|
||||||
|
// Subtype for glasses_state
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/glasses
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/glasses/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_glasses_state
|
||||||
|
|
||||||
|
// Subtype for nif_state
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/nif
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/nif/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_nif_state
|
||||||
|
|
||||||
|
// Subtype for NTOS
|
||||||
|
/datum/tgui_module/alarm_monitor/engineering/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/security
|
||||||
|
/datum/tgui_module/alarm_monitor/security/New()
|
||||||
|
..()
|
||||||
|
alarm_handlers = list(camera_alarm, motion_alarm)
|
||||||
|
|
||||||
|
// Subtype for glasses_state
|
||||||
|
/datum/tgui_module/alarm_monitor/security/glasses
|
||||||
|
/datum/tgui_module/alarm_monitor/security/glasses/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_glasses_state
|
||||||
|
|
||||||
|
// Subtype for NTOS
|
||||||
|
/datum/tgui_module/alarm_monitor/security/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/register_alarm(var/object, var/procName)
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
AH.register_alarm(object, procName)
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/unregister_alarm(var/object)
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
AH.unregister_alarm(object)
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/all_alarms()
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
var/list/all_alarms = new()
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
all_alarms += AH.visible_alarms(z)
|
||||||
|
|
||||||
|
return all_alarms
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/major_alarms()
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
var/list/all_alarms = new()
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
all_alarms += AH.major_alarms(z)
|
||||||
|
|
||||||
|
return all_alarms
|
||||||
|
|
||||||
|
// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise.
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/has_major_alarms()
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
if(AH.has_major_alarms(z))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/proc/minor_alarms()
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
var/list/all_alarms = new()
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
all_alarms += AH.minor_alarms(z)
|
||||||
|
|
||||||
|
return all_alarms
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
// Camera stuff is AI only.
|
||||||
|
// If you're not an AI, this is a read-only UI.
|
||||||
|
if(!isAI(usr))
|
||||||
|
return
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("switchTo")
|
||||||
|
var/obj/machinery/camera/C = locate(params["camera"]) in cameranet.cameras
|
||||||
|
if(!C)
|
||||||
|
return
|
||||||
|
|
||||||
|
usr.switch_to_camera(C)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
/datum/tgui_module/alarm_monitor/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
|
||||||
|
var/categories[0]
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
for(var/datum/alarm_handler/AH in alarm_handlers)
|
||||||
|
categories[++categories.len] = list("category" = AH.category, "alarms" = list())
|
||||||
|
for(var/datum/alarm/A in AH.visible_alarms(z))
|
||||||
|
var/cameras[0]
|
||||||
|
var/lost_sources[0]
|
||||||
|
|
||||||
|
if(isAI(user))
|
||||||
|
for(var/obj/machinery/camera/C in A.cameras())
|
||||||
|
cameras[++cameras.len] = C.tgui_structure()
|
||||||
|
for(var/datum/alarm_source/AS in A.sources)
|
||||||
|
if(!AS.source)
|
||||||
|
lost_sources[++lost_sources.len] = AS.source_name
|
||||||
|
|
||||||
|
categories[categories.len]["alarms"] += list(list(
|
||||||
|
"name" = "[A.alarm_name()]" + "[A.max_severity() > 1 ? "(MAJOR)" : ""]",
|
||||||
|
"origin_lost" = A.origin == null,
|
||||||
|
"has_cameras" = cameras.len,
|
||||||
|
"cameras" = cameras,
|
||||||
|
"lost_sources" = lost_sources.len ? sanitize(english_list(lost_sources, nothing_text = "", and_text = ", ")) : ""))
|
||||||
|
data["categories"] = categories
|
||||||
|
|
||||||
|
return data
|
||||||
560
code/modules/tgui/modules/appearance_changer.dm
Normal file
560
code/modules/tgui/modules/appearance_changer.dm
Normal file
@@ -0,0 +1,560 @@
|
|||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer
|
||||||
|
name = "Appearance Editor"
|
||||||
|
tgui_id = "AppearanceChanger"
|
||||||
|
var/flags = APPEARANCE_ALL_HAIR
|
||||||
|
var/mob/living/carbon/human/owner = null
|
||||||
|
var/list/valid_species = list()
|
||||||
|
var/list/valid_hairstyles = list()
|
||||||
|
var/list/valid_facial_hairstyles = list()
|
||||||
|
|
||||||
|
var/check_whitelist
|
||||||
|
var/list/whitelist
|
||||||
|
var/list/blacklist
|
||||||
|
|
||||||
|
var/customize_usr = FALSE
|
||||||
|
|
||||||
|
// Stuff needed to render the map
|
||||||
|
var/map_name
|
||||||
|
var/obj/screen/map_view/cam_screen
|
||||||
|
var/list/cam_plane_masters
|
||||||
|
var/obj/screen/background/cam_background
|
||||||
|
var/obj/screen/skybox/local_skybox
|
||||||
|
// Stuff for moving cameras
|
||||||
|
var/turf/last_camera_turf
|
||||||
|
|
||||||
|
var/list/valid_earstyles = list()
|
||||||
|
var/list/valid_tailstyles = list()
|
||||||
|
var/list/valid_wingstyles = list()
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/New(
|
||||||
|
var/host,
|
||||||
|
mob/living/carbon/human/H,
|
||||||
|
check_species_whitelist = 1,
|
||||||
|
list/species_whitelist = list(),
|
||||||
|
list/species_blacklist = list())
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
map_name = "appearance_changer_[REF(src)]_map"
|
||||||
|
// Initialize map objects
|
||||||
|
cam_screen = new
|
||||||
|
cam_screen.name = "screen"
|
||||||
|
cam_screen.assigned_map = map_name
|
||||||
|
cam_screen.del_on_map_removal = FALSE
|
||||||
|
cam_screen.screen_loc = "[map_name]:1,1"
|
||||||
|
|
||||||
|
cam_plane_masters = get_tgui_plane_masters()
|
||||||
|
|
||||||
|
for(var/plane in cam_plane_masters)
|
||||||
|
var/obj/screen/instance = plane
|
||||||
|
instance.assigned_map = map_name
|
||||||
|
instance.del_on_map_removal = FALSE
|
||||||
|
instance.screen_loc = "[map_name]:CENTER"
|
||||||
|
|
||||||
|
local_skybox = new()
|
||||||
|
local_skybox.assigned_map = map_name
|
||||||
|
local_skybox.del_on_map_removal = FALSE
|
||||||
|
local_skybox.screen_loc = "[map_name]:CENTER,CENTER"
|
||||||
|
cam_plane_masters += local_skybox
|
||||||
|
|
||||||
|
cam_background = new
|
||||||
|
cam_background.assigned_map = map_name
|
||||||
|
cam_background.del_on_map_removal = FALSE
|
||||||
|
update_active_camera_screen()
|
||||||
|
|
||||||
|
owner = H
|
||||||
|
if(owner)
|
||||||
|
GLOB.moved_event.register(owner, src, .proc/update_active_camera_screen)
|
||||||
|
check_whitelist = check_species_whitelist
|
||||||
|
whitelist = species_whitelist
|
||||||
|
blacklist = species_blacklist
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/Destroy()
|
||||||
|
GLOB.moved_event.unregister(owner, src, .proc/update_active_camera_screen)
|
||||||
|
last_camera_turf = null
|
||||||
|
qdel(cam_screen)
|
||||||
|
QDEL_LIST(cam_plane_masters)
|
||||||
|
qdel(cam_background)
|
||||||
|
cut_data()
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/ui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("race")
|
||||||
|
if(can_change(APPEARANCE_RACE) && (params["race"] in valid_species))
|
||||||
|
if(target.change_species(params["race"]))
|
||||||
|
cut_data()
|
||||||
|
generate_data(usr)
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_RACE)
|
||||||
|
return 1
|
||||||
|
if("gender")
|
||||||
|
if(can_change(APPEARANCE_GENDER) && (params["gender"] in get_genders()))
|
||||||
|
if(target.change_gender(params["gender"]))
|
||||||
|
cut_data()
|
||||||
|
generate_data(usr)
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_GENDER)
|
||||||
|
return 1
|
||||||
|
if("gender_id")
|
||||||
|
if(can_change(APPEARANCE_GENDER) && (params["gender_id"] in all_genders_define_list))
|
||||||
|
target.identifying_gender = params["gender_id"]
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_GENDER_ID)
|
||||||
|
return 1
|
||||||
|
if("skin_tone")
|
||||||
|
if(can_change_skin_tone())
|
||||||
|
var/new_s_tone = input(usr, "Choose your character's skin-tone:\n(Light 1 - 220 Dark)", "Skin Tone", -target.s_tone + 35) as num|null
|
||||||
|
if(isnum(new_s_tone) && can_still_topic(usr, state))
|
||||||
|
new_s_tone = 35 - max(min( round(new_s_tone), 220),1)
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_SKINTONE)
|
||||||
|
return target.change_skin_tone(new_s_tone)
|
||||||
|
if("skin_color")
|
||||||
|
if(can_change_skin_color())
|
||||||
|
var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", rgb(target.r_skin, target.g_skin, target.b_skin)) as color|null
|
||||||
|
if(new_skin && can_still_topic(usr, state))
|
||||||
|
var/r_skin = hex2num(copytext(new_skin, 2, 4))
|
||||||
|
var/g_skin = hex2num(copytext(new_skin, 4, 6))
|
||||||
|
var/b_skin = hex2num(copytext(new_skin, 6, 8))
|
||||||
|
if(target.change_skin_color(r_skin, g_skin, b_skin))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_SKINCOLOR)
|
||||||
|
return 1
|
||||||
|
if("hair")
|
||||||
|
if(can_change(APPEARANCE_HAIR) && (params["hair"] in valid_hairstyles))
|
||||||
|
if(target.change_hair(params["hair"]))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||||
|
return 1
|
||||||
|
if("hair_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select hair color.", "Hair Color", rgb(target.r_hair, target.g_hair, target.b_hair)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
var/r_hair = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
var/g_hair = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
var/b_hair = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
if(target.change_hair_color(r_hair, g_hair, b_hair))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("facial_hair")
|
||||||
|
if(can_change(APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles))
|
||||||
|
if(target.change_facial_hair(params["facial_hair"]))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_F_HAIRSTYLE)
|
||||||
|
return 1
|
||||||
|
if("facial_hair_color")
|
||||||
|
if(can_change(APPEARANCE_FACIAL_HAIR_COLOR))
|
||||||
|
var/new_facial = input("Please select facial hair color.", "Facial Hair Color", rgb(target.r_facial, target.g_facial, target.b_facial)) as color|null
|
||||||
|
if(new_facial && can_still_topic(usr, state))
|
||||||
|
var/r_facial = hex2num(copytext(new_facial, 2, 4))
|
||||||
|
var/g_facial = hex2num(copytext(new_facial, 4, 6))
|
||||||
|
var/b_facial = hex2num(copytext(new_facial, 6, 8))
|
||||||
|
if(target.change_facial_hair_color(r_facial, g_facial, b_facial))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_F_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("eye_color")
|
||||||
|
if(can_change(APPEARANCE_EYE_COLOR))
|
||||||
|
var/new_eyes = input("Please select eye color.", "Eye Color", rgb(target.r_eyes, target.g_eyes, target.b_eyes)) as color|null
|
||||||
|
if(new_eyes && can_still_topic(usr, state))
|
||||||
|
var/r_eyes = hex2num(copytext(new_eyes, 2, 4))
|
||||||
|
var/g_eyes = hex2num(copytext(new_eyes, 4, 6))
|
||||||
|
var/b_eyes = hex2num(copytext(new_eyes, 6, 8))
|
||||||
|
if(target.change_eye_color(r_eyes, g_eyes, b_eyes))
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_EYES)
|
||||||
|
return 1
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
if("ear")
|
||||||
|
if(can_change(APPEARANCE_ALL_HAIR))
|
||||||
|
var/datum/sprite_accessory/ears/instance = locate(params["ref"])
|
||||||
|
if(params["clear"])
|
||||||
|
instance = null
|
||||||
|
if(!istype(instance) && !params["clear"])
|
||||||
|
return FALSE
|
||||||
|
owner.ear_style = instance
|
||||||
|
owner.update_hair()
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||||
|
return TRUE
|
||||||
|
if("ears_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select ear color.", "Ear Color", rgb(target.r_ears, target.g_ears, target.b_ears)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_ears = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_ears = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_ears = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_hair()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("ears2_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select secondary ear color.", "2nd Ear Color", rgb(target.r_ears2, target.g_ears2, target.b_ears2)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_ears2 = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_ears2 = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_ears2 = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_hair()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("tail")
|
||||||
|
if(can_change(APPEARANCE_ALL_HAIR))
|
||||||
|
var/datum/sprite_accessory/tail/instance = locate(params["ref"])
|
||||||
|
if(params["clear"])
|
||||||
|
instance = null
|
||||||
|
if(!istype(instance) && !params["clear"])
|
||||||
|
return FALSE
|
||||||
|
owner.tail_style = instance
|
||||||
|
owner.update_tail_showing()
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||||
|
return TRUE
|
||||||
|
if("tail_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select tail color.", "Tail Color", rgb(target.r_tail, target.g_tail, target.b_tail)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_tail = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_tail = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_tail = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_tail_showing()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("tail2_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select secondary tail color.", "2nd Tail Color", rgb(target.r_tail2, target.g_tail2, target.b_tail2)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_tail2 = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_tail2 = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_tail2 = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_tail_showing()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("wing")
|
||||||
|
if(can_change(APPEARANCE_ALL_HAIR))
|
||||||
|
var/datum/sprite_accessory/wing/instance = locate(params["ref"])
|
||||||
|
if(params["clear"])
|
||||||
|
instance = null
|
||||||
|
if(!istype(instance) && !params["clear"])
|
||||||
|
return FALSE
|
||||||
|
owner.wing_style = instance
|
||||||
|
owner.update_wing_showing()
|
||||||
|
update_dna()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||||
|
return TRUE
|
||||||
|
if("wing_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select wing color.", "Wing Color", rgb(target.r_wing, target.g_wing, target.b_wing)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_wing = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_wing = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_wing = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_wing_showing()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
if("wing2_color")
|
||||||
|
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||||
|
var/new_hair = input("Please select secondary wing color.", "2nd Wing Color", rgb(target.r_wing2, target.g_wing2, target.b_wing2)) as color|null
|
||||||
|
if(new_hair && can_still_topic(usr, state))
|
||||||
|
target.r_wing2 = hex2num(copytext(new_hair, 2, 4))
|
||||||
|
target.g_wing2 = hex2num(copytext(new_hair, 4, 6))
|
||||||
|
target.b_wing2 = hex2num(copytext(new_hair, 6, 8))
|
||||||
|
update_dna()
|
||||||
|
owner.update_wing_showing()
|
||||||
|
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||||
|
return 1
|
||||||
|
// VOREStation Add End
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/ui_interact(mob/user, datum/tgui/ui = null, datum/tgui/parent_ui = null, datum/tgui_state/custom_state)
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(user))
|
||||||
|
return TRUE
|
||||||
|
target = user
|
||||||
|
|
||||||
|
if(!target || !target.species)
|
||||||
|
return
|
||||||
|
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
update_active_camera_screen()
|
||||||
|
if(!ui)
|
||||||
|
// Register map objects
|
||||||
|
user.client.register_map_obj(cam_screen)
|
||||||
|
for(var/plane in cam_plane_masters)
|
||||||
|
user.client.register_map_obj(plane)
|
||||||
|
user.client.register_map_obj(cam_background)
|
||||||
|
// Open UI
|
||||||
|
ui = new(user, src, tgui_id, name)
|
||||||
|
ui.open()
|
||||||
|
if(custom_state)
|
||||||
|
ui.set_state(custom_state)
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/tgui_static_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
generate_data(usr)
|
||||||
|
|
||||||
|
if(can_change(APPEARANCE_RACE))
|
||||||
|
var/species[0]
|
||||||
|
for(var/specimen in valid_species)
|
||||||
|
species[++species.len] = list("specimen" = specimen)
|
||||||
|
data["species"] = species
|
||||||
|
|
||||||
|
if(can_change(APPEARANCE_HAIR))
|
||||||
|
var/hair_styles[0]
|
||||||
|
for(var/hair_style in valid_hairstyles)
|
||||||
|
hair_styles[++hair_styles.len] = list("hairstyle" = hair_style)
|
||||||
|
data["hair_styles"] = hair_styles
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
data["ear_styles"] = valid_earstyles
|
||||||
|
data["tail_styles"] = valid_tailstyles
|
||||||
|
data["wing_styles"] = valid_wingstyles
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
if(can_change(APPEARANCE_FACIAL_HAIR))
|
||||||
|
var/facial_hair_styles[0]
|
||||||
|
for(var/facial_hair_style in valid_facial_hairstyles)
|
||||||
|
facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_style)
|
||||||
|
data["facial_hair_styles"] = facial_hair_styles
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
generate_data(user)
|
||||||
|
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
data["name"] = target.name
|
||||||
|
data["specimen"] = target.species.name
|
||||||
|
data["gender"] = target.gender
|
||||||
|
data["gender_id"] = target.identifying_gender
|
||||||
|
data["change_race"] = can_change(APPEARANCE_RACE)
|
||||||
|
|
||||||
|
data["change_gender"] = can_change(APPEARANCE_GENDER)
|
||||||
|
if(data["change_gender"])
|
||||||
|
var/genders[0]
|
||||||
|
for(var/gender in get_genders())
|
||||||
|
genders[++genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender)
|
||||||
|
data["genders"] = genders
|
||||||
|
var/id_genders[0]
|
||||||
|
for(var/gender in all_genders_define_list)
|
||||||
|
id_genders[++id_genders.len] = list("gender_name" = gender2text(gender), "gender_key" = gender)
|
||||||
|
data["id_genders"] = id_genders
|
||||||
|
|
||||||
|
data["change_hair"] = can_change(APPEARANCE_HAIR)
|
||||||
|
if(data["change_hair"])
|
||||||
|
data["hair_style"] = target.h_style
|
||||||
|
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
data["ear_style"] = target.ear_style
|
||||||
|
data["tail_style"] = target.tail_style
|
||||||
|
data["wing_style"] = target.wing_style
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR)
|
||||||
|
if(data["change_facial_hair"])
|
||||||
|
data["facial_hair_style"] = target.f_style
|
||||||
|
|
||||||
|
data["change_skin_tone"] = can_change_skin_tone()
|
||||||
|
data["change_skin_color"] = can_change_skin_color()
|
||||||
|
if(data["change_skin_color"])
|
||||||
|
data["skin_color"] = rgb(target.r_skin, target.g_skin, target.b_skin)
|
||||||
|
|
||||||
|
data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR)
|
||||||
|
if(data["change_eye_color"])
|
||||||
|
data["eye_color"] = rgb(target.r_eyes, target.g_eyes, target.b_eyes)
|
||||||
|
|
||||||
|
data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR)
|
||||||
|
if(data["change_hair_color"])
|
||||||
|
data["hair_color"] = rgb(target.r_hair, target.g_hair, target.b_hair)
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
data["ears_color"] = rgb(target.r_ears, target.g_ears, target.b_ears)
|
||||||
|
data["ears2_color"] = rgb(target.r_ears2, target.g_ears2, target.b_ears2)
|
||||||
|
data["tail_color"] = rgb(target.r_tail, target.g_tail, target.b_tail)
|
||||||
|
data["tail2_color"] = rgb(target.r_tail2, target.g_tail2, target.b_tail2)
|
||||||
|
data["wing_color"] = rgb(target.r_wing, target.g_wing, target.b_wing)
|
||||||
|
data["wing2_color"] = rgb(target.r_wing2, target.g_wing2, target.b_wing2)
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR)
|
||||||
|
if(data["change_facial_hair_color"])
|
||||||
|
data["facial_hair_color"] = rgb(target.r_facial, target.g_facial, target.b_facial)
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/tgui_static_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
data["mapRef"] = map_name
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/update_active_camera_screen()
|
||||||
|
var/turf/newturf = get_turf(customize_usr ? tgui_host() : owner)
|
||||||
|
if(newturf == last_camera_turf)
|
||||||
|
return
|
||||||
|
|
||||||
|
last_camera_turf = newturf
|
||||||
|
|
||||||
|
var/list/visible_turfs = list()
|
||||||
|
for(var/turf/T in range(1, newturf))
|
||||||
|
visible_turfs += T
|
||||||
|
|
||||||
|
cam_screen.vis_contents = visible_turfs
|
||||||
|
cam_background.icon_state = "clear"
|
||||||
|
cam_background.fill_rect(1, 1, 3, 3)
|
||||||
|
|
||||||
|
local_skybox.cut_overlays()
|
||||||
|
local_skybox.add_overlay(SSskybox.get_skybox(get_z(newturf)))
|
||||||
|
local_skybox.scale_to_view(3)
|
||||||
|
local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - newturf.x, (world.maxy>>1) - newturf.y)
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/update_dna()
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
if(target && (flags & APPEARANCE_UPDATE_DNA))
|
||||||
|
target.update_dna()
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/can_change(var/flag)
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
return target && (flags & flag)
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/can_change_skin_tone()
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_TONE
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/can_change_skin_color()
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
|
||||||
|
return target && (flags & APPEARANCE_SKIN) && target.species.appearance_flags & HAS_SKIN_COLOR
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/cut_data()
|
||||||
|
// Making the assumption that the available species remain constant
|
||||||
|
valid_hairstyles.Cut()
|
||||||
|
valid_facial_hairstyles.Cut()
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
valid_earstyles.Cut()
|
||||||
|
valid_tailstyles.Cut()
|
||||||
|
valid_wingstyles.Cut()
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/generate_data(mob/user)
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(user))
|
||||||
|
return TRUE
|
||||||
|
target = user
|
||||||
|
if(!target)
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!LAZYLEN(valid_species))
|
||||||
|
valid_species = target.generate_valid_species(check_whitelist, whitelist, blacklist)
|
||||||
|
|
||||||
|
if(!LAZYLEN(valid_hairstyles) || !LAZYLEN(valid_facial_hairstyles))
|
||||||
|
valid_hairstyles = target.generate_valid_hairstyles(check_gender = 0)
|
||||||
|
valid_facial_hairstyles = target.generate_valid_facial_hairstyles()
|
||||||
|
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
if(!LAZYLEN(valid_earstyles))
|
||||||
|
for(var/path in ear_styles_list)
|
||||||
|
var/datum/sprite_accessory/ears/instance = ear_styles_list[path]
|
||||||
|
if(can_use_sprite(instance, target, user))
|
||||||
|
valid_earstyles.Add(list(list(
|
||||||
|
"name" = instance.name,
|
||||||
|
"instance" = REF(instance),
|
||||||
|
"color" = !!instance.do_colouration,
|
||||||
|
"second_color" = !!instance.extra_overlay,
|
||||||
|
)))
|
||||||
|
|
||||||
|
if(!LAZYLEN(valid_tailstyles))
|
||||||
|
for(var/path in tail_styles_list)
|
||||||
|
var/datum/sprite_accessory/tail/instance = tail_styles_list[path]
|
||||||
|
if(can_use_sprite(instance, target, user))
|
||||||
|
valid_tailstyles.Add(list(list(
|
||||||
|
"name" = instance.name,
|
||||||
|
"instance" = REF(instance),
|
||||||
|
"color" = !!instance.do_colouration,
|
||||||
|
"second_color" = !!instance.extra_overlay,
|
||||||
|
)))
|
||||||
|
|
||||||
|
if(!LAZYLEN(valid_wingstyles))
|
||||||
|
for(var/path in wing_styles_list)
|
||||||
|
var/datum/sprite_accessory/wing/instance = wing_styles_list[path]
|
||||||
|
if(can_use_sprite(instance, target, user))
|
||||||
|
valid_wingstyles.Add(list(list(
|
||||||
|
"name" = instance.name,
|
||||||
|
"instance" = REF(instance),
|
||||||
|
"color" = !!instance.do_colouration,
|
||||||
|
"second_color" = !!instance.extra_overlay,
|
||||||
|
)))
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/proc/get_genders()
|
||||||
|
var/mob/living/carbon/human/target = owner
|
||||||
|
if(customize_usr)
|
||||||
|
if(!ishuman(usr))
|
||||||
|
return TRUE
|
||||||
|
target = usr
|
||||||
|
var/datum/species/S = target.species
|
||||||
|
var/list/possible_genders = S.genders
|
||||||
|
if(!target.internal_organs_by_name["cell"])
|
||||||
|
return possible_genders
|
||||||
|
possible_genders = possible_genders.Copy()
|
||||||
|
possible_genders |= NEUTER
|
||||||
|
return possible_genders
|
||||||
|
|
||||||
|
// Used for subtypes to handle messaging or whatever.
|
||||||
|
/datum/tgui_module/appearance_changer/proc/changed_hook(flag)
|
||||||
|
return
|
||||||
|
|
||||||
|
// VOREStation Add - Ears/Tails/Wings
|
||||||
|
/datum/tgui_module/appearance_changer/proc/can_use_sprite(datum/sprite_accessory/X, mob/living/carbon/human/target, mob/user)
|
||||||
|
if(X.apply_restrictions && !(target.species.name in X.species_allowed))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(LAZYLEN(X.ckeys_allowed) && !(user?.ckey in X.ckeys_allowed) && !(target.ckey in X.ckeys_allowed))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
return TRUE
|
||||||
|
// VOREStation Add End
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/mirror
|
||||||
|
name = "SalonPro Nano-Mirror™"
|
||||||
|
flags = APPEARANCE_ALL_HAIR
|
||||||
|
customize_usr = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/mirror/coskit
|
||||||
|
name = "SalonPro Porta-Makeover Deluxe™"
|
||||||
45
code/modules/tgui/modules/appearance_changer_vr.dm
Normal file
45
code/modules/tgui/modules/appearance_changer_vr.dm
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/datum/tgui_module/appearance_changer/vore
|
||||||
|
name = "Appearance Editor (Vore)"
|
||||||
|
flags = APPEARANCE_ALL
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/vore/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_conscious_state
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/vore/tgui_status(mob/user, datum/tgui_state/state)
|
||||||
|
if(!isbelly(owner.loc))
|
||||||
|
return UI_CLOSE
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/vore/update_active_camera_screen()
|
||||||
|
cam_screen.vis_contents = list(owner)
|
||||||
|
cam_background.icon_state = "clear"
|
||||||
|
cam_background.fill_rect(1, 1, 1, 1)
|
||||||
|
local_skybox.cut_overlays()
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/vore/tgui_close(mob/user)
|
||||||
|
. = ..()
|
||||||
|
QDEL_IN(src, 1)
|
||||||
|
|
||||||
|
/datum/tgui_module/appearance_changer/vore/changed_hook(flag)
|
||||||
|
var/mob/living/carbon/human/M = owner
|
||||||
|
var/mob/living/O = usr
|
||||||
|
|
||||||
|
switch(flag)
|
||||||
|
if(APPEARANCECHANGER_CHANGED_RACE)
|
||||||
|
to_chat(M, "<span class='notice'>You lose sensation of your body, feeling only the warmth of everything around you... </span>")
|
||||||
|
to_chat(O, "<span class='notice'>Your body shifts as you make dramatic changes to your captive's body.</span>")
|
||||||
|
if(APPEARANCECHANGER_CHANGED_GENDER)
|
||||||
|
to_chat(M, "<span class='notice'>Your body feels very strange...</span>")
|
||||||
|
to_chat(O, "<span class='notice'>You feel strange as you alter your captive's gender.</span>")
|
||||||
|
if(APPEARANCECHANGER_CHANGED_GENDER_ID)
|
||||||
|
to_chat(M, "<span class='notice'>You start to feel... [capitalize(M.gender)]?</span>")
|
||||||
|
to_chat(O, "<span class='notice'>You feel strange as you alter your captive's gender identity.</span>")
|
||||||
|
if(APPEARANCECHANGER_CHANGED_SKINTONE, APPEARANCECHANGER_CHANGED_SKINCOLOR)
|
||||||
|
to_chat(M, "<span class='notice'>Your body tingles all over...</span>")
|
||||||
|
to_chat(O, "<span class='notice'>You tingle as you make noticeable changes to your captive's body.</span>")
|
||||||
|
if(APPEARANCECHANGER_CHANGED_HAIRSTYLE, APPEARANCECHANGER_CHANGED_HAIRCOLOR, APPEARANCECHANGER_CHANGED_F_HAIRSTYLE, APPEARANCECHANGER_CHANGED_F_HAIRCOLOR)
|
||||||
|
to_chat(M, "<span class='notice'>Your body tingles all over...</span>")
|
||||||
|
to_chat(O, "<span class='notice'>You tingle as you make noticeable changes to your captive's body.</span>")
|
||||||
|
if(APPEARANCECHANGER_CHANGED_EYES)
|
||||||
|
to_chat(M, "<span class='notice'>You feel lightheaded and drowsy...</span>")
|
||||||
|
to_chat(O, "<span class='notice'>You feel warm as you make subtle changes to your captive's body.</span>")
|
||||||
115
code/modules/tgui/modules/atmos_control.dm
Normal file
115
code/modules/tgui/modules/atmos_control.dm
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/datum/tgui_module/atmos_control
|
||||||
|
name = "Atmospherics Control"
|
||||||
|
tgui_id = "AtmosControl"
|
||||||
|
var/obj/access = new()
|
||||||
|
var/emagged = 0
|
||||||
|
var/ui_ref
|
||||||
|
var/list/monitored_alarms = list()
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids)
|
||||||
|
..()
|
||||||
|
access.req_access = req_access
|
||||||
|
access.req_one_access = req_one_access
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/ui_act(action, params, datum/tgui/ui)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("alarm")
|
||||||
|
if(ui_ref)
|
||||||
|
var/obj/machinery/alarm/alarm = locate(params["alarm"]) in (monitored_alarms.len ? monitored_alarms : machines)
|
||||||
|
if(alarm)
|
||||||
|
var/datum/tgui_state/TS = generate_state(alarm)
|
||||||
|
alarm.tgui_interact(usr, parent_ui = ui_ref, state = TS)
|
||||||
|
return 1
|
||||||
|
if("setZLevel")
|
||||||
|
ui.set_map_z_level(params["mapZLevel"])
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/ui_assets(mob/user)
|
||||||
|
return list(
|
||||||
|
get_asset_datum(/datum/asset/simple/nanomaps),
|
||||||
|
)
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/ui_interact(mob/user, datum/tgui/ui = null)
|
||||||
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
|
if(!ui)
|
||||||
|
ui = new(user, src, tgui_id, name)
|
||||||
|
ui.autoupdate = TRUE
|
||||||
|
ui.open()
|
||||||
|
ui_ref = ui
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/tgui_static_data(mob/user)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
var/z = get_z(user)
|
||||||
|
var/list/map_levels = using_map.get_map_levels(z)
|
||||||
|
|
||||||
|
// TODO: Move these to a cache, similar to cameras
|
||||||
|
var/alarms[0]
|
||||||
|
for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines))
|
||||||
|
if(!monitored_alarms.len && alarm.alarms_hidden)
|
||||||
|
continue
|
||||||
|
if(!(alarm.z in map_levels))
|
||||||
|
continue
|
||||||
|
alarms[++alarms.len] = list(
|
||||||
|
"name" = sanitize(alarm.name),
|
||||||
|
"ref"= "\ref[alarm]",
|
||||||
|
"danger" = max(alarm.danger_level, alarm.alarm_area.atmosalm),
|
||||||
|
"x" = alarm.x,
|
||||||
|
"y" = alarm.y,
|
||||||
|
"z" = alarm.z)
|
||||||
|
.["alarms"] = alarms
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
|
||||||
|
var/z = get_z(user)
|
||||||
|
var/list/map_levels = using_map.get_map_levels(z)
|
||||||
|
data["map_levels"] = map_levels
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/tgui_close()
|
||||||
|
. = ..()
|
||||||
|
ui_ref = null
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/proc/generate_state(air_alarm)
|
||||||
|
var/datum/tgui_state/air_alarm_remote/state = new()
|
||||||
|
state.atmos_control = src
|
||||||
|
state.air_alarm = air_alarm
|
||||||
|
return state
|
||||||
|
|
||||||
|
/datum/tgui_state/air_alarm_remote
|
||||||
|
var/datum/tgui_module/atmos_control/atmos_control = null
|
||||||
|
var/obj/machinery/alarm/air_alarm = null
|
||||||
|
|
||||||
|
/datum/tgui_state/air_alarm_remote/can_use_topic(src_object, mob/user)
|
||||||
|
if(!atmos_control.ui_ref)
|
||||||
|
qdel(src)
|
||||||
|
return UI_CLOSE
|
||||||
|
if(has_access(user))
|
||||||
|
return UI_INTERACTIVE
|
||||||
|
return UI_UPDATE
|
||||||
|
|
||||||
|
/datum/tgui_state/air_alarm_remote/proc/has_access(var/mob/user)
|
||||||
|
return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO) || (access_ce in user.GetAccess()))
|
||||||
|
|
||||||
|
/datum/tgui_state/air_alarm_remote/Destroy()
|
||||||
|
atmos_control = null
|
||||||
|
air_alarm = null
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/atmos_control/robot
|
||||||
|
/datum/tgui_module/atmos_control/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
@@ -18,10 +18,8 @@
|
|||||||
var/obj/screen/background/cam_background
|
var/obj/screen/background/cam_background
|
||||||
var/obj/screen/background/cam_foreground
|
var/obj/screen/background/cam_foreground
|
||||||
var/obj/screen/skybox/local_skybox
|
var/obj/screen/skybox/local_skybox
|
||||||
// Needed for moving camera support
|
// Stuff for moving cameras
|
||||||
var/camera_diff_x = -1
|
var/turf/last_camera_turf
|
||||||
var/camera_diff_y = -1
|
|
||||||
var/camera_diff_z = -1
|
|
||||||
|
|
||||||
/datum/tgui_module/camera/New(host, list/network_computer)
|
/datum/tgui_module/camera/New(host, list/network_computer)
|
||||||
. = ..()
|
. = ..()
|
||||||
@@ -36,14 +34,14 @@
|
|||||||
cam_screen.assigned_map = map_name
|
cam_screen.assigned_map = map_name
|
||||||
cam_screen.del_on_map_removal = FALSE
|
cam_screen.del_on_map_removal = FALSE
|
||||||
cam_screen.screen_loc = "[map_name]:1,1"
|
cam_screen.screen_loc = "[map_name]:1,1"
|
||||||
cam_plane_masters = list()
|
|
||||||
|
|
||||||
for(var/plane in subtypesof(/obj/screen/plane_master))
|
cam_plane_masters = get_tgui_plane_masters()
|
||||||
var/obj/screen/instance = new plane()
|
|
||||||
|
for(var/plane in cam_plane_masters)
|
||||||
|
var/obj/screen/instance = plane
|
||||||
instance.assigned_map = map_name
|
instance.assigned_map = map_name
|
||||||
instance.del_on_map_removal = FALSE
|
instance.del_on_map_removal = FALSE
|
||||||
instance.screen_loc = "[map_name]:CENTER"
|
instance.screen_loc = "[map_name]:CENTER"
|
||||||
cam_plane_masters += instance
|
|
||||||
|
|
||||||
local_skybox = new()
|
local_skybox = new()
|
||||||
local_skybox.assigned_map = map_name
|
local_skybox.assigned_map = map_name
|
||||||
@@ -70,6 +68,10 @@
|
|||||||
cam_foreground.add_overlay(noise)
|
cam_foreground.add_overlay(noise)
|
||||||
|
|
||||||
/datum/tgui_module/camera/Destroy()
|
/datum/tgui_module/camera/Destroy()
|
||||||
|
if(active_camera)
|
||||||
|
GLOB.moved_event.unregister(active_camera, src, .proc/update_active_camera_screen)
|
||||||
|
active_camera = null
|
||||||
|
last_camera_turf = null
|
||||||
qdel(cam_screen)
|
qdel(cam_screen)
|
||||||
QDEL_LIST(cam_plane_masters)
|
QDEL_LIST(cam_plane_masters)
|
||||||
qdel(cam_background)
|
qdel(cam_background)
|
||||||
@@ -91,7 +93,7 @@
|
|||||||
concurrent_users += user_ref
|
concurrent_users += user_ref
|
||||||
// Turn on the console
|
// Turn on the console
|
||||||
if(length(concurrent_users) == 1 && is_living)
|
if(length(concurrent_users) == 1 && is_living)
|
||||||
playsound(ui_host(), 'sound/machines/terminal_on.ogg', 25, FALSE)
|
playsound(tgui_host(), 'sound/machines/terminal_on.ogg', 25, FALSE)
|
||||||
// Register map objects
|
// Register map objects
|
||||||
user.client.register_map_obj(cam_screen)
|
user.client.register_map_obj(cam_screen)
|
||||||
for(var/plane in cam_plane_masters)
|
for(var/plane in cam_plane_masters)
|
||||||
@@ -106,15 +108,14 @@
|
|||||||
var/list/data = list()
|
var/list/data = list()
|
||||||
data["activeCamera"] = null
|
data["activeCamera"] = null
|
||||||
if(active_camera)
|
if(active_camera)
|
||||||
differential_check()
|
|
||||||
data["activeCamera"] = list(
|
data["activeCamera"] = list(
|
||||||
name = active_camera.c_tag,
|
name = active_camera.c_tag,
|
||||||
status = active_camera.status,
|
status = active_camera.status,
|
||||||
)
|
)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
/datum/tgui_module/camera/ui_static_data(mob/user)
|
/datum/tgui_module/camera/tgui_static_data(mob/user)
|
||||||
var/list/data = list()
|
var/list/data = ..()
|
||||||
data["mapRef"] = map_name
|
data["mapRef"] = map_name
|
||||||
var/list/cameras = get_available_cameras(user)
|
var/list/cameras = get_available_cameras(user)
|
||||||
data["cameras"] = list()
|
data["cameras"] = list()
|
||||||
@@ -130,44 +131,70 @@
|
|||||||
|
|
||||||
/datum/tgui_module/camera/ui_act(action, params)
|
/datum/tgui_module/camera/ui_act(action, params)
|
||||||
if(..())
|
if(..())
|
||||||
return
|
return TRUE
|
||||||
|
|
||||||
|
if(action && !issilicon(usr))
|
||||||
|
playsound(tgui_host(), "terminal_type", 50, 1)
|
||||||
|
|
||||||
if(action == "switch_camera")
|
if(action == "switch_camera")
|
||||||
var/c_tag = params["name"]
|
var/c_tag = params["name"]
|
||||||
var/list/cameras = get_available_cameras(usr)
|
var/list/cameras = get_available_cameras(usr)
|
||||||
var/obj/machinery/camera/C = cameras["[ckey(c_tag)]"]
|
var/obj/machinery/camera/C = cameras["[ckey(c_tag)]"]
|
||||||
|
if(active_camera)
|
||||||
|
GLOB.moved_event.unregister(active_camera, src, .proc/update_active_camera_screen)
|
||||||
active_camera = C
|
active_camera = C
|
||||||
playsound(ui_host(), get_sfx("terminal_type"), 25, FALSE)
|
GLOB.moved_event.register(active_camera, src, .proc/update_active_camera_screen)
|
||||||
|
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
|
||||||
reload_cameraview()
|
update_active_camera_screen()
|
||||||
|
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/datum/tgui_module/camera/proc/differential_check()
|
if(action == "pan")
|
||||||
var/turf/T = get_turf(active_camera)
|
var/dir = params["dir"]
|
||||||
if(T)
|
var/turf/T = get_turf(active_camera)
|
||||||
var/new_x = T.x
|
for(var/i in 1 to 10)
|
||||||
var/new_y = T.y
|
T = get_step(T, dir)
|
||||||
var/new_z = T.z
|
if(T)
|
||||||
if((new_x != camera_diff_x) || (new_y != camera_diff_y) || (new_z != camera_diff_z))
|
var/obj/machinery/camera/target
|
||||||
reload_cameraview()
|
var/best_dist = INFINITY
|
||||||
|
|
||||||
/datum/tgui_module/camera/proc/reload_cameraview()
|
var/list/possible_cameras = get_available_cameras(usr)
|
||||||
|
for(var/obj/machinery/camera/C in get_area(T))
|
||||||
|
if(!possible_cameras["[ckey(C.c_tag)]"])
|
||||||
|
continue
|
||||||
|
var/dist = get_dist(C, T)
|
||||||
|
if(dist < best_dist)
|
||||||
|
best_dist = dist
|
||||||
|
target = C
|
||||||
|
|
||||||
|
if(target)
|
||||||
|
if(active_camera)
|
||||||
|
GLOB.moved_event.unregister(active_camera, src, .proc/update_active_camera_screen)
|
||||||
|
active_camera = target
|
||||||
|
GLOB.moved_event.register(active_camera, src, .proc/update_active_camera_screen)
|
||||||
|
playsound(tgui_host(), get_sfx("terminal_type"), 25, FALSE)
|
||||||
|
update_active_camera_screen()
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/camera/proc/update_active_camera_screen()
|
||||||
// Show static if can't use the camera
|
// Show static if can't use the camera
|
||||||
if(!active_camera?.can_use())
|
if(!active_camera?.can_use())
|
||||||
show_camera_static()
|
show_camera_static()
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
var/turf/camTurf = get_turf(active_camera)
|
// If we're not forcing an update for some reason and the cameras are in the same location,
|
||||||
|
// we don't need to update anything.
|
||||||
|
// Most security cameras will end here as they're not moving.
|
||||||
|
var/turf/newturf = get_turf(active_camera)
|
||||||
|
if(newturf == last_camera_turf)
|
||||||
|
return
|
||||||
|
|
||||||
camera_diff_x = camTurf.x
|
// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
|
||||||
camera_diff_y = camTurf.y
|
last_camera_turf = get_turf(active_camera)
|
||||||
camera_diff_z = camTurf.z
|
|
||||||
|
|
||||||
var/list/visible_turfs = list()
|
var/list/visible_turfs = list()
|
||||||
for(var/turf/T in (active_camera.isXRay() \
|
for(var/turf/T in (active_camera.isXRay() \
|
||||||
? range(active_camera.view_range, camTurf) \
|
? range(active_camera.view_range, newturf) \
|
||||||
: view(active_camera.view_range, camTurf)))
|
: view(active_camera.view_range, newturf)))
|
||||||
visible_turfs += T
|
visible_turfs += T
|
||||||
|
|
||||||
var/list/bbox = get_bbox_of_atoms(visible_turfs)
|
var/list/bbox = get_bbox_of_atoms(visible_turfs)
|
||||||
@@ -181,9 +208,9 @@
|
|||||||
cam_foreground.fill_rect(1, 1, size_x, size_y)
|
cam_foreground.fill_rect(1, 1, size_x, size_y)
|
||||||
|
|
||||||
local_skybox.cut_overlays()
|
local_skybox.cut_overlays()
|
||||||
local_skybox.add_overlay(SSskybox.get_skybox(get_z(camTurf)))
|
local_skybox.add_overlay(SSskybox.get_skybox(get_z(newturf)))
|
||||||
local_skybox.scale_to_view(size_x)
|
local_skybox.scale_to_view(size_x)
|
||||||
local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - camTurf.x, (world.maxy>>1) - camTurf.y)
|
local_skybox.set_position("CENTER", "CENTER", (world.maxx>>1) - newturf.x, (world.maxy>>1) - newturf.y)
|
||||||
|
|
||||||
// Returns the list of cameras accessible from this computer
|
// Returns the list of cameras accessible from this computer
|
||||||
// This proc operates in two distinct ways depending on the context in which the module is created.
|
// This proc operates in two distinct ways depending on the context in which the module is created.
|
||||||
@@ -193,10 +220,10 @@
|
|||||||
var/list/all_networks = list()
|
var/list/all_networks = list()
|
||||||
// Access Based
|
// Access Based
|
||||||
if(access_based)
|
if(access_based)
|
||||||
for(var/network in GLOB.using_map.station_networks)
|
for(var/network in using_map.station_networks)
|
||||||
if(can_access_network(user, get_camera_access(network), 1))
|
if(can_access_network(user, get_camera_access(network), 1))
|
||||||
all_networks.Add(network)
|
all_networks.Add(network)
|
||||||
for(var/network in GLOB.using_map.secondary_networks)
|
for(var/network in using_map.secondary_networks)
|
||||||
if(can_access_network(user, get_camera_access(network), 0))
|
if(can_access_network(user, get_camera_access(network), 0))
|
||||||
all_networks.Add(network)
|
all_networks.Add(network)
|
||||||
// Network Based
|
// Network Based
|
||||||
@@ -235,7 +262,7 @@
|
|||||||
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
|
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
|
||||||
local_skybox.cut_overlays()
|
local_skybox.cut_overlays()
|
||||||
|
|
||||||
/datum/tgui_module/camera/ui_close(mob/user)
|
/datum/tgui_module/camera/tgui_close(mob/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
var/user_ref = REF(user)
|
var/user_ref = REF(user)
|
||||||
var/is_living = isliving(user)
|
var/is_living = isliving(user)
|
||||||
@@ -246,41 +273,17 @@
|
|||||||
user.client.clear_map(map_name)
|
user.client.clear_map(map_name)
|
||||||
// Turn off the console
|
// Turn off the console
|
||||||
if(length(concurrent_users) == 0 && is_living)
|
if(length(concurrent_users) == 0 && is_living)
|
||||||
|
if(active_camera)
|
||||||
|
GLOB.moved_event.unregister(active_camera, src, .proc/update_active_camera_screen)
|
||||||
active_camera = null
|
active_camera = null
|
||||||
playsound(ui_host(), 'sound/machines/terminal_off.ogg', 25, FALSE)
|
playsound(tgui_host(), 'sound/machines/terminal_off.ogg', 25, FALSE)
|
||||||
|
|
||||||
// NTOS Version
|
// NTOS Version
|
||||||
// Please note, this isn't a very good replacement for converting modular computers 100% to TGUI
|
// Please note, this isn't a very good replacement for converting modular computers 100% to TGUI
|
||||||
// If/when that is done, just move all the PC_ specific data and stuff to the modular computers themselves
|
// If/when that is done, just move all the PC_ specific data and stuff to the modular computers themselves
|
||||||
// instead of copying this approach here.
|
// instead of copying this approach here.
|
||||||
/datum/tgui_module/camera/ntos
|
/datum/tgui_module/camera/ntos
|
||||||
tgui_id = "NtosCameraConsole"
|
ntos = TRUE
|
||||||
|
|
||||||
/datum/tgui_module/camera/ntos/ui_state()
|
|
||||||
return GLOB.ntos_state
|
|
||||||
|
|
||||||
/datum/tgui_module/camera/ntos/ui_static_data()
|
|
||||||
. = ..()
|
|
||||||
|
|
||||||
var/datum/computer_file/program/host = ui_host()
|
|
||||||
if(istype(host) && host.computer)
|
|
||||||
. += host.computer.get_header_data()
|
|
||||||
|
|
||||||
/datum/tgui_module/camera/ntos/ui_act(action, params)
|
|
||||||
if(..())
|
|
||||||
return
|
|
||||||
|
|
||||||
var/datum/computer_file/program/host = ui_host()
|
|
||||||
if(istype(host) && host.computer)
|
|
||||||
if(action == "PC_exit")
|
|
||||||
host.computer.kill_program()
|
|
||||||
return TRUE
|
|
||||||
if(action == "PC_shutdown")
|
|
||||||
host.computer.shutdown_computer()
|
|
||||||
return TRUE
|
|
||||||
if(action == "PC_minimize")
|
|
||||||
host.computer.minimize_program(usr)
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
// ERT Version provides some additional networks.
|
// ERT Version provides some additional networks.
|
||||||
/datum/tgui_module/camera/ntos/ert
|
/datum/tgui_module/camera/ntos/ert
|
||||||
@@ -292,4 +295,4 @@
|
|||||||
additional_networks = list(NETWORK_MERCENARY, NETWORK_ERT, NETWORK_CRESCENT)
|
additional_networks = list(NETWORK_MERCENARY, NETWORK_ERT, NETWORK_CRESCENT)
|
||||||
|
|
||||||
/datum/tgui_module/camera/ntos/hacked/New(host)
|
/datum/tgui_module/camera/ntos/hacked/New(host)
|
||||||
. = ..(host, GLOB.using_map.station_networks.Copy())
|
. = ..(host, using_map.station_networks.Copy())
|
||||||
|
|||||||
487
code/modules/tgui/modules/communications.dm
Normal file
487
code/modules/tgui/modules/communications.dm
Normal file
@@ -0,0 +1,487 @@
|
|||||||
|
#define COMM_SCREEN_MAIN 1
|
||||||
|
#define COMM_SCREEN_STAT 2
|
||||||
|
#define COMM_SCREEN_MESSAGES 3
|
||||||
|
|
||||||
|
#define COMM_AUTHENTICATION_NONE 0
|
||||||
|
#define COMM_AUTHENTICATION_MIN 1
|
||||||
|
#define COMM_AUTHENTICATION_MAX 2
|
||||||
|
|
||||||
|
#define COMM_MSGLEN_MINIMUM 6
|
||||||
|
#define COMM_CCMSGLEN_MINIMUM 20
|
||||||
|
|
||||||
|
/datum/tgui_module/communications
|
||||||
|
name = "Command & Communications"
|
||||||
|
tgui_id = "CommunicationsConsole"
|
||||||
|
|
||||||
|
var/emagged = FALSE
|
||||||
|
|
||||||
|
var/current_viewing_message_id = 0
|
||||||
|
var/current_viewing_message = null
|
||||||
|
|
||||||
|
var/authenticated = COMM_AUTHENTICATION_NONE
|
||||||
|
var/menu_state = COMM_SCREEN_MAIN
|
||||||
|
var/ai_menu_state = COMM_SCREEN_MAIN
|
||||||
|
var/aicurrmsg
|
||||||
|
|
||||||
|
var/message_cooldown
|
||||||
|
var/centcomm_message_cooldown
|
||||||
|
var/tmp_alertlevel = 0
|
||||||
|
|
||||||
|
var/stat_msg1
|
||||||
|
var/stat_msg2
|
||||||
|
var/display_type = "blank"
|
||||||
|
|
||||||
|
var/datum/announcement/priority/crew_announcement
|
||||||
|
|
||||||
|
var/datum/lore/atc_controller/ATC
|
||||||
|
|
||||||
|
var/list/req_access = list()
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/New(host)
|
||||||
|
. = ..()
|
||||||
|
ATC = atc
|
||||||
|
crew_announcement = new()
|
||||||
|
crew_announcement.newscast = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/ui_interact(mob/user, datum/tgui/ui)
|
||||||
|
if(using_map && !(get_z(user) in using_map.contact_levels))
|
||||||
|
to_chat(user, "<span class='danger'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||||
|
return FALSE
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/proc/is_authenticated(mob/user, message = TRUE)
|
||||||
|
if(authenticated == COMM_AUTHENTICATION_MAX)
|
||||||
|
return COMM_AUTHENTICATION_MAX
|
||||||
|
else if(isobserver(user))
|
||||||
|
var/mob/observer/dead/D = user
|
||||||
|
if(D.can_admin_interact())
|
||||||
|
return COMM_AUTHENTICATION_MAX
|
||||||
|
else if(authenticated)
|
||||||
|
return COMM_AUTHENTICATION_MIN
|
||||||
|
else
|
||||||
|
if(message)
|
||||||
|
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||||
|
return COMM_AUTHENTICATION_NONE
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/proc/change_security_level(new_level)
|
||||||
|
tmp_alertlevel = new_level
|
||||||
|
var/old_level = security_level
|
||||||
|
if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||||
|
if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||||
|
if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this
|
||||||
|
set_security_level(tmp_alertlevel)
|
||||||
|
if(security_level != old_level)
|
||||||
|
//Only notify the admins if an actual change happened
|
||||||
|
log_game("[key_name(usr)] has changed the security level to [get_security_level()].")
|
||||||
|
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
|
||||||
|
switch(security_level)
|
||||||
|
if(SEC_LEVEL_GREEN)
|
||||||
|
feedback_inc("alert_comms_green",1)
|
||||||
|
if(SEC_LEVEL_YELLOW)
|
||||||
|
feedback_inc("alert_comms_yellow",1)
|
||||||
|
if(SEC_LEVEL_VIOLET)
|
||||||
|
feedback_inc("alert_comms_violet",1)
|
||||||
|
if(SEC_LEVEL_ORANGE)
|
||||||
|
feedback_inc("alert_comms_orange",1)
|
||||||
|
if(SEC_LEVEL_BLUE)
|
||||||
|
feedback_inc("alert_comms_blue",1)
|
||||||
|
tmp_alertlevel = 0
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/ui_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
data["is_ai"] = isAI(user) || isrobot(user)
|
||||||
|
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
|
||||||
|
data["emagged"] = emagged
|
||||||
|
data["authenticated"] = is_authenticated(user, 0)
|
||||||
|
data["authmax"] = data["authenticated"] == COMM_AUTHENTICATION_MAX ? TRUE : FALSE
|
||||||
|
data["atcsquelch"] = ATC.squelched
|
||||||
|
data["boss_short"] = using_map.boss_short
|
||||||
|
|
||||||
|
data["stat_display"] = list(
|
||||||
|
"type" = display_type,
|
||||||
|
// "icon" = display_icon,
|
||||||
|
"line_1" = (stat_msg1 ? stat_msg1 : "-----"),
|
||||||
|
"line_2" = (stat_msg2 ? stat_msg2 : "-----"),
|
||||||
|
|
||||||
|
"presets" = list(
|
||||||
|
list("name" = "blank", "label" = "Clear", "desc" = "Blank slate."),
|
||||||
|
list("name" = "time", "label" = "Station Time", "desc" = "The current time according to the station's clock."),
|
||||||
|
list("name" = "shuttle", "label" = "Tram ETA", "desc" = "Display how much time is left."), //VOREStation Edit - Shuttle ETA -> Tram ETA because we use trams
|
||||||
|
list("name" = "message", "label" = "Message", "desc" = "A custom message.")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
data["security_level"] = security_level
|
||||||
|
switch(security_level)
|
||||||
|
if(SEC_LEVEL_BLUE)
|
||||||
|
data["security_level_color"] = "blue";
|
||||||
|
if(SEC_LEVEL_ORANGE)
|
||||||
|
data["security_level_color"] = "orange";
|
||||||
|
if(SEC_LEVEL_VIOLET)
|
||||||
|
data["security_level_color"] = "violet";
|
||||||
|
if(SEC_LEVEL_YELLOW)
|
||||||
|
data["security_level_color"] = "yellow";
|
||||||
|
if(SEC_LEVEL_GREEN)
|
||||||
|
data["security_level_color"] = "green";
|
||||||
|
if(SEC_LEVEL_RED)
|
||||||
|
data["security_level_color"] = "red";
|
||||||
|
else
|
||||||
|
data["security_level_color"] = "purple";
|
||||||
|
data["str_security_level"] = capitalize(get_security_level())
|
||||||
|
data["levels"] = list(
|
||||||
|
list("id" = SEC_LEVEL_GREEN, "name" = "Green", "icon" = "dove"),
|
||||||
|
list("id" = SEC_LEVEL_YELLOW, "name" = "Yellow", "icon" = "exclamation-triangle"),
|
||||||
|
list("id" = SEC_LEVEL_BLUE, "name" = "Blue", "icon" = "eye"),
|
||||||
|
list("id" = SEC_LEVEL_ORANGE, "name" = "Orange", "icon" = "wrench"),
|
||||||
|
list("id" = SEC_LEVEL_VIOLET, "name" = "Violet", "icon" = "biohazard"),
|
||||||
|
)
|
||||||
|
|
||||||
|
var/datum/comm_message_listener/l = obtain_message_listener()
|
||||||
|
data["messages"] = l.messages
|
||||||
|
data["message_deletion_allowed"] = l != global_message_listener
|
||||||
|
data["message_current_id"] = current_viewing_message_id
|
||||||
|
data["message_current"] = current_viewing_message
|
||||||
|
|
||||||
|
// data["lastCallLoc"] = SSshuttle.emergencyLastCallLoc ? format_text(SSshuttle.emergencyLastCallLoc.name) : null
|
||||||
|
data["msg_cooldown"] = message_cooldown ? (round((message_cooldown - world.time) / 10)) : 0
|
||||||
|
data["cc_cooldown"] = centcomm_message_cooldown ? (round((centcomm_message_cooldown - world.time) / 10)) : 0
|
||||||
|
|
||||||
|
data["esc_callable"] = emergency_shuttle.location() && !emergency_shuttle.online() ? TRUE : FALSE
|
||||||
|
data["esc_recallable"] = emergency_shuttle.location() && emergency_shuttle.online() ? TRUE : FALSE
|
||||||
|
data["esc_status"] = FALSE
|
||||||
|
if(emergency_shuttle.has_eta())
|
||||||
|
var/timeleft = emergency_shuttle.estimate_arrival_time()
|
||||||
|
data["esc_status"] = emergency_shuttle.online() ? "ETA:" : "RECALLING:"
|
||||||
|
data["esc_status"] += " [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/proc/setCurrentMessage(mob/user, value)
|
||||||
|
current_viewing_message_id = value
|
||||||
|
|
||||||
|
var/datum/comm_message_listener/l = obtain_message_listener()
|
||||||
|
for(var/list/m in l.messages)
|
||||||
|
if(m["id"] == current_viewing_message_id)
|
||||||
|
current_viewing_message = m
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/proc/setMenuState(mob/user, value)
|
||||||
|
if(isAI(user) || isrobot(user))
|
||||||
|
ai_menu_state = value
|
||||||
|
else
|
||||||
|
menu_state = value
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/proc/obtain_message_listener()
|
||||||
|
if(istype(host, /datum/computer_file/program/comm))
|
||||||
|
var/datum/computer_file/program/comm/P = host
|
||||||
|
return P.message_core
|
||||||
|
return global_message_listener
|
||||||
|
|
||||||
|
/proc/post_status(atom/source, command, data1, data2, mob/user = null)
|
||||||
|
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
|
||||||
|
|
||||||
|
if(!frequency)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/datum/signal/status_signal = new
|
||||||
|
status_signal.source = source
|
||||||
|
status_signal.transmission_method = TRANSMISSION_RADIO
|
||||||
|
status_signal.data["command"] = command
|
||||||
|
|
||||||
|
switch(command)
|
||||||
|
if("message")
|
||||||
|
status_signal.data["msg1"] = data1
|
||||||
|
status_signal.data["msg2"] = data2
|
||||||
|
log_admin("STATUS: [user] set status screen message: [data1] [data2]")
|
||||||
|
//message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]")
|
||||||
|
if("alert")
|
||||||
|
status_signal.data["picture_state"] = data1
|
||||||
|
|
||||||
|
frequency.post_signal(null, status_signal)
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
if(using_map && !(get_z(usr) in using_map.contact_levels))
|
||||||
|
to_chat(usr, "<span class='danger'>Unable to establish a connection: You're too far away from the station!</span>")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
. = TRUE
|
||||||
|
if(action == "auth")
|
||||||
|
if(!ishuman(usr))
|
||||||
|
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||||
|
return FALSE
|
||||||
|
// Logout function.
|
||||||
|
if(authenticated != COMM_AUTHENTICATION_NONE)
|
||||||
|
authenticated = COMM_AUTHENTICATION_NONE
|
||||||
|
crew_announcement.announcer = null
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
return
|
||||||
|
// Login function.
|
||||||
|
if(check_access(usr, access_heads))
|
||||||
|
authenticated = COMM_AUTHENTICATION_MIN
|
||||||
|
if(check_access(usr, access_captain))
|
||||||
|
authenticated = COMM_AUTHENTICATION_MAX
|
||||||
|
var/mob/M = usr
|
||||||
|
var/obj/item/weapon/card/id = M.GetIdCard()
|
||||||
|
if(istype(id))
|
||||||
|
crew_announcement.announcer = GetNameAndAssignmentFromId(id)
|
||||||
|
if(authenticated == COMM_AUTHENTICATION_NONE)
|
||||||
|
to_chat(usr, "<span class='warning'>You need to wear your ID.</span>")
|
||||||
|
|
||||||
|
// All functions below this point require authentication.
|
||||||
|
if(!is_authenticated(usr))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
// main interface
|
||||||
|
if("main")
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
if("newalertlevel")
|
||||||
|
if(isAI(usr) || isrobot(usr))
|
||||||
|
to_chat(usr, "<span class='warning'>Firewalls prevent you from changing the alert level.</span>")
|
||||||
|
return
|
||||||
|
else if(isobserver(usr))
|
||||||
|
var/mob/observer/dead/D = usr
|
||||||
|
if(D.can_admin_interact())
|
||||||
|
change_security_level(text2num(params["level"]))
|
||||||
|
return TRUE
|
||||||
|
else if(!ishuman(usr))
|
||||||
|
to_chat(usr, "<span class='warning'>Security measures prevent you from changing the alert level.</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(is_authenticated(usr))
|
||||||
|
change_security_level(text2num(params["level"]))
|
||||||
|
else
|
||||||
|
to_chat(usr, "<span class='warning'>You are not authorized to do this.</span>")
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
if("announce")
|
||||||
|
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||||
|
if(message_cooldown > world.time)
|
||||||
|
to_chat(usr, "<span class='warning'>Please allow at least one minute to pass between announcements.</span>")
|
||||||
|
return
|
||||||
|
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement") as null|message
|
||||||
|
if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||||
|
return
|
||||||
|
if(length(input) < COMM_MSGLEN_MINIMUM)
|
||||||
|
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.</span>")
|
||||||
|
return
|
||||||
|
crew_announcement.Announce(input)
|
||||||
|
message_cooldown = world.time + 600 //One minute
|
||||||
|
|
||||||
|
if("callshuttle")
|
||||||
|
if(!is_authenticated(usr))
|
||||||
|
return
|
||||||
|
|
||||||
|
call_shuttle_proc(usr)
|
||||||
|
if(emergency_shuttle.online())
|
||||||
|
post_status(src, "shuttle", user = usr)
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
if("cancelshuttle")
|
||||||
|
if(isAI(usr) || isrobot(usr))
|
||||||
|
to_chat(usr, "<span class='warning'>Firewalls prevent you from recalling the shuttle.</span>")
|
||||||
|
return
|
||||||
|
var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No")
|
||||||
|
if(response == "Yes")
|
||||||
|
cancel_call_proc(usr)
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
if("messagelist")
|
||||||
|
current_viewing_message = null
|
||||||
|
current_viewing_message_id = null
|
||||||
|
if(params["msgid"])
|
||||||
|
setCurrentMessage(usr, text2num(params["msgid"]))
|
||||||
|
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||||
|
|
||||||
|
if("toggleatc")
|
||||||
|
ATC.squelched = !ATC.squelched
|
||||||
|
|
||||||
|
if("delmessage")
|
||||||
|
var/datum/comm_message_listener/l = obtain_message_listener()
|
||||||
|
if(params["msgid"])
|
||||||
|
setCurrentMessage(usr, text2num(params["msgid"]))
|
||||||
|
var/response = alert("Are you sure you wish to delete this message?", "Confirm", "Yes", "No")
|
||||||
|
if(response == "Yes")
|
||||||
|
if(current_viewing_message)
|
||||||
|
if(l != global_message_listener)
|
||||||
|
l.Remove(current_viewing_message)
|
||||||
|
current_viewing_message = null
|
||||||
|
setMenuState(usr, COMM_SCREEN_MESSAGES)
|
||||||
|
|
||||||
|
if("status")
|
||||||
|
setMenuState(usr, COMM_SCREEN_STAT)
|
||||||
|
|
||||||
|
// Status display stuff
|
||||||
|
if("setstat")
|
||||||
|
display_type = params["statdisp"]
|
||||||
|
switch(display_type)
|
||||||
|
if("message")
|
||||||
|
post_status(src, "message", stat_msg1, stat_msg2, user = usr)
|
||||||
|
if("alert")
|
||||||
|
post_status(src, "alert", params["alert"], user = usr)
|
||||||
|
else
|
||||||
|
post_status(src, params["statdisp"], user = usr)
|
||||||
|
|
||||||
|
if("setmsg1")
|
||||||
|
stat_msg1 = reject_bad_text(sanitize(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40), 40)
|
||||||
|
setMenuState(usr, COMM_SCREEN_STAT)
|
||||||
|
|
||||||
|
if("setmsg2")
|
||||||
|
stat_msg2 = reject_bad_text(sanitize(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40), 40)
|
||||||
|
setMenuState(usr, COMM_SCREEN_STAT)
|
||||||
|
|
||||||
|
// OMG CENTCOMM LETTERHEAD
|
||||||
|
if("MessageCentCom")
|
||||||
|
if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
|
||||||
|
if(centcomm_message_cooldown > world.time)
|
||||||
|
to_chat(usr, "<span class='warning'>Arrays recycling. Please stand by.</span>")
|
||||||
|
return
|
||||||
|
var/input = sanitize(input("Please choose a message to transmit to [using_map.boss_short] via quantum entanglement. \
|
||||||
|
Please be aware that this process is very expensive, and abuse will lead to... termination. \
|
||||||
|
Transmission does not guarantee a response. \
|
||||||
|
There is a 30 second delay before you may send another message, be clear, full and concise.", "Central Command Quantum Messaging") as null|message)
|
||||||
|
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||||
|
return
|
||||||
|
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||||
|
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||||
|
return
|
||||||
|
CentCom_announce(input, usr)
|
||||||
|
to_chat(usr, "<font color='blue'>Message transmitted.</font>")
|
||||||
|
log_game("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]")
|
||||||
|
centcomm_message_cooldown = world.time + 300 // 30 seconds
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
// OMG SYNDICATE ...LETTERHEAD
|
||||||
|
if("MessageSyndicate")
|
||||||
|
if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (emagged))
|
||||||
|
if(centcomm_message_cooldown > world.time)
|
||||||
|
to_chat(usr, "Arrays recycling. Please stand by.")
|
||||||
|
return
|
||||||
|
var/input = sanitize(input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", ""))
|
||||||
|
if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
|
||||||
|
return
|
||||||
|
if(length(input) < COMM_CCMSGLEN_MINIMUM)
|
||||||
|
to_chat(usr, "<span class='warning'>Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.</span>")
|
||||||
|
return
|
||||||
|
Syndicate_announce(input, usr)
|
||||||
|
to_chat(usr, "<font color='blue'>Message transmitted.</font>")
|
||||||
|
log_game("[key_name(usr)] has made an illegal announcement: [input]")
|
||||||
|
centcomm_message_cooldown = world.time + 300 // 30 seconds
|
||||||
|
|
||||||
|
if("RestoreBackup")
|
||||||
|
to_chat(usr, "Backup routing data restored!")
|
||||||
|
emagged = FALSE
|
||||||
|
setMenuState(usr, COMM_SCREEN_MAIN)
|
||||||
|
|
||||||
|
/datum/tgui_module/communications/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
/* Etc global procs */
|
||||||
|
/proc/enable_prison_shuttle(var/mob/user)
|
||||||
|
for(var/obj/machinery/computer/prison_shuttle/PS in machines)
|
||||||
|
PS.allowedtocall = !(PS.allowedtocall)
|
||||||
|
|
||||||
|
/proc/call_shuttle_proc(var/mob/user)
|
||||||
|
if ((!( ticker ) || !emergency_shuttle.location()))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!universe.OnShuttleCall(usr))
|
||||||
|
to_chat(user, "<span class='notice'>Cannot establish a bluespace connection.</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(deathsquad.deployed)
|
||||||
|
to_chat(user, "[using_map.boss_short] will not allow the shuttle to be called. Consider all contracts terminated.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(emergency_shuttle.deny_shuttle)
|
||||||
|
to_chat(user, "The emergency shuttle may not be sent at this time. Please try again later.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE
|
||||||
|
to_chat(user, "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(emergency_shuttle.going_to_centcom())
|
||||||
|
to_chat(user, "The emergency shuttle may not be called while returning to [using_map.boss_short].")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(emergency_shuttle.online())
|
||||||
|
to_chat(user, "The emergency shuttle is already on its way.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(ticker.mode.name == "blob")
|
||||||
|
to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
|
||||||
|
return
|
||||||
|
|
||||||
|
emergency_shuttle.call_evac()
|
||||||
|
log_game("[key_name(user)] has called the shuttle.")
|
||||||
|
message_admins("[key_name_admin(user)] has called the shuttle.", 1)
|
||||||
|
admin_chat_message(message = "Emergency evac beginning! Called by [key_name(user)]!", color = "#CC2222") //VOREStation Add
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
/proc/init_shift_change(var/mob/user, var/force = 0)
|
||||||
|
if ((!( ticker ) || !emergency_shuttle.location()))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(emergency_shuttle.going_to_centcom())
|
||||||
|
to_chat(user, "The shuttle may not be called while returning to [using_map.boss_short].")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(emergency_shuttle.online())
|
||||||
|
to_chat(user, "The shuttle is already on its way.")
|
||||||
|
return
|
||||||
|
|
||||||
|
// if force is 0, some things may stop the shuttle call
|
||||||
|
if(!force)
|
||||||
|
if(emergency_shuttle.deny_shuttle)
|
||||||
|
to_chat(user, "[using_map.boss_short] does not currently have a shuttle available in your sector. Please try again later.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(deathsquad.deployed == 1)
|
||||||
|
to_chat(user, "[using_map.boss_short] will not allow the shuttle to be called. Consider all contracts terminated.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(world.time < 54000) // 30 minute grace period to let the game get going
|
||||||
|
to_chat(user, "The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(ticker.mode.auto_recall_shuttle)
|
||||||
|
//New version pretends to call the shuttle but cause the shuttle to return after a random duration.
|
||||||
|
emergency_shuttle.auto_recall = 1
|
||||||
|
|
||||||
|
if(ticker.mode.name == "blob" || ticker.mode.name == "epidemic")
|
||||||
|
to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.")
|
||||||
|
return
|
||||||
|
|
||||||
|
emergency_shuttle.call_transfer()
|
||||||
|
|
||||||
|
//delay events in case of an autotransfer
|
||||||
|
if (isnull(user))
|
||||||
|
SSevents.delay_events(EVENT_LEVEL_MODERATE, 9000) //15 minutes
|
||||||
|
SSevents.delay_events(EVENT_LEVEL_MAJOR, 9000)
|
||||||
|
|
||||||
|
log_game("[user? key_name(user) : "Autotransfer"] has called the shuttle.")
|
||||||
|
message_admins("[user? key_name_admin(user) : "Autotransfer"] has called the shuttle.", 1)
|
||||||
|
admin_chat_message(message = "Autotransfer shuttle dispatched, shift ending soon.", color = "#2277BB") //VOREStation Add
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
/proc/cancel_call_proc(var/mob/user)
|
||||||
|
if (!( ticker ) || !emergency_shuttle.can_recall())
|
||||||
|
return
|
||||||
|
if((ticker.mode.name == "blob")||(ticker.mode.name == "Meteor"))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!emergency_shuttle.going_to_centcom()) //check that shuttle isn't already heading to CentCom
|
||||||
|
emergency_shuttle.recall()
|
||||||
|
log_game("[key_name(user)] has recalled the shuttle.")
|
||||||
|
message_admins("[key_name_admin(user)] has recalled the shuttle.", 1)
|
||||||
|
return
|
||||||
|
|
||||||
|
/proc/is_relay_online()
|
||||||
|
for(var/obj/machinery/telecomms/relay/M in world)
|
||||||
|
if(M.stat == 0)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
14
code/modules/tgui/modules/crew_manifest.dm
Normal file
14
code/modules/tgui/modules/crew_manifest.dm
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/datum/tgui_module/crew_manifest
|
||||||
|
name = "Crew Manifest"
|
||||||
|
tgui_id = "CrewManifest"
|
||||||
|
|
||||||
|
/datum/tgui_module/crew_manifest/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
if(data_core)
|
||||||
|
data_core.get_manifest_list()
|
||||||
|
data["manifest"] = PDA_Manifest
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/crew_manifest/robot
|
||||||
|
/datum/tgui_module/crew_manifest/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
@@ -2,12 +2,20 @@
|
|||||||
name = "Crew monitor"
|
name = "Crew monitor"
|
||||||
tgui_id = "CrewMonitor"
|
tgui_id = "CrewMonitor"
|
||||||
|
|
||||||
|
/datum/tgui_module/crew_monitor/ui_assets(mob/user)
|
||||||
|
return list(
|
||||||
|
get_asset_datum(/datum/asset/simple/nanomaps),
|
||||||
|
)
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ui_act(action, params, datum/tgui/ui)
|
/datum/tgui_module/crew_monitor/ui_act(action, params, datum/tgui/ui)
|
||||||
if(..())
|
if(..())
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
|
if(action && !issilicon(usr))
|
||||||
|
playsound(tgui_host(), "terminal_type", 50, 1)
|
||||||
|
|
||||||
var/turf/T = get_turf(usr)
|
var/turf/T = get_turf(usr)
|
||||||
if(!T || !(T.z in GLOB.using_map.player_levels))
|
if(!T || !(T.z in using_map.player_levels))
|
||||||
to_chat(usr, "<span class='warning'><b>Unable to establish a connection</b>: You're too far away from the station!</span>")
|
to_chat(usr, "<span class='warning'><b>Unable to establish a connection</b>: You're too far away from the station!</span>")
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
@@ -15,17 +23,17 @@
|
|||||||
if("track")
|
if("track")
|
||||||
if(isAI(usr))
|
if(isAI(usr))
|
||||||
var/mob/living/silicon/ai/AI = usr
|
var/mob/living/silicon/ai/AI = usr
|
||||||
var/mob/living/carbon/human/H = locate(params["track"]) in GLOB.mob_list
|
var/mob/living/carbon/human/H = locate(params["track"]) in mob_list
|
||||||
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
|
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
|
||||||
AI.ai_actual_track(H)
|
AI.ai_actual_track(H)
|
||||||
return TRUE
|
return TRUE
|
||||||
if("setZLevel")
|
if("setZLevel")
|
||||||
ui.set_map_z_level(params["mapZLevel"])
|
ui.set_map_z_level(params["mapZLevel"])
|
||||||
SStgui.update_uis(src)
|
return TRUE
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ui_interact(mob/user, datum/tgui/ui = null)
|
/datum/tgui_module/crew_monitor/ui_interact(mob/user, datum/tgui/ui = null)
|
||||||
var/z = get_z(user)
|
var/z = get_z(user)
|
||||||
var/list/map_levels = GLOB.using_map.get_map_levels(z, FALSE)
|
var/list/map_levels = using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE)
|
||||||
|
|
||||||
if(!map_levels.len)
|
if(!map_levels.len)
|
||||||
to_chat(user, "<span class='warning'>The crew monitor doesn't seem like it'll work here.</span>")
|
to_chat(user, "<span class='warning'>The crew monitor doesn't seem like it'll work here.</span>")
|
||||||
@@ -40,64 +48,41 @@
|
|||||||
ui.open()
|
ui.open()
|
||||||
|
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ui_data(mob/user, ui_key = "main", datum/ui_state/state = GLOB.default_state)
|
/datum/tgui_module/crew_monitor/ui_data(mob/user)
|
||||||
var/data[0]
|
var/data[0]
|
||||||
|
|
||||||
data["isAI"] = isAI(user)
|
data["isAI"] = isAI(user)
|
||||||
|
|
||||||
var/z = get_z(user)
|
var/z = get_z(user)
|
||||||
var/list/map_levels = uniqueList(GLOB.using_map.get_map_levels(z, FALSE))
|
var/list/map_levels = uniquelist(using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
|
||||||
data["map_levels"] = map_levels
|
data["map_levels"] = map_levels
|
||||||
|
|
||||||
data["crewmembers"] = list()
|
var/list/crewmembers = list()
|
||||||
for(var/zlevel in map_levels)
|
for(var/zlevel in map_levels)
|
||||||
data["crewmembers"] += crew_repository.health_data(zlevel)
|
crewmembers += crew_repository.health_data(zlevel)
|
||||||
|
|
||||||
|
// This is apparently necessary, because the above loop produces an emergent behavior
|
||||||
|
// of telling you what coordinates someone is at even without sensors on,
|
||||||
|
// because it strictly sorts by zlevel from bottom to top, and by coordinates from top left to bottom right.
|
||||||
|
shuffle_inplace(crewmembers)
|
||||||
|
data["crewmembers"] = crewmembers
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ntos
|
/datum/tgui_module/crew_monitor/ntos
|
||||||
tgui_id = "NtosCrewMonitor"
|
ntos = TRUE
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ntos/ui_state(mob/user)
|
|
||||||
return GLOB.ntos_state
|
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ntos/ui_static_data()
|
|
||||||
. = ..()
|
|
||||||
|
|
||||||
var/datum/computer_file/program/host = ui_host()
|
|
||||||
if(istype(host) && host.computer)
|
|
||||||
. += host.computer.get_header_data()
|
|
||||||
|
|
||||||
/datum/tgui_module/crew_monitor/ntos/ui_act(action, params)
|
|
||||||
if(..())
|
|
||||||
return
|
|
||||||
|
|
||||||
var/datum/computer_file/program/host = ui_host()
|
|
||||||
if(istype(host) && host.computer)
|
|
||||||
if(action == "PC_exit")
|
|
||||||
host.computer.kill_program()
|
|
||||||
return TRUE
|
|
||||||
if(action == "PC_shutdown")
|
|
||||||
host.computer.shutdown_computer()
|
|
||||||
return TRUE
|
|
||||||
if(action == "PC_minimize")
|
|
||||||
host.computer.minimize_program(usr)
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
// Subtype for glasses_state
|
// Subtype for glasses_state
|
||||||
/datum/tgui_module/crew_monitor/glasses
|
/datum/tgui_module/crew_monitor/glasses
|
||||||
|
/datum/tgui_module/crew_monitor/glasses/tgui_state(mob/user)
|
||||||
/datum/tgui_module/crew_monitor/glasses/ui_state(mob/user)
|
return GLOB.tgui_glasses_state
|
||||||
return GLOB.ui_glasses_state
|
|
||||||
|
|
||||||
// Subtype for self_state
|
// Subtype for self_state
|
||||||
/datum/tgui_module/crew_monitor/robot
|
/datum/tgui_module/crew_monitor/robot
|
||||||
|
/datum/tgui_module/crew_monitor/robot/tgui_state(mob/user)
|
||||||
/datum/tgui_module/crew_monitor/robot/ui_state(mob/user)
|
return GLOB.tgui_self_state
|
||||||
return GLOB.self_state
|
|
||||||
|
|
||||||
// Subtype for nif_state
|
// Subtype for nif_state
|
||||||
/datum/tgui_module/crew_monitor/nif
|
/datum/tgui_module/crew_monitor/nif
|
||||||
|
/datum/tgui_module/crew_monitor/nif/tgui_state(mob/user)
|
||||||
/datum/tgui_module/crew_monitor/nif/ui_state(mob/user)
|
return GLOB.tgui_nif_state
|
||||||
return GLOB.ui_nif_state
|
|
||||||
|
|||||||
68
code/modules/tgui/modules/gyrotron_control.dm
Normal file
68
code/modules/tgui/modules/gyrotron_control.dm
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/datum/tgui_module/gyrotron_control
|
||||||
|
name = "Gyrotron Control"
|
||||||
|
tgui_id = "GyrotronControl"
|
||||||
|
|
||||||
|
var/gyro_tag = ""
|
||||||
|
var/scan_range = 25
|
||||||
|
|
||||||
|
/datum/tgui_module/gyrotron_control/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
// If the command requires a gyrotron, and we can't find it, we don't need to check any further
|
||||||
|
var/obj/machinery/power/emitter/gyrotron/G = null
|
||||||
|
if(params["gyro"])
|
||||||
|
G = locate(params["gyro"]) in GLOB.gyrotrons
|
||||||
|
if(!istype(G))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("set_tag")
|
||||||
|
var/new_ident = sanitize_text(input("Enter a new ident tag.", "Gyrotron Control", gyro_tag) as null|text)
|
||||||
|
if(new_ident)
|
||||||
|
gyro_tag = new_ident
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("toggle_active")
|
||||||
|
G.activate(usr)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("set_str")
|
||||||
|
var/new_strength = params["str"]
|
||||||
|
if(istext(new_strength))
|
||||||
|
new_strength = text2num(new_strength)
|
||||||
|
if(new_strength)
|
||||||
|
G.set_beam_power(new_strength)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("set_rate")
|
||||||
|
var/new_delay = params["rate"]
|
||||||
|
if(istext(new_delay))
|
||||||
|
new_delay = text2num(new_delay)
|
||||||
|
if(new_delay)
|
||||||
|
G.rate = new_delay
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/gyrotron_control/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
var/list/gyros = list()
|
||||||
|
|
||||||
|
for(var/obj/machinery/power/emitter/gyrotron/G in GLOB.gyrotrons)
|
||||||
|
if(G.id_tag == gyro_tag)// && (get_dist(get_turf(G), get_turf(src)) <= scan_range))
|
||||||
|
gyros.Add(list(list(
|
||||||
|
"name" = G.name,
|
||||||
|
"active" = G.active,
|
||||||
|
"strength" = G.mega_energy,
|
||||||
|
"fire_delay" = G.rate,
|
||||||
|
"deployed" = (G.state == 2),
|
||||||
|
"x" = G.x,
|
||||||
|
"y" = G.y,
|
||||||
|
"z" = G.z,
|
||||||
|
"ref" = "\ref[G]"
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["gyros"] = gyros
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/gyrotron_control/ntos
|
||||||
|
ntos = TRUE
|
||||||
224
code/modules/tgui/modules/law_manager.dm
Normal file
224
code/modules/tgui/modules/law_manager.dm
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
/datum/tgui_module/law_manager
|
||||||
|
name = "Law manager"
|
||||||
|
tgui_id = "LawManager"
|
||||||
|
var/ion_law = "IonLaw"
|
||||||
|
var/zeroth_law = "ZerothLaw"
|
||||||
|
var/inherent_law = "InherentLaw"
|
||||||
|
var/supplied_law = "SuppliedLaw"
|
||||||
|
var/supplied_law_position = MIN_SUPPLIED_LAW_NUMBER
|
||||||
|
|
||||||
|
var/global/list/datum/ai_laws/admin_laws
|
||||||
|
var/global/list/datum/ai_laws/player_laws
|
||||||
|
var/mob/living/silicon/owner = null
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/New(mob/living/silicon/S)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
owner = S
|
||||||
|
|
||||||
|
if(!admin_laws)
|
||||||
|
admin_laws = new()
|
||||||
|
player_laws = new()
|
||||||
|
|
||||||
|
init_subtypes(/datum/ai_laws, admin_laws)
|
||||||
|
admin_laws = dd_sortedObjectList(admin_laws)
|
||||||
|
|
||||||
|
for(var/datum/ai_laws/laws in admin_laws)
|
||||||
|
if(laws.selectable)
|
||||||
|
player_laws += laws
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/ui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("law_channel")
|
||||||
|
if(params["law_channel"] in owner.law_channels())
|
||||||
|
owner.lawchannel = params["law_channel"]
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("state_law")
|
||||||
|
var/datum/ai_law/AL = locate(params["ref"]) in owner.laws.all_laws()
|
||||||
|
if(AL)
|
||||||
|
var/state_law = text2num(params["state_law"])
|
||||||
|
owner.laws.set_state_law(AL, state_law)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("add_zeroth_law")
|
||||||
|
if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law)
|
||||||
|
owner.set_zeroth_law(zeroth_law)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("add_ion_law")
|
||||||
|
if(ion_law && is_malf(usr))
|
||||||
|
owner.add_ion_law(ion_law)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("add_inherent_law")
|
||||||
|
if(inherent_law && is_malf(usr))
|
||||||
|
owner.add_inherent_law(inherent_law)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("add_supplied_law")
|
||||||
|
if(supplied_law && supplied_law_position >= 1 && MIN_SUPPLIED_LAW_NUMBER <= MAX_SUPPLIED_LAW_NUMBER && is_malf(usr))
|
||||||
|
owner.add_supplied_law(supplied_law_position, supplied_law)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("change_zeroth_law")
|
||||||
|
var/new_law = sanitize(params["val"])
|
||||||
|
if(new_law && new_law != zeroth_law && can_still_topic(usr, state))
|
||||||
|
zeroth_law = new_law
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("change_ion_law")
|
||||||
|
var/new_law = sanitize(params["val"])
|
||||||
|
if(new_law && new_law != ion_law && can_still_topic(usr, state))
|
||||||
|
ion_law = new_law
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("change_inherent_law")
|
||||||
|
var/new_law = sanitize(params["val"])
|
||||||
|
if(new_law && new_law != inherent_law && can_still_topic(usr, state))
|
||||||
|
inherent_law = new_law
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("change_supplied_law")
|
||||||
|
var/new_law = sanitize(params["val"])
|
||||||
|
if(new_law && new_law != supplied_law && can_still_topic(usr, state))
|
||||||
|
supplied_law = new_law
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("change_supplied_law_position")
|
||||||
|
var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null
|
||||||
|
if(isnum(new_position) && can_still_topic(usr, state))
|
||||||
|
supplied_law_position = CLAMP(new_position, 1, MAX_SUPPLIED_LAW_NUMBER)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("edit_law")
|
||||||
|
if(is_malf(usr))
|
||||||
|
var/datum/ai_law/AL = locate(params["edit_law"]) in owner.laws.all_laws()
|
||||||
|
if(AL)
|
||||||
|
var/new_law = sanitize(input(usr, "Enter new law. Leaving the field blank will cancel the edit.", "Edit Law", AL.law))
|
||||||
|
if(new_law && new_law != AL.law && is_malf(usr) && can_still_topic(usr, state))
|
||||||
|
log_and_message_admins("has changed a law of [owner] from '[AL.law]' to '[new_law]'")
|
||||||
|
AL.law = new_law
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("delete_law")
|
||||||
|
if(is_malf(usr))
|
||||||
|
var/datum/ai_law/AL = locate(params["delete_law"]) in owner.laws.all_laws()
|
||||||
|
if(AL && is_malf(usr))
|
||||||
|
owner.delete_law(AL)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("state_laws")
|
||||||
|
owner.statelaws(owner.laws)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("state_law_set")
|
||||||
|
var/datum/ai_laws/ALs = locate(params["state_law_set"]) in (is_admin(usr) ? admin_laws : player_laws)
|
||||||
|
if(ALs)
|
||||||
|
owner.statelaws(ALs)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("transfer_laws")
|
||||||
|
if(is_malf(usr))
|
||||||
|
var/datum/ai_laws/ALs = locate(params["transfer_laws"]) in (is_admin(usr) ? admin_laws : player_laws)
|
||||||
|
if(ALs)
|
||||||
|
log_and_message_admins("has transfered the [ALs.name] laws to [owner].")
|
||||||
|
ALs.sync(owner, 0)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("notify_laws")
|
||||||
|
to_chat(owner, "<span class='danger'>Law Notice</span>")
|
||||||
|
owner.laws.show_laws(owner)
|
||||||
|
if(isAI(owner))
|
||||||
|
var/mob/living/silicon/ai/AI = owner
|
||||||
|
for(var/mob/living/silicon/robot/R in AI.connected_robots)
|
||||||
|
to_chat(R, "<span class='danger'>Law Notice</span>")
|
||||||
|
R.laws.show_laws(R)
|
||||||
|
if(usr != owner)
|
||||||
|
to_chat(usr, "<span class='notice'>Laws displayed.</span>")
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/ui_interact(mob/user, datum/tgui/ui)
|
||||||
|
owner.lawsync()
|
||||||
|
return ..() // 800, is_malf(user) ? 600 : 400
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/ui_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
data["ion_law_nr"] = ionnum()
|
||||||
|
data["ion_law"] = ion_law
|
||||||
|
data["zeroth_law"] = zeroth_law
|
||||||
|
data["inherent_law"] = inherent_law
|
||||||
|
data["supplied_law"] = supplied_law
|
||||||
|
data["supplied_law_position"] = supplied_law_position
|
||||||
|
|
||||||
|
package_laws(data, "zeroth_laws", list(owner.laws.zeroth_law))
|
||||||
|
package_laws(data, "ion_laws", owner.laws.ion_laws)
|
||||||
|
package_laws(data, "inherent_laws", owner.laws.inherent_laws)
|
||||||
|
package_laws(data, "supplied_laws", owner.laws.supplied_laws)
|
||||||
|
|
||||||
|
data["isAI"] = isAI(owner)
|
||||||
|
data["isMalf"] = is_malf(user)
|
||||||
|
data["isSlaved"] = owner.is_slaved()
|
||||||
|
data["isAdmin"] = is_admin(user)
|
||||||
|
|
||||||
|
var/list/channels = list()
|
||||||
|
for(var/ch_name in owner.law_channels())
|
||||||
|
channels[++channels.len] = list("channel" = ch_name)
|
||||||
|
data["channel"] = owner.lawchannel
|
||||||
|
data["channels"] = channels
|
||||||
|
data["law_sets"] = package_multiple_laws(data["isAdmin"] ? admin_laws : player_laws)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws)
|
||||||
|
var/list/packaged_laws = list()
|
||||||
|
for(var/datum/ai_law/AL in laws)
|
||||||
|
packaged_laws[++packaged_laws.len] = list("law" = AL.law, "index" = AL.get_index(), "state" = owner.laws.get_state_law(AL), "ref" = "\ref[AL]")
|
||||||
|
data[field] = packaged_laws
|
||||||
|
data["has_[field]"] = packaged_laws.len
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/proc/package_multiple_laws(var/list/datum/ai_laws/laws)
|
||||||
|
var/list/law_sets = list()
|
||||||
|
for(var/datum/ai_laws/ALs in laws)
|
||||||
|
var/list/packaged_laws = list()
|
||||||
|
package_laws(packaged_laws, "zeroth_laws", list(ALs.zeroth_law, ALs.zeroth_law_borg))
|
||||||
|
package_laws(packaged_laws, "ion_laws", ALs.ion_laws)
|
||||||
|
package_laws(packaged_laws, "inherent_laws", ALs.inherent_laws)
|
||||||
|
package_laws(packaged_laws, "supplied_laws", ALs.supplied_laws)
|
||||||
|
law_sets[++law_sets.len] = list("name" = ALs.name, "header" = ALs.law_header, "ref" = "\ref[ALs]","laws" = packaged_laws)
|
||||||
|
|
||||||
|
return law_sets
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/proc/is_malf(var/mob/user)
|
||||||
|
return (is_admin(user) && !owner.is_slaved()) || is_special_role(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/proc/is_special_role(var/mob/user)
|
||||||
|
if(user.mind.special_role)
|
||||||
|
return TRUE
|
||||||
|
else
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/mob/living/silicon/proc/is_slaved()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
/mob/living/silicon/robot/is_slaved()
|
||||||
|
return lawupdate && connected_ai ? sanitize(connected_ai.name) : null
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/proc/sync_laws(var/mob/living/silicon/ai/AI)
|
||||||
|
if(!AI)
|
||||||
|
return
|
||||||
|
for(var/mob/living/silicon/robot/R in AI.connected_robots)
|
||||||
|
R.sync()
|
||||||
|
log_and_message_admins("has syncronized [AI]'s laws with its borgs.")
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/robot
|
||||||
|
/datum/tgui_module/law_manager/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
|
|
||||||
|
/datum/tgui_module/law_manager/admin
|
||||||
|
/datum/tgui_module/law_manager/admin/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_admin_state
|
||||||
235
code/modules/tgui/modules/ntos-only/cardmod.dm
Normal file
235
code/modules/tgui/modules/ntos-only/cardmod.dm
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
// This really should be used for both regular ID computers and NTOS, but
|
||||||
|
// the data structures are just different enough right now that I can't be assed
|
||||||
|
/datum/tgui_module/cardmod
|
||||||
|
name = "ID card modification program"
|
||||||
|
ntos = TRUE
|
||||||
|
tgui_id = "IdentificationComputer"
|
||||||
|
var/mod_mode = 1
|
||||||
|
var/is_centcom = 0
|
||||||
|
|
||||||
|
/datum/tgui_module/cardmod/tgui_static_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
if(data_core)
|
||||||
|
data_core.get_manifest_list()
|
||||||
|
data["manifest"] = PDA_Manifest
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/cardmod/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/datum/computer_file/program/card_mod/program = host
|
||||||
|
if(!istype(program))
|
||||||
|
return 0
|
||||||
|
var/list/data = ..()
|
||||||
|
data["station_name"] = station_name()
|
||||||
|
data["mode"] = mod_mode
|
||||||
|
data["printing"] = FALSE
|
||||||
|
if(program && program.computer)
|
||||||
|
data["have_id_slot"] = !!program.computer.card_slot
|
||||||
|
data["have_printer"] = !!program.computer.nano_printer
|
||||||
|
data["authenticated"] = program.can_run(user)
|
||||||
|
if(!program.computer.card_slot)
|
||||||
|
mod_mode = 0 //We can't modify IDs when there is no card reader
|
||||||
|
else
|
||||||
|
data["have_id_slot"] = 0
|
||||||
|
data["have_printer"] = 0
|
||||||
|
data["authenticated"] = 0
|
||||||
|
data["centcom_access"] = is_centcom
|
||||||
|
|
||||||
|
|
||||||
|
data["has_modify"] = null
|
||||||
|
data["account_number"] = null
|
||||||
|
data["id_rank"] = null
|
||||||
|
data["target_owner"] = null
|
||||||
|
data["target_name"] = null
|
||||||
|
if(program && program.computer && program.computer.card_slot)
|
||||||
|
var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
|
||||||
|
data["has_modify"] = !!id_card
|
||||||
|
data["account_number"] = id_card ? id_card.associated_account_number : null
|
||||||
|
data["id_rank"] = id_card && id_card.assignment ? id_card.assignment : "Unassigned"
|
||||||
|
data["target_owner"] = id_card && id_card.registered_name ? id_card.registered_name : "-----"
|
||||||
|
data["target_name"] = id_card ? id_card.name : "-----"
|
||||||
|
|
||||||
|
var/list/departments = list()
|
||||||
|
for(var/D in SSjob.get_all_department_datums())
|
||||||
|
var/datum/department/dept = D
|
||||||
|
if(!dept.assignable) // No AI ID cards for you.
|
||||||
|
continue
|
||||||
|
if(dept.centcom_only && !is_centcom)
|
||||||
|
continue
|
||||||
|
departments.Add(list(list(
|
||||||
|
"department_name" = dept.name,
|
||||||
|
"jobs" = format_jobs(SSjob.get_job_titles_in_department(dept.name)),
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["departments"] = departments
|
||||||
|
|
||||||
|
var/list/all_centcom_access = list()
|
||||||
|
var/list/regions = list()
|
||||||
|
if(program.computer.card_slot && program.computer.card_slot.stored_card)
|
||||||
|
var/obj/item/weapon/card/id/id_card = program.computer.card_slot.stored_card
|
||||||
|
if(is_centcom)
|
||||||
|
for(var/access in get_all_centcom_access())
|
||||||
|
all_centcom_access.Add(list(list(
|
||||||
|
"desc" = replacetext(get_centcom_access_desc(access), " ", " "),
|
||||||
|
"ref" = access,
|
||||||
|
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||||
|
data["all_centcom_access"] = all_centcom_access
|
||||||
|
else
|
||||||
|
for(var/i in ACCESS_REGION_SECURITY to ACCESS_REGION_SUPPLY)
|
||||||
|
var/list/accesses = list()
|
||||||
|
for(var/access in get_region_accesses(i))
|
||||||
|
if(get_access_desc(access))
|
||||||
|
accesses.Add(list(list(
|
||||||
|
"desc" = replacetext(get_access_desc(access), " ", " "),
|
||||||
|
"ref" = access,
|
||||||
|
"allowed" = (access in id_card.access) ? 1 : 0)))
|
||||||
|
|
||||||
|
regions.Add(list(list(
|
||||||
|
"name" = get_region_accesses_name(i),
|
||||||
|
"accesses" = accesses)))
|
||||||
|
data["regions"] = regions
|
||||||
|
|
||||||
|
data["regions"] = regions
|
||||||
|
data["all_centcom_access"] = all_centcom_access
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/cardmod/proc/format_jobs(list/jobs)
|
||||||
|
var/datum/computer_file/program/card_mod/program = host
|
||||||
|
if(!istype(program))
|
||||||
|
return null
|
||||||
|
|
||||||
|
var/obj/item/weapon/card/id/id_card = program.computer.card_slot ? program.computer.card_slot.stored_card : null
|
||||||
|
var/list/formatted = list()
|
||||||
|
for(var/job in jobs)
|
||||||
|
formatted.Add(list(list(
|
||||||
|
"display_name" = replacetext(job, " ", " "),
|
||||||
|
"target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned",
|
||||||
|
"job" = job)))
|
||||||
|
|
||||||
|
return formatted
|
||||||
|
|
||||||
|
/datum/tgui_module/cardmod/ui_act(action, list/params, datum/tgui/ui)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
var/datum/computer_file/program/card_mod/program = host
|
||||||
|
if(!istype(program))
|
||||||
|
return TRUE
|
||||||
|
var/obj/item/modular_computer/computer = tgui_host()
|
||||||
|
if(!istype(computer))
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/obj/item/weapon/card/id/user_id_card = usr.GetIdCard()
|
||||||
|
var/obj/item/weapon/card/id/id_card
|
||||||
|
if(computer.card_slot)
|
||||||
|
id_card = computer.card_slot.stored_card
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("mode")
|
||||||
|
mod_mode = clamp(text2num(params["mode_target"]), 0, 1)
|
||||||
|
. = TRUE
|
||||||
|
if("print")
|
||||||
|
if(computer && computer.nano_printer) //This option should never be called if there is no printer
|
||||||
|
if(!mod_mode)
|
||||||
|
if(program.can_run(usr, 1))
|
||||||
|
var/contents = {"<h4>Access Report</h4>
|
||||||
|
<u>Prepared By:</u> [user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]<br>
|
||||||
|
<u>For:</u> [id_card.registered_name ? id_card.registered_name : "Unregistered"]<br>
|
||||||
|
<hr>
|
||||||
|
<u>Assignment:</u> [id_card.assignment]<br>
|
||||||
|
<u>Account Number:</u> #[id_card.associated_account_number]<br>
|
||||||
|
<u>Blood Type:</u> [id_card.blood_type]<br><br>
|
||||||
|
<u>Access:</u><br>
|
||||||
|
"}
|
||||||
|
|
||||||
|
var/known_access_rights = get_access_ids(ACCESS_TYPE_STATION|ACCESS_TYPE_CENTCOM)
|
||||||
|
for(var/A in id_card.access)
|
||||||
|
if(A in known_access_rights)
|
||||||
|
contents += " [get_access_desc(A)]"
|
||||||
|
|
||||||
|
if(!computer.nano_printer.print_text(contents,"access report"))
|
||||||
|
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
|
||||||
|
else
|
||||||
|
var/contents = {"<h4>Crew Manifest</h4>
|
||||||
|
<br>
|
||||||
|
[data_core ? data_core.get_manifest(0) : ""]
|
||||||
|
"}
|
||||||
|
if(!computer.nano_printer.print_text(contents,text("crew manifest ([])", stationtime2text())))
|
||||||
|
to_chat(usr, "<span class='notice'>Hardware error: Printer was unable to print the file. It may be out of paper.</span>")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
computer.visible_message("<span class='notice'>\The [computer] prints out paper.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("modify")
|
||||||
|
if(computer && computer.card_slot)
|
||||||
|
if(id_card)
|
||||||
|
data_core.manifest_modify(id_card.registered_name, id_card.assignment, id_card.rank)
|
||||||
|
computer.proc_eject_id(usr)
|
||||||
|
. = TRUE
|
||||||
|
if("terminate")
|
||||||
|
if(computer && program.can_run(usr, 1))
|
||||||
|
id_card.assignment = "Dismissed" //VOREStation Edit: setting adjustment
|
||||||
|
id_card.access = list()
|
||||||
|
callHook("terminate_employee", list(id_card))
|
||||||
|
. = TRUE
|
||||||
|
if("reg")
|
||||||
|
if(computer && program.can_run(usr, 1))
|
||||||
|
var/temp_name = sanitizeName(params["reg"], allow_numbers = TRUE)
|
||||||
|
if(temp_name)
|
||||||
|
id_card.registered_name = temp_name
|
||||||
|
else
|
||||||
|
computer.visible_message("<span class='notice'>[computer] buzzes rudely.</span>")
|
||||||
|
. = TRUE
|
||||||
|
if("account")
|
||||||
|
if(computer && program.can_run(usr, 1))
|
||||||
|
var/account_num = text2num(params["account"])
|
||||||
|
id_card.associated_account_number = account_num
|
||||||
|
. = TRUE
|
||||||
|
if("assign")
|
||||||
|
if(computer && program.can_run(usr, 1) && id_card)
|
||||||
|
var/t1 = params["assign_target"]
|
||||||
|
if(t1 == "Custom")
|
||||||
|
var/temp_t = sanitize(input("Enter a custom job assignment.","Assignment", id_card.assignment), 45)
|
||||||
|
//let custom jobs function as an impromptu alt title, mainly for sechuds
|
||||||
|
if(temp_t)
|
||||||
|
id_card.assignment = temp_t
|
||||||
|
else
|
||||||
|
var/list/access = list()
|
||||||
|
if(is_centcom)
|
||||||
|
access = get_centcom_access(t1)
|
||||||
|
else
|
||||||
|
var/datum/job/jobdatum
|
||||||
|
for(var/jobtype in typesof(/datum/job))
|
||||||
|
var/datum/job/J = new jobtype
|
||||||
|
if(ckey(J.title) == ckey(t1))
|
||||||
|
jobdatum = J
|
||||||
|
break
|
||||||
|
if(!jobdatum)
|
||||||
|
to_chat(usr, "<span class='warning'>No log exists for this job: [t1]</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
access = jobdatum.get_access()
|
||||||
|
|
||||||
|
id_card.access = access
|
||||||
|
id_card.assignment = t1
|
||||||
|
id_card.rank = t1
|
||||||
|
|
||||||
|
callHook("reassign_employee", list(id_card))
|
||||||
|
. = TRUE
|
||||||
|
if("access")
|
||||||
|
if(computer && program.can_run(usr, 1))
|
||||||
|
var/access_type = text2num(params["access_target"])
|
||||||
|
var/access_allowed = text2num(params["allowed"])
|
||||||
|
if(access_type in get_access_ids(ACCESS_TYPE_STATION|ACCESS_TYPE_CENTCOM))
|
||||||
|
id_card.access -= access_type
|
||||||
|
if(!access_allowed)
|
||||||
|
id_card.access += access_type
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if(id_card)
|
||||||
|
id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])")
|
||||||
|
|
||||||
48
code/modules/tgui/modules/ntos-only/configurator.dm
Normal file
48
code/modules/tgui/modules/ntos-only/configurator.dm
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/datum/tgui_module/computer_configurator
|
||||||
|
name = "NTOS Computer Configuration Tool"
|
||||||
|
ntos = TRUE
|
||||||
|
tgui_id = "Configuration"
|
||||||
|
var/obj/item/modular_computer/movable = null
|
||||||
|
|
||||||
|
/datum/tgui_module/computer_configurator/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
movable = tgui_host()
|
||||||
|
// No computer connection, we can't get data from that.
|
||||||
|
if(!istype(movable))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
data["disk_size"] = movable.hard_drive.max_capacity
|
||||||
|
data["disk_used"] = movable.hard_drive.used_capacity
|
||||||
|
data["power_usage"] = movable.last_power_usage
|
||||||
|
data["battery_exists"] = movable.battery_module ? 1 : 0
|
||||||
|
if(movable.battery_module)
|
||||||
|
data["battery_rating"] = movable.battery_module.battery.maxcharge
|
||||||
|
data["battery_percent"] = round(movable.battery_module.battery.percent())
|
||||||
|
|
||||||
|
if(movable.battery_module && movable.battery_module.battery)
|
||||||
|
data["battery"] = list("max" = movable.battery_module.battery.maxcharge, "charge" = round(movable.battery_module.battery.charge))
|
||||||
|
|
||||||
|
var/list/hardware = movable.get_all_components()
|
||||||
|
var/list/all_entries[0]
|
||||||
|
for(var/obj/item/weapon/computer_hardware/H in hardware)
|
||||||
|
all_entries.Add(list(list(
|
||||||
|
"name" = H.name,
|
||||||
|
"desc" = H.desc,
|
||||||
|
"enabled" = H.enabled,
|
||||||
|
"critical" = H.critical,
|
||||||
|
"powerusage" = H.power_usage
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["hardware"] = all_entries
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/computer_configurator/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return
|
||||||
|
switch(action)
|
||||||
|
if("PC_toggle_component")
|
||||||
|
var/obj/item/weapon/computer_hardware/H = movable.find_hardware_by_name(params["name"])
|
||||||
|
if(H && istype(H))
|
||||||
|
H.enabled = !H.enabled
|
||||||
|
. = TRUE
|
||||||
476
code/modules/tgui/modules/ntos-only/email.dm
Normal file
476
code/modules/tgui/modules/ntos-only/email.dm
Normal file
@@ -0,0 +1,476 @@
|
|||||||
|
/datum/tgui_module/email_client
|
||||||
|
name = "Email Client"
|
||||||
|
tgui_id = "NtosEmailClient"
|
||||||
|
|
||||||
|
var/stored_login = ""
|
||||||
|
var/stored_password = ""
|
||||||
|
var/error = ""
|
||||||
|
|
||||||
|
var/msg_title = ""
|
||||||
|
var/msg_body = ""
|
||||||
|
var/msg_recipient = ""
|
||||||
|
var/datum/computer_file/msg_attachment = null
|
||||||
|
var/folder = "Inbox"
|
||||||
|
var/addressbook = FALSE
|
||||||
|
var/new_message = FALSE
|
||||||
|
|
||||||
|
var/last_message_count = 0 // How many messages were there during last check.
|
||||||
|
var/read_message_count = 0 // How many messages were there when user has last accessed the UI.
|
||||||
|
|
||||||
|
var/datum/computer_file/downloading = null
|
||||||
|
var/download_progress = 0
|
||||||
|
var/download_speed = 0
|
||||||
|
|
||||||
|
var/datum/computer_file/data/email_account/current_account = null
|
||||||
|
var/datum/computer_file/data/email_message/current_message = null
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/proc/log_in()
|
||||||
|
for(var/datum/computer_file/data/email_account/account in ntnet_global.email_accounts)
|
||||||
|
if(!account.can_login)
|
||||||
|
continue
|
||||||
|
if(account.login == stored_login)
|
||||||
|
if(account.password == stored_password)
|
||||||
|
if(account.suspended)
|
||||||
|
error = "This account has been suspended. Please contact the system administrator for assistance."
|
||||||
|
return 0
|
||||||
|
current_account = account
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
error = "Invalid Password"
|
||||||
|
return 0
|
||||||
|
error = "Invalid Login"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
// Returns 0 if no new messages were received, 1 if there is an unread message but notification has already been sent.
|
||||||
|
// and 2 if there is a new message that appeared in this tick (and therefore notification should be sent by the program).
|
||||||
|
/datum/tgui_module/email_client/proc/check_for_new_messages(var/messages_read = FALSE)
|
||||||
|
if(!current_account)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var/list/allmails = current_account.all_emails()
|
||||||
|
|
||||||
|
if(allmails.len > last_message_count)
|
||||||
|
. = 2
|
||||||
|
else if(allmails.len > read_message_count)
|
||||||
|
. = 1
|
||||||
|
else
|
||||||
|
. = 0
|
||||||
|
|
||||||
|
last_message_count = allmails.len
|
||||||
|
if(messages_read)
|
||||||
|
read_message_count = allmails.len
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/proc/log_out()
|
||||||
|
current_account = null
|
||||||
|
downloading = null
|
||||||
|
download_progress = 0
|
||||||
|
last_message_count = 0
|
||||||
|
read_message_count = 0
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
// Password has been changed by other client connected to this email account
|
||||||
|
if(current_account)
|
||||||
|
if(current_account.password != stored_password)
|
||||||
|
log_out()
|
||||||
|
error = "Invalid Password"
|
||||||
|
// Banned.
|
||||||
|
if(current_account.suspended)
|
||||||
|
log_out()
|
||||||
|
error = "This account has been suspended. Please contact the system administrator for assistance."
|
||||||
|
|
||||||
|
// So, TGUI has a bug/feature where it just conveniently doesn't bother to clear out old data if it only gets
|
||||||
|
// a partial data update; as such, we have to make sure to null all of these out ourselves so the UI works properly.
|
||||||
|
data["accounts"] = null
|
||||||
|
data["addressbook"] = null
|
||||||
|
data["cur_attachment_filename"] = null
|
||||||
|
data["cur_attachment_size"] = null
|
||||||
|
data["cur_body"] = null
|
||||||
|
data["cur_hasattachment"] = null
|
||||||
|
data["cur_source"] = null
|
||||||
|
data["cur_timestamp"] = null
|
||||||
|
data["cur_title"] = null
|
||||||
|
data["cur_uid"] = null
|
||||||
|
data["current_account"] = null
|
||||||
|
data["down_filename"] = null
|
||||||
|
data["down_progress"] = null
|
||||||
|
data["down_size"] = null
|
||||||
|
data["down_speed"] = null
|
||||||
|
data["downloading"] = null
|
||||||
|
data["error"] = null
|
||||||
|
data["folder"] = null
|
||||||
|
data["label_deleted"] = null
|
||||||
|
data["label_inbox"] = null
|
||||||
|
data["label_spam"] = null
|
||||||
|
data["messagecount"] = null
|
||||||
|
data["messages"] = null
|
||||||
|
data["msg_attachment_filename"] = null
|
||||||
|
data["msg_attachment_size"] = null
|
||||||
|
data["msg_body"] = null
|
||||||
|
data["msg_hasattachment"] = null
|
||||||
|
data["msg_recipient"] = null
|
||||||
|
data["msg_title"] = null
|
||||||
|
data["new_message"] = null
|
||||||
|
data["stored_login"] = null
|
||||||
|
data["stored_password"] = null
|
||||||
|
|
||||||
|
if(error)
|
||||||
|
data["error"] = error
|
||||||
|
else if(downloading)
|
||||||
|
data["downloading"] = 1
|
||||||
|
data["down_filename"] = "[downloading.filename].[downloading.filetype]"
|
||||||
|
data["down_progress"] = download_progress
|
||||||
|
data["down_size"] = downloading.size
|
||||||
|
data["down_speed"] = download_speed
|
||||||
|
|
||||||
|
else if(istype(current_account))
|
||||||
|
data["current_account"] = current_account.login
|
||||||
|
if(addressbook)
|
||||||
|
var/list/all_accounts = list()
|
||||||
|
for(var/datum/computer_file/data/email_account/account in ntnet_global.email_accounts)
|
||||||
|
if(!account.can_login)
|
||||||
|
continue
|
||||||
|
all_accounts.Add(list(list(
|
||||||
|
"login" = account.login
|
||||||
|
)))
|
||||||
|
data["addressbook"] = 1
|
||||||
|
data["accounts"] = all_accounts
|
||||||
|
else if(new_message)
|
||||||
|
data["new_message"] = 1
|
||||||
|
data["msg_title"] = msg_title
|
||||||
|
data["msg_body"] = pencode2html(msg_body)
|
||||||
|
data["msg_recipient"] = msg_recipient
|
||||||
|
if(msg_attachment)
|
||||||
|
data["msg_hasattachment"] = 1
|
||||||
|
data["msg_attachment_filename"] = "[msg_attachment.filename].[msg_attachment.filetype]"
|
||||||
|
data["msg_attachment_size"] = msg_attachment.size
|
||||||
|
else if (current_message)
|
||||||
|
data["cur_title"] = current_message.title
|
||||||
|
data["cur_body"] = pencode2html(current_message.stored_data)
|
||||||
|
data["cur_timestamp"] = current_message.timestamp
|
||||||
|
data["cur_source"] = current_message.source
|
||||||
|
data["cur_uid"] = current_message.uid
|
||||||
|
if(istype(current_message.attachment))
|
||||||
|
data["cur_hasattachment"] = 1
|
||||||
|
data["cur_attachment_filename"] = "[current_message.attachment.filename].[current_message.attachment.filetype]"
|
||||||
|
data["cur_attachment_size"] = current_message.attachment.size
|
||||||
|
else
|
||||||
|
data["label_inbox"] = "Inbox ([current_account.inbox.len])"
|
||||||
|
data["label_spam"] = "Spam ([current_account.spam.len])"
|
||||||
|
data["label_deleted"] = "Deleted ([current_account.deleted.len])"
|
||||||
|
var/list/message_source
|
||||||
|
if(folder == "Inbox")
|
||||||
|
message_source = current_account.inbox
|
||||||
|
else if(folder == "Spam")
|
||||||
|
message_source = current_account.spam
|
||||||
|
else if(folder == "Deleted")
|
||||||
|
message_source = current_account.deleted
|
||||||
|
|
||||||
|
if(message_source)
|
||||||
|
data["folder"] = folder
|
||||||
|
var/list/all_messages = list()
|
||||||
|
for(var/datum/computer_file/data/email_message/message in message_source)
|
||||||
|
all_messages.Add(list(list(
|
||||||
|
"title" = message.title,
|
||||||
|
"body" = pencode2html(message.stored_data),
|
||||||
|
"source" = message.source,
|
||||||
|
"timestamp" = message.timestamp,
|
||||||
|
"uid" = message.uid
|
||||||
|
)))
|
||||||
|
data["messages"] = all_messages
|
||||||
|
data["messagecount"] = all_messages.len
|
||||||
|
else
|
||||||
|
data["stored_login"] = stored_login
|
||||||
|
data["stored_password"] = stars(stored_password, 0)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/proc/find_message_by_fuid(var/fuid)
|
||||||
|
if(!istype(current_account))
|
||||||
|
return
|
||||||
|
|
||||||
|
// params works with strings, so this makes it a bit easier for us
|
||||||
|
if(istext(fuid))
|
||||||
|
fuid = text2num(fuid)
|
||||||
|
|
||||||
|
for(var/datum/computer_file/data/email_message/message in current_account.all_emails())
|
||||||
|
if(message.uid == fuid)
|
||||||
|
return message
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/proc/clear_message()
|
||||||
|
new_message = FALSE
|
||||||
|
msg_title = ""
|
||||||
|
msg_body = ""
|
||||||
|
msg_recipient = ""
|
||||||
|
msg_attachment = null
|
||||||
|
current_message = null
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/proc/relayed_process(var/netspeed)
|
||||||
|
download_speed = netspeed
|
||||||
|
if(!downloading)
|
||||||
|
return
|
||||||
|
download_progress = min(download_progress + netspeed, downloading.size)
|
||||||
|
if(download_progress >= downloading.size)
|
||||||
|
var/obj/item/modular_computer/MC = tgui_host()
|
||||||
|
if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
|
||||||
|
error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
|
||||||
|
downloading = null
|
||||||
|
download_progress = 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(MC.hard_drive.store_file(downloading))
|
||||||
|
error = "File successfully downloaded to local device."
|
||||||
|
else
|
||||||
|
error = "Error saving file: I/O Error: The hard drive may be full or nonfunctional."
|
||||||
|
downloading = null
|
||||||
|
download_progress = 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
/datum/tgui_module/email_client/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/mob/living/user = usr
|
||||||
|
check_for_new_messages(1) // Any actual interaction (button pressing) is considered as acknowledging received message, for the purpose of notification icons.
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("login")
|
||||||
|
log_in()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("logout")
|
||||||
|
log_out()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("reset")
|
||||||
|
error = ""
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("new_message")
|
||||||
|
new_message = TRUE
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("cancel")
|
||||||
|
if(addressbook)
|
||||||
|
addressbook = FALSE
|
||||||
|
else
|
||||||
|
clear_message()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("addressbook")
|
||||||
|
addressbook = TRUE
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("set_recipient")
|
||||||
|
msg_recipient = sanitize(params["set_recipient"])
|
||||||
|
addressbook = FALSE
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("edit_title")
|
||||||
|
var/newtitle = sanitize(params["val"], 100)
|
||||||
|
if(newtitle)
|
||||||
|
msg_title = newtitle
|
||||||
|
return 1
|
||||||
|
|
||||||
|
// This uses similar editing mechanism as the FileManager program, therefore it supports various paper tags and remembers formatting.
|
||||||
|
if("edit_body")
|
||||||
|
var/oldtext = html_decode(msg_body)
|
||||||
|
oldtext = replacetext(oldtext, "\[editorbr\]", "\n")
|
||||||
|
|
||||||
|
var/newtext = sanitize(replacetext(input(usr, "Enter your message. You may use most tags from paper formatting", "Message Editor", oldtext) as message|null, "\n", "\[editorbr\]"), 20000)
|
||||||
|
if(newtext)
|
||||||
|
msg_body = newtext
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("edit_recipient")
|
||||||
|
var/newrecipient = sanitize(params["val"], 100)
|
||||||
|
if(newrecipient)
|
||||||
|
msg_recipient = newrecipient
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("edit_login")
|
||||||
|
var/newlogin = sanitize(params["val"], 100)
|
||||||
|
if(newlogin)
|
||||||
|
stored_login = newlogin
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("edit_password")
|
||||||
|
var/newpass = sanitize(params["val"], 100)
|
||||||
|
if(newpass)
|
||||||
|
stored_password = newpass
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("delete")
|
||||||
|
if(!istype(current_account))
|
||||||
|
return 1
|
||||||
|
var/datum/computer_file/data/email_message/M = find_message_by_fuid(params["delete"])
|
||||||
|
if(!istype(M))
|
||||||
|
return 1
|
||||||
|
if(folder == "Deleted")
|
||||||
|
current_account.deleted.Remove(M)
|
||||||
|
qdel(M)
|
||||||
|
else
|
||||||
|
current_account.deleted.Add(M)
|
||||||
|
current_account.inbox.Remove(M)
|
||||||
|
current_account.spam.Remove(M)
|
||||||
|
if(current_message == M)
|
||||||
|
current_message = null
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("send")
|
||||||
|
if(!current_account)
|
||||||
|
return 1
|
||||||
|
if((msg_title == "") || (msg_body == "") || (msg_recipient == ""))
|
||||||
|
error = "Error sending mail: Title or message body is empty!"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
var/datum/computer_file/data/email_message/message = new()
|
||||||
|
message.title = msg_title
|
||||||
|
message.stored_data = msg_body
|
||||||
|
message.source = current_account.login
|
||||||
|
message.attachment = msg_attachment
|
||||||
|
if(!current_account.send_mail(msg_recipient, message))
|
||||||
|
error = "Error sending email: this address doesn't exist."
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
error = "Email successfully sent."
|
||||||
|
clear_message()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("set_folder")
|
||||||
|
folder = params["set_folder"]
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("reply")
|
||||||
|
var/datum/computer_file/data/email_message/M = find_message_by_fuid(params["reply"])
|
||||||
|
if(!istype(M))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
new_message = TRUE
|
||||||
|
msg_recipient = M.source
|
||||||
|
msg_title = "Re: [M.title]"
|
||||||
|
msg_body = "\[editorbr\]\[editorbr\]\[editorbr\]\[br\]==============================\[br\]\[editorbr\]"
|
||||||
|
msg_body += "Received by [current_account.login] at [M.timestamp]\[br\]\[editorbr\][M.stored_data]"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("view")
|
||||||
|
var/datum/computer_file/data/email_message/M = find_message_by_fuid(params["view"])
|
||||||
|
if(istype(M))
|
||||||
|
current_message = M
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("changepassword")
|
||||||
|
var/oldpassword = sanitize(input(user,"Please enter your old password:", "Password Change"), 100)
|
||||||
|
if(!oldpassword)
|
||||||
|
return 1
|
||||||
|
var/newpassword1 = sanitize(input(user,"Please enter your new password:", "Password Change"), 100)
|
||||||
|
if(!newpassword1)
|
||||||
|
return 1
|
||||||
|
var/newpassword2 = sanitize(input(user,"Please re-enter your new password:", "Password Change"), 100)
|
||||||
|
if(!newpassword2)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(!istype(current_account))
|
||||||
|
error = "Please log in before proceeding."
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(current_account.password != oldpassword)
|
||||||
|
error = "Incorrect original password"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(newpassword1 != newpassword2)
|
||||||
|
error = "The entered passwords do not match."
|
||||||
|
return 1
|
||||||
|
|
||||||
|
current_account.password = newpassword1
|
||||||
|
stored_password = newpassword1
|
||||||
|
error = "Your password has been successfully changed!"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
// The following entries are Modular Computer framework only, and therefore won't do anything in other cases (like AI View)
|
||||||
|
|
||||||
|
if("save")
|
||||||
|
// Fully dependant on modular computers here.
|
||||||
|
var/obj/item/modular_computer/MC = tgui_host()
|
||||||
|
|
||||||
|
if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
|
||||||
|
error = "Error exporting file. Are you using a functional and NTOS-compliant device?"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
var/filename = sanitize(input(user,"Please specify file name:", "Message export"), 100)
|
||||||
|
if(!filename)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
var/datum/computer_file/data/email_message/M = find_message_by_fuid(params["save"])
|
||||||
|
var/datum/computer_file/data/mail = istype(M) ? M.export() : null
|
||||||
|
if(!istype(mail))
|
||||||
|
return 1
|
||||||
|
mail.filename = filename
|
||||||
|
if(!MC.hard_drive || !MC.hard_drive.store_file(mail))
|
||||||
|
error = "Internal I/O error when writing file, the hard drive may be full."
|
||||||
|
else
|
||||||
|
error = "Email exported successfully"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("addattachment")
|
||||||
|
var/obj/item/modular_computer/MC = tgui_host()
|
||||||
|
msg_attachment = null
|
||||||
|
|
||||||
|
if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
|
||||||
|
error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
var/list/filenames = list()
|
||||||
|
for(var/datum/computer_file/CF in MC.hard_drive.stored_files)
|
||||||
|
if(CF.unsendable)
|
||||||
|
continue
|
||||||
|
filenames.Add(CF.filename)
|
||||||
|
var/picked_file = input(user, "Please pick a file to send as attachment (max 32GQ)") as null|anything in filenames
|
||||||
|
|
||||||
|
if(!picked_file)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
|
||||||
|
error = "Error uploading file. Are you using a functional and NTOSv2-compliant device?"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
for(var/datum/computer_file/CF in MC.hard_drive.stored_files)
|
||||||
|
if(CF.unsendable)
|
||||||
|
continue
|
||||||
|
if(CF.filename == picked_file)
|
||||||
|
msg_attachment = CF.clone()
|
||||||
|
break
|
||||||
|
if(!istype(msg_attachment))
|
||||||
|
msg_attachment = null
|
||||||
|
error = "Unknown error when uploading attachment."
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if(msg_attachment.size > 32)
|
||||||
|
error = "Error uploading attachment: File exceeds maximal permitted file size of 32GQ."
|
||||||
|
msg_attachment = null
|
||||||
|
else
|
||||||
|
error = "File [msg_attachment.filename].[msg_attachment.filetype] has been successfully uploaded."
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("downloadattachment")
|
||||||
|
if(!current_account || !current_message || !current_message.attachment)
|
||||||
|
return 1
|
||||||
|
var/obj/item/modular_computer/MC = tgui_host()
|
||||||
|
if(!istype(MC) || !MC.hard_drive || !MC.hard_drive.check_functionality())
|
||||||
|
error = "Error downloading file. Are you using a functional and NTOSv2-compliant device?"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
downloading = current_message.attachment.clone()
|
||||||
|
download_progress = 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("canceldownload")
|
||||||
|
downloading = null
|
||||||
|
download_progress = 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if("remove_attachment")
|
||||||
|
msg_attachment = null
|
||||||
|
return 1
|
||||||
241
code/modules/tgui/modules/ntos-only/uav.dm
Normal file
241
code/modules/tgui/modules/ntos-only/uav.dm
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
/datum/tgui_module/uav
|
||||||
|
name = "UAV Control"
|
||||||
|
tgui_id = "UAV"
|
||||||
|
ntos = TRUE
|
||||||
|
var/obj/item/device/uav/current_uav = null //The UAV we're watching
|
||||||
|
var/signal_strength = 0 //Our last signal strength report (cached for a few seconds)
|
||||||
|
var/signal_test_counter = 0 //How long until next signal strength check
|
||||||
|
var/list/viewers //Who's viewing a UAV through us
|
||||||
|
var/adhoc_range = 30 //How far we can operate on a UAV without NTnet
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
if(current_uav)
|
||||||
|
if(QDELETED(current_uav))
|
||||||
|
set_current(null)
|
||||||
|
else if(signal_test_counter-- <= 0)
|
||||||
|
signal_strength = get_signal_to(current_uav)
|
||||||
|
if(!signal_strength)
|
||||||
|
set_current(null)
|
||||||
|
else // Don't reset counter until we find a UAV that's actually in range we can stay connected to
|
||||||
|
signal_test_counter = 20
|
||||||
|
|
||||||
|
data["current_uav"] = null
|
||||||
|
if(current_uav)
|
||||||
|
data["current_uav"] = list("status" = current_uav.get_status_string(), "power" = current_uav.state == 1 ? 1 : null)
|
||||||
|
data["signal_strength"] = signal_strength ? signal_strength >= 2 ? "High" : "Low" : "None"
|
||||||
|
data["in_use"] = LAZYLEN(viewers)
|
||||||
|
|
||||||
|
var/list/paired_map = list()
|
||||||
|
var/obj/item/modular_computer/mc_host = tgui_host()
|
||||||
|
if(istype(mc_host))
|
||||||
|
for(var/puav in mc_host.paired_uavs)
|
||||||
|
var/weakref/wr = puav
|
||||||
|
var/obj/item/device/uav/U = wr.resolve()
|
||||||
|
paired_map.Add(list(list("name" = "[U ? U.nickname : "!!Missing!!"]", "uavref" = "\ref[U]")))
|
||||||
|
|
||||||
|
data["paired_uavs"] = paired_map
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/ui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("switch_uav")
|
||||||
|
var/obj/item/device/uav/U = locate(params["switch_uav"]) //This is a \ref to the UAV itself
|
||||||
|
if(!istype(U))
|
||||||
|
to_chat(usr,"<span class='warning'>Something is blocking the connection to that UAV. In-person investigation is required.</span>")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(!get_signal_to(U))
|
||||||
|
to_chat(usr,"<span class='warning'>The screen freezes for a moment, before returning to the UAV selection menu. It's not able to connect to that UAV.</span>")
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
set_current(U)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("del_uav")
|
||||||
|
var/refstring = params["del_uav"] //This is a \ref to the UAV itself
|
||||||
|
var/obj/item/modular_computer/mc_host = tgui_host()
|
||||||
|
//This is so we can really scrape up any weakrefs that can't resolve
|
||||||
|
for(var/weakref/wr in mc_host.paired_uavs)
|
||||||
|
if(wr.ref == refstring)
|
||||||
|
if(current_uav?.weakref == wr)
|
||||||
|
set_current(null)
|
||||||
|
LAZYREMOVE(mc_host.paired_uavs, wr)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("view_uav")
|
||||||
|
if(!current_uav)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(current_uav.check_eye(usr) < 0)
|
||||||
|
to_chat(usr,"<span class='warning'>The screen freezes for a moment, before returning to the UAV selection menu. It's not able to connect to that UAV.</span>")
|
||||||
|
else
|
||||||
|
viewing_uav(usr) ? unlook(usr) : look(usr)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("power_uav")
|
||||||
|
if(!current_uav)
|
||||||
|
return FALSE
|
||||||
|
else if(current_uav.toggle_power())
|
||||||
|
//Clean up viewers faster
|
||||||
|
if(LAZYLEN(viewers))
|
||||||
|
for(var/weakref/W in viewers)
|
||||||
|
var/M = W.resolve()
|
||||||
|
if(M)
|
||||||
|
unlook(M)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/proc/set_current(var/obj/item/device/uav/U)
|
||||||
|
if(current_uav == U)
|
||||||
|
return
|
||||||
|
|
||||||
|
signal_strength = 0
|
||||||
|
current_uav = U
|
||||||
|
|
||||||
|
if(LAZYLEN(viewers))
|
||||||
|
for(var/weakref/W in viewers)
|
||||||
|
var/M = W.resolve()
|
||||||
|
if(M)
|
||||||
|
if(current_uav)
|
||||||
|
to_chat(M, "<span class='warning'>You're disconnected from the UAV's camera!</span>")
|
||||||
|
unlook(M)
|
||||||
|
else
|
||||||
|
look(M)
|
||||||
|
|
||||||
|
////
|
||||||
|
//// Finding signal strength between us and the UAV
|
||||||
|
////
|
||||||
|
/datum/tgui_module/uav/proc/get_signal_to(atom/movable/AM)
|
||||||
|
// Following roughly the ntnet signal levels
|
||||||
|
// 0 is none
|
||||||
|
// 1 is weak
|
||||||
|
// 2 is strong
|
||||||
|
var/obj/item/modular_computer/host = tgui_host() //Better not add this to anything other than modular computers.
|
||||||
|
if(!istype(host))
|
||||||
|
return
|
||||||
|
var/our_signal = host.get_ntnet_status() //1 low, 2 good, 3 wired, 0 none
|
||||||
|
var/their_z = get_z(AM)
|
||||||
|
|
||||||
|
//If we have no NTnet connection don't bother getting theirs
|
||||||
|
if(!our_signal)
|
||||||
|
if(get_z(host) == their_z && (get_dist(host, AM) < adhoc_range))
|
||||||
|
return 1 //We can connect (with weak signal) in same z without ntnet, within 30 turfs
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var/list/zlevels_in_range = using_map.get_map_levels(their_z, FALSE)
|
||||||
|
var/list/zlevels_in_long_range = using_map.get_map_levels(their_z, TRUE, om_range = DEFAULT_OVERMAP_RANGE) - zlevels_in_range
|
||||||
|
var/their_signal = 0
|
||||||
|
for(var/relay in ntnet_global.relays)
|
||||||
|
var/obj/machinery/ntnet_relay/R = relay
|
||||||
|
if(!R.operable())
|
||||||
|
continue
|
||||||
|
if(R.z == their_z)
|
||||||
|
their_signal = 2
|
||||||
|
break
|
||||||
|
if(R.z in zlevels_in_range)
|
||||||
|
their_signal = 2
|
||||||
|
break
|
||||||
|
if(R.z in zlevels_in_long_range)
|
||||||
|
their_signal = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
if(!their_signal) //They have no NTnet at all
|
||||||
|
if(get_z(host) == their_z && (get_dist(host, AM) < adhoc_range))
|
||||||
|
return 1 //We can connect (with weak signal) in same z without ntnet, within 30 turfs
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return max(our_signal, their_signal)
|
||||||
|
|
||||||
|
/* All handling viewers */
|
||||||
|
/datum/tgui_module/uav/Destroy()
|
||||||
|
if(LAZYLEN(viewers))
|
||||||
|
for(var/weakref/W in viewers)
|
||||||
|
var/M = W.resolve()
|
||||||
|
if(M)
|
||||||
|
unlook(M)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/tgui_status(mob/user)
|
||||||
|
. = ..()
|
||||||
|
if(. > UI_DISABLED)
|
||||||
|
if(viewing_uav(user))
|
||||||
|
look(user)
|
||||||
|
return
|
||||||
|
unlook(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/tgui_close(mob/user)
|
||||||
|
. = ..()
|
||||||
|
unlook(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/proc/viewing_uav(mob/user)
|
||||||
|
return (weakref(user) in viewers)
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/proc/look(mob/user)
|
||||||
|
if(issilicon(user)) //Too complicated for me to want to mess with at the moment
|
||||||
|
to_chat(user, "<span class='warning'>Regulations prevent you from controlling several corporeal forms at the same time!</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(!current_uav)
|
||||||
|
return
|
||||||
|
|
||||||
|
if(user.machine != tgui_host())
|
||||||
|
user.set_machine(tgui_host())
|
||||||
|
user.reset_view(current_uav)
|
||||||
|
current_uav.add_master(user)
|
||||||
|
LAZYDISTINCTADD(viewers, weakref(user))
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/proc/unlook(mob/user)
|
||||||
|
user.unset_machine()
|
||||||
|
user.reset_view()
|
||||||
|
if(current_uav)
|
||||||
|
current_uav.remove_master(user)
|
||||||
|
LAZYREMOVE(viewers, weakref(user))
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/check_eye(mob/user)
|
||||||
|
if(get_dist(user, tgui_host()) > 1 || user.blinded || !current_uav)
|
||||||
|
unlook(user)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
var/viewflag = current_uav.check_eye(user)
|
||||||
|
if(viewflag < 0) //camera doesn't work
|
||||||
|
unlook(user)
|
||||||
|
return -1
|
||||||
|
|
||||||
|
return viewflag
|
||||||
|
|
||||||
|
////
|
||||||
|
//// Relaying movements to the UAV
|
||||||
|
////
|
||||||
|
/datum/tgui_module/uav/relaymove(var/mob/user, direction)
|
||||||
|
if(current_uav)
|
||||||
|
return current_uav.relaymove(user, direction, signal_strength)
|
||||||
|
|
||||||
|
////
|
||||||
|
//// The effects when looking through a UAV
|
||||||
|
////
|
||||||
|
/datum/tgui_module/uav/apply_visual(mob/M)
|
||||||
|
if(!M.client)
|
||||||
|
return
|
||||||
|
if(weakref(M) in viewers)
|
||||||
|
M.overlay_fullscreen("fishbed",/obj/screen/fullscreen/fishbed)
|
||||||
|
M.overlay_fullscreen("scanlines",/obj/screen/fullscreen/scanline)
|
||||||
|
|
||||||
|
if(signal_strength <= 1)
|
||||||
|
M.overlay_fullscreen("whitenoise",/obj/screen/fullscreen/noise)
|
||||||
|
else
|
||||||
|
M.clear_fullscreen("whitenoise", 0)
|
||||||
|
else
|
||||||
|
remove_visual(M)
|
||||||
|
|
||||||
|
/datum/tgui_module/uav/remove_visual(mob/M)
|
||||||
|
if(!M.client)
|
||||||
|
return
|
||||||
|
M.clear_fullscreen("fishbed",0)
|
||||||
|
M.clear_fullscreen("scanlines",0)
|
||||||
|
M.clear_fullscreen("whitenoise",0)
|
||||||
460
code/modules/tgui/modules/overmap.dm
Normal file
460
code/modules/tgui/modules/overmap.dm
Normal file
@@ -0,0 +1,460 @@
|
|||||||
|
/datum/tgui_module/ship
|
||||||
|
var/obj/effect/overmap/visitable/ship/linked
|
||||||
|
var/list/viewers
|
||||||
|
var/extra_view = 0
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/New()
|
||||||
|
. = ..()
|
||||||
|
sync_linked()
|
||||||
|
if(linked)
|
||||||
|
name = "[linked.name] [name]"
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/Destroy()
|
||||||
|
if(LAZYLEN(viewers))
|
||||||
|
for(var/weakref/W in viewers)
|
||||||
|
var/M = W.resolve()
|
||||||
|
if(M)
|
||||||
|
unlook(M)
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/tgui_status(mob/user)
|
||||||
|
. = ..()
|
||||||
|
if(. > UI_DISABLED)
|
||||||
|
if(viewing_overmap(user))
|
||||||
|
look(user)
|
||||||
|
return
|
||||||
|
unlook(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/tgui_close(mob/user)
|
||||||
|
. = ..()
|
||||||
|
user.unset_machine()
|
||||||
|
unlook(user)
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/sync_linked()
|
||||||
|
var/obj/effect/overmap/visitable/ship/sector = get_overmap_sector(get_z(tgui_host()))
|
||||||
|
if(!sector)
|
||||||
|
return
|
||||||
|
return attempt_hook_up_recursive(sector)
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/attempt_hook_up_recursive(obj/effect/overmap/visitable/ship/sector)
|
||||||
|
if(attempt_hook_up(sector))
|
||||||
|
return sector
|
||||||
|
for(var/obj/effect/overmap/visitable/ship/candidate in sector)
|
||||||
|
if((. = .(candidate)))
|
||||||
|
return
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/attempt_hook_up(obj/effect/overmap/visitable/ship/sector)
|
||||||
|
if(!istype(sector))
|
||||||
|
return
|
||||||
|
if(sector.check_ownership(tgui_host()))
|
||||||
|
linked = sector
|
||||||
|
return 1
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/look(var/mob/user)
|
||||||
|
if(linked)
|
||||||
|
user.set_machine(src)
|
||||||
|
user.reset_view(linked)
|
||||||
|
user.set_viewsize(world.view + extra_view)
|
||||||
|
GLOB.moved_event.register(user, src, /datum/tgui_module/ship/proc/unlook)
|
||||||
|
LAZYDISTINCTADD(viewers, weakref(user))
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/unlook(var/mob/user)
|
||||||
|
user.reset_view()
|
||||||
|
user.set_viewsize() // reset to default
|
||||||
|
GLOB.moved_event.unregister(user, src, /datum/tgui_module/ship/proc/unlook)
|
||||||
|
LAZYREMOVE(viewers, weakref(user))
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/proc/viewing_overmap(mob/user)
|
||||||
|
return (weakref(user) in viewers)
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/check_eye(var/mob/user)
|
||||||
|
if(!get_dist(user, tgui_host()) > 1 || user.blinded || !linked)
|
||||||
|
unlook(user)
|
||||||
|
return -1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
/datum/tgui_module/ship/nav
|
||||||
|
name = "Navigation Display"
|
||||||
|
tgui_id = "OvermapNavigation"
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/nav/ui_interact(mob/user, datum/tgui/ui)
|
||||||
|
if(!linked)
|
||||||
|
var/obj/machinery/computer/ship/navigation/host = tgui_host()
|
||||||
|
if(istype(host))
|
||||||
|
// Real Computer path
|
||||||
|
host.display_reconnect_dialog(user, "Navigation")
|
||||||
|
return
|
||||||
|
|
||||||
|
// NTOS Path
|
||||||
|
if(!sync_linked())
|
||||||
|
to_chat(user, "<span class='warning'>You don't appear to be on a spaceship...</span>")
|
||||||
|
if(ui)
|
||||||
|
ui.close(can_be_suspended = FALSE)
|
||||||
|
if(ntos)
|
||||||
|
var/obj/item/modular_computer/M = tgui_host()
|
||||||
|
if(istype(M))
|
||||||
|
M.kill_program()
|
||||||
|
return
|
||||||
|
|
||||||
|
. = ..()
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/nav/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
var/turf/T = get_turf(linked)
|
||||||
|
var/obj/effect/overmap/visitable/sector/current_sector = locate() in T
|
||||||
|
|
||||||
|
data["sector"] = current_sector ? current_sector.name : "Deep Space"
|
||||||
|
data["sector_info"] = current_sector ? current_sector.desc : "Not Available"
|
||||||
|
data["s_x"] = linked.x
|
||||||
|
data["s_y"] = linked.y
|
||||||
|
data["speed"] = round(linked.get_speed()*1000, 0.01)
|
||||||
|
data["accel"] = round(linked.get_acceleration()*1000, 0.01)
|
||||||
|
data["heading"] = linked.get_heading_degrees()
|
||||||
|
data["viewing"] = viewing_overmap(user)
|
||||||
|
|
||||||
|
if(linked.get_speed())
|
||||||
|
data["ETAnext"] = "[round(linked.ETA()/10)] seconds"
|
||||||
|
else
|
||||||
|
data["ETAnext"] = "N/A"
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/nav/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if(!linked)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(action == "viewing")
|
||||||
|
viewing_overmap(usr) ? unlook(usr) : look(usr)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/nav/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
// Full monty control computer
|
||||||
|
/datum/tgui_module/ship/fullmonty
|
||||||
|
name = "Full Monty Overmap Control"
|
||||||
|
tgui_id = "OvermapFull"
|
||||||
|
// HELM
|
||||||
|
var/autopilot = 0
|
||||||
|
var/autopilot_disabled = TRUE
|
||||||
|
var/list/known_sectors = list()
|
||||||
|
var/dx //desitnation
|
||||||
|
var/dy //coordinates
|
||||||
|
var/speedlimit = 1/(20 SECONDS) //top speed for autopilot, 5
|
||||||
|
var/accellimit = 0.001 //manual limiter for acceleration
|
||||||
|
// SENSORS
|
||||||
|
var/obj/machinery/shipsensors/sensors
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/fullmonty/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_admin_state
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/fullmonty/New(host, obj/effect/overmap/visitable/ship/new_linked)
|
||||||
|
. = ..()
|
||||||
|
if(!istype(new_linked))
|
||||||
|
CRASH("Warning, [new_linked] is not an overmap ship! Something went horribly wrong for [usr]!")
|
||||||
|
return
|
||||||
|
linked = new_linked
|
||||||
|
name = initial(name) + " ([linked.name])"
|
||||||
|
// HELM
|
||||||
|
var/area/overmap/map = locate() in world
|
||||||
|
for(var/obj/effect/overmap/visitable/sector/S in map)
|
||||||
|
if(S.known)
|
||||||
|
var/datum/computer_file/data/waypoint/R = new()
|
||||||
|
R.fields["name"] = S.name
|
||||||
|
R.fields["x"] = S.x
|
||||||
|
R.fields["y"] = S.y
|
||||||
|
known_sectors[S.name] = R
|
||||||
|
// SENSORS
|
||||||
|
for(var/obj/machinery/shipsensors/S in global.machines)
|
||||||
|
if(linked.check_ownership(S))
|
||||||
|
sensors = S
|
||||||
|
break
|
||||||
|
|
||||||
|
/datum/tgui_module/ship/fullmonty/relaymove(var/mob/user, direction)
|
||||||
|
if(viewing_overmap(user) && linked)
|
||||||
|
direction = turn(direction,pick(90,-90))
|
||||||
|
linked.relaymove(user, direction, accellimit)
|
||||||
|
return 1
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
// Beware ye eyes. This holds all of the data from helm, engine, and sensor control all at once.
|
||||||
|
/datum/tgui_module/ship/fullmonty/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
// HELM
|
||||||
|
var/turf/T = get_turf(linked)
|
||||||
|
var/obj/effect/overmap/visitable/sector/current_sector = locate() in T
|
||||||
|
|
||||||
|
data["sector"] = current_sector ? current_sector.name : "Deep Space"
|
||||||
|
data["sector_info"] = current_sector ? current_sector.desc : "Not Available"
|
||||||
|
data["landed"] = linked.get_landed_info()
|
||||||
|
data["s_x"] = linked.x
|
||||||
|
data["s_y"] = linked.y
|
||||||
|
data["dest"] = dy && dx
|
||||||
|
data["d_x"] = dx
|
||||||
|
data["d_y"] = dy
|
||||||
|
data["speedlimit"] = speedlimit ? speedlimit*1000 : "Halted"
|
||||||
|
data["accel"] = min(round(linked.get_acceleration()*1000, 0.01),accellimit*1000)
|
||||||
|
data["heading"] = linked.get_heading_degrees()
|
||||||
|
data["autopilot_disabled"] = autopilot_disabled
|
||||||
|
data["autopilot"] = autopilot
|
||||||
|
data["manual_control"] = viewing_overmap(user)
|
||||||
|
data["canburn"] = linked.can_burn()
|
||||||
|
data["accellimit"] = accellimit*1000
|
||||||
|
|
||||||
|
var/speed = round(linked.get_speed()*1000, 0.01)
|
||||||
|
var/speed_color = null
|
||||||
|
if(linked.get_speed() < SHIP_SPEED_SLOW)
|
||||||
|
speed_color = "good"
|
||||||
|
if(linked.get_speed() > SHIP_SPEED_FAST)
|
||||||
|
speed_color = "average"
|
||||||
|
data["speed"] = speed
|
||||||
|
data["speed_color"] = speed_color
|
||||||
|
|
||||||
|
if(linked.get_speed())
|
||||||
|
data["ETAnext"] = "[round(linked.ETA()/10)] seconds"
|
||||||
|
else
|
||||||
|
data["ETAnext"] = "N/A"
|
||||||
|
|
||||||
|
var/list/locations[0]
|
||||||
|
for (var/key in known_sectors)
|
||||||
|
var/datum/computer_file/data/waypoint/R = known_sectors[key]
|
||||||
|
var/list/rdata[0]
|
||||||
|
rdata["name"] = R.fields["name"]
|
||||||
|
rdata["x"] = R.fields["x"]
|
||||||
|
rdata["y"] = R.fields["y"]
|
||||||
|
rdata["reference"] = "\ref[R]"
|
||||||
|
locations.Add(list(rdata))
|
||||||
|
|
||||||
|
data["locations"] = locations
|
||||||
|
|
||||||
|
// ENGINES
|
||||||
|
data["global_state"] = linked.engines_state
|
||||||
|
data["global_limit"] = round(linked.thrust_limit*100)
|
||||||
|
var/total_thrust = 0
|
||||||
|
|
||||||
|
var/list/enginfo = list()
|
||||||
|
for(var/datum/ship_engine/E in linked.engines)
|
||||||
|
var/list/rdata = list()
|
||||||
|
rdata["eng_type"] = E.name
|
||||||
|
rdata["eng_on"] = E.is_on()
|
||||||
|
rdata["eng_thrust"] = E.get_thrust()
|
||||||
|
rdata["eng_thrust_limiter"] = round(E.get_thrust_limit()*100)
|
||||||
|
var/list/status = E.get_status()
|
||||||
|
if(!islist(status))
|
||||||
|
log_runtime(EXCEPTION("Warning, ship [E.name] (\ref[E]) for [linked.name] returned a non-list status!"))
|
||||||
|
status = list("Error")
|
||||||
|
rdata["eng_status"] = status
|
||||||
|
rdata["eng_reference"] = "\ref[E]"
|
||||||
|
total_thrust += E.get_thrust()
|
||||||
|
enginfo.Add(list(rdata))
|
||||||
|
|
||||||
|
data["engines_info"] = enginfo
|
||||||
|
data["total_thrust"] = total_thrust
|
||||||
|
|
||||||
|
// SENSORS
|
||||||
|
data["viewing"] = viewing_overmap(user)
|
||||||
|
data["on"] = 0
|
||||||
|
data["range"] = "N/A"
|
||||||
|
data["health"] = 0
|
||||||
|
data["max_health"] = 0
|
||||||
|
data["heat"] = 0
|
||||||
|
data["critical_heat"] = 0
|
||||||
|
data["status"] = "MISSING"
|
||||||
|
data["contacts"] = list()
|
||||||
|
|
||||||
|
if(sensors)
|
||||||
|
data["on"] = sensors.use_power
|
||||||
|
data["range"] = sensors.range
|
||||||
|
data["health"] = sensors.health
|
||||||
|
data["max_health"] = sensors.max_health
|
||||||
|
data["heat"] = sensors.heat
|
||||||
|
data["critical_heat"] = sensors.critical_heat
|
||||||
|
if(sensors.health == 0)
|
||||||
|
data["status"] = "DESTROYED"
|
||||||
|
else if(!sensors.powered())
|
||||||
|
data["status"] = "NO POWER"
|
||||||
|
else if(!sensors.in_vacuum())
|
||||||
|
data["status"] = "VACUUM SEAL BROKEN"
|
||||||
|
else
|
||||||
|
data["status"] = "OK"
|
||||||
|
var/list/contacts = list()
|
||||||
|
for(var/obj/effect/overmap/O in view(7,linked))
|
||||||
|
if(linked == O)
|
||||||
|
continue
|
||||||
|
if(!O.scannable)
|
||||||
|
continue
|
||||||
|
var/bearing = round(90 - ATAN2(O.x - linked.x, O.y - linked.y),5)
|
||||||
|
if(bearing < 0)
|
||||||
|
bearing += 360
|
||||||
|
contacts.Add(list(list("name"=O.name, "ref"="\ref[O]", "bearing"=bearing)))
|
||||||
|
data["contacts"] = contacts
|
||||||
|
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
// Beware ye eyes. This holds all of the ACTIONS from helm, engine, and sensor control all at once.
|
||||||
|
/datum/tgui_module/ship/fullmonty/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
/* HELM */
|
||||||
|
if("add")
|
||||||
|
var/datum/computer_file/data/waypoint/R = new()
|
||||||
|
var/sec_name = input("Input navigation entry name", "New navigation entry", "Sector #[known_sectors.len]") as text
|
||||||
|
if(!sec_name)
|
||||||
|
sec_name = "Sector #[known_sectors.len]"
|
||||||
|
R.fields["name"] = sec_name
|
||||||
|
if(sec_name in known_sectors)
|
||||||
|
to_chat(usr, "<span class='warning'>Sector with that name already exists, please input a different name.</span>")
|
||||||
|
return TRUE
|
||||||
|
switch(params["add"])
|
||||||
|
if("current")
|
||||||
|
R.fields["x"] = linked.x
|
||||||
|
R.fields["y"] = linked.y
|
||||||
|
if("new")
|
||||||
|
var/newx = input("Input new entry x coordinate", "Coordinate input", linked.x) as num
|
||||||
|
var/newy = input("Input new entry y coordinate", "Coordinate input", linked.y) as num
|
||||||
|
R.fields["x"] = CLAMP(newx, 1, world.maxx)
|
||||||
|
R.fields["y"] = CLAMP(newy, 1, world.maxy)
|
||||||
|
known_sectors[sec_name] = R
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("remove")
|
||||||
|
var/datum/computer_file/data/waypoint/R = locate(params["remove"])
|
||||||
|
if(R)
|
||||||
|
known_sectors.Remove(R.fields["name"])
|
||||||
|
qdel(R)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("setcoord")
|
||||||
|
if(params["setx"])
|
||||||
|
var/newx = input("Input new destiniation x coordinate", "Coordinate input", dx) as num|null
|
||||||
|
if(newx)
|
||||||
|
dx = CLAMP(newx, 1, world.maxx)
|
||||||
|
|
||||||
|
if(params["sety"])
|
||||||
|
var/newy = input("Input new destiniation y coordinate", "Coordinate input", dy) as num|null
|
||||||
|
if(newy)
|
||||||
|
dy = CLAMP(newy, 1, world.maxy)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("setds")
|
||||||
|
dx = text2num(params["x"])
|
||||||
|
dy = text2num(params["y"])
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("reset")
|
||||||
|
dx = 0
|
||||||
|
dy = 0
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("speedlimit")
|
||||||
|
var/newlimit = input("Input new speed limit for autopilot (0 to brake)", "Autopilot speed limit", speedlimit*1000) as num|null
|
||||||
|
if(newlimit)
|
||||||
|
speedlimit = CLAMP(newlimit/1000, 0, 100)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("accellimit")
|
||||||
|
var/newlimit = input("Input new acceleration limit", "Acceleration limit", accellimit*1000) as num|null
|
||||||
|
if(newlimit)
|
||||||
|
accellimit = max(newlimit/1000, 0)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("move")
|
||||||
|
var/ndir = text2num(params["dir"])
|
||||||
|
ndir = turn(ndir,pick(90,-90))
|
||||||
|
linked.relaymove(usr, ndir, accellimit)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("brake")
|
||||||
|
linked.decelerate()
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("apilot")
|
||||||
|
if(autopilot_disabled)
|
||||||
|
autopilot = FALSE
|
||||||
|
else
|
||||||
|
autopilot = !autopilot
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("apilot_lock")
|
||||||
|
autopilot_disabled = !autopilot_disabled
|
||||||
|
autopilot = FALSE
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("manual")
|
||||||
|
viewing_overmap(usr) ? unlook(usr) : look(usr)
|
||||||
|
. = TRUE
|
||||||
|
/* END HELM */
|
||||||
|
/* ENGINES */
|
||||||
|
if("global_toggle")
|
||||||
|
linked.engines_state = !linked.engines_state
|
||||||
|
for(var/datum/ship_engine/E in linked.engines)
|
||||||
|
if(linked.engines_state == !E.is_on())
|
||||||
|
E.toggle()
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("set_global_limit")
|
||||||
|
var/newlim = input("Input new thrust limit (0..100%)", "Thrust limit", linked.thrust_limit*100) as num
|
||||||
|
linked.thrust_limit = clamp(newlim/100, 0, 1)
|
||||||
|
for(var/datum/ship_engine/E in linked.engines)
|
||||||
|
E.set_thrust_limit(linked.thrust_limit)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("global_limit")
|
||||||
|
linked.thrust_limit = clamp(linked.thrust_limit + text2num(params["global_limit"]), 0, 1)
|
||||||
|
for(var/datum/ship_engine/E in linked.engines)
|
||||||
|
E.set_thrust_limit(linked.thrust_limit)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("set_limit")
|
||||||
|
var/datum/ship_engine/E = locate(params["engine"])
|
||||||
|
var/newlim = input("Input new thrust limit (0..100)", "Thrust limit", E.get_thrust_limit()) as num
|
||||||
|
var/limit = clamp(newlim/100, 0, 1)
|
||||||
|
if(istype(E))
|
||||||
|
E.set_thrust_limit(limit)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("limit")
|
||||||
|
var/datum/ship_engine/E = locate(params["engine"])
|
||||||
|
var/limit = clamp(E.get_thrust_limit() + text2num(params["limit"]), 0, 1)
|
||||||
|
if(istype(E))
|
||||||
|
E.set_thrust_limit(limit)
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
if("toggle_engine")
|
||||||
|
var/datum/ship_engine/E = locate(params["engine"])
|
||||||
|
if(istype(E))
|
||||||
|
E.toggle()
|
||||||
|
. = TRUE
|
||||||
|
/* END ENGINES */
|
||||||
|
/* SENSORS */
|
||||||
|
if("range")
|
||||||
|
var/nrange = input("Set new sensors range", "Sensor range", sensors.range) as num|null
|
||||||
|
if(nrange)
|
||||||
|
sensors.set_range(CLAMP(nrange, 1, world.view))
|
||||||
|
. = TRUE
|
||||||
|
if("toggle_sensor")
|
||||||
|
sensors.toggle()
|
||||||
|
. = TRUE
|
||||||
|
if("viewing")
|
||||||
|
if(usr && !isAI(usr))
|
||||||
|
viewing_overmap(usr) ? unlook(usr) : look(usr)
|
||||||
|
. = TRUE
|
||||||
|
/* END SENSORS */
|
||||||
|
|
||||||
|
// We don't want these to do anything.
|
||||||
|
/datum/tgui_module/ship/fullmonty/sync_linked()
|
||||||
|
return
|
||||||
|
/datum/tgui_module/ship/fullmonty/attempt_hook_up_recursive()
|
||||||
|
return
|
||||||
|
/datum/tgui_module/ship/fullmonty/attempt_hook_up()
|
||||||
|
return
|
||||||
85
code/modules/tgui/modules/power_monitor.dm
Normal file
85
code/modules/tgui/modules/power_monitor.dm
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/datum/tgui_module/power_monitor
|
||||||
|
name = "Power monitor"
|
||||||
|
tgui_id = "PowerMonitor"
|
||||||
|
var/list/grid_sensors
|
||||||
|
var/active_sensor = null //name_tag of the currently selected sensor
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/New()
|
||||||
|
. = ..()
|
||||||
|
refresh_sensors()
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/ui_data(mob/user)
|
||||||
|
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.
|
||||||
|
var/obj/machinery/power/sensor/focus = null
|
||||||
|
|
||||||
|
var/z = get_z(user)
|
||||||
|
var/list/map_levels = using_map.get_map_levels(z)
|
||||||
|
|
||||||
|
// Build list of data from sensor readings.
|
||||||
|
for(var/obj/machinery/power/sensor/S in grid_sensors)
|
||||||
|
if(!(S.z in map_levels))
|
||||||
|
continue
|
||||||
|
sensors.Add(list(list(
|
||||||
|
"name" = S.name_tag,
|
||||||
|
"alarm" = S.check_grid_warning()
|
||||||
|
)))
|
||||||
|
if(S.name_tag == active_sensor)
|
||||||
|
focus = S
|
||||||
|
|
||||||
|
data["all_sensors"] = sensors
|
||||||
|
if(focus)
|
||||||
|
data["focus"] = focus.tgui_data(user)
|
||||||
|
else
|
||||||
|
data["focus"] = null
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("clear")
|
||||||
|
active_sensor = null
|
||||||
|
. = TRUE
|
||||||
|
if("refresh")
|
||||||
|
refresh_sensors()
|
||||||
|
. = TRUE
|
||||||
|
if("setsensor")
|
||||||
|
active_sensor = params["id"]
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/proc/has_alarm()
|
||||||
|
for(var/obj/machinery/power/sensor/S in grid_sensors)
|
||||||
|
if(S.check_grid_warning())
|
||||||
|
return TRUE
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/proc/refresh_sensors()
|
||||||
|
grid_sensors = list()
|
||||||
|
|
||||||
|
// Handle ultranested programs
|
||||||
|
var/turf/T = get_turf(tgui_host())
|
||||||
|
|
||||||
|
var/list/levels = list()
|
||||||
|
if(!T) // Safety check
|
||||||
|
return
|
||||||
|
if(T)
|
||||||
|
levels += using_map.get_map_levels(T.z, FALSE)
|
||||||
|
for(var/obj/machinery/power/sensor/S in machines)
|
||||||
|
if(T && (S.loc.z == T.z) || (S.loc.z in levels) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
|
||||||
|
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
|
||||||
|
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
|
||||||
|
else
|
||||||
|
grid_sensors += S
|
||||||
|
|
||||||
|
/datum/tgui_module/power_monitor/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
// Subtype for self_state
|
||||||
|
/datum/tgui_module/power_monitor/robot
|
||||||
|
/datum/tgui_module/power_monitor/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
118
code/modules/tgui/modules/rcon.dm
Normal file
118
code/modules/tgui/modules/rcon.dm
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/datum/tgui_module/rcon
|
||||||
|
name = "Power RCON"
|
||||||
|
tgui_id = "RCON"
|
||||||
|
|
||||||
|
var/list/known_SMESs = null
|
||||||
|
var/list/known_breakers = null
|
||||||
|
|
||||||
|
/datum/tgui_module/rcon/ui_data(mob/user)
|
||||||
|
FindDevices() // Update our devices list
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
// SMES DATA (simplified view)
|
||||||
|
var/list/smeslist[0]
|
||||||
|
for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs)
|
||||||
|
smeslist.Add(list(list(
|
||||||
|
"capacity" = SMES.capacity,
|
||||||
|
"capacityPercent" = round(100*SMES.charge/SMES.capacity, 0.1),
|
||||||
|
"charge" = SMES.charge,
|
||||||
|
"input_set" = SMES.input_attempt,
|
||||||
|
"input_val" = round(SMES.input_level/1000, 0.1),
|
||||||
|
"output_set" = SMES.output_attempt,
|
||||||
|
"output_val" = round(SMES.output_level/1000, 0.1),
|
||||||
|
"output_load" = round(SMES.output_used/1000, 0.1),
|
||||||
|
"RCON_tag" = SMES.RCon_tag
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["smes_info"] = sortByKey(smeslist, "RCON_tag")
|
||||||
|
|
||||||
|
// BREAKER DATA (simplified view)
|
||||||
|
var/list/breakerlist[0]
|
||||||
|
for(var/obj/machinery/power/breakerbox/BR in known_breakers)
|
||||||
|
breakerlist.Add(list(list(
|
||||||
|
"RCON_tag" = BR.RCon_tag,
|
||||||
|
"enabled" = BR.on
|
||||||
|
)))
|
||||||
|
data["breaker_info"] = breakerlist
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/rcon/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("smes_in_toggle")
|
||||||
|
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
|
||||||
|
if(SMES)
|
||||||
|
SMES.toggle_input()
|
||||||
|
. = TRUE
|
||||||
|
if("smes_out_toggle")
|
||||||
|
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
|
||||||
|
if(SMES)
|
||||||
|
SMES.toggle_output()
|
||||||
|
. = TRUE
|
||||||
|
if("smes_in_set")
|
||||||
|
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
|
||||||
|
if(SMES)
|
||||||
|
var/inputset = (input(usr, "Enter new input level (0-[SMES.input_level_max/1000] kW)", "SMES Input Power Control", SMES.input_level/1000) as num) * 1000
|
||||||
|
SMES.set_input(inputset)
|
||||||
|
. = TRUE
|
||||||
|
if("smes_out_set")
|
||||||
|
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(params["smes"])
|
||||||
|
if(SMES)
|
||||||
|
var/outputset = (input(usr, "Enter new output level (0-[SMES.output_level_max/1000] kW)", "SMES Output Power Control", SMES.output_level/1000) as num) * 1000
|
||||||
|
SMES.set_output(outputset)
|
||||||
|
. = TRUE
|
||||||
|
if("toggle_breaker")
|
||||||
|
var/obj/machinery/power/breakerbox/toggle = null
|
||||||
|
for(var/obj/machinery/power/breakerbox/breaker in known_breakers)
|
||||||
|
if(breaker.RCon_tag == params["breaker"])
|
||||||
|
toggle = breaker
|
||||||
|
if(toggle)
|
||||||
|
if(toggle.update_locked)
|
||||||
|
to_chat(usr, "The breaker box was recently toggled. Please wait before toggling it again.")
|
||||||
|
else
|
||||||
|
toggle.auto_toggle()
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
|
||||||
|
// Proc: GetSMESByTag()
|
||||||
|
// Parameters: 1 (tag - RCON tag of SMES we want to look up)
|
||||||
|
// Description: Looks up and returns SMES which has matching RCON tag
|
||||||
|
/datum/tgui_module/rcon/proc/GetSMESByTag(var/tag)
|
||||||
|
if(!tag)
|
||||||
|
return
|
||||||
|
|
||||||
|
for(var/obj/machinery/power/smes/buildable/S in known_SMESs)
|
||||||
|
if(S.RCon_tag == tag)
|
||||||
|
return S
|
||||||
|
|
||||||
|
// Proc: FindDevices()
|
||||||
|
// Parameters: None
|
||||||
|
// Description: Refreshes local list of known devices.
|
||||||
|
/datum/tgui_module/rcon/proc/FindDevices()
|
||||||
|
known_SMESs = new /list()
|
||||||
|
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
var/list/map_levels = using_map.get_map_levels(z)
|
||||||
|
|
||||||
|
for(var/obj/machinery/power/smes/buildable/SMES in GLOB.smeses)
|
||||||
|
if(!(SMES.z in map_levels))
|
||||||
|
continue
|
||||||
|
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
|
||||||
|
known_SMESs.Add(SMES)
|
||||||
|
|
||||||
|
known_breakers = new /list()
|
||||||
|
for(var/obj/machinery/power/breakerbox/breaker in machines)
|
||||||
|
if(!(breaker.z in map_levels))
|
||||||
|
continue
|
||||||
|
if(breaker.RCon_tag != "NO_TAG")
|
||||||
|
known_breakers.Add(breaker)
|
||||||
|
|
||||||
|
/datum/tgui_module/rcon/ntos
|
||||||
|
ntos = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/rcon/robot
|
||||||
|
/datum/tgui_module/rcon/robot/tgui_state(mob/user)
|
||||||
|
return GLOB.tgui_self_state
|
||||||
73
code/modules/tgui/modules/rustcore_monitor.dm
Normal file
73
code/modules/tgui/modules/rustcore_monitor.dm
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/datum/tgui_module/rustcore_monitor
|
||||||
|
name = "R-UST Core Monitoring"
|
||||||
|
tgui_id = "RustCoreMonitor"
|
||||||
|
|
||||||
|
var/core_tag = ""
|
||||||
|
|
||||||
|
/datum/tgui_module/rustcore_monitor/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/obj/machinery/power/fusion_core/C = null
|
||||||
|
if(params["core"])
|
||||||
|
C = locate(params["core"]) in GLOB.fusion_cores
|
||||||
|
if(!istype(C))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("toggle_active")
|
||||||
|
if(!C.Startup()) //Startup() whilst the device is active will return null.
|
||||||
|
C.Shutdown()
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("toggle_reactantdump")
|
||||||
|
C.reactant_dump = !C.reactant_dump
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("set_tag")
|
||||||
|
var/new_ident = sanitize_text(input("Enter a new ident tag.", "Core Control", core_tag) as null|text)
|
||||||
|
if(new_ident)
|
||||||
|
core_tag = new_ident
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("set_fieldstr")
|
||||||
|
var/new_strength = params["fieldstr"]
|
||||||
|
C.target_field_strength = new_strength
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/rustcore_monitor/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
var/list/cores = list()
|
||||||
|
|
||||||
|
for(var/obj/machinery/power/fusion_core/C in GLOB.fusion_cores)
|
||||||
|
if(C.id_tag == core_tag)
|
||||||
|
|
||||||
|
var/list/reactants = list()
|
||||||
|
|
||||||
|
if(C.owned_field)
|
||||||
|
for(var/reagent in C.owned_field.dormant_reactant_quantities)
|
||||||
|
reactants.Add(list(list(
|
||||||
|
"name" = reagent,
|
||||||
|
"amount" = C.owned_field.dormant_reactant_quantities[reagent]
|
||||||
|
)))
|
||||||
|
|
||||||
|
cores.Add(list(list(
|
||||||
|
"name" = C.name,
|
||||||
|
"has_field" = C.owned_field ? TRUE : FALSE,
|
||||||
|
"reactant_dump" = C.reactant_dump,
|
||||||
|
"core_operational" = C.check_core_status(),
|
||||||
|
"field_instability" = (C.owned_field ? "[C.owned_field.percent_unstable * 100]%" : "ERROR"),
|
||||||
|
"field_temperature" = (C.owned_field ? "[C.owned_field.plasma_temperature + 295]K" : "ERROR"),
|
||||||
|
"field_strength" = C.field_strength,
|
||||||
|
"target_field_strength" = C.target_field_strength,
|
||||||
|
"x" = C.x,
|
||||||
|
"y" = C.y,
|
||||||
|
"z" = C.z,
|
||||||
|
"ref" = "\ref[C]"
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["cores"] = cores
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/rustcore_monitor/ntos
|
||||||
|
ntos = TRUE
|
||||||
51
code/modules/tgui/modules/rustfuel_control.dm
Normal file
51
code/modules/tgui/modules/rustfuel_control.dm
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/datum/tgui_module/rustfuel_control
|
||||||
|
name = "Fuel Injector Control"
|
||||||
|
tgui_id = "RustFuelControl"
|
||||||
|
|
||||||
|
var/fuel_tag = ""
|
||||||
|
|
||||||
|
/datum/tgui_module/rustfuel_control/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("toggle_active")
|
||||||
|
var/obj/machinery/fusion_fuel_injector/FI = locate(params["fuel"]) in GLOB.fuel_injectors
|
||||||
|
if(!istype(FI))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(FI.injecting)
|
||||||
|
FI.StopInjecting()
|
||||||
|
else
|
||||||
|
FI.BeginInjecting()
|
||||||
|
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("set_tag")
|
||||||
|
var/new_ident = sanitize_text(input("Enter a new ident tag.", "Gyrotron Control", fuel_tag) as null|text)
|
||||||
|
if(new_ident)
|
||||||
|
fuel_tag = new_ident
|
||||||
|
|
||||||
|
/datum/tgui_module/rustfuel_control/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
var/list/fuels = list()
|
||||||
|
|
||||||
|
for(var/obj/machinery/fusion_fuel_injector/FI in GLOB.fuel_injectors)
|
||||||
|
if(FI.id_tag == fuel_tag)
|
||||||
|
fuels.Add(list(list(
|
||||||
|
"name" = FI.name,
|
||||||
|
"active" = FI.injecting,
|
||||||
|
"fuel_type" = (FI.cur_assembly ? FI.cur_assembly.fuel_type : "NONE"),
|
||||||
|
"fuel_amt" = (FI.cur_assembly ? "[FI.cur_assembly.percent_depleted * 100]%" : "NONE"),
|
||||||
|
"deployed" = FI.anchored,
|
||||||
|
"x" = FI.x,
|
||||||
|
"y" = FI.y,
|
||||||
|
"z" = FI.z,
|
||||||
|
"ref" = "\ref[FI]"
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["fuels"] = fuels
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/rustfuel_control/ntos
|
||||||
|
ntos = TRUE
|
||||||
46
code/modules/tgui/modules/shutoff_monitor.dm
Normal file
46
code/modules/tgui/modules/shutoff_monitor.dm
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/datum/tgui_module/shutoff_monitor
|
||||||
|
name = "Shutoff Valve Monitoring"
|
||||||
|
tgui_id = "ShutoffMonitor"
|
||||||
|
|
||||||
|
/datum/tgui_module/shutoff_monitor/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("toggle_enable")
|
||||||
|
var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"])
|
||||||
|
if(!istype(S))
|
||||||
|
return FALSE
|
||||||
|
S.close_on_leaks = !S.close_on_leaks
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("toggle_open")
|
||||||
|
var/obj/machinery/atmospherics/valve/shutoff/S = locate(params["valve"])
|
||||||
|
if(!istype(S))
|
||||||
|
return FALSE
|
||||||
|
if(S.open)
|
||||||
|
S.close()
|
||||||
|
else
|
||||||
|
S.open()
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/shutoff_monitor/ui_data(mob/user)
|
||||||
|
var/list/data = list()
|
||||||
|
var/list/valves = list()
|
||||||
|
|
||||||
|
for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves)
|
||||||
|
valves.Add(list(list(
|
||||||
|
"name" = S.name,
|
||||||
|
"enabled" = S.close_on_leaks,
|
||||||
|
"open" = S.open,
|
||||||
|
"x" = S.x,
|
||||||
|
"y" = S.y,
|
||||||
|
"z" = S.z,
|
||||||
|
"ref" = "\ref[S]"
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["valves"] = valves
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/shutoff_monitor/ntos
|
||||||
|
ntos = TRUE
|
||||||
108
code/modules/tgui/modules/supermatter_monitor.dm
Normal file
108
code/modules/tgui/modules/supermatter_monitor.dm
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor
|
||||||
|
name = "Supermatter monitor"
|
||||||
|
tgui_id = "SupermatterMonitor"
|
||||||
|
var/list/supermatters
|
||||||
|
var/obj/machinery/power/supermatter/active = null // Currently selected supermatter crystal.
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/Destroy()
|
||||||
|
. = ..()
|
||||||
|
active = null
|
||||||
|
supermatters = null
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/New()
|
||||||
|
..()
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
// Refreshes list of active supermatter crystals
|
||||||
|
/datum/tgui_module/supermatter_monitor/proc/refresh()
|
||||||
|
supermatters = list()
|
||||||
|
var/z = get_z(tgui_host())
|
||||||
|
if(!z)
|
||||||
|
return
|
||||||
|
var/valid_z_levels = using_map.get_map_levels(z)
|
||||||
|
for(var/obj/machinery/power/supermatter/S in machines)
|
||||||
|
// Delaminating, not within coverage, not on a tile.
|
||||||
|
if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/))
|
||||||
|
continue
|
||||||
|
supermatters.Add(S)
|
||||||
|
|
||||||
|
if(!(active in supermatters))
|
||||||
|
active = null
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/proc/get_status()
|
||||||
|
. = SUPERMATTER_INACTIVE
|
||||||
|
for(var/obj/machinery/power/supermatter/S in supermatters)
|
||||||
|
. = max(., S.get_status())
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/ui_data(mob/user)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
if(istype(active))
|
||||||
|
var/turf/T = get_turf(active)
|
||||||
|
if(!T)
|
||||||
|
active = null
|
||||||
|
return
|
||||||
|
var/datum/gas_mixture/air = T.return_air()
|
||||||
|
if(!istype(air))
|
||||||
|
active = null
|
||||||
|
return
|
||||||
|
|
||||||
|
data["active"] = 1
|
||||||
|
data["SM_area"] = get_area(active)
|
||||||
|
data["SM_integrity"] = active.get_integrity()
|
||||||
|
data["SM_power"] = active.power
|
||||||
|
data["SM_ambienttemp"] = air.temperature
|
||||||
|
data["SM_ambientpressure"] = air.return_pressure()
|
||||||
|
data["SM_EPR"] = active.get_epr()
|
||||||
|
//data["SM_EPR"] = active.get_epr()
|
||||||
|
if(air.total_moles)
|
||||||
|
data["SM_gas_O2"] = round(100*air.gas["oxygen"]/air.total_moles,0.01)
|
||||||
|
data["SM_gas_CO2"] = round(100*air.gas["carbon_dioxide"]/air.total_moles,0.01)
|
||||||
|
data["SM_gas_N2"] = round(100*air.gas["nitrogen"]/air.total_moles,0.01)
|
||||||
|
data["SM_gas_PH"] = round(100*air.gas["phoron"]/air.total_moles,0.01)
|
||||||
|
data["SM_gas_N2O"] = round(100*air.gas["sleeping_agent"]/air.total_moles,0.01)
|
||||||
|
else
|
||||||
|
data["SM_gas_O2"] = 0
|
||||||
|
data["SM_gas_CO2"] = 0
|
||||||
|
data["SM_gas_N2"] = 0
|
||||||
|
data["SM_gas_PH"] = 0
|
||||||
|
data["SM_gas_N2O"] = 0
|
||||||
|
else
|
||||||
|
var/list/SMS = list()
|
||||||
|
for(var/obj/machinery/power/supermatter/S in supermatters)
|
||||||
|
var/area/A = get_area(S)
|
||||||
|
if(!A)
|
||||||
|
continue
|
||||||
|
|
||||||
|
SMS.Add(list(list(
|
||||||
|
"area_name" = A.name,
|
||||||
|
"integrity" = S.get_integrity(),
|
||||||
|
"uid" = S.uid
|
||||||
|
)))
|
||||||
|
|
||||||
|
data["active"] = 0
|
||||||
|
data["supermatters"] = SMS
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/ui_act(action, params)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("clear")
|
||||||
|
active = null
|
||||||
|
. = TRUE
|
||||||
|
if("refresh")
|
||||||
|
refresh()
|
||||||
|
. = TRUE
|
||||||
|
if("set")
|
||||||
|
var/newuid = text2num(params["set"])
|
||||||
|
for(var/obj/machinery/power/supermatter/S in supermatters)
|
||||||
|
if(S.uid == newuid)
|
||||||
|
active = S
|
||||||
|
. = TRUE
|
||||||
|
|
||||||
|
/datum/tgui_module/supermatter_monitor/ntos
|
||||||
|
ntos = TRUE
|
||||||
85
code/modules/tgui/modules/teleporter.dm
Normal file
85
code/modules/tgui/modules/teleporter.dm
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/datum/tgui_module/teleport_control
|
||||||
|
name = "Teleporter Control"
|
||||||
|
tgui_id = "Teleporter"
|
||||||
|
var/locked_name = "Not Locked"
|
||||||
|
var/obj/item/locked = null
|
||||||
|
var/obj/machinery/teleport/station/station = null
|
||||||
|
var/obj/machinery/teleport/hub/hub = null
|
||||||
|
|
||||||
|
/datum/tgui_module/teleport_control/ui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
var/list/data = ..()
|
||||||
|
|
||||||
|
data["locked_name"] = locked_name || "No Target"
|
||||||
|
data["station_connected"] = !!station
|
||||||
|
data["hub_connected"] = !!hub
|
||||||
|
data["calibrated"] = hub?.accurate
|
||||||
|
data["teleporter_on"] = station?.engaged
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
/datum/tgui_module/teleport_control/ui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
|
||||||
|
if(..())
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
switch(action)
|
||||||
|
if("select_target")
|
||||||
|
var/list/L = list()
|
||||||
|
var/list/areaindex = list()
|
||||||
|
|
||||||
|
for(var/obj/item/device/radio/beacon/R in all_beacons)
|
||||||
|
var/turf/T = get_turf(R)
|
||||||
|
if(!T)
|
||||||
|
continue
|
||||||
|
if(!(T.z in using_map.player_levels))
|
||||||
|
continue
|
||||||
|
var/tmpname = T.loc.name
|
||||||
|
if(areaindex[tmpname])
|
||||||
|
tmpname = "[tmpname] ([++areaindex[tmpname]])"
|
||||||
|
else
|
||||||
|
areaindex[tmpname] = 1
|
||||||
|
L[tmpname] = R
|
||||||
|
|
||||||
|
for(var/obj/item/weapon/implant/tracking/I in all_tracking_implants)
|
||||||
|
if(!I.implanted || !ismob(I.loc))
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
var/mob/M = I.loc
|
||||||
|
if(M.stat == 2)
|
||||||
|
if(M.timeofdeath + 6000 < world.time)
|
||||||
|
continue
|
||||||
|
var/turf/T = get_turf(M)
|
||||||
|
if(T)
|
||||||
|
continue
|
||||||
|
if(!(T in using_map.station_levels))
|
||||||
|
continue
|
||||||
|
var/tmpname = M.real_name
|
||||||
|
if(areaindex[tmpname])
|
||||||
|
tmpname = "[tmpname] ([++areaindex[tmpname]])"
|
||||||
|
else
|
||||||
|
areaindex[tmpname] = 1
|
||||||
|
L[tmpname] = I
|
||||||
|
|
||||||
|
var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null
|
||||||
|
if(!desc)
|
||||||
|
return FALSE
|
||||||
|
if(tgui_status(usr, state) != UI_INTERACTIVE)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
locked = L[desc]
|
||||||
|
locked_name = desc
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("test_fire")
|
||||||
|
station?.testfire()
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
if("toggle_on")
|
||||||
|
if(!station)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(station.engaged)
|
||||||
|
station.disengage()
|
||||||
|
else
|
||||||
|
station.engage()
|
||||||
|
|
||||||
|
return TRUE
|
||||||
@@ -25,7 +25,7 @@ GLOBAL_DATUM_INIT(ui_glasses_state, /datum/ui_state/glasses_state, new)
|
|||||||
if(H.glasses == src_object)
|
if(H.glasses == src_object)
|
||||||
return user.shared_ui_interaction()
|
return user.shared_ui_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
GLOBAL_DATUM_INIT(ui_nif_state, /datum/ui_state/nif_state, new)
|
GLOBAL_DATUM_INIT(ui_nif_state, /datum/ui_state/nif_state, new)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ GLOBAL_DATUM_INIT(ui_nif_state, /datum/ui_state/nif_state, new)
|
|||||||
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
|
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
|
||||||
return user.shared_ui_interaction()
|
return user.shared_ui_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|
||||||
GLOBAL_DATUM_INIT(ui_commlink_state, /datum/ui_state/commlink_state, new)
|
GLOBAL_DATUM_INIT(ui_commlink_state, /datum/ui_state/commlink_state, new)
|
||||||
|
|
||||||
@@ -45,4 +45,4 @@ GLOBAL_DATUM_INIT(ui_commlink_state, /datum/ui_state/commlink_state, new)
|
|||||||
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
|
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
|
||||||
return user.shared_ui_interaction()
|
return user.shared_ui_interaction()
|
||||||
|
|
||||||
return STATUS_CLOSE
|
return UI_CLOSE
|
||||||
|
|||||||
41
code/modules/tgui/states/inventory_vr.dm
Normal file
41
code/modules/tgui/states/inventory_vr.dm
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
GLOBAL_DATUM_INIT(tgui_glasses_state, /datum/tgui_state/glasses_state, new)
|
||||||
|
/datum/tgui_state/glasses_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
|
if(ishuman(user))
|
||||||
|
var/mob/living/carbon/human/H = user
|
||||||
|
if(H.glasses == src_object)
|
||||||
|
return user.shared_tgui_interaction()
|
||||||
|
|
||||||
|
return UI_CLOSE
|
||||||
|
|
||||||
|
GLOBAL_DATUM_INIT(tgui_nif_state, /datum/tgui_state/nif_state, new)
|
||||||
|
/datum/tgui_state/nif_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
|
if(ishuman(user))
|
||||||
|
var/mob/living/carbon/human/H = user
|
||||||
|
if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif)
|
||||||
|
return user.shared_tgui_interaction()
|
||||||
|
|
||||||
|
return UI_CLOSE
|
||||||
|
|
||||||
|
// This is slightly distinct from the module state, as it wants to update if not working
|
||||||
|
GLOBAL_DATUM_INIT(tgui_nif_main_state, /datum/tgui_state/nif_main_state, new)
|
||||||
|
/datum/tgui_state/nif_main_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
|
if(ishuman(user))
|
||||||
|
var/mob/living/carbon/human/H = user
|
||||||
|
if(!H.nif || src_object != H.nif)
|
||||||
|
return UI_CLOSE
|
||||||
|
|
||||||
|
if(H.nif.stat == NIF_WORKING)
|
||||||
|
return user.shared_tgui_interaction()
|
||||||
|
else
|
||||||
|
return min(user.shared_tgui_interaction(), UI_UPDATE)
|
||||||
|
|
||||||
|
return UI_CLOSE
|
||||||
|
|
||||||
|
GLOBAL_DATUM_INIT(tgui_commlink_state, /datum/tgui_state/commlink_state, new)
|
||||||
|
/datum/tgui_state/commlink_state/can_use_topic(var/src_object, var/mob/user)
|
||||||
|
if(ishuman(user))
|
||||||
|
var/mob/living/carbon/human/H = user
|
||||||
|
if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object)
|
||||||
|
return user.shared_tgui_interaction()
|
||||||
|
|
||||||
|
return UI_CLOSE
|
||||||
18
code/modules/tgui/states/vorepanel_vr.dm
Normal file
18
code/modules/tgui/states/vorepanel_vr.dm
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* tgui state: vorepanel_state
|
||||||
|
*
|
||||||
|
* Only checks that the user and src_object are the same.
|
||||||
|
**/
|
||||||
|
|
||||||
|
GLOBAL_DATUM_INIT(tgui_vorepanel_state, /datum/tgui_state/vorepanel_state, new)
|
||||||
|
|
||||||
|
/datum/tgui_state/vorepanel_state/can_use_topic(src_object, mob/user)
|
||||||
|
if(src_object != user)
|
||||||
|
// Note, in order to allow others to look at others vore panels, change this to
|
||||||
|
// UI_UPDATE
|
||||||
|
return UI_CLOSE
|
||||||
|
if(!user.client)
|
||||||
|
return UI_CLOSE
|
||||||
|
if(user.stat == DEAD)
|
||||||
|
return UI_DISABLED
|
||||||
|
return UI_INTERACTIVE
|
||||||
Reference in New Issue
Block a user