-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathpinnable_accessory.dm
80 lines (68 loc) · 3.11 KB
/
pinnable_accessory.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/// This accessory can be pinned onto someone else
/datum/component/pinnable_accessory
/// Do we let people know what we're doing?
var/silent
/// How long does it take to pin this onto someone?
var/pinning_time
/// Optional callback invoked before pinning, will cancel if it returns FALSE
var/datum/callback/on_pre_pin
/datum/component/pinnable_accessory/Initialize(silent = FALSE, pinning_time = 2 SECONDS, datum/callback/on_pre_pin = null)
. = ..()
if (!istype(parent, /obj/item/clothing/accessory))
return COMPONENT_INCOMPATIBLE
src.silent = silent
src.pinning_time = pinning_time
src.on_pre_pin = on_pre_pin
/datum/component/pinnable_accessory/RegisterWithParent()
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_atom_interact))
/datum/component/pinnable_accessory/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
/// Called when you whack someone with this accessory
/datum/component/pinnable_accessory/proc/on_atom_interact(obj/item/clothing/accessory/badge, mob/target, mob/user, proximity_flag, click_parameters)
SIGNAL_HANDLER
if (!ishuman(target) || target == user)
return
INVOKE_ASYNC(src, PROC_REF(try_to_pin), badge, target, user)
return COMPONENT_CANCEL_ATTACK_CHAIN
/// Actually try to pin it on
/datum/component/pinnable_accessory/proc/try_to_pin(obj/item/clothing/accessory/badge, mob/living/carbon/human/distinguished, mob/user)
var/obj/item/clothing/under/distinguished_uniform = distinguished.w_uniform
if(!istype(distinguished_uniform))
distinguished.balloon_alert(user, "no uniform to pin on!")
return
if(!badge.can_attach_accessory(distinguished_uniform, user))
// Check handles feedback messages and etc
return
if (!silent)
user.visible_message(
span_notice("[user] tries to pin [badge] on [distinguished]'s chest."),
span_notice("You try to pin [badge] on [distinguished]'s chest."),
)
if (on_pre_pin && !on_pre_pin.Invoke(distinguished, user))
return
if(!pin_checks(user, distinguished) || !do_after(user, pinning_time, distinguished, extra_checks = CALLBACK(src, PROC_REF(pin_checks), user, distinguished)))
return
var/pinned = distinguished_uniform.attach_accessory(badge, user)
if (silent)
return
if (pinned)
user.visible_message(
span_notice("[user] pins [badge] on [distinguished]'s chest."),
span_notice("You pin [badge] on [distinguished]'s chest."),
)
else
user.visible_message(
span_warning("[user] fails to pin [badge] on [distinguished]'s chest, seemingly unable to part with it."),
span_warning("You fail to pin [badge] on [distinguished]'s chest."),
)
/// Callback for do_after to check if we can still be pinned
/datum/component/pinnable_accessory/proc/pin_checks(mob/living/pinner, mob/living/carbon/human/pinning_on)
if(QDELETED(parent) || QDELETED(pinner) || QDELETED(pinning_on))
return FALSE
if(!pinner.is_holding(parent) || !pinner.Adjacent(pinning_on))
return FALSE
var/obj/item/clothing/accessory/badge = parent
var/obj/item/clothing/under/pinning_on_uniform = pinning_on.w_uniform
if(!istype(pinning_on_uniform) || !badge.can_attach_accessory(pinning_on_uniform, pinner))
return FALSE
return TRUE