summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/player-act.cc
diff options
context:
space:
mode:
authorSteve Melenchuk <smelenchuk@gmail.com>2014-04-16 21:08:32 -0600
committerSteve Melenchuk <smelenchuk@gmail.com>2014-04-27 17:02:33 -0600
commitfde016144d74dc363d43e65ef647e980391aeadc (patch)
tree49d3673f03e94bc9c7cd3d9e52233b11288cb366 /crawl-ref/source/player-act.cc
parentec5b00754ba4caf6cd637a454de3f9989dd7ea0f (diff)
downloadcrawl-ref-fde016144d74dc363d43e65ef647e980391aeadc.tar.gz
crawl-ref-fde016144d74dc363d43e65ef647e980391aeadc.zip
Ranged weapon delay.
Moves the delay calculations into player and monster respectively so that it can properly be done at the start of the ranged attack; it doesn't make sense to have them in attack or ranged_attack.
Diffstat (limited to 'crawl-ref/source/player-act.cc')
-rw-r--r--crawl-ref/source/player-act.cc94
1 files changed, 94 insertions, 0 deletions
diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc
index 289f8f26ad..f0b83f9443 100644
--- a/crawl-ref/source/player-act.cc
+++ b/crawl-ref/source/player-act.cc
@@ -15,6 +15,7 @@
#include "coordit.h"
#include "dgnevent.h"
#include "env.h"
+#include "fight.h"
#include "food.h"
#include "goditem.h"
#include "hints.h"
@@ -270,6 +271,99 @@ brand_type player::damage_brand(int)
return ret;
}
+random_var player::attack_delay(item_def *weap, item_def *projectile,
+ bool random, bool scaled) const
+{
+ random_var attk_delay = constant(15);
+ const int armour_penalty = adjusted_body_armour_penalty(20);
+ const int base_shield_penalty = adjusted_shield_penalty(20);
+
+ bool check_weapon = (!projectile && !!weap)
+ || projectile
+ && (is_launched(this, weap, *projectile)
+ != LRET_THROWN);
+
+ if (!check_weapon)
+ {
+ if (form_uses_xl())
+ {
+ attk_delay =
+ constant(10)
+ - div_rand_round(constant(you.experience_level * 10), 54);
+ }
+ else
+ {
+ attk_delay =
+ rv::max(constant(10),
+ (rv::roll_dice(1, 10) +
+ div_rand_round(
+ rv::roll_dice(2, armour_penalty),
+ 20)));
+
+ // Unarmed speed. Min delay is 10 - 270/54 = 5.
+ if (you.burden_state == BS_UNENCUMBERED)
+ {
+ skill_type sk = projectile ? SK_THROWING : SK_UNARMED_COMBAT;
+ attk_delay -= div_rand_round(constant(you.skill(sk, 10)), 54);
+ }
+
+ // Bats are faster (for what good it does them).
+ if (you.form == TRAN_BAT && !projectile)
+ attk_delay = div_rand_round(attk_delay * constant(3), 5);
+ }
+ }
+ else
+ {
+ if (weap && is_weapon(*weap)
+ && (!projectile && !is_range_weapon(*weap)
+ || projectile
+ && is_launched(this, weap, *projectile) == LRET_LAUNCHED))
+ {
+ const skill_type wpn_skill = is_range_weapon(*weap)
+ ? range_skill(*weap)
+ : weapon_skill(*weap);
+ attk_delay = constant(property(*weap, PWPN_SPEED));
+ attk_delay -=
+ div_rand_round(constant(you.skill(wpn_skill, 10)), 20);
+
+ // apply minimum to weapon skill modification
+ attk_delay = rv::max(attk_delay, weapon_min_delay(*weap));
+
+ if (weap->base_type == OBJ_WEAPONS
+ && get_weapon_brand(*weap) == SPWPN_SPEED)
+ {
+ attk_delay = div_rand_round(constant(2) * attk_delay, 3);
+ }
+ }
+ }
+
+ // At the moment it never gets this low anyway.
+ attk_delay = rv::max(attk_delay, constant(3));
+
+ // Calculate this separately to avoid overflowing the weights in
+ // the random_var.
+ random_var shield_penalty = constant(0);
+ if (base_shield_penalty)
+ {
+ shield_penalty =
+ div_rand_round(rv::min(rv::roll_dice(1, base_shield_penalty),
+ rv::roll_dice(1, base_shield_penalty)),
+ 20);
+ }
+ // Give unarmed shield-users a slight penalty always.
+ if (!weap && player_wearing_slot(EQ_SHIELD))
+ shield_penalty += rv::random2(2);
+
+ int final_delay = random ? attk_delay.roll() + shield_penalty.roll()
+ : attk_delay.expected() + shield_penalty.expected();
+ // Stop here if we just want the unmodified value.
+ if (!scaled)
+ return final_delay;
+
+ const int scaling = finesse_adjust_delay(you.time_taken);
+ return max(2, div_rand_round(scaling * final_delay, 10));
+}
+
// Returns the item in the given equipment slot, NULL if the slot is empty.
// eq must be in [EQ_WEAPON, EQ_RING_AMULET], or bad things will happen.
item_def *player::slot_item(equipment_type eq, bool include_melded) const