/// <summary> /// Remove a given room sector's FD and reset its FDIndex to 0. /// </summary> public void RemoveFloorData(TRRoomSector sector) { if (_entries.Remove(sector.FDIndex)) { sector.FDIndex = 0; } }
/// <summary> /// Create a slot in the FD for a room sector that currently points to dummy FD. /// </summary> public void CreateFloorData(TRRoomSector sector) { int index; if (_entries.Count == 0) { // Highly unlikely that we would have cleared all FD, but in any case the // first index should always be 1 index = 1; } else { // Get the highest index, which is the last key as we use a SortedDictionary. // Add the total length of the entries at that key to get the next index for // allocating to this sector. index = _entries.Keys.ToList().Last(); List <FDEntry> entries = _entries[index]; foreach (FDEntry entry in entries) { index += entry.Flatten().Length; } } _entries.Add(index, new List <FDEntry>()); sector.FDIndex = (ushort)index; }
public void FloorData_RemoveFDTest() { //Read Dragons Lair data TR2LevelReader reader = new TR2LevelReader(); TR2Level lvl = reader.ReadLevel("xian.tr2"); //Parse the floordata using FDControl FDControl fdataReader = new FDControl(); fdataReader.ParseFromLevel(lvl); //Find a sector that currently has floor data int room, roomSector = -1; for (room = 0; room < lvl.NumRooms; room++) { roomSector = lvl.Rooms[room].SectorList.ToList().FindIndex(s => s.FDIndex > 0); if (roomSector != -1) { break; } } if (roomSector == -1) { Assert.Fail("Could not locate a Room Sector that has floor data associated with it."); } TRRoomSector sector = lvl.Rooms[room].SectorList[roomSector]; // Remove the FD for this sector fdataReader.RemoveFloorData(sector); Assert.AreEqual(sector.FDIndex, 0, "Sector still has FD allocated."); //Write the data back fdataReader.WriteToLevel(lvl); //Save it and read it back in TR2LevelWriter writer = new TR2LevelWriter(); writer.WriteLevelToFile(lvl, "TEST.tr2"); lvl = reader.ReadLevel("TEST.tr2"); //Reassign the sector sector = lvl.Rooms[room].SectorList[roomSector]; fdataReader = new FDControl(); fdataReader.ParseFromLevel(lvl); //Ensure the sector still has FD associated with it Assert.AreEqual(sector.FDIndex, 0, "Sector still has FD after write/read."); }
public void FloorData_InsertFDTest() { //Read Dragons Lair data TR2LevelReader reader = new TR2LevelReader(); TR2Level lvl = reader.ReadLevel("xian.tr2"); //Parse the floordata using FDControl FDControl fdataReader = new FDControl(); fdataReader.ParseFromLevel(lvl); //Find a sector that currently has no floor data int room, roomSector = -1; for (room = 0; room < lvl.NumRooms; room++) { roomSector = lvl.Rooms[room].SectorList.ToList().FindIndex(s => s.FDIndex == 0); if (roomSector != -1) { break; } } if (roomSector == -1) { Assert.Fail("Could not locate a Room Sector that does not have floor data associated with it."); } TRRoomSector sector = lvl.Rooms[room].SectorList[roomSector]; // Create a slot in the FD for this sector fdataReader.CreateFloorData(sector); Assert.AreNotEqual(sector.FDIndex, 0, "Sector does not have FD allocated."); // Add a music trigger fdataReader.Entries[sector.FDIndex].Add(new FDTriggerEntry { Setup = new FDSetup(FDFunctions.Trigger), TrigSetup = new FDTrigSetup(), TrigActionList = new List <FDActionListItem> { new FDActionListItem { TrigAction = FDTrigAction.PlaySoundtrack, Parameter = 40 } } }); //Write the data back fdataReader.WriteToLevel(lvl); //Save it and read it back in TR2LevelWriter writer = new TR2LevelWriter(); writer.WriteLevelToFile(lvl, "TEST.tr2"); lvl = reader.ReadLevel("TEST.tr2"); //Reassign the sector sector = lvl.Rooms[room].SectorList[roomSector]; fdataReader = new FDControl(); fdataReader.ParseFromLevel(lvl); //Ensure the sector still has FD associated with it Assert.AreNotEqual(sector.FDIndex, 0, "Sector no longer has FD after write/read."); //Verify there is one entry for this sector Assert.AreEqual(fdataReader.Entries[sector.FDIndex].Count, 1); //Verify the trigger we added matches what we expect FDEntry entry = fdataReader.Entries[sector.FDIndex][0]; Assert.IsTrue(entry is FDTriggerEntry); FDTriggerEntry triggerEntry = entry as FDTriggerEntry; Assert.IsTrue(triggerEntry.Setup.Function == (byte)FDFunctions.Trigger); Assert.IsTrue(triggerEntry.TrigActionList.Count == 1); Assert.IsTrue(triggerEntry.TrigActionList[0].TrigAction == FDTrigAction.PlaySoundtrack); Assert.IsTrue(triggerEntry.TrigActionList[0].Parameter == 40); }
private void RandomizeSecretTracks(TR2Level level, FDControl floorData) { // Generate new triggers for secrets to allow different sounds for each one List <TRAudioTrack> secretTracks = _tracks[TRAudioCategory.Secret]; Dictionary <int, TR2Entity> secrets = GetSecretItems(level); foreach (int entityIndex in secrets.Keys) { TR2Entity secret = secrets[entityIndex]; TRRoomSector sector = FDUtilities.GetRoomSector(secret.X, secret.Y, secret.Z, secret.Room, level, floorData); if (sector.FDIndex == 0) { // The secret is positioned on a tile that currently has no FD, so create it floorData.CreateFloorData(sector); } List <FDEntry> entries = floorData.Entries[sector.FDIndex]; FDTriggerEntry existingTriggerEntry = entries.Find(e => e is FDTriggerEntry) as FDTriggerEntry; bool existingEntityPickup = false; if (existingTriggerEntry != null) { if (existingTriggerEntry.TrigType == FDTrigType.Pickup && existingTriggerEntry.TrigActionList[0].Parameter == entityIndex) { // GW gold secret (default location) already has a pickup trigger to spawn the // TRex (or whatever enemy) so we'll just append to that item list here existingEntityPickup = true; } else { // There is already a non-pickup trigger for this sector so while nothing is wrong with // adding a pickup trigger, the game ignores it. So in this instance, the sound that // plays will just be whatever is set in the script. continue; } } // Generate a new music action FDActionListItem musicAction = new FDActionListItem { TrigAction = FDTrigAction.PlaySoundtrack, Parameter = secretTracks[_generator.Next(0, secretTracks.Count)].ID }; // For GW default gold, just append it if (existingEntityPickup) { existingTriggerEntry.TrigActionList.Add(musicAction); } else { entries.Add(new FDTriggerEntry { // The values here are replicated from Trigger#112 (in trview) in GW. // The first action list must be the entity being picked up and so // remaining action list items are actioned on pick up. Setup = new FDSetup { Value = 1028 }, TrigSetup = new FDTrigSetup { Value = 15872 }, TrigActionList = new List <FDActionListItem> { new FDActionListItem { TrigAction = FDTrigAction.Object, Parameter = (ushort)entityIndex }, musicAction } }); } } }