diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 98ad3b28ca..0d1a04d4e2 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -180,4 +180,4 @@
#define MOB_PULL_NONE 0
#define MOB_PULL_SMALLER 1
#define MOB_PULL_SAME 2
-#define MOB_PULL_LARGER 3
\ No newline at end of file
+#define MOB_PULL_LARGER 3
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 1c74362c2e..3c65b03f73 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -10,7 +10,7 @@ item/resolve_attackby() calls the target atom's attackby() proc.
Mobs:
mob/living/attackby() after checking for surgery, calls the item's attack() proc.
-item/attack() generates attack logs and calls the mob's attacked_with_item() proc.
+item/attack() generates attack logs, sets click cooldown and calls the mob's attacked_with_item() proc. If you override this, consider whether you need to set a click cooldown, play attack animations, and generate logs yourself.
mob/attacked_with_item() should then do mob-type specific stuff (like determining hit/miss, handling shields, etc) and then possibly call the item's apply_hit_effect() proc to actually apply the effects of being hit.
Item Hit Effects:
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 4bef5534f3..7a7ecbcf4e 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -20,16 +20,20 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/affecting = H.get_organ(zone)
- user << "An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!"
+ user << "An unexplicable force rips through your [affecting.name], tearing the sword from your grasp!"
else
- user << "An unexplicable force rips through you, tearing the sword from your grasp!"
+ user << "An unexplicable force rips through you, tearing the sword from your grasp!"
//random amount of damage between half of the blade's force and the full force of the blade.
- user.apply_damage(rand(force/2, force), BRUTE, zone, 0)
+ user.apply_damage(rand(force/2, force), BRUTE, zone, 0, sharp=1, edge=1)
user.Weaken(5)
user.drop_from_inventory(src)
throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed)
+
+ var/spooky = pick('sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg', 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/wail.ogg')
+ playsound(loc, spooky, 50, 1)
+
return 1
/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9b40cf4e8c..4d04c7b3aa 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -453,6 +453,9 @@ var/list/global/slot_flags_enumeration = list(
M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(M)
+
src.add_fingerprint(user)
//if((CLUMSY in user.mutations) && prob(50))
// M = user
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 5859096546..7a8740c287 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -39,6 +39,9 @@
user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])")
msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)")
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(M)
+
if(!clown_check(user)) return
if(broken)
user << "\The [src] is broken."
@@ -112,6 +115,9 @@
/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
if(!user || !clown_check(user)) return
+
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+
if(broken)
user.show_message("The [src.name] is broken", 2)
return
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index c7f90e9746..f0c70dde9a 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -79,6 +79,8 @@
user << "\The [M]'s pupils narrow slightly, but are still very dilated."
else
user << "\The [M]'s pupils narrow."
+
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively
flick("flash", M.flash)
else
return ..()
diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm
index b78c305f9a..2b7307f6ff 100644
--- a/code/game/objects/items/weapons/clown_items.dm
+++ b/code/game/objects/items/weapons/clown_items.dm
@@ -53,6 +53,7 @@
/obj/item/weapon/soap/attack(mob/living/target, mob/living/user, var/target_zone)
if(target && user && ishuman(target) && ishuman(user) && !user.incapacitated() && user.zone_sel &&user.zone_sel.selecting == "mouth" )
user.visible_message("\The [user] washes \the [target]'s mouth out with soap!")
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //prevent spam
return
..()
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 5e2cb1946d..2c1292fad8 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -114,6 +114,9 @@
if(!do_after(user,50))
return
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
+ user.do_attack_animation(M)
+
M.visible_message("\The [M] has been injected with \the [src] by \the [user].")
var/mob/living/carbon/human/H = M
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 8e3fed202d..6f5e2d3d53 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -46,6 +46,7 @@
if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/) || istype(target, /obj/item/clothing/accessory/storage/) || istype(target, /obj/item/clothing/under))
return
user << "Planting explosives..."
+ user.do_attack_animation(target)
if(do_after(user, 50) && in_range(user, target))
user.drop_item()
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 4b43cc2601..ce2384ccb3 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -74,6 +74,9 @@
msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]")
feedback_add_details("handcuffs","H")
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(H)
+
user.visible_message("\The [user] has put [cuff_type] on \the [H]!")
// Apply cuffs.
@@ -166,4 +169,4 @@ var/last_chew = 0
item_state = null
icon = 'icons/obj/bureaucracy.dmi'
breakouttime = 200
- cuff_type = "duct tape"
\ No newline at end of file
+ cuff_type = "duct tape"
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 8011d25859..da7f1b1401 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -30,18 +30,18 @@
if (!istype(M, /mob/living/carbon))
return
if (user && src.imp)
- for (var/mob/O in viewers(M, null))
- O.show_message("[user] is attemping to implant [M].", 1)
+ M.visible_message("[user] is attemping to implant [M].")
+
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
+ user.do_attack_animation(M)
var/turf/T1 = get_turf(M)
if (T1 && ((M == user) || do_after(user, 50)))
if(user && M && (get_turf(M) == T1) && src && src.imp)
- for (var/mob/O in viewers(M, null))
- O.show_message("[M] has been implanted by [user].", 1)
+ M.visible_message("[M] has been implanted by [user].")
admin_attack_log(user, M, "Implanted using \the [src.name] ([src.imp.name])", "Implanted with \the [src.name] ([src.imp.name])", "used an implanter, [src.name] ([src.imp.name]), on")
- user.show_message("You implanted the implant into [M].")
if(src.imp.implanted(M))
src.imp.loc = M
src.imp.imp_in = M
diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm
index b5c966ebd5..d4f4518780 100644
--- a/code/game/objects/items/weapons/material/kitchen.dm
+++ b/code/game/objects/items/weapons/material/kitchen.dm
@@ -101,13 +101,6 @@
return
return ..()
-/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
- if ((CLUMSY in user.mutations) && prob(50))
- user << "You somehow managed to cut yourself with \the [src]."
- user.take_organ_damage(20)
- return
- return ..()
-
/obj/item/weapon/material/kitchen/utensil/knife/plastic
default_material = "plastic"
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index 94c55de5b0..b289e79257 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -26,33 +26,7 @@
else
user.take_organ_damage(2*force)
return
-/*this is already called in ..()
- src.add_fingerprint(user)
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
-
- log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])")
-*/
- if (user.a_intent == I_HURT)
- if(!..()) return
- //playsound(src.loc, "swing_hit", 50, 1, -1)
- if (M.stuttering < 8 && (!(HULK in M.mutations)) /*&& (!istype(H:wear_suit, /obj/item/clothing/suit/judgerobe))*/)
- M.stuttering = 8
- M.Stun(8)
- M.Weaken(8)
- for(var/mob/O in viewers(M))
- if (O.client) O.show_message("\The [M] has been beaten with \the [src] by [user]!", 1, "You hear someone fall", 2)
- else
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1, -1)
- M.Stun(5)
- M.Weaken(5)
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
- msg_admin_attack("[key_name(user)] attacked [key_name(user)] with [src.name] (INTENT: [uppertext(user.a_intent)])")
- src.add_fingerprint(user)
-
- for(var/mob/O in viewers(M))
- if (O.client) O.show_message("\The [M] has been stunned with \the [src] by [user]!", 1, "You hear someone fall", 2)
+ return ..()
//Telescopic baton
/obj/item/weapon/melee/telebaton
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index fe1e62caa0..83d3296981 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -115,7 +115,7 @@
item_state = "cutters_yellow"
/obj/item/weapon/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob)
- if((C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable)))
+ if(user.a_intent == I_HELP && (C.handcuffed) && (istype(C.handcuffed, /obj/item/weapon/handcuffs/cable)))
usr.visible_message("\The [usr] cuts \the [C]'s restraints with \the [src]!",\
"You cut \the [C]'s restraints with \the [src]!",\
"You hear cable being cut.")
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index fa698f97ed..0f5cebc44d 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -22,6 +22,9 @@
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(M)
+
if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
user << "You don't have the dexterity to do this!"
return
diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
index a579ceab8e..8fed533bb6 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
@@ -72,6 +72,9 @@ var/global/list/stool_cache = list() //haha stool
/obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob)
if (prob(5) && istype(M,/mob/living))
user.visible_message("[user] breaks [src] over [M]'s back!")
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ user.do_attack_animation(M)
+
user.removeItem(src)
dismantle()
qdel(src)
diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm
index b78b0ffac3..2908a7b639 100644
--- a/code/modules/clothing/under/accessories/badges.dm
+++ b/code/modules/clothing/under/accessories/badges.dm
@@ -38,6 +38,8 @@
/obj/item/clothing/accessory/badge/attack(mob/living/carbon/human/M, mob/living/user)
if(isliving(user))
user.visible_message("[user] invades [M]'s personal space, thrusting [src] into their face insistently.","You invade [M]'s personal space, thrusting [src] into their face insistently.")
+ user.do_attack_animation(M)
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam
//.Holobadges.
/obj/item/clothing/accessory/badge/holo
@@ -127,4 +129,4 @@
new /obj/item/clothing/accessory/badge/holo/hos(src)
new /obj/item/clothing/accessory/badge/holo/cord(src)
..()
- return
\ No newline at end of file
+ return
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index 3dbb74d933..ba96ada8b7 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -256,6 +256,7 @@
user.visible_message("You open up the book and show it to [M]. ", \
" [user] opens up a book and shows it to [M]. ")
M << browse("Penned by [author].
" + "[dat]", "window=book")
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam
/*
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index de6c67446e..bc28b4577b 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -214,7 +214,7 @@
admin_attack_log(usr, attacker_message="Fired [src]", admin_message="fired a gun ([src]) (MODE: [src.mode_name]) [reflex ? "by reflex" : "manually"].")
//update timing
- user.setClickCooldown(4)
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
user.setMoveCooldown(move_delay)
next_fire_time = world.time + fire_delay
@@ -419,4 +419,4 @@
return new_mode
/obj/item/weapon/gun/attack_self(mob/user)
- switch_firemodes(user)
\ No newline at end of file
+ switch_firemodes(user)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index 7632f8456f..28b4704fdd 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -37,6 +37,8 @@
user << "You cannot inject a robotic limb."
return
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
+ user.do_attack_animation(M)
user << "You inject [M] with [src]."
M << "You feel a tiny prick!"
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 9b4b697f9c..c35928d22d 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -176,6 +176,9 @@
else
user.visible_message("[user] begins hunting for an injection port on [target]'s suit!")
+ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
+ user.do_attack_animation(target)
+
if(!do_mob(user, target, injtime))
return