static void Main(string[] args) { Console.WindowHeight = 50; Console.BufferHeight = 32766; UnlockValidator.Run(); if (args.Length > 0) { foreach (var arg in args) { if (File.Exists(arg)) { LoadAndPrintHighlight(new FileInfo(arg)); } else if (Directory.Exists(arg)) { foreach (var file in Directory.GetFiles(arg, "*", SearchOption.AllDirectories)) { LoadAndPrintHighlight(new FileInfo(file)); } } } } else { var overwatchAppdataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Blizzard Entertainment/Overwatch")); foreach (var userFolder in overwatchAppdataFolder.GetDirectories()) { var highlightsFolder = new DirectoryInfo(Path.Combine(userFolder.FullName, "Highlights")); if (highlightsFolder.Exists) { foreach (var item in highlightsFolder.GetFiles()) { LoadAndPrintHighlight(item); } } } } Tracer.DumpToConsole(); Tracer.DumpToFile("tracer.log"); Console.ReadLine(); }
public HighlightInfo(BinaryReader br, MajorVersion gameMajorVersion) { // player name of the highlight protagonist (will differ for other people's POTGs) this.playerName = br.ReadNullPaddedUTF8(); // wheeeeeeee if (gameMajorVersion >= new MajorVersion(1, 16, VersionBranch.None)) { byte unknown1 = br.ReadByte(); Debug.Assert(unknown1 == 0); } // 1 for potg, 0 for top5 highlight, 4 for manual highlight this.typeFlags = (HighlightTypeFlag)br.ReadByte(); Debug.Assert(Extensions.AreAllFlagsDefined(typeFlags)); this.unknown2 = br.ReadUInt32(); Debug.Assert((unknown2 & 0x80000000u) == 0x80000000u); Debug.Assert((unknown2 & 0x7FFFFFFFu) <= 0x0000FFFFu); this.unknown3 = br.ReadUInt32(); Debug.Assert((unknown3 & 0x80000000u) == 0x80000000u); Debug.Assert((unknown3 & 0x7FFFFFFFu) <= 0x0000FFFFu); Debug.Assert(unknown3 >= unknown2); this.unknown4 = br.ReadSingle(); Debug.Assert(!float.IsInfinity(unknown4) && !float.IsNaN(unknown4)); this.unknown5 = br.ReadSingle(); Debug.Assert(!float.IsInfinity(unknown5) && !float.IsNaN(unknown5)); // seems to be nonzero if the player starts the highlight in the air - elevation? this.unknown6 = br.ReadUInt32(); if (gameMajorVersion >= new MajorVersion(1, 17, VersionBranch.None)) { // 0 for defense team, 1 for attack team. not sure how this handles oasis/nepal/ilios/lijiangtower yet this.unknown7 = br.ReadUInt32(); Debug.Assert(unknown7 == 0 || unknown7 == 1 || unknown7 == 4); } this.highlightIntroPosition = br.ReadVec3(); Debug.Assert(highlightIntroPosition.IsFinite()); this.highlightIntroDirection = br.ReadVec3(); Debug.Assert(highlightIntroDirection.IsFinite()); Debug.Assert(highlightIntroDirection.IsUnitVector()); this.upVector = br.ReadVec3(); Debug.Assert(upVector.IsFinite()); Debug.Assert(upVector.IsUnitVector()); Debug.Assert(Math.Round(upVector.x) == 0); Debug.Assert(Math.Round(upVector.y) == 1); Debug.Assert(Math.Round(upVector.z) == 0); this.hero = br.ReadHero64(); this.skin = br.ReadSkin64(); this.weaponSkin = br.ReadWeaponSkin64(); // at a hazy guess these might be to do with the new country-specific skins for the world cup? if (gameMajorVersion >= new MajorVersion(1, 17, VersionBranch.None)) { this.unknown8 = br.ReadUInt64(); Debug.Assert(unknown8 == 0); this.unknown9 = br.ReadUInt64(); Debug.Assert(unknown9 == 0); } this.highlightIntro = br.ReadHighlightIntro64(); this.category = br.ReadHighlightCategory64(); this.timestamp = br.ReadUInt64(); this.uuid = new HighlightUUID(br); UnlockValidator.RunForHeroWithUnlocks(hero, skin, weaponSkin, highlightIntro); Debug.Assert(this.unknown3 >= this.unknown2); }
public HeroWithUnlockables(BinaryReader br, MajorVersion gameMajorVersion) { this.skin = br.ReadSkin32(); this.weaponSkin = br.ReadWeaponSkin32(); this.highlightIntro = br.ReadHighlightIntro32(); int numSprays = br.ReadInt32(); this.sprays = br.ReadSpray32s(numSprays); int numVoiceLines = br.ReadInt32(); this.voiceLines = br.ReadVoiceLine32s(numVoiceLines); int numEmotes = br.ReadInt32(); this.emotes = br.ReadEmote32s(numEmotes); // might be to do with team affiliation? seems to be either 0 or 1 depending on team - not sure about -1?? if (gameMajorVersion >= new MajorVersion(1, 17, VersionBranch.None)) { this.unknownInV17 = br.ReadInt32(); Debug.Assert(unknownInV17 == -1 || unknownInV17 == 0 || unknownInV17 == 1 || unknownInV17 == 4); } this.hero = br.ReadHero64(); // AI players in custom matches have no HighlightIntro, no unlocks, and always use classic skins // Bots in the Junkenstein/Uprising modes sometimes use non-classic skins. if (highlightIntro == HighlightIntro.None) { Debug.Assert(this.sprays.Length == 0); Debug.Assert(this.voiceLines.Length == 0); Debug.Assert(this.emotes.Length == 0); Debug.Assert( ($"{skin}" == $"{hero}_Classic") || (hero == Hero.Junkrat && skin == Skin.Junkrat_DrJunkenstein) || (hero == Hero.Mercy && skin == Skin.Mercy_Witch) || (hero == Hero.Reaper && skin == Skin.Reaper_Dracula) || (hero == Hero.Roadhog && skin == Skin.Roadhog_JunkensteinsMonster) || (hero == Hero.Orisa && skin == Skin.Orisa_NullSector) || (hero == Hero.UprisingEvent_00000173 && skin == Skin.UprisingEvent_00000173_Classic) || (hero == Hero.UprisingEvent_00000178 && skin == Skin.UprisingEvent_00000178_Classic) || (hero == Hero.UprisingEvent_00000179 && skin == Skin.UprisingEvent_00000179_Classic) || (hero == Hero.RetributionEvent_000001AC && skin == Skin.RetributionEvent_000001AC_Classic) || (hero == Hero.RetributionEvent_000001B8 && skin == Skin.RetributionEvent_000001B8_Classic) || (hero == Hero.RetributionEvent_000001BA && skin == Skin.RetributionEvent_000001BA_Classic) || (hero == Hero.RetributionEvent_000001BB && skin == Skin.RetributionEvent_000001BB_Classic) || (hero == Hero.RetributionEvent_000001CE && skin == Skin.RetributionEvent_000001CE_Classic) ); Debug.Assert( ($"{weaponSkin}" == $"{hero}_Classic") || (hero == Hero.Junkrat && weaponSkin == WeaponSkin.Junkrat_DrJunkenstein) || (hero == Hero.Mercy && weaponSkin == WeaponSkin.Mercy_Witch) || (hero == Hero.Reaper && weaponSkin == WeaponSkin.Reaper_Dracula) || (hero == Hero.Roadhog && weaponSkin == WeaponSkin.Roadhog_JunkensteinsMonster) || (hero == Hero.Orisa && weaponSkin == WeaponSkin.Orisa_NullSector) || (hero == Hero.UprisingEvent_00000173 && weaponSkin == WeaponSkin.UprisingEvent_00000173_Classic) || (hero == Hero.UprisingEvent_00000178 && weaponSkin == WeaponSkin.UprisingEvent_00000178_Classic) || (hero == Hero.UprisingEvent_00000179 && weaponSkin == WeaponSkin.UprisingEvent_00000179_Classic) || (hero == Hero.RetributionEvent_000001AC && weaponSkin == WeaponSkin.RetributionEvent_000001AC_Classic) || (hero == Hero.RetributionEvent_000001B8 && weaponSkin == WeaponSkin.RetributionEvent_000001B8_Classic) || (hero == Hero.RetributionEvent_000001BA && weaponSkin == WeaponSkin.RetributionEvent_000001BA_Classic) || (hero == Hero.RetributionEvent_000001BB && weaponSkin == WeaponSkin.RetributionEvent_000001BB_Classic) || (hero == Hero.RetributionEvent_000001CE && weaponSkin == WeaponSkin.RetributionEvent_000001CE_Classic) ); } // Ensure that unlocks are correctly mapped to heroes UnlockValidator.RunForHeroWithUnlocks(hero, skin, weaponSkin, highlightIntro, sprays, emotes, voiceLines); }