diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 8fec6c9c01..afb0e6c44a 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -108,7 +108,7 @@ W.afterattack(A, src, 1, params) // 1 indicates adjacency else if(ismob(A)) // No instant mob attacking - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) UnarmedAttack(A, 1) trigger_aiming(TARGET_CAN_CLICK) @@ -129,7 +129,7 @@ W.afterattack(A, src, 1, params) // 1: clicking something Adjacent else if(ismob(A)) // No instant mob attacking - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) UnarmedAttack(A, 1) trigger_aiming(TARGET_CAN_CLICK) return diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index b41dd9c57b..5b4f29a6a4 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -46,6 +46,22 @@ avoid code duplication. This includes items that may sometimes act as a standard return 0 return I.attack(src, user, user.zone_sel.selecting) +// Used to get how fast a mob should attack, and influences click delay. +// This is just for inheritence. +/mob/proc/get_attack_speed() + return DEFAULT_ATTACK_COOLDOWN + +// Same as above but actually does useful things. +// W is the item being used in the attack, if any. modifier is if the attack should be longer or shorter than usual, for whatever reason. +/mob/living/get_attack_speed(var/obj/item/W) + var/speed = DEFAULT_ATTACK_COOLDOWN + if(W && istype(W)) + speed = W.attackspeed + for(var/datum/modifier/M in modifiers) + if(!isnull(M.attack_speed_percent)) + speed *= M.attack_speed_percent + return speed + // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. /obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) @@ -68,7 +84,7 @@ avoid code duplication. This includes items that may sometimes act as a standard msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) ///////////////////////// - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) var/hit_zone = M.resolve_item_attack(src, user, target_zone) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 8cf8948bb7..a80ff05eac 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -59,7 +59,7 @@ if(!..()) return 0 - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) A.attack_generic(src,rand(5,6),"bitten") /* @@ -87,7 +87,7 @@ custom_emote(1,"[friendly] [A]!") return - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) if(isliving(A)) target_mob = A PunchTarget() @@ -96,7 +96,7 @@ A.attack_generic(src, rand(melee_damage_lower, melee_damage_upper), attacktext) /mob/living/simple_animal/RangedAttack(var/atom/A) - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) var/distance = get_dist(src, A) if(prob(spattack_prob) && (distance >= spattack_min_range) && (distance <= spattack_max_range)) diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index 436e7353ec..5f2561c25c 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -74,7 +74,7 @@ return 0 rig.selected_module.engage(A, alert_ai) if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns - setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + setClickCooldown(get_attack_speed()) return 1 return 0 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 05ef232595..d16084ae66 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -125,7 +125,7 @@ if(user.species.can_shred(user)) set_status(0) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) visible_message("\The [user] slashes at [src]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) add_hiddenprint(user) @@ -205,7 +205,7 @@ src.bugged = 1 else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if (W.force >= src.toughness) user.do_attack_animation(src) visible_message("[src] has been [W.attack_verb.len? pick(W.attack_verb) : "attacked"] with [W] by [user]!") diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 76eb2da2d5..2ed722e129 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -96,7 +96,7 @@ for reference: return return else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) if("fire") health -= W.force * 1 @@ -214,7 +214,7 @@ for reference: if(health <= 0) explode() return - + /obj/machinery/deployable/barrier/emp_act(severity) if(stat & (BROKEN|NOPOWER)) return diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index bf40ad9fff..870b080c79 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -132,7 +132,7 @@ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's a weapon, let's hit it. var/obj/item/weapon/W = C - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) @@ -162,7 +162,7 @@ else if(src.density && (user.a_intent == I_HURT)) //If we can't pry it open and it's not a weapon.... Eh, let's attack it anyway. var/obj/item/weapon/W = C - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) //No actual non-weapon item shouls have a force greater than the min_force, but let's include this just in case. diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 4c3823f11e..02437194bd 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -260,7 +260,7 @@ //psa to whoever coded this, there are plenty of objects that need to call attack() on doors without bludgeoning them. if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card)) var/obj/item/weapon/W = I - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 4fc02c70cc..d25473e709 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -161,7 +161,7 @@ playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[user] smashes against the [src.name].", 1) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) take_damage(25) return return src.attackby(user, user) @@ -246,7 +246,7 @@ //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) var/aforce = I.force playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[src] was hit by [I].") diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index fe0ebfdb2f..9e88c95594 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -381,7 +381,7 @@ var/list/turret_icons else //if the turret was attacked with the intention of harming it: - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) take_damage(I.force * 0.5) if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off if(!attacked && !emagged) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index db8fc51992..f71a40a011 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -505,7 +505,7 @@ return /obj/mecha/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) src.log_message("Attack by hand/paw. Attacker - [user].",1) if(istype(user,/mob/living/carbon/human)) @@ -513,7 +513,6 @@ if(H.species.can_shred(user)) if(!prob(src.deflect_chance)) src.take_damage(15) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) user << "You slash at the armored suit!" @@ -666,7 +665,7 @@ return /obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) src.log_message("Attacked by [W]. Attacker - [user]") if(prob(src.deflect_chance)) user << "\The [W] bounces off [src.name]." @@ -1763,7 +1762,7 @@ /obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(!damage) return 0 diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm index 3d9713cd29..2c864f0a56 100644 --- a/code/game/objects/effects/alien/aliens.dm +++ b/code/game/objects/effects/alien/aliens.dm @@ -120,7 +120,7 @@ /obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) var/aforce = W.force health = max(0, health - aforce) playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) @@ -227,7 +227,7 @@ Alien plants should do something if theres a lot of poison return /obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.attack_verb.len) visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") else diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 4cc39d4e67..a26c1169d5 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -21,7 +21,7 @@ return /obj/effect/spider/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.attack_verb.len) visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 8b00612641..ff7be9f549 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -80,6 +80,7 @@ var/list/sprite_sheets_obj = list() var/toolspeed = 1.0 // This is a multipler on how 'fast' a tool works. e.g. setting this to 0.5 will make the tool work twice as fast. + var/attackspeed = DEFAULT_ATTACK_COOLDOWN // How long click delay will be when using this, in 1/10ths of a second. Checked in the user's get_attack_speed(). var/addblends // Icon overlay for ADD highlights when applicable. /obj/item/New() @@ -457,7 +458,7 @@ 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.setClickCooldown(user.get_attack_speed()) user.do_attack_animation(M) src.add_fingerprint(user) diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 8eec816a50..2435e807f9 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -62,7 +62,7 @@ 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.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) if(!clown_check(user)) return @@ -75,9 +75,6 @@ if(!check_capacitor(user)) return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - user.do_attack_animation(M) - playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) var/flashfail = 0 @@ -147,7 +144,7 @@ /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) + user.setClickCooldown(user.get_attack_speed(src)) if(broken) user.show_message("The [src.name] is broken", 2) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 083f83c1c9..cfd3b398e3 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -163,7 +163,7 @@ else user << "\The [M]'s pupils narrow." - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively + user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively M.flash_eyes() else return ..() diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 63a0df6d32..7b156c025f 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -34,7 +34,7 @@ if(!S.get_damage()) user << "Nothing to fix here." else if(can_use(1)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(S.open >= 2) if(do_after(user,5 * toolspeed)) S.heal_damage(20, 20, robo_repair = 1) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 897ac43ff4..b1f623081d 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -81,7 +81,7 @@ msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]") feedback_add_details("handcuffs","H") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(H) user.visible_message("\The [user] has put [cuff_type] on \the [H]!") @@ -286,7 +286,7 @@ var/last_chew = 0 msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]") feedback_add_details("legcuffs","H") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(H) user.visible_message("\The [user] has put [cuff_type] on \the [H]!") diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 53aa3258e1..24d6ee4f59 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -217,7 +217,7 @@ var/obj/O = AM O.emp_act(3) // A weaker severity is used because this has infinite uses. playsound(get_turf(O), 'sound/effects/EMPulse.ogg', 100, 1) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) // A lot of objects don't set click delay. + user.setClickCooldown(user.get_attack_speed(src)) // A lot of objects don't set click delay. return ..() /obj/item/weapon/melee/energy/sword/ionic_rapier/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone) diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm index 41bcedbf21..c2ea991d98 100644 --- a/code/game/objects/items/weapons/trays.dm +++ b/code/game/objects/items/weapons/trays.dm @@ -17,7 +17,7 @@ var/max_carry = 10 /obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) // Drop all the things. All of them. overlays.Cut() for(var/obj/item/I in carrying) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index e8ce7430c9..c077668bbd 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -21,7 +21,7 @@ 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.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") @@ -134,7 +134,7 @@ qdel(src) /obj/effect/energy_net/user_unbuckle_mob(mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) visible_message("[user] begins to tear at \the [src]!") if(do_after(usr, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) if(!buckled_mob) diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 0bf155dc49..9bceee8f6e 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -81,7 +81,7 @@ health = maxhealth else take_damage(C.force) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(C)) return ..() /obj/structure/catwalk/Crossed() diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 2dcb1ddaad..d1516a9e66 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -55,7 +55,7 @@ /obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) src.health -= W.force diff --git a/code/game/objects/structures/fitness.dm b/code/game/objects/structures/fitness.dm index 3bb158a576..d29ad16f74 100644 --- a/code/game/objects/structures/fitness.dm +++ b/code/game/objects/structures/fitness.dm @@ -18,7 +18,7 @@ to_chat(user, "You need more energy to use the punching bag. Go eat something.") else if(user.a_intent == I_HURT) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) flick("[icon_state]_hit", src) playsound(src.loc, 'sound/effects/woodhit.ogg', 25, 1, -1) user.do_attack_animation(src) diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index d7960b5982..1b5322cfa7 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -36,7 +36,7 @@ to_chat(user, "\The [W] is ineffective at harming \the [src].") hit_animation() - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) // Shakes the tree slightly, more or less stolen from lockers. diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 2f0a032f21..aec6ce94c1 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -27,7 +27,7 @@ /obj/structure/grille/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) user.do_attack_animation(src) @@ -151,7 +151,7 @@ //window placing end else if(!(W.flags & CONDUCT) || !shock(user, 70)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) user.do_attack_animation(src) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) switch(W.damtype) diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index 7000e39974..1acafd5726 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -258,7 +258,7 @@ else playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) take_damage(W.force) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) 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 f6ee039977..02ea01556a 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -72,7 +72,7 @@ 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.setClickCooldown(user.get_attack_speed()) user.do_attack_animation(M) user.drop_from_inventory(src) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 0228b1d943..3bdbca1b54 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -18,7 +18,7 @@ /obj/structure/toilet/attack_hand(mob/living/user as mob) if(swirlie) - usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + usr.setClickCooldown(user.get_attack_speed()) usr.visible_message("[user] slams the toilet seat onto [swirlie.name]'s head!", "You slam the toilet seat onto [swirlie.name]'s head!", "You hear reverberating porcelain.") swirlie.adjustBruteLoss(5) return @@ -54,7 +54,7 @@ return if(istype(I, /obj/item/weapon/grab)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(I)) var/obj/item/weapon/grab/G = I if(isliving(G.affecting)) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 49f3bb8437..eaf9b47103 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -172,7 +172,7 @@ playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) /obj/structure/window/attack_hand(mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(HULK in user.mutations) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) user.visible_message("[user] smashes through [src]!") @@ -200,7 +200,7 @@ return /obj/structure/window/attack_generic(var/mob/user, var/damage) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) if(!damage) return if(damage >= 10) @@ -295,7 +295,7 @@ var/obj/item/frame/F = W F.try_build(src) else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) hit(W.force) diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index e227bb7467..01633b65d3 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -90,7 +90,7 @@ radiate() add_fingerprint(user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if (HULK in user.mutations) if (rotting || !prob(material.hardness)) @@ -104,7 +104,7 @@ /turf/simulated/wall/attack_generic(var/mob/user, var/damage, var/attack_message, var/wallbreaker) radiate() - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if(!damage || !wallbreaker) try_touch(user, rotting) @@ -122,7 +122,7 @@ /turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) if (!user.) user << "You don't have the dexterity to do this!" return diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0b02b98ef3..a5440483c7 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -209,7 +209,8 @@ var/list/admin_verbs_debug = list( /client/proc/show_gm_status, /datum/admins/proc/change_weather, /datum/admins/proc/change_time, - /client/proc/admin_give_modifier + /client/proc/admin_give_modifier, + /client/proc/simple_DPS ) var/list/admin_verbs_paranoid_debug = list( @@ -290,6 +291,7 @@ var/list/admin_verbs_hideable = list( /client/proc/kill_airgroup, /client/proc/debug_controller, /client/proc/startSinglo, + /client/proc/simple_DPS, /client/proc/cmd_debug_mob_lists, /client/proc/cmd_debug_using_map, /client/proc/cmd_debug_del_all, diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 981d5c7b7b..02c3fbc7b6 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -16,6 +16,56 @@ // callproc moved to code/modules/admin/callproc +/client/proc/simple_DPS() + set name = "Simple DPS" + set category = "Debug" + set desc = "Gives a really basic idea of how much hurt something in-hand does." + + var/obj/item/I = null + var/mob/living/user = null + if(isliving(usr)) + user = usr + I = user.get_active_hand() + if(!I || !istype(I)) + to_chat(user, "You need to have something in your active hand, to use this verb.") + return + var/weapon_attack_speed = user.get_attack_speed(I) / 10 + var/weapon_damage = I.force + + if(istype(I, /obj/item/weapon/gun)) + var/obj/item/weapon/gun/G = I + var/obj/item/projectile/P + + if(istype(I, /obj/item/weapon/gun/energy)) + var/obj/item/weapon/gun/energy/energy_gun = G + P = new energy_gun.projectile_type() + + else if(istype(I, /obj/item/weapon/gun/projectile)) + var/obj/item/weapon/gun/projectile/projectile_gun = G + var/obj/item/ammo_casing/ammo = projectile_gun.chambered + P = ammo.BB + + else + to_chat(user, "DPS calculation by this verb is not supported for \the [G]'s type. Energy or Ballistic only, sorry.") + + weapon_damage = P.damage + weapon_attack_speed = G.fire_delay / 10 + qdel(P) + + var/DPS = weapon_damage / weapon_attack_speed + to_chat(user, "Damage: [weapon_damage]") + to_chat(user, "Attack Speed: [weapon_attack_speed]/s") + to_chat(user, "\The [I] does [DPS] damage per second.") + if(DPS > 0) + to_chat(user, "At your maximum health ([user.getMaxHealth()]), it would take approximately;") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_softcrit) / DPS] seconds to softcrit you. ([config.health_threshold_softcrit] health)") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_crit) / DPS] seconds to hardcrit you. ([config.health_threshold_crit] health)") + to_chat(user, "[(user.getMaxHealth() - config.health_threshold_dead) / DPS] seconds to kill you. ([config.health_threshold_dead] health)") + + else + to_chat(user, "You need to be a living mob, with hands, and for an object to be in your active hand, to use this verb.") + return + /client/proc/Cell() set category = "Debug" set name = "Cell" diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index b66abd61da..f08f28d97a 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -238,7 +238,7 @@ /obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) plant_controller.add_plant(src) if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/surgical/scalpel)) diff --git a/code/modules/hydroponics/spreading/spreading_response.dm b/code/modules/hydroponics/spreading/spreading_response.dm index 80d72055eb..12747666c4 100644 --- a/code/modules/hydroponics/spreading/spreading_response.dm +++ b/code/modules/hydroponics/spreading/spreading_response.dm @@ -61,7 +61,7 @@ "You hear shredding and ripping.") unbuckle() else - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) health -= rand(1,5) var/text = pick("rip","tear","pull", "bite", "tug") user.visible_message(\ diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 4eee4ee91b..4a924fdca3 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -568,7 +568,7 @@ return else if(O.force && seed) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(O)) user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!") if(!dead) health -= O.force diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 3facabe6f9..7164396f29 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -42,6 +42,7 @@ var/accuracy_dispersion // Positive numbers make gun firing cover a wider tile range, and therefore more inaccurate. Negatives help negate dispersion penalties. var/metabolism_percent // Adjusts the mob's metabolic rate, which affects reagent processing. Won't affect mobs without reagent processing. var/icon_scale_percent // Makes the holder's icon get scaled up or down. + var/attack_speed_percent // Makes the holder's 'attack speed' (click delay) shorter or longer. /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder @@ -206,6 +207,9 @@ if(!isnull(icon_scale_percent)) effects += "Your appearance is [multipler_to_percentage(icon_scale_percent, TRUE)] [icon_scale_percent > 1 ? "larger" : "smaller"]." + if(!isnull(attack_speed_percent)) + effects += "The delay between attacking is [multipler_to_percentage(attack_speed_percent, TRUE)] [disable_duration_percent > 1.0 ? "longer" : "shorter"]." + return jointext(effects, "
") diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 6c3cd7f1db..6b07aa8b0c 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -486,7 +486,7 @@ return var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(WT)) adjustBruteLoss(-30) updatehealth() add_fingerprint(user) @@ -502,7 +502,7 @@ return var/obj/item/stack/cable_coil/coil = W if (coil.use(1)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) adjustFireLoss(-30) updatehealth() for(var/mob/O in viewers(user, null)) diff --git a/code/modules/mob/living/simple_animal/slime/combat.dm b/code/modules/mob/living/simple_animal/slime/combat.dm index 0068ee728c..8554a27e5f 100644 --- a/code/modules/mob/living/simple_animal/slime/combat.dm +++ b/code/modules/mob/living/simple_animal/slime/combat.dm @@ -213,7 +213,7 @@ // Otherwise they're probably fighting the slime. if(prob(25)) visible_message("\The [user]'s [W] passes right through [src]!") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) return ..() diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 1508aff08a..b6ad2fff2c 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -411,7 +411,7 @@ user << "You can't reach your [src.name] while holding [tool] in your [owner.get_bodypart_name(grasp)]." return 0 - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(tool)) if(!do_mob(user, owner, 10)) user << "You must stand still to do that." return 0 diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 39ce99d188..0c5f8ebaac 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -699,7 +699,7 @@ var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) user.visible_message("[user.name] slashes at the [src.name]!", "You slash at the [src.name]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 216332cbdd..8cdcf67178 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -527,7 +527,7 @@ if(istype(user,/mob/living/carbon/human)) var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed()) for(var/mob/M in viewers(src)) M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) broken() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 6721cbd3bb..fc89bab93d 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -101,7 +101,7 @@ user << "\The [blocked] is in the way!" return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things + user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things self_feed_message(user) reagents.trans_to_mob(user, issmall(user) ? ceil(amount_per_transfer_from_this/2) : amount_per_transfer_from_this, CHEM_INGEST) feed_sound(user) @@ -119,7 +119,7 @@ other_feed_message_start(user, target) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, target)) return diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index c49c76be01..100aa43165 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -68,7 +68,7 @@ user << "\The [blocked] is in the way!" return - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //puts a limit on how fast people can eat/drink things + user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things if (fullness <= 50) M << "You hungrily chew out a piece of [src] and gobble it!" if (fullness > 50 && fullness <= 150) @@ -101,7 +101,7 @@ user.visible_message("[user] cannot force anymore of [src] down [M]'s throat.") return 0 - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index e21baa48e2..bc83d8c9cf 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -51,7 +51,7 @@ user.visible_message("[user] attempts to force [M] to swallow \the [src].") - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return diff --git a/code/modules/shieldgen/energy_field.dm b/code/modules/shieldgen/energy_field.dm index 5dc6af651d..e558a2621e 100644 --- a/code/modules/shieldgen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -49,7 +49,7 @@ if(W.force) adjust_strength(-W.force / 20) user.do_attack_animation(src) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) ..() /obj/effect/energy_field/attack_hand(var/mob/living/user) diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index eb70ca64ce..f725508c88 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -94,7 +94,7 @@ if(health < maxhealth) if(open) health = min(maxhealth, health+10) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) playsound(src, T.usesound, 50, 1) user.visible_message("[user] repairs [src]!"," You repair [src]!") else @@ -104,7 +104,7 @@ else user << "Unable to repair while [src] is off." else if(hasvar(W,"force") && hasvar(W,"damtype")) - user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) if("fire") health -= W.force * fire_dam_coeff diff --git a/code/modules/xenobio/items/extracts.dm b/code/modules/xenobio/items/extracts.dm index 87542b70f0..8d7d338bad 100644 --- a/code/modules/xenobio/items/extracts.dm +++ b/code/modules/xenobio/items/extracts.dm @@ -899,6 +899,7 @@ evasion = 2 slowdown = -1 + attack_speed_percent = 0.75 // *********************