Merge pull request #8741 from ShadowLarkens/tgui_exploration

TGUI exploration
This commit is contained in:
Novacat
2020-08-20 18:52:52 -04:00
committed by GitHub
34 changed files with 1655 additions and 1324 deletions
+20 -27
View File
@@ -15,7 +15,6 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
anchored = TRUE
circuit = /obj/item/weapon/circuitboard/pointdefense_control
var/list/targets = list() // Targets being engaged by associated batteries
var/ui_template = "pointdefense_control.tmpl"
var/id_tag = null
/obj/machinery/pointdefense_control/Initialize(mapload)
@@ -37,48 +36,42 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
if(!id_tag)
. += "[desc_panel_image("multitool")]to set ident tag"
/obj/machinery/pointdefense_control/ui_interact(var/mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(ui_template)
var/list/data = build_ui_data()
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, ui_template, name, 400, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/pointdefense_control/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PointDefenseControl") // 400, 600
ui.open()
/obj/machinery/pointdefense_control/attack_hand(mob/user)
if((. = ..()))
return
if(CanUseTopic(user, global.default_state) > STATUS_CLOSE)
ui_interact(user)
if(..())
return TRUE
tgui_interact(user)
return TRUE
/obj/machinery/pointdefense_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
/obj/machinery/pointdefense_control/Topic(var/mob/user, var/href_list)
if((. = ..()))
return
if(href_list["toggle_active"])
var/obj/machinery/power/pointdefense/PD = locate(href_list["toggle_active"])
if(action == "toggle_active")
var/obj/machinery/power/pointdefense/PD = locate(params["target"])
if(!istype(PD))
return TOPIC_NOACTION
return FALSE
//if(!lan || !lan.is_connected(PD))
if(PD.id_tag != id_tag)
return TOPIC_NOACTION
return FALSE
if(!(get_z(PD) in GetConnectedZlevels(get_z(src))))
to_chat(user, "<span class='warning'>[PD] is not within control range.</span>")
return TOPIC_NOACTION
to_chat(usr, "<span class='warning'>[PD] is not within control range.</span>")
return FALSE
if(!PD.Activate()) //Activate() whilst the device is active will return false.
PD.Deactivate()
return TOPIC_REFRESH
return TRUE
/obj/machinery/pointdefense_control/proc/build_ui_data()
/obj/machinery/pointdefense_control/tgui_data(mob/user)
var/list/data = list()
data["id"] = id_tag
data["name"] = name
var/list/turrets = list()
if(id_tag)
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
@@ -189,6 +189,8 @@
/datum/computer_file/program/proc/check_eye(var/mob/user)
if(NM)
return NM.check_eye(user)
if(TM)
return TM.check_eye(user)
else
return -1
@@ -1,7 +1,7 @@
/datum/computer_file/program/ship_nav
filename = "navviewer"
filedesc = "Ship Navigational Screen"
nanomodule_path = /datum/nano_module/program/ship/nav
tguimodule_path = /datum/tgui_module/ship/nav/ntos
program_icon_state = "helm"
program_key_state = "generic_key"
program_menu_icon = "pin-s"
@@ -10,54 +10,3 @@
requires_ntnet = 1
network_destination = "ship position sensors"
size = 4
/datum/nano_module/program/ship/nav
name = "Navigation Display"
/datum/nano_module/program/ship/nav/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
if(!linked)
to_chat(user, "<span class='warning'>You don't appear to be on a spaceship...</span>")
if(program)
program.kill_program()
else if(ui)
ui.close()
return
var/list/data = list()
if(program)
data = program.get_header_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"
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "nav.tmpl", "[linked.name] Navigation Screen", 380, 530, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/datum/nano_module/program/ship/nav/OnTopic(var/mob/user, var/list/href_list)
if(..())
return TOPIC_HANDLED
if (!linked)
return TOPIC_NOACTION
if (href_list["viewing"])
viewing_overmap(user) ? unlook(user) : look(user)
return TOPIC_REFRESH
@@ -1,87 +0,0 @@
/datum/nano_module/program/ship
var/obj/effect/overmap/visitable/ship/linked
var/list/viewers
var/extra_view = 0
/datum/nano_module/program/ship/New()
..()
sync_linked()
if(linked)
name = "[linked.name] [name]"
/datum/nano_module/program/ship/Destroy()
if(LAZYLEN(viewers))
for(var/weakref/W in viewers)
var/M = W.resolve()
if(M)
unlook(M)
. = ..()
/datum/nano_module/program/ship/proc/sync_linked()
var/obj/effect/overmap/visitable/ship/sector = get_overmap_sector(get_z(nano_host()))
if(!sector)
return
return attempt_hook_up_recursive(sector)
/datum/nano_module/program/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/nano_module/program/ship/proc/attempt_hook_up(obj/effect/overmap/visitable/ship/sector)
if(!istype(sector))
return
if(sector.check_ownership(nano_host()))
linked = sector
return 1
/datum/nano_module/program/ship/proc/look(var/mob/user)
if(linked)
user.machine = nano_host()
user.reset_view(linked)
user.set_viewsize(world.view + extra_view)
GLOB.moved_event.register(user, src, /datum/nano_module/program/ship/proc/unlook)
LAZYDISTINCTADD(viewers, weakref(user))
/datum/nano_module/program/ship/proc/unlook(var/mob/user)
user.reset_view()
user.set_viewsize() // reset to default
GLOB.moved_event.unregister(user, src, /datum/nano_module/program/ship/proc/unlook)
LAZYREMOVE(viewers, weakref(user))
/datum/nano_module/program/ship/proc/viewing_overmap(mob/user)
return (weakref(user) in viewers)
/datum/nano_module/program/ship/proc/DefaultTopicState()
return global.default_state
/datum/nano_module/program/ship/Topic(var/href, var/href_list = list(), var/datum/topic_state/state)
if((. = ..()))
return
state = state || DefaultTopicState() || global.default_state
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
CouldUseTopic(usr)
return OnTopic(usr, href_list, state)
CouldNotUseTopic(usr)
return TRUE
/datum/nano_module/program/ship/proc/OnTopic(var/mob/user, var/href_list, var/datum/topic_state/state)
return TOPIC_NOACTION
/datum/nano_module/program/ship/proc/CouldNotUseTopic(mob/user)
. = ..()
unlook(user)
/datum/nano_module/program/ship/proc/CouldUseTopic(mob/user)
. = ..()
if(viewing_overmap(user))
look(user)
/datum/nano_module/program/ship/check_eye(var/mob/user)
if (!get_dist(user, nano_host()) > 1 || user.blinded || !linked )
unlook(user)
return -1
else
return 0
@@ -118,14 +118,30 @@ obj/machinery/computer/ship/disperser/proc/is_valid_setup()
if(B)
return B
/obj/machinery/computer/ship/disperser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = TRUE)
/obj/machinery/computer/ship/disperser/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
if(!linked)
display_reconnect_dialog(user, "disperser synchronization")
return
var/data[0]
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OvermapDisperser", "[linked.name] ORB control") // 400, 550
ui.open()
if (!link_parts())
/obj/machinery/computer/ship/disperser/tgui_data(mob/user)
var/list/data = list()
data["faillink"] = FALSE
data["calibration"] = null
data["overmapdir"] = null
data["cal_accuracy"] = 0
data["strength"] = 0
data["range"] = 0
data["next_shot"] = -1
data["nopower"] = TRUE
data["skill"] = FALSE
data["chargeload"] = null
if(!link_parts())
data["faillink"] = TRUE
else
data["calibration"] = calibration
@@ -137,56 +153,58 @@ obj/machinery/computer/ship/disperser/proc/is_valid_setup()
data["nopower"] = !data["faillink"] && (!front.powered() || !middle.powered() || !back.powered())
data["skill"] = user.get_skill_value(core_skill) > skill_offset
var/charge = "<b>UNKNOWN ERROR</b>"
var/charge = "UNKNOWN ERROR"
if(get_charge_type() == OVERMAP_WEAKNESS_NONE)
charge = "<b>ERROR</b>: No valid charge detected."
charge = "ERROR: No valid charge detected."
else
var/obj/structure/ship_munition/disperser_charge/B = get_charge()
charge = B.chargedesc
data["chargeload"] = charge
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "disperser.tmpl", "[linked.name] ORB control", 400, 550)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/computer/ship/disperser/OnTopic(mob/user, list/href_list, state)
. = ..()
if(.)
return
/obj/machinery/computer/ship/disperser/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(!linked)
return TOPIC_HANDLED
return FALSE
if (href_list["choose"])
overmapdir = sanitize_integer(text2num(href_list["choose"]), 0, 9, 0)
reset_calibration()
switch(action)
if("choose")
overmapdir = sanitize_integer(text2num(params["dir"]), 0, 9, 0)
reset_calibration()
. = TRUE
if(href_list["calibration"])
var/input = input("0-9", "disperser calibration", 0) as num|null
if(!isnull(input)) //can be zero so we explicitly check for null
var/calnum = sanitize_integer(text2num(href_list["calibration"]), 0, caldigit)//sanitiiiiize
calibration[calnum + 1] = sanitize_integer(input, 0, 9, 0)//must add 1 because nanoui indexes from 0
if("calibration")
var/input = input("0-9", "disperser calibration", 0) as num|null
if(!isnull(input)) //can be zero so we explicitly check for null
var/calnum = sanitize_integer(text2num(params["calibration"]), 0, caldigit)//sanitiiiiize
calibration[calnum + 1] = sanitize_integer(input, 0, 9, 0)//must add 1 because js indexes from 0
. = TRUE
if(href_list["skill_calibration"])
for(var/i = 1 to min(caldigit, user.get_skill_value(core_skill) - skill_offset))
calibration[i] = calexpected[i]
if("skill_calibration")
for(var/i = 1 to min(caldigit, usr.get_skill_value(core_skill) - skill_offset))
calibration[i] = calexpected[i]
. = TRUE
if(href_list["strength"])
var/input = input("1-5", "disperser strength", 1) as num|null
if(input && CanInteract(user, state))
strength = sanitize_integer(input, 1, 5, 1)
middle.update_idle_power_usage(strength * range * 100)
if("strength")
var/input = input("1-5", "disperser strength", 1) as num|null
if(input && tgui_status(usr, state) == STATUS_INTERACTIVE)
strength = sanitize_integer(input, 1, 5, 1)
middle.update_idle_power_usage(strength * range * 100)
. = TRUE
if(href_list["range"])
var/input = input("1-5", "disperser radius", 1) as num|null
if(input && CanInteract(user, state))
range = sanitize_integer(input, 1, 5, 1)
middle.update_idle_power_usage(strength * range * 100)
if("range")
var/input = input("1-5", "disperser radius", 1) as num|null
if(input && tgui_status(usr, state) == STATUS_INTERACTIVE)
range = sanitize_integer(input, 1, 5, 1)
middle.update_idle_power_usage(strength * range * 100)
. = TRUE
if(href_list["fire"])
fire(user)
if("fire")
fire(usr)
. = TRUE
return TOPIC_REFRESH
if(. && !issilicon(usr))
playsound(src, "terminal_type", 50, 1)
@@ -54,22 +54,8 @@
//
// Topic
//
/obj/machinery/computer/ship/proc/DefaultTopicState()
return global.default_state
/obj/machinery/computer/ship/Topic(var/href, var/href_list = list(), var/datum/topic_state/state)
if((. = ..()))
return
state = state || DefaultTopicState() || global.default_state
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
CouldUseTopic(usr)
return OnTopic(usr, href_list, state)
CouldNotUseTopic(usr)
return TRUE
/obj/machinery/computer/ship/proc/OnTopic(var/mob/user, var/href_list, var/datum/topic_state/state)
return TOPIC_NOACTION
/obj/machinery/computer/ship/tgui_state()
return GLOB.tgui_default_state
//
// Interaction
@@ -80,11 +66,11 @@
// If you perform direct interactions in here, you are responsible for ensuring that full interactivity checks have been made (i.e CanInteract).
// The checks leading in to here only guarantee that the user should be able to view a UI.
/obj/machinery/computer/ship/proc/interface_interact(var/mob/user)
ui_interact(user)
tgui_interact(user)
return TRUE
/obj/machinery/computer/ship/attack_ai(mob/user)
if(CanUseTopic(user, DefaultTopicState()) > STATUS_CLOSE)
if(tgui_status(user, tgui_state()) > STATUS_CLOSE)
return interface_interact(user)
// After a recent rework this should mostly be safe.
@@ -98,6 +84,6 @@
return
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied.</span>")
return 1
if(CanUseTopic(user, DefaultTopicState()) > STATUS_CLOSE)
return TRUE
if(tgui_status(user, tgui_state()) > STATUS_CLOSE)
return interface_interact(user)
@@ -5,92 +5,92 @@
icon_keyboard = "tech_key"
icon_screen = "engines"
circuit = /obj/item/weapon/circuitboard/engine
var/display_state = "status"
/obj/machinery/computer/ship/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/computer/ship/engines/tgui_interact(mob/user, datum/tgui/ui)
if(!linked)
display_reconnect_dialog(user, "ship control systems")
return
var/data[0]
data["state"] = display_state
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OvermapEngines", "[linked.name] Engines Control") // 390, 530
ui.open()
/obj/machinery/computer/ship/engines/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = list()
data["global_state"] = linked.engines_state
data["global_limit"] = round(linked.thrust_limit*100)
var/total_thrust = 0
var/list/enginfo[0]
var/list/enginfo = list()
for(var/datum/ship_engine/E in linked.engines)
var/list/rdata[0]
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)
rdata["eng_status"] = E.get_status()
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
return data
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "engines_control.tmpl", "[linked.name] Engines Control", 390, 530)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/ship/engines/OnTopic(var/mob/user, var/list/href_list, state)
/obj/machinery/computer/ship/engines/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return ..()
return TRUE
if(href_list["state"])
display_state = href_list["state"]
return TOPIC_REFRESH
switch(action)
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(href_list["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()
return TOPIC_REFRESH
if("set_global_limit")
var/newlim = input("Input new thrust limit (0..100%)", "Thrust limit", linked.thrust_limit*100) as num
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
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(href_list["set_global_limit"])
var/newlim = input("Input new thrust limit (0..100%)", "Thrust limit", linked.thrust_limit*100) as num
if(!CanInteract(user, state))
return TOPIC_NOACTION
linked.thrust_limit = CLAMP(newlim/100, 0, 1)
for(var/datum/ship_engine/E in linked.engines)
E.set_thrust_limit(linked.thrust_limit)
return TOPIC_REFRESH
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(href_list["global_limit"])
linked.thrust_limit = CLAMP(linked.thrust_limit + text2num(href_list["global_limit"]), 0, 1)
for(var/datum/ship_engine/E in linked.engines)
E.set_thrust_limit(linked.thrust_limit)
return TOPIC_REFRESH
if(href_list["engine"])
if(href_list["set_limit"])
var/datum/ship_engine/E = locate(href_list["engine"])
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
if(!CanInteract(user, state))
return
var/limit = CLAMP(newlim/100, 0, 1)
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
var/limit = clamp(newlim/100, 0, 1)
if(istype(E))
E.set_thrust_limit(limit)
return TOPIC_REFRESH
if(href_list["limit"])
var/datum/ship_engine/E = locate(href_list["engine"])
var/limit = CLAMP(E.get_thrust_limit() + text2num(href_list["limit"]), 0, 1)
if(istype(E))
E.set_thrust_limit(limit)
return TOPIC_REFRESH
. = TRUE
if(href_list["toggle"])
var/datum/ship_engine/E = locate(href_list["engine"])
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")
var/datum/ship_engine/E = locate(params["engine"])
if(istype(E))
E.toggle()
return TOPIC_REFRESH
return TOPIC_REFRESH
return TOPIC_NOACTION
. = TRUE
if(. && !issilicon(usr))
playsound(src, "terminal_type", 50, 1)
+166 -166
View File
@@ -22,6 +22,7 @@ GLOBAL_LIST_EMPTY(all_waypoints)
circuit = /obj/item/weapon/circuitboard/helm
core_skill = /datum/skill/pilot
var/autopilot = 0
var/autopilot_disabled = TRUE
var/list/known_sectors = list()
var/dx //desitnation
var/dy //coordinates
@@ -36,7 +37,7 @@ GLOBAL_LIST_EMPTY(all_waypoints)
/obj/machinery/computer/ship/helm/proc/get_known_sectors()
var/area/overmap/map = locate() in world
for(var/obj/effect/overmap/visitable/sector/S in map)
if (S.known)
if(S.known)
var/datum/computer_file/data/waypoint/R = new()
R.fields["name"] = S.name
R.fields["x"] = S.x
@@ -45,7 +46,7 @@ GLOBAL_LIST_EMPTY(all_waypoints)
/obj/machinery/computer/ship/helm/process()
..()
if (autopilot && dx && dy)
if(autopilot && dx && dy && !autopilot_disabled)
var/turf/T = locate(dx,dy,global.using_map.overmap_z)
if(linked.loc == T)
if(linked.is_still())
@@ -60,13 +61,13 @@ GLOBAL_LIST_EMPTY(all_waypoints)
var/heading = linked.get_heading()
// Destination is current grid or speedlimit is exceeded
if ((get_dist(linked.loc, T) <= brake_path) || speed > speedlimit)
if((get_dist(linked.loc, T) <= brake_path) || speed > speedlimit)
linked.decelerate()
// Heading does not match direction
else if (heading & ~direction)
else if(heading & ~direction)
linked.accelerate(turn(heading & ~direction, 180), accellimit)
// All other cases, move toward direction
else if (speed + acceleration <= speedlimit)
else if(speed + acceleration <= speedlimit)
linked.accelerate(direction, accellimit)
linked.operator_skill = null//if this is on you can't dodge meteors
return
@@ -78,149 +79,176 @@ GLOBAL_LIST_EMPTY(all_waypoints)
linked.relaymove(user, direction, accellimit)
return 1
/obj/machinery/computer/ship/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/computer/ship/helm/tgui_interact(mob/user, datum/tgui/ui)
if(!linked)
display_reconnect_dialog(user, "helm")
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OvermapHelm", "[linked.name] Helm Control") // 565, 545
ui.open()
/obj/machinery/computer/ship/helm/tgui_data(mob/user)
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["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
var/turf/T = get_turf(linked)
var/obj/effect/overmap/visitable/sector/current_sector = locate() in T
data["ETAnext"] = "N/A"
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"] = autopilot
data["manual_control"] = viewing_overmap(user)
data["canburn"] = linked.can_burn()
data["accellimit"] = accellimit*1000
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))
var/speed = round(linked.get_speed()*1000, 0.01)
if(linked.get_speed() < SHIP_SPEED_SLOW)
speed = "<span class='good'>[speed]</span>"
if(linked.get_speed() > SHIP_SPEED_FAST)
speed = "<span class='average'>[speed]</span>"
data["speed"] = speed
data["locations"] = locations
return data
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
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "helm.tmpl", "[linked.name] Helm Control", 565, 545)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/ship/helm/OnTopic(var/mob/user, var/list/href_list, state)
/obj/machinery/computer/ship/helm/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TOPIC_HANDLED
return TRUE
if(!linked)
return TOPIC_HANDLED
return FALSE
if (href_list["add"])
var/datum/computer_file/data/waypoint/R = new()
var/sec_name = input("Input naviation entry name", "New navigation entry", "Sector #[known_sectors.len]") as text
if(!CanInteract(user,state))
return TOPIC_NOACTION
if(!sec_name)
sec_name = "Sector #[known_sectors.len]"
R.fields["name"] = sec_name
if(sec_name in known_sectors)
to_chat(user, "<span class='warning'>Sector with that name already exists, please input a different name.</span>")
return TOPIC_REFRESH
switch(href_list["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
if(!CanInteract(user,state))
return TOPIC_REFRESH
var/newy = input("Input new entry y coordinate", "Coordinate input", linked.y) as num
if(!CanInteract(user,state))
return TOPIC_NOACTION
R.fields["x"] = CLAMP(newx, 1, world.maxx)
R.fields["y"] = CLAMP(newy, 1, world.maxy)
known_sectors[sec_name] = R
switch(action)
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(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
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
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return TRUE
var/newy = input("Input new entry y coordinate", "Coordinate input", linked.y) as num
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
R.fields["x"] = CLAMP(newx, 1, world.maxx)
R.fields["y"] = CLAMP(newy, 1, world.maxy)
known_sectors[sec_name] = R
. = TRUE
if (href_list["remove"])
var/datum/computer_file/data/waypoint/R = locate(href_list["remove"])
if(R)
known_sectors.Remove(R.fields["name"])
qdel(R)
if("remove")
var/datum/computer_file/data/waypoint/R = locate(params["remove"])
if(R)
known_sectors.Remove(R.fields["name"])
qdel(R)
. = TRUE
if (href_list["setx"])
var/newx = input("Input new destiniation x coordinate", "Coordinate input", dx) as num|null
if(!CanInteract(user,state))
return
if (newx)
dx = CLAMP(newx, 1, world.maxx)
if("setcoord")
if(params["setx"])
var/newx = input("Input new destiniation x coordinate", "Coordinate input", dx) as num|null
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return
if(newx)
dx = CLAMP(newx, 1, world.maxx)
if (href_list["sety"])
var/newy = input("Input new destiniation y coordinate", "Coordinate input", dy) as num|null
if(!CanInteract(user,state))
return
if (newy)
dy = CLAMP(newy, 1, world.maxy)
if(params["sety"])
var/newy = input("Input new destiniation y coordinate", "Coordinate input", dy) as num|null
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return
if(newy)
dy = CLAMP(newy, 1, world.maxy)
. = TRUE
if (href_list["x"] && href_list["y"])
dx = text2num(href_list["x"])
dy = text2num(href_list["y"])
if("setds")
dx = text2num(params["x"])
dy = text2num(params["y"])
. = TRUE
if (href_list["reset"])
dx = 0
dy = 0
if("reset")
dx = 0
dy = 0
. = TRUE
if (href_list["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)
if (href_list["accellimit"])
var/newlimit = input("Input new acceleration limit", "Acceleration limit", accellimit*1000) as num|null
if(newlimit)
accellimit = max(newlimit/1000, 0)
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 (href_list["move"])
var/ndir = text2num(href_list["move"])
if(prob(user.skill_fail_chance(/datum/skill/pilot, 50, linked.skill_needed, factor = 1)))
ndir = turn(ndir,pick(90,-90))
linked.relaymove(user, ndir, accellimit)
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 (href_list["brake"])
linked.decelerate()
if("move")
var/ndir = text2num(params["dir"])
if(prob(usr.skill_fail_chance(/datum/skill/pilot, 50, linked.skill_needed, factor = 1)))
ndir = turn(ndir,pick(90,-90))
linked.relaymove(usr, ndir, accellimit)
. = TRUE
if (href_list["apilot"])
autopilot = !autopilot
if("brake")
linked.decelerate()
. = TRUE
if (href_list["manual"])
viewing_overmap(user) ? unlook(user) : look(user)
if("apilot")
if(autopilot_disabled)
autopilot = FALSE
else
autopilot = !autopilot
. = TRUE
if("apilot_lock")
autopilot_disabled = !autopilot_disabled
autopilot = FALSE
. = TRUE
add_fingerprint(user)
updateUsrDialog()
if("manual")
viewing_overmap(usr) ? unlook(usr) : look(usr)
. = TRUE
add_fingerprint(usr)
if(. && !issilicon(usr))
playsound(src, "terminal_type", 50, 1)
/obj/machinery/computer/ship/navigation
@@ -228,49 +256,21 @@ GLOBAL_LIST_EMPTY(all_waypoints)
icon_keyboard = "generic_key"
icon_screen = "helm"
circuit = /obj/item/weapon/circuitboard/nav
var/datum/tgui_module/ship/nav/nav_tgui
/obj/machinery/computer/ship/navigation/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(!linked)
display_reconnect_dialog(user, "Navigation")
return
/obj/machinery/computer/ship/navigation/Initialize()
. = ..()
nav_tgui = new(src)
var/data[0]
/obj/machinery/computer/ship/navigation/Destroy()
QDEL_NULL(nav_tgui)
. = ..()
/obj/machinery/computer/ship/navigation/sync_linked(user)
return nav_tgui?.sync_linked()
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"
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "nav.tmpl", "[linked.name] Navigation Screen", 380, 530)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/ship/navigation/OnTopic(var/mob/user, var/list/href_list)
if(..())
return TOPIC_HANDLED
if (!linked)
return TOPIC_NOACTION
if (href_list["viewing"])
viewing_overmap(user) ? unlook(user) : look(user)
return TOPIC_REFRESH
/obj/machinery/computer/ship/navigation/tgui_interact(mob/user, datum/tgui/ui)
return nav_tgui?.tgui_interact(user, ui)
/obj/machinery/computer/ship/navigation/telescreen //little hacky but it's only used on one ship so it should be okay
icon_state = "tele_nav"
+50 -41
View File
@@ -20,14 +20,29 @@
sensors = S
break
/obj/machinery/computer/ship/sensors/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/computer/ship/sensors/tgui_interact(mob/user, datum/tgui/ui)
if(!linked)
display_reconnect_dialog(user, "sensors")
return
var/data[0]
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OvermapShipSensors", "[linked.name] Sensors Control") // 420, 530
ui.open()
/obj/machinery/computer/ship/sensors/tgui_data(mob/user)
var/list/data = list()
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
@@ -53,54 +68,48 @@
if(bearing < 0)
bearing += 360
contacts.Add(list(list("name"=O.name, "ref"="\ref[O]", "bearing"=bearing)))
if(contacts.len)
data["contacts"] = contacts
else
data["status"] = "MISSING"
data["range"] = "N/A"
data["on"] = 0
data["contacts"] = contacts
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "shipsensors.tmpl", "[linked.name] Sensors Control", 420, 530, src)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/computer/ship/sensors/OnTopic(var/mob/user, var/list/href_list, state)
/obj/machinery/computer/ship/sensors/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TOPIC_HANDLED
return TRUE
if (!linked)
return TOPIC_NOACTION
if(!linked)
return FALSE
if (href_list["viewing"])
if(user && !isAI(user))
viewing_overmap(user) ? unlook(user) : look(user)
return TOPIC_REFRESH
switch(action)
if("viewing")
if(usr && !isAI(usr))
viewing_overmap(usr) ? unlook(usr) : look(usr)
. = TRUE
if (href_list["link"])
find_sensors()
return TOPIC_REFRESH
if("link")
find_sensors()
. = TRUE
if("scan")
var/obj/effect/overmap/O = locate(params["scan"])
if(istype(O) && !QDELETED(O) && (O in view(7,linked)))
new/obj/item/weapon/paper/(get_turf(src), O.get_scan_data(usr), "paper (Sensor Scan - [O])")
. = TRUE
if(sensors)
if (href_list["range"])
var/nrange = input("Set new sensors range", "Sensor range", sensors.range) as num|null
if(!CanInteract(user,state))
return TOPIC_NOACTION
if (nrange)
sensors.set_range(CLAMP(nrange, 1, world.view))
return TOPIC_REFRESH
if (href_list["toggle"])
sensors.toggle()
return TOPIC_REFRESH
switch(action)
if("range")
var/nrange = input("Set new sensors range", "Sensor range", sensors.range) as num|null
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
if(nrange)
sensors.set_range(CLAMP(nrange, 1, world.view))
. = TRUE
if("toggle")
sensors.toggle()
. = TRUE
if (href_list["scan"])
var/obj/effect/overmap/O = locate(href_list["scan"])
if(istype(O) && !QDELETED(O) && (O in view(7,linked)))
playsound(src, "sound/machines/dotprinter.ogg", 30, 1)
new/obj/item/weapon/paper/(get_turf(src), O.get_scan_data(user), "paper (Sensor Scan - [O])")
return TOPIC_HANDLED
if(. && !issilicon(usr))
playsound(src, "terminal_type", 50, 1)
/obj/machinery/computer/ship/sensors/process()
..()
+29 -15
View File
@@ -37,22 +37,31 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
popup.set_content("<center><strong><font color = 'red'>Error</strong></font><br>Unable to connect to [flavor].<br><a href='?src=\ref[src];sync=1'>Reconnect</a></center>")
popup.open()
/obj/machinery/computer/ship/Topic(href, href_list)
if(..())
return TRUE
if(href_list["sync"])
if(sync_linked(usr))
interface_interact(usr)
return TRUE
// In computer_shims for now - we had to define it.
// /obj/machinery/computer/ship/interface_interact(var/mob/user)
// ui_interact(user)
// return TRUE
/obj/machinery/computer/ship/OnTopic(var/mob/user, var/list/href_list)
/obj/machinery/computer/ship/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TOPIC_HANDLED
if(href_list["sync"])
sync_linked(user)
return TOPIC_REFRESH
if(href_list["close"])
unlook(user)
user.unset_machine()
return TOPIC_HANDLED
return TOPIC_NOACTION
return TRUE
switch(action)
if("sync")
sync_linked(usr)
return TRUE
if("close")
unlook(usr)
usr.unset_machine()
return TRUE
return FALSE
// Management of mob view displacement. look to shift view to the ship on the overmap; unlook to shift back.
@@ -60,6 +69,7 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
if(linked)
apply_visual(user)
user.reset_view(linked)
user.set_machine(src)
user.set_viewsize(world.view + extra_view)
GLOB.moved_event.register(user, src, /obj/machinery/computer/ship/proc/unlook)
// TODO GLOB.stat_set_event.register(user, src, /obj/machinery/computer/ship/proc/unlook)
@@ -75,17 +85,21 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
/obj/machinery/computer/ship/proc/viewing_overmap(mob/user)
return (weakref(user) in viewers)
/obj/machinery/computer/ship/CouldNotUseTopic(mob/user)
/obj/machinery/computer/ship/tgui_status(mob/user)
. = ..()
if(. > STATUS_DISABLED)
if(viewing_overmap(user))
look(user)
return
unlook(user)
/obj/machinery/computer/ship/CouldUseTopic(mob/user)
/obj/machinery/computer/ship/tgui_close(mob/user)
. = ..()
if(viewing_overmap(user))
look(user)
user.unset_machine()
unlook(user)
/obj/machinery/computer/ship/check_eye(var/mob/user)
if (!get_dist(user, src) > 1 || user.blinded || !linked )
if(!get_dist(user, src) > 1 || user.blinded || !linked)
unlook(user)
return -1
else
+1 -1
View File
@@ -19,7 +19,7 @@ var/list/ship_engines = list()
//Returns status string for this engine
/datum/ship_engine/proc/get_status()
return "All systems nominal"
return list("All systems nominal")
/datum/ship_engine/proc/get_thrust()
return 1
@@ -103,18 +103,17 @@
. = list()
.+= "Location: [get_area(src)]."
if(stat & NOPOWER)
.+= "<span class='average'>Insufficient power to operate.</span>"
.+= list(list("Insufficient power to operate.", "bad"))
if(!check_fuel())
.+= "<span class='average'>Insufficient fuel for a burn.</span>"
.+= list(list("Insufficient fuel for a burn.", "bad"))
if(stat & BROKEN)
.+= "<span class='average'>Inoperable engine configuration.</span>"
.+= list(list("Inoperable engine configuration.", "bad"))
if(blockage)
.+= "<span class='average'>Obstruction of airflow detected.</span>"
.+= list(list("Obstruction of airflow detected.", "bad"))
.+= "Propellant total mass: [round(air_contents.get_mass(),0.01)] kg."
.+= "Propellant used per burn: [round(air_contents.get_mass() * volume_per_burn * thrust_limit / air_contents.volume,0.01)] kg."
.+= "Propellant pressure: [round(air_contents.return_pressure()/1000,0.1)] MPa."
. = jointext(.,"<br>")
/obj/machinery/atmospherics/unary/engine/power_change()
. = ..()
@@ -61,9 +61,7 @@
. = list()
.+= "Location: [get_area(src)]."
if(!powered())
.+= "Insufficient power to operate."
. = jointext(.,"<br>")
.+= list(list("Insufficient power to operate.", "bad"))
/obj/machinery/ion_engine/proc/burn()
if(!on && !powered())
+81 -80
View File
@@ -400,8 +400,14 @@
spinup_counter = round(spinup_delay / idle_multiplier)
update_icon()
/obj/machinery/power/shield_generator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/power/shield_generator/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "OvermapShieldGenerator", name) // 500, 800
ui.open()
/obj/machinery/power/shield_generator/tgui_data(mob/user)
var/list/data = list()
data["running"] = running
data["modes"] = get_flag_descriptions()
@@ -427,12 +433,7 @@
data["idle_valid_values"] = idle_valid_values
data["spinup_counter"] = spinup_counter
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "shield_generator.tmpl", src.name, 500, 800)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
return data
/obj/machinery/power/shield_generator/attack_hand(mob/user)
if((. = ..()))
@@ -440,99 +441,99 @@
if(panel_open && Adjacent(user))
wires.Interact(user)
return
if(CanUseTopic(user, global.default_state) > STATUS_CLOSE)
ui_interact(user)
return TRUE
tgui_interact(user)
/obj/machinery/power/shield_generator/CanUseTopic(var/mob/user)
/obj/machinery/power/shield_generator/tgui_status(mob/user)
if(issilicon(user) && !Adjacent(user) && ai_control_disabled)
return STATUS_UPDATE
if(panel_open)
return min(..(), STATUS_DISABLED)
return ..()
/obj/machinery/power/shield_generator/Topic(href, href_list, datum/topic_state/state = default_state)
if((. = ..()))
return
/obj/machinery/power/shield_generator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(href_list["begin_shutdown"])
if(running < SHIELD_RUNNING) // Discharging or off
return
var/alert = alert(usr, "Are you sure you wish to do this? It will drain the power inside the internal storage rapidly.", "Are you sure?", "Yes", "No")
if(!CanInteract(usr, state))
return
if(running < SHIELD_RUNNING)
return
if(alert == "Yes")
set_idle(TRUE) // do this first to clear the field
running = SHIELD_DISCHARGING
return TOPIC_REFRESH
switch(action)
if("begin_shutdown")
if(running < SHIELD_RUNNING) // Discharging or off
return
var/alert = alert(usr, "Are you sure you wish to do this? It will drain the power inside the internal storage rapidly.", "Are you sure?", "Yes", "No")
if(tgui_status(usr, state) != STATUS_INTERACTIVE)
return
if(running < SHIELD_RUNNING)
return
if(alert == "Yes")
set_idle(TRUE) // do this first to clear the field
running = SHIELD_DISCHARGING
return TRUE
if(href_list["start_generator"])
if(offline_for)
return
set_idle(TRUE)
return TOPIC_REFRESH
if("start_generator")
if(offline_for)
return
set_idle(TRUE)
return TRUE
if(href_list["toggle_idle"])
if(running < SHIELD_RUNNING)
return TOPIC_HANDLED
set_idle(text2num(href_list["toggle_idle"]))
return TOPIC_REFRESH
if("toggle_idle")
if(running < SHIELD_RUNNING)
return TRUE
set_idle(text2num(params["toggle_idle"]))
return TRUE
// Instantly drops the shield, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge.
if(href_list["emergency_shutdown"])
if(!running)
return TOPIC_HANDLED
// Instantly drops the shield, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge.
if("emergency_shutdown")
if(!running)
return TRUE
var/choice = input(usr, "Are you sure that you want to initiate an emergency shield shutdown? This will instantly drop the shield, and may result in unstable release of stored electromagnetic energy. Proceed at your own risk.") in list("Yes", "No")
if((choice != "Yes") || !running)
return TOPIC_HANDLED
var/choice = input(usr, "Are you sure that you want to initiate an emergency shield shutdown? This will instantly drop the shield, and may result in unstable release of stored electromagnetic energy. Proceed at your own risk.") in list("Yes", "No")
if((choice != "Yes") || !running)
return TRUE
// If the shield would take 5 minutes to disperse and shut down using regular methods, it will take x1.5 (7 minutes and 30 seconds) of this time to cool down after emergency shutdown
offline_for = round(current_energy / (SHIELD_SHUTDOWN_DISPERSION_RATE / 1.5))
var/old_energy = current_energy
shutdown_field()
log_and_message_admins("has triggered \the [src]'s emergency shutdown!", usr)
spawn()
empulse(src, old_energy / 60000000, old_energy / 32000000, 1) // If shields are charged at 450 MJ, the EMP will be 7.5, 14.0625. 90 MJ, 1.5, 2.8125
old_energy = 0
// If the shield would take 5 minutes to disperse and shut down using regular methods, it will take x1.5 (7 minutes and 30 seconds) of this time to cool down after emergency shutdown
offline_for = round(current_energy / (SHIELD_SHUTDOWN_DISPERSION_RATE / 1.5))
var/old_energy = current_energy
shutdown_field()
log_and_message_admins("has triggered \the [src]'s emergency shutdown!", usr)
spawn()
empulse(src, old_energy / 60000000, old_energy / 32000000, 1) // If shields are charged at 450 MJ, the EMP will be 7.5, 14.0625. 90 MJ, 1.5, 2.8125
old_energy = 0
return TOPIC_REFRESH
return TRUE
if(mode_changes_locked)
return TOPIC_REFRESH
return TRUE
if(href_list["set_range"])
var/new_range = input(usr, "Enter new field range (1-[world.maxx]). Leave blank to cancel.", "Field Radius Control", field_radius) as num
if(!new_range)
return TOPIC_HANDLED
target_radius = between(1, new_range, world.maxx)
return TOPIC_REFRESH
switch(action)
if("set_range")
var/new_range = input(usr, "Enter new field range (1-[world.maxx]). Leave blank to cancel.", "Field Radius Control", field_radius) as num
if(!new_range)
return TRUE
target_radius = between(1, new_range, world.maxx)
return TRUE
if(href_list["set_input_cap"])
var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num)
if(!new_cap)
input_cap = 0
return
input_cap = max(0, new_cap) * 1000
return TOPIC_REFRESH
if("set_input_cap")
var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num)
if(!new_cap)
input_cap = 0
return
input_cap = max(0, new_cap) * 1000
return TRUE
if(href_list["toggle_mode"])
// Toggling hacked-only modes requires the hacked var to be set to 1
if((text2num(href_list["toggle_mode"]) & (MODEFLAG_BYPASS | MODEFLAG_OVERCHARGE)) && !hacked)
return TOPIC_HANDLED
if("toggle_mode")
// Toggling hacked-only modes requires the hacked var to be set to 1
if((text2num(params["toggle_mode"]) & (MODEFLAG_BYPASS | MODEFLAG_OVERCHARGE)) && !hacked)
return TRUE
toggle_flag(text2num(href_list["toggle_mode"]))
return TOPIC_REFRESH
toggle_flag(text2num(params["toggle_mode"]))
return TRUE
if(href_list["switch_idle"])
if(running == SHIELD_SPINNING_UP)
return TOPIC_REFRESH
var/new_idle = text2num(href_list["switch_idle"])
if(new_idle in idle_valid_values)
idle_multiplier = new_idle
return TOPIC_REFRESH
if("switch_idle")
if(running == SHIELD_SPINNING_UP)
return TRUE
var/new_idle = text2num(params["switch_idle"])
if(new_idle in idle_valid_values)
idle_multiplier = new_idle
return TRUE
/obj/machinery/power/shield_generator/proc/field_integrity()
if(full_shield_strength)
+3
View File
@@ -26,6 +26,9 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
if(host)
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) == STATUS_INTERACTIVE)
+137
View File
@@ -0,0 +1,137 @@
/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(. > STATUS_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(tgui_host())
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/tgui_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/tgui_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/tgui_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
-91
View File
@@ -1,91 +0,0 @@
{{if data.faillink}}
<div class='notice'>
ERROR: Machine is incomplete, out of range, or misaligned!
</div>
{{else}}
<div style="float:left;width:50%">
<h3>Targeting</h3>
<div class='block'>
<div class='item'>
<div class='item'>
{{:helper.link('', 'triangle-1-nw', { 'choose' : 9 }, data.overmapdir == 9 ? 'selected' : null, null)}}
{{:helper.link('', 'triangle-1-n', { 'choose' : 1 }, data.overmapdir == 1 ? 'selected' : null, null)}}
{{:helper.link('', 'triangle-1-ne', { 'choose' : 5 }, data.overmapdir == 5 ? 'selected' : null, null)}}
</div>
<div class='item'>
{{:helper.link('', 'triangle-1-w', { 'choose' : 8 }, data.overmapdir == 8 ? 'selected' : null, null)}}
{{:helper.link('', 'circle-close', { 'choose' : 0 }, data.overmapdir == 0 ? 'selected' : null, null)}}
{{:helper.link('', 'triangle-1-e', { 'choose' : 4 }, data.overmapdir == 4 ? 'selected' : null, null)}}
</div>
<div class='item'>
{{:helper.link('', 'triangle-1-sw', { 'choose' : 10 }, data.overmapdir == 10 ? 'selected' : null, null)}}
{{:helper.link('', 'triangle-1-s', { 'choose' : 2 }, data.overmapdir == 2 ? 'selected' : null, null)}}
{{:helper.link('', 'triangle-1-se', { 'choose' : 6 }, data.overmapdir == 6 ? 'selected' : null, null)}}
</div>
</div>
</div>
</div>
<div style="float:right;width:50%">
<h3>Charge</h3>
<div class='block'>
{{if data.nopower}}
<b>At least one part of the machine is unpowered.</b>
{{/if}}
<div class='itemLabelWidest'>
Charge Load Type
</div>
<div class='item'>
{{:data.chargeload}}
</div>
<div class='itemLabelWidest'>
Cooldown
</div>
<div class='item'>
{{if data.next_shot == 0}}
Ready
{{else}}
{{:data.next_shot}} seconds
<br><i>Warning: Do not fire during cooldown.</i>
{{/if}}
</div>
</div>
</div>
<hr>
<div style="float:left;width:50%">
<h3>Calibration</h3>
<div class='block'>
<div class='itemLabelWidest'>
{{:data.cal_accuracy}}%
</div>
<div class='itemLabelWidest'>
{{:helper.link('Pre-Calibration', 'transfer-e-w', { 'skill_calibration' : 1 }, data.skill ? null : 'disabled', null)}}
</div><br>
{{for data.calibration}}
<div class='item'>
{{:helper.link(value, 'shuffle', { 'calibration' : index }, null, null)}}
<br>
</div>
{{/for}}
</div>
</div>
<div style="float:right;width:50%">
<h3>Setup</h3>
<div class='block'>
<div class='itemLabelWidest'>
Strength
</div>
<div class='item'>
{{:helper.link(data.strength, 'lightbulb', { 'strength' : 1 }, null, null)}}
</div>
<div class='itemLabelWidest'>
Radius
</div>
<div class='item'>
{{:helper.link(data.range, 'arrow-4-diag', { 'range' : 1 }, null, null)}}
</div>
</div>
</div>
<div class='item'>
{{:helper.link("Fire", 'alert', { 'fire' : 1 }, null, null)}}
</div>
{{/if}}
-110
View File
@@ -1,110 +0,0 @@
<div class="item">
{{:helper.link('Overall info', 'note', {'state' :'status'}, null, data.state == 'status' ? 'selected' : null)}}
{{:helper.link('Details', 'note', {'state' : 'engines'}, null, data.state == 'engines' ? 'selected' : null)}}
</div>
<div class="item">
<div class='item'>
<div class="itemLabel">
<span class='average'>Global controls:</span>
</div>
<div class="itemContent">
{{:helper.link(data.global_state ? 'Shut all down' : 'Power all up', 'power', {'global_toggle' : 1}, null, data.global_state ? 'selected' : null)}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Volume limit:</span>
</div>
<div class="itemContent">
{{:helper.link('', 'circle-plus', { 'global_limit' : 0.1}, null, null)}}
{{:helper.link(data.global_limit+'%', null, { 'set_global_limit' : 1 }, null, null)}}
{{:helper.link('', 'circle-minus', { 'global_limit' : -0.1}, null, null)}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Total thrust:</span>
</div>
<div class="itemContent">
<span class='white'>{{:data.total_thrust}}</span>
</div>
</div>
</div>
{{if data.state == "engines"}}
{{if data.engines_info}}
{{for data.engines_info}}
<div class='item'>
<div class="itemLabel">
<span class='white'>Engine #{{:(index + 1)}}:</span>
</div>
<div class="itemContent">
{{:helper.link(value.eng_on ? 'Shutdown' : 'Power up', 'power', { 'toggle' : 1, 'engine' : value.eng_reference }, null, value.eng_on ? value.eng_on == 1 ? 'linkOn' : 'yellowButton' : null)}}
</div>
<div class='statusDisplay'>
<div class='item'>
<div class="itemLabel">
<span class='average'>Type:</span>
</div>
<div class="itemContent">
<span class='white'>{{:value.eng_type}}</span>
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Status:</span>
</div>
<div class="itemContent">
<span class='{{:value.eng_on ? value.eng_on == 1 ? 'good' : 'average' : 'bad'}}'>{{:value.eng_on ? value.eng_on == 1 ? 'Online' : 'Booting' : 'Offline'}}</span><br>
<span class='white'>{{:value.eng_status}}</span>
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Current thrust:</span>
</div>
<div class="itemContent">
<span class='white'>{{:value.eng_thrust}}</span>
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Volume limit:</span>
</div>
<div class="itemContent">
{{:helper.link('', 'circle-plus', { 'limit' : 0.1, 'engine' : value.eng_reference }, null, null)}}
{{:helper.link(value.eng_thrust_limiter+'%', null, { 'set_limit' : 1, 'engine' : value.eng_reference }, null, null)}}
{{:helper.link('', 'circle-minus', { 'limit' : -0.1, 'engine' : value.eng_reference }, null, null)}}
</div>
</div>
</div>
{{/for}}
{{/if}}
{{/if}}
{{if data.state == "status"}}
{{if data.engines_info}}
{{for data.engines_info}}
<div class='block'>
<div class='item'>
<div class="itemLabel">
<span class='white'>Engine #{{:(index + 1)}}:</span>
</div>
<div class="itemContent">
{{:helper.link(value.eng_on ? 'Shutdown' : 'Power up', 'power', { 'toggle' : 1, 'engine' : value.eng_reference }, null, value.eng_on ? value.eng_on == 1 ? 'linkOn' : 'yellowButton' : null)}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Thrust:</span>
<br>
<span class='average'>Volume limit:</span>
</div>
<div class="itemContent">
<span class='white'>{{:value.eng_thrust}}</span>
<br>
<span class='white'>{{:value.eng_thrust_limiter}}%</span>
</div>
</div>
</div>
{{/for}}
{{/if}}
{{/if}}
-159
View File
@@ -1,159 +0,0 @@
<div style="float:left;width:45%;">
<fieldset style="min-height:180px;background-color: #202020;">
<legend style="text-align:center">Flight data</legend>
<div class='item'>
<div class="itemLabelWider">
ETA to next grid:
</div>
<div style="float:right">
{{:data.ETAnext}}
</div>
</div>
<div class='item'>
<div class="itemLabelWider">
Speed:
</div>
<div style="float:right">
{{:data.speed}} Gm/h
</div>
</div>
<div class='item'>
<div class="itemLabelWider">
Acceleration:
</div>
<div style="float:right">
{{:data.accel}} Gm/h
</div>
</div>
<div class='item'>
<div class="itemLabelWider">
Heading:
</div>
<div style="float:right">
{{:data.heading}}&deg;
</div>
</div>
<div class='item'>
<div class="itemLabelWider">
Acceleration limiter:
</div>
<div style="float:right">
{{:helper.link(data.accellimit, null, { 'accellimit' : 1}, null, null)}} Gm/h
</div>
</div>
</fieldset>
</div>
<div style="float:left;width:25%">
<fieldset style="min-height:180px;background-color: #202020;">
<legend style="text-align:center">Manual control</legend>
<div class='item'>
<div class='item'>
{{:helper.link('', 'triangle-1-nw', { 'move' : 9 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'triangle-1-n', { 'move' : 1 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'triangle-1-ne', { 'move' : 5 }, data.canburn ? null : 'disabled', null)}}
</div>
<div class='item'>
{{:helper.link('', 'triangle-1-w', { 'move' : 8 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'circle-close', { 'brake' : 1 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'triangle-1-e', { 'move' : 4 }, data.canburn ? null : 'disabled', null)}}
</div>
<div class='item'>
{{:helper.link('', 'triangle-1-sw', { 'move' : 10 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'triangle-1-s', { 'move' : 2 }, data.canburn ? null : 'disabled', null)}}
{{:helper.link('', 'triangle-1-se', { 'move' : 6 }, data.canburn ? null : 'disabled', null)}}
</div>
<div class='item'>
<span class='white'>Direct control</span>
<br>
{{:helper.link(data.manual_control ? 'Engaged' : 'Disengaged', 'shuffle', { 'manual' : 1 }, null, data.manual_control ? 'selected' : null)}}
</div>
</div>
</fieldset>
</div>
<div style="float:left;width:30%">
<fieldset style="min-height:180px;background-color: #202020;">
<legend style="text-align:center">Autopilot</legend>
<div class='item'>
<div class="itemLabelWide">
Target:
</div>
<div class="itemContent">
{{if data.dest}}
{{:helper.link(data.d_x, null, { 'setx' : 1 }, null, null)}} {{:helper.link(data.d_y, null, { 'sety' : 1 }, null, null)}}
{{else}}
{{:helper.link('None', null, { 'sety' : 1, 'setx' : 1 }, null, null)}}
{{/if}}
</div>
</div>
<div class='item'>
<div class="itemLabelWide">
Speed limit:
</div>
<div class="itemContent">
{{:helper.link(data.speedlimit, null, { 'speedlimit' : 1 }, null, null)}} Gm/h
</div>
</div>
<div class="item">
{{:helper.link(data.autopilot ? 'Engaged' : 'Disengaged', 'gear', { 'apilot' : 1 }, data.dest ? null : 'disabled', data.autopilot ? 'selected' : null)}}
</div>
</fieldset>
</div>
<div class='block' style='clear: both;'>
<h3>Navigation data</h3>
<div class='item'>
<div class="itemLabel">
Location:
</div>
<div class="itemContent">
{{:data.sector}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
Coordinates:
</div>
<div class="itemContent">
{{:data.s_x}} : {{:data.s_y}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
Scan data:
</div>
<div class="itemContent">
{{:data.sector_info}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
Status:
</div>
<div class="itemContent">
{{:data.landed}}
</div>
</div>
<div class='item'>
{{:helper.link('Save current position', 'disk', { 'add' : 'current' }, null)}}
{{:helper.link('Add new entry', 'document', { 'add' : 'new' }, null)}}
</div>
<div class='statusDisplay'>
<table style="width:100%">
<tr><th style="width:40%">Name<th>Coordinates<th>Actions
{{for data.locations}}
<tr class="candystripe"><td>{{:value.name}}
<td>{{:value.x}} : {{:value.y}}
<td>{{:helper.link('Plot course', 'arrowreturnthick-1-e', { 'x' : value.x, 'y' : value.y }, null, null)}}
{{:helper.link('Remove', 'close', { 'remove' : value.reference }, null, null)}}
{{/for}}
</table>
</div>
</div>
-59
View File
@@ -1,59 +0,0 @@
<h3>Navigation</h3>
<div class='block'>
<div class='item'>
<div class="itemContent">
<div class='item'>
<span class='white'>Map view</span>
{{:helper.link(data.viewing ? 'Engaged' : 'Disengaged', 'shuffle', { 'viewing' : 1 }, null, data.viewing ? 'selected' : null)}}
</div>
</div>
</div>
</div>
<div style="float:left;width:50%">
<h3>Sector information</h3>
<div class='block'>
{{:data.sector}}
<br>
<span class='average'>Coordinates:</span> {{:data.s_x}} : {{:data.s_y}}
<br>
<span class='average'>Additional information:</span> {{:data.sector_info}}
</div>
</div>
<div style="float:right;width:50%">
<h3>Flight data</h3>
<div class='block'>
<div class='item'>
<div class="itemLabel">
<span class='average'>ETA to next grid:</span>
</div>
<div style="float:right">
{{:data.ETAnext}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Speed:</span>
</div>
<div style="float:right">
{{:data.speed}} Gm/h
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Acceleration:</span>
</div>
<div style="float:right">
{{:data.accel}} Gm/h
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='average'>Heading:</span>
</div>
<div style="float:right">
{{:data.heading}}&deg;
</div>
</div>
</div>
</div>
-54
View File
@@ -1,54 +0,0 @@
<h2>Fire Assist Mainframe: {{:data.id || "[no tag]"}}</h2>
{{if !(data.id)}}
<div class="notice">
<span class='bad'>This system has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.</span>
</div>
{{/if}}
{{for data.turrets}}
<h3>{{:value.id}}</h3>
<div class="item">
<div class="itemLabelWide">
Battery status
</div>
<div class="itemContentMedium">
{{if value.active}}
<span class="fixedLeft good">Online</span> {{:helper.link('Shut down', null, {'toggle_active': value.ref})}}
{{else}}
<span class="fixedLeft average">Offline</span> {{:helper.link('Start up', null, {'toggle_active': value.ref})}}
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabelWide">
Effective range
</div>
<div class="itemContentMedium">
{{:value.effective_range}}
</div>
</div>
<div class="item">
<div class="itemLabelWide">
Reaction wheel delay
</div>
<div class="itemContentMedium">
{{:value.reaction_wheel_delay}}
</div>
</div>
<div class="item">
<div class="itemLabelWide">
Recharge time
</div>
<div class="itemContentMedium">
{{:value.recharge_time}}
</div>
{{empty}}
<div class="item">
<div class="itemLabel">
Error:
</div>
<div class="itemContent">
No weapon systems detected. Please check network connection.
</div>
</div>
<hr/>
{{/for}}
-158
View File
@@ -1,158 +0,0 @@
{{if data.offline_for}}
<h1>EMERGENCY SHUTDOWN</h1>
<b>An emergency shutdown has been initiated - generator cooling down</b><br>
<i>Please wait until the generator cools down before resuming operation. Estimated time left: {{:data.offline_for}} seconds.</i>
{{else}}
<h2>SYSTEM STATUS</h2>
<div class="item">
<div class="itemLabel">
Generator is:
</div>
<div class="itemContent">
{{if data.running == 2}}
{{if data.overloaded}}
Recovering
{{else}}
Active
{{/if}}
{{else data.running == 1}}
Shutting Down
{{else data.running == 3}}
Inactive
{{else data.running == 4}}
Spinning Up&nbsp;
{{if data.target_radius != data.field_radius}}
(Adjusting Radius)
{{else}}
({{:data.spinup_counter * 2}}s)
{{/if}}
{{else}}
Offline
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Energy Storage:
</div>
<div class="itemContent">
{{:data.current_energy}}/{{:data.max_energy}} MJ ({{:data.percentage_energy}}%)
</div>
</div>
<div class="item">
<div class="itemLabel">
Shield Integrity:
</div>
<div class="itemContent">
{{:data.field_integrity}}%
</div>
</div>
<div class="item">
<div class="itemLabel">
Mitigation:
</div>
<div class="itemContent">
{{:data.mitigation_em}}% EM / {{:data.mitigation_physical}}% PH / {{:data.mitigation_heat}}% HE / {{:data.mitigation_max}}% MAX
</div>
</div>
<div class="item">
<div class="itemLabel">
Upkeep Energy Use:
</div>
<div class="itemContent">
{{:data.upkeep_power_usage}} kW
</div>
</div>
<div class="item">
<div class="itemLabel">
Total Energy Use:
</div>
<div class="itemContent">
{{if data.input_cap_kw}}
{{:data.power_usage}} / {{:data.input_cap_kw}} kW
{{else}}
{{:data.power_usage}} kW (No Limit)
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Field Size:
</div>
<div class="itemContent">
{{:data.functional_segments}} / {{:data.total_segments}} m2 (radius {{:data.field_radius}}, target {{:data.target_radius}})
</div>
</div>
<h2>CONTROLS</h2>
<table>
<tr>
{{if (data.running >= 2)}}
<td>{{:helper.link('Turn off', null, {'begin_shutdown' : '1'})}}
{{if (data.running == 3)}}
<td>{{:helper.link('Activate', null, {'toggle_idle' : '0'})}} </td>
{{else}}
<td>{{:helper.link('Deactivate', null, {'toggle_idle' : '1'})}} </td>
{{/if}}
{{else}}
<td>{{:helper.link('Turn on', null, {'start_generator' : '1'})}}
{{/if}}
{{if data.running}}
{{if data.hacked}}
<td>{{:helper.link('EMERGENCY SHUTDOWN', null, {'emergency_shutdown' : '1'}, null, 'redButton')}}
{{/if}}
{{/if}}
<tr>
<td>{{:helper.link('Set Field Range', null, {'set_range' : '1'})}}
<td>{{:helper.link('Set Input Cap', null, {'set_input_cap' : '1'})}}
<tr>
<td>Set inactive power use intensity:</td>
<td>
{{for data.idle_valid_values}}
{{:helper.link(value, null, {'switch_idle' : value}, (value == data.idle_multiplier) ? 'selected' : (data.running == 4 ? 'disabled' : null))}}
{{/for}}
</td>
</table>
<h2>FIELD CALIBRATION</h2>
<hr>
{{for data.modes}}
<div class="item">
<div class="itemLabel">
Mode:
</div>
<div class="itemContent">
{{:value.name}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Description:
</div>
<div class="itemContent">
{{:value.desc}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Status:
</div>
<div class="itemContent">
{{if value.status}}
Enabled
{{else}}
Disabled
{{/if}}
{{:helper.link('Toggle', null, {'toggle_mode' : value.flag})}}
</div>
</div>
<div class="item">
<div class="itemLabel">
Multiplier:
</div>
<div class="itemContent">
{{:value.multiplier}}
</div>
</div>
<hr>
{{/for}}
{{/if}}
-90
View File
@@ -1,90 +0,0 @@
<h3>Sensors control console</h3>
<div class='block'>
{{:helper.link(data.on ? 'Switch off' : 'Switch on', 'gear', { 'toggle' : 1 }, data.status != 'MISSING' ? null : 'disabled', data.on ? 'selected' : null)}}
<div class='item'>
<div class="itemLabel">
<span class='white'>Status:</span>
</div>
<div class="itemContent">
{{:data.status}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
<span class='white'>Range:</span>
</div>
<div class="itemContent">
{{:helper.link(data.range, null, { 'range' : 1 }, null, null)}}
</div>
</div>
</div>
<div class='block'>
<div class='item'>
<div class="itemLabel">
Integrity:
</div>
<div class="itemContent">
{{if data.health < (data.max_health * 0.25)}}
{{:helper.displayBar(data.health, 0, data.max_health, 'bad')}}
<br><span class="bad">{{:data.health}}/{{:data.max_health}}</span>
{{else data.health < data.max_health *.75}}
{{:helper.displayBar(data.health, 0, data.max_health, 'average')}}
<br><span class="average">{{:data.health}}/{{:data.max_health}}</span>
{{else}}
{{:helper.displayBar(data.health, 0, data.max_health, 'good')}}
<br><span class="good">{{:data.health}}/{{:data.max_health}}</span>
{{/if}}
</div>
</div>
<div class='item'>
<div class="itemLabel">
Temperature:
</div>
<div class="itemContent">
{{if data.heat < (data.critical_heat * 0.5)}}
{{:helper.displayBar(data.heat, 0, data.critical_heat, 'good')}}
{{else data.heat < (data.critical_heat * 0.75)}}
{{:helper.displayBar(data.heat, 0, data.critical_heat, 'average')}}
{{else}}
{{:helper.displayBar(data.heat, 0, data.critical_heat, 'bad')}}
{{/if}}
</div>
<div class="itemContent">
{{if data.heat < (data.critical_heat * 0.5)}}
<span class="good">Temperature low.</span>
{{else data.heat < (data.critical_heat * 0.75)}}
<span class="average">Sensor temperature high!</span>
{{else}}
<span class="bad">TEMPERATURE CRITICAL: Disable or reduce power immediately!</span>
{{/if}}
</div>
</div>
</div>
<div class='item'>
<div class="itemContent">
<div class='item'>
<span class='white'>Sector map view</span>
{{:helper.link(data.viewing ? 'Engaged' : 'Disengaged', 'shuffle', { 'viewing' : 1 }, null, data.viewing ? 'selected' : null)}}
</div>
</div>
</div>
<h4>Sensor contacts</h4>
<div class='block'>
{{if data.contacts}}
<table>
{{for data.contacts}}
<tr>
<div class='item'>
<td>{{:helper.link('Scan', 'search' ,{ 'scan' : value.ref }, null, null)}}</td>
<td><span class='white'>{{:value.name}}</span>, bearing {{:value.bearing}}</td>
</div>
</tr>
{{/for}}
</table>
{{/if}}
</div>
{{if data.status == 'MISSING'}}
<div class='item'>
{{:helper.link('Link up with the sensor suite', 'gear', { 'link' : 1 }, data.status == 'MISSING' ? null : 'disabled', null)}}
</div>
{{/if}}
@@ -0,0 +1,15 @@
import { NtosWindow } from '../layouts';
import { OvermapNavigationContent } from './OvermapNavigation';
export const NtosOvermapNavigation = () => {
return (
<NtosWindow
width={380}
height={530}
resizable>
<NtosWindow.Content scrollable>
<OvermapNavigationContent />
</NtosWindow.Content>
</NtosWindow>
);
};
@@ -0,0 +1,129 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, AnimatedNumber } from "../components";
import { Window } from "../layouts";
import { OvermapPanControls } from './common/Overmap';
export const OvermapDisperser = (props, context) => {
return (
<Window width={400} height={550} resizable>
<Window.Content>
<OvermapDisperserContent />
</Window.Content>
</Window>
);
};
const OvermapDisperserContent = (props, context) => {
const { act, data } = useBackend(context);
const {
faillink,
calibration,
overmapdir,
cal_accuracy,
strength,
range,
next_shot,
nopower,
skill,
chargeload,
} = data;
if (faillink) {
return (
<Section title="Error">
Machine is incomplete, out of range, or misaligned!
</Section>
);
}
return (
<Flex wrap="wrap" spacing={1}>
<Flex.Item basis="22%">
<Section title="Targeting" textAlign="center">
<OvermapPanControls actToDo="choose" selected={val => val === overmapdir} />
</Section>
</Flex.Item>
<Flex.Item basis="74%" grow={1}>
<Section title="Charge">
<LabeledList>
{nopower && (
<LabeledList.Item label="Error">
At least one part of the machine is unpowered.
</LabeledList.Item>
) || null}
<LabeledList.Item label="Charge Load Type">
{chargeload}
</LabeledList.Item>
<LabeledList.Item label="Cooldown">
{next_shot === 0 && (
<Box color="good">Ready</Box>
) || next_shot > 1 && (
<Box color="average">
<AnimatedNumber value={next_shot} /> Seconds
<Box color="bad">Warning: Do not fire during cooldown.</Box>
</Box>
) || null}
</LabeledList.Item>
</LabeledList>
</Section>
</Flex.Item>
<Flex.Item basis="50%" mt={1}>
<Section title="Calibration">
<AnimatedNumber value={cal_accuracy} />%
<Button
ml={1}
icon="exchange-alt"
onClick={() => act("skill_calibration")}>
Pre-Calibration
</Button>
<Box mt={1}>
{calibration.map((cal, i) => (
<Box key={i}>
Cal #{i}:
<Button
ml={1}
icon="random"
onClick={() => act("calibration", { calibration: i })}>
{cal.toString() /* We do this to make the button size correctly at 0 */}
</Button>
</Box>
))}
</Box>
</Section>
</Flex.Item>
<Flex.Item basis="45%" grow={1} mt={1}>
<Section title="Setup">
<LabeledList>
<LabeledList.Item label="Strength">
<Button
fluid
icon="fist-raised"
onClick={() => act("strength")}>
{strength}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Radius">
<Button
fluid
icon="expand-arrows-alt"
onClick={() => act("range")}>
{range}
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
</Flex.Item>
<Flex.Item grow={1} mt={1}>
<Button
fluid
color="red"
icon="bomb"
onClick={() => act("fire")}>
Fire ORB
</Button>
</Flex.Item>
</Flex>
);
};
@@ -0,0 +1,110 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, AnimatedNumber, Collapsible } from "../components";
import { Window } from "../layouts";
export const OvermapEngines = (props, context) => {
const { act, data } = useBackend(context);
const {
global_state, // This indicates all engines being powered up or not
global_limit, // Global Thrust limit
engines_info, // Array of engines
total_thrust, // Total thrust of all engines together
} = data;
return (
<Window width={390} height={530}>
<Window.Content>
<Section title="Status">
<LabeledList>
<LabeledList.Item label="Engines">
<Button
icon="power-off"
selected={global_state}
onClick={() => act("global_toggle")}>
{global_state ? "Shut All Engines Down" : "Start All Engines"}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Volume Limit">
<Button
onClick={() => act("global_limit", { global_limit: -0.1 })}
icon="minus" />
<Button onClick={() => act("set_global_limit")}>
{global_limit}%
</Button>
<Button
onClick={() => act("global_limit", { global_limit: 0.1 })}
icon="plus" />
</LabeledList.Item>
<LabeledList.Item label="Total Thrust">
<AnimatedNumber value={total_thrust} />
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Engines" height="340px" style={{ "overflow-y": "auto" }}>
{engines_info.map((engine, i) => (
<Flex spacing={1} mt={i !== 0 && -1} key={i}>
<Flex.Item basis="80%">
<Collapsible title={(
<Box inline>
Engine #{i + 1} |
Thrust: <AnimatedNumber value={engine.eng_thrust} /> |
Limit: <AnimatedNumber value={engine.eng_thrust_limiter} format={val => val + "%"} />
</Box>
// "Engine " + (i + 1)
// + " | Thrust: " + engine.eng_thrust
// + " | Limit: " + engine.eng_thrust_limiter + "%"
)}>
<Section width="127%">
<LabeledList>
<LabeledList.Item label="Type">
{engine.eng_type}
</LabeledList.Item>
<LabeledList.Item label="Status">
<Box color={engine.eng_on ? (engine.eng_on === 1 ? "good" : "average") : "bad"}>
{engine.eng_on ? (engine.eng_on === 1 ? "Online" : "Booting") : "Offline"}
</Box>
{engine.eng_status.map(status => {
if (Array.isArray(status)) {
return <Box color={status[1]}>{status[0]}</Box>;
} else {
return <Box>{status}</Box>;
}
})}
</LabeledList.Item>
<LabeledList.Item label="Current Thrust">
{engine.eng_thrust}
</LabeledList.Item>
<LabeledList.Item label="Volume Limit">
<Button
onClick={() => act("limit", { limit: -0.1, engine: engine.eng_reference })}
icon="minus" />
<Button onClick={() => act("set_limit", { engine: engine.eng_reference })}>
{engine.eng_thrust_limiter}%
</Button>
<Button
onClick={() => act("limit", { limit: 0.1, engine: engine.eng_reference })}
icon="plus" />
</LabeledList.Item>
</LabeledList>
</Section>
</Collapsible>
</Flex.Item>
<Flex.Item basis="20%">
<Button
fluid
iconSpin={engine.eng_on === -1}
color={engine.eng_on === -1 ? "purple" : null}
selected={engine.eng_on === 1}
icon="power-off"
onClick={() => act("toggle", { engine: engine.eng_reference })}>
{engine.eng_on ? (engine.eng_on === 1 ? "Shutoff" : "Booting") : "Startup"}
</Button>
</Flex.Item>
</Flex>
))}
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,235 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table } from "../components";
import { Window } from "../layouts";
import { OvermapFlightData, OvermapPanControls } from './common/Overmap';
export const OvermapHelm = (props, context) => {
const { act, data } = useBackend(context);
return (
<Window width={565} height={545} resizable>
<Window.Content>
<Flex>
<Flex.Item basis="40%" height="180px">
<OvermapFlightDataWrap />
</Flex.Item>
<Flex.Item basis="25%" height="180px">
<OvermapManualControl />
</Flex.Item>
<Flex.Item basis="35%" height="180px">
<OvermapAutopilot />
</Flex.Item>
</Flex>
<OvermapNavComputer />
</Window.Content>
</Window>
);
};
export const OvermapFlightDataWrap = (props, context) => {
const { act, data } = useBackend(context);
// While, yes, this is a strange choice to use fieldset over Section
// just look at how pretty the legend is, sticking partially through the border ;///;
return (
<fieldset style={{ height: "100%", border: "1px solid #4972a1", margin: 'none' }} className="Section">
<legend>Flight Data</legend>
<OvermapFlightData />
</fieldset>
);
};
const OvermapManualControl = (props, context) => {
const { act, data } = useBackend(context);
const {
canburn,
manual_control,
} = data;
return (
<fieldset style={{ height: "100%", border: "1px solid #4972a1" }} className="Section">
<legend>Manual Control</legend>
<Flex align="center" justify="center">
<Flex.Item>
<OvermapPanControls disabled={!canburn} actToDo="move" />
</Flex.Item>
</Flex>
<Box textAlign="center" mt={1}>
<Box bold underline>
Direct Control
</Box>
<Button
selected={manual_control}
onClick={() => act("manual")}
icon="compass">
{manual_control ? "Enabled" : "Disabled"}
</Button>
</Box>
</fieldset>
);
};
const OvermapAutopilot = (props, context) => {
const { act, data } = useBackend(context);
const {
dest,
d_x,
d_y,
speedlimit,
autopilot,
autopilot_disabled,
} = data;
if (autopilot_disabled) {
return (
<fieldset style={{ height: "100%", border: "1px solid #4972a1" }} className="Section">
<legend>Autopilot</legend>
<Box textAlign="center" color="bad" fontSize={1.2}>
AUTOPILOT DISABLED
</Box>
<Box textAlign="center" color="average">
Warning: This vessel is equipped with a class I autopilot.
Class I autopilots are unable to do anything but fly in a
straight line directly towards the target, and may result in
collisions.
</Box>
<Box textAlign="center">
<Button.Confirm
mt={1}
color="bad"
content="Unlock Autopilot"
confirmContent="ACCEPT RISKS?"
icon="exclamation-triangle"
confirmIcon="exclamation-triangle"
onClick={() => act("apilot_lock")} />
</Box>
</fieldset>
);
}
return (
<fieldset style={{ height: "100%", border: "1px solid #4972a1" }} className="Section">
<legend>Autopilot</legend>
<LabeledList>
<LabeledList.Item label="Target">
{dest && (
<Fragment>
<Button onClick={() => act("setcoord", { setx: true })}>
{d_x}
</Button>
<Button onClick={() => act("setcoord", { sety: true })}>
{d_y}
</Button>
</Fragment>
) || (
<Button icon="pen" onClick={() => act("setcoord", { setx: true, sety: true })}>
None
</Button>
)}
</LabeledList.Item>
<LabeledList.Item label="Speed Limit">
<Button
icon="tachometer-alt"
onClick={() => act("speedlimit")}>
{speedlimit} Gm/h
</Button>
</LabeledList.Item>
</LabeledList>
<Button
mt={1}
fluid
selected={autopilot}
disabled={!dest}
icon="robot"
onClick={() => act("apilot")}>
{autopilot ? "Engaged" : "Disengaged"}
</Button>
<Button
fluid
color="good"
icon="exclamation-triangle"
onClick={() => act("apilot_lock")}>
Lock Autopilot
</Button>
</fieldset>
);
};
const OvermapNavComputer = (props, context) => {
const { act, data } = useBackend(context);
const {
sector,
s_x,
s_y,
sector_info,
landed,
locations,
} = data;
return (
<Section title="Navigation Data" m={0.3} mt={1}>
<LabeledList>
<LabeledList.Item label="Location">
{sector}
</LabeledList.Item>
<LabeledList.Item label="Coordinates">
{s_x} : {s_y}
</LabeledList.Item>
<LabeledList.Item label="Scan Data">
{sector_info}
</LabeledList.Item>
<LabeledList.Item label="Status">
{landed}
</LabeledList.Item>
</LabeledList>
<Flex mt={1} align="center" justify="center" spacing={1}>
<Flex.Item basis="50%">
<Button
fluid
icon="save"
onClick={() => act("add", { add: "current" })}>
Save Current Position
</Button>
</Flex.Item>
<Flex.Item basis="50%">
<Button
fluid
icon="sticky-note"
onClick={() => act("add", { add: "new" })}>
Add New Entry
</Button>
</Flex.Item>
</Flex>
<Section mt={1} scrollable height="130px">
<Table>
<Table.Row header>
<Table.Cell>Name</Table.Cell>
<Table.Cell>Coordinates</Table.Cell>
<Table.Cell>Actions</Table.Cell>
</Table.Row>
{locations.map(loc => (
<Table.Row key={loc.name}>
<Table.Cell>{loc.name}</Table.Cell>
<Table.Cell>{loc.x} : {loc.y}</Table.Cell>
<Table.Cell collapsing>
<Button
icon="rocket"
onClick={() => act("setds", { x: loc.x, y: loc.y })}>
Plot Course
</Button>
<Button
icon="trash"
onClick={() => act("remove", { remove: loc.reference })}>
Remove
</Button>
</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
</Section>
);
};
@@ -0,0 +1,54 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
import { OvermapFlightData } from "./common/Overmap";
export const OvermapNavigation = (props, context) => {
return (
<Window width={380} height={530} resizable>
<Window.Content>
<OvermapNavigationContent />
</Window.Content>
</Window>
);
};
export const OvermapNavigationContent = (props, context) => {
const { act, data } = useBackend(context);
const {
sector,
s_x,
s_y,
sector_info,
viewing,
} = data;
return (
<Fragment>
<Section title="Current Location" buttons={
<Button
icon="eye"
selected={viewing}
onClick={() => act("viewing")}>
Map View
</Button>
}>
<LabeledList>
<LabeledList.Item label="Current Location">
{sector}
</LabeledList.Item>
<LabeledList.Item label="Coordiantes">
{s_x} : {s_y}
</LabeledList.Item>
<LabeledList.Item label="Additional Information">
{sector_info}
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Flight Data">
<OvermapFlightData disableLimiterControls />
</Section>
</Fragment>
);
};
@@ -0,0 +1,212 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, AnimatedNumber } from "../components";
import { Window } from "../layouts";
export const OvermapShieldGenerator = (props, context) => {
return (
<Window width={500} height={800} resizable>
<Window.Content scrollable>
<OvermapShieldGeneratorContent />
</Window.Content>
</Window>
);
};
const OvermapShieldGeneratorContent = (props, context) => {
const { act, data } = useBackend(context);
const {
modes,
offline_for,
} = data;
if (offline_for) {
return (
<Section title="EMERGENCY SHUTDOWN" color="bad">
An emergency shutdown has been initiated - generator cooling down.
Please wait until the generator cools down before resuming operation.
Estimated time left: {offline_for} seconds.
</Section>
);
}
return (
<Fragment>
<OvermapShieldGeneratorStatus />
<OvermapShieldGeneratorControls />
<Section title="Field Calibration">
{modes.map(mode => (
<Section title={mode.name} level={2} key={mode.name} buttons={
<Button
icon="power-off"
selected={mode.status}
onClick={() => act("toggle_mode", { toggle_mode: mode.flag })}>
{mode.status ? "Enabled" : "Disabled"}
</Button>
}>
<Box color="label">
{mode.desc}
</Box>
<Box mt={0.5}>
Multiplier: {mode.multiplier}
</Box>
</Section>
))}
</Section>
</Fragment>
);
};
const OvermapShieldGeneratorStatus = (props, context) => {
const { act, data } = useBackend(context);
const {
running,
overloaded,
mitigation_max,
mitigation_physical,
mitigation_em,
mitigation_heat,
field_integrity,
max_energy,
current_energy,
percentage_energy,
total_segments,
functional_segments,
field_radius,
target_radius,
input_cap_kw,
upkeep_power_usage,
power_usage,
spinup_counter,
} = data;
return (
<Section title="System Status">
<LabeledList>
<LabeledList.Item label="Generator is">
{running === 1 && (
<Box color="average">Shutting Down</Box>
) || running === 2 && (
overloaded && (
<Box color="bad">Overloaded</Box>
) || (
<Box color="good">Running</Box>
)
) || running === 3 && (
<Box color="average">Inactive</Box>
) || running === 4 && (
<Box color="blue">
Spinning Up&nbsp;
{target_radius !== field_radius && (
<Box inline>(Adjusting Radius)</Box>
) || (
<Box inline>{spinup_counter * 2}s</Box>
)}
</Box>
) || (
<Box color="bad">
Offline
</Box>
)}
</LabeledList.Item>
<LabeledList.Item label="Energy Storage">
<ProgressBar
value={current_energy}
maxValue={max_energy}>
{current_energy} / {max_energy} MJ ({percentage_energy}%)
</ProgressBar>
</LabeledList.Item>
<LabeledList.Item label="Shield Integrity">
<AnimatedNumber value={field_integrity} />%
</LabeledList.Item>
<LabeledList.Item label="Mitigation">
{mitigation_em}% EM / {mitigation_physical}% PH / {mitigation_heat}% HE / {mitigation_max}% MAX
</LabeledList.Item>
<LabeledList.Item label="Upkeep Energy Use">
<AnimatedNumber value={upkeep_power_usage} /> kW
</LabeledList.Item>
<LabeledList.Item label="Total Energy Use">
{input_cap_kw && (
<Box>
<ProgressBar
value={power_usage}
maxValue={input_cap_kw}>
{power_usage} / {input_cap_kw} kW
</ProgressBar>
</Box>
) || (
<Box>
<AnimatedNumber value={power_usage} /> kW (No Limit)
</Box>
)}
</LabeledList.Item>
<LabeledList.Item label="Field Size">
<AnimatedNumber value={functional_segments} />&nbsp;/&nbsp;
<AnimatedNumber value={total_segments} /> m&sup2;
(radius <AnimatedNumber value={field_radius} />, target <AnimatedNumber value={target_radius} />)
</LabeledList.Item>
</LabeledList>
</Section>
);
};
const OvermapShieldGeneratorControls = (props, context) => {
const { act, data } = useBackend(context);
const {
running,
hacked,
idle_multiplier,
idle_valid_values,
} = data;
return (
<Section title="Controls" buttons={
<Fragment>
{running >= 2 && (
<Box>
<Button icon="power-off" onClick={() => act("begin_shutdown")} selected>Turn off</Button>
{running === 3 && (
<Button icon="power-off" onClick={() => act("toggle_idle", { toggle_idle: 0 })}>Activate</Button>
) || (
<Button icon="power-off" onClick={() => act("toggle_idle", { toggle_idle: 1 })} selected>
Deactivate
</Button>
)}
</Box>
) || (
<Button icon="power-off" onClick={() => act("start_generator")}>Turn on</Button>
)}
{running && hacked && (
<Button icon="exclamation-triangle" onClick={() => act("emergency_shutdown")} color="bad">
EMERGENCY SHUTDOWN
</Button>
) || null}
</Fragment>
}>
<Button
icon="expand-arrows-alt"
onClick={() => act("set_range")}>
Set Field Range
</Button>
<Button
icon="bolt"
onClick={() => act("set_input_cap")}>
Set Input Cap
</Button>
<LabeledList>
<LabeledList.Item label="Set inactive power use intensity">
{idle_valid_values.map(val => (
<Button
key={val}
selected={val === idle_multiplier}
disabled={running === 4}
onClick={() => act("switch_idle", { switch_idle: val })}>
{val}
</Button>
))}
</LabeledList.Item>
</LabeledList>
</Section>
);
};
@@ -0,0 +1,111 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
export const OvermapShipSensors = (props, context) => {
const { act, data } = useBackend(context);
const {
viewing,
on,
range,
health,
max_health,
heat,
critical_heat,
status,
contacts,
} = data;
return (
<Window width={375} height={545} resizable>
<Window.Content>
<Section title="Status" buttons={(
<Fragment>
<Button
icon="eye"
selected={viewing}
onClick={() => act("viewing")}>
Map View
</Button>
<Button
icon="power-off"
selected={on}
onClick={() => act("toggle")}>
{on ? "Sensors Enabled" : "Sensors Disabled"}
</Button>
</Fragment>
)}>
<LabeledList>
<LabeledList.Item label="Status">
{status}
</LabeledList.Item>
<LabeledList.Item label="Range">
<Button
icon="signal"
onClick={() => act("range")}>
{range}
</Button>
</LabeledList.Item>
<LabeledList.Item label="Integrity">
<ProgressBar
ranges={{
good: [max_health * 0.75, Infinity],
average: [max_health * 0.25, max_health * 0.75],
bad: [-Infinity, max_health * 0.25],
}}
value={health}
maxValue={max_health}>
{health} / {max_health}
</ProgressBar>
</LabeledList.Item>
<LabeledList.Item label="Temperature">
<ProgressBar
ranges={{
bad: [critical_heat * 0.75, Infinity],
average: [critical_heat * 0.5, critical_heat * 0.75],
good: [-Infinity, critical_heat * 0.5],
}}
value={heat}
maxValue={critical_heat}>
{heat < critical_heat * 0.5 && (
<Box>Temperature low.</Box>
) || heat < critical_heat * 0.75 && (
<Box>Sensor temperature high!</Box>
) || (
<Box>TEMPERATURE CRITICAL: Disable or reduce power immediately!</Box>
)}
</ProgressBar>
</LabeledList.Item>
</LabeledList>
</Section>
<Section title="Contacts">
{contacts.length && contacts.map(alien => (
<Button
key={alien.ref}
fluid
icon="search"
onClick={() => act("scan", { scan: alien.ref })}>
<Box bold inline>Scan: {alien.name}</Box>
<Box inline>, bearing: {alien.bearing}&deg;</Box>
</Button>
)) || (
<Box color="average">
No contacts on sensors.
</Box>
)}
</Section>
{data.status === "MISSING" && (
<Section title="Error">
<Button
icon="wifi"
onClick={() => act("link")}>
Link up with sensor suite?
</Button>
</Section>
) || null}
</Window.Content>
</Window>
);
};
@@ -0,0 +1,47 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, AnimatedNumber } from "../components";
import { Window } from "../layouts";
export const PointDefenseControl = (props, context) => {
const { act, data } = useBackend(context);
const {
id,
turrets,
} = data;
return (
<Window width={400} height={600}>
<Window.Content scrollable>
<Section title={"Fire Assist Mainframe: " + (id || "[no tag]")}>
{turrets.length && turrets.map(pd => (
<Section level={2} title={pd.id} key={pd.id} buttons={
<Button
selected={pd.active}
icon="power-off"
onClick={() => act("toggle_active", { target: pd.ref })}>
{pd.active ? "Online" : "Offline"}
</Button>
}>
<LabeledList>
<LabeledList.Item label="Effective range">
{pd.effective_range}
</LabeledList.Item>
<LabeledList.Item label="Reaction wheel delay">
{pd.reaction_wheel_delay}
</LabeledList.Item>
<LabeledList.Item label="Recharge time">
{pd.recharge_time}
</LabeledList.Item>
</LabeledList>
</Section>
)) || (
<Box color="bad">
Error: No weapon systems detected. Please check network connection.
</Box>
)}
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,117 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table } from "../../components";
export const OvermapFlightData = (props, context) => {
const { act, data } = useBackend(context);
const {
disableLimiterControls,
} = props;
const {
ETAnext,
speed,
speed_color,
accel,
heading,
accellimit,
} = data;
// While, yes, this is a strange choice to use fieldset over Section
// just look at how pretty the legend is, sticking partially through the border ;///;
return (
<LabeledList>
<LabeledList.Item label="ETA To Next Grid">
{ETAnext}
</LabeledList.Item>
<LabeledList.Item label="Speed" color={speed_color}>
{speed} Gm/h
</LabeledList.Item>
<LabeledList.Item label="Acceleration">
{accel} Gm/h
</LabeledList.Item>
<LabeledList.Item label="Heading">
{heading}&deg;
</LabeledList.Item>
{!disableLimiterControls && (
<LabeledList.Item label="Acceleration Limiter">
<Button onClick={() => act("accellimit")}>
{accellimit} Gm/h
</Button>
</LabeledList.Item>
) || null}
</LabeledList>
);
};
export const OvermapPanControls = (props, context) => {
const { act } = useBackend(context);
const {
disabled,
actToDo,
selected = val => false,
} = props;
return (
<Fragment>
<Box>
<Button
disabled={disabled}
selected={selected(9)}
onClick={() => act(actToDo, { dir: 9 })}
icon="arrow-up"
iconRotation={-45} />
<Button
disabled={disabled}
selected={selected(1)}
onClick={() => act(actToDo, { dir: 1 })}
icon="arrow-up" />
<Button
disabled={disabled}
selected={selected(5)}
onClick={() => act(actToDo, { dir: 5 })}
icon="arrow-up"
iconRotation={45} />
</Box>
<Box>
<Button
disabled={disabled}
selected={selected(8)}
onClick={() => act(actToDo, { dir: 8 })}
icon="arrow-left" />
<Button
disabled={disabled}
selected={selected(0)}
onClick={() => act("brake")}
icon="ban" />
<Button
disabled={disabled}
selected={selected(4)}
onClick={() => act(actToDo, { dir: 4 })}
icon="arrow-right" />
</Box>
<Box>
<Button
disabled={disabled}
selected={selected(10)}
onClick={() => act(actToDo, { dir: 10 })}
icon="arrow-down"
iconRotation={45} />
<Button
disabled={disabled}
selected={selected(2)}
onClick={() => act(actToDo, { dir: 2 })}
icon="arrow-down" />
<Button
disabled={disabled}
selected={selected(6)}
onClick={() => act(actToDo, { dir: 6 })}
icon="arrow-down"
iconRotation={-45} />
</Box>
</Fragment>
);
};
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -2901,7 +2901,6 @@
#include "code\modules\modular_computers\file_system\programs\security\alarm_monitor.dm"
#include "code\modules\modular_computers\file_system\programs\security\digitalwarrant.dm"
#include "code\modules\modular_computers\file_system\programs\ships\navigation.dm"
#include "code\modules\modular_computers\file_system\programs\ships\ship.dm"
#include "code\modules\modular_computers\hardware\_hardware.dm"
#include "code\modules\modular_computers\hardware\battery_module.dm"
#include "code\modules\modular_computers\hardware\card_slot.dm"
@@ -3497,6 +3496,7 @@
#include "code\modules\tgui\modules\atmos_control.dm"
#include "code\modules\tgui\modules\camera.dm"
#include "code\modules\tgui\modules\crew_monitor.dm"
#include "code\modules\tgui\modules\overmap.dm"
#include "code\modules\tgui\modules\power_monitor.dm"
#include "code\modules\tgui\modules\rcon.dm"
#include "code\modules\tgui\modules\shutoff_monitor.dm"