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

159 lines
6.5 KiBLFS
C#
Executable File

using Barotrauma;
using Microsoft.Xna.Framework;
using MoreLevelContent.Shared.Utils;
using System;
using System.Linq;
using System.Xml.Linq;
namespace MoreLevelContent.Shared.Generation
{
internal abstract class MapModule
{
public MapModule() => InitProjSpecific();
protected MapDirector Instance => MapDirector.Instance;
protected abstract void InitProjSpecific();
protected static bool TryGetMissionByTag(string tag, LevelData data, out MissionPrefab missionPrefab, string forceMission = "")
{
var orderedMissions = MissionPrefab.Prefabs.Where(m => m.Tags.Contains(tag)).OrderBy(m => m.UintIdentifier);
if (!string.IsNullOrEmpty(forceMission))
{
orderedMissions = orderedMissions.Where(m => m.Identifier == forceMission).OrderBy(m => m.UintIdentifier);
}
Random rand = new MTRandom(ToolBox.StringToInt(data.Seed));
missionPrefab = ToolBox.SelectWeightedRandom(orderedMissions, p => p.Commonness, rand);
return missionPrefab != null;
}
protected LocationConnection WalkConnection(Location start, Random rand, int preferedWalkDistance)
{
// Since we do a connection step at the end of the process, there's one step implict in every walk
// so we subtract a step here
int actualWalkDist = preferedWalkDistance - 1;
if (actualWalkDist <= 0)
{
return GetConnectionWeighted(start, rand);
}
Location location = WalkLocation(start, rand, actualWalkDist);
return GetConnectionWeighted(location, rand);
}
protected Location WalkLocation(Location start, Random rand, int preferedWalkDistance, LocationConnection from = null)
{
var filteredConnections = start.Connections.Where(c => c != from);
if (!filteredConnections.Any())
{
return start;
}
LocationConnection connectionToTravel = ToolBox.SelectWeightedRandom(
filteredConnections.ToList(),
filteredConnections.Select(c => GetConnectionWeight(start, c)).ToList(),
rand);
Location walkedLocation = connectionToTravel.OtherLocation(start);
preferedWalkDistance--;
// if we haven't walked our wanted dist or
if (preferedWalkDistance > 0) walkedLocation = WalkLocation(walkedLocation, rand, preferedWalkDistance);
return walkedLocation;
}
static LocationConnection GetConnectionWeighted(Location location, Random rand)
{
LocationConnection connectionToTravel = ToolBox.SelectWeightedRandom(
location.Connections,
location.Connections.Select(c => GetConnectionWeight(location, c)).ToList(),
rand);
return connectionToTravel;
}
static float GetConnectionWeight(Location location, LocationConnection c)
{
// get the destination of this connection
Location destination = c.OtherLocation(location);
if (destination == null) { return 0; }
float minWeight = 0.0001f;
float lowWeight = 0.2f;
float normalWeight = 1.0f;
float maxWeight = 2.0f;
// prefer connections we haven't passed through
float weight = c.Passed ? lowWeight : normalWeight;
if (location.Biome.AllowedZones.Contains(1))
{
// In the first biome, give a stronger preference for locations that are farther to the right)
float diff = destination.MapPosition.X - location.MapPosition.X;
if (diff < 0)
{
weight *= 0.1f;
}
else
{
float maxRelevantDiff = 300;
weight = MathHelper.Lerp(weight, maxWeight, MathUtils.InverseLerp(0, maxRelevantDiff, diff));
}
}
else if (destination.MapPosition.X > location.MapPosition.X)
{
weight *= 2.0f;
}
if (destination.IsRadiated())
{
weight *= 0.001f;
}
// Prefer locations that have been revealed
if (!destination.Discovered)
{
weight *= 0.5f;
}
return MathHelper.Clamp(weight, minWeight, maxWeight);
}
protected void SendChatUpdate(string msg)
{
#if CLIENT
if (GameMain.Client != null)
{
GameMain.Client.AddChatMessage(msg, Barotrauma.Networking.ChatMessageType.Default, TextManager.Get("mlc.navigationannouce").Value);
}
else
{
GameMain.GameSession?.GameMode.CrewManager.AddSinglePlayerChatMessage(
TextManager.Get("mlc.navigationannouce").Value,
msg,
Barotrauma.Networking.ChatMessageType.Default,
sender: null);
}
#endif
}
protected void AddNewsStory(string tag, LocationConnection connection)
{
#if CLIENT
string randomTag = MLCUtils.GetRandomTag(tag, connection.LevelData);
string msg = TextManager.GetWithVariables(randomTag, ("[location1]", $"‖color:gui.orange‖{connection.Locations[0].DisplayName}‖end‖"), ("[location2]", $"‖color:gui.orange‖{connection.Locations[1].DisplayName}‖end‖")).Value;
Log.Debug($"Added text tag {randomTag} : {msg} to news ticket");
MapDirector.Instance.AddNewsStory(msg);
#endif
}
public virtual void OnAddExtraMissions(CampaignMode __instance, LevelData levelData) { }
public virtual void OnPreRoundStart(LevelData levelData) { }
public virtual void OnPostRoundStart(LevelData levelData) { }
public virtual void OnLevelDataGenerate(LevelData __instance, LocationConnection locationConnection) { }
public virtual void OnProgressWorld(Map __instance) { }
public virtual void OnLevelDataLoad(LevelData __instance, XElement element) { }
public virtual void OnLevelDataSave(LevelData __instance, XElement parentElement) { }
public virtual void OnMapLoad(Map __instance) { }
public virtual void OnLevelGenerate(LevelData levelData, bool mirror) { }
}
}