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:
itseasytosee
2022-10-08 18:51:29 -07:00
committed by GitHub
co-authored by Mothblocks
parent cc1d242273
commit e0b706c36c
8 changed files with 129 additions and 33 deletions
@@ -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"
+58
View File
@@ -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)
+1 -30
View File
@@ -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.
+60
View File
@@ -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
+1
View File
@@ -28,6 +28,7 @@
/obj/item/storage/belt/Initialize(mapload)
. = ..()
AddElement(/datum/element/attack_equip)
update_appearance()
/obj/item/storage/belt/utility
+4 -3
View File
@@ -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))
+1
View File
@@ -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"