Adds an atmos debugging tool and excited group visualizer (#52395)

* Adds an atmos debugging tool and excited group visualizer

* rebuild moment

* yarn install -> yarn run build

* Sigh

* Fixed UI, did not test, needs a rebuild.

* Proper flexing

* Adds varied colors, improved ui courtusy of stylemistake:

* Fixes a runtime, updates tgui

* added superconductors, cleaned up some shitcode, removed a clashing color

* Woop

* Speed

* rebuild

* Adds a tick count

* begone auto-update

* color defines

* rebuild moment

* color improvements, fixes updating

* adds another preprocesser define to handle showing max shares in the ui

* test of application system?

* patches up some display issues, allows for smooth flowing from one group to another

* overlay-ified

* client testing

* dmi moment

* plane master

* it fucking works

* size change

* passthrough

* rebuild moment

* adresses review concerns, toggles active turf vis on when testing

Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
LemonInTheDark
2020-08-03 00:15:08 -07:00
committed by GitHub
parent 8063a1f009
commit 092af76b5d
14 changed files with 362 additions and 19 deletions

View File

@@ -20,15 +20,19 @@
#define COLOR_OLIVE "#808000"
#define COLOR_LIME "#32CD32"
#define COLOR_GREEN "#008000"
#define COLOR_VIBRANT_LIME "#00FF00"
#define COLOR_CYAN "#00FFFF"
#define COLOR_DARK_CYAN "#00a2ff"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_BLUE_LIGHT "#33CCFF"
#define COLOR_NAVY "#000080"
#define COLOR_PINK "#FFC0CB"
#define COLOR_MAGENTA "#FF00FF"
#define COLOR_VIOLET "#b900f7"
#define COLOR_PURPLE "#800080"
#define COLOR_ORANGE "#FF9900"
#define COLOR_TAN_ORANGE "#ff7b00"
#define COLOR_BEIGE "#CEB689"
#define COLOR_BLUE_GRAY "#75A2BB"
#define COLOR_BROWN "#BA9F6D"

View File

@@ -121,24 +121,27 @@
#define CAMERA_STATIC_LAYER 19
#define CAMERA_STATIC_RENDER_TARGET "CAMERA_STATIC_PLANE"
#define ATMOS_GROUP_PLANE 20
#define ATMOS_GROUP_LAYER 20
//HUD layer defines
#define FULLSCREEN_PLANE 20
#define FLASH_LAYER 20
#define FULLSCREEN_LAYER 20.1
#define UI_DAMAGE_LAYER 20.2
#define BLIND_LAYER 20.3
#define CRIT_LAYER 20.4
#define CURSE_LAYER 20.5
#define FULLSCREEN_PLANE 21
#define FLASH_LAYER 21
#define FULLSCREEN_LAYER 21.1
#define UI_DAMAGE_LAYER 21.2
#define BLIND_LAYER 21.3
#define CRIT_LAYER 21.4
#define CURSE_LAYER 21.5
#define FULLSCREEN_RENDER_TARGET "FULLSCREEN_PLANE"
#define HUD_PLANE 21
#define HUD_LAYER 21
#define HUD_PLANE 22
#define HUD_LAYER 22
#define HUD_RENDER_TARGET "HUD_PLANE"
#define ABOVE_HUD_PLANE 22
#define ABOVE_HUD_LAYER 22
#define ABOVE_HUD_PLANE 23
#define ABOVE_HUD_LAYER 23
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
#define SPLASHSCREEN_LAYER 24
#define SPLASHSCREEN_PLANE 24
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"

View File

@@ -30,7 +30,8 @@
#endif //ifdef LEGACY_REFERENCE_TRACKING
//#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
#define TRACK_MAX_SHARE //Allows max share tracking, for use in the atmos debugging ui
#endif //ifdef TESTING
//#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between

View File

@@ -0,0 +1 @@
GLOBAL_LIST_INIT(contrast_colors, list(COLOR_RED, COLOR_VIOLET, COLOR_DARK_CYAN, COLOR_TAN_ORANGE, COLOR_BLACK))

View File

@@ -138,3 +138,10 @@
plane = CAMERA_STATIC_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
/obj/screen/plane_master/excited_turfs
name = "atmos excited turfs"
plane = ATMOS_GROUP_PLANE
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
alpha = 0

View File

@@ -37,6 +37,7 @@ SUBSYSTEM_DEF(air)
var/map_loading = TRUE
var/list/queued_for_activation
var/display_all_groups = FALSE
/datum/controller/subsystem/air/stat_entry(msg)
msg += "C:{"
@@ -65,6 +66,7 @@ SUBSYSTEM_DEF(air)
setup_atmos_machinery()
setup_pipenets()
gas_reactions = init_gas_reactions()
setup_turf_visuals()
return ..()
@@ -145,6 +147,7 @@ SUBSYSTEM_DEF(air)
resumed = 0
currentpart = SSAIR_REBUILD_PIPENETS
SStgui.update_uis(SSair) //Lightning fast debugging motherfucker
/datum/controller/subsystem/air/proc/process_pipenets(resumed = 0)
@@ -255,8 +258,8 @@ SUBSYSTEM_DEF(air)
active_turfs -= T
if(currentpart == SSAIR_ACTIVETURFS)
currentrun -= T
#ifdef VISUALIZE_ACTIVE_TURFS
T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00")
#ifdef VISUALIZE_ACTIVE_TURFS //Use this when you want details about how the turfs are moving, display_all_groups should work for normal operation
T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_VIBRANT_LIME)
#endif
if(istype(T))
T.excited = 0
@@ -266,7 +269,7 @@ SUBSYSTEM_DEF(air)
/datum/controller/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = 1)
if(istype(T) && T.air)
#ifdef VISUALIZE_ACTIVE_TURFS
T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY)
T.add_atom_colour(COLOR_VIBRANT_LIME, TEMPORARY_COLOUR_PRIORITY)
#endif
T.excited = 1
active_turfs |= T
@@ -301,6 +304,11 @@ SUBSYSTEM_DEF(air)
// Clear active turfs - faster than removing every single turf in the world
// one-by-one, and Initalize_Atmos only ever adds `src` back in.
#ifdef VISUALIZE_ACTIVE_TURFS
for(var/jumpy in active_turfs)
var/turf/active = jumpy
active.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_VIBRANT_LIME)
#endif
active_turfs.Cut()
for(var/thing in turfs_to_init)
@@ -380,6 +388,17 @@ SUBSYSTEM_DEF(air)
AM.build_network()
CHECK_TICK
GLOBAL_LIST_EMPTY(colored_turfs)
GLOBAL_LIST_EMPTY(colored_images)
/datum/controller/subsystem/air/proc/setup_turf_visuals()
for(var/sharp_color in GLOB.contrast_colors)
var/obj/effect/overlay/atmos_excited/suger_high = new()
GLOB.colored_turfs += suger_high
var/image/shiny = new('icons/effects/effects.dmi', suger_high, "atmos_top", ATMOS_GROUP_LAYER)
shiny.plane = ATMOS_GROUP_PLANE
shiny.color = sharp_color
GLOB.colored_images += shiny
/datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines)
for(var/A in atmos_machines)
var/obj/machinery/atmospherics/AM = A
@@ -415,3 +434,97 @@ SUBSYSTEM_DEF(air)
return gas_string
var/datum/atmosphere/mix = atmos_gen[gas_string]
return mix.gas_string
/datum/controller/subsystem/air/ui_state(mob/user)
return GLOB.debug_state
/datum/controller/subsystem/air/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AtmosControlPanel")
ui.set_autoupdate(FALSE)
ui.open()
/datum/controller/subsystem/air/ui_data(mob/user)
var/list/data = list()
data["excited_groups"] = list()
for(var/datum/excited_group/group in excited_groups)
var/turf/T = group.turf_list[1]
var/area/target = get_area(T)
var/max = 0
#ifdef TRACK_MAX_SHARE
for(var/who in group.turf_list)
var/turf/open/lad = who
max = max(lad.max_share, max)
#endif
data["excited_groups"] += list(list(
"jump_to" = REF(T), //Just go to the first turf
"group" = REF(group),
"area" = target.name,
"breakdown" = group.breakdown_cooldown,
"dismantle" = group.dismantle_cooldown,
"size" = group.turf_list.len,
"should_show" = group.should_display,
"max_share" = max
))
data["active_size"] = active_turfs.len
data["hotspots_size"] = hotspots.len
data["excited_size"] = excited_groups.len
data["conducting_size"] = active_super_conductivity.len
data["frozen"] = can_fire
data["show_all"] = display_all_groups
data["fire_count"] = times_fired
#ifdef TRACK_MAX_SHARE
data["display_max"] = TRUE
#else
data["display_max"] = FALSE
#endif
var/obj/screen/plane_master/plane = user.hud_used.plane_masters["[ATMOS_GROUP_PLANE]"]
data["showing_user"] = (plane.alpha == 255)
return data
/datum/controller/subsystem/air/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..() || !check_rights_for(usr.client, R_DEBUG))
return
switch(action)
if("move-to-target")
var/turf/target = locate(params["spot"])
if(!target)
return
usr.forceMove(target)
usr.update_parallax_contents()
if("toggle-freeze")
can_fire = !can_fire
return TRUE
if("toggle_show_group")
var/datum/excited_group/group = locate(params["group"])
if(!group)
return
group.should_display = !group.should_display
if(display_all_groups)
return TRUE
if(group.should_display)
group.display_turfs()
else
group.hide_turfs()
return TRUE
if("toggle_show_all")
display_all_groups = !display_all_groups
for(var/datum/excited_group/group in excited_groups)
if(display_all_groups)
group.display_turfs()
else if(!group.should_display) //Don't flicker yeah?
group.hide_turfs()
return TRUE
if("toggle_user_display")
var/obj/screen/plane_master/plane = ui.user.hud_used.plane_masters["[ATMOS_GROUP_PLANE]"]
if(!plane.alpha)
if(ui.user.client)
ui.user.client.images += GLOB.colored_images
plane.alpha = 255
else
if(ui.user.client)
ui.user.client.images -= GLOB.colored_images
plane.alpha = 0
return TRUE

View File

@@ -52,3 +52,15 @@
vis_flags = NONE
var/unused = 0 //When detected to be unused it gets set to world.time, after a while it gets removed
var/cache_expiration = 2 MINUTES // overlays which go unused for 2 minutes get cleaned up
/obj/effect/overlay/atmos_excited
name = "excited group"
icon = null
icon_state = null
anchored = TRUE // should only appear in vis_contents, but to be safe
appearance_flags = RESET_TRANSFORM | TILE_BOUND
invisibility = INVISIBILITY_ABSTRACT
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = ATMOS_GROUP_LAYER
plane = ATMOS_GROUP_PLANE

View File

@@ -165,6 +165,7 @@ GLOBAL_PROTECT(admin_verbs_debug)
/client/proc/cmd_display_init_log,
/client/proc/cmd_display_overlay_log,
/client/proc/reload_configuration,
/client/proc/atmos_control,
/client/proc/reload_cards,
/client/proc/validate_cards,
/client/proc/test_cardpack_distribution,
@@ -559,6 +560,13 @@ GLOBAL_PROTECT(admin_verbs_hideable)
log_admin("[key_name(usr)] has modified Dynamic Explosion Scale: [ex_scale]")
message_admins("[key_name_admin(usr)] has modified Dynamic Explosion Scale: [ex_scale]")
/client/proc/atmos_control()
set name = "Atmos Control Panel"
set category = "Debug"
if(!check_rights(R_DEBUG))
return
SSair.ui_interact(mob)
/client/proc/reload_cards()
set name = "Reload Cards"
set category = "Debug"

View File

@@ -33,6 +33,9 @@
var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time
var/list/atmos_overlay_types //gas IDs of current active gas overlays
#ifdef TRACK_MAX_SHARE
var/max_share = 0
#endif
/turf/open/Initialize()
if(!blocks_air)
@@ -144,7 +147,18 @@
.[gastype] = TRUE
/////////////////////////////SIMULATION///////////////////////////////////
#ifdef TRACK_MAX_SHARE
#define LAST_SHARE_CHECK \
var/last_share = our_air.last_share;\
max_share = max(last_share, max_share);\
if(last_share > MINIMUM_AIR_TO_SUSPEND){\
our_excited_group.reset_cooldowns();\
cached_atmos_cooldown = 0;\
} else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\
our_excited_group.dismantle_cooldown = 0;\
cached_atmos_cooldown = 0;\
}
#else
#define LAST_SHARE_CHECK \
var/last_share = our_air.last_share;\
if(last_share > MINIMUM_AIR_TO_SUSPEND){\
@@ -154,6 +168,7 @@
our_excited_group.dismantle_cooldown = 0;\
cached_atmos_cooldown = 0;\
}
#endif
/turf/proc/process_cell(fire_count)
SSair.remove_from_active(src)
@@ -176,6 +191,10 @@
var/datum/gas_mixture/our_air = air
#ifdef TRACK_MAX_SHARE
max_share = 0 //Gotta reset our tracker
#endif
for(var/t in adjacent_turfs)
var/turf/open/enemy_tile = t
@@ -281,6 +300,9 @@
var/list/turf_list = list()
var/breakdown_cooldown = 0
var/dismantle_cooldown = 0
var/should_display = FALSE
var/display_id = 0
var/static/wrapping_id = 0
/datum/excited_group/New()
SSair.excited_groups += src
@@ -289,6 +311,8 @@
turf_list += T
T.excited_group = src
reset_cooldowns()
if(should_display || SSair.display_all_groups)
display_turf(T)
/datum/excited_group/proc/merge_groups(datum/excited_group/E)
if(turf_list.len > E.turf_list.len)
@@ -297,6 +321,10 @@
var/turf/open/T = t
T.excited_group = src
turf_list += T
should_display = E.should_display | should_display
if(should_display || SSair.display_all_groups)
E.hide_turfs()
display_turfs()
reset_cooldowns()
else
SSair.excited_groups -= src
@@ -305,6 +333,10 @@
T.excited_group = E
E.turf_list += T
E.reset_cooldowns()
E.should_display = E.should_display | should_display
if(E.should_display || SSair.display_all_groups)
hide_turfs()
E.display_turfs()
/datum/excited_group/proc/reset_cooldowns()
breakdown_cooldown = 0
@@ -347,15 +379,42 @@
T.excited = FALSE
T.excited_group = null
SSair.active_turfs -= T
#ifdef VISUALIZE_ACTIVE_TURFS //Use this when you want details about how the turfs are moving, display_all_groups should work for normal operation
T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, COLOR_VIBRANT_LIME)
#endif
garbage_collect()
/datum/excited_group/proc/garbage_collect()
if(display_id) //If we ever did make those changes
hide_turfs()
for(var/t in turf_list)
var/turf/open/T = t
T.excited_group = null
turf_list.Cut()
SSair.excited_groups -= src
/datum/excited_group/proc/display_turfs()
if(display_id == 0) //Hasn't been shown before
wrapping_id = wrapping_id % GLOB.colored_turfs.len
wrapping_id++ //We do this after because lists index at 1
display_id = wrapping_id
for(var/thing in turf_list)
var/turf/display = thing
display.vis_contents += GLOB.colored_turfs[display_id]
/datum/excited_group/proc/hide_turfs()
for(var/thing in turf_list)
var/turf/display = thing
display.vis_contents -= GLOB.colored_turfs[display_id]
display_id = 0
/datum/excited_group/proc/display_turf(turf/thing)
if(display_id == 0) //Hasn't been shown before
wrapping_id = wrapping_id % GLOB.colored_turfs.len
wrapping_id++ //We do this after because lists index at 1
display_id = wrapping_id
thing.vis_contents += GLOB.colored_turfs[display_id]
////////////////////////SUPERCONDUCTIVITY/////////////////////////////
/turf/proc/conductivity_directions()
if(archived_cycle < SSair.times_fired)

View File

@@ -0,0 +1,6 @@
GLOBAL_DATUM_INIT(debug_state, /datum/ui_state/debug_state, new)
/datum/ui_state/debug_state/can_use_topic(src_object, mob/user)
if(check_rights_for(user.client, R_DEBUG))
return UI_INTERACTIVE
return UI_CLOSE

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 KiB

After

Width:  |  Height:  |  Size: 885 KiB

View File

@@ -177,6 +177,7 @@
#include "code\_globalvars\lists\achievements.dm"
#include "code\_globalvars\lists\admin.dm"
#include "code\_globalvars\lists\client.dm"
#include "code\_globalvars\lists\color.dm"
#include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\keybindings.dm"
#include "code\_globalvars\lists\maintenance_loot.dm"
@@ -3089,6 +3090,7 @@
#include "code\modules\tgui\states\always.dm"
#include "code\modules\tgui\states\conscious.dm"
#include "code\modules\tgui\states\contained.dm"
#include "code\modules\tgui\states\debug.dm"
#include "code\modules\tgui\states\deep_inventory.dm"
#include "code\modules\tgui\states\default.dm"
#include "code\modules\tgui\states\hands.dm"

View File

@@ -0,0 +1,127 @@
import { map, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { useBackend } from '../backend';
import { Box, Button, Flex, Section, Table } from '../components';
import { Window } from '../layouts';
export const AtmosControlPanel = (props, context) => {
const { act, data } = useBackend(context);
const groups = flow([
map((group, i) => ({
...group,
// Generate a unique id
id: group.area + i,
})),
sortBy(group => group.id),
])(data.excited_groups);
return (
<Window
title="SSAir Control Panel"
width={900}
height={500}
resizable>
<Section m={1}>
<Flex
justify="space-between"
align="baseline">
<Flex.Item>
<Button
onClick={() => act('toggle-freeze')}
color={data.frozen === 1 ? 'good' : 'bad'}>
{data.frozen === 1
? 'Freeze Subsystem'
: 'Unfreeze Subsystem'}
</Button>
</Flex.Item>
<Flex.Item>
Fire Cnt: {data.fire_count}
</Flex.Item>
<Flex.Item>
Active Turfs: {data.active_size}
</Flex.Item>
<Flex.Item>
Excited Groups: {data.excited_size}
</Flex.Item>
<Flex.Item>
Hotspots: {data.hotspots_size}
</Flex.Item>
<Flex.Item>
Superconductors: {data.conducting_size}
</Flex.Item>
<Flex.Item>
<Button.Checkbox
checked={data.showing_user}
onClick={() => act('toggle_user_display')}>
Personal View
</Button.Checkbox>
</Flex.Item>
<Flex.Item>
<Button.Checkbox
checked={data.show_all}
onClick={() => act('toggle_show_all')}>
Display all
</Button.Checkbox>
</Flex.Item>
</Flex>
</Section>
<Box fillPositionedParent top="45px">
<Window.Content scrollable>
<Section>
<Table>
<Table.Row header>
<Table.Cell>
Area Name
</Table.Cell>
<Table.Cell collapsing>
Breakdown
</Table.Cell>
<Table.Cell collapsing>
Dismantle
</Table.Cell>
<Table.Cell collapsing>
Turfs
</Table.Cell>
<Table.Cell collapsing>
{data.display_max === 1 && "Max Share"}
</Table.Cell>
<Table.Cell collapsing>
Display
</Table.Cell>
</Table.Row>
{groups.map(group => (
<tr key={group.id}>
<td>
<Button
content={group.area}
onClick={() => act('move-to-target', {
spot: group.jump_to,
})} />
</td>
<td>
{group.breakdown}
</td>
<td>
{group.dismantle}
</td>
<td>
{group.size}
</td>
<td>
{data.display_max === 1 && group.max_share}
</td>
<td>
<Button.Checkbox
checked={group.should_show}
onClick={() => act('toggle_show_group', {
group: group.group,
})} />
</td>
</tr>
))}
</Table>
</Section>
</Window.Content>
</Box>
</Window>
);
};

File diff suppressed because one or more lines are too long