Skip to content

Commit

Permalink
Add support for Unfinished Business (#580)
Browse files Browse the repository at this point in the history
See #580 for details.
Resolves #579.
  • Loading branch information
lahm86 committed Dec 10, 2023
1 parent 1582983 commit ba5a8a0
Show file tree
Hide file tree
Showing 144 changed files with 40,673 additions and 1,115 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## [Unreleased](https://github.com/LostArtefacts/TR-Rando/compare/V1.7.3...master) - xxxx-xx-xx
- added support for Unfinished Business and playing in combined game mode for TR1 (#580)
- added a TR2 secret pack (Eycore) (#559)
- added a TR2 secret pack (Towandaa) (#558)
- added more return paths to TR2 and TR3 (#563)
Expand All @@ -8,8 +9,12 @@
- added an option to control key item continuity e.g. The Seraph being placed as an item in Barkhang Monastery if The Deck hasn't been visited (#474)
- added item randomization to Home Sweet Home, provided the level starts with weapons and ammo already (#474)
- added support for TR1X 3.0, including randomized enemy item drops (#572)
- added support for Lara's gym outfit in all levels in TR1 (#580)
- fixed spelling mistakes in TR1 French gamestring localization (#560)
- fixed a key item softlock in Diving Area (#564)
- fixed Pierre not spawning if he is positioned underwater (he will now always spawn on land) (#580)
- fixed certain enemy combinations causing import failures in TR2 (#577)
- improved secret reward allocation in TR1 to be fairer (#580)
- improved changelog, readme and contributing documentation
- improved regular item, key item, and secret item location generation and selection in TR1-3 (#474)
- removed TombATI support (#572)
Expand Down
Binary file modified Deps/TRGE.Coord.dll
Binary file not shown.
Binary file modified Deps/TRGE.Core.dll
Binary file not shown.
1 change: 1 addition & 0 deletions LocationExport/LocationExport.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<WarningLevel>4</WarningLevel>
<OutputType>Exe</OutputType>
<SelfContained>false</SelfContained>
<Copyright>Copyright © Tomb Raider Community 2023</Copyright>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion LocationExport/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void Main(string[] args)
}
else if (levelType == "TR1")
{
foreach (string lvl in TR1LevelNames.AsList)
foreach (string lvl in TR1LevelNames.AsListWithGold)
{
if (File.Exists(lvl))
{
Expand Down
1 change: 1 addition & 0 deletions ModelExport/ModelExport.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<WarningLevel>4</WarningLevel>
<OutputType>Exe</OutputType>
<SelfContained>false</SelfContained>
<Copyright>Copyright © Tomb Raider Community 2023</Copyright>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img alt="TR Rando" src="Resources/randomizerlogo.png"/>
</p>

TR Rando is a randomizer tool for the classic Tomb Raider series (TR 1-3). It allows you to change many aspects of the
TR Rando is a randomizer tool for the classic Tomb Raider series (TR 1-3 and Unfinished Business). It allows you to change many aspects of the
original levels, such as item pickups, secrets, enemies, Lara's appearance, level order, text...[and so much more](#features).

## Installation
Expand Down
4 changes: 4 additions & 0 deletions Resources/Documentation/RETURNPATHS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Following are details on the return paths that are available. See `Global Settin
| Natla's Mines | Trapdoors added in the TNT area to return back across the lava or back to the start. |
| Atlantis | Link rooms added between rooms 30 and 50. |
| The Great Pyramid | _Not implemented due to trap behaviour._ |
| Return to Egypt | Door added between rooms 73 and 75. |
| Temple of the Cat | Link rooms added between rooms 0 and 32; step added in room 89. |
| Atlantean Stronghold | Door added between rooms 6 and 62; link room added between rooms 4 and 15. |
| The Hive | Link rooms added between rooms 20 and 23, and 29 and 37. Point of no return remains at room 10. |

## TR2
| Level | Description |
Expand Down
Binary file modified Resources/UI.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions Resources/trview/plugins/key_items/plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ m_KeyNames[1][22183] = "P1 Fuse (conveyor)"
m_KeyNames[1][22148] = "P1 Fuse (Cowboy)"
m_KeyNames[1][22146] = "P1 Fuse (Cowboy, alt)"
m_KeyNames[1][22216] = "P2 Pyramid Key"
m_KeyNames[1][25192] = "K1 Gold Key"
m_KeyNames[1][26146] = "K1 Ornate Key (near pyramid)"
m_KeyNames[1][26196] = "K1 Ornate Key (croc pool)"
m_KeyNames[1][26192] = "K1 Ornate Key (tiers south)"
m_KeyNames[1][26303] = "K1 Ornate Key (tiers north)"
m_KeyNames[1][26269] = "K1 Ornate Key (cubby south)"
m_KeyNames[1][26365] = "K1 Ornate Key (cubby north)"
m_KeyNames[1][26206] = "K1 Ornate Key (cat statue)"

-- TR2
m_KeyNames[2] = {}
Expand Down
1 change: 1 addition & 0 deletions SFXExport/SFXExport.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<WarningLevel>4</WarningLevel>
<OutputType>Exe</OutputType>
<SelfContained>false</SelfContained>
<Copyright>Copyright © Tomb Raider Community 2023</Copyright>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
Expand Down
115 changes: 115 additions & 0 deletions TREnvironmentEditor/Helpers/EMEntityFinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using TRFDControl;
using TRFDControl.Utilities;
using TRLevelControl.Helpers;
using TRLevelControl.Model;

namespace TREnvironmentEditor.Helpers;

public class EMEntityFinder
{
public EMLocation Location { get; set; }
public EMEntityType Type { get; set; }
public List<short> Types { get; set; }

public int GetEntity(TR1Level level)
{
FDControl floorData = new();
floorData.ParseFromLevel(level);

EMLevelData data = EMLevelData.GetData(level);

List<TR1Type> types = new();
if (Type == EMEntityType.Item)
{
types.AddRange(TR1TypeUtilities.GetStandardPickupTypes());
}
else if (Type == EMEntityType.KeyItem)
{
types.AddRange(TR1TypeUtilities.GetKeyItemTypes());
}
if (Types != null)
{
types.AddRange(Types.Select(t => (TR1Type)t));
}

return GetEntity(level.Entities, types, data,
l => FDUtilities.GetRoomSector(l.X, l.Y, l.Z, l.Room, level, floorData));
}

public int GetEntity(TR2Level level)
{
FDControl floorData = new();
floorData.ParseFromLevel(level);

EMLevelData data = EMLevelData.GetData(level);

List<TR2Type> types = new();
if (Type == EMEntityType.Item)
{
types.AddRange(TR2TypeUtilities.GetStandardPickupTypes());
}
else if (Type == EMEntityType.KeyItem)
{
types.AddRange(TR2TypeUtilities.GetKeyItemTypes());
}
if (Types != null)
{
types.AddRange(Types.Select(t => (TR2Type)t));
}

return GetEntity(level.Entities, types, data,
l => FDUtilities.GetRoomSector(l.X, l.Y, l.Z, l.Room, level, floorData));
}

public int GetEntity(TR3Level level)
{
FDControl floorData = new();
floorData.ParseFromLevel(level);

EMLevelData data = EMLevelData.GetData(level);

List<TR3Type> types = new();
if (Type == EMEntityType.Item)
{
types.AddRange(TR3TypeUtilities.GetStandardPickupTypes());
}
else if (Type == EMEntityType.KeyItem)
{
types.AddRange(TR3TypeUtilities.GetKeyItemTypes());
}
if (Types != null)
{
types.AddRange(Types.Select(t => (TR3Type)t));
}

return GetEntity(level.Entities, types, data,
l => FDUtilities.GetRoomSector(l.X, l.Y, l.Z, l.Room, level, floorData));
}

public int GetEntity<E, T>(List<E> entities, List<T> types, EMLevelData data, Func<EMLocation, TRRoomSector> sectorFunc)
where E : TREntity<T>
where T : Enum
{
EMLocation location = new()
{
X = Location.X,
Y = Location.Y,
Z = Location.Z,
Room = data.ConvertRoom(Location.Room)
};

TRRoomSector sector = sectorFunc(location);
for (int i = 0; i < entities.Count; i++)
{
E entity = entities[i];
if (types.Contains(entity.TypeID)
&& entity.Room == location.Room
&& sectorFunc(new() { X = entity.X, Y = entity.Y, Z = entity.Z, Room = entity.Room }) == sector)
{
return i;
}
}

return -1;
}
}
8 changes: 8 additions & 0 deletions TREnvironmentEditor/Helpers/EMEntityType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TREnvironmentEditor.Helpers;

public enum EMEntityType
{
Any,
Item,
KeyItem,
}
4 changes: 4 additions & 0 deletions TREnvironmentEditor/Model/EMType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public enum EMType
SwapFace = 32,
ImportTexture = 33,
CreateStaticMesh = 34,
CreateTexture = 36,

// Entity types 41-60
MoveSlot = 41,
Expand Down Expand Up @@ -57,6 +58,8 @@ public enum EMType
KillLara = 70,
RemoveTriggerAction = 71,
RemoveEntityTriggers = 72,
MergeTriggers = 73,
ResetPickupTrigger = 74,

// Portal types 81-100
VisibilityPortal = 81,
Expand All @@ -81,6 +84,7 @@ public enum EMType
CreateWall = 127,
GenerateLight = 128,
MoveCamera = 129,
LockMusic = 130,

// Models
ImportModel = 141,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace TREnvironmentEditor.Model.Types;
public class EMModifyEntityFunction : BaseEMFunction
{
public int EntityIndex { get; set; }
public EMEntityFinder EntityFinder { get; set; }
public bool? Invisible { get; set; }
public bool? ClearBody { get; set; }
public short? Intensity1 { get; set; }
Expand All @@ -15,19 +16,22 @@ public class EMModifyEntityFunction : BaseEMFunction
public override void ApplyToLevel(TR1Level level)
{
EMLevelData data = GetData(level);
ModifyEntity(level.Entities[data.ConvertEntity(EntityIndex)]);
int entityIndex = EntityFinder?.GetEntity(level) ?? EntityIndex;
ModifyEntity(level.Entities[data.ConvertEntity(entityIndex)]);
}

public override void ApplyToLevel(TR2Level level)
{
EMLevelData data = GetData(level);
ModifyEntity(level.Entities[data.ConvertEntity(EntityIndex)]);
int entityIndex = EntityFinder?.GetEntity(level) ?? EntityIndex;
ModifyEntity(level.Entities[data.ConvertEntity(entityIndex)]);
}

public override void ApplyToLevel(TR3Level level)
{
EMLevelData data = GetData(level);
ModifyEntity(level.Entities[data.ConvertEntity(EntityIndex)]);
int entityIndex = EntityFinder?.GetEntity(level) ?? EntityIndex;
ModifyEntity(level.Entities[data.ConvertEntity(entityIndex)]);
}

private void ModifyEntity(TR1Entity entity)
Expand Down
22 changes: 19 additions & 3 deletions TREnvironmentEditor/Model/Types/Models/EMImportModelFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@ namespace TREnvironmentEditor.Model.Types;
public class EMImportModelFunction : BaseEMFunction
{
public List<short> Models { get; set; }
public Dictionary<short, short> AliasPriority { get; set; }
public bool ForceCinematicOverwrite { get; set; }

public override void ApplyToLevel(TR1Level level)
{
TR1ModelImporter importer = new(Tags?.Contains(EMTag.CommunityPatchOnly) ?? false)
{
Level = level,
EntitiesToImport = Models.Select(m => (TR1Type)m),
DataFolder = @"Resources\TR1\Models"
DataFolder = @"Resources\TR1\Models",
ForceCinematicOverwrite = ForceCinematicOverwrite
};

importer.Data.AliasPriority = GetAliasPriority<TR1Type>();
importer.Import();
}

Expand All @@ -26,9 +30,11 @@ public override void ApplyToLevel(TR2Level level)
{
Level = level,
EntitiesToImport = Models.Select(m => (TR2Type)m),
DataFolder = @"Resources\TR2\Models"
DataFolder = @"Resources\TR2\Models",
ForceCinematicOverwrite = ForceCinematicOverwrite
};

importer.Data.AliasPriority = GetAliasPriority<TR2Type>();
importer.Import();
}

Expand All @@ -38,9 +44,19 @@ public override void ApplyToLevel(TR3Level level)
{
Level = level,
EntitiesToImport = Models.Select(m => (TR3Type)m),
DataFolder = @"Resources\TR3\Models"
DataFolder = @"Resources\TR3\Models",
ForceCinematicOverwrite = ForceCinematicOverwrite
};

importer.Data.AliasPriority = GetAliasPriority<TR3Type>();
importer.Import();
}

private Dictionary<T, T> GetAliasPriority<T>()
where T : Enum
{
return AliasPriority?
.Select(kv => new KeyValuePair<T, T>((T)(object)(int)kv.Key, (T)(object)(int)kv.Value))
.ToDictionary(kv => kv.Key, kv => kv.Value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,34 @@ public class EMAdjustVisibilityPortalFunction : BaseEMFunction

public override void ApplyToLevel(TR1Level level)
{
EMLevelData data = new() { NumRooms = level.NumRooms };
AdjustPortal(Array.Find(level.Rooms[data.ConvertRoom(BaseRoom)].Portals, p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
EMLevelData data = GetData(level);
AdjustPortals(level.Rooms[data.ConvertRoom(BaseRoom)].Portals.Where(p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
}

public override void ApplyToLevel(TR2Level level)
{
EMLevelData data = new() { NumRooms = level.NumRooms };
AdjustPortal(Array.Find(level.Rooms[data.ConvertRoom(BaseRoom)].Portals, p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
EMLevelData data = GetData(level);
AdjustPortals(level.Rooms[data.ConvertRoom(BaseRoom)].Portals.Where(p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
}

public override void ApplyToLevel(TR3Level level)
{
EMLevelData data = new() { NumRooms = level.NumRooms };
AdjustPortal(Array.Find(level.Rooms[data.ConvertRoom(BaseRoom)].Portals, p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
EMLevelData data = GetData(level);
AdjustPortals(level.Rooms[data.ConvertRoom(BaseRoom)].Portals.Where(p => p.AdjoiningRoom == data.ConvertRoom(AdjoiningRoom)));
}

private void AdjustPortal(TRRoomPortal portal)
private void AdjustPortals(IEnumerable<TRRoomPortal> portals)
{
if (portal == null)
foreach (TRRoomPortal portal in portals)
{
return;
}

foreach (int vertexIndex in VertexChanges.Keys)
{
TRVertex currentVertex = portal.Vertices[vertexIndex];
TRVertex vertexChange = VertexChanges[vertexIndex];
currentVertex.X += vertexChange.X;
currentVertex.Y += vertexChange.Y;
currentVertex.Z += vertexChange.Z;
foreach (int vertexIndex in VertexChanges.Keys)
{
TRVertex currentVertex = portal.Vertices[vertexIndex];
TRVertex vertexChange = VertexChanges[vertexIndex];
currentVertex.X += vertexChange.X;
currentVertex.Y += vertexChange.Y;
currentVertex.Z += vertexChange.Z;
}
}
}
}
5 changes: 5 additions & 0 deletions TREnvironmentEditor/Model/Types/Rooms/EMCreateRoomFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,11 @@ private static sbyte GetSectorHeight(int sectorIndex, Dictionary<sbyte, List<int

private void GenerateFaces(List<TRRoomSector> sectors, List<TRFace4> faces, List<TRVertex> vertices)
{
if (Textures == null)
{
return;
}

for (int x = 0; x < Width; x++)
{
for (int z = 0; z < Depth; z++)
Expand Down

0 comments on commit ba5a8a0

Please sign in to comment.