def greatsword_damage(lvl, start_mod, weapon_bonus, enemy, power_atk): num_asis = get_num_asis(lvl) final_mod, num_asis = max_mod(start_mod, num_asis) action_attacks = get_num_attacks(lvl) prof = proficiency(lvl) gwm = False if num_asis >= 1: gwm = True damage_mod = final_mod + weapon_bonus weapon_dmg = Damage("2d6r2 + " + str(damage_mod)) if gwm and power_atk: weapon_dmg = Damage("2d6r2 + " + str(damage_mod + 10)) to_hit = final_mod + weapon_bonus + prof hit_bonus = Constant(to_hit) if gwm and power_atk: hit_bonus = Constant(to_hit - 5) attack = Attack(hit_bonus, enemy) attack.add_damage(weapon_dmg) round_dmg = MultiAttack() for i in range(action_attacks): round_dmg.add_attack(attack.copy()) if gwm: round_dmg.add_crit_extra_attack(attack.copy()) dmg = round_dmg.get_dmg_rv() return dmg
def halberd_damage(lvl, start_mod, weapon_bonus, enemy, power_atk): num_asis = get_num_asis(lvl) final_mod, num_asis = max_mod(start_mod, num_asis) action_attacks = get_num_attacks(lvl) prof = proficiency(lvl) gwm = False if num_asis >= 1: gwm = True num_asis -= 1 pam = False if num_asis >= 1: pam = True damage_mod = final_mod + weapon_bonus weapon_dmg = Damage("1d10r2 + " + str(damage_mod)) pommel_dmg = Damage("1d4r2 + " + str(damage_mod)) if gwm and power_atk: weapon_dmg = Damage("1d10r2 + " + str(damage_mod + 10)) pommel_dmg = Damage("1d4r2 + " + str(damage_mod + 10)) to_hit = final_mod + weapon_bonus + prof hit_bonus = Constant(to_hit) if gwm and power_atk: hit_bonus = Constant(to_hit - 5) attack = Attack(hit_bonus, enemy) attack.add_damage(weapon_dmg) round_dmg = MultiAttack() for i in range(action_attacks): round_dmg.add_attack(attack.copy()) # technically, you can wait to use the pam bonus action # until you don't crit your normal attacks, otherwise you # get a 1d10 bonus action attack from gwm rather than 1d4 # however, that is much more complicated to simulate # and unlikely to change the result much if pam: pommel_atk = Attack(hit_bonus, enemy) pommel_atk.add_damage(pommel_dmg) round_dmg.add_attack(pommel_atk) elif gwm: round_dmg.add_crit_extra_attack(attack.copy()) dmg = round_dmg.get_dmg_rv() return dmg
def longsword_damage(lvl, start_mod, weapon_bonus, enemy, power_atk): num_asis = get_num_asis(lvl) final_mod, num_asis = max_mod(start_mod, num_asis) action_attacks = get_num_attacks(lvl) prof = proficiency(lvl) if num_asis >= 1: # get shield master, assume the shove knocks prone always # this isn't the best assumption, but I don't have a way # to handle this conditional yet. enemy.apply_hit_type(HitType.ADVANTAGE) damage_mod = final_mod + weapon_bonus + 2 weapon_dmg = Damage("1d8 + " + str(damage_mod)) to_hit = final_mod + weapon_bonus + prof hit_bonus = Constant(to_hit) attack = Attack(hit_bonus, enemy) attack.add_damage(weapon_dmg) round_dmg = MultiAttack() for i in range(action_attacks): round_dmg.add_attack(attack.copy()) dmg = round_dmg.get_dmg_rv() return dmg
def archery_damage(lvl, start_mod, weapon_bonus, enemy, power_atk): num_asis = get_num_asis(lvl) final_mod, num_asis = max_mod(start_mod, num_asis) action_attacks = get_num_attacks(lvl) prof = proficiency(lvl) sharpshooter = False if num_asis >= 1: sharpshooter = True damage_mod = final_mod + weapon_bonus weapon_dmg = Damage("1d8 + " + str(damage_mod)) if sharpshooter and power_atk: weapon_dmg = Damage("1d8 + " + str(damage_mod + 10)) to_hit = final_mod + 2 + weapon_bonus + prof hit_bonus = Constant(to_hit) if sharpshooter and power_atk: hit_bonus = Constant(to_hit - 5) attack = Attack(hit_bonus, enemy) attack.add_damage(weapon_dmg) round_dmg = MultiAttack() for i in range(action_attacks): round_dmg.add_attack(attack.copy()) dmg = round_dmg.get_dmg_rv() return dmg
def dual_wield_damage(lvl, start_mod, weapon_bonus, enemy, power_atk): num_asis = get_num_asis(lvl) final_mod, num_asis = max_mod(start_mod, num_asis) action_attacks = get_num_attacks(lvl) prof = proficiency(lvl) weapon_die = "1d6" if num_asis >= 1: # dual wielder feat (sigh...) weapon_die = "1d8" damage_mod = final_mod + weapon_bonus weapon_dmg = Damage(weapon_die + " + " + str(damage_mod)) to_hit = final_mod + weapon_bonus + prof hit_bonus = Constant(to_hit) attack = Attack(hit_bonus, enemy) attack.add_damage(weapon_dmg) round_dmg = MultiAttack() bonus_attacks = 1 #bonus_attacks = action_attacks for i in range(action_attacks + bonus_attacks): round_dmg.add_attack(attack.copy()) dmg = round_dmg.get_dmg_rv() return dmg
auto_crit = False turn_one = True # lvl 11 gloomstalker ranger using longbow, 20 dex, hunter's mark damage = Damage("1d8 + 1d6 + 5", resisted) bonus_atk_damage = Damage("2d8 + 1d6 + 5", resisted) hit_bonus = Constant(11) # dex + prof + 2 = 5 + 4 + 2 enemy = Enemy(armor_class, hit_type, auto_crit) attack = Attack(hit_bonus, enemy) attack.add_damage(damage) attack2 = attack.copy() attack3 = Attack(hit_bonus, enemy) attack3.add_damage(bonus_atk_damage) attack_miss = attack.copy() round_dmg = MultiAttack() round_dmg.add_attack(attack) round_dmg.add_attack(attack2) if turn_one: round_dmg.add_attack(attack3) round_dmg.add_miss_extra_attack(attack_miss)
def ragemage_damage(class_lvls, enemy, weapon_bonus, haste_status=HasteStatus.INACTIVE, shove=False, action_surge=False, giants_might=False, elven_accuracy=False): lvl = get_character_lvl(class_lvls) prof = proficiency(lvl) cantrip_dice = get_cantrip_dice(lvl) rogue_lvl = get_class_lvl(class_lvls, MultiClasses.ROGUE) fighter_lvl = get_class_lvl(class_lvls, MultiClasses.FIGHTER) wizard_lvl = get_class_lvl(class_lvls, MultiClasses.WIZARD) barb_lvl = get_class_lvl(class_lvls, MultiClasses.BARBARIAN) sneak_attack_dice = math.ceil(rogue_lvl / 2) first_hit_dice = sneak_attack_dice if fighter_lvl >= 3 and giants_might: first_hit_dice += 1 first_hit_dmg = Damage(str(first_hit_dice) + "d6") dueling = 0 if fighter_lvl > 0: dueling = 2 damage_bonus = 5 + weapon_bonus + dueling rapier = Damage("1d8 + " + str(damage_bonus)) booming_blade = rapier.copy() if cantrip_dice > 1: booming_blade = Damage(str(cantrip_dice) + "d8 + " + str(damage_bonus)) hit_bonus = Constant(5 + weapon_bonus + prof) num_attacks = 1 num_attacks_bb = 0 if wizard_lvl >= 6: num_attacks_bb = 1 else: if fighter_lvl >= 5 or barb_lvl >= 5: num_attacks = 2 if haste_status == HasteStatus.CASTING: num_attacks_bb = 0 elif haste_status == HasteStatus.ACTIVE: num_attacks += 1 elif haste_status == HasteStatus.DROPPED: num_attacks = 0 num_attacks_bb = 0 if action_surge and fighter_lvl >= 2: num_attacks += 1 num_attacks_bb += 1 if shove and num_attacks + num_attacks_bb >= 2: num_attacks -= 1 if elven_accuracy: enemy.apply_hit_type(HitType.SUPER_ADVANTAGE) else: enemy.apply_hit_type(HitType.ADVANTAGE) attack = Attack(hit_bonus, enemy) attack.add_damage(rapier) attack_bb = Attack(hit_bonus, enemy) attack_bb.add_damage(booming_blade) round_dmg = MultiAttack() for i in range(num_attacks): round_dmg.add_attack(attack.copy()) for i in range(num_attacks_bb): round_dmg.add_attack(attack_bb.copy()) round_dmg.add_first_hit_damage(first_hit_dmg) dmg = round_dmg.get_dmg_rv() return dmg
def sequoia_damage_haste(lvl, enemy, sharpshooter=False, multitarget=False, haste_status=HasteStatus.INACTIVE, using_pw=False, hunters_mark_active=True): # 6 is 20 dex and a +1 longbow longbow_hm = Damage("1d8 + 1d6 + 6") if sharpshooter: longbow_hm = Damage("1d8 + 1d6 + 16") longbow = Damage("1d8 + 6") if sharpshooter: longbow = Damage("1d8 + 16") planar_warrior = Damage("1d8") if lvl >= 11: planar_warrior = Damage("2d8") prof = proficiency(lvl) # 20 dex (+5), archery fighting style, +1 longbow hit_bonus = Constant(5 + 2 + 1 + prof) if sharpshooter: hit_bonus = Constant(2 + 1 + prof) num_attacks = 1 num_hm_attacks = 0 if hunters_mark_active: num_attacks = 0 num_hm_attacks = 1 if lvl >= 11 and multitarget: num_attacks = 2 num_hm_attacks = 1 elif lvl >= 5: num_hm_attacks = 2 if haste_status == HasteStatus.CASTING: num_attacks = 0 num_hm_attacks = 1 elif haste_status == HasteStatus.ACTIVE: num_hm_attacks += 1 elif haste_status == HasteStatus.DROPPED: num_attacks = 0 num_hm_attacks = 0 else: if lvl >= 11 and multitarget: num_attacks = 3 elif lvl >= 5: num_attacks = 2 if haste_status == HasteStatus.CASTING: num_attacks = 1 elif haste_status == HasteStatus.ACTIVE: num_attacks += 1 elif haste_status == HasteStatus.DROPPED: num_attacks = 0 attack = Attack(hit_bonus, enemy) attack.add_damage(longbow) attack_hm = Attack(hit_bonus, enemy) attack_hm.add_damage(longbow_hm) round_dmg = MultiAttack() for i in range(num_attacks): round_dmg.add_attack(attack.copy()) for i in range(num_hm_attacks): round_dmg.add_attack(attack_hm.copy()) if using_pw: round_dmg.add_first_hit_damage(planar_warrior) dmg = round_dmg.get_dmg_rv() return dmg
# enemy assumptions armor_class = 16 hit_type = HitType.ADVANTAGE resisted = False auto_crit = False # lvl 9 half-orc zealot barbarian, reckless attack, greataxe damage = Damage("1d12 + 5 + 3", resisted) damage.set_crit_bonus("2d12") divine_fury_dmg = Damage("1d6 + 4", resisted) hit_bonus = Constant(9) # str + prof = 5 + 4 enemy = Enemy(armor_class, hit_type, auto_crit) attack = Attack(hit_bonus, enemy) attack.add_damage(damage) attack2 = attack.copy() round_dmg = MultiAttack() round_dmg.add_attack(attack) round_dmg.add_attack(attack2) round_dmg.add_first_hit_damage(divine_fury_dmg) dpr = round_dmg.get_dmg_rv() dpr.describe(True)