Bravo Six, Going Dark: Refactors client colors to fix dupe issues and support filters (#89843)

## About The Pull Request

Completely refactored how client colors are handled. Now they're similar
to traits, having a source associated with them. Instead of adding and
removing by strict type (which makes client colors prone to getting
duplicated and not cleaned up) you remove a filter associated with a
specific source. Adding another client color with the same source as an
already existing one will replace the existing one if its of a different
type, or do nothing if they're the same (unless force is set to TRUE).
Client colors can also force filter splitting, putting all colors that
come before them, themselves, and all colors after them into separate
filters - this is useful to prevent mixing in filters which are supposed
to remove a certain color.

<details>

<summary>Example of how Perceptomatrix and nightmare vision goggles
combined before this PR:</summary>


![dreamseeker_fBOse2i0jq](https://github.com/user-attachments/assets/fb164e1f-ce8b-4a8c-8820-5db25e710056)

And this is after, as you can see nightmare vision effect's red is only
slightly tinted by perceptomatix instead of being literally halved.


![dreamseeker_U6A24fetK8](https://github.com/user-attachments/assets/8d8b3eb5-9f53-4646-bc56-0f5897013c6f)

</details>

Additionally, added support for custom filters (and not just colors) to
client color code to allow us to work with more colorspaces.

Also fixed weird blindness behavior, so this also 
Closes #89787

## Why It's Good For The Game

Makes code less ass to work with, fixes weird color mixing, etc.

## Changelog
🆑
fix: Fixed perceptomatix helmet allowing you to see even when
unconscious
refactor: Refactored how client colors are handled, ensuring that
certain effects like nightmare goggles don't disappear when another
vision-affecting piece of clothing is worn.
/🆑
This commit is contained in:
SmArtKar
2025-03-17 11:35:11 +00:00
committed by GitHub
parent 54e1428806
commit 845ed7459e
24 changed files with 322 additions and 271 deletions
+2 -2
View File
@@ -52,14 +52,14 @@
// Check for the status effect, duh
TEST_ASSERT(dummy.is_blind(), "Dummy, [status_message], did not have the blind status effect.")
// Being more technical, we need to check for client color and screen overlays
TEST_ASSERT(HAS_CLIENT_COLOR(dummy, /datum/client_colour/monochrome/blind), "Dummy, [status_message], did not have the monochrome client color.")
TEST_ASSERT(HAS_CLIENT_COLOR(dummy, /datum/client_colour/monochrome), "Dummy, [status_message], did not have the monochrome client color.")
TEST_ASSERT(HAS_SCREEN_OVERLAY(dummy, /atom/movable/screen/fullscreen/blind), "Dummy, [status_message], did not have a blind screen overlay in their list of screens.")
/datum/unit_test/blindness/proc/check_if_not_blind(mob/living/carbon/human/dummy, status_message = "after being cured of blindness")
// Check for no status effect
TEST_ASSERT(!dummy.is_blind(), "Dummy, [status_message], still had the blindness status effect.")
// Check that the client color and screen overlay are gone
TEST_ASSERT(!HAS_CLIENT_COLOR(dummy, /datum/client_colour/monochrome/blind), "Dummy, [status_message], still had the monochrome client color.")
TEST_ASSERT(!HAS_CLIENT_COLOR(dummy, /datum/client_colour/monochrome), "Dummy, [status_message], still had the monochrome client color.")
TEST_ASSERT(!HAS_SCREEN_OVERLAY(dummy, /atom/movable/screen/fullscreen/blind), "Dummy, [status_message], still had the blind sceen overlay.")
/**
+8 -2
View File
@@ -5,5 +5,11 @@
for(var/datum/client_colour/colour as anything in subtypesof(/datum/client_colour))
// colours can be color matrices (lists), which initial() cannot read.
colour = new colour
if(!color_to_full_rgba_matrix(colour.colour, FALSE))
TEST_FAIL("[colour.type] has an invalid default colour value: [colour.colour]")
if (islist(colour.color))
var/list/potential_filter = colour.color
// If our list has "type" in it then its a filter, ignore that
if (potential_filter["type"])
continue
if(!color_to_full_rgba_matrix(colour.color, FALSE))
TEST_FAIL("[colour.type] has an invalid default colour value: [colour.color]")