From 2f7db506ebc9c5336569d910588f2cf6109b8f7c Mon Sep 17 00:00:00 2001 From: Neerti Date: Tue, 28 Nov 2017 16:11:56 -0500 Subject: [PATCH] Adds Variable Click Delay Now certain weapons can strike faster or slower than usual. No weapons currently do this as this PR just lays the groundwork for that. The click delay can also be modified with traits. The slime agility modifier makes attacks happen 25% sooner. Adds debug test verb to display a weapon's DPS. It's really basic but should be sufficient for future force adjustments I might do in the future. --- code/_onclick/click.dm | 4 +- code/_onclick/item_attack.dm | 18 ++++++- code/_onclick/other_mobs.dm | 6 +-- code/_onclick/rig.dm | 2 +- code/game/machinery/camera/camera.dm | 4 +- code/game/machinery/deployable.dm | 4 +- code/game/machinery/doors/blast_door.dm | 4 +- code/game/machinery/doors/door.dm | 2 +- code/game/machinery/doors/windowdoor.dm | 4 +- code/game/machinery/portable_turret.dm | 2 +- code/game/mecha/mecha.dm | 7 ++- code/game/objects/effects/alien/aliens.dm | 4 +- code/game/objects/effects/spiders.dm | 2 +- code/game/objects/items.dm | 3 +- code/game/objects/items/devices/flash.dm | 7 +-- code/game/objects/items/devices/flashlight.dm | 2 +- code/game/objects/items/stacks/nanopaste.dm | 2 +- code/game/objects/items/weapons/handcuffs.dm | 4 +- .../objects/items/weapons/melee/energy.dm | 2 +- code/game/objects/items/weapons/trays.dm | 2 +- code/game/objects/items/weapons/weaponry.dm | 4 +- code/game/objects/structures/catwalk.dm | 2 +- code/game/objects/structures/displaycase.dm | 2 +- code/game/objects/structures/fitness.dm | 2 +- code/game/objects/structures/flora/trees.dm | 2 +- code/game/objects/structures/grille.dm | 4 +- code/game/objects/structures/railing.dm | 2 +- .../structures/stool_bed_chair_nest/stools.dm | 2 +- code/game/objects/structures/watercloset.dm | 4 +- code/game/objects/structures/window.dm | 6 +-- code/game/turfs/simulated/wall_attacks.dm | 6 +-- code/modules/admin/admin_verbs.dm | 4 +- code/modules/admin/verbs/debug.dm | 50 +++++++++++++++++++ .../hydroponics/spreading/spreading.dm | 2 +- .../spreading/spreading_response.dm | 2 +- code/modules/hydroponics/trays/tray.dm | 2 +- code/modules/mob/_modifiers/modifiers.dm | 4 ++ .../modules/mob/living/silicon/robot/robot.dm | 4 +- .../mob/living/simple_animal/slime/combat.dm | 2 +- code/modules/organs/organ_external.dm | 2 +- code/modules/power/apc.dm | 2 +- code/modules/power/lighting.dm | 2 +- code/modules/reagents/reagent_containers.dm | 4 +- .../reagent_containers/food/snacks.dm | 4 +- .../reagents/reagent_containers/pill.dm | 2 +- code/modules/shieldgen/energy_field.dm | 2 +- code/modules/vehicles/vehicle.dm | 4 +- code/modules/xenobio/items/extracts.dm | 1 + 48 files changed, 142 insertions(+), 72 deletions(-) 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 // *********************