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); }