Adds automatic GAGS icon generation for mapping and the loadout menu (#90940)

## About The Pull Request

Revival of https://github.com/tgstation/tgstation/pull/86482, which is
even more doable now that we have rustg iconforge generation.

What this PR does:

- Sets up every single GAGS icon in the game to have their own preview
icon autogenerated during compile. This is configurable to not run
during live. The icons are created in `icons/map_icons/..`
- This also has the side effect of providing accurate GAGS icons for
things like the loadout menu. No more having to create your own
previews.


![FOuGL6ofxC](https://github.com/user-attachments/assets/e5414971-7f13-4883-9f7f-a8a212b46fe8)

<details><summary>Mappers rejoice!</summary>


![StrongDMM_1oeMSoRHXT](https://github.com/user-attachments/assets/83dcfe4c-31be-4953-98f3-dff90268bbc4)


![StrongDMM_uyqu3CggPn](https://github.com/user-attachments/assets/7896f99e-2656-40e1-a9da-3a513882365a)

</details>

<details><summary>Uses iconforge so it does not take up much time during
init</summary>


![dreamdaemon_u4Md3Dqwge](https://github.com/user-attachments/assets/17baaff8-5d5e-4a4d-ba8f-9dd548024155)

</details>

---

### Copied from https://github.com/tgstation/tgstation/pull/86482 as
this still applies:

Note for Spriters:

After you've assigned the correct values to vars, you must run the game
through init on your local machine and commit the changes to the map
icon dmi files. Unit tests should catch all cases of forgetting to
assign the correct vars, or not running through init.

Note for Server Operators:

In order to not generate these icons on live I've added a new config
entry which should be disabled on live called GENERATE_ASSETS_IN_INIT in
the config.txt


## Why It's Good For The Game

No more error icons in SDMM and loadout.

## Changelog

🆑
refactor: preview icons for greyscale items are now automatically
generated, meaning you can see GAGS as they actually appear ingame while
mapping or viewing the loadout menu.
/🆑

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
This commit is contained in:
Bloop
2025-05-24 15:21:02 -07:00
committed by GitHub
co-authored by LemonInTheDark
parent 57b964a484
commit cb51a652a9
143 changed files with 1198 additions and 444 deletions
@@ -1,8 +1,9 @@
/obj/item/quantum_keycard
name = "quantum keycard"
desc = "A keycard able to link to a quantum pad's particle signature, allowing other quantum pads to travel there instead of their linked pad."
icon = 'icons/obj/devices/tool.dmi'
icon_state = "quantum_keycard_gags"
icon = 'icons/map_icons/items/_item.dmi'
icon_state = "/obj/item/quantum_keycard"
post_init_icon_state = "quantum_keycard_gags"
greyscale_config = /datum/greyscale_config/quantum_keycard
greyscale_colors = COLOR_WHITE
inhand_icon_state = "card-id"
@@ -1,11 +1,12 @@
/obj/item/encryptionkey
name = "standard encryption key"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey"
post_init_icon_state = "cypherkey_basic"
desc = "An encryption key for a radio headset."
icon = 'icons/obj/devices/circuitry_n_data.dmi'
icon_state = "cypherkey_basic"
icon_preview = 'icons/obj/fluff/previews.dmi'
icon_state_preview = "cypherkey"
w_class = WEIGHT_CLASS_TINY
greyscale_config = /datum/greyscale_config/encryptionkey_basic
greyscale_colors = "#820a16#3758c4"
/// What channels does this encryption key grant to the parent headset.
var/list/channels = list()
/// Flags for which "special" radio networks should be accessible
@@ -13,9 +14,6 @@
/// Assoc list of language to how well understood it is. 0 is invalid, 100 is perfect.
var/list/language_data
greyscale_config = /datum/greyscale_config/encryptionkey_basic
greyscale_colors = "#820a16#3758c4"
/obj/item/encryptionkey/examine(mob/user)
. = ..()
if(!LAZYLEN(channels) && !(special_channels & RADIO_SPECIAL_BINARY) && !LAZYLEN(language_data))
@@ -49,7 +47,9 @@
/obj/item/encryptionkey/syndicate
name = "syndicate encryption key"
icon_state = "cypherkey_syndicate"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/syndicate"
post_init_icon_state = "cypherkey_syndicate"
channels = list(RADIO_CHANNEL_SYNDICATE = 1)
special_channels = RADIO_SPECIAL_SYNDIE
greyscale_config = /datum/greyscale_config/encryptionkey_syndicate
@@ -57,7 +57,9 @@
/obj/item/encryptionkey/binary
name = "binary translator key"
icon_state = "cypherkey_basic"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/binary"
post_init_icon_state = "cypherkey_basic"
special_channels = RADIO_SPECIAL_BINARY
language_data = list(
/datum/language/machine = 100,
@@ -67,153 +69,199 @@
/obj/item/encryptionkey/headset_sec
name = "security radio encryption key"
icon_state = "cypherkey_security"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_sec"
post_init_icon_state = "cypherkey_security"
channels = list(RADIO_CHANNEL_SECURITY = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_security
greyscale_colors = "#820a16#280b1a"
/obj/item/encryptionkey/headset_eng
name = "engineering radio encryption key"
icon_state = "cypherkey_engineering"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_eng"
post_init_icon_state = "cypherkey_engineering"
channels = list(RADIO_CHANNEL_ENGINEERING = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_engineering
greyscale_colors = "#f8d860#dca01b"
/obj/item/encryptionkey/headset_rob
name = "robotics radio encryption key"
icon_state = "cypherkey_engineering"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_rob"
post_init_icon_state = "cypherkey_engineering"
channels = list(RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_ENGINEERING = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_engineering
greyscale_colors = "#793a80#dca01b"
/obj/item/encryptionkey/headset_med
name = "medical radio encryption key"
icon_state = "cypherkey_medical"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_med"
post_init_icon_state = "cypherkey_medical"
channels = list(RADIO_CHANNEL_MEDICAL = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_medical
greyscale_colors = "#ebebeb#69abd1"
/obj/item/encryptionkey/headset_sci
name = "science radio encryption key"
icon_state = "cypherkey_research"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_sci"
post_init_icon_state = "cypherkey_research"
channels = list(RADIO_CHANNEL_SCIENCE = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_research
greyscale_colors = "#793a80#bc4a9b"
/obj/item/encryptionkey/headset_medsci
name = "medical research radio encryption key"
icon_state = "cypherkey_medical"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_medsci"
post_init_icon_state = "cypherkey_medical"
channels = list(RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_MEDICAL = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_medical
greyscale_colors = "#ebebeb#9d1de8"
/obj/item/encryptionkey/headset_srvsec
name = "law and order radio encryption key"
icon_state = "cypherkey_service"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_srvsec"
post_init_icon_state = "cypherkey_service"
channels = list(RADIO_CHANNEL_SERVICE = 1, RADIO_CHANNEL_SECURITY = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_service
greyscale_colors = "#820a16#3bca5a"
/obj/item/encryptionkey/headset_srvmed
name = "psychology radio encryption key"
icon_state = "cypherkey_service"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_srvmed"
post_init_icon_state = "cypherkey_service"
channels = list(RADIO_CHANNEL_MEDICAL = 1, RADIO_CHANNEL_SERVICE = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_service
greyscale_colors = "#ebebeb#3bca5a"
/obj/item/encryptionkey/headset_srvent
name = "press radio encryption key"
icon_state = "cypherkey_service"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_srvent"
post_init_icon_state = "cypherkey_service"
channels = list(RADIO_CHANNEL_SERVICE = 1, RADIO_CHANNEL_ENTERTAINMENT = 0)
greyscale_config = /datum/greyscale_config/encryptionkey_service
greyscale_colors = "#83eb8f#3bca5a"
/obj/item/encryptionkey/headset_com
name = "command radio encryption key"
icon_state = "cypherkey_cube"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_com"
post_init_icon_state = "cypherkey_cube"
channels = list(RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_cube
greyscale_colors = "#2b2793#67a552"
/obj/item/encryptionkey/heads
flags_1 = parent_type::flags_1 | NO_NEW_GAGS_PREVIEW_1
/obj/item/encryptionkey/heads/captain
name = "\proper the captain's encryption key"
icon_state = "cypherkey_cube"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/captain"
post_init_icon_state = "cypherkey_cube"
channels = list(RADIO_CHANNEL_COMMAND = 1, RADIO_CHANNEL_SECURITY = 1, RADIO_CHANNEL_ENGINEERING = 0, RADIO_CHANNEL_SCIENCE = 0, RADIO_CHANNEL_MEDICAL = 0, RADIO_CHANNEL_SUPPLY = 0, RADIO_CHANNEL_SERVICE = 0)
greyscale_config = /datum/greyscale_config/encryptionkey_cube
greyscale_colors = "#2b2793#dca01b"
/obj/item/encryptionkey/heads/rd
name = "\proper the research director's encryption key"
icon_state = "cypherkey_research"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/rd"
post_init_icon_state = "cypherkey_research"
channels = list(RADIO_CHANNEL_SCIENCE = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_research
greyscale_colors = "#bc4a9b#793a80"
/obj/item/encryptionkey/heads/hos
name = "\proper the head of security's encryption key"
icon_state = "cypherkey_security"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/hos"
post_init_icon_state = "cypherkey_security"
channels = list(RADIO_CHANNEL_SECURITY = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_security
greyscale_colors = "#280b1a#820a16"
/obj/item/encryptionkey/heads/ce
name = "\proper the chief engineer's encryption key"
icon_state = "cypherkey_engineering"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/ce"
post_init_icon_state = "cypherkey_engineering"
channels = list(RADIO_CHANNEL_ENGINEERING = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_engineering
greyscale_colors = "#dca01b#f8d860"
/obj/item/encryptionkey/heads/cmo
name = "\proper the chief medical officer's encryption key"
icon_state = "cypherkey_medical"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/cmo"
post_init_icon_state = "cypherkey_medical"
channels = list(RADIO_CHANNEL_MEDICAL = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_medical
greyscale_colors = "#ebebeb#2b2793"
/obj/item/encryptionkey/heads/hop
name = "\proper the head of personnel's encryption key"
icon_state = "cypherkey_cube"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/hop"
post_init_icon_state = "cypherkey_cube"
channels = list(RADIO_CHANNEL_SERVICE = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_cube
greyscale_colors = "#2b2793#c2c1c9"
/obj/item/encryptionkey/heads/qm
name = "\proper the quartermaster's encryption key"
icon_state = "cypherkey_cargo"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/heads/qm"
post_init_icon_state = "cypherkey_cargo"
channels = list(RADIO_CHANNEL_SUPPLY = 1, RADIO_CHANNEL_COMMAND = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_cargo
greyscale_colors = "#49241a#dca01b"
/obj/item/encryptionkey/headset_cargo
name = "supply radio encryption key"
icon_state = "cypherkey_cargo"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_cargo"
post_init_icon_state = "cypherkey_cargo"
channels = list(RADIO_CHANNEL_SUPPLY = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_cargo
greyscale_colors = "#49241a#7b3f2e"
/obj/item/encryptionkey/headset_mining
name = "mining radio encryption key"
icon_state = "cypherkey_cargo"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_mining"
post_init_icon_state = "cypherkey_cargo"
channels = list(RADIO_CHANNEL_SUPPLY = 1, RADIO_CHANNEL_SCIENCE = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_cargo
greyscale_colors = "#49241a#bc4a9b"
/obj/item/encryptionkey/headset_service
name = "service radio encryption key"
icon_state = "cypherkey_service"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_service"
post_init_icon_state = "cypherkey_service"
channels = list(RADIO_CHANNEL_SERVICE = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_service
greyscale_colors = "#3758c4#3bca5a"
/obj/item/encryptionkey/headset_cent
name = "\improper CentCom radio encryption key"
icon_state = "cypherkey_centcom"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/headset_cent"
post_init_icon_state = "cypherkey_centcom"
special_channels = RADIO_SPECIAL_CENTCOM
channels = list(RADIO_CHANNEL_CENTCOM = 1)
greyscale_config = /datum/greyscale_config/encryptionkey_centcom
greyscale_colors = "#24a157#dca01b"
/obj/item/encryptionkey/ai //ported from NT, this goes 'inside' the AI.
flags_1 = parent_type::flags_1 | NO_NEW_GAGS_PREVIEW_1
channels = list(
RADIO_CHANNEL_COMMAND = 1,
RADIO_CHANNEL_SECURITY = 1,
@@ -228,6 +276,7 @@
/obj/item/encryptionkey/ai_with_binary
name = "ai encryption key"
flags_1 = parent_type::flags_1 | NO_NEW_GAGS_PREVIEW_1
channels = list(
RADIO_CHANNEL_COMMAND = 1,
RADIO_CHANNEL_SECURITY = 1,
@@ -246,7 +295,9 @@
/obj/item/encryptionkey/ai/evil //ported from NT, this goes 'inside' the AI.
name = "syndicate binary encryption key"
icon_state = "cypherkey_syndicate"
icon = 'icons/map_icons/items/encryptionkey.dmi'
icon_state = "/obj/item/encryptionkey/ai_with_binary"
post_init_icon_state = "cypherkey_syndicate"
channels = list(RADIO_CHANNEL_SYNDICATE = 1)
special_channels = RADIO_SPECIAL_SYNDIE
greyscale_config = /datum/greyscale_config/encryptionkey_syndicate