Reduces species feature boilerplate (#93570)

## About The Pull Request

Rather than having 100 separate list variables on `SSaccessories`, have
1 list for all feature keys that are associated with sprite accessories

This way you can get a feature by doing
`SSaccessories.feature_list[key]`, instead of necessitating
`SSaccessories.ears_list`, `SSaccessories.tail_list`, etc.

This lets us cut back on a lot of boilerplate in prefs, dna, and organs

## Why It's Good For The Game

We can see the benefit in this example: This is all the code for horn
DNA, bodypart overlay, and preference
```dm
/datum/dna_block/feature/accessory/horn
	feature_key = FEATURE_HORNS
```
```dm
/datum/bodypart_overlay/mutant/horns
	layers = EXTERNAL_ADJACENT
	feature_key = FEATURE_HORNS
	dyable = TRUE

/datum/bodypart_overlay/mutant/horns/can_draw_on_bodypart(obj/item/bodypart/bodypart_owner)
	return !(bodypart_owner.owner?.obscured_slots & HIDEHAIR)
```
```dm
/datum/preference/choiced/species_feature/lizard_horns
	savefile_key = "feature_lizard_horns"
	savefile_identifier = PREFERENCE_CHARACTER
	category = PREFERENCE_CATEGORY_FEATURES
	main_feature_name = "Horns"
	should_generate_icons = TRUE
	relevant_organ = /obj/item/organ/horns

/datum/preference/choiced/species_feature/lizard_horns/icon_for(value)
	return generate_lizard_side_shot(get_accessory_for_value(value), "horns")
```

## Changelog

🆑 Melbert
refactor: Refactored species unique organs slightly, particularly how
they are set up at game start. Report any oddities, like invisible tails
or wings
/🆑

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
MrMelbert
2025-10-30 03:46:32 +01:00
committed by GitHub
co-authored by Ghom
parent 340f9d5fe8
commit 585b02c325
30 changed files with 181 additions and 374 deletions
@@ -219,8 +219,7 @@
var/list/radial_wings = list()
var/list/name2type = list()
for(var/obj/item/organ/wings/functional/possible_type as anything in wing_types)
var/datum/sprite_accessory/accessory = initial(possible_type.sprite_accessory_override) //get the type
accessory = SSaccessories.wings_list[initial(accessory.name)] //get the singleton instance
var/datum/sprite_accessory/accessory = SSaccessories.feature_list[FEATURE_WINGS][possible_type::sprite_accessory_override::name] //get the singleton instance
var/image/img = image(icon = accessory.icon, icon_state = "m_wingsopen_[accessory.icon_state]_BEHIND") //Process the HUD elements
img.transform *= 0.5
img.pixel_w = -32