159 lines
6.4 KiB
C#
Executable File
159 lines
6.4 KiB
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) { }
|
|
}
|
|
}
|