public static HighlightCategory ReadHighlightCategory64(this BinaryReader br) { const ulong CategoryMask = 0x0830000000000000ul; ulong value = br.ReadUInt64(); Debug.Assert((value & 0xFFFFFFFF00000000ul) == CategoryMask || value == 0); HighlightCategory category = (HighlightCategory)(value & 0xFFFFFFFFu); Debug.Assert(Enum.IsDefined(typeof(HighlightCategory), category), $"Undefined highlight category {(uint)category:X8}"); return(category); }
/// <summary> /// Initializes a new instance of the <see cref="LogHighlight" /> class. /// </summary> /// <param name="category">The category.</param> public LogHighlight(HighlightCategory category) { Category = category; }
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); }