Skip to content

Commit

Permalink
Miscellaneous TRR fixes (#704)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 authored Jun 18, 2024
1 parent d17e7eb commit d47b78c
Show file tree
Hide file tree
Showing 47 changed files with 1,327 additions and 168 deletions.
Binary file modified Deps/TRGE.Coord.dll
Binary file not shown.
Binary file modified Deps/TRGE.Core.dll
Binary file not shown.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ For keeping track of levels while you play, check out the [TRRandoTracker](https
![TR1 Rando](Resources/Screenshots/Compressed/TR1_3.jpg)
![TR1 Rando](Resources/Screenshots/Compressed/TR1_4.jpg)
![TR1R Rando](Resources/Screenshots/Compressed/TR1R_1.jpg)
![TR1R Rando](Resources/Screenshots/Compressed/TR1R_2.jpg)
![TR2 Rando](Resources/Screenshots/Compressed/TR2_1.jpg)
![TR2 Rando](Resources/Screenshots/Compressed/TR2_4.jpg)
![TR2 Rando](Resources/Screenshots/Compressed/TR2_5.jpg)
![TR2R Rando](Resources/Screenshots/Compressed/TR2R_1.jpg)
![TR2R Rando](Resources/Screenshots/Compressed/TR2R_2.jpg)
![TR3 Rando](Resources/Screenshots/Compressed/TR3_2.jpg)
![TR3 Rando](Resources/Screenshots/Compressed/TR3_3.jpg)
![TR3R Rando](Resources/Screenshots/Compressed/TR3R_1.jpg)
![TR3R Rando](Resources/Screenshots/Compressed/TR3R_2.jpg)

[View all](Resources/Screenshots).

Expand Down
2 changes: 1 addition & 1 deletion Resources/Documentation/RETURNPATHS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Return paths

Return paths can be added to the majority of levels, which allows repeat exploration without having to save and load. In some cases - such as The River Ganges - it also allows exploring levels fully where it would otherwise not be possible.
Return paths can be added to the majority of levels, which allows repeat exploration without having to save and load. In some cases - such as The River Ganges - it also allows exploring levels fully where it would otherwise not be possible. Return paths cannot currently be applied to TR I-III Remastered.

Following are details on the return paths that are available. See `Global Settings` for managing whether or not these paths are added.

Expand Down
2 changes: 2 additions & 0 deletions Resources/Documentation/SECRETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ The options are:
# TR2
The standard Stone, Jade and Gold dragons will be placed in each level.

Note that in TR2 Remastered, secret rewards cannot be changed: you will always receive the same rewards as per OG. In addition, while secrets are added to Dragon's Lair and Home Sweet Home, you do not receive any rewards for collecting all three in each level.

----
## TR3
Secret randomization logic in TR3 works in exactly the same way as TR1.
Expand Down
Binary file added Resources/Screenshots/Compressed/TR1R_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Screenshots/Compressed/TR2R_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Screenshots/Compressed/TR3R_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Screenshots/TR1R_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Screenshots/TR2R_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Screenshots/TR3R_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Resources/Using/game.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/Using/trr_appid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 23 additions & 20 deletions TRDataControl/Data/Remastered/BaseTRRDataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,33 @@ public void SetData(TRDictionary<TKey, TRModel> pdpData, Dictionary<TKey, TAlias

public void SetPDPData(TRDictionary<TKey, TRModel> pdpData, TKey sourceType, TKey destinationType)
{
TKey translatedKey = TranslateKey(sourceType);
if (!_pdpCache.ContainsKey(sourceType))
lock (_pdpCache)
{
string sourceLevel = GetSourceLevel(sourceType)
?? throw new KeyNotFoundException($"Source PDP file for {sourceType} is undefined");

TRPDPControlBase<TKey> control = GetPDPControl();
TRDictionary<TKey, TRModel> models = control.Read(Path.Combine(PDPFolder, Path.GetFileNameWithoutExtension(sourceLevel) + _pdpExt));
if (models.ContainsKey(translatedKey))
{
_pdpCache[sourceType] = models[translatedKey];
}
else if (models.ContainsKey(destinationType))
{
_pdpCache[sourceType] = models[destinationType];
}
else
TKey translatedKey = TranslateKey(sourceType);
if (!_pdpCache.ContainsKey(sourceType))
{
throw new KeyNotFoundException($"Could not load cached PDP data for {sourceType}");
string sourceLevel = GetSourceLevel(sourceType)
?? throw new KeyNotFoundException($"Source PDP file for {sourceType} is undefined");

TRPDPControlBase<TKey> control = GetPDPControl();
TRDictionary<TKey, TRModel> models = control.Read(Path.Combine(PDPFolder, Path.GetFileNameWithoutExtension(sourceLevel) + _pdpExt));
if (models.ContainsKey(translatedKey))
{
_pdpCache[sourceType] = models[translatedKey];
}
else if (models.ContainsKey(destinationType))
{
_pdpCache[sourceType] = models[destinationType];
}
else
{
throw new KeyNotFoundException($"Could not load cached PDP data for {sourceType}");
}
}
}

translatedKey = TranslateKey(destinationType);
pdpData[translatedKey] = _pdpCache[sourceType];
translatedKey = TranslateKey(destinationType);
pdpData[translatedKey] = _pdpCache[sourceType];
}
}

public void SetMapData(Dictionary<TKey, TAlias> mapData, TKey sourceType, TKey destinationType)
Expand Down
19 changes: 13 additions & 6 deletions TRDataControl/Transport/TRDataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ private void CleanRemovalList()
cleanedEntities.Add(type);
}
}
TypesToRemove = cleanedEntities;

var dependencies = TypesToImport.SelectMany(t => Data.GetDependencies(t)).Select(t => Data.TranslateAlias(t));
TypesToRemove = cleanedEntities.Where(e => !dependencies.Contains(e)).ToList();
}

private void CleanAliases()
Expand Down Expand Up @@ -159,17 +161,22 @@ private void CleanAliases()

private void ValidateBlobList(List<T> modelTypes, List<B> importBlobs)
{
Dictionary<T, List<T>> detectedAliases = new();
foreach (T entity in modelTypes)
Dictionary<T, SortedSet<T>> detectedAliases = new();
foreach (T type in modelTypes)
{
if (Data.IsAlias(entity))
T inferredType = type;
if (Data.AliasPriority?.ContainsKey(type) ?? false)
{
inferredType = Data.GetLevelAlias(LevelName, type);
}
if (Data.IsAlias(inferredType))
{
T masterType = Data.TranslateAlias(entity);
T masterType = Data.TranslateAlias(inferredType);
if (!detectedAliases.ContainsKey(masterType))
{
detectedAliases[masterType] = new();
}
detectedAliases[masterType].Add(entity);
detectedAliases[masterType].Add(inferredType);
}
}

Expand Down
6 changes: 5 additions & 1 deletion TRLevelControl/Build/TRSpriteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ public TRDictionary<T, TRSpriteSequence> ReadSprites(TRLevelReader reader)
{
string sprMarker = new(reader.ReadChars(_sprMarker.Length));
Debug.Assert(sprMarker == _sprMarker);
Debug.Assert(_version != TRGameVersion.TR5 || reader.ReadByte() == 0);
if (_version == TRGameVersion.TR5)
{
byte end = reader.ReadByte();
Debug.Assert(end == 0);
}
}

uint numTextures = reader.ReadUInt32();
Expand Down
3 changes: 2 additions & 1 deletion TRLevelControl/Build/TRTextureBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public List<TRObjectTexture> ReadObjectTextures(TRLevelReader reader)
Debug.Assert(texMarker == _texMarker);
if (_version == TRGameVersion.TR5)
{
Debug.Assert(reader.ReadByte() == 0);
byte end = reader.ReadByte();
Debug.Assert(end == 0);
}
}

Expand Down
17 changes: 17 additions & 0 deletions TRLevelControl/Helpers/TR1TypeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ public static class TR1TypeUtilities
{
public static readonly Dictionary<TR1Type, Dictionary<TR1Type, List<string>>> LevelAliases = new()
{
[TR1Type.LaraMiscAnim_H] = new()
{
[TR1Type.LaraMiscAnim_H_General] =
new() { TR1LevelNames.CAVES, TR1LevelNames.VILCABAMBA, TR1LevelNames.FOLLY, TR1LevelNames.COLOSSEUM, TR1LevelNames.CISTERN, TR1LevelNames.TIHOCAN },
[TR1Type.LaraMiscAnim_H_Valley] =
new() { TR1LevelNames.VALLEY },
[TR1Type.LaraMiscAnim_H_Qualopec] =
new() { TR1LevelNames.QUALOPEC },
[TR1Type.LaraMiscAnim_H_Midas] =
new() { TR1LevelNames.MIDAS },
[TR1Type.LaraMiscAnim_H_Sanctuary] =
new() { TR1LevelNames.SANCTUARY },
[TR1Type.LaraMiscAnim_H_Atlantis] =
new() { TR1LevelNames.ATLANTIS },
[TR1Type.LaraMiscAnim_H_Pyramid] =
new() { TR1LevelNames.PYRAMID },
},
[TR1Type.FlyingAtlantean] = new()
{
[TR1Type.BandagedFlyer] =
Expand Down
15 changes: 15 additions & 0 deletions TRLevelControl/Helpers/TR2TypeUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ public static class TR2TypeUtilities
[TR2Type.LaraAssault] =
new() { TR2LevelNames.ASSAULT },
},
[TR2Type.LaraMiscAnim_H] = new()
{
[TR2Type.LaraMiscAnim_H_Wall] =
new() { TR2LevelNames.GW },
[TR2Type.LaraMiscAnim_H_Venice] =
new() { TR2LevelNames.BARTOLI },
[TR2Type.LaraMiscAnim_H_Unwater] =
new() { TR2LevelNames.RIG, TR2LevelNames.DA, TR2LevelNames.FATHOMS, TR2LevelNames.DORIA, TR2LevelNames.DECK },
[TR2Type.LaraMiscAnim_H_Ice] =
new() { TR2LevelNames.COT, TR2LevelNames.CHICKEN },
[TR2Type.LaraMiscAnim_H_Xian] =
new() { TR2LevelNames.FLOATER, TR2LevelNames.LAIR },
[TR2Type.LaraMiscAnim_H_HSH] =
new() { TR2LevelNames.HOME }
},
[TR2Type.Barracuda] = new()
{
[TR2Type.BarracudaIce] =
Expand Down
9 changes: 9 additions & 0 deletions TRLevelControl/Model/Common/FloorData/FDControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ public void RemoveEntityTriggers(int entityIndex)
}
}

public List<short> GetTriggerRooms<R>(int entityIndex, List<R> rooms)
where R : TRRoom
{
List<FDTriggerEntry> triggers = GetEntityTriggers(entityIndex);
return Enumerable.Range(0, rooms.Count)
.Where(i => rooms[i].Sectors.Any(s => s.FDIndex != 0 && triggers.Any(_entries[s.FDIndex].Contains)))
.Select(i => (short)i).ToList();
}

public TRRoomSector GetRoomSector<R>(int x, int y, int z, short roomNumber, List<R> rooms)
where R : TRRoom
{
Expand Down
3 changes: 2 additions & 1 deletion TRLevelControl/TRGControlBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public static TRGData Read(string filePath)
public static TRGData Read(Stream stream)
{
using TRLevelReader reader = new(stream);
Debug.Assert(reader.ReadUInt32() == _trgMagic);
uint magic = reader.ReadUInt32();
Debug.Assert(magic == _trgMagic);

TRGData data = new();

Expand Down
36 changes: 36 additions & 0 deletions TRLevelControlTests/TR1/FDTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,42 @@ public void GetEntityTriggers()
TestGetEntityTriggers(level.FloorData, 1);
}

[TestMethod]
[Description("Get list of rooms that contain an entity's triggers.")]
public void GetTriggerRooms()
{
TR1Level level = GetTR1TestLevel();

// Check original single trigger
List<short> rooms = level.FloorData.GetTriggerRooms(12, level.Rooms);
Assert.AreEqual(1, rooms.Count);
Assert.IsTrue(rooms.Contains(6));

void AddTestTrigger(TRRoomSector sector)
{
level.FloorData.CreateFloorData(sector);
level.FloorData[sector.FDIndex].Add(new FDTriggerEntry
{
Actions = new()
{
new() { Parameter = 12 }
}
});
}

// Add another in a different room
AddTestTrigger(level.Rooms[4].GetSector(3, 1, TRUnit.Sector));
rooms = level.FloorData.GetTriggerRooms(12, level.Rooms);
Assert.AreEqual(2, rooms.Count);
Assert.IsTrue(rooms.Contains(4));
Assert.IsTrue(rooms.Contains(6));

// Add a third but in the same room - we don't want duplicate room numbers returned
AddTestTrigger(level.Rooms[4].GetSector(3, 2, TRUnit.Sector));
rooms = level.FloorData.GetTriggerRooms(12, level.Rooms);
Assert.AreEqual(2, rooms.Count);
}

[TestMethod]
[Description("Test finding secret triggers.")]
public void GetSecretTriggers()
Expand Down
3 changes: 3 additions & 0 deletions TRRandomizerCore/Helpers/ChecksumTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ public bool Test(string file)
"79e3f05f963acac6f864ba81555cc15d", // MONASTRY.TR2
"cf4f784bdfa0b5794b3437e4d9ed04d8", // ICECAVE.TR2

// TR2R V1.3+
"ef2f5a3e08bd10655c38707e6657c687", // LEVEL5.TR2

// TR3
"5e11d251ddb12b98ebead1883dc12d2a", // HOUSE.TR2
"9befdc5075fdb84450d2ed0533719b12", // JUNGLE.TR2 (International)
Expand Down
2 changes: 2 additions & 0 deletions TRRandomizerCore/Randomizers/Shared/EnvironmentPicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ public List<EMEditorSet> GetRandomAny(EMEditorMapping mapping)
{
// Pick a random number of packs to apply, but at least 1
sets = pool.RandomSelection(_generator, _generator.Next(1, pool.Count + 1));
// Ensure original order is kept as some mods rely on other things happening first
sets.Sort((s1, s2) => pool.IndexOf(s1).CompareTo(pool.IndexOf(s2)));
}

return sets;
Expand Down
5 changes: 1 addition & 4 deletions TRRandomizerCore/Randomizers/Shared/ItemAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,7 @@ public void ApplyItemSwaps(string levelName, List<E> items)
}
}

if (!Settings.AllowEnemyKeyDrops)
{
ExcludeEnemyKeyDrops(items);
}
ExcludeEnemyKeyDrops(items);
}

protected List<E> GetPickups(string levelName, List<E> items, bool isUnarmed)
Expand Down
4 changes: 2 additions & 2 deletions TRRandomizerCore/Randomizers/Shared/LocationPicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class LocationPicker : IRouteManager
private Random _generator;

public Func<Location, bool> TriggerTestAction { get; set; }
public Func<Location, bool, bool> KeyItemTestAction { get; set; }
public Func<Location, bool, List<short>, bool> KeyItemTestAction { get; set; }
public List<ExtRoomInfo> RoomInfos { get; set; }
public int LevelSize { get; private set; }

Expand Down Expand Up @@ -138,7 +138,7 @@ public Location GetKeyItemLocation<T>(int keyItemID, TREntity<T> entity, bool ha
continue;
}

if (KeyItemTestAction != null && !KeyItemTestAction(newLocation, hasPickupTrigger))
if (KeyItemTestAction != null && !KeyItemTestAction(newLocation, hasPickupTrigger, roomPool))
{
continue;
}
Expand Down
Loading

0 comments on commit d47b78c

Please sign in to comment.