Files
BarotraumaModServer/LocalMods/More Level Content/CSharp/Shared/Generation/Map/Modules/PirateOutpostMapModule.cs
2026-06-09 00:42:10 +03:00

175 lines
6.6 KiBLFS
C#
Executable File

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<Location> _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}");
}
}
}
}
}
}