From fb8b4700b9bca828b5e496ef038845408085c63c Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Sat, 16 Apr 2022 09:36:41 +0100 Subject: [PATCH 01/11] #323 Rig Flipmap Fix Ensures the flipmap is off if the end level trigger for Rig has been moved to avoid a softlock. --- .../TR2/Environment/RIG.TR2-Environment.json | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/TRRandomizerCore/Resources/TR2/Environment/RIG.TR2-Environment.json b/TRRandomizerCore/Resources/TR2/Environment/RIG.TR2-Environment.json index d6ebdc0ea..12b97a33b 100644 --- a/TRRandomizerCore/Resources/TR2/Environment/RIG.TR2-Environment.json +++ b/TRRandomizerCore/Resources/TR2/Environment/RIG.TR2-Environment.json @@ -180,6 +180,35 @@ } } } + }, + + { + "Comments": "Ensure the flip map is off otherwise it's possible to softlock here (if the second pool before the end was skipped, the flipmap will be on).", + "EMType": 61, + "Locations": [ + { + "X": 38400, + "Y": -512, + "Z": 26112, + "Room": 70 + } + ], + "TriggerEntry": { + "Setup": { + "Value": 4 + }, + "TrigSetup": { + "Value": 15872 + }, + "TrigType": 0, + "TrigActionList": [ + { + "TrigAction": 5, + "Parameter": 0 + } + ] + } + } ] ], From c69ef8020061744e6592ecbd235b2ff75e539b38 Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Wed, 20 Apr 2022 19:18:00 +0100 Subject: [PATCH 02/11] #324 - Landmark Import Failure If trying to import landmarks and the number of object textures is already at the maximum for a level, the packing attempt will now no longer proceed as this expects at least one rectangle - otherwise it throws an exception. --- .../Textures/Landmarks/AbstractLandmarkImporter.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs b/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs index 9de191ea9..0b8dbccd5 100644 --- a/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs +++ b/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs @@ -26,9 +26,15 @@ public bool Import(L level, AbstractTextureMapping mapping, bool isLevelMi // Ensure any changes already made are committed to the level mapping.CommitGraphics(); + // If we are already at the maximum number of textures, bail out. + List textures = GetObjectTextures(level).ToList(); + if (textures.Count == MaxTextures) + { + return false; + } + using (AbstractTexturePacker packer = CreatePacker(level)) { - List textures = GetObjectTextures(level).ToList(); foreach (StaticTextureSource source in mapping.LandmarkMapping.Keys) { if (textures.Count == MaxTextures) From be54adeb3948b1c933501e4de7ecdd97aeae66fe Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 25 Apr 2022 11:59:28 +0100 Subject: [PATCH 03/11] #325 Lost Floater Enemy Ensures that enemy 52 won't drop to the level floor by moving him if he can't fly. --- .../Environment/FLOATING.TR2-Environment.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json b/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json index 81a37de64..6422788e9 100644 --- a/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json +++ b/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json @@ -281,6 +281,28 @@ } } ] + }, + + { + "Condition": { + "Comments": "#325 If enemy 52 can't fly, move him to a platform to avoid dropping to the level floor.", + "ConditionType": 0, + "EntityIndex": 52, + "EntityTypes": [ 25, 28, 29, 38, 43, 47 ] + }, + "OnFalse": [ + { + "EMType": 44, + "EntityIndex": 52, + "TargetLocation": { + "X": 39424, + "Y": -4096, + "Z": 49664, + "Room": 63, + "Angle": -32768 + } + } + ] } ], From 4cd44945b441bef7176cf521a04b56cf06b9fa3b Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 25 Apr 2022 12:36:48 +0100 Subject: [PATCH 04/11] #304 Cross-game Preparations Some preparations for cross-game level support. - Zones/ZoneGroups implemented for TR1 as per TR2&3. Unit test added for adding to zones. - Ability to set the number of sounds in TRSoundDetails. - Ability to find tile segments from texture indices in texture packer. - Ability to add faces to meshes in MeshEditor. - Several general models made available for import (bridges, keys, some traps etc). - Fixes some texture deduplication issues in GW. --- TRLevelReader/Helpers/TR1BoxUtilities.cs | 88 ++++++++++++++++++ TRLevelReader/Model/Base/Enums/TRZones.cs | 8 ++ TRLevelReader/Model/Base/TRLevel.cs | 17 +--- TRLevelReader/Model/Base/TRSoundDetails.cs | 14 ++- TRLevelReader/Model/Base/TRZone.cs | 49 +++++----- TRLevelReader/Model/Base/TRZoneGroup.cs | 25 +++++ TRLevelReader/TRLevelReader.cs | 9 +- TRLevelReaderUnitTests/TRLevel_UnitTests.cs | 51 ++++++++++ .../Data/TR2DefaultDataProvider.cs | 8 +- .../Packing/AbstractTexturePacker.cs | 30 ++++++ TRRandomizerCore/Helpers/MeshEditor.cs | 16 ++++ .../Resources/TR2/Models/BridgeFlat/Data.json | 1 + .../TR2/Models/BridgeFlat/Segments.png | Bin 0 -> 3615 bytes .../TR2/Models/BridgeTilt1/Data.json | 1 + .../TR2/Models/BridgeTilt1/Segments.png | Bin 0 -> 3615 bytes .../TR2/Models/BridgeTilt2/Data.json | 1 + .../TR2/Models/BridgeTilt2/Segments.png | Bin 0 -> 3615 bytes .../Resources/TR2/Models/Disc_H/Data.json | 1 + .../Resources/TR2/Models/Disc_H/Segments.png | Bin 0 -> 747 bytes .../Resources/TR2/Models/Discgun/Data.json | 1 + .../Resources/TR2/Models/Discgun/Segments.png | Bin 0 -> 2514 bytes .../Resources/TR2/Models/Door1/Data.json | 1 + .../Resources/TR2/Models/Door1/Segments.png | Bin 0 -> 7688 bytes .../Resources/TR2/Models/Door2/Data.json | 1 + .../Resources/TR2/Models/Door2/Segments.png | Bin 0 -> 7688 bytes .../Resources/TR2/Models/Door3/Data.json | 1 + .../Resources/TR2/Models/Door3/Segments.png | Bin 0 -> 7952 bytes .../Resources/TR2/Models/Door4/Data.json | 1 + .../Resources/TR2/Models/Door4/Segments.png | Bin 0 -> 3375 bytes .../TR2/Models/FallingBlock/Data.json | 1 + .../TR2/Models/FallingBlock/Segments.png | Bin 0 -> 2653 bytes .../Models/FallingCeilingOrSandbag/Data.json | 1 + .../FallingCeilingOrSandbag/Segments.png | Bin 0 -> 2425 bytes .../Resources/TR2/Models/Gong/Data.json | 1 + .../Resources/TR2/Models/Gong/Segments.png | Bin 0 -> 19517 bytes .../Resources/TR2/Models/Key2_M_H/Data.json | 1 + .../TR2/Models/Key2_M_H/Segments.png | Bin 0 -> 5350 bytes .../Resources/TR2/Models/Key3_M_H/Data.json | 1 + .../TR2/Models/Key3_M_H/Segments.png | Bin 0 -> 683 bytes .../Resources/TR2/Models/Key4_M_H/Data.json | 1 + .../TR2/Models/Key4_M_H/Segments.png | Bin 0 -> 623 bytes .../Resources/TR2/Models/Keyhole3/Data.json | 1 + .../TR2/Models/Keyhole3/Segments.png | Bin 0 -> 453 bytes .../Resources/TR2/Models/Keyhole4/Data.json | 1 + .../TR2/Models/Keyhole4/Segments.png | Bin 0 -> 510 bytes .../TR2/Models/LiftingDoor1/Data.json | 1 + .../TR2/Models/LiftingDoor1/Segments.png | Bin 0 -> 2797 bytes .../Resources/TR2/Models/Monk/Data.json | 1 + .../Resources/TR2/Models/Monk/Segments.png | Bin 0 -> 13562 bytes .../Resources/TR2/Models/PushBlock1/Data.json | 1 + .../TR2/Models/PushBlock1/Segments.png | Bin 0 -> 8380 bytes .../Puzzle1_M_H_CircuitBreaker/Data.json | 1 + .../Puzzle1_M_H_CircuitBreaker/Segments.png | Bin 0 -> 832 bytes .../TR2/Models/PuzzleDone1/Data.json | 1 + .../TR2/Models/PuzzleDone1/Segments.png | Bin 0 -> 1276 bytes .../TR2/Models/PuzzleHole1/Data.json | 1 + .../TR2/Models/PuzzleHole1/Segments.png | Bin 0 -> 1152 bytes .../Resources/TR2/Models/Quest1_M_H/Data.json | 1 + .../TR2/Models/Quest1_M_H/Segments.png | Bin 0 -> 3778 bytes .../TR2/Models/SandbagOrBallsack/Data.json | 1 + .../TR2/Models/SandbagOrBallsack/Segments.png | Bin 0 -> 3113 bytes .../TR2/Models/SlammingDoor/Data.json | 1 + .../TR2/Models/SlammingDoor/Segments.png | Bin 0 -> 5014 bytes .../TR2/Models/TibetanBell/Data.json | 1 + .../TR2/Models/TibetanBell/Segments.png | Bin 0 -> 7173 bytes .../TR2/Models/UnderwaterSwitch/Data.json | 1 + .../TR2/Models/UnderwaterSwitch/Segments.png | Bin 0 -> 671 bytes .../TR2/Models/WaterfallMist_N/Data.json | 1 + .../TR2/Models/WaterfallMist_N/Segments.png | Bin 0 -> 1909 bytes .../Deduplication/WALL.TR2-TextureRemap.json | 49 ++++++++++ 70 files changed, 352 insertions(+), 41 deletions(-) create mode 100644 TRLevelReader/Helpers/TR1BoxUtilities.cs create mode 100644 TRLevelReader/Model/Base/Enums/TRZones.cs create mode 100644 TRLevelReader/Model/Base/TRZoneGroup.cs create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Disc_H/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Disc_H/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Discgun/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Discgun/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door2/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door2/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door3/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door3/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door4/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Door4/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/FallingBlock/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/FallingBlock/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Gong/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Gong/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key4_M_H/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Key4_M_H/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Keyhole3/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Keyhole3/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Keyhole4/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Keyhole4/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Monk/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Monk/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/PushBlock1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/PushBlock1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Puzzle1_M_H_CircuitBreaker/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Puzzle1_M_H_CircuitBreaker/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/PuzzleDone1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/PuzzleDone1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/PuzzleHole1/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/PuzzleHole1/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/Quest1_M_H/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/Quest1_M_H/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/SlammingDoor/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/SlammingDoor/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/TibetanBell/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/TibetanBell/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/UnderwaterSwitch/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/UnderwaterSwitch/Segments.png create mode 100644 TRRandomizerCore/Resources/TR2/Models/WaterfallMist_N/Data.json create mode 100644 TRRandomizerCore/Resources/TR2/Models/WaterfallMist_N/Segments.png diff --git a/TRLevelReader/Helpers/TR1BoxUtilities.cs b/TRLevelReader/Helpers/TR1BoxUtilities.cs new file mode 100644 index 000000000..4d375e904 --- /dev/null +++ b/TRLevelReader/Helpers/TR1BoxUtilities.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TRLevelReader.Model; +using TRLevelReader.Model.Base.Enums; + +namespace TRLevelReader.Helpers +{ + public static class TR1BoxUtilities + { + public static void DuplicateZone(TRLevel level, int boxIndex) + { + TRZoneGroup zoneGroup = level.Zones[boxIndex]; + List zones = level.Zones.ToList(); + zones.Add(new TRZoneGroup + { + NormalZone = zoneGroup.NormalZone.Clone(), + AlternateZone = zoneGroup.AlternateZone.Clone() + }); + level.Zones = zones.ToArray(); + } + + public static TRZoneGroup[] ReadZones(uint numBoxes, ushort[] zoneData) + { + // Initialise the zone groups - one for every box. + TRZoneGroup[] zones = new TRZoneGroup[numBoxes]; + for (int i = 0; i < zones.Length; i++) + { + zones[i] = new TRZoneGroup + { + NormalZone = new TRZone(), + AlternateZone = new TRZone() + }; + } + + // Build the zones, mapping the multidimensional ushort structures into the corresponding + // zone object values. + IEnumerable flipValues = Enum.GetValues(typeof(FlipStatus)).Cast(); + IEnumerable zoneValues = Enum.GetValues(typeof(TRZones)).Cast(); + + int valueIndex = 0; + foreach (FlipStatus flip in flipValues) + { + foreach (TRZones zone in zoneValues) + { + for (int box = 0; box < zones.Length; box++) + { + zones[box][flip].GroundZones[zone] = zoneData[valueIndex++]; + } + } + + for (int box = 0; box < zones.Length; box++) + { + zones[box][flip].FlyZone = zoneData[valueIndex++]; + } + } + + return zones; + } + + public static ushort[] FlattenZones(TRZoneGroup[] zoneGroups) + { + // Convert the zone objects back into a flat ushort list. + IEnumerable flipValues = Enum.GetValues(typeof(FlipStatus)).Cast(); + IEnumerable zoneValues = Enum.GetValues(typeof(TRZones)).Cast(); + + List zones = new List(); + + foreach (FlipStatus flip in flipValues) + { + foreach (TRZones zone in zoneValues) + { + for (int box = 0; box < zoneGroups.Length; box++) + { + zones.Add(zoneGroups[box][flip].GroundZones[zone]); + } + } + + for (int box = 0; box < zoneGroups.Length; box++) + { + zones.Add(zoneGroups[box][flip].FlyZone); + } + } + + return zones.ToArray(); + } + } +} \ No newline at end of file diff --git a/TRLevelReader/Model/Base/Enums/TRZones.cs b/TRLevelReader/Model/Base/Enums/TRZones.cs new file mode 100644 index 000000000..46c8a000e --- /dev/null +++ b/TRLevelReader/Model/Base/Enums/TRZones.cs @@ -0,0 +1,8 @@ +namespace TRLevelReader.Model.Base.Enums +{ + public enum TRZones + { + Zone1 = 0, + Zone2 = 1 + } +} \ No newline at end of file diff --git a/TRLevelReader/Model/Base/TRLevel.cs b/TRLevelReader/Model/Base/TRLevel.cs index 908b2691a..8f6e54660 100644 --- a/TRLevelReader/Model/Base/TRLevel.cs +++ b/TRLevelReader/Model/Base/TRLevel.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using TRLevelReader.Helpers; using TRLevelReader.Serialization; namespace TRLevelReader.Model @@ -220,19 +221,7 @@ public class TRLevel : BaseTRLevel, ISerializableCompact /// public ushort[] Overlaps { get; set; } - public ushort[] Zones { get; set; } - - public ushort[] GroundZone { get; set; } - - public ushort[] GroundZone2 { get; set; } - - public ushort[] FlyZone { get; set; } - - public ushort[] GroundZoneAlt { get; set; } - - public ushort[] GroundZoneAlt2 { get; set; } - - public ushort[] FlyZoneAlt { get; set; } + public TRZoneGroup[] Zones { get; set; } /// /// 4 bytes @@ -371,7 +360,7 @@ public byte[] Serialize() foreach (TRBox box in Boxes) { writer.Write(box.Serialize()); } writer.Write(NumOverlaps); foreach (ushort overlap in Overlaps) { writer.Write(overlap); } - foreach (ushort zone in Zones) { writer.Write(zone); } + foreach (ushort zone in TR1BoxUtilities.FlattenZones(Zones)) { writer.Write(zone); } writer.Write(NumAnimatedTextures); writer.Write((ushort)AnimatedTextures.Length); foreach (TRAnimatedTexture texture in AnimatedTextures) { writer.Write(texture.Serialize()); } diff --git a/TRLevelReader/Model/Base/TRSoundDetails.cs b/TRLevelReader/Model/Base/TRSoundDetails.cs index c0979c7c3..15ce1005a 100644 --- a/TRLevelReader/Model/Base/TRSoundDetails.cs +++ b/TRLevelReader/Model/Base/TRSoundDetails.cs @@ -17,7 +17,19 @@ public class TRSoundDetails : ISerializableCompact public ushort Chance { get; set; } public ushort Characteristics { get; set; } - public int NumSounds => (Characteristics & 0x00FC) >> 2; // get bits 2-7 + + public int NumSounds + { + get + { + return (Characteristics & 0x00FC) >> 2; // get bits 2-7 + } + set + { + Characteristics = (ushort)(Characteristics & ~(Characteristics & 0x00FC)); + Characteristics |= (ushort)(value << 2); + } + } public override string ToString() { diff --git a/TRLevelReader/Model/Base/TRZone.cs b/TRLevelReader/Model/Base/TRZone.cs index 79b080abf..7d23fafd3 100644 --- a/TRLevelReader/Model/Base/TRZone.cs +++ b/TRLevelReader/Model/Base/TRZone.cs @@ -2,26 +2,20 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; - +using TRLevelReader.Model.Base.Enums; using TRLevelReader.Serialization; namespace TRLevelReader.Model { - public class TRZone : ISerializableCompact + public class TRZone : ISerializableCompact, ICloneable { - public ushort GroundZone1Normal { get; set; } - - public ushort GroundZone2Normal { get; set; } - - public ushort FlyZoneNormal { get; set; } - - public ushort GroundZone1Alternate { get; set; } + public Dictionary GroundZones { get; set; } + public ushort FlyZone { get; set; } - public ushort GroundZone2Alternate { get; set; } - - public ushort FlyZoneAlternate { get; set; } + public TRZone() + { + GroundZones = new Dictionary(); + } public byte[] Serialize() { @@ -29,16 +23,29 @@ public byte[] Serialize() { using (BinaryWriter writer = new BinaryWriter(stream)) { - writer.Write(GroundZone1Normal); - writer.Write(GroundZone2Normal); - writer.Write(FlyZoneNormal); - writer.Write(GroundZone1Alternate); - writer.Write(GroundZone2Alternate); - writer.Write(FlyZoneAlternate); + foreach (ushort zone in GroundZones.Values) + { + writer.Write(zone); + } + writer.Write(FlyZone); } return stream.ToArray(); } } + + public TRZone Clone() + { + return new TRZone + { + GroundZones = GroundZones.ToDictionary(e => e.Key, e => e.Value), + FlyZone = FlyZone + }; + } + + object ICloneable.Clone() + { + return Clone(); + } } -} +} \ No newline at end of file diff --git a/TRLevelReader/Model/Base/TRZoneGroup.cs b/TRLevelReader/Model/Base/TRZoneGroup.cs new file mode 100644 index 000000000..2780527f1 --- /dev/null +++ b/TRLevelReader/Model/Base/TRZoneGroup.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using TRLevelReader.Model.Base.Enums; + +namespace TRLevelReader.Model +{ + public class TRZoneGroup : Dictionary + { + /// + /// Zone values when flipmap is off. + /// + public TRZone NormalZone + { + get => this[FlipStatus.Off]; + set => this[FlipStatus.Off] = value; + } + /// + /// Zone values when flipmap is on. + /// + public TRZone AlternateZone + { + get => this[FlipStatus.On]; + set => this[FlipStatus.On] = value; + } + } +} \ No newline at end of file diff --git a/TRLevelReader/TRLevelReader.cs b/TRLevelReader/TRLevelReader.cs index 187a4fa98..719cd3cfa 100644 --- a/TRLevelReader/TRLevelReader.cs +++ b/TRLevelReader/TRLevelReader.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using TRLevelReader.Helpers; using TRLevelReader.Model; namespace TRLevelReader @@ -284,12 +285,12 @@ public TRLevel ReadLevel(string Filename) level.Overlaps[i] = reader.ReadUInt16(); } - level.Zones = new ushort[6 * level.NumBoxes]; - - for (int i = 0; i < level.Zones.Count(); i++) + ushort[] zoneData = new ushort[level.NumBoxes * 6]; + for (int i = 0; i < zoneData.Length; i++) { - level.Zones[i] = reader.ReadUInt16(); + zoneData[i] = reader.ReadUInt16(); } + level.Zones = TR1BoxUtilities.ReadZones(level.NumBoxes, zoneData); //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) //followed by a ushort to describe the number of actual texture group objects. diff --git a/TRLevelReaderUnitTests/TRLevel_UnitTests.cs b/TRLevelReaderUnitTests/TRLevel_UnitTests.cs index 88c1682af..5ffcf5110 100644 --- a/TRLevelReaderUnitTests/TRLevel_UnitTests.cs +++ b/TRLevelReaderUnitTests/TRLevel_UnitTests.cs @@ -10,6 +10,8 @@ using TRFDControl.FDEntryTypes; using TRFDControl.Utilities; using System.Linq; +using TRLevelReader.Model.Base.Enums; +using TRLevelReader.Helpers; namespace TRLevelReaderUnitTests { @@ -386,5 +388,54 @@ public void Floordata_ReadWrite_DefaultTest() TR1LevelWriter writer = new TR1LevelWriter(); writer.WriteLevelToFile(lvl, "level10c_fdata.phd"); } + + [TestMethod] + public void ModifyZonesTest() + { + TR1LevelReader reader = new TR1LevelReader(); + TRLevel lvl = reader.ReadLevel("level1.phd"); + + // For every box, store the current zone. We use the serialized form + // for comparison. + Dictionary flipOffZones = new Dictionary(); + Dictionary flipOnZones = new Dictionary(); + for (int i = 0; i < lvl.NumBoxes; i++) + { + flipOffZones[i] = lvl.Zones[i][FlipStatus.Off].Serialize(); + flipOnZones[i] = lvl.Zones[i][FlipStatus.On].Serialize(); + } + + // Add a new box + List boxes = lvl.Boxes.ToList(); + boxes.Add(boxes[0]); + lvl.Boxes = boxes.ToArray(); + lvl.NumBoxes++; + + // Add a new zone for the box and store its serialized form for comparison + int newBoxIndex = (int)(lvl.NumBoxes - 1); + TR1BoxUtilities.DuplicateZone(lvl, 0); + flipOffZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.Off].Serialize(); + flipOnZones[newBoxIndex] = lvl.Zones[newBoxIndex][FlipStatus.On].Serialize(); + + // Verify the number of zone ushorts matches what's expected for the box count + Assert.AreEqual(TR1BoxUtilities.FlattenZones(lvl.Zones).Length, (int)(6 * lvl.NumBoxes)); + + // Write and re-read the level + new TR1LevelWriter().WriteLevelToFile(lvl, "TEST.phd"); + lvl = reader.ReadLevel("TEST.phd"); + + // Capture all of the zones again. Make sure the addition of the zone above didn't + // affect any of the others and that the addition itself matches after IO. + for (int i = 0; i < lvl.NumBoxes; i++) + { + byte[] flipOff = lvl.Zones[i][FlipStatus.Off].Serialize(); + Assert.IsTrue(flipOffZones.ContainsKey(i)); + CollectionAssert.AreEqual(flipOffZones[i], flipOff); + + byte[] flipOn = lvl.Zones[i][FlipStatus.On].Serialize(); + Assert.IsTrue(flipOnZones.ContainsKey(i)); + CollectionAssert.AreEqual(flipOnZones[i], flipOn); + } + } } } diff --git a/TRModelTransporter/Data/TR2DefaultDataProvider.cs b/TRModelTransporter/Data/TR2DefaultDataProvider.cs index 1902bef8e..d5276539c 100644 --- a/TRModelTransporter/Data/TR2DefaultDataProvider.cs +++ b/TRModelTransporter/Data/TR2DefaultDataProvider.cs @@ -184,7 +184,11 @@ public IEnumerable GetIgnorableTextureIndices(TR2Entities entity) [TR2Entities.RedSnowmobile] = new List { TR2Entities.SnowmobileWake_S_H }, [TR2Entities.XianGuardSword] - = new List { TR2Entities.XianGuardSparkles_S_H } + = new List { TR2Entities.XianGuardSparkles_S_H }, + [TR2Entities.WaterfallMist_N] + = new List { TR2Entities.WaterRipples_S_H }, + [TR2Entities.Key2_M_H] + = new List { TR2Entities.Key2_S_P } }; private static readonly List _cinematicEntities = new List @@ -373,6 +377,8 @@ public IEnumerable GetIgnorableTextureIndices(TR2Entities entity) { [TR2Entities.LaraMiscAnim_H] = new List(), // empty list indicates to ignore everything + [TR2Entities.WaterfallMist_N] + = new List { 0, 1, 2, 3, 4, 5, 6, 11, 15, 20, 22 }, [TR2Entities.LaraSnowmobAnim_H] = new List { 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 20, 21, 23 }, [TR2Entities.SnowmobileBelt] diff --git a/TRModelTransporter/Packing/AbstractTexturePacker.cs b/TRModelTransporter/Packing/AbstractTexturePacker.cs index e49b695d1..a6d0e37c1 100644 --- a/TRModelTransporter/Packing/AbstractTexturePacker.cs +++ b/TRModelTransporter/Packing/AbstractTexturePacker.cs @@ -110,6 +110,21 @@ public Dictionary> GetModelSegments(E mo return segmentMap; } + public Dictionary> GetObjectTextureSegments(IEnumerable indices) + { + Dictionary> segmentMap = new Dictionary>(); + foreach (TexturedTile tile in _tiles) + { + List segments = tile.GetObjectTextureIndexSegments(indices); + if (segments.Count > 0) + { + segmentMap[tile] = segments; + } + } + + return segmentMap; + } + protected abstract TRMesh[] GetModelMeshes(E modelEntity); public Dictionary> GetSpriteSegments(E entity) @@ -137,6 +152,21 @@ public Dictionary> GetSpriteSegments(E e return segmentMap; } + public Dictionary> GetSpriteTextureSegments(IEnumerable indices) + { + Dictionary> segmentMap = new Dictionary>(); + foreach (TexturedTile tile in _tiles) + { + List segments = tile.GetSpriteTextureIndexSegments(indices); + if (segments.Count > 0) + { + segmentMap[tile] = segments; + } + } + + return segmentMap; + } + protected abstract TRSpriteSequence GetSpriteSequence(E entity); protected IEnumerable GetMeshTextureIndices(TRMesh[] meshes) diff --git a/TRRandomizerCore/Helpers/MeshEditor.cs b/TRRandomizerCore/Helpers/MeshEditor.cs index a0455605f..d7c05dafb 100644 --- a/TRRandomizerCore/Helpers/MeshEditor.cs +++ b/TRRandomizerCore/Helpers/MeshEditor.cs @@ -116,6 +116,22 @@ public void RemoveColouredTriangles(IEnumerable indices) Mesh.NumColouredTriangles = (short)triangles.Count; } + public void AddTexturedRectangle(TRFace4 face) + { + List rectangles = Mesh.TexturedRectangles.ToList(); + rectangles.Add(face); + Mesh.TexturedRectangles = rectangles.ToArray(); + Mesh.NumTexturedRectangles = (short)rectangles.Count; + } + + public void AddTexturedTriangle(TRFace3 face) + { + List triangles = Mesh.TexturedTriangles.ToList(); + triangles.Add(face); + Mesh.TexturedTriangles = triangles.ToArray(); + Mesh.NumTexturedTriangles = (short)triangles.Count; + } + public TRMesh CloneMesh(TRMesh mesh) { TRMesh clone = new TRMesh diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Data.json b/TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Data.json new file mode 100644 index 000000000..4ba772ff7 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Data.json @@ -0,0 +1 @@ +{"Animations":{"434":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":434,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":355,"NumAnimCommands":0,"AnimCommand":1624},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65026,510,3,53,65026,510,0,3,0,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":72932,"Centre":{"X":0,"Y":25,"Z":0},"CollRadius":128549,"NumVertices":8,"Vertices":[{"X":510,"Y":50,"Z":-510},{"X":-510,"Y":50,"Z":-510},{"X":-510,"Y":50,"Z":510},{"X":510,"Y":50,"Z":510},{"X":510,"Y":0,"Z":-510},{"X":-510,"Y":0,"Z":-510},{"X":-510,"Y":0,"Z":510},{"X":510,"Y":0,"Z":510}],"NumNormals":8,"Normals":[{"X":11526,"Y":11526,"Z":0},{"X":-11526,"Y":11526,"Z":0},{"X":-11526,"Y":11526,"Z":0},{"X":11526,"Y":11526,"Z":0},{"X":11526,"Y":-11526,"Z":0},{"X":-11526,"Y":-11526,"Z":0},{"X":-11526,"Y":-11526,"Z":0},{"X":11526,"Y":-11526,"Z":0}],"Lights":null,"NumTexturedRectangles":4,"TexturedRectangles":[{"Vertices":[1,0,3,2],"Texture":924},{"Vertices":[6,5,1,2],"Texture":925},{"Vertices":[3,0,4,7],"Texture":925},{"Vertices":[4,5,6,7],"Texture":924}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":-1,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":117,"NumMeshes":1,"StartingMesh":301,"MeshTree":1088,"FrameOffset":385152,"Animation":434},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":1,"AtlasAndFlag":5,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":924,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}],"1":[{"Texture":{"Attribute":1,"AtlasAndFlag":9,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":255,"Fraction":167}},{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":255,"Fraction":167}}]},"IsTriangle":false,"Index":925,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 64","64, 0, 64, 8"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Segments.png b/TRRandomizerCore/Resources/TR2/Models/BridgeFlat/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..05adfe1a80ff8a661c7f7998f08cfbc0e23d39dc GIT binary patch literal 3615 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 literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Data.json b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Data.json new file mode 100644 index 000000000..1f86e8a8f --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Data.json @@ -0,0 +1 @@ +{"Animations":{"435":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":435,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":355,"NumAnimCommands":0,"AnimCommand":1624},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65026,510,5,315,65026,510,0,160,0,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":73092,"Centre":{"X":5,"Y":23,"Z":-2},"CollRadius":87604,"NumVertices":8,"Vertices":[{"X":510,"Y":-105,"Z":-510},{"X":-510,"Y":155,"Z":-510},{"X":-510,"Y":155,"Z":510},{"X":510,"Y":-105,"Z":510},{"X":510,"Y":-155,"Z":-510},{"X":-510,"Y":105,"Z":-510},{"X":-510,"Y":105,"Z":510},{"X":510,"Y":-155,"Z":510}],"NumNormals":8,"Normals":[{"X":2847,"Y":11168,"Z":-11526},{"X":2847,"Y":11168,"Z":-11526},{"X":2847,"Y":11169,"Z":11526},{"X":2847,"Y":11169,"Z":11526},{"X":-2847,"Y":-11169,"Z":-11525},{"X":-2847,"Y":-11169,"Z":-11525},{"X":-2847,"Y":-11169,"Z":11526},{"X":-2847,"Y":-11169,"Z":11526}],"Lights":null,"NumTexturedRectangles":4,"TexturedRectangles":[{"Vertices":[0,3,2,1],"Texture":924},{"Vertices":[7,4,5,6],"Texture":924},{"Vertices":[2,3,7,6],"Texture":925},{"Vertices":[5,4,0,1],"Texture":925}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":-1,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":118,"NumMeshes":1,"StartingMesh":302,"MeshTree":1088,"FrameOffset":385172,"Animation":435},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":1,"AtlasAndFlag":5,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":924,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}],"1":[{"Texture":{"Attribute":1,"AtlasAndFlag":9,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":255,"Fraction":167}},{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":255,"Fraction":167}}]},"IsTriangle":false,"Index":925,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 64","64, 0, 64, 8"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Segments.png b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt1/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..05adfe1a80ff8a661c7f7998f08cfbc0e23d39dc GIT binary patch literal 3615 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 literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Data.json b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Data.json new file mode 100644 index 000000000..3c924aa4e --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Data.json @@ -0,0 +1 @@ +{"Animations":{"436":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":436,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":355,"NumAnimCommands":0,"AnimCommand":1624},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65026,510,5,571,65026,510,0,288,0,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":73252,"Centre":{"X":0,"Y":0,"Z":0},"CollRadius":75721,"NumVertices":8,"Vertices":[{"X":510,"Y":-233,"Z":-510},{"X":-510,"Y":283,"Z":-510},{"X":-510,"Y":283,"Z":510},{"X":510,"Y":-233,"Z":510},{"X":510,"Y":-282,"Z":-510},{"X":-510,"Y":233,"Z":-510},{"X":-510,"Y":233,"Z":510},{"X":510,"Y":-283,"Z":510}],"NumNormals":8,"Normals":[{"X":5195,"Y":10288,"Z":-11526},{"X":5195,"Y":10288,"Z":-11526},{"X":5195,"Y":10289,"Z":11526},{"X":5195,"Y":10289,"Z":11526},{"X":-5195,"Y":-10289,"Z":-11525},{"X":-5195,"Y":-10289,"Z":-11525},{"X":-5195,"Y":-10289,"Z":11526},{"X":-5195,"Y":-10289,"Z":11526}],"Lights":null,"NumTexturedRectangles":4,"TexturedRectangles":[{"Vertices":[0,3,2,1],"Texture":924},{"Vertices":[7,4,5,6],"Texture":924},{"Vertices":[2,3,7,6],"Texture":925},{"Vertices":[5,4,0,1],"Texture":925}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":-1,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":119,"NumMeshes":1,"StartingMesh":303,"MeshTree":1088,"FrameOffset":385192,"Animation":436},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":1,"AtlasAndFlag":5,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":924,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}],"1":[{"Texture":{"Attribute":1,"AtlasAndFlag":9,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":255,"Fraction":175},"YCoordinate":{"Whole":255,"Fraction":167}},{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":255,"Fraction":167}}]},"IsTriangle":false,"Index":925,"Classification":"09908143b3fa6fd285c6eaca4c80606f"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 64","64, 0, 64, 8"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Segments.png b/TRRandomizerCore/Resources/TR2/Models/BridgeTilt2/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..05adfe1a80ff8a661c7f7998f08cfbc0e23d39dc GIT binary patch literal 3615 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 literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/Disc_H/Data.json b/TRRandomizerCore/Resources/TR2/Models/Disc_H/Data.json new file mode 100644 index 000000000..e7928f0fe --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/Disc_H/Data.json @@ -0,0 +1 @@ +{"Animations":{"306":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":100},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":306,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":294,"NumAnimCommands":0,"AnimCommand":1282},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65529,7,65494,44,65491,43,0,1,65533,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":49512,"Centre":{"X":0,"Y":0,"Z":2},"CollRadius":47,"NumVertices":16,"Vertices":[{"X":-7,"Y":-15,"Z":18},{"X":-7,"Y":-15,"Z":-14},{"X":-7,"Y":15,"Z":18},{"X":-7,"Y":15,"Z":-14},{"X":0,"Y":-43,"Z":2},{"X":0,"Y":43,"Z":2},{"X":0,"Y":-2,"Z":46},{"X":0,"Y":-2,"Z":-42},{"X":7,"Y":-15,"Z":18},{"X":7,"Y":-15,"Z":-14},{"X":7,"Y":15,"Z":18},{"X":7,"Y":15,"Z":-14},{"X":0,"Y":-32,"Z":34},{"X":0,"Y":-32,"Z":-29},{"X":0,"Y":30,"Z":35},{"X":0,"Y":32,"Z":-31}],"NumNormals":16,"Normals":[{"X":-15996,"Y":-2213,"Z":2221},{"X":-16000,"Y":-2240,"Z":-2160},{"X":-15998,"Y":2154,"Z":2263},{"X":-16024,"Y":2105,"Z":-2116},{"X":93,"Y":-16300,"Z":10},{"X":91,"Y":16295,"Z":408},{"X":93,"Y":-303,"Z":16297},{"X":91,"Y":-553,"Z":-16290},{"X":16018,"Y":-2132,"Z":2140},{"X":16022,"Y":-2158,"Z":-2082},{"X":16020,"Y":2075,"Z":2181},{"X":16044,"Y":2029,"Z":-2039},{"X":110,"Y":-11590,"Z":11460},{"X":109,"Y":-11820,"Z":-11224},{"X":111,"Y":11207,"Z":11836},{"X":106,"Y":11492,"Z":-11559}],"Lights":null,"NumTexturedRectangles":2,"TexturedRectangles":[{"Vertices":[9,8,10,11],"Texture":737},{"Vertices":[0,1,3,2],"Texture":737}],"NumTexturedTriangles":24,"TexturedTriangles":[{"Vertices":[7,9,11],"Texture":738},{"Vertices":[8,9,4],"Texture":739},{"Vertices":[1,0,4],"Texture":739},{"Vertices":[1,7,3],"Texture":738},{"Vertices":[2,3,5],"Texture":740},{"Vertices":[6,0,2],"Texture":738},{"Vertices":[11,10,5],"Texture":740},{"Vertices":[8,6,10],"Texture":738},{"Vertices":[13,1,4],"Texture":739},{"Vertices":[7,1,13],"Texture":739},{"Vertices":[7,15,3],"Texture":738},{"Vertices":[15,5,3],"Texture":738},{"Vertices":[4,0,12],"Texture":739},{"Vertices":[0,6,12],"Texture":739},{"Vertices":[14,6,2],"Texture":738},{"Vertices":[5,14,2],"Texture":738},{"Vertices":[13,9,7],"Texture":739},{"Vertices":[9,13,4],"Texture":739},{"Vertices":[15,7,11],"Texture":738},{"Vertices":[5,15,11],"Texture":738},{"Vertices":[14,5,10],"Texture":738},{"Vertices":[6,14,10],"Texture":738},{"Vertices":[8,12,6],"Texture":739},{"Vertices":[12,8,4],"Texture":739}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":0,"OffsetX":-75,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":61,"NumMeshes":1,"StartingMesh":251,"MeshTree":936,"FrameOffset":310788,"Animation":306},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":48},"YCoordinate":{"Whole":1,"Fraction":24}},{"XCoordinate":{"Whole":255,"Fraction":71},"YCoordinate":{"Whole":1,"Fraction":24}},{"XCoordinate":{"Whole":255,"Fraction":71},"YCoordinate":{"Whole":255,"Fraction":47}},{"XCoordinate":{"Whole":1,"Fraction":48},"YCoordinate":{"Whole":255,"Fraction":47}}]},"IsTriangle":false,"Index":737,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}],"1":[{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":1,"Fraction":144}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":144}},{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":738,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"},{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":1,"Fraction":112},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":144}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":740,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}],"2":[{"Texture":{"Attribute":0,"AtlasAndFlag":8,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":1,"Fraction":72}},{"XCoordinate":{"Whole":255,"Fraction":23},"YCoordinate":{"Whole":1,"Fraction":72}},{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":255,"Fraction":79}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":739,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 24, 24","24, 0, 24, 16","48, 0, 24, 8"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/Disc_H/Segments.png b/TRRandomizerCore/Resources/TR2/Models/Disc_H/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..71d238dc99764478e4c3d99c0c9bf9c3c8be09ac GIT binary patch literal 747 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0)R01Isjz*ydB^}V(629*Rtv=P8E0!S04V77Ua zjBl<DT| zVltfQu+nn1MUS6Gw13_6JFKNa#8T+WUSO!;L5Bxfsk*K0EaMD_wzK zG8)WaPMct=ofUJC*&-K-W4)Tc1>0M5wV0JbbFtDKBC>38+0h9`Sp#&Y#9#JhHi4>i zXh9OXZq;e@{v{CBbzQ&TgMGi-k=+|)+Z>G7IiiemVV&HT0q;NtjZzr6GQU;g8HB7z znd1ZkZ=6ONK|*_-VNpi8ko%iiAh!+0^Z6ZY%kAccL@^%sECu=ln+JG=?S?kK{2a_y zL>c8m8l+c$2{cHK2jsS}7_x)-%$hi#qPg-t$|x6dGDM49&Se;@ZQH(Sa@y9NGm_co zkSiB`qKt9@G1ff=>20O-E4X!}*>zo;Y&ILgw%=|+Bgo6p4(;nY5oMGM2;-{rZjs8C zGam2iMK(<{K=D#!z&29z^OL}Plu<4qXzHFa?D-|Ae(^Kk8!+b8Jth71PBT6u0x18J zdrIl>Tk6FDZb>K6_v9;Qk@Y)$|G002ovPDHLkV1kO$T3!GE literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/Discgun/Data.json b/TRRandomizerCore/Resources/TR2/Models/Discgun/Data.json new file mode 100644 index 000000000..2f054d178 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/Discgun/Data.json @@ -0,0 +1 @@ +{"Animations":{"307":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":307,"NextFrame":0,"NumStateChanges":1,"StateChangeOffset":294,"NumAnimCommands":0,"AnimCommand":1282},"AnimationDispatches":{"326":{"Low":0,"High":1,"NextAnimation":308,"NextFrame":1}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":1,"NumAnimDispatches":1,"AnimDispatch":326}]},"308":{"Animation":{"FrameOffset":20,"FrameRate":1,"FrameSize":10,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":1,"FrameEnd":30,"NextAnimation":308,"NextFrame":1,"NumStateChanges":1,"StateChangeOffset":295,"NumAnimCommands":0,"AnimCommand":1282},"AnimationDispatches":{"327":{"Low":30,"High":31,"NextAnimation":307,"NextFrame":0}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":0,"NumAnimDispatches":1,"AnimDispatch":327}]}},"AnimationFrames":[65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152,65500,30,64963,65130,65028,65100,65533,65046,65028,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":49940,"Centre":{"X":5,"Y":-2,"Z":59},"CollRadius":112,"NumVertices":8,"Vertices":[{"X":33,"Y":-83,"Z":72},{"X":33,"Y":84,"Z":72},{"X":-33,"Y":84,"Z":72},{"X":-33,"Y":-83,"Z":72},{"X":33,"Y":-83,"Z":0},{"X":33,"Y":84,"Z":0},{"X":-33,"Y":84,"Z":0},{"X":-33,"Y":-83,"Z":0}],"NumNormals":8,"Normals":[{"X":9409,"Y":-9409,"Z":9414},{"X":9413,"Y":9412,"Z":9408},{"X":-9409,"Y":9410,"Z":9414},{"X":-9413,"Y":-9412,"Z":9408},{"X":9409,"Y":-9409,"Z":-9414},{"X":9413,"Y":9412,"Z":-9408},{"X":-9409,"Y":9410,"Z":-9414},{"X":-9413,"Y":-9412,"Z":-9408}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[0,3,2,1],"Texture":741},{"Vertices":[1,5,4,0],"Texture":742},{"Vertices":[2,6,5,1],"Texture":742},{"Vertices":[3,7,6,2],"Texture":742},{"Vertices":[0,4,7,3],"Texture":742},{"Vertices":[7,4,5,6],"Texture":742}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":0,"OffsetX":-75,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":62,"NumMeshes":1,"StartingMesh":252,"MeshTree":936,"FrameOffset":310808,"Animation":307},"Dependencies":[61],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":184},"YCoordinate":{"Whole":1,"Fraction":192}},{"XCoordinate":{"Whole":255,"Fraction":207},"YCoordinate":{"Whole":1,"Fraction":192}},{"XCoordinate":{"Whole":255,"Fraction":207},"YCoordinate":{"Whole":255,"Fraction":239}},{"XCoordinate":{"Whole":1,"Fraction":184},"YCoordinate":{"Whole":255,"Fraction":239}}]},"IsTriangle":false,"Index":741,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}],"1":[{"Texture":{"Attribute":0,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":1,"Fraction":112}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":1,"Fraction":112}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":255,"Fraction":175}},{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":255,"Fraction":175}}]},"IsTriangle":false,"Index":742,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["24, 0, 24, 48","0, 0, 24, 64"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/Discgun/Segments.png b/TRRandomizerCore/Resources/TR2/Models/Discgun/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..4ef5ee16f62ffe7198a79b530724d4989bbd8eff GIT binary patch literal 2514 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 FV1j!fUO@l= literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/FallingBlock/Data.json b/TRRandomizerCore/Resources/TR2/Models/FallingBlock/Data.json new file mode 100644 index 000000000..e7cc07979 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/FallingBlock/Data.json @@ -0,0 +1 @@ +{"Animations":{"299":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":16,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":299,"NextFrame":0,"NumStateChanges":1,"StateChangeOffset":291,"NumAnimCommands":0,"AnimCommand":1272},"AnimationDispatches":{"323":{"Low":0,"High":1,"NextAnimation":300,"NextFrame":1}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":1,"NumAnimDispatches":1,"AnimDispatch":323}]},"300":{"Animation":{"FrameOffset":32,"FrameRate":1,"FrameSize":22,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":1,"FrameEnd":36,"NextAnimation":301,"NextFrame":37,"NumStateChanges":0,"StateChangeOffset":292,"NumAnimCommands":1,"AnimCommand":1272},"AnimationDispatches":{},"Commands":{"1272":{"Command":5,"Params":[2,66]}},"Sound":{"SampleIndices":{"73":[76]},"SoundDetails":{"60":{"Sample":73,"Volume":32767,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"66":60}},"StateChanges":[]},"301":{"Animation":{"FrameOffset":1616,"FrameRate":1,"FrameSize":22,"StateID":2,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":37,"FrameEnd":99,"NextAnimation":301,"NextFrame":39,"NumStateChanges":1,"StateChangeOffset":292,"NumAnimCommands":1,"AnimCommand":1275},"AnimationDispatches":{"324":{"Low":37,"High":80,"NextAnimation":302,"NextFrame":100}},"Commands":{"1275":{"Command":5,"Params":[38,67]}},"Sound":{"SampleIndices":{"74":[77]},"SoundDetails":{"61":{"Sample":74,"Volume":32767,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"67":61}},"StateChanges":[{"StateID":3,"NumAnimDispatches":1,"AnimDispatch":324}]},"302":{"Animation":{"FrameOffset":4388,"FrameRate":1,"FrameSize":22,"StateID":3,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":100,"FrameEnd":127,"NextAnimation":302,"NextFrame":127,"NumStateChanges":0,"StateChangeOffset":293,"NumAnimCommands":2,"AnimCommand":1278},"AnimationDispatches":{},"Commands":{"1278":{"Command":4,"Params":[]},"1279":{"Command":5,"Params":[101,68]}},"Sound":{"SampleIndices":{"75":[78]},"SoundDetails":{"62":{"Sample":75,"Volume":32767,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"68":62}},"StateChanges":[]}},"AnimationFrames":[65029,508,65018,65082,65029,505,80,65066,65408,49152,49152,49152,49152,49152,49152,49152,65029,508,65003,65082,65026,505,80,65066,65408,49152,16394,111,64512,49162,17404,50173,17398,16,0,22,0,56,65029,508,64991,65082,65024,505,80,65066,65408,49152,16401,16395,49171,17402,50173,17393,16,0,22,0,56,0,65029,508,64980,65092,65026,505,80,65066,65408,49152,16394,224,1018,49181,17405,49154,17400,16,0,22,0,56,65029,508,64977,65095,65028,505,80,65066,65408,49152,16386,224,1015,49183,16386,49157,16386,16,0,22,0,56,65029,508,64991,65082,65025,505,80,65066,65408,49152,16395,143,65534,49164,16395,50168,16393,16,0,22,0,56,65029,508,64973,65102,65024,505,80,65066,65408,49152,16401,47,64517,50170,16401,50156,16398,16,0,22,0,56,65029,508,64978,65097,65028,505,80,65066,65408,49152,49152,31,64514,50171,16396,50158,16397,16,0,22,0,56,65029,508,64992,65082,65030,505,80,65066,65408,49152,17393,47,65533,49154,16389,50164,16392,16,0,22,0,56,65029,508,65001,65082,65028,505,80,65066,65408,49152,49152,111,65534,49163,17406,50168,17403,16,0,22,0,56,65029,508,64991,65082,65024,505,80,65066,65408,49152,16401,16395,49171,17402,50173,17393,16,0,22,0,56,0,65029,508,64980,65092,65025,505,80,65066,65408,49152,16395,224,1019,49180,17404,49155,17400,16,0,22,0,56,65029,508,64977,65095,65028,505,80,65066,65408,49152,16386,224,1015,49183,16386,49157,16386,16,0,22,0,56,65029,508,64991,65082,65025,505,80,65066,65408,49152,16394,143,65534,49164,16395,50168,16394,16,0,22,0,56,65029,508,64973,65102,65024,505,80,65066,65408,49152,16401,47,64517,50170,16401,50156,16398,16,0,22,0,56,65029,508,64973,65102,65026,505,80,65066,65408,49152,16391,31,64516,50169,16399,50156,16398,16,0,22,0,56,65029,508,64983,65092,65029,505,80,65066,65408,49152,17401,31,64512,50173,16394,50160,16396,16,0,22,0,56,65029,508,64992,65082,65030,505,80,65066,65408,49152,17393,47,65533,49154,16389,50164,16392,16,0,22,0,56,65029,508,64998,65082,65029,505,80,65066,65408,49152,17400,95,65533,49159,16385,50167,49152,16,0,22,0,56,65029,508,64998,65082,65026,505,80,65066,65408,49152,16391,143,65535,49165,17404,50169,17399,16,0,22,0,56,65029,508,64991,65082,65024,505,80,65066,65408,49152,16401,16395,49171,17402,50173,17393,16,0,22,0,56,0,65029,508,64977,65095,65028,505,80,65066,65408,49152,16386,224,1015,49183,16386,49157,16386,16,0,22,0,56,65029,508,64989,65082,65025,505,80,65066,65408,49152,16394,143,65534,49164,16395,50168,16394,16,0,22,0,56,65029,508,64973,65102,65024,505,80,65066,65408,49152,16401,47,64517,50170,16401,50156,16398,16,0,22,0,56,65029,508,64973,65102,65026,505,80,65066,65408,49152,16391,31,64516,50168,16399,50156,239,65535,16,0,22,0,65029,508,64982,65092,65029,505,80,65066,65408,49152,17401,31,64512,50173,16394,50160,207,65535,16,0,22,0,65029,508,64992,65082,65030,505,80,65066,65408,49152,17393,47,65533,49154,16389,50164,16392,16,0,22,0,56,65029,508,64960,65082,65028,505,80,65066,65408,49152,50175,111,65534,49162,17407,50168,16320,1,16,0,22,0,65029,508,64902,65082,65024,513,80,65066,65408,49152,16401,16395,49171,17402,50173,16144,2,16,0,22,0,56,65029,508,64954,65090,65022,506,80,65066,65408,49152,176,1,208,1019,49179,17406,49154,16256,1,16,0,22,65029,509,64920,65095,65026,505,80,65066,65408,49152,32,2,224,1015,49183,16386,49157,16386,16,0,22,0,65029,509,64934,65098,65024,505,80,65066,65408,49152,96,2,208,1017,49181,49152,49156,111,65534,16,0,22,65029,508,64969,65127,65023,505,80,65066,65408,49152,192,1,192,1020,49177,17403,49153,143,65534,16,0,22,65029,508,64991,65169,65024,505,80,65066,65408,49152,16401,16395,49171,17402,50173,239,65533,16,0,22,0,56,65029,508,64989,65219,65028,505,80,65066,65408,49152,351,65534,207,62467,16383,64522,16351,65535,15,65533,399,65532,65029,509,64988,65279,65028,507,80,65066,65408,49152,399,65533,223,59398,16367,65534,79,65535,15,65532,623,65530,65029,511,64973,65330,65029,509,80,65066,65408,49152,272,1021,47,64517,16336,1018,16401,50156,879,64506,16,0,65027,513,64909,65370,65026,505,80,65066,65408,49152,16,1020,16096,13314,16320,1020,16417,16368,974,1151,63481,16,65026,514,64848,65420,65025,506,80,65066,65408,49152,16160,1020,15728,28672,16320,1021,784,1025,50095,1439,62456,16,65024,517,64794,65460,65027,506,80,65066,65408,49152,15888,2043,15344,47100,16304,1023,1040,2050,50063,1743,61430,16,65021,519,64756,65495,65026,506,80,65066,65408,49152,15616,2043,14945,2038,16304,1025,1312,2051,50031,2063,59381,16,65018,520,64730,65519,65026,507,80,65066,65408,49152,15344,3066,14545,27626,16288,1027,1584,4100,0,1869,2367,57331,65015,522,64715,8,65025,508,80,65066,65408,49152,15056,4089,14177,60374,16288,1029,1856,5126,16,1835,2687,54256,65011,524,64678,21,65024,509,80,65066,65408,49152,14768,5112,13874,39861,16272,1031,2128,7176,16,1801,2991,50156,65008,526,64652,48,65023,509,80,65066,65408,49152,14464,6135,13715,30598,16256,1033,2400,10251,16,1766,3295,41958,65004,528,64641,101,65022,508,80,65066,65408,49152,14176,7158,13732,26450,16256,1035,2688,14351,16,1731,3599,25558,65000,532,64642,149,65020,508,80,65066,65408,49152,13872,10228,13941,10022,16240,2061,2976,19476,32,1695,3886,31645,64996,532,64656,189,65019,508,80,65066,65408,49152,13568,13297,14245,43785,16240,2063,3280,29726,32,1660,3913,62076,64992,526,64680,216,65018,507,80,65066,65408,49152,13264,17389,14597,62198,16224,2066,3568,50226,32,1624,3640,45613,64987,527,64688,235,65017,506,80,65066,65408,49152,12976,26596,14982,4842,16224,2068,3857,58490,32,1588,3320,26139,64984,527,64675,249,65015,507,80,65066,65408,49152,12688,48080,15350,5859,16208,2071,3861,55671,32,528,3016,17940,64987,526,64670,252,65014,509,80,65066,65408,49152,12434,17262,15733,65245,16208,2073,3575,9673,48,493,2680,12816,64989,530,64675,245,65012,510,80,65066,65408,49152,12518,37466,16181,56025,16192,3100,3239,32222,48,457,2360,9742,64992,527,64674,221,65011,512,80,65066,65408,49152,12791,23081,293,40660,16192,3103,2887,43496,48,421,2008,6668,64995,527,64675,190,65009,513,80,65066,65408,49152,13063,38427,789,19147,16176,3106,2519,49646,48,384,1672,4619,64999,526,64695,153,65007,514,80,65066,65408,49152,13351,45588,1252,55998,16176,3109,2151,54769,48,347,1336,3595,65004,527,64732,104,65006,515,80,65066,65408,49152,13623,49681,1652,18088,16160,3113,1751,57844,64,310,984,2571,65008,527,64779,50,65004,516,80,65066,65408,49152,13911,52751,1939,32391,16160,3116,1351,60917,64,272,648,1547,65014,527,64779,20,65002,516,80,65066,65408,49152,14199,55821,2034,38495,16144,3120,951,63990,64,234,295,65035,65017,528,64800,21,65001,516,80,65066,65408,49152,14503,57868,1921,44601,16144,3124,536,503,64,197,16327,64011,65011,528,64840,27,64999,515,80,65066,65408,49152,14791,59916,1648,59932,16128,3128,120,2551,80,159,15959,62987,65005,530,64892,71,64998,514,80,65066,65408,49152,15111,60939,1296,19977,16128,3132,16072,4599,80,122,15575,61964,65000,531,64952,110,64995,514,80,65066,65408,49152,15415,62987,895,54783,16128,3136,15656,6646,80,86,15175,59917,64996,534,65013,137,64994,510,80,65066,65408,49152,15735,64011,479,30201,16112,3141,15224,9717,80,49,14775,57870,64992,536,65050,164,64992,508,80,65066,65408,49152,16072,523,95,11766,16112,3145,14792,11764,95,64526,14343,53776,64990,539,65024,182,64990,508,80,65066,65408,49152,40,1547,16078,60916,16112,3151,14360,14834,95,65513,13895,49684,64988,540,64961,192,64989,511,80,65066,65408,49152,456,3595,15630,44534,16096,3160,13912,18927,95,65472,13415,40476,64988,542,64901,204,64986,514,80,65066,65408,49152,904,5644,15150,27132,16096,3170,13464,26089,95,65429,12919,18992,64987,544,64833,221,64984,517,80,65066,65408,49152,1368,8718,14670,7689,16096,3181,13016,40412,95,65385,12485,16049,64986,542,64766,221,64982,519,80,65066,65408,49152,1848,11792,14205,46622,16080,3193,12569,33188,95,65340,12752,65471,64992,536,64710,213,64981,520,80,65066,65408,49152,2344,16916,13789,8769,16080,3206,12558,37984,95,64271,13264,29665,64997,537,64670,196,64979,521,80,65066,65408,49152,2824,25114,13484,17016,16080,3219,13007,36898,95,64227,13792,17387,65002,538,64646,204,64978,521,80,65066,65408,49152,3272,40489,13371,8899,16080,3232,13471,51221,95,64185,14320,12272,65008,541,64637,212,64978,520,80,65066,65408,49152,3689,20052,13466,4873,16080,2219,13935,58383,95,64146,14848,8178,65013,537,64637,213,64978,519,80,65066,65408,49152,3900,38692,13705,24378,16080,2230,14399,62476,95,64110,15360,5107,65018,539,64648,218,64978,517,80,65066,65408,49152,3662,56244,13960,62298,16096,2239,14863,64523,95,65103,15872,2036,65014,536,64663,215,64979,515,80,65066,65408,49152,3391,22482,14216,45934,16096,3269,15296,1034,95,65077,16351,65524,65010,534,64679,204,64980,513,80,65066,65408,49152,3183,33757,14408,36732,16096,3274,15744,3081,95,65058,431,64499,65007,532,64691,198,64981,511,80,65066,65408,49152,3039,39906,14536,32644,16096,3275,16176,4105,95,65045,847,62451,65004,531,64696,183,64982,510,80,65066,65408,49152,2991,41956,14584,31622,16112,3273,224,5129,95,65041,1231,60402,65001,530,64694,167,64984,510,80,65066,65408,49152,3023,41956,14568,32645,16112,4293,640,7177,95,65043,815,61427,64997,529,64688,144,64987,512,80,65066,65408,49152,3103,40931,14488,36739,16128,4288,1104,8203,95,65050,399,61427,64994,527,64678,120,64989,514,80,65066,65408,49152,3215,38881,14376,42878,16144,4281,1584,11277,95,65061,16351,62452,64990,526,64667,152,64992,517,80,65066,65408,49152,3359,34781,14232,52086,16160,4274,2064,14352,95,64052,15903,62452,64986,527,64655,220,64995,520,80,65066,65408,49152,3535,25557,14056,65387,16160,4266,2560,20501,111,63047,15455,63476,64982,528,64645,276,64998,525,80,65066,65408,49152,3743,3007,13849,18267,16176,5280,3072,31777,111,63068,15007,64501,64977,528,64638,309,65000,527,80,65066,65408,49152,3949,34655,13657,43844,16192,5270,3552,64577,111,62069,14543,65525,64980,527,64636,316,65004,532,80,65066,65408,49152,3881,30299,13482,15138,16208,5259,3892,15632,127,62096,14048,1013,64976,522,64639,311,65007,534,80,65066,65408,49152,3608,38436,13370,64244,16224,4224,3527,2500,143,61100,13568,2036,64980,518,64647,277,65010,535,80,65066,65408,49152,3304,21012,13371,55998,16240,4211,3063,32225,143,61130,13072,5106,64984,517,64662,223,65013,535,80,65066,65408,49152,2984,13837,13484,45707,16256,4198,2599,43499,143,62185,12576,18407,64989,516,64686,174,65016,534,80,65066,65408,49152,2632,8713,13693,23139,16272,4184,2151,48625,159,62217,12503,37396,64993,514,64719,152,65006,578,80,65066,65408,49152,2296,5639,13965,54854,16288,4170,1719,52725,143,63273,13015,56834,64999,512,64758,115,64978,612,80,65066,65408,49152,1944,3589,14270,12849,16304,3131,1335,55800,143,64329,13543,60927,65005,512,64803,52,64955,621,80,65066,65408,49152,1576,2564,14606,29219,16320,3115,967,57850,127,64361,14071,61950,65011,510,64851,65509,64929,609,80,65066,65408,49152,1224,515,14942,42520,16336,2075,647,59899,111,65415,14615,62974,65018,510,64901,65417,64922,577,80,65066,65408,49152,871,65026,15262,52752,16368,2058,359,61948,95,65444,15159,63998,65024,510,64952,65316,64911,538,80,65066,65408,49152,519,64002,15582,60938,0,2041,135,63998,64,959,15719,65022,65028,511,64959,65223,64898,506,80,65066,65408,49152,183,64001,15871,1541,16,2024,16343,65022,32,985,16280,509,65024,511,64909,65157,64890,527,80,65066,65408,49152,16231,62976,16143,7681,32,982,16216,1535,16,1007,472,509,65020,512,65277,38,64877,544,80,65482,65408,49152,15927,62976,16383,11774,48,964,16168,3583,15,64514,1048,1533,65003,517,65038,36,64879,507,81,65439,65408,49152,15607,62974,143,13817,128,903,1272,9731,16351,64527,1223,61944,64977,549,64643,65486,64884,512,81,65396,65407,49152,15223,63995,175,14834,255,64290,3694,60337,16255,63509,1783,50668,64999,576,64469,65460,64888,528,82,65353,65407,49152,14808,2550,111,13802,352,670,863,62449,16159,63508,2231,40417,65001,577,64404,65429,64881,552,82,65310,65407,49152,14312,7663,31,11748,511,64040,15328,4083,16047,63504,2487,35293,64947,575,64369,65390,64880,580,83,65267,65407,49152,13752,16870,16383,11746,479,61901,13616,14318,15935,63498,2743,30169,65005,567,64326,65528,64950,601,82,65320,65407,49152,12920,51655,16383,11749,415,60790,12550,64065,15871,63493,3015,25044,65018,558,64337,22,64960,611,82,65372,65407,49152,12879,7221,16383,11755,351,62756,14039,59912,15839,64514,3255,18894,65025,547,64467,4,64886,596,81,65424,65408,49152,14111,50188,16383,11762,303,63702,15367,64003,15887,64514,3463,12745,65022,537,64707,6,64853,574,80,65477,65408,49152,15455,58370,16383,11770,255,63628,16295,62976,15999,64514,3607,11721,64999,527,64960,22,64926,571,80,65477,65408,49152,415,63487,16383,11778,175,62532,391,62977,16127,64514,3655,20946,64989,519,65053,13,64949,579,80,65477,65408,49152,1760,2055,16383,11784,95,63492,455,62978,16287,64514,3591,38372,65019,536,64908,24,64997,594,80,65477,65408,49152,3088,26653,16383,11788,48,975,16295,61955,31,64514,1048,1533,65018,554,64817,10,64997,591,80,65477,65408,49152,3781,63872,16383,11783,48,938,15751,61954,31,64514,552,1532,65019,542,64891,17,64918,598,80,65477,65408,49152,2839,37348,16383,11771,80,918,15927,61953,31,64514,408,1531,65019,528,65039,5,64897,597,80,65477,65408,49152,1927,53747,16383,11771,95,65427,16295,61952,31,64514,16312,2555,65019,517,65197,5,64907,613,80,65477,65408,49152,1031,60920,16383,11771,79,65447,16295,61952,31,64514,15784,3580,65019,514,65316,5,64907,628,80,65477,65408,49152,151,63997,16383,11771,16,972,16295,61952,31,64514,15512,4605,65019,513,65418,33,64912,633,80,65477,65408,49152,15799,64000,16383,11771,16368,1009,16295,61952,31,64514,15864,3583,65019,512,65421,35,64922,615,80,65477,65408,49152,15383,63999,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65337,18,64910,615,80,65477,65408,49152,15063,63997,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65294,18,64924,615,80,65477,65408,49152,14583,65019,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65263,18,64926,615,80,65477,65408,49152,14072,1530,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65253,18,64933,615,80,65477,65408,49152,13880,1529,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65287,18,64919,615,80,65477,65408,49152,14503,65019,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65354,18,64905,615,80,65477,65408,49152,15335,63997,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65406,18,64919,615,80,65477,65408,49152,15639,63998,16383,11771,16368,1009,16295,61952,31,64514,88,3584,65019,512,65424,24,64936,615,80,65477,65408,49152,15799,63999,16383,11771,16368,1009,16295,61952,31,64514,88,3584],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":46836,"Centre":{"X":0,"Y":0,"Z":0},"CollRadius":513,"NumVertices":3,"Vertices":[{"X":16,"Y":-16,"Z":0},{"X":16,"Y":16,"Z":0},{"X":-16,"Y":16,"Z":0}],"NumNormals":3,"Normals":[{"X":0,"Y":0,"Z":-16300},{"X":0,"Y":0,"Z":-16300},{"X":0,"Y":0,"Z":-16300}],"Lights":null,"NumTexturedRectangles":0,"TexturedRectangles":[],"NumTexturedTriangles":1,"TexturedTriangles":[{"Vertices":[0,1,2],"Texture":732}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":46904,"Centre":{"X":-5649,"Y":-36,"Z":0},"CollRadius":52890,"NumVertices":6,"Vertices":[{"X":-5604,"Y":-50,"Z":-123},{"X":-5820,"Y":-50,"Z":-123},{"X":-5604,"Y":-50,"Z":187},{"X":-5604,"Y":-14,"Z":-123},{"X":-5820,"Y":-14,"Z":-123},{"X":-5604,"Y":-14,"Z":187}],"NumNormals":6,"Normals":[{"X":9411,"Y":-9411,"Z":-9411},{"X":-9810,"Y":-11974,"Z":-5107},{"X":2525,"Y":-13969,"Z":8011},{"X":9411,"Y":9411,"Z":-9411},{"X":-9810,"Y":11974,"Z":-5107},{"X":2525,"Y":13969,"Z":8011}],"Lights":null,"NumTexturedRectangles":3,"TexturedRectangles":[{"Vertices":[0,3,4,1],"Texture":733},{"Vertices":[1,4,5,2],"Texture":733},{"Vertices":[2,5,3,0],"Texture":733}],"NumTexturedTriangles":2,"TexturedTriangles":[{"Vertices":[1,2,0],"Texture":732},{"Vertices":[3,5,4],"Texture":732}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":47044,"Centre":{"X":-9,"Y":-50,"Z":-46},"CollRadius":59240,"NumVertices":14,"Vertices":[{"X":402,"Y":-50,"Z":-77},{"X":186,"Y":-50,"Z":-387},{"X":-155,"Y":-50,"Z":-387},{"X":-402,"Y":-50,"Z":-77},{"X":-310,"Y":-50,"Z":232},{"X":62,"Y":-50,"Z":387},{"X":402,"Y":-50,"Z":108},{"X":402,"Y":-14,"Z":-77},{"X":186,"Y":-14,"Z":-387},{"X":-155,"Y":-14,"Z":-387},{"X":-402,"Y":-14,"Z":-77},{"X":-310,"Y":-14,"Z":232},{"X":62,"Y":-14,"Z":387},{"X":402,"Y":-14,"Z":108}],"NumNormals":14,"Normals":[{"X":10729,"Y":-11795,"Z":-3382},{"X":6557,"Y":-8004,"Z":-12594},{"X":-4727,"Y":-12108,"Z":-9836},{"X":-10609,"Y":-12203,"Z":-2058},{"X":-10593,"Y":-7891,"Z":9551},{"X":2041,"Y":-8210,"Z":13933},{"X":9876,"Y":-12094,"Z":4680},{"X":10729,"Y":11795,"Z":-3382},{"X":6557,"Y":8004,"Z":-12595},{"X":-4727,"Y":12108,"Z":-9836},{"X":-10609,"Y":12203,"Z":-2058},{"X":-10593,"Y":7891,"Z":9551},{"X":2041,"Y":8210,"Z":13933},{"X":9876,"Y":12094,"Z":4680}],"Lights":null,"NumTexturedRectangles":11,"TexturedRectangles":[{"Vertices":[3,4,5,6],"Texture":733},{"Vertices":[2,3,6,0],"Texture":733},{"Vertices":[0,7,8,1],"Texture":733},{"Vertices":[1,8,9,2],"Texture":733},{"Vertices":[2,9,10,3],"Texture":733},{"Vertices":[3,10,11,4],"Texture":733},{"Vertices":[4,11,12,5],"Texture":733},{"Vertices":[5,12,13,6],"Texture":733},{"Vertices":[6,13,7,0],"Texture":733},{"Vertices":[11,10,13,12],"Texture":733},{"Vertices":[9,7,13,10],"Texture":733}],"NumTexturedTriangles":2,"TexturedTriangles":[{"Vertices":[2,0,1],"Texture":732},{"Vertices":[9,8,7],"Texture":732}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":47360,"Centre":{"X":-26,"Y":-50,"Z":4527},"CollRadius":44470,"NumVertices":8,"Vertices":[{"X":-216,"Y":-50,"Z":4486},{"X":-216,"Y":-50,"Z":4671},{"X":-31,"Y":-50,"Z":4794},{"X":216,"Y":-50,"Z":4486},{"X":-216,"Y":-14,"Z":4486},{"X":-216,"Y":-14,"Z":4671},{"X":-31,"Y":-14,"Z":4794},{"X":216,"Y":-14,"Z":4486}],"NumNormals":8,"Normals":[{"X":-9411,"Y":-9411,"Z":-9411},{"X":-12501,"Y":-8041,"Z":6690},{"X":2070,"Y":-9150,"Z":13330},{"X":9620,"Y":-12319,"Z":-4624},{"X":-9411,"Y":9411,"Z":-9411},{"X":-12501,"Y":8041,"Z":6690},{"X":2070,"Y":9150,"Z":13330},{"X":9620,"Y":12320,"Z":-4624}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[1,2,3,0],"Texture":733},{"Vertices":[0,4,5,1],"Texture":733},{"Vertices":[1,5,6,2],"Texture":733},{"Vertices":[2,6,7,3],"Texture":733},{"Vertices":[3,7,4,0],"Texture":733},{"Vertices":[6,5,4,7],"Texture":733}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":47540,"Centre":{"X":4933,"Y":-32,"Z":0},"CollRadius":2531,"NumVertices":8,"Vertices":[{"X":4933,"Y":-50,"Z":-402},{"X":4933,"Y":-50,"Z":402},{"X":5211,"Y":-50,"Z":31},{"X":5118,"Y":-50,"Z":-279},{"X":4933,"Y":-14,"Z":-402},{"X":4933,"Y":-14,"Z":402},{"X":5211,"Y":-14,"Z":31},{"X":5118,"Y":-14,"Z":-279}],"NumNormals":8,"Normals":[{"X":-5279,"Y":-11855,"Z":-9864},{"X":-2755,"Y":-13776,"Z":8266},{"X":14002,"Y":-7965,"Z":2490},{"X":11570,"Y":-7649,"Z":-8563},{"X":-5279,"Y":11855,"Z":-9864},{"X":-2755,"Y":13776,"Z":8266},{"X":14002,"Y":7965,"Z":2490},{"X":11570,"Y":7649,"Z":-8563}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[1,2,3,0],"Texture":733},{"Vertices":[0,4,5,1],"Texture":733},{"Vertices":[1,5,6,2],"Texture":733},{"Vertices":[2,6,7,3],"Texture":733},{"Vertices":[3,7,4,0],"Texture":733},{"Vertices":[4,7,6,5],"Texture":733}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":47720,"Centre":{"X":-16,"Y":-50,"Z":-4391},"CollRadius":12419,"NumVertices":8,"Vertices":[{"X":370,"Y":-50,"Z":-4391},{"X":246,"Y":-50,"Z":-4607},{"X":-124,"Y":-50,"Z":-4761},{"X":-402,"Y":-50,"Z":-4391},{"X":370,"Y":-14,"Z":-4391},{"X":246,"Y":-14,"Z":-4607},{"X":-124,"Y":-14,"Z":-4761},{"X":-402,"Y":-14,"Z":-4391}],"NumNormals":8,"Normals":[{"X":9988,"Y":-11504,"Z":5796},{"X":9538,"Y":-7613,"Z":-10805},{"X":-3623,"Y":-8722,"Z":-13285},{"X":-9719,"Y":-12149,"Z":4860},{"X":9988,"Y":11504,"Z":5796},{"X":9538,"Y":7613,"Z":-10805},{"X":-3623,"Y":8722,"Z":-13285},{"X":-9719,"Y":12149,"Z":4860}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[1,2,3,0],"Texture":733},{"Vertices":[0,4,5,1],"Texture":733},{"Vertices":[1,5,6,2],"Texture":733},{"Vertices":[2,6,7,3],"Texture":733},{"Vertices":[3,7,4,0],"Texture":733},{"Vertices":[6,5,4,7],"Texture":733}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":47900,"Centre":{"X":-5672,"Y":-35,"Z":4},"CollRadius":55303,"NumVertices":8,"Vertices":[{"X":-5625,"Y":-50,"Z":245},{"X":-5625,"Y":-50,"Z":-247},{"X":-5964,"Y":-50,"Z":30},{"X":-5841,"Y":-50,"Z":245},{"X":-5625,"Y":-14,"Z":245},{"X":-5625,"Y":-14,"Z":-247},{"X":-5964,"Y":-14,"Z":30},{"X":-5841,"Y":-14,"Z":245}],"NumNormals":8,"Normals":[{"X":9411,"Y":-9411,"Z":9411},{"X":4541,"Y":-12380,"Z":-9582},{"X":-13408,"Y":-8930,"Z":-2481},{"X":-7083,"Y":-8158,"Z":12205},{"X":9411,"Y":9411,"Z":9411},{"X":4541,"Y":12380,"Z":-9582},{"X":-13408,"Y":8930,"Z":-2481},{"X":-7083,"Y":8158,"Z":12205}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[3,0,1,2],"Texture":733},{"Vertices":[0,4,5,1],"Texture":733},{"Vertices":[1,5,6,2],"Texture":733},{"Vertices":[2,6,7,3],"Texture":733},{"Vertices":[3,7,4,0],"Texture":733},{"Vertices":[4,7,6,5],"Texture":733}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":6032,"OffsetY":2,"OffsetZ":-256},{"Flags":3,"OffsetX":16,"OffsetY":2,"OffsetZ":16},{"Flags":3,"OffsetX":-368,"OffsetY":2,"OffsetZ":-4864},{"Flags":3,"OffsetX":-5520,"OffsetY":2,"OffsetZ":224},{"Flags":3,"OffsetX":-176,"OffsetY":2,"OffsetZ":5024},{"Flags":1,"OffsetX":6051,"OffsetY":2,"OffsetZ":385},{"Flags":0,"OffsetX":-75,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":55,"NumMeshes":7,"StartingMesh":242,"MeshTree":912,"FrameOffset":303740,"Animation":299},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":3,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":1,"Fraction":96}},{"XCoordinate":{"Whole":255,"Fraction":63},"YCoordinate":{"Whole":1,"Fraction":96}},{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":732,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"},{"Texture":{"Attribute":0,"AtlasAndFlag":3,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":1,"Fraction":96}},{"XCoordinate":{"Whole":255,"Fraction":63},"YCoordinate":{"Whole":1,"Fraction":96}},{"XCoordinate":{"Whole":255,"Fraction":63},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":1,"Fraction":0},"YCoordinate":{"Whole":255,"Fraction":159}}]},"IsTriangle":false,"Index":733,"Classification":"48d536b2de1195d0c9f6ea8ab884085e"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 64"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/FallingBlock/Segments.png b/TRRandomizerCore/Resources/TR2/Models/FallingBlock/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..56d2c4a8123606191c47434afa2d71a10d83c94e GIT binary patch literal 2653 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 LNkvXXu0mjfB`byL literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Data.json b/TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Data.json new file mode 100644 index 000000000..043a9875e --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Data.json @@ -0,0 +1 @@ +{"Animations":{"386":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":18,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":386,"NextFrame":0,"NumStateChanges":1,"StateChangeOffset":326,"NumAnimCommands":0,"AnimCommand":1482},"AnimationDispatches":{"358":{"Low":0,"High":1,"NextAnimation":387,"NextFrame":1}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":1,"NumAnimDispatches":1,"AnimDispatch":358}]},"387":{"Animation":{"FrameOffset":36,"FrameRate":1,"FrameSize":18,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":1,"FrameEnd":40,"NextAnimation":387,"NextFrame":1,"NumStateChanges":1,"StateChangeOffset":327,"NumAnimCommands":1,"AnimCommand":1482},"AnimationDispatches":{"359":{"Low":1,"High":41,"NextAnimation":388,"NextFrame":41}},"Commands":{"1482":{"Command":5,"Params":[1,67]}},"Sound":{"SampleIndices":{"73":[77]},"SoundDetails":{"60":{"Sample":73,"Volume":32767,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"67":60}},"StateChanges":[{"StateID":2,"NumAnimDispatches":1,"AnimDispatch":359}]},"388":{"Animation":{"FrameOffset":1476,"FrameRate":1,"FrameSize":18,"StateID":2,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":41,"FrameEnd":67,"NextAnimation":388,"NextFrame":67,"NumStateChanges":0,"StateChangeOffset":328,"NumAnimCommands":6,"AnimCommand":1485},"AnimationDispatches":{},"Commands":{"1485":{"Command":4,"Params":[]},"1486":{"Command":6,"Params":[42,1]},"1489":{"Command":6,"Params":[46,1]},"1492":{"Command":6,"Params":[58,1]},"1495":{"Command":6,"Params":[65,1]},"1498":{"Command":5,"Params":[41,68]}},"Sound":{"SampleIndices":{"74":[78]},"SoundDetails":{"61":{"Sample":74,"Volume":32767,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"68":61}},"StateChanges":[]}},"AnimationFrames":[64866,1042,64528,64999,64777,290,65529,64727,65415,49152,16191,64514,16368,1011,207,65535,15,65526,64866,1042,64528,64999,64777,290,65529,64727,65415,49152,16191,64514,16368,1011,207,65535,15,65526,64850,1040,64514,65041,64776,290,65529,64727,65415,49152,15999,64516,16368,999,399,65534,15,65516,64827,1026,64510,65084,64767,290,65529,64727,65415,49152,15807,63494,16352,987,607,65533,15,64482,64818,1008,64500,65120,64751,291,65529,64727,65415,49152,15599,63497,16352,974,799,65532,15,64472,64800,993,64455,65157,64746,293,65529,64727,65415,49152,15407,62475,16336,962,1007,64507,15,64462,64796,965,64400,65197,64730,293,65529,64727,65415,49152,15215,61454,16336,950,1199,64506,15,63428,64785,934,64348,65236,64712,293,65529,64727,65415,49152,15007,59409,16336,1961,1407,63481,15,63418,64787,898,64290,65274,64706,296,65529,64727,65415,49152,14815,57364,16320,1949,1599,63479,15,63408,64780,851,64243,65309,64693,296,65529,64727,65415,49152,14623,55319,16320,1937,1807,62454,15,62375,64788,808,64199,65354,64689,298,65529,64727,65415,49152,14431,53275,16320,2949,1999,61428,15,62365,64797,761,64158,65385,64681,300,65529,64727,65415,49152,14239,49184,16320,2936,2207,59379,15,62355,64800,704,64120,65415,64681,302,65529,64727,65415,49152,14047,45093,16304,2924,2399,58352,16383,61321,64814,651,64087,65442,64670,303,65529,64727,65415,49152,13855,39980,16304,3936,2607,55278,16383,61311,64832,588,64065,65477,64675,304,65529,64727,65415,49152,13663,32820,16304,3923,2799,52202,16383,61301,64841,522,64038,65509,64684,307,65529,64727,65415,49152,13487,23614,16304,4935,2991,48102,16383,60267,64863,460,64018,65529,64680,309,65529,64727,65415,49152,13295,10316,16304,4923,3199,41951,16383,60257,64887,391,63986,20,64680,312,65529,64727,65415,49152,13134,57439,16304,4910,3391,32725,16383,60248,64887,361,63966,46,64695,314,65529,64727,65415,49152,12974,29819,16304,5922,3583,16325,16367,59214,64882,362,63951,67,64700,316,65529,64727,65415,49152,12845,53413,16304,5910,3758,47011,16367,59204,64879,359,63940,86,64706,319,65529,64727,65415,49152,12780,58593,16304,6921,3885,21321,16367,59194,64875,357,63934,102,64691,322,65529,64727,65415,49152,12779,56612,16304,6909,3882,54954,16367,59184,64872,368,63940,125,64658,323,65529,64727,65415,49152,12858,64862,16304,6897,3737,37464,16351,58150,64870,369,63943,136,64610,326,65529,64727,65415,49152,12986,24966,16304,7909,3561,5689,16351,58140,64868,373,63959,143,64568,328,65529,64727,65415,49152,13145,63904,16304,7896,3368,55849,16351,58130,64864,374,63970,158,64526,330,65529,64727,65415,49152,13321,46515,16304,8908,3160,46624,16335,58121,64862,376,63994,161,64486,333,65529,64727,65415,49152,13497,33216,16304,8896,2968,40474,16335,58111,64859,379,64023,179,64460,335,65529,64727,65415,49152,13689,25034,16320,8883,2776,36373,16335,58101,64856,382,64055,205,64435,337,65529,64727,65415,49152,13865,17874,16320,9895,2568,33298,16319,57067,64854,414,64092,217,64400,339,65529,64727,65415,49152,14057,12760,16320,9883,2376,31247,16319,57057,64850,445,64130,237,64379,340,65529,64727,65415,49152,14249,8669,16336,9870,2184,29197,16303,57047,64847,473,64149,244,64360,342,65529,64727,65415,49152,14441,4578,16336,10882,1976,28171,16303,57037,64844,499,64177,258,64344,344,65529,64727,65415,49152,14649,2534,16336,10870,1784,27146,16303,57027,64813,521,64201,259,64327,345,65529,64727,65415,49152,14841,489,16352,10858,1576,26120,16287,57018,64780,540,64232,267,64319,347,65529,64727,65415,49152,15032,63980,16352,10845,1384,25095,16287,57008,64758,563,64269,263,64320,347,65529,64727,65415,49152,15224,62959,16352,10833,1176,25094,16287,56998,64733,574,64303,255,64311,349,65529,64727,65415,49152,15432,60914,16368,11845,984,24069,16271,56988,64711,590,64342,256,64322,350,65529,64727,65415,49152,15624,60916,16368,11832,776,24068,16271,58002,64680,593,64385,243,64326,353,65529,64727,65415,49152,15816,59895,0,11820,584,24067,16271,57992,64661,601,64429,238,64335,354,65529,64727,65415,49152,16008,58873,0,11808,376,23042,16255,57982,64647,605,64437,220,64352,355,65529,64727,65415,49152,16216,58875,0,11795,184,23041,16255,57972,64647,605,64437,220,64352,355,65529,64727,65415,49152,16216,58875,0,11795,184,23041,16255,57972,64609,676,64578,65399,64367,373,65529,64727,65415,49152,16216,58879,176,12828,104,23034,16383,59970,64581,677,64316,18,64383,398,65529,64727,65415,49152,16216,58884,272,13841,8,23027,127,59919,64654,593,63872,116,64395,396,65529,64727,65415,49152,16200,58888,256,10719,16024,23024,239,56799,64796,566,63680,224,64390,381,65529,64727,65415,49152,16168,58889,192,9635,15224,24050,287,55756,64846,457,63698,241,64397,360,65529,64727,65415,49152,16104,58888,112,9571,14184,23032,271,54722,64849,426,63743,180,64391,328,65529,64727,65415,49152,16040,58885,32,10532,13128,11783,207,52643,64845,422,63842,111,64389,299,65529,64727,65415,49152,15944,58881,16368,12523,12435,2899,111,50557,64823,417,63987,65507,64360,269,65529,64727,65415,49152,15864,58877,16304,12483,13089,3026,31,50519,64796,413,63800,65324,64306,281,65529,64727,65415,49152,15784,59898,16240,10403,13712,59352,16319,51505,64773,520,63627,65308,64269,297,65529,64727,65415,49152,15704,59896,16192,10359,14256,53210,16239,54539,64654,556,63581,65169,64208,308,65529,64727,65415,49152,15656,59896,16192,13363,14768,47070,16303,53510,64564,523,63679,65191,64196,306,65529,64727,65415,49152,15576,58872,16256,17379,15248,39909,16383,52482,64624,398,63853,65302,64248,295,65529,64727,65415,49152,15512,58874,16304,19356,15664,32747,47,51454,64779,401,63770,65434,64314,305,65529,64727,65415,49152,15480,57851,16336,20310,16080,26609,95,50423,64756,402,63723,10,64310,335,65529,64727,65415,49152,15464,56829,16352,21272,144,21495,111,48364,64640,404,63751,60,64310,338,65529,64727,65415,49152,15512,56832,16352,19206,672,19451,111,47325,64536,409,63836,87,64308,317,65529,64727,65415,49152,15688,56835,16304,12075,1280,21503,79,46285,64451,732,63963,81,64331,307,65529,64727,65415,49152,15992,56839,16304,1899,1952,25605,31,46266,64378,1222,64111,58,64345,328,65529,64727,65415,49152,16312,57867,16383,58294,2656,36880,16367,46247,64331,1451,64291,58,64345,373,65529,64727,65415,49152,16312,57867,111,53242,3361,6193,16303,47251,64316,1449,64472,58,64345,412,65529,64727,65415,49152,16312,57867,223,50215,3796,22785,16255,48256,64311,1335,64639,58,64345,365,65529,64727,65415,49152,16312,57867,207,55300,3796,22785,16207,49261,64193,1112,64724,58,64345,304,65529,64727,65415,49152,16312,57867,191,63438,3796,22785,16207,47185,64096,1165,64724,58,64345,322,65529,64727,65415,49152,16312,57867,239,61406,3796,22785,16191,45110,64022,1257,64724,58,64345,362,65529,64727,65415,49152,16312,57867,287,59391,3796,22785,16191,43035,63976,1257,64724,58,64345,362,65529,64727,65415,49152,16312,57867,287,59391,3796,22785,16175,43007],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":83832,"Centre":{"X":0,"Y":0,"Z":0},"CollRadius":5,"NumVertices":3,"Vertices":[{"X":-3,"Y":-3,"Z":0},{"X":3,"Y":3,"Z":0},{"X":-3,"Y":3,"Z":0}],"NumNormals":3,"Normals":[{"X":0,"Y":0,"Z":16300},{"X":0,"Y":0,"Z":16300},{"X":0,"Y":0,"Z":16300}],"Lights":null,"NumTexturedRectangles":0,"TexturedRectangles":[],"NumTexturedTriangles":1,"TexturedTriangles":[{"Vertices":[1,0,2],"Texture":1053}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":83900,"Centre":{"X":-8669,"Y":-6,"Z":1776},"CollRadius":513,"NumVertices":8,"Vertices":[{"X":-8634,"Y":-187,"Z":2019},{"X":-8998,"Y":-144,"Z":2026},{"X":-9033,"Y":-144,"Z":1829},{"X":-8660,"Y":-187,"Z":1593},{"X":-8418,"Y":187,"Z":2113},{"X":-9038,"Y":187,"Z":2075},{"X":-9087,"Y":187,"Z":1797},{"X":-8516,"Y":187,"Z":1372}],"NumNormals":8,"Normals":[{"X":4157,"Y":-10907,"Z":11377},{"X":-8640,"Y":-10221,"Z":9304},{"X":-11780,"Y":-8400,"Z":-7508},{"X":6969,"Y":-13457,"Z":-6003},{"X":14733,"Y":-1001,"Z":6902},{"X":-6945,"Y":3365,"Z":14357},{"X":-14045,"Y":6135,"Z":-5548},{"X":-2133,"Y":1338,"Z":-16104}],"Lights":null,"NumTexturedRectangles":3,"TexturedRectangles":[{"Vertices":[0,3,2,1],"Texture":1054},{"Vertices":[1,2,6,5],"Texture":1054},{"Vertices":[6,7,4,5],"Texture":1054}],"NumTexturedTriangles":6,"TexturedTriangles":[{"Vertices":[5,4,0],"Texture":1053},{"Vertices":[1,5,0],"Texture":1053},{"Vertices":[6,2,7],"Texture":1053},{"Vertices":[2,3,7],"Texture":1053},{"Vertices":[4,7,3],"Texture":1053},{"Vertices":[0,4,3],"Texture":1053}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":84096,"Centre":{"X":43,"Y":15,"Z":-5144},"CollRadius":764,"NumVertices":8,"Vertices":[{"X":720,"Y":-101,"Z":-5000},{"X":-685,"Y":-37,"Z":-5083},{"X":-685,"Y":-37,"Z":-5287},{"X":720,"Y":-101,"Z":-5287},{"X":790,"Y":65,"Z":-5000},{"X":-705,"Y":65,"Z":-5083},{"X":-705,"Y":65,"Z":-5287},{"X":790,"Y":65,"Z":-5287}],"NumNormals":8,"Normals":[{"X":4885,"Y":-8818,"Z":12809},{"X":-9338,"Y":-10251,"Z":8567},{"X":-9016,"Y":-10372,"Z":-8765},{"X":7435,"Y":-11764,"Z":-8486},{"X":9629,"Y":7066,"Z":11093},{"X":-7382,"Y":5567,"Z":13424},{"X":-9876,"Y":8197,"Z":-10048},{"X":10074,"Y":6694,"Z":-10927}],"Lights":null,"NumTexturedRectangles":5,"TexturedRectangles":[{"Vertices":[3,2,1,0],"Texture":1054},{"Vertices":[1,2,6,5],"Texture":1054},{"Vertices":[2,3,7,6],"Texture":1054},{"Vertices":[3,0,4,7],"Texture":1054},{"Vertices":[4,5,6,7],"Texture":1054}],"NumTexturedTriangles":2,"TexturedTriangles":[{"Vertices":[4,0,5],"Texture":1053},{"Vertices":[0,1,5],"Texture":1053}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":84280,"Centre":{"X":5340,"Y":-4,"Z":-12},"CollRadius":402,"NumVertices":7,"Vertices":[{"X":5617,"Y":-108,"Z":72},{"X":5315,"Y":-204,"Z":-214},{"X":5617,"Y":-108,"Z":-214},{"X":5617,"Y":204,"Z":72},{"X":5220,"Y":204,"Z":247},{"X":5252,"Y":204,"Z":-214},{"X":5617,"Y":204,"Z":-214}],"NumNormals":7,"Normals":[{"X":2690,"Y":-12080,"Z":10608},{"X":-5183,"Y":-15001,"Z":-3714},{"X":11174,"Y":-8190,"Z":-8588},{"X":11721,"Y":8356,"Z":7648},{"X":-3974,"Y":3931,"Z":15312},{"X":-15802,"Y":1462,"Z":-3722},{"X":9411,"Y":9411,"Z":-9411}],"Lights":null,"NumTexturedRectangles":3,"TexturedRectangles":[{"Vertices":[1,2,6,5],"Texture":1054},{"Vertices":[2,0,3,6],"Texture":1054},{"Vertices":[3,4,5,6],"Texture":1054}],"NumTexturedTriangles":4,"TexturedTriangles":[{"Vertices":[2,1,0],"Texture":1053},{"Vertices":[4,3,0],"Texture":1053},{"Vertices":[5,4,0],"Texture":1053},{"Vertices":[1,5,0],"Texture":1053}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":84448,"Centre":{"X":-289,"Y":0,"Z":6463},"CollRadius":546,"NumVertices":6,"Vertices":[{"X":-278,"Y":-161,"Z":6662},{"X":-771,"Y":-161,"Z":6662},{"X":-278,"Y":161,"Z":6662},{"X":-771,"Y":161,"Z":6662},{"X":-468,"Y":161,"Z":6264},{"X":192,"Y":161,"Z":6264}],"NumNormals":6,"Normals":[{"X":6924,"Y":-8340,"Z":12173},{"X":-11406,"Y":-11147,"Z":-3367},{"X":4945,"Y":7661,"Z":13511},{"X":-9697,"Y":12189,"Z":4804},{"X":-8728,"Y":2442,"Z":-13548},{"X":15118,"Y":5212,"Z":3158}],"Lights":null,"NumTexturedRectangles":3,"TexturedRectangles":[{"Vertices":[0,1,3,2],"Texture":1054},{"Vertices":[1,0,5,4],"Texture":1054},{"Vertices":[2,3,4,5],"Texture":1054}],"NumTexturedTriangles":2,"TexturedTriangles":[{"Vertices":[4,3,1],"Texture":1053},{"Vertices":[2,5,0],"Texture":1053}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":8890,"OffsetY":30,"OffsetZ":-1966},{"Flags":3,"OffsetX":257,"OffsetY":152,"OffsetZ":5411},{"Flags":3,"OffsetX":-5835,"OffsetY":13,"OffsetZ":-27},{"Flags":1,"OffsetX":127,"OffsetY":56,"OffsetZ":-6901},{"Flags":2,"OffsetX":-1,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":79,"NumMeshes":5,"StartingMesh":300,"MeshTree":1132,"FrameOffset":416568,"Animation":386},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":1,"Fraction":208}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":208}},{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":255,"Fraction":247}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":1053,"Classification":"bed545a99ee57e17134e6f2ab35b5413"},{"Texture":{"Attribute":0,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":1,"Fraction":208}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":208}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":247}},{"XCoordinate":{"Whole":1,"Fraction":72},"YCoordinate":{"Whole":255,"Fraction":247}}]},"IsTriangle":false,"Index":1054,"Classification":"bed545a99ee57e17134e6f2ab35b5413"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 40"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Segments.png b/TRRandomizerCore/Resources/TR2/Models/FallingCeilingOrSandbag/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..b02d549308ead30a7f347b0907e4c050f04f653d GIT binary patch literal 2425 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 GoAO`3w)21h literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Data.json b/TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Data.json new file mode 100644 index 000000000..da592c899 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Data.json @@ -0,0 +1 @@ +{"Animations":{"444":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":11,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":2,"NextAnimation":444,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":343,"NumAnimCommands":0,"AnimCommand":1564},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65408,98,65359,104,65436,70,65526,65502,65529,14,31625,65408,98,65359,104,65436,70,65526,65502,65529,14,31625,65408,98,65359,104,65436,70,65526,65502,65529,14,31625],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":111084,"Centre":{"X":-3,"Y":-1,"Z":14},"CollRadius":179,"NumVertices":32,"Vertices":[{"X":11,"Y":175,"Z":11},{"X":-9,"Y":175,"Z":11},{"X":-9,"Y":-105,"Z":11},{"X":11,"Y":-105,"Z":11},{"X":11,"Y":175,"Z":-9},{"X":-9,"Y":175,"Z":-9},{"X":-9,"Y":-105,"Z":-9},{"X":11,"Y":-105,"Z":-9},{"X":-12,"Y":175,"Z":1},{"X":1,"Y":-105,"Z":-13},{"X":15,"Y":-105,"Z":1},{"X":1,"Y":175,"Z":14},{"X":1,"Y":175,"Z":-13},{"X":15,"Y":175,"Z":1},{"X":1,"Y":-105,"Z":14},{"X":-12,"Y":-105,"Z":1},{"X":-18,"Y":-175,"Z":18},{"X":18,"Y":-175,"Z":18},{"X":-18,"Y":-175,"Z":-18},{"X":18,"Y":-175,"Z":-18},{"X":-50,"Y":-135,"Z":0},{"X":0,"Y":-135,"Z":50},{"X":50,"Y":-135,"Z":0},{"X":0,"Y":-135,"Z":-50},{"X":-18,"Y":-95,"Z":18},{"X":18,"Y":-95,"Z":18},{"X":-18,"Y":-95,"Z":-18},{"X":18,"Y":-95,"Z":-18},{"X":34,"Y":-135,"Z":-34},{"X":-34,"Y":-135,"Z":-34},{"X":-34,"Y":-135,"Z":34},{"X":34,"Y":-135,"Z":34}],"NumNormals":32,"Normals":[{"X":6006,"Y":13903,"Z":6026},{"X":-10233,"Y":7896,"Z":9932},{"X":-11696,"Y":0,"Z":11353},{"X":11507,"Y":0,"Z":11545},{"X":9942,"Y":7874,"Z":-10239},{"X":-10070,"Y":7976,"Z":-10033},{"X":-11547,"Y":0,"Z":-11505},{"X":11355,"Y":0,"Z":-11694},{"X":-11222,"Y":11821,"Z":77},{"X":144,"Y":0,"Z":-16299},{"X":16300,"Y":0,"Z":127},{"X":140,"Y":7694,"Z":14369},{"X":99,"Y":11832,"Z":-11211},{"X":14363,"Y":7707,"Z":112},{"X":159,"Y":0,"Z":16299},{"X":-16300,"Y":0,"Z":112},{"X":-7499,"Y":-12379,"Z":7499},{"X":7499,"Y":-12379,"Z":7499},{"X":-7499,"Y":-12379,"Z":-7499},{"X":7499,"Y":-12379,"Z":-7499},{"X":-16300,"Y":0,"Z":0},{"X":0,"Y":0,"Z":16300},{"X":16300,"Y":0,"Z":0},{"X":0,"Y":0,"Z":-16300},{"X":-7499,"Y":12379,"Z":7499},{"X":7499,"Y":12379,"Z":7499},{"X":-7499,"Y":12379,"Z":-7499},{"X":7499,"Y":12379,"Z":-7499},{"X":11526,"Y":0,"Z":-11526},{"X":-11526,"Y":0,"Z":-11526},{"X":-11526,"Y":0,"Z":11526},{"X":11526,"Y":0,"Z":11526}],"Lights":null,"NumTexturedRectangles":13,"TexturedRectangles":[{"Vertices":[14,2,1,11],"Texture":1237},{"Vertices":[3,14,11,0],"Texture":1237},{"Vertices":[0,8,5,12],"Texture":1238},{"Vertices":[1,8,0,11],"Texture":1239},{"Vertices":[15,6,5,8],"Texture":1237},{"Vertices":[2,15,8,1],"Texture":1237},{"Vertices":[7,10,13,4],"Texture":1237},{"Vertices":[10,3,0,13],"Texture":1237},{"Vertices":[6,9,12,5],"Texture":1237},{"Vertices":[9,7,4,12],"Texture":1237},{"Vertices":[13,0,12,4],"Texture":1239},{"Vertices":[16,17,19,18],"Texture":1240},{"Vertices":[27,25,24,26],"Texture":1241}],"NumTexturedTriangles":24,"TexturedTriangles":[{"Vertices":[23,18,19],"Texture":1242},{"Vertices":[16,18,20],"Texture":1242},{"Vertices":[17,16,21],"Texture":1242},{"Vertices":[19,17,22],"Texture":1242},{"Vertices":[21,31,17],"Texture":1242},{"Vertices":[20,30,16],"Texture":1243},{"Vertices":[23,29,18],"Texture":1243},{"Vertices":[22,28,19],"Texture":1242},{"Vertices":[31,25,22],"Texture":1242},{"Vertices":[26,23,27],"Texture":1242},{"Vertices":[30,24,21],"Texture":1242},{"Vertices":[29,26,20],"Texture":1242},{"Vertices":[24,20,26],"Texture":1242},{"Vertices":[25,21,24],"Texture":1242},{"Vertices":[27,22,25],"Texture":1242},{"Vertices":[28,27,23],"Texture":1242},{"Vertices":[28,23,19],"Texture":1242},{"Vertices":[22,27,28],"Texture":1242},{"Vertices":[29,20,18],"Texture":1243},{"Vertices":[23,26,29],"Texture":1242},{"Vertices":[30,21,16],"Texture":1242},{"Vertices":[20,24,30],"Texture":1242},{"Vertices":[31,22,17],"Texture":1242},{"Vertices":[21,25,31],"Texture":1242}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":-42,"OffsetY":20,"OffsetZ":2}],"Model":{"ID":198,"NumMeshes":1,"StartingMesh":348,"MeshTree":1140,"FrameOffset":396598,"Animation":444},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":255,"Fraction":159}},{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":255,"Fraction":159}}]},"IsTriangle":false,"Index":1237,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"},{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":1,"Fraction":32}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":1,"Fraction":32}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":255,"Fraction":47}},{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":255,"Fraction":47}}]},"IsTriangle":false,"Index":1238,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"},{"Texture":{"Attribute":0,"AtlasAndFlag":7,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":1,"Fraction":104}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":1,"Fraction":104}},{"XCoordinate":{"Whole":255,"Fraction":39},"YCoordinate":{"Whole":255,"Fraction":111}},{"XCoordinate":{"Whole":1,"Fraction":24},"YCoordinate":{"Whole":255,"Fraction":111}}]},"IsTriangle":false,"Index":1239,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"}],"1":[{"Texture":{"Attribute":0,"AtlasAndFlag":8,"Vertices":[{"XCoordinate":{"Whole":0,"Fraction":224},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":0,"Fraction":224},"YCoordinate":{"Whole":0,"Fraction":40}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":1243,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"},{"Texture":{"Attribute":0,"AtlasAndFlag":8,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":1,"Fraction":40}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":1242,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"},{"Texture":{"Attribute":0,"AtlasAndFlag":8,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":1,"Fraction":40}},{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":1,"Fraction":40}},{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":255,"Fraction":71}}]},"IsTriangle":false,"Index":1241,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"},{"Texture":{"Attribute":0,"AtlasAndFlag":8,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":1,"Fraction":40}},{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":1,"Fraction":40}},{"XCoordinate":{"Whole":255,"Fraction":255},"YCoordinate":{"Whole":255,"Fraction":71}},{"XCoordinate":{"Whole":1,"Fraction":224},"YCoordinate":{"Whole":255,"Fraction":71}}]},"IsTriangle":false,"Index":1240,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"}]},"SpriteTextures":{"Key2_S_P":{"2":[{"Texture":{"Atlas":12,"X":80,"Y":48,"Width":14591,"Height":16639,"LeftSide":-99,"TopSide":-213,"RightSide":100,"BottomSide":14},"Index":28,"Classification":"9fd5006dbd27ed6dda29aad8e3642033"}]}},"SpriteSequences":{"Key2_S_P":{"SpriteID":194,"NegativeLength":-1,"Offset":28}},"TextureSegments":["89, 0, 16, 160","0, 0, 32, 32","32, 0, 57, 65"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Segments.png b/TRRandomizerCore/Resources/TR2/Models/Key2_M_H/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..cb9befdb86efc182b7a7492661ad6ff61d260aa0 GIT binary patch literal 5350 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 DJ)G-+ literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Data.json b/TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Data.json new file mode 100644 index 000000000..d6ccfc526 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Data.json @@ -0,0 +1 @@ +{"Animations":{"478":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":478,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":360,"NumAnimCommands":0,"AnimCommand":1608},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65501,37,65381,1,65531,5,1,65459,0,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":121952,"Centre":{"X":7,"Y":3,"Z":5},"CollRadius":87,"NumVertices":66,"Vertices":[{"X":13,"Y":-67,"Z":5},{"X":-15,"Y":-67,"Z":5},{"X":23,"Y":-57,"Z":5},{"X":-26,"Y":-57,"Z":5},{"X":13,"Y":-47,"Z":5},{"X":-13,"Y":-47,"Z":5},{"X":15,"Y":-78,"Z":5},{"X":36,"Y":-57,"Z":5},{"X":15,"Y":-37,"Z":5},{"X":-15,"Y":-37,"Z":5},{"X":-36,"Y":-57,"Z":5},{"X":-15,"Y":-78,"Z":5},{"X":5,"Y":-47,"Z":5},{"X":5,"Y":-54,"Z":5},{"X":-5,"Y":-54,"Z":5},{"X":-5,"Y":-47,"Z":5},{"X":13,"Y":-67,"Z":-5},{"X":-15,"Y":-67,"Z":-5},{"X":23,"Y":-57,"Z":-5},{"X":-26,"Y":-57,"Z":-5},{"X":13,"Y":-47,"Z":-5},{"X":-13,"Y":-47,"Z":-5},{"X":15,"Y":-78,"Z":-5},{"X":36,"Y":-57,"Z":-5},{"X":15,"Y":-37,"Z":-5},{"X":-15,"Y":-37,"Z":-5},{"X":-36,"Y":-57,"Z":-5},{"X":-15,"Y":-78,"Z":-5},{"X":5,"Y":-47,"Z":-5},{"X":5,"Y":-54,"Z":-5},{"X":-5,"Y":-54,"Z":-5},{"X":-5,"Y":-47,"Z":-5},{"X":5,"Y":-37,"Z":-5},{"X":-5,"Y":-37,"Z":-5},{"X":5,"Y":-37,"Z":5},{"X":-5,"Y":-37,"Z":5},{"X":5,"Y":78,"Z":5},{"X":-5,"Y":78,"Z":5},{"X":-20,"Y":78,"Z":5},{"X":-35,"Y":78,"Z":5},{"X":-35,"Y":70,"Z":5},{"X":-20,"Y":70,"Z":5},{"X":-20,"Y":64,"Z":5},{"X":-30,"Y":64,"Z":5},{"X":-30,"Y":56,"Z":5},{"X":-20,"Y":56,"Z":5},{"X":-20,"Y":51,"Z":5},{"X":-35,"Y":51,"Z":5},{"X":-35,"Y":43,"Z":5},{"X":-20,"Y":43,"Z":5},{"X":-5,"Y":43,"Z":5},{"X":5,"Y":78,"Z":-5},{"X":-5,"Y":78,"Z":-5},{"X":-20,"Y":78,"Z":-5},{"X":-35,"Y":78,"Z":-5},{"X":-35,"Y":70,"Z":-5},{"X":-20,"Y":70,"Z":-5},{"X":-20,"Y":64,"Z":-5},{"X":-30,"Y":64,"Z":-5},{"X":-30,"Y":56,"Z":-5},{"X":-20,"Y":56,"Z":-5},{"X":-20,"Y":51,"Z":-5},{"X":-35,"Y":51,"Z":-5},{"X":-35,"Y":43,"Z":-5},{"X":-5,"Y":43,"Z":-5},{"X":-20,"Y":43,"Z":-5}],"NumNormals":66,"Normals":[{"X":-4233,"Y":10219,"Z":11972},{"X":4233,"Y":10219,"Z":11972},{"X":-9411,"Y":0,"Z":13309},{"X":9030,"Y":-500,"Z":13561},{"X":-4233,"Y":-10219,"Z":11972},{"X":3703,"Y":-10556,"Z":11855},{"X":4233,"Y":-10219,"Z":11973},{"X":9411,"Y":0,"Z":13309},{"X":4233,"Y":10219,"Z":11972},{"X":-4233,"Y":10219,"Z":11972},{"X":-9411,"Y":0,"Z":13309},{"X":-4233,"Y":-10219,"Z":11973},{"X":9411,"Y":-9411,"Z":9411},{"X":9411,"Y":-9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":-4233,"Y":10219,"Z":-11972},{"X":4233,"Y":10219,"Z":-11972},{"X":-9411,"Y":0,"Z":-13309},{"X":9030,"Y":-500,"Z":-13561},{"X":-4233,"Y":-10219,"Z":-11972},{"X":3703,"Y":-10556,"Z":-11855},{"X":4233,"Y":-10219,"Z":-11973},{"X":9411,"Y":0,"Z":-13309},{"X":4233,"Y":10219,"Z":-11972},{"X":-4233,"Y":10219,"Z":-11972},{"X":-9411,"Y":0,"Z":-13309},{"X":-4233,"Y":-10219,"Z":-11973},{"X":9411,"Y":-9411,"Z":-9411},{"X":9411,"Y":-9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":9411,"Z":-9411},{"X":9411,"Y":9411,"Z":9411},{"X":-9411,"Y":9411,"Z":9411},{"X":9411,"Y":9411,"Z":9411},{"X":0,"Y":0,"Z":16300},{"X":-7290,"Y":0,"Z":14579},{"X":-9411,"Y":9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":0,"Y":-11526,"Z":11526},{"X":0,"Y":11526,"Z":11526},{"X":-9411,"Y":9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":0,"Y":-11526,"Z":11526},{"X":0,"Y":11526,"Z":11526},{"X":-9411,"Y":9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":-7290,"Y":0,"Z":14579},{"X":-9411,"Y":-9411,"Z":9411},{"X":9411,"Y":9411,"Z":-9411},{"X":0,"Y":0,"Z":-16300},{"X":-7290,"Y":0,"Z":-14579},{"X":-9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":0,"Y":-11526,"Z":-11526},{"X":0,"Y":11526,"Z":-11526},{"X":-9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":0,"Y":-11526,"Z":-11526},{"X":0,"Y":11526,"Z":-11526},{"X":-9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":-7290,"Y":0,"Z":-14579}],"Lights":null,"NumTexturedRectangles":53,"TexturedRectangles":[{"Vertices":[47,48,63,62],"Texture":1375},{"Vertices":[43,44,59,58],"Texture":1375},{"Vertices":[39,40,55,54],"Texture":1375},{"Vertices":[41,56,55,40],"Texture":1375},{"Vertices":[38,41,40,39],"Texture":1375},{"Vertices":[54,55,56,53],"Texture":1375},{"Vertices":[46,49,48,47],"Texture":1375},{"Vertices":[62,63,65,61],"Texture":1375},{"Vertices":[59,44,45,60],"Texture":1375},{"Vertices":[58,59,60,57],"Texture":1375},{"Vertices":[43,58,57,42],"Texture":1375},{"Vertices":[39,54,51,36],"Texture":1375},{"Vertices":[65,64,52,53],"Texture":1375},{"Vertices":[63,48,50,64],"Texture":1375},{"Vertices":[53,38,49,65],"Texture":1375},{"Vertices":[6,22,27,11],"Texture":1375},{"Vertices":[11,27,26,10],"Texture":1375},{"Vertices":[10,26,25,9],"Texture":1375},{"Vertices":[7,23,22,6],"Texture":1375},{"Vertices":[8,24,23,7],"Texture":1375},{"Vertices":[9,25,33,35],"Texture":1375},{"Vertices":[34,32,24,8],"Texture":1375},{"Vertices":[64,50,35,33],"Texture":1376},{"Vertices":[32,34,36,51],"Texture":1377},{"Vertices":[50,49,38,37],"Texture":1375},{"Vertices":[25,21,31,33],"Texture":1375},{"Vertices":[26,19,21,25],"Texture":1375},{"Vertices":[19,26,27,17],"Texture":1375},{"Vertices":[17,27,22,16],"Texture":1375},{"Vertices":[16,22,23,18],"Texture":1375},{"Vertices":[2,7,6,0],"Texture":1375},{"Vertices":[0,6,11,1],"Texture":1375},{"Vertices":[1,11,10,3],"Texture":1375},{"Vertices":[7,2,4,8],"Texture":1375},{"Vertices":[24,20,18,23],"Texture":1375},{"Vertices":[32,28,20,24],"Texture":1375},{"Vertices":[8,4,12,34],"Texture":1375},{"Vertices":[35,15,5,9],"Texture":1375},{"Vertices":[9,5,3,10],"Texture":1375},{"Vertices":[29,30,14,13],"Texture":1375},{"Vertices":[29,13,12,28],"Texture":1375},{"Vertices":[14,30,31,15],"Texture":1375},{"Vertices":[13,14,37,36],"Texture":1378},{"Vertices":[30,29,51,52],"Texture":1378},{"Vertices":[15,31,21,5],"Texture":1375},{"Vertices":[4,20,28,12],"Texture":1375},{"Vertices":[2,18,20,4],"Texture":1375},{"Vertices":[5,21,19,3],"Texture":1375},{"Vertices":[1,3,19,17],"Texture":1375},{"Vertices":[0,1,17,16],"Texture":1375},{"Vertices":[18,2,0,16],"Texture":1375},{"Vertices":[42,45,44,43],"Texture":1375},{"Vertices":[46,47,62,61],"Texture":1375}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":0,"OffsetX":-4,"OffsetY":193,"OffsetZ":0}],"Model":{"ID":199,"NumMeshes":1,"StartingMesh":416,"MeshTree":1420,"FrameOffset":433324,"Animation":478},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":11,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":152}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":1,"Fraction":152}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":255,"Fraction":215}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":215}}]},"IsTriangle":false,"Index":1378,"Classification":"45341cc1cc5a485ca18fd816b833175b"},{"Texture":{"Attribute":0,"AtlasAndFlag":11,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":255,"Fraction":215}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":215}}]},"IsTriangle":false,"Index":1377,"Classification":"45341cc1cc5a485ca18fd816b833175b"},{"Texture":{"Attribute":0,"AtlasAndFlag":11,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":1,"Fraction":160}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":255,"Fraction":199}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":199}}]},"IsTriangle":false,"Index":1376,"Classification":"45341cc1cc5a485ca18fd816b833175b"},{"Texture":{"Attribute":0,"AtlasAndFlag":11,"Vertices":[{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":1,"Fraction":168}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":1,"Fraction":168}},{"XCoordinate":{"Whole":1,"Fraction":128},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":255,"Fraction":135},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":1375,"Classification":"45341cc1cc5a485ca18fd816b833175b"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 8, 64"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Segments.png b/TRRandomizerCore/Resources/TR2/Models/Key3_M_H/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..ada8298355cce868f78cb97ca81f1e6d81f2ba5a GIT binary patch literal 683 zcmV;c0#yBpP)T%00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0zgSbK~zXf<&`UX z!$1s#7xoB&riO-wriKdx4NU`kcz6EU9mi?Dwg)Is_My>eB&*x9*6CQ6ZgrHkwXTEj z%2wy&zRh-w)6LdE?JR~wO-EfuU$WM^9=n3evM9QzxH9Z}4MTHc%Njt_V8B&FSdtRo zn}%Wd_*uhg0;2&?;Rhky*P3*NO%wx;118J>95z_`N{aolwLU;;YF&h(Y3TEC1?;<8 z-lJ!=Kq5y+5b1A#^=V>X=H=!_!NA`1a=;2xdF-NtKD8^7)?;pU%Uhk|Ow&`qXpvmv zOzo|sZB7cg*nkG;05K%M-(pfeE)mPwX?m)+q4l{Btwp8>0g|eL`q2If_&(KuoWFmg ze=t#IFq-# zSqqd1iqjSJl>!QfOb}(_AVn%GxupK9zW?-R6><Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0t87!K~zXfrI)dC zgD?<8Dg6m4^9v~{-BMCgx}>F~q;#AAC9K2~hb#%l(#(!dw|ApmOCpnIp6{#0^Vz>Z z`DtoH%{cm4+_+3@KMZU4=p2Twb!*VIH;4Z2=M++0`?KY{udx2KKNw6IVQtL{)VQ8$ z2qxV;_QBk=%^OeaLx2?#i_>hm+J0v+HWNcUz^L+ycOTh-K)<0E5JZ3r?wy((S2QRNux7^W z?jt+6LUz-zMtp&*?LYlDafP^6@$Mr#fPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0a{5!K~y+Tg_J9n zgfI|Aku66e+ai%8u}CBm*|ufNk-Y_$(A$`GWw=%6ks>f4?#ZVr@1-gns?YpRFh8eD zejfcgimSL8JjXT--95G6O&a^g*2i=-eAFc9a~8ntf*lnY1VKujiTV`%_oo1o&el7S!gHhtZ08v~Mw$v}I6amk56 zMg}fk=J*#EP1uj(#Q&|}+<=_DxQJ^r@J&DD0^1h#b(Kw83Aq7c63iFKR4P-So)VZV zCiJlL`?chFJl?i6U~UGn4b011fPN+5xw!)6C>}8b{wor`0wd+-3cT`&40n%w212XY v@)o&*y@4Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0h38YK~y+Tg_I$; zgD?z*kw_#Gi=0Gakw_$Rb`m*>egC&FU&<{lhi&4X9@^x7N!qQN$2u%?=bEQB>G>Rf zYF!^G_miq=s6FuY8VbGNvuoea^(qR%WO&qpLJ_%r-=x($05J9Sq3V>uk&<(jfGP=N z_V7#qHZZ3W4Eau4%*3S8X`in04#qA5#xb5@e(69}S7BZHux+CUvQia$2t#sm07gJ! z7q#aU04~hOVE}dHP}^&|I8Q-717ZitXLSG{0DL?EjwA(0g0N4_T?fh&2qgd?y3hn2 z+R!wOn_=z-W=f314gj&NfBPD?*Wxgsd^><(%sCK%5w*PmY(%`61hDffV48ZrT%BXC zxB}oESd!m~C3Rf{(8(`Aeg{;Zo@ox?kZ-Tv%q2j)3;~GE0nuEqsPa9`3xHR4BmlS* z=MfNpP$~#h%ovlp_zJixJx@EwTmU*@UuH;?5X656c{O+P>g`;~cL1tqW&W((V*&Uk zo+--z=ui&8N2b68azL)U@~adR#}qrdi#yeYe-W^vxAIg)OaK4?07*qoM6N<$f+JGT A-~a#s literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Data.json b/TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Data.json new file mode 100644 index 000000000..b15f58cd4 --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Data.json @@ -0,0 +1 @@ +{"Animations":{"406":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":0,"NextAnimation":406,"NextFrame":0,"NumStateChanges":1,"StateChangeOffset":336,"NumAnimCommands":0,"AnimCommand":1521},"AnimationDispatches":{"368":{"Low":0,"High":1,"NextAnimation":408,"NextFrame":2}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":1,"NumAnimDispatches":1,"AnimDispatch":368}]},"407":{"Animation":{"FrameOffset":20,"FrameRate":1,"FrameSize":10,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":1,"FrameEnd":1,"NextAnimation":407,"NextFrame":1,"NumStateChanges":1,"StateChangeOffset":337,"NumAnimCommands":0,"AnimCommand":1521},"AnimationDispatches":{"369":{"Low":1,"High":2,"NextAnimation":409,"NextFrame":63}},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[{"StateID":0,"NumAnimDispatches":1,"AnimDispatch":369}]},"408":{"Animation":{"FrameOffset":40,"FrameRate":1,"FrameSize":10,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":2,"FrameEnd":62,"NextAnimation":407,"NextFrame":1,"NumStateChanges":0,"StateChangeOffset":338,"NumAnimCommands":1,"AnimCommand":1521},"AnimationDispatches":{},"Commands":{"1521":{"Command":5,"Params":[14,82]}},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{"82":-1}},"StateChanges":[]},"409":{"Animation":{"FrameOffset":1260,"FrameRate":1,"FrameSize":10,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":63,"FrameEnd":73,"NextAnimation":410,"NextFrame":74,"NumStateChanges":0,"StateChangeOffset":338,"NumAnimCommands":1,"AnimCommand":1524},"AnimationDispatches":{},"Commands":{"1524":{"Command":5,"Params":[63,83]}},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{"83":-1}},"StateChanges":[]},"410":{"Animation":{"FrameOffset":1480,"FrameRate":1,"FrameSize":10,"StateID":0,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":74,"FrameEnd":81,"NextAnimation":406,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":338,"NumAnimCommands":0,"AnimCommand":1527},"AnimationDispatches":{},"Commands":{},"Sound":{"SampleIndices":{},"SoundDetails":{},"SoundMapIndices":{}},"StateChanges":[]}},"AnimationFrames":[65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,62460,64508,64840,64933,513,64508,64840,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63475,65523,64978,65071,513,65523,64978,49152,65024,512,63477,65525,64978,65071,513,65525,64978,49152,65024,512,63482,65530,64978,65071,513,65530,64978,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63486,65534,64977,65070,513,65534,64977,49152,65024,512,63482,65530,64977,65070,513,65530,64977,49152,65024,512,63475,65523,64976,65069,513,65523,64976,49152,65024,512,63466,65514,64975,65068,513,65514,64975,49152,65024,512,63454,65502,64973,65066,513,65502,64973,49152,65024,512,63439,65487,64971,65064,513,65487,64971,49152,65024,512,63421,65469,64969,65062,513,65469,64969,49152,65024,512,63401,65449,64966,65059,513,65449,64966,49152,65024,512,63378,65426,64963,65056,513,65426,64963,49152,65024,512,63354,65402,64960,65053,513,65402,64960,49152,65024,512,63330,65378,64957,65050,513,65378,64957,49152,65024,512,63307,65355,64954,65047,513,65355,64954,49152,65024,512,63283,65331,64950,65043,513,65331,64950,49152,65024,512,63260,65308,64947,65040,513,65308,64947,49152,65024,512,63236,65284,64944,65037,513,65284,64944,49152,65024,512,63213,65261,64941,65034,513,65261,64941,49152,65024,512,63189,65237,64938,65031,513,65237,64938,49152,65024,512,63166,65214,64935,65028,513,65214,64935,49152,65024,512,63142,65190,64932,65025,513,65190,64932,49152,65024,512,63119,65167,64928,65021,513,65167,64928,49152,65024,512,63095,65143,64925,65018,513,65143,64925,49152,65024,512,63072,65120,64922,65015,513,65120,64922,49152,65024,512,63048,65096,64919,65012,513,65096,64919,49152,65024,512,63025,65073,64916,65009,513,65073,64916,49152,65024,512,63001,65049,64913,65006,513,65049,64913,49152,65024,512,62978,65026,64909,65002,513,65026,64909,49152,65024,512,62954,65002,64906,64999,513,65002,64906,49152,65024,512,62931,64979,64903,64996,513,64979,64903,49152,65024,512,62907,64955,64900,64993,513,64955,64900,49152,65024,512,62884,64932,64897,64990,513,64932,64897,49152,65024,512,62860,64908,64894,64987,513,64908,64894,49152,65024,512,62836,64884,64891,64984,513,64884,64891,49152,65024,512,62813,64861,64887,64980,513,64861,64887,49152,65024,512,62789,64837,64884,64977,513,64837,64884,49152,65024,512,62766,64814,64881,64974,513,64814,64881,49152,65024,512,62742,64790,64878,64971,513,64790,64878,49152,65024,512,62719,64767,64875,64968,513,64767,64875,49152,65024,512,62695,64743,64872,64965,513,64743,64872,49152,65024,512,62672,64720,64869,64962,513,64720,64869,49152,65024,512,62648,64696,64865,64958,513,64696,64865,49152,65024,512,62625,64673,64862,64955,513,64673,64862,49152,65024,512,62601,64649,64859,64952,513,64649,64859,49152,65024,512,62578,64626,64856,64949,513,64626,64856,49152,65024,512,62554,64602,64853,64946,513,64602,64853,49152,65024,512,62531,64579,64850,64943,513,64579,64850,49152,65024,512,62507,64555,64847,64940,513,64555,64847,49152,65024,512,62484,64532,64843,64936,513,64532,64843,49152,65024,512,62460,64508,64840,64933,513,64508,64840,49152,65024,512,62417,64465,64840,64933,513,64465,64840,49152,65024,512,62420,64468,64840,64933,513,64468,64840,49152,65024,512,62428,64476,64840,64933,513,64476,64840,49152,65024,512,62441,64489,64840,64933,513,64489,64840,49152,65024,512,62460,64508,64840,64933,513,64508,64840,49152,65024,512,62460,64508,64840,64933,513,64508,64840,49152,65024,512,62470,64518,64842,64935,513,64518,64842,49152,65024,512,62501,64549,64846,64939,513,64549,64846,49152,65024,512,62553,64601,64853,64946,513,64601,64853,49152,65024,512,62624,64672,64862,64955,513,64672,64862,49152,65024,512,62717,64765,64875,64968,513,64765,64875,49152,65024,512,62830,64878,64890,64983,513,64878,64890,49152,65024,512,62964,65012,64908,65001,513,65012,64908,49152,65024,512,63118,65166,64928,65021,513,65166,64928,49152,65024,512,63292,65340,64952,65045,513,65340,64952,49152,65024,512,63488,0,64978,65071,513,0,64978,49152,65024,512,63411,65459,64966,65059,513,65459,64966,49152,65024,512,63363,65411,64959,65052,513,65411,64959,49152,65024,512,63349,65397,64957,65050,513,65397,64957,49152,65024,512,63348,65396,64957,65050,513,65396,64957,49152,65024,512,63349,65397,64957,65050,513,65397,64957,49152,65024,512,63360,65408,64959,65052,513,65408,64959,49152,65024,512,63402,65450,64965,65058,513,65450,64965,49152,65024,512,63488,0,64978,65071,513,0,64978,49152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":85564,"Centre":{"X":-513,"Y":-1024,"Z":47},"CollRadius":66683,"NumVertices":8,"Vertices":[{"X":-1,"Y":0,"Z":93},{"X":-1025,"Y":0,"Z":93},{"X":-1025,"Y":-2048,"Z":93},{"X":-1,"Y":-2048,"Z":93},{"X":-1,"Y":0,"Z":0},{"X":-1025,"Y":0,"Z":0},{"X":-1025,"Y":-2048,"Z":0},{"X":-1,"Y":-2048,"Z":0}],"NumNormals":8,"Normals":[{"X":9411,"Y":9411,"Z":9411},{"X":-9411,"Y":9411,"Z":9411},{"X":-9411,"Y":-9411,"Z":9411},{"X":9411,"Y":-9411,"Z":9411},{"X":9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":9411,"Z":-9411},{"X":-9411,"Y":-9411,"Z":-9411},{"X":9411,"Y":-9411,"Z":-9411}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[3,2,1,0],"Texture":1070},{"Vertices":[4,0,1,5],"Texture":1071},{"Vertices":[2,6,5,1],"Texture":1071},{"Vertices":[6,2,3,7],"Texture":1071},{"Vertices":[7,3,0,4],"Texture":1071},{"Vertices":[6,7,4,5],"Texture":1070}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":2,"OffsetX":-1,"OffsetY":0,"OffsetZ":0}],"Model":{"ID":111,"NumMeshes":1,"StartingMesh":309,"MeshTree":1148,"FrameOffset":427476,"Animation":406},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":1,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":184},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":1,"Fraction":184},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":1070,"Classification":"bed545a99ee57e17134e6f2ab35b5413"},{"Texture":{"Attribute":0,"AtlasAndFlag":4,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":240},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":1,"Fraction":128}},{"XCoordinate":{"Whole":255,"Fraction":247},"YCoordinate":{"Whole":255,"Fraction":191}},{"XCoordinate":{"Whole":1,"Fraction":240},"YCoordinate":{"Whole":255,"Fraction":191}}]},"IsTriangle":false,"Index":1071,"Classification":"bed545a99ee57e17134e6f2ab35b5413"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 64, 64"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Segments.png b/TRRandomizerCore/Resources/TR2/Models/LiftingDoor1/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..cf212f4360ed6d74c7e0e8617d43220b6be2ab13 GIT binary patch literal 2797 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D3W7;QK~#8NwVNSx zBS{Q}4Hqsn3=Ir4G&M8~G&BtiG&Bti3|ttxFmU1hh5H*meXk|&+?2KRTy>|a-Wj*m zucg$FE7X4<^6QH9QT{cZu@jO#1);Fm*eGl z+^c`P-CQ=CwZ7l&qoEg=Q|!W@<48Z-;qa{MR3E)5-W0PwzrH?SagWEX`lj|xarthA z;^Wg=Uvi}}5uZ^41f5L~z+gVpzuU)WCJHb};))JL>H9R4eoeT0xH>z7&ul{NVk3kEkrNZ`e!2Uaow1I=|k;rEdkG0HSlX zAb`R)A(dUNh=Airf$VApqHqfA>}usogn|3;@J$Or+Je2^t@U}c8RRkV3M0jcF}cF6 zLT5q1Js-9*plD{VzsKma+D<61$F)pyt*;YQwh zxL;qN7A{fv`F6B$i-5PclL&)6+EYaVB$78U#5KpY!eHqds|ubfvWY8QGg{DvwCrjH z0??;!5djtHtUOo9RQ~BhEQ6nK1mxO}{hT13Mh z=HZ@QVZ{e3q7zaS%nGIKY6V;-c5#(j25yn{`1s8tfN(z_BV{t@pJGRo^Ks8rfHV|y zTq{qT@0Z#pA`R_Li7m~EEn>B#O-jDP3xd;#j|G)$+<+xUARUP)hg#;J(=exJ6q?D@qJp|+e zGp77yE@AKmA?N_ILJ(l-1}+81#bs-Abcq0ppep!+RJh|G_TV^uqyzm*0gjT_g0LVQ zf?$*VJ-b=~7sp&&2yk%0!v-f>ihw%2vGamc7Vah- zIc&yLUUs#jf)}fdE(A>5ECR;L=D1d1vRZbv0^aA@dm039AE!nKmuUU`{IJpm0%$A* z#jie#6bd5qRVX-&5_aUY71kM9E-nSr!6i!E)GCK@bRGdk$T%!~A9<4FT2WZXiaL{D zCo*wAPhK5TWJLrxJ4O*u&l${9jR+6{Fu^g=3DqlrVJNs@y11(B1}-|JmZMt)+^PZe z>)=I5bHl+U$F&0M`+U!qU9F6>#n#4sdp}#aqzVzB)mspBSO7(BkSzP7L4bTFiZGB5 zoCR`RD>&r7<^mUe7uS6!Nbyq*2#2z(l_G#eBNg$pB0&8_05>r2u#XNa;2dti9Rzr| ztg3^{s&Qy?aEk!Fmx!EaO!>=Pq^X|TcxbWS+>omQ;Oy7nlGiRSMbJ72#1Ys%jVjNB zFmP+-75>r3ciN!WpN zt1lcw0b@&X3+C&bK>+iU|IASla3z8QtqPgO=D1eSfdD60D_UIK zU!OlLT#nZ0gP&ckRG6a+0j#_ULC-xl7g;Xu%a{2_l)xngc%_wH zty~F+g}@FX0TLily8>yXe8`;0ajn!FAt(I6#aI`YS7I*iJ{0~4 z1bKq7Ij$9S1ZKR90Qa60U~6-5A>gk&j>1G$y%uNXhx6-<1PGubnp3Q_s?TF(v#XUV ztS&Bp9d>YW>U{K$?nOZTVMNZS50Icob>#w`hN0v?p=S{gxSSeY+;{URjLtnzgXrm1 zUJ#*Tm|G$dq@r69;2c;OFkVUI!ru7hClT-KYVzSl}uG^cU;d4}o~2W)VbpycS=^1rM@Z zTo(9`Kai;KcK|ggjC2kmL)Uv2Kvx79xY)~z6583-3gM2k{P=>^CK@W@MFbeUWUPZh zj%$T&1APr#kb9m5z;$1A;)whDjOd=$0LIW%_lN>gfDZiy$Bcj~n%UJ#P38~)F2=aH z{BacLva1!M4{~c4V4g|~r9?!?*xKR)9XYNQ4Gs|Pp9@m8!XXx1^c~!a0Eeuq_<#I? zgl^1L#Yn2Ua}H->s;;wAT7WnR*|?#v)mxB?tUvxhf>o*&$Z@TpM|0{0lT)n7wd`sI zOtx1SS1DjD7lFO3*#6=RNyO7APj9kktx!3ihs`8f@C%-;%E8w3OpH*T>i2D7UbiVkNC%g}I~-v>AkPUt`uq-9qtkcDrg zS2&Q zt^%TZ@wBYVGXt1Ro?WfTuqbSf4RsQ92*6gg@UOzY+P@-z8|pxgYXx13j}v~ZCTDOf zwZcgE9Dw8evYhQOyIQIGhRs9*_f;5aS{x>=(8zJE0EC|7lwNb?b9i>O0v@C~1YopF zEKaj%l>*aNg#52Rkl@_y;DYJa01TH623hD4U2LylGp5=#>cx^70U8+kuA!`|8v*Vk zE`(~wFbDuo;U2b3SD%LS+M&uRT8?W4ol1l3Y6aXXu-VlLdf;MgcC}K(It3Furx8Q_ zpg{n0s*nPNk8EWIER~BRgBH9RtRf~tBhX|2*6Qn78&6ypSdz0^NLZxoYNfxPS4*hT_zd? z81*7n=L21bfUrUD8V%g~uQl_dFn!t%A%OjqD(Nta<1}jz4m=EXaus4B%+VzZ`O}uO zyI=#j_(udVPc3+*hjNwX5!htovyrVj+Ti5itFM zgl=#?8z2IT`)cLjw2vlY0$ATAAWeOp;DQA30I#8e-hBW7 z>HfRF%E9*U9G!BuML#+>d3PdowOMB{%4 zsMYP89ROU8HPpNQzz?}Lr4%PoUQ&DYt}=Ii;(SM7Zqv2?Xldocy~V2e zo$iQ{LJha~9v;lq{dmC;8nwCG+i-g{X?LHoe-?^745qE`58x_@nO;{1Moc9tYWA7! z-Q>JF@55%dSXU%m+3+#-fE1xl46&lFwijk-&sRjK!$MGu4kR;J!Ns6x3%yE z2P>4AhUe2IbbJ*E*YQ4=juAG_3NTmRb}wKASLt;Wn_px zfKZ1iWF8*O57Am90)uuLi=8-g^{fKaWZ)0}G9M-w5C5 z%wV#rmhH)sB|7iZ-N5#tKiS@q<3|o>M71GOlhaDaL`UN`OeHY@vqV+9TQ^C z=|t(L@}}wAhk~-1c2=yUZ>8!<~$wy;SQQ88+R2kSlK@VY5os9Dz7R_$d+ZZ*O3s=U0MSm3E~Mbj(A z%iSl*?(>FnPius_(8h*KJx3~GgZY!u?Ehp(0k+?t&2f9Rc19xG14z%D4uhf}tueP2 zD{wk9f`>mOFvdjX&rsg_gfbeXf;}U|0CX?&;`7j_fm?#lYkSkZ1H0HWlB)lvna{QO zKBgI?(o{UZWgeVW(kV|mr=>3CSNv*w=<~=r(w&hD_cmaVYN;vCj}|EL(Px8%ZpB)m z^+GPOukcy7yHCAHbdBU0duZEmzK_?05JL-m92UJTFi7_nx_r(0Elo zbgso!dHmK6H~)NS+}+GSKK_|L76N}jHdIxqZZ8s zV)I;y~u%*JFk=kIe2HOL5*8 z&MX@oM*YQpVJpI$xuliBApWlTcrU3>C%T%kZ|$h<wNar=|t&f$=wyZcm>m-1pV4YA5dH{B{jgYYP$?tEP@sC_5Jdz`|)nI z*XUjK-6)xi;G&zOz3dtt{pO!DVkRUXMx2<6Hp~p}wLypto-#cSb1cNy(t#Ou#ZiNx z@_@sDsVg<*=5iUu-IZ5Ha>#@5`AiOGTyCxZs@{FK58gXNVm{EHC`Q(`0TUu(p|Dn{ zrrBt?hVSY+G=@{xr~hm1Qf8ZKth{aB!QHj}>usqys%~BjttRW=dsBZWLsM=}et{aq z`rcF#<23W2;E!U?J89;XUpn&CnI}68$Gx)jZakw1Qt{ATA51-r5#li0Sf(h)#&~?X zHIS{6@J{u6mbPCCb)uUT!8fip3O{f$_K{^a)}qmLITVxNb|ZF|-PLt20{jq8U5AVM=r==HOl6(grw*QeS?xlp@(MUI8u8n{$e%b9R1k=6F@;7h z(?`KNn}X~$r4O_B!zx%XSL-4c49GZ>*zMOreu3*hl z$Ko?VKG^=DHeJ17v#@V{gLqIg2$W-Ue=;LjpGlo~G&@2(yxkhFMr3(Mg)c<`s0L3s zI9LYPG}jKM*;*r;l)i;qcmJ-L)QkEpglsManpW&=KdJ&b3Nu=dxr0}JECrwU)EPfQ zDsqdFQ&X#)qzjC{1v@WS`^_w=cghAZ-0mqDp_c7fDkJ8$SAH3raSscJ2E=~x-i6!S z=Hj=XK%2UgwFe%mldb|K2UX+MJJyj$+h@jTS>8Wfwj$wDJ(?r*Dv{X0R}A1!iv?p?mjO#sp1PSch2vUbhoot0Fr-ZSY z?6UhJzxxV81h>_1UN`bOSh%%d;x8&vW6GRnw!&FoBp2O~gef%5K5fceKQ7B(E2We~ z$8VoZ&AB(bMK?!i{9;ww;8CjrS>G)7LM31Kn1A@q)-gKOKmZ!69Q9Ss_sxecR{0#K z{!-oMp=36lY;K4&l{y*wf@C>Oq<8dGFYz7tDewm0n0|`%JHI;z`JbnvAiFw|A)!VQV4xyLQ^pPN|*|_yfQGb@I z)(>j24Q$!3yiw+L+ZI~;GEP#W+Cg$pCS6#r{w(krdyi+`SPdA;b0}3XL$%Q@or?2k z7u>1__wJ`X*j2M7zsk*G-0NqK?k*JCt?n>K#Xi11 zmpZW7m@M9L(CL!^6Z>4(1V>%GaXAo00-YuN+ZyUkpRBU`&vkg;w`8A;R6PHzAFONR zN{?-7sBW&UCPE;HiHO*$ap`rr0M5F>-0L^)0=Zf2BLDPC-Cs(T{ zL6b$LbsQ779+CGi+sm|?I^6PTA35dtH>>bbdQU6Zx+U581#R9OnZ}A0#p;i72V;!{ zJZ)ZCB&CrQoul-=S&C?m2~+xQjXo}ST3#KSpK@h!50$AJ3md0=cz_;n$Dd;V>UTvC z*D~dlz4`*id>)&zZH9FAwm7#kG1XoM{;)Qe5Rn>xD*fFAnQAe$`S%i4MPB2dC@ufyO$6Jear!Py@ zjD9+Ovf=@bWIE=z17<@f*gBB|H-oVv)5oz5DHI>CNDog7od z_xg@oew+#G81khJCFj*PiyPK9OGBR6xMlv3s}rK8AnzP#FA8bfj~gAA$!F+`ee()P zW{XCS2Bfd!{?z8xY1NiE@m?^hej-rH>rc5YU^~FKHF$dCXy>ctthFgV`pLJ#aSq5R z@z#oVw9n{?tD`1N3E$=btrR7a&Bkb8HPI>1DUE`O*zxLob@<^B)*WoY5>dAD;ST!X-s9rs}(iL0G{q7*mXW1d0v9*-PSCN^0xY3@8 zHJJE$<;K@WZ!ptgTp$r8oq*$Z z)k#pis!q6Z5~~gxy<3{brDj+Wg~YHx)xA@=wS*q9*Ea6S34RgvJfjz$0I z{TfG9W-5Z!Mh6S7YJEaKBHr@aC=v88U8~)`r65|$D}`St`j7Hp#*_2vZqS=Q{N6B2 z9vIdy*hY9n{JuhtB%xQeE-lTcac6gQWvw~zbypp zs#gCH4YHqq{4+pVRn4VDu165>eA|C}M|#)jz}fehg}_T=Z4Oc_xLAUxTddWU1pkBY`^--)rw=Y^!^I++V)9agcm%z;*SP_Vnwg!PqSO#VD+Bom$v@mvE-_ ze85hCa-vShi7^fHGnXO-x0I4%IJF+0;E)D>cxDT2=Dv|d+yp(Ell^tpp@jQZLr$`O zPHEg{X$gz{w#u_tYic%fN#|awN?23)wwz z^WfQ*TZ*SX>A#qs(&HXJM3h`@UQxh0AUzVN5Z)_xAbZdcr}ZRz+ff-R>3T2Lx0X*Y z1377X&tc6A$!W1#BAum#gKY|Sbe784#yy{T943-=pwKOgXGyWQ5Y0Dt;fmFMB(4D@ zF+>z_W>^_5^$-gCQyJUj!aBwmlf|LYB<`I=JNT2IGPIWR+EQ#4qrhchT++GXLx;|y zwnUZ}W={yPGY$Fu1@G!$)L3;;jjy`xq{_50J7{Uh)R4!{_*=+2Z-2)Vck(~{-0J?h@=-;cUX;iS5cEF61PrAa?t*Gvkt$jXyzcIP(0oS<|wvRG9W4LUVa#fy%YwNN}uoGc1qr7EIm^Km~>_^*ghVkmUbM4Ko z>GJ_J(*=*i3__GILUyn16Dbw>isWe<-Fc&oLrFNQi>>q7@6iBIiYttM$`hgEIbS>3 z(^uu-HEKS>c2`XZko?_^|CHopfm#;u9$R^f@*a%k-Cx0aOPiQJMNh06m#bN;eJ*a# zBg*2-8hgOaAB9K*rrs;(iNZT?Tp6FOG}c{ON?K|dawh!+Rf{I5vc!w@8W*5H7PbzZ9ub~jLBu)@x`A%|-7ZsmvHaYm8rf|)Y{>Xh z5V(77SBg2TX2^^-LhYRM{{vfw_?7OH>JgLQ*+kZKGOnSo2poD~&4Ef3x*{ckB)v*DIHhoO~Uv|Z8 zuh%xy9O^us2Z_4}GzZ>G*3uhUTFXRa&DIAj0$k_!+5tGKyY2Q_OJd7&JT(9`^sEG< z)U@-nu73NKiWIdF#Om4iL_>H5W_i=yc-1M-~x=QpqxhAS-pJ`yT{KfCC~WZ ze2%DoL(L1Wzq6Dw`T9eu?k7=638q;57tgYXYG92|yzIe(1-Tx;>uS zq9k&J1Jjf&VPz%0FvBvNVe9sG_j-(;T;}ZGlbIM_7@)NGR8R18_X09baZ+(m(cg2B z<`gsfgZEsVo?GS_#(Q{^j_E}aENru$`6JD*XGr1HfNa<&~B0vE7L?8r&WG$$Gavxr?s z*Dm^EC{2%MCb)$DH;h=&ioLP~dJo^4oY=OX%Cq1o&%nz$WNsCudB<%PpVsWdwrUFf zNYoa!ur4SFW>=)-d;iX~a6*VoP;!Vl!51eq?*#| zEJC`cltn#YK=s{R7rh16&()cuPcB*Sc=`CK;2s5zMRl`YC~-9b=49)0Q2 zGa9k7ql%T_jMP|c4SY`p1?%3qNWvwePTjSjMVC?8}MuGW{9R}PUzf)(? zvm)Pdzm}w>y!#{d6vuP`M8bQ$$*2VOeEOlOySKaYOB-2*m78v@dDDv0Q*ms!@=`kM zEWHKfU>Sz3V66n76#RsmLx6(f`Sp->!PzUbm?FEQ>tVWgYdW3c7e!{?u=AaH8S`8_ zWFyd( zx%}8Ca%n8Po0|NCef`zRtkn~HF2Un{P?vXkN`L!?i$pSj2S~w4 z&d+3XnS?rbfy(LqSC#nX_>>v-?1t#rwe6o1--ElG&nkCGnH~+*UTW2f(Fz~!`BT1{ z(HVYBTNvu@CM!*l&xRne5fA2AC@@&cJc$yRt+YW?#!0zxVe~&kHO+_-(<_~0J+H?T zFv_}IlVDhHk}Ircem6nRq6sy~*VlFD52Bg&c(EZ?SRswWyx!EV{^N+d#&Z`xs^SPD=^FjW*0lP~y+(g|^Lmd}G z+W6AP{aY>mN4M4oW*VLsZj5Wvp9H53v zpm?eRSfIe9YxUvRoqJ2JOw~Wz>;_f%Q)@ez@}n>dY-bi-A$U6gI|G^xx2ztqTVnNV z=M!Go*(>kvLYaCQX3Kf8=)y9e)UfcI>CneUqqb=u<-s0wJz@CnzD%XGd<0 z{V8wB>roo-6{!=hbD`EU7~H0`K=3@N`l;EHXFY`0H_3uaU>Rb&d3LYeOs)Spm#e zSL{gdd>S5%5aQK1?vOj~&m%ufM~q}3Q%xEEbTsIR%-w|#i>;C&cJse(dVsG6 zi?wo+6o*@P30Uv+D=s>J3h6>8#@^WAf`$%?=;II7WQ)<&H(VCovX?kC|30)=lO+vA z@mSx_>TVn^7!dV`vlt+~WDlh%cdn8f@5yD07F8#j_utJw4ELBDB68Lcl(!8-EBX@m zYQ08EOPxP|7g(v9kS*pFU z*6dh5yiZ$@SSs86I=@4j5NHgu8Ey`nx6JAfT|PzhGpeB5rJqYLG1s!dlR)Ep2L_0(oUw_n_?-r+1yi>7u&z}UdqaC0&cW~)!S{G z_zRid-pqMBI|BT=nzr8p1wOWR+0O~Qj0fDOfVvw-t+-(pzhs>?`7gGI`&$>E17-3t zs2jbGvE&h)j?v*Ob{xy3t5D0SsJ4b{$L~${x^1_LIflgh%fow(zD*4pO>wRojK75K z$b_EmWxW8hiD?X#Ow)L0x)BTU??|jwKd$%JZcPl>+M}bz@7fA)4J9uxXp8@YLl|Efm=JmB7Y4Fe z-A{5p`VuPdHB>QOLib;DZfjPB=qDiLhl!T0p3LuAJHu+X>vnnAV`z(zhX=@Mkgli# z07)U(HS|Dv*VupjK56XH zyt0R-3j4Fw<#cPV|C!+J4RhdlzngV9&Og7UZ(6DTW?cPwqP$F61e;{rkeK@D1s)3H z=IjOBG*TC#PCK8p&Iri-FarmyV{V<~=iwo$q^Xdb)dY<@WFvbRIYQ23>vXOnM_>N{ z8KyyyOORWA=DDIAZYf>tlAo^N=;fU9NI4x15URgV==B5Y0%)X6wO)`J>0g?jQ>(JJ zeX+(`uq{-SbCaQOU?`bJ% z&hFC|Xf@#pPLBm#(4GHY_;07x?1z*IOFeo8Xexq&MQTseQzarS-F3Gp4X6HW30x1M25=K9{r z`3hP)bF4eOg?IRcT62hHo@P^n+@)NHnRYEK(J3J-H9(xnHcNS(w7?z5DE#z6GAu(4 ze96DRR0+5vzJH|u(D{~}BmHo8F$d&Bi#XNfj~}jD^L`ba3Ab-_=TaGm;g7Ff|Glv$ zesG>rRr1%)>pJJ3=2GtE1e4LtpB>Rl20|OnEp`gH%ZO@cFPw&kHRuI*WQY=I2BhUa zu@(N8(?6&FPp;f2S;=FySK!Tm2qNlUedrIUxJ53Aa66iMy|F@l=&pJ0df16cdCH$r zu+I-xA}J}c0a`k+dW z##j3NmKb?;zUe?j^5Q$r`qd{&Y8gVeC(`@U7y~%2IOjovaWGuS@x#R6zE}%P&+X_n z3!i+Zsh;R6*BIxo1xIPg|Cv_vO6^-;H{suQiYwEZ2RuSiH(f%wqze@JqfI&@FN$wY zti9_*2?Phs^Uf1so*%XCr-xL-yI=t#*tm7bY%5>#5w%u7eeWoG&#O_?DC_>_sgl}fp@ZV@iYtS(XVPn2 z_?oStFGsmb``a9m3zgG_oqEA4;iADHw)D|SLp{ww2P*uD7Ek;Y8;sQm0IZYvxW5LkuedP~_TlV$F z+C}?(d4lu94q`GGh~C1SZbfz(z!rIQ!Kd+u9`cQI9?KP*x!MSUU0$mYu^N)zeilln zfG?6eEW_MqaDO}ax;o}T3SYe3H*mHevOSCcPVk%zf$Q*@w0{Fz8uY+QBFJ69)FOT~ z^S?Y4vNujvcvr#B!F*H!e<^x;d;CC|ql3L-kR_FaaP=)Z2MA1O|C|Xg;?3#V;n)l` z{d_az^#wHNb*FKjw)-hp|L*MnkF7|nEHOS!M5Y*3XBXdVX9o)F<_<8pSrE2@@Zs?mk^Gs=UoOj0{2FN$xU1)iZH5T?;ES& za;+SvaOxY#a#pC1IG@O7&l$kpHs*qJipB*61sxq8g>M3+u`9C|U=pagc+TtKlu$EW z4(kR$ISz-GJWY6q&?vMP6h9klBFqe*X8XPk8sZX-JD1I^b}gI@zEuMj+ou8w?mSIj zb1VbLjcP*8Rd6b~(0j0=bIeL(7cc+J(~Ic8Wu2v+#pPP*<25qJm-)nilQn*CXxFl( zX<><`w*z;_S{q8pCzAv3?u75fR@8J+2Y*0#B}WjzK9$UC0<5!M#Vil zA$UdSWeu-xZ&Cg5m>)Cit6k`#pc+WheKeZ462Ee#A;wq~uj{c`pi6PiZSZ7+ zNnpKcb;V}&=^f1Hg9hX~wSi#|&!53>siIPLWVYAP-IKzDVWHM=_^DV}_MJ*nDV-+G z|F~EQg_3GH#lf(7$9`U?w==aXR3oi!J7cOFPhxC4g4{zXwymU<{Ur9>Li0{;zOvsnBfqW;cAlyyPiicHQFKOpuzM zQU3_1ytnK>G$kHOq5ob4omWa4@hR6Lt<)y%E{(|Y9~K=zCPS^7CYPQ1TXKop$??%- zZ6KJ*SoxX@ufrV&I>PuNxiferg3zR{X`2y6+AW#e%=8Q(bSMZB)mz|Y^U0Qh#jRfL zbs7C_a(&IfoWuP_ual|!O_+pjOv4=f#zICNUM~ooL9nmwW4#cU21xgBbs6ZMk1ayP zidTgu`#DFILNPsRUwbI#H9DvEE2MIHt!{ z`W2lfxTm<*&gvR+?qF2ZUA9LW@(A^NRC5eR&tclZ#vPa=)LX+{E_Z8uzt<*tTq z@ja1_ugQf4A10ENM5zgdCKvt^;DjOg>wm*bifTpTNqFc38L9M3lR zngmMHFMJL>tpwO&=hNO)g06ph)%C@-bk!@rG<1esN2 z*9qA&7;Rkyr;}tN#qP?V+%^24E){%TLGqNZUQB`XwIbH1G9hvTe%1M8eC$soIg=6y zJ9e%+xJs!w`e|Qx44I}={QOQz%;ZzBHPGbjSS@aaG z5db26n~-8^J(oKc2YRmp*g2=Ls^IIn{o7gO9jmBkAg4`5;$=Hnei=~SvrB-^`T>S9 zSs-gk;WQsx)8pLaB_(%);Ii>b32zhOu9yl5bc*f@@;f-byDjXi<5wDFDNHo)=F`kS z4i5Sut!yeXR&%h(wKq(wqaJbjpnI_YzSSmXRn&Sdyg{)P!F2#gE!$x53HIAE{M?7Y z&rg4@r}}lEy?IM-C$delNm!w`yugG4)TUEx(KtAXAUn(D-h;I6$mJ}u()qFT^wgfd zI^i}4hGMKKvk*UM{Dg5%+a?We>ttHk(k=l06G#(k1I>nIf3btgsp~Q>mxm(8zm$aJ z>}r2paQH-=j-U21%s#DUpEL5pu;U9&>m7DvYjmVg+-<_lVRvQk$P;SQ9Q2IUl~#$8 zar+Q@31K<Z5ha0{TbNfi?e9DKm{3#0{fv~|-f1qnH8WZ#>r2ADkGNyjN z&P1xzGHoeh@!X~@l+uNQa3t2%5QaiFW#?K_fz7Ia9OjV$MXk6kz6@CZfP`3DI^TgO-6BL=r< zF_YL`-+6X5W}bEEP$ebe(oUUpORI%u4Pk9a{H{WKywB^kjYtj3Y!cJUJ%@fc>1htv zxQ*$9vC?nJ)WlcTV=I0iy%U42B5*Vh<{@{@SN8KKUP@L-{>kL*Kuz0R|4lW&1}IA^ zZ+*x%eKCDyut_fZX}K@Q3t#Kgg|EmvD5J40zt_AC9qgJC&A$udOyy<(bAI%4LpeXn+-Eij%4 zZ9oonm6fH4iikU(E;Jd+PcD_ z-UQZcFpH{Sdy1A#Rl#r%g7M}sa?;)X8x1s1%0pOYw%=+zr_8j3a5D=;1ib~84kd~_ z-5Le!E|?+UlDK_=*X^e1kn~WLb1zwlqmd;YF(cn`@aHkYc(yZZbi88UgZYbl5K|bN z>}|)Yi7-TLQSb488Yc5)N$aX-k@v6qH@nrHglGaR@J;FdnC306 z>R-BT+)gmpR?aE3qN_y%_>m;%GmuPCJW!OyTJq2u9#dyA$82_jqyh^3ABj^rwAVK^ zq)@{6CI^PLIC>m(aVx2P;MT10vaw;MA7!VLgGl6ZWnPkj>0O{KJ!A3TAFv<`#O%Cl zt?kB=9jw;6PY+T{8ZM3$t4~XehC)YoR7=5GaFqwO-IfI*%TKdPev#auzTEEr8bvKO zlcP1A?GvCsnzfS(6qQcFiiIhxodz0wr59C?a*!;oQ zvRQ|oJRD_B(mijTMtBdo(;-y~UkUSS-|gs;Kv78x`m%?Zt4ss&OsfFDx`K#3iCF{# zJ#xgRoS^I8$#v$4`e ze$aq}$ZBi35OL2=%?X5EwlsMFyCY?XhdgPu&a~1|6`Mv;n?W!ALwHMhYdG9s|4<0_ z-_DxUmuw17Byi+_f0W)KI^Fm%Uui=DQry8l{wV|8(Z*64#FumEQ|K@)e@YqiHENnd zrBf+HM4#DwAKEN#J49ru^6&q%r*#X7rCc{A!k0}_g)L?qhL{a$WqrIwrz+ls+hEwe z(DV`F*afW_2tuxPM!RL*4~`cL5;Zx^w@sy(T3!uZY7_l-Wt+>VJuxOvC~^_~>GCy} z^SZdAsB~`@txL4f3qW+na#L_eE&KINZVrJGk?d1d`#mrW*#VQR-YCCKeYMSsIeyE% zIXAYo%<%`5L9~Jk@dz7wQ7Qi~I)2Ce@gB^VRu=9d6)c75jv_|6JSkQf3z)8}eUNa5 zAB%UuJG98D^PmSZn*y)Xi|~~R%df3;4Z#hgEcI-EgA>!2LONvqz^B1C>=wHNrNn_- zg<2KhM_#f3O95e%!ul_70&O5>MAVk)Q87mf{UjGRK=>+KQag!teIl?jc$oDi^K;`# zznlC(5RBCLLQ1(Xi+kPUm3Kv2=MJA0(=C+yLC~R+qx-|QQZk9s!^go=e;OreIcqV) zTkwaprokq#rF+5pJtS<4aRxI{jl<;NO2Vyk1^6UshlOMcX*bMJQV=j6je{mHeLM3F zl;TGa#1r@dkQq`J?fQnd!N*IggZ5e)IVBS2i}}L}&|cfkEOzdcD$lZ%t&ADcj=%)X zT&oZS{&uGb!&}JR3(n)rmZyfE zcgOj+n`+SKK>cgdG&)$i_@c{6Zz=gK#5ka0qo+Z@L5&l&c>fF5pzW!<+z@m?_DD#F zKZ}ZlwO&T2gUUY%N17rxqf=yd!lU?fkWUT^VUShV#Srn#v;3U) zfR~tU=-MW=JP)fAag6`sZv7|k?|+chMg>DgbyWaJ-O-oG1>XMlJfWJ|!WGMIWg z6>=WL2P*S>5sIzRJ%2X4TVp$k6P?h9!$b#%Ay@UEqx(5m%9*@n2ARjKn5{#pn%YCv zKb@+C#RE21phtp|2co`{LphRY6N^KE0BuNmOg58oI84Ac_j1TIFz`A)d}Am zDD?A+!4rgvLXp#lY>_fZYj}gpqK8#MmIv$8e@V{0Y-ygb<$e<9BI*U?kvz^@x+6hO zB27c*!qQGgooW{ffebl`W){CWtbZdvEA%NZa|si0MtS6)e#b(EoCH8Fn>$W66|9qB z`=aB1W|@EWe~$J~&e*jA{bR_mUd=|{ZK{|`TvSh2Y{t}o3;WMp2L-D0;6gwVquIDo z>radP$oT(H6e*fwCt#EoN)@*TJ)_wO-z)wv7XGOnGIIqFpPj>>RMC7Bi$sQZsh5Hz znS+(U=09QQPGKFm^j}MN9K_D+DVeI)l=W*a3Tm#B2Xl=@KawA^iS zo0KUrm)J13T(-H+?DF&d{qZ`NKhEPk&g=C$uh;YSJSWA~1-=h@5DEamK1T=pivR%H z9Rlj2dv;si$N%WN9Vq-F{1i~pr@XK`5e~3(wgZ6bOmXgY$nIP$#Nk>v0PJu7pMbi9 zOZ<0NUvRXyyBy;)Gycyr*`6ARtCmzshsINfBT^~$8D})$eoskHN!6PF6S&RxUBR%< z;-9|OKP!7?d3YN}+SO~%6%`c^=x7+1{xz{;Zy_<>yd5O60xek1EhQt-&S?`Z@u3^N zhU7|BSZv4!XJ)MwIni9tVNZ^)6ACtG26v(jiv>SZ1nt3Ur(^i+<-x(GEk?xzCI%PS z95W%XXeMC3^TtdwEBXAjEo}zHee!Un(b|unTMN^_7I{skPp_-+)=x30)+*+R3ZE7< zYGZb0`sdEb;M$x-a)A$Thq0w8=ot)F^D*>>9o?=(TAionQmGH;sF+so<+B0~x7R&B z;%I&*YkJ{6{V8vIAo)*|O}U!|TfpUxHLh@dsAr>DmpA*VnD|!C>P$FYut7;4J{=rY zluK6Y)?tsjI%6v|F$tMlM!YnYkJM@L=EVK8P+)fZT*Cq3j;QEwon>T8Owb*E) zV`HMRmWc=sUQg+ivP#covm;=u9g%+M*# zSIf+U-#v@7Qr`SmN)E^R<_vmi6Es&5dkOfjs>KuWG~n_~C>h@V$#mK`JP zVtP+gd~ia6OL_Ab`D?L*A}6x~OXJY4z?^5qD2^M{SXsL0a<_v6#n}1N@vGr`$z)8&;xF<9^Hxp-B zOX|vU@we*C4S}TvvE-vMZ@8q!yEkD?ZiwazrRtg&RMYczyzic0yzC)jTC23(e6=JE}vsHGy{cDRLE1jmQVg6((d z*7Ie49`a_tDW!6(LH%yHVHt$87G(}%i&>T@q%@trwQ+h~7jJ087Gp79Ukgx8ke%bq zM}W=T@Yiph(8O3nZPkRZe(ohgLQ^0~8YCCmqHOIl9<``H$r*f8JXyUzYdz@^?!k}c z=04{Qc_2dJUr@}f@G%!Y^WH+EJU}0Q4L){%O0#nRuc2EV@=&jU!)EKW z1v3js`X|_;Z2hn?;D0xf(D~>`Q<-;b1Eln~&Dy#A2c&r~otiSEFSVJ}G^98d4Z4%d z@Dj$LjwKor7!UvtaCP}E3jWzQa}oyYXu%oaLTr{eMh81=sst5$25xVY6edP1_wnJA zW72ywTKKP6jE@#92D&0GT^U21ECwHg8dYTiVB!H6P=9OOmX+AlO(&JBAH=`JmVd(j zQiI$&j|41Abb#rZ9@N%xglmDS#3TLFw5dBF-?BI!QWh(Q`VwlJXJuf1JKDle>7A#z z9ksIIa_NR8G!dhFcPKE70?Sd%;!lL$lRyo$W#%!-lcAIs$;a6c9zqT)Fo?cy}+3mj2b zUf_-@f$MX=$MED+bQCuTNKcqIPbyx!00nL;x(D1&m>1P$S=Y^6@GY3k11@`hRh<3+ zf2LR^YDzif?0+L}O!#!-+(ppic2b&GSMy7jED)8l2F7;xs)0g$06u43pX}T;J>2UO zzg}0+s-hKmHuJ%EA+9;Qd|to&3&^zq>}jrgiA3o}w}z<{RBMJMdyJ4NM}yg2)O{y@ z+wLVP_51&}`Awt2`F$BDx%-|~fG}cpT=Aw2(SABroCs?ZTm;qc!x(GrUicSiO1FoV z-}*@HM$84?;+8c!m}Y*NI^?b$4?E1aJR=yP#bG#mU;dr7CK`!i3xMXO(4|@-x~@^G zY=|r0h$E{Go8t=Nd)1%boiAef+p#BP=YLgehdn*T|WG1&3)4PucA)UWU*}D)r?qY=5P|rz~3~Ure^=j^H5nyEn^+YO+ z*hRH+JV8~rjO_P0P|QKfmO6_ZlDD^72b^r}Ts7>~fxRRHAmg$g_;|zqC9y*6 ztD=+CwS4cJ5?F8o^r6k=D*QO;Pi1UyjZniqkS=J{W3&aZdh>PHPEqhM+sFocsfWvR zboHXga|+TO&mX)VVs_B1r)x%2Rlzs@Lbz-(aG= z_1Cqy2M;UBb7dMK-oVm-&|R|-AcZ*4Bz~H~%ZYX7?*_v=s?rx7CTaq-_ceI{!vm4! z*BVHAb9wBUqoc7S9etKPc_}&lzH)zgXV+s{epBCWY;|C5f_lUm=;xa9grS9IdTsqi zhYc5*!P6!z#BQ?~rE>!n3aH&3g%k3pBHq8u=l^))UMvkv%1HxpkRT9nR?1yA90uw% z_g?|^Yr#49!9aaA&u1~|zz7s*$In50TO_?K2hxpnuws2q5aKAf2%_;keyC1PX?CR_I!|_6t*b z8shEmO@A4y{d;}q8h?XbG0cP)g7PyaiZR!3v?|Qc+1h;TvmVw8#Q*{s00e_z4K)JV zan==E<7$Rw!j|0Am1-Y;Oxv2I>Bx%{RS6NcLyNDq@3&cQ-sO?Jl>Fkm1=Lfs8>5zz zd=DeRA)9g}qT0kvgOEFUNyot4-I}hYmPWnV&E~{VZqw4jFiJ=Ks~>b%)S1( ziW9<(hxle@vhl!5troU%*R4ZVZR*6xX5k5Y>@A@lJuTQQx^k6{3Yfctl&d%GlEG@W z?W{6{hplRtA%*d=9lMINtr-(<)Ld8(FQAW6oQzfP=Ok#&KxvT121B3Po1g%%gtki! zZ}mjkvMJwwR+6pa*^n5DKC+Tk^B~@FMK7@=MjeF$!xSC{hY&>sTHjfx_1V|fZh@|X z&LczDHQ6~MU}6{Z9{aGpi>NcYN$X8VQqF#EPi=;Dih@S8A>b?;7=H<*FwRP~gfCnY z*v(lZb(W0vjS8AYBqyJ-pjTRJrh1;Rhcpi!WOkUx!t z{kL6)b1Jl$)K>KUS^|Vdc01sy?OC?IA?$y5q3ZGSkZjD|ITF6zix4|5j$K5bm98Jm zpD2mn_iz}q1Z3Pwe9L<-kybzw{!&dlF4jwpIS4r5Oboex-Aw~xkIPY1Ut)2kRf}Q6 zoDkong3Mw5T75vYmc?quVs_#oQ(H8|6;)8jsMo+#BxMwTWASqWlI6uI>!{3# zh>rIGzFkt8Pn!QE!TLDFi37j#RP{eTkBX4zrz*rUqhCLxJEP%|kis5B<-A#I@`uId z`n(-Rr@)5i4pPWo7d|XJqFsDH#4nn^#D@}J05Z}YZnns%!uD6ncGoG2YQ+vVyjhRp zbKYcR=0UKw8!E=U&xI6gOL$6Gial$=SQINxnMmw^m$jn_GLtkQ3J+cby$tx?1hq|_ zmn{7E5x3W9l$e}+sBve$iS8u=c$U45#P|U3dfAr=v5CUL z(K6_Xn^hn_C*8^a{$P}hHQdyZgmmnSJ>M40^<=tV-e#Y`_~M*mh5cWVs{ zU#wN$fmuDqkv24zn}N&G^n#XN%_= zT#d`n>!K}^%c`?veFd+;{m0hV)Mm~zlw=oxj^pZ;ZjuvEMAJq;-(3$Q$jwb8%C- zt*E>yOMdBhIjri=LSEF8c;AESNUtI%P7Xe#e#H|hJ>)c}BzEHWsRVX_A@KG%H|S7t z_Zz(oJ-_h$=7ZY?KuPPdEm)Euo`Zv8lRN<6hH;Yl%c5N{Jc|fsbS|qW63dkA69_13OHd_bK+KC1A zbK>KI{$0)Kl*^d2bUCWfMe0IS*ii5|Lr;Js-Y{JGS7OHBL=W^kCres$q zIcuZ)|0AZ4Z@)fnm5s!iZf!ikk8lwz0z#k!vGqf3ubPX0vMIo$qUM#DT9}L}3Uo=< z6{-JIw;x>SEHEmVs!{>v)>h^tzmmn`jB)bVwQ;`GpiQ8WPgcMAR(R0fn_FgyB1o!D z_hu1LHWghSEJQ>RP46h75*<#Rnb4}=CK}7%9B0X@DN*CqU(#&vp{&AsMiA#o;@UiJ zJ^ExFs=EO7E*xwDwdEuu#^~~8>sV8BjuW#k(A}`Pn$dqjkU@CY5Y@B@?#JFU3JI3~ zJw>7LeN0*Hrp2jCiPOn$Kt*)59Cok{?XuWt;JJW|JGwxg9mf2rtloIM2UFa4C~KSD zy9*(w3}M4r-sp8kGx^Xs3ook z5c3RT#V*{@r*l=XL!Pb_xj;~ef#N3Ex8i;2k)R&KuYKagZC;)0l9E(O-Y+`k-67Ji z$m}VH6N9T4L9QdEh9a8=$KLEnk*+TJ?`XZyLY@f)uMP8nUNmpw-^DtVT(>gn#D~%kv0_0q&EdBj^M_e`Whphdls2u9ONARx;$EklV`@o-{ej)GoAvZjt=~+M3 z$&p$8lcRi9>5}MKiWUhM&LwjKqwS&6*iASveLLDWdp#@NI2v3AvBl9GnEOKvfXAw+ zpI}#lz6@)`x3Hw&Eo80Qc8GCMjR&+qzn{Bj;cxm9zk6D-)YT3?3sUeoM0uNOuf zI8sCwe!UsToHMk{?~sH$rWPGzGE~`Mx3&+4*HHgSQYsCAUR)_)2DxwEd(>ih<1siG6rvUepT^oot5m;X_dv6-d>xH^WfwTA4+IhYNtGe83G>`>%9ovX`$Wnx2GQ*@`g`ey}-a5 z0L&d2u7mTTFx8>d-wB4QKpe@rGG5v(qqK%4>6&nM*&2qJ== zbwVgu-OEYTLKb_+++(%$^3KuQ_vBluiOM%}mQIIqK6l|~-|i8+SY5t>n!l(a&^-w< zdt6W*3WkA>{|=SS$;T(5cWX`Zwce+_`+Mx>go%@-QcdaQ0sQLNM8w;lBExbbzu{OL z%H$wazeelMEEz8isO;qF0KyshaN@hZ+Ov9_`<@Ph`!6~5#3ar-Wc3AsZmUxaVTpuG z&kASBe5s3VWJ9xL?xS`WZ6lI**z7gbQn~X+PF(rRb*0oL>;uCB-xFbY)E9Z+e%`uL zjmt74K3;LV=tc-E_1wlVt1jc=JwMGGmVB2VOJ8cIOVhU|38}rWAFMvVshi|Gix&T1 zik%kjr%N8mi_{0oKTAhIZ9$)e4iLlRg)Pt3oOimC|JGTZ>=o!H*V!Bxg3)`5c_wVA zL1=QzzOI}(e6N|xP9LB|ircDzm;v$!MSkT7HKl#|r5RX`xU~4=bH`Pit4%S~%>kj? z8}5{$Rk!ZL@>wYOevS5(B8-mlJk4TL#qmB=hO$d>JbB76mlK%d0XCFqQZp0R zB0-Pi!_{`mLg(+4IZ`#S$ww{ueqAfLBA!;In$s&mIeS2)Z`~23&@^*cacdHj%cnqm z^9-||YAt*%2GbPjKRBi!S?nHTDC0jf9aCE+pqI6%Q^sLl^fd%HdEnReu~#?}Ss2lQ zzEgE_K*z_DHcCh8K4Pt<3IwQE{s?Spt6RW8Rc}*>+jp1m1wKL9eZA#>Bz%7?D@S^l z?;{Il5f>XILW<@r9LvE>HVb@}mi;^uPX5~u&WaXo&#^b}x(Li3+|MC@gxFU7v~%?s z7#-X;;l9ZO!{F0;D^aM`W}4F!VrgcKPa5I5*1SMBGE#ok*PNBI{dMozd-J8!>lOUx z7p9!}BjNxoEqy?YW_GGJ-RsS193?t+UjW`Co*7)JpIetE%#9UX)rI(UU#fta);Mlr7-759f;Mn zvF~FWyL86=LbjHT7v{->`6O6uTV^(k#o?X$Xf?+kJF#Yk8;|?nNmF6C$Hzl$<(k-! zo=gS*h)k{b0`C1!FC>m0Pz;RS$yU2?9`7`x00DmmTtyC2q)I$OSA78GZsC{P7mhhr zK>>Yg*!OoWYBLQXx`ux<424Orv&U+O2sYN@GditN>*Pw8c(F}Shblaf)twM2*6&;zD(GKzuoo(;~*_Qg^ypDN)%bKN9D!tQ7rMQ3`$E4bOPS_ahY;y64Fj~@_6hG{g z@(ga6stPI#Y(+O&E(O(Rd&2&Z(tREfLQ!2asqZxIt$Y=D3GOux$rFkR5Z9SFo`Ke# z(UlI}nj^0li!eBfN|JE_jP+03$4Z|6IzNx}ccZU3EPHULNf+YFUZ78K{L6u>#RV+@ zaPc~^J3-ZrnfqEtz(A+6;-=|IxIfnz4|@@h1TNHX(J52O|2RICo?zeZ#vs%k)8Ria09yB? zBA1|K2zLz}0)3R<(o>4*rpk*D#7TM|b+Bzq$^tp;y%+3erv`CBIInz!?N*3@&~W|c zByDk_nj4mC#Ps~F+)?=1#G4L~uy52keGf!{LuQ3=db~1|cw!t9v;&_KuZD7xz z7JyDK1hmX4I91%NvoYu$sNX-mJ(=pY$_!}+3gfVfsobZ_qujrRl@>YjuWg0YrJnek z+{Sa7Zgk+_pprbM<f`9X0#OnuF`ZyM$(mkQ^Tpcz-g)edT>7hQgv1}Vb8+> zZo`*DDq+xsjJ|?(7vDN;7H{AlqTBd5cPc_t=cz^y28z25R^A6WlM%QcZ~hk!qw=+3E%i z)i&EFwXl0UqG>pAf3#=Ll2mN>F83AY2^^h798zKa(FN*gghgbNQh+%~6irkrl)U+k zR8pB|ww!CYNO*HekE|WOA}A1$%FuBm>`k`!tDpx5cnmP+X#i}K&&*Mk*5XNRhEYVQkE z(Lt;lzc4yU`uUeZMONk};4;fJw+fQ}uv&fwF59dF+yIIX6PV9cl7e=zv9gw=2k^S1^Z0L# zs%fq?jWPO1Yb^n0?!9QAjA(g(16F3dRR+X-OsR~A63>;n0s0J2W;BW{=0|d2tTQ#) zO7giAc4nad^=!L*51guR3O{|GI1p* z3=2(bI0QsM^Vu%iZa!dQ0@jES?ld01b zIV__M*NnEaU6FnR!(#lxvoVIi?QW|0*S};PPSM-}LUA;Zm>_*@sNv%u_{M~any-Yh zPa*zE&!1h!W5d+dxVYvK^s+ujxMUG9QdbDb3OE=a=|@-HnsM^WEc<*~WwB-2bNmYkMNb=vgx(uNHY zv{l3;d~1X!V%6wT8ulGuVEb52Cj|9qQLGR`R1Q}kNU4L2hlh8O08NTP{kMTPRJdJK?$Fm0p%Rp6KncktZ zP8X*yOtAmV#T+NQECNd$Kq< ze&`d`w7I$@j)Zv$W>Hu7YhrLG0o2O$Zlhz(fUo23^`)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0@X=GK~zXft(BpY zq(BfvTOyH2EE0*tB9S9Ujzz810}?8a;#!>Srr+Lmz)7ZQbroPR+!1ym%uL6PJ+nDc5pSP*Y zZ?ni}i2H(N&Z!$70^?#t%h2W9)aRG6HSq2_u&#F?ff!Q2{5p099!8*KUqm1`0fcq} zkOJO`1X)iIA_88O1(`$!pzJ`|ViV*(#u_9fWA99ZjgcrwTtIBfQ)3VFl6lxY1dPxH zs-VW$EeVnwT+GAz#6m0r9Rgn*3@yFi+>Gp$3osk?rxQzeb;P2e;j z2FkWtvtFx!jq7S6`^*E*auCqa^c9~4*vXs*R;t+F|gD`s}aJxJ49$Fvf+$($PgH4e=owUuW)oHl@AA)9~j+fJj9WVy43y3fTOhom;_xN5A za+ZS#0a{W%*Dlf;hhPv{#^aPn6&kzd%bNR7*T7M_NS(p81g(oWVfo7c^S^MGgK%>D zxYz}#I}+K+|H4@g!UZb1eYw7-`Pu)%Sq>r!9OSVB7diW1ILkpqwq}bgu=%5P&;A$A zau7kTu^&dAwz49~<1ErWBlPU+q4?Dr&^3ry!6gu95%(&22tZCEr?C^L^C)zz#R#zr z)Owu;FNP(`928pw^}IjzMC=3#N`dQ7=jr&1`~efdil<{ws>0b>MCP&wzx}Bv0Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1d&NZK~z{r#h9U% z<2VpS0|NsMO$`kVO$`kL1DhH)3=CZuIB?+5f&B?f_gA#d_tYIHtM0pWXm2uLRadF&hyPvVZUxw%j)pr7qgkq^$ui)f zKBT&>Q&XsxW8Ji=Ynwa!TAtT+v;PYUztP+0MP@W z55odDYp#HoHEbkVDrSg)EbqndwYV=m04fe!A_Fc}I55o5G{#V)&TUJJg*Qo{53}3Tm$<3%f2HH*W6zKk>=h5^0ZrG(i-3n z&_H^t=-N-e5d-000=jwvi#AiW`rMMJ-UDDvZo1~~Qwun@fI*gu+yNR+HoeLi%UGYO ztRU43`FF9*8L<5BBS4IC?NhF$V55(WRB8dFZ?S|VeH9QWs@E;B?8W$4xUV2U1t1EW ztEr@i0gdT6wCTrD0T#fpyIp8}1u&M@hlG2I5xo#)Kp+4r0kcgB5zE`FT7Qk*9bnim zdUEV9FY)pY29h_6_um>Y;7XMN`OP7i)Gt3yjg z*9DOLDJUE2kE4Cw+e11JwILV-aBatzIeETfMO<=V!>0tKl8oMyg7bkZE6Bd#b>%12 zre!1vPtJb9=cERD?d$ZW`xhwy*LHlF!(3vNG08!$vVvJrLHVH!NCkKTI=!Dp;-)ug zrKQw}4>sb_?B~tMNDFogIxF+kctUD;NnfPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Qkg{K~z{r#h5Fb zqd*WvM@Ax%SR}F~7Kx0E92*%qGIr(2l`Ge-oWHSug{@QcB^6%t_-1Fs{eY&r>Tvr3 z$wU8m8NO59={)q8%aD#|SJkGWXl`=AvMPtvc3&=PHwM_Ajt*CJy|a{cJ;?!!su-%K z8tS0R0;{?iQd8fx&*lA68spy~0UnypU99?cI2;ak-7Ep2_F{C_@jpv|>HIjlc>Ogz z)K)tWF>tpbE)VX4yV7? zBRc(f_G?M)irW(X6t@Og9ghxK+E7=W$%fhi+h)bV02mcvkP5HG&D&lB)DQ#b4jLd@ z0QzDuKqjmb`gs<~*A!#cVg(2+*9*Y@}+p>dy9`?4Xh&xf!Km0^~f#s_#6<79b*S+6yga@g~7RI^#f0 zs`FTE4NwmiW9MyKfH=sTgdz4hxCV%ObSBB#P;t#rsyJ+hEl6v*&CcEF!k+l1}Q7JL2c0!V%e zS{tG$F%%Ra=MgZ16U%YxZ@HA08nh7;0dbO}&q;&hLGB!6-tZI9pD>M9Q-mjHzC;J* ztN_(6aAN60U+%@6)Sy;$aFQIfI5YuXn!=xeo!+0u#7&>1rM+_ONX#B!9AaW)UviO? z+|-~JF%F1h1}`|hNqnOw2SI&3cG?p$@jV*>W4phv-|GgTgzZ7dXOBUbge1=)hKEy)4nBKc0Gr|};y;2e~>ZF6q~Ov67Z)r&FG Sfi3<30000y9TpIwYl8^4)V1w5PUOEa$JM&-68q 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 B^YZ`z literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Data.json b/TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Data.json new file mode 100644 index 000000000..0fd67579c --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Data.json @@ -0,0 +1 @@ +{"Animations":{"391":{"Animation":{"FrameOffset":0,"FrameRate":1,"FrameSize":12,"StateID":1,"Speed":{"Whole":0,"Fraction":0},"Accel":{"Whole":0,"Fraction":0},"FrameStart":0,"FrameEnd":58,"NextAnimation":391,"NextFrame":0,"NumStateChanges":0,"StateChangeOffset":340,"NumAnimCommands":1,"AnimCommand":1592},"AnimationDispatches":{},"Commands":{"1592":{"Command":5,"Params":[41,218]}},"Sound":{"SampleIndices":{"146":[239]},"SoundDetails":{"119":{"Sample":146,"Volume":26213,"Chance":0,"Characteristics":24580,"NumSounds":1}},"SoundMapIndices":{"218":119}},"StateChanges":[]}},"AnimationFrames":[64621,93,64000,65137,65189,63,65530,64043,65394,49152,49271,50153,64593,93,64000,65119,65189,63,65530,64043,65394,49152,49275,50157,64575,93,64000,65108,65189,63,65530,64043,65394,49152,49275,50166,64569,93,64000,65104,65189,63,65530,64043,65394,49152,49272,49153,64575,93,64000,65111,65189,63,65530,64043,65394,49152,49267,49163,64600,93,64000,65130,65189,63,65530,64043,65394,49152,49260,49169,64639,93,64000,65160,65189,63,65530,64043,65394,49152,49251,49170,64688,93,64000,65193,65189,63,65530,64043,65394,49152,49241,49170,64748,93,64000,65225,65189,63,65530,64043,65394,49152,49230,49169,64815,93,64000,65253,65189,63,65530,64043,65394,49152,49219,49168,64891,93,64000,65276,65189,63,65530,64043,65394,49152,49207,49166,64973,93,64000,65292,65189,63,65530,64043,65394,49152,49195,49164,65057,93,64000,65300,65189,63,65530,64043,65394,49152,49184,49163,65141,93,64000,65314,65189,63,65530,64043,65394,49152,49172,49161,65220,146,64000,65324,65189,63,65530,64043,65394,49152,49161,49160,65290,194,64000,65329,65189,63,65530,64043,65394,49152,49152,49160,65355,238,64000,65328,65189,63,65530,64043,65394,49152,50166,49161,65399,302,64000,65324,65189,63,65530,64043,65394,49152,50157,49162,65431,365,64000,65317,65189,63,65530,64043,65394,49152,50147,49164,65431,425,64000,65306,65189,63,65530,64043,65394,49152,50138,49166,65431,483,64000,65292,65189,63,65530,64043,65394,49152,50128,49168,65431,538,64000,65276,65189,63,65530,64043,65394,49152,50119,49171,65431,589,64000,65263,65189,63,65530,64043,65394,49152,50110,49173,65431,639,64000,65250,65189,63,65530,64043,65394,49152,50101,49175,65431,685,64000,65236,65189,63,65530,64043,65394,49152,50093,49177,65431,729,64000,65220,65189,63,65530,64043,65394,49152,50085,49179,65431,770,64000,65204,65189,63,65530,64043,65394,49152,50078,49180,65431,807,64000,65187,65189,63,65530,64043,65394,49152,50071,49181,65431,843,64000,65169,65189,63,65530,64043,65394,49152,50065,49181,65431,874,64000,65150,65189,63,65530,64043,65394,49152,50059,49180,65431,901,64000,65138,65189,63,65530,64043,65394,49152,50056,49175,65431,916,64000,65131,65189,63,65530,64043,65394,49152,50057,49165,65431,918,64000,65134,65189,63,65530,64043,65394,49152,50062,49153,65431,907,64000,65143,65189,63,65530,64043,65394,49152,50068,50166,65431,881,64000,65162,65189,63,65530,64043,65394,49152,50075,50160,65431,843,64000,65188,65189,63,65530,64043,65394,49152,50084,50158,65431,796,64000,65215,65189,63,65530,64043,65394,49152,50093,50158,65431,741,64000,65240,65189,63,65530,64043,65394,49152,50102,50158,65431,677,64000,65264,65189,63,65530,64043,65394,49152,50113,50159,65431,607,64000,65282,65189,63,65530,64043,65394,49152,50123,50161,65431,532,64000,65294,65189,63,65530,64043,65394,49152,50134,50163,65431,456,64000,65301,65189,63,65530,64043,65394,49152,50145,50165,65430,381,64000,65314,65189,63,65530,64043,65394,49152,50155,50166,65379,307,64000,65324,65189,63,65530,64043,65394,49152,50165,50167,65335,242,64000,65328,65189,63,65530,64043,65394,49152,50174,50167,65293,180,64000,65329,65189,63,65530,64043,65394,49152,49159,50167,65234,134,64000,65326,65189,63,65530,64043,65394,49152,49168,50166,65174,93,64000,65319,65189,63,65530,64043,65394,49152,49177,50165,65115,93,64000,65310,65189,63,65530,64043,65394,49152,49186,50163,65058,93,64000,65297,65189,63,65530,64043,65394,49152,49195,50161,65004,93,64000,65282,65189,63,65530,64043,65394,49152,49204,50160,64951,93,64000,65269,65189,63,65530,64043,65394,49152,49212,50158,64901,93,64000,65258,65189,63,65530,64043,65394,49152,49221,50156,64853,93,64000,65245,65189,63,65530,64043,65394,49152,49229,50155,64807,93,64000,65229,65189,63,65530,64043,65394,49152,49237,50153,64764,93,64000,65212,65189,63,65530,64043,65394,49152,49245,50152,64724,93,64000,65194,65189,63,65530,64043,65394,49152,49252,50152,64687,93,64000,65176,65189,63,65530,64043,65394,49152,49259,50151,64652,93,64000,65156,65189,63,65530,64043,65394,49152,49265,50152],"CinematicFrames":[],"Colours":{},"HardcodedSound":null,"Meshes":[{"Pointer":77628,"Centre":{"X":-3,"Y":-43,"Z":-25},"CollRadius":119,"NumVertices":10,"Vertices":[{"X":-99,"Y":-43,"Z":-35},{"X":99,"Y":-43,"Z":-35},{"X":49,"Y":43,"Z":-35},{"X":-49,"Y":43,"Z":-35},{"X":-99,"Y":-43,"Z":35},{"X":99,"Y":-43,"Z":35},{"X":49,"Y":43,"Z":35},{"X":-49,"Y":43,"Z":35},{"X":0,"Y":-43,"Z":35},{"X":0,"Y":-43,"Z":-35}],"NumNormals":10,"Normals":[{"X":-9982,"Y":5763,"Z":-11526},{"X":9982,"Y":5763,"Z":-11526},{"X":7058,"Y":12225,"Z":-8150},{"X":-5335,"Y":9241,"Z":-12322},{"X":-9982,"Y":5763,"Z":11526},{"X":9982,"Y":5763,"Z":11526},{"X":7058,"Y":12225,"Z":8150},{"X":-5335,"Y":9241,"Z":12322},{"X":0,"Y":0,"Z":16300},{"X":0,"Y":0,"Z":-16300}],"Lights":null,"NumTexturedRectangles":5,"TexturedRectangles":[{"Vertices":[1,5,6,2],"Texture":1200},{"Vertices":[2,6,7,3],"Texture":1200},{"Vertices":[3,7,4,0],"Texture":1200},{"Vertices":[2,3,9,1],"Texture":1200},{"Vertices":[8,7,6,5],"Texture":1200}],"NumTexturedTriangles":2,"TexturedTriangles":[{"Vertices":[9,3,0],"Texture":1201},{"Vertices":[8,4,7],"Texture":1201}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":77836,"Centre":{"X":-1,"Y":311,"Z":-7},"CollRadius":312,"NumVertices":8,"Vertices":[{"X":-10,"Y":622,"Z":-7},{"X":8,"Y":622,"Z":-7},{"X":8,"Y":1,"Z":-7},{"X":-10,"Y":1,"Z":-7},{"X":-10,"Y":622,"Z":7},{"X":8,"Y":622,"Z":7},{"X":8,"Y":1,"Z":7},{"X":-10,"Y":1,"Z":7}],"NumNormals":8,"Normals":[{"X":-9411,"Y":9411,"Z":-9411},{"X":9411,"Y":9411,"Z":-9411},{"X":11526,"Y":0,"Z":-11526},{"X":-11526,"Y":0,"Z":-11526},{"X":-9411,"Y":9411,"Z":9411},{"X":9411,"Y":9411,"Z":9411},{"X":11526,"Y":0,"Z":11526},{"X":-11526,"Y":0,"Z":11526}],"Lights":null,"NumTexturedRectangles":5,"TexturedRectangles":[{"Vertices":[3,2,1,0],"Texture":1202},{"Vertices":[0,1,5,4],"Texture":1203},{"Vertices":[2,6,5,1],"Texture":1202},{"Vertices":[7,3,0,4],"Texture":1202},{"Vertices":[4,5,6,7],"Texture":1202}],"NumTexturedTriangles":0,"TexturedTriangles":[],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]},{"Pointer":78004,"Centre":{"X":-3,"Y":320,"Z":-6},"CollRadius":335,"NumVertices":14,"Vertices":[{"X":-146,"Y":571,"Z":-158},{"X":64,"Y":571,"Z":-205},{"X":209,"Y":571,"Z":-47},{"X":145,"Y":571,"Z":158},{"X":-64,"Y":571,"Z":205},{"X":-210,"Y":571,"Z":47},{"X":-146,"Y":160,"Z":-158},{"X":64,"Y":160,"Z":-205},{"X":209,"Y":160,"Z":-47},{"X":145,"Y":160,"Z":158},{"X":-64,"Y":160,"Z":205},{"X":-210,"Y":160,"Z":47},{"X":-2,"Y":-10,"Z":0},{"X":0,"Y":623,"Z":0}],"NumNormals":14,"Normals":[{"X":-8313,"Y":10741,"Z":-9012},{"X":3647,"Y":10741,"Z":-11705},{"X":11961,"Y":10741,"Z":-2694},{"X":8313,"Y":10741,"Z":9012},{"X":-3647,"Y":10741,"Z":11705},{"X":-11961,"Y":10741,"Z":2694},{"X":-9857,"Y":-7384,"Z":-10678},{"X":4314,"Y":-7407,"Z":-13864},{"X":14156,"Y":-7424,"Z":-3190},{"X":9839,"Y":-7416,"Z":10672},{"X":-4328,"Y":-7393,"Z":13867},{"X":-14180,"Y":-7377,"Z":3192},{"X":-28,"Y":-16300,"Z":0},{"X":0,"Y":16300,"Z":0}],"Lights":null,"NumTexturedRectangles":6,"TexturedRectangles":[{"Vertices":[6,7,1,0],"Texture":1204},{"Vertices":[7,8,2,1],"Texture":1204},{"Vertices":[8,9,3,2],"Texture":1204},{"Vertices":[9,10,4,3],"Texture":1204},{"Vertices":[10,11,5,4],"Texture":1204},{"Vertices":[11,6,0,5],"Texture":1204}],"NumTexturedTriangles":12,"TexturedTriangles":[{"Vertices":[13,0,1],"Texture":1205},{"Vertices":[13,1,2],"Texture":1205},{"Vertices":[13,2,3],"Texture":1205},{"Vertices":[13,3,4],"Texture":1205},{"Vertices":[13,4,5],"Texture":1205},{"Vertices":[13,5,0],"Texture":1205},{"Vertices":[12,7,6],"Texture":1205},{"Vertices":[12,8,7],"Texture":1205},{"Vertices":[12,9,8],"Texture":1205},{"Vertices":[12,10,9],"Texture":1205},{"Vertices":[12,11,10],"Texture":1205},{"Vertices":[12,6,11],"Texture":1205}],"NumColouredRectangles":0,"ColouredRectangles":[],"NumColouredTriangles":0,"ColouredTriangles":[]}],"MeshTrees":[{"Flags":0,"OffsetX":0,"OffsetY":42,"OffsetZ":0},{"Flags":0,"OffsetX":0,"OffsetY":622,"OffsetZ":0},{"Flags":2,"OffsetX":-835,"OffsetY":-7592,"OffsetZ":1001}],"Model":{"ID":58,"NumMeshes":3,"StartingMesh":309,"MeshTree":1164,"FrameOffset":373500,"Animation":391},"Dependencies":[],"ObjectTextures":{"0":[{"Texture":{"Attribute":0,"AtlasAndFlag":6,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":239},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":239},"YCoordinate":{"Whole":255,"Fraction":63}},{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":255,"Fraction":63}}]},"IsTriangle":false,"Index":1204,"Classification":"3b8ffd3f07a14f328555809df926a7a0"},{"Texture":{"Attribute":0,"AtlasAndFlag":6,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":239},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":255,"Fraction":31}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":1205,"Classification":"3b8ffd3f07a14f328555809df926a7a0"},{"Texture":{"Attribute":0,"AtlasAndFlag":6,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":223},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":255,"Fraction":23}},{"XCoordinate":{"Whole":0,"Fraction":0},"YCoordinate":{"Whole":0,"Fraction":0}}]},"IsTriangle":true,"Index":1201,"Classification":"3b8ffd3f07a14f328555809df926a7a0"},{"Texture":{"Attribute":0,"AtlasAndFlag":6,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":223},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":223},"YCoordinate":{"Whole":255,"Fraction":23}},{"XCoordinate":{"Whole":1,"Fraction":200},"YCoordinate":{"Whole":255,"Fraction":23}}]},"IsTriangle":false,"Index":1200,"Classification":"3b8ffd3f07a14f328555809df926a7a0"}],"1":[{"Texture":{"Attribute":1,"AtlasAndFlag":10,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":136},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":167},"YCoordinate":{"Whole":1,"Fraction":0}},{"XCoordinate":{"Whole":255,"Fraction":167},"YCoordinate":{"Whole":255,"Fraction":23}},{"XCoordinate":{"Whole":1,"Fraction":136},"YCoordinate":{"Whole":255,"Fraction":23}}]},"IsTriangle":false,"Index":1203,"Classification":"3b8ffd3f07a14f328555809df926a7a0"}],"2":[{"Texture":{"Attribute":0,"AtlasAndFlag":11,"Vertices":[{"XCoordinate":{"Whole":1,"Fraction":152},"YCoordinate":{"Whole":1,"Fraction":72}},{"XCoordinate":{"Whole":255,"Fraction":159},"YCoordinate":{"Whole":1,"Fraction":72}},{"XCoordinate":{"Whole":255,"Fraction":159},"YCoordinate":{"Whole":255,"Fraction":135}},{"XCoordinate":{"Whole":1,"Fraction":152},"YCoordinate":{"Whole":255,"Fraction":135}}]},"IsTriangle":false,"Index":1202,"Classification":"3b8ffd3f07a14f328555809df926a7a0"}]},"SpriteTextures":{},"SpriteSequences":{},"TextureSegments":["0, 0, 40, 64","40, 0, 32, 24","72, 0, 8, 64"]} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Segments.png b/TRRandomizerCore/Resources/TR2/Models/SandbagOrBallsack/Segments.png new file mode 100644 index 0000000000000000000000000000000000000000..365278bd1c54a5e16c8ab16d62fcd5b466a27d2f GIT binary patch literal 3113 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
  • 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 literal 0 HcmV?d00001 diff --git a/TRRandomizerCore/Resources/TR2/Textures/Deduplication/WALL.TR2-TextureRemap.json b/TRRandomizerCore/Resources/TR2/Textures/Deduplication/WALL.TR2-TextureRemap.json index 5013a2afd..925b25e1d 100644 --- a/TRRandomizerCore/Resources/TR2/Textures/Deduplication/WALL.TR2-TextureRemap.json +++ b/TRRandomizerCore/Resources/TR2/Textures/Deduplication/WALL.TR2-TextureRemap.json @@ -1675,6 +1675,47 @@ "TileIndex": 7, "Bounds": "88, 208, 16, 16" }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "0, 40, 24, 32" + }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "24, 48, 24, 32" + }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "48, 48, 24, 32" + }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "72, 56, 24, 32" + }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "96, 64, 24, 32" + }, + { "Entities": [ 0, @@ -1714,6 +1755,14 @@ ], "TileIndex": 6, "Bounds": "96, 64, 24, 32" + }, + { + "Entities": [ + 0, + 3 + ], + "TileIndex": 6, + "Bounds": "208, 32, 24, 32" } ] } \ No newline at end of file From 5e8561a7502f3ffaf63ade1a90a320de67610aac Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:44:36 +0100 Subject: [PATCH 05/11] #272 Excludable Enemies - Adds support to allow choosing which enemies are available in the randomization pool. This does work mainly on "best effort", but exclusion priority can be defined so that enemies that the randomizer has a chance to focus on excluding any that are particularly undesirable. An option is in place to show a warning message if an excluded enemy has ended up in the game. - Ensures skidoo drivers are limited if they are heavily present in any level. - Rotates an enemy in Floaters if the type is flamethrower for a better chance of killing him. --- Deps/TRGE.Core.dll | Bin 130560 -> 130560 bytes TRLevelReader/Helpers/TR2EntityUtilities.cs | 14 + TRLevelReader/Helpers/TR3EntityUtilities.cs | 14 + .../Editors/RandomizerSettings.cs | 18 ++ TRRandomizerCore/Editors/TR2RandoEditor.cs | 16 +- TRRandomizerCore/Editors/TR3RandoEditor.cs | 9 +- .../Helpers/TRRandomizationCategory.cs | 3 +- .../Helpers/TRRandomizationEventArgs.cs | 2 + TRRandomizerCore/Levels/TR2CombinedLevel.cs | 21 ++ .../Processors/AbstractLevelProcessor.cs | 8 + .../Randomizers/TR2/TR2EnemyRandomizer.cs | 255 +++++++++++++--- .../Randomizers/TR3/TR3EnemyRandomizer.cs | 193 ++++++++---- .../Environment/FLOATING.TR2-Environment.json | 22 ++ .../enemy_restrictions_special.json | 4 +- .../TR2/Restrictions/excludable_enemies.json | 44 +++ .../TR3/Restrictions/excludable_enemies.json | 41 +++ TRRandomizerCore/TRRandomizerController.cs | 28 ++ .../Utilities/LocationGenerator.cs | 2 +- .../Utilities/TR2EnemyUtilities.cs | 13 +- .../Model/BoolItemIDControlClass.cs | 19 ++ TRRandomizerView/Model/ControllerOptions.cs | 61 ++++ TRRandomizerView/TRRandomizerView.csproj | 8 + TRRandomizerView/Windows/AdvancedWindow.xaml | 65 ++++- .../Windows/AdvancedWindow.xaml.cs | 10 + TRRandomizerView/Windows/EnemyWindow.xaml | 173 +++++++++++ TRRandomizerView/Windows/EnemyWindow.xaml.cs | 274 ++++++++++++++++++ .../Windows/RandomizeProgressWindow.xaml.cs | 17 ++ 27 files changed, 1204 insertions(+), 130 deletions(-) create mode 100644 TRRandomizerCore/Resources/TR2/Restrictions/excludable_enemies.json create mode 100644 TRRandomizerCore/Resources/TR3/Restrictions/excludable_enemies.json create mode 100644 TRRandomizerView/Model/BoolItemIDControlClass.cs create mode 100644 TRRandomizerView/Windows/EnemyWindow.xaml create mode 100644 TRRandomizerView/Windows/EnemyWindow.xaml.cs diff --git a/Deps/TRGE.Core.dll b/Deps/TRGE.Core.dll index 781b77d99a6ef75a963ac6f27d7fd66ac1658c2d..c4f33fe8833746797687bdc3bb98da42db4361ed 100644 GIT binary patch delta 9511 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 delta 9463 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 c{3B^YWy+znulN GetEntityFamily(TR2Entities entity) return new List { entity }; } + public static List RemoveAliases(IEnumerable entities) + { + List ents = new List(); + foreach (TR2Entities ent in entities) + { + TR2Entities normalisedEnt = TranslateEntityAlias(ent); + if (!ents.Contains(normalisedEnt)) + { + ents.Add(normalisedEnt); + } + } + return ents; + } + public static List GetLaraTypes() { return new List diff --git a/TRLevelReader/Helpers/TR3EntityUtilities.cs b/TRLevelReader/Helpers/TR3EntityUtilities.cs index a97907d66..058155125 100644 --- a/TRLevelReader/Helpers/TR3EntityUtilities.cs +++ b/TRLevelReader/Helpers/TR3EntityUtilities.cs @@ -95,6 +95,20 @@ public static TR3Entities GetAliasForLevel(string lvl, TR3Entities entity) return entity; } + public static List RemoveAliases(IEnumerable entities) + { + List ents = new List(); + foreach (TR3Entities ent in entities) + { + TR3Entities normalisedEnt = TranslateEntityAlias(ent); + if (!ents.Contains(normalisedEnt)) + { + ents.Add(normalisedEnt); + } + } + return ents; + } + public static List GetLaraTypes() { return new List diff --git a/TRRandomizerCore/Editors/RandomizerSettings.cs b/TRRandomizerCore/Editors/RandomizerSettings.cs index 3210ae611..71e878c8f 100644 --- a/TRRandomizerCore/Editors/RandomizerSettings.cs +++ b/TRRandomizerCore/Editors/RandomizerSettings.cs @@ -3,6 +3,8 @@ using TRRandomizerCore.Helpers; using TRGE.Core; using System.Drawing; +using System.Collections.Generic; +using System.Linq; namespace TRRandomizerCore.Editors { @@ -54,6 +56,12 @@ public class RandomizerSettings public bool DocileBirdMonsters { get; set; } public RandoDifficulty RandoEnemyDifficulty { get; set; } public bool MaximiseDragonAppearance { get; set; } + public bool UseEnemyExclusions { get; set; } + public List ExcludedEnemies { get; set; } + public Dictionary ExcludableEnemies { get; set; } + public bool ShowExclusionWarnings { get; set; } + public List IncludedEnemies => ExcludableEnemies.Keys.Except(ExcludedEnemies).ToList(); + public bool OneEnemyMode => IncludedEnemies.Count == 1; public bool GlitchedSecrets { get; set; } public bool UseRewardRoomCameras { get; set; } public bool PersistOutfits { get; set; } @@ -124,6 +132,13 @@ public void ApplyConfig(Config config) DocileBirdMonsters = config.GetBool(nameof(DocileBirdMonsters)); RandoEnemyDifficulty = (RandoDifficulty)config.GetEnum(nameof(RandoEnemyDifficulty), typeof(RandoDifficulty), RandoDifficulty.Default); MaximiseDragonAppearance = config.GetBool(nameof(MaximiseDragonAppearance)); + UseEnemyExclusions = config.GetBool(nameof(UseEnemyExclusions)); + ShowExclusionWarnings = config.GetBool(nameof(ShowExclusionWarnings)); + ExcludedEnemies = config.GetString(nameof(ExcludedEnemies)) + .Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries) + .Select(s => short.Parse(s)) + .Where(s => ExcludableEnemies.ContainsKey(s)) + .ToList(); RandomizeTextures = config.GetBool(nameof(RandomizeTextures)); TextureSeed = config.GetInt(nameof(TextureSeed), defaultSeed); @@ -219,6 +234,9 @@ public void StoreConfig(Config config) config[nameof(DocileBirdMonsters)] = DocileBirdMonsters; config[nameof(RandoEnemyDifficulty)] = RandoEnemyDifficulty; config[nameof(MaximiseDragonAppearance)] = MaximiseDragonAppearance; + config[nameof(ExcludedEnemies)] = string.Join(",", ExcludedEnemies); + config[nameof(UseEnemyExclusions)] = UseEnemyExclusions; + config[nameof(ShowExclusionWarnings)] = ShowExclusionWarnings; config[nameof(RandomizeTextures)] = RandomizeTextures; config[nameof(TextureSeed)] = TextureSeed; diff --git a/TRRandomizerCore/Editors/TR2RandoEditor.cs b/TRRandomizerCore/Editors/TR2RandoEditor.cs index 811af026b..b2831009a 100644 --- a/TRRandomizerCore/Editors/TR2RandoEditor.cs +++ b/TRRandomizerCore/Editors/TR2RandoEditor.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.IO; using System.Linq; using TRGE.Coord; using TRGE.Core; +using TRLevelReader.Helpers; using TRRandomizerCore.Processors; using TRRandomizerCore.Randomizers; using TRRandomizerCore.Textures; @@ -17,7 +20,10 @@ public TR2RandoEditor(TRDirectoryIOArgs args, TREdition edition) protected override void ApplyConfig(Config config) { - Settings = new RandomizerSettings(); + Settings = new RandomizerSettings + { + ExcludableEnemies = JsonConvert.DeserializeObject>(File.ReadAllText(@"Resources\TR2\Restrictions\excludable_enemies.json")) + }; Settings.ApplyConfig(config); } @@ -48,6 +54,12 @@ protected override void SaveImpl(AbstractTRScriptEditor scriptEditor, TRSaveMoni TR23ScriptEditor tr23ScriptEditor = scriptEditor as TR23ScriptEditor; string wipDirectory = _io.WIPOutputDirectory.FullName; + if (Settings.DevelopmentMode) + { + (tr23ScriptEditor.Script as TR23Script).LevelSelectEnabled = true; + scriptEditor.SaveScript(); + } + // Texture monitoring is needed between enemy and texture randomization // to track where imported enemies are placed. using (TR2TextureMonitorBroker textureMonitor = new TR2TextureMonitorBroker()) diff --git a/TRRandomizerCore/Editors/TR3RandoEditor.cs b/TRRandomizerCore/Editors/TR3RandoEditor.cs index 41a4a1ace..e8f94fa99 100644 --- a/TRRandomizerCore/Editors/TR3RandoEditor.cs +++ b/TRRandomizerCore/Editors/TR3RandoEditor.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using System.Drawing; +using Newtonsoft.Json; +using System.Collections.Generic; using System.IO; using System.Linq; using TRGE.Coord; @@ -20,7 +20,10 @@ public TR3RandoEditor(TRDirectoryIOArgs args, TREdition edition) protected override void ApplyConfig(Config config) { - Settings = new RandomizerSettings(); + Settings = new RandomizerSettings + { + ExcludableEnemies = JsonConvert.DeserializeObject>(File.ReadAllText(@"Resources\TR3\Restrictions\excludable_enemies.json")) + }; Settings.ApplyConfig(config); } diff --git a/TRRandomizerCore/Helpers/TRRandomizationCategory.cs b/TRRandomizerCore/Helpers/TRRandomizationCategory.cs index a911be285..212ca9c4e 100644 --- a/TRRandomizerCore/Helpers/TRRandomizationCategory.cs +++ b/TRRandomizerCore/Helpers/TRRandomizationCategory.cs @@ -7,6 +7,7 @@ public enum TRRandomizationCategory PreRandomize, Randomize, Commit, - Cancel + Cancel, + Warning } } \ No newline at end of file diff --git a/TRRandomizerCore/Helpers/TRRandomizationEventArgs.cs b/TRRandomizerCore/Helpers/TRRandomizationEventArgs.cs index e21a0bbed..3883acabf 100644 --- a/TRRandomizerCore/Helpers/TRRandomizationEventArgs.cs +++ b/TRRandomizerCore/Helpers/TRRandomizationEventArgs.cs @@ -43,6 +43,8 @@ private static TRRandomizationCategory ConvertCategory(TRSaveCategory category) return TRRandomizationCategory.Cancel; // The operation has been cancelled externally case TRSaveCategory.Commit: return TRRandomizationCategory.Commit; // TRGE is commiting the changes to the original data directory + case TRSaveCategory.Warning: + return TRRandomizationCategory.Warning; // A processor wants to send a warning message default: return TRRandomizationCategory.None; } diff --git a/TRRandomizerCore/Levels/TR2CombinedLevel.cs b/TRRandomizerCore/Levels/TR2CombinedLevel.cs index 9377779b9..55c8e6b70 100644 --- a/TRRandomizerCore/Levels/TR2CombinedLevel.cs +++ b/TRRandomizerCore/Levels/TR2CombinedLevel.cs @@ -137,5 +137,26 @@ public int GetMaximumEntityLimit() return limit; } + + public int GetActualEntityCount() + { + int count = 0; + foreach (TR2Entity entity in Data.Entities) + { + switch ((TR2Entities)entity.TypeID) + { + case TR2Entities.MercSnowmobDriver: + count += 2; + break; + case TR2Entities.MarcoBartoli: + count += 7; + break; + default: + count++; + break; + } + } + return count; + } } } \ No newline at end of file diff --git a/TRRandomizerCore/Processors/AbstractLevelProcessor.cs b/TRRandomizerCore/Processors/AbstractLevelProcessor.cs index 5686a70b2..76eb9fbf6 100644 --- a/TRRandomizerCore/Processors/AbstractLevelProcessor.cs +++ b/TRRandomizerCore/Processors/AbstractLevelProcessor.cs @@ -81,6 +81,14 @@ internal void SetMessage(string text) } } + internal void SetWarning(string text) + { + lock (_monitorLock) + { + SaveMonitor.FireSaveStateChanged(category: TRSaveCategory.Warning, customDescription: text); + } + } + public void HandleException(Exception e) { lock (_monitorLock) diff --git a/TRRandomizerCore/Randomizers/TR2/TR2EnemyRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/TR2EnemyRandomizer.cs index dd8086e31..75b1942ab 100644 --- a/TRRandomizerCore/Randomizers/TR2/TR2EnemyRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/TR2EnemyRandomizer.cs @@ -1,6 +1,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Numerics; +using TRFDControl; +using TRFDControl.FDEntryTypes; +using TRFDControl.Utilities; using TRGE.Core; using TRLevelReader.Helpers; using TRLevelReader.Model; @@ -18,6 +23,8 @@ namespace TRRandomizerCore.Randomizers public class TR2EnemyRandomizer : BaseTR2Randomizer { private Dictionary> _gameEnemyTracker; + private List _excludedEnemies; + private ISet _resultantEnemies; internal int MaxPackingAttempts { get; set; } internal TR2TextureMonitorBroker TextureMonitor { get; set; } @@ -95,6 +102,12 @@ private void RandomizeEnemiesCrossLevel() // Track enemies whose counts across the game are restricted _gameEnemyTracker = TR2EnemyUtilities.PrepareEnemyGameTracker(Settings.DocileBirdMonsters, Settings.RandoEnemyDifficulty); + // #272 Selective enemy pool - convert the shorts in the settings to actual entity types + _excludedEnemies = Settings.UseEnemyExclusions ? + Settings.ExcludedEnemies.Select(s => (TR2Entities)s).ToList() : + new List(); + _resultantEnemies = new HashSet(); + SetMessage("Randomizing enemies - importing models"); foreach (EnemyProcessor processor in processors) { @@ -119,6 +132,28 @@ private void RandomizeEnemiesCrossLevel() { _processingException.Throw(); } + + // If any exclusions failed to be avoided, send a message + if (Settings.ShowExclusionWarnings) + { + VerifyExclusionStatus(); + } + } + + private void VerifyExclusionStatus() + { + List failedExclusions = _resultantEnemies.ToList().FindAll(_excludedEnemies.Contains); + if (failedExclusions.Count > 0) + { + // A little formatting + List failureNames = new List(); + foreach (TR2Entities entity in failedExclusions) + { + failureNames.Add(Settings.ExcludableEnemies[(short)entity]); + } + failureNames.Sort(); + SetWarning(string.Format("The following enemies could not be excluded entirely from the randomization pool.{0}{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, failureNames))); + } } private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, int reduceEnemyCountBy = 0) @@ -139,6 +174,8 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, List chickenGuisers = TR2EnemyUtilities.GetEnemyGuisers(TR2Entities.BirdMonster); TR2Entities chickenGuiser = TR2Entities.BirdMonster; + RandoDifficulty difficulty = GetImpliedDifficulty(); + // #148 For HSH, we lock the enemies that are required for the kill counter to work outside // the gate, which means the game still has the correct target kill count, while allowing // us to randomize the ones inside the gate (except the final shotgun goon). @@ -172,30 +209,18 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, // Do we need at least one enemy that can drop? bool droppableEnemyRequired = TR2EnemyUtilities.IsDroppableEnemyRequired(level); - // Let's try to populate the list. Start by adding one water enemy - // and one droppable enemy if they are needed. + // Let's try to populate the list. Start by adding one water enemy and one droppable + // enemy if they are needed. If we want to exclude, try to select based on user priority. if (waterEnemyRequired) { List waterEnemies = TR2EntityUtilities.KillableWaterCreatures(); - TR2Entities entity; - do - { - entity = waterEnemies[_generator.Next(0, waterEnemies.Count)]; - } - while (!TR2EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)); - newEntities.Add(entity); + newEntities.Add(SelectRequiredEnemy(waterEnemies, level, difficulty)); } if (droppableEnemyRequired) { List droppableEnemies = TR2EntityUtilities.GetCrossLevelDroppableEnemies(!Settings.ProtectMonks); - TR2Entities entity; - do - { - entity = droppableEnemies[_generator.Next(0, droppableEnemies.Count)]; - } - while (!TR2EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)); - newEntities.Add(entity); + newEntities.Add(SelectRequiredEnemy(droppableEnemies, level, difficulty)); } // Are there any other types we need to retain? @@ -207,16 +232,34 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, } } - // Get all other candidate enemies and fill the list - List allEnemies = TR2EntityUtilities.GetCandidateCrossLevelEnemies(); + // Get all other candidate supported enemies + List allEnemies = TR2EntityUtilities.GetCandidateCrossLevelEnemies().FindAll(e => TR2EnemyUtilities.IsEnemySupported(level.Name, e, difficulty)); + if (Settings.OneEnemyMode || Settings.IncludedEnemies.Count < newEntities.Capacity) + { + // Marco isn't excludable in his own right because supporting a dragon-only game is impossible + allEnemies.Remove(TR2Entities.MarcoBartoli); + } + + // Remove all exclusions from the pool, and adjust the target capacity + allEnemies.RemoveAll(e => _excludedEnemies.Contains(e)); - while (newEntities.Count < newEntities.Capacity) + IEnumerable ex = allEnemies.Where(e => !newEntities.Any(TR2EntityUtilities.GetEntityFamily(e).Contains)); + List unalisedEntities = TR2EntityUtilities.RemoveAliases(ex); + while (unalisedEntities.Count < newEntities.Capacity - newEntities.Count) + { + --newEntities.Capacity; + } + + // Fill the list from the remaining candidates. Keep track of ones tested to avoid + // looping infinitely if it's not possible to fill to capacity + ISet testedEntities = new HashSet(); + while (newEntities.Count < newEntities.Capacity && testedEntities.Count < allEnemies.Count) { TR2Entities entity; // Try to enforce Marco's appearance, but only if this isn't the final packing attempt if (Settings.MaximiseDragonAppearance && !newEntities.Contains(TR2Entities.MarcoBartoli) - && TR2EnemyUtilities.IsEnemySupported(level.Name, TR2Entities.MarcoBartoli, Settings.RandoEnemyDifficulty) + && TR2EnemyUtilities.IsEnemySupported(level.Name, TR2Entities.MarcoBartoli, difficulty) && reduceEnemyCountBy == 0) { entity = TR2Entities.MarcoBartoli; @@ -226,10 +269,12 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, entity = allEnemies[_generator.Next(0, allEnemies.Count)]; } + testedEntities.Add(entity); + int adjustmentCount = TR2EnemyUtilities.GetTargetEnemyAdjustmentCount(level.Name, entity); - if (adjustmentCount != 0) + if (!Settings.OneEnemyMode && adjustmentCount != 0) { - while (newEntities.Count >= newEntities.Capacity + adjustmentCount) + while (newEntities.Count > 0 && newEntities.Count >= newEntities.Capacity + adjustmentCount) { newEntities.RemoveAt(newEntities.Count - 1); } @@ -238,33 +283,23 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, // Check if the use of this enemy triggers an overwrite of the pool, for example // the dragon in HSH. Null means nothing special has been defined. - List> restrictedCombinations = TR2EnemyUtilities.GetPermittedCombinations(level.Name, entity, Settings.RandoEnemyDifficulty); + List> restrictedCombinations = TR2EnemyUtilities.GetPermittedCombinations(level.Name, entity, difficulty); if (restrictedCombinations != null) { do { - // Pick a combination, ensuring we honour docile bird monsters if present + // Pick a combination, ensuring we honour docile bird monsters if present, + // and try to select a group that doesn't contain an excluded enemy. newEntities.Clear(); newEntities.AddRange(restrictedCombinations[_generator.Next(0, restrictedCombinations.Count)]); } - while (Settings.DocileBirdMonsters && newEntities.Contains(TR2Entities.BirdMonster) && chickenGuisers.All(g => newEntities.Contains(g))); + while (Settings.DocileBirdMonsters && newEntities.Contains(TR2Entities.BirdMonster) && chickenGuisers.All(g => newEntities.Contains(g)) + || (newEntities.Any(_excludedEnemies.Contains) && restrictedCombinations.Any(c => !c.Any(_excludedEnemies.Contains)))); break; } - // Make sure this isn't known to be unsupported in the level - if (!TR2EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)) - { - continue; - } - // If it's the chicken in HSH but we're not using docile, we don't want it ending the level - if (!Settings.DocileBirdMonsters && entity == TR2Entities.BirdMonster && level.Is(TR2LevelNames.HOME)) - { - continue; - } - - // If it's a docile chicken in Barkhang, it won't work because we can't disguise monks in this level. - if (Settings.DocileBirdMonsters && entity == TR2Entities.BirdMonster && level.Is(TR2LevelNames.MONASTERY)) + if (!Settings.DocileBirdMonsters && entity == TR2Entities.BirdMonster && level.Is(TR2LevelNames.HOME) && allEnemies.Except(newEntities).Count() > 1) { continue; } @@ -281,8 +316,13 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, } else { - // Otherwise, pick something else - continue; + // Otherwise, pick something else. If we tried to previously exclude this + // enemy and couldn't, it will slip through the net and so the appearances + // will increase. + if (allEnemies.Except(newEntities).Count() > 1) + { + continue; + } } } @@ -320,6 +360,26 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, } } + // If everything we are including is restriced by room, we need to provide at least one other enemy type + Dictionary> restrictedRoomEnemies = TR2EnemyUtilities.GetRestrictedEnemyRooms(level.Name, difficulty); + if (restrictedRoomEnemies != null && newEntities.All(e => restrictedRoomEnemies.ContainsKey(e))) + { + List pool = TR2EntityUtilities.GetCrossLevelDroppableEnemies(!Settings.ProtectMonks); + do + { + TR2Entities fallbackEnemy; + do + { + fallbackEnemy = pool[_generator.Next(0, pool.Count)]; + } + while ((_excludedEnemies.Contains(fallbackEnemy) && pool.Any(e => !_excludedEnemies.Contains(e))) + || newEntities.Contains(fallbackEnemy) + || !TR2EnemyUtilities.IsEnemySupported(level.Name, fallbackEnemy, difficulty)); + newEntities.Add(fallbackEnemy); + } + while (newEntities.All(e => restrictedRoomEnemies.ContainsKey(e))); + } + // #144 Decide at this point who will be guising unless it has already been decided above (e.g. HSH) if (Settings.DocileBirdMonsters && newEntities.Contains(TR2Entities.BirdMonster) && chickenGuiser == TR2Entities.BirdMonster) { @@ -338,6 +398,46 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR2CombinedLevel level, }; } + private TR2Entities SelectRequiredEnemy(List pool, TR2CombinedLevel level, RandoDifficulty difficulty) + { + pool.RemoveAll(e => !TR2EnemyUtilities.IsEnemySupported(level.Name, e, difficulty)); + + TR2Entities entity; + if (pool.All(_excludedEnemies.Contains)) + { + // Select the last excluded enemy (lowest priority) + entity = _excludedEnemies.Last(e => pool.Contains(e)); + } + else + { + do + { + entity = pool[_generator.Next(0, pool.Count)]; + } + while (_excludedEnemies.Contains(entity)); + } + + return entity; + } + + private RandoDifficulty GetImpliedDifficulty() + { + if (_excludedEnemies.Count > 0 && Settings.RandoEnemyDifficulty == RandoDifficulty.Default) + { + // If every enemy in the pool has room restrictions for any level, we have to imply NoRestrictions difficulty mode + List includedEnemies = Settings.ExcludableEnemies.Keys.Except(Settings.ExcludedEnemies).Select(s => (TR2Entities)s).ToList(); + foreach (TR2ScriptedLevel level in Levels) + { + IEnumerable restrictedRoomEnemies = TR2EnemyUtilities.GetRestrictedEnemyRooms(level.LevelFileBaseName.ToUpper(), RandoDifficulty.Default).Keys; + if (includedEnemies.All(e => restrictedRoomEnemies.Contains(e))) + { + return RandoDifficulty.NoRestrictions; + } + } + } + return Settings.RandoEnemyDifficulty; + } + private void RandomizeEnemiesNatively(TR2CombinedLevel level) { // For the assault course, nothing will be changed for the time being @@ -410,6 +510,8 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti // Keep track of any new entities added (e.g. Skidoo) List newEntities = new List(); + RandoDifficulty difficulty = GetImpliedDifficulty(); + // #148 If it's HSH and we have been able to import cross-level, we will add 15 // dogs outside the gate to ensure the kill counter works. Dogs, Goon1 and // StickGoons will have been excluded from the cross-level pool for simplicity @@ -435,7 +537,7 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti } // First iterate through any enemies that are restricted by room - Dictionary> enemyRooms = TR2EnemyUtilities.GetRestrictedEnemyRooms(level.Name, Settings.RandoEnemyDifficulty); + Dictionary> enemyRooms = TR2EnemyUtilities.GetRestrictedEnemyRooms(level.Name, difficulty); if (enemyRooms != null) { foreach (TR2Entities entity in enemyRooms.Keys) @@ -446,7 +548,7 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti } List rooms = enemyRooms[entity]; - int maxEntityCount = TR2EnemyUtilities.GetRestrictedEnemyLevelCount(entity, Settings.RandoEnemyDifficulty); + int maxEntityCount = TR2EnemyUtilities.GetRestrictedEnemyLevelCount(entity, difficulty); if (maxEntityCount == -1) { // We are allowed any number, but this can't be more than the number of unique rooms, @@ -609,7 +711,8 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti // #278 Flamethrowers in room 29 after pulling the lever are too difficult, but if difficulty is set to unrestricted // and they do end up here, environment mods will change their positions. - if (level.Is(TR2LevelNames.FLOATER) && Settings.RandoEnemyDifficulty == RandoDifficulty.Default && (enemyIndex == 34 || enemyIndex == 35)) + int totalRestrictionCount = TR2EnemyUtilities.GetRestrictedEnemyTotalTypeCount(difficulty); + if (level.Is(TR2LevelNames.FLOATER) && difficulty == RandoDifficulty.Default && (enemyIndex == 34 || enemyIndex == 35) && enemyPool.Count > totalRestrictionCount) { while (newEntityType == TR2Entities.FlamethrowerGoon) { @@ -620,10 +723,10 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti // If we are restricting count per level for this enemy and have reached that count, pick // something else. This applies when we are restricting by in-level count, but not by room // (e.g. Winston). - int maxEntityCount = TR2EnemyUtilities.GetRestrictedEnemyLevelCount(newEntityType, Settings.RandoEnemyDifficulty); + int maxEntityCount = TR2EnemyUtilities.GetRestrictedEnemyLevelCount(newEntityType, difficulty); if (maxEntityCount != -1) { - if (level.Data.Entities.ToList().FindAll(e => e.TypeID == (short)newEntityType).Count >= maxEntityCount) + if (level.Data.Entities.ToList().FindAll(e => e.TypeID == (short)newEntityType).Count >= maxEntityCount && enemyPool.Count > totalRestrictionCount) { TR2Entities tmp = newEntityType; while (newEntityType == tmp) @@ -647,6 +750,9 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti // to the dragon, which will be handled above in defined rooms, but the check should be made // here in case this needs to be extended later. TR2EnemyUtilities.SetEntityTriggers(level.Data, currentEntity); + + // Track every enemy type across the game + _resultantEnemies.Add(newEntityType); } // MercSnowMobDriver relies on RedSnowmobile so it will be available in the model list @@ -702,9 +808,64 @@ private void RandomizeEnemies(TR2CombinedLevel level, EnemyRandomizationCollecti level.Data.NumEntities = (uint)levelEntities.Count; } + // Check in case there are too many skidoo drivers + if (difficulty == RandoDifficulty.NoRestrictions && Array.Find(level.Data.Entities, e => e.TypeID == (short)TR2Entities.MercSnowmobDriver) != null) + { + LimitSkidooEntities(level); + } + RandomizeEnemyMeshes(level, enemies); } + private void LimitSkidooEntities(TR2CombinedLevel level) + { + // Although 256 is the entity limit, any more than 250 and the level can't be saved + const int skidooLimit = 250; + if (level.GetActualEntityCount() >= skidooLimit) + { + FDControl floorData = new FDControl(); + floorData.ParseFromLevel(level.Data); + LocationGenerator locationGenerator = new LocationGenerator(); + List replacementPool = TR2EntityUtilities.GetListOfAmmoTypes(); + + TR2Entity[] skidMen; + do + { + skidMen = Array.FindAll(level.Data.Entities, e => e.TypeID == (short)TR2Entities.MercSnowmobDriver); + if (skidMen.Length == 0) + { + break; + } + + // Select a random Skidoo driver and convert him into a pickup + TR2Entity skidMan = skidMen[_generator.Next(0, skidMen.Length)]; + skidMan.TypeID = (short)replacementPool[_generator.Next(0, replacementPool.Count)]; + + // Make sure the pickup is pickupable + TRRoomSector sector = FDUtilities.GetRoomSector(skidMan.X, skidMan.Y, skidMan.Z, skidMan.Room, level.Data, floorData); + skidMan.Y = sector.Floor * 256; + if (sector.FDIndex != 0) + { + FDEntry entry = floorData.Entries[sector.FDIndex].Find(e => e is FDSlantEntry s && s.Type == FDSlantEntryType.FloorSlant); + if (entry is FDSlantEntry slant) + { + Vector4? bestMidpoint = locationGenerator.GetBestSlantMidpoint(slant); + if (bestMidpoint.HasValue) + { + skidMan.Y += (int)bestMidpoint.Value.Y; + } + } + } + + // Get rid of the enemy's triggers + FDUtilities.RemoveEntityTriggers(level.Data, Array.IndexOf(level.Data.Entities, skidMan), floorData); + } + while (level.GetActualEntityCount() >= skidooLimit); + + floorData.WriteToLevel(level.Data); + } + } + private void RandomizeEnemyMeshes(TR2CombinedLevel level, EnemyRandomizationCollection enemies) { // #314 A very primitive start to mixing-up enemy meshes - monks and yetis can take on Lara's meshes @@ -909,6 +1070,10 @@ internal void ApplyRandomization() } _outer.RandomizeEnemies(level, enemies); + if (_outer.Settings.DevelopmentMode) + { + Debug.WriteLine(level.Name + ": " + string.Join(", ", enemies.All)); + } } _outer.SaveLevel(level); diff --git a/TRRandomizerCore/Randomizers/TR3/TR3EnemyRandomizer.cs b/TRRandomizerCore/Randomizers/TR3/TR3EnemyRandomizer.cs index ac5868834..171ca07f1 100644 --- a/TRRandomizerCore/Randomizers/TR3/TR3EnemyRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3/TR3EnemyRandomizer.cs @@ -1,22 +1,18 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using TRRandomizerCore.Helpers; -using TRRandomizerCore.Levels; -using TRRandomizerCore.Processors; -using TRRandomizerCore.Utilities; using TRGE.Core; using TRLevelReader.Helpers; using TRLevelReader.Model; using TRLevelReader.Model.Enums; using TRModelTransporter.Transport; -using System.Diagnostics; +using TRRandomizerCore.Helpers; +using TRRandomizerCore.Levels; +using TRRandomizerCore.Processors; using TRRandomizerCore.Textures; -using Newtonsoft.Json; -using TREnvironmentEditor; -using TRFDControl.Utilities; -using TRFDControl; -using TRFDControl.FDEntryTypes; +using TRRandomizerCore.Utilities; namespace TRRandomizerCore.Randomizers { @@ -24,6 +20,8 @@ public class TR3EnemyRandomizer : BaseTR3Randomizer { private Dictionary> _gameEnemyTracker; private Dictionary> _pistolLocations; + private List _excludedEnemies; + private ISet _resultantEnemies; internal TR3TextureMonitorBroker TextureMonitor { get; set; } public ItemFactory ItemFactory { get; set; } @@ -93,6 +91,12 @@ private void RandomizeEnemiesCrossLevel() // Track enemies whose counts across the game are restricted _gameEnemyTracker = TR3EnemyUtilities.PrepareEnemyGameTracker(Settings.RandoEnemyDifficulty); + // #272 Selective enemy pool - convert the shorts in the settings to actual entity types + _excludedEnemies = Settings.UseEnemyExclusions ? + Settings.ExcludedEnemies.Select(s => (TR3Entities)s).ToList() : + new List(); + _resultantEnemies = new HashSet(); + SetMessage("Randomizing enemies - importing models"); foreach (EnemyProcessor processor in processors) { @@ -117,6 +121,28 @@ private void RandomizeEnemiesCrossLevel() { _processingException.Throw(); } + + // If any exclusions failed to be avoided, send a message + if (Settings.ShowExclusionWarnings) + { + VerifyExclusionStatus(); + } + } + + private void VerifyExclusionStatus() + { + List failedExclusions = _resultantEnemies.ToList().FindAll(_excludedEnemies.Contains); + if (failedExclusions.Count > 0) + { + // A little formatting + List failureNames = new List(); + foreach (TR3Entities entity in failedExclusions) + { + failureNames.Add(Settings.ExcludableEnemies[(short)entity]); + } + failureNames.Sort(); + SetWarning(string.Format("The following enemies could not be excluded entirely from the randomization pool.{0}{0}{1}", Environment.NewLine, string.Join(Environment.NewLine, failureNames))); + } } private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) @@ -131,12 +157,8 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) List oldEntities = GetCurrentEnemyEntities(level); // Get the list of canidadates - List allEnemies = TR3EntityUtilities.GetCandidateCrossLevelEnemies(); - if (!Settings.DocileBirdMonsters) - { - allEnemies.Remove(TR3Entities.Willie); - } - + List allEnemies = TR3EntityUtilities.GetCandidateCrossLevelEnemies().FindAll(e => TR3EnemyUtilities.IsEnemySupported(level.Name, e, Settings.RandoEnemyDifficulty)); + // Work out how many we can support int enemyCount = oldEntities.Count + TR3EnemyUtilities.GetEnemyAdjustmentCount(level.Name); List newEntities = new List(enemyCount); @@ -151,25 +173,13 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) if (waterEnemyRequired) { List waterEnemies = TR3EntityUtilities.GetKillableWaterEnemies(); - TR3Entities entity; - do - { - entity = waterEnemies[_generator.Next(0, waterEnemies.Count)]; - } - while (!TR3EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)); - newEntities.Add(entity); + newEntities.Add(SelectRequiredEnemy(waterEnemies, level, Settings.RandoEnemyDifficulty)); } if (droppableEnemyRequired) { List droppableEnemies = TR3EntityUtilities.FilterDroppableEnemies(allEnemies, Settings.ProtectMonks); - TR3Entities entity; - do - { - entity = droppableEnemies[_generator.Next(0, droppableEnemies.Count)]; - } - while (!TR3EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)); - newEntities.Add(entity); + newEntities.Add(SelectRequiredEnemy(droppableEnemies, level, Settings.RandoEnemyDifficulty)); } // Are there any other types we need to retain? @@ -181,10 +191,29 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) } } - // Fill the list from the remaining candidates - while (newEntities.Count < newEntities.Capacity) + if (!Settings.DocileBirdMonsters || Settings.OneEnemyMode || Settings.IncludedEnemies.Count < newEntities.Capacity) + { + // Willie isn't excludable in his own right because supporting a Willie-only game is impossible + allEnemies.Remove(TR3Entities.Willie); + } + + // Remove all exclusions from the pool, and adjust the target capacity + allEnemies.RemoveAll(e => _excludedEnemies.Contains(e)); + + IEnumerable ex = allEnemies.Where(e => !newEntities.Any(TR3EntityUtilities.GetEntityFamily(e).Contains)); + List unalisedEntities = TR3EntityUtilities.RemoveAliases(ex); + while (unalisedEntities.Count < newEntities.Capacity - newEntities.Count) + { + --newEntities.Capacity; + } + + // Fill the list from the remaining candidates. Keep track of ones tested to avoid + // looping infinitely if it's not possible to fill to capacity + ISet testedEntities = new HashSet(); + while (newEntities.Count < newEntities.Capacity && testedEntities.Count < allEnemies.Count) { TR3Entities entity = allEnemies[_generator.Next(0, allEnemies.Count)]; + testedEntities.Add(entity); // Make sure this isn't known to be unsupported in the level if (!TR3EnemyUtilities.IsEnemySupported(level.Name, entity, Settings.RandoEnemyDifficulty)) @@ -210,8 +239,13 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) } else { - // Otherwise, pick something else - continue; + // Otherwise, pick something else. If we tried to previously exclude this + // enemy and couldn't, it will slip through the net and so the appearances + // will increase. + if (allEnemies.Except(newEntities).Count() > 1) + { + continue; + } } } @@ -225,25 +259,26 @@ private EnemyTransportCollection SelectCrossLevelEnemies(TR3CombinedLevel level) } } - if (newEntities.Capacity > 1 && newEntities.Any(e => TR3EnemyUtilities.IsEnemyRestricted(level.Name, e))) + if (newEntities.Capacity > 1 && newEntities.All(e => TR3EnemyUtilities.IsEnemyRestricted(level.Name, e))) { // Make sure we have an unrestricted enemy available for the individual level conditions. This will // guarantee a "safe" enemy for the level; we avoid aliases here to avoid further complication. - TR3Entities unrestrictedEnemy; - do + bool RestrictionCheck(TR3Entities e) => + (droppableEnemyRequired && !TR3EntityUtilities.CanDropPickups(e, Settings.ProtectMonks)) + || !TR3EnemyUtilities.IsEnemySupported(level.Name, e, Settings.RandoEnemyDifficulty) + || newEntities.Contains(e) + || TR3EntityUtilities.IsWaterCreature(e) + || TR3EnemyUtilities.IsEnemyRestricted(level.Name, e) + || TR3EntityUtilities.TranslateEntityAlias(e) != e; + + List unrestrictedPool = allEnemies.FindAll(e => !RestrictionCheck(e)); + if (unrestrictedPool.Count == 0) { - unrestrictedEnemy = allEnemies[_generator.Next(0, allEnemies.Count)]; + // We are going to have to pull in the full list of candiates again, so ignoring any exclusions + unrestrictedPool = TR3EntityUtilities.GetCandidateCrossLevelEnemies().FindAll(e => !RestrictionCheck(e)); } - while - ( - (droppableEnemyRequired && !TR3EntityUtilities.CanDropPickups(unrestrictedEnemy, Settings.ProtectMonks)) - || newEntities.Contains(unrestrictedEnemy) - || TR3EntityUtilities.IsWaterCreature(unrestrictedEnemy) - || TR3EnemyUtilities.IsEnemyRestricted(level.Name, unrestrictedEnemy) - || TR3EntityUtilities.TranslateEntityAlias(unrestrictedEnemy) != unrestrictedEnemy - ); - newEntities.Add(unrestrictedEnemy); + newEntities.Add(unrestrictedPool[_generator.Next(0, unrestrictedPool.Count)]); } if (Settings.DevelopmentMode) @@ -267,6 +302,28 @@ private List GetCurrentEnemyEntities(TR3CombinedLevel level) return oldEntities; } + private TR3Entities SelectRequiredEnemy(List pool, TR3CombinedLevel level, RandoDifficulty difficulty) + { + pool.RemoveAll(e => !TR3EnemyUtilities.IsEnemySupported(level.Name, e, difficulty)); + + TR3Entities entity; + if (pool.All(_excludedEnemies.Contains)) + { + // Select the last excluded enemy (lowest priority) + entity = _excludedEnemies.Last(e => pool.Contains(e)); + } + else + { + do + { + entity = pool[_generator.Next(0, pool.Count)]; + } + while (_excludedEnemies.Contains(entity)); + } + + return entity; + } + private void RandomizeEnemiesNatively(TR3CombinedLevel level) { // For the assault course, nothing will be changed for the time being @@ -424,7 +481,7 @@ private void RandomizeEnemies(TR3CombinedLevel level, EnemyRandomizationCollecti int maxEntityCount = TR3EnemyUtilities.GetRestrictedEnemyLevelCount(newEntityType, Settings.RandoEnemyDifficulty); if (maxEntityCount != -1) { - if (level.Data.Entities.ToList().FindAll(e => e.TypeID == (short)newEntityType).Count >= maxEntityCount) + if (level.Data.Entities.ToList().FindAll(e => e.TypeID == (short)newEntityType).Count >= maxEntityCount && enemyPool.Count > maxEntityCount) { TR3Entities tmp = newEntityType; while (newEntityType == tmp || TR3EnemyUtilities.IsEnemyRestricted(level.Name, newEntityType)) @@ -452,13 +509,18 @@ private void RandomizeEnemies(TR3CombinedLevel level, EnemyRandomizationCollecti } } } - else if (level.Is(TR3LevelNames.RXTECH) && level.IsWillardSequence && Settings.RandoEnemyDifficulty == RandoDifficulty.Default && (currentEntity.Room == 14 || currentEntity.Room == 45)) + else if (level.Is(TR3LevelNames.RXTECH) + && level.IsWillardSequence + && Settings.RandoEnemyDifficulty == RandoDifficulty.Default + && newEntityType == TR3Entities.RXTechFlameLad + && (currentEntity.Room == 14 || currentEntity.Room == 45)) { // #269 We don't want flamethrowers here because they're hostile, so getting off the minecart - // safely is too difficult. - while (newEntityType == TR3Entities.RXTechFlameLad || TR3EnemyUtilities.IsEnemyRestricted(level.Name, newEntityType)) + // safely is too difficult. We can only change them if there is something else unrestricted available. + List safePool = enemyPool.FindAll(e => e != TR3Entities.RXTechFlameLad && !TR3EnemyUtilities.IsEnemyRestricted(level.Name, e)); + if (safePool.Count > 0) { - newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; + newEntityType = safePool[_generator.Next(0, safePool.Count)]; } } else if (level.Is(TR3LevelNames.HSC)) @@ -473,24 +535,26 @@ private void RandomizeEnemies(TR3CombinedLevel level, EnemyRandomizationCollecti newEntityType = TR3Entities.Prisoner; } } - else if (currentEntity.Room == 78) + else if (currentEntity.Room == 78 && newEntityType == TR3Entities.Monkey) { // #286 Monkeys cannot share AI Ambush spots largely, but these are needed here to ensure the enemies // come through the gate before the timer closes them again. Just ensure no monkeys are here. - while (newEntityType == TR3Entities.Monkey || TR3EnemyUtilities.IsEnemyRestricted(level.Name, newEntityType)) + List safePool = enemyPool.FindAll(e => e != TR3Entities.Monkey && !TR3EnemyUtilities.IsEnemyRestricted(level.Name, e)); + if (safePool.Count > 0) { - newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; + newEntityType = safePool[_generator.Next(0, safePool.Count)]; + } + else + { + // Full monkey mode means we have to move them inside the gate + currentEntity.Z -= 4096; } } } - else if (level.Is(TR3LevelNames.THAMES) && (currentEntity.Room == 61 || currentEntity.Room == 62)) + else if (level.Is(TR3LevelNames.THAMES) && (currentEntity.Room == 61 || currentEntity.Room == 62) && newEntityType == TR3Entities.Monkey) { - // #286 Ban monkeys from these two rooms for now because of JP entity index differences (environment mods - // can't yet tell the difference). - while (newEntityType == TR3Entities.Monkey || TR3EnemyUtilities.IsEnemyRestricted(level.Name, newEntityType)) - { - newEntityType = enemyPool[_generator.Next(0, enemyPool.Count)]; - } + // #286 Move the monkeys away from the AI entities + currentEntity.Z -= 1024; } // Make sure to convert back to the actual type @@ -506,6 +570,9 @@ private void RandomizeEnemies(TR3CombinedLevel level, EnemyRandomizationCollecti { targetEntity.Invisible = false; } + + // Track every enemy type across the game + _resultantEnemies.Add(newEntityType); } // Add extra ammo based on this level's difficulty diff --git a/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json b/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json index 6422788e9..f8c32b0a7 100644 --- a/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json +++ b/TRRandomizerCore/Resources/TR2/Environment/FLOATING.TR2-Environment.json @@ -44,6 +44,28 @@ ] }, + { + "Condition": { + "Comments": "Similary in the cage room, rotate enemy 108 so there is a bit of time to escape after triggering him.", + "ConditionType": 0, + "EntityIndex": 108, + "EntityType": 34 + }, + "OnTrue": [ + { + "EMType": 44, + "EntityIndex": 108, + "TargetLocation": { + "X": 38400, + "Y": 4608, + "Z": 81408, + "Room": 145, + "Angle": 16384 + } + } + ] + }, + { "Condition": { "Comments": "If Marco has been added, make a new room for him and move him to it.", diff --git a/TRRandomizerCore/Resources/TR2/Restrictions/enemy_restrictions_special.json b/TRRandomizerCore/Resources/TR2/Restrictions/enemy_restrictions_special.json index 177f22c4f..9bc51e4c9 100644 --- a/TRRandomizerCore/Resources/TR2/Restrictions/enemy_restrictions_special.json +++ b/TRRandomizerCore/Resources/TR2/Restrictions/enemy_restrictions_special.json @@ -2943,9 +2943,7 @@ ], "1": [ [ 40, 20, 1009, 21 ], - [ 40, 20, 1009, 36 ], - [ 40, 20, 1010, 21 ], - [ 40, 20, 1010, 36 ], + [ 40, 20, 1010, 21 ], [ 40, 20, 38, 21 ], [ 40, 20, 38, 36 ], [ 40, 20, 37, 21 ], diff --git a/TRRandomizerCore/Resources/TR2/Restrictions/excludable_enemies.json b/TRRandomizerCore/Resources/TR2/Restrictions/excludable_enemies.json new file mode 100644 index 000000000..aab1248ae --- /dev/null +++ b/TRRandomizerCore/Resources/TR2/Restrictions/excludable_enemies.json @@ -0,0 +1,44 @@ +{ + "1009": "Barracuda (Tibet)", + "1008": "Barracuda (Underwater Levels)", + "1010": "Barracuda (Temple of Xian)", + "1000": "Tiger (Bengal)", + "46": "Bird Monster", + "27": "Black Moray Eel", + "38": "Crow", + "15": "Doberman", + "47": "Eagle", + "34": "Flamethrower", + "30": "Gunman 1 (Shotgun)", + "31": "Gunman 2 (Rifle)", + "19": "Knifethrower", + "16": "Masked Goon 1 (Jacket)", + "17": "Masked Goon 2 (Waistcoat)", + "18": "Masked Goon 3 (T-Shirt)", + "48": "Mercenary 1 (Grey Trousers)", + "49": "Mercenary 2 (Blue Trousers)", + "50": "Mercenary 3 (Green Trousers)", + "52": "Skidoo Driver", + "53": "Monk (Long Stick)", + "54": "Monk (Knife Stick)", + "21": "Rat", + "29": "Scuba Diver", + "25": "Shark", + "20": "Shotgun Goon", + "1001": "Snow Leopard", + "36": "Spider (Small)", + "37": "Spider (Large)", + "1003": "Stick Goon (Bandana)", + "1004": "Stick Goon (Black Jacket)", + "1005": "Stick Goon (Bodywarmer)", + "1006": "Stick Goon (Green Vest)", + "1007": "Stick Goon (White Vest)", + "33": "Stick Goon (White T-Shirt)", + "214": "T-Rex", + "1002": "Tiger (White)", + "260": "Winston", + "41": "Jade Guardian (Spear)", + "43": "Jade Guardian (Sword)", + "26": "Yellow Moray Eel", + "45": "Yeti" +} \ No newline at end of file diff --git a/TRRandomizerCore/Resources/TR3/Restrictions/excludable_enemies.json b/TRRandomizerCore/Resources/TR3/Restrictions/excludable_enemies.json new file mode 100644 index 000000000..4b8e9720b --- /dev/null +++ b/TRRandomizerCore/Resources/TR3/Restrictions/excludable_enemies.json @@ -0,0 +1,41 @@ +{ + "46": "RX Tech Claw Mutant", + "1000": "Cobra (India)", + "1001": "Cobra (Nevada)", + "34": "Compsognathus", + "42": "RX Tech Crawler Mutant", + "32": "Crocodile", + "27": "Crow", + "65": "Dam Guard", + "41": "Dog (Antarctica)", + "2000": "Dog (London)", + "2001": "Dog (Nevada)", + "25": "Killer Whale", + "35": "Lizard Man", + "56": "London Guard", + "51": "Mercenary (London)", + "37": "Mercenary (South Pacific)", + "71": "Monkey", + "61": "MP (Handgun)", + "63": "MP (MP5)", + "60": "MP (Baton)", + "62": "Prisoner", + "53": "Punk", + "288": "Raptor", + "23": "Rat", + "40": "Gunman (Meteorite Cavern)", + "39": "Gunman (Antarctica)", + "50": "Flamethrower", + "26": "Scuba Diver", + "70": "Shiva", + "28": "Tiger", + "45": "Tinnos Monster", + "44": "Tinnos Wasp", + "73": "Tony", + "20": "Tribesman (Axe)", + "21": "Tribesman (Dart)", + "287": "T-Rex", + "29": "Vulture", + "360": "Winston (Regular)", + "361": "Winston (Camoflauge)" +} \ No newline at end of file diff --git a/TRRandomizerCore/TRRandomizerController.cs b/TRRandomizerCore/TRRandomizerController.cs index 789e0fdf1..1667c475d 100644 --- a/TRRandomizerCore/TRRandomizerController.cs +++ b/TRRandomizerCore/TRRandomizerController.cs @@ -461,6 +461,34 @@ public bool MaximiseDragonAppearance set => LevelRandomizer.MaximiseDragonAppearance = value; } + public bool UseEnemyExclusions + { + get => LevelRandomizer.UseEnemyExclusions; + set => LevelRandomizer.UseEnemyExclusions = value; + } + + public bool ShowExclusionWarnings + { + get => LevelRandomizer.ShowExclusionWarnings; + set => LevelRandomizer.ShowExclusionWarnings = value; + } + + public List ExcludedEnemies + { + get => LevelRandomizer.ExcludedEnemies; + set => LevelRandomizer.ExcludedEnemies = value; + } + + public Dictionary ExcludableEnemies + { + get => LevelRandomizer.ExcludableEnemies; + } + + public List IncludedEnemies + { + get => LevelRandomizer.IncludedEnemies; + } + public bool RandomizeOutfits { get => LevelRandomizer.RandomizeOutfits; diff --git a/TRRandomizerCore/Utilities/LocationGenerator.cs b/TRRandomizerCore/Utilities/LocationGenerator.cs index c06d3cfff..fe3e41624 100644 --- a/TRRandomizerCore/Utilities/LocationGenerator.cs +++ b/TRRandomizerCore/Utilities/LocationGenerator.cs @@ -296,7 +296,7 @@ private bool IsTriggerInvalid(FDTriggerEntry trigger) ); } - private Vector4? GetBestSlantMidpoint(FDSlantEntry slant) + public Vector4? GetBestSlantMidpoint(FDSlantEntry slant) { List corners = new List { 0, 0, 0, 0 }; if (slant.XSlant > 0) diff --git a/TRRandomizerCore/Utilities/TR2EnemyUtilities.cs b/TRRandomizerCore/Utilities/TR2EnemyUtilities.cs index cf0bfef58..04cc8bd79 100644 --- a/TRRandomizerCore/Utilities/TR2EnemyUtilities.cs +++ b/TRRandomizerCore/Utilities/TR2EnemyUtilities.cs @@ -177,6 +177,16 @@ public static int GetRestrictedEnemyLevelCount(TR2Entities entity, RandoDifficul return -1; } + public static int GetRestrictedEnemyTotalTypeCount(RandoDifficulty difficulty) + { + if (difficulty == RandoDifficulty.Default) + { + return _restrictedEnemyLevelCountsDefault.Count; + } + + return _restrictedEnemyLevelCountsTechnical.Count; + } + public static List> GetPermittedCombinations(string lvl, TR2Entities entity, RandoDifficulty difficulty) { if (_specialEnemyCombinations.ContainsKey(lvl) && _specialEnemyCombinations[lvl].ContainsKey(entity)) @@ -284,7 +294,6 @@ public static EnemyDifficulty GetEnemyDifficulty(List enemies) TR2Entities.Barracuda, TR2Entities.BlackMorayEel, TR2Entities.ScubaDiver, TR2Entities.Shark, TR2Entities.YellowMorayEel }, - // #192 The Barkhang/Opera House freeze appears to be caused by dead floating water creatures, so they're all banished [TR2LevelNames.MONASTERY] = new List { @@ -300,7 +309,7 @@ public static EnemyDifficulty GetEnemyDifficulty(List enemies) TR2Entities.BlackMorayEel, TR2Entities.Doberman, TR2Entities.MaskedGoon1, TR2Entities.MaskedGoon2, TR2Entities.MaskedGoon3, TR2Entities.MercSnowmobDriver, TR2Entities.MonkWithKnifeStick, TR2Entities.MonkWithLongStick, TR2Entities.StickWieldingGoon1, - TR2Entities.StickWieldingGoon2, TR2Entities.Winston, TR2Entities.YellowMorayEel + TR2Entities.StickWieldingGoon2, TR2Entities.Winston, TR2Entities.YellowMorayEel, TR2Entities.ShotgunGoon } }; diff --git a/TRRandomizerView/Model/BoolItemIDControlClass.cs b/TRRandomizerView/Model/BoolItemIDControlClass.cs new file mode 100644 index 000000000..0d7394ead --- /dev/null +++ b/TRRandomizerView/Model/BoolItemIDControlClass.cs @@ -0,0 +1,19 @@ +using System; + +namespace TRRandomizerView.Model +{ + public class BoolItemIDControlClass : BoolItemControlClass, ICloneable + { + public int ID { get; set; } + + public BoolItemIDControlClass Clone() + { + return (BoolItemIDControlClass)MemberwiseClone(); + } + + object ICloneable.Clone() + { + return Clone(); + } + } +} \ No newline at end of file diff --git a/TRRandomizerView/Model/ControllerOptions.cs b/TRRandomizerView/Model/ControllerOptions.cs index 00f945f92..200fed505 100644 --- a/TRRandomizerView/Model/ControllerOptions.cs +++ b/TRRandomizerView/Model/ControllerOptions.cs @@ -58,6 +58,8 @@ public class ControllerOptions : INotifyPropertyChanged private bool _vfxWave; private List _secretBoolItemControls, _itemBoolItemControls, _enemyBoolItemControls, _textureBoolItemControls, _audioBoolItemControls, _outfitBoolItemControls, _textBoolItemControls, _startBoolItemControls, _environmentBoolItemControls; + private List _selectableEnemies; + private bool _useEnemyExclusions, _showExclusionWarnings; private RandoDifficulty _randoEnemyDifficulty; private ItemDifficulty _randoItemDifficulty; @@ -1111,6 +1113,36 @@ public List EnemyBoolItemControls } } + public List SelectableEnemyControls + { + get => _selectableEnemies; + set + { + _selectableEnemies = value; + FirePropertyChanged(); + } + } + + public bool UseEnemyExclusions + { + get => _useEnemyExclusions; + set + { + _useEnemyExclusions = value; + FirePropertyChanged(); + } + } + + public bool ShowExclusionWarnings + { + get => _showExclusionWarnings; + set + { + _showExclusionWarnings = value; + FirePropertyChanged(); + } + } + public List TextureBoolItemControls { get => _textureBoolItemControls; @@ -1508,6 +1540,9 @@ public void Load(TRRandomizerController controller) DocileBirdMonsters.Value = _controller.DocileBirdMonsters; MaximiseDragonAppearance.Value = _controller.MaximiseDragonAppearance; RandoEnemyDifficulty = _controller.RandoEnemyDifficulty; + UseEnemyExclusions = _controller.UseEnemyExclusions; + ShowExclusionWarnings = _controller.ShowExclusionWarnings; + LoadEnemyExclusions(); RandomizeSecrets = _controller.RandomizeSecrets; SecretSeed = _controller.SecretSeed; @@ -1564,6 +1599,26 @@ public void Load(TRRandomizerController controller) FireSupportPropertiesChanged(); } + public void LoadEnemyExclusions() + { + SelectableEnemyControls = new List(); + + // Add exclusions based on priority (i.e. order) followed by the remaining included controls + _controller.ExcludedEnemies.ForEach(e => SelectableEnemyControls.Add(new BoolItemIDControlClass + { + ID = e, + Title = _controller.ExcludableEnemies[e], + Value = true + })); + + _controller.IncludedEnemies.ForEach(e => SelectableEnemyControls.Add(new BoolItemIDControlClass + { + ID = e, + Title = _controller.ExcludableEnemies[e], + Value = false + })); + } + public void RandomizeActiveSeeds() { Random rng = new Random(); @@ -1759,6 +1814,12 @@ public void Save() _controller.DocileBirdMonsters = DocileBirdMonsters.Value; _controller.MaximiseDragonAppearance = MaximiseDragonAppearance.Value; _controller.RandoEnemyDifficulty = RandoEnemyDifficulty; + _controller.UseEnemyExclusions = UseEnemyExclusions; + _controller.ShowExclusionWarnings = ShowExclusionWarnings; + + List excludedEnemies = new List(); + SelectableEnemyControls.FindAll(c => c.Value).ForEach(c => excludedEnemies.Add((short)c.ID)); + _controller.ExcludedEnemies = excludedEnemies; _controller.RandomizeSecrets = RandomizeSecrets; _controller.SecretSeed = SecretSeed; diff --git a/TRRandomizerView/TRRandomizerView.csproj b/TRRandomizerView/TRRandomizerView.csproj index 19ebf4b22..72b1afd2f 100644 --- a/TRRandomizerView/TRRandomizerView.csproj +++ b/TRRandomizerView/TRRandomizerView.csproj @@ -97,6 +97,7 @@ + @@ -107,6 +108,9 @@ AdvancedWindow.xaml + + EnemyWindow.xaml + GlobalSeedWindow.xaml @@ -165,6 +169,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/TRRandomizerView/Windows/AdvancedWindow.xaml b/TRRandomizerView/Windows/AdvancedWindow.xaml index 1f977a2bc..4e59fb15a 100644 --- a/TRRandomizerView/Windows/AdvancedWindow.xaml +++ b/TRRandomizerView/Windows/AdvancedWindow.xaml @@ -72,6 +72,8 @@ + + @@ -180,7 +182,7 @@ - @@ -239,8 +241,51 @@ + + + + + + + + + + + + + + + + + + + + + + + +