Hostility Fix + Story Work
Fixed various bugs caused by triggering wormhole animation multiple times Sector -> Galaxy Fixed bug in hostility system; deserialized entities' PresencePermitted was silently throwing an exception (due to Faction being null during initialization) and thus never updating in response to security level changes Worked a bit on story processing
This commit is contained in:
parent
710d17ff4c
commit
2f98904614
26 changed files with 301 additions and 255 deletions
|
|
@ -146,6 +146,15 @@ public abstract class Entity
|
|||
//ItemManager.Log($"Entity {Name} is activating!");
|
||||
_active = true;
|
||||
Heatstroke = 0;
|
||||
|
||||
// The entity's presence is permitted when its faction owns the zone, or the current security level at its location is low enough
|
||||
PresencePermitted = new ReadOnlyReactiveProperty<bool>(CurrentSecurityLevel.Select(security =>
|
||||
{
|
||||
var factionRelationship = GetFactionRelationship(Zone.GalaxyZone.Owner);
|
||||
var presencePermitted = IsPresencePermitted(factionRelationship, security);
|
||||
return presencePermitted;
|
||||
}), initialValue: true);
|
||||
|
||||
foreach (var item in Equipment)
|
||||
foreach (var behavior in item.Behaviors)
|
||||
{
|
||||
|
|
@ -269,9 +278,7 @@ public abstract class Entity
|
|||
.Merge(HypothermiaDeath.Select(_ => CauseOfDeath.Hypothermia))
|
||||
.Merge(ItemDestroyed.Where(i=>i.GetBehavior<Cockpit>()!=null).Select(_ => CauseOfDeath.CockpitDestroyed));
|
||||
|
||||
// The entity's presence is permitted when its faction owns the zone, or the current security level at its location is low enough
|
||||
PresencePermitted = new ReadOnlyReactiveProperty<bool>(CurrentSecurityLevel.Select(security =>
|
||||
IsPresencePermitted(GetFactionRelationship(Zone.SectorZone.Owner), security)), true);
|
||||
//CurrentSecurityLevel.Value = SecurityLevel.Open;
|
||||
}
|
||||
|
||||
public bool IsHostileTo(Entity other, bool recursive = false)
|
||||
|
|
@ -281,8 +288,8 @@ public abstract class Entity
|
|||
|
||||
// TODO: Inter-faction hostility
|
||||
// When the entity faction owns the zone, they are hostile to trespassers or those hostile to them
|
||||
if (Faction.ID == Zone.SectorZone.Owner.ID)
|
||||
return recursive ? !other.PresencePermitted.Value : !other.PresencePermitted.Value || other.IsHostileTo(this, true);
|
||||
if (Faction.ID == Zone.GalaxyZone.Owner.ID)
|
||||
return recursive ? !(other.PresencePermitted?.Value ?? true) : !(other.PresencePermitted?.Value ?? true)|| other.IsHostileTo(this, true);
|
||||
|
||||
return !recursive && other.IsHostileTo(this, true);
|
||||
}
|
||||
|
|
@ -293,7 +300,7 @@ public abstract class Entity
|
|||
if (faction == null)
|
||||
return FactionRelationship.Neutral;
|
||||
if (this is Ship {IsPlayerShip: true})
|
||||
return Zone.Sector.FactionRelationships[faction];
|
||||
return Zone.Galaxy.FactionRelationships[faction];
|
||||
return faction.ID == Faction.ID ? FactionRelationship.Beloved : FactionRelationship.Neutral;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,12 @@ public enum CompoundCommodityCategory
|
|||
Assemblies = 5
|
||||
}
|
||||
|
||||
public enum LocationType
|
||||
{
|
||||
Station,
|
||||
Planet
|
||||
}
|
||||
|
||||
public enum FactionRelationship
|
||||
{
|
||||
Hated = 0, // Kill on sight
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DataStructures.ViliWonka.Heap;
|
||||
using Ink.Runtime;
|
||||
using MIConvexHull;
|
||||
using JM.LinqFaster;
|
||||
using UniRx;
|
||||
|
|
@ -12,25 +13,25 @@ using Unity.Mathematics;
|
|||
using static Unity.Mathematics.math;
|
||||
using Random = Unity.Mathematics.Random;
|
||||
|
||||
public class Sector
|
||||
public class Galaxy
|
||||
{
|
||||
public Dictionary<Faction, SectorZone> HomeZones = new Dictionary<Faction, SectorZone>();
|
||||
public Dictionary<Faction, SectorZone> BossZones = new Dictionary<Faction, SectorZone>();
|
||||
public HashSet<SectorZone> DiscoveredZones = new HashSet<SectorZone>();
|
||||
public Dictionary<Faction, GalaxyZone> HomeZones = new Dictionary<Faction, GalaxyZone>();
|
||||
public Dictionary<Faction, GalaxyZone> BossZones = new Dictionary<Faction, GalaxyZone>();
|
||||
public HashSet<GalaxyZone> DiscoveredZones = new HashSet<GalaxyZone>();
|
||||
|
||||
public SectorBackgroundSettings Background { get; }
|
||||
public NameGeneratorSettings NameGeneratorSettings { get; }
|
||||
public Faction[] Factions { get; }
|
||||
public SectorZone[] Zones { get; }
|
||||
public SectorZone Entrance { get; }
|
||||
public SectorZone Exit { get; }
|
||||
public GalaxyZone[] Zones { get; }
|
||||
public GalaxyZone Entrance { get; }
|
||||
public GalaxyZone Exit { get; }
|
||||
public Dictionary<Faction, FactionRelationship> FactionRelationships { get; } = new Dictionary<Faction, FactionRelationship>();
|
||||
|
||||
private HashSet<Guid> _containedFactions;
|
||||
private SectorZone[] _exitPath;
|
||||
private GalaxyZone[] _exitPath;
|
||||
private Dictionary<Faction, MarkovNameGenerator> _nameGenerators = new Dictionary<Faction, MarkovNameGenerator>();
|
||||
|
||||
public SectorZone[] ExitPath
|
||||
public GalaxyZone[] ExitPath
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -40,7 +41,7 @@ public class Sector
|
|||
}
|
||||
}
|
||||
|
||||
public Sector(CultCache cultCache, SavedGame savedGame)
|
||||
public Galaxy(CultCache cultCache, SavedGame savedGame)
|
||||
{
|
||||
Background = savedGame.Background;
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ public class Sector
|
|||
|
||||
Zones = savedGame.Zones.Select(zone =>
|
||||
{
|
||||
return new SectorZone
|
||||
return new GalaxyZone
|
||||
{
|
||||
Name = zone.Name,
|
||||
Position = zone.Position,
|
||||
|
|
@ -82,7 +83,7 @@ public class Sector
|
|||
CalculateDistanceMatrix();
|
||||
}
|
||||
|
||||
public Sector(
|
||||
public Galaxy(
|
||||
SectorGenerationSettings settings,
|
||||
SectorBackgroundSettings background,
|
||||
NameGeneratorSettings nameGeneratorSettings,
|
||||
|
|
@ -121,7 +122,7 @@ public class Sector
|
|||
if(progressCallback!=null) Thread.Sleep(500); // Inserting Delay to make it seem like it's doing more work lmao
|
||||
}
|
||||
|
||||
public Sector(
|
||||
public Galaxy(
|
||||
TutorialGenerationSettings settings,
|
||||
SectorBackgroundSettings background,
|
||||
NameGeneratorSettings nameGeneratorSettings,
|
||||
|
|
@ -229,14 +230,14 @@ public class Sector
|
|||
if(progressCallback!=null) Thread.Sleep(500); // Inserting Delay to make it seem like it's doing more work lmao
|
||||
}
|
||||
|
||||
private SectorZone[] GenerateZones(int zoneCount, ref Random random, Action<string> progressCallback = null)
|
||||
private GalaxyZone[] GenerateZones(int zoneCount, ref Random random, Action<string> progressCallback = null)
|
||||
{
|
||||
var outputSamples = WeightedSampleElimination.GeneratePoints(zoneCount,
|
||||
ref random,
|
||||
Background.CloudDensity,
|
||||
v => (.2f - lengthsq(v - float2(.5f))) * 4,
|
||||
progressCallback);
|
||||
return outputSamples.Select(v => new SectorZone {Position = v}).ToArray();
|
||||
return outputSamples.Select(v => new GalaxyZone {Position = v}).ToArray();
|
||||
}
|
||||
|
||||
private void PlaceFactionsMain(int bossCount, Action<string> progressCallback = null)
|
||||
|
|
@ -343,9 +344,9 @@ public class Sector
|
|||
if (progressCallback != null) Thread.Sleep(500); // Inserting Delay to make it seem like it's doing more work lmao
|
||||
|
||||
// Create a delaunay triangulation to connect adjacent sectors
|
||||
var triangulation = DelaunayTriangulation<Vertex2<SectorZone>, Cell2<SectorZone>>
|
||||
.Create(Zones.Select(z => new Vertex2<SectorZone>(z.Position, z)).ToList(), 1e-7f);
|
||||
var links = new HashSet<(SectorZone, SectorZone)>();
|
||||
var triangulation = DelaunayTriangulation<Vertex2<GalaxyZone>, Cell2<GalaxyZone>>
|
||||
.Create(Zones.Select(z => new Vertex2<GalaxyZone>(z.Position, z)).ToList(), 1e-7f);
|
||||
var links = new HashSet<(GalaxyZone, GalaxyZone)>();
|
||||
foreach (var cell in triangulation.Cells)
|
||||
{
|
||||
if (!links.Contains((cell.Vertices[0].StoredObject, cell.Vertices[1].StoredObject)) &&
|
||||
|
|
@ -377,14 +378,14 @@ public class Sector
|
|||
link.Item2.AdjacentZones.Add(link.Item1);
|
||||
}
|
||||
|
||||
float LinkWeight((SectorZone, SectorZone) link)
|
||||
float LinkWeight((GalaxyZone, GalaxyZone) link)
|
||||
{
|
||||
return 1 / saturate(Background.CloudDensity((link.Item1.Position + link.Item2.Position) / 2)) *
|
||||
lengthsq(link.Item1.Position - link.Item2.Position) *
|
||||
(link.Item1.AdjacentZones.Count - 1) * (link.Item2.AdjacentZones.Count - 1);
|
||||
}
|
||||
|
||||
var heap = new MaxHeap<(SectorZone, SectorZone)>(links.Count);
|
||||
var heap = new MaxHeap<(GalaxyZone, GalaxyZone)>(links.Count);
|
||||
foreach (var link in links) heap.PushObj(link, LinkWeight(link));
|
||||
while (heap.Count > linkDensity * links.Count)
|
||||
{
|
||||
|
|
@ -430,12 +431,12 @@ public class Sector
|
|||
{
|
||||
public float Cost;
|
||||
public DijkstraVertex Parent;
|
||||
public SectorZone Zone;
|
||||
public GalaxyZone Zone;
|
||||
}
|
||||
|
||||
public Dictionary<SectorZone, int> ConnectedRegionDistance(SectorZone v)
|
||||
public Dictionary<GalaxyZone, int> ConnectedRegionDistance(GalaxyZone v)
|
||||
{
|
||||
var members = new Dictionary<SectorZone, int> {{v, 0}};
|
||||
var members = new Dictionary<GalaxyZone, int> {{v, 0}};
|
||||
int cost = 1;
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -455,36 +456,36 @@ public class Sector
|
|||
}
|
||||
}
|
||||
|
||||
public HashSet<SectorZone> ConnectedRegion(
|
||||
SectorZone v,
|
||||
SectorZone ignoreLinkSource,
|
||||
SectorZone ignoreLinkTarget,
|
||||
public HashSet<GalaxyZone> ConnectedRegion(
|
||||
GalaxyZone v,
|
||||
GalaxyZone ignoreLinkSource,
|
||||
GalaxyZone ignoreLinkTarget,
|
||||
int maxDistance = int.MaxValue)
|
||||
{
|
||||
return ConnectedRegion(v, x => x.Item1 != ignoreLinkSource || x.Item2 != ignoreLinkTarget, maxDistance);
|
||||
}
|
||||
|
||||
public HashSet<SectorZone> ConnectedRegion(
|
||||
SectorZone v,
|
||||
SectorZone ignoreZone,
|
||||
public HashSet<GalaxyZone> ConnectedRegion(
|
||||
GalaxyZone v,
|
||||
GalaxyZone ignoreZone,
|
||||
int maxDistance = int.MaxValue)
|
||||
{
|
||||
return ConnectedRegion(v, x => x.Item2 != ignoreZone, maxDistance);
|
||||
}
|
||||
|
||||
public HashSet<SectorZone> ConnectedRegion(
|
||||
SectorZone v,
|
||||
public HashSet<GalaxyZone> ConnectedRegion(
|
||||
GalaxyZone v,
|
||||
int maxDistance = int.MaxValue)
|
||||
{
|
||||
return ConnectedRegion(v, x => true, maxDistance);
|
||||
}
|
||||
|
||||
public HashSet<SectorZone> ConnectedRegion(
|
||||
SectorZone v,
|
||||
Predicate<(SectorZone source, SectorZone target)> linkFilter,
|
||||
public HashSet<GalaxyZone> ConnectedRegion(
|
||||
GalaxyZone v,
|
||||
Predicate<(GalaxyZone source, GalaxyZone target)> linkFilter,
|
||||
int maxDistance = int.MaxValue)
|
||||
{
|
||||
var visited = new HashSet<SectorZone> {v};
|
||||
var visited = new HashSet<GalaxyZone> {v};
|
||||
int cost = 1;
|
||||
while (true)
|
||||
{
|
||||
|
|
@ -504,12 +505,12 @@ public class Sector
|
|||
}
|
||||
}
|
||||
|
||||
public SectorZone[] FindPath(SectorZone source, SectorZone target, bool bestFirst = false)
|
||||
public GalaxyZone[] FindPath(GalaxyZone source, GalaxyZone target, bool bestFirst = false)
|
||||
{
|
||||
MinHeap<DijkstraVertex> unsearchedNodes = new MinHeap<DijkstraVertex>();
|
||||
unsearchedNodes.PushObj(new DijkstraVertex{Zone = source}, 0);
|
||||
//SortedList<float,DijkstraVertex> members = new SortedList<float,DijkstraVertex>{{0, new DijkstraVertex{Zone = source}}};
|
||||
var searched = new HashSet<SectorZone>();
|
||||
var searched = new HashSet<GalaxyZone>();
|
||||
while (true)
|
||||
{
|
||||
if(unsearchedNodes.Count == 0) return null; // No nodes left unsearched
|
||||
|
|
@ -523,7 +524,7 @@ public class Sector
|
|||
return path.Select(dv => dv.Zone).ToArray();
|
||||
}
|
||||
// For each adjacent star (filter already visited stars unless heuristic is in use)
|
||||
IEnumerable<SectorZone> zonesToSearch = s.Zone.AdjacentZones;
|
||||
IEnumerable<GalaxyZone> zonesToSearch = s.Zone.AdjacentZones;
|
||||
if (!bestFirst) zonesToSearch = zonesToSearch.Where(z => !searched.Contains(z));
|
||||
foreach (var dijkstraStar in zonesToSearch
|
||||
// Cost is parent cost plus distance squared
|
||||
|
|
@ -535,15 +536,33 @@ public class Sector
|
|||
}
|
||||
}
|
||||
|
||||
public class SectorZone
|
||||
public class GalaxyZone
|
||||
{
|
||||
public string Name;
|
||||
public float2 Position;
|
||||
public List<SectorZone> AdjacentZones = new List<SectorZone>();
|
||||
public List<GalaxyZone> AdjacentZones = new List<GalaxyZone>();
|
||||
public int Isolation;
|
||||
public Dictionary<SectorZone, int> Distance;
|
||||
public Dictionary<GalaxyZone, int> Distance;
|
||||
public Faction[] Factions;
|
||||
public Faction Owner;
|
||||
public Zone Contents;
|
||||
public ZonePack PackedContents;
|
||||
public bool NamedZone;
|
||||
public List<LocationStory> Locations = new List<LocationStory>();
|
||||
}
|
||||
|
||||
public class GalaxyQuest
|
||||
{
|
||||
public Story Story;
|
||||
public Dictionary<string, LocationStory> Locations = new Dictionary<string, LocationStory>();
|
||||
}
|
||||
|
||||
public class LocationStory
|
||||
{
|
||||
public string FileName;
|
||||
public string Name;
|
||||
public Story Story;
|
||||
public Faction Faction;
|
||||
public SecurityLevel Security;
|
||||
public LocationType Type;
|
||||
}
|
||||
|
|
@ -10,22 +10,22 @@ public class LoadoutGenerator
|
|||
{
|
||||
public Random Random;
|
||||
public ItemManager ItemManager { get; }
|
||||
public Sector Sector { get; }
|
||||
public SectorZone Zone { get; }
|
||||
public Galaxy Galaxy { get; }
|
||||
public GalaxyZone Zone { get; }
|
||||
public Faction Faction { get; }
|
||||
public float PriceExponent { get; }
|
||||
|
||||
public LoadoutGenerator(
|
||||
ref Random random,
|
||||
ItemManager itemManager,
|
||||
Sector sector,
|
||||
SectorZone zone,
|
||||
Galaxy galaxy,
|
||||
GalaxyZone zone,
|
||||
Faction faction,
|
||||
float priceExponent)
|
||||
{
|
||||
Random = random;
|
||||
ItemManager = itemManager;
|
||||
Sector = sector;
|
||||
Galaxy = galaxy;
|
||||
Zone = zone;
|
||||
Faction = faction;
|
||||
PriceExponent = priceExponent;
|
||||
|
|
@ -107,12 +107,12 @@ public class LoadoutGenerator
|
|||
(hullFilter?.Invoke(item) ?? true) &&
|
||||
item.HullType == type &&
|
||||
item.Manufacturer != Guid.Empty &&
|
||||
(Sector?.ContainsFaction(item.Manufacturer) ?? true) &&
|
||||
(Galaxy?.ContainsFaction(item.Manufacturer) ?? true) &&
|
||||
(Faction == null || item.Manufacturer == Faction.ID || Faction.Allegiance.ContainsKey(item.Manufacturer)))
|
||||
.WeightedRandomElements(ref Random,
|
||||
item =>
|
||||
(Faction == null || item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance[item.Manufacturer]) / // Prioritize items from allied manufacturers
|
||||
(Zone?.Distance[Sector.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] ?? 1) / // Penalize distance to manufacturer headquarters
|
||||
(Zone?.Distance[Galaxy.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] ?? 1) / // Penalize distance to manufacturer headquarters
|
||||
pow(item.Price, PriceExponent), // Penalize item price to a controllable degree
|
||||
1
|
||||
).FirstOrDefault();
|
||||
|
|
@ -124,13 +124,13 @@ public class LoadoutGenerator
|
|||
.Where(item =>
|
||||
item.Price > 0 &&
|
||||
item.Manufacturer != Guid.Empty &&
|
||||
(Sector?.ContainsFaction(item.Manufacturer) ?? true) &&
|
||||
(Galaxy?.ContainsFaction(item.Manufacturer) ?? true) &&
|
||||
(Faction == null || Faction.Allegiance.ContainsKey(item.Manufacturer)) &&
|
||||
(filter?.Invoke(item) ?? true))
|
||||
.WeightedRandomElements(ref Random, item =>
|
||||
(Faction == null || item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance[item.Manufacturer]) * // Prioritize items from allied manufacturers
|
||||
pow(item.Shape.Coordinates.Length, sizeExponent) / // Prioritize larger items
|
||||
(Zone?.Distance[Sector.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] ?? 1) / // Penalize distance to manufacturer headquarters
|
||||
(Zone?.Distance[Galaxy.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] ?? 1) / // Penalize distance to manufacturer headquarters
|
||||
pow(item.Price, PriceExponent), // Penalize item price to a controllable degree
|
||||
count
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Ink;
|
||||
using Ink.Runtime;
|
||||
using Ink.Parsed;
|
||||
using MessagePack;
|
||||
using Path = System.IO.Path;
|
||||
using Random = Unity.Mathematics.Random;
|
||||
using Story = Ink.Runtime.Story;
|
||||
|
||||
public class StoryProcessor : IZoneResolver, IFactionResolver
|
||||
{
|
||||
|
|
@ -24,62 +25,67 @@ public class StoryProcessor : IZoneResolver, IFactionResolver
|
|||
public string LoadInkFileContents (string fullFilename) => File.ReadAllText (fullFilename);
|
||||
}
|
||||
|
||||
private Dictionary<Story, SectorZone> _placedStories = new Dictionary<Story, SectorZone>();
|
||||
private Dictionary<Story, string[]> _storyKnotPaths = new Dictionary<Story, string[]>();
|
||||
private Dictionary<Story, GalaxyZone> _storyLocations = new Dictionary<Story, GalaxyZone>();
|
||||
private Dictionary<string, Story> _processedStories = new Dictionary<string, Story>();
|
||||
private DirectoryInfo _locationsPath;
|
||||
private DirectoryInfo _questsPath;
|
||||
private IFileHandler _inkFileHandler;
|
||||
|
||||
public DirectoryInfo NarrativeDirectory { get; }
|
||||
private Random _random;
|
||||
public Sector Sector { get; }
|
||||
public Galaxy Galaxy { get; }
|
||||
public PlayerSettings Settings { get; }
|
||||
|
||||
public StoryProcessor(PlayerSettings settings, DirectoryInfo narrativeDirectory, Sector sector, ref Random random)
|
||||
public StoryProcessor(PlayerSettings settings, DirectoryInfo narrativeDirectory, Galaxy galaxy, ref Random random)
|
||||
{
|
||||
NarrativeDirectory = narrativeDirectory;
|
||||
Sector = sector;
|
||||
Galaxy = galaxy;
|
||||
_random = random;
|
||||
Settings = settings;
|
||||
|
||||
_inkFileHandler = new AetheriaInkFileHandler(narrativeDirectory);
|
||||
|
||||
_locationsPath = narrativeDirectory.CreateSubdirectory("Locations");
|
||||
_questsPath = narrativeDirectory.CreateSubdirectory("Quests");
|
||||
}
|
||||
|
||||
public Dictionary<Story, SectorZone> PlaceStories()
|
||||
public void ProcessStories()
|
||||
{
|
||||
var locationFiles = _locationsPath.EnumerateFiles("*.ink");
|
||||
foreach(var inkFile in locationFiles) PlaceStory(GetStory(inkFile));
|
||||
return _placedStories;
|
||||
foreach(var inkFile in locationFiles) ProcessLocation(GetStory(inkFile), inkFile);
|
||||
|
||||
var questFiles = _questsPath.EnumerateFiles("*ink");
|
||||
foreach(var inkFile in questFiles) ProcessQuest(GetStory(inkFile));
|
||||
}
|
||||
|
||||
public SectorZone ResolveZone(string path)
|
||||
public GalaxyZone ResolveZone(string path)
|
||||
{
|
||||
// Handle special cases: "start" and "end"
|
||||
if (path.Equals("start", StringComparison.InvariantCultureIgnoreCase))
|
||||
return Sector.Entrance;
|
||||
return Galaxy.Entrance;
|
||||
if (path.Equals("end", StringComparison.InvariantCultureIgnoreCase))
|
||||
return Sector.Exit;
|
||||
return Galaxy.Exit;
|
||||
|
||||
// Handle faction home reference: format = "home.<faction>"
|
||||
if(path.StartsWith("home"))
|
||||
{
|
||||
var factionString = path.Substring(5);
|
||||
var faction = ResolveFaction(factionString);
|
||||
return !Sector.HomeZones.ContainsKey(faction) ? null : Sector.HomeZones[faction];
|
||||
return !Galaxy.HomeZones.ContainsKey(faction) ? null : Galaxy.HomeZones[faction];
|
||||
}
|
||||
|
||||
var locationInkFile = new FileInfo(Path.Combine(_locationsPath.FullName, $"{path}.ink"));
|
||||
if (!locationInkFile.Exists) return null;
|
||||
|
||||
var story = GetStory(locationInkFile);
|
||||
PlaceStory(story);
|
||||
return _placedStories.ContainsKey(story) ? _placedStories[story] : null;
|
||||
ProcessLocation(story, locationInkFile);
|
||||
return _storyLocations.ContainsKey(story) ? _storyLocations[story] : null;
|
||||
}
|
||||
|
||||
public Faction ResolveFaction(string name)
|
||||
{
|
||||
return Sector.Factions.FirstOrDefault(f => f.Name.StartsWith(name, StringComparison.InvariantCultureIgnoreCase));
|
||||
return Galaxy.Factions.FirstOrDefault(f => f.Name.StartsWith(name, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
Story GetStory(FileInfo inkFile)
|
||||
|
|
@ -109,16 +115,30 @@ public class StoryProcessor : IZoneResolver, IFactionResolver
|
|||
fileHandler = _inkFileHandler
|
||||
});
|
||||
var story = compiler.Compile();
|
||||
var knots = compiler.parsedStory.FindAll<Knot>().Select(k=>k.runtimePath.ToString()).ToArray();
|
||||
_storyKnotPaths[story] = knots;
|
||||
File.WriteAllText(compiledFileName, story.ToJson());
|
||||
return story;
|
||||
}
|
||||
|
||||
public void PlaceStory(Story story)
|
||||
{
|
||||
if (_placedStories.ContainsKey(story)) return; // Don't place already placed stories, idiot!
|
||||
_placedStories[story] = null; // Avoids potential for infinite loops when evaluating constraints
|
||||
|
||||
var contentTags = GetContentTags(story);
|
||||
public void ProcessQuest(Story story)
|
||||
{
|
||||
var quest = new GalaxyQuest();
|
||||
quest.Story = story;
|
||||
foreach (var knot in _storyKnotPaths[story])
|
||||
{
|
||||
var tags = GetContentTags(story.TagsForContentAtPath(knot));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessLocation(Story story, FileInfo inkFile)
|
||||
{
|
||||
if (_storyLocations.ContainsKey(story)) return; // Don't place already placed stories, idiot!
|
||||
_storyLocations[story] = null; // Avoids potential for infinite loops when evaluating constraints
|
||||
var fileName = Path.GetFileNameWithoutExtension(inkFile.FullName);
|
||||
|
||||
var contentTags = GetContentTags(story.globalTags);
|
||||
|
||||
var constraints = new List<ZoneConstraint>();
|
||||
if(contentTags.ContainsKey("constraint"))
|
||||
|
|
@ -157,16 +177,34 @@ public class StoryProcessor : IZoneResolver, IFactionResolver
|
|||
else
|
||||
selector = new RandomSelector(ref _random);
|
||||
|
||||
var zoneCandidates = new List<SectorZone>();
|
||||
zoneCandidates.AddRange(Sector.Zones.Where(z=>constraints.All(c=>c.Test(z))));
|
||||
_placedStories[story] = selector.SelectZone(zoneCandidates);
|
||||
var zoneCandidates = new List<GalaxyZone>();
|
||||
zoneCandidates.AddRange(Galaxy.Zones.Where(z=>!z.NamedZone && constraints.All(c=>c.Test(z))));
|
||||
|
||||
var zone = selector.SelectZone(zoneCandidates);
|
||||
|
||||
var location = new LocationStory
|
||||
{
|
||||
FileName = fileName,
|
||||
Name = contentTags.ContainsKey("name") ? contentTags["name"].First() : fileName,
|
||||
Faction = contentTags.ContainsKey("faction") ? ResolveFaction(contentTags["faction"].First()) : zone.Owner,
|
||||
Security = contentTags.ContainsKey("security")
|
||||
? (SecurityLevel) Enum.Parse(typeof(SecurityLevel), contentTags["security"].First(), true)
|
||||
: SecurityLevel.Open,
|
||||
Story = story,
|
||||
Type = contentTags.ContainsKey("type")
|
||||
? (LocationType) Enum.Parse(typeof(LocationType), contentTags["type"].First(), true)
|
||||
: LocationType.Station
|
||||
};
|
||||
zone.Locations.Add(location);
|
||||
|
||||
_storyLocations[story] = zone;
|
||||
}
|
||||
|
||||
// Parse all tags of the format X:Y into a dictionary with a list of every Y for each X
|
||||
public static Dictionary<string, List<string>> GetContentTags(Story story)
|
||||
public static Dictionary<string, List<string>> GetContentTags(List<string> tags)
|
||||
{
|
||||
var contentTags = new Dictionary<string, List<string>>();
|
||||
foreach (var tag in story.globalTags)
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (tag.IndexOf(':') == -1) continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using System.Linq;
|
|||
|
||||
public interface IZoneResolver
|
||||
{
|
||||
public SectorZone ResolveZone(string path);
|
||||
public GalaxyZone ResolveZone(string path);
|
||||
}
|
||||
|
||||
public interface IFactionResolver
|
||||
|
|
@ -16,12 +16,12 @@ public abstract class ZoneConstraint
|
|||
{
|
||||
public bool Flip = false;
|
||||
|
||||
public bool Test(SectorZone zone)
|
||||
public bool Test(GalaxyZone zone)
|
||||
{
|
||||
return Flip ^ TestZone(zone);
|
||||
}
|
||||
|
||||
protected abstract bool TestZone(SectorZone zone);
|
||||
protected abstract bool TestZone(GalaxyZone zone);
|
||||
}
|
||||
|
||||
public class FactionPresenceConstraint : ZoneConstraint
|
||||
|
|
@ -32,7 +32,7 @@ public class FactionPresenceConstraint : ZoneConstraint
|
|||
TargetFaction = resolver.ResolveFaction(args[0]);
|
||||
}
|
||||
|
||||
protected override bool TestZone(SectorZone zone)
|
||||
protected override bool TestZone(GalaxyZone zone)
|
||||
{
|
||||
return zone.Factions.Any(f=>f.ID == TargetFaction?.ID);
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ public class FactionOwnerConstraint : ZoneConstraint
|
|||
TargetFaction = resolver.ResolveFaction(args[0]);
|
||||
}
|
||||
|
||||
protected override bool TestZone(SectorZone zone)
|
||||
protected override bool TestZone(GalaxyZone zone)
|
||||
{
|
||||
return zone.Owner.ID == TargetFaction?.ID;
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ public class FactionOwnerConstraint : ZoneConstraint
|
|||
|
||||
public class DistanceConstraint : ZoneConstraint
|
||||
{
|
||||
private SectorZone _targetZone;
|
||||
private GalaxyZone _targetZone;
|
||||
private Predicate<int> _test;
|
||||
|
||||
public DistanceConstraint(string[] args, IZoneResolver zoneResolver)
|
||||
|
|
@ -82,7 +82,7 @@ public class DistanceConstraint : ZoneConstraint
|
|||
}
|
||||
}
|
||||
|
||||
protected override bool TestZone(SectorZone zone)
|
||||
protected override bool TestZone(GalaxyZone zone)
|
||||
{
|
||||
return _targetZone != null && _test(zone.Distance[_targetZone]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@ using Random = Unity.Mathematics.Random;
|
|||
|
||||
public abstract class ZoneSelector
|
||||
{
|
||||
public abstract SectorZone SelectZone(List<SectorZone> candidates);
|
||||
public abstract GalaxyZone SelectZone(List<GalaxyZone> candidates);
|
||||
}
|
||||
|
||||
public abstract class OrderedZoneSelector : ZoneSelector
|
||||
{
|
||||
public bool Flip = false;
|
||||
|
||||
protected abstract Func<SectorZone, IComparable> Comparison { get; }
|
||||
protected abstract Func<GalaxyZone, IComparable> Comparison { get; }
|
||||
|
||||
public override SectorZone SelectZone(List<SectorZone> candidates)
|
||||
public override GalaxyZone SelectZone(List<GalaxyZone> candidates)
|
||||
{
|
||||
var sorted = candidates.OrderBy(Comparison);
|
||||
return Flip ? sorted.Last() : sorted.First();
|
||||
|
|
@ -24,7 +24,7 @@ public abstract class OrderedZoneSelector : ZoneSelector
|
|||
|
||||
public class DistanceSelector : OrderedZoneSelector
|
||||
{
|
||||
private SectorZone Target { get; }
|
||||
private GalaxyZone Target { get; }
|
||||
|
||||
|
||||
public DistanceSelector(string[] args, IZoneResolver zoneResolver)
|
||||
|
|
@ -32,7 +32,7 @@ public class DistanceSelector : OrderedZoneSelector
|
|||
Target = zoneResolver.ResolveZone(args[0].Trim());
|
||||
}
|
||||
|
||||
protected override Func<SectorZone, IComparable> Comparison => zone => Target?.Distance[zone] ?? 0;
|
||||
protected override Func<GalaxyZone, IComparable> Comparison => zone => Target?.Distance[zone] ?? 0;
|
||||
}
|
||||
|
||||
public class RandomSelector : ZoneSelector
|
||||
|
|
@ -44,7 +44,7 @@ public class RandomSelector : ZoneSelector
|
|||
Random = random;
|
||||
}
|
||||
|
||||
public override SectorZone SelectZone(List<SectorZone> candidates)
|
||||
public override GalaxyZone SelectZone(List<GalaxyZone> candidates)
|
||||
{
|
||||
return candidates[Random.NextInt(candidates.Count)];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public class OrbitalEntity : Entity
|
|||
{
|
||||
if (SecurityRadius < 1) return false;
|
||||
if (Faction == null) return false;
|
||||
return !IsPresencePermitted(Zone.Sector.FactionRelationships[Faction], SecurityLevel);
|
||||
return !IsPresencePermitted(Zone.Galaxy.FactionRelationships[Faction], SecurityLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,35 +49,35 @@ public class SavedGame
|
|||
|
||||
public SavedGame() { }
|
||||
|
||||
public SavedGame(Sector sector, Zone currentZone, Entity currentEntity)
|
||||
public SavedGame(Galaxy galaxy, Zone currentZone, Entity currentEntity)
|
||||
{
|
||||
DiscoveredZones = sector.DiscoveredZones.Select(dz => Array.IndexOf(sector.Zones, dz)).ToArray();
|
||||
Background = sector.Background;
|
||||
Factions = sector.HomeZones.Keys.Select(f => f.ID).ToArray();
|
||||
Relationships = sector.Factions.Select(f => sector.FactionRelationships[f]).ToArray();
|
||||
DiscoveredZones = galaxy.DiscoveredZones.Select(dz => Array.IndexOf(galaxy.Zones, dz)).ToArray();
|
||||
Background = galaxy.Background;
|
||||
Factions = galaxy.HomeZones.Keys.Select(f => f.ID).ToArray();
|
||||
Relationships = galaxy.Factions.Select(f => galaxy.FactionRelationships[f]).ToArray();
|
||||
|
||||
HomeZones = sector.HomeZones.ToDictionary(
|
||||
HomeZones = galaxy.HomeZones.ToDictionary(
|
||||
x => Array.IndexOf(Factions, x.Key.ID),
|
||||
x => Array.IndexOf(sector.Zones, x.Value));
|
||||
BossZones = sector.BossZones.ToDictionary(
|
||||
x => Array.IndexOf(galaxy.Zones, x.Value));
|
||||
BossZones = galaxy.BossZones.ToDictionary(
|
||||
x => Array.IndexOf(Factions, x.Key.ID),
|
||||
x => Array.IndexOf(sector.Zones, x.Value));
|
||||
x => Array.IndexOf(galaxy.Zones, x.Value));
|
||||
|
||||
Zones = sector.Zones.Select(zone => new SavedZone
|
||||
Zones = galaxy.Zones.Select(zone => new SavedZone
|
||||
{
|
||||
Name = zone.Name,
|
||||
Position = zone.Position,
|
||||
AdjacentZones = zone.AdjacentZones.Select(az=> Array.IndexOf(sector.Zones, az)).ToArray(),
|
||||
AdjacentZones = zone.AdjacentZones.Select(az=> Array.IndexOf(galaxy.Zones, az)).ToArray(),
|
||||
Factions = zone.Factions.Select(f=> Array.IndexOf(Factions, f.ID)).ToArray(),
|
||||
Contents = zone.Contents?.PackZone(),
|
||||
Owner = zone.Owner == null ? -1 : Array.IndexOf(Factions, zone.Owner.ID)
|
||||
}).ToArray();
|
||||
|
||||
CurrentZone = Array.FindIndex(sector.Zones, zone => zone.Contents == currentZone);
|
||||
CurrentZone = Array.FindIndex(galaxy.Zones, zone => zone.Contents == currentZone);
|
||||
CurrentZoneEntity = currentZone.Entities.IndexOf(currentEntity);
|
||||
|
||||
Entrance = Array.IndexOf(sector.Zones, sector.Entrance);
|
||||
Exit = Array.IndexOf(sector.Zones, sector.Exit);
|
||||
Entrance = Array.IndexOf(galaxy.Zones, galaxy.Entrance);
|
||||
Exit = Array.IndexOf(galaxy.Zones, galaxy.Exit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public class Ship : Entity
|
|||
private float2 _wormholePosition;
|
||||
private float2 _wormholeExitVelocity;
|
||||
|
||||
public bool WormholeAnimationInProgress => _enteringWormhole || _exitingWormhole;
|
||||
public float ForwardThrust { get; private set; }
|
||||
public float ReverseThrust { get; private set; }
|
||||
public float LeftStrafeThrust { get; private set; }
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ using Unity.Mathematics;
|
|||
public class Wormhole
|
||||
{
|
||||
public float2 Position;
|
||||
public SectorZone Target;
|
||||
public GalaxyZone Target;
|
||||
}
|
||||
|
|
@ -41,18 +41,18 @@ public class Zone
|
|||
get => (float) _time;
|
||||
}
|
||||
public ZonePack Pack { get; }
|
||||
public SectorZone SectorZone { get; }
|
||||
public Sector Sector { get; }
|
||||
public GalaxyZone GalaxyZone { get; }
|
||||
public Galaxy Galaxy { get; }
|
||||
|
||||
public Zone(ItemManager itemManager, PlanetSettings settings, ZonePack pack, SectorZone sectorZone, Sector sector)
|
||||
public Zone(ItemManager itemManager, PlanetSettings settings, ZonePack pack, GalaxyZone galaxyZone, Galaxy galaxy)
|
||||
{
|
||||
_time = pack.Time;
|
||||
SectorZone = sectorZone;
|
||||
Sector = sector;
|
||||
GalaxyZone = galaxyZone;
|
||||
Galaxy = galaxy;
|
||||
Pack = pack;
|
||||
_itemManager = itemManager;
|
||||
Settings = settings;
|
||||
_random = new Random(Convert.ToUInt32(abs(sectorZone?.Name.GetHashCode() ?? 1337)));
|
||||
_random = new Random(Convert.ToUInt32(abs(galaxyZone?.Name.GetHashCode() ?? 1337)));
|
||||
|
||||
foreach (var orbit in pack.Orbits)
|
||||
{
|
||||
|
|
@ -311,12 +311,12 @@ public class Zone
|
|||
|
||||
public SecurityLevel GetSecurityLevel(float2 pos)
|
||||
{
|
||||
if (SectorZone.Owner==null) return SecurityLevel.Open;
|
||||
if (GalaxyZone.Owner==null) return SecurityLevel.Open;
|
||||
|
||||
var security = SecurityLevel.Open;
|
||||
foreach (var entity in Entities)
|
||||
{
|
||||
if (entity is OrbitalEntity orbitalEntity && orbitalEntity.SecurityRadius > 1 && entity.Faction.ID == SectorZone.Owner.ID)
|
||||
if (entity is OrbitalEntity orbitalEntity && orbitalEntity.SecurityRadius > 1 && entity.Faction.ID == GalaxyZone.Owner.ID)
|
||||
{
|
||||
if (orbitalEntity.SecurityLevel > security && length(orbitalEntity.Position.xz - pos) < orbitalEntity.SecurityRadius * Settings.SecureAreaRadiusMultiplier)
|
||||
security = orbitalEntity.SecurityLevel;
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@ public static class ZoneGenerator
|
|||
public static ZonePack GenerateZone(
|
||||
ItemManager itemManager,
|
||||
ZoneGenerationSettings zoneSettings,
|
||||
Sector sector,
|
||||
SectorZone sectorZone,
|
||||
Galaxy galaxy,
|
||||
GalaxyZone galaxyZone,
|
||||
bool isTutorial = false)
|
||||
{
|
||||
var pack = new ZonePack();
|
||||
|
||||
var random = new Random(unchecked((uint) sectorZone.Name.GetHashCode()) ^ hash(sectorZone.Position));
|
||||
var random = new Random(unchecked((uint) galaxyZone.Name.GetHashCode()) ^ hash(galaxyZone.Position));
|
||||
|
||||
var density = saturate(sector.Background.CloudDensity(sectorZone.Position)/2);
|
||||
var density = saturate(galaxy.Background.CloudDensity(galaxyZone.Position)/2);
|
||||
pack.Radius = zoneSettings.ZoneRadius.Evaluate(density);
|
||||
pack.Mass = zoneSettings.ZoneMass.Evaluate(density);
|
||||
var targetSubzoneCount = zoneSettings.SubZoneCount.Evaluate(density);
|
||||
|
|
@ -222,9 +222,9 @@ public static class ZoneGenerator
|
|||
return planetData;
|
||||
}).ToList();
|
||||
|
||||
var nearestFaction = sector.Factions.MinBy(f => sector.HomeZones[f].Distance[sectorZone]);
|
||||
var nearestFactionHomeZone = sector.HomeZones[nearestFaction];
|
||||
var factionPresence = nearestFaction.InfluenceDistance - nearestFactionHomeZone.Distance[sectorZone] + 1;
|
||||
var nearestFaction = galaxy.Factions.MinBy(f => galaxy.HomeZones[f].Distance[galaxyZone]);
|
||||
var nearestFactionHomeZone = galaxy.HomeZones[nearestFaction];
|
||||
var factionPresence = nearestFaction.InfluenceDistance - nearestFactionHomeZone.Distance[galaxyZone] + 1;
|
||||
|
||||
var stationCount = (int)(random.NextFloat() * (factionPresence + 1));
|
||||
var potentialLagrangePoints = planets
|
||||
|
|
@ -240,7 +240,7 @@ public static class ZoneGenerator
|
|||
.ToArray();
|
||||
|
||||
var loadoutGenerator = isTutorial ? new LoadoutGenerator(ref random, itemManager, nearestFaction, .5f) :
|
||||
new LoadoutGenerator(ref random, itemManager, sector, sectorZone, nearestFaction, .5f);
|
||||
new LoadoutGenerator(ref random, itemManager, galaxy, galaxyZone, nearestFaction, .5f);
|
||||
|
||||
foreach (var orbit in selectedStationOrbits)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue