mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 06:00:16 +01:00
Put clothing on people by clicking on them with clothing inhand + targeting correct area. (#69560)
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
co-authored by
Mothblocks
parent
cc1d242273
commit
e0b706c36c
@@ -1,3 +1,6 @@
|
||||
// /obj/item/clothing
|
||||
/// (/obj/item/clothing, visor_state) - When a clothing gets it's visor toggled.
|
||||
#define COMSIG_CLOTHING_VISOR_TOGGLE "clothing_visor_toggle"
|
||||
// /obj/item/clothing
|
||||
/// Sent when mobs try to equip clothing on others through attacking
|
||||
#define COMSIG_CLOTHING_ATTACK_EQUIP "clothing_attack_equip"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Attached to an item, when the item is used to attack a human, and the attacker isn't in combat mode, attempts to equip the item to the target after the normal delay.
|
||||
*
|
||||
* Uses the compare_zone_to_item_slot() proc to see if the attacker is targeting a valid slot.
|
||||
*/
|
||||
/datum/element/attack_equip
|
||||
|
||||
/datum/element/attack_equip/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!isitem(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/on_item_attack)
|
||||
|
||||
/datum/element/attack_equip/Detach(datum/source, ...)
|
||||
. = ..()
|
||||
|
||||
UnregisterSignal(source, COMSIG_ITEM_ATTACK)
|
||||
|
||||
/datum/element/attack_equip/proc/on_item_attack(obj/item/attire, mob/living/target, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
if(user.combat_mode || !ishuman(target) || target == user)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/sharp_dresser = target
|
||||
var/targeted_zone = user.zone_selected
|
||||
|
||||
if(!attire.compare_zone_to_item_slot(targeted_zone))
|
||||
return
|
||||
|
||||
if(attire.mob_can_equip(target, user, attire.slot_flags, disable_warning = TRUE, bypass_equip_delay_self = TRUE))
|
||||
INVOKE_ASYNC(src, .proc/equip, attire, sharp_dresser, user)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
|
||||
/datum/element/attack_equip/proc/equip(obj/item/attire, mob/living/carbon/human/sharp_dresser, mob/living/user)
|
||||
|
||||
if(HAS_TRAIT(attire, TRAIT_NODROP))
|
||||
to_chat(user, span_warning("You can't put [attire] on [sharp_dresser], it's stuck to your hand!"))
|
||||
return
|
||||
var/equip_time = attire.equip_delay_other
|
||||
|
||||
attire.item_start_equip(sharp_dresser, attire, user)
|
||||
|
||||
if(!do_mob(user, sharp_dresser, equip_time))
|
||||
return
|
||||
|
||||
if(QDELETED(src) || QDELETED(sharp_dresser))
|
||||
return
|
||||
|
||||
if(!user.Adjacent(sharp_dresser)) // Due to teleporting shenanigans
|
||||
user.put_in_hands(attire)
|
||||
return
|
||||
|
||||
user.temporarilyRemoveItemFromInventory(attire)
|
||||
|
||||
sharp_dresser.equip_to_slot_if_possible(attire, attire.slot_flags)
|
||||
|
||||
return finish_equip_mob(attire, sharp_dresser, user)
|
||||
@@ -87,37 +87,8 @@
|
||||
/// Start the equipping process. This is the proc you should yield in.
|
||||
/// Returns TRUE/FALSE depending on if it is allowed.
|
||||
/datum/strippable_item/proc/start_equip(atom/source, obj/item/equipping, mob/user)
|
||||
if (warn_dangerous_clothing && isclothing(source))
|
||||
var/obj/item/clothing/clothing = source
|
||||
if(clothing.clothing_flags & DANGEROUS_OBJECT)
|
||||
source.visible_message(
|
||||
span_danger("[user] tries to put [equipping] on [source]."),
|
||||
span_userdanger("[user] tries to put [equipping] on you."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
else
|
||||
source.visible_message(
|
||||
span_notice("[user] tries to put [equipping] on [source]."),
|
||||
span_notice("[user] tries to put [equipping] on you."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/victim_human = source
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(user.name, "tried equipping you with [equipping]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
else if(victim_human.is_blind())
|
||||
to_chat(source, span_userdanger("You feel someone trying to put something on you."))
|
||||
|
||||
to_chat(user, span_notice("You try to put [equipping] on [source]..."))
|
||||
|
||||
user.log_message("is putting [equipping] on [key_name(source)]", LOG_ATTACK, color="red")
|
||||
source.log_message("is having [equipping] put on them by [key_name(user)]", LOG_VICTIM, color="orange", log_globally=FALSE)
|
||||
|
||||
equipping.item_start_equip(source, equipping, user, warn_dangerous_clothing)
|
||||
return TRUE
|
||||
|
||||
/// The proc that places the item on the source. This should not yield.
|
||||
|
||||
@@ -1486,3 +1486,63 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons
|
||||
*/
|
||||
/obj/item/proc/get_writing_implement_details()
|
||||
return null
|
||||
|
||||
/**
|
||||
* When called on an item, and given a body targeting zone, this will return TRUE if the item slot matches the target zone, and FALSE otherwise.
|
||||
* Currently supports the jumpsuit, outersuit, backpack, belt, gloves, hat, ears, neck, mask, eyes, and feet slots. All other slots will auto return FALSE.
|
||||
*/
|
||||
/obj/item/proc/compare_zone_to_item_slot(zone)
|
||||
switch(slot_flags)
|
||||
if(ITEM_SLOT_ICLOTHING, ITEM_SLOT_OCLOTHING, ITEM_SLOT_BACK)
|
||||
return (zone == BODY_ZONE_CHEST)
|
||||
if(ITEM_SLOT_BELT)
|
||||
return (zone == BODY_ZONE_PRECISE_GROIN)
|
||||
if(ITEM_SLOT_GLOVES)
|
||||
return (zone == BODY_ZONE_R_ARM || zone == BODY_ZONE_L_ARM)
|
||||
if(ITEM_SLOT_HEAD, ITEM_SLOT_EARS, ITEM_SLOT_NECK)
|
||||
return (zone == BODY_ZONE_HEAD)
|
||||
if(ITEM_SLOT_MASK)
|
||||
return (zone == BODY_ZONE_PRECISE_MOUTH)
|
||||
if(ITEM_SLOT_EYES)
|
||||
return (zone == BODY_ZONE_PRECISE_EYES)
|
||||
if(ITEM_SLOT_FEET)
|
||||
return (zone == BODY_ZONE_L_LEG || zone == BODY_ZONE_R_LEG)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* This proc calls at the begining of anytime an item is being equiped to a target by another mob.
|
||||
* It handles initial messages, AFK stripping, and initial logging.
|
||||
*/
|
||||
/obj/item/proc/item_start_equip(atom/target, obj/item/equipping, mob/user, warn_dangerous = TRUE)
|
||||
|
||||
if(warn_dangerous && isclothing(equipping))
|
||||
var/obj/item/clothing/clothing = equipping
|
||||
if(clothing.clothing_flags & DANGEROUS_OBJECT)
|
||||
target.visible_message(
|
||||
span_danger("[user] tries to put [equipping] on [target]."),
|
||||
span_userdanger("[user] tries to put [equipping] on you."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
else
|
||||
target.visible_message(
|
||||
span_notice("[user] tries to put [equipping] on [target]."),
|
||||
span_notice("[user] tries to put [equipping] on you."),
|
||||
ignored_mobs = user,
|
||||
)
|
||||
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/victim_human = target
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(user.name, "tried equipping you with [equipping]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
else if(victim_human.is_blind())
|
||||
to_chat(target, span_userdanger("You feel someone trying to put something on you."))
|
||||
user.do_item_attack_animation(target, used_item = equipping)
|
||||
|
||||
to_chat(user, span_notice("You try to put [equipping] on [target]..."))
|
||||
|
||||
user.log_message("is putting [equipping] on [key_name(target)]", LOG_ATTACK, color="red")
|
||||
target.log_message("is having [equipping] put on them by [key_name(user)]", LOG_VICTIM, color="orange", log_globally=FALSE)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/obj/item/storage/backpack/Initialize(mapload)
|
||||
. = ..()
|
||||
create_storage(max_slots = 21, max_total_storage = 21)
|
||||
AddElement(/datum/element/attack_equip)
|
||||
|
||||
/*
|
||||
* Backpack Types
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
/obj/item/storage/belt/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/attack_equip)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/storage/belt/utility
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
AddElement(/datum/element/venue_price, FOOD_PRICE_CHEAP)
|
||||
if(can_be_bloody && ((body_parts_covered & FEET) || (flags_inv & HIDESHOES)))
|
||||
LoadComponent(/datum/component/bloodysoles)
|
||||
AddElement(/datum/element/attack_equip)
|
||||
if(!icon_state)
|
||||
item_flags |= ABSTRACT
|
||||
|
||||
@@ -104,8 +105,8 @@
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/attack(mob/living/M, mob/living/user, params)
|
||||
if(user.combat_mode || !ismoth(M) || ispickedupmob(src))
|
||||
/obj/item/clothing/attack(mob/living/target, mob/living/user, params)
|
||||
if(user.combat_mode || !ismoth(target) || ispickedupmob(src))
|
||||
return ..()
|
||||
if(clothing_flags & INEDIBLE_CLOTHING)
|
||||
return ..()
|
||||
@@ -113,7 +114,7 @@
|
||||
moth_snack = new
|
||||
moth_snack.name = name
|
||||
moth_snack.clothing = WEAKREF(src)
|
||||
moth_snack.attack(M, user, params)
|
||||
moth_snack.attack(target, user, params)
|
||||
|
||||
/obj/item/clothing/attackby(obj/item/W, mob/user, params)
|
||||
if(!istype(W, repairable_by))
|
||||
|
||||
@@ -998,6 +998,7 @@
|
||||
#include "code\datums\elements\art.dm"
|
||||
#include "code\datums\elements\atmos_requirements.dm"
|
||||
#include "code\datums\elements\atmos_sensitive.dm"
|
||||
#include "code\datums\elements\attack_equip.dm"
|
||||
#include "code\datums\elements\backblast.dm"
|
||||
#include "code\datums\elements\bane.dm"
|
||||
#include "code\datums\elements\basic_body_temp_sensitive.dm"
|
||||
|
||||
Reference in New Issue
Block a user