def __init__(self, cycle, time_in_execute_range=.35, tricks_on_cooldown=True, response_time=.5, dmg_poison='dp', utl_poison=None, duration=300, use_opener='always', opener_name='default', is_pvp=False, stormlash=False, shiv_interval=0): self.cycle = cycle self.time_in_execute_range = time_in_execute_range self.tricks_on_cooldown = tricks_on_cooldown self.response_time = response_time self.dmg_poison = dmg_poison self.utl_poison = utl_poison self.duration = duration self.use_opener = use_opener # Allowed values are 'always' (vanish/shadowmeld on cooldown), 'opener' (once per fight) and 'never' self.opener_name = opener_name self.is_pvp = is_pvp self.use_stormlash = stormlash self.shiv_interval = int(shiv_interval) if self.shiv_interval < 10 and not self.shiv_interval == 0: self.shiv_interval = 10 allowed_openers_per_spec = { 'assassination': tuple(['mutilate']), 'combat': ('sinister_strike', 'revealing_strike'), 'subtlety': () } allowed_openers = allowed_openers_per_spec[self.get_spec()] + ('ambush', 'garrote', 'default', 'cpg') if opener_name not in allowed_openers: raise exceptions.InvalidInputException(_('Opener {opener} is not allowed in {cycle} cycles.').format(opener=opener_name, cycle=self.get_spec())) if opener_name == 'default': default_openers = { 'assassination': 'ambush', 'combat': 'sinister_strike', 'subtlety': 'ambush'} self.opener_name = default_openers[self.get_spec()] if dmg_poison not in (None, 'dp', 'wp'): raise exceptions.InvalidInputException(_('You can only choose Deadly(dp) or Wound(wp) as a damage poison')) if utl_poison not in (None, 'cp', 'mnp', 'lp', 'pp'): raise exceptions.InvalidInputException(_('You can only choose Crippling(cp), Mind-Numbing(mnp), Leeching(lp) or Paralytic(pp) as a non-lethal poison'))
def set_enchant(self, enchant): if enchant == None: self.del_enchant() else: if self.is_melee(): if enchant in self.allowed_melee_enchants: self.del_enchant() proc = procs.Proc(**self.allowed_melee_enchants[enchant]) setattr(self, enchant, proc) else: raise exceptions.InvalidInputException(_('Enchant {enchant} is not allowed.').format(enchant=enchant)) else: raise exceptions.InvalidInputException(_('Only melee weapons can be enchanted with {enchant}.').format(enchant=enchant))
def get_class_number(self, game_class): for i in self.GAME_CLASS_NUMBER.keys(): if self.GAME_CLASS_NUMBER[i] == game_class: return i raise exceptions.InvalidInputException( _('{game_class} is not a supported game class').format( game_class=game_class))
def _set_constants_for_class(self): # These factors are class-specific. Generaly those go in the class module, # unless it's basic stuff like combat ratings or base stats that we can # datamine for all classes/specs at once. if self.talents.game_class != self.glyphs.game_class: raise exceptions.InvalidInputException( _('You must specify the same class for your talents and glyphs' )) self.game_class = self.talents.game_class
def __init__(self, cycle, time_in_execute_range=.35, response_time=.5, latency=.03, dmg_poison='dp', utl_poison=None, duration=300, use_opener='always', opener_name='default', is_pvp=False, shiv_interval=0, adv_params=None, merge_damage=True, num_boss_adds=0, feint_interval=0, default_ep_stat='ap', is_day=False, is_demon=False): self.cycle = cycle self.time_in_execute_range = time_in_execute_range self.response_time = response_time self.latency = latency self.dmg_poison = dmg_poison self.utl_poison = utl_poison self.duration = duration self.use_opener = use_opener # Allowed values are 'always' (vanish/shadowmeld on cooldown), 'opener' (once per fight) and 'never' self.opener_name = opener_name self.is_pvp = is_pvp self.feint_interval = feint_interval self.merge_damage = merge_damage self.is_day = is_day self.is_demon = is_demon self.num_boss_adds = max(num_boss_adds, 0) self.shiv_interval = float(shiv_interval) self.adv_params = self.interpret_adv_params(adv_params) self.default_ep_stat = default_ep_stat if self.shiv_interval < 10 and not self.shiv_interval == 0: self.shiv_interval = 10 allowed_openers_per_spec = { 'assassination': ('mutilate', 'dispatch', 'envenom'), 'combat': ('sinister_strike', 'revealing_strike', 'eviscerate'), 'subtlety': () } allowed_openers = allowed_openers_per_spec[self.cycle._cycle_type] + ('ambush', 'garrote', 'default', 'cpg') if opener_name not in allowed_openers: raise exceptions.InvalidInputException(_('Opener {opener} is not allowed in {cycle} cycles.').format(opener=opener_name, cycle=self.cycle._cycle_type)) if opener_name == 'default': default_openers = { 'assassination': 'mutilate', 'combat': 'ambush', 'subtlety': 'ambush'} self.opener_name = default_openers[self.cycle._cycle_type] if dmg_poison not in (None, 'dp', 'wp'): raise exceptions.InvalidInputException(_('You can only choose Deadly(dp) or Wound(wp) as a damage poison')) if utl_poison not in (None, 'cp', 'mnp', 'lp', 'pp'): raise exceptions.InvalidInputException(_('You can only choose Crippling(cp), Mind-Numbing(mnp), Leeching(lp) or Paralytic(pp) as a non-lethal poison'))
def get_adv_param(self, type, default_val, min_bound=-10000, max_bound=10000, ignore_bounds=False): if type in self.settings.adv_params and not ignore_bounds: return max(min(float(self.settings.adv_params[type]), max_bound), min_bound) elif type in self.settings.adv_params: return self.settings.adv_params[type] else: return default_val raise exceptions.InvalidInputException( _('Improperly defined parameter type: ' + type))
def interpret_adv_params(self, s=""): data = {} max_effects = 8 current_effects = 0 if s != "" and s: for e in s.split(';'): if e != "": tmp = e.split(':') try: data[tmp[0].strip().lower()] = tmp[1].strip().lower() #strip() and lower() needed so that everyone is on the same page print data[tmp[0].strip().lower()] + ' : ' + tmp[0].strip().lower() current_effects += 1 if current_effects == max_effects: return data except: raise exceptions.InvalidInputException(_('Advanced Parameter ' + e + ' found corrupt. Properly structure params and try again.')) return data
def _set_constants_for_level(self): self.buffs.level = self.level self.stats.level = self.level self.race.level = self.level self.stats.gear_buffs.level = self.level # calculate and cache the level-dependent armor mitigation parameter self.armor_mitigation_parameter = armor_mitigation.parameter( self.level) # target level dependent constants try: self.target_base_armor = self.TARGET_BASE_ARMOR_VALUES[ self.target_level] except KeyError as e: raise exceptions.InvalidInputException( _('There\'s no armor value for a target level {level}').format( level=str(e))) self.crit_reduction = .01 * self.level_difference
def raid_settings_modifiers(self, attack_kind, armor=None, affect_resil=True): # This function wraps spell, bleed and physical debuffs from raid # along with all-damage buff and armor reduction. It should be called # from every damage dealing formula. Armor can be overridden if needed. if attack_kind not in ('physical', 'spell', 'bleed'): raise exceptions.InvalidInputException( _('Attacks must be categorized as physical, spell or bleed')) elif attack_kind == 'spell': return self.buffs.spell_damage_multiplier() elif attack_kind == 'bleed': return self.buffs.bleed_damage_multiplier() elif attack_kind == 'physical': armor_override = self.target_armor(armor) return self.buffs.physical_damage_multiplier( ) * self.armor_mitigation_multiplier(armor_override)
def get_random_prop_point(self, item_level): if item_level < 1: raise exceptions.InvalidInputException( _('item_level={item_level} need to be >= 1').format( item_level=item_level)) return self.RANDOM_PROP_POINTS[item_level][1]