diff --git a/code/__DEFINES/~skyrat_defines/lewd_defines.dm b/code/__DEFINES/~skyrat_defines/lewd_defines.dm index 90711768d36..93d54149799 100644 --- a/code/__DEFINES/~skyrat_defines/lewd_defines.dm +++ b/code/__DEFINES/~skyrat_defines/lewd_defines.dm @@ -78,3 +78,20 @@ /area/centcom/holding/cafe/ruin/xenonest,\ /area/centcom/holding/cafe/beach,\ ) + +/// Applied to a mob wearing gloves that should be passable for hand surgery (e.g. ball mittens). +#define TRAIT_GLOVE_SURGERY_PASSTHROUGH "glove_surgery_passthrough" +/// Trait source for ball_mittens_fumble component. +#define MITTENS_FUMBLE_TRAIT "ball_mittens_fumble" + + +/// Fired on a mob in attempt_pickup after mobility checks. Handler can set pickup_mods["delay"] or return COMPONENT_BLOCK_ITEM_PICKUP. +#define COMSIG_LIVING_ITEM_ATTEMPT_PICKUP "living_item_attempt_pickup" +#define COMPONENT_BLOCK_ITEM_PICKUP (1<<0) + +/// Fired on a mob when they interact with machinery, before interact() runs. Return COMPONENT_BLOCK_MACHINERY_INTERACT to block. +#define COMSIG_MOB_MACHINERY_INTERACT "mob_machinery_interact" +#define COMPONENT_BLOCK_MACHINERY_INTERACT (1<<1) + +/// Fired on a mob when attempt_pickup fails due to fail_chance in pickup_mods. (obj/item/item) +#define COMSIG_LIVING_ITEM_PICKUP_FAILED "living_item_pickup_failed" diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 70cb1811034..b6e46ff6976 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -704,6 +704,10 @@ //Return a non FALSE value to interrupt attack_hand propagation to subtypes. /obj/machinery/interact(mob/user) + // BUBBER EDIT ADDITION - allow components on the user to intercept or delay machinery interaction + if(SEND_SIGNAL(user, COMSIG_MOB_MACHINERY_INTERACT, src) & COMPONENT_BLOCK_MACHINERY_INTERACT) + return FALSE + // BUBBER EDIT ADDITION END update_last_used(user) return ..() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index bfcf2ab4e59..301bfcc57d2 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -420,6 +420,8 @@ lefthand_file = SSgreyscale.GetColoredIconByType(greyscale_config_inhand_left, greyscale_colors) if(greyscale_config_inhand_right) righthand_file = SSgreyscale.GetColoredIconByType(greyscale_config_inhand_right, greyscale_colors) + // BUBBER EDIT ADDITION - Fire COMSIG_ATOM_UPDATED_ICON after all GAGS icons update so update_icon_updates_onmob can refresh worn overlays + SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON) /obj/item/verb/move_to_top() set name = "Move To Top" @@ -574,6 +576,18 @@ if(!(user.mobility_flags & MOBILITY_PICKUP)) return + // BUBBER EDIT ADDITION - allow components on the user to inject a pickup delay or fail chance (e.g. ball mittens fumble) + var/list/pickup_mods = list("delay" = 0, "fail_chance" = 0) + if(SEND_SIGNAL(user, COMSIG_LIVING_ITEM_ATTEMPT_PICKUP, src, pickup_mods) & COMPONENT_BLOCK_ITEM_PICKUP) + return + if(pickup_mods["delay"]) + if(!do_after(user, pickup_mods["delay"], src, timed_action_flags = IGNORE_HELD_ITEM)) + return + if(pickup_mods["fail_chance"] && prob(pickup_mods["fail_chance"])) + SEND_SIGNAL(user, COMSIG_LIVING_ITEM_PICKUP_FAILED, src) + return + // BUBBER EDIT ADDITION END + if(!skip_grav) //Heavy gravity makes picking up things very slow. var/grav = user.has_gravity() diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index fcf292496f2..e5ebe9cb4fc 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -443,6 +443,10 @@ return covered_flags /mob/living/carbon/is_location_accessible(location, exluded_equipment_slots = NONE) + // BUBBER EDIT ADDITION - ball mittens surgery passthrough + if(HAS_TRAIT(src, TRAIT_GLOVE_SURGERY_PASSTHROUGH)) + exluded_equipment_slots |= ITEM_SLOT_GLOVES + // BUBBER EDIT ADDITION END switch(location) // Snowflake checks for these precise zones if(BODY_ZONE_PRECISE_EYES) diff --git a/code/modules/surgery/operations/_operation.dm b/code/modules/surgery/operations/_operation.dm index 26d647f2472..12a3fe54988 100644 --- a/code/modules/surgery/operations/_operation.dm +++ b/code/modules/surgery/operations/_operation.dm @@ -470,7 +470,7 @@ GLOBAL_DATUM_INIT(operations, /datum/operation_holder, new) /datum/surgery_operation/proc/check_availability(mob/living/patient, atom/movable/operating_on, mob/living/surgeon, tool, operated_zone) SHOULD_NOT_OVERRIDE(TRUE) SHOULD_NOT_SLEEP(TRUE) - SHOULD_BE_PURE(TRUE) + // BUBBER EDIT REMOVAL - SHOULD_BE_PURE(TRUE) removed to allow clothing items to override is_location_accessible if(isnull(operating_on)) return FALSE diff --git a/icons/map_icons/clothing/_clothing.dmi b/icons/map_icons/clothing/_clothing.dmi index 8dd4f7952e0..45438b87349 100644 Binary files a/icons/map_icons/clothing/_clothing.dmi and b/icons/map_icons/clothing/_clothing.dmi differ diff --git a/modular_skyrat/modules/GAGS/greyscale_configs.dm b/modular_skyrat/modules/GAGS/greyscale_configs.dm index 8e47adef44d..59bf969d9f3 100644 --- a/modular_skyrat/modules/GAGS/greyscale_configs.dm +++ b/modular_skyrat/modules/GAGS/greyscale_configs.dm @@ -1403,6 +1403,18 @@ TREK name = "Catgloves Worn" icon_file = 'modular_skyrat/modules/GAGS/icons/catglove_worn.dmi' + +/datum/greyscale_config/magpaws + name = "Magpaws" + icon_file = 'modular_skyrat/modules/GAGS/icons/magpaws.dmi' + json_config = 'modular_skyrat/modules/GAGS/json_configs/gloves/magpaws.json' + +/datum/greyscale_config/magpaws/worn + name = "Magpaws Worn" + icon_file = 'modular_skyrat/modules/GAGS/icons/magpaws.dmi' + json_config = 'modular_skyrat/modules/GAGS/json_configs/gloves/magpaws_worn.json' + + // MISC SHOES /datum/greyscale_config/heels diff --git a/modular_skyrat/modules/GAGS/icons/catglove.dmi b/modular_skyrat/modules/GAGS/icons/catglove.dmi index 1a0ad7234ea..fe8de214915 100644 Binary files a/modular_skyrat/modules/GAGS/icons/catglove.dmi and b/modular_skyrat/modules/GAGS/icons/catglove.dmi differ diff --git a/modular_skyrat/modules/GAGS/icons/catglove_worn.dmi b/modular_skyrat/modules/GAGS/icons/catglove_worn.dmi index 2b5d8708c2e..c7c0cec7b06 100644 Binary files a/modular_skyrat/modules/GAGS/icons/catglove_worn.dmi and b/modular_skyrat/modules/GAGS/icons/catglove_worn.dmi differ diff --git a/modular_skyrat/modules/GAGS/icons/credit.md b/modular_skyrat/modules/GAGS/icons/credit.md new file mode 100644 index 00000000000..9b9846c2139 --- /dev/null +++ b/modular_skyrat/modules/GAGS/icons/credit.md @@ -0,0 +1 @@ +catglove.cmi and catglove_worn.dmi by Online! (Discord) 🩵 \ No newline at end of file diff --git a/modular_skyrat/modules/GAGS/icons/magpaws.dmi b/modular_skyrat/modules/GAGS/icons/magpaws.dmi new file mode 100644 index 00000000000..13ed07e5f19 Binary files /dev/null and b/modular_skyrat/modules/GAGS/icons/magpaws.dmi differ diff --git a/modular_skyrat/modules/GAGS/json_configs/gloves/catgloves.json b/modular_skyrat/modules/GAGS/json_configs/gloves/catgloves.json index 217e9e5ba85..5b0b49f47fa 100644 --- a/modular_skyrat/modules/GAGS/json_configs/gloves/catgloves.json +++ b/modular_skyrat/modules/GAGS/json_configs/gloves/catgloves.json @@ -4,13 +4,25 @@ "type": "icon_state", "icon_state": "catglove", "blend_mode": "overlay", - "color_ids": [ 1 ] + "color_ids": [ + 1 + ] }, { "type": "icon_state", "icon_state": "catglove_paws", "blend_mode": "overlay", - "color_ids": [ 2 ] + "color_ids": [ + 2 + ] + }, + { + "type": "icon_state", + "icon_state": "catgloves_tag", + "blend_mode": "overlay", + "color_ids": [ + 3 + ] } ] } diff --git a/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws.json b/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws.json new file mode 100644 index 00000000000..422e9f01b2c --- /dev/null +++ b/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws.json @@ -0,0 +1,28 @@ +{ + "magpaws": [ + { + "type": "icon_state", + "icon_state": "GAGSpawnsMainOBJ", + "blend_mode": "overlay", + "color_ids": [ + 1 + ] + }, + { + "type": "icon_state", + "icon_state": "GAGgumdropsOBJ", + "blend_mode": "overlay", + "color_ids": [ + 2 + ] + }, + { + "type": "icon_state", + "icon_state": "GAGsymbolOBJ", + "blend_mode": "overlay", + "color_ids": [ + 3 + ] + } + ] +} diff --git a/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws_worn.json b/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws_worn.json new file mode 100644 index 00000000000..7ca94ea5af8 --- /dev/null +++ b/modular_skyrat/modules/GAGS/json_configs/gloves/magpaws_worn.json @@ -0,0 +1,28 @@ +{ + "magpaws_worn": [ + { + "type": "icon_state", + "icon_state": "GAGspawsMainMOB", + "blend_mode": "overlay", + "color_ids": [ + 1 + ] + }, + { + "type": "icon_state", + "icon_state": "GAGpawscolorMainMOB", + "blend_mode": "overlay", + "color_ids": [ + 2 + ] + }, + { + "type": "icon_state", + "icon_state": "GaGsymbolMainMOB", + "blend_mode": "overlay", + "color_ids": [ + 3 + ] + } + ] +} diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/clothing_pref_check.dm b/modular_skyrat/modules/modular_items/lewd_items/code/clothing_pref_check.dm index ab865536af4..e005031601e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/clothing_pref_check.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/clothing_pref_check.dm @@ -13,7 +13,7 @@ GLOBAL_LIST_INIT(pref_checked_clothes, list( /obj/item/clothing/suit/straight_jacket/kinky_sleepbag, /obj/item/clothing/suit/straight_jacket/latex_straight_jacket, /obj/item/clothing/gloves/ball_mittens, - /obj/item/clothing/gloves/ball_mittens_reinforced, + /obj/item/clothing/gloves/ball_mittens/loadout_paw, /obj/item/clothing/suit/straight_jacket/shackles, /obj/item/clothing/suit/straight_jacket/shackles/reinforced, /obj/item/clothing/gloves/shibari_hands, @@ -23,7 +23,10 @@ GLOBAL_LIST_INIT(pref_checked_clothes, list( /obj/item/clothing/mob_can_equip(mob/living/user, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, ignore_equipped = FALSE, indirect_action) if((slot_flags & slot) && (src.type in GLOB.pref_checked_clothes)) - if(!(user.client?.prefs?.read_preference(/datum/preference/toggle/erp/sex_toy))) - return FALSE + // indirect_action = TRUE means this is an outfit/loadout equip, not a player action. + // Allow it through - the player selected this item in their loadout deliberately. + // Also allow when there is no client yet (round start character transfer not complete). + if(!indirect_action && user.client) + if(!(user.client?.prefs?.read_preference(/datum/preference/toggle/erp/sex_toy))) + return FALSE return ..() - diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_gloves.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_gloves.dm index f5b247b60fc..97ca033d638 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_gloves.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_clothing/lewd_gloves.dm @@ -1,40 +1,558 @@ -//normal ball mittens + +/datum/component/ball_mittens_fumble + dupe_mode = COMPONENT_DUPE_UNIQUE + var/struggle_delay_min = 0.8 SECONDS + var/interact_delay = 1.5 SECONDS + var/max_item_size = WEIGHT_CLASS_HUGE + var/cuff_resist_multiplier = 3 + var/gun_spread_penalty = 12 + var/is_interacting = FALSE + var/obj/item/tracked_cuffs = null + +/datum/component/ball_mittens_fumble/Initialize() + . = ..() + if(!istype(parent, /obj/item/clothing/gloves/ball_mittens)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_pre_unequip)) + +/datum/component/ball_mittens_fumble/proc/register_wearer(mob/living/wearer) + var/obj/item/clothing/gloves/ball_mittens/mittens = parent + if(mittens.is_paw_skin && isliving(wearer)) + wearer.add_mood_event("paw_mittens", /datum/mood_event/wearing_paw_mittens) + if(!mittens.spawn_flavor_shown && mittens.loadout_created) + mittens.spawn_flavor_shown = TRUE + INVOKE_ASYNC(mittens, TYPE_PROC_REF(/obj/item/clothing/gloves/ball_mittens, deferred_spawn_flavor), wearer) + ADD_TRAIT(wearer, TRAIT_GLOVE_SURGERY_PASSTHROUGH, MITTENS_FUMBLE_TRAIT) + RegisterSignal(wearer, COMSIG_LIVING_ITEM_ATTEMPT_PICKUP, PROC_REF(on_attempt_pickup)) + RegisterSignal(wearer, COMSIG_LIVING_ITEM_PICKUP_FAILED, PROC_REF(on_pickup_failed)) + RegisterSignal(wearer, COMSIG_MOB_MACHINERY_INTERACT, PROC_REF(on_machinery_interact)) + RegisterSignal(wearer, COMSIG_MOB_CLICKON, PROC_REF(on_clickon)) + RegisterSignal(wearer, COMSIG_MOB_REMOVING_CUFFS, PROC_REF(on_removing_cuffs)) + RegisterSignal(wearer, COMSIG_MOB_FIRED_GUN, PROC_REF(on_fired_gun)) + RegisterSignal(wearer, COMSIG_TRY_STRIP, PROC_REF(on_try_strip)) + RegisterSignal(wearer, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(on_mousedrop_receive)) + RegisterSignal(wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) + +/datum/component/ball_mittens_fumble/proc/unregister_wearer(mob/living/wearer) + if(!isliving(wearer)) + return + wearer.clear_mood_event("paw_mittens") + REMOVE_TRAIT(wearer, TRAIT_GLOVE_SURGERY_PASSTHROUGH, MITTENS_FUMBLE_TRAIT) + UnregisterSignal(wearer, list( + COMSIG_LIVING_ITEM_ATTEMPT_PICKUP, + COMSIG_LIVING_ITEM_PICKUP_FAILED, + COMSIG_MOB_MACHINERY_INTERACT, + COMSIG_MOB_CLICKON, + COMSIG_MOB_REMOVING_CUFFS, + COMSIG_MOB_FIRED_GUN, + COMSIG_TRY_STRIP, + COMSIG_LIVING_UNARMED_ATTACK, + COMSIG_MOUSEDROPPED_ONTO, + )) + +/datum/component/ball_mittens_fumble/proc/on_pre_unequip(datum/source, force) + SIGNAL_HANDLER + if(force) + return + var/obj/item/clothing/gloves/ball_mittens/mittens = parent + var/mob/living/wearer = mittens.loc + if(!isliving(wearer)) + return + to_chat(wearer, span_purple("You struggle furiously with [mittens], but you're not even sure if these can come off.")) + return COMPONENT_ITEM_BLOCK_UNEQUIP + +/datum/component/ball_mittens_fumble/proc/get_hand_descriptor(mob/living/wearer) + if(!iscarbon(wearer)) + return "chunky mitts" + var/mob/living/carbon/human/human_wearer = wearer + var/obj/item/clothing/gloves/ball_mittens/mittens = human_wearer.gloves + if(istype(mittens) && mittens.is_paw_skin) + return "paws" + return "chunky mitts" + +/// Intercepts item pickups via attempt_pickup. Enforces the one-item limit and injects a short pickup delay. +/datum/component/ball_mittens_fumble/proc/on_attempt_pickup(mob/living/wearer, obj/item/item, list/pickup_mods) + SIGNAL_HANDLER + if(!isgun(item) && item.w_class >= max_item_size) + pickup_mods["delay"] = struggle_delay_min * (item.w_class - max_item_size + 2) + pickup_mods["fail_chance"] = min(75, (item.w_class - max_item_size) * 25) + to_chat(wearer, span_warning("You wrestle with [item], trying to get it between your [get_hand_descriptor(wearer)]...")) + return + var/hand_desc = get_hand_descriptor(wearer) + var/player_msgs = list( + "You awkwardly wedge the [item] between your [hand_desc]...", + "You clumsily pin the [item] between your [hand_desc]...", + "You struggle to secure the [item] in your [hand_desc] before finally succeeding.", + "You carefully balance the [item] between your unwieldy [hand_desc]..." + ) + to_chat(wearer, span_purple(pick(player_msgs))) + var/public_msg + if(isgun(item)) + var/gun_msgs = list( + "[wearer] takes hold of the [item] in defiance of common sense.", + "[wearer] awkwardly presses the [item] between [wearer.p_their()] [hand_desc].", + "[wearer] picks up the [item], awkwardly pressing [wearer.p_their()] pads against the trigger guard!" + ) + public_msg = pick(gun_msgs) + else + var/general_msgs = list( + "[wearer] awkwardly secures the [item] in [wearer.p_their()] [hand_desc].", + "[wearer] carefully grips the [item] with [wearer.p_their()] [hand_desc].", + "[wearer] almost drops [item] before managing to press it between [wearer.p_their()] [hand_desc].", + "[wearer] carefully balances the [item] between [wearer.p_their()] [hand_desc]." + ) + public_msg = pick(general_msgs) + wearer.visible_message(span_warning(public_msg)) + pickup_mods["delay"] = struggle_delay_min + +/datum/component/ball_mittens_fumble/proc/on_pickup_failed(mob/living/wearer, obj/item/item) + SIGNAL_HANDLER + var/hand_desc = get_hand_descriptor(wearer) + to_chat(wearer, span_warning("[item] slips out of your [hand_desc]!")) + playsound(wearer, 'modular_skyrat/modules/modular_items/lewd_items/sounds/latex.ogg', 30, TRUE) + +/// Handles machinery interaction delay via COMSIG_MOB_MACHINERY_INTERACT. +/datum/component/ball_mittens_fumble/proc/on_machinery_interact(mob/living/wearer, obj/machinery/machine) + SIGNAL_HANDLER + if(is_interacting) + return + // Simple toggle/single-action machines trivial to operate with a paw - bypass delay + var/static/list/paw_passthrough = typecacheof(list( + /obj/machinery/button, + /obj/machinery/photobooth, + /obj/machinery/light_switch, + /obj/machinery/shower, + /obj/machinery/firealarm, + /obj/machinery/conveyor, + /obj/machinery/conveyor_switch, + /obj/machinery/grill, + /obj/machinery/oven, + /obj/machinery/food_cart, + )) + if(is_type_in_typecache(machine, paw_passthrough)) + return + INVOKE_ASYNC(src, PROC_REF(fumble_interact), wearer, machine) + return COMPONENT_BLOCK_MACHINERY_INTERACT + +/datum/component/ball_mittens_fumble/proc/on_clickon(mob/living/wearer, atom/target, list/modifiers) + SIGNAL_HANDLER + if(wearer.throw_mode) + var/obj/item/held = wearer.get_active_held_item() + if(!held) + wearer.throw_mode_off(THROW_MODE_TOGGLE) + return COMSIG_MOB_CANCEL_CLICKON + if(prob(5)) + to_chat(wearer, span_purple("You try to grip the [held] with your [get_hand_descriptor(wearer)] to throw it, but it clatters noisily to the floor instead.")) + playsound(wearer, 'modular_skyrat/modules/modular_items/lewd_items/sounds/latex.ogg', 30, TRUE) + wearer.dropItemToGround(held) + wearer.throw_mode_off(THROW_MODE_TOGGLE) + return COMSIG_MOB_CANCEL_CLICKON + if(modifiers && (LAZYACCESS(modifiers, SHIFT_CLICK) || LAZYACCESS(modifiers, ALT_CLICK) || LAZYACCESS(modifiers, RIGHT_CLICK) || LAZYACCESS(modifiers, CTRL_CLICK))) + return + if(get_dist(wearer, target) > 1) + return + if(isclothing(target) && isliving(target.loc) && !wearer.get_active_held_item() && !wearer.combat_mode) + var/obj/item/clothing/cloth = target + var/mob/living/living_loc = target.loc + var/in_hand = (target in wearer.held_items) + var/truly_worn = (cloth.slot_flags && living_loc.get_item_by_slot(cloth.slot_flags) == cloth) + if(in_hand || truly_worn) + if(istype(cloth, /obj/item/clothing/gloves/ball_mittens)) + INVOKE_ASYNC(cloth, TYPE_PROC_REF(/obj/item/clothing/gloves/ball_mittens, doStrip), wearer, wearer) + return COMSIG_MOB_CANCEL_CLICKON + INVOKE_ASYNC(src, PROC_REF(clothing_struggle), wearer, target) + return COMSIG_MOB_CANCEL_CLICKON + +/datum/component/ball_mittens_fumble/proc/clothing_struggle(mob/living/wearer, obj/item/clothing/cloth) + var/delay = 12 SECONDS + var/hand_desc = get_hand_descriptor(wearer) + to_chat(wearer, span_purple("You struggle to remove [cloth]. It's extremely difficult with your [hand_desc]... (This will take around [DisplayTimeText(delay)] and you need to stand still.)")) + if(!do_after(wearer, delay, cloth, timed_action_flags = IGNORE_HELD_ITEM)) + to_chat(wearer, span_warning("You give up on [cloth].")) + return + if(QDELETED(src) || QDELETED(wearer) || QDELETED(cloth)) + return + wearer.dropItemToGround(cloth) + +/datum/component/ball_mittens_fumble/proc/on_unarmed_attack(mob/living/wearer, atom/attack_target, proximity_flag, list/modifiers) + SIGNAL_HANDLER + if(!proximity_flag || !isliving(attack_target)) + return + playsound(wearer, pick('sound/items/toy_squeak/toysqueak1.ogg', 'sound/items/toy_squeak/toysqueak2.ogg', 'sound/items/toy_squeak/toysqueak3.ogg'), 40, TRUE) + +/datum/component/ball_mittens_fumble/proc/on_mousedrop_receive(mob/living/wearer, atom/from, mob/user, params) + SIGNAL_HANDLER + if(user != wearer || !isitem(from)) + return + var/obj/item/dragged = from + var/slot = wearer.get_slot_by_item(dragged) + if(!(slot & (ITEM_SLOT_BELT|ITEM_SLOT_BACK))) + return + INVOKE_ASYNC(src, PROC_REF(delayed_drag_unequip), wearer, dragged) + return COMPONENT_CANCEL_MOUSEDROPPED_ONTO + +/datum/component/ball_mittens_fumble/proc/delayed_drag_unequip(mob/living/wearer, obj/item/item) + var/hand_desc = get_hand_descriptor(wearer) + to_chat(wearer, span_purple("You carefully work at your [item] with your [hand_desc]...")) + if(!do_after(wearer, struggle_delay_min, item, timed_action_flags = IGNORE_HELD_ITEM)) + to_chat(wearer, span_warning("You give up on [item].")) + return + if(QDELETED(src) || QDELETED(wearer) || QDELETED(item)) + return + if(!wearer.get_slot_by_item(item)) + return + wearer.put_in_hands(item) + +/datum/component/ball_mittens_fumble/proc/on_try_strip(mob/living/wearer, atom/target, obj/item/item) + SIGNAL_HANDLER + // COMSIG_TRY_STRIP and COMSIG_BEING_STRIPPED share the same signal string "try_strip". + // When item IS on the wearer: signal fired via COMSIG_BEING_STRIPPED - someone acting on the wearer - allow. + // When item is NOT on the wearer but in target's held_items: equip action onto the wearer - allow. + // When item is NOT on the wearer and NOT in target's hands: wearer is stripping from target - delay. + if(wearer.get_slot_by_item(item)) + return + if(isliving(target)) + var/mob/living/living_target = target + if(item in living_target.held_items) + return // Item in target's hands = equip action, not a strip + if(!isliving(target) || !isitem(item)) + return COMPONENT_CANT_STRIP + to_chat(wearer, span_purple("You fumble awkwardly at [target]'s gear with your [get_hand_descriptor(wearer)], trying to find a grip...")) + INVOKE_ASYNC(src, PROC_REF(delayed_strip), wearer, target, item) + return COMPONENT_CANT_STRIP + +/datum/component/ball_mittens_fumble/proc/delayed_strip(mob/living/wearer, mob/living/target, obj/item/item) + if(!do_after(wearer, item.strip_delay * 2.5, target, timed_action_flags = IGNORE_HELD_ITEM)) + to_chat(wearer, span_warning("You give up trying to remove [item] from [target].")) + return + if(QDELETED(src) || QDELETED(wearer) || QDELETED(target) || QDELETED(item)) + return + item.doStrip(wearer, target) + +/datum/component/ball_mittens_fumble/proc/on_removing_cuffs(mob/living/wearer, obj/item/cuffs) + SIGNAL_HANDLER + if(!cuffs) + return + if(cuffs == tracked_cuffs) + return + tracked_cuffs = cuffs + var/original = cuffs.breakouttime + cuffs.breakouttime = original * cuff_resist_multiplier + addtimer(CALLBACK(src, PROC_REF(restore_breakouttime), cuffs, original), 1, TIMER_UNIQUE | TIMER_OVERRIDE) + +/datum/component/ball_mittens_fumble/proc/restore_breakouttime(obj/item/cuffs, original_time) + if(QDELETED(cuffs)) + tracked_cuffs = null + return + cuffs.breakouttime = original_time + tracked_cuffs = null + +/datum/component/ball_mittens_fumble/proc/on_fired_gun(mob/living/wearer, obj/item/gun/gun, atom/target, params, zone_override, list/bonus_spread_values) + SIGNAL_HANDLER + if(!isgun(gun) || !islist(bonus_spread_values)) + return + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += gun_spread_penalty + +/datum/component/ball_mittens_fumble/proc/fumble_interact(mob/living/wearer, obj/machinery/machine) + is_interacting = TRUE + var/hand_desc = get_hand_descriptor(wearer) + var/msg = istype(machine, /obj/machinery/vending) ? \ + "You awkwardly mash your [hand_desc] against [machine]'s keypad..." : \ + "You awkwardly paw at [machine] with your [hand_desc]..." + wearer.face_atom(machine) + to_chat(wearer, span_purple(msg)) + wearer.visible_message(span_warning("[wearer] awkwardly paws at [machine] with [wearer.p_their()] [hand_desc], visibly struggling to use it.")) + if(!do_after(wearer, interact_delay, machine)) + to_chat(wearer, span_warning("You give up on [machine].")) + is_interacting = FALSE + return + if(QDELETED(src) || QDELETED(wearer) || QDELETED(machine) || get_dist(wearer, machine) > 1) + is_interacting = FALSE + return + machine.interact(wearer) + is_interacting = FALSE + +// ============================================================ + +/datum/atom_skin/ball_mittens_skin + abstract_type = /datum/atom_skin/ball_mittens_skin + greyscale_item_path = /obj/item/clothing/gloves/ball_mittens/loadout_paw + +/datum/atom_skin/ball_mittens_skin/default + preview_name = "Ball Mittens" + reset_missing = TRUE + +/datum/atom_skin/ball_mittens_skin/cat_paws + preview_name = "Cat Paws" + new_name = "latex paw mittens" + new_desc = "A pair of inflatable latex mittens shaped like rounded paws. Helpless AND humiliating." + change_worn_icon_state = FALSE + greyscale_item_path = null + new_icon = 'icons/map_icons/clothing/_clothing.dmi' + new_icon_state = "/obj/item/clothing/gloves/ball_mittens/loadout_paw" + new_worn_icon = 'modular_skyrat/modules/GAGS/icons/catglove_worn.dmi' + +/datum/atom_skin/ball_mittens_skin/cat_paws/get_preview_icon(atom/for_atom) + return image(icon = 'icons/map_icons/clothing/_clothing.dmi', icon_state = "/obj/item/clothing/gloves/ball_mittens/loadout_paw") + +/datum/atom_skin/ball_mittens_skin/cat_paws/apply(atom/apply_to, mob/user) + var/obj/item/clothing/gloves/ball_mittens/mittens = apply_to + if(istype(mittens)) + mittens.greyscale_config = /datum/greyscale_config/catgloves + mittens.greyscale_config_worn = /datum/greyscale_config/catgloves/worn + if(!mittens.greyscale_colors || mittens.greyscale_colors == "") + mittens.greyscale_colors = "#242329#7B48A6#15B1BF" + mittens.flags_1 |= IS_PLAYER_COLORABLE_1 + . = ..() + if(istype(mittens)) + mittens.is_paw_skin = TRUE + mittens.worn_icon = 'modular_skyrat/modules/GAGS/icons/catglove_worn.dmi' + mittens.icon_state = "catgloves" + mittens.worn_icon_state = "catgloves" + mittens.set_greyscale(mittens.greyscale_colors, /datum/greyscale_config/catgloves) + +/datum/atom_skin/ball_mittens_skin/cat_paws/clear_skin(atom/clear_from) + var/obj/item/clothing/gloves/ball_mittens/mittens = clear_from + if(istype(mittens)) + mittens.is_paw_skin = FALSE + mittens.greyscale_config = null + mittens.greyscale_config_worn = null + mittens.flags_1 &= ~IS_PLAYER_COLORABLE_1 + mittens.icon_state = initial(mittens.icon_state) + mittens.worn_icon_state = initial(mittens.worn_icon_state) + mittens.worn_icon = initial(mittens.worn_icon) + . = ..() + if(istype(mittens)) + mittens.update_appearance() + +// ============================================================ + /obj/item/clothing/gloves/ball_mittens name = "ball mittens" - desc = "A nice, comfortable pair of inflatable ball gloves." + desc = "A pair of inflatable latex mittens. Adorable and comfortable, but completely useless for anything requiring fingers. Getting these off yourself is a serious ordeal — you'll probably want help." icon_state = "ballmittens" - inhand_icon_state = null + inhand_icon_state = "" // Explicitly empty - null can cause BYOND to fall back to the main icon icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_clothing/lewd_gloves.dmi' worn_icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/mob/lewd_clothing/lewd_gloves.dmi' - breakouttime = 1 SECONDS + strip_delay = 8 SECONDS + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/ball_mittens + equip_sound = 'modular_zubbers/sound/lewd/rubber1.ogg' + drop_sound = 'modular_zubbers/sound/lewd/rubber2.ogg' + pickup_sound = 'modular_zubbers/sound/lewd/rubber3.ogg' + var/is_paw_skin = FALSE + var/spawn_flavor_shown = FALSE + var/loadout_created = FALSE + var/lights_on = FALSE -//That part allows reinforcing this item with handcuffs -/obj/item/clothing/gloves/ball_mittens/attackby(obj/item/attacking_item, mob/user, params) +/obj/item/clothing/gloves/ball_mittens/Initialize(mapload) . = ..() - if(.) + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/clothing/gloves/ball_mittens/equipped(mob/user, slot) + . = ..() + if(slot != ITEM_SLOT_GLOVES) return - if(!istype(attacking_item, /obj/item/restraints/handcuffs)) + if(is_paw_skin) + to_chat(user, span_purple("The [src] seal around your hands. You pull at them and find it completely impossible to remove them...")) + else + to_chat(user, span_purple("Your hands sink into [src]. Soft, round, and not particularly good at anything. As soon as you put them on, you hear them self inflate. Oh shit...")) + RegisterSignal(src, COMSIG_OBJ_RESKIN, PROC_REF(on_reskin)) + var/datum/component/ball_mittens_fumble/comp = AddComponent(/datum/component/ball_mittens_fumble) + comp.register_wearer(user) + +/obj/item/clothing/gloves/ball_mittens/dropped(mob/user) + . = ..() + UnregisterSignal(src, COMSIG_OBJ_RESKIN) + var/datum/component/ball_mittens_fumble/comp = GetComponent(/datum/component/ball_mittens_fumble) + comp?.unregister_wearer(user) + qdel(comp) + +/obj/item/clothing/gloves/ball_mittens/proc/on_reskin(datum/source, skin_name) + SIGNAL_HANDLER + is_paw_skin = (skin_name == "Cat Paws") + var/mob/living/wearer = loc + if(!isliving(wearer)) return - var/obj/item/clothing/gloves/ball_mittens_reinforced/reinforced_muffs = new - remove_item_from_storage(user) - user.put_in_hands(reinforced_muffs) - to_chat(user, span_notice("You reinforced the belts on [src] with [attacking_item].")) - qdel(attacking_item) - qdel(src) + if(is_paw_skin) + wearer.add_mood_event("paw_mittens", /datum/mood_event/wearing_paw_mittens) + to_chat(wearer, span_purple("The nanite-infused rubber shifts your hands into soft, rounded paw shapes.")) + else + wearer.clear_mood_event("paw_mittens") + to_chat(wearer, span_purple("The mittens ease back into their round ball shape. Still completely useless.")) + +/// Opens the GAGS recolor menu for spray can use on paw mittens. +/// gags_recolorable.open_ui() uses initial() on greyscale_config which returns null +/// for runtime-assigned configs, so we open the menu with the live config directly. +/obj/item/clothing/gloves/ball_mittens/proc/paw_spray_interact(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/toy/crayon/spraycan)) + return NONE + var/obj/item/toy/crayon/spraycan/can = tool + if(can.is_capped) + user.balloon_alert(user, "take the cap off first!") + return ITEM_INTERACT_BLOCKING + if(can.check_empty()) + user.balloon_alert(user, "empty!") + return ITEM_INTERACT_BLOCKING + if(!user.client) + return ITEM_INTERACT_BLOCKING + var/list/allowed = list("[/datum/greyscale_config/catgloves]", "[/datum/greyscale_config/catgloves/worn]") + var/datum/greyscale_modify_menu/spray_paint/menu = new( + src, user.client, allowed, + CALLBACK(src, PROC_REF(apply_spray_colors), can), + "catgloves", + /datum/greyscale_config/catgloves, + greyscale_colors, + can, + ) + menu.ui_interact(user) + return ITEM_INTERACT_SUCCESS + +/obj/item/clothing/gloves/ball_mittens/proc/apply_spray_colors(obj/item/toy/crayon/spraycan/can, datum/greyscale_modify_menu/menu) + if(QDELETED(src) || QDELETED(can) || QDELETED(menu)) + return + if(can.is_capped || can.check_empty()) + menu.ui_close() + return + can.use_charges() + if(can.pre_noise) + audible_message(span_hear("You hear spraying.")) + playsound(loc, 'sound/effects/spray.ogg', 50, TRUE, 5) + set_greyscale(menu.split_colors) + +/obj/item/clothing/gloves/ball_mittens/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(is_paw_skin && istype(tool, /obj/item/toy/crayon/spraycan)) + return paw_spray_interact(user, tool, modifiers) + return ..() + +/obj/item/clothing/gloves/ball_mittens/update_overlays() + . = ..() + if(lights_on && is_paw_skin) + . += emissive_appearance(icon, icon_state, src, alpha = 100) + +/obj/item/clothing/gloves/ball_mittens/worn_overlays(mutable_appearance/standing, isinhands, icon_file) + . = ..() + if(lights_on && is_paw_skin) + . += emissive_appearance(standing.icon, standing.icon_state, src, alpha = 100) + +/obj/item/clothing/gloves/ball_mittens/examine(mob/user) + . = ..() + if(is_paw_skin) + . += span_notice("There's a paw-friendly switch on the cuff. It's currently [lights_on ? "ON" : "OFF"]. \[Toggle\]") + +/obj/item/clothing/gloves/ball_mittens/Topic(href, href_list) + . = ..() + if(href_list["toggle_lights"]) + if(!usr || !ishuman(usr)) + return + var/mob/living/carbon/human/toggler = usr + if(toggler.gloves != src) + return + lights_on = !lights_on + playsound(src, 'sound/machines/click.ogg', 30, FALSE) + to_chat(usr, span_notice("You turn the accent lighting [lights_on ? "on" : "off"].")) + update_appearance() + +/obj/item/clothing/gloves/ball_mittens/proc/deferred_spawn_flavor(mob/user) + if(user.client) + show_spawn_flavor(user) + return + RegisterSignal(user, COMSIG_MOB_LOGIN, PROC_REF(on_client_login_flavor)) + +/obj/item/clothing/gloves/ball_mittens/proc/on_client_login_flavor(mob/user) + SIGNAL_HANDLER + UnregisterSignal(user, COMSIG_MOB_LOGIN) + show_spawn_flavor(user) + +/datum/armor/ball_mittens + bio = 1 + +/obj/item/clothing/gloves/ball_mittens/proc/show_spawn_flavor(mob/user) + if(!user?.client) + return + if(is_paw_skin) + to_chat(user, span_purple("You look down at your paws. Round and soft and utterly useless. You blush as you think about how difficult this is going to make your day at work.")) + else + to_chat(user, span_purple("You look down at [src]. Why did I come to work like this?")) + +/obj/item/clothing/gloves/ball_mittens/attackby(obj/item/item, mob/living/user, params) + if(!istype(item, /obj/item/clothing/gloves/color/yellow)) + return ..() + if(siemens_coefficient == 0) + to_chat(user, span_warning("[src] are already insulated.")) + return + user.visible_message( + span_notice("[user] holds [item] up to [src] with a look of intense concentration, then discards it with a sigh."), + span_notice("You press [item] against [src], attempting to combine them. Halfway through you realize latex is, in fact, already an insulator. You throw away the insulated gloves.") + ) + siemens_coefficient = 0 + name = "insulated [name]" + if(desc == initial(desc)) + desc = "A pair of inflatable latex mittens. Someone has helpfully applied insulated gloves to them, only to realise too late that latex was already an insulator." + qdel(item) + update_appearance() return TRUE -//ball_mittens reinforced -/obj/item/clothing/gloves/ball_mittens_reinforced //We getting this item by using handcuffs on normal ball mittens - name = "reinforced ball mittens" - desc = "Do not put these on, it's REALLY hard to take them off! But they look so comfortable..." - icon_state = "ballmittens" - inhand_icon_state = null - icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/obj/lewd_clothing/lewd_gloves.dmi' - worn_icon = 'modular_skyrat/modules/modular_items/lewd_items/icons/mob/lewd_clothing/lewd_gloves.dmi' - clothing_flags = DANGEROUS_OBJECT - breakouttime = 100 SECONDS //do not touch this, i beg you. +/obj/item/clothing/gloves/ball_mittens/doStrip(mob/stripper, mob/owner) + if(stripper != owner) + if(!owner.dropItemToGround(src, force = TRUE)) + return FALSE + if(HAS_TRAIT(stripper, TRAIT_STICKY_FINGERS)) + stripper.put_in_hands(src) + return TRUE + var/delay = 1 MINUTES + to_chat(owner, span_purple("You attempt to remove [src]... (This will take around [DisplayTimeText(delay)] and you need to stand still.)")) + to_chat(owner, span_purple("You struggle furiously with [src], but you're not even sure if these can come off.")) + playsound(owner, pick('modular_zubbers/sound/lewd/rubber1.ogg', 'modular_zubbers/sound/lewd/rubber2.ogg', 'modular_zubbers/sound/lewd/rubber3.ogg'), 40, TRUE) + if(!do_after(owner, delay, src, timed_action_flags = IGNORE_HELD_ITEM)) + to_chat(owner, span_purple("You give up trying to escape [src]. Maybe having [src] isn't so bad...")) + return FALSE + if(QDELETED(src) || !isliving(loc)) + return FALSE + if(!owner.dropItemToGround(src, force = TRUE)) + return FALSE + if(HAS_TRAIT(stripper, TRAIT_STICKY_FINGERS)) + stripper.put_in_hands(src) + return TRUE + +// ============================================================ +// Loadout subtype for paw mittens. +// ============================================================ + +/obj/item/clothing/gloves/ball_mittens/loadout_paw + name = "latex paw mittens" + desc = "A pair of inflatable latex mittens shaped like rounded paws. Helpless AND humiliating." + greyscale_config = /datum/greyscale_config/catgloves + greyscale_config_worn = /datum/greyscale_config/catgloves/worn + greyscale_colors = "#242329#7B48A6#15B1BF" + flags_1 = IS_PLAYER_COLORABLE_1 + worn_icon = 'modular_skyrat/modules/GAGS/icons/catglove_worn.dmi' + worn_icon_state = "catgloves" + icon_state = "BasePaws" + post_init_icon_state = "catgloves" + icon_preview = 'icons/map_icons/clothing/_clothing.dmi' + icon_state_preview = "/obj/item/clothing/gloves/ball_mittens/loadout_paw" + is_paw_skin = TRUE + inhand_icon_state = "greyscale_gloves" + alternate_worn_layer = SHOES_LAYER // Ensures paws render above mech_suit which claims GLOVES_LAYER + +/obj/item/clothing/gloves/ball_mittens/loadout_paw/Initialize(mapload) + . = ..() + loadout_created = TRUE + for(var/datum/component/reskinable_item/reskin_comp in GetComponents(/datum/component/reskinable_item)) + qdel(reskin_comp) + +/obj/item/clothing/gloves/ball_mittens/loadout_paw/equipped(mob/user, slot) + . = ..() + if(slot != ITEM_SLOT_GLOVES) + return + update_greyscale() + +// ============================================================ + +/datum/mood_event/wearing_paw_mittens + description = span_purple("So-ft... Ro-und... Use-less... Lo-ve it!\n") -//latex gloves /obj/item/clothing/gloves/latex_gloves name = "latex gloves" desc = "Awesome looking gloves that are satisfying to the touch." diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm index a7253d276ef..0d842d7f221 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_helpers/human.dm @@ -357,15 +357,6 @@ * MISC LOGIC */ -// Handles breaking out of gloves that restrain people. -/mob/living/carbon/human/resist_restraints() - if(gloves?.breakouttime) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT - cuff_resist(gloves) - else - ..() - /// Checks if the human is wearing a condom, and also hasn't broken it. /mob/living/carbon/human/proc/is_wearing_condom() if(!penis || !istype(penis, /obj/item/clothing/sextoy/condom)) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/_erp_disabled_item_enforcement.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/_erp_disabled_item_enforcement.dm index 0b5155e6cd3..fd68b0c3118 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/_erp_disabled_item_enforcement.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_items/_erp_disabled_item_enforcement.dm @@ -77,8 +77,9 @@ . = ..() if(CONFIG_GET(flag/disable_lewd_items)) return INITIALIZE_HINT_QDEL + AddComponent(/datum/component/reskinable_item, /datum/atom_skin/ball_mittens_skin, FALSE) -/obj/item/clothing/gloves/ball_mittens_reinforced/Initialize(mapload) +/obj/item/clothing/gloves/ball_mittens/loadout_paw/Initialize(mapload) . = ..() if(CONFIG_GET(flag/disable_lewd_items)) return INITIALIZE_HINT_QDEL @@ -237,8 +238,3 @@ . = ..() if(CONFIG_GET(flag/disable_lewd_items)) return INITIALIZE_HINT_QDEL - -/obj/item/toy/plush/aeri/Initialize(mapload) - . = ..() - if(CONFIG_GET(flag/disable_lewd_items)) - return INITIALIZE_HINT_QDEL diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm index bf075cf3e9e..34ec651693e 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm @@ -124,6 +124,7 @@ //hands /obj/item/clothing/gloves/ball_mittens = 8, + /obj/item/clothing/gloves/ball_mittens/loadout_paw = 5, ), ), list( diff --git a/modular_zubbers/code/_globalvars/lists/erp_items.dm b/modular_zubbers/code/_globalvars/lists/erp_items.dm index 20a9a4be496..cd9795ad789 100644 --- a/modular_zubbers/code/_globalvars/lists/erp_items.dm +++ b/modular_zubbers/code/_globalvars/lists/erp_items.dm @@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(erp_items, list( /obj/item/clothing/glasses/blindfold/kinky, /obj/item/clothing/glasses/hypno, /obj/item/clothing/gloves/ball_mittens, - /obj/item/clothing/gloves/ball_mittens_reinforced, + /obj/item/clothing/gloves/ball_mittens/loadout_paw, /obj/item/clothing/head/domina_cap, /obj/item/clothing/mask/ballgag, /obj/item/clothing/mask/gas/bdsm_mask, diff --git a/modular_zubbers/code/modules/clothing/gloves/misc.dm b/modular_zubbers/code/modules/clothing/gloves/misc.dm index 7eb04b29d49..215d6ccd81f 100644 --- a/modular_zubbers/code/modules/clothing/gloves/misc.dm +++ b/modular_zubbers/code/modules/clothing/gloves/misc.dm @@ -15,17 +15,86 @@ //Cat Gloves seemingly by Taomayo of MonkeStation /obj/item/clothing/gloves/cat - desc = "hewwo everynyaan!!" + desc = "\"High Tech\" paw shaped gloves perfect for cosplay enthusiasts, streamers and general weirdos. hewwo everynyaan!!" name = "cat gloves" icon = 'icons/map_icons/clothing/_clothing.dmi' icon_state = "/obj/item/clothing/gloves/cat" post_init_icon_state = "catgloves" flags_1 = IS_PLAYER_COLORABLE_1 - greyscale_colors = "#ffffff#FFC0CB" + greyscale_colors = "#ffffff#FFC0CB#B0EAF6" greyscale_config_worn = /datum/greyscale_config/catgloves/worn greyscale_config = /datum/greyscale_config/catgloves greyscale_config_inhand_left = null greyscale_config_inhand_right = null + resistance_flags = FIRE_PROOF + var/lights_on = FALSE + +/obj/item/clothing/gloves/cat/Initialize(mapload) + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/clothing/gloves/cat/equipped(mob/user, slot) + . = ..() + if(slot == ITEM_SLOT_GLOVES) + ADD_TRAIT(user, TRAIT_GLOVE_SURGERY_PASSTHROUGH, "cat_gloves") + +/obj/item/clothing/gloves/cat/dropped(mob/user) + . = ..() + REMOVE_TRAIT(user, TRAIT_GLOVE_SURGERY_PASSTHROUGH, "cat_gloves") + +/obj/item/clothing/gloves/cat/update_overlays() + . = ..() + if(lights_on) + . += emissive_appearance(icon, icon_state, src, alpha = 100) + +/obj/item/clothing/gloves/cat/worn_overlays(mutable_appearance/standing, isinhands, icon_file) + . = ..() + if(lights_on) + . += emissive_appearance(standing.icon, standing.icon_state, src, alpha = 100) + +/obj/item/clothing/gloves/cat/examine(mob/user) + . = ..() + . += span_notice("There's a small switch on the wrist. It's currently [lights_on ? "ON" : "OFF"]. \[Toggle\]") + +/obj/item/clothing/gloves/cat/Topic(href, href_list) + . = ..() + if(href_list["toggle_lights"]) + if(!usr || !ishuman(usr)) + return + var/mob/living/carbon/human/toggler = usr + if(toggler.gloves != src) + return + lights_on = !lights_on + playsound(src, 'sound/machines/click.ogg', 30, FALSE) + to_chat(usr, span_notice("You turn the accent lighting [lights_on ? "on" : "off"].")) + update_appearance() + +/obj/item/clothing/gloves/cat/attackby(obj/item/item, mob/living/user, params) + if(!istype(item, /obj/item/clothing/gloves/color/yellow)) + return ..() + if(siemens_coefficient == 0) + to_chat(user, span_warning("[src] are already insulated.")) + return + user.visible_message( + span_notice("[user] awkwardly crams [item] inside [src]."), + span_notice("You press [item] against [src], after some time you succeed at inserting [item] inside.") + ) + siemens_coefficient = 0 + name = "insulated [name]" + if(desc == initial(desc)) + desc = "A pair of cat gloves with a pair of insulated gloves awkwardly crammed inside them. Somehow this works." + qdel(item) + update_appearance() + return TRUE + +/obj/item/clothing/gloves/cat/equipped(mob/user, slot) + . = ..() + if(slot == ITEM_SLOT_GLOVES) + ADD_TRAIT(user, TRAIT_GLOVE_SURGERY_PASSTHROUGH, "cat_gloves") + +/obj/item/clothing/gloves/cat/dropped(mob/user) + . = ..() + REMOVE_TRAIT(user, TRAIT_GLOVE_SURGERY_PASSTHROUGH, "cat_gloves") //Metrocop Gloves by ... Dun dun dun, HL13 station. diff --git a/modular_zubbers/code/modules/loadout/categories/gloves.dm b/modular_zubbers/code/modules/loadout/categories/gloves.dm index 1c4e067803d..5e7534286dd 100644 --- a/modular_zubbers/code/modules/loadout/categories/gloves.dm +++ b/modular_zubbers/code/modules/loadout/categories/gloves.dm @@ -157,6 +157,14 @@ name = "Charcoal Fingerless Gloves" item_path = /obj/item/clothing/gloves/skyy +// Uses a loadout-only dummy type that holds the catgloves GAGS config at type level +// so the loadout color picker works, then swaps itself for real ball mittens in paw mode on spawn. +// i know this is probably dumb but I couldn't figure out a better way to do it :( +/datum/loadout_item/gloves/ball_mittens_paw + name = "Latex Paw Mittens" + item_path = /obj/item/clothing/gloves/ball_mittens/loadout_paw + erp_item = TRUE + /* * RINGS */ diff --git a/modular_zubbers/code/modules/loadout/categories/toys.dm b/modular_zubbers/code/modules/loadout/categories/toys.dm index 59b3907e29d..21073b5d61e 100644 --- a/modular_zubbers/code/modules/loadout/categories/toys.dm +++ b/modular_zubbers/code/modules/loadout/categories/toys.dm @@ -209,6 +209,11 @@ name = "Strapon" item_path = /obj/item/clothing/strapon +/datum/loadout_item/toys/lewd/ball_mittens + name = "Ball Mittens" + item_path = /obj/item/clothing/gloves/ball_mittens + erp_item = TRUE + /datum/loadout_item/toys/lewd/aeri name = "Interdimensional Terrorist Plushie" item_path = /obj/item/toy/plush/aeri