diff --git a/TREnvironmentEditor/EMEditorMapping.cs b/TREnvironmentEditor/EMEditorMapping.cs index 396539d34..5d9867353 100644 --- a/TREnvironmentEditor/EMEditorMapping.cs +++ b/TREnvironmentEditor/EMEditorMapping.cs @@ -8,7 +8,7 @@ namespace TREnvironmentEditor { public class EMEditorMapping { - private static readonly EMConverter _converter = new EMConverter(); + public static readonly EMConverter Converter = new EMConverter(); public EMEditorSet All { get; set; } public EMEditorSet NonPurist { get; set; } @@ -34,7 +34,7 @@ public static EMEditorMapping Get(string packPath) { if (File.Exists(packPath)) { - return JsonConvert.DeserializeObject(File.ReadAllText(packPath), _converter); + return JsonConvert.DeserializeObject(File.ReadAllText(packPath), Converter); } return null; diff --git a/TREnvironmentEditor/Model/BaseEMCondition.cs b/TREnvironmentEditor/Model/BaseEMCondition.cs index cb6354462..023300e89 100644 --- a/TREnvironmentEditor/Model/BaseEMCondition.cs +++ b/TREnvironmentEditor/Model/BaseEMCondition.cs @@ -7,5 +7,6 @@ public abstract class BaseEMCondition public EMConditionType ConditionType { get; set; } public abstract bool GetResult(TR2Level level); + public abstract bool GetResult(TR3Level level); } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/BaseEMFunction.cs b/TREnvironmentEditor/Model/BaseEMFunction.cs index c8c1eb6ac..d54d820cc 100644 --- a/TREnvironmentEditor/Model/BaseEMFunction.cs +++ b/TREnvironmentEditor/Model/BaseEMFunction.cs @@ -14,6 +14,7 @@ public abstract class BaseEMFunction public EMType EMType { get; set; } public abstract void ApplyToLevel(TR2Level level); + public abstract void ApplyToLevel(TR3Level level); /// /// Gets the expected vertices for a flat tile. @@ -71,5 +72,16 @@ public ISet GetAdjacentRooms(TR2Room room, bool above) } return rooms; } + + // This allows us to access the last item in a specific list, so if for example one mod has created + // a new room, subsequent mods can retrieve its number using short.MaxValue. + protected int ConvertItemNumber(int itemNumber, ushort numItems) + { + if (itemNumber == short.MaxValue) + { + itemNumber = numItems - 1; + } + return itemNumber; + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Conditions/Entities/EMEntityPropertyCondition.cs b/TREnvironmentEditor/Model/Conditions/Entities/EMEntityPropertyCondition.cs index 66c601f88..7d33ef30f 100644 --- a/TREnvironmentEditor/Model/Conditions/Entities/EMEntityPropertyCondition.cs +++ b/TREnvironmentEditor/Model/Conditions/Entities/EMEntityPropertyCondition.cs @@ -1,12 +1,11 @@ using TRLevelReader.Model; -using TRLevelReader.Model.Enums; namespace TREnvironmentEditor.Model.Conditions { public class EMEntityPropertyCondition : BaseEMCondition { public int EntityIndex { get; set; } - public TR2Entities? EntityType { get; set; } + public short? EntityType { get; set; } public bool? Invisible { get; set; } public bool? ClearBody { get; set; } public short? Intensity1 { get; set; } @@ -15,11 +14,20 @@ public class EMEntityPropertyCondition : BaseEMCondition public override bool GetResult(TR2Level level) { - TR2Entity entity = level.Entities[EntityIndex]; + return GetResult(level.Entities[EntityIndex]); + } + + public override bool GetResult(TR3Level level) + { + return GetResult(level.Entities[EntityIndex]); + } + + private bool GetResult(TR2Entity entity) + { bool result = true; if (EntityType.HasValue) { - result &= (TR2Entities)entity.TypeID == EntityType.Value; + result &= entity.TypeID == EntityType.Value; } if (Invisible.HasValue) { diff --git a/TREnvironmentEditor/Model/EMConditionalEditorSet.cs b/TREnvironmentEditor/Model/EMConditionalEditorSet.cs index 064c77449..79ceb253d 100644 --- a/TREnvironmentEditor/Model/EMConditionalEditorSet.cs +++ b/TREnvironmentEditor/Model/EMConditionalEditorSet.cs @@ -13,5 +13,10 @@ public List GetApplicableSets(TR2Level level) { return Condition.GetResult(level) ? OnTrue : OnFalse; } + + public List GetApplicableSets(TR3Level level) + { + return Condition.GetResult(level) ? OnTrue : OnFalse; + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/EMEditorGroupedSet.cs b/TREnvironmentEditor/Model/EMEditorGroupedSet.cs index 72f115ce3..6810e333c 100644 --- a/TREnvironmentEditor/Model/EMEditorGroupedSet.cs +++ b/TREnvironmentEditor/Model/EMEditorGroupedSet.cs @@ -16,5 +16,14 @@ public void ApplyToLevel(TR2Level level, EMEditorSet follower, IEnumerable excludedTypes) + { + if (Leader.IsApplicable(excludedTypes) && follower.IsApplicable(excludedTypes)) + { + Leader.ApplyToLevel(level, excludedTypes); + follower.ApplyToLevel(level, excludedTypes); + } + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/EMEditorSet.cs b/TREnvironmentEditor/Model/EMEditorSet.cs index 785310414..6275b5144 100644 --- a/TREnvironmentEditor/Model/EMEditorSet.cs +++ b/TREnvironmentEditor/Model/EMEditorSet.cs @@ -8,7 +8,18 @@ public class EMEditorSet : List, ITextureModifier { // A set of modifications that must be done together e.g. adding a ladder and a step - public void ApplyToLevel(TR2Level level, IEnumerable excludedTypes) + public void ApplyToLevel(TR2Level level, IEnumerable excludedTypes = null) + { + if (IsApplicable(excludedTypes)) + { + foreach (BaseEMFunction mod in this) + { + mod.ApplyToLevel(level); + } + } + } + + public void ApplyToLevel(TR3Level level, IEnumerable excludedTypes = null) { if (IsApplicable(excludedTypes)) { @@ -21,12 +32,15 @@ public void ApplyToLevel(TR2Level level, IEnumerable excludedTypes) public bool IsApplicable(IEnumerable excludedTypes) { - // The modification will only be performed if all types in this set are to be included. - foreach (BaseEMFunction mod in this) + if (excludedTypes != null) { - if (excludedTypes.Contains(mod.EMType)) + // The modification will only be performed if all types in this set are to be included. + foreach (BaseEMFunction mod in this) { - return false; + if (excludedTypes.Contains(mod.EMType)) + { + return false; + } } } diff --git a/TREnvironmentEditor/Model/EMType.cs b/TREnvironmentEditor/Model/EMType.cs index b075d2cc5..c6accd05b 100644 --- a/TREnvironmentEditor/Model/EMType.cs +++ b/TREnvironmentEditor/Model/EMType.cs @@ -50,6 +50,8 @@ public enum EMType // Room types 121+ ModifyRoom = 121, ModifyOverlaps = 122, + CopyRoom = 123, + CopyVertexAttributes = 124, // NOOP/Placeholder NOOP = 1000 diff --git a/TREnvironmentEditor/Model/Types/EMPlaceholderFunction.cs b/TREnvironmentEditor/Model/Types/EMPlaceholderFunction.cs index c987d104d..042332ca8 100644 --- a/TREnvironmentEditor/Model/Types/EMPlaceholderFunction.cs +++ b/TREnvironmentEditor/Model/Types/EMPlaceholderFunction.cs @@ -8,5 +8,7 @@ public override void ApplyToLevel(TR2Level level) { // NOOP } + + public override void ApplyToLevel(TR3Level level) { } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Entities/EMAdjustEntityPositionFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMAdjustEntityPositionFunction.cs index 9197cab5e..5c35560c8 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMAdjustEntityPositionFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMAdjustEntityPositionFunction.cs @@ -2,13 +2,12 @@ using System.Linq; using TREnvironmentEditor.Helpers; using TRLevelReader.Model; -using TRLevelReader.Model.Enums; namespace TREnvironmentEditor.Model.Types { public class EMAdjustEntityPositionFunction : BaseEMFunction { - public TR2Entities EntityType { get; set; } + public short EntityType { get; set; } public Dictionary> RoomMap { get; set; } public override void ApplyToLevel(TR2Level level) @@ -16,7 +15,18 @@ public override void ApplyToLevel(TR2Level level) // Example use case is rotating wall blades, which need various different angles across the levels after mirroring. // X, Y, Z in the target relocation will be relative to the current location; the angle will be the new angle. - List entities = level.Entities.ToList().FindAll(e => (TR2Entities)e.TypeID == EntityType); + List entities = level.Entities.ToList().FindAll(e => e.TypeID == EntityType); + AdjustEntities(entities); + } + + public override void ApplyToLevel(TR3Level level) + { + List entities = level.Entities.ToList().FindAll(e => e.TypeID == EntityType); + AdjustEntities(entities); + } + + private void AdjustEntities(List entities) + { foreach (int roomNumber in RoomMap.Keys) { foreach (short currentAngle in RoomMap[roomNumber].Keys) diff --git a/TREnvironmentEditor/Model/Types/Entities/EMConvertEnemyFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMConvertEnemyFunction.cs index 9dae97c93..81a300a66 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMConvertEnemyFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMConvertEnemyFunction.cs @@ -40,6 +40,11 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } public enum EnemyType diff --git a/TREnvironmentEditor/Model/Types/Entities/EMConvertEntityFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMConvertEntityFunction.cs index b96e4defb..0097ac186 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMConvertEntityFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMConvertEntityFunction.cs @@ -6,11 +6,16 @@ namespace TREnvironmentEditor.Model.Types public class EMConvertEntityFunction : BaseEMFunction { public int EntityIndex { get; set; } - public TR2Entities NewEntityType { get; set; } + public short NewEntityType { get; set; } public override void ApplyToLevel(TR2Level level) { - level.Entities[EntityIndex].TypeID = (short)NewEntityType; + level.Entities[EntityIndex].TypeID = NewEntityType; + } + + public override void ApplyToLevel(TR3Level level) + { + level.Entities[EntityIndex].TypeID = NewEntityType; } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Entities/EMModifyEntityFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMModifyEntityFunction.cs index 6cb59eda4..7214c9eca 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMModifyEntityFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMModifyEntityFunction.cs @@ -13,7 +13,16 @@ public class EMModifyEntityFunction : BaseEMFunction public override void ApplyToLevel(TR2Level level) { - TR2Entity entity = level.Entities[EntityIndex]; + ModifyEntity(level.Entities[EntityIndex]); + } + + public override void ApplyToLevel(TR3Level level) + { + ModifyEntity(level.Entities[EntityIndex]); + } + + private void ModifyEntity(TR2Entity entity) + { if (Invisible.HasValue) { entity.Invisible = Invisible.Value; diff --git a/TREnvironmentEditor/Model/Types/Entities/EMMoveEnemyFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMMoveEnemyFunction.cs index 2558c50dc..56b9f4654 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMMoveEnemyFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMMoveEnemyFunction.cs @@ -37,5 +37,10 @@ public override void ApplyToLevel(TR2Level level) // Otherwise, reposition the enemy and its triggers. RepositionTriggerable(enemy, level); } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Entities/EMMoveEntityFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMMoveEntityFunction.cs index 10bcb4037..162ac08af 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMMoveEntityFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMMoveEntityFunction.cs @@ -10,7 +10,17 @@ public class EMMoveEntityFunction : BaseEMFunction public override void ApplyToLevel(TR2Level level) { - TR2Entity entity = level.Entities[EntityIndex]; + MoveEntity(level.Entities[EntityIndex]); + + } + + public override void ApplyToLevel(TR3Level level) + { + MoveEntity(level.Entities[EntityIndex]); + } + + private void MoveEntity(TR2Entity entity) + { entity.X = TargetLocation.X; entity.Y = TargetLocation.Y; entity.Z = TargetLocation.Z; diff --git a/TREnvironmentEditor/Model/Types/Entities/EMMovePickupFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMMovePickupFunction.cs index e7f0b8de1..a7861dbda 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMMovePickupFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMMovePickupFunction.cs @@ -59,5 +59,10 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Entities/EMMoveSlotFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMMoveSlotFunction.cs index 59fa79521..9f3888e62 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMMoveSlotFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMMoveSlotFunction.cs @@ -65,6 +65,11 @@ public override void ApplyToLevel(TR2Level level) } } + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } + protected void MoveTriggers(FDControl control, TRRoomSector currentSector, TRRoomSector newSector) { if (newSector.FDIndex == 0) diff --git a/TREnvironmentEditor/Model/Types/Entities/EMMoveTrapFunction.cs b/TREnvironmentEditor/Model/Types/Entities/EMMoveTrapFunction.cs index f22a211b2..0b1d7dcd7 100644 --- a/TREnvironmentEditor/Model/Types/Entities/EMMoveTrapFunction.cs +++ b/TREnvironmentEditor/Model/Types/Entities/EMMoveTrapFunction.cs @@ -9,5 +9,10 @@ public override void ApplyToLevel(TR2Level level) TR2Entity trap = level.Entities[EntityIndex]; RepositionTriggerable(trap, level); } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs index 2e9fc0e11..47e9395ab 100644 --- a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs +++ b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs @@ -522,5 +522,10 @@ private void MirrorTextures(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Portals/EMCollisionalPortalFunction.cs b/TREnvironmentEditor/Model/Types/Portals/EMCollisionalPortalFunction.cs index 00f361f38..8668a7b57 100644 --- a/TREnvironmentEditor/Model/Types/Portals/EMCollisionalPortalFunction.cs +++ b/TREnvironmentEditor/Model/Types/Portals/EMCollisionalPortalFunction.cs @@ -26,22 +26,62 @@ public override void ApplyToLevel(TR2Level level) // interested in first before making any changes. foreach (short fromRoomNumber in Portals.Keys) { + int convertedFromRoomNumber = ConvertItemNumber(fromRoomNumber, level.NumRooms); foreach (short toRoomNumber in Portals[fromRoomNumber].Keys) { + int convertedToRoomNumber = ConvertItemNumber(toRoomNumber, level.NumRooms); foreach (EMLocation sectorLocation in Portals[fromRoomNumber][toRoomNumber]) { - TRRoomSector sector = FDUtilities.GetRoomSector(sectorLocation.X, sectorLocation.Y, sectorLocation.Z, fromRoomNumber, level, control); - + TRRoomSector sector = FDUtilities.GetRoomSector(sectorLocation.X, sectorLocation.Y, sectorLocation.Z, (short)convertedFromRoomNumber, level, control); + if (!sectorMap.ContainsKey(sector)) { sectorMap[sector] = new List(); } - sectorMap[sector].Add((ushort)toRoomNumber); + sectorMap[sector].Add((ushort)convertedToRoomNumber); } } } // Now create the new entries for all the portals. + CreatePortals(sectorMap, control); + + control.WriteToLevel(level); + } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + Dictionary> sectorMap = new Dictionary>(); + + foreach (short fromRoomNumber in Portals.Keys) + { + int convertedFromRoomNumber = ConvertItemNumber(fromRoomNumber, level.NumRooms); + foreach (short toRoomNumber in Portals[fromRoomNumber].Keys) + { + int convertedToRoomNumber = ConvertItemNumber(toRoomNumber, level.NumRooms); + foreach (EMLocation sectorLocation in Portals[fromRoomNumber][toRoomNumber]) + { + TRRoomSector sector = FDUtilities.GetRoomSector(sectorLocation.X, sectorLocation.Y, sectorLocation.Z, (short)convertedFromRoomNumber, level, control); + + if (!sectorMap.ContainsKey(sector)) + { + sectorMap[sector] = new List(); + } + sectorMap[sector].Add((ushort)convertedToRoomNumber); + } + } + } + + CreatePortals(sectorMap, control); + + control.WriteToLevel(level); + } + + private void CreatePortals(Dictionary> sectorMap, FDControl control) + { foreach (TRRoomSector sector in sectorMap.Keys) { if (sector.FDIndex == 0) @@ -58,8 +98,6 @@ public override void ApplyToLevel(TR2Level level) }); } } - - control.WriteToLevel(level); } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs b/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs index 2e9f33eb1..c627d3c41 100644 --- a/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs +++ b/TREnvironmentEditor/Model/Types/Portals/EMVisibilityPortalFunction.cs @@ -12,9 +12,29 @@ public override void ApplyToLevel(TR2Level level) { foreach (int roomNumber in Portals.Keys) { - TR2Room room = level.Rooms[roomNumber]; + TRRoomPortal portal = Portals[roomNumber]; + portal.AdjoiningRoom = (ushort)ConvertItemNumber(portal.AdjoiningRoom, level.NumRooms); + + int convertedRoomNumbew = ConvertItemNumber(roomNumber, level.NumRooms); + TR2Room room = level.Rooms[convertedRoomNumbew]; + List portals = room.Portals.ToList(); + portals.Add(portal); + room.Portals = portals.ToArray(); + room.NumPortals++; + } + } + + public override void ApplyToLevel(TR3Level level) + { + foreach (int roomNumber in Portals.Keys) + { + TRRoomPortal portal = Portals[roomNumber]; + portal.AdjoiningRoom = (ushort)ConvertItemNumber(portal.AdjoiningRoom, level.NumRooms); + + int convertedRoomNumbew = ConvertItemNumber(roomNumber, level.NumRooms); + TR3Room room = level.Rooms[convertedRoomNumbew]; List portals = room.Portals.ToList(); - portals.Add(Portals[roomNumber]); + portals.Add(portal); room.Portals = portals.ToArray(); room.NumPortals++; } diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs new file mode 100644 index 000000000..9389f2012 --- /dev/null +++ b/TREnvironmentEditor/Model/Types/Rooms/EMCopyRoomFunction.cs @@ -0,0 +1,322 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TREnvironmentEditor.Helpers; +using TRFDControl; +using TRFDControl.FDEntryTypes; +using TRFDControl.Utilities; +using TRLevelReader.Helpers; +using TRLevelReader.Model; + +namespace TREnvironmentEditor.Model.Types +{ + public class EMCopyRoomFunction : BaseEMFunction + { + // Floor and ceiling of -127 on sectors means impenetrable walls around it + private static readonly sbyte _solidSector = -127; + private static readonly byte _noRoom = 255; + + public short RoomIndex { get; set; } + public EMLocation NewLocation { get; set; } + public EMLocation LinkedLocation { get; set; } + + public override void ApplyToLevel(TR2Level level) + { + throw new NotImplementedException(); + } + + public override void ApplyToLevel(TR3Level level) + { + TR3Room baseRoom = level.Rooms[RoomIndex]; + + int xdiff = NewLocation.X - baseRoom.Info.X; + int ydiff = NewLocation.Y - baseRoom.Info.YBottom; + int zdiff = NewLocation.Z - baseRoom.Info.Z; + + TR3Room newRoom = new TR3Room + { + AlternateRoom = -1, + AmbientIntensity = baseRoom.AmbientIntensity, + Filler = baseRoom.Filler, + Flags = baseRoom.Flags, + Info = new TRRoomInfo + { + X = NewLocation.X, + YBottom = NewLocation.Y, + YTop = NewLocation.Y + (baseRoom.Info.YTop - baseRoom.Info.YBottom), + Z = NewLocation.Z + }, + Lights = new TR3RoomLight[baseRoom.NumLights], + LightMode = baseRoom.LightMode, + NumDataWords = baseRoom.NumDataWords, + NumLights = baseRoom.NumLights, + NumPortals = 0, + NumStaticMeshes = baseRoom.NumStaticMeshes, + NumXSectors = baseRoom.NumXSectors, + NumZSectors = baseRoom.NumZSectors, + Portals = new TRRoomPortal[] { }, + ReverbInfo = baseRoom.ReverbInfo, + RoomData = new TR3RoomData + { + NumRectangles = baseRoom.RoomData.NumRectangles, + NumSprites = baseRoom.RoomData.NumSprites, + NumTriangles = baseRoom.RoomData.NumTriangles, + NumVertices = baseRoom.RoomData.NumVertices, + Rectangles = new TRFace4[baseRoom.RoomData.NumRectangles], + Sprites = new TRRoomSprite[baseRoom.RoomData.NumSprites], + Triangles = new TRFace3[baseRoom.RoomData.NumTriangles], + Vertices = new TR3RoomVertex[baseRoom.RoomData.NumVertices] + }, + Sectors = new TRRoomSector[baseRoom.Sectors.Length], + StaticMeshes = new TR3RoomStaticMesh[baseRoom.NumStaticMeshes], + WaterScheme = baseRoom.WaterScheme + }; + + // Lights + for (int i = 0; i < newRoom.Lights.Length; i++) + { + newRoom.Lights[i] = new TR3RoomLight + { + Colour = baseRoom.Lights[i].Colour, + LightProperties = baseRoom.Lights[i].LightProperties, + LightType = baseRoom.Lights[i].LightType, + X = baseRoom.Lights[i].X + xdiff, + Y = baseRoom.Lights[i].Y + ydiff, + Z = baseRoom.Lights[i].Z + zdiff + }; + } + + // Faces + for (int i = 0; i < newRoom.RoomData.NumRectangles; i++) + { + newRoom.RoomData.Rectangles[i] = new TRFace4 + { + Texture = baseRoom.RoomData.Rectangles[i].Texture, + Vertices = new ushort[baseRoom.RoomData.Rectangles[i].Vertices.Length] + }; + for (int j = 0; j < newRoom.RoomData.Rectangles[i].Vertices.Length; j++) + { + newRoom.RoomData.Rectangles[i].Vertices[j] = baseRoom.RoomData.Rectangles[i].Vertices[j]; + } + } + + for (int i = 0; i < newRoom.RoomData.NumTriangles; i++) + { + newRoom.RoomData.Triangles[i] = new TRFace3 + { + Texture = baseRoom.RoomData.Triangles[i].Texture, + Vertices = new ushort[baseRoom.RoomData.Triangles[i].Vertices.Length] + }; + for (int j = 0; j < newRoom.RoomData.Triangles[i].Vertices.Length; j++) + { + newRoom.RoomData.Triangles[i].Vertices[j] = baseRoom.RoomData.Triangles[i].Vertices[j]; + } + } + + // Vertices + for (int i = 0; i < newRoom.RoomData.Vertices.Length; i++) + { + newRoom.RoomData.Vertices[i] = new TR3RoomVertex + { + Attributes = baseRoom.RoomData.Vertices[i].Attributes, + Colour = baseRoom.RoomData.Vertices[i].Colour, + Lighting = baseRoom.RoomData.Vertices[i].Lighting, + Vertex = new TRVertex + { + X = baseRoom.RoomData.Vertices[i].Vertex.X, // Room coords for X and Z + Y = (short)(baseRoom.RoomData.Vertices[i].Vertex.Y + ydiff), + Z = baseRoom.RoomData.Vertices[i].Vertex.Z + } + }; + } + + // Sprites + for (int i = 0; i < newRoom.RoomData.NumSprites; i++) + { + newRoom.RoomData.Sprites[i] = new TRRoomSprite + { + Texture = baseRoom.RoomData.Sprites[i].Texture, + Vertex = baseRoom.RoomData.Sprites[i].Vertex + }; + } + + // Static Meshes + for (int i = 0; i < newRoom.NumStaticMeshes; i++) + { + newRoom.StaticMeshes[i] = new TR3RoomStaticMesh + { + Colour = baseRoom.StaticMeshes[i].Colour, + MeshID = baseRoom.StaticMeshes[i].MeshID, + Rotation = baseRoom.StaticMeshes[i].Rotation, + Unused = baseRoom.StaticMeshes[i].Unused, + X = (uint)(baseRoom.StaticMeshes[i].X + xdiff), + Y = (uint)(baseRoom.StaticMeshes[i].Y + ydiff), + Z = (uint)(baseRoom.StaticMeshes[i].Z + zdiff) + }; + } + + // Boxes, zones and sectors + FDControl floorData = new FDControl(); + floorData.ParseFromLevel(level); + + TRRoomSector linkedSector = FDUtilities.GetRoomSector(LinkedLocation.X, LinkedLocation.Y, LinkedLocation.Z, LinkedLocation.Room, level, floorData); + ushort newBoxIndex = (ushort)level.NumBoxes; + int linkedBoxIndex = (linkedSector.BoxIndex & 0x7FF0) >> 4; + int linkedMaterial = linkedSector.BoxIndex & 0x000F; // TR3-5 store material in bits 0-3 - wood, mud etc + + // Duplicate the zone for the new box and link the current box to the new room + TR2BoxUtilities.DuplicateZone(level, linkedBoxIndex); + TR2Box linkedBox = level.Boxes[linkedBoxIndex]; + List overlaps = TR2BoxUtilities.GetOverlaps(level, linkedBox); + overlaps.Add(newBoxIndex); + TR2BoxUtilities.UpdateOverlaps(level, linkedBox, overlaps); + + // Make a new box for the new room + byte xmin = (byte)(newRoom.Info.X / SectorSize); + byte zmin = (byte)(newRoom.Info.Z / SectorSize); + byte xmax = (byte)((newRoom.Info.X / SectorSize) + (newRoom.Sectors.Length / newRoom.NumZSectors)); + byte zmax = (byte)((newRoom.Info.Z / SectorSize) + (newRoom.Sectors.Length % newRoom.NumZSectors)); + TR2Box box = new TR2Box + { + XMin = xmin, + ZMin = zmin, + XMax = xmax, + ZMax = zmax, + TrueFloor = (short)newRoom.Info.YBottom + }; + List boxes = level.Boxes.ToList(); + boxes.Add(box); + level.Boxes = boxes.ToArray(); + level.NumBoxes++; + + // Link the box to the room we're joining to + TR2BoxUtilities.UpdateOverlaps(level, box, new List { (ushort)linkedBoxIndex }); + + // Now update each of the sectors in the new room. The box index in each sector + // needs to reference the material so pack this into the box index. + newBoxIndex <<= 4; + newBoxIndex |= (ushort)linkedMaterial; + + for (int i = 0; i < newRoom.Sectors.Length; i++) + { + int sectorYDiff = 0; + ushort sectorBoxIndex = baseRoom.Sectors[i].BoxIndex; + // Only change the sector if it's not impenetrable + if (baseRoom.Sectors[i].Ceiling != _solidSector || baseRoom.Sectors[i].Floor != _solidSector) + { + sectorYDiff = ydiff / ClickSize; + sectorBoxIndex = newBoxIndex; + } + + newRoom.Sectors[i] = new TRRoomSector + { + BoxIndex = sectorBoxIndex, + Ceiling = (sbyte)(baseRoom.Sectors[i].Ceiling + sectorYDiff), + FDIndex = 0, // Initialise to no FD + Floor = (sbyte)(baseRoom.Sectors[i].Floor + sectorYDiff), + RoomAbove = _noRoom, + RoomBelow = _noRoom + }; + + // Duplicate the FD too for everything except triggers. Track any portals + // so they can be blocked off. + if (baseRoom.Sectors[i].FDIndex != 0) + { + List entries = floorData.Entries[baseRoom.Sectors[i].FDIndex]; + List newEntries = new List(); + foreach (FDEntry entry in entries) + { + switch ((FDFunctions)entry.Setup.Function) + { + case FDFunctions.PortalSector: + // This portal will no longer be valid in the new room's position, + // so block off the wall + newRoom.Sectors[i].Floor = newRoom.Sectors[i].Ceiling = _solidSector; + break; + case FDFunctions.FloorSlant: + FDSlantEntry slantEntry = entry as FDSlantEntry; + newEntries.Add(new FDSlantEntry() + { + Setup = new FDSetup() { Value = slantEntry.Setup.Value }, + SlantValue = slantEntry.SlantValue, + Type = FDSlantEntryType.FloorSlant + }); + break; + case FDFunctions.CeilingSlant: + FDSlantEntry ceilingSlant = entry as FDSlantEntry; + newEntries.Add(new FDSlantEntry() + { + Setup = new FDSetup() { Value = ceilingSlant.Setup.Value }, + SlantValue = ceilingSlant.SlantValue, + Type = FDSlantEntryType.CeilingSlant + }); + break; + case FDFunctions.KillLara: + newEntries.Add(new FDKillLaraEntry() + { + Setup = new FDSetup() { Value = entry.Setup.Value } + }); + break; + case FDFunctions.ClimbableWalls: + newEntries.Add(new FDClimbEntry() + { + Setup = new FDSetup() { Value = entry.Setup.Value } + }); + break; + case FDFunctions.FloorTriangulationNWSE_Solid: + case FDFunctions.FloorTriangulationNESW_Solid: + case FDFunctions.CeilingTriangulationNW_Solid: + case FDFunctions.CeilingTriangulationNE_Solid: + case FDFunctions.FloorTriangulationNWSE_SW: + case FDFunctions.FloorTriangulationNWSE_NE: + case FDFunctions.FloorTriangulationNESW_SW: + case FDFunctions.FloorTriangulationNESW_NW: + case FDFunctions.CeilingTriangulationNW_SW: + case FDFunctions.CeilingTriangulationNW_NE: + case FDFunctions.CeilingTriangulationNE_NW: + case FDFunctions.CeilingTriangulationNE_SE: + TR3TriangulationEntry triEntry = entry as TR3TriangulationEntry; + newEntries.Add(new TR3TriangulationEntry + { + Setup = new FDSetup { Value = triEntry.Setup.Value }, + TriData = new FDTriangulationData { Value = triEntry.TriData.Value } + }); + break; + case FDFunctions.Monkeyswing: + newEntries.Add(new TR3MonkeySwingEntry() + { + Setup = new FDSetup() { Value = entry.Setup.Value } + }); + break; + case FDFunctions.DeferredTriggeringOrMinecartRotateLeft: + newEntries.Add(new TR3MinecartRotateLeftEntry() + { + Setup = new FDSetup() { Value = entry.Setup.Value } + }); + break; + case FDFunctions.MechBeetleOrMinecartRotateRight: + newEntries.Add(new TR3MinecartRotateRightEntry() + { + Setup = new FDSetup() { Value = entry.Setup.Value } + }); + break; + } + } + + if (newEntries.Count > 0) + { + floorData.CreateFloorData(newRoom.Sectors[i]); + floorData.Entries[newRoom.Sectors[i].FDIndex].AddRange(newEntries); + } + } + } + + floorData.WriteToLevel(level); + + List rooms = level.Rooms.ToList(); + rooms.Add(newRoom); + level.Rooms = rooms.ToArray(); + level.NumRooms++; + } + } +} \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMCopyVertexAttributesFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMCopyVertexAttributesFunction.cs new file mode 100644 index 000000000..5d9007175 --- /dev/null +++ b/TREnvironmentEditor/Model/Types/Rooms/EMCopyVertexAttributesFunction.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using TREnvironmentEditor.Helpers; +using TRLevelReader.Model; + +namespace TREnvironmentEditor.Model.Types +{ + public class EMCopyVertexAttributesFunction : BaseEMFunction + { + public Dictionary>> FaceMap { get; set; } + + public override void ApplyToLevel(TR2Level level) + { + throw new NotImplementedException(); + } + + public override void ApplyToLevel(TR3Level level) + { + foreach (short roomNumber in FaceMap.Keys) + { + TR3Room room = level.Rooms[ConvertItemNumber(roomNumber, level.NumRooms)]; + foreach (EMTextureFaceType faceType in FaceMap[roomNumber].Keys) + { + foreach (int baseFaceIndex in FaceMap[roomNumber][faceType].Keys) + { + ushort[] baseVertices, copyVertices; + switch (faceType) + { + case EMTextureFaceType.Rectangles: + baseVertices = room.RoomData.Rectangles[baseFaceIndex].Vertices; + copyVertices = room.RoomData.Rectangles[FaceMap[roomNumber][faceType][baseFaceIndex]].Vertices; + break; + case EMTextureFaceType.Triangles: + baseVertices = room.RoomData.Triangles[baseFaceIndex].Vertices; + copyVertices = room.RoomData.Triangles[FaceMap[roomNumber][faceType][baseFaceIndex]].Vertices; + break; + default: + throw new ArgumentException(); + } + + for (int i = 0; i < baseVertices.Length; i++) + { + TR3RoomVertex baseVertex = room.RoomData.Vertices[baseVertices[i]]; + TR3RoomVertex copyVertex = room.RoomData.Vertices[copyVertices[i]]; + copyVertex.Attributes = baseVertex.Attributes; + copyVertex.Colour = baseVertex.Colour; + copyVertex.Lighting = baseVertex.Lighting; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMModifyOverlapsFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMModifyOverlapsFunction.cs index 77258e3c8..8860217cb 100644 --- a/TREnvironmentEditor/Model/Types/Rooms/EMModifyOverlapsFunction.cs +++ b/TREnvironmentEditor/Model/Types/Rooms/EMModifyOverlapsFunction.cs @@ -33,5 +33,30 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + if (RemoveLinks != null) + { + foreach (ushort boxIndex in RemoveLinks.Keys) + { + TR2Box box = level.Boxes[boxIndex]; + List overlaps = TR2BoxUtilities.GetOverlaps(level, box); + overlaps.RemoveAll(o => RemoveLinks[boxIndex].Contains(o)); + TR2BoxUtilities.UpdateOverlaps(level, box, overlaps); + } + } + + if (AddLinks != null) + { + foreach (ushort boxIndex in AddLinks.Keys) + { + TR2Box box = level.Boxes[boxIndex]; + List overlaps = TR2BoxUtilities.GetOverlaps(level, box); + overlaps.AddRange(AddLinks[boxIndex]); + TR2BoxUtilities.UpdateOverlaps(level, box, overlaps); + } + } + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Rooms/EMModifyRoomFunction.cs b/TREnvironmentEditor/Model/Types/Rooms/EMModifyRoomFunction.cs index 2b3074c64..69139b3b8 100644 --- a/TREnvironmentEditor/Model/Types/Rooms/EMModifyRoomFunction.cs +++ b/TREnvironmentEditor/Model/Types/Rooms/EMModifyRoomFunction.cs @@ -23,5 +23,10 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs b/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs index ead72e3ba..2a8b933b9 100644 --- a/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Sounds/EMAddSoundSourceFunction.cs @@ -15,5 +15,13 @@ public override void ApplyToLevel(TR2Level level) level.SoundSources = soundSources.ToArray(); level.NumSoundSources++; } + + public override void ApplyToLevel(TR3Level level) + { + List soundSources = level.SoundSources.ToList(); + soundSources.Add(Source); + level.SoundSources = soundSources.ToArray(); + level.NumSoundSources++; + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Sounds/EMMoveSoundSourceFunction.cs b/TREnvironmentEditor/Model/Types/Sounds/EMMoveSoundSourceFunction.cs index 52364f5ff..dab612697 100644 --- a/TREnvironmentEditor/Model/Types/Sounds/EMMoveSoundSourceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Sounds/EMMoveSoundSourceFunction.cs @@ -10,7 +10,16 @@ public class EMMoveSoundSourceFunction : BaseEMFunction public override void ApplyToLevel(TR2Level level) { - TRSoundSource source = level.SoundSources[Index]; + MoveSoundSource(level.SoundSources[Index]); + } + + public override void ApplyToLevel(TR3Level level) + { + MoveSoundSource(level.SoundSources[Index]); + } + + private void MoveSoundSource(TRSoundSource source) + { source.X += Relocation.X; source.Y += Relocation.Y; source.Z += Relocation.Z; diff --git a/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs b/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs index a6eebfb7d..b000b9db2 100644 --- a/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Sounds/EMRemoveSoundSourceFunction.cs @@ -12,13 +12,31 @@ public override void ApplyToLevel(TR2Level level) { // Can't remove by index in case several are called in succession List sources = level.SoundSources.ToList(); - TRSoundSource source = sources.Find(s => s.X == Source.X && s.Y == Source.Y && s.Z == Source.Z); - if (source != null) + if (RemoveSource(sources)) { - sources.Remove(source); level.SoundSources = sources.ToArray(); level.NumSoundSources--; } } + + public override void ApplyToLevel(TR3Level level) + { + List sources = level.SoundSources.ToList(); + if (RemoveSource(sources)) + { + level.SoundSources = sources.ToArray(); + level.NumSoundSources--; + } + } + + private bool RemoveSource(List sources) + { + TRSoundSource source = sources.Find(s => s.X == Source.X && s.Y == Source.Y && s.Z == Source.Z); + if (source != null) + { + return sources.Remove(source); + } + return false; + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMCeilingFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMCeilingFunction.cs index 1c018a257..0094d760c 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMCeilingFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMCeilingFunction.cs @@ -22,5 +22,10 @@ public override void ApplyToLevel(TR2Level level) room.Info.YTop = min * ClickSize; } } + + public override void ApplyToLevel(TR3Level level) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMDrainFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMDrainFunction.cs index a598baf41..5a376aaea 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMDrainFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMDrainFunction.cs @@ -57,5 +57,10 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMFloodFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMFloodFunction.cs index e39e07365..7e611ec87 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMFloodFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMFloodFunction.cs @@ -43,5 +43,10 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs index 9e0d6c731..4ae3dd445 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMFloorFunction.cs @@ -271,5 +271,10 @@ public void RemapTextures(Dictionary indexMap) SideTexture = indexMap[SideTexture]; } } + + public override void ApplyToLevel(TR3Level level) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Surfaces/EMLadderFunction.cs b/TREnvironmentEditor/Model/Types/Surfaces/EMLadderFunction.cs index baa9cabf5..3fd3885ee 100644 --- a/TREnvironmentEditor/Model/Types/Surfaces/EMLadderFunction.cs +++ b/TREnvironmentEditor/Model/Types/Surfaces/EMLadderFunction.cs @@ -20,6 +20,33 @@ public override void ApplyToLevel(TR2Level level) FDControl control = new FDControl(); control.ParseFromLevel(level); + TRRoomSector sector = FDUtilities.GetRoomSector(Location.X, Location.Y, Location.Z, Location.Room, level, control); + ModifyLadder(sector, control); + + control.WriteToLevel(level); + + // Unfortunately the ladder texture may not match the walls we are targeting, but + // we can maybe look at generating a ladder texture with a transparent background for + // each level, and then merging it with the wall in a particular room (similar to the way + // landmarks are done), provided there is enough texture space. + ApplyTextures(level); + } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + TRRoomSector sector = FDUtilities.GetRoomSector(Location.X, Location.Y, Location.Z, Location.Room, level, control); + ModifyLadder(sector, control); + + control.WriteToLevel(level); + + ApplyTextures(level); + } + + private void ModifyLadder(TRRoomSector sector, FDControl control) + { // Rosetta: Collisional floordata functions should always come first in sequence, with floor // collision function strictly being first and ceiling collision function strictly being second. // The reason is hardcoded floordata collision parser which always expects these two functions @@ -29,7 +56,6 @@ public override void ApplyToLevel(TR2Level level) bool removeAll = !IsPositiveX && !IsPositiveZ && !IsNegativeX && !IsNegativeZ; - TRRoomSector sector = FDUtilities.GetRoomSector(Location.X, Location.Y, Location.Z, Location.Room, level, control); if (!removeAll && sector.FDIndex == 0) { control.CreateFloorData(sector); @@ -66,14 +92,6 @@ public override void ApplyToLevel(TR2Level level) control.Entries[sector.FDIndex].Insert(index + 1, climbEntry); } - - control.WriteToLevel(level); - - // Unfortunately the ladder texture may not match the walls we are targeting, but - // we can maybe look at generating a ladder texture with a transparent background for - // each level, and then merging it with the wall in a particular room (similar to the way - // landmarks are done), provided there is enough texture space. - ApplyTextures(level); } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Textures/EMAddStaticMeshFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMAddStaticMeshFunction.cs index 859826239..9b59099b3 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMAddStaticMeshFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMAddStaticMeshFunction.cs @@ -59,5 +59,10 @@ public override void ApplyToLevel(TR2Level level) room.NumStaticMeshes = (ushort)meshes.Count; } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Textures/EMModifyFaceFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMModifyFaceFunction.cs index 7fe494be8..0849f40c5 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMModifyFaceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMModifyFaceFunction.cs @@ -16,7 +16,7 @@ public override void ApplyToLevel(TR2Level level) { foreach (EMFaceModification mod in Modifications) { - TR2Room room = level.Rooms[mod.RoomNumber]; + TR2Room room = level.Rooms[ConvertItemNumber(mod.RoomNumber, level.NumRooms)]; switch (mod.FaceType) { case EMTextureFaceType.Rectangles: @@ -33,14 +33,51 @@ public override void ApplyToLevel(TR2Level level) { foreach (EMFaceRotation rot in Rotations) { - TR2Room room = level.Rooms[rot.RoomNumber]; + TR2Room room = level.Rooms[ConvertItemNumber(rot.RoomNumber, level.NumRooms)]; switch (rot.FaceType) { case EMTextureFaceType.Rectangles: - RotateRectangles(room, rot); + RotateRectangles(room.RoomData.Rectangles, rot); break; case EMTextureFaceType.Triangles: - RotateTriangles(room, rot); + RotateTriangles(room.RoomData.Triangles, rot); + break; + } + } + } + } + + public override void ApplyToLevel(TR3Level level) + { + if (Modifications != null) + { + foreach (EMFaceModification mod in Modifications) + { + TR3Room room = level.Rooms[ConvertItemNumber(mod.RoomNumber, level.NumRooms)]; + switch (mod.FaceType) + { + case EMTextureFaceType.Rectangles: + ModifyRectangles(room, mod); + break; + case EMTextureFaceType.Triangles: + ModifyTriangles(room, mod); + break; + } + } + } + + if (Rotations != null) + { + foreach (EMFaceRotation rot in Rotations) + { + TR3Room room = level.Rooms[ConvertItemNumber(rot.RoomNumber, level.NumRooms)]; + switch (rot.FaceType) + { + case EMTextureFaceType.Rectangles: + RotateRectangles(room.RoomData.Rectangles, rot); + break; + case EMTextureFaceType.Triangles: + RotateTriangles(room.RoomData.Triangles, rot); break; } } @@ -67,6 +104,26 @@ private void ModifyRectangles(TR2Room room, EMFaceModification mod) room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); } + private void ModifyRectangles(TR3Room room, EMFaceModification mod) + { + TRFace4 rect = room.RoomData.Rectangles[mod.FaceIndex]; + List allVertices = room.RoomData.Vertices.ToList(); + foreach (int vertIndex in mod.VertexChanges.Keys) + { + TR3RoomVertex currentRoomVertex = allVertices[rect.Vertices[vertIndex]]; + TRVertex newVertex = mod.VertexChanges[vertIndex]; + TR3RoomVertex newRoomVertex = GenerateRoomVertex(currentRoomVertex, newVertex); + + // Remap the face to use this vertex + rect.Vertices[vertIndex] = (ushort)allVertices.Count; + allVertices.Add(newRoomVertex); + } + + room.RoomData.Vertices = allVertices.ToArray(); + room.RoomData.NumVertices = (short)allVertices.Count; + room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); + } + private void ModifyTriangles(TR2Room room, EMFaceModification mod) { TRFace3 tri = room.RoomData.Triangles[mod.FaceIndex]; @@ -87,6 +144,26 @@ private void ModifyTriangles(TR2Room room, EMFaceModification mod) room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); } + private void ModifyTriangles(TR3Room room, EMFaceModification mod) + { + TRFace3 tri = room.RoomData.Triangles[mod.FaceIndex]; + List allVertices = room.RoomData.Vertices.ToList(); + foreach (int vertIndex in mod.VertexChanges.Keys) + { + TR3RoomVertex currentRoomVertex = allVertices[tri.Vertices[vertIndex]]; + TRVertex newVertex = mod.VertexChanges[vertIndex]; + TR3RoomVertex newRoomVertex = GenerateRoomVertex(currentRoomVertex, newVertex); + + // Remap the face to use this vertex + tri.Vertices[vertIndex] = (ushort)allVertices.Count; + allVertices.Add(newRoomVertex); + } + + room.RoomData.Vertices = allVertices.ToArray(); + room.RoomData.NumVertices = (short)allVertices.Count; + room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); + } + private TR2RoomVertex GenerateRoomVertex(TR2RoomVertex currentRoomVertex, TRVertex newVertex) { // We create a new vertex because we can't guarantee nothing else is using it. @@ -106,20 +183,39 @@ private TR2RoomVertex GenerateRoomVertex(TR2RoomVertex currentRoomVertex, TRVert }; } - private void RotateRectangles(TR2Room room, EMFaceRotation rot) + private TR3RoomVertex GenerateRoomVertex(TR3RoomVertex currentRoomVertex, TRVertex newVertex) + { + // We create a new vertex because we can't guarantee nothing else is using it. + // Note the vertex values in the mod are added to the existing values, so we + // don't have to define those we aren't changing. + return new TR3RoomVertex + { + Attributes = currentRoomVertex.Attributes, + Lighting = currentRoomVertex.Lighting, + Colour = currentRoomVertex.Colour, + Vertex = new TRVertex + { + X = (short)(currentRoomVertex.Vertex.X + newVertex.X), + Y = (short)(currentRoomVertex.Vertex.Y + newVertex.Y), + Z = (short)(currentRoomVertex.Vertex.Z + newVertex.Z) + } + }; + } + + private void RotateRectangles(TRFace4[] rectangles, EMFaceRotation rot) { foreach (int rectIndex in rot.FaceIndices) { - TRFace4 face = room.RoomData.Rectangles[rectIndex]; + TRFace4 face = rectangles[rectIndex]; face.Vertices = RotateVertices(face.Vertices, rot); } } - private void RotateTriangles(TR2Room room, EMFaceRotation rot) + private void RotateTriangles(TRFace3[] triangles, EMFaceRotation rot) { foreach (int triIndex in rot.FaceIndices) { - TRFace3 face = room.RoomData.Triangles[triIndex]; + TRFace3 face = triangles[triIndex]; face.Vertices = RotateVertices(face.Vertices, rot); } } diff --git a/TREnvironmentEditor/Model/Types/Textures/EMRefaceFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMRefaceFunction.cs index 527e97988..7901bf0e5 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMRefaceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMRefaceFunction.cs @@ -13,26 +13,49 @@ public override void ApplyToLevel(TR2Level level) ApplyTextures(level); } + public override void ApplyToLevel(TR3Level level) + { + ApplyTextures(level); + } + public void ApplyTextures(TR2Level level) { foreach (ushort texture in TextureMap.Keys) { foreach (int roomIndex in TextureMap[texture].Keys) { - foreach (EMTextureFaceType faceType in TextureMap[texture][roomIndex].Keys) + TR2Room room = level.Rooms[ConvertItemNumber(roomIndex, level.NumRooms)]; + ApplyTextures(texture, TextureMap[texture][roomIndex], room.RoomData.Rectangles, room.RoomData.Triangles); + } + } + } + + public void ApplyTextures(TR3Level level) + { + foreach (ushort texture in TextureMap.Keys) + { + foreach (int roomIndex in TextureMap[texture].Keys) + { + TR3Room room = level.Rooms[ConvertItemNumber(roomIndex, level.NumRooms)]; + ApplyTextures(texture, TextureMap[texture][roomIndex], room.RoomData.Rectangles, room.RoomData.Triangles); + } + } + } + + private void ApplyTextures(ushort texture, Dictionary faceMap, TRFace4[] rectangles, TRFace3[] triangles) + { + foreach (EMTextureFaceType faceType in faceMap.Keys) + { + foreach (int faceIndex in faceMap[faceType]) + { + switch (faceType) { - foreach (int faceIndex in TextureMap[texture][roomIndex][faceType]) - { - switch (faceType) - { - case EMTextureFaceType.Rectangles: - level.Rooms[roomIndex].RoomData.Rectangles[faceIndex].Texture = texture; - break; - case EMTextureFaceType.Triangles: - level.Rooms[roomIndex].RoomData.Triangles[faceIndex].Texture = texture; - break; - } - } + case EMTextureFaceType.Rectangles: + rectangles[faceIndex].Texture = texture; + break; + case EMTextureFaceType.Triangles: + triangles[faceIndex].Texture = texture; + break; } } } diff --git a/TREnvironmentEditor/Model/Types/Textures/EMRemoveFaceFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMRemoveFaceFunction.cs index d455eeb1d..0eb45be6e 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMRemoveFaceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMRemoveFaceFunction.cs @@ -43,6 +43,40 @@ public override void ApplyToLevel(TR2Level level) } } + public override void ApplyToLevel(TR3Level level) + { + foreach (int roomNumber in GeometryMap.Keys) + { + TR3Room room = level.Rooms[roomNumber]; + List rectangleRemovals = new List(); + List triangleRemovals = new List(); + + foreach (EMTextureFaceType faceType in GeometryMap[roomNumber].Keys) + { + foreach (int faceIndex in GeometryMap[roomNumber][faceType]) + { + switch (faceType) + { + case EMTextureFaceType.Rectangles: + rectangleRemovals.Add(faceIndex); + break; + case EMTextureFaceType.Triangles: + triangleRemovals.Add(faceIndex); + break; + } + } + } + + room.RoomData.Rectangles = RemoveEntries(room.RoomData.Rectangles, rectangleRemovals); + room.RoomData.Triangles = RemoveEntries(room.RoomData.Triangles, triangleRemovals); + + room.RoomData.NumRectangles = (short)room.RoomData.Rectangles.Length; + room.RoomData.NumTriangles = (short)room.RoomData.Triangles.Length; + + room.NumDataWords = (uint)(room.RoomData.Serialize().Length / 2); + } + } + private static T[] RemoveEntries(T[] items, List indices) { List itemList = items.ToList(); diff --git a/TREnvironmentEditor/Model/Types/Textures/EMRemoveStaticMeshFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMRemoveStaticMeshFunction.cs index 0fdde8feb..df3ca8fe0 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMRemoveStaticMeshFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMRemoveStaticMeshFunction.cs @@ -47,5 +47,10 @@ public override void ApplyToLevel(TR2Level level) } } } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMAppendTrigerActionFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMAppendTrigerActionFunction.cs index 6763bafda..4bda0b1a2 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMAppendTrigerActionFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMAppendTrigerActionFunction.cs @@ -29,5 +29,24 @@ public override void ApplyToLevel(TR2Level level) control.WriteToLevel(level); } } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + TRRoomSector sector = FDUtilities.GetRoomSector(Location.X, Location.Y, Location.Z, Location.Room, level, control); + if (sector.FDIndex == 0) + { + return; + } + + FDTriggerEntry trigger = control.Entries[sector.FDIndex].Find(e => e is FDTriggerEntry) as FDTriggerEntry; + if (trigger != null) + { + trigger.TrigActionList.AddRange(ActionItems); + control.WriteToLevel(level); + } + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs index 26fab8798..5231e95f6 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMCameraTriggerFunction.cs @@ -55,6 +55,40 @@ public override void ApplyToLevel(TR2Level level) control.WriteToLevel(level); } + public override void ApplyToLevel(TR3Level level) + { + List cameras = level.Cameras.ToList(); + cameras.Add(Camera); + level.Cameras = cameras.ToArray(); + + ushort cameraIndex = (ushort)level.NumCameras; + level.NumCameras++; + + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + if (AttachToItems != null) + { + foreach (ushort item in AttachToItems) + { + TR2Entity attachToEntity = level.Entities[item]; + TRRoomSector sector = FDUtilities.GetRoomSector(attachToEntity.X, attachToEntity.Y, attachToEntity.Z, attachToEntity.Room, level, control); + AttachToSector(sector, control, cameraIndex); + } + } + + if (AttachToLocations != null) + { + foreach (EMLocation location in AttachToLocations) + { + TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); + AttachToSector(sector, control, cameraIndex); + } + } + + control.WriteToLevel(level); + } + private void AttachToSector(TRRoomSector sector, FDControl control, ushort cameraIndex) { if (sector.FDIndex != 0) diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateSwitchTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateSwitchTriggerFunction.cs index 9e075c784..c76809f5d 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateSwitchTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateSwitchTriggerFunction.cs @@ -57,5 +57,10 @@ public override void ApplyToLevel(TR2Level level) control.WriteToLevel(level); } + + public override void ApplyToLevel(TR3Level level) + { + throw new System.NotImplementedException(); + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateTriggerFunction.cs index c89dd0df7..81cd21ee8 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMDuplicateTriggerFunction.cs @@ -32,19 +32,50 @@ public override void ApplyToLevel(TR2Level level) foreach (EMLocation location in Locations) { TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); - if (sector.FDIndex == 0) - { - control.CreateFloorData(sector); - } + AppendTriggers(sector, triggerEntries, control); + } + + control.WriteToLevel(level); + } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); - List entries = control.Entries[sector.FDIndex]; - if (entries.FindIndex(e => e is FDTriggerEntry) == -1) - { - entries.AddRange(triggerEntries); - } + TRRoomSector baseSector = FDUtilities.GetRoomSector(BaseLocation.X, BaseLocation.Y, BaseLocation.Z, BaseLocation.Room, level, control); + if (baseSector.FDIndex == 0) + { + return; + } + + List triggerEntries = control.Entries[baseSector.FDIndex].FindAll(e => e is FDTriggerEntry); + if (triggerEntries.Count == 0) + { + return; + } + + foreach (EMLocation location in Locations) + { + TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); + AppendTriggers(sector, triggerEntries, control); } control.WriteToLevel(level); } + + private void AppendTriggers(TRRoomSector sector, List triggerEntries, FDControl control) + { + if (sector.FDIndex == 0) + { + control.CreateFloorData(sector); + } + + List entries = control.Entries[sector.FDIndex]; + if (entries.FindIndex(e => e is FDTriggerEntry) == -1) + { + entries.AddRange(triggerEntries); + } + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMMoveTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMMoveTriggerFunction.cs index 3cac16794..994802845 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMMoveTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMMoveTriggerFunction.cs @@ -20,6 +20,28 @@ public override void ApplyToLevel(TR2Level level) TRRoomSector baseSector = FDUtilities.GetRoomSector(BaseLocation.X, BaseLocation.Y, BaseLocation.Z, BaseLocation.Room, level, control); TRRoomSector newSector = FDUtilities.GetRoomSector(NewLocation.X, NewLocation.Y, NewLocation.Z, NewLocation.Room, level, control); + if (MoveTriggers(baseSector, newSector, control)) + { + control.WriteToLevel(level); + } + } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + TRRoomSector baseSector = FDUtilities.GetRoomSector(BaseLocation.X, BaseLocation.Y, BaseLocation.Z, BaseLocation.Room, level, control); + TRRoomSector newSector = FDUtilities.GetRoomSector(NewLocation.X, NewLocation.Y, NewLocation.Z, NewLocation.Room, level, control); + + if (MoveTriggers(baseSector, newSector, control)) + { + control.WriteToLevel(level); + } + } + + private bool MoveTriggers(TRRoomSector baseSector, TRRoomSector newSector, FDControl control) + { if (baseSector.FDIndex != 0) { if (newSector.FDIndex == 0) @@ -36,8 +58,10 @@ public override void ApplyToLevel(TR2Level level) control.RemoveFloorData(baseSector); } - control.WriteToLevel(level); + return true; } + + return false; } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMRemoveTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMRemoveTriggerFunction.cs index e3895402d..b219548a7 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMRemoveTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMRemoveTriggerFunction.cs @@ -30,16 +30,46 @@ public override void ApplyToLevel(TR2Level level) { foreach (int roomNumber in Rooms) { - foreach (TRRoomSector sector in level.Rooms[roomNumber].SectorList) - { - RemoveSectorTriggers(sector, control); - } + RemoveSectorListTriggers(level.Rooms[roomNumber].SectorList, control); } } control.WriteToLevel(level); } + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + if (Locations != null) + { + foreach (EMLocation location in Locations) + { + TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); + RemoveSectorTriggers(sector, control); + } + } + + if (Rooms != null) + { + foreach (int roomNumber in Rooms) + { + RemoveSectorListTriggers(level.Rooms[roomNumber].Sectors, control); + } + } + + control.WriteToLevel(level); + } + + private void RemoveSectorListTriggers(IEnumerable sectors, FDControl control) + { + foreach (TRRoomSector sector in sectors) + { + RemoveSectorTriggers(sector, control); + } + } + private void RemoveSectorTriggers(TRRoomSector sector, FDControl control) { if (sector.FDIndex == 0) diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMReplaceTriggerActionParameterFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMReplaceTriggerActionParameterFunction.cs index 024a3b9db..9410ac7f1 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMReplaceTriggerActionParameterFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMReplaceTriggerActionParameterFunction.cs @@ -20,19 +20,38 @@ public override void ApplyToLevel(TR2Level level) foreach (EMLocation location in Locations) { TRRoomSector baseSector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); - if (baseSector.FDIndex == 0) - { - return; - } - - List actions = FDUtilities.GetActionListItems(control, TrigAction, baseSector.FDIndex); - foreach (FDActionListItem action in actions) - { - action.Parameter = NewParameter; - } + ReplaceActionParameter(baseSector, control); } control.WriteToLevel(level); } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + foreach (EMLocation location in Locations) + { + TRRoomSector baseSector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); + ReplaceActionParameter(baseSector, control); + } + + control.WriteToLevel(level); + } + + private void ReplaceActionParameter(TRRoomSector baseSector, FDControl control) + { + if (baseSector.FDIndex == 0) + { + return; + } + + List actions = FDUtilities.GetActionListItems(control, TrigAction, baseSector.FDIndex); + foreach (FDActionListItem action in actions) + { + action.Parameter = NewParameter; + } + } } } \ No newline at end of file diff --git a/TREnvironmentEditor/Model/Types/Triggers/EMTriggerFunction.cs b/TREnvironmentEditor/Model/Types/Triggers/EMTriggerFunction.cs index 86de732d9..91790fd0b 100644 --- a/TREnvironmentEditor/Model/Types/Triggers/EMTriggerFunction.cs +++ b/TREnvironmentEditor/Model/Types/Triggers/EMTriggerFunction.cs @@ -23,30 +23,41 @@ public override void ApplyToLevel(TR2Level level) foreach (EMLocation location in Locations) { TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); - // If there is no floor data create the FD to begin with. - if (sector.FDIndex == 0) - { - control.CreateFloorData(sector); - } + CreateTrigger(sector, control); + } - List entries = control.Entries[sector.FDIndex]; - if (Replace) - { - entries.Clear(); - } - if (entries.FindIndex(e => e is FDTriggerEntry) == -1) + // Handle any specifics that the trigger may rely on + foreach (FDActionListItem action in TriggerEntry.TrigActionList) + { + switch (action.TrigAction) { - entries.Add(TriggerEntry); + case FDTrigAction.ClearBodies: + SetEnemyClearBodies(level.Entities); + break; } } + control.WriteToLevel(level); + } + + public override void ApplyToLevel(TR3Level level) + { + FDControl control = new FDControl(); + control.ParseFromLevel(level); + + foreach (EMLocation location in Locations) + { + TRRoomSector sector = FDUtilities.GetRoomSector(location.X, location.Y, location.Z, location.Room, level, control); + CreateTrigger(sector, control); + } + // Handle any specifics that the trigger may rely on foreach (FDActionListItem action in TriggerEntry.TrigActionList) { switch (action.TrigAction) { case FDTrigAction.ClearBodies: - SetEnemyClearBodies(level); + SetEnemyClearBodies(level.Entities); break; } } @@ -54,9 +65,28 @@ public override void ApplyToLevel(TR2Level level) control.WriteToLevel(level); } - private void SetEnemyClearBodies(TR2Level level) + private void CreateTrigger(TRRoomSector sector, FDControl control) + { + // If there is no floor data create the FD to begin with. + if (sector.FDIndex == 0) + { + control.CreateFloorData(sector); + } + + List entries = control.Entries[sector.FDIndex]; + if (Replace) + { + entries.Clear(); + } + if (entries.FindIndex(e => e is FDTriggerEntry) == -1) + { + entries.Add(TriggerEntry); + } + } + + private void SetEnemyClearBodies(IEnumerable levelEntities) { - foreach (TR2Entity entity in level.Entities) + foreach (TR2Entity entity in levelEntities) { if (TR2EntityUtilities.IsEnemyType((TR2Entities)entity.TypeID)) { diff --git a/TREnvironmentEditor/Parsing/EMConverter.cs b/TREnvironmentEditor/Parsing/EMConverter.cs index e8bf4c693..ebc2ac20b 100644 --- a/TREnvironmentEditor/Parsing/EMConverter.cs +++ b/TREnvironmentEditor/Parsing/EMConverter.cs @@ -122,6 +122,10 @@ private object ReadEMType(JObject jo) return JsonConvert.DeserializeObject(jo.ToString(), _resolver); case EMType.ModifyOverlaps: return JsonConvert.DeserializeObject(jo.ToString(), _resolver); + case EMType.CopyRoom: + return JsonConvert.DeserializeObject(jo.ToString(), _resolver); + case EMType.CopyVertexAttributes: + return JsonConvert.DeserializeObject(jo.ToString(), _resolver); // NOOP case EMType.NOOP: diff --git a/TRFDControl/FDControl.cs b/TRFDControl/FDControl.cs index 8d0b8e3d5..c67f14fec 100644 --- a/TRFDControl/FDControl.cs +++ b/TRFDControl/FDControl.cs @@ -290,7 +290,7 @@ private void ParseFromSector(TRRoomSector sector, ushort[] FloorData, uint NumFl break; case FDFunctions.MechBeetleOrMinecartRotateRight: - TR3MinecraftRotateRightEntry mineright = new TR3MinecraftRotateRightEntry() + TR3MinecartRotateRightEntry mineright = new TR3MinecartRotateRightEntry() { Setup = new FDSetup() { Value = FloorData[index] }, }; diff --git a/TRFDControl/FDEntryTypes/TR3MinecraftRotateRightEntry.cs b/TRFDControl/FDEntryTypes/TR3MinecartRotateRightEntry.cs similarity index 75% rename from TRFDControl/FDEntryTypes/TR3MinecraftRotateRightEntry.cs rename to TRFDControl/FDEntryTypes/TR3MinecartRotateRightEntry.cs index 4ab4b5a57..49cdcfe85 100644 --- a/TRFDControl/FDEntryTypes/TR3MinecraftRotateRightEntry.cs +++ b/TRFDControl/FDEntryTypes/TR3MinecartRotateRightEntry.cs @@ -6,7 +6,7 @@ namespace TRFDControl.FDEntryTypes { - public class TR3MinecraftRotateRightEntry : FDEntry + public class TR3MinecartRotateRightEntry : FDEntry { } }