add top two weapon comparison based on ratio

This commit is contained in:
Bryce Allen
2016-08-20 10:01:16 -05:00
parent 3a2eba00e7
commit 88ff0d15be
2 changed files with 92 additions and 6 deletions

View File

@@ -186,6 +186,9 @@ def parse_args(argv):
parser.add_argument("-p", "--parts",
help="Limit analysis to specified parts"
+" (comma separated list)")
parser.add_argument("-o", "--motion", type=int,
help="Use specified motion value instead of weapon "
+"average")
parser.add_argument("-l", "--phial",
help="Show CB phial damage at the sepcified level"
+" (1, 2, 3, 5=ultra) instead of normal motion"
@@ -290,6 +293,24 @@ def print_sorted_damage(names, damage_map_base, weapon_damage_map, parts):
print "% 2d" % part_damage.average(),
print
if len(names) > 1:
w1 = weapon_damage_map[names_sorted[0]]
w2 = weapon_damage_map[names_sorted[1]]
m, ratio = w1.compare_break_even(w2)
print
print "Comparison of '%s' and '%s'" % (
names_sorted[0], names_sorted[1])
print "Hitbox ratio:", m, "%0.2f" % ratio
for line in w1.get_raw_element_ratios():
line = list(line)
if m*line[3] > m*ratio:
line.append(names_sorted[0])
else:
line.append(names_sorted[1])
# (part, raw, element, ratio)
print "%-22s %02d %02d %0.2f %s" % tuple(line)
def print_damage_percent_diff(names, damage_map_base, weapon_damage_map, parts):
for part in parts:
@@ -432,6 +453,9 @@ def main():
motion = motiondb[weapon_type].average
print "Weapon Type: %s" % weapon_type
print "Average Motion: %0.1f" % motion
if args.motion:
motion = args.motion
print "Specified Motion: %0.1f" % motion
print "Monster Breaks: %s" % ", ".join(monster_breaks)
skill_names = get_skill_names(args)
print "Common Skills:", ", ".join(skill for skill in skill_names if skill)

View File

@@ -21,11 +21,19 @@ def raw_damage(true_raw, sharpness, affinity, monster_hitbox, motion):
Calculate raw damage to a monster part with the given true raw,
sharpness, monster raw weakness, and weapon motion value.
"""
return floor(true_raw
return floor(raw_damage_nohitbox(true_raw, sharpness, affinity, motion)
* monster_hitbox / 100.0)
def raw_damage_nohitbox(true_raw, sharpness, affinity, motion):
"""
Calculate raw damage to a monster part with the given true raw,
sharpness, monster raw weakness, and weapon motion value.
"""
return (true_raw
* SharpnessLevel.raw_modifier(sharpness)
* (1 + (affinity / 400.0))
* motion / 100.0
* monster_hitbox / 100.0)
* motion / 100.0)
def element_damage(raw_element, sharpness, monster_ehitbox):
@@ -34,11 +42,19 @@ def element_damage(raw_element, sharpness, monster_ehitbox):
attack, the given sharpness, and the given monster elemental weakness.
Note that this is independent of the motion value of the attack.
"""
return floor(raw_element
* SharpnessLevel.element_modifier(sharpness)
return floor(element_damage_nohitbox(raw_element, sharpness)
* monster_ehitbox / 100.0)
def element_damage_nohitbox(raw_element, sharpness):
"""
Calculate elemental damage to a monster part with the given elemental
attack, the given sharpness, and the given monster elemental weakness.
Note that this is independent of the motion value of the attack.
"""
return (raw_element * SharpnessLevel.element_modifier(sharpness))
class MotionType(object):
CUT = "cut"
IMPACT = "impact"
@@ -506,6 +522,52 @@ class WeaponMonsterDamage(object):
average += damage.total
return average / self.break_count
def compare_break_even(self, other_wd, motion=None):
"""
Compare with another weapon damage, to determine the break even
point of the raw/element hitbox. Assumes same element.
Returns (m, ratio), where ratio is the break even for the ratio of
raw hitbox to element hitbox. If m is 1, then self is better
when the ratio is larger (favors raw). If m is -1, then self is
better when the ratio is smaller (favors element).
"""
r1, e1 = self.nohitbox_damage(motion)
r2, e2 = other_wd.nohitbox_damage(motion)
#print r1, e1
#print r2, e2
rdiff = r1 - r2
ediff = e2 - e1
m = 1
if rdiff < 0:
m = -1
return m, (float(ediff) / rdiff)
def get_raw_element_ratios(self):
# TODO: better MIXED handling
if self.damage_type in (WeaponType.CUT, WeaponType.MIXED):
raw_type = "cut"
else:
raw_type = "impact"
hitboxes = []
for row in self.monster_damage._rows:
part = row["body_part"]
hitbox = int(row[raw_type])
ehitbox = int(row[str(self.etype.lower())])
hitboxes.append((part, hitbox, ehitbox, float(hitbox) / ehitbox))
return hitboxes
def nohitbox_damage(self, motion=None):
"""
Note: uses first element only, so not good for dual element DB.
"""
if motion is None:
motion = self.motion
raw = raw_damage_nohitbox(self.true_raw, self.sharpness,
self.affinity, motion)
element = element_damage_nohitbox(self.eattack, self.sharpness)
return (raw, element)
def __getitem__(self, key):
return self.damage_map[key]