diff --git a/CHANGELOG.md b/CHANGELOG.md index a5d0c3d4d..a4f3a8231 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## [Unreleased](https://github.com/LostArtefacts/TR-Rando/compare/V1.11.0...master) - xxxx-xx-xx +- added an option to remove crystals in classic TR3 ## [V1.11.0](https://github.com/LostArtefacts/TR-Rando/compare/V1.10.2...V1.11.0) - 2025-10-05 - added support for TR1X 4.15 (now the minimum version supported) (#803) diff --git a/TRDataControl/Data/TR1DataProvider.cs b/TRDataControl/Data/TR1DataProvider.cs index 329e41f76..f71e24b8d 100644 --- a/TRDataControl/Data/TR1DataProvider.cs +++ b/TRDataControl/Data/TR1DataProvider.cs @@ -16,7 +16,7 @@ public TRBlobType GetBlobType(TR1Type type) { return TRBlobType.Sprite; } - if (type >= TR1Type.SceneryBase && type < TR1Type.SecretScion_M_H) + if (type > TR1Type.HarpoonProjectile_H && type < TR1Type.M16_S_P) { return TRBlobType.StaticMesh; } @@ -123,6 +123,22 @@ public IEnumerable GetHardcodedSounds(TR1Type type) private static readonly Dictionary> _typeDependencies = new() { + [TR1Type.LaraFlareAnim_H] = new() + { + TR1Type.FlareSparks_M_H, TR1Type.Flares_M_H, TR1Type.Flare_H, TR1Type.Flares_S_P + }, + [TR1Type.LaraM16Anim_H] = new() + { + TR1Type.M16Gunflare_H, TR1Type.M16_M_H, TR1Type.M16Ammo_M_H, TR1Type.M16_S_P, TR1Type.M16Ammo_S_P, + }, + [TR1Type.LaraGrenadeAnim_H] = new() + { + TR1Type.GrenadeProjectile_H, TR1Type.GrenadeLauncher_M_H, TR1Type.Grenades_M_H, TR1Type.GrenadeLauncher_S_P, TR1Type.Grenades_S_P, + }, + [TR1Type.LaraHarpoonAnim_H] = new() + { + TR1Type.HarpoonProjectile_H, TR1Type.Harpoon_M_H, TR1Type.HarpoonAmmo_M_H, TR1Type.Harpoon_S_P, TR1Type.HarpoonAmmo_S_P, + }, [TR1Type.Adam] = new() { TR1Type.LaraMiscAnim_H_Pyramid, TR1Type.Explosion1_S_H }, [TR1Type.AtlanteanLava] @@ -363,6 +379,14 @@ public IEnumerable GetHardcodedSounds(TR1Type type) TR1Type.SecretLeadBar_S_P, TR1Type.SecretGoldBar_S_P, TR1Type.SecretAnkh_S_P, + + TR1Type.Flares_S_P, + TR1Type.M16_S_P, + TR1Type.GrenadeLauncher_S_P, + TR1Type.Harpoon_S_P, + TR1Type.M16Ammo_S_P, + TR1Type.Grenades_S_P, + TR1Type.HarpoonAmmo_S_P, }; #endregion diff --git a/TRDataControl/Data/TR2DataProvider.cs b/TRDataControl/Data/TR2DataProvider.cs index ec0b1856e..9b4981c6a 100644 --- a/TRDataControl/Data/TR2DataProvider.cs +++ b/TRDataControl/Data/TR2DataProvider.cs @@ -16,7 +16,7 @@ public TRBlobType GetBlobType(TR2Type type) { return TRBlobType.Sprite; } - if (type > TR2Type.MonkWithNoShadow && type < TR2Type.BengalTiger) + if (type > TR2Type.SecretOption3 && type < TR2Type.BengalTiger) { return TRBlobType.StaticMesh; } @@ -438,6 +438,7 @@ public IEnumerable GetHardcodedSounds(TR2Type type) TR2Type.Flame_S_H, TR2Type.FontGraphics_S_H, TR2Type.AssaultNumbers, + TR2Type.PickupAid, }; #endregion diff --git a/TRLevelControl/Helpers/TR1TypeUtilities.cs b/TRLevelControl/Helpers/TR1TypeUtilities.cs index 8a1a96a6a..fb8bfb7c5 100644 --- a/TRLevelControl/Helpers/TR1TypeUtilities.cs +++ b/TRLevelControl/Helpers/TR1TypeUtilities.cs @@ -62,6 +62,35 @@ public static class TR1TypeUtilities } }; + public static string GetName(TR1Type type) + { + // TODO: remove once static mesh enum entries are removed + return type switch + { + TR1Type.LaraFlareAnim_H => "LaraFlareAnim_H", + TR1Type.Flare_H => "Flare_H", + TR1Type.FlareSparks_M_H => "FlareSparks_M_H", + TR1Type.Flares_S_P => "Flares_S_P", + TR1Type.Flares_M_H => "Flares_M_H", + + TR1Type.LaraM16Anim_H => "LaraM16Anim_H", + TR1Type.LaraGrenadeAnim_H => "LaraGrenadeAnim_H", + TR1Type.LaraHarpoonAnim_H => "LaraHarpoonAnim_H", + + TR1Type.M16_M_H => "M16_M_H", + TR1Type.GrenadeLauncher_M_H => "GrenadeLauncher_M_H", + TR1Type.Harpoon_M_H => "Harpoon_M_H", + TR1Type.M16Ammo_M_H => "M16Ammo_M_H", + TR1Type.Grenades_M_H => "Grenades_M_H", + TR1Type.HarpoonAmmo_M_H => "HarpoonAmmo_M_H", + + TR1Type.M16Gunflare_H => "M16Gunflare_H", + TR1Type.GrenadeProjectile_H => "GrenadeProjectile_H", + TR1Type.HarpoonProjectile_H => "HarpoonProjectile_H", + _ => type.ToString(), + }; + } + public static TR1Type TranslateAlias(TR1Type type) { foreach (TR1Type parentType in TypeFamilies.Keys) diff --git a/TRLevelControl/Model/TR1/Enums/TR1FX.cs b/TRLevelControl/Model/TR1/Enums/TR1FX.cs index 7ebaafc5f..ad008c163 100644 --- a/TRLevelControl/Model/TR1/Enums/TR1FX.cs +++ b/TRLevelControl/Model/TR1/Enums/TR1FX.cs @@ -19,4 +19,7 @@ public enum TR1FX : short DrawRightGun = 14, Chainblock = 15, Flicker = 16, + HideItem = 17, + ShadowOn = 18, + ShadowOff = 19, } diff --git a/TRLevelControl/Model/TR1/Enums/TR1Type.cs b/TRLevelControl/Model/TR1/Enums/TR1Type.cs index a74b84103..de853528d 100644 --- a/TRLevelControl/Model/TR1/Enums/TR1Type.cs +++ b/TRLevelControl/Model/TR1/Enums/TR1Type.cs @@ -204,33 +204,62 @@ public enum TR1Type : uint Skybox_H = Unused01, PickupAid_S_H = Unused02, Glow_S_H = Unused03, + Flares_S_P = Unused04, + Flares_M_H = Unused05, LaraPonytail_H_U = 189, FontGraphics_S_H = 190, + Winston = 191, + LaraFlareAnim_H = 192, + Flare_H = 193, + FlareSparks_M_H = 194, + + LaraExtraSkinTrex = 195, + LaraExtraSkinMidas = 196, + LaraExtraSkinDagger1 = 197, + LaraExtraSkinDagger2 = 198, + LaraHairSwap = 199, + LaraHairBodySwap = 200, + + LaraM16Anim_H = 201, + LaraGrenadeAnim_H = 202, + LaraHarpoonAnim_H = 203, + + M16_M_H = 204, + GrenadeLauncher_M_H = 205, + Harpoon_M_H = 206, + M16Ammo_M_H = 207, + Grenades_M_H = 208, + HarpoonAmmo_M_H = 209, + + M16Gunflare_H = 210, + GrenadeProjectile_H = 211, + HarpoonProjectile_H = 212, + // Scenery - Plant0 = 191, - Plant1 = 192, - Plant2 = 193, - Plant3 = 194, - Plant4 = 195, - Plant5 = 196, - Plant6 = 197, - Plant7 = 198, - Plant8 = 199, - Plant9 = 200, - Furniture0 = 201, - Furniture1 = 202, - Furniture2 = 203, - Furniture3 = 204, - Furniture4 = 205, - Furniture5 = 206, - Furniture6 = 207, - Furniture7 = 208, - Furniture8 = 209, - Furniture9 = 210, - Rock0 = 211, - Rock1 = 212, + Plant0 = Winston, + Plant1 = LaraFlareAnim_H, + Plant2 = Flare_H, + Plant3 = FlareSparks_M_H, + Plant4 = LaraExtraSkinTrex, + Plant5 = LaraExtraSkinMidas, + Plant6 = LaraExtraSkinDagger1, + Plant7 = LaraExtraSkinDagger2, + Plant8 = LaraHairSwap, + Plant9 = LaraHairBodySwap, + Furniture0 = LaraM16Anim_H, + Furniture1 = LaraGrenadeAnim_H, + Furniture2 = LaraHarpoonAnim_H, + Furniture3 = M16_M_H, + Furniture4 = GrenadeLauncher_M_H, + Furniture5 = Harpoon_M_H, + Furniture6 = M16Ammo_M_H, + Furniture7 = Grenades_M_H, + Furniture8 = HarpoonAmmo_M_H, + Furniture9 = M16Gunflare_H, + Rock0 = GrenadeProjectile_H, + Rock1 = HarpoonProjectile_H, Rock2 = 213, Rock3 = 214, Rock4 = 215, @@ -259,7 +288,14 @@ public enum TR1Type : uint Debris7 = 238, Debris8 = 239, Debris9 = 240, - SceneryBase = Plant0, + SceneryBase = Winston, + + M16_S_P = 241, + GrenadeLauncher_S_P = 242, + Harpoon_S_P = 243, + M16Ammo_S_P = 244, + Grenades_S_P = 245, + HarpoonAmmo_S_P = 246, // Unused models, so repurposed as duplicate puzzle items for importing as secret pickups SecretScion_M_H = 700, diff --git a/TRLevelControl/Model/TR2/Enums/TR2FX.cs b/TRLevelControl/Model/TR2/Enums/TR2FX.cs index 9b35900f6..c6a9f139e 100644 --- a/TRLevelControl/Model/TR2/Enums/TR2FX.cs +++ b/TRLevelControl/Model/TR2/Enums/TR2FX.cs @@ -32,4 +32,6 @@ public enum TR2FX : short AssaultStop = 29, AssaultStart = 30, AssaultEnd = 31, + ShadowOn = 32, + ShadowOff = 33, } diff --git a/TRLevelControl/Model/TR2/Enums/TR2Type.cs b/TRLevelControl/Model/TR2/Enums/TR2Type.cs index 175f5a86b..7726a6e26 100644 --- a/TRLevelControl/Model/TR2/Enums/TR2Type.cs +++ b/TRLevelControl/Model/TR2/Enums/TR2Type.cs @@ -279,21 +279,31 @@ public enum TR2Type : uint Bear = 265, Wolf = 266, MonkWithNoShadow = 267, + PickupAid = 268, + SavegameCrystal_P = 269, + LaraExtraSkinTrex = 270, + LaraExtraSkinMidas = 271, + LaraExtraSkinDagger1 = 272, + LaraExtraSkinDagger2 = 273, + LaraHairSwap = 274, + SecretOption1 = 275, + SecretOption2 = 276, + SecretOption3 = 277, // Scenery - TODO: get rid of defined statics Plant0 = Bear, Plant1 = Wolf, Plant2 = MonkWithNoShadow, - Plant3 = 268, - Plant4 = 269, - Plant5 = 270, - Plant6 = 271, - Plant7 = 272, - Plant8 = 273, - Plant9 = 274, - Furniture0 = 275, - Furniture1 = 276, - Furniture2 = 277, + Plant3 = PickupAid, + Plant4 = SavegameCrystal_P, + Plant5 = LaraExtraSkinTrex, + Plant6 = LaraExtraSkinMidas, + Plant7 = LaraExtraSkinDagger1, + Plant8 = LaraExtraSkinDagger2, + Plant9 = LaraHairSwap, + Furniture0 = SecretOption1, + Furniture1 = SecretOption2, + Furniture2 = SecretOption3, Furniture3 = 278, Furniture4 = 279, Furniture5 = 280, diff --git a/TRRandomizerCore/Editors/RandomizerSettings.cs b/TRRandomizerCore/Editors/RandomizerSettings.cs index c3a315cc5..e54c8a647 100644 --- a/TRRandomizerCore/Editors/RandomizerSettings.cs +++ b/TRRandomizerCore/Editors/RandomizerSettings.cs @@ -149,6 +149,7 @@ public class RandomizerSettings public bool AutoLaunchGame { get; set; } public bool AddReturnPaths { get; set; } public bool FixOGBugs { get; set; } + public bool RemoveCrystals { get; set; } public bool RandomizeItemTypes { get; set; } public bool RandomizeItemPositions { get; set; } @@ -343,6 +344,7 @@ public void ApplyConfig(Config config) AutoLaunchGame = config.GetBool(nameof(AutoLaunchGame)); AddReturnPaths = config.GetBool(nameof(AddReturnPaths), true); FixOGBugs = config.GetBool(nameof(FixOGBugs), true); + RemoveCrystals = config.GetBool(nameof(RemoveCrystals)); RandomizeSecretRewardsPhysical = config.GetBool(nameof(RandomizeSecretRewardsPhysical)); SecretRewardsPhysicalSeed = config.GetInt(nameof(SecretRewardsPhysicalSeed), defaultSeed); @@ -515,6 +517,7 @@ public void StoreConfig(Config config) config[nameof(AutoLaunchGame)] = AutoLaunchGame; config[nameof(AddReturnPaths)] = AddReturnPaths; config[nameof(FixOGBugs)] = FixOGBugs; + config[nameof(RemoveCrystals)] = RemoveCrystals; config[nameof(RandomizeSecretRewardsPhysical)] = RandomizeSecretRewardsPhysical; config[nameof(SecretRewardsPhysicalSeed)] = SecretRewardsPhysicalSeed; diff --git a/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs b/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs index cadef3da8..4019214a8 100644 --- a/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs +++ b/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs @@ -148,6 +148,19 @@ private void AdjustLevel(TR3CombinedLevel level) } } } + + if (Settings.RemoveCrystals) + { + for (int i = 0; i < level.Data.Entities.Count; i++) + { + var item = level.Data.Entities[i]; + if (item.TypeID == TR3Type.SaveCrystal_P) + { + item.TypeID = TR3Type.LookAtItem_H; + ItemFactory.FreeItem(level.Name, i); + } + } + } } private void ImportUPV(TR3CombinedLevel level) diff --git a/TRRandomizerCore/TRRandomizerController.cs b/TRRandomizerCore/TRRandomizerController.cs index 6b7832330..63ebe00b0 100644 --- a/TRRandomizerCore/TRRandomizerController.cs +++ b/TRRandomizerCore/TRRandomizerController.cs @@ -1211,6 +1211,12 @@ public bool FixOGBugs set => LevelRandomizer.FixOGBugs = value; } + public bool RemoveCrystals + { + get => LevelRandomizer.RemoveCrystals; + set => LevelRandomizer.RemoveCrystals = value; + } + public bool RandomizeVfx { get => LevelRandomizer.RandomizeVfx; diff --git a/TRRandomizerCore/TRRandomizerType.cs b/TRRandomizerCore/TRRandomizerType.cs index abfe5e6aa..d71476a86 100644 --- a/TRRandomizerCore/TRRandomizerType.cs +++ b/TRRandomizerCore/TRRandomizerType.cs @@ -71,4 +71,5 @@ public enum TRRandomizerType Wireframe, HideDeadTrexes, Vehicles, + RemoveCrystals, } diff --git a/TRRandomizerCore/TRVersionSupport.cs b/TRRandomizerCore/TRVersionSupport.cs index 6d3434c3c..cc66d7a1c 100644 --- a/TRRandomizerCore/TRVersionSupport.cs +++ b/TRRandomizerCore/TRVersionSupport.cs @@ -180,6 +180,7 @@ internal class TRVersionSupport TRRandomizerType.LevelSequence, TRRandomizerType.NightMode, TRRandomizerType.Outfit, + TRRandomizerType.RemoveCrystals, TRRandomizerType.ReturnPaths, TRRandomizerType.RewardRooms, TRRandomizerType.Secret, diff --git a/TRRandomizerView/Model/ControllerOptions.cs b/TRRandomizerView/Model/ControllerOptions.cs index 1f315d64b..1a1c6f277 100644 --- a/TRRandomizerView/Model/ControllerOptions.cs +++ b/TRRandomizerView/Model/ControllerOptions.cs @@ -28,7 +28,7 @@ public class ControllerOptions : INotifyPropertyChanged private GameMode _gameMode; private GameMode[] _gameModes; - private bool _addReturnPaths, _fixOGBugs, _disableDemos, _autoLaunchGame; + private bool _addReturnPaths, _fixOGBugs, _disableDemos, _autoLaunchGame, _removeCrystals; private BoolItemControlClass _randomizeLevelSequencing; private BoolItemControlClass _isHardSecrets, _allowGlitched, _guaranteeSecrets, _useRandomSecretModels, _enableUWCornerSecrets; @@ -1548,6 +1548,16 @@ public bool FixOGBugs } } + public bool RemoveCrystals + { + get => _removeCrystals; + set + { + _removeCrystals = value; + FirePropertyChanged(); + } + } + public bool DisableDemos { get => _disableDemos; @@ -3056,6 +3066,7 @@ public void Load(TRRandomizerController controller) AutoLaunchGame = _controller.AutoLaunchGame; AddReturnPaths = _controller.AddReturnPaths; FixOGBugs = _controller.FixOGBugs; + RemoveCrystals = _controller.RemoveCrystals; SpriteRandoModes = Enum.GetValues(); SpriteRandoMode = _controller.SpriteRandoMode; @@ -3289,6 +3300,7 @@ public void Save() _controller.AutoLaunchGame = AutoLaunchGame; _controller.AddReturnPaths = AddReturnPaths; _controller.FixOGBugs = FixOGBugs; + _controller.RemoveCrystals = RemoveCrystals; _controller.SpriteRandoMode = SpriteRandoMode; _controller.RandomizeItemSprites = RandomizeItemSprites; @@ -3373,6 +3385,7 @@ public void Unload() public bool IsItemSpriteTypeSupported => IsRandomizationSupported(TRRandomizerType.ItemSprite); public bool IsReturnPathsTypeSupported => IsRandomizationSupported(TRRandomizerType.ReturnPaths); public bool IsGeneralBugFixesTypeSupported => IsRandomizationSupported(TRRandomizerType.GeneralBugFixes); + public bool IsRemoveCrystalsTypeSupported => IsRandomizationSupported(TRRandomizerType.RemoveCrystals); private bool IsRandomizationSupported(TRRandomizerType randomizerType) { diff --git a/TRRandomizerView/Windows/GlobalSettingsWindow.xaml b/TRRandomizerView/Windows/GlobalSettingsWindow.xaml index 4de01537c..3f298674c 100644 --- a/TRRandomizerView/Windows/GlobalSettingsWindow.xaml +++ b/TRRandomizerView/Windows/GlobalSettingsWindow.xaml @@ -54,6 +54,7 @@ + @@ -104,6 +105,18 @@ Grid.Column="1" Visibility="{Binding IsGeneralBugFixesTypeSupported, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToCollapsedConverter}}" Text="Fix original level bugs and oversights, such as missing textures or untriggered enemies."/> + + + + Removes all savegame/healing crystal items. +