Permalink
Browse files

real ppm?

This /definitely/ needs another set of eyes. I had to funnel haste
through all the proc information.
  • Loading branch information...
1 parent 4c25cd8 commit 97c74c5047a5e110a670b3ca87079bcbbd51512f Pathal committed Oct 15, 2012
Showing with 42 additions and 17 deletions.
  1. +2 −0 .gitignore
  2. +18 −13 shadowcraft/calcs/rogue/Aldriana/__init__.py
  3. +4 −2 shadowcraft/objects/proc_data.py
  4. +18 −2 shadowcraft/objects/procs.py
View
@@ -6,3 +6,5 @@
dist
build
MANIFEST
+item_db
+item_db.db
@@ -512,7 +512,7 @@ def get_damage_breakdown(self, current_stats, attacks_per_second, crit_rates, da
average_dps += uptime * damage_tuple[0] * self.spell_hit_chance()
crit_dps += uptime * damage_tuple[1] * self.spell_hit_chance()
damage_breakdown['stormlash'] = average_dps, crit_dps
-
+
if 'hemorrhage_ticks' in attacks_per_second:
dps_from_hit_hemo = self.get_dps_contribution(self.hemorrhage_tick_damage(average_ap, from_crit_hemo=False), crit_rates['hemorrhage'], attacks_per_second['hemorrhage_ticks'] * (1 - crit_rates['hemorrhage']))
dps_from_crit_hemo = self.get_dps_contribution(self.hemorrhage_tick_damage(average_ap, from_crit_hemo=True), crit_rates['hemorrhage'], attacks_per_second['hemorrhage_ticks'] * crit_rates['hemorrhage'])
@@ -590,7 +590,7 @@ def update_with_autoattack_passives(self, attacks_per_second, *args, **kwargs):
attacks_per_second['main_gauche'] = main_gauche_proc_rate * attacks_per_second['mh_autoattack_hits']
- def get_mh_procs_per_second(self, proc, attacks_per_second, crit_rates):
+ def get_mh_procs_per_second(self, proc, attacks_per_second, crit_rates, haste=0.0):
triggers_per_second = 0
if proc.procs_off_auto_attacks():
if proc.procs_off_crit_only():
@@ -619,10 +619,11 @@ def get_mh_procs_per_second(self, proc, attacks_per_second, crit_rates):
triggers_per_second += attacks_per_second['garrote']
if 'hemorrhage_ticks' in attacks_per_second:
triggers_per_second += attacks_per_second['hemorrhage']
-
+ if proc.is_real_ppm():
+ return triggers_per_second * proc.proc_rate(self.stats.mh.speed, haste=haste)
return triggers_per_second * proc.proc_rate(self.stats.mh.speed)
- def get_oh_procs_per_second(self, proc, attacks_per_second, crit_rates):
+ def get_oh_procs_per_second(self, proc, attacks_per_second, crit_rates, haste=0.0):
triggers_per_second = 0
if proc.procs_off_auto_attacks():
if proc.procs_off_crit_only():
@@ -636,10 +637,11 @@ def get_oh_procs_per_second(self, proc, attacks_per_second, crit_rates):
triggers_per_second += attacks_per_second[ability] * crit_rates[ability]
else:
triggers_per_second += attacks_per_second[ability]
-
+ if proc.is_real_ppm():
+ return 60 * proc.proc_rate(self.stats.mh.speed, haste=haste)
return triggers_per_second * proc.proc_rate(self.stats.oh.speed)
- def get_other_procs_per_second(self, proc, attacks_per_second, crit_rates):
+ def get_other_procs_per_second(self, proc, attacks_per_second, crit_rates, haste=0.0):
triggers_per_second = 0
if proc.procs_off_harmful_spells():
@@ -671,22 +673,26 @@ def get_other_procs_per_second(self, proc, attacks_per_second, crit_rates):
triggers_per_second += attacks_per_second['hemorrhage_ticks'] * crit_rates['hemorrhage']
else:
triggers_per_second += attacks_per_second['hemorrhage_ticks']
- if proc.is_ppm():
+ if proc.is_real_ppm():
+ return 60 * proc.proc_rate(self.stats.mh.speed, haste=haste)
+ elif proc.is_ppm():
if triggers_per_second == 0:
return 0
else:
raise InputNotModeledException(_('PPMs that also proc off spells are not yet modeled.'))
else:
return triggers_per_second * proc.proc_rate()
- def get_procs_per_second(self, proc, attacks_per_second, crit_rates):
+ def get_procs_per_second(self, proc, attacks_per_second, crit_rates, haste=0.0):
# TODO: Include damaging proc hits in figuring out how often everything else procs.
if getattr(proc, 'mh_only', False):
- procs_per_second = self.get_mh_procs_per_second(proc, attacks_per_second, crit_rates)
+ procs_per_second = self.get_mh_procs_per_second(proc, attacks_per_second, crit_rates, haste=haste)
elif getattr(proc, 'oh_only', False):
- procs_per_second = self.get_oh_procs_per_second(proc, attacks_per_second, crit_rates)
+ procs_per_second = self.get_oh_procs_per_second(proc, attacks_per_second, crit_rates, haste=haste)
else:
- procs_per_second = self.get_mh_procs_per_second(proc, attacks_per_second, crit_rates) + self.get_oh_procs_per_second(proc, attacks_per_second, crit_rates) + self.get_other_procs_per_second(proc, attacks_per_second, crit_rates)
+ procs_per_second = self.get_mh_procs_per_second(proc, attacks_per_second, crit_rates, haste=haste)
+ procs_per_second += self.get_oh_procs_per_second(proc, attacks_per_second, crit_rates, haste=haste)
+ procs_per_second += self.get_other_procs_per_second(proc, attacks_per_second, crit_rates, haste=haste)
return procs_per_second
@@ -1274,9 +1280,8 @@ def combat_dps_breakdown(self):
if self.settings.cycle.blade_flurry:
damage_breakdown['blade_flurry'] = 0
- triggers = ['sinister_strike', 'autoattack', 'revealing_strike', 'eviscerate', 'shadow_blades', 'main_gauche', 'killing_spree']
for key in damage_breakdown:
- if key in triggers:
+ if key in self.melee_attacks:
damage_breakdown['blade_flurry'] += damage_breakdown[key] * self.armor_mitigation_multiplier(self.target_armor())
return damage_breakdown
@@ -315,13 +315,15 @@
'trigger': 'all_melee_attacks'
},
'windsong': {
+ 'real_ppm':True,
'icd': 0,
- 'ppm': 3,
+ 'ppm': 2,
'trigger': 'all_attacks'
},
'elemental_force': {
+ 'real_ppm':True,
'icd': 0,
- 'ppm': 1,
+ 'ppm': 10,
'trigger': 'all_attacks'
},
# 5.0 Procs
@@ -34,14 +34,15 @@ def __setattr__(self, name, value):
else:
raise InvalidProcException(_('Behaviour \'{behaviour}\' is not defined for {proc}').format(proc=self.proc_name, behaviour=value))
- def _set_behaviour(self, icd, trigger, proc_chance=False, ppm=False, on_crit=False, on_procced_strikes=True):
+ def _set_behaviour(self, icd, trigger, proc_chance=False, ppm=False, on_crit=False, on_procced_strikes=True, real_ppm=False):
# This could be merged with __setattr__; its sole purpose is
# to clearly surface the parameters passed with the behaviours.
self.proc_chance = proc_chance
self.trigger = trigger
self.icd = icd
self.on_crit = on_crit
self.ppm = ppm
+ self.real_ppm=real_ppm
self.on_procced_strikes = on_procced_strikes # Main Gauche and its kin
def procs_off_auto_attacks(self):
@@ -104,22 +105,37 @@ def procs_off_procced_strikes(self):
else:
return False
- def proc_rate(self, speed=None):
+ def proc_rate(self, speed=None, haste=0.0):
if self.is_ppm():
if speed is None:
raise InvalidProcException(_('Weapon speed needed to calculate the proc rate of {proc}').format(proc=self.proc_name))
else:
return self.ppm * speed / 60.
+ elif self.is_real_ppm():
+ if speed is None:
+ raise InvalidProcException(_('Weapon speed needed to calculate the proc rate of {proc}').format(proc=self.proc_name))
+ else:
+ return (1 + haste/100) * self.ppm / 60
else:
return self.proc_chance
def is_ppm(self):
if self.proc_chance not in (False, None) and self.ppm == False:
return False
+ elif self.real_ppm == True:
+ return False
elif self.ppm not in (False, None) and self.proc_chance == False:
return True
else:
raise InvalidProcException(_('Invalid data for proc {proc}').format(proc=self.proc_name))
+
+ def is_real_ppm(self):
+ if self.real_ppm == True and (self.ppm not in (False, None)):
+ return True
+ elif self.real_ppm in (False, None):
+ return False
+ else:
+ raise InvalidProcException(_('Invalid data for proc {proc}').format(proc=self.proc_name))
class ProcsList(object):
allowed_procs = proc_data.allowed_procs

0 comments on commit 97c74c5

Please sign in to comment.