/// <summary>Initializes a new window</summary> public BriefingUIPage() { Items = new BriefingUIItem[5]; for (int i = 0; i < 5; i++) { Items[i] = new BriefingUIItem(); } }
/// <summary>Saves the array data to the items</summary> /// <param name="data">A [5,5] array of viewport settings</param> /// <exception cref="ArgumentException"><i>data</i>'s dimensions are not at least [5,5].</exception> void setRawData(short[,] data) { if (data.GetLength(0) < 5 || data.GetLength(1) < 5) //~MG was 0 and 0 { throw new ArgumentException("Not enough data elements."); } for (int i = 0; i < 5; i++) { BriefingUIItem item = Items[i]; item.Top = data[i, 0]; item.Left = data[i, 1]; item.Bottom = data[i, 2]; item.Right = data[i, 3]; item.IsVisible = Convert.ToBoolean(data[i, 4]); } }
/// <summary>Saves the mission to <see cref="MissionFile.MissionPath"/></summary> /// <exception cref="UnauthorizedAccessException">Write permissions for <see cref="MissionFile.MissionPath"/> are denied</exception> public void Save() { //[JB] Added backup logic. See the TIE Save() function for comments. if (File.Exists(MissionPath) && (File.GetAttributes(MissionPath) & FileAttributes.ReadOnly) != 0) { throw new UnauthorizedAccessException("Cannot save, existing file is read-only."); } FileStream fs = null; string backup = MissionPath.ToLower().Replace(".xwi", "_xwi.bak"); bool backupCreated = false, writerCreated = false; if (File.Exists(MissionPath) && MissionPath.ToLower() != backup) { try { if (File.Exists(backup)) { File.Delete(backup); } File.Copy(MissionPath, backup); backupCreated = true; } catch { } } try { if (File.Exists(MissionPath)) { File.Delete(MissionPath); } fs = File.OpenWrite(MissionPath); BinaryWriter bw = new BinaryWriter(fs, System.Text.Encoding.GetEncoding(437)); //[JB] Changed encoding to IBM437 (OEM United States) to properly handle the DOS ASCII character set. writerCreated = true; bw.Write((short)0x2); //Platform bw.Write(TimeLimitMinutes); bw.Write(EndEvent); bw.Write(RndSeed); bw.Write(Location); for (int i = 0; i < 3; i++) { long p = fs.Position; bw.Write(_endOfMissionMessages[i].ToCharArray()); bw.Write('\0'); fs.Position = p + 0x40; } int numFG = 0; int numOG = 0; for (int i = 0; i < FlightGroups.Count; i++) { if (FlightGroups[i].CraftType > 0) { numFG++; } if (FlightGroups[i].ObjectType > 0) { numOG++; } } bw.Write((short)numFG); bw.Write((short)numOG); #region Flightgroups for (int i = 0; i < FlightGroups.Count; i++) { if (FlightGroups[i].CraftType == 0) { continue; } long p = fs.Position; #region Craft bw.Write(FlightGroups[i].Name.ToCharArray()); fs.Position = p + 0x10; bw.Write(FlightGroups[i].Cargo.ToCharArray()); fs.Position = p + 0x20; bw.Write(FlightGroups[i].SpecialCargo.ToCharArray()); fs.Position = p + 0x30; bw.Write((short)FlightGroups[i].SpecialCargoCraft); bw.Write((short)FlightGroups[i].CraftType); bw.Write((short)FlightGroups[i].IFF); bw.Write((short)FlightGroups[i].Status1); bw.Write((short)FlightGroups[i].NumberOfCraft); bw.Write((short)FlightGroups[i].NumberOfWaves); #endregion #region Arr/Dep bw.Write((short)FlightGroups[i].ArrivalEvent); bw.Write((short)FlightGroups[i].ArrivalDelay); bw.Write((short)FlightGroups[i].ArrivalFG); bw.Write((short)FlightGroups[i].Mothership); bw.Write((short)FlightGroups[i].ArrivalHyperspace); bw.Write((short)FlightGroups[i].DepartureHyperspace); #endregion //Waypoints (7 real waypoints, rest are virtualized BRF coordinate sets) for (int j = 0; j < 4; j++) { for (int k = 0; k < 7; k++) { bw.Write(FlightGroups[i].Waypoints[k][j] /* * (j == 1 ? -1 : 1))*/); } } //More craft info bw.Write((short)FlightGroups[i].Formation); bw.Write((short)FlightGroups[i].PlayerCraft); bw.Write((short)FlightGroups[i].AI); bw.Write(FlightGroups[i].Order); bw.Write(FlightGroups[i].DockTimeThrottle); bw.Write((short)FlightGroups[i].Markings); bw.Write((short)FlightGroups[i].Markings); //Was Unknown1. Another color value. Official missions always have the same color. bw.Write(FlightGroups[i].Objective); bw.Write(FlightGroups[i].TargetPrimary); bw.Write(FlightGroups[i].TargetSecondary); } // OBJECT GROUPS for (int i = 0; i < FlightGroups.Count; i++) { if (FlightGroups[i].ObjectType == 0) { continue; } long p = fs.Position; bw.Write(FlightGroups[i].Name.ToCharArray()); fs.Position = p + 0x10; bw.Write(FlightGroups[i].Cargo.ToCharArray()); fs.Position = p + 0x20; bw.Write(FlightGroups[i].SpecialCargo.ToCharArray()); fs.Position = p + 0x30; bw.Write(FlightGroups[i].SpecialCargoCraft); bw.Write(FlightGroups[i].ObjectType); bw.Write((short)FlightGroups[i].IFF); //The format begins to deviate here bw.Write((short)FlightGroups[i].Formation); bw.Write((short)FlightGroups[i].NumberOfCraft); bw.Write(FlightGroups[i].Waypoints[0][0]); bw.Write(FlightGroups[i].Waypoints[0][1]); bw.Write(FlightGroups[i].Waypoints[0][2]); bw.Write(FlightGroups[i].Yaw); //Conversion to/from degrees handled in the editor. This helps preserve the exact values used by pilot proving ground platforms. bw.Write(FlightGroups[i].Pitch); bw.Write(FlightGroups[i].Roll); } #endregion fs.SetLength(fs.Position); fs.Close(); } catch { if (fs != null) { fs.Close(); } if (writerCreated && backupCreated) { File.Delete(MissionPath); File.Copy(backup, MissionPath); File.Delete(backup); } throw; } if (backupCreated) { File.Delete(backup); } //Finished saving XWI file. Now save the BRF file. string BriefingPath = MissionPath; bool upper; //This stuff is merely to try and make the BRF extension match the case of the XWI, so the file names look nice and tidy. int extPos = BriefingPath.LastIndexOf('.'); if (extPos >= 0 && extPos < BriefingPath.Length - 1) { upper = char.IsUpper(BriefingPath[extPos + 1]); //Detect case from the first character of the extension. BriefingPath = BriefingPath.Remove(extPos + 1); //Strip extension so a new one can be added. } else { upper = char.IsUpper(BriefingPath[BriefingPath.Length - 1]); //If for some reason the file has no extension, detect from the last character of the name. BriefingPath += "."; } BriefingPath += upper ? "BRF" : "brf"; if (File.Exists(BriefingPath) && (File.GetAttributes(BriefingPath) & FileAttributes.ReadOnly) != 0) { throw new UnauthorizedAccessException("Cannot save briefing, existing file is read-only."); } fs = null; backup = BriefingPath.ToLower().Replace(".brf", "_brf.bak"); backupCreated = false; writerCreated = false; if (File.Exists(BriefingPath) && BriefingPath.ToLower() != backup) { try { if (File.Exists(backup)) { File.Delete(backup); } File.Copy(BriefingPath, backup); backupCreated = true; } catch { } } try { if (File.Exists(BriefingPath)) { File.Delete(BriefingPath); } fs = File.OpenWrite(BriefingPath); BinaryWriter bw = new BinaryWriter(fs, System.Text.Encoding.GetEncoding(437)); //[JB] Changed encoding to IBM437 (OEM United States) to properly handle the DOS ASCII character set. writerCreated = true; bw.Write((short)2); //Version bw.Write((short)FlightGroupsBriefing.Count); bw.Write(Briefing.MaxCoordSet); //Coordinate count; long p = 0; int wp = 0; for (int i = 0; i < Briefing.MaxCoordSet; i++) //Coordinate count { //Just in case there too many coord sets than what the editor allows, read them but only load them if the indexes are valid. if (i == 0) { wp = 0; //SP1 } else { wp = 7 + i - 1; //CS1 starts at [7], but at this point i==1 so subtract to compensate } if (wp >= 10) { wp = -1; } for (int j = 0; j < FlightGroupsBriefing.Count; j++) { for (int k = 0; k < 3; k++) { short dat = 0; if (wp >= 0) { dat = FlightGroupsBriefing[j].Waypoints[wp][k]; } bw.Write(dat); } } } for (int i = 0; i < FlightGroupsBriefing.Count; i++) { if (FlightGroupsBriefing[i].IsFlightGroup()) { bw.Write((short)FlightGroupsBriefing[i].CraftType); } else { bw.Write(FlightGroupsBriefing[i].ObjectType); } bw.Write((short)FlightGroupsBriefing[i].IFF); bw.Write((short)FlightGroupsBriefing[i].NumberOfCraft); bw.Write((short)FlightGroupsBriefing[i].NumberOfWaves); p = fs.Position; bw.Write(FlightGroupsBriefing[i].Name.ToCharArray()); fs.Position = p + 0x10; bw.Write(FlightGroupsBriefing[i].Cargo.ToCharArray()); fs.Position = p + 0x20; bw.Write(FlightGroupsBriefing[i].SpecialCargo.ToCharArray()); fs.Position = p + 0x30; bw.Write(FlightGroupsBriefing[i].SpecialCargoCraft); bw.Write(FlightGroupsBriefing[i].Yaw); bw.Write(FlightGroupsBriefing[i].Pitch); bw.Write(FlightGroupsBriefing[i].Roll); } #region WindowUISettings short count = (short)Briefing.WindowSettings.Count; bw.Write(count); for (int i = 0; i < count; i++) { for (int j = 0; j < 5; j++) { BriefingUIItem item = Briefing.WindowSettings[i].Items[j]; bw.Write(item.Top); bw.Write(item.Left); bw.Write(item.Bottom); bw.Write(item.Right); bw.Write(Convert.ToInt16(item.IsVisible)); } } #endregion WindowUISettings #region Pages bw.Write((short)Briefing.Pages.Count); for (int i = 0; i < Briefing.Pages.Count; i++) { BriefingPage pg = Briefing.GetBriefingPage(i); bw.Write(pg.Length); bw.Write(pg.EventsLength); bw.Write(pg.CoordSet); bw.Write(pg.PageType); byte[] briefBuffer = new byte[pg.EventsLength * 2]; Buffer.BlockCopy(pg.Events, 0, briefBuffer, 0, briefBuffer.Length); bw.Write(briefBuffer); } #endregion Pages bw.Write(TimeLimitMinutes); bw.Write(EndEvent); bw.Write(RndSeed); bw.Write(Briefing.MissionLocation); p = fs.Position; for (int i = 0; i < 3; i++) { bw.Write(EndOfMissionMessages[i].ToCharArray()); fs.Position = p + ((i + 1) * 64); } p = fs.Position; for (int i = 0; i < FlightGroupsBriefing.Count; i++) { fs.Position += 68; bw.Write((short)FlightGroupsBriefing[i].PlayerCraft); fs.Position = p + ((i + 1) * 90); } #region Text/Tags bw.Write((short)32); //Count for (int i = 0; i < 32; i++) { bw.Write((short)Briefing.BriefingTag[i].Length); bw.Write(Briefing.BriefingTag[i].ToCharArray()); } bw.Write((short)32); for (int i = 0; i < 32; i++) { string t = Briefing.RemoveBrackets(Briefing.BriefingString[i]); int len = t.Length; bw.Write((short)len); bw.Write(t.ToCharArray()); byte[] highlight = Briefing.TranslateStringToHighlight(Briefing.BriefingString[i]); bw.Write(highlight); } #endregion Text/Tags fs.SetLength(fs.Position); fs.Close(); } catch { if (fs != null) { fs.Close(); } if (writerCreated && backupCreated) { File.Delete(BriefingPath); File.Copy(backup, BriefingPath); File.Delete(backup); } throw; } if (backupCreated) { File.Delete(backup); } }
/// <summary>Loads a mission briefing (.BRF) file from an open FileStream</summary> /// <param name="stream">Opened FileStream to mission briefing file</param> /// <exception cref="InvalidDataException"><paramref name="stream"/> is not a valid X-wing mission briefing file</exception> public void LoadBriefingFromStream(FileStream stream) { BinaryReader br = new BinaryReader(stream, System.Text.Encoding.GetEncoding(437)); //[JB] Changed encoding to IBM437 (OEM United States) to properly handle the DOS ASCII character set. string str; short s; s = br.ReadInt16(); //PlatformID if (s != 2) { throw new InvalidDataException("Not a valid X-wing briefing file."); } short shipCount = br.ReadInt16(); short coordCount = br.ReadInt16(); FlightGroupsBriefing = new FlightGroupCollection(shipCount); int wp; for (int i = 0; i < coordCount; i++) { //Just in case there too many coord sets than what the editor allows, read them but only load them if the indexes are valid. if (i == 0) { wp = 0; //SP1 } else { wp = 7 + i - 1; //CS1 starts at [7], but at this point i==1 so subtract to compensate } if (wp >= 10) { wp = -1; } for (int j = 0; j < shipCount; j++) { for (int k = 0; k < 3; k++) { short dat = br.ReadInt16(); if (wp >= 0) { FlightGroupsBriefing[j].Waypoints[wp][k] = dat; } } if (wp >= 0 && wp < 7) { FlightGroupsBriefing[j].Waypoints[wp][3] = 1; } } } if (coordCount < 2) { coordCount = 2; //Sanity check for editor purposes. All LEC missions have 2 sets. } else if (coordCount > 4) { coordCount = 4; } Briefing.MaxCoordSet = coordCount; for (int i = 0; i < shipCount; i++) { s = br.ReadInt16(); //craft type if (s < 18) { FlightGroupsBriefing[i].CraftType = (byte)s; FlightGroupsBriefing[i].ObjectType = 0; } else { FlightGroupsBriefing[i].CraftType = 0; FlightGroupsBriefing[i].ObjectType = s; } FlightGroupsBriefing[i].IFF = (byte)br.ReadInt16(); FlightGroupsBriefing[i].NumberOfCraft = (byte)br.ReadInt16(); FlightGroupsBriefing[i].NumberOfWaves = (byte)br.ReadInt16(); FlightGroupsBriefing[i].Name = new string(br.ReadChars(16)); FlightGroupsBriefing[i].Cargo = new string(br.ReadChars(16)); FlightGroupsBriefing[i].SpecialCargo = new string(br.ReadChars(16)); FlightGroupsBriefing[i].SpecialCargoCraft = br.ReadInt16(); FlightGroupsBriefing[i].Yaw = br.ReadInt16(); FlightGroupsBriefing[i].Pitch = br.ReadInt16(); FlightGroupsBriefing[i].Roll = br.ReadInt16(); } #region WindowUISettings short count = br.ReadInt16(); //Setting count. Usually 2, but not always. Briefing.ResetUISettings(count); for (int i = 0; i < count; i++) { for (int j = 0; j < 5; j++) { BriefingUIItem item = Briefing.WindowSettings[i].Items[j]; item.Top = br.ReadInt16(); item.Left = br.ReadInt16(); item.Bottom = br.ReadInt16(); item.Right = br.ReadInt16(); item.IsVisible = Convert.ToBoolean(br.ReadInt16()); } } #endregion WindowUISettings #region Pages count = br.ReadInt16(); Briefing.ResetPages(count); for (int i = 0; i < count; i++) { BriefingPage pg = Briefing.Pages[i]; pg.Length = br.ReadInt16(); //total ticks pg.EventsLength = br.ReadInt16(); //Count of Int16s pg.CoordSet = br.ReadInt16(); pg.PageType = br.ReadInt16(); byte[] briefBuffer = br.ReadBytes(pg.EventsLength * 2); Buffer.BlockCopy(briefBuffer, 0, pg.Events, 0, briefBuffer.Length); } #endregion Pages stream.Position += 6; /*s = br.ReadInt16(); //TimeLimitMinutes? * s = br.ReadInt16(); //EndEvent? * s = br.ReadInt16(); //Unknown1?*/ Briefing.MissionLocation = br.ReadInt16(); stream.Position += 3 * 64; /*for (int i = 0; i < 3; i++) //EndOfMissionMessages * str = new string(br.ReadChars(64));*/ stream.Position += 90 * shipCount; /*for (int i = 0; i < shipCount; i++) * { * //No idea what data this is, or even what order. * br.ReadBytes(68); * s = br.ReadInt16(); //PlayerCraft? * br.ReadBytes(20); * }*/ #region Text/Tags count = br.ReadInt16(); //Tags Briefing.ResizeTagList(count); for (int i = 0; i < count; i++) { short len = br.ReadInt16(); Briefing.BriefingTag[i] = new string(br.ReadChars(len)); } count = br.ReadInt16(); //Text Briefing.ResizeStringList(count); for (int i = 0; i < count; i++) { short len = br.ReadInt16(); str = new string(br.ReadChars(len)); byte[] highlight = new byte[len]; br.Read(highlight, 0, len); Briefing.BriefingString[i] = Briefing.TranslateHighlightToString(str, highlight); } #endregion Text/Tags }