void _initialize() { OfficersPresent = BriefingOfficers.FlightOfficer; _invalidError = _invalidError.Replace("{0}", "TIE"); _iffHostile[0] = true; _iffNameIndexer = new IffNameIndexer(this); _iffHostileIndexer = new Indexer <bool>(_iffHostile, new bool[] { true, true, false, false, false, false }); _endOfMissionIndexer = new Indexer <string>(_endOfMissionMessages, 63); FlightGroups = new FlightGroupCollection(); Messages = new MessageCollection(); GlobalGoals = new Globals(); Briefing = new Briefing(); BriefingQuestions = new Questions(); }
/// <summary>Loads a mission from an open FileStream</summary> /// <param name="stream">Opened FileStream to mission file</param> /// <exception cref="System.IO.InvalidDataException"><i>stream</i> is not a valid TIE mission file</exception> public void LoadFromStream(FileStream stream) { if (MissionFile.GetPlatform(stream) != MissionFile.Platform.TIE) { throw new InvalidDataException(_invalidError); } BinaryReader br = new BinaryReader(stream, System.Text.Encoding.Default); //[JB] Added encoding int i; stream.Position = 2; short numFlightGroups = br.ReadInt16(); short numMessages = br.ReadInt16(); stream.Position = 0xA; try { OfficersPresent = (Mission.BriefingOfficers)br.ReadByte(); } catch { OfficersPresent = Mission.BriefingOfficers.Both; } stream.Position = 0xD; CapturedOnEjection = br.ReadBoolean(); stream.Position = 0x18; for (i = 0; i < 6; i++) { EndOfMissionMessages[i] = new string(br.ReadChars(64)); } stream.Position += 2; byte[] buffer = new byte[64]; for (i = 2; i < 6; i++) { IFFs[i] = new string(br.ReadChars(12)); } #region FlightGroups FlightGroups = new FlightGroupCollection(numFlightGroups); for (i = 0; i < FlightGroups.Count; i++) { #region Craft int j; FlightGroups[i].Name = new string(br.ReadChars(12)); FlightGroups[i].Pilot = new string(br.ReadChars(12)); //not used by TIE FlightGroups[i].Cargo = new string(br.ReadChars(12)); FlightGroups[i].SpecialCargo = new string(br.ReadChars(12)); stream.Read(buffer, 0, 0x38); FlightGroups[i].SpecialCargoCraft = buffer[0]; FlightGroups[i].RandSpecCargo = Convert.ToBoolean(buffer[1]); FlightGroups[i].CraftType = buffer[2]; FlightGroups[i].NumberOfCraft = buffer[3]; // the Rand part of the check below is because if true, don't need to mess with it if (!FlightGroups[i].RandSpecCargo) { if (FlightGroups[i].SpecialCargoCraft >= FlightGroups[i].NumberOfCraft) { FlightGroups[i].SpecialCargoCraft = 0; } else { FlightGroups[i].SpecialCargoCraft++; } } FlightGroups[i].Status1 = buffer[4]; FlightGroups[i].Missile = buffer[5]; FlightGroups[i].Beam = buffer[6]; FlightGroups[i].IFF = buffer[7]; FlightGroups[i].AI = buffer[8]; FlightGroups[i].Markings = buffer[9]; FlightGroups[i].FollowsOrders = Convert.ToBoolean(buffer[0xA]); FlightGroups[i].Unknowns.Unknown1 = buffer[0xB]; FlightGroups[i].Formation = buffer[0xC]; FlightGroups[i].FormDistance = buffer[0xD]; FlightGroups[i].GlobalGroup = buffer[0xE]; FlightGroups[i].FormLeaderDist = buffer[0xF]; FlightGroups[i].NumberOfWaves = (byte)(buffer[0x10] + 1); FlightGroups[i].Unknowns.Unknown5 = buffer[0x11]; FlightGroups[i].PlayerCraft = buffer[0x12]; FlightGroups[i].Yaw = (short)Math.Round((double)(sbyte)buffer[0x13] * 360 / 0x100); FlightGroups[i].Pitch = (short)Math.Round((double)(sbyte)buffer[0x14] * 360 / 0x100); FlightGroups[i].Pitch += (short)(FlightGroups[i].Pitch < -90 ? 270 : -90); FlightGroups[i].Roll = (short)Math.Round((double)(sbyte)buffer[0x15] * 360 / 0x100); FlightGroups[i].Unknowns.Unknown9 = Convert.ToBoolean(buffer[0x16]); FlightGroups[i].Unknowns.Unknown10 = buffer[0x17]; FlightGroups[i].Unknowns.Unknown11 = buffer[0x18]; #endregion #region Arr/Dep FlightGroups[i].Difficulty = buffer[0x19]; FlightGroups[i].ArrDepTriggers[0] = new Trigger(buffer, 0x1A); FlightGroups[i].ArrDepTriggers[1] = new Trigger(buffer, 0x1E); FlightGroups[i].AT1AndOrAT2 = Convert.ToBoolean(buffer[0x22]); FlightGroups[i].Unknowns.Unknown12 = buffer[0x23]; FlightGroups[i].ArrivalDelayMinutes = buffer[0x24]; FlightGroups[i].ArrivalDelaySeconds = buffer[0x25]; FlightGroups[i].ArrDepTriggers[2] = new Trigger(buffer, 0x26); FlightGroups[i].DepartureTimerMinutes = buffer[0x2A]; FlightGroups[i].DepartureTimerSeconds = buffer[0x2B]; FlightGroups[i].AbortTrigger = buffer[0x2C]; FlightGroups[i].Unknowns.Unknown15 = buffer[0x2D]; FlightGroups[i].Unknowns.Unknown16 = buffer[0x2E]; FlightGroups[i].Unknowns.Unknown17 = buffer[0x2F]; FlightGroups[i].ArrivalCraft1 = buffer[0x30]; FlightGroups[i].ArrivalMethod1 = Convert.ToBoolean(buffer[0x31]); FlightGroups[i].DepartureCraft1 = buffer[0x32]; FlightGroups[i].DepartureMethod1 = Convert.ToBoolean(buffer[0x33]); FlightGroups[i].ArrivalCraft2 = buffer[0x34]; FlightGroups[i].ArrivalMethod2 = Convert.ToBoolean(buffer[0x35]); FlightGroups[i].DepartureCraft2 = buffer[0x36]; FlightGroups[i].DepartureMethod2 = Convert.ToBoolean(buffer[0x37]); #endregion stream.Read(buffer, 0, 0x36); for (j = 0; j < 3; j++) { FlightGroups[i].Orders[j] = new FlightGroup.Order(buffer, j * 18); } stream.Read(buffer, 0, 0xA); FlightGroups[i].Goals = new FlightGroup.FGGoals(buffer, 0); for (j = 0; j < 4; j++) { for (int k = 0; k < 15; k++) { FlightGroups[i].Waypoints[k][j] = (short)(br.ReadInt16() * (j == 1 ? -1 : 1)); } } FlightGroups[i].Unknowns.Unknown19 = br.ReadBoolean(); stream.Position++; FlightGroups[i].Unknowns.Unknown20 = br.ReadByte(); FlightGroups[i].Unknowns.Unknown21 = br.ReadBoolean(); } #endregion #region Messages if (numMessages != 0) { Messages = new MessageCollection(numMessages); for (i = 0; i < Messages.Count; i++) { Messages[i].MessageString = new string(br.ReadChars(64)).Trim('\0'); if (Messages[i].MessageString.IndexOf('\0') != -1) { Messages[i].MessageString = Messages[i].MessageString.Substring(0, Messages[i].MessageString.IndexOf('\0')); } Messages[i].Color = 0; if (Messages[i].MessageString.Length > 0) //[JB] Added length check, otherwise empty strings would crash the load process and make the mission unrecoverable to anything but hex editing. { char c = Messages[i].MessageString[0]; if (c >= '1' && c <= '3') { Messages[i].Color = (byte)(c - '0'); Messages[i].MessageString = Messages[i].MessageString.Substring(1); } } stream.Read(buffer, 0, 8); Messages[i].Triggers[0] = new Trigger(buffer, 0); Messages[i].Triggers[1] = new Trigger(buffer, 4); Messages[i].Short = new string(br.ReadChars(12)); stream.Position += 4; Messages[i].Delay = br.ReadByte(); Messages[i].Trig1AndOrTrig2 = br.ReadBoolean(); } } else { Messages.Clear(); } #endregion #region Globals for (i = 0; i < 3; i++) { stream.Read(buffer, 0, 8); GlobalGoals.Goals[i].Triggers[0] = new Trigger(buffer, 0); GlobalGoals.Goals[i].Triggers[1] = new Trigger(buffer, 4); stream.Position += 0x11; //for some reason, there's triggers with Var set with no Type if (GlobalGoals.Goals[i].Triggers[0].VariableType == 0) { GlobalGoals.Goals[i].Triggers[0].Variable = 0; } if (GlobalGoals.Goals[i].Triggers[1].VariableType == 0) { GlobalGoals.Goals[i].Triggers[1].Variable = 0; } GlobalGoals.Goals[i].T1AndOrT2 = br.ReadBoolean(); stream.Position += 2; } #endregion #region Briefing Briefing.Length = br.ReadInt16(); Briefing.Unknown1 = br.ReadInt16(); stream.Position += 6; // StartLength, EventsLength, Res(0) for (i = 0; i < 12; i++) { stream.Read(buffer, 0, 0x40); Buffer.BlockCopy(buffer, 0, Briefing.Events, 0x40 * i, 0x40); } stream.Read(buffer, 0, 0x20); Buffer.BlockCopy(buffer, 0, Briefing.Events, 0x300, 0x20); for (i = 0; i < 32; i++) { int j = br.ReadInt16(); if (j > 0) { Briefing.BriefingTag[i] = new string(br.ReadChars(j)); } } for (i = 0; i < 32; i++) { int j = br.ReadInt16(); if (j > 0) { Briefing.BriefingString[i] = new string(br.ReadChars(j)); } } #endregion #region Questions for (i = 0; i < 10; i++) { int j, k, l = 0; j = br.ReadInt16(); //read the question length, we're just not going to save it if (j == 1) { stream.Position++; //if it's just the return, get rid of it continue; } if (j == 0) { continue; } for (k = 0; k < j; k++) { BriefingQuestions.PreMissQuestions[i] += br.ReadChar().ToString(); l++; if (stream.ReadByte() == 10) { break; } else { stream.Position--; } } l++; for (k = l; k < j; k++) { int b = stream.ReadByte(); switch (b) //TIE uses char(2) and char(1) for bolding in this section { case 1: BriefingQuestions.PreMissAnswers[i] += "]"; break; case 2: BriefingQuestions.PreMissAnswers[i] += "["; break; case 10: BriefingQuestions.PreMissAnswers[i] += "\r\n"; //because txt doesn't like \n by itself break; default: BriefingQuestions.PreMissAnswers[i] += Convert.ToChar(b).ToString(); break; } } } for (i = 0; i < 10; i++) { int j, k, l = 2; j = br.ReadInt16(); //also got rid of saving here, calc'ing on the fly if (j == 3) { stream.Position += 3; // goddamn TFW-isms continue; } if (j == 0) { continue; } BriefingQuestions.PostTrigger[i] = br.ReadByte(); BriefingQuestions.PostTrigType[i] = br.ReadByte(); for (k = 0; k < j; k++) { BriefingQuestions.PostMissQuestions[i] += br.ReadChar().ToString(); l++; if (stream.ReadByte() == 10) { break; } else { stream.Position--; } } l++; for (k = l; k < j; k++) { int b = stream.ReadByte(); switch (b) { case 0: k = j; break; case 1: BriefingQuestions.PostMissAnswers[i] += "]"; break; case 2: BriefingQuestions.PostMissAnswers[i] += "["; break; case 10: BriefingQuestions.PostMissAnswers[i] += "\r\n"; break; case 255: k = j; break; default: BriefingQuestions.PostMissAnswers[i] += Convert.ToChar(b).ToString(); break; } } } #endregion MissionPath = stream.Name; }