diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 805592f6887..b30f1420596 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -45,8 +45,8 @@ name = "retro identification card" desc = "A card used to provide ID and determine access across the station." icon_state = "card_grey" - worn_icon_state = "card_retro" inhand_icon_state = "card-id" + worn_icon_state = "nothing" lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' slot_flags = ITEM_SLOT_ID @@ -880,7 +880,6 @@ name = "identification card" desc = "A card used to provide ID and determine access across the station. Has an integrated digital display and advanced microchips." icon_state = "card_grey" - worn_icon_state = "card_grey" wildcard_slots = WILDCARD_LIMIT_GREY flags_1 = UNPAINTABLE_1 @@ -1038,13 +1037,11 @@ name = "rainbow identification card" desc = "A rainbow card, promoting fun in a 'business proper' sense!" icon_state = "card_rainbow" - worn_icon_state = "card_rainbow" /obj/item/card/id/advanced/silver name = "silver identification card" desc = "A silver card which shows honour and dedication." icon_state = "card_silver" - worn_icon_state = "card_silver" inhand_icon_state = "silver_id" assigned_icon_state = "assigned_silver" wildcard_slots = WILDCARD_LIMIT_SILVER @@ -1063,7 +1060,6 @@ name = "gold identification card" desc = "A golden card which shows power and might." icon_state = "card_gold" - worn_icon_state = "card_gold" inhand_icon_state = "gold_id" assigned_icon_state = "assigned_gold" wildcard_slots = WILDCARD_LIMIT_GOLD @@ -1090,7 +1086,6 @@ name = "\improper CentCom ID" desc = "An ID straight from Central Command." icon_state = "card_centcom" - worn_icon_state = "card_centcom" assigned_icon_state = "assigned_centcom" registered_name = JOB_CENTCOM registered_age = null @@ -1136,7 +1131,6 @@ name = "black identification card" desc = "This card is telling you one thing and one thing alone. The person holding this card is an utter badass." icon_state = "card_black" - worn_icon_state = "card_black" assigned_icon_state = "assigned_syndicate" wildcard_slots = WILDCARD_LIMIT_GOLD @@ -1186,7 +1180,6 @@ name = "\improper Debug ID" desc = "A debug ID card. Has ALL the all access, you really shouldn't have this." icon_state = "card_centcom" - worn_icon_state = "card_centcom" assigned_icon_state = "assigned_centcom" trim = /datum/id_trim/admin wildcard_slots = WILDCARD_LIMIT_ADMIN @@ -1199,7 +1192,6 @@ name = "prisoner ID card" desc = "You are a number, you are not a free man." icon_state = "card_prisoner" - worn_icon_state = "card_prisoner" inhand_icon_state = "orange-id" lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' @@ -1312,7 +1304,6 @@ registered_name = "Highlander" desc = "There can be only one!" icon_state = "card_black" - worn_icon_state = "card_black" assigned_icon_state = "assigned_syndicate" trim = /datum/id_trim/highlander wildcard_slots = WILDCARD_LIMIT_ADMIN @@ -1605,7 +1596,6 @@ /// A special variant of the classic chameleon ID card which accepts all access. /obj/item/card/id/advanced/chameleon/black icon_state = "card_black" - worn_icon_state = "card_black" assigned_icon_state = "assigned_syndicate" wildcard_slots = WILDCARD_LIMIT_GOLD diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 95f321e7171..0e55a8f7087 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -204,6 +204,7 @@ desc = "A hand-held long-range environmental scanner which reports current gas levels." name = "long-range gas analyzer" icon_state = "analyzerranged" + worn_icon_state = "analyzer" w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron = 100, /datum/material/glass = 20, /datum/material/gold = 300, /datum/material/bluespace=200) grind_results = list(/datum/reagent/mercury = 5, /datum/reagent/iron = 5, /datum/reagent/silicon = 5) diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index 89df0b9db49..49bbc14f8d6 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -135,7 +135,7 @@ desc = "An ominous card that contains the location of the station, and when applied to a communications console, \ the ability to long-distance contact the Syndicate fleet." icon_state = "battlecruisercaller" - worn_icon_state = "battlecruisercaller" + worn_icon_state = "emag" ///whether we have called the battlecruiser var/used = FALSE /// The battlecruiser team that the battlecruiser will get added to diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 23d8ee44831..9b143fa5728 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -272,6 +272,7 @@ name = "Crusader's Hood" desc = "A brownish hood." icon = 'icons/obj/clothing/head/chaplain.dmi' + worn_icon = 'icons/mob/clothing/head/chaplain.dmi' icon_state = "crusader" inhand_icon_state = null w_class = WEIGHT_CLASS_NORMAL @@ -300,6 +301,7 @@ name = "Prophet's Hat" desc = "A religious-looking hat." icon_state = null + worn_icon = 'icons/mob/clothing/head/helmet.dmi' inhand_icon_state = null flags_1 = 0 armor_type = /datum/armor/crusader_prophet diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm index 413b319eb09..13f321b5106 100644 --- a/code/game/objects/items/storage/wallets.dm +++ b/code/game/objects/items/storage/wallets.dm @@ -151,6 +151,7 @@ /obj/item/storage/wallet/random icon_state = "random_wallet" // for mapping purposes + worn_icon_state = "wallet" /obj/item/storage/wallet/random/Initialize(mapload) . = ..() diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 71eb2819196..ce83258a28a 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -338,6 +338,7 @@ LINEN BINS name = "random bedsheet" desc = "If you're reading this description ingame, something has gone wrong! Honk!" bedsheet_type = BEDSHEET_ABSTRACT + item_flags = ABSTRACT var/static/list/bedsheet_list var/spawn_type = BEDSHEET_SINGLE @@ -364,6 +365,7 @@ LINEN BINS name = "random dorms bedsheet" desc = "If you're reading this description ingame, something has gone wrong! Honk!" bedsheet_type = BEDSHEET_DOUBLE + item_flags = ABSTRACT slot_flags = null /obj/item/bedsheet/dorms/Initialize(mapload) @@ -545,6 +547,7 @@ LINEN BINS /obj/item/bedsheet/dorms_double icon_state = "random_bedsheet" + item_flags = ABSTRACT bedsheet_type = BEDSHEET_ABSTRACT /obj/item/bedsheet/dorms_double/Initialize(mapload) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 4560c986a37..01930613fd9 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -476,6 +476,7 @@ name = "flesh mass" icon_state = "lingspacesuit_t" icon = 'icons/obj/clothing/suits/costume.dmi' + worn_icon = 'icons/mob/clothing/suits/costume.dmi' desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel." item_flags = DROPDEL clothing_flags = STOPSPRESSUREDAMAGE //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it, it still ends up in your blood. (also balance but muh fluff) diff --git a/code/modules/hydroponics/grown/rainbow_bunch.dm b/code/modules/hydroponics/grown/rainbow_bunch.dm index 91c6aae2cfa..14d0648b666 100644 --- a/code/modules/hydroponics/grown/rainbow_bunch.dm +++ b/code/modules/hydroponics/grown/rainbow_bunch.dm @@ -33,12 +33,13 @@ throw_range = 3 attack_verb_continuous = list("pompfs") attack_verb_simple = list("pompf") + greyscale_colors = "#000000" //only here for unit testing. overriden in initialize() greyscale_config = /datum/greyscale_config/flower_simple greyscale_config_worn = /datum/greyscale_config/flower_simple_worn /obj/item/food/grown/rainbow_flower/Initialize(mapload) . = ..() - if(greyscale_colors) + if(greyscale_colors != initial(greyscale_colors)) return var/flower_color = rand(1,8) diff --git a/code/modules/instruments/piano_synth.dm b/code/modules/instruments/piano_synth.dm index 630bf8819dd..416d164cac0 100644 --- a/code/modules/instruments/piano_synth.dm +++ b/code/modules/instruments/piano_synth.dm @@ -56,6 +56,7 @@ name = "\improper Nanotrasen space pods" desc = "Flex your money, AND ignore what everyone else says, all at once!" icon_state = "spacepods" + worn_icon = 'icons/mob/clothing/ears.dmi' inhand_icon_state = null slot_flags = ITEM_SLOT_EARS strip_delay = 100 //air pods don't fall out diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index 50929e504e5..aa92c242850 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -147,7 +147,7 @@ There are several things that need to be remembered: var/icon_file if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item))) - icon_file = 'icons/mob/simple/mob.dmi' + icon_file = 'icons/mob/clothing/id.dmi' id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 9f0a25b8886..2e48818bb10 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -260,7 +260,7 @@ desc = "Used to set the destination of properly wrapped packages." icon = 'icons/obj/device.dmi' icon_state = "cargo tagger" - worn_icon_state = "cargo tagger" + worn_icon_state = "cargotagger" var/currTag = 0 //Destinations are stored in code\globalvars\lists\flavor_misc.dm var/locked_destination = FALSE //if true, users can't open the destination tag window to prevent changing the tagger's current destination w_class = WEIGHT_CLASS_TINY diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 2b934bf479e..59a4e947550 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -208,6 +208,7 @@ #include "verify_config_tags.dm" #include "verify_emoji_names.dm" #include "wizard_loadout.dm" +#include "worn_icons.dm" #ifdef REFERENCE_TRACKING_DEBUG //Don't try and parse this file if ref tracking isn't turned on. IE: don't parse ref tracking please mr linter #include "find_reference_sanity.dm" #endif diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cardboard.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cardboard.png index 4d5f458fd9f..ba4d67ad07f 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cardboard.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_golem_cardboard.png differ diff --git a/code/modules/unit_tests/worn_icons.dm b/code/modules/unit_tests/worn_icons.dm new file mode 100644 index 00000000000..ce1b0540249 --- /dev/null +++ b/code/modules/unit_tests/worn_icons.dm @@ -0,0 +1,117 @@ +/// Makes sure suit slot items aren't using CS:S fallbacks. +/datum/unit_test/worn_icons + var/static/list/possible_icon_states = list() + /// additional_icon_location is for downstream modularity support for finding missing sprites in additonal DMI file locations. + /// Make sure this location is also present in tools/deploy.sh + /// If you need additional paths ontop of this second one, you can add another generate_possible_icon_states_list("your/folder/path/") below the if(additional_icon_location) block in Run(), and make sure to add that path to tools/deploy.sh as well. + var/additional_icon_location = null + +/datum/unit_test/worn_icons/proc/generate_possible_icon_states_list(directory_path) + if(!directory_path) + directory_path = "icons/mob/clothing/" + for(var/file_path in flist(directory_path)) + if(findtext(file_path, ".dmi")) + for(var/sprite_icon in icon_states("[directory_path][file_path]", 1)) //2nd arg = 1 enables 64x64+ icon support, otherwise you'll end up with "sword0_1" instead of "sword" + possible_icon_states[sprite_icon] += list("[directory_path][file_path]") + else + possible_icon_states += generate_possible_icon_states_list("[directory_path][file_path]") + +/datum/unit_test/worn_icons/Run() + generate_possible_icon_states_list() + if(additional_icon_location) + generate_possible_icon_states_list(additional_icon_location) + + var/list/already_warned_icons = list() + + for(var/obj/item/item_path as anything in (subtypesof(/obj/item) - typesof(/obj/item/mod))) + var/cached_slot_flags = initial(item_path.slot_flags) + if(!cached_slot_flags || (cached_slot_flags & ITEM_SLOT_LPOCKET) || (cached_slot_flags & ITEM_SLOT_RPOCKET) || initial(item_path.item_flags) & ABSTRACT) + continue + + + if(initial(item_path.greyscale_colors) && initial(item_path.greyscale_config)) //GAGS has its own unit test. + continue + + var/worn_icon = initial(item_path.worn_icon) //override icon file. where our sprite is contained if set. (ie modularity stuff) + var/worn_icon_state = initial(item_path.worn_icon_state) //overrides icon_state. + var/icon_state = worn_icon_state || initial(item_path.icon_state) //icon_state. what sprite name we are looking for. + + + if(isnull(icon_state)) + continue //no sprite for the item. + if(icon_state in already_warned_icons) + continue + + var/match_message + if(icon_state in possible_icon_states) + for(var/file_place in possible_icon_states[icon_state]) + match_message += (match_message ? " & '[file_place]'" : " - Matching sprite found in: '[file_place]'") + + if(worn_icon) //easiest to check since we override everything. this automatically includes downstream support. + if(!(icon_state in icon_states(worn_icon, 1))) + TEST_FAIL("[item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in worn_icon override file, '[worn_icon]'[match_message]") + continue + + var/icon_file //checks against all the default icon locations if one isn't defined. + var/fail_reasons + var/spacer + if(cached_slot_flags & ITEM_SLOT_BACK) + icon_file = 'icons/mob/clothing/back.dmi' + + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_ID) + icon_file = 'icons/mob/clothing/id.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_GLOVES) + icon_file = 'icons/mob/clothing/hands.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_EYES) + icon_file = 'icons/mob/clothing/eyes.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_EARS) + icon_file = 'icons/mob/clothing/ears.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_NECK) + icon_file = 'icons/mob/clothing/neck.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_MASK) + icon_file = 'icons/mob/clothing/mask.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(cached_slot_flags & ITEM_SLOT_BELT) + icon_file = 'icons/mob/clothing/belt.dmi' + if(!(icon_state in icon_states(icon_file, 1))) + already_warned_icons += icon_state + fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]" + spacer = "\n\t" + + if(fail_reasons) + TEST_FAIL(fail_reasons) + diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 21d49fc738c..1de907be97c 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index 6c0e5014909..3bb1c17e35d 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/id.dmi b/icons/mob/clothing/id.dmi index 1b3f320c753..d5ed308f5d9 100644 Binary files a/icons/mob/clothing/id.dmi and b/icons/mob/clothing/id.dmi differ diff --git a/icons/mob/clothing/id_card.dmi b/icons/mob/clothing/id_card.dmi deleted file mode 100644 index ab573279f30..00000000000 Binary files a/icons/mob/clothing/id_card.dmi and /dev/null differ diff --git a/tools/deploy.sh b/tools/deploy.sh index 8a0cf9d29a3..b91eee1331e 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -11,9 +11,10 @@ fi mkdir -p \ $1/_maps \ - $1/icons/effects \ - $1/icons/mob/clothing \ + $1/icons/effects \ + $1/icons/mob/clothing \ $1/icons/mob/inhands \ + $1/icons/mob/simple \ $1/icons/obj \ $1/icons/runtime \ $1/sound/runtime \ @@ -31,6 +32,7 @@ cp -r _maps/* $1/_maps/ cp -r icons/effects/* $1/icons/effects/ cp -r icons/mob/clothing/* $1/icons/mob/clothing/ cp -r icons/mob/inhands/* $1/icons/mob/inhands/ +cp -r icons/mob/simple/* $1/icons/mob/simple/ cp -r icons/obj/* $1/icons/obj/ cp -r icons/runtime/* $1/icons/runtime/ cp -r sound/runtime/* $1/sound/runtime/