using Barotrauma; using MoreLevelContent.Missions; using MoreLevelContent.Shared.Data; using System.Collections.Generic; using System.Xml.Linq; using System; using System.Linq; using MoreLevelContent.Shared.Generation.Pirate; using Microsoft.Xna.Framework; namespace MoreLevelContent.Shared.Generation { internal partial class PirateOutpostMapModule : MapModule { List _DisallowedLocations; protected override void InitProjSpecific() { _DisallowedLocations = new(); } public override void OnLevelDataGenerate(LevelData __instance, LocationConnection locationConnection) => SetPirateData(__instance, __instance.MLC(), locationConnection); public override void OnMapLoad(Map __instance) { // Map has no pirate outposts, lets generate some if (!__instance.Connections.Any(c => c.LevelData.MLC().PirateData.HasPirateBase)) { Log.Debug("Map has no pirate bases, adding some..."); for (int i = 0; i < __instance.Connections.Count; i++) { var connection = __instance.Connections[i]; SetPirateData(connection.LevelData, connection.LevelData.MLC(), connection); } } else { Log.Debug("Map has pirate bases"); } } void SetPirateData(LevelData levelData, LevelData_MLCData additionalData, LocationConnection locationConnection) { PirateSpawnData spawnData = new PirateSpawnData(levelData, locationConnection); // Prevent pirate outposts from spawning too clustered together if (spawnData.WillSpawn && locationConnection.Locations.Any(l => _DisallowedLocations.Contains(l))) { // Unless they're husked, then that's fine if (!spawnData.Husked) { spawnData.WillSpawn = false; spawnData.Husked = false; } } // Add nearby locations to disallowed list if (spawnData.WillSpawn) { _DisallowedLocations.AddRange(locationConnection.Locations); } additionalData.PirateData = new PirateData(spawnData); } } internal class PirateSpawnData { public PirateSpawnData(LevelData levelData, LocationConnection connection) { Random rand = new MTRandom(ToolBox.StringToInt(levelData.Seed)); UpdatePirateSpawnData(rand, levelData, connection); int spawnInt = rand.Next(100); int huskInt = rand.Next(100); WillSpawn = _ModifiedSpawnChance > spawnInt; Husked = _ModifiedHuskChance > huskInt; } public bool WillSpawn { get; set; } public bool Husked { get; set; } public float PirateDifficulty { get; private set; } public override string ToString() => $"Will Spawn: {WillSpawn}, Is Husked: {Husked}"; private float _ModifiedSpawnChance; private float _ModifiedHuskChance; private void UpdatePirateSpawnData(Random rand, LevelData levelData, LocationConnection connection) { var levelDiff = levelData.Difficulty; float a = PirateOutpostDirector.Config.PeakSpawnChance; float b = a / 2500; float c = MathF.Pow(levelDiff - 50.0f, 2); var spawnChance = (-b * c) + a; var huskChance = MathF.Max(PirateOutpostDirector.Config.BaseHuskChance, levelDiff / 10); ModifyChances(); _ModifiedSpawnChance = spawnChance; _ModifiedHuskChance = huskChance; float difficultyNoise = Math.Abs(MathHelper.Lerp(-PirateOutpostDirector.Config.DifficultyNoise, PirateOutpostDirector.Config.DifficultyNoise, (float)rand.NextDouble())); PirateDifficulty = levelDiff + difficultyNoise; void ModifyChances() { // Don't spawn bases on routes with an abyss creature if (levelData.HasHuntingGrounds) { spawnChance = 0; Log.Debug("Set spawn chance to 0 due to hunting grounds"); return; } foreach (var location in connection.Locations) { var identifier = location.Type.Identifier; if (CompatabilityHelper.Instance.DynamicEuropaInstalled) { // Double spawn chance on routes leading to pirate outposts ModifySpawn("PirateOutpost", 2); // Don't spawn on areas leading to military ModifySpawn("Camp", 0); ModifySpawn("Base", 0); ModifySpawn("Blockade", 0); ModifyHusk("HuskgroundsDE", 10f); ModifyHusk("OuterHuskLair", 5f); } // Increased chance to spawn next to natural formations ModifySpawn("None", 1.5f); // Increased chance to spawn next to abandoned outposts ModifySpawn("Abandoned", 1.3f); // Never spawn if one of the connections is a military outpost ModifySpawn("Military", 0); // No chance if city ModifySpawn("City", 0f); // Slightly reduced chance if leading to a outpost ModifySpawn("Outpost", 0.25f); // Slightly reduced chance if leading to a research outpost ModifySpawn("Research", 0.25f); // Slightly reduced chance if leading to a research outpost ModifySpawn("Mine", 0.25f); // Never spawn leading to the end ModifySpawn("EndLocation", 0); void ModifySpawn(string input, float multi) { if (identifier == input) spawnChance *= multi; //Log.Debug($"M SC {input}: {spawnChance}"); } void ModifyHusk(string input, float multi) { if (identifier == input) spawnChance *= multi; //Log.Debug($"M HC {input}: {spawnChance}"); } } } } } }