|
|
|
@ -67,7 +67,7 @@ def parse_args(argv):
|
|
|
|
help="add Sharpness +1 skill, default off")
|
|
|
|
help="add Sharpness +1 skill, default off")
|
|
|
|
parser.add_argument("-f", "--awaken", action="store_true",
|
|
|
|
parser.add_argument("-f", "--awaken", action="store_true",
|
|
|
|
default=False,
|
|
|
|
default=False,
|
|
|
|
help="add Awaken (FreeElement), default off")
|
|
|
|
help="add Awaken (FreeElemnt), default off")
|
|
|
|
parser.add_argument("-a", "--attack-up",
|
|
|
|
parser.add_argument("-a", "--attack-up",
|
|
|
|
type=int, choices=range(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")
|
|
|
|
@ -81,9 +81,21 @@ def parse_args(argv):
|
|
|
|
parser.add_argument("-t", "--artillery",
|
|
|
|
parser.add_argument("-t", "--artillery",
|
|
|
|
type=int, choices=[0,1,2], default=0,
|
|
|
|
type=int, choices=[0,1,2], default=0,
|
|
|
|
help="0-2 for no artillery, novice, god")
|
|
|
|
help="0-2 for no artillery, novice, god")
|
|
|
|
|
|
|
|
parser.add_argument("-z", "--frenzy",
|
|
|
|
|
|
|
|
help="With virus affinity boost, must be either"
|
|
|
|
|
|
|
|
+" 15 (normal) or 30 (with Frenzy Res skill)",
|
|
|
|
|
|
|
|
type=int, choices=[0, 15, 30], default=0)
|
|
|
|
parser.add_argument("-p", "--parts",
|
|
|
|
parser.add_argument("-p", "--parts",
|
|
|
|
help="Limit analysis to specified parts"
|
|
|
|
help="Limit analysis to specified parts"
|
|
|
|
+" (comma separated list)")
|
|
|
|
+" (comma separated list)")
|
|
|
|
|
|
|
|
parser.add_argument("-l", "--phial",
|
|
|
|
|
|
|
|
help="Show CB phial damage at the sepcified level"
|
|
|
|
|
|
|
|
+" (1, 2, 3, 5=ultra) instead of normal motion"
|
|
|
|
|
|
|
|
+" values.",
|
|
|
|
|
|
|
|
type=int, choices=[0, 1, 2, 3, 5], default=0)
|
|
|
|
|
|
|
|
parser.add_argument("-d", "--diff", action="store_true", default=False,
|
|
|
|
|
|
|
|
help="Show percent difference in damage to each part"
|
|
|
|
|
|
|
|
+" from first weapon in list.")
|
|
|
|
parser.add_argument("-m", "--match", nargs="*",
|
|
|
|
parser.add_argument("-m", "--match", nargs="*",
|
|
|
|
help="WEAPON_TYPE,ELEMENT_OR_STATUS_OR_RAW"
|
|
|
|
help="WEAPON_TYPE,ELEMENT_OR_STATUS_OR_RAW"
|
|
|
|
+" Include all matching weapons in their final form."
|
|
|
|
+" Include all matching weapons in their final form."
|
|
|
|
@ -104,6 +116,121 @@ def parse_args(argv):
|
|
|
|
return parser.parse_args(argv)
|
|
|
|
return parser.parse_args(argv)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_sorted_phial_damage(names, damage_map_base, weapon_damage_map, parts,
|
|
|
|
|
|
|
|
level):
|
|
|
|
|
|
|
|
def cb_levelN(weapon):
|
|
|
|
|
|
|
|
return avg_phial(weapon_damage_map[weapon], level=level)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def avg_phial(wd, level=5):
|
|
|
|
|
|
|
|
total = 0.0
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
|
|
|
|
total += sum(wd.cb_phial_damage[part][level])
|
|
|
|
|
|
|
|
return total / len(parts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
names_sorted = list(names)
|
|
|
|
|
|
|
|
names_sorted.sort(key=cb_levelN, reverse=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_print_headers(parts, damage_map_base)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for name in names_sorted:
|
|
|
|
|
|
|
|
print "%-20s:" % name,
|
|
|
|
|
|
|
|
damage_map = weapon_damage_map[name]
|
|
|
|
|
|
|
|
print "%0.2f" % avg_phial(damage_map, level=level),
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
|
|
|
|
part_damage = damage_map[part]
|
|
|
|
|
|
|
|
print "%0.2f" % sum(damage_map.cb_phial_damage[part][level]),
|
|
|
|
|
|
|
|
print
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _print_headers(parts, damage_map_base):
|
|
|
|
|
|
|
|
print
|
|
|
|
|
|
|
|
avg_hitbox = (sum(damage_map_base[part].hitbox for part in parts)
|
|
|
|
|
|
|
|
/ float(len(parts)))
|
|
|
|
|
|
|
|
cols = ["%s (%d)" % (part, damage_map_base[part].hitbox)
|
|
|
|
|
|
|
|
for part in parts]
|
|
|
|
|
|
|
|
cols = ["%s (%d)" % ("Avg", avg_hitbox)] + cols
|
|
|
|
|
|
|
|
print " | ".join(cols)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_sorted_damage(names, damage_map_base, weapon_damage_map, parts):
|
|
|
|
|
|
|
|
def uniform_average(weapon):
|
|
|
|
|
|
|
|
return weapon_damage_map[weapon].averages["uniform"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
names_sorted = list(names)
|
|
|
|
|
|
|
|
names_sorted.sort(key=uniform_average, reverse=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_print_headers(parts, damage_map_base)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#print
|
|
|
|
|
|
|
|
#print " | ".join(["%-15s" % "Avg"] + parts)
|
|
|
|
|
|
|
|
#print " | ".join([" "] + [str(damage_map_base[part].hitbox)
|
|
|
|
|
|
|
|
# for part in parts])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for name in names_sorted:
|
|
|
|
|
|
|
|
print "%-20s:" % name,
|
|
|
|
|
|
|
|
damage_map = weapon_damage_map[name]
|
|
|
|
|
|
|
|
print "%0.2f" % damage_map.averages["uniform"],
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
|
|
|
|
part_damage = damage_map[part]
|
|
|
|
|
|
|
|
print "%0.2f" % part_damage.total,
|
|
|
|
|
|
|
|
print
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_damage_percent_diff(names, damage_map_base, weapon_damage_map, parts):
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
|
|
|
|
tdiffs = [percent_change(
|
|
|
|
|
|
|
|
damage_map_base[part].total,
|
|
|
|
|
|
|
|
weapon_damage_map[w][part].total
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
for w in names[1:]]
|
|
|
|
|
|
|
|
ediffs = [percent_change(
|
|
|
|
|
|
|
|
damage_map_base[part].element,
|
|
|
|
|
|
|
|
weapon_damage_map[w][part].element
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
for w in names[1:]]
|
|
|
|
|
|
|
|
bdiffs = [percent_change(
|
|
|
|
|
|
|
|
damage_map_base[part].break_diff(),
|
|
|
|
|
|
|
|
weapon_damage_map[w][part].break_diff()
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
damage = damage_map_base[part]
|
|
|
|
|
|
|
|
print "%22s%s h%02d %0.2f (%s) h%02d %0.2f (%s) %+0.2f (%s)" \
|
|
|
|
|
|
|
|
% (part, "*" if damage.is_breakable() else " ",
|
|
|
|
|
|
|
|
damage.hitbox,
|
|
|
|
|
|
|
|
damage.total,
|
|
|
|
|
|
|
|
tdiff_s,
|
|
|
|
|
|
|
|
damage.ehitbox,
|
|
|
|
|
|
|
|
damage.element,
|
|
|
|
|
|
|
|
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 " --------------------"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for avg_type in "uniform raw weakpart_raw element weakpart_element break_raw break_element break_only".split():
|
|
|
|
|
|
|
|
base = damage_map_base.averages[avg_type]
|
|
|
|
|
|
|
|
diffs = [percent_change(
|
|
|
|
|
|
|
|
base,
|
|
|
|
|
|
|
|
weapon_damage_map[w].averages[avg_type]
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
for w in names[1:]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
diff_s = ",".join("%+0.1f%%" % i for i in diffs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print "%22s %0.2f (%s)" % (avg_type, base, diff_s)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if __name__ == '__main__':
|
|
|
|
args = parse_args(None)
|
|
|
|
args = parse_args(None)
|
|
|
|
|
|
|
|
|
|
|
|
@ -117,20 +244,27 @@ if __name__ == '__main__':
|
|
|
|
|
|
|
|
|
|
|
|
weapons = []
|
|
|
|
weapons = []
|
|
|
|
weapon_type = None
|
|
|
|
weapon_type = None
|
|
|
|
|
|
|
|
names_set = set()
|
|
|
|
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)
|
|
|
|
|
|
|
|
names_set.add(name)
|
|
|
|
weapons.append(weapon)
|
|
|
|
weapons.append(weapon)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
for w in match_weapons:
|
|
|
|
|
|
|
|
# skip weapons already explicitly names in arg list.
|
|
|
|
|
|
|
|
# Especially useful in diff mode.
|
|
|
|
|
|
|
|
if w.name in names_set:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
weapons.append(w)
|
|
|
|
|
|
|
|
|
|
|
|
if not weapons:
|
|
|
|
if not weapons:
|
|
|
|
print "Err: no matching weapons"
|
|
|
|
print "Err: no matching weapons"
|
|
|
|
sys.exit(1)
|
|
|
|
sys.exit(1)
|
|
|
|
@ -139,6 +273,9 @@ if __name__ == '__main__':
|
|
|
|
|
|
|
|
|
|
|
|
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"]
|
|
|
|
|
|
|
|
if args.phial and weapon_type != "Charge Blade":
|
|
|
|
|
|
|
|
print "ERROR: phial option is only supported for Charge Blade"
|
|
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
motion = motiondb[weapon_type].average
|
|
|
|
motion = motiondb[weapon_type].average
|
|
|
|
print "Weapon Type: %s" % weapon_type
|
|
|
|
print "Weapon Type: %s" % weapon_type
|
|
|
|
print "Average Motion: %0.1f" % motion
|
|
|
|
print "Average Motion: %0.1f" % motion
|
|
|
|
@ -171,7 +308,8 @@ if __name__ == '__main__':
|
|
|
|
element_skill=args.element_up,
|
|
|
|
element_skill=args.element_up,
|
|
|
|
awaken=args.awaken,
|
|
|
|
awaken=args.awaken,
|
|
|
|
artillery_level=args.artillery,
|
|
|
|
artillery_level=args.artillery,
|
|
|
|
limit_parts=args.parts)
|
|
|
|
limit_parts=args.parts,
|
|
|
|
|
|
|
|
frenzy_bonus=args.frenzy)
|
|
|
|
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:
|
|
|
|
if wd.etype2:
|
|
|
|
@ -185,62 +323,20 @@ if __name__ == '__main__':
|
|
|
|
print str(e)
|
|
|
|
print str(e)
|
|
|
|
sys.exit(1)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
damage_map_base = weapon_damage_map[weapons[0].name]
|
|
|
|
damage_map_base = weapon_damage_map[names[0]]
|
|
|
|
|
|
|
|
|
|
|
|
if limit_parts:
|
|
|
|
if limit_parts:
|
|
|
|
parts = limit_parts
|
|
|
|
parts = limit_parts
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
parts = damage_map_base.parts
|
|
|
|
parts = damage_map_base.parts
|
|
|
|
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
if args.diff:
|
|
|
|
tdiffs = [percent_change(
|
|
|
|
print_damage_percent_diff(names, damage_map_base,
|
|
|
|
damage_map_base[part].total,
|
|
|
|
weapon_damage_map, parts)
|
|
|
|
weapon_damage_map[w][part].total
|
|
|
|
elif args.phial:
|
|
|
|
)
|
|
|
|
print_sorted_phial_damage(names, damage_map_base,
|
|
|
|
for w in names[1:]]
|
|
|
|
weapon_damage_map, parts,
|
|
|
|
ediffs = [percent_change(
|
|
|
|
level=args.phial)
|
|
|
|
damage_map_base[part].element,
|
|
|
|
else:
|
|
|
|
weapon_damage_map[w][part].element
|
|
|
|
print_sorted_damage(names, damage_map_base,
|
|
|
|
)
|
|
|
|
weapon_damage_map, parts)
|
|
|
|
for w in names[1:]]
|
|
|
|
|
|
|
|
bdiffs = [percent_change(
|
|
|
|
|
|
|
|
damage_map_base[part].break_diff(),
|
|
|
|
|
|
|
|
weapon_damage_map[w][part].break_diff()
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
damage = damage_map_base[part]
|
|
|
|
|
|
|
|
print "%22s%s h%02d %0.2f (%s) h%02d %0.2f (%s) %+0.2f (%s)" \
|
|
|
|
|
|
|
|
% (part, "*" if damage.is_breakable() else " ",
|
|
|
|
|
|
|
|
damage.hitbox,
|
|
|
|
|
|
|
|
damage.total,
|
|
|
|
|
|
|
|
tdiff_s,
|
|
|
|
|
|
|
|
damage.ehitbox,
|
|
|
|
|
|
|
|
damage.element,
|
|
|
|
|
|
|
|
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 " --------------------"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for avg_type in "uniform raw weakpart_raw element weakpart_element break_raw break_element break_only".split():
|
|
|
|
|
|
|
|
base = damage_map_base.averages[avg_type]
|
|
|
|
|
|
|
|
diffs = [percent_change(
|
|
|
|
|
|
|
|
base,
|
|
|
|
|
|
|
|
weapon_damage_map[w].averages[avg_type]
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
for w in names[1:]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
diff_s = ",".join("%+0.1f%%" % i for i in diffs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print "%22s %0.2f (%s)" % (avg_type, base, diff_s)
|
|
|
|
|
|
|
|
|