diff --git a/SCHIZO/Commands/DevCommands.cs b/SCHIZO/Commands/DevCommands.cs index e0ad00de..da6e0a4c 100644 --- a/SCHIZO/Commands/DevCommands.cs +++ b/SCHIZO/Commands/DevCommands.cs @@ -137,4 +137,25 @@ public static object SetField(string typeName, string memberName, string valueSt throw new InvalidOperationException("Unreachable"); } } + + + [Command(Name = "dump_spawn_biomes", + DisplayName = "Dump Spawn Biomes", + Description = "List the biomes where a given techtype is registered to spawn", + RegisterConsoleCommand = true)] + public static string DumpSpawnBiomes(string classIdOrTechType) + { + string classId = Guid.TryParse(classIdOrTechType, out Guid guid) ? guid.ToString() + : UWE.Utils.TryParseEnum(classIdOrTechType, out TechType techType) ? CraftData.GetClassIdForTechType(techType) + : null; + + if (classId is null) return MessageHelpers.TechTypeNotFound(classIdOrTechType); + + CSVEntitySpawner spawner = GameObject.FindObjectOfType<CSVEntitySpawner>(); + LootDistributionData lootData = spawner ? spawner.lootDistribution : BiomeHelpers.baseGameLootData; + + return lootData.srcDistribution.TryGetValue(classId, out LootDistributionData.SrcData srcData) + ? string.Join(",", srcData.distribution.Select(bd => bd.biome)) + : $"No data for {classIdOrTechType}"; + } } diff --git a/SCHIZO/Helpers/BiomeHelpers.cs b/SCHIZO/Helpers/BiomeHelpers.cs index 70ceb82a..9c0ab33a 100644 --- a/SCHIZO/Helpers/BiomeHelpers.cs +++ b/SCHIZO/Helpers/BiomeHelpers.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Text.RegularExpressions; namespace SCHIZO.Helpers; @@ -14,11 +16,36 @@ public static IEnumerable<BiomeType> GetBiomesEndingInAny(params string[] filter .Where(biome => filters.Any(f => biome.ToString().EndsWith(f))); } - public static IEnumerable<BiomeType> GetBiomesContainingAny(params string[] filters) + public static IEnumerable<BiomeType> GetBiomesMatching([StringSyntax("Regex")] params string[] filters) { if (filters.Length == 0) return []; + + List<Regex> regexes = filters.Select(f => new Regex(f, RegexOptions.Compiled | RegexOptions.Singleline)).ToList(); return Enum.GetValues(typeof(BiomeType)) .Cast<BiomeType>() - .Where(biome => filters.Any(f => biome.ToString().Contains(f))); + .Where(biome => regexes.Any(f => f.IsMatch(biome.ToString()))); + } + + // unfortunately not accessible in main menu (when we register our creatures) + // hopefully it's not too big of an impact on load time + internal static readonly LootDistributionData baseGameLootData = LootDistributionData.Load("Balance/EntityDistributions"); + + public static IEnumerable<BiomeType> GetBiomesFor(IEnumerable<TechType> techTypes) + { + HashSet<BiomeType> set = []; + foreach (TechType tt in techTypes) + { + string classId = CraftData.GetClassIdForTechType(tt); + if (!baseGameLootData.srcDistribution.TryGetValue(classId, out LootDistributionData.SrcData srcData)) + { + LOGGER.LogWarning($"Could not get biomes for {tt} - not in loot data!"); + continue; + } + + List<BiomeType> biomes = srcData.distribution.Select(bd => bd.biome).ToList(); + set.AddRange(biomes); + } + LOGGER.LogWarning(string.Join(",", set.Select(b => b.ToString()))); + return set; } } diff --git a/SCHIZO/Resources/AssetBundles/Assets.cs b/SCHIZO/Resources/AssetBundles/Assets.cs index e9c851ab..fe4acfee 100644 --- a/SCHIZO/Resources/AssetBundles/Assets.cs +++ b/SCHIZO/Resources/AssetBundles/Assets.cs @@ -12,7 +12,7 @@ namespace SCHIZO.Resources; public static class Assets { - private const int _rnd = 1702156462; + private const int _rnd = 1101407721; private static readonly UnityEngine.AssetBundle _a = ResourceManager.GetAssetBundle("assets"); diff --git a/SCHIZO/Resources/AssetBundles/assets b/SCHIZO/Resources/AssetBundles/assets index 1473f63f..24b65780 100644 Binary files a/SCHIZO/Resources/AssetBundles/assets and b/SCHIZO/Resources/AssetBundles/assets differ diff --git a/SCHIZO/Spawns/BiomeSpawnData.cs b/SCHIZO/Spawns/BiomeSpawnData.cs index 3d5fbd9c..8628dcee 100644 --- a/SCHIZO/Spawns/BiomeSpawnData.cs +++ b/SCHIZO/Spawns/BiomeSpawnData.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using SCHIZO.Helpers; namespace SCHIZO.Spawns; @@ -16,7 +17,8 @@ public IEnumerable<BiomeType> GetBiomes() BiomeSpawnLocation.OpenWater => BiomeHelpers.GetBiomesEndingInAny("_Open", "_Open_CreatureOnly"), BiomeSpawnLocation.Surfaces => BiomeHelpers.GetBiomesEndingInAny("Ground", "Wall", "Floor", "Ledge", "CaveEntrance", "CavePlants", "SandFlat", "ShellTunnelHuge", "Grass", "Sand", "Mountains", "Beach"), - BiomeSpawnLocation.Custom => BiomeHelpers.GetBiomesContainingAny(Data.biomeFilters), + BiomeSpawnLocation.Custom => BiomeHelpers.GetBiomesMatching(Data.biomeFilters), + BiomeSpawnLocation.CopyFromOthers => BiomeHelpers.GetBiomesFor(Data.copyFrom.Cast<TechType>()), _ => throw new InvalidOperationException($"Invalid spawn location {Location}") }; } diff --git a/Unity/Assets/Editor/Scripts/Extensions/SerializedPropertyExtensions.cs b/Unity/Assets/Editor/Scripts/Extensions/SerializedPropertyExtensions.cs index b323eaf1..9708eb37 100644 --- a/Unity/Assets/Editor/Scripts/Extensions/SerializedPropertyExtensions.cs +++ b/Unity/Assets/Editor/Scripts/Extensions/SerializedPropertyExtensions.cs @@ -28,7 +28,7 @@ private static GetFieldInfo Setup() public static T GetCustomAttribute<T>(this SerializedProperty prop) where T : Attribute { FieldInfo info = prop.GetFieldInfoAndStaticType(out _); - return info.GetCustomAttribute<T>(); + return info?.GetCustomAttribute<T>(); } public static bool TryGetAttributeInHierarchy<T>(this SerializedProperty prop, out T attribute, out SerializedProperty ancestorWithAttribute) where T : Attribute diff --git a/Unity/Assets/Mod/Anneel/Spawns.asset b/Unity/Assets/Mod/Anneel/Spawns.asset index 2c482a1e..1f32b140 100644 --- a/Unity/Assets/Mod/Anneel/Spawns.asset +++ b/Unity/Assets/Mod/Anneel/Spawns.asset @@ -11,15 +11,17 @@ MonoBehaviour: m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 31176ccc850eb4a40a6800859f45666b, type: 3} m_Name: Spawns - m_EditorClassIdentifier: + m_EditorClassIdentifier: subnautica: spawn: 1 - spawnLocation: 0 + spawnLocation: 3 biomeFilters: [] + copyFrom: c8090000d3090000ce090000d1090000c5090000e3090000fa090000d7090000d8090000f2090000d5090000ca090000 belowZero: spawn: 1 spawnLocation: 0 biomeFilters: [] + copyFrom: rules: - count: 1 probability: 0.01 diff --git a/Unity/Assets/Mod/Ermfish/Spawns.asset b/Unity/Assets/Mod/Ermfish/Spawns.asset index f0131c6f..8bb97b07 100644 --- a/Unity/Assets/Mod/Ermfish/Spawns.asset +++ b/Unity/Assets/Mod/Ermfish/Spawns.asset @@ -11,15 +11,17 @@ MonoBehaviour: m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 31176ccc850eb4a40a6800859f45666b, type: 3} m_Name: Spawns - m_EditorClassIdentifier: + m_EditorClassIdentifier: subnautica: spawn: 1 - spawnLocation: 0 + spawnLocation: 3 biomeFilters: [] + copyFrom: c8090000d3090000ce090000d1090000c5090000e3090000fa090000d7090000d8090000f2090000 belowZero: spawn: 1 spawnLocation: 0 biomeFilters: [] + copyFrom: rules: - count: 1 probability: 0.025 diff --git a/Unity/Assets/Mod/Ermshark/Spawns.asset b/Unity/Assets/Mod/Ermshark/Spawns.asset index 7f396e3e..b6e6aa70 100644 --- a/Unity/Assets/Mod/Ermshark/Spawns.asset +++ b/Unity/Assets/Mod/Ermshark/Spawns.asset @@ -11,15 +11,17 @@ MonoBehaviour: m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 31176ccc850eb4a40a6800859f45666b, type: 3} m_Name: Spawns - m_EditorClassIdentifier: + m_EditorClassIdentifier: subnautica: spawn: 1 - spawnLocation: 0 + spawnLocation: 3 biomeFilters: [] + copyFrom: c8090000d3090000ce090000d1090000c5090000e3090000fa090000d7090000d8090000f2090000d5090000ca090000e6090000f3090000d0090000f1090000e7090000f7090000f8090000db090000 belowZero: spawn: 1 spawnLocation: 0 biomeFilters: [] + copyFrom: rules: - count: 1 - probability: 0.005 + probability: 0.001 diff --git a/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnData.cs b/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnData.cs index 7f73d863..b38003ac 100644 --- a/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnData.cs +++ b/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnData.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; +using SCHIZO.Interop.Subnautica.Enums; +using SCHIZO.Registering; using TriInspector; using UnityEngine; @@ -9,9 +11,9 @@ namespace SCHIZO.Spawns [CreateAssetMenu(menuName = "SCHIZO/Spawns/Biome Spawn Data")] public sealed partial class BiomeSpawnData : ScriptableObject { - [SerializeField, UsedImplicitly] + [SerializeField, UsedImplicitly, Game(Game.Subnautica)] private GameSpecificData subnautica; - [SerializeField, UsedImplicitly] + [SerializeField, UsedImplicitly, Game(Game.BelowZero)] private GameSpecificData belowZero; [TableList] public List<BiomeSpawnRule> rules; @@ -24,6 +26,8 @@ public struct GameSpecificData public BiomeSpawnLocation spawnLocation; [EnableIf(nameof(spawn)), ShowIf(nameof(spawnLocation), BiomeSpawnLocation.Custom)] public string[] biomeFilters; + [EnableIf(nameof(spawn)), ShowIf(nameof(spawnLocation), BiomeSpawnLocation.CopyFromOthers)] + public TechType_All[] copyFrom; } } } diff --git a/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnLocation.cs b/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnLocation.cs index c106984c..6684c4ef 100644 --- a/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnLocation.cs +++ b/Unity/Assets/Scripts/SCHIZO/Spawns/BiomeSpawnLocation.cs @@ -5,5 +5,6 @@ public enum BiomeSpawnLocation OpenWater, Surfaces, Custom, + CopyFromOthers, } }