From 669c36417ac3aad6fdd9daab74ca183283f2fd9f Mon Sep 17 00:00:00 2001 From: Mathilde <146444134+ibexgoetia@users.noreply.github.com> Date: Fri, 10 Apr 2026 13:04:08 +0200 Subject: [PATCH] Horse bridles (#5162) ## About The Pull Request This has been more or less in the works for a bit. This PR adds a horse bridle to the game. It's worn on the face/mask slot, and can be found in the loadout menu (under Masks) or in the lustwish vendor (under Restraints). It includes blinders and a bit, which will blind and gag the wearer, respectively. By default both are inactive. Interacting with it by alt clicking will cycle through a few modes: Blinders + Bit, Blinders, Bit, None. When worn you can also set them individually (though the alt click cycling still works). The blinders and the bit can also be cycled by others with the strip menu; this will take 4 seconds. To avoid this from happening, you can interact with the bridle in your hand to secure the straps. This will also prevent you from setting them yourself; you will have to unsecure the straps for it. ## Why It's Good For The Game It's a very neat addition for equine characters and for people into horse stuff. It's not necessarily an ERP item (in my opinion as much of an ERP item as the collars) so I haven't set it as an ERP item specifically, but I can change it if you think that would be better. ## Proof Of Testing File is too big for github https://files.catbox.moe/31vy7y.mp4 ## Changelog :cl: add: Added horse bridles to the loadout menu and the lustwish vendors. They come equipped with settable blinders and bit. /:cl: --- .../code/modules/lewd_machinery/bridle.dm | 340 ++++++++++++++++++ .../code/modules/loadout/categories/masks.dm | 4 + .../code/modules/vending/lustwish.dm | 1 + .../icons/mob/clothing/mask/mask.dmi | Bin 6555 -> 6984 bytes .../icons/obj/clothing/mask/mask.dmi | Bin 956 -> 1149 bytes tgstation.dme | 1 + tgui/packages/tgui/interfaces/StripMenu.tsx | 5 + 7 files changed, 351 insertions(+) create mode 100644 modular_zubbers/code/modules/lewd_machinery/bridle.dm diff --git a/modular_zubbers/code/modules/lewd_machinery/bridle.dm b/modular_zubbers/code/modules/lewd_machinery/bridle.dm new file mode 100644 index 00000000000..e186ab5f805 --- /dev/null +++ b/modular_zubbers/code/modules/lewd_machinery/bridle.dm @@ -0,0 +1,340 @@ + +/obj/item/clothing/mask/bridle + name = "bridle" + desc = "A Sunny Stables design of a leather horse bridle, complete with blinders and a bit. It's made of several leather straps and metal fittings. You can tighten or loosen the straps to make sure that the blinders and the bit stay in place." + icon_state = "bridle" + inhand_icon_state = "sechailer" + icon = 'modular_zubbers/icons/obj/clothing/mask/mask.dmi' + worn_icon = 'modular_zubbers/icons/mob/clothing/mask/mask.dmi' + worn_icon_state = "bridle" + throwforce = 0 + w_class = WEIGHT_CLASS_SMALL + flags_cover = NONE + actions_types = list( + /datum/action/item_action/bridle_toggle_blinders, + /datum/action/item_action/bridle_toggle_gag, + ) + action_slots = ITEM_SLOT_MASK + var/blinders_enabled = FALSE + var/gag_enabled = FALSE + var/blinders_tint = 2 + var/last_blinders_enabled = FALSE + var/last_gag_enabled = FALSE + var/straps_locked = FALSE + var/strip_adjust_delay = 4 SECONDS + +/obj/item/clothing/mask/bridle/Initialize(mapload) + . = ..() + update_bridle_state() + +/obj/item/clothing/mask/bridle/Destroy() + var/mob/living/carbon/wearer = get_wearer() + if(wearer) + remove_gag(wearer) + wearer.update_tint() + return ..() + +/obj/item/clothing/mask/bridle/equipped(mob/living/carbon/user, slot) + . = ..() + if(!(slot & ITEM_SLOT_MASK)) + return + playsound(user, 'sound/items/equip/toolbelt_equip.ogg', 50, TRUE) + update_bridle_state(user) + user.update_action_buttons() + +/obj/item/clothing/mask/bridle/dropped(mob/living/carbon/user) + . = ..() + if(gag_enabled) + remove_gag(user) + if(blinders_enabled) + user.update_tint() + user.update_worn_mask() + user.update_action_buttons() + +/obj/item/clothing/mask/bridle/click_alt(mob/user) + if(!istype(user) || user.incapacitated) + return CLICK_ACTION_BLOCKING + cycle_mode(user) + return CLICK_ACTION_SUCCESS + +/obj/item/clothing/mask/bridle/attack_self(mob/user) + . = ..() + if(!istype(user) || user.incapacitated) + return + straps_locked = !straps_locked + if(straps_locked) + to_chat(user, span_notice("You secure the bridle's straps.")) + else + to_chat(user, span_notice("You loosen the bridle's straps.")) + +/obj/item/clothing/mask/bridle/proc/get_wearer() + var/mob/living/carbon/wearer = istype(loc, /mob/living/carbon) ? loc : null + if(wearer && wearer.get_item_by_slot(ITEM_SLOT_MASK) == src) + return wearer + return null + +/obj/item/clothing/mask/bridle/proc/should_show_user_message(mob/user) + if(!user) + return FALSE + return user.get_item_by_slot(ITEM_SLOT_MASK) != src + +/obj/item/clothing/mask/bridle/proc/locked_message(mob/user) + if(!user) + return + if(should_show_user_message(user)) + to_chat(user, span_notice("The straps are too secure to adjust.")) + else + to_chat(user, span_warning("The straps are too secure!")) + +/obj/item/clothing/mask/bridle/examine(mob/user) + . = ..() + var/blinders_state_text = blinders_enabled ? "down" : "up" + var/gag_state_text = gag_enabled ? "set" : "unset" + . += span_notice("The blinders are [blinders_state_text], and the bit is [gag_state_text].") + +/obj/item/clothing/mask/bridle/proc/update_bridle_state(mob/user, notify_wearer = TRUE) + var/mob/living/carbon/wearer = get_wearer() + worn_icon_state = blinders_enabled ? "bridle_blinders" : "bridle" + tint = blinders_enabled ? blinders_tint : 0 + flags_cover = gag_enabled ? MASKCOVERSMOUTH : NONE + if(wearer) + if(blinders_enabled != last_blinders_enabled) + if(notify_wearer) + var/blinders_action + var/blinders_action_self + var/blinders_effect + var/blinders_self + if(blinders_enabled) + blinders_action = "lowers" + blinders_action_self = "lower" + blinders_effect = "obscuring your vision" + blinders_self = "lower, obscuring your vision" + else + blinders_action = "raises" + blinders_action_self = "raise" + blinders_effect = "restoring your sight" + blinders_self = "raise, restoring your sight" + if(user && user != wearer) + to_chat(wearer, span_userdanger("[user] [blinders_action] the bridle's blinders, [blinders_effect].")) + else if(user) + to_chat(wearer, span_notice("You [blinders_action_self] the bridle's blinders, [blinders_effect].")) + else + to_chat(wearer, span_notice("The bridle's blinders [blinders_self].")) + last_blinders_enabled = blinders_enabled + if(gag_enabled != last_gag_enabled) + if(notify_wearer) + var/gag_action + var/gag_action_self + var/gag_effect + var/gag_self + if(gag_enabled) + gag_action = "sets" + gag_action_self = "set" + gag_effect = "muffling your speech" + gag_self = "fits in your mouth, muffling your speech" + else + gag_action = "loosens" + gag_action_self = "loosen" + gag_effect = "letting you speak freely" + gag_self = "loosens, allowing you to speak freely" + if(user && user != wearer) + to_chat(wearer, span_userdanger("[user] [gag_action] the bridle's bit, [gag_effect].")) + else if(user) + to_chat(wearer, span_notice("You [gag_action_self] the bridle's bit, [gag_effect].")) + else + to_chat(wearer, span_notice("The bridle's bit [gag_self].")) + last_gag_enabled = gag_enabled + wearer.update_tint() + wearer.update_worn_mask() + if(gag_enabled) + apply_gag(wearer) + else + remove_gag(wearer) + +/obj/item/clothing/mask/bridle/proc/toggle_blinders(mob/user) + if(straps_locked) + locked_message(user) + return + blinders_enabled = !blinders_enabled + if(should_show_user_message(user)) + var/blinders_action + if(blinders_enabled) + blinders_action = "lower" + else + blinders_action = "raise" + to_chat(user, span_notice("You [blinders_action] the bridle's blinders.")) + update_bridle_state(user) + +/obj/item/clothing/mask/bridle/proc/toggle_gag(mob/user) + if(straps_locked) + locked_message(user) + return + gag_enabled = !gag_enabled + if(should_show_user_message(user)) + var/gag_action + if(gag_enabled) + gag_action = "secure" + else + gag_action = "loosen" + to_chat(user, span_notice("You [gag_action] the bridle's bit.")) + update_bridle_state(user) + +/obj/item/clothing/mask/bridle/proc/cycle_mode(mob/user) + if(straps_locked) + locked_message(user) + return + if(!blinders_enabled && !gag_enabled) + set_mode(TRUE, FALSE, user) + return + if(blinders_enabled && !gag_enabled) + set_mode(FALSE, TRUE, user) + return + if(!blinders_enabled && gag_enabled) + set_mode(TRUE, TRUE, user) + return + set_mode(FALSE, FALSE, user) + +/obj/item/clothing/mask/bridle/proc/set_mode(new_blinders, new_gag, mob/user, notify_wearer = TRUE) + if(straps_locked) + locked_message(user) + return + blinders_enabled = new_blinders + gag_enabled = new_gag + if(user) + var/balloon_state + if(blinders_enabled && gag_enabled) + balloon_state = "blinders + bit" + else if(blinders_enabled) + balloon_state = "blinders" + else if(gag_enabled) + balloon_state = "bit" + else + balloon_state = "none" + if(should_show_user_message(user)) + balloon_alert(user, "mode: [balloon_state]") + if(should_show_user_message(user)) + var/state_text + if(blinders_enabled && gag_enabled) + state_text = "blinders and bit" + else if(blinders_enabled) + state_text = "blinders" + else if(gag_enabled) + state_text = "bit" + else + state_text = "none" + to_chat(user, span_notice("Bridle set to: [state_text].")) + update_bridle_state(user, notify_wearer) + +/obj/item/clothing/mask/bridle/proc/strip_adjust(mob/living/carbon/wearer, mob/living/stripper) + if(!wearer || !stripper) + return + if(straps_locked) + locked_message(stripper) + return + if(wearer.get_item_by_slot(ITEM_SLOT_MASK) != src) + return + if(!stripper.Adjacent(wearer)) + wearer.balloon_alert(stripper, "can't reach!") + return + if(!do_after(stripper, strip_adjust_delay, wearer)) + return + var/old_blinders = blinders_enabled + var/old_gag = gag_enabled + var/new_blinders + var/new_gag + if(!blinders_enabled && !gag_enabled) + new_blinders = TRUE + new_gag = FALSE + else if(blinders_enabled && !gag_enabled) + new_blinders = FALSE + new_gag = TRUE + else if(!blinders_enabled && gag_enabled) + new_blinders = TRUE + new_gag = TRUE + else + new_blinders = FALSE + new_gag = FALSE + var/list/parts = list() + if(old_blinders != new_blinders) + parts += (new_blinders ? "lower the bridle's blinders" : "raise the bridle's blinders") + if(old_gag != new_gag) + parts += (new_gag ? "set the bridle's bit" : "loosen the bridle's bit") + var/action_text = parts.len ? jointext(parts, " and ") : "adjust the bridle" + to_chat(stripper, span_notice("You [action_text].")) + set_mode(new_blinders, new_gag, stripper, TRUE) + +/datum/strippable_item/mob_item_slot/mask/get_alternate_actions(atom/source, mob/user, obj/item/item) + . = ..() + var/obj/item/clothing/mask/bridle/bridle = item + if(!istype(bridle)) + return + . += "adjust_bridle" + +/datum/strippable_item/mob_item_slot/mask/perform_alternate_action(atom/source, mob/user, action_key, obj/item/item) + if(!..()) + return + var/obj/item/clothing/mask/bridle/bridle = item + if(!istype(bridle)) + return + if(action_key == "adjust_bridle") + bridle.strip_adjust(source, user) + +/obj/item/clothing/mask/bridle/proc/apply_gag(mob/living/carbon/wearer) + if(!wearer || wearer.get_item_by_slot(ITEM_SLOT_MASK) != src) + return + UnregisterSignal(wearer, list(COMSIG_MOB_SAY, COMSIG_MOB_PRE_EMOTED)) + RegisterSignal(wearer, COMSIG_MOB_SAY, PROC_REF(muzzle_talk)) + RegisterSignal(wearer, COMSIG_MOB_PRE_EMOTED, PROC_REF(emote_override)) + +/obj/item/clothing/mask/bridle/proc/remove_gag(mob/living/carbon/wearer) + if(!wearer) + return + UnregisterSignal(wearer, list(COMSIG_MOB_SAY, COMSIG_MOB_PRE_EMOTED)) + +/obj/item/clothing/mask/bridle/proc/emote_override(mob/living/source, key, params, type_override, intentional, datum/emote/emote) + SIGNAL_HANDLER + if(emote.muzzle_ignore) + return NONE + if(emote.key in list("snort", "neigh", "neigh2")) //Can still do horse emotes because DUH + return NONE + if(!emote.hands_use_check && (emote.emote_type & EMOTE_AUDIBLE)) + source.audible_message("makes a [pick("strong ", "weak ", "")]noise.", audible_message_flags = EMOTE_MESSAGE|ALWAYS_SHOW_SELF_MESSAGE) + return COMPONENT_CANT_EMOTE + return NONE + +/obj/item/clothing/mask/bridle/proc/muzzle_talk(datum/source, list/speech_args) + SIGNAL_HANDLER + if(HAS_TRAIT(source, TRAIT_SIGN_LANG)) + return + var/spoken_message = speech_args[SPEECH_MESSAGE] + if(spoken_message) + var/list/words = splittext(spoken_message, " ") + var/yell_suffix = copytext(spoken_message, findtext(spoken_message, "!")) + spoken_message = "" + + for(var/ind = 1 to length(words)) + var/new_word = "" + for(var/i = 1 to length(words[ind]) + rand(-1,1)) + new_word += "m" + new_word += "f" + words[ind] = yell_suffix ? uppertext(new_word) : new_word + spoken_message = "[jointext(words, " ")][yell_suffix]" + speech_args[SPEECH_MESSAGE] = spoken_message + +/datum/action/item_action/bridle_toggle_blinders + name = "Toggle blinders" + desc = "Adjust the bridle blinders." + +/datum/action/item_action/bridle_toggle_blinders/Trigger(trigger_flags) + var/obj/item/clothing/mask/bridle/bridle = target + if(istype(bridle)) + bridle.toggle_blinders(owner) + +/datum/action/item_action/bridle_toggle_gag + name = "Toggle gag" + desc = "Adjust the bridle bit." + +/datum/action/item_action/bridle_toggle_gag/Trigger(trigger_flags) + var/obj/item/clothing/mask/bridle/bridle = target + if(istype(bridle)) + bridle.toggle_gag(owner) diff --git a/modular_zubbers/code/modules/loadout/categories/masks.dm b/modular_zubbers/code/modules/loadout/categories/masks.dm index be8e8322e1f..cd31dace1c7 100644 --- a/modular_zubbers/code/modules/loadout/categories/masks.dm +++ b/modular_zubbers/code/modules/loadout/categories/masks.dm @@ -218,6 +218,10 @@ item_path = /obj/item/clothing/mask/whistle restricted_roles = list(ALL_JOBS_SEC) +/datum/loadout_item/mask/utility/bridle + name = "Bridle" + item_path = /obj/item/clothing/mask/bridle + /* * COSTUMES */ diff --git a/modular_zubbers/code/modules/vending/lustwish.dm b/modular_zubbers/code/modules/vending/lustwish.dm index 8ef32a2852f..463c8e7f117 100644 --- a/modular_zubbers/code/modules/vending/lustwish.dm +++ b/modular_zubbers/code/modules/vending/lustwish.dm @@ -7,6 +7,7 @@ /obj/item/clothing/neck/human_petcollar/locked/ringbell = 8, /obj/item/clothing/neck/inferno_collar = 8, /obj/item/clothing/neck/flower_collar = 8, + /obj/item/clothing/mask/bridle = 8, ) ), diff --git a/modular_zubbers/icons/mob/clothing/mask/mask.dmi b/modular_zubbers/icons/mob/clothing/mask/mask.dmi index 3c45ed707cbccc372c5bf93e0d2ef778e0bf4b3a..8a329c62629e126c52357575b0765d430cbb0209 100644 GIT binary patch literal 6984 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 F{~OiCQ9=L! literal 6555 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 = { icon: 'ribbon', text: 'Strip accessory', }, + + adjust_bridle: { + icon: 'mask', + text: 'Adjust bridle', + }, }; const SLOTS: Record<