diff --git a/public/game_files/horn_material.json b/public/game_files/horn_material.json new file mode 100644 index 0000000..02ca6e6 --- /dev/null +++ b/public/game_files/horn_material.json @@ -0,0 +1,172 @@ +{ + "Dm_Enemy_Bokoblin_Boss_Senior": "Item_Enemy_133", + "Dm_Enemy_Bokoblin_Junior": "Item_Enemy_77", + "Dm_Enemy_Bokoblin_Middle": "Item_Enemy_78", + "Dm_Enemy_Bokoblin_Senior": "Item_Enemy_79", + "Dm_Enemy_Zombie_Junior_Defense": "Item_Enemy_77", + "Enemy_Bokoblin_Armor_Dark": "Item_Enemy_80", + "Enemy_Bokoblin_Armor_Junior": "Item_Enemy_77", + "Enemy_Bokoblin_Armor_Middle": "Item_Enemy_78", + "Enemy_Bokoblin_Armor_Senior": "Item_Enemy_79", + "Enemy_Bokoblin_Bone_Junior": "Item_Enemy_77", + "Enemy_Bokoblin_Bone_Junior_AllDay": "Item_Enemy_77", + "Enemy_Bokoblin_Bone_Junior_AllDay_AlwaysRespawn": "Item_Enemy_77", + "Enemy_Bokoblin_Bone_Junior_Head": "Item_Enemy_77", + "Enemy_Bokoblin_Bone_Junior_Head_AllDay": "Item_Enemy_77", + "Enemy_Bokoblin_Boss_Dark": "Item_Enemy_134", + "Enemy_Bokoblin_Boss_Junior": "Item_Enemy_64", + "Enemy_Bokoblin_Boss_Middle": "Item_Enemy_132", + "Enemy_Bokoblin_Boss_Senior": "Item_Enemy_133", + "Enemy_Bokoblin_Boss_Senior_NoOrder": "Item_Enemy_133", + "Enemy_Bokoblin_Dark": "Item_Enemy_80", + "Enemy_Bokoblin_Guard_Junior": "Item_Enemy_77", + "Enemy_Bokoblin_Guard_Junior_Ambush": "Item_Enemy_77", + "Enemy_Bokoblin_Guard_Junior_Cliff": "Item_Enemy_77", + "Enemy_Bokoblin_Guard_Junior_Golem_Fort": "Item_Enemy_77", + "Enemy_Bokoblin_Guard_Junior_TreeHouseTop": "Item_Enemy_77", + "Enemy_Bokoblin_Guard_Middle": "Item_Enemy_78", + "Enemy_Bokoblin_Guard_Middle_Ambush": "Item_Enemy_78", + "Enemy_Bokoblin_Guard_Middle_Cliff": "Item_Enemy_78", + "Enemy_Bokoblin_Guard_Middle_TreeHouseTop": "Item_Enemy_78", + "Enemy_Bokoblin_Junior": "Item_Enemy_77", + "Enemy_Bokoblin_Middle": "Item_Enemy_78", + "Enemy_Bokoblin_NoSleep_Junior": "Item_Enemy_77", + "Enemy_Bokoblin_Senior": "Item_Enemy_79", + "Enemy_Bokoblin_Sniper_Junior": "Item_Enemy_77", + "Enemy_CDungeon_Practice": "NoHorn", + "Enemy_Chuchu_Electric_Junior": "Item_Enemy_77", + "Enemy_Chuchu_Electric_Middle": "Item_Enemy_77", + "Enemy_Chuchu_Electric_Middle_Army": "Item_Enemy_77", + "Enemy_Chuchu_Electric_Senior": "Item_Enemy_77", + "Enemy_Chuchu_Fire_Junior": "Item_Enemy_77", + "Enemy_Chuchu_Fire_Middle": "Item_Enemy_77", + "Enemy_Chuchu_Fire_Middle_Army": "Item_Enemy_77", + "Enemy_Chuchu_Fire_Senior": "Item_Enemy_77", + "Enemy_Chuchu_Ice_Junior": "Item_Enemy_77", + "Enemy_Chuchu_Ice_Middle": "Item_Enemy_77", + "Enemy_Chuchu_Ice_Middle_Army": "Item_Enemy_77", + "Enemy_Chuchu_Ice_Senior": "Item_Enemy_77", + "Enemy_Chuchu_Junior": "Item_Enemy_77", + "Enemy_Chuchu_Middle": "Item_Enemy_77", + "Enemy_Chuchu_Senior": "Item_Enemy_77", + "Enemy_Drake": "Item_Enemy_77", + "Enemy_Drake_Electric": "Item_Enemy_77", + "Enemy_Drake_Fire": "Item_Enemy_77", + "Enemy_Drake_Ice": "Item_Enemy_77", + "Enemy_Drake_Mix": "Item_Enemy_77", + "Enemy_Ganondorf": "Item_Enemy_77", + "Enemy_Ganondorf_Miasma": "Item_Enemy_77", + "Enemy_Giant_Bone": "Item_Enemy_142", + "Enemy_Giant_Bone_AllDay": "Item_Enemy_142", + "Enemy_Giant_Bone_Eye": "Item_Enemy_77", + "Enemy_Giant_Bone_Eye_AllDay": "Item_Enemy_77", + "Enemy_Giant_Junior": "Item_Enemy_142", + "Enemy_Giant_Junior_KeyCrystal": "Item_Enemy_142", + "Enemy_Giant_Middle": "Item_Enemy_143", + "Enemy_Giant_Senior": "Item_Enemy_144", + "Enemy_Golem_Fire": "Item_Enemy_77", + "Enemy_Golem_Fire_KeyCrystal": "Item_Enemy_77", + "Enemy_Golem_Fort_A": "Item_Enemy_77", + "Enemy_Golem_Fort_A_Wander": "Item_Enemy_77", + "Enemy_Golem_Ice": "Item_Enemy_77", + "Enemy_Golem_Ice_KeyCrystal": "Item_Enemy_77", + "Enemy_Golem_Junior": "Item_Enemy_77", + "Enemy_Golem_Junior_KeyCrystal": "Item_Enemy_77", + "Enemy_Golem_Little": "Item_Enemy_77", + "Enemy_Golem_Little_Fire": "Item_Enemy_77", + "Enemy_Golem_Little_Ice": "Item_Enemy_77", + "Enemy_Golem_Middle": "Item_Enemy_77", + "Enemy_Golem_Senior": "Item_Enemy_77", + "Enemy_Horablin_Dark": "Item_Enemy_103", + "Enemy_Horablin_Guard_Junior": "Item_Enemy_100", + "Enemy_Horablin_Guard_Middle": "Item_Enemy_101", + "Enemy_Horablin_Junior": "Item_Enemy_100", + "Enemy_Horablin_Middle": "Item_Enemy_101", + "Enemy_Horablin_Senior": "Item_Enemy_102", + "Enemy_LikeLike_Crack": "Item_Enemy_77", + "Enemy_LikeLike_Crack_RagdollShort": "Item_Enemy_77", + "Enemy_LikeLike_Electric": "Item_Enemy_77", + "Enemy_LikeLike_Electric_RagdollShort": "Item_Enemy_77", + "Enemy_LikeLike_Fire": "Item_Enemy_77", + "Enemy_LikeLike_Fire_RagdollShort": "Item_Enemy_77", + "Enemy_LikeLike_Ice": "Item_Enemy_77", + "Enemy_LikeLike_Ice_RagdollShort": "Item_Enemy_77", + "Enemy_LikeLike_Plane": "Item_Enemy_77", + "Enemy_LikeLike_Plane_RagdollShort": "Item_Enemy_77", + "Enemy_LikeLike_Tar": "Item_Enemy_77", + "Enemy_Lizalfos_Bone_Junior": "Item_Enemy_106", + "Enemy_Lizalfos_Bone_Junior_Head": "Item_Enemy_106", + "Enemy_Lizalfos_Dark": "Item_Enemy_109", + "Enemy_Lizalfos_Electric": "Item_Enemy_60", + "Enemy_Lizalfos_Fire": "Item_Enemy_58", + "Enemy_Lizalfos_Fire_GerudoCanyon": "Item_Enemy_58", + "Enemy_Lizalfos_Fire_GerudoCanyon_PopUp": "Item_Enemy_58", + "Enemy_Lizalfos_Guard_Junior": "Item_Enemy_106", + "Enemy_Lizalfos_Guard_Junior_LongVisibility": "Item_Enemy_106", + "Enemy_Lizalfos_Guard_Middle": "Item_Enemy_107", + "Enemy_Lizalfos_Guard_Middle_LongVisibility": "Item_Enemy_107", + "Enemy_Lizalfos_Ice": "Item_Enemy_59", + "Enemy_Lizalfos_Ice_GerudoCanyon": "Item_Enemy_59", + "Enemy_Lizalfos_Ice_GerudoCanyon_Popup": "Item_Enemy_59", + "Enemy_Lizalfos_Junior": "Item_Enemy_106", + "Enemy_Lizalfos_Middle": "Item_Enemy_107", + "Enemy_Lizalfos_Senior": "Item_Enemy_108", + "Enemy_Lynel_Boss": "Item_Enemy_148", + "Enemy_Lynel_Boss_Dark": "Item_Enemy_151", + "Enemy_Lynel_Boss_Middle": "Item_Enemy_149", + "Enemy_Lynel_Boss_Senior": "Item_Enemy_150", + "Enemy_Lynel_Dark": "Item_Enemy_151", + "Enemy_Lynel_Junior": "Item_Enemy_148", + "Enemy_Lynel_Middle": "Item_Enemy_149", + "Enemy_Lynel_Senior": "Item_Enemy_150", + "Enemy_MiddleBoss_Goron": "Item_Enemy_77", + "Enemy_Mogurudo_Baby_Junior": "Item_Enemy_77", + "Enemy_Mogurudo_Junior": "Item_Enemy_186", + "Enemy_Mogurudo_Middle": "Item_Enemy_187", + "Enemy_Mogurudo_Senior": "Item_Enemy_188", + "Enemy_Moriblin_Bone_Junior": "Item_Enemy_89", + "Enemy_Moriblin_Bone_Junior_AllDay": "Item_Enemy_89", + "Enemy_Moriblin_Bone_Junior_AllDay_AlwaysRespawn": "Item_Enemy_89", + "Enemy_Moriblin_Bone_Junior_Head": "Item_Enemy_89", + "Enemy_Moriblin_Bone_Junior_Head_AllDay": "Item_Enemy_89", + "Enemy_Moriblin_Dark": "Item_Enemy_92", + "Enemy_Moriblin_Junior": "Item_Enemy_89", + "Enemy_Moriblin_Junior_LongSight": "Item_Enemy_89", + "Enemy_Moriblin_Junior_Lookout_Cliff": "Item_Enemy_89", + "Enemy_Moriblin_Middle": "Item_Enemy_90", + "Enemy_Moriblin_Senior": "Item_Enemy_91", + "Enemy_Octarock": "Item_Enemy_77", + "Enemy_Octarock_Desert": "Item_Enemy_77", + "Enemy_Octarock_Forest": "Item_Enemy_77", + "Enemy_Octarock_Snow": "Item_Enemy_77", + "Enemy_PhantomGanon": "Item_Enemy_77", + "Enemy_Sandworm": "Item_Enemy_77", + "Enemy_Treant_Bee": "Item_Enemy_77", + "Enemy_Treant_Broadleaf": "Item_Enemy_77", + "Enemy_Treant_D": "Item_Enemy_77", + "Enemy_Treant_E": "Item_Enemy_77", + "Enemy_Zombie_Boss_Junior": "Item_Enemy_77", + "Enemy_Zombie_Boss_Junior_Defense": "Item_Enemy_77", + "Enemy_Zombie_Boss_Junior_ForDungeonBossGerudoBattle": "Item_Enemy_77", + "Enemy_Zombie_Junior": "Item_Enemy_77", + "Enemy_Zombie_Junior_Defense": "Item_Enemy_77", + "Enemy_Zombie_Junior_ForDungeonBossGerudoBattle": "Item_Enemy_77", + "Enemy_Zonau_Golem_Dark": "Item_Enemy_193", + "Enemy_Zonau_Golem_Junior": "Item_Enemy_67", + "Enemy_Zonau_Golem_Junior_ForFirstSmallDungeon": "Item_Enemy_67", + "Enemy_Zonau_Golem_Middle": "Item_Enemy_191", + "Enemy_Zonau_Golem_Senior": "Item_Enemy_192", + "Enemy_Zonau_Robot_Dark": "Item_Enemy_169", + "Enemy_Zonau_Robot_Junior": "Item_Enemy_166", + "Enemy_Zonau_Robot_Junior_Beginning": "Item_Enemy_166", + "Enemy_Zonau_Robot_Junior_Lookout": "Item_Enemy_166", + "Enemy_Zonau_Robot_Junior_Lookout_Mile": "Item_Enemy_166", + "Enemy_Zonau_Robot_Middle": "Item_Enemy_167", + "Enemy_Zonau_Robot_Middle_Lookout": "Item_Enemy_167", + "Enemy_Zonau_Robot_Senior": "Item_Enemy_168", + "Ganondorf_Miasma_Parturition": "Item_Enemy_77", + "MiasmaSwarm": "Item_Enemy_77", + "MiasmaSwarm_DekuTree": "Item_Enemy_77", + "MiasmaSwarm_LastDungeon": "Item_Enemy_77", + "MiasmaTentacle": "Item_Enemy_77" +} diff --git a/src/components/AppMapDetailsObj.ts b/src/components/AppMapDetailsObj.ts index d7bab59..5fedfd1 100644 --- a/src/components/AppMapDetailsObj.ts +++ b/src/components/AppMapDetailsObj.ts @@ -79,6 +79,9 @@ export default class AppMapDetailsObj extends AppMapDetailsBase + elements.DropTableElement.some((el: any) => el.IsProxySetting && el.ProxyType == 'TBox') + ) + .map((elements: any) => elements.DropActorDropTable).pop() + if (table_name) + this.dropTableChest = await MapMgr.getInstance().getObjDropTables("TBox_Field_Enemy", table_name) + } + if (this.minObj.name.startsWith("Enemy_Sandworm")) { + // Fake a ProxyType: TBox to get the contents of the Molduga Chest + this.dropTableChest = await MapMgr.getInstance().getObjDropTables("TBox_Field_Iron_Sandworm", "Sandworm") + let el = this.dropTables.items.find((el: any) => el.DropActorDropTable == "Sandworm") + if (el) { + el.DropTableElement[0].IsProxySetting = true + el.DropTableElement[0].ProxyType = "TBox" + } + } } + this.areaData = await this.getAreaData(); + this.hornMaterial = await MsgMgr.getInstance().getHornMaterialData(); this.aiGroups = await MapMgr.getInstance().getObjAiGroups(this.obj.map_type, this.obj.map_name, this.obj.hash_id); @@ -488,6 +517,123 @@ export default class AppMapDetailsObj extends AppMapDetailsBase { + return { num: fish.num, name: this.getName(fish.name) } + }) + } + if (item.ProxyType == "ZonauBlockMaster" && this.areaData.SpObjCapsuleBlockMaster) { + let len = this.areaData.SpObjCapsuleBlockMaster.length + let num = 100.0 / len; + return this.areaData.SpObjCapsuleBlockMaster.map((fish: any) => { + return { num, name: this.getName(fish.name) } + }) + } + if (item.ProxyType == "EcoSystemRain" && this.areaData.RainBonusMaterial) { + return this.areaData.RainBonusMaterial.map((wet: any) => { + return { num: wet.num, name: this.getName(wet.name) } + }) + } + if (item.ProxyType == "HornMaterial" && this.minObj) { + return this.getName(this.hornMaterial[this.minObj.name] || "Unknown Horn Material") + } + if (item.ProxyType == "TBox" && this.dropTableChest) { + return this.dropTableChest.items[0].DropTableElement.map((v: any) => { + let name = this.getDropItemName(v) + return { num: v.DropProbability, name } + }) + } + return "Unknown Proxy Type" + } + + getDropItemName(item: any) { + if (item.isProxySetting) + return this.getDropTableProxy(item) + return this.getName(item.DropActorName.split("/").pop().split(".")[0]) + } + findItemByHash(group: any[], links: any[], name: string): any { let hashes = links.map(link => link.DestUnitHashId); let out = group.find(g => g.data.UnitConfigName == name && hashes.includes(g.hash_id)); diff --git a/src/components/AppMapDetailsObj.vue b/src/components/AppMapDetailsObj.vue index ce9fca3..940d5a5 100644 --- a/src/components/AppMapDetailsObj.vue +++ b/src/components/AppMapDetailsObj.vue @@ -79,10 +79,27 @@ - + +
{{item.DropProbability}}% - {{item.ProxyType}} - {{item.WeaponType}} - {{getName(item.DropActorName.split("/").pop().split(".")[0])}} -
@@ -202,5 +219,12 @@ text-align: right; margin-right: 1em; } + +.drop-probability-sub { + display: inline-block; + width: 2.5em; + text-align: right; + margin-right: 1em; +} diff --git a/src/services/MsgMgr.ts b/src/services/MsgMgr.ts index 5e4f5b5..bf72604 100644 --- a/src/services/MsgMgr.ts +++ b/src/services/MsgMgr.ts @@ -15,6 +15,7 @@ export class MsgMgr { private climate: any | null = null; private area: any | null = null; private metadata: any | null = null; + private hornMaterial: any | null = null; async init() { const PREFIX = `${GAME_FILES}/text/`; @@ -71,6 +72,14 @@ export class MsgMgr { return this.metadata[item]; } + async getHornMaterialData() { + if (!this.hornMaterial) { + const res = await fetch(`${GAME_FILES}/horn_material.json`); + this.hornMaterial = await res.json(); + } + return this.hornMaterial + } + /// Get a message by its message ID (e.g. EventFlowMsg/AncientBall_Kakariko:Label). getMsg(id: string): string { const [file, label] = id.split(':'); diff --git a/tools/get_horn_data.py b/tools/get_horn_data.py new file mode 100644 index 0000000..9c484a5 --- /dev/null +++ b/tools/get_horn_data.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +import json +from pathlib import Path + +NAMES = json.load(open("names.json","r")) + + +def get_component(par, name, base): + common_path = Path('Pack') / 'ResidentCommon' + if 'Components' in par and name in par['Components']: + # Remove leading '?' and match locally or globally + file = par['Components'][name].replace("?", "").replace(".bgyml",".json") + if file == "": + return None, None + local = base / file + if local.exists(): + return local, base + common = common_path / file + if common.exists(): + return common, base + return None, None + + if not '$parent' in par: + return None, None + # Remove leading 'Work/' and match locally or globally (for the parent) + stub = par['$parent'].replace("Work/", "").replace(".gyml",".json") + local = base / stub + if local.exists(): + parent = json.load(open(local,"r"))['RootNode'] + return get_component(parent, name, base) + + common = common_path / stub + if common.exists(): + parent = json.load(open(common,"r"))['RootNode'] + return get_component(parent, name, common_path) + + return None, None + +p = Path("Pack/Actor") + +horns = {} + +for actor in p.glob("*"): + name = actor.name + file = str(actor.name) + ".engine__actor__ActorParam.json" + + actor_path = actor / 'Actor' / file + if not actor_path.exists(): + continue + actor_par = json.load(open(actor_path, "r"))['RootNode'] + + # GameParameterTableRef + gp_path, actor = get_component(actor_par, "GameParameterTableRef", actor) + if not gp_path: + continue + + gp = json.load(open(gp_path, "r"))['RootNode'] + + # HornTypeAndAttachmentMappingTable + horn_path, actor = get_component(gp, 'HornTypeAndAttachmentMappingTable', actor) + if not horn_path: + continue + + horn = json.load(open(horn_path, "r"))['RootNode'] + + attachments = horn['HornTypeAndAttachmentMapping'] + # Frox are the only ones with 2 horns, they are the same + # Just assume its one + if name.startswith("FldObj_"): # Ignore Figure of Enemies + continue + for attach in attachments[:1]: + attach_type = attach.get('HornType') or "Default" + attach_name = attach.get('AttachmentName') or "NoHorn" + attach_name = attach_name.split("/")[-1].split(".")[0] + ui_name = NAMES.get(attach_name) or attach_name + ui_actor_name = NAMES.get(name) or name + horns[name] = { + "ui_actor_name": ui_actor_name, + "ui_name": ui_name, + "name": name, + "attach_name": attach_name, + } + +horn_material = {} +for key in sorted(horns.keys()): + val = horns[key] + horn_material[val['name']] = val['attach_name'] + +print(json.dumps(horn_material, indent=2)) +