diff --git a/bin/mharmor.py b/bin/mharmor.py index 15facbc..6fd56e9 100755 --- a/bin/mharmor.py +++ b/bin/mharmor.py @@ -38,7 +38,7 @@ def parse_args(argv): def find_armors(args): - db = MHDB(_pathfix.db_path) + db = MHDB() skills = {} skill_ids = [] # preserve arg order @@ -113,7 +113,7 @@ def find_armors(args): if args.type and a.slot != args.type: continue total = skill_totals[a.id] - print a.id, skill_totals[a.id], a.one_line_u(), + print skill_totals[a.id], a.one_line_u(), if args.resist: print args.resist.title(), a[args.resist + "_res"] else: diff --git a/bin/mhdamage.py b/bin/mhdamage.py index 38bfeab..1531542 100755 --- a/bin/mhdamage.py +++ b/bin/mhdamage.py @@ -9,7 +9,7 @@ import _pathfix from mhapi.db import MHDB, MHDBX from mhapi.damage import MotionValueDB, WeaponMonsterDamage -from mhapi.model import SharpnessLevel, Weapon +from mhapi.model import SharpnessLevel, Weapon, ItemStars from mhapi import skills from mhapi.util import ELEMENTS, WEAPON_TYPES, WTYPE_ABBR @@ -30,6 +30,25 @@ def weapon_match_tuple(arg): return (wtype, element) +ANY = object() +def parse_stars(arg): + if arg is None: + return None + arg = arg.lower() + if arg in ("*", "any"): + return ANY + if arg in ("none", ""): + return None + return int(arg) + + +def quest_level_tuple(arg): + parts = arg.split(",") + while len(parts) < 4: + parts.append(None) + return [parse_stars(p) for p in parts] + + def _make_db_sharpness_string(level_string): #print "level string", level_string level_value = SharpnessLevel.__dict__[level_string.upper()] @@ -199,6 +218,9 @@ def parse_args(argv): +" Examples: 'DinoSnS,SnS,190,0,Blue,Fire,30'" +" 'AkantorHam,Hammer,240,25,Green'", type=weapon_stats_tuple, default=[]) + parser.add_argument("-q", "--quest-level", + help="village,guild[,permit[,arena]]", + type=quest_level_tuple) parser.add_argument("monster", help="Full name of monster") parser.add_argument("weapon", nargs="*", @@ -324,7 +346,20 @@ def print_damage_percent_diff(names, damage_map_base, weapon_damage_map, parts): print "%22s %0.2f (%s)" % (avg_type, base, diff_s) -if __name__ == '__main__': +def match_quest_level(match_level, weapon_level): + #print match_level, weapon_level + if match_level is ANY: + return True + if match_level is None: + if weapon_level is not None: + return False + return True + if weapon_level is None or weapon_level > match_level: + return False + return True + + +def main(): args = parse_args(None) game_uses_true_raw = False @@ -332,7 +367,11 @@ if __name__ == '__main__': db = MHDBX() game_uses_true_raw = True elif args.monster_hunter_gen: - db = MHDB(game="gen") + if args.quest_level: + comps = True + else: + comps = False + db = MHDB(game="gen", include_item_components=comps) game_uses_true_raw = True else: db = MHDB(game="4u") @@ -362,8 +401,12 @@ if __name__ == '__main__': for match_tuple in args.match: # TODO: better validation wtype, element = match_tuple + if args.quest_level: + final=None + else: + final=1 match_weapons = db.get_weapons_by_query(wtype=wtype, element=element, - final=1) + final=final) for w in match_weapons: # skip weapons already explicitly names in arg list. # Especially useful in diff mode. @@ -398,12 +441,34 @@ if __name__ == '__main__': else: limit_parts = None + if args.quest_level: + village, guild, permit, arena = args.quest_level + print "Filter by Quest Levels:", args.quest_level + weapons2 = dict() + for w in weapons: + if (not match_quest_level(village, w["village_stars"]) + and not match_quest_level(guild, w["guild_stars"])): + continue + if not match_quest_level(permit, w["permit_stars"]): + continue + if not match_quest_level(arena, w["arena_stars"]): + continue + weapons2[w.id] = w + parent_ids = set(w.parent_id for w in weapons2.values()) + for wid in weapons2.keys(): + if wid in parent_ids: + del weapons2[wid] + weapons = weapons2.values() + names = [w.name for w in weapons] + weapon_damage_map = dict() for row in weapons: name = row["name"] row_type = row["wtype"] if row_type != weapon_type: - raise ValueError("Weapon '%s' is different type" % name) + raise ValueError( + "Weapon '%s' is different type, got '%s' expected '%s'" + % (name, row_type, weapon_type)) try: skill_args = skill_args_map.get(name, args) wd = WeaponMonsterDamage(row, @@ -456,3 +521,6 @@ if __name__ == '__main__': print_sorted_damage(names, damage_map_base, weapon_damage_map, parts) + +if __name__ == '__main__': + main() diff --git a/db/mhgen.db b/db/mhgen.db index 158d361..f2f287d 100644 Binary files a/db/mhgen.db and b/db/mhgen.db differ diff --git a/mhapi/damage.py b/mhapi/damage.py index 9fb27c5..9b7875e 100644 --- a/mhapi/damage.py +++ b/mhapi/damage.py @@ -214,7 +214,7 @@ class WeaponMonsterDamage(object): self.sharpness = self.weapon.sharpness.max #print "sharpness=", self.sharpness if self.weapon["affinity"]: - if (isinstance(self.weapon["affinity"], str) + if (isinstance(self.weapon["affinity"], basestring) and "/" in self.weapon["affinity"]): self.chaotic = True # Handle chaotic gore affinity, e.g. -35/10. This means that diff --git a/mhapi/db.py b/mhapi/db.py index d38ae6c..d7c6ac1 100644 --- a/mhapi/db.py +++ b/mhapi/db.py @@ -25,6 +25,13 @@ def _db_path(game=None): return os.path.join(project_path, "db", "mh%s.db" % game) +ARMOR_HUNTER_TYPES = { + "Blade": 0, + "Gunner": 1, + "Both": 2, +} + + class MHDB(object): """ Wrapper around the Android App sqlite3 db. The following conventions @@ -38,8 +45,7 @@ class MHDB(object): """ # buy and sell are empty, uses weapon.create_cost and upgrade_cost _weapon_select = """ - SELECT items._id, items.type, items.name, - items.rarity, weapons.* + SELECT items.*, weapons.* FROM weapons LEFT JOIN items ON weapons._id = items._id """ @@ -74,6 +80,16 @@ class MHDB(object): game = os.environ.get("MHAPI_GAME") assert game in ("4u", "gen") self.game = game + + if game == "4u": + # filter out non-localized DLC + self._weapon_select = (MHDB._weapon_select + + "WHERE items.name != items.name_jp\n") + else: + # no filter needed, but having where in all cases simplifies + # queries below + self._weapon_select = (MHDB._weapon_select + + "WHERE 1=1\n") if path is None: path = _db_path(game) self.conn = sqlite3.connect(path) @@ -341,7 +357,7 @@ class MHDB(object): def get_weapons(self): # Note: weapons only available via JP DLC have no localized # name, filter them out. - q = MHDB._weapon_select + q = self._weapon_select return self._query_all("weapons", q, model_cls=model.Weapon) def get_weapons_by_query(self, wtype=None, element=None, @@ -353,7 +369,7 @@ class MHDB(object): @final should be string '1' or '0' """ - q = MHDB._weapon_select + q = self._weapon_select where = [] args = [] if wtype is not None: @@ -369,24 +385,24 @@ class MHDB(object): where.append("final = ?") args.append(final) if where: - q += "WHERE " + "\nAND ".join(where) + q += "AND " + "\nAND ".join(where) results = self._query_all("weapons", q, tuple(args), model_cls=model.Weapon) return results def get_weapon(self, weapon_id): - return self._query_one("weapon", MHDB._weapon_select + """ - WHERE weapons._id=? + return self._query_one("weapon", self._weapon_select + """ + AND weapons._id=? """, (weapon_id,), model_cls=model.Weapon) def get_weapon_by_name(self, name): - return self._query_one("weapon", MHDB._weapon_select + """ - WHERE items.name=? + return self._query_one("weapon", self._weapon_select + """ + AND items.name=? """, (name,), model_cls=model.Weapon) def get_weapons_by_parent(self, parent_id): - return self._query_all("weapon_by_parent", MHDB._weapon_select + """ - WHERE weapons.parent_id=? + return self._query_all("weapon_by_parent", self._weapon_select + """ + AND weapons.parent_id=? """, (parent_id,), model_cls=model.Weapon) def get_armors(self): @@ -467,7 +483,11 @@ class MHDB(object): def get_armors_by_skills(self, skill_tree_ids, hunter_type): args = sorted(skill_tree_ids) placeholders = ", ".join(["?"] * len(skill_tree_ids)) - args += [hunter_type] + both_type = "Both" + if self.game == "gen": + both_type = ARMOR_HUNTER_TYPES[both_type] + hunter_type = ARMOR_HUNTER_TYPES[hunter_type] + args += [both_type, hunter_type] return self._query_all("decorations", """ SELECT items._id, items.type, items.name, items.rarity, items.buy, armor.* @@ -479,7 +499,7 @@ class MHDB(object): WHERE items.type = 'Armor' AND item_to_skill_tree.skill_tree_id IN (%s) AND item_to_skill_tree.point_value > 0 - AND armor.hunter_type IN ('Both', ?) + AND armor.hunter_type IN (?, ?) GROUP BY item_to_skill_tree.item_id """ % placeholders, tuple(args), model_cls=model.Armor) diff --git a/mhapi/model.py b/mhapi/model.py index db9fcd6..099954b 100644 --- a/mhapi/model.py +++ b/mhapi/model.py @@ -85,7 +85,7 @@ class RowModel(ModelBase): data[key_value].append(item) def __str__(self): - if "name" in self._data: + if "name" in self._data and self.name is not None: name = urllib.quote(self.name, safe=" ") else: name = str(self.id)