Files
Bubberstation/code/datums/components/toggle_attached_clothing.dm
Waterpig bb70889f6e TG Upstream Part 1
3591 individual conflicts

Update build.js

Update install_node.sh

Update byond.js

oh my fucking god

hat

slow

huh

holy shit

we all fall down

2 more I missed

2900 individual conflicts

2700 Individual conflicts

replaces yarn file with tg version, bumping us down to 2200-ish

Down to 2000 individual conflicts

140 down

mmm

aaaaaaaaaaaaaaaaaaa

not yt

575

soon

900 individual conflicts

600 individual conflicts, 121 file conflicts

im not okay

160 across 19 files

29 in 4 files

0 conflicts, compiletime fix time

some minor incap stuff

missed ticks

weird dupe definition stuff

missed ticks 2

incap fixes

undefs and pie fix

Radio update and some extra minor stuff

returns a single override

no more dupe definitions, 175 compiletime errors

Unticked file fix

sound and emote stuff

honk and more radio stuff
2024-10-19 08:04:33 -07:00

218 lines
8.0 KiB
Plaintext

/**
* Component which allows clothing to deploy a different kind of clothing onto you.
* The simplest example is hooded suits deploying hoods onto your head.
*/
/datum/component/toggle_attached_clothing
/// Instance of the item we're creating
var/obj/item/deployable
/// Action used to toggle deployment
var/datum/action/item_action/toggle_action
/// Typepath of what we're creating
var/deployable_type
/// Which slot this item equips into
var/equipped_slot
/// Name of toggle action
var/action_name = ""
/// If true, we delete our deployable on toggle rather than putting it in nullspace
var/destroy_on_removal
/// Current state of our deployable equipment
var/currently_deployed = FALSE
/// What should be added to the end of the parent icon state when equipment is deployed? Set to "" for no change
var/parent_icon_state_suffix = ""
/// Icon state for overlay to display over the parent item while deployable item is not deployed
var/down_overlay_state_suffix = ""
/// Overlay to display over the parent item while deployable item is not deployed
var/mutable_appearance/undeployed_overlay
/// Optional callback triggered before deploying, return TRUE to continue or FALSE to cancel
var/datum/callback/pre_creation_check
/// Optional callback triggered when we create our deployable equipment
var/datum/callback/on_created
/// Optional callback triggered when we have deployed our equipment
var/datum/callback/on_deployed
/// Optional callback triggered before we hide our equipment, before as we may delete it afterwards
var/datum/callback/on_removed
/datum/component/toggle_attached_clothing/Initialize(
deployable_type,
equipped_slot,
action_name = "Toggle",
destroy_on_removal = FALSE,
parent_icon_state_suffix = "",
down_overlay_state_suffix = "",
datum/callback/pre_creation_check,
datum/callback/on_created,
datum/callback/on_deployed,
datum/callback/on_removed,
)
. = ..()
if (!isitem(parent))
return COMPONENT_INCOMPATIBLE
if (!deployable_type || !equipped_slot)
return COMPONENT_INCOMPATIBLE // Not strictly true but INITIALIZE_HINT_QDEL doesn't work from components
src.deployable_type = deployable_type
src.equipped_slot = equipped_slot
src.destroy_on_removal = destroy_on_removal
src.parent_icon_state_suffix = parent_icon_state_suffix
src.down_overlay_state_suffix = down_overlay_state_suffix
src.pre_creation_check = pre_creation_check
src.on_created = on_created
src.on_deployed = on_deployed
src.on_removed = on_removed
var/obj/item/clothing_parent = parent
toggle_action = new(parent)
toggle_action.name = action_name
clothing_parent.add_item_action(toggle_action)
RegisterSignal(parent, COMSIG_ITEM_UI_ACTION_CLICK, PROC_REF(on_toggle_pressed))
RegisterSignal(parent, COMSIG_ITEM_UI_ACTION_SLOT_CHECKED, PROC_REF(on_action_slot_checked))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_parent_equipped))
RegisterSignal(parent, COMSIG_ITEM_POST_UNEQUIP, PROC_REF(remove_deployable))
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED_AS_OUTFIT, PROC_REF(on_parent_equipped_outfit))
if (down_overlay_state_suffix)
var/overlay_state = "[initial(clothing_parent.icon_state)][down_overlay_state_suffix]"
undeployed_overlay = mutable_appearance(initial(clothing_parent.worn_icon), overlay_state, -SUIT_LAYER)
RegisterSignal(parent, COMSIG_ITEM_GET_WORN_OVERLAYS, PROC_REF(on_checked_overlays))
clothing_parent.update_slot_icon()
if (!destroy_on_removal)
create_deployable()
/datum/component/toggle_attached_clothing/Destroy(force)
unequip_deployable()
QDEL_NULL(deployable)
QDEL_NULL(toggle_action)
undeployed_overlay = null
pre_creation_check = null
on_created = null
on_deployed = null
on_removed = null
return ..()
/// Toggle deployable when the UI button is clicked
/datum/component/toggle_attached_clothing/proc/on_toggle_pressed(obj/item/source, mob/user, datum/action)
SIGNAL_HANDLER
if (action != toggle_action)
return
toggle_deployable()
return COMPONENT_ACTION_HANDLED
/// Called when action attempts to check what slot the item is worn in
/datum/component/toggle_attached_clothing/proc/on_action_slot_checked(obj/item/clothing/source, mob/user, datum/action, slot)
SIGNAL_HANDLER
if (action != toggle_action)
return
if (!(source.slot_flags & slot))
return COMPONENT_ITEM_ACTION_SLOT_INVALID
/// Apply an overlay while the item is not deployed
/datum/component/toggle_attached_clothing/proc/on_checked_overlays(obj/item/source, list/overlays, mutable_appearance/standing, isinhands, icon_file)
SIGNAL_HANDLER
if (isinhands || currently_deployed)
return
overlays += undeployed_overlay
/// Deploys gear if it is hidden, hides it if it is deployed
/datum/component/toggle_attached_clothing/proc/toggle_deployable()
if (currently_deployed)
remove_deployable()
return
var/obj/item/parent_gear = parent
if (!ishuman(parent_gear.loc))
return
var/mob/living/carbon/human/wearer = parent_gear.loc
if (wearer.is_holding(parent_gear))
parent_gear.balloon_alert(wearer, "wear it first!")
return
if (wearer.get_item_by_slot(equipped_slot))
parent_gear.balloon_alert(wearer, "slot occupied!")
return
if (!deployable && !create_deployable())
return
if (!wearer.equip_to_slot_if_possible(deployable, slot = equipped_slot))
if(destroy_on_removal)
remove_deployable()
return
currently_deployed = TRUE
on_deployed?.Invoke(deployable)
if (parent_icon_state_suffix)
parent_gear.icon_state = "[initial(parent_gear.icon_state)][parent_icon_state_suffix]"
parent_gear.worn_icon_state = parent_gear.icon_state
parent_gear.update_slot_icon()
wearer.update_mob_action_buttons()
/// Undeploy gear if it moves slots somehow
/datum/component/toggle_attached_clothing/proc/on_parent_equipped(obj/item/clothing/source, mob/equipper, slot)
SIGNAL_HANDLER
if (slot & equipped_slot)
return
remove_deployable()
/// Display deployed if worn in an outfit
/datum/component/toggle_attached_clothing/proc/on_parent_equipped_outfit(obj/item/clothing/source, mob/equipper, visuals_only, slot)
SIGNAL_HANDLER
create_deployable()
toggle_deployable()
/// Create our gear, returns true if we actually made anything
/datum/component/toggle_attached_clothing/proc/create_deployable()
if (deployable)
return FALSE
if (pre_creation_check && !pre_creation_check.Invoke())
return FALSE
deployable = new deployable_type(parent)
if (!istype(deployable))
stack_trace("Tried to create non-clothing item from toggled clothing.")
RegisterSignal(deployable, COMSIG_ITEM_DROPPED, PROC_REF(on_deployed_dropped))
RegisterSignal(deployable, COMSIG_ITEM_EQUIPPED, PROC_REF(on_deployed_equipped))
RegisterSignal(deployable, COMSIG_QDELETING, PROC_REF(on_deployed_destroyed))
on_created?.Invoke(deployable)
return TRUE
/// Undeploy gear if you drop it
/datum/component/toggle_attached_clothing/proc/on_deployed_dropped()
SIGNAL_HANDLER
remove_deployable()
/// Undeploy gear if it moves slots somehow
/datum/component/toggle_attached_clothing/proc/on_deployed_equipped(obj/item/clothing/source, mob/equipper, slot)
SIGNAL_HANDLER
if (source.slot_flags & slot)
return
remove_deployable()
/// Undeploy gear if it is deleted
/datum/component/toggle_attached_clothing/proc/on_deployed_destroyed()
SIGNAL_HANDLER
remove_deployable()
deployable = null
/// Removes our deployed equipment from the wearer
/datum/component/toggle_attached_clothing/proc/remove_deployable()
SIGNAL_HANDLER
unequip_deployable()
if (!currently_deployed)
return
currently_deployed = FALSE
on_removed?.Invoke(deployable)
var/obj/item/parent_gear = parent
if(destroy_on_removal)
QDEL_NULL(deployable)
if(parent_icon_state_suffix)
parent_gear.icon_state = "[initial(parent_gear.icon_state)]"
parent_gear.worn_icon_state = parent_gear.icon_state
parent_gear.update_slot_icon()
parent_gear.update_item_action_buttons()
/// Removes an equipped deployable atom upon its retraction or destruction
/datum/component/toggle_attached_clothing/proc/unequip_deployable()
if (!deployable)
return
if (!ishuman(deployable.loc))
deployable.forceMove(parent)
return
var/mob/living/carbon/human/wearer = deployable.loc
wearer.transferItemToLoc(deployable, parent, force = TRUE, silent = TRUE)