mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 12:26:35 +01:00
- separates the composition of cyborgs into modules, iconsets, chassis, upgrades - modules / chassis atm can provide items, so can upgrades; in the future we will want to probably generalize the item API a bit so components can work - chassis now can (unimplemented) easily be made to give different stats - reorganizes all the cyborg sprites - adds generalized item mounts with redirection support and tears out legacy cyborg items - entirely rebalances modules & writes some new lawsets in for future use --------- Co-authored-by: silicons <silicons@silicons.dev>
503 lines
22 KiB
Plaintext
503 lines
22 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2024 Citadel Station Developers *//
|
|
|
|
/**
|
|
* Item rendering system
|
|
* Procs in here can be called and overridden as needed, but you should know what you're doing
|
|
* if you choose to do so!
|
|
*
|
|
* * IF YOU ONLY CARE ABOUT MAKING A NEW ITEM OR ARE CONVERTING AN ITEM, JUST READ THIS!!
|
|
*
|
|
* 0. Do you want the on-mob icons to be *entirely* shared/defaulted? If so, why are you here?
|
|
* Use the old system, by putting your states into the default icons as defined in
|
|
* [code/modules/mob/inventory/slot_meta.dm]
|
|
* and setting inhand_state and worn_state so they're found.
|
|
* If you want to share *some* icons, read State Generation and
|
|
* use worn_icon, and inhand_icon to do what you need to do.
|
|
*
|
|
* !! If your sprite already exists in default icons, it will override what !!
|
|
* !! we do here. This is an unfortunate tradeoff of speed we have to make. !!
|
|
* !! Make sure to set worn_species_default to FALSE to stop this. !!
|
|
* ?? THIS IS SOMETIMES A GOOD THING. ??
|
|
* ?? There's common states available for inhands and some worn stuff. ??
|
|
* ?? You just need to set inhand_state and worn_state to use them! ??
|
|
*
|
|
* Otherwise, continue on with the rest of the steps, setting
|
|
* worn_render_flags = NONE
|
|
* to instruct the system to ignore default icons entirely.
|
|
*
|
|
* ?? A note on bitfields: worn_render_flags ??
|
|
* ?? Without getting into the nitty gritty, worn_render_flags control all ??
|
|
* ?? behavior and logic. When the guide below says "add" a flag of a certain ??
|
|
* ?? name to it, it means boolean OR it. ??
|
|
* ?? For noncoders, basically: to combine, say, WORN_RENDER_SLOT_ONE_FOR_ALL ??
|
|
* ?? and WORN_RENDER_INHAND_ONE_FOR_ALL, you just put a | between them, like so: ??
|
|
* ?? worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL | WORN_RENDER_INHAND_ONE_FOR_ALL ??
|
|
* ?? Congratulations, you used a bitfield. ??
|
|
*
|
|
* 1. Have a sensical place for your item's .dmi.
|
|
* e.g. /obj/item/pickaxe goes in icons/modules/mining/tools/pickaxe.dmi
|
|
* 2. Put what the item looks like in the world, and in your inventory, as the base state.
|
|
* e.g. a sprite of a pickaxe as state `pickaxe`. Set your item's icon_state to this,
|
|
* and its icon to the file you made.
|
|
* 3. Add inhands if needed with state_left and state_right.
|
|
* In this case, it'd be
|
|
* pickaxe_left
|
|
* pickaxe_right
|
|
* If you for some reason want it to use a singular state only when inhand,
|
|
* set worn_inhand_ignored to TRUE, and it'll render as pickaxe_all instead.
|
|
* 4. Does the item go in multiple slots and require multiple sprites?
|
|
* If not, add WORN_RENDER_SLOT_ONE_TO_ALL to worn_render_flags,
|
|
* and it'll render as pickaxe_all always.
|
|
* pickaxe_all
|
|
* If so, set states for each slot id, e.g. in this case,
|
|
* pickaxe_back
|
|
* pickaxe_belt
|
|
* A full list of slot ids are in [code/modules/mob/inventory/slot_meta.dm].
|
|
* 5. Do you care about bodytypes? If so, set worn_bodytypes to the bodytypes you want
|
|
* to implement with bitfield notation, aka
|
|
* worn_bodytypes = BODYTYPE_TESHARI | BODYTYPE_UNATHI
|
|
* Then, put in states for the bodytypes in question like so:
|
|
* pickaxe_back_teshari
|
|
* pickaxe_back_unathi
|
|
* A full list of available bodytypes and what the string keys for them are
|
|
* in [code/__DEFINES/inventory/bodytypes.dm].
|
|
* The default bodytypes, as well as any bodytypes that aren't explicitly set as implemented,
|
|
* do not get appended (e.g. if a human or vox puts it on it's still pickaxe_back)
|
|
* 6. Do you want the base state, in this case 'pickaxe', for on-mob generation
|
|
* to be different from icon_state? This is useful if you want to switch
|
|
* your item's icon state or worn state without impacting the others.
|
|
* If so, set overrides for worn (held in inventory slots) and inhand (held in hands)
|
|
* worn_state = "pickaxe_onbody"
|
|
* inhand_state = "pickaxe_onhand"
|
|
* like so. Generation for the previous parts will become
|
|
* pickaxe_onbody_back
|
|
* pickaxe_onbody_belt
|
|
* or in the example of "ignore slot"
|
|
* pickaxe_onbody_all
|
|
* and for inhands
|
|
* pickaxe_onhand_left
|
|
* pickaxe_onhand_right
|
|
* 7. Defaulting: In the case you want to default slot/inhands (usually one but not the other),
|
|
* simply add to worn_render_flags, depending on which:
|
|
* WORN_RENDER_SLOT_ALLOW_DEFAULT
|
|
* WORN_RENDER_INHAND_ALLOW_DEFAULt
|
|
* 8. Congratulations, you're done!
|
|
*
|
|
* * Overall Goal
|
|
* - Being able to stuff an entire item's assets in one icon
|
|
* - Otherwise being able to split an entire item's assets into modular folders
|
|
* - Generic inhands and slot icons go in general onmob item folders
|
|
* - Not forcing usage of something as asinine as suit.dmi
|
|
*
|
|
* * Limitations
|
|
* - inhand state only supports left and right; no weird index-based for now. this can easily change.
|
|
*
|
|
* * State Generation
|
|
* This is only pertinent to single-icon rendering, which the system falls back to
|
|
* if it can't find anything else. This is what people should be using for non-reused
|
|
* item sprites.
|
|
*
|
|
* This system also supports worn_icon and inhand_icon if you really want to split it up.
|
|
*
|
|
* Pattern:
|
|
*
|
|
* state_slot_bodytype, where
|
|
* state: (inhand_state if inhand, worn_state if not) || icon_state
|
|
* slot: the inventory slot's `render_key`, or null if worn slot is ignored
|
|
* if it's a hand, it'll be _left or _right if it's not ignored.
|
|
* bodytype: if not trampled, or ignored, the bodytype as string (see DEFINES)
|
|
* if converted to default, or it is default, or is ignored, this is null
|
|
*
|
|
* Obviously the _ part of the state is left out if the part doesn't exist
|
|
*
|
|
* Examples:
|
|
* in world/on map/in inventory:
|
|
* pickaxe
|
|
*
|
|
* worn:
|
|
* pickaxe_belt (implicit default bodytype)
|
|
* pickaxe_belt_teshari
|
|
* pickaxe_left
|
|
* pickaxe_right
|
|
* pickaxe_right_teshari (overrides on teshari)
|
|
*
|
|
* * Coloration
|
|
*
|
|
* ! Coloration WIP. For now, color var only.
|
|
* ! TODO: GAGS, polychromatic overlays with _1, _2, _3, _..., and RED/BLUE, RED/GREEN, GREEN/BLUE matrices.
|
|
* ! TODO: For most of these, it will require mutating the icon states used.
|
|
*
|
|
* * Alignment
|
|
*
|
|
* Mobs are usually able to be shifted left/right, but are always aligned so that their bottom pixels
|
|
* are on the first pixel of their 'real' tile.
|
|
*
|
|
* With that in mind, we allow using the x_mob_y_align variable to shift sprites up, to avoid
|
|
* needing entirely centered sprites.
|
|
*
|
|
* That said, x alignment shifting will never happen due to limitations, so x still has to use centering.
|
|
*
|
|
* * Why mutable appearances?
|
|
* Rendering of equipment changes regularly. They're quite literally built to be changed.
|
|
* Since items always have the same direction as wearer, this means we don't have to use images.
|
|
*
|
|
* * Centering
|
|
* All sprites are centered on the mob regardless of dimensions.
|
|
* The species/mob in question can then pixel shift the resulting object as fit.
|
|
*
|
|
* ? Everything else: read the procs.
|
|
*/
|
|
/obj/item
|
|
//! LEGACY
|
|
//** These specify item/icon overrides for _slots_
|
|
|
|
/// Overrides the default item_state for particular slots.
|
|
var/list/item_state_slots = list()
|
|
|
|
/// Used to specify the icon file to be used when the item is worn. If not set the default icon for that slot will be used.
|
|
/// If icon_override or sprite_sheets are set they will take precendence over this, assuming they apply to the slot in question.
|
|
/// Only slot_l_hand/slot_r_hand are implemented at the moment. Others to be implemented as needed.
|
|
var/list/item_icons
|
|
|
|
/// Used to override hardcoded clothing dmis in human clothing proc. //TODO: Get rid of this crap -Zandario
|
|
var/icon_override = null
|
|
|
|
//** These specify item/icon overrides for _species_
|
|
//TODO Refactor this from the ground up. Too many overrides. -Zandario
|
|
//! THIS IS NOW BANNED. DO NOT USE THIS OR I WILL PUT A LEMON ON YOUR EYES. ~silicons
|
|
//! Use the new bodytype system, PLEASE.
|
|
//! Accessories are currently exempt from the ban, but also accessories need refactored
|
|
//! God this is fucking asinine
|
|
/* Species-specific sprites, concept stolen from Paradise//vg/.
|
|
* ex:
|
|
* sprite_sheets = list(
|
|
* BODYTYPE_STRING_TAJARAN = 'icons/cat/are/bad'
|
|
* )
|
|
* If index term exists and icon_override is not set, this sprite sheet will be used.
|
|
*/
|
|
var/list/sprite_sheets
|
|
|
|
/// Species-specific sprite sheets for inventory sprites
|
|
/// Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called.
|
|
var/list/sprite_sheets_obj
|
|
|
|
// todo: remove
|
|
/// worn icon file
|
|
var/icon/default_worn_icon
|
|
|
|
//! NEW RENDERING SYSTEM (to be used by all new content tm); read comment section at top
|
|
//? for when base icon is used for render
|
|
/// icon alignment y shift
|
|
var/icon_mob_y_align = 0
|
|
//? for equipment slots: prioritized over icon, icon_state, icon dimensions
|
|
/// state to use; icon_state is used if this isn't set
|
|
var/worn_state
|
|
/// worn icon used instead of base icon
|
|
var/icon/worn_icon
|
|
/// dimensions of our worn icon file if different from icon
|
|
var/worn_x_dimension = 32
|
|
/// dimensions of our worn icon file if different from icon
|
|
var/worn_y_dimension = 32
|
|
/// worn icon alignment y shift
|
|
var/worn_mob_y_align = 0
|
|
//? for hands: prioritized over icon, icon_state, icon dimensions
|
|
/// state to use; worn_state, then icon_state is used if this isn't set
|
|
var/inhand_state
|
|
/// inhand icon used instead of base icon
|
|
var/icon/inhand_icon
|
|
/// dimensions of inhand sprites if different from icon
|
|
var/inhand_x_dimension = 32
|
|
/// dimensions of inhand sprites if different from icon
|
|
var/inhand_y_dimension = 32
|
|
/// inhnad icon alignment y shift
|
|
var/inhand_mob_y_align = 0
|
|
/// inhand default domain aka which icon we grab to check for state
|
|
var/inhand_default_type = INHAND_DEFAULT_ICON_GENERAL
|
|
//? for belts
|
|
/// state to use in [icons/mob/clothing/belt.dmi] for belt overlay
|
|
var/belt_state
|
|
//? general handling directives
|
|
/**
|
|
* bodytypes that *can* get trampled to default if the default icon is not found on species
|
|
*
|
|
* for slot defaults, this means using the default icon state.
|
|
* for new rendering, this means using the fallback state on the slot for a bodytype.
|
|
*/
|
|
var/datum/bodytypes/worn_bodytypes_fallback = BODYTYPES_ALL
|
|
/// bodytypes that are implemented. Anything not in here is converted to default, if slot fallback state is unavailable.
|
|
var/datum/bodytypes/worn_bodytypes = BODYTYPES(BODYTYPE_DEFAULT)
|
|
/// bodytypes that just skip rendering (i hate teshari)
|
|
var/datum/bodytypes/worn_bodytypes_invisible = BODYTYPES_NONE
|
|
/// worn rendering flags
|
|
var/worn_render_flags = WORN_RENDER_INHAND_ALLOW_DEFAULT | WORN_RENDER_SLOT_ALLOW_DEFAULT
|
|
//? support for adminbus
|
|
/// vv only; slot id to icon; worn_x_dimension and worn_y_dimension will be used in this case.
|
|
VAR_PRIVATE/list/worn_icon_override
|
|
/// vv only; slot id to state
|
|
VAR_PRIVATE/list/worn_state_override
|
|
/// vv only; set to override layer
|
|
VAR_PRIVATE/worn_layer_override
|
|
|
|
/obj/item/Initialize(mapload)
|
|
. = ..()
|
|
CONSTRUCT_BODYTYPES(worn_bodytypes)
|
|
CONSTRUCT_BODYTYPES(worn_bodytypes_invisible)
|
|
CONSTRUCT_BODYTYPES(worn_bodytypes_fallback)
|
|
|
|
/**
|
|
* update our worn icon if we can
|
|
*/
|
|
/obj/item/proc/update_worn_icon()
|
|
if(!worn_slot)
|
|
return // acceptable
|
|
var/mob/M = get_worn_mob()
|
|
ASSERT(M) // not acceptable
|
|
if(held_index)
|
|
M.update_inv_hand(held_index)
|
|
return
|
|
switch(worn_slot)
|
|
if(SLOT_ID_BACK)
|
|
M.update_inv_back()
|
|
if(SLOT_ID_BELT)
|
|
M.update_inv_belt()
|
|
if(SLOT_ID_GLASSES)
|
|
M.update_inv_glasses()
|
|
if(SLOT_ID_GLOVES)
|
|
M.update_inv_gloves()
|
|
if(SLOT_ID_HANDCUFFED)
|
|
M.update_inv_handcuffed()
|
|
if(SLOT_ID_HANDS)
|
|
CRASH("why did we go here when we should have short-circuited at the held_index check?")
|
|
if(SLOT_ID_HEAD)
|
|
M.update_inv_head()
|
|
if(SLOT_ID_LEFT_EAR, SLOT_ID_RIGHT_EAR)
|
|
M.update_inv_ears()
|
|
if(SLOT_ID_MASK)
|
|
M.update_inv_wear_mask()
|
|
if(SLOT_ID_SHOES)
|
|
M.update_inv_shoes()
|
|
if(SLOT_ID_SUIT)
|
|
M.update_inv_wear_suit()
|
|
if(SLOT_ID_SUIT_STORAGE)
|
|
M.update_inv_s_store()
|
|
if(SLOT_ID_UNIFORM)
|
|
M.update_inv_w_uniform()
|
|
if(SLOT_ID_WORN_ID)
|
|
M.update_inv_wear_id()
|
|
|
|
/**
|
|
* Renders either a list, or a single image or mutable appearance of what we should be applied to a mob with.
|
|
*
|
|
* @params
|
|
* * M - the mob we're rendering
|
|
* * slot_id_or_hand_index - the slot ID or numerical held index we're in
|
|
* * bodytype - the effective bodytype
|
|
*/
|
|
/obj/item/proc/render_mob_appearance(mob/M, slot_id_or_hand_index, bodytype = BODYTYPE_DEFAULT)
|
|
// SHOULD_NOT_OVERRIDE(TRUE) // if you think you need to, rethink.
|
|
// todo: eh reevaluate later
|
|
// determine if in hands
|
|
var/inhands = isnum(slot_id_or_hand_index)? slot_id_or_hand_index : null
|
|
var/datum/inventory_slot/slot_meta
|
|
// resolve slot
|
|
if(inhands)
|
|
slot_meta = resolve_inventory_slot((slot_id_or_hand_index % 2)? /datum/inventory_slot/abstract/hand/left : /datum/inventory_slot/abstract/hand/right)
|
|
else
|
|
slot_meta = resolve_inventory_slot(slot_id_or_hand_index)
|
|
|
|
var/list/resolved = resolve_worn_assets(M, slot_meta, inhands, bodytype)
|
|
|
|
var/rendered = list(_render_mob_appearance(M, slot_meta, inhands, bodytype, resolved[WORN_DATA_ICON], resolved[WORN_DATA_STATE], resolved[WORN_DATA_LAYER], resolved [WORN_DATA_SIZE_X], resolved[WORN_DATA_SIZE_Y], resolved[WORN_DATA_ALIGN_Y]))
|
|
|
|
SEND_SIGNAL(M, COMSIG_CARBON_UPDATING_OVERLAY, rendered, CARBON_APPEARANCE_UPDATE_CLOTHING)
|
|
|
|
return rendered[1]
|
|
|
|
/obj/item/proc/_render_mob_appearance(mob/M, datum/inventory_slot/slot_meta, inhands, bodytype, icon_used, state_used, layer_used, dim_x, dim_y, align_y)
|
|
SHOULD_NOT_OVERRIDE(TRUE) // if you think you need to, rethink.
|
|
PRIVATE_PROC(TRUE) // if you think you need to call this, rethink.
|
|
var/list/additional = render_additional(M, icon_used, state_used, layer_used, dim_x, dim_y, align_y, bodytype, inhands, slot_meta)
|
|
// todo: signal with (args, add)
|
|
// todo: args' indices should be defines
|
|
var/no_render = inhands? (worn_render_flags & WORN_RENDER_INHAND_NO_RENDER) : ((worn_render_flags & WORN_RENDER_SLOT_NO_RENDER) || worn_bodytypes_invisible?.contains(bodytype))
|
|
var/mutable_appearance/MA
|
|
// worn_state_guard makes us not render if we'd render the same as in-inventory icon.
|
|
if(no_render) // don't bother
|
|
return additional
|
|
MA = mutable_appearance(icon_used, state_used, layer_used, FLOAT_PLANE)
|
|
// temporary - until coloration
|
|
MA.color = color
|
|
MA = center_appearance(MA, dim_x, dim_y)
|
|
MA.pixel_y += align_y
|
|
MA = render_apply_overlays(MA, bodytype, inhands, slot_meta, icon_used)
|
|
MA = render_apply_blood(MA, bodytype, inhands, slot_meta, icon_used)
|
|
MA = render_apply_custom(M, MA, bodytype, inhands, slot_meta, icon_used, align_y)
|
|
return length(additional)? (additional + MA) : MA
|
|
|
|
/**
|
|
* override to apply custom stuff to rendering; called last
|
|
*
|
|
* icon/icon state/layer information is included in the mutable appearance
|
|
*/
|
|
/obj/item/proc/render_apply_custom(mob/M, mutable_appearance/MA, bodytype, inhands, datum/inventory_slot/slot_meta, icon_used, align_y)
|
|
return MA
|
|
|
|
/**
|
|
* override to determine how we apply blood overlays to rendering
|
|
*
|
|
* icon/icon state/layer information is included in the mutable appearance
|
|
*/
|
|
/obj/item/proc/render_apply_blood(mutable_appearance/MA, bodytype, inhands, datum/inventory_slot/slot_meta, icon_used)
|
|
return MA
|
|
|
|
/**
|
|
* override to apply overlays to our current mutable appearance; called first
|
|
*/
|
|
/obj/item/proc/render_apply_overlays(mutable_appearance/MA, bodytype, inhands, datum/inventory_slot/slot_meta, icon_used)
|
|
if(addblends)
|
|
var/mutable_appearance/adding = mutable_appearance(icon = MA.icon, icon_state = addblends)
|
|
adding.blend_mode = BLEND_ADD
|
|
MA.add_overlay(adding)
|
|
return MA
|
|
|
|
/**
|
|
* override to include additional appearances while rendering
|
|
*/
|
|
/obj/item/proc/render_additional(mob/M, icon/icon_used, state_used, layer_used, dim_x, dim_y, align_y, bodytype, inhands, datum/inventory_slot/slot_meta)
|
|
RETURN_TYPE(/list)
|
|
return list()
|
|
|
|
/**
|
|
* returns a tuple of (icon, state, layer, size_x, size_y)
|
|
*
|
|
* @params
|
|
* - M - mob putting us on; optional
|
|
* - slot_meta - inventory slot datum
|
|
* - inhands - if we're going to inhands
|
|
* - bodytype - bodytype in question
|
|
*/
|
|
/obj/item/proc/resolve_worn_assets(mob/M, datum/inventory_slot/slot_meta, inhands, bodytype)
|
|
if(istext(slot_meta))
|
|
slot_meta = resolve_inventory_slot(slot_meta)
|
|
var/list/data = new /list(WORN_DATA_LIST_SIZE)
|
|
|
|
//? state ; item_state_slots --> (worn_state | inhand_state) --> item_state --> icon_state
|
|
data[WORN_DATA_STATE] = resolve_legacy_state(M, slot_meta, inhands, bodytype)
|
|
|
|
//? icon, size
|
|
//* icon_override
|
|
if(icon_override)
|
|
data[WORN_DATA_ICON] = icon_override
|
|
switch(slot_meta.id)
|
|
if(SLOT_ID_LEFT_HAND)
|
|
data[WORN_DATA_STATE] += "_l"
|
|
if(SLOT_ID_RIGHT_HAND)
|
|
data[WORN_DATA_STATE] += "_r"
|
|
if(SLOT_ID_LEFT_EAR)
|
|
data[WORN_DATA_STATE] += "_l"
|
|
if(SLOT_ID_RIGHT_EAR)
|
|
data[WORN_DATA_STATE] += "_l"
|
|
data[WORN_DATA_SIZE_X] = worn_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = worn_y_dimension
|
|
|
|
//* species-specific sprite sheets
|
|
else if(length(sprite_sheets) && !inhands && (sprite_sheets[bodytype_to_string(bodytype)]))
|
|
data[WORN_DATA_ICON] = sprite_sheets[bodytype_to_string(bodytype)]
|
|
data[WORN_DATA_SIZE_X] = WORLD_ICON_SIZE
|
|
data[WORN_DATA_SIZE_Y] = WORLD_ICON_SIZE
|
|
|
|
//* slot-specific sprite sheets
|
|
else if(item_icons?[slot_meta.id])
|
|
data[WORN_DATA_ICON] = item_icons[slot_meta.id]
|
|
data[WORN_DATA_SIZE_X] = worn_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = worn_y_dimension
|
|
|
|
//* item default_worn_icon override
|
|
else if(default_worn_icon && !inhands)
|
|
// todo: rework
|
|
data[WORN_DATA_ICON] = default_worn_icon
|
|
data[WORN_DATA_SIZE_X] = worn_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = worn_y_dimension
|
|
|
|
//* inventory slot defaults
|
|
else if(inhands? (worn_render_flags & WORN_RENDER_INHAND_ALLOW_DEFAULT) : (worn_render_flags & WORN_RENDER_SLOT_ALLOW_DEFAULT))
|
|
var/list/resolved = slot_meta.resolve_default_assets(bodytype, data[WORN_DATA_STATE], M, src, inhand_default_type)
|
|
if(!resolved && (bodytype != BODYTYPE_DEFAULT) && worn_bodytypes_fallback?.contains(bodytype))
|
|
// attempt 2 - use fallback if available
|
|
if(!(slot_meta.handle_worn_fallback(bodytype, data)))
|
|
// attempt 3 - convert to default if specified to convert
|
|
resolved = slot_meta.resolve_default_assets(BODYTYPE_DEFAULT, data[WORN_DATA_STATE], M, src, inhand_default_type)
|
|
if(resolved)
|
|
data[WORN_DATA_ICON] = resolved[1]
|
|
data[WORN_DATA_SIZE_X] = resolved[2]
|
|
data[WORN_DATA_SIZE_Y] = resolved[3]
|
|
|
|
//* Now, the actual intended render system.
|
|
if(!data[WORN_DATA_ICON])
|
|
// grab icon based on priority
|
|
if(!inhands && !worn_bodytypes?.contains(bodytype) && worn_bodytypes_fallback?.contains(bodytype) && slot_meta.handle_worn_fallback(bodytype, data))
|
|
// special: if bodytypes isn't in, and species has fallback
|
|
// .. well don't do anything as handle_sprite_fallback will write to the data list.
|
|
else if(inhands && inhand_icon)
|
|
data[WORN_DATA_ICON] = inhand_icon
|
|
data[WORN_DATA_SIZE_X] = inhand_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = inhand_y_dimension
|
|
data[WORN_DATA_ALIGN_Y] = inhand_mob_y_align
|
|
data[WORN_DATA_STATE] = resolve_worn_state(inhands, (worn_render_flags & WORN_RENDER_SLOT_USE_PLURAL) ?(slot_meta.render_key_plural || slot_meta.render_key) : slot_meta.render_key, bodytype)
|
|
else if(!inhands && worn_icon)
|
|
data[WORN_DATA_ICON] = worn_icon
|
|
data[WORN_DATA_SIZE_X] = worn_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = worn_y_dimension
|
|
data[WORN_DATA_ALIGN_Y] = worn_mob_y_align
|
|
data[WORN_DATA_STATE] = resolve_worn_state(inhands, (worn_render_flags & WORN_RENDER_SLOT_USE_PLURAL)? (slot_meta.render_key_plural || slot_meta.render_key) : slot_meta.render_key, bodytype)
|
|
else
|
|
data[WORN_DATA_ICON] = icon
|
|
data[WORN_DATA_SIZE_X] = icon_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = icon_y_dimension
|
|
data[WORN_DATA_ALIGN_Y] = icon_mob_y_align
|
|
data[WORN_DATA_STATE] = resolve_worn_state(inhands, (worn_render_flags & WORN_RENDER_SLOT_USE_PLURAL)? (slot_meta.render_key_plural || slot_meta.render_key) : slot_meta.render_key, bodytype)
|
|
|
|
//? layer ; worn_layer --> slot defaults for the item in question
|
|
data[WORN_DATA_LAYER] = worn_layer_override || slot_meta.resolve_default_layer(bodytype, M, src)
|
|
|
|
//* Handle overrides
|
|
if(LAZYACCESS(worn_icon_override, slot_meta.id))
|
|
data[WORN_DATA_ICON] = worn_icon_override[slot_meta.id]
|
|
// if you fuck this up, Skill Issue. We have to align somehow.
|
|
data[WORN_DATA_SIZE_X] = icon_x_dimension
|
|
data[WORN_DATA_SIZE_Y] = icon_y_dimension
|
|
if(LAZYACCESS(worn_state_override, slot_meta.id))
|
|
data[WORN_DATA_STATE] = worn_state_override[slot_meta.id]
|
|
|
|
return data
|
|
|
|
/obj/item/proc/debug_worn_assets(slot_or_id, mob/M = get_worn_mob(), bodytype)
|
|
var/mob/living/carbon/human/H = ishuman(M)? M : null
|
|
var/datum/inventory_slot/slot_meta
|
|
if(isnull(slot_or_id))
|
|
slot_or_id = inv_slot_or_index
|
|
if(isnum(slot_or_id))
|
|
slot_meta = resolve_inventory_slot((slot_or_id % 2)? /datum/inventory_slot/abstract/hand/left : /datum/inventory_slot/abstract/hand/right)
|
|
else
|
|
slot_meta = resolve_inventory_slot(slot_or_id)
|
|
if(isnull(bodytype) && H)
|
|
bodytype = H.species.get_effective_bodytype(H, src, slot_meta)
|
|
. = resolve_worn_assets(M, slot_meta, isnum(slot_or_id), bodytype)
|
|
.[WORN_DATA_ICON] = "[.[WORN_DATA_ICON]]"
|
|
|
|
// todo: remove, aka get rid of fucking uniform _s state
|
|
/obj/item/proc/resolve_legacy_state(mob/M, datum/inventory_slot/slot_meta, inhands, bodytype)
|
|
return (item_state_slots?[slot_meta.id]) || (inhands? inhand_state : worn_state) || item_state || icon_state
|
|
|
|
/obj/item/proc/resolve_worn_state(inhands, slot_key, bodytype)
|
|
// PRIVATE_PROC(TRUE)
|
|
if(inhands)
|
|
return "[base_worn_state(inhands, slot_key, bodytype)][(worn_render_flags & WORN_RENDER_INHAND_ONE_FOR_ALL)? "_all" : "_[slot_key]"]"
|
|
return "[base_worn_state(inhands, slot_key, bodytype)][(worn_render_flags & WORN_RENDER_SLOT_ONE_FOR_ALL)? "_all" : "_[slot_key]"][((bodytype != BODYTYPE_DEFAULT) && worn_bodytypes?.contains(bodytype))? "_[bodytype_to_string(bodytype)]" : ""]"
|
|
|
|
/obj/item/proc/base_worn_state(inhands, slot_key, bodytype)
|
|
if(inhands)
|
|
return inhand_state || icon_state
|
|
return worn_state || icon_state
|