damage: add match option, part filter, cb phial

This commit is contained in:
Bryce Allen
2015-08-19 00:54:15 -05:00
parent 26e376eefb
commit c4edd66c6a
3 changed files with 313 additions and 18 deletions

View File

@@ -9,6 +9,44 @@ from mhapi.db import MHDB
from mhapi.damage import MotionValueDB, WeaponMonsterDamage
from mhapi.model import SharpnessLevel
from mhapi import skills
from mhapi.util import ELEMENTS, WEAPON_TYPES, WTYPE_ABBR
def weapon_match_tuple(arg):
parts = arg.split(",")
if len(parts) == 1:
wtype = parts[0]
element = None
elif len(parts) == 2:
wtype = parts[0]
element = parts[1]
else:
raise ValueError("Bad arg, use 'weapon_type,element_or_status'")
wtype = get_wtype_match(wtype)
if element is not None:
element = get_element_match(element)
return (wtype, element)
def get_wtype_match(term):
abbr_result = WTYPE_ABBR.get(term.upper())
if abbr_result is not None:
return abbr_result
term = term.title()
for wtype in WEAPON_TYPES:
if wtype.startswith(term):
return wtype
raise ValueError("Unknown weapon type: %s" % term)
def get_element_match(term):
term = term.title()
for element in ELEMENTS:
if element.startswith(term):
return element
if term.lower() == "raw":
return "Raw"
raise ValueError("Unknown element or status: %s" % term)
def percent_change(a, b):
@@ -31,18 +69,35 @@ def parse_args(argv):
default=False,
help="add Awaken (FreeElement), default off")
parser.add_argument("-a", "--attack-up",
type=int, choices=xrange(0, 5), default=0,
type=int, choices=range(0, 5), default=0,
help="1-4 for AuS, M, L, XL")
parser.add_argument("-c", "--critical-eye",
type=int, choices=xrange(0, 5), default=0,
type=int, choices=range(0, 5), default=0,
help="1-4 for CE+1, +2, +3 and Critical God")
parser.add_argument("-e", "--element-up",
type=int, choices=xrange(0, 5), default=0,
type=int, choices=range(0, 5), default=0,
help="1-4 for (element) Atk +1, +2, +3 and"
" Element Attack Up")
parser.add_argument("-t", "--artillery",
type=int, choices=[0,1,2], default=0,
help="0-2 for no artillery, novice, god")
parser.add_argument("-p", "--parts",
help="Limit analysis to specified parts"
+" (comma separated list)")
parser.add_argument("-m", "--match", nargs="*",
help="WEAPON_TYPE,ELEMENT_OR_STATUS_OR_RAW"
+" Include all matching weapons in their final form."
+" Supports abbreviations like LS for Long Sword"
+" and Para for Paralysis or Blast for Blastblight."
+" If just WEAPON_TYPE is given, include all final"
+" weapons of that type."
+" Examples: 'Great Sword,Raw'"
+" 'Sword and Shield,Para'"
+" 'HH,Blast' 'Hammer'",
type=weapon_match_tuple, default=[])
parser.add_argument("monster",
help="Full name of monster")
parser.add_argument("weapon", nargs="+",
parser.add_argument("weapon", nargs="*",
help="One or more weapons of same class to compare,"
" full names")
@@ -59,13 +114,29 @@ if __name__ == '__main__':
if not monster:
raise ValueError("Monster '%s' not found" % args.monster)
monster_damage = db.get_monster_damage(monster.id)
weapons = []
weapon_type = None
for match_tuple in args.match:
# TODO: better validation
wtype, element = match_tuple
match_weapons = db.get_weapons_by_query(wtype=wtype, element=element,
final=1)
weapons.extend(match_weapons)
for name in args.weapon:
weapon = db.get_weapon_by_name(name)
if not weapon:
raise ValueError("Weapon '%s' not found" % name)
weapons.append(weapon)
if not weapons:
print "Err: no matching weapons"
sys.exit(1)
names = [w.name for w in weapons]
monster_breaks = db.get_monster_breaks(monster.id)
weapon_type = weapons[0]["wtype"]
motion = motiondb[weapon_type].average
@@ -78,8 +149,15 @@ if __name__ == '__main__':
skills.CriticalEye.name(args.critical_eye),
skills.ElementAttackUp.name(args.element_up)]
print "Skills:", ", ".join(skill for skill in skill_names if skill)
if args.parts:
limit_parts = args.parts.split(",")
else:
limit_parts = None
weapon_damage_map = dict()
for name, row in zip(args.weapon, weapons):
for row in weapons:
name = row["name"]
row_type = row["wtype"]
if row_type != weapon_type:
raise ValueError("Weapon '%s' is different type" % name)
@@ -91,35 +169,45 @@ if __name__ == '__main__':
attack_skill=args.attack_up,
critical_eye_skill=args.critical_eye,
element_skill=args.element_up,
awaken=args.awaken)
awaken=args.awaken,
artillery_level=args.artillery,
limit_parts=args.parts)
print "%-20s: %4.0f %2.0f%%" % (name, wd.attack, wd.affinity),
if wd.etype:
print "(%4.0f %s)" % (wd.eattack, wd.etype),
if wd.etype2:
print "(%4.0f %s, %4.0f %s)" \
% (wd.eattack, wd.etype, wd.eattack2, wd.etype2),
else:
print "(%4.0f %s)" % (wd.eattack, wd.etype),
print SharpnessLevel.name(wd.sharpness)
weapon_damage_map[name] = wd
except ValueError as e:
print str(e)
sys.exit(1)
damage_map_base = weapon_damage_map[args.weapon[0]]
parts = damage_map_base.parts
damage_map_base = weapon_damage_map[weapons[0].name]
if limit_parts:
parts = limit_parts
else:
parts = damage_map_base.parts
for part in parts:
tdiffs = [percent_change(
damage_map_base[part].total,
weapon_damage_map[w][part].total
)
for w in args.weapon[1:]]
for w in names[1:]]
ediffs = [percent_change(
damage_map_base[part].element,
weapon_damage_map[w][part].element
)
for w in args.weapon[1:]]
for w in names[1:]]
bdiffs = [percent_change(
damage_map_base[part].break_diff(),
weapon_damage_map[w][part].break_diff()
)
for w in args.weapon[1:]]
for w in names[1:]]
tdiff_s = ",".join("%+0.1f%%" % i for i in tdiffs)
ediff_s = ",".join("%+0.1f%%" % i for i in ediffs)
bdiff_s = ",".join("%+0.1f%%" % i for i in bdiffs)
@@ -134,6 +222,14 @@ if __name__ == '__main__':
ediff_s,
damage.break_diff(),
bdiff_s)
if weapon_type == "Charge Blade":
for level in (0, 1, 2, 3, 5):
print " " * 20, level,
for wname in names:
wd = weapon_damage_map[wname]
damage = wd.cb_phial_damage[part][level]
print "(%0.f, %0.f, %0.f);" % damage,
print
print " --------------------"
@@ -143,7 +239,7 @@ if __name__ == '__main__':
base,
weapon_damage_map[w].averages[avg_type]
)
for w in args.weapon[1:]]
for w in names[1:]]
diff_s = ",".join("%+0.1f%%" % i for i in diffs)