Skip to content

Commit

Permalink
Dropship weapons console TGUI (#4812)
Browse files Browse the repository at this point in the history
# About the pull request

Migrates the dropship weapons panel to TGUI. Design is primarily
inspired by the MultiFunction Displays used in modern aircraft.

The UI consists of two identical and independent panels. The pilot can
choose which panels to display.

Code wise this PR introduces the MFD which is a reusable component.

<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game
nanoui bad tgui good
# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Put screenshots and videos here with an empty line between the
screenshots and the `<details>` tags.
## Update - Some styling improvements
Improving the overall look and feel, making the background a dark grey
over a black, rounding the edges. Making inactive buttons appear greyed
out.

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/0965b5cb-21b0-4b7f-84ea-40651e83a02e)



## Welcome screen - blurb for lore

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/5872dcb6-ba87-485e-a736-8de0b3e5e36d)

## Equipment panel and map 

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/85fde5cc-e4a8-439e-8c55-d010a4780d8c)

## Equipment panel with camera

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/034a2833-d37c-4c6b-8b08-64e3e09aefb0)

## Weapon panel and Camera 

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/ce246258-a879-4220-b481-3d5fbc800651)

## Target Acquisition with camera

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/2778b9da-76f9-4c37-b3ba-9d45a1bdc625)
 
## Medevac lift with stretcher camera

![image](https://github.com/cmss13-devs/cmss13/assets/101871009/7e9ef10b-811c-4922-9f24-ae805bae24d9)


</details>


# Changelog
:cl:
ui: tgui dropship weapons console
refactor: added MFD panel
refactor: creates datum component to manage camera code
qol: CAS weapons operator can see camera in UI
add: CAS can offset in X and Y coordinates
refactor: CAS can offset in different direction to attack vector
/:cl:

---------

Co-authored-by: fira <[email protected]>
  • Loading branch information
mullenpaul and fira authored Dec 25, 2023
1 parent 65f2581 commit bc787f6
Show file tree
Hide file tree
Showing 47 changed files with 5,142 additions and 1,209 deletions.
1 change: 1 addition & 0 deletions code/__DEFINES/__game.dm
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ block( \
#define FIRE_MISSION_WEAPON_REMOVED 8
#define FIRE_MISSION_WEAPON_UNUSABLE 16
#define FIRE_MISSION_WEAPON_OUT_OF_AMMO 32
#define FIRE_MISSION_BAD_DIRECTION 64
#define FIRE_MISSION_NOT_EXECUTABLE -1

//Defines for firemission state
Expand Down
9 changes: 9 additions & 0 deletions code/__DEFINES/dcs/signals/atom/signals_item.dm
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@

//from /datum/authority/branch/role/proc/equip_role()
#define COMSIG_POST_SPAWN_UPDATE "post_spawn_update"

#define COMSIG_CAMERA_MAPNAME_ASSIGNED "camera_manager_mapname_assigned"
#define COMSIG_CAMERA_REGISTER_UI "camera_manager_register_ui"
#define COMSIG_CAMERA_UNREGISTER_UI "camera_manager_unregister_ui"
#define COMSIG_CAMERA_SET_NVG "camera_manager_set_nvg"
#define COMSIG_CAMERA_CLEAR_NVG "camera_manager_clear_nvg"
#define COMSIG_CAMERA_SET_TARGET "camera_manager_set_target"
#define COMSIG_CAMERA_SET_AREA "camera_manager_set_area"
#define COMSIG_CAMERA_CLEAR "camera_manager_clear_target"
2 changes: 2 additions & 0 deletions code/__DEFINES/dcs/signals/atom/signals_obj.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@
/// from /obj/proc/afterbuckle()
#define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle"

#define COMSIG_DROPSHIP_ADD_EQUIPMENT "dropship_add_equipment"
#define COMSIG_DROPSHIP_REMOVE_EQUIPMENT "dropship_remove_equipment"
#define COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED "structure_crate_squad_launched"
1 change: 1 addition & 0 deletions code/__DEFINES/layers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
///--------------- FULLSCREEN RUNECHAT BUBBLES ------------
#define LIGHTING_PLANE 100
#define EXTERIOR_LIGHTING_PLANE 101
#define NVG_PLANE 110

///Popup Chat Messages
#define RUNECHAT_PLANE 501
Expand Down
8 changes: 8 additions & 0 deletions code/_onclick/hud/rendering/plane_master.dm
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@
remove_filter("AO")
add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA"))

/atom/movable/screen/plane_master/nvg_plane
name = "NVG plane"
plane = NVG_PLANE
render_relay_plane = RENDER_PLANE_GAME
blend_mode_override = BLEND_MULTIPLY
//icon = 'icons/mob/hud/screen1.dmi'
//icon_state = "noise"

/atom/movable/screen/plane_master/fullscreen
name = "fullscreen alert plane"
plane = FULLSCREEN_PLANE
Expand Down
235 changes: 235 additions & 0 deletions code/game/camera_manager/camera_manager.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
#define DEFAULT_MAP_SIZE 15

#define RENDER_MODE_TARGET 1
#define RENDER_MODE_AREA 2

/datum/component/camera_manager
var/map_name
var/obj/structure/machinery/camera/current
var/datum/shape/rectangle/current_area
var/atom/movable/screen/map_view/cam_screen
var/atom/movable/screen/background/cam_background
var/list/range_turfs = list()
/// The turf where the camera was last updated.
var/turf/last_camera_turf
var/target_x
var/target_y
var/target_z
var/target_width
var/target_height
var/list/cam_plane_masters
var/isXRay = FALSE
var/render_mode = RENDER_MODE_TARGET

/datum/component/camera_manager/Initialize()
. = ..()
map_name = "camera_manager_[REF(src)]_map"
cam_screen = new
cam_screen.name = "screen"
cam_screen.assigned_map = map_name
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_background = new
cam_background.assigned_map = map_name
cam_background.del_on_map_removal = FALSE

cam_plane_masters = list()
for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
var/atom/movable/screen/plane_master/instance = new plane()
add_plane(instance)

/datum/component/camera_manager/Destroy(force, ...)
. = ..()
range_turfs = null
current_area = null
cam_plane_masters = null
QDEL_NULL(cam_background)
QDEL_NULL(cam_screen)
if(current)
UnregisterSignal(current, COMSIG_PARENT_QDELETING)

/datum/component/camera_manager/proc/add_plane(atom/movable/screen/plane_master/instance)
instance.assigned_map = map_name
instance.del_on_map_removal = FALSE
if(instance.blend_mode_override)
instance.blend_mode = instance.blend_mode_override
instance.screen_loc = "[map_name]:CENTER"
cam_plane_masters["[instance.plane]"] = instance

/datum/component/camera_manager/proc/register(source, mob/user)
SIGNAL_HANDLER
var/client/user_client = user.client
if(!user_client)
return
user_client.register_map_obj(cam_background)
user_client.register_map_obj(cam_screen)
for(var/plane_id in cam_plane_masters)
user_client.register_map_obj(cam_plane_masters[plane_id])

/datum/component/camera_manager/proc/unregister(source, mob/user)
SIGNAL_HANDLER
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])

/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))
RegisterSignal(parent, COMSIG_CAMERA_SET_NVG, PROC_REF(enable_nvg))
RegisterSignal(parent, COMSIG_CAMERA_CLEAR_NVG, PROC_REF(disable_nvg))
RegisterSignal(parent, COMSIG_CAMERA_SET_AREA, PROC_REF(set_camera_rect))
RegisterSignal(parent, COMSIG_CAMERA_SET_TARGET, PROC_REF(set_camera))
RegisterSignal(parent, COMSIG_CAMERA_CLEAR, PROC_REF(clear_camera))

/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)
UnregisterSignal(parent, COMSIG_CAMERA_CLEAR_NVG)
UnregisterSignal(parent, COMSIG_CAMERA_SET_AREA)
UnregisterSignal(parent, COMSIG_CAMERA_SET_TARGET)
UnregisterSignal(parent, COMSIG_CAMERA_CLEAR)

/datum/component/camera_manager/proc/clear_camera()
SIGNAL_HANDLER
if(current)
UnregisterSignal(current, COMSIG_PARENT_QDELETING)
current_area = null
current = null
target_x = null
target_y = null
target_z = null
target_width = null
target_height = null
show_camera_static()

/datum/component/camera_manager/proc/set_camera(source, atom/target, w, h)
SIGNAL_HANDLER
render_mode = RENDER_MODE_TARGET
if(current)
UnregisterSignal(current, COMSIG_PARENT_QDELETING)
current = target
target_width = w
target_height = h
RegisterSignal(current, COMSIG_PARENT_QDELETING, PROC_REF(show_camera_static))
update_target_camera()

/datum/component/camera_manager/proc/set_camera_rect(source, x, y, z, w, h)
SIGNAL_HANDLER
render_mode = RENDER_MODE_AREA
if(current)
UnregisterSignal(current, COMSIG_PARENT_QDELETING)
current = null
current_area = RECT(x, y, w, h)
target_x = x
target_y = y
target_z = z
update_area_camera()

/datum/component/camera_manager/proc/enable_nvg(source, power, matrixcol)
SIGNAL_HANDLER
for(var/plane_id in cam_plane_masters)
var/atom/movable/screen/plane_master/plane = cam_plane_masters["[plane_id]"]
plane.add_filter("nvg", 1, color_matrix_filter(color_matrix_from_string(matrixcol)))
sync_lighting_plane_alpha(LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)

/datum/component/camera_manager/proc/disable_nvg()
SIGNAL_HANDLER
for(var/plane_id in cam_plane_masters)
var/atom/movable/screen/plane_master/plane = cam_plane_masters["[plane_id]"]
plane.remove_filter("nvg")
sync_lighting_plane_alpha(LIGHTING_PLANE_ALPHA_VISIBLE)

/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)
lighting.alpha = lighting_alpha
var/atom/movable/screen/plane_master/lighting/exterior_lighting = cam_plane_masters["[EXTERIOR_LIGHTING_PLANE]"]
if (exterior_lighting)
exterior_lighting.alpha = min(GLOB.minimum_exterior_lighting_alpha, lighting_alpha)

/**
* Set the displayed camera to the static not-connected.
*/
/datum/component/camera_manager/proc/show_camera_static()
cam_screen.vis_contents.Cut()
last_camera_turf = null
cam_background.icon_state = "scanline2"
cam_background.fill_rect(1, 1, DEFAULT_MAP_SIZE, DEFAULT_MAP_SIZE)

/datum/component/camera_manager/proc/update_target_camera()
// Show static if can't use the camera
if(!current?.can_use())
show_camera_static()
return

// Is this camera located in or attached to a living thing, Vehicle or helmet? If so, assume the camera's loc is the living (or non) thing.
var/cam_location = current
if(isliving(current.loc) || isVehicle(current.loc))
cam_location = current.loc
else if(istype(current.loc, /obj/item/clothing/head/helmet/marine))
var/obj/item/clothing/head/helmet/marine/helmet = current.loc
cam_location = helmet.loc

// If we're not forcing an update for some reason and the cameras are in the same location,
// we don't need to update anything.
// Most security cameras will end here as they're not moving.
var/newturf = get_turf(cam_location)
if(last_camera_turf == newturf)
return

// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
last_camera_turf = get_turf(cam_location)

var/list/visible_things = current.isXRay() ? range(current.view_range, cam_location) : view(current.view_range, cam_location)
render_objects(visible_things)

/datum/component/camera_manager/proc/update_area_camera()
// Show static if can't use the camera
if(!current_area || !target_z)
show_camera_static()
return

// If we're not forcing an update for some reason and the cameras are in the same location,
// we don't need to update anything.
// Most security cameras will end here as they're not moving.
var/turf/new_location = locate(target_x, target_y, target_z)
if(last_camera_turf == new_location)
return

// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
last_camera_turf = new_location

var/x_size = current_area.width
var/y_size = current_area.height
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)

/datum/component/camera_manager/proc/render_objects(list/visible_things)
var/list/visible_turfs = list()
for(var/turf/visible_turf in visible_things)
visible_turfs += visible_turf

var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
var/size_y = bbox[4] - bbox[2] + 1

cam_screen.vis_contents = visible_turfs
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)

#undef DEFAULT_MAP_SIZE
#undef RENDER_MODE_TARGET
#undef RENDER_MODE_AREA
Loading

0 comments on commit bc787f6

Please sign in to comment.