Added Console
Debug commands can now be executed using an in-game console
This commit is contained in:
parent
b589a6422c
commit
75eb534983
305 changed files with 2975 additions and 17480 deletions
|
|
@ -15,14 +15,7 @@ public class AgentController
|
|||
private Locomotion _locomotion;
|
||||
private VelocityMatch _velocityMatch;
|
||||
private Random _random = new Random((uint) (DateTime.Now.Ticks%uint.MaxValue));
|
||||
private float _stoppingTime;
|
||||
private float _stoppingDistance;
|
||||
private float _turnaroundDistance;
|
||||
private float _turnaroundTime;
|
||||
private IAnalogBehavior _thrust;
|
||||
private IAnalogBehavior _turning;
|
||||
private KeyValuePair<DatabaseEntry, Entity> _objective;
|
||||
private float _velocityLimit;
|
||||
|
||||
public AgentController(GameContext context, ZoneData zone, Entity entity)
|
||||
{
|
||||
|
|
@ -39,41 +32,31 @@ public class AgentController
|
|||
};
|
||||
EntityAgent.CurrentBehavior = _locomotion;
|
||||
RandomTarget();
|
||||
_thrust = entity.Axes.Keys.FirstOrDefault(x => x is Thruster);
|
||||
_turning = entity.Axes.Keys.FirstOrDefault(x => x is Turning);
|
||||
var velocityLimitData = entity.GetBehaviorData<VelocityLimitData>().FirstOrDefault();
|
||||
_velocityLimit = Context.Evaluate(velocityLimitData.TopSpeed, entity.Hull, entity);
|
||||
_stoppingTime = _velocityLimit / Context.Evaluate((_thrust.Data as ThrusterData).Thrust, _thrust.Item, Entity) * Entity.Mass;
|
||||
_stoppingDistance = _stoppingTime * _velocityLimit / 2;
|
||||
_turnaroundTime = PI / Context.Evaluate((_turning.Data as TurningData).Torque, _turning.Item, entity) * entity.Mass;
|
||||
_turnaroundDistance = _turnaroundTime * _velocityLimit;
|
||||
_locomotion.LeadTime = _stoppingTime;
|
||||
}
|
||||
|
||||
public void Update(float delta)
|
||||
{
|
||||
EntityAgent.Update(delta);
|
||||
var distance = length(_locomotion.Objective.Position - Entity.Position);
|
||||
Context.Log(
|
||||
$"Agent Mode: {EntityAgent.CurrentBehavior.GetType()} " +
|
||||
$"Agent Distance: {distance} " +
|
||||
$"Turnaround Distance: {_stoppingDistance + _turnaroundDistance} " +
|
||||
$"Objective: {_objective.Key.ID.ToString().Substring(0, 8)}");
|
||||
// Context.Log(
|
||||
// $"Agent Mode: {EntityAgent.CurrentBehavior.GetType()} " +
|
||||
// $"Agent Distance: {distance} " +
|
||||
// $"Turnaround Distance: {_stoppingDistance + _turnaroundDistance} " +
|
||||
// $"Objective: {_objective.Key.ID.ToString().Substring(0, 8)}");
|
||||
|
||||
if (EntityAgent.CurrentBehavior == _locomotion)
|
||||
{
|
||||
var velocity = length(Entity.Velocity);
|
||||
_stoppingTime = velocity / Context.Evaluate((_thrust.Data as ThrusterData).Thrust, _thrust.Item, Entity) * Entity.Mass;
|
||||
_stoppingDistance = _stoppingTime * velocity / 2;
|
||||
if (distance < _stoppingDistance + _turnaroundDistance)
|
||||
EntityAgent.CurrentBehavior = _velocityMatch;
|
||||
_velocityMatch.Objective = _locomotion.Objective;
|
||||
var matchDistanceTime = _velocityMatch.MatchDistanceTime;
|
||||
_locomotion.LeadTime = matchDistanceTime.y;
|
||||
if (distance < matchDistanceTime.x)
|
||||
EntityAgent.CurrentBehavior = _velocityMatch;
|
||||
}
|
||||
}
|
||||
|
||||
private void RandomTarget()
|
||||
{
|
||||
var entities = Context.ZoneContents[Zone].ToArray();
|
||||
var entities = Context.ZoneContents[Zone].Where(kvp=>!(kvp.Key is ShipData)).ToArray();
|
||||
_objective = entities[_random.NextInt(entities.Length)];
|
||||
_locomotion.Objective = _objective.Value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,4 +35,22 @@ public class VelocityMatch : AgentBehavior
|
|||
_entity.Axes[_thrust] = saturate(length(pow(saturate(dot(normalize(_entity.Direction),normalize(deltaV))), 8)*length(deltaV))*ThrustSensitivity);
|
||||
}
|
||||
}
|
||||
|
||||
public float2 MatchDistanceTime
|
||||
{
|
||||
get
|
||||
{
|
||||
var velocity = length(_entity.Velocity);
|
||||
var deltaV = Objective.Velocity - _entity.Velocity;
|
||||
|
||||
var stoppingTime = length(deltaV) / _entity.Context.Evaluate((_thrust.Data as ThrusterData).Thrust, _thrust.Item, _entity) * _entity.Mass;
|
||||
var stoppingDistance = stoppingTime * velocity / 2;
|
||||
|
||||
var angleDiff = _entity.Direction.AngleDiff(deltaV);
|
||||
var turnaroundTime = angleDiff / _entity.Context.Evaluate((_turning.Data as TurningData).Torque, _turning.Item, _entity) * _entity.Mass;
|
||||
var turnaroundDistance = turnaroundTime * velocity;
|
||||
|
||||
return float2(stoppingDistance + turnaroundDistance, stoppingTime + turnaroundTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ public interface IAnalogBehavior : IBehavior
|
|||
void SetAxis(float value);
|
||||
}
|
||||
|
||||
public interface IPersistentBehavior//<T> where T : IBehavior
|
||||
{
|
||||
object Store();
|
||||
IBehavior Restore(GameContext context, Entity entity, Gear item, Guid data);
|
||||
}
|
||||
|
||||
[InspectableField,
|
||||
Union(0, typeof(ProjectileWeaponData)),
|
||||
Union(1, typeof(LauncherData)),
|
||||
|
|
@ -43,6 +49,7 @@ public interface IAnalogBehavior : IBehavior
|
|||
Union(9, typeof(TurningData)),
|
||||
Union(10, typeof(VelocityConversionData)),
|
||||
Union(11, typeof(VelocityLimitData)),
|
||||
Union(12, typeof(FactoryData)),
|
||||
JsonConverter(typeof(JsonKnownTypesConverter<IBehaviorData>)), JsonObject(MemberSerialization.OptIn)]
|
||||
public interface IBehaviorData
|
||||
{
|
||||
|
|
|
|||
191
Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs
Normal file
191
Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MessagePack;
|
||||
using Newtonsoft.Json;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
|
||||
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
|
||||
public class FactoryData : IBehaviorData
|
||||
{
|
||||
[InspectableField, JsonProperty("toolingTime"), Key(0)]
|
||||
public PerformanceStat ToolingTime = new PerformanceStat();
|
||||
|
||||
[InspectableField, JsonProperty("automation"), Key(1)]
|
||||
public int AutomationPoints;
|
||||
|
||||
public IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
|
||||
{
|
||||
return new Factory(context, this, entity, item);
|
||||
}
|
||||
}
|
||||
|
||||
public class Factory : IBehavior, IPersistentBehavior//<Factory>
|
||||
{
|
||||
public Entity Entity { get; }
|
||||
public Gear Item { get; }
|
||||
public GameContext Context { get; }
|
||||
|
||||
public IBehaviorData Data => _data;
|
||||
|
||||
private FactoryData _data;
|
||||
|
||||
private BlueprintData _blueprint;
|
||||
private float _remainingManHours;
|
||||
private bool _retooling;
|
||||
private List<ItemInstance> _reservedStock = new List<ItemInstance>();
|
||||
private int _assignedPopulation;
|
||||
private int _productionQuality;
|
||||
|
||||
public Factory(GameContext context, FactoryData data, Entity entity, Gear item)
|
||||
{
|
||||
Context = context;
|
||||
_data = data;
|
||||
Entity = entity;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update(float delta)
|
||||
{
|
||||
if (_retooling || _reservedStock.Count > 0)
|
||||
{
|
||||
_remainingManHours -= delta / 3600 * (_assignedPopulation + _data.AutomationPoints) / _productionQuality;
|
||||
}
|
||||
|
||||
if (_remainingManHours < 0)
|
||||
{
|
||||
if (_retooling)
|
||||
_retooling = false;
|
||||
else if (_reservedStock.Count > 0)
|
||||
{
|
||||
var blueprintItemData = Context.Cache.Get(_blueprint.Item);
|
||||
|
||||
for (int i = 0; i < _blueprint.Quantity; i++)
|
||||
{
|
||||
CraftedItemInstance newItem;
|
||||
|
||||
if (blueprintItemData is EquippableItemData equippableItemData)
|
||||
{
|
||||
var newGear = new Gear
|
||||
{
|
||||
Context = Context,
|
||||
Data = blueprintItemData.ID,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(),
|
||||
Quality = _productionQuality * _blueprint.Quality,
|
||||
Blueprint = _blueprint
|
||||
};
|
||||
newGear.Durability = Context.Evaluate(equippableItemData.Durability, newGear);
|
||||
newItem = newGear;
|
||||
}
|
||||
else
|
||||
{
|
||||
newItem = new CompoundCommodity
|
||||
{
|
||||
Context = Context,
|
||||
Data = blueprintItemData.ID,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(),
|
||||
Quality = _productionQuality * _blueprint.Quality,
|
||||
Blueprint = _blueprint
|
||||
};
|
||||
}
|
||||
Context.Cache.Add(newItem);
|
||||
Entity.Cargo.Add(newItem);
|
||||
}
|
||||
Entity.RecalculateMass();
|
||||
|
||||
var simpleIngredients = new List<SimpleCommodity>();
|
||||
var compoundIngredients = new List<CompoundCommodity>();
|
||||
var hasAllIngredients = true;
|
||||
foreach (var kvp in _blueprint.Ingredients)
|
||||
{
|
||||
var itemData = Context.Cache.Get(kvp.Key);
|
||||
if (itemData is SimpleCommodityData)
|
||||
{
|
||||
var matchingItem = Entity.Cargo.FirstOrDefault(ii =>
|
||||
{
|
||||
var simpleCommodity = ii as SimpleCommodity;
|
||||
if (simpleCommodity == null) return false;
|
||||
return simpleCommodity.Data == itemData.ID && simpleCommodity.Quantity >= kvp.Value;
|
||||
}) as SimpleCommodity;
|
||||
hasAllIngredients = hasAllIngredients && matchingItem != null;
|
||||
if(matchingItem != null)
|
||||
simpleIngredients.Add(matchingItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
var matchingItems =
|
||||
Entity.Cargo.Where(ii => (ii as CompoundCommodity)?.Data == itemData.ID).Cast<CompoundCommodity>().ToArray();
|
||||
hasAllIngredients = hasAllIngredients && matchingItems.Length >= kvp.Value;
|
||||
if(matchingItems.Length >= kvp.Value)
|
||||
compoundIngredients.AddRange(matchingItems);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAllIngredients)
|
||||
{
|
||||
_reservedStock.AddRange(compoundIngredients);
|
||||
foreach (var compoundCommodity in compoundIngredients)
|
||||
{
|
||||
Entity.Cargo.Remove(compoundCommodity);
|
||||
}
|
||||
foreach (var simpleCommodity in simpleIngredients)
|
||||
{
|
||||
var blueprintQuantity = _blueprint.Ingredients
|
||||
.First(ingredient => ingredient.Key == simpleCommodity.ID).Value;
|
||||
if (simpleCommodity.Quantity == blueprintQuantity)
|
||||
{
|
||||
_reservedStock.Add(simpleCommodity);
|
||||
Entity.Cargo.Remove(simpleCommodity);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newSimpleCommodity = new SimpleCommodity
|
||||
{
|
||||
Context = Context,
|
||||
Data = simpleCommodity.Data,
|
||||
ID = Guid.NewGuid(),
|
||||
Quantity = blueprintQuantity
|
||||
};
|
||||
simpleCommodity.Quantity -= blueprintQuantity;
|
||||
_reservedStock.Add(newSimpleCommodity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object Store()
|
||||
{
|
||||
return new FactoryPersistence
|
||||
{
|
||||
Blueprint = _blueprint.ID,
|
||||
RemainingManHours = _remainingManHours,
|
||||
Retooling = _retooling,
|
||||
ReservedStock = _reservedStock.Select(i=>i.ID).ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
public IBehavior Restore(GameContext context, Entity entity, Gear item, Guid data)
|
||||
{
|
||||
var equippable = item.ItemData;
|
||||
var behaviorData = (FactoryData) equippable.Behaviors.First(b => b is FactoryData);
|
||||
return new Factory(context, behaviorData, entity, item);
|
||||
}
|
||||
}
|
||||
|
||||
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
|
||||
public class FactoryPersistence
|
||||
{
|
||||
public Guid Blueprint;
|
||||
public float RemainingManHours;
|
||||
public bool Retooling;
|
||||
public Guid[] ReservedStock;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f6378c7d7a9be24c9830679aabe55ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -35,6 +35,9 @@ public class BlueprintData : DatabaseEntry, INamedEntry
|
|||
|
||||
[InspectableDatabaseLink(typeof(BlueprintData)), JsonProperty("researchDependencies"), Key(9)]
|
||||
public List<Guid> Dependencies = new List<Guid>();
|
||||
|
||||
[InspectableDatabaseLink(typeof(CraftedItemData)), JsonProperty("factoryItem"), Key(11)]
|
||||
public Guid FactoryItem;
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ public class Entity
|
|||
public float2 Velocity;
|
||||
public Dictionary<Guid, List<IActivatedBehavior>> Bindings;
|
||||
public Dictionary<IAnalogBehavior, float> Axes;
|
||||
public readonly GameContext Context;
|
||||
public readonly List<ItemInstance> Cargo;
|
||||
public readonly List<Gear> EquippedItems;
|
||||
|
||||
protected readonly GameContext Context;
|
||||
protected readonly List<IBehavior> Behaviors;
|
||||
protected readonly List<Gear> Items;
|
||||
protected readonly List<ItemInstance> Cargo;
|
||||
|
||||
public Gear Hull { get; }
|
||||
|
||||
|
|
@ -33,19 +33,13 @@ public class Entity
|
|||
{
|
||||
Context = context;
|
||||
|
||||
Items = items.ToList();
|
||||
EquippedItems = items.ToList();
|
||||
Cargo = cargo.ToList();
|
||||
Hull = hull;
|
||||
|
||||
Mass = hull?.Mass ?? 0 +
|
||||
Items.Sum(i => i.Mass) +
|
||||
Cargo.Sum(ii => ii.Mass);
|
||||
|
||||
SpecificHeat = (hull?.HeatCapacity ?? 0) +
|
||||
Items.Sum(i => i.HeatCapacity) +
|
||||
Cargo.Sum(ii => ii.HeatCapacity);
|
||||
|
||||
var activeItems = hull == null ? Items : Items.Append(hull);
|
||||
RecalculateMass();
|
||||
|
||||
var activeItems = Hull == null ? EquippedItems : EquippedItems.Append(Hull);
|
||||
|
||||
Behaviors = activeItems
|
||||
.Where(i=>i.ItemData.Behaviors?.Any()??false)
|
||||
|
|
@ -61,6 +55,22 @@ public class Entity
|
|||
Axes = Behaviors
|
||||
.Where(b => b is IAnalogBehavior)
|
||||
.ToDictionary(b => b as IAnalogBehavior, b => 0f);
|
||||
|
||||
foreach (var behavior in Behaviors)
|
||||
{
|
||||
behavior.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public void RecalculateMass()
|
||||
{
|
||||
Mass = Hull?.Mass ?? 0 +
|
||||
EquippedItems.Sum(i => i.Mass) +
|
||||
Cargo.Sum(ii => ii.Mass);
|
||||
|
||||
SpecificHeat = (Hull?.HeatCapacity ?? 0) +
|
||||
EquippedItems.Sum(i => i.HeatCapacity) +
|
||||
Cargo.Sum(ii => ii.HeatCapacity);
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetBehaviors<T>() where T : class, IBehavior
|
||||
|
|
@ -90,7 +100,7 @@ public class Entity
|
|||
foreach(var behavior in Behaviors)
|
||||
behavior.Update(delta);
|
||||
|
||||
foreach (var item in Items.Where(item => item.ItemData.Performance(Temperature) < .01f))
|
||||
foreach (var item in EquippedItems.Where(item => item.ItemData.Performance(Temperature) < .01f))
|
||||
item.Durability -= delta;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,8 @@ public enum HardpointType
|
|||
Tool,
|
||||
Energy,
|
||||
Ballistic,
|
||||
Launcher
|
||||
Launcher,
|
||||
Infrastructure
|
||||
}
|
||||
|
||||
public enum DamageType
|
||||
|
|
|
|||
|
|
@ -223,11 +223,11 @@ public static class Extensions
|
|||
|
||||
public static float AngleDiff(this float2 a, float2 b)
|
||||
{
|
||||
var directionAngle = atan2(b.y, b.x) / PI;
|
||||
var currentAngle = atan2(a.y, a.x) / PI;
|
||||
var directionAngle = atan2(b.y, b.x);
|
||||
var currentAngle = atan2(a.y, a.x);
|
||||
var d1 = directionAngle - currentAngle;
|
||||
var d2 = directionAngle - 2 - currentAngle;
|
||||
var d3 = directionAngle + 2 - currentAngle;
|
||||
var d2 = directionAngle - 2 * PI - currentAngle;
|
||||
var d3 = directionAngle + 2 * PI - currentAngle;
|
||||
return abs(d1) < abs(d2) ? abs(d1) < abs(d3) ? d1 : d3 : abs(d2) < abs(d3) ? d2 : d3;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,7 +204,8 @@ public class GameContext
|
|||
quality = item.CompoundQuality();
|
||||
else
|
||||
{
|
||||
var ingredients = item.Ingredients.Where(i => activeEffects.Any(e => e.Ingredient == i.Data)).ToArray();
|
||||
var ingredientInstances = item.Ingredients.Select(i => Cache.Get<ItemInstance>(i)).ToArray();
|
||||
var ingredients = ingredientInstances.Where(i => activeEffects.Any(e => e.Ingredient == i.Data)).ToArray();
|
||||
if(ingredients.Length != activeEffects.Length)
|
||||
{
|
||||
_logger($"Item {item.ID} does not have the ingredients specified by the stat effects of its blueprint!");
|
||||
|
|
@ -297,6 +298,8 @@ public class GameContext
|
|||
})
|
||||
.ToList();
|
||||
|
||||
Cache.AddAll(ingredients);
|
||||
|
||||
if (item is EquippableItemData equippableItemData)
|
||||
{
|
||||
var newGear = new Gear
|
||||
|
|
@ -304,22 +307,25 @@ public class GameContext
|
|||
Context = this,
|
||||
Data = data,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = ingredients,
|
||||
Ingredients = ingredients.Select(i=>i.ID).ToList(),
|
||||
Quality = quality,
|
||||
Blueprint = blueprint
|
||||
};
|
||||
newGear.Durability = Evaluate(equippableItemData.Durability, newGear);
|
||||
Cache.Add(newGear);
|
||||
return newGear;
|
||||
}
|
||||
|
||||
return new CompoundCommodity
|
||||
var newCommodity = new CompoundCommodity
|
||||
{
|
||||
Context = this,
|
||||
Data = data,
|
||||
ID = Guid.NewGuid(),
|
||||
Ingredients = ingredients,
|
||||
Ingredients = ingredients.Select(i=>i.ID).ToList(),
|
||||
Quality = quality,
|
||||
Blueprint = blueprint
|
||||
};
|
||||
Cache.Add(newCommodity);
|
||||
return newCommodity;
|
||||
}
|
||||
}
|
||||
|
|
@ -97,6 +97,9 @@ public class GlobalData : DatabaseEntry
|
|||
|
||||
[InspectableField, JsonProperty("planetMass"), Key(28)]
|
||||
public float PlanetMass = 100f;
|
||||
|
||||
[InspectableField, JsonProperty("orbitSpeedMultiplier"), Key(29)]
|
||||
public float OrbitSpeedMultiplier = .25f;
|
||||
|
||||
public float PlanetRadius(float mass)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public abstract class CraftedItemInstance : ItemInstance
|
|||
{
|
||||
[JsonProperty("quality"), Key(2)] public float Quality;
|
||||
|
||||
[JsonProperty("ingredients"), Key(3)] public List<ItemInstance> Ingredients = new List<ItemInstance>();
|
||||
[JsonProperty("ingredients"), Key(3)] public List<Guid> Ingredients = new List<Guid>();
|
||||
|
||||
[JsonProperty("blueprint"), Key(4)] public BlueprintData Blueprint;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class OrbitalEntity : Entity
|
|||
{
|
||||
var orbitData = Context.Cache.Get<OrbitData>(orbit);
|
||||
_orbitPositions[orbit] = GetOrbitPosition(orbitData.Parent) + (orbitData.Period < .01f ? float2.zero :
|
||||
OrbitData.Evaluate((float) (Context.Time / -orbitData.Period + orbitData.Phase)) *
|
||||
OrbitData.Evaluate((float) (Context.Time / -orbitData.Period * Context.GlobalData.OrbitSpeedMultiplier + orbitData.Phase)) *
|
||||
orbitData.Distance);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue