Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous TRR fixes #704

Merged
merged 20 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
chreden marked this conversation as resolved.
Show resolved Hide resolved
{
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
Loading