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.
This commit is contained in:
Neerti
2017-11-28 16:11:56 -05:00
parent 034d5391d7
commit 2f7db506eb
48 changed files with 142 additions and 72 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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))

View File

@@ -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

View File

@@ -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("<span class='warning'>\The [user] slashes at [src]!</span>")
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("<span class='warning'><b>[src] has been [W.attack_verb.len? pick(W.attack_verb) : "attacked"] with [W] by [user]!</b></span>")

View File

@@ -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

View File

@@ -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.

View File

@@ -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)

View File

@@ -161,7 +161,7 @@
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("<span class='danger'>[user] smashes against the [src.name].</span>", 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("<span class='danger'>[src] was hit by [I].</span>")

View File

@@ -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)

View File

@@ -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 << "<span class='danger'>You slash at the armored suit!</span>"
@@ -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 << "<span class='danger'>\The [W] bounces off [src.name].</span>"
@@ -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

View File

@@ -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("<span class='danger'>\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
else

View File

@@ -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("<span class='warning'>\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")

View File

@@ -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()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])</font>"
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)") //BS12 EDIT ALG
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
user.do_attack_animation(M)
src.add_fingerprint(user)

View File

@@ -62,7 +62,7 @@
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to flash [M.name] ([M.ckey])</font>")
msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
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("<span class='warning'>The [src.name] is broken</span>", 2)

View File

@@ -163,7 +163,7 @@
else
user << "<span class='notice'>\The [M]'s pupils narrow.</span>"
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 ..()

View File

@@ -34,7 +34,7 @@
if(!S.get_damage())
user << "<span class='notice'>Nothing to fix here.</span>"
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)

View File

@@ -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("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
@@ -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("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")

View File

@@ -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)

View File

@@ -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)

View File

@@ -21,7 +21,7 @@
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
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("<span class='danger'>[user] begins to tear at \the [src]!</span>")
if(do_after(usr, escape_time, src, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY)))
if(!buckled_mob)

View File

@@ -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()

View File

@@ -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

View File

@@ -18,7 +18,7 @@
to_chat(user, "<span class='warning'>You need more energy to use the punching bag. Go eat something.</span>")
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)

View File

@@ -36,7 +36,7 @@
to_chat(user, "<span class='warning'>\The [W] is ineffective at harming \the [src].</span>")
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.

View File

@@ -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)

View File

@@ -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 ..()

View File

@@ -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("<span class='danger'>[user] breaks [src] over [M]'s back!</span>")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed())
user.do_attack_animation(M)
user.drop_from_inventory(src)

View File

@@ -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("<span class='danger'>[user] slams the toilet seat onto [swirlie.name]'s head!</span>", "<span class='notice'>You slam the toilet seat onto [swirlie.name]'s head!</span>", "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))

View File

@@ -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("<span class='danger'>[user] smashes through [src]!</span>")
@@ -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)

View File

@@ -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 << "<span class='warning'>You don't have the dexterity to do this!</span>"
return

View File

@@ -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,

View File

@@ -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, "<span class='warning'>You need to have something in your active hand, to use this verb.</span>")
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, "<span class='warning'>DPS calculation by this verb is not supported for \the [G]'s type. Energy or Ballistic only, sorry.</span>")
weapon_damage = P.damage
weapon_attack_speed = G.fire_delay / 10
qdel(P)
var/DPS = weapon_damage / weapon_attack_speed
to_chat(user, "<span class='notice'>Damage: [weapon_damage]</span>")
to_chat(user, "<span class='notice'>Attack Speed: [weapon_attack_speed]/s</span>")
to_chat(user, "<span class='notice'>\The [I] does <b>[DPS]</b> damage per second.</span>")
if(DPS > 0)
to_chat(user, "<span class='notice'>At your maximum health ([user.getMaxHealth()]), it would take approximately;</span>")
to_chat(user, "<span class='notice'>[(user.getMaxHealth() - config.health_threshold_softcrit) / DPS] seconds to softcrit you. ([config.health_threshold_softcrit] health)</span>")
to_chat(user, "<span class='notice'>[(user.getMaxHealth() - config.health_threshold_crit) / DPS] seconds to hardcrit you. ([config.health_threshold_crit] health)</span>")
to_chat(user, "<span class='notice'>[(user.getMaxHealth() - config.health_threshold_dead) / DPS] seconds to kill you. ([config.health_threshold_dead] health)</span>")
else
to_chat(user, "<span class='warning'>You need to be a living mob, with hands, and for an object to be in your active hand, to use this verb.</span>")
return
/client/proc/Cell()
set category = "Debug"
set name = "Cell"

View File

@@ -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))

View File

@@ -61,7 +61,7 @@
"<span class='warning'>You hear shredding and ripping.</span>")
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(\

View File

@@ -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("<span class='danger'>\The [seed.display_name] has been attacked by [user] with \the [O]!</span>")
if(!dead)
health -= O.force

View File

@@ -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, "<br>")

View File

@@ -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))

View File

@@ -213,7 +213,7 @@
// Otherwise they're probably fighting the slime.
if(prob(25))
visible_message("<span class='danger'>\The [user]'s [W] passes right through [src]!</span>")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(W))
return
..()

View File

@@ -411,7 +411,7 @@
user << "<span class='warning'>You can't reach your [src.name] while holding [tool] in your [owner.get_bodypart_name(grasp)].</span>"
return 0
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(tool))
if(!do_mob(user, owner, 10))
user << "<span class='warning'>You must stand still to do that.</span>"
return 0

View File

@@ -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("<span call='warning'>[user.name] slashes at the [src.name]!</span>", "<span class='notice'>You slash at the [src.name]!</span>")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)

View File

@@ -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("<font color='red'>[user.name] smashed the light!</font>", 3, "You hear a tinkle of breaking glass", 2)
broken()

View File

@@ -101,7 +101,7 @@
user << "<span class='warning'>\The [blocked] is in the way!</span>"
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

View File

@@ -68,7 +68,7 @@
user << "<span class='warning'>\The [blocked] is in the way!</span>"
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 << "<span class='danger'>You hungrily chew out a piece of [src] and gobble it!</span>"
if (fullness > 50 && fullness <= 150)
@@ -101,7 +101,7 @@
user.visible_message("<span class='danger'>[user] cannot force anymore of [src] down [M]'s throat.</span>")
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()]\] <font color='orange'>Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]</font>")

View File

@@ -51,7 +51,7 @@
user.visible_message("<span class='warning'>[user] attempts to force [M] to swallow \the [src].</span>")
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.setClickCooldown(user.get_attack_speed(src))
if(!do_mob(user, M))
return

View File

@@ -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)

View File

@@ -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("<font color='red'>[user] repairs [src]!</font>","<font color='blue'> You repair [src]!</font>")
else
@@ -104,7 +104,7 @@
else
user << "<span class='notice'>Unable to repair while [src] is off.</span>"
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

View File

@@ -899,6 +899,7 @@
evasion = 2
slowdown = -1
attack_speed_percent = 0.75
// *********************