def merge_weapons(): inc_data = requests.get("https://mhw-db.com/weapons").json() data = load_data().weapon_map not_exist = [] mismatches_atk = [] mismatches_def = [] mismatches_other = [] def print_all(items): for item in items: print(item) print() for weapon_inc in inc_data: inc_id = weapon_inc['id'] inc_type = weapon_inc['type'] name = weapon_inc['name'] inc_label = f"{name} ({inc_type})" # Our system uses I/II/III, their's uses 1/2/3 if name not in data.names('en'): name = name.replace(" 3", " III") name = name.replace(" 2", " II") name = name.replace(" 1", " I") if name not in data.names('en'): not_exist.append(f"{name} does not exist ({inc_type} {inc_id}).") continue # todo: add to our database existing = data.entry_of('en', name) # Incoming basic data for the weapon entry inc_attack = weapon_inc['attack']['display'] inc_defense = weapon_inc['attributes'].get('defense', 0) inc_phial = weapon_inc['attributes'].get('phialType', None) inc_phial_power = None inc_kinsect = weapon_inc['attributes'].get('boostType', None) inc_affinity = weapon_inc['attributes'].get('affinity', 0) # Ensure minimum of 3 slots (avoid out of bounds) weapon_inc['slots'] += [{'rank':0}] * 3 inc_slot1 = weapon_inc['slots'][0]['rank'] inc_slot2 = weapon_inc['slots'][1]['rank'] inc_slot3 = weapon_inc['slots'][2]['rank'] # If there are two values and the second is a number, populate the phial power if inc_phial and ' ' in inc_phial: values = inc_phial.split(' ') if len(values) == 2 and values[1].isdigit(): inc_phial = values[0] inc_phial_power = int(values[1]) inc_shelling_type = None inc_shelling_level = None if 'shellingType' in weapon_inc['attributes']: (left, right) = weapon_inc['attributes']['shellingType'].split(' ') inc_shelling_type = left.lower() inc_shelling_level = int(right.lower().replace('lv', '')) # Simple validation comparisons if existing['attack'] != inc_attack: mismatches_atk.append(f"WARNING: {inc_label} has mismatching attack " + f"(internal {existing['attack']} | external {inc_attack} | ext id {inc_id})") if (existing['defense'] or 0) != inc_defense: mismatches_def.append(f"WARNING: {inc_label} has mismatching defense " + f"(internal {existing['defense']} | external {inc_defense} | ext id {inc_id})") if existing['kinsect_bonus'] and existing['kinsect_bonus'] != inc_kinsect: mismatches_other.append(f"Warning: {inc_label} has mismatching kinsect bonus") if existing['phial'] and existing['phial'] != inc_phial: mismatches_other.append(f"WARNING: {inc_label} has mismatching phial") if existing['phial_power'] and existing['phial_power'] != inc_phial_power: mismatches_other.append(f"WARNING: {inc_label} has mismatching phial power") if existing['shelling'] and existing['shelling'] != inc_shelling_type: mismatches_other.append(f"Warning: {inc_label} has mismatching shell type") if existing['shelling_level'] and existing['shelling_level'] != inc_shelling_level: mismatches_other.append(f"Warning: {inc_label} has mismatching shell level") def copy_maybe(field_name, value): "Inner function to copy a value if no value exists and there is a new val" if not existing[field_name] and value: existing[field_name] = value def copy_with_warning(field_name, value): if existing[field_name] != value: print(f"OVERRIDING: {inc_label} will get new {field_name}") existing[field_name] = value # Copy over new base data if there are new fields copy_maybe('kinsect_bonus', inc_kinsect) copy_maybe('phial', inc_phial) copy_maybe('phial_power', inc_phial_power) copy_maybe('shelling', inc_shelling_type) copy_maybe('shelling_level', inc_shelling_level) copy_maybe('affinity', inc_affinity) # Copy over with warning. TODO: Add arg to require opt in to overwrite slots copy_with_warning('slot_1', inc_slot1) copy_with_warning('slot_2', inc_slot2) copy_with_warning('slot_3', inc_slot3) # Add sharpness data for anything that's missing sharpness data if 'durability' in weapon_inc and not existing.get('sharpness', None): inc_sharpness = weapon_inc['durability'][5] maxed = weapon_inc['durability'][0] == inc_sharpness existing['sharpness'] = { 'maxed': 'TRUE' if maxed else 'FALSE', 'red': inc_sharpness['red'], 'orange': inc_sharpness['orange'], 'yellow': inc_sharpness['yellow'], 'green': inc_sharpness['green'], 'blue': inc_sharpness['blue'], 'white': inc_sharpness['white'], 'purple': 0 } # print errors and warnings print_all(not_exist) print_all(mismatches_atk) print_all(mismatches_def) print_all(mismatches_other) weapon_base_schema = schema.WeaponBaseSchema() writer.save_base_map_csv('weapons/weapon_base_NEW.csv', data, schema=weapon_base_schema) writer.save_data_csv('weapons/weapon_sharpness_NEW.csv', data, key='sharpness')
def update_weapons(): mhdata = load_data() print("Existing Data loaded. Using to update weapon info") weapon_loader = WeaponDataLoader() item_text_handler = ItemTextHandler() skill_text_handler = SkillTextHandler() notes_data = load_schema(wep_wsl.WepWsl, "common/equip/wep_whistle.wep_wsl") sharpness_reader = SharpnessDataReader() ammo_reader = WeaponAmmoLoader() coating_data = load_schema(bbtbl.Bbtbl, "common/equip/bottle_table.bbtbl") print("Loaded initial weapon binary data data") def bind_weapon_blade_ext(weapon_type: str, existing_entry, binary: wp_dat.WpDatEntry): for key in [ 'kinsect_bonus', 'phial', 'phial_power', 'shelling', 'shelling_level', 'notes' ]: existing_entry[key] = None if weapon_type == cfg.CHARGE_BLADE: existing_entry['phial'] = cb_phials[binary.wep1_id] if weapon_type == cfg.SWITCH_AXE: (phial, power) = s_axe_phials[binary.wep1_id] existing_entry['phial'] = phial existing_entry['phial_power'] = power if weapon_type == cfg.GUNLANCE: # first 5 are normals, second 5 are wide, third 5 are long shelling = ['normal', 'wide', 'long'][binary.wep1_id // 5] level = (binary.wep1_id % 5) + 1 existing_entry['shelling'] = shelling existing_entry['shelling_level'] = level if weapon_type == cfg.INSECT_GLAIVE: existing_entry['kinsect_bonus'] = glaive_boosts[binary.wep1_id] if weapon_type == cfg.HUNTING_HORN: note_entry = notes_data[binary.wep1_id] notes = [note_entry.note1, note_entry.note2, note_entry.note3] notes = [str(note_colors[n]) for n in notes] existing_entry['notes'] = "".join(notes) # Store new weapon entries new_weapon_map = DataMap(languages="en", start_id=mhdata.weapon_map.max_id + 1) # Iterate over weapon types for weapon_type in cfg.weapon_types: print(f"Processing {weapon_type}") # Note: weapon data ordering is unknown. order field and tree_id asc are sometimes wrong # Therefore its unsorted, we have to work off the spreadsheet order weapon_tree = weapon_loader.load_tree(weapon_type) print(f"Loaded {weapon_type} weapon tree binary data") multiplier = cfg.weapon_multiplier[weapon_type] # Iterate over nodes in the weapon tree (does depth first search) for weapon_node in weapon_tree: binary = weapon_node.binary name = weapon_node.name existing_entry = mhdata.weapon_map.entry_of('en', name['en']) new_entry = {} if existing_entry: new_entry = {**existing_entry} # Bind name and parent new_entry['name'] = name new_entry['weapon_type'] = weapon_type new_entry['previous_en'] = None if weapon_node.parent != None: new_entry['previous_en'] = weapon_node.parent.name['en'] # Bind info new_entry['weapon_type'] = weapon_type new_entry['rarity'] = binary.rarity + 1 new_entry['attack'] = binary.raw_damage * multiplier new_entry['affinity'] = binary.affinity new_entry['defense'] = binary.defense or None new_entry['slot_1'] = binary.gem_slot1_lvl new_entry['slot_2'] = binary.gem_slot2_lvl new_entry['slot_3'] = binary.gem_slot3_lvl new_entry['elderseal'] = elderseal[binary.elderseal] # Bind Elements if name['en'] in ["Twin Nails", "Fire and Ice"]: print(f"Skipping {name['en']} element data") else: hidden = binary.hidden_element_id != 0 element_id = binary.hidden_element_id if hidden else binary.element_id element_atk = binary.hidden_element_damage if hidden else binary.element_damage new_entry['element_hidden'] = hidden new_entry['element1'] = elements[element_id] new_entry[ 'element1_attack'] = element_atk * 10 if element_atk else None new_entry['element2'] = None new_entry['element2_attack'] = None # Bind skill skill = skill_text_handler.get_skilltree_name(binary.skill_id) new_entry['skill'] = skill['en'] if binary.skill_id != 0 else None # Bind Extras (Blade/Gun/Bow data) if weapon_type in cfg.weapon_types_melee: bind_weapon_blade_ext(weapon_type, new_entry, binary) new_entry['sharpness'] = sharpness_reader.sharpness_for(binary) elif weapon_type in cfg.weapon_types_gun: (ammo_name, ammo_data) = ammo_reader.create_data_for( wtype=weapon_type, tree=weapon_node.tree, binary=weapon_node.binary) new_entry['ammo_config'] = ammo_name else: # TODO: Bows have an Enabled+ flag. Find out what it means # 1 = enabled, 2 = enabled+ coating_binary = coating_data[binary.special_ammo_type] new_entry['bow'] = { 'close': coating_binary.close_range > 0, 'power': coating_binary.power > 0, 'paralysis': coating_binary.paralysis > 0, 'poison': coating_binary.poison > 0, 'sleep': coating_binary.sleep > 0, 'blast': coating_binary.blast > 0 } # crafting data new_entry['craft'] = [] if weapon_node.craft: new_entry['craft'].append({ 'type': 'Create', **convert_recipe(item_text_handler, weapon_node.craft) }) if weapon_node.upgrade: new_entry['craft'].append({ 'type': 'Upgrade', **convert_recipe(item_text_handler, weapon_node.upgrade) }) new_weapon_map.insert(new_entry) # Write new data writer = create_writer() writer.save_base_map_csv( "weapons/weapon_base.csv", new_weapon_map, schema=schema.WeaponBaseSchema(), translation_filename="weapons/weapon_base_translations.csv") writer.save_data_csv("weapons/weapon_sharpness.csv", new_weapon_map, key="sharpness", schema=schema.WeaponSharpnessSchema()) writer.save_data_csv("weapons/weapon_bow_ext.csv", new_weapon_map, key="bow", schema=schema.WeaponBowSchema()) writer.save_data_csv("weapons/weapon_craft.csv", new_weapon_map, key="craft", schema=schema.WeaponCraftSchema()) writer.save_keymap_csv("weapons/weapon_ammo.csv", ammo_reader.data, schema=schema.WeaponAmmoSchema()) print("Weapon files updated\n") add_missing_items(item_text_handler.encountered, mhdata=mhdata)
def update_weapons(mhdata, item_updater: ItemUpdater): skill_text_handler = SkillTextHandler() print("Beginning load of binary weapon data") weapon_loader = WeaponDataLoader() notes_data = load_schema(wep_wsl.WepWsl, "common/equip/wep_whistle.wep_wsl") sharpness_reader = SharpnessDataReader() ammo_reader = WeaponAmmoLoader() coating_data = load_schema(bbtbl.Bbtbl, "common/equip/bottle_table.bbtbl") print("Loaded weapon binary data") def bind_weapon_blade_ext(weapon_type: str, existing_entry, weapon): binary: wp_dat.WpDatEntry = weapon.binary for key in ['kinsect_bonus', 'phial', 'phial_power', 'shelling', 'shelling_level', 'notes']: existing_entry[key] = None if weapon_type == cfg.CHARGE_BLADE: existing_entry['phial'] = cb_phials[binary.wep1_id] if weapon_type == cfg.SWITCH_AXE: try: (phial, power) = s_axe_phials[binary.wep1_id] existing_entry['phial'] = phial existing_entry['phial_power'] = power except: raise KeyError(f"Failed to load saxe phials for {weapon.name['en']} (SAXE ID: {binary.wep1_id})") if weapon_type == cfg.GUNLANCE: # first 5 are normals, second 5 are wide, third 5 are long if binary.wep1_id >= 15: value = binary.wep1_id - 15 shelling = ['normal', 'wide', 'long'][value % 3] level = value // 3 + 6 else: shelling = ['normal', 'wide', 'long'][binary.wep1_id // 5] level = (binary.wep1_id % 5) + 1 existing_entry['shelling'] = shelling existing_entry['shelling_level'] = level if weapon_type == cfg.INSECT_GLAIVE: try: existing_entry['kinsect_bonus'] = glaive_boosts[binary.wep1_id] except: raise KeyError(f"Failed to load kinsect bonus for {weapon.name['en']} (BOOST ID: {binary.wep1_id})") if weapon_type == cfg.HUNTING_HORN: note_entry = notes_data[binary.wep1_id] notes = [note_entry.note1, note_entry.note2, note_entry.note3] notes = [str(note_colors[n]) for n in notes] existing_entry['notes'] = "".join(notes) # Load weapon tree binary data weapon_trees = {} for weapon_type in cfg.weapon_types: weapon_tree = weapon_loader.load_tree(weapon_type) print(f"Loaded {weapon_type} weapon tree binary data") weapon_trees[weapon_type] = weapon_tree # Load Kulve Augment Data kulve_augments = weapon_loader.load_kulve_augments() artifacts.write_dicts_artifact("kulve_augments.csv", kulve_augments.flattened()) # Write artifact lines print("Writing artifact files for weapons (use it to add new weapons)") write_weapon_artifacts(mhdata, weapon_trees, ammo_reader) # Store new weapon entries new_weapon_map = DataMap(languages=["en"], start_id=mhdata.weapon_map.max_id+1, keys_ex=["weapon_type"]) # Iterate over existing weapons, merge new data in for existing_entry in mhdata.weapon_map.values(): weapon_type = existing_entry['weapon_type'] weapon_tree = weapon_trees[weapon_type] # Note: weapon data ordering is unknown. order field and tree_id asc are sometimes wrong # Therefore its unsorted, we have to work off the spreadsheet order multiplier = cfg.weapon_multiplier[weapon_type] weapon = weapon_tree.by_name(existing_entry.name('en')) if not weapon: print(f"Could not find binary entry for {existing_entry.name('en')}") new_weapon_map.insert(existing_entry) continue is_kulve = existing_entry['category'] == 'Kulve' is_special = existing_entry['category'] in ('Kulve', 'Safi') binary = weapon.binary name = weapon.name new_entry = { **existing_entry } # Bind name and parent new_entry['name'] = name new_entry['weapon_type'] = weapon_type new_entry['previous_en'] = None if weapon.parent != None: new_entry['previous_en'] = weapon.parent.name['en'] # Apply augmentation if its a kulve weapon that can get augmented if is_kulve: augment_params = kulve_augments.get(weapon_type, weapon.rarity) if augment_params: weapon = AugmentedWeapon(weapon, augment_params, 4) # Bind info new_entry['weapon_type'] = weapon_type new_entry['rarity'] = weapon.rarity new_entry['attack'] = (weapon.attack * multiplier).quantize(Decimal('1.'), rounding=ROUND_HALF_UP) new_entry['affinity'] = weapon.affinity new_entry['defense'] = weapon.defense or None new_entry['slot_1'] = binary.gem_slot1_lvl new_entry['slot_2'] = binary.gem_slot2_lvl new_entry['slot_3'] = binary.gem_slot3_lvl new_entry['elderseal'] = elderseal[binary.elderseal] # Bind Elements if name['en'] in ["Twin Nails", "Fire and Ice", "Blizzard and Blaze"]: print(f"Skipping {name['en']} element data") else: hidden = binary.hidden_element_id != 0 element_atk = weapon.element_value new_entry['element_hidden'] = hidden new_entry['element1'] = weapon.element_type new_entry['element1_attack'] = element_atk * 10 if element_atk else None new_entry['element2'] = None new_entry['element2_attack'] = None # Bind skill skill = skill_text_handler.get_skilltree_name(binary.skill_id) new_entry['skill'] = skill['en'] if binary.skill_id != 0 else None # Bind Extras (Blade/Gun/Bow data) if weapon_type in cfg.weapon_types_melee: bind_weapon_blade_ext(weapon_type, new_entry, weapon) new_entry['sharpness'] = sharpness_reader.sharpness_for(binary) elif weapon_type in cfg.weapon_types_gun: tree = weapon.tree if is_special: tree = existing_entry['category'] (ammo_name, ammo_data) = ammo_reader.create_data_for( wtype=weapon_type, tree=tree, binary=weapon.binary) new_entry['ammo_config'] = ammo_name else: # TODO: Bows have an Enabled+ flag. Find out what it means # 1 = enabled, 2 = enabled+ coating_binary = coating_data[binary.special_ammo_type] new_entry['bow'] = { 'close': coating_binary.close_range > 0, 'power': coating_binary.power > 0, 'paralysis': coating_binary.paralysis > 0, 'poison': coating_binary.poison > 0, 'sleep': coating_binary.sleep > 0, 'blast': coating_binary.blast > 0 } # crafting data new_entry['craft'] = [] if weapon.craft: new_entry['craft'].append({ 'type': 'Create', **convert_recipe(item_updater, weapon.craft) }) if weapon.upgrade: new_entry['craft'].append({ 'type': 'Upgrade', **convert_recipe(item_updater, weapon.upgrade) }) new_weapon_map.insert(new_entry) # Write new data writer = create_writer() writer.save_base_map_csv( "weapons/weapon_base.csv", new_weapon_map, schema=schema.WeaponBaseSchema(), translation_filename="weapons/weapon_base_translations.csv" ) writer.save_data_csv( "weapons/weapon_sharpness.csv", new_weapon_map, key="sharpness", schema=schema.WeaponSharpnessSchema() ) writer.save_data_csv( "weapons/weapon_bow_ext.csv", new_weapon_map, key="bow", schema=schema.WeaponBowSchema() ) writer.save_data_csv( "weapons/weapon_craft.csv", new_weapon_map, key="craft", schema=schema.WeaponRecipeSchema() ) writer.save_keymap_csv( "weapons/weapon_ammo.csv", ammo_reader.data, schema=schema.WeaponAmmoSchema() ) print("Weapon files updated\n")