|
|
|
@ -9,6 +9,44 @@ from mhapi.db import MHDB
|
|
|
|
from mhapi.damage import MotionValueDB, WeaponMonsterDamage
|
|
|
|
from mhapi.damage import MotionValueDB, WeaponMonsterDamage
|
|
|
|
from mhapi.model import SharpnessLevel
|
|
|
|
from mhapi.model import SharpnessLevel
|
|
|
|
from mhapi import skills
|
|
|
|
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):
|
|
|
|
def percent_change(a, b):
|
|
|
|
@ -31,18 +69,35 @@ def parse_args(argv):
|
|
|
|
default=False,
|
|
|
|
default=False,
|
|
|
|
help="add Awaken (FreeElement), default off")
|
|
|
|
help="add Awaken (FreeElement), default off")
|
|
|
|
parser.add_argument("-a", "--attack-up",
|
|
|
|
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")
|
|
|
|
help="1-4 for AuS, M, L, XL")
|
|
|
|
parser.add_argument("-c", "--critical-eye",
|
|
|
|
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")
|
|
|
|
help="1-4 for CE+1, +2, +3 and Critical God")
|
|
|
|
parser.add_argument("-e", "--element-up",
|
|
|
|
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"
|
|
|
|
help="1-4 for (element) Atk +1, +2, +3 and"
|
|
|
|
" Element Attack Up")
|
|
|
|
" 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",
|
|
|
|
parser.add_argument("monster",
|
|
|
|
help="Full name of 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,"
|
|
|
|
help="One or more weapons of same class to compare,"
|
|
|
|
" full names")
|
|
|
|
" full names")
|
|
|
|
|
|
|
|
|
|
|
|
@ -59,13 +114,29 @@ if __name__ == '__main__':
|
|
|
|
if not monster:
|
|
|
|
if not monster:
|
|
|
|
raise ValueError("Monster '%s' not found" % args.monster)
|
|
|
|
raise ValueError("Monster '%s' not found" % args.monster)
|
|
|
|
monster_damage = db.get_monster_damage(monster.id)
|
|
|
|
monster_damage = db.get_monster_damage(monster.id)
|
|
|
|
|
|
|
|
|
|
|
|
weapons = []
|
|
|
|
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:
|
|
|
|
for name in args.weapon:
|
|
|
|
weapon = db.get_weapon_by_name(name)
|
|
|
|
weapon = db.get_weapon_by_name(name)
|
|
|
|
if not weapon:
|
|
|
|
if not weapon:
|
|
|
|
raise ValueError("Weapon '%s' not found" % name)
|
|
|
|
raise ValueError("Weapon '%s' not found" % name)
|
|
|
|
weapons.append(weapon)
|
|
|
|
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)
|
|
|
|
monster_breaks = db.get_monster_breaks(monster.id)
|
|
|
|
weapon_type = weapons[0]["wtype"]
|
|
|
|
weapon_type = weapons[0]["wtype"]
|
|
|
|
motion = motiondb[weapon_type].average
|
|
|
|
motion = motiondb[weapon_type].average
|
|
|
|
@ -78,8 +149,15 @@ if __name__ == '__main__':
|
|
|
|
skills.CriticalEye.name(args.critical_eye),
|
|
|
|
skills.CriticalEye.name(args.critical_eye),
|
|
|
|
skills.ElementAttackUp.name(args.element_up)]
|
|
|
|
skills.ElementAttackUp.name(args.element_up)]
|
|
|
|
print "Skills:", ", ".join(skill for skill in skill_names if skill)
|
|
|
|
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()
|
|
|
|
weapon_damage_map = dict()
|
|
|
|
for name, row in zip(args.weapon, weapons):
|
|
|
|
for row in weapons:
|
|
|
|
|
|
|
|
name = row["name"]
|
|
|
|
row_type = row["wtype"]
|
|
|
|
row_type = row["wtype"]
|
|
|
|
if row_type != weapon_type:
|
|
|
|
if row_type != weapon_type:
|
|
|
|
raise ValueError("Weapon '%s' is different type" % name)
|
|
|
|
raise ValueError("Weapon '%s' is different type" % name)
|
|
|
|
@ -91,9 +169,15 @@ if __name__ == '__main__':
|
|
|
|
attack_skill=args.attack_up,
|
|
|
|
attack_skill=args.attack_up,
|
|
|
|
critical_eye_skill=args.critical_eye,
|
|
|
|
critical_eye_skill=args.critical_eye,
|
|
|
|
element_skill=args.element_up,
|
|
|
|
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),
|
|
|
|
print "%-20s: %4.0f %2.0f%%" % (name, wd.attack, wd.affinity),
|
|
|
|
if wd.etype:
|
|
|
|
if 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 "(%4.0f %s)" % (wd.eattack, wd.etype),
|
|
|
|
print SharpnessLevel.name(wd.sharpness)
|
|
|
|
print SharpnessLevel.name(wd.sharpness)
|
|
|
|
weapon_damage_map[name] = wd
|
|
|
|
weapon_damage_map[name] = wd
|
|
|
|
@ -101,7 +185,11 @@ if __name__ == '__main__':
|
|
|
|
print str(e)
|
|
|
|
print str(e)
|
|
|
|
sys.exit(1)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
damage_map_base = weapon_damage_map[args.weapon[0]]
|
|
|
|
damage_map_base = weapon_damage_map[weapons[0].name]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if limit_parts:
|
|
|
|
|
|
|
|
parts = limit_parts
|
|
|
|
|
|
|
|
else:
|
|
|
|
parts = damage_map_base.parts
|
|
|
|
parts = damage_map_base.parts
|
|
|
|
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
for part in parts:
|
|
|
|
@ -109,17 +197,17 @@ if __name__ == '__main__':
|
|
|
|
damage_map_base[part].total,
|
|
|
|
damage_map_base[part].total,
|
|
|
|
weapon_damage_map[w][part].total
|
|
|
|
weapon_damage_map[w][part].total
|
|
|
|
)
|
|
|
|
)
|
|
|
|
for w in args.weapon[1:]]
|
|
|
|
for w in names[1:]]
|
|
|
|
ediffs = [percent_change(
|
|
|
|
ediffs = [percent_change(
|
|
|
|
damage_map_base[part].element,
|
|
|
|
damage_map_base[part].element,
|
|
|
|
weapon_damage_map[w][part].element
|
|
|
|
weapon_damage_map[w][part].element
|
|
|
|
)
|
|
|
|
)
|
|
|
|
for w in args.weapon[1:]]
|
|
|
|
for w in names[1:]]
|
|
|
|
bdiffs = [percent_change(
|
|
|
|
bdiffs = [percent_change(
|
|
|
|
damage_map_base[part].break_diff(),
|
|
|
|
damage_map_base[part].break_diff(),
|
|
|
|
weapon_damage_map[w][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)
|
|
|
|
tdiff_s = ",".join("%+0.1f%%" % i for i in tdiffs)
|
|
|
|
ediff_s = ",".join("%+0.1f%%" % i for i in ediffs)
|
|
|
|
ediff_s = ",".join("%+0.1f%%" % i for i in ediffs)
|
|
|
|
bdiff_s = ",".join("%+0.1f%%" % i for i in bdiffs)
|
|
|
|
bdiff_s = ",".join("%+0.1f%%" % i for i in bdiffs)
|
|
|
|
@ -134,6 +222,14 @@ if __name__ == '__main__':
|
|
|
|
ediff_s,
|
|
|
|
ediff_s,
|
|
|
|
damage.break_diff(),
|
|
|
|
damage.break_diff(),
|
|
|
|
bdiff_s)
|
|
|
|
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 " --------------------"
|
|
|
|
print " --------------------"
|
|
|
|
|
|
|
|
|
|
|
|
@ -143,7 +239,7 @@ if __name__ == '__main__':
|
|
|
|
base,
|
|
|
|
base,
|
|
|
|
weapon_damage_map[w].averages[avg_type]
|
|
|
|
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)
|
|
|
|
diff_s = ",".join("%+0.1f%%" % i for i in diffs)
|
|
|
|
|
|
|
|
|
|
|
|
|