break improvements
This commit is contained in:
@@ -43,6 +43,7 @@ def monster_json(db, path):
|
|||||||
m.update_indexes(indexes)
|
m.update_indexes(indexes)
|
||||||
data = m.as_data()
|
data = m.as_data()
|
||||||
damage = db.get_monster_damage(m.id)
|
damage = db.get_monster_damage(m.id)
|
||||||
|
damage.set_breakable(db.get_monster_breaks(m.id))
|
||||||
data["damage"] = damage.as_data()
|
data["damage"] = damage.as_data()
|
||||||
with open(monster_path, "w") as f:
|
with open(monster_path, "w") as f:
|
||||||
json.dump(data, f, cls=model.ModelJSONEncoder, indent=2)
|
json.dump(data, f, cls=model.ModelJSONEncoder, indent=2)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import difflib
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from mhapi import skills
|
from mhapi import skills
|
||||||
from mhapi.model import SharpnessLevel
|
from mhapi.model import SharpnessLevel, _break_find
|
||||||
|
|
||||||
|
|
||||||
WEAKPART_WEIGHT = 0.5
|
WEAKPART_WEIGHT = 0.5
|
||||||
@@ -160,7 +160,7 @@ class WeaponMonsterDamage(object):
|
|||||||
Class for calculating how much damage a weapon does to a monster.
|
Class for calculating how much damage a weapon does to a monster.
|
||||||
Does not include overall monster defense.
|
Does not include overall monster defense.
|
||||||
"""
|
"""
|
||||||
def __init__(self, weapon_row, monster_row, monster_damage_rows, motion,
|
def __init__(self, weapon_row, monster_row, monster_damage, motion,
|
||||||
sharp_plus=False, breakable_parts=None,
|
sharp_plus=False, breakable_parts=None,
|
||||||
attack_skill=skills.AttackUp.NONE,
|
attack_skill=skills.AttackUp.NONE,
|
||||||
critical_eye_skill=skills.CriticalEye.NONE,
|
critical_eye_skill=skills.CriticalEye.NONE,
|
||||||
@@ -168,7 +168,7 @@ class WeaponMonsterDamage(object):
|
|||||||
awaken=False):
|
awaken=False):
|
||||||
self.weapon = weapon_row
|
self.weapon = weapon_row
|
||||||
self.monster = monster_row
|
self.monster = monster_row
|
||||||
self.monster_damage = monster_damage_rows
|
self.monster_damage = monster_damage
|
||||||
self.motion = motion
|
self.motion = motion
|
||||||
self.sharp_plus = sharp_plus
|
self.sharp_plus = sharp_plus
|
||||||
self.breakable_parts = breakable_parts
|
self.breakable_parts = breakable_parts
|
||||||
@@ -259,7 +259,8 @@ class WeaponMonsterDamage(object):
|
|||||||
part_damage.part = part
|
part_damage.part = part
|
||||||
if alt is None:
|
if alt is None:
|
||||||
if (self.breakable_parts
|
if (self.breakable_parts
|
||||||
and _part_find(part, self.breakable_parts)):
|
and _break_find(part, self.monster_damage.parts.keys(),
|
||||||
|
self.breakable_parts)):
|
||||||
part_damage.breakable = True
|
part_damage.breakable = True
|
||||||
if hitbox > self.max_raw_part[1]:
|
if hitbox > self.max_raw_part[1]:
|
||||||
self.max_raw_part = (part, hitbox)
|
self.max_raw_part = (part, hitbox)
|
||||||
@@ -505,26 +506,6 @@ class PartDamage(object):
|
|||||||
hitbox, ehitbox, state)
|
hitbox, ehitbox, state)
|
||||||
|
|
||||||
|
|
||||||
def _part_find(part, breaks):
|
|
||||||
if (part == "Wing" and "Wing" not in breaks
|
|
||||||
and "Talon" in breaks):
|
|
||||||
# for Teostra
|
|
||||||
return "Talon"
|
|
||||||
if (part == "Head" and "Head" not in breaks
|
|
||||||
and "Horn" in breaks):
|
|
||||||
# for Fatalis
|
|
||||||
return "Horn"
|
|
||||||
if (part == "Winglegs" and "Winglegs" not in breaks
|
|
||||||
and "Wing Leg" in breaks):
|
|
||||||
# for Gore
|
|
||||||
return "Wing Leg"
|
|
||||||
#print "part_find", part, breaks
|
|
||||||
matches = difflib.get_close_matches(part, breaks, 1, 0.8)
|
|
||||||
if matches:
|
|
||||||
return matches[0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def element_attack_up(value):
|
def element_attack_up(value):
|
||||||
return value * 1.1
|
return value * 1.1
|
||||||
|
|
||||||
|
|||||||
@@ -309,9 +309,14 @@ class MHDB(object):
|
|||||||
List of strings.
|
List of strings.
|
||||||
"""
|
"""
|
||||||
def model(row):
|
def model(row):
|
||||||
return row["condition"][len("Break "):]
|
condition = row["condition"]
|
||||||
|
if condition == "Tail Carve":
|
||||||
|
return "Tail"
|
||||||
|
else:
|
||||||
|
return condition[len("Break "):]
|
||||||
|
|
||||||
return self._query_all("monster_breaks", """
|
return self._query_all("monster_breaks", """
|
||||||
SELECT DISTINCT condition FROM hunting_rewards
|
SELECT DISTINCT condition FROM hunting_rewards
|
||||||
WHERE monster_id=? AND condition LIKE 'Break %'
|
WHERE monster_id=?
|
||||||
|
AND (condition LIKE 'Break %' OR condition = 'Tail Carve')
|
||||||
""", (monster_id,), model_cls=model)
|
""", (monster_id,), model_cls=model)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import json
|
|||||||
import urllib
|
import urllib
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import re
|
import re
|
||||||
|
import difflib
|
||||||
|
|
||||||
from mhapi.util import EnumBase
|
from mhapi.util import EnumBase
|
||||||
|
|
||||||
@@ -242,6 +243,11 @@ class MonsterPartStateDamage(RowModel):
|
|||||||
self._data["part"] = part
|
self._data["part"] = part
|
||||||
self._data["state"] = state
|
self._data["state"] = state
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
for col in "impact cut shot ko ice dragon water fire thunder".split():
|
||||||
|
if self[col] != other[col]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class MonsterPartDamage(ModelBase):
|
class MonsterPartDamage(ModelBase):
|
||||||
"""
|
"""
|
||||||
@@ -250,14 +256,30 @@ class MonsterPartDamage(ModelBase):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, part):
|
def __init__(self, part):
|
||||||
self.part = part
|
self.part = part
|
||||||
|
self.breakable = False
|
||||||
self.states = {}
|
self.states = {}
|
||||||
|
|
||||||
def add_state(self, state, damage_row):
|
def add_state(self, state, damage_row):
|
||||||
self.states[state] = MonsterPartStateDamage(self.part, state,
|
self.states[state] = MonsterPartStateDamage(self.part, state,
|
||||||
damage_row)
|
damage_row)
|
||||||
|
# TODO: what about state 'Without Hide' for S.Nerscylla, which
|
||||||
|
# appears like it might be the same as Break Part, or might
|
||||||
|
# affect across hitzones.
|
||||||
|
if state == "Break Part":
|
||||||
|
# the default damage should be sorted before the alternate
|
||||||
|
# state damage
|
||||||
|
assert "Default" in self.states
|
||||||
|
if self.states[state] != self.states["Default"]:
|
||||||
|
# if the damage is different for break state, the part
|
||||||
|
# must be breakable, even if we couldn't find a match
|
||||||
|
# when searching break rewards
|
||||||
|
self.breakable = True
|
||||||
|
|
||||||
def as_data(self):
|
def as_data(self):
|
||||||
return self.states
|
return dict(
|
||||||
|
breakable=self.breakable,
|
||||||
|
damage=self.states
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MonsterDamage(ModelBase):
|
class MonsterDamage(ModelBase):
|
||||||
@@ -270,8 +292,11 @@ class MonsterDamage(ModelBase):
|
|||||||
self.parts = {}
|
self.parts = {}
|
||||||
self.states = set()
|
self.states = set()
|
||||||
for row in damage_rows:
|
for row in damage_rows:
|
||||||
|
if row["cut"] == -1:
|
||||||
|
# -1 indicates missing data
|
||||||
|
continue
|
||||||
part = row["body_part"]
|
part = row["body_part"]
|
||||||
state = "Normal"
|
state = "Default"
|
||||||
m = re.match(r"([^(]+) \(([^)]+)\)", part)
|
m = re.match(r"([^(]+) \(([^)]+)\)", part)
|
||||||
if m:
|
if m:
|
||||||
part = m.group(1)
|
part = m.group(1)
|
||||||
@@ -286,3 +311,42 @@ class MonsterDamage(ModelBase):
|
|||||||
states=list(self.states),
|
states=list(self.states),
|
||||||
parts=self.parts
|
parts=self.parts
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_breakable(self, breakable_list):
|
||||||
|
"""
|
||||||
|
Set breakable flag on parts based on the breakable list from
|
||||||
|
rewards (use MHDB.get_monster_breaks).
|
||||||
|
"""
|
||||||
|
for name, part_damage in self.parts.iteritems():
|
||||||
|
if _break_find(name, self.parts, breakable_list):
|
||||||
|
part_damage.breakable = True
|
||||||
|
|
||||||
|
|
||||||
|
def _break_find(part, parts, breaks):
|
||||||
|
# favor 'Tail Tip' over Tail for Basarios
|
||||||
|
if part == "Tail" and "Tail Tip" in parts:
|
||||||
|
return None
|
||||||
|
if part == "Tail Tip" and "Tail" in breaks:
|
||||||
|
return "Tail"
|
||||||
|
if part == "Neck/Tail" and "Tail" in breaks:
|
||||||
|
return "Tail"
|
||||||
|
if part == "Wing" and "Wing" not in breaks:
|
||||||
|
if "Talon" in breaks and "Talon" not in parts:
|
||||||
|
# for Teostra
|
||||||
|
return "Talon"
|
||||||
|
if part == "Head" and "Head" not in breaks:
|
||||||
|
if "Horn" in breaks and "Horn" not in parts:
|
||||||
|
# for Fatalis
|
||||||
|
return "Horn"
|
||||||
|
if "Ear" in breaks and "Ear" not in parts:
|
||||||
|
# Kecha Wacha
|
||||||
|
return "Ear"
|
||||||
|
if part == "Winglegs" and "Winglegs" not in breaks:
|
||||||
|
if "Wing Leg" in breaks and "Wing Leg" not in parts:
|
||||||
|
# for Gore
|
||||||
|
return "Wing Leg"
|
||||||
|
#print "part_find", part, breaks
|
||||||
|
matches = difflib.get_close_matches(part, breaks, 1, 0.8)
|
||||||
|
if matches:
|
||||||
|
return matches[0]
|
||||||
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user