Files
fulpstation/code/__HELPERS/colors.dm
A miscellaneous Fern 9bd86e85b5 June/July TGU: Loadout menu, flatpackers and... whatever else! (#1230)
* Initial Commit

* Not quite all was staged, apparently.

* Multiline no longer necessary

* For my convenience...

* Forgot an important little tidbit in routes.tsx

* This updated, apparently.

* And now hell breaks loose

* First batch

* Second Batch

* Third batch (Unit Tests)

* Improvised shotgun ammo is gone; Vibebots are refactored

* UpdatePath sweeps in our fulp_modules/_maps folder

* I can't bring myself to do it.

* Map stuff

* Didn't mean to leave this uncommented

* I carpet-bombed them with Find-Replace. Let's see what linters think

* I sure do hope this is comprehensive and doesn't break other things

* This may take a while

* Next Round

* Hopefully the last batch before getting on with actual fixes

* Telescreens

* :/

* Stragglers

* Helio Emergency Shuttle; NearStation adjustments.

* Only one more commit for greenchecks... Shuttle code be dammed.

* Pff, the file was missing

* Same treatment as the other map files.

* Missed a comma :P

* BZ chambers for Xenobiology

* Odd. Most of these got done earlier. Not sure why this one wasn't.

* Mapping sweep. I didn't adjust C_tags in Theia. Another time.

* The balloon alerts overlap

* I hate TGU I hate TGU

* I meant to say "I hate TG" on the last one. Freudian slip.

* Fix Fix

* Nanite research cost rebalance

* TGU-Update: Step 0

* Yeah I figured it'd do this.

* I accidentally undid this

* Failed to catch this one

* I don't trust hundredths not to break or be broken somewhere.

* Little air alarm tweaks

* Ports #1228

* Stuff I missed

* Silly

* TGU so nice we're going to make it thrice

* Yarn

* Should be all? Fixes cult stun too.

* Thermomachine layers

* Free square spellcheck to rerun tests and see if it's consistent

* All credit goes to QLA for reminding me to actually do this

* Update to e40becd742

* github folder
2024-08-06 20:17:51 -04:00

151 lines
5.6 KiB
Plaintext

/// Given a color in the format of "#RRGGBB", will return if the color
/// is dark.
/proc/is_color_dark(color, threshold = 25)
var/hsl = rgb2num(color, COLORSPACE_HSL)
return hsl[3] < threshold
/// Given a 3 character color (no hash), converts it into #RRGGBB (with hash)
/proc/expand_three_digit_color(color)
if (length_char(color) != 3)
CRASH("Invalid 3 digit color: [color]")
var/final_color = "#"
for (var/digit = 1 to 3)
final_color += copytext(color, digit, digit + 1)
final_color += copytext(color, digit, digit + 1)
return final_color
/// Given a color in the format of "#RRGGBB" or "#RRGGBBAA", gives back a 4 entry list with the number values of each
/proc/split_color(color)
var/list/output = rgb2num(color)
if(length(output) == 3)
output += 255
return output
///Returns a random color picked from a list, has 2 modes (0 and 1), mode 1 doesn't pick white, black or gray
/proc/random_colour(mode = 0)
switch(mode)
if(0)
return pick("white","black","gray","red","green","blue","brown","yellow","orange","darkred",
"crimson","lime","darkgreen","cyan","navy","teal","purple","indigo")
if(1)
return pick("red","green","blue","brown","yellow","orange","darkred","crimson",
"lime","darkgreen","cyan","navy","teal","purple","indigo")
else
return "white"
///Inverts the colour of an HTML string
/proc/invert_HTML_colour(HTMLstring)
if(!istext(HTMLstring))
CRASH("Given non-text argument!")
else if(length(HTMLstring) != 7)
CRASH("Given non-HTML argument!")
else if(length_char(HTMLstring) != 7)
CRASH("Given non-hex symbols in argument!")
var/list/color = rgb2num(HTMLstring)
return rgb(255 - color[1], 255 - color[2], 255 - color[3])
///Flash a color on the passed mob
/proc/flash_color(mob_or_client, flash_color=COLOR_CULT_RED, flash_time=20)
var/mob/flashed_mob
if(ismob(mob_or_client))
flashed_mob = mob_or_client
else if(istype(mob_or_client, /client))
var/client/flashed_client = mob_or_client
flashed_mob = flashed_client.mob
if(!istype(flashed_mob))
return
var/datum/client_colour/temp/temp_color = new(flashed_mob)
temp_color.colour = flash_color
temp_color.fade_in = flash_time * 0.25
temp_color.fade_out = flash_time * 0.25
QDEL_IN(temp_color, (flash_time * 0.5) + 1)
flashed_mob.add_client_colour(temp_color)
/// Blends together two colors (passed as 3 or 4 length lists) using the screen blend mode
/// Much like multiply, screen effects the brightness of the resulting color
/// Screen blend will always lighten the resulting color, since before multiplication we invert the colors
/// This makes our resulting output brighter instead of darker
/proc/blend_screen_color(list/first_color, list/second_color)
var/list/output = new /list(4)
// max out any non existant alphas
if(length(first_color) < 4)
first_color[4] = 255
if(length(second_color) < 4)
second_color[4] = 255
// time to do our blending
for(var/i in 1 to 4)
output[i] = (1 - (1 - first_color[i] / 255) * (1 - second_color[i] / 255)) * 255
return output
/// Used to blend together two different color cutoffs
/// Uses the screen blendmode under the hood, essentially just [/proc/blend_screen_color]
/// But paired down and modified to work for our color range
/// Accepts the color cutoffs as two 3 length list(0-100,...) arguments
/proc/blend_cutoff_colors(list/first_color, list/second_color)
// These runtimes usually mean that either the eye or the glasses have an incorrect color_cutoffs
ASSERT(first_color?.len == 3, "First color must be a 3 length list, received [json_encode(first_color)]")
ASSERT(second_color?.len == 3, "Second color must be a 3 length list, received [json_encode(second_color)]")
var/list/output = new /list(3)
// Invert the colors, multiply to "darken" (actually lights), then uninvert to get back to what we want
for(var/i in 1 to 3)
output[i] = (1 - (1 - first_color[i] / 100) * (1 - second_color[i] / 100)) * 100
return output
/**
* Gets a color for a name, will return the same color for a given string consistently within a round.atom
*
* Note that this proc aims to produce pastel-ish colors using the HSL colorspace. These seem to be favorable for displaying on the map.
*
* Arguments:
* * name - The name to generate a color for
* * sat_shift - A value between 0 and 1 that will be multiplied against the saturation
* * lum_shift - A value between 0 and 1 that will be multiplied against the luminescence
*/
/proc/colorize_string(name, sat_shift = 1, lum_shift = 1)
// seed to help randomness
var/static/rseed = rand(1,26)
// get hsl using the selected 6 characters of the md5 hash
var/hash = copytext(md5(name + GLOB.round_id), rseed, rseed + 6)
var/h = hex2num(copytext(hash, 1, 3)) * (360 / 255)
var/s = (hex2num(copytext(hash, 3, 5)) >> 2) * ((CM_COLOR_SAT_MAX - CM_COLOR_SAT_MIN) / 63) + CM_COLOR_SAT_MIN
var/l = (hex2num(copytext(hash, 5, 7)) >> 2) * ((CM_COLOR_LUM_MAX - CM_COLOR_LUM_MIN) / 63) + CM_COLOR_LUM_MIN
// adjust for shifts
s = clamp(s * sat_shift, 0, 1)
l = clamp(l * lum_shift, 0, 1)
// convert to rgb
var/h_int = round(h/60) // mapping each section of H to 60 degree sections
var/c = (1 - abs(2 * l - 1)) * s
var/x = c * (1 - abs((h / 60) % 2 - 1))
var/m = l - c * 0.5
x = (x + m) * 255
c = (c + m) * 255
m *= 255
switch(h_int)
if(0)
return "#[num2hex(c, 2)][num2hex(x, 2)][num2hex(m, 2)]"
if(1)
return "#[num2hex(x, 2)][num2hex(c, 2)][num2hex(m, 2)]"
if(2)
return "#[num2hex(m, 2)][num2hex(c, 2)][num2hex(x, 2)]"
if(3)
return "#[num2hex(m, 2)][num2hex(x, 2)][num2hex(c, 2)]"
if(4)
return "#[num2hex(x, 2)][num2hex(m, 2)][num2hex(c, 2)]"
if(5)
return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]"
#define RANDOM_COLOUR (rgb(rand(0,255),rand(0,255),rand(0,255)))