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 8fec6c9c010..afb0e6c44aa 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 b41dd9c57b6..5b4f29a6a44 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 8cf8948bb7e..a80ff05eac1 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 436e7353ec7..5f2561c25c7 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 05ef232595d..d16084ae661 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 76eb2da2d5a..2ed722e1296 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 bf40ad9fff4..870b080c79f 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 4c3823f11e8..02437194bd0 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 4fc02c70cce..d25473e709f 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 fe0ebfdb2f9..9e88c955941 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 db8fc519925..f71a40a011c 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 3d9713cd29a..2c864f0a56c 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 4cc39d4e676..a26c1169d5f 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 8b00612641c..ff7be9f549f 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 8eec816a50c..2435e807f99 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 083f83c1c95..cfd3b398e3f 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 63a0df6d326..7b156c025ff 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 897ac43ff4f..b1f623081de 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 53aa3258e1c..24d6ee4f597 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 41bcedbf217..c2ea991d98d 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 e8ce7430c9f..c077668bbd2 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 0bf155dc49d..9bceee8f6e3 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 2dcb1ddaad8..d1516a9e66c 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 3bb158a576b..d29ad16f740 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 d7960b59825..1b5322cfa7e 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 2f0a032f21d..aec6ce94c19 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 7000e399741..1acafd5726b 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 f6ee039977b..02ea01556a9 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 0228b1d9430..3bdbca1b549 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 49f3bb84370..eaf9b471037 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 e227bb74670..01633b65d34 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 0b02b98ef32..a5440483c76 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 981d5c7b7b6..02c3fbc7b6b 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 b66abd61daa..f08f28d97a0 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 80d72055eba..12747666c49 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 4eee4ee91ba..4a924fdca3a 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 3facabe6f97..7164396f297 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 6c3cd7f1dbd..6b07aa8b0c8 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 0068ee728c9..8554a27e5f7 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 1508aff08a9..b6ad2fff2c7 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 39ce99d1881..0c5f8ebaac4 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 216332cbdd3..8cdcf671787 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 6721cbd3bbc..fc89bab93da 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 c49c76be01c..100aa43165d 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 e21baa48e26..bc83d8c9cfb 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 5dc6af651d3..e558a2621e2 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 eb70ca64ce5..f725508c883 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 87542b70f0d..8d7d338bad2 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 // *********************