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

Fix miscellaneous TR3 issues #678

Merged
merged 9 commits into from
May 20, 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
12 changes: 9 additions & 3 deletions TRDataControl/Data/TR3DataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,15 @@ public IEnumerable<TR3SFX> GetHardcodedSounds(TR3Type type)
= new() { TR3Type.Quest2_M_H },

[TR3Type.Pistols_P] =
new() { TR3Type.LaraPistolAnimation_H, TR3Type.Gunflare_H, TR3Type.Pistols_M_H, TR3Type.PistolAmmo_P, TR3Type.PistolAmmo_M_H },
new() { TR3Type.Gunflare_H, TR3Type.Pistols_M_H, TR3Type.PistolAmmo_P },
[TR3Type.PistolAmmo_P] =
new() { TR3Type.PistolAmmo_M_H },
[TR3Type.Shotgun_P] =
new() { TR3Type.LaraShotgunAnimation_H, TR3Type.Gunflare_H, TR3Type.Shotgun_M_H, TR3Type.ShotgunAmmo_P, TR3Type.ShotgunAmmo_M_H },
[TR3Type.Deagle_P] =
new() { TR3Type.LaraDeagleAnimation_H, TR3Type.Gunflare_H, TR3Type.Deagle_M_H, TR3Type.DeagleAmmo_P, TR3Type.DeagleAmmo_M_H },
new() { TR3Type.Gunflare_H, TR3Type.Deagle_M_H, TR3Type.DeagleAmmo_P, TR3Type.DeagleAmmo_M_H },
[TR3Type.Uzis_P] =
new() { TR3Type.LaraUziAnimation_H, TR3Type.Gunflare_H, TR3Type.Uzis_M_H, TR3Type.UziAmmo_P, TR3Type.UziAmmo_M_H },
new() { TR3Type.Gunflare_H, TR3Type.Uzis_M_H, TR3Type.UziAmmo_P, TR3Type.UziAmmo_M_H },
[TR3Type.Harpoon_P] =
new() { TR3Type.LaraHarpoonAnimation_H, TR3Type.Harpoon_M_H, TR3Type.Harpoons_P, TR3Type.Harpoons_M_H, TR3Type.HarpoonSingle2 },
[TR3Type.MP5_P] =
Expand All @@ -195,6 +197,10 @@ public IEnumerable<TR3SFX> GetHardcodedSounds(TR3Type type)
new() { TR3Type.LaraRocketAnimation_H, TR3Type.RocketLauncher_M_H, TR3Type.Rockets_P, TR3Type.Rockets_M_H, TR3Type.RocketSingle },
[TR3Type.GrenadeLauncher_P] =
new() { TR3Type.LaraGrenadeAnimation_H, TR3Type.GrenadeLauncher_M_H, TR3Type.Grenades_P, TR3Type.Grenades_M_H, TR3Type.GrenadeSingle },
[TR3Type.SmallMed_P] =
new() { TR3Type.SmallMed_M_H },
[TR3Type.LargeMed_P] =
new() { TR3Type.LargeMed_M_H },
};

private static readonly Dictionary<TR3Type, List<TR3Type>> _typeAliases = new()
Expand Down
17 changes: 17 additions & 0 deletions TRDataControl/Transport/TR3/TR3DataExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,21 @@ protected override TRDictionary<TR3Type, TRSpriteSequence> SpriteSequences

protected override List<TRCinematicFrame> CinematicFrames
=> Level.CinematicFrames;

protected override void PreCreation(TR3Level level, TR3Type type, TRBlobType blobType)
{
switch (type)
{
case TR3Type.Quest1_P:
case TR3Type.Quest1_M_H:
level.Models.ChangeKey(TR3Type.Puzzle1_P, TR3Type.Quest1_P);
level.Models.ChangeKey(TR3Type.Puzzle1_M_H, TR3Type.Quest1_M_H);
break;
case TR3Type.Quest2_P:
case TR3Type.Quest2_M_H:
level.Models.ChangeKey(TR3Type.Puzzle1_P, TR3Type.Quest2_P);
level.Models.ChangeKey(TR3Type.Puzzle1_M_H, TR3Type.Quest2_M_H);
break;
}
}
}
11 changes: 7 additions & 4 deletions TRDataControl/Transport/TR3/TR3MassExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ protected override TR3Level ReadLevel(string path)
{
[TR3LevelNames.JUNGLE] = new()
{
TR3Type.LaraIndia, TR3Type.Monkey, TR3Type.Tiger, TR3Type.Door1
TR3Type.LaraIndia, TR3Type.Monkey, TR3Type.Tiger, TR3Type.Door1,
TR3Type.Pistols_P, TR3Type.PistolAmmo_P, TR3Type.Shotgun_P, TR3Type.Deagle_P, TR3Type.Uzis_P,
TR3Type.MP5_P, TR3Type.Harpoon_P, TR3Type.RocketLauncher_P, TR3Type.GrenadeLauncher_P,
TR3Type.SmallMed_P, TR3Type.LargeMed_P,
},
[TR3LevelNames.RUINS] = new()
{
Expand All @@ -34,7 +37,7 @@ protected override TR3Level ReadLevel(string path)
},
[TR3LevelNames.COASTAL] = new()
{
TR3Type.LaraCoastal, TR3Type.Croc, TR3Type.TribesmanAxe, TR3Type.TribesmanDart
TR3Type.LaraCoastal, TR3Type.Croc, TR3Type.TribesmanAxe, TR3Type.TribesmanDart, TR3Type.Quest1_P
},
[TR3LevelNames.CRASH] = new()
{
Expand Down Expand Up @@ -93,9 +96,9 @@ protected override TR3Level ReadLevel(string path)
{
TR3Type.Willie, TR3Type.RXGunLad
},
[TR3LevelNames.HALLOWS] = new()
[TR3LevelNames.MADHOUSE] = new()
{

TR3Type.Quest2_P
},
[TR3LevelNames.ASSAULT] = new()
{
Expand Down
5 changes: 5 additions & 0 deletions TRImageControl/Palette/TRPalette16Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public int Import(TRColour4 colour)
{
int index = _palette.FindIndex(c
=> c.Red == colour.Red && c.Green == colour.Green && c.Blue == colour.Blue);
if (_freeIndices.Contains(index))
{
// Avoid assigning and then later repurposing the same index.
index = -1;
}

if (index == -1)
{
Expand Down
60 changes: 10 additions & 50 deletions TRLevelControl/Model/Common/TRObjectTexture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,63 +98,23 @@ public List<TRObjectTextureVert> GetExtendedPoints()

public void FlipHorizontal()
{
switch (UVMode)
(Vertices[1], Vertices[0]) = (Vertices[0], Vertices[1]);
if (!HasTriangleVertex)
{
case TRUVMode.NW_Clockwise:
UVMode = TRUVMode.NE_AntiClockwise;
break;
case TRUVMode.NE_AntiClockwise:
UVMode = TRUVMode.NW_Clockwise;
break;
case TRUVMode.SW_AntiClockwise:
UVMode = TRUVMode.SE_Clockwise;
break;
case TRUVMode.SE_Clockwise:
UVMode = TRUVMode.SW_AntiClockwise;
break;
case TRUVMode.NE_Clockwise:
UVMode = TRUVMode.NW_AntiClockwise;
break;
case TRUVMode.NW_AntiClockwise:
UVMode = TRUVMode.NE_Clockwise;
break;
case TRUVMode.SW_Clockwise:
UVMode = TRUVMode.SE_AntiClockwise;
break;
case TRUVMode.SE_AntiClockwise:
UVMode = TRUVMode.SW_Clockwise;
break;
(Vertices[3], Vertices[2]) = (Vertices[2], Vertices[3]);
}
}

public void FlipVertical()
{
switch (UVMode)
if (HasTriangleVertex)
{
case TRUVMode.NW_Clockwise:
UVMode = TRUVMode.SW_AntiClockwise;
break;
case TRUVMode.SW_AntiClockwise:
UVMode = TRUVMode.NW_Clockwise;
break;
case TRUVMode.NE_Clockwise:
UVMode = TRUVMode.SE_AntiClockwise;
break;
case TRUVMode.SE_AntiClockwise:
UVMode = TRUVMode.NE_Clockwise;
break;
case TRUVMode.SE_Clockwise:
UVMode = TRUVMode.NE_AntiClockwise;
break;
case TRUVMode.NE_AntiClockwise:
UVMode = TRUVMode.SE_Clockwise;
break;
case TRUVMode.SW_Clockwise:
UVMode = TRUVMode.NW_AntiClockwise;
break;
case TRUVMode.NW_AntiClockwise:
UVMode = TRUVMode.SW_Clockwise;
break;
(Vertices[2], Vertices[0]) = (Vertices[0], Vertices[2]);
}
else
{
(Vertices[3], Vertices[0]) = (Vertices[0], Vertices[3]);
(Vertices[2], Vertices[1]) = (Vertices[1], Vertices[2]);
}
}

Expand Down
16 changes: 8 additions & 8 deletions TRLevelControlTests/Common/TextureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -689,12 +689,12 @@ static void Test(TRObjectTexture texture, TRUVMode expected)
}

Test(MakeNWClockwiseQuad(), TRUVMode.NE_AntiClockwise);
Test(MakeNEClockwiseQuad(), TRUVMode.NW_AntiClockwise);
Test(MakeNEClockwiseQuad(), TRUVMode.SE_AntiClockwise);
Test(MakeSEClockwiseQuad(), TRUVMode.SW_AntiClockwise);
Test(MakeSWClockwiseQuad(), TRUVMode.SE_AntiClockwise);
Test(MakeNWAntiClockwiseQuad(), TRUVMode.NE_Clockwise);
Test(MakeSWClockwiseQuad(), TRUVMode.NW_AntiClockwise);
Test(MakeNWAntiClockwiseQuad(), TRUVMode.SW_Clockwise);
Test(MakeNEAntiClockwiseQuad(), TRUVMode.NW_Clockwise);
Test(MakeSEAntiClockwiseQuad(), TRUVMode.SW_Clockwise);
Test(MakeSEAntiClockwiseQuad(), TRUVMode.NE_Clockwise);
Test(MakeSWAntiClockwiseQuad(), TRUVMode.SE_Clockwise);
}

Expand All @@ -708,12 +708,12 @@ static void Test(TRObjectTexture texture, TRUVMode expected)
}

Test(MakeNWClockwiseQuad(), TRUVMode.SW_AntiClockwise);
Test(MakeNEClockwiseQuad(), TRUVMode.SE_AntiClockwise);
Test(MakeNEClockwiseQuad(), TRUVMode.NW_AntiClockwise);
Test(MakeSEClockwiseQuad(), TRUVMode.NE_AntiClockwise);
Test(MakeSWClockwiseQuad(), TRUVMode.NW_AntiClockwise);
Test(MakeNWAntiClockwiseQuad(), TRUVMode.SW_Clockwise);
Test(MakeSWClockwiseQuad(), TRUVMode.SE_AntiClockwise);
Test(MakeNWAntiClockwiseQuad(), TRUVMode.NE_Clockwise);
Test(MakeNEAntiClockwiseQuad(), TRUVMode.SE_Clockwise);
Test(MakeSEAntiClockwiseQuad(), TRUVMode.NE_Clockwise);
Test(MakeSEAntiClockwiseQuad(), TRUVMode.SW_Clockwise);
Test(MakeSWAntiClockwiseQuad(), TRUVMode.NW_Clockwise);
}

Expand Down
70 changes: 38 additions & 32 deletions TRRandomizerCore/Randomizers/TR3/TR3ItemRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ namespace TRRandomizerCore.Randomizers;

public class TR3ItemRandomizer : BaseTR3Randomizer
{
private static readonly List<TR3Type> _assaultPickupModels = new()
{
TR3Type.PistolAmmo_P,
TR3Type.Shotgun_P,
TR3Type.Deagle_P,
TR3Type.Uzis_P,
TR3Type.MP5_P,
TR3Type.RocketLauncher_P,
TR3Type.GrenadeLauncher_P,
TR3Type.Harpoon_P,
TR3Type.SmallMed_P,
TR3Type.LargeMed_P,
TR3Type.LaraDeagleAnimation_H_Nevada,
TR3Type.LaraUziAnimation_H_Nevada,
};

private readonly Dictionary<string, List<Location>> _excludedLocations;
private readonly Dictionary<string, List<Location>> _pistolLocations;

Expand Down Expand Up @@ -92,41 +108,11 @@ public void RandomizeKeyItems()

private bool ImportAssaultModels(TR3CombinedLevel level)
{
// #312 We need all item models plus Lara's associated weapon animations for the
// assault course. The DEagle and Uzi anims will match Lara's default home outfit
// - outfit rando will take care of replacing these if it's enabled.
TR3DataImporter importer = new()
{
Level = level.Data,
LevelName = level.Name,
ClearUnusedSprites = false,
TypesToImport = new List<TR3Type>
{
TR3Type.LaraShotgunAnimation_H,
TR3Type.LaraDeagleAnimation_H_Home,
TR3Type.LaraUziAnimation_H_Home,
TR3Type.LaraMP5Animation_H,
TR3Type.LaraRocketAnimation_H,
TR3Type.LaraGrenadeAnimation_H,
TR3Type.LaraHarpoonAnimation_H,
TR3Type.PistolAmmo_P,
TR3Type.Shotgun_P, TR3Type.Shotgun_M_H,
TR3Type.ShotgunAmmo_P, TR3Type.ShotgunAmmo_M_H,
TR3Type.Deagle_P, TR3Type.Deagle_M_H,
TR3Type.DeagleAmmo_P, TR3Type.DeagleAmmo_M_H,
TR3Type.Uzis_P, TR3Type.Uzis_M_H,
TR3Type.UziAmmo_P, TR3Type.UziAmmo_M_H,
TR3Type.MP5_P, TR3Type.MP5_M_H,
TR3Type.MP5Ammo_P, TR3Type.MP5Ammo_M_H,
TR3Type.RocketLauncher_M_H, TR3Type.RocketLauncher_P,
TR3Type.Rockets_M_H, TR3Type.Rockets_P,
TR3Type.GrenadeLauncher_M_H, TR3Type.GrenadeLauncher_P,
TR3Type.Grenades_M_H, TR3Type.Grenades_P,
TR3Type.Harpoon_M_H, TR3Type.Harpoon_P,
TR3Type.Harpoons_M_H, TR3Type.Harpoons_P,
TR3Type.SmallMed_P, TR3Type.SmallMed_M_H,
TR3Type.LargeMed_P, TR3Type.LargeMed_M_H
},
TypesToImport = _assaultPickupModels,
DataFolder = GetResourcePath(@"TR3\Objects")
};

Expand All @@ -138,8 +124,28 @@ private bool ImportAssaultModels(TR3CombinedLevel level)

try
{
// Try to import the selected models into the level.
importer.Import();

// Manipulate the Nevada leg meshes to match the home outfit.
// Anything using vertex 26 and above is a holstered gun face.
TRModel pistolModel = level.Data.Models[TR3Type.LaraPistolAnimation_H];
TRModel deagleModel = level.Data.Models[TR3Type.LaraDeagleAnimation_H];
TRModel uzisModel = level.Data.Models[TR3Type.LaraUziAnimation_H];

static void CopyFaces(TRMesh baseMesh, TRMesh targetMesh)
{
static bool regularFace(TRMeshFace f) => f.Vertices.All(v => v < 26);
targetMesh.TexturedRectangles.RemoveAll(regularFace);
targetMesh.TexturedTriangles.RemoveAll(regularFace);
targetMesh.TexturedRectangles.AddRange(baseMesh.TexturedRectangles.FindAll(regularFace));
targetMesh.TexturedTriangles.AddRange(baseMesh.TexturedTriangles.FindAll(regularFace));
}

deagleModel.Meshes[1] = pistolModel.Meshes[1];
CopyFaces(pistolModel.Meshes[4], deagleModel.Meshes[4]);
CopyFaces(pistolModel.Meshes[1], uzisModel.Meshes[1]);
CopyFaces(pistolModel.Meshes[4], uzisModel.Meshes[4]);

return true;
}
catch (PackingException)
Expand Down
4 changes: 4 additions & 0 deletions TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ private static void CreateTrapdoorTrigger(TR3Entity door, short doorIndex, TR3Le

private void PlaceAllSecrets(TR3CombinedLevel level, List<TR3Type> pickupTypes, TRSecretRoom<TR2Entity> rewardRoom)
{
if (!_locations.ContainsKey(level.Name))
{
return;
}
List<Location> locations = _locations[level.Name];

TRSecretPlacement<TR3Type> secret = new();
Expand Down
2 changes: 1 addition & 1 deletion TRRandomizerCore/Resources/TR2/Textures/wireframing.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"ExcludedTextures": [ 1437, 1505, 1506, 1507 ]
},
"HOUSE.TR2": {
"ExcludedTextures": [ 93, 96, 97, 125 ]
"ExcludedTextures": [ 1283, 1284, 1285, 1286 ]
},
"ASSAULT.TR2": {
"ExcludedTextures": [ 799, 800, 801, 802 ]
Expand Down
Loading
Loading