From b6ed599741b71b874bc4eba06b2429c41bae5295 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Sat, 6 Jan 2024 06:28:51 -0800 Subject: [PATCH] Polish Dropship Weapons UI (#5298) # About the pull request This PR is a follow up to #4812 polishing minor issues that were discovered but not addressed in that PR. - Fire missions can now be scrolled in target acquisition - The target selection in equipment view is now the same as other panels (and can be scrolled now too) - Fixed deploying equipment like the spotlight and sentry - ~~Partially~~ fixed camera view for sentry ~~(map size doesn't always get set correctly some reason)~~ - Fixed the extra scrolling of fire missions - Fixed the scrolling of target selection being a fixed quantity of 10 targets - Improved menuing for the fire mission and strike sub menus - Fixed strike ready messaging - Map and Cam buttons are now mutually exclusive to one another (would just break the byond UI) - Camera now resets when a CAS flare is destroyed (unless fire mission is underway) - Camera now resets when sentry undeploys (if it was being used) - Tweaked some button placements - Fixed medevac layout - Fixed direct fire (strike & equipment) - Fixed camera views not handling /datum/component/overlay_lighting correctly (fixed by using TILE_BOUND planes; but will note it won't work completely correct if on a byond version prior to 515.1609 because of https://www.byond.com/forum/post/2873835) - Fixed some hard deletes in `/client/proc/clear_map` based on https://github.com/tgstation/tgstation/pull/61562 - Renamed nvgon and nvgoff to NV-ON and NV-OFF # Explain why it's good for the game Fixes issues such as (but not limited to): ![target](https://github.com/cmss13-devs/cmss13/assets/76988376/7e1b8389-d466-4ef0-a436-a91c19c53c60) ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/5c291ca5-204a-49c3-b281-32b7f4fc530a) # Testing Photographs and Procedure
Screenshots & Videos ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/f8db9791-5c8d-4dc2-90bb-7a8b91f6fde9) ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/c1a659af-8d05-408f-89e8-c95597cfc79a) ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/858c307c-1914-48dc-98ed-5fba6c2429e0) ![light](https://github.com/cmss13-devs/cmss13/assets/76988376/755c270f-5269-473f-897f-354bba3a5353)
# Changelog :cl: Drathek ui: Polished various aspects of the new dropship weapons UI fix: Fixed CAS direct firing fix: Fixed Medevac buttons not moving the dropship (still currently requires manual winch) fix: Fixed camera_manager resizing the view incorrectly because of overlay_lighting refactor: Ported some hard delete fixes for maps. /:cl: --- code/_onclick/hud/map_popups.dm | 3 +- code/game/camera_manager/camera_manager.dm | 26 +-- .../cas_manager/datums/cas_fire_envelope.dm | 22 ++- .../game/machinery/computer/camera_console.dm | 3 +- .../machinery/computer/dropship_weapons.dm | 79 +++++---- code/modules/cm_marines/dropship_equipment.dm | 25 +-- .../interfaces/DropshipWeaponsConsole.tsx | 22 ++- .../tgui/interfaces/MfdPanels/CameraPanel.tsx | 6 +- .../interfaces/MfdPanels/EquipmentPanel.tsx | 10 -- .../interfaces/MfdPanels/FiremissionPanel.tsx | 24 +-- .../tgui/interfaces/MfdPanels/FultonPanel.tsx | 5 +- .../tgui/interfaces/MfdPanels/MGPanel.tsx | 5 +- .../interfaces/MfdPanels/MedevacPanel.tsx | 13 +- .../MfdPanels/MultifunctionDisplay.tsx | 1 + .../tgui/interfaces/MfdPanels/SentryPanel.tsx | 3 +- .../interfaces/MfdPanels/SpotlightPanel.tsx | 5 +- .../interfaces/MfdPanels/SupportPanel.tsx | 3 + .../interfaces/MfdPanels/TargetAquisition.tsx | 160 +++++++++++++----- .../tgui/interfaces/MfdPanels/WeaponPanel.tsx | 149 +++++++++------- .../interfaces/MfdPanels/stateManagers.ts | 11 ++ .../tgui/interfaces/MfdPanels/types.ts | 2 +- 21 files changed, 365 insertions(+), 212 deletions(-) diff --git a/code/_onclick/hud/map_popups.dm b/code/_onclick/hud/map_popups.dm index aed6b46a7905..26dc93bbff2b 100644 --- a/code/_onclick/hud/map_popups.dm +++ b/code/_onclick/hud/map_popups.dm @@ -118,10 +118,11 @@ * anyway. they're effectively qdel'd. */ /client/proc/clear_map(map_name) - if(!map_name || !(map_name in screen_maps)) + if(!map_name || !screen_maps[map_name]) return FALSE for(var/atom/movable/screen/screen_obj in screen_maps[map_name]) screen_maps[map_name] -= screen_obj + remove_from_screen(screen_obj) if(screen_obj.del_on_map_removal) qdel(screen_obj) screen_maps -= map_name diff --git a/code/game/camera_manager/camera_manager.dm b/code/game/camera_manager/camera_manager.dm index 93d56aca443c..450c7c8beb64 100644 --- a/code/game/camera_manager/camera_manager.dm +++ b/code/game/camera_manager/camera_manager.dm @@ -25,13 +25,16 @@ . = ..() map_name = "camera_manager_[REF(src)]_map" cam_screen = new + cam_screen.icon = null cam_screen.name = "screen" cam_screen.assigned_map = map_name cam_screen.del_on_map_removal = FALSE cam_screen.screen_loc = "[map_name]:1,1" + cam_screen.appearance_flags |= TILE_BOUND cam_background = new cam_background.assigned_map = map_name cam_background.del_on_map_removal = FALSE + cam_background.appearance_flags |= TILE_BOUND cam_plane_masters = list() for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness) @@ -42,14 +45,17 @@ . = ..() range_turfs = null current_area = null - cam_plane_masters = null + QDEL_LIST_ASSOC_VAL(cam_plane_masters) QDEL_NULL(cam_background) QDEL_NULL(cam_screen) if(current) UnregisterSignal(current, COMSIG_PARENT_QDELETING) + current = null + last_camera_turf = null /datum/component/camera_manager/proc/add_plane(atom/movable/screen/plane_master/instance) instance.assigned_map = map_name + instance.appearance_flags |= TILE_BOUND instance.del_on_map_removal = FALSE if(instance.blend_mode_override) instance.blend_mode = instance.blend_mode_override @@ -61,8 +67,8 @@ var/client/user_client = user.client if(!user_client) return - user_client.register_map_obj(cam_background) user_client.register_map_obj(cam_screen) + user_client.register_map_obj(cam_background) for(var/plane_id in cam_plane_masters) user_client.register_map_obj(cam_plane_masters[plane_id]) @@ -71,14 +77,10 @@ var/client/user_client = user.client if(!user_client) return - user_client.clear_map(cam_background) - user_client.clear_map(cam_screen) - for(var/plane_id in cam_plane_masters) - user_client.clear_map(cam_plane_masters[plane_id]) + user_client.clear_map(map_name) /datum/component/camera_manager/RegisterWithParent() . = ..() - START_PROCESSING(SSdcs, src) SEND_SIGNAL(parent, COMSIG_CAMERA_MAPNAME_ASSIGNED, map_name) RegisterSignal(parent, COMSIG_CAMERA_REGISTER_UI, PROC_REF(register)) RegisterSignal(parent, COMSIG_CAMERA_UNREGISTER_UI, PROC_REF(unregister)) @@ -90,8 +92,6 @@ /datum/component/camera_manager/UnregisterFromParent() . = ..() - STOP_PROCESSING(SSdcs, src) - UnregisterSignal(parent, COMSIG_CAMERA_REGISTER_UI) UnregisterSignal(parent, COMSIG_CAMERA_UNREGISTER_UI) UnregisterSignal(parent, COMSIG_CAMERA_SET_NVG) @@ -134,6 +134,8 @@ target_x = x target_y = y target_z = z + target_width = w + target_height = h update_area_camera() /datum/component/camera_manager/proc/enable_nvg(source, power, matrixcol) @@ -152,10 +154,10 @@ /datum/component/camera_manager/proc/sync_lighting_plane_alpha(lighting_alpha) var/atom/movable/screen/plane_master/lighting/lighting = cam_plane_masters["[LIGHTING_PLANE]"] - if (lighting) + if(lighting) lighting.alpha = lighting_alpha var/atom/movable/screen/plane_master/lighting/exterior_lighting = cam_plane_masters["[EXTERIOR_LIGHTING_PLANE]"] - if (exterior_lighting) + if(exterior_lighting) exterior_lighting.alpha = min(GLOB.minimum_exterior_lighting_alpha, lighting_alpha) /** @@ -215,7 +217,7 @@ var/turf/target = locate(current_area.center_x, current_area.center_y, target_z) var/list/visible_things = isXRay ? range("[x_size]x[y_size]", target) : view("[x_size]x[y_size]", target) - src.render_objects(visible_things) + render_objects(visible_things) /datum/component/camera_manager/proc/render_objects(list/visible_things) var/list/visible_turfs = list() diff --git a/code/game/cas_manager/datums/cas_fire_envelope.dm b/code/game/cas_manager/datums/cas_fire_envelope.dm index 04cd688194dd..d9355cd005a9 100644 --- a/code/game/cas_manager/datums/cas_fire_envelope.dm +++ b/code/game/cas_manager/datums/cas_fire_envelope.dm @@ -19,7 +19,7 @@ var/datum/cas_signal/recorded_loc = null var/obj/effect/firemission_guidance/guidance - + var/atom/tracked_object /datum/cas_fire_envelope/New() ..() @@ -27,6 +27,7 @@ /datum/cas_fire_envelope/Destroy(force, ...) linked_console = null + untrack_object() return ..() /datum/cas_fire_envelope/ui_data(mob/user) @@ -151,7 +152,9 @@ recorded_loc = marker return TRUE -/datum/cas_fire_envelope/proc/change_current_loc(location) +/datum/cas_fire_envelope/proc/change_current_loc(location, atom/object) + if(object) + untrack_object() if(!location && guidance) for(var/mob/M in guidance.users) if(istype(M) && M.client) @@ -162,6 +165,21 @@ guidance = new /obj/effect/firemission_guidance() guidance.forceMove(location) guidance.updateCameras(linked_console) + if(object) + tracked_object = object + RegisterSignal(tracked_object, COMSIG_PARENT_QDELETING, PROC_REF(on_tracked_object_del)) + +/// Call to unregister the on_tracked_object_del behavior +/datum/cas_fire_envelope/proc/untrack_object() + if(tracked_object) + UnregisterSignal(tracked_object, COMSIG_PARENT_QDELETING) + tracked_object = null + +/// Signal handler for when we are viewing a object in cam is qdel'd (but camera actually is actually some other obj) +/datum/cas_fire_envelope/proc/on_tracked_object_del(atom/target) + SIGNAL_HANDLER + tracked_object = null + change_current_loc() /datum/cas_fire_envelope/proc/user_is_guided(user) return guidance && (user in guidance.users) diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index 1a00e194b5eb..d7dbfb9717cc 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -58,9 +58,8 @@ SStgui.close_uis(src) QDEL_NULL(current) QDEL_NULL(cam_screen) - qdel(cam_screen) QDEL_NULL(cam_background) - qdel(cam_background) + QDEL_NULL_LIST(cam_plane_masters) last_camera_turf = null concurrent_users = null return ..() diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index db376c40029c..dce026f4ce33 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -33,6 +33,8 @@ var/camera_width = 11 var/camera_height = 11 var/camera_map_name + ///Tracks equipment with a camera that is deployed and we are viewing + var/obj/structure/dropship_equipment/camera_area_equipment = null var/registered = FALSE @@ -62,17 +64,20 @@ /obj/structure/machinery/computer/dropship_weapons/attack_hand(mob/user) if(..()) return - if(!allowed(user)) + if(!allowed(user)) + // TODO: Restore cas simulator + to_chat(user, SPAN_WARNING("Weapons modification access denied.")) + return TRUE // everyone can access the simulator, requested feature. - to_chat(user, SPAN_WARNING("Weapons modification access denied, attempting to launch simulation.")) + /*to_chat(user, SPAN_WARNING("Weapons modification access denied, attempting to launch simulation.")) if(!selected_firemission) to_chat(user, SPAN_WARNING("Firemission must be selected before attempting to run the simulation")) - return + return TRUE tgui_interact(user) - return 1 + return FALSE*/ user.set_interaction(src) ui_interact(user) @@ -100,7 +105,7 @@ /obj/structure/machinery/computer/dropship_weapons/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0) var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag) - if (!istype(dropship)) + if(!istype(dropship)) return var/screen_mode = 0 @@ -129,11 +134,6 @@ if(screen_mode != 3 || !selected_firemission || dropship.mode != SHUTTLE_CALL) update_location(user, null) - ui_data(user) - if(!tacmap.map_holder) - var/level = SSmapping.levels_by_trait(tacmap.targeted_ztrait) - tacmap.map_holder = SSminimaps.fetch_tacmap_datum(level[1], tacmap.allowed_flags) - user.client.register_map_obj(tacmap.map_holder.map) tgui_interact(user) /obj/structure/machinery/computer/dropship_weapons/tgui_interact(mob/user, datum/tgui/ui) @@ -141,10 +141,15 @@ var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag) RegisterSignal(dropship, COMSIG_DROPSHIP_ADD_EQUIPMENT, PROC_REF(equipment_update)) RegisterSignal(dropship, COMSIG_DROPSHIP_REMOVE_EQUIPMENT, PROC_REF(equipment_update)) - registered=TRUE + registered = TRUE + + if(!tacmap.map_holder) + var/level = SSmapping.levels_by_trait(tacmap.targeted_ztrait) + tacmap.map_holder = SSminimaps.fetch_tacmap_datum(level[1], tacmap.allowed_flags) ui = SStgui.try_update_ui(user, src, ui) - if (!ui) + if(!ui) + user.client.register_map_obj(tacmap.map_holder.map) SEND_SIGNAL(src, COMSIG_CAMERA_REGISTER_UI, user) ui = new(user, src, "DropshipWeaponsConsole", "Weapons Console") ui.open() @@ -255,7 +260,7 @@ switch(action) if("button_push") playsound(src, get_sfx("terminal_button"), 25, FALSE) - return TRUE + return FALSE if("select_equipment") var/base_tag = params["equipment_id"] @@ -303,12 +308,13 @@ var/mount_point = equipment.ship_base.attach_id if(mount_point != equipment_tag) continue - if (istype(equipment, /obj/structure/dropship_equipment/sentry_holder)) + if(istype(equipment, /obj/structure/dropship_equipment/sentry_holder)) var/obj/structure/dropship_equipment/sentry_holder/sentry = equipment var/obj/structure/machinery/defenses/sentry/defense = sentry.deployed_turret - if (defense.has_camera) + if(defense.has_camera) defense.set_range() var/datum/shape/rectangle/current_bb = defense.range_bounds + camera_area_equipment = sentry SEND_SIGNAL(src, COMSIG_CAMERA_SET_AREA, current_bb.center_x, current_bb.center_y, defense.loc.z, current_bb.width, current_bb.height) return TRUE @@ -329,6 +335,7 @@ if(medevac.linked_stretcher) SEND_SIGNAL(src, COMSIG_CAMERA_SET_TARGET, medevac.linked_stretcher, 5, 5) return TRUE + if("fulton-target") var/equipment_tag = params["equipment_id"] for(var/obj/structure/dropship_equipment/equipment as anything in shuttle.equipments) @@ -340,6 +347,7 @@ var/target_ref = params["ref"] fulton.automate_interact(user, target_ref) return TRUE + if("fire-weapon") var/weapon_tag = params["eqp_tag"] var/obj/structure/dropship_equipment/weapon/DEW = get_weapon(weapon_tag) @@ -347,19 +355,23 @@ return FALSE var/datum/cas_signal/sig = get_cas_signal(camera_target_id) - if(!sig) return FALSE selected_equipment = DEW - ui_open_fire(user, shuttle, camera_target_id) + if(ui_open_fire(user, shuttle, camera_target_id)) + if(firemission_envelope) + firemission_envelope.untrack_object() return TRUE + if("deploy-equipment") var/equipment_tag = params["equipment_id"] for(var/obj/structure/dropship_equipment/equipment as anything in shuttle.equipments) var/mount_point = equipment.ship_base.attach_id if(mount_point != equipment_tag) continue + if(camera_area_equipment == equipment) + set_camera_target(null) equipment.equipment_interact(user) return TRUE @@ -384,13 +396,8 @@ var/x_offset_value = params["x_offset_value"] var/y_offset_value = params["y_offset_value"] - var/datum/cas_iff_group/cas_group = GLOB.cas_groups[faction] - var/datum/cas_signal/cas_sig - for(var/X in cas_group.cas_signals) - var/datum/cas_signal/LT = X - if(LT.target_id == target_id && LT.valid_signal()) - cas_sig = LT - break + camera_target_id = target_id + var/datum/cas_signal/cas_sig = get_cas_signal(camera_target_id, valid_only = TRUE) // we don't want rapid offset changes to trigger admin warnings // and block the user from accessing TGUI // we change the minute_count @@ -408,12 +415,14 @@ current.y + dy, current.z) - firemission_envelope.change_current_loc(new_target) - + camera_area_equipment = null + firemission_envelope.change_current_loc(new_target, cas_sig) return TRUE + if("nvg-enable") SEND_SIGNAL(src, COMSIG_CAMERA_SET_NVG, 5, "#7aff7a") return TRUE + if("nvg-disable") SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR_NVG) return TRUE @@ -447,24 +456,28 @@ /obj/structure/machinery/computer/dropship_weapons/proc/get_weapon(eqp_tag) var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag) - for(var/obj/structure/dropship_equipment/equipment in dropship.equipments) - if(istype(equipment, /obj/structure/dropship_equipment/weapon)) - //is weapon - if(selected_equipment == equipment) - return equipment + var/obj/structure/dropship_equipment/equipment = dropship.equipments[eqp_tag] + if(istype(equipment, /obj/structure/dropship_equipment/weapon)) + //is weapon + return equipment return -/obj/structure/machinery/computer/dropship_weapons/proc/get_cas_signal(target_ref) +/obj/structure/machinery/computer/dropship_weapons/proc/get_cas_signal(target_ref, valid_only = FALSE) if(!target_ref) return var/datum/cas_iff_group/cas_group = GLOB.cas_groups[faction] for(var/datum/cas_signal/sig in cas_group.cas_signals) if(sig.target_id == target_ref) + if(valid_only && !sig.valid_signal()) + continue return sig - /obj/structure/machinery/computer/dropship_weapons/proc/set_camera_target(target_ref) + camera_area_equipment = null + if(firemission_envelope) + firemission_envelope.untrack_object() + var/datum/cas_signal/target = get_cas_signal(target_ref) camera_target_id = target_ref if(!target) diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index 59aa1428e23e..785283541eb8 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -332,11 +332,11 @@ /obj/structure/dropship_equipment/mg_holder/ui_data(mob/user) . = list() - var/is_deployed = deployed_mg.loc == src + var/is_deployed = deployed_mg.loc != src .["name"] = name .["selection_state"] = list() .["health"] = health - .["health_max"] = 100 + .["health_max"] = initial(health) .["rounds"] = deployed_mg.rounds .["max_rounds"] = deployed_mg.rounds_max .["deployed"] = is_deployed @@ -486,8 +486,6 @@ point_cost = 0 -#define LIGHTING_MAX_LUMINOSITY_SHIPLIGHTS 12 - /obj/structure/dropship_equipment/electronics/spotlights name = "\improper AN/LEN-15 Spotlight" shorthand = "Spotlight" @@ -502,7 +500,7 @@ if(spotlights_cooldown > world.time) to_chat(user, SPAN_WARNING("[src] is busy.")) return //prevents spamming deployment/undeployment - if(luminosity != brightness) + if(!light_on) set_light(brightness) icon_state = "spotlights_on" to_chat(user, SPAN_NOTICE("You turn on [src].")) @@ -515,13 +513,13 @@ /obj/structure/dropship_equipment/electronics/spotlights/update_equipment() ..() if(ship_base) - if(luminosity != brightness) + if(!light_on) icon_state = "spotlights_off" else icon_state = "spotlights_on" else icon_state = "spotlights" - if(luminosity) + if(light_on) set_light(0) /obj/structure/dropship_equipment/electronics/spotlights/on_launch() @@ -530,7 +528,13 @@ /obj/structure/dropship_equipment/electronics/spotlights/on_arrival() set_light(brightness) -#undef LIGHTING_MAX_LUMINOSITY_SHIPLIGHTS +/obj/structure/dropship_equipment/electronics/spotlights/ui_data(mob/user) + . = list() + var/is_deployed = light_on + .["name"] = name + .["health"] = health + .["health_max"] = initial(health) + .["deployed"] = is_deployed @@ -887,7 +891,8 @@ if (evaccee_triagecard_color && evaccee_triagecard_color == "none") evaccee_triagecard_color = null - .["[evaccee_name] [evaccee_triagecard_color ? "\[" + uppertext(evaccee_triagecard_color) + "\]" : ""] ([AR.name])"] = MS + var/key_name = strip_improper("[evaccee_name] [evaccee_triagecard_color ? "\[" + uppertext(evaccee_triagecard_color) + "\]" : ""] ([AR.name])") + .[key_name] = MS /obj/structure/dropship_equipment/medevac_system/proc/can_medevac(mob/user) if(!linked_shuttle) @@ -907,7 +912,7 @@ var/list/possible_stretchers = get_targets() - if(!possible_stretchers.len) + if(!length(possible_stretchers)) to_chat(user, SPAN_WARNING("No active medevac stretcher detected.")) return FALSE return TRUE diff --git a/tgui/packages/tgui/interfaces/DropshipWeaponsConsole.tsx b/tgui/packages/tgui/interfaces/DropshipWeaponsConsole.tsx index 629191b3ba70..feb27a9d57c3 100644 --- a/tgui/packages/tgui/interfaces/DropshipWeaponsConsole.tsx +++ b/tgui/packages/tgui/interfaces/DropshipWeaponsConsole.tsx @@ -11,6 +11,7 @@ import { SupportMfdPanel } from './MfdPanels/SupportPanel'; import { FiremissionMfdPanel } from './MfdPanels/FiremissionPanel'; import { TargetAquisitionMfdPanel } from './MfdPanels/TargetAquisition'; import { mfdState } from './MfdPanels/stateManagers'; +import { otherMfdState } from './MfdPanels/stateManagers'; import { Dpad } from './common/Dpad'; export interface DropshipProps { @@ -271,6 +272,7 @@ const WeaponsMfdPanel = (props, context) => { const BaseMfdPanel = (props: MfdProps, context) => { const { setPanelState } = mfdState(context, props.panelStateId); + const { otherPanelState } = otherMfdState(context, props.otherPanelStateId); return ( { ]} bottomButtons={[ {}, - { children: 'MAPS', onClick: () => setPanelState('map') }, - { children: 'CAMS', onClick: () => setPanelState('camera') }, + { + children: otherPanelState !== 'map' ? 'MAPS' : undefined, + onClick: () => setPanelState('map'), + }, + { + children: otherPanelState !== 'camera' ? 'CAMS' : undefined, + onClick: () => setPanelState('camera'), + }, ]}>
@@ -337,7 +345,10 @@ export const DropshipWeaponsConsole = () => { - + @@ -356,7 +367,10 @@ export const DropshipWeaponsConsole = () => { - + diff --git a/tgui/packages/tgui/interfaces/MfdPanels/CameraPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/CameraPanel.tsx index f3a1197e9802..8bf5807b9fcd 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/CameraPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/CameraPanel.tsx @@ -11,9 +11,9 @@ export const CameraMfdPanel = (props: MfdProps, context) => { return ( act('nvg-enable') }, - { children: 'nvgoff', onClick: () => act('nvg-disable') }, + leftButtons={[ + { children: 'NV-ON', onClick: () => act('nvg-enable') }, + { children: 'NV-OFF', onClick: () => act('nvg-disable') }, ]} bottomButtons={[{ children: 'EXIT', onClick: () => setPanelState('') }]}> diff --git a/tgui/packages/tgui/interfaces/MfdPanels/EquipmentPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/EquipmentPanel.tsx index 05a500563b52..8f2cff9f1842 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/EquipmentPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/EquipmentPanel.tsx @@ -314,16 +314,6 @@ export const EquipmentMfdPanel = (props: MfdProps, context) => { return ( setPanelState('firemission'), - }, - {}, - {}, - ]} leftButtons={[ weap2 ? generateButton(weap2) : {}, weap1 ? generateButton(weap1) : {}, diff --git a/tgui/packages/tgui/interfaces/MfdPanels/FiremissionPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/FiremissionPanel.tsx index fd71dab8f045..0eaa43f53478 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/FiremissionPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/FiremissionPanel.tsx @@ -67,11 +67,7 @@ const FiremissionMfdHomePage = (props: MfdProps, context) => { const firemission = data.firemission_data.length > x ? data.firemission_data[x] : undefined; return { - children: firemission ? ( -
- FM {x + 1}
{firemission?.name} -
- ) : undefined, + children: firemission ?
FM {x + 1}
: undefined, onClick: () => setSelectedFm(firemission?.name), }; }; @@ -95,7 +91,6 @@ const FiremissionMfdHomePage = (props: MfdProps, context) => { leftButtons={left_firemissions} rightButtons={right_firemissions} topButtons={[ - {}, {}, {}, fmName @@ -110,10 +105,11 @@ const FiremissionMfdHomePage = (props: MfdProps, context) => { }, } : {}, + {}, { - children: , + children: fmOffset > 0 ? : undefined, onClick: () => { - if (fmOffset >= 1) { + if (fmOffset > 0) { setFmOffset(fmOffset - 1); } }, @@ -128,9 +124,12 @@ const FiremissionMfdHomePage = (props: MfdProps, context) => { {}, {}, { - children: , + children: + fmOffset + 10 < data.firemission_data?.length ? ( + + ) : undefined, onClick: () => { - if (fmOffset + 8 < data.firemission_data.length) { + if (fmOffset + 10 < data.firemission_data?.length) { setFmOffset(fmOffset + 1); } }, @@ -212,7 +211,10 @@ const ViewFiremissionMfdPanel = ( bottomButtons={[ { children: 'EXIT', - onClick: () => setPanelState(''), + onClick: () => { + setSelectedFm(undefined); + setPanelState(''); + }, }, ]} rightButtons={editFm === true ? rightButtons : []}> diff --git a/tgui/packages/tgui/interfaces/MfdPanels/FultonPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/FultonPanel.tsx index 05d33e51a8d1..5bb2f462d1a2 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/FultonPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/FultonPanel.tsx @@ -55,7 +55,7 @@ export const FultonMfdPanel = (props: MfdProps, context) => { { children: , onClick: () => { - if (fulltonOffset >= 1) { + if (fulltonOffset > 0) { setFultonOffset(fulltonOffset - 1); } }, @@ -70,6 +70,9 @@ export const FultonMfdPanel = (props: MfdProps, context) => { }, }, ]} + topButtons={[ + { children: 'EQUIP', onClick: () => setPanelState('equipment') }, + ]} bottomButtons={[ { children: 'EXIT', diff --git a/tgui/packages/tgui/interfaces/MfdPanels/MGPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/MGPanel.tsx index dc6df25e17c1..fac34ef3e49a 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/MGPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/MGPanel.tsx @@ -7,6 +7,7 @@ import { EquipmentContext, MGSpec } from './types'; const MgPanel = (props: DropshipEquipment) => { const mgData = props.data as MGSpec; + return ( @@ -44,6 +45,8 @@ export const MgMfdPanel = (props: MfdProps, context) => { const { setPanelState } = mfdState(context, props.panelStateId); const { equipmentState } = useEquipmentState(context, props.panelStateId); const mg = data.equipment_data.find((x) => x.mount_point === equipmentState); + const deployLabel = (mg?.data?.deployed ?? 0) === 1 ? 'RETRACT' : 'DEPLOY'; + return ( { ]} leftButtons={[ { - children: 'DEPLOY', + children: deployLabel, onClick: () => act('deploy-equipment', { equipment_id: mg?.mount_point }), }, diff --git a/tgui/packages/tgui/interfaces/MfdPanels/MedevacPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/MedevacPanel.tsx index 634b4ef2a52e..a804b4d92e59 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/MedevacPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/MedevacPanel.tsx @@ -48,6 +48,7 @@ const MedevacOccupant = (props: { data: MedevacTargets }) => ( ); export const MedevacMfdPanel = (props: MfdProps, context) => { + const { data, act } = useBackend(context); const [medevacOffset, setMedevacOffset] = useLocalState( context, `${props.panelStateId}_medevacoffset`, @@ -56,8 +57,6 @@ export const MedevacMfdPanel = (props: MfdProps, context) => { const { setPanelState } = mfdState(context, props.panelStateId); const { equipmentState } = useEquipmentState(context, props.panelStateId); - const { data, act } = useBackend(context); - const result = data.equipment_data.find( (x) => x.mount_point === equipmentState ); @@ -85,6 +84,7 @@ export const MedevacMfdPanel = (props: MfdProps, context) => { const all_targets = range(medevacOffset, medevacOffset + 8) .map((x) => data.medevac_targets[x]) .filter((x) => x !== undefined); + return ( { { children: , onClick: () => { - if (medevacOffset >= 1) { + if (medevacOffset > 0) { setMedevacOffset(medevacOffset - 1); } }, @@ -109,10 +109,7 @@ export const MedevacMfdPanel = (props: MfdProps, context) => { }, ]} topButtons={[ - { - children: 'EQUIP', - onClick: () => setPanelState('equipment'), - }, + { children: 'EQUIP', onClick: () => setPanelState('equipment') }, ]} bottomButtons={[ { @@ -168,7 +165,7 @@ export const MedevacMfdPanel = (props: MfdProps, context) => { {all_targets.map((x) => ( <> - + diff --git a/tgui/packages/tgui/interfaces/MfdPanels/MultifunctionDisplay.tsx b/tgui/packages/tgui/interfaces/MfdPanels/MultifunctionDisplay.tsx index 9df7eaffcde4..35f81b45ed3e 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/MultifunctionDisplay.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/MultifunctionDisplay.tsx @@ -13,6 +13,7 @@ export interface MfdProps { rightButtons?: Array; bottomButtons?: Array; children?: InfernoNode; + otherPanelStateId?: string; } export const MfdButton = (props: ButtonProps, context) => { diff --git a/tgui/packages/tgui/interfaces/MfdPanels/SentryPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/SentryPanel.tsx index d8ea220ec986..c5f9bd04c1b0 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/SentryPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/SentryPanel.tsx @@ -57,6 +57,7 @@ export const SentryMfdPanel = (props: MfdProps, context) => { ); const deployLabel = (sentry?.data?.deployed ?? 0) === 1 ? 'RETRACT' : 'DEPLOY'; + return ( { act('deploy-equipment', { equipment_id: sentry?.mount_point }), }, { - children: 'CAMERA', + children: sentry?.data?.camera_available ? 'CAMERA' : undefined, onClick: () => act('set-camera-sentry', { equipment_id: sentry?.mount_point }), }, diff --git a/tgui/packages/tgui/interfaces/MfdPanels/SpotlightPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/SpotlightPanel.tsx index ce241420497e..f3a5884f89ca 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/SpotlightPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/SpotlightPanel.tsx @@ -33,6 +33,9 @@ export const SpotlightMfdPanel = (props: MfdProps, context) => { const spotlight = data.equipment_data.find( (x) => x.mount_point === equipmentState ); + const deployLabel = + (spotlight?.data?.deployed ?? 0) === 1 ? 'DISABLE' : 'ENABLE'; + return ( { ]} leftButtons={[ { - children: 'DEPLOY', + children: deployLabel, onClick: () => act('deploy-equipment', { equipment_id: spotlight?.mount_point }), }, diff --git a/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx index 1eca123173b0..5767b4960840 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx @@ -36,6 +36,9 @@ export const SupportMfdPanel = (props: MfdProps, context) => { return ( setPanelState('equipment') }, + ]} bottomButtons={[ { children: 'EXIT', diff --git a/tgui/packages/tgui/interfaces/MfdPanels/TargetAquisition.tsx b/tgui/packages/tgui/interfaces/MfdPanels/TargetAquisition.tsx index 49f22db18104..ebaacfb90337 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/TargetAquisition.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/TargetAquisition.tsx @@ -59,7 +59,7 @@ const useTargetFiremissionSelect = (context) => { }; }; -const useTargetOffset = (context, panelId: string) => { +export const useTargetOffset = (context, panelId: string) => { const [data, set] = useLocalState(context, `${panelId}_targetOffset`, 0); return { targetOffset: data, @@ -79,7 +79,7 @@ const useTargetSubmenu = (context, panelId: string) => { }; }; -const TargetLines = (props: { panelId: string }, context) => { +export const TargetLines = (props: { panelId: string }, context) => { const { data } = useBackend< EquipmentContext & FiremissionContext & TargetContext >(context); @@ -140,6 +140,34 @@ const leftButtonGenerator = (context, panelId: string) => { useTargetFiremissionSelect(context); const { weaponSelected, setWeaponSelected } = useWeaponSelectedState(context); const weapons = data.equipment_data.filter((x) => x.is_weapon); + const [fmOffset] = useLocalState( + context, + `${panelId}_fm_strike_select_offset`, + 0 + ); + const firemission_mapper = (x: number) => { + if (x === 0) { + return { + children: 'CANCEL', + onClick: () => { + setFiremissionSelected(undefined); + setStrikeMode(undefined); + setLeftButtonMode(undefined); + }, + }; + } + x -= 1; + const firemission = + data.firemission_data.length > x ? data.firemission_data[x] : undefined; + return { + children: firemission ?
FM {x + 1}
: undefined, + onClick: () => { + setFiremissionSelected(data.firemission_data[x]); + setLeftButtonMode(undefined); + }, + }; + }; + if (leftButtonMode === undefined) { return [ { @@ -154,26 +182,30 @@ const leftButtonGenerator = (context, panelId: string) => { } if (leftButtonMode === 'STRIKE') { if (strikeMode === 'weapon' && weaponSelected === undefined) { - return weapons.map((x) => { - return { - children: x.shorthand, + const cancelButton = [ + { + children: 'CANCEL', onClick: () => { - setWeaponSelected(x.mount_point); + setFiremissionSelected(undefined); + setStrikeMode(undefined); setLeftButtonMode(undefined); }, - }; - }); + }, + ]; + return cancelButton.concat( + weapons.map((x) => { + return { + children: x.shorthand, + onClick: () => { + setWeaponSelected(x.eqp_tag); + setLeftButtonMode(undefined); + }, + }; + }) + ); } if (strikeMode === 'firemission' && firemissionSelected === undefined) { - return data.firemission_data.map((x) => { - return { - children: x.name, - onClick: () => { - setFiremissionSelected(x); - setLeftButtonMode(undefined); - }, - }; - }); + return range(fmOffset, fmOffset + 5).map(firemission_mapper); } return [ { children: 'CANCEL', onClick: () => setLeftButtonMode(undefined) }, @@ -230,7 +262,7 @@ const leftButtonGenerator = (context, panelId: string) => { return []; }; -const lazeMapper = (context, offset) => { +export const lazeMapper = (context, offset) => { const { act, data } = useBackend(context); const { setSelectedTarget } = useLazeTarget(context); @@ -271,6 +303,21 @@ const lazeMapper = (context, offset) => { }; }; +export const getLastTargetName = (data) => { + const target = data.targets_data[data.targets_data.length - 1] ?? undefined; + const isDebug = target?.target_name.includes('debug'); + if (isDebug) { + return 'debug ' + target.target_name.split(' ')[3]; + } + const label = target?.target_name.split(' ')[0] ?? ''; + const squad = label[0] ?? undefined; + const number = label.split('-')[1] ?? undefined; + + return squad !== undefined && number !== undefined + ? `${squad}-${number}` + : target?.target_name; +}; + export const TargetAquisitionMfdPanel = (props: MfdProps, context) => { const { panelStateId } = props; @@ -288,45 +335,37 @@ export const TargetAquisitionMfdPanel = (props: MfdProps, context) => { context, panelStateId ); + const [fmOffset, setFmOffset] = useLocalState( + context, + `${props.panelStateId}_fm_strike_select_offset`, + 0 + ); + const { leftButtonMode } = useTargetSubmenu(context, props.panelStateId); const { fmXOffsetValue } = useFiremissionXOffsetValue(context); const { fmYOffsetValue } = useFiremissionYOffsetValue(context); - const lazes = range(0, 5).map((x) => - x > data.targets_data.length ? undefined : data.targets_data[x] - ); - const strikeConfigLabel = strikeMode === 'weapon' - ? data.equipment_data.find((x) => x.mount_point === weaponSelected)?.name + ? data.equipment_data.find((x) => x.eqp_tag === weaponSelected)?.name : firemissionSelected !== undefined ? data.firemission_data.find( (x) => x.mission_tag === firemissionSelected.mission_tag )?.name : 'NONE'; - const lazeIndex = lazes.findIndex((x) => x?.target_tag === selectedTarget); - const strikeReady = strikeMode !== undefined && lazeIndex !== -1; + const strikeReady = + selectedTarget !== undefined && + strikeDirection !== undefined && + ((strikeMode === 'weapon' && + weaponSelected !== undefined && + data.equipment_data.find((x) => x.eqp_tag === weaponSelected)) || + (strikeMode === 'firemission' && firemissionSelected !== undefined)); const targets = range(targetOffset, targetOffset + 5).map((x) => lazeMapper(context, x) ); - const getLastName = () => { - const target = data.targets_data[data.targets_data.length - 1] ?? undefined; - const isDebug = target?.target_name.includes('debug'); - if (isDebug) { - return 'debug ' + target.target_name.split(' ')[3]; - } - const label = target?.target_name.split(' ')[0] ?? ''; - const squad = label[0] ?? undefined; - const number = label.split('-')[1] ?? undefined; - - return squad !== undefined && number !== undefined - ? `${squad}-${number}` - : target?.target_name; - }; - if ( selectedTarget && data.targets_data.find((x) => `${x.target_tag}` === `${selectedTarget}`) === @@ -361,7 +400,20 @@ export const TargetAquisitionMfdPanel = (props: MfdProps, context) => { } }, }, - {}, + { + children: + leftButtonMode === 'STRIKE' && + strikeMode === 'firemission' && + firemissionSelected === undefined && + fmOffset > 0 ? ( + + ) : undefined, + onClick: () => { + if (fmOffset > 0) { + setFmOffset(fmOffset - 1); + } + }, + }, {}, {}, { @@ -378,16 +430,29 @@ export const TargetAquisitionMfdPanel = (props: MfdProps, context) => { children: 'EXIT', onClick: () => setPanelState(''), }, - {}, + { + children: + leftButtonMode === 'STRIKE' && + strikeMode === 'firemission' && + firemissionSelected === undefined && + fmOffset + 4 < data.firemission_data?.length ? ( + + ) : undefined, + onClick: () => { + if (fmOffset + 4 < data.firemission_data?.length) { + setFmOffset(fmOffset + 1); + } + }, + }, {}, {}, { children: - targetOffset < lazes.length ? ( + targetOffset + 5 < data.targets_data?.length ? ( ) : undefined, onClick: () => { - if (targetOffset < lazes.length) { + if (targetOffset + 5 < data.targets_data?.length) { setTargetOffset(targetOffset + 1); } }, @@ -443,8 +508,9 @@ export const TargetAquisitionMfdPanel = (props: MfdProps, context) => {

Target selected:{' '} - {lazes.find((x) => x?.target_tag === selectedTarget) - ?.target_name ?? 'NONE'} + {data.targets_data.find( + (x) => x?.target_tag === selectedTarget + )?.target_name ?? 'NONE'}

@@ -502,7 +568,7 @@ export const TargetAquisitionMfdPanel = (props: MfdProps, context) => { LATEST - {getLastName()} + {getLastTargetName(data)} )} diff --git a/tgui/packages/tgui/interfaces/MfdPanels/WeaponPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/WeaponPanel.tsx index 090001aa3ac9..cec542fdc3d1 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/WeaponPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/WeaponPanel.tsx @@ -1,10 +1,11 @@ import { range } from 'common/collections'; import { useBackend } from '../../backend'; -import { Box, Stack } from '../../components'; +import { Box, Icon, Stack } from '../../components'; import { DropshipEquipment } from '../DropshipWeaponsConsole'; import { MfdProps, MfdPanel } from './MultifunctionDisplay'; import { mfdState, useWeaponState } from './stateManagers'; import { LazeTarget } from './types'; +import { getLastTargetName, lazeMapper, TargetLines, useTargetOffset } from './TargetAquisition'; const EmptyWeaponPanel = (props, context) => { return
Nothing Listed
; @@ -14,30 +15,12 @@ interface EquipmentContext { targets_data: Array; } -const getLazeButtonProps = (context) => { - const { act, data } = useBackend(context); - const lazes = range(0, 5).map((x) => - x > data.targets_data.length ? undefined : data.targets_data[x] - ); - const get_laze = (index: number) => { - const laze = lazes.find((_, i) => i === index); - if (laze === undefined) { - return { - children: '', - onClick: () => act('set-camera', { equipment_id: null }), - }; - } - return { - children: laze?.target_name.split(' ')[0] ?? 'NONE', - onClick: laze - ? () => act('set-camera', { 'equipment_id': laze.target_tag }) - : undefined, - }; - }; - return [get_laze(0), get_laze(1), get_laze(2), get_laze(3), get_laze(4)]; -}; +const WeaponPanel = ( + props: { panelId: string; equipment: DropshipEquipment }, + context +) => { + const { data } = useBackend(context); -const WeaponPanel = (props: { equipment: DropshipEquipment }, context) => { return ( @@ -45,7 +28,7 @@ const WeaponPanel = (props: { equipment: DropshipEquipment }, context) => { ACTIONS - {false && ( + {true && ( { - - - - SELECT - - - TARGETS - - - - - - - - + + + {data.targets_data.length === 0 && ( + + + NO TARGETS + + + )} + {data.targets_data.length > 0 && ( + + + SELECT + + + TARGETS + + + {Math.min(5, data.targets_data.length)} of{' '} + {data.targets_data.length} + + {data.targets_data.length > 0 && ( + <> + + LATEST + + + {getLastTargetName(data)} + + + )} + + )} + + @@ -146,7 +135,14 @@ export const WeaponMfdPanel = (props: MfdProps, context) => { const { setPanelState } = mfdState(context, props.panelStateId); const { weaponState } = useWeaponState(context, props.panelStateId); const { data, act } = useBackend(context); + const { targetOffset, setTargetOffset } = useTargetOffset( + context, + props.panelStateId + ); const weap = data.equipment_data.find((x) => x.mount_point === weaponState); + const targets = range(targetOffset, targetOffset + 5).map((x) => + lazeMapper(context, x) + ); return ( { onClick: () => setPanelState(''), }, {}, + {}, + {}, + { + children: + targetOffset + 5 < data.targets_data?.length ? ( + + ) : undefined, + onClick: () => { + if (targetOffset + 5 < data.targets_data?.length) { + setTargetOffset(targetOffset + 1); + } + }, + }, ]} topButtons={[ + { children: 'EQUIP', onClick: () => setPanelState('equipment') }, + {}, + {}, + {}, { - children: 'EQUIP', - onClick: () => setPanelState('equipment'), + children: targetOffset > 0 ? : undefined, + onClick: () => { + if (targetOffset > 0) { + setTargetOffset(targetOffset - 1); + } + }, }, ]} - rightButtons={getLazeButtonProps(context)}> + rightButtons={targets}> - {weap ? : } + {weap ? ( + + ) : ( + + )} ); diff --git a/tgui/packages/tgui/interfaces/MfdPanels/stateManagers.ts b/tgui/packages/tgui/interfaces/MfdPanels/stateManagers.ts index e639938eabf8..4b1729dce0f7 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/stateManagers.ts +++ b/tgui/packages/tgui/interfaces/MfdPanels/stateManagers.ts @@ -60,6 +60,17 @@ export const mfdState = (context, panelId: string) => { }; }; +export const otherMfdState = (context, otherPanelId: string | undefined) => { + const [data] = useSharedState( + context, + `${otherPanelId}_panelstate`, + '' + ); + return { + otherPanelState: data, + }; +}; + export const useWeaponState = (context, panelId: string) => { const [data, set] = useSharedState( context, diff --git a/tgui/packages/tgui/interfaces/MfdPanels/types.ts b/tgui/packages/tgui/interfaces/MfdPanels/types.ts index 78e7c3314b30..c20449ece428 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/types.ts +++ b/tgui/packages/tgui/interfaces/MfdPanels/types.ts @@ -66,7 +66,7 @@ export type SentrySpec = { kills: number; iff_status: string[]; camera_available: number; - deployed: number; + deployed: 0 | 1; }; export type SpotlightSpec = {