New Inventory System + Overhaul

Removed universal GameContext references
Refactored GameContext: It's now only responsible for item management. As such it's now called ItemManager
GlobalData is gone, relevant settings are distributed amongst specialized settings classes
Entities are no longer database entries, references to them are now direct - Zone is reponsible for storing them in ZonePacks
Controller subtypes are now generic classes, class argument is task type
Inventory is now a 2D grid instead of a list
Entity temperature is now a 2D grid instead of a number
Item sizes are now arbitrary shapes instead of a number
Hardpoints are now arbitrary shapes instead
Equipped items have their own temperatures
Map view now displays sunlight colors
Integrated Allegorithmic Substance Plugin
Imported Djinni ship and assigned Substance materials
Removed Node Editor framework (might come back later but needs work to integrate with behavior system)
This commit is contained in:
Reinier Vens 2020-12-10 23:20:38 +00:00
commit f643f6cc8a
330 changed files with 24242 additions and 2830 deletions

View file

@ -18,10 +18,10 @@ public abstract class AgentBehavior
protected float TurningInput(float2 deltaV) => clamp(-Entity.Direction.AngleDiff(deltaV) * ControllerData.TurningSensitivity, -1, 1);
protected ControllerData ControllerData;
protected GameContext Context;
protected ItemManager Context;
protected Entity Entity;
public AgentBehavior(GameContext context, Entity entity, ControllerData controllerData)
public AgentBehavior(ItemManager context, Entity entity, ControllerData controllerData)
{
Context = context;
Entity = entity;

View file

@ -12,7 +12,7 @@ public class Aim : AgentBehavior
private Turning _turning;
private VelocityLimit _velocityLimit;
public Aim(GameContext context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
public Aim(ItemManager context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
{
_velocityLimit = Entity.GetBehaviors<VelocityLimit>().FirstOrDefault();
_thrust = Entity.GetBehavior<Thruster>();

View file

@ -9,10 +9,10 @@ public class HaulingTask : AgentTask
public override TaskType Type => TaskType.Haul;
[JsonProperty("origin"), Key(4)]
public Guid Origin;
public Entity Origin;
[JsonProperty("target"), Key(5)]
public Guid Target;
public Entity Target;
[JsonProperty("itemType"), Key(6)]
public Guid ItemType;

View file

@ -14,7 +14,7 @@ public class Locomotion : AgentBehavior
private Turning _turning;
private VelocityLimit _velocityLimit;
public Locomotion(GameContext context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
public Locomotion(ItemManager context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
{
_velocityLimit = Entity.GetBehaviors<VelocityLimit>().FirstOrDefault();
_thrust = Entity.GetBehavior<Thruster>();

View file

@ -12,7 +12,7 @@ public class StationTowing : AgentTask
[IgnoreMember] public override TaskType Type => TaskType.Tow;
[JsonProperty("station"), Key(4)]
public Guid Station;
public OrbitalEntity Station;
[JsonProperty("orbitParent"), Key(5)]
public Guid OrbitParent;

View file

@ -13,9 +13,9 @@ public class VelocityMatch : AgentBehavior
private Turning _turning;
private const float TargetThreshold = .1f;
private GameContext _context;
private ItemManager _context;
public VelocityMatch(GameContext context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
public VelocityMatch(ItemManager context, Entity entity, ControllerData controllerData) : base(context, entity, controllerData)
{
_context = context;
_thrust = Entity.GetBehavior<Thruster>();

View file

@ -0,0 +1,5 @@
public class WanderTask : AgentTask
{
public override TaskType Type => TaskType.None;
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2320c5e3a86f42eeacb133b6529bfe89
timeCreated: 1607467429

View file

@ -41,6 +41,11 @@ public interface IAlwaysUpdatedBehavior
void AlwaysUpdate(float delta);
}
public interface IOrderedBehavior
{
int Order { get; }
}
public interface IPersistentBehavior//<T> where T : IBehavior
{
PersistentBehaviorData Store();
@ -52,12 +57,12 @@ public interface IPopulationAssignment
int AssignedPopulation { get; set; }
}
public interface IController
public interface IController<T> where T: AgentTask
{
bool Available { get; }
TaskType TaskType { get; }
//TaskType TaskType { get; }
Zone Zone { get; }
void AssignTask(Guid task);
void AssignTask(T task);
}
[MessagePackObject,
@ -106,5 +111,5 @@ public abstract class BehaviorData
[InspectableField, JsonProperty("group"), Key(0)]
public int Group;
public abstract IBehavior CreateInstance(GameContext context, Entity entity, Gear item);
public abstract IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item);
}

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using MessagePack;
using Newtonsoft.Json;
using UniRx;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using float2 = Unity.Mathematics.float2;
@ -26,27 +27,28 @@ public abstract class ControllerData : BehaviorData
public float TargetDistance = 10;
}
public abstract class ControllerBase : IBehavior, IController, IInitializableBehavior
public abstract class ControllerBase<T> : IBehavior, IController<T>, IInitializableBehavior where T : AgentTask
{
protected Guid HomeEntity => (_entity as Ship)?.HomeEntity ?? Guid.Empty;
public bool Available => _spaceworthy && Task == Guid.Empty;
public abstract TaskType TaskType { get; }
public Zone Zone => _entity.Zone;
protected Entity HomeEntity => (Entity as Ship)?.HomeEntity;
public bool Available => _spaceworthy && Task == null;
//public abstract TaskType TaskType { get; }
public Zone Zone => Entity.Zone;
public BehaviorData Data => _controllerData;
protected ItemManager ItemManager { get; }
protected Entity Entity { get; }
protected Locomotion Locomotion;
protected VelocityMatch VelocityMatch;
protected Aim Aim;
protected Func<float2> TargetPosition;
protected Func<float2> TargetVelocity;
protected bool MatchVelocity;
protected List<ZoneDefinition> Path;
protected Guid Task;
// protected List<ZoneDefinition> Path;
protected T Task;
protected bool Moving;
protected bool Waiting;
private GameContext _context;
private Entity _entity;
private ControllerData _controllerData;
private MovementPhase _movementPhase;
private Action _onFinishMoving;
@ -54,33 +56,36 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
private float _waitTime;
private Action _onFinishWaiting;
public ControllerBase(GameContext context, ControllerData data, Entity entity)
public ControllerBase(ItemManager itemManager, ControllerData data, Entity entity)
{
_context = context;
ItemManager = itemManager;
Entity = entity;
_controllerData = data;
_entity = entity;
entity.GearEvent.OnChanged += () =>
{
_spaceworthy = entity.GetBehavior<Thruster>() != null && entity.GetBehavior<Reactor>() != null;
if(_spaceworthy)
CreateBehaviors();
};
CheckSpaceworthiness();
entity.EquippedItems.ObserveAdd().Subscribe(added => CheckSpaceworthiness());
}
private void CheckSpaceworthiness()
{
_spaceworthy = Entity.GetBehavior<Thruster>() != null && Entity.GetBehavior<Reactor>() != null;
if(_spaceworthy)
CreateBehaviors();
}
public void CreateBehaviors()
{
Locomotion = new Locomotion(_context, _entity, _controllerData);
VelocityMatch = new VelocityMatch(_context, _entity, _controllerData);
Aim = new Aim(_context, _entity, _controllerData);
Locomotion = new Locomotion(ItemManager, Entity, _controllerData);
VelocityMatch = new VelocityMatch(ItemManager, Entity, _controllerData);
Aim = new Aim(ItemManager, Entity, _controllerData);
}
public void Initialize()
{
CreateBehaviors();
_context.CorporationControllers[_entity.Corporation].Add(this);
// _context.CorporationControllers[_entity.Corporation].Add(this);
}
public void AssignTask(Guid task)
public void AssignTask(T task)
{
Task = task;
Moving = false;
@ -91,7 +96,7 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
if (Available)
{
// No task is assigned and we're at home, do nothing!
if (_entity.Parent == HomeEntity)
if (Entity.Parent == HomeEntity)
return false;
// No task is assigned, but we're not home, go home!
@ -115,11 +120,11 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
if (Moving)
{
if(_entity.Parent!=Guid.Empty)
_entity.RemoveParent();
if(Entity.Parent!=null)
Entity.RemoveParent();
var targetPosition = TargetPosition();
var distance = length(targetPosition - _entity.Position);
var distance = length(targetPosition - Entity.Position);
if (MatchVelocity)
{
var targetVelocity = TargetVelocity();
@ -165,28 +170,24 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
public void FinishTask()
{
if (Task == Guid.Empty)
if (Task == null)
return;
var task = _context.Cache.Get(Task);
_context.Cache.Delete(task);
_context.Cache.Get<Corporation>(_entity.Corporation).Tasks.Remove(task.ID);
Task = Guid.Empty;
Task = null;
}
public void GoHome(Action onFinish = null)
{
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
if (Zone == homeEntity.Zone) MoveTo(homeEntity, true, () =>
MoveTo(HomeEntity, true, () =>
{
_entity.SetParent(homeEntity);
Entity.SetParent(HomeEntity);
onFinish?.Invoke();
});
else MoveTo(homeEntity.Zone.Data.ID, () => MoveTo(homeEntity, true, () =>
{
_entity.SetParent(homeEntity);
onFinish?.Invoke();
}));
// else MoveTo(homeEntity.Zone.Data.ID, () => MoveTo(homeEntity, true, () =>
// {
// _entity.SetParent(homeEntity);
// onFinish?.Invoke();
// }));
}
public void Wait(float time, Action onFinish = null)
@ -226,25 +227,25 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
_onFinishMoving = onFinish;
}
public void MoveTo(Guid zone, Action onFinish = null)
{
var path = _context.FindPath(_context.GalaxyZones[Zone.Data.ID], _context.GalaxyZones[zone]);
void OnNextZone()
{
path.RemoveAt(0);
if (path.Count > 0)
{
MoveTo(Zone.WormholePosition(Path[0]), false, OnNextZone);
}
else
{
onFinish?.Invoke();
}
}
OnNextZone();
}
// public void MoveTo(Guid zone, Action onFinish = null)
// {
// var path = _context.FindPath(_context.GalaxyZones[Zone.Data.ID], _context.GalaxyZones[zone]);
//
// void OnNextZone()
// {
// path.RemoveAt(0);
// if (path.Count > 0)
// {
// MoveTo(Zone.WormholePosition(Path[0]), false, OnNextZone);
// }
// else
// {
// onFinish?.Invoke();
// }
// }
//
// OnNextZone();
// }
}
public enum MovementPhase

View file

@ -9,7 +9,7 @@ public class CooldownData : BehaviorData
[InspectableField, JsonProperty("cooldown"), Key(1), RuntimeInspectable]
public PerformanceStat Cooldown = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Cooldown(context, this, entity, item);
}
@ -18,16 +18,15 @@ public class CooldownData : BehaviorData
public class Cooldown : IBehavior, IAlwaysUpdatedBehavior
{
private CooldownData _data;
public BehaviorData Data => _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
public BehaviorData Data => _data;
private EquippedItem Item { get; }
private ItemManager Context { get; }
private float _cooldown; // Normalized
public Cooldown(GameContext context, CooldownData data, Entity entity, Gear item)
public Cooldown(ItemManager context, CooldownData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -49,6 +48,6 @@ public class Cooldown : IBehavior, IAlwaysUpdatedBehavior
public void AlwaysUpdate(float delta)
{
_cooldown -= delta / Context.Evaluate(_data.Cooldown, Item, Entity);
_cooldown -= delta / Context.Evaluate(_data.Cooldown, Item.EquippableItem, Entity);
}
}

View file

@ -12,23 +12,24 @@ public class EnergyDrawData : BehaviorData
[InspectableField, JsonProperty("perSecond"), Key(2)]
public bool PerSecond;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new EnergyDraw(context, this, entity, item);
}
}
public class EnergyDraw : IBehavior
public class EnergyDraw : IBehavior, IOrderedBehavior
{
private EnergyDrawData _data;
public int Order => -100;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public EnergyDraw(GameContext context, EnergyDrawData data, Entity entity, Gear item)
public EnergyDraw(ItemManager context, EnergyDrawData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -38,7 +39,7 @@ public class EnergyDraw : IBehavior
public bool Update(float delta)
{
Entity.Energy -= Context.Evaluate(_data.Draw, Item, Entity) * (_data.PerSecond ? delta : 1);
Entity.Energy -= Context.Evaluate(_data.Draw, Item.EquippableItem, Entity) * (_data.PerSecond ? delta : 1);
return true;
}
}

View file

@ -22,13 +22,13 @@ public class FactoryData : BehaviorData
[InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("productionProfile"), Key(4)]
public Dictionary<Guid, float> ProductionProfile = new Dictionary<Guid, float>();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Factory(context, this, entity, item);
}
}
public class Factory : IBehavior, IPersistentBehavior, IPopulationAssignment
public class Factory : IBehavior//, IPersistentBehavior, IPopulationAssignment
{
public float ProductionQuality;
public double RetoolingTime;
@ -38,8 +38,8 @@ public class Factory : IBehavior, IPersistentBehavior, IPopulationAssignment
public int AssignedPopulation { get; set; }
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
@ -56,11 +56,10 @@ public class Factory : IBehavior, IPersistentBehavior, IPopulationAssignment
Active = false;
if(value != Guid.Empty)
{
ItemName = Context.Cache.Get<ItemData>(Context.Cache.Get<BlueprintData>(value).Item).Name;
ItemName = Context.ItemData.Get<ItemData>(Context.ItemData.Get<BlueprintData>(value).Item).Name;
RetoolingTime = ToolingTime;
_retooling = true;
}
Item.Change();
}
}
}
@ -71,102 +70,207 @@ public class Factory : IBehavior, IPersistentBehavior, IPopulationAssignment
private bool _retooling = false;
private float _currentProductionQuality;
public Factory(GameContext context, FactoryData data, Entity entity, Gear item)
public Factory(ItemManager context, FactoryData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
Entity = entity;
Item = item;
}
public bool Update(float delta)
{
ToolingTime = Context.Evaluate(_data.ToolingTime, Item, Entity);
var blueprint = Context.Cache.Get<BlueprintData>(_blueprint);
if (blueprint == null)
return false;
if (ItemUnderConstruction != Guid.Empty)
{
Entity.IncompleteCargo[ItemUnderConstruction] =
Entity.IncompleteCargo[ItemUnderConstruction] - delta * (AssignedPopulation + _data.AutomationPoints) /
pow(lerp(blueprint.QualityFloor, 1, saturate(_currentProductionQuality)),
blueprint.ProductionExponent);
if(Entity.IncompleteCargo[ItemUnderConstruction] < 0)
{
var item = Context.Cache.Get<ItemInstance>(ItemUnderConstruction);
if (item is SimpleCommodity simpleCommodity)
Entity.AddCargo(simpleCommodity);
else if (item is CraftedItemInstance craftedItemInstance)
Entity.AddCargo(craftedItemInstance);
Entity.IncompleteCargo.Remove(ItemUnderConstruction);
ItemUnderConstruction = Guid.Empty;
foreach (var attribute in _data.ProductionProfile)
Entity.Personality[attribute.Key] = lerp(Entity.Personality[attribute.Key], attribute.Value,
Context.GlobalData.ProductionPersonalityLerp * ((float) AssignedPopulation / Entity.Population));
Item.Change();
}
return true;
}
if (RetoolingTime > 0)
{
RetoolingTime -= delta;
return false;
}
if (_retooling)
{
_retooling = false;
Item.Change();
}
if (Active)
{
var profileDistance = 0f;
if (_data.ProductionProfile.Any())
profileDistance = _data.ProductionProfile.Sum(x => abs(x.Value - Entity.Personality[x.Key])) /
_data.ProductionProfile.Count;
var personalityQuality =
(_data.AutomationPoints * _data.AutomationQuality + AssignedPopulation * (1 - profileDistance)) /
(_data.AutomationPoints + AssignedPopulation);
ItemUnderConstruction = Entity.Build(blueprint,
blueprint.Quality *
pow(personalityQuality, blueprint.PersonalityExponent) *
pow(ProductionQuality, blueprint.QualityExponent) *
// Applying exponents to two random numbers and averaging them produces a range of interesting probability distributions for quality
(pow(Context.Random.NextFloat(), blueprint.RandomQualityExponent) +
pow(Context.Random.NextFloat(), blueprint.RandomQualityExponent)) / 2, ItemName);
if(ItemUnderConstruction!=Guid.Empty)
Item.Change();
}
// ToolingTime = Context.Evaluate(_data.ToolingTime, Item, Entity);
// var blueprint = Context.ItemData.Get<BlueprintData>(_blueprint);
// if (blueprint == null)
// return false;
//
// if (ItemUnderConstruction != Guid.Empty)
// {
// Entity.IncompleteCargo[ItemUnderConstruction] =
// Entity.IncompleteCargo[ItemUnderConstruction] - delta * (AssignedPopulation + _data.AutomationPoints) /
// pow(lerp(blueprint.QualityFloor, 1, saturate(_currentProductionQuality)),
// blueprint.ProductionExponent);
//
// if(Entity.IncompleteCargo[ItemUnderConstruction] < 0)
// {
// var item = Context.ItemData.Get<ItemInstance>(ItemUnderConstruction);
// if (item is SimpleCommodity simpleCommodity)
// Entity.AddCargo(simpleCommodity);
// else if (item is CraftedItemInstance craftedItemInstance)
// Entity.AddCargo(craftedItemInstance);
// Entity.IncompleteCargo.Remove(ItemUnderConstruction);
// ItemUnderConstruction = Guid.Empty;
// foreach (var attribute in _data.ProductionProfile)
// Entity.Personality[attribute.Key] = lerp(Entity.Personality[attribute.Key], attribute.Value,
// Context.GameplaySettings.ProductionPersonalityLerp * ((float) AssignedPopulation / Entity.Population));
// }
//
// return true;
// }
//
// if (RetoolingTime > 0)
// {
// RetoolingTime -= delta;
// return false;
// }
//
// if (_retooling)
// {
// _retooling = false;
// }
//
// if (Active)
// {
// var profileDistance = 0f;
// if (_data.ProductionProfile.Any())
// profileDistance = _data.ProductionProfile.Sum(x => abs(x.Value - Entity.Personality[x.Key])) /
// _data.ProductionProfile.Count;
// var personalityQuality =
// (_data.AutomationPoints * _data.AutomationQuality + AssignedPopulation * (1 - profileDistance)) /
// (_data.AutomationPoints + AssignedPopulation);
// ItemUnderConstruction = Entity.Build(blueprint,
// blueprint.Quality *
// pow(personalityQuality, blueprint.PersonalityExponent) *
// pow(ProductionQuality, blueprint.QualityExponent) *
// // Applying exponents to two random numbers and averaging them produces a range of interesting probability distributions for quality
// (pow(Context.Random.NextFloat(), blueprint.RandomQualityExponent) +
// pow(Context.Random.NextFloat(), blueprint.RandomQualityExponent)) / 2, ItemName);
// }
//
return false;
}
// TODO Update Factory Persistence
public PersistentBehaviorData Store()
{
return new FactoryPersistence
{
Blueprint = _blueprint,
RetoolingTime = RetoolingTime,
AssignedPopulation = AssignedPopulation,
ProductionQuality = ProductionQuality
};
}
public void Restore(PersistentBehaviorData data)
{
var factoryPersistence = data as FactoryPersistence;
_blueprint = factoryPersistence.Blueprint;
RetoolingTime = factoryPersistence.RetoolingTime;
AssignedPopulation = factoryPersistence.AssignedPopulation;
ProductionQuality = factoryPersistence.ProductionQuality;
}
//
// // TODO Update Factory Persistence
// public PersistentBehaviorData Store()
// {
// return new FactoryPersistence
// {
// Blueprint = _blueprint,
// RetoolingTime = RetoolingTime,
// AssignedPopulation = AssignedPopulation,
// ProductionQuality = ProductionQuality
// };
// }
//
// public void Restore(PersistentBehaviorData data)
// {
// var factoryPersistence = data as FactoryPersistence;
// _blueprint = factoryPersistence.Blueprint;
// RetoolingTime = factoryPersistence.RetoolingTime;
// AssignedPopulation = factoryPersistence.AssignedPopulation;
// ProductionQuality = factoryPersistence.ProductionQuality;
// }
//
// public Guid Build(BlueprintData blueprint, float quality, string name, bool direct = false)
// {
// if (direct)
// {
// if(blueprint.FactoryItem!=Guid.Empty)
// throw new ArgumentException("Attempted to directly build a blueprint which requires a factory!");
// var blueprintItem = Context.Cache.Get<GearData>(blueprint.Item);
// if(blueprintItem == null)
// throw new ArgumentException("Attempted to directly build a blueprint for a missing or incompatible item!");
// }
//
// //var newItemID = Guid.Empty;
//
// // GetBlueprintIngredients will assign the output lists with the items matching the blueprint, and return false if they are not found
// if (!GetBlueprintIngredients(blueprint, out var simpleIngredients, out var compoundIngredients))
// return Guid.Empty;
//
// // These will be bundled with the data for the compound commodity instance
// var ingredients = new List<ItemInstance>();
// ingredients.AddRange(compoundIngredients.Select(RemoveCargo));
// ingredients.AddRange(simpleIngredients.Select(sc => RemoveCargo(sc, blueprint.Ingredients[sc.Data])));
//
// var blueprintItemData = Context.Cache.Get(blueprint.Item);
//
// // Creating new crafted item instances is a bit more complicated
// if (blueprintItemData is CraftedItemData)
// {
// CraftedItemInstance newItem;
//
// if (blueprintItemData is EquippableItemData equippableItemData)
// {
// var newGear = new EquippableItem
// {
// Context = Context,
// Data = blueprintItemData.ID,
// Ingredients = ingredients.Select(ii=>ii.ID).ToList(),
// Quality = quality,
// Blueprint = blueprint.ID,
// Name = name,
// SourceEntity = ID
// };
// newGear.Durability = Context.Evaluate(equippableItemData.Durability, newGear);
// newItem = newGear;
// }
// else
// {
// newItem = new CompoundCommodity
// {
// Context = Context,
// Data = blueprintItemData.ID,
// Ingredients = ingredients.Select(ii=>ii.ID).ToList(),
// Quality = quality,
// Blueprint = blueprint.ID,
// Name = name,
// SourceEntity = ID
// };
// }
// Context.Cache.Add(newItem);
// if (direct)
// IncompleteGear[newItem.ID] = blueprint.ProductionTime;
// else
// IncompleteCargo[newItem.ID] = blueprint.ProductionTime;
// return newItem.ID;
// }
//
// var newSimpleCommodity = new SimpleCommodity
// {
// Context = Context,
// Data = blueprintItemData.ID,
// Quantity = 1
// };
// Context.Cache.Add(newSimpleCommodity);
// IncompleteCargo[newSimpleCommodity.ID] = blueprint.ProductionTime;
// return newSimpleCommodity.ID;
// }
//
// public bool GetBlueprintIngredients(BlueprintData blueprint, out List<SimpleCommodity> simpleIngredients,
// out List<CompoundCommodity> compoundIngredients)
// {
// simpleIngredients = new List<SimpleCommodity>();
// compoundIngredients = new List<CompoundCommodity>();
// var hasAllIngredients = true;
// var cargoInstances = Cargo.Select(c => Context.Cache.Get<ItemInstance>(c));
// foreach (var kvp in blueprint.Ingredients)
// {
// var itemData = Context.Cache.Get(kvp.Key);
// if (itemData is SimpleCommodityData)
// {
// var matchingItem = cargoInstances.FirstOrDefault(ii =>
// {
// if (!(ii is SimpleCommodity simpleCommodity)) 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 =
// cargoInstances.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.Take(kvp.Value));
// }
// }
//
// return hasAllIngredients;
// }
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]

View file

@ -12,136 +12,121 @@ public class HaulingControllerData : ControllerData
{
[InspectableField, JsonProperty("targetDistance"), Key(6)]
public float DockTime = 2;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new HaulingController(context, this, entity, item);
}
}
public class HaulingController : ControllerBase, IBehavior, IPersistentBehavior
public class HaulingController : ControllerBase<HaulingTask>, IBehavior, IPersistentBehavior
{
public override TaskType TaskType => TaskType.Haul;
public BehaviorData Data => _data;
private HaulingControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private ItemManager ItemManager { get; }
private Entity Entity { get; }
private EquippedItem Item { get; }
private bool _taskStarted;
private int _itemsDelivered;
private int _itemsCarried;
private SimpleCommodity _simpleCommodityDelivery;
private List<CraftedItemInstance> _craftedItemDelivery = new List<CraftedItemInstance>();
public HaulingController(GameContext context, HaulingControllerData data, Entity entity, Gear item) : base(context, data, entity)
public HaulingController(ItemManager itemManager, HaulingControllerData data, Entity entity, EquippedItem item) : base(itemManager, data, entity)
{
_context = context;
ItemManager = itemManager;
_data = data;
_entity = entity;
_item = item;
Entity = entity;
Item = item;
}
public new bool Update(float delta)
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
if (haulingTask != null)
if (Task != null)
{
if (!_taskStarted)
{
MoveTo(haulingTask.Zone, OnOriginZoneArrival);
MoveTo(Task.Origin, true, OnPickup);
//MoveTo(haulingTask.Zone, OnOriginZoneArrival);
_taskStarted = true;
}
}
return base.Update(delta);
}
void OnOriginZoneArrival()
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
_entity.SetMessage("Entering pickup phase.");
MoveTo(_context.Cache.Get<Entity>(haulingTask.Origin), true, OnPickup);
}
// void OnOriginZoneArrival()
// {
// var haulingTask = _context.ItemData.Get<HaulingTask>(Task);
//
// _entity.SetMessage("Entering pickup phase.");
//
// MoveTo(_context.ItemData.Get<Entity>(haulingTask.Origin), true, OnPickup);
// }
void OnPickup()
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
var target = Zone.Entities[haulingTask.Origin] as OrbitalEntity;
Entity.SetParent(Task.Origin);
_itemsCarried = Task.Origin.TryTransferItems(Entity, Task.ItemType, Task.Quantity - _itemsDelivered);
if (_itemsCarried == 0)
{
FinishTask();
return;
}
_entity.SetParent(target);
var itemData = _context.Cache.Get<ItemData>(haulingTask.ItemType);
int quantity = min((int) ((_entity.Capacity - _entity.OccupiedCapacity) / itemData.Size), haulingTask.Quantity - _itemsDelivered);
if (itemData is SimpleCommodityData)
{
var itemMatch = target.Cargo
.Select(id => _context.Cache.Get<SimpleCommodity>(id))
.FirstOrDefault(ii => ii != null && ii.Data == haulingTask.ItemType);
if(itemMatch==null)
FinishTask();
_simpleCommodityDelivery = _entity.AddCargo(target.RemoveCargo(itemMatch, quantity));
}
else if (itemData is CraftedItemData)
{
var itemMatches = target.Cargo
.Select(id => _context.Cache.Get<CraftedItemInstance>(id))
.Where(ii => ii != null && ii.Data == haulingTask.ItemType)
.ToArray();
if(!itemMatches.Any())
FinishTask();
foreach (var match in itemMatches)
_craftedItemDelivery.Add(_entity.AddCargo(target.RemoveCargo(match)));
}
Wait(_data.DockTime, OnItemObtained);
}
void OnItemObtained()
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
_entity.SetMessage("Entering delivery phase.");
Entity.SetMessage("Entering delivery phase.");
var target = _context.Cache.Get<Entity>(haulingTask.Target);
MoveTo(target.Zone.Data.ID, OnTargetZoneArrival);
MoveTo(Task.Target, true, OnDelivery);
//MoveTo(target.Zone.Data.ID, OnTargetZoneArrival);
}
void OnTargetZoneArrival()
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
MoveTo(_context.Cache.Get<Entity>(haulingTask.Target), true, OnDelivery);
}
// void OnTargetZoneArrival()
// {
// var haulingTask = _context.ItemData.Get<HaulingTask>(Task);
//
// MoveTo(_context.ItemData.Get<Entity>(haulingTask.Target), true, OnDelivery);
// }
void OnDelivery()
{
var haulingTask = _context.Cache.Get<HaulingTask>(Task);
var target = Zone.Entities[haulingTask.Target] as OrbitalEntity;
_entity.SetParent(target);
var itemData = _context.Cache.Get<ItemData>(haulingTask.ItemType);
if (itemData is SimpleCommodityData)
{
target.AddCargo(_entity.RemoveCargo(_simpleCommodityDelivery, _simpleCommodityDelivery.Quantity));
_itemsDelivered += _simpleCommodityDelivery.Quantity;
_simpleCommodityDelivery = null;
}
else if (itemData is CraftedItemData)
{
foreach (var item in _craftedItemDelivery)
target.AddCargo(_entity.RemoveCargo(item));
_itemsDelivered += _craftedItemDelivery.Count;
_craftedItemDelivery.Clear();
}
Entity.SetParent(Task.Target);
var itemsDelivered = Entity.TryTransferItems(Task.Target, Task.ItemType, _itemsCarried);
_itemsCarried -= itemsDelivered;
_itemsDelivered += itemsDelivered;
Wait(_data.DockTime, () =>
{
if(_itemsDelivered == haulingTask.Quantity)
// We were unable to transfer all onboard items to target entity, cargo is probably full. Bring back the surplus and end the mission
if(_itemsCarried > 0)
MoveTo(Task.Origin, true, ReturnSurplusToOrigin);
// We have delivered the target quantity of items, end the mission
else if(_itemsDelivered >= Task.Quantity)
FinishTask();
// We aren't done yet. Resetting the task will make us go for another delivery run
else
_taskStarted = false;
});
}
void ReturnSurplusToOrigin()
{
Entity.SetParent(Task.Origin);
Entity.TryTransferItems(Task.Origin, Task.ItemType, _itemsCarried);
Wait(_data.DockTime, OnItemObtained);
FinishTask();
}
public PersistentBehaviorData Store()
{
return new HaulingControllerPersistence
@ -160,5 +145,5 @@ public class HaulingController : ControllerBase, IBehavior, IPersistentBehavior
public class HaulingControllerPersistence : PersistentBehaviorData
{
[JsonProperty("task"), Key(0)]
public Guid Task;
public HaulingTask Task;
}

View file

@ -12,7 +12,7 @@ public class HeatData : BehaviorData
[InspectableField, JsonProperty("perSecond"), Key(2)]
public bool PerSecond;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Heat(context, this, entity, item);
}
@ -23,12 +23,12 @@ public class Heat : IBehavior
private HeatData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public Heat(GameContext context, HeatData data, Entity entity, Gear item)
public Heat(ItemManager context, HeatData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -38,7 +38,7 @@ public class Heat : IBehavior
public bool Update(float delta)
{
Entity.AddHeat(Context.Evaluate(_data.Heat, Item, Entity) * (_data.PerSecond ? delta : 1));
Item.Temperature += Context.Evaluate(_data.Heat, Item.EquippableItem, Entity) * (_data.PerSecond ? delta : 1) / Context.GetThermalMass(Item.EquippableItem);
return true;
}
}

View file

@ -7,7 +7,7 @@ public class HitscanData : WeaponData
[InspectableField, JsonProperty("perSecond"), Key(6)]
public bool PerSecond;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Hitscan(context, this, entity, item);
}
@ -19,14 +19,14 @@ public class Hitscan : IBehavior
private float _cooldown; // normalized
private HitscanData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
private float _firingVisibility;
public BehaviorData Data => _data;
public float Range { get; private set; }
public Hitscan(GameContext context, HitscanData c, Entity entity, Gear item)
public Hitscan(ItemManager context, HitscanData c, Entity entity, EquippedItem item)
{
Context = context;
_data = c;
@ -37,7 +37,7 @@ public class Hitscan : IBehavior
public bool Update(float delta)
{
// TODO: Implement hitscan weapons!
Range = Context.Evaluate(_data.Range, Item, Entity);
Range = Context.Evaluate(_data.Range, Item.EquippableItem, Entity);
return true;
}

View file

@ -10,7 +10,7 @@ public class ItemUsageData : BehaviorData
[InspectableDatabaseLink(typeof(SimpleCommodityData)), JsonProperty("item"), Key(1), RuntimeInspectable]
public Guid Item;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new ItemUsage(context, this, entity, item);
}
@ -21,12 +21,12 @@ public class ItemUsage : IBehavior
private ItemUsageData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public ItemUsage(GameContext context, ItemUsageData data, Entity entity, Gear item)
public ItemUsage(ItemManager context, ItemUsageData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -36,19 +36,15 @@ public class ItemUsage : IBehavior
public bool Update(float delta)
{
var cargoInstances = Entity.Cargo.Select(c => Context.Cache.Get<ItemInstance>(c));
if (cargoInstances.FirstOrDefault(c => c.Data == _data.Item) is SimpleCommodity item)
{
if (item.Quantity > 1)
item.Quantity--;
else
{
Entity.Cargo.Remove(item.ID);
Context.Cache.Delete(item);
}
var cargo = Entity.FindItemInCargo(_data.Item);
if (cargo == null) return false;
return true;
}
return false;
var item = cargo.ItemsOfType[_data.Item][0];
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
if (item is CraftedItemInstance craftedItemInstance)
cargo.Remove(craftedItemInstance);
return true;
}
}

View file

@ -37,7 +37,7 @@ public class LauncherData : WeaponData
[InspectableField, JsonProperty("lockOnTime"), Key(15)]
public PerformanceStat LockOnTime = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Launcher(context, this, entity, item);
}
@ -52,13 +52,13 @@ public class Launcher : IBehavior, IAlwaysUpdatedBehavior
private LauncherData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
private float _firingVisibility;
public BehaviorData Data => _data;
public Launcher(GameContext context, LauncherData m, Entity entity, Gear item)
public Launcher(ItemManager context, LauncherData m, Entity entity, EquippedItem item)
{
Context = context;
_data = m;

View file

@ -10,117 +10,110 @@ using static Unity.Mathematics.math;
[MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)]
public class MiningControllerData : ControllerData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new MiningController(context, this, entity, item);
}
}
public class MiningController : ControllerBase, IBehavior, IPersistentBehavior, IInitializableBehavior
public class MiningController : ControllerBase<Mining>, IBehavior, IPersistentBehavior, IInitializableBehavior
{
public override TaskType TaskType => TaskType.Mine;
public BehaviorData Data => _data;
private MiningControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private EquippedItem Item { get; }
private bool _taskStarted;
private int _asteroid = -1;
private MiningTool _miningTool;
private Switch _toolSwitch;
public MiningController(GameContext context, MiningControllerData data, Entity entity, Gear item) : base(context, data, entity)
public MiningController(ItemManager itemManager, MiningControllerData data, Entity entity, EquippedItem item) : base(itemManager, data, entity)
{
_context = context;
_data = data;
_entity = entity;
_item = item;
Item = item;
}
public new void Initialize()
{
_miningTool = _entity.GetBehavior<MiningTool>();
_toolSwitch = _entity.GetSwitch<MiningTool>();
_miningTool = Entity.GetBehavior<MiningTool>();
_toolSwitch = Entity.GetSwitch<MiningTool>();
base.Initialize();
}
public new bool Update(float delta)
{
var miningTask = _context.Cache.Get<Mining>(Task);
if (miningTask != null)
{
if (!_taskStarted)
{
NextAsteroid();
_taskStarted = true;
}
else
{
if (!Moving)
{
if (_entity.OccupiedCapacity < _entity.Capacity - 1)
{
var asteroidTransform = Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid);
if (length(_entity.Position - asteroidTransform.xy) - asteroidTransform.w > _miningTool.Range)
{
_entity.SetMessage("Moving to target asteroid.");
MoveTo(() => Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid).xy,
() => Zone.GetAsteroidVelocity(miningTask.Asteroids, _asteroid));
_toolSwitch.Activated = false;
}
else
{
if (Zone.AsteroidExists(miningTask.Asteroids, _asteroid))
{
_miningTool.AsteroidBelt = miningTask.Asteroids;
_miningTool.Asteroid = _asteroid;
_toolSwitch.Activated = true;
Aim.Objective = Zone.GetAsteroidTransform(miningTask.Asteroids, _asteroid).xy;
Aim.Update(delta);
}
else NextAsteroid();
}
}
else
{
_entity.SetMessage("Out of cargo space. Returning home to offload cargo.");
GoHome(OnArriveHome);
}
}
}
}
// if (Task != null)
// {
// if (!_taskStarted)
// {
// NextAsteroid();
// _taskStarted = true;
// }
// else
// {
// if (!Moving)
// {
// if (_entity.OccupiedCapacity < _entity.Capacity - 1)
// {
// var asteroidTransform = Zone.GetAsteroidTransform(Task.Asteroids, _asteroid);
// if (length(_entity.Position - asteroidTransform.xy) - asteroidTransform.w > _miningTool.Range)
// {
// _entity.SetMessage("Moving to target asteroid.");
// MoveTo(() => Zone.GetAsteroidTransform(Task.Asteroids, _asteroid).xy,
// () => Zone.GetAsteroidVelocity(Task.Asteroids, _asteroid));
// _toolSwitch.Activated = false;
// }
// else
// {
// if (Zone.AsteroidExists(Task.Asteroids, _asteroid))
// {
// _miningTool.AsteroidBelt = Task.Asteroids;
// _miningTool.Asteroid = _asteroid;
// _toolSwitch.Activated = true;
// Aim.Objective = Zone.GetAsteroidTransform(Task.Asteroids, _asteroid).xy;
// Aim.Update(delta);
// }
// else NextAsteroid();
// }
// }
// else
// {
// _entity.SetMessage("Out of cargo space. Returning home to offload cargo.");
// GoHome(OnArriveHome);
// }
// }
// }
// }
return base.Update(delta);
}
private void OnArriveHome()
{
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
foreach (var item in _entity.Cargo
.Select(id => _context.Cache.Get<ItemInstance>(id))
.Where(item => item is SimpleCommodity)
.Cast<SimpleCommodity>()
.ToArray())
{
int quantity = min((int) ((homeEntity.Capacity - homeEntity.OccupiedCapacity) / item.ItemData.Size), item.Quantity);
var newItem = _entity.RemoveCargo(item, quantity);
homeEntity.AddCargo(newItem);
if (quantity < item.Quantity)
{
homeEntity.SetMessage("Colony is out of cargo space. Closing Mining Task.");
FinishTask();
_taskStarted = false;
return;
}
}
}
// private void OnArriveHome()
// {
// var homeEntity = _context.ItemData.Get<Entity>(HomeEntity);
// foreach (var item in _entity.Cargo
// .Select(id => _context.ItemData.Get<ItemInstance>(id))
// .Where(item => item is SimpleCommodity)
// .Cast<SimpleCommodity>()
// .ToArray())
// {
// int quantity = min((int) ((homeEntity.Capacity - homeEntity.OccupiedCapacity) / _context.GetData(item).Size), item.Quantity);
// var newItem = _entity.RemoveCargo(item, quantity);
// homeEntity.AddCargo(newItem);
//
// if (quantity < item.Quantity)
// {
// homeEntity.SetMessage("Colony is out of cargo space. Closing Mining Task.");
// FinishTask();
// _taskStarted = false;
// return;
// }
// }
// }
private void NextAsteroid()
{
var miningTask = _context.Cache.Get<Mining>(Task);
_asteroid = Zone.NearestAsteroid(miningTask.Asteroids, _entity.Position);
_entity.SetMessage("Selecting new asteroid.");
_asteroid = Zone.NearestAsteroid(Task.Asteroids, Entity.Position);
Entity.SetMessage("Selecting new asteroid.");
}
public PersistentBehaviorData Store()
@ -141,5 +134,5 @@ public class MiningController : ControllerBase, IBehavior, IPersistentBehavior,
public class MiningControllerPersistence : PersistentBehaviorData
{
[JsonProperty("task"), Key(0)]
public Guid Task;
public Mining Task;
}

View file

@ -20,7 +20,7 @@ public class MiningToolData : BehaviorData
[InspectableField, JsonProperty("range"), Key(4)]
public PerformanceStat Range = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new MiningTool(context, this, entity, item);
}
@ -34,13 +34,13 @@ public class MiningTool : IBehavior
private MiningToolData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public float Range { get; private set; }
public MiningTool(GameContext context, MiningToolData data, Entity entity, Gear item)
public MiningTool(ItemManager context, MiningToolData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -50,7 +50,7 @@ public class MiningTool : IBehavior
public bool Update(float delta)
{
Range = Context.Evaluate(_data.Range, Item, Entity);
Range = Context.Evaluate(_data.Range, Item.EquippableItem, Entity);
var asteroidTransform = Entity.Zone.GetAsteroidTransform(AsteroidBelt, Asteroid);
if (AsteroidBelt != Guid.Empty &&
Entity.Zone.AsteroidExists(AsteroidBelt, Asteroid) &&
@ -60,9 +60,9 @@ public class MiningTool : IBehavior
Entity,
AsteroidBelt,
Asteroid,
Context.Evaluate(_data.DamagePerSecond, Item, Entity) * delta,
Context.Evaluate(_data.Efficiency, Item, Entity),
Context.Evaluate(_data.Penetration, Item, Entity));
Context.Evaluate(_data.DamagePerSecond, Item.EquippableItem, Entity) * delta,
Context.Evaluate(_data.Efficiency, Item.EquippableItem, Entity),
Context.Evaluate(_data.Penetration, Item.EquippableItem, Entity));
return true;
}

View file

@ -10,58 +10,50 @@ using static Unity.Mathematics.math;
[MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)]
public class PatrolControllerData : ControllerData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new PatrolController(context, this, entity, item);
}
}
public class PatrolController : IBehavior, IController, IInitializableBehavior
public class PatrolController : IBehavior, IInitializableBehavior
{
public TaskType TaskType => TaskType.None;
public bool Available => false;
public Zone Zone => _entity.Zone;
public BehaviorData Data => _data;
private PatrolControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private ItemManager Context { get; }
private Entity Entity { get; }
private EquippedItem Item { get; }
private Locomotion _locomotion;
private Guid _targetOrbit;
public PatrolController(GameContext context, PatrolControllerData data, Entity entity, Gear item)
public PatrolController(ItemManager context, PatrolControllerData data, Entity entity, EquippedItem item)
{
_context = context;
Context = context;
_data = data;
_entity = entity;
_item = item;
Entity = entity;
Item = item;
}
public void Initialize()
{
_locomotion = new Locomotion(_context, _entity, _data);
_locomotion = new Locomotion(Context, Entity, _data);
RandomTarget();
}
public bool Update(float delta)
{
_locomotion.Objective = Zone.GetOrbitPosition(_targetOrbit);
_locomotion.Objective = Entity.Zone.GetOrbitPosition(_targetOrbit);
_locomotion.Update(delta);
if(length(_entity.Position - _locomotion.Objective) < _data.TargetDistance)
if(length(Entity.Position - _locomotion.Objective) < _data.TargetDistance)
RandomTarget();
return true;
}
public void AssignTask(Guid task)
{
throw new NotImplementedException();
}
private void RandomTarget()
{
_targetOrbit = Zone.Planets.Keys.ToArray()[_context.Random.NextInt(Zone.Planets.Count)];
_targetOrbit = Entity.Zone.Planets.Keys.ToArray()[Context.Random.NextInt(Entity.Zone.Planets.Count)];
}
}

View file

@ -16,7 +16,7 @@ public class ProjectileWeaponData : WeaponData
[InspectableField, JsonProperty("bulletVelocity"), Key(9)]
public PerformanceStat Velocity = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new ProjectileWeapon(context, this, entity, item);
}
@ -26,12 +26,12 @@ public class ProjectileWeapon : IBehavior
{
private ProjectileWeaponData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public ProjectileWeapon(GameContext context, ProjectileWeaponData c, Entity entity, Gear item)
public ProjectileWeapon(ItemManager context, ProjectileWeaponData c, Entity entity, EquippedItem item)
{
Context = context;
_data = c;

View file

@ -9,7 +9,7 @@ public class RadianceData : BehaviorData
[InspectableField, JsonProperty("radiance"), Key(1), RuntimeInspectable]
public PerformanceStat Radiance = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Radiance(context, this, entity, item);
}
@ -20,12 +20,12 @@ public class Radiance : IBehavior
private RadianceData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public Radiance(GameContext context, RadianceData data, Entity entity, Gear item)
public Radiance(ItemManager context, RadianceData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;

View file

@ -9,7 +9,7 @@ public class RadiatorData : BehaviorData
[InspectableField, JsonProperty("emissivity"), Key(1), RuntimeInspectable]
public PerformanceStat Emissivity = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Radiator(context, this, entity, item);
}
@ -18,8 +18,8 @@ public class RadiatorData : BehaviorData
public class Radiator : IBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
@ -27,7 +27,7 @@ public class Radiator : IBehavior
private RadiatorData _data;
public Radiator(GameContext context, RadiatorData data, Entity entity, Gear item)
public Radiator(ItemManager context, RadiatorData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
@ -37,9 +37,9 @@ public class Radiator : IBehavior
public bool Update(float delta)
{
Emissivity = Context.Evaluate(_data.Emissivity, Item, Entity);
var rad = pow(Entity.Temperature, Context.GlobalData.HeatRadiationPower) * Context.GlobalData.HeatRadiationMultiplier * Emissivity;
Entity.Temperature -= rad * delta;
Emissivity = Context.Evaluate(_data.Emissivity, Item.EquippableItem, Entity);
var rad = pow(Item.Temperature, Context.GameplaySettings.HeatRadiationExponent) * Context.GameplaySettings.HeatRadiationMultiplier * Emissivity;
Item.Temperature -= rad * delta;
Entity.VisibilitySources[this] = rad;
return true;
}

View file

@ -19,7 +19,7 @@ public class ReactorData : BehaviorData
[InspectableField, JsonProperty("underload"), Key(5), RuntimeInspectable]
public PerformanceStat ThrottlingFactor = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Reactor(context, this, entity, item);
}
@ -30,13 +30,13 @@ public class Reactor : IBehavior
private ReactorData _data;
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
public float Capacitance;
public Reactor(GameContext context, ReactorData data, Entity entity, Gear item)
public Reactor(ItemManager context, ReactorData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
@ -46,22 +46,22 @@ public class Reactor : IBehavior
public bool Update(float delta)
{
Capacitance = Context.Evaluate(_data.Capacitance, Item, Entity);
var charge = Context.Evaluate(_data.Charge, Item, Entity) * delta;
var efficiency = Context.Evaluate(_data.Efficiency, Item, Entity);
Capacitance = Context.Evaluate(_data.Capacitance, Item.EquippableItem, Entity);
var charge = Context.Evaluate(_data.Charge, Item.EquippableItem, Entity) * delta;
var efficiency = Context.Evaluate(_data.Efficiency, Item.EquippableItem, Entity);
Entity.AddHeat(charge / efficiency);
Item.Temperature += (charge / efficiency) / Context.GetThermalMass(Item.EquippableItem);
Entity.Energy += charge;
if (Entity.Energy > Capacitance)
{
Entity.AddHeat(-(Entity.Energy - Capacitance) / efficiency * (1 - 1 / Context.Evaluate(_data.ThrottlingFactor, Item, Entity)));
Item.Temperature -= (Entity.Energy - Capacitance) / efficiency * (1 - 1 / Context.Evaluate(_data.ThrottlingFactor, Item.EquippableItem, Entity)) / Context.GetThermalMass(Item.EquippableItem);
Entity.Energy = Capacitance;
}
if (Entity.Energy < 0)
{
Entity.AddHeat( -Entity.Energy / Context.Evaluate(_data.OverloadEfficiency, Item, Entity));
Item.Temperature += -Entity.Energy / Context.Evaluate(_data.OverloadEfficiency, Item.EquippableItem, Entity) / Context.GetThermalMass(Item.EquippableItem);
Entity.Energy = 0;
}
return true;

View file

@ -12,7 +12,7 @@ public class ReflectorData : BehaviorData
// [InspectableAnimationCurve, JsonProperty("visibility"), Key(1)]
// public float4[] VisibilityCurve;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Reflector(context, this, entity, item);
}
@ -21,14 +21,14 @@ public class ReflectorData : BehaviorData
public class Reflector : IBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
private ReflectorData _data;
public Reflector(GameContext context, ReflectorData data, Entity entity, Gear item)
public Reflector(ItemManager context, ReflectorData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;

View file

@ -17,7 +17,7 @@ public class ResourceScannerData : BehaviorData
[InspectableField, JsonProperty("scanDuration"), Key(3), RuntimeInspectable]
public PerformanceStat ScanDuration = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new ResourceScanner(context, this, entity, item);
}
@ -32,8 +32,8 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
private Guid _scanTarget;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public float Range { get; private set; }
@ -53,7 +53,7 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
}
}
public ResourceScanner(GameContext context, ResourceScannerData data, Entity entity, Gear item)
public ResourceScanner(ItemManager context, ResourceScannerData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -63,7 +63,7 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
public bool Update(float delta)
{
var planetData = Context.Cache.Get<BodyData>(ScanTarget);
var planetData = Context.ItemData.Get<BodyData>(ScanTarget);
if (planetData != null)
{
if (planetData is AsteroidBeltData beltData)
@ -75,7 +75,8 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
_scanTime += delta;
if (_scanTime > ScanDuration)
{
Context.Cache.Get<Corporation>(Entity.Corporation).PlanetSurveyFloor[ScanTarget] = MinimumDensity;
// TODO: Implement Scanning!
//Context.ItemData.Get<Corporation>(Entity.Corporation).PlanetSurveyFloor[ScanTarget] = MinimumDensity;
_scanTime = 0;
}
return true;
@ -88,7 +89,7 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
_scanTime += delta;
if (_scanTime > ScanDuration)
{
Context.Cache.Get<Corporation>(Entity.Corporation).PlanetSurveyFloor[ScanTarget] = MinimumDensity;
//Context.ItemData.Get<Corporation>(Entity.Corporation).PlanetSurveyFloor[ScanTarget] = MinimumDensity;
_scanTime = 0;
}
return true;
@ -100,8 +101,8 @@ public class ResourceScanner : IBehavior, IAlwaysUpdatedBehavior
public void AlwaysUpdate(float delta)
{
Range = Context.Evaluate(_data.Range, Item, Entity);
MinimumDensity = Context.Evaluate(_data.MinimumDensity, Item, Entity);
ScanDuration = Context.Evaluate(_data.ScanDuration, Item, Entity);
Range = Context.Evaluate(_data.Range, Item.EquippableItem, Entity);
MinimumDensity = Context.Evaluate(_data.MinimumDensity, Item.EquippableItem, Entity);
ScanDuration = Context.Evaluate(_data.ScanDuration, Item.EquippableItem, Entity);
}
}

View file

@ -8,7 +8,7 @@ public class SensorData : BehaviorData
[InspectableField, JsonProperty("sensitivity"), Key(3), RuntimeInspectable]
public PerformanceStat Sensitivity = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Sensor(context, this, entity, item);
}
@ -19,12 +19,12 @@ public class Sensor : IBehavior
private SensorData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public Sensor(GameContext context, SensorData data, Entity entity, Gear item)
public Sensor(ItemManager context, SensorData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;

View file

@ -12,7 +12,7 @@ public class ShieldData : BehaviorData
[InspectableField, JsonProperty("shielding"), Key(2), RuntimeInspectable]
public PerformanceStat Shielding = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Shield(context, this, entity, item);
}
@ -21,14 +21,14 @@ public class ShieldData : BehaviorData
public class Shield : IBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
private ShieldData _data;
public Shield(GameContext context, ShieldData data, Entity entity, Gear item)
public Shield(ItemManager context, ShieldData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;

View file

@ -18,7 +18,7 @@ public class StatModifierData : BehaviorData
[InspectableType(typeof(BehaviorData)), JsonProperty("requireBehavior"), Key(4)]
public Type RequireBehavior;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new StatModifier(context, this, entity, item);
}
@ -29,8 +29,8 @@ public class StatModifier : IBehavior, IInitializableBehavior, IDisposableBehavi
{
private StatModifierData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
@ -38,10 +38,10 @@ public class StatModifier : IBehavior, IInitializableBehavior, IDisposableBehavi
private static Type[] _statObjects;
private static Type[] StatObjects => _statObjects ?? (_statObjects = typeof(BehaviorData).GetAllChildClasses()
.Concat(typeof(EquippableItemData).GetAllChildClasses()).ToArray());
private static Type[] StatObjects => _statObjects = _statObjects ?? typeof(BehaviorData).GetAllChildClasses()
.Concat(typeof(EquippableItemData).GetAllChildClasses()).ToArray();
public StatModifier(GameContext context, StatModifierData data, Entity entity, Gear item)
public StatModifier(ItemManager context, StatModifierData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -59,19 +59,17 @@ public class StatModifier : IBehavior, IInitializableBehavior, IDisposableBehavi
if (statField != null)
{
if (typeof(EquippableItemData).IsAssignableFrom(targetType))
_stats = Entity.Hardpoints
.Select(hp => hp.Gear)
.Where(gear => gear != null)
.Where(gear => _data.RequireBehavior == null || gear.ItemData.Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
.Where(gear => gear.ItemData.GetType() == targetType)
.Select(gear => statField.GetValue(gear.ItemData) as PerformanceStat)
_stats = Entity.EquippedItems
.Select(hp => hp.EquippableItem)
.Where(gear => _data.RequireBehavior == null || Context.GetData(gear).Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
.Where(gear => Context.GetData(gear).GetType() == targetType)
.Select(gear => statField.GetValue(Context.GetData(gear)) as PerformanceStat)
.ToArray();
else
_stats = Entity.Hardpoints
.Select(hp => hp.Gear)
.Where(gear => gear != null)
.Where(gear => _data.RequireBehavior == null || gear.ItemData.Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
.SelectMany(gear => gear.ItemData.Behaviors)
_stats = Entity.EquippedItems
.Select(hp => hp.EquippableItem)
.Where(gear => _data.RequireBehavior == null || Context.GetData(gear).Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
.SelectMany(gear => Context.GetData(gear).Behaviors)
.Where(behaviorData => behaviorData.GetType() == targetType)
.Select(behaviorData => statField.GetValue(behaviorData) as PerformanceStat)
.ToArray();
@ -84,7 +82,7 @@ public class StatModifier : IBehavior, IInitializableBehavior, IDisposableBehavi
foreach (var stat in _stats)
(_data.Type == StatModifierType.Constant
? stat.GetConstantModifiers(Entity)
: stat.GetScaleModifiers(Entity))[this] = Context.Evaluate(_data.Modifier, Item, Entity);
: stat.GetScaleModifiers(Entity))[this] = Context.Evaluate(_data.Modifier, Item.EquippableItem, Entity);
return true;
}

View file

@ -11,109 +11,102 @@ using static Unity.Mathematics.math;
[MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)]
public class SurveyControllerData : ControllerData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new SurveyController(context, this, entity, item);
}
}
public class SurveyController : ControllerBase, IBehavior, IPersistentBehavior, IInitializableBehavior
public class SurveyController : ControllerBase<Survey>, IBehavior, IPersistentBehavior, IInitializableBehavior
{
public override TaskType TaskType => TaskType.Explore;
private EquippedItem Item { get; }
public BehaviorData Data => _data;
private SurveyControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private bool _taskStarted;
private ResourceScanner _scanningTool;
private Switch _toolSwitch;
private Guid _targetPlanet;
private int _asteroid = -1;
public SurveyController(GameContext context, SurveyControllerData data, Entity entity, Gear item) : base(context, data, entity)
public SurveyController(ItemManager itemManager, SurveyControllerData data, Entity entity, EquippedItem item) : base(itemManager, data, entity)
{
_context = context;
_data = data;
_entity = entity;
_item = item;
Item = item;
}
public new void Initialize()
{
_scanningTool = _entity.GetBehavior<ResourceScanner>();
_toolSwitch = _entity.GetSwitch<ResourceScanner>();
_scanningTool = Entity.GetBehavior<ResourceScanner>();
_toolSwitch = Entity.GetSwitch<ResourceScanner>();
base.Initialize();
}
public new bool Update(float delta)
{
var surveyTask = _context.Cache.Get<Survey>(Task);
var corporation = _context.Cache.Get<Corporation>(_entity.Corporation);
if (surveyTask != null)
{
if (!_taskStarted)
{
if (surveyTask.Planets.Any())
{
_entity.SetMessage("Moving to survey target.");
NextPlanet();
_scanningTool.ScanTarget = _targetPlanet;
_scanningTool.Asteroid = _asteroid;
if (!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) ||
corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity)
{
var planetData = _context.Cache.Get<BodyData>(_targetPlanet);
MoveTo(() =>
{
var target = GetPosition(planetData, _asteroid);
var targetToUs = _entity.Position - target;
return target + normalize(targetToUs) * _scanningTool.Range / 2;
},
() => GetVelocity(planetData, _asteroid),
() => _entity.SetMessage("Arrived at target. Scanning for resources."));
_taskStarted = true;
}
else
surveyTask.Planets.Remove(_targetPlanet);
}
else
{
_entity.SetMessage("Survey complete. Returning Home.");
FinishTask();
}
}
else
{
if (!Moving)
{
var planetData = _context.Cache.Get<BodyData>(_targetPlanet);
if ((!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) ||
corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity) &&
length(_entity.Position - GetPosition(planetData, _asteroid)) < _scanningTool.Range)
{
_toolSwitch.Activated = true;
Aim.Objective = GetPosition(planetData, _asteroid);
Aim.Update(delta);
}
else
{
_toolSwitch.Activated = false;
_taskStarted = false;
}
}
}
}
// var corporation = _context.ItemData.Get<Corporation>(_entity.Corporation);
// if (surveyTask != null)
// {
// if (!_taskStarted)
// {
// if (surveyTask.Planets.Any())
// {
// _entity.SetMessage("Moving to survey target.");
// NextPlanet();
// _scanningTool.ScanTarget = _targetPlanet;
// _scanningTool.Asteroid = _asteroid;
// if (!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) ||
// corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity)
// {
// var planetData = _context.ItemData.Get<BodyData>(_targetPlanet);
// MoveTo(() =>
// {
// var target = GetPosition(planetData, _asteroid);
// var targetToUs = _entity.Position - target;
// return target + normalize(targetToUs) * _scanningTool.Range / 2;
// },
// () => GetVelocity(planetData, _asteroid),
// () => _entity.SetMessage("Arrived at target. Scanning for resources."));
// _taskStarted = true;
// }
// else
// surveyTask.Planets.Remove(_targetPlanet);
// }
// else
// {
// _entity.SetMessage("Survey complete. Returning Home.");
// FinishTask();
// }
// }
// else
// {
// if (!Moving)
// {
// var planetData = _context.ItemData.Get<BodyData>(_targetPlanet);
// if ((!corporation.PlanetSurveyFloor.ContainsKey(_targetPlanet) ||
// corporation.PlanetSurveyFloor[_targetPlanet] + .5f < _scanningTool.MinimumDensity) &&
// length(_entity.Position - GetPosition(planetData, _asteroid)) < _scanningTool.Range)
// {
// _toolSwitch.Activated = true;
// Aim.Objective = GetPosition(planetData, _asteroid);
// Aim.Update(delta);
// }
// else
// {
// _toolSwitch.Activated = false;
// _taskStarted = false;
// }
// }
// }
// }
return base.Update(delta);
}
private void NextPlanet()
{
var surveyTask = _context.Cache.Get<Survey>(Task);
var planets = surveyTask.Planets.Select(id => Zone.Planets[id]);
var nearestPlanet = planets.MinBy(p => lengthsq(_entity.Position - GetPosition(p)));
_asteroid = nearestPlanet is AsteroidBeltData ? Zone.NearestAsteroid(nearestPlanet.ID, _entity.Position) : -1;
var planets = Task.Planets.Select(id => Zone.Planets[id]);
var nearestPlanet = planets.MinBy(p => lengthsq(Entity.Position - GetPosition(p)));
_asteroid = nearestPlanet is AsteroidBeltData ? Zone.NearestAsteroid(nearestPlanet.ID, Entity.Position) : -1;
_targetPlanet = nearestPlanet.ID;
}
@ -121,7 +114,7 @@ public class SurveyController : ControllerBase, IBehavior, IPersistentBehavior,
{
if (planet is AsteroidBeltData)
{
if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, _entity.Position);
if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, Entity.Position);
return Zone.GetAsteroidTransform(planet.ID, asteroid).xy;
}
return Zone.GetOrbitPosition(planet.Orbit);
@ -131,7 +124,7 @@ public class SurveyController : ControllerBase, IBehavior, IPersistentBehavior,
{
if (planet is AsteroidBeltData)
{
if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, _entity.Position);
if(asteroid == -1) asteroid = Zone.NearestAsteroid(planet.ID, Entity.Position);
return Zone.GetAsteroidVelocity(planet.ID, asteroid);
}
return Zone.GetOrbitVelocity(planet.Orbit);
@ -155,5 +148,5 @@ public class SurveyController : ControllerBase, IBehavior, IPersistentBehavior,
public class SurveyControllerPersistence : PersistentBehaviorData
{
[JsonProperty("task"), Key(0)]
public Guid Task;
public Survey Task;
}

View file

@ -6,7 +6,7 @@ using Newtonsoft.Json;
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-25)]
public class SwitchData : BehaviorData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Switch(context, this, entity, item);
}
@ -17,14 +17,14 @@ public class Switch : IBehavior
private SwitchData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public bool Activated { get; set; }
public Switch(GameContext context, SwitchData data, Entity entity, Gear item)
public Switch(ItemManager context, SwitchData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;

View file

@ -12,7 +12,7 @@ public class ThermotoggleData : BehaviorData
[InspectableField, JsonProperty("highPass"), Key(2)]
public bool HighPass;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Thermotoggle(context, this, entity, item);
}
@ -24,12 +24,12 @@ public class Thermotoggle : IBehavior
private ThermotoggleData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
public Thermotoggle(GameContext context, ThermotoggleData data, Entity entity, Gear item)
public Thermotoggle(ItemManager context, ThermotoggleData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -40,6 +40,6 @@ public class Thermotoggle : IBehavior
public bool Update(float delta)
{
return Entity.Temperature < TargetTemperature ^ _data.HighPass;
return Item.Temperature < TargetTemperature ^ _data.HighPass;
}
}

View file

@ -15,7 +15,7 @@ public class ThrusterData : BehaviorData
[InspectableField, JsonProperty("heat"), Key(3)]
public PerformanceStat Heat = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Thruster(context, this, entity, item);
}
@ -24,8 +24,8 @@ public class ThrusterData : BehaviorData
public class Thruster : IAnalogBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public float Thrust { get; private set; }
@ -41,7 +41,7 @@ public class Thruster : IAnalogBehavior
private float _input;
public Thruster(GameContext context, ThrusterData data, Entity entity, Gear item)
public Thruster(ItemManager context, ThrusterData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
@ -51,10 +51,10 @@ public class Thruster : IAnalogBehavior
public bool Update(float delta)
{
Thrust = Context.Evaluate(_data.Thrust, Item, Entity);
Thrust = Context.Evaluate(_data.Thrust, Item.EquippableItem, Entity);
Entity.Velocity += Entity.Direction * _input * Thrust / Entity.Mass * delta;
Entity.AddHeat(_input * Context.Evaluate(_data.Heat, Item, Entity) * delta);
Entity.VisibilitySources[this] = _input * Context.Evaluate(_data.Visibility, Item, Entity);
Item.Temperature += (_input * Context.Evaluate(_data.Heat, Item.EquippableItem, Entity) * delta) / Context.GetThermalMass(Item.EquippableItem);
Entity.VisibilitySources[this] = _input * Context.Evaluate(_data.Visibility, Item.EquippableItem, Entity);
return true;
}
}

View file

@ -10,82 +10,70 @@ using static Unity.Mathematics.math;
[MessagePackObject, JsonObject(MemberSerialization.OptIn), EntityTypeRestriction(HullType.Ship), Order(-100)]
public class TowingControllerData : ControllerData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new TowingController(context, this, entity, item);
}
}
public class TowingController : ControllerBase, IBehavior, IPersistentBehavior
public class TowingController : ControllerBase<StationTowing>, IBehavior, IPersistentBehavior
{
public override TaskType TaskType => TaskType.Tow;
public BehaviorData Data => _data;
private TowingControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private EquippedItem Item { get; }
private bool _taskStarted;
public TowingController(GameContext context, TowingControllerData data, Entity entity, Gear item) : base(context, data, entity)
public TowingController(ItemManager itemManager, TowingControllerData data, Entity entity, EquippedItem item) : base(itemManager, data, entity)
{
_context = context;
_data = data;
_entity = entity;
_item = item;
Item = item;
}
public new bool Update(float delta)
{
var towingTask = _context.Cache.Get<StationTowing>(Task);
if (towingTask != null)
if (Task != null)
{
if (!_taskStarted)
{
MoveTo(towingTask.Zone, OnZoneArrival);
MoveTo(Task.Station, true, OnPickup);
_taskStarted = true;
}
}
return base.Update(delta);
}
void OnZoneArrival()
{
var towingTask = _context.Cache.Get<StationTowing>(Task);
_entity.SetMessage("Entering pickup phase.");
MoveTo(_context.Cache.Get<Entity>(towingTask.Station), true, OnPickup);
}
// void OnZoneArrival()
// {
// var towingTask = _context.ItemData.Get<StationTowing>(Task);
//
// _entity.SetMessage("Entering pickup phase.");
//
// MoveTo(_context.ItemData.Get<Entity>(towingTask.Station), true, OnPickup);
// }
void OnPickup()
{
var towingTask = _context.Cache.Get<StationTowing>(Task);
var target = Zone.Entities[towingTask.Station] as OrbitalEntity;
Task.Station.SetParent(Entity);
target.SetParent(_entity);
_entity.SetMessage("Entering delivery phase.");
Entity.SetMessage("Entering delivery phase.");
MoveTo(() =>
{
var orbitParent = Zone.GetOrbitPosition(towingTask.OrbitParent);
var parentToUs = _entity.Position - orbitParent;
return orbitParent + normalize(parentToUs) * towingTask.OrbitDistance;
}, () => Zone.GetOrbitVelocity(towingTask.OrbitParent), OnDelivery);
var orbitParent = Zone.GetOrbitPosition(Task.OrbitParent);
var parentToUs = Entity.Position - orbitParent;
return orbitParent + normalize(parentToUs) * Task.OrbitDistance;
}, () => Zone.GetOrbitVelocity(Task.OrbitParent), OnDelivery);
}
void OnDelivery()
{
var towingTask = _context.Cache.Get<StationTowing>(Task);
var target = Zone.Entities[towingTask.Station] as OrbitalEntity;
Task.Station.RemoveParent();
target.RemoveParent();
_entity.SetMessage("Target delivered. Returning Home.");
Entity.SetMessage("Target delivered. Returning Home.");
var orbit = Zone.CreateOrbit(towingTask.OrbitParent, _entity.Position);
target.OrbitData = orbit.ID;
var orbit = Zone.CreateOrbit(Task.OrbitParent, Entity.Position);
Task.Station.OrbitData = orbit.ID;
FinishTask();
_taskStarted = false;
@ -109,5 +97,5 @@ public class TowingController : ControllerBase, IBehavior, IPersistentBehavior
public class TowingControllerPersistence : PersistentBehaviorData
{
[JsonProperty("task"), Key(0)]
public Guid Task;
public StationTowing Task;
}

View file

@ -6,7 +6,7 @@ using Newtonsoft.Json;
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-20)]
public class TriggerData : BehaviorData
{
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Trigger(context, this, entity, item);
}
@ -17,8 +17,8 @@ public class Trigger : IBehavior
private TriggerData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
@ -29,7 +29,7 @@ public class Trigger : IBehavior
_pulled = true;
}
public Trigger(GameContext context, TriggerData data, Entity entity, Gear item)
public Trigger(ItemManager context, TriggerData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;

View file

@ -15,7 +15,7 @@ public class TurningData : BehaviorData
[InspectableField, JsonProperty("heat"), Key(3)]
public PerformanceStat Heat = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Turning(context, this, entity, item);
}
@ -24,8 +24,8 @@ public class TurningData : BehaviorData
public class Turning : IAnalogBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public float Torque { get; private set; }
@ -41,7 +41,7 @@ public class Turning : IAnalogBehavior
private float _input;
public Turning(GameContext context, TurningData data, Entity entity, Gear item)
public Turning(ItemManager context, TurningData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
@ -55,10 +55,10 @@ public class Turning : IAnalogBehavior
public bool Update(float delta)
{
Torque = Context.Evaluate(_data.Torque, Item, Entity);
Torque = Context.Evaluate(_data.Torque, Item.EquippableItem, Entity);
Entity.Direction = mul(Entity.Direction, Unity.Mathematics.float2x2.Rotate(_input * Torque / Entity.Mass * delta));
Entity.AddHeat(abs(_input) * Context.Evaluate(_data.Heat, Item, Entity) * delta);
Entity.VisibilitySources[this] = abs(_input) * Context.Evaluate(_data.Visibility, Item, Entity);
Item.Temperature += (abs(_input) * Context.Evaluate(_data.Heat, Item.EquippableItem, Entity) * delta) / Context.GetThermalMass(Item.EquippableItem);
Entity.VisibilitySources[this] = abs(_input) * Context.Evaluate(_data.Visibility, Item.EquippableItem, Entity);
return true;
}

View file

@ -9,7 +9,7 @@ public class VelocityConversionData : BehaviorData
[InspectableField, JsonProperty("traction"), Key(1), RuntimeInspectable]
public PerformanceStat Traction = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new VelocityConversion(context, this, entity, item);
}
@ -18,14 +18,14 @@ public class VelocityConversionData : BehaviorData
public class VelocityConversion : IBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public BehaviorData Data => _data;
private VelocityConversionData _data;
public VelocityConversion(GameContext context, VelocityConversionData data, Entity entity, Gear item)
public VelocityConversion(ItemManager context, VelocityConversionData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;

View file

@ -9,7 +9,7 @@ public class VelocityLimitData : BehaviorData
[InspectableField, JsonProperty("topSpeed"), Key(1), RuntimeInspectable]
public PerformanceStat TopSpeed = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new VelocityLimit(context, this, entity, item);
}
@ -19,8 +19,8 @@ public class VelocityLimitData : BehaviorData
public class VelocityLimit : IBehavior
{
public Entity Entity { get; }
public Gear Item { get; }
public GameContext Context { get; }
public EquippedItem Item { get; }
public ItemManager Context { get; }
public float Limit { get; private set; }
@ -28,7 +28,7 @@ public class VelocityLimit : IBehavior
private VelocityLimitData _data;
public VelocityLimit(GameContext context, VelocityLimitData data, Entity entity, Gear item)
public VelocityLimit(ItemManager context, VelocityLimitData data, Entity entity, EquippedItem item)
{
Context = context;
_data = data;
@ -42,7 +42,7 @@ public class VelocityLimit : IBehavior
public bool Update(float delta)
{
Limit = Context.Evaluate(_data.TopSpeed, Item, Entity);
Limit = Context.Evaluate(_data.TopSpeed, Item.EquippableItem, Entity);
if (length(Entity.Velocity) > Limit)
Entity.Velocity = normalize(Entity.Velocity) * Limit;
return true;

View file

@ -12,7 +12,7 @@ public class VisibilityData : BehaviorData
[InspectableField, JsonProperty("visibilityDecay"), Key(2)]
public PerformanceStat VisibilityDecay = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new Visibility(context, this, entity, item);
}
@ -23,14 +23,14 @@ public class Visibility : IBehavior, IAlwaysUpdatedBehavior
private VisibilityData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
private EquippedItem Item { get; }
private ItemManager Context { get; }
public BehaviorData Data => _data;
private float _cooldown; // Normalized
public Visibility(GameContext context, VisibilityData data, Entity entity, Gear item)
public Visibility(ItemManager context, VisibilityData data, Entity entity, EquippedItem item)
{
_data = data;
Entity = entity;
@ -40,14 +40,14 @@ public class Visibility : IBehavior, IAlwaysUpdatedBehavior
public bool Update(float delta)
{
Entity.VisibilitySources[this] = Context.Evaluate(_data.Visibility, Item, Entity);
Entity.VisibilitySources[this] = Context.Evaluate(_data.Visibility, Item.EquippableItem, Entity);
return true;
}
public void AlwaysUpdate(float delta)
{
// TODO: Time independent decay?
Entity.VisibilitySources[this] *= Context.Evaluate(_data.VisibilityDecay, Item, Entity);
Entity.VisibilitySources[this] *= Context.Evaluate(_data.VisibilityDecay, Item.EquippableItem, Entity);
if (Entity.VisibilitySources[this] < 0.01f) Entity.VisibilitySources.Remove(this);
}

View file

@ -14,32 +14,26 @@ public class WanderControllerData : ControllerData
[InspectableField, JsonProperty("randomDockTime"), Key(6)]
public float RandomDockTime = 5;
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
{
return new WanderController(context, this, entity, item);
}
}
public class WanderController : ControllerBase, IBehavior
public class WanderController : ControllerBase<WanderTask>, IBehavior
{
public WanderTarget WanderTarget;
public override TaskType TaskType => TaskType.None;
public BehaviorData Data => _data;
private WanderControllerData _data;
private GameContext _context;
private Entity _entity;
private Gear _item;
private EquippedItem Item { get; }
private Guid _target;
private float _dockTime = -1;
public WanderController(GameContext context, WanderControllerData data, Entity entity, Gear item) : base(context, data, entity)
public WanderController(ItemManager itemManager, WanderControllerData data, Entity entity, EquippedItem item) : base(itemManager, data, entity)
{
_context = context;
_data = data;
_entity = entity;
_item = item;
Task = Guid.NewGuid();
Item = item;
}
public new bool Update(float delta)
@ -58,17 +52,17 @@ public class WanderController : ControllerBase, IBehavior
if (WanderTarget == WanderTarget.Planets)
{
var planets = Zone.Planets.Values.ToArray();
var randomPlanet = planets[_context.Random.NextInt(planets.Length)];
var randomPlanet = planets[ItemManager.Random.NextInt(planets.Length)];
MoveTo(() => Zone.GetOrbitPosition(randomPlanet.Orbit), () => Zone.GetOrbitVelocity(randomPlanet.Orbit));
}
else if (WanderTarget == WanderTarget.Orbitals)
{
var entities = Zone.Entities.Values.ToArray();
var randomEntity = entities[_context.Random.NextInt(entities.Length)];
var entities = Zone.Entities.Where(e=>e is OrbitalEntity).ToArray();
var randomEntity = entities[ItemManager.Random.NextInt(entities.Length)];
MoveTo(randomEntity, true, () =>
{
_entity.SetParent(randomEntity);
_dockTime = _context.Random.NextFloat(_data.RandomDockTime);
Entity.SetParent(randomEntity);
_dockTime = ItemManager.Random.NextFloat(_data.RandomDockTime);
});
}
}

View file

@ -20,10 +20,10 @@ public interface INamedEntry
Union(3, typeof(HullData)),
Union(4, typeof(SimpleCommodity)),
Union(5, typeof(CompoundCommodity)),
Union(6, typeof(Gear)),
Union(6, typeof(EquippableItem)),
Union(7, typeof(BlueprintData)),
Union(8, typeof(GalaxyMapLayerData)),
Union(9, typeof(GlobalData)),
// Union(9, typeof(GlobalData)),
Union(10, typeof(ZoneData)),
Union(11, typeof(PlayerData)),
Union(12, typeof(Corporation)),
@ -50,5 +50,4 @@ public abstract class DatabaseEntry
{
[JsonProperty("id"), Key(0)]
public Guid ID = Guid.NewGuid();
[IgnoreMember] public GameContext Context { get; set; }
}

View file

@ -2,9 +2,9 @@
"name": "Economy.Shared.Unity",
"references": [
"MessagePack",
"MagicOnion.Abstractions",
"Unity.Mathematics",
"UniRx"
"UniRx",
"com.alelievr.NodeGraphProcessor.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@ public enum LauncherCaliber
public enum HardpointType
{
Hull,
Thermal,
Thruster,
WarpThruster,
Reactor,

View file

@ -29,12 +29,12 @@ public static class Extensions
peer.Send(MessagePackSerializer.Serialize(message as Message), method);
}
public static float Performance(this EquippableItemData itemData, float temperature)
{
return saturate(itemData.HeatPerformanceCurve.Evaluate(saturate(
(temperature - itemData.MinimumTemperature) /
(itemData.MaximumTemperature - itemData.MinimumTemperature))));
}
// public static float Performance(this EquippableItemData itemData, float temperature)
// {
// return saturate(itemData.HeatPerformanceCurve.Evaluate(saturate(
// (temperature - itemData.MinimumTemperature) /
// (itemData.MaximumTemperature - itemData.MinimumTemperature))));
// }
public static string SplitCamelCase( this string str )
{

View file

@ -8,162 +8,6 @@ using static Unity.Mathematics.math;
using static Unity.Mathematics.noise;
using static NoiseFbm;
[Inspectable, Serializable, RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GlobalData : DatabaseEntry
{
[InspectableField, JsonProperty("galaxyName"), Key(1)]
public string GalaxyName;
[InspectableDatabaseLink(typeof(ZoneData)), JsonProperty("arrivalZone"), Key(2)]
public Guid ArrivalZone;
[InspectableField, JsonProperty("galaxyArms"), Key(4)]
public int Arms = 4;
[InspectableField, JsonProperty("galaxyTwist"), Key(5)]
public float Twist = 10;
[InspectableField, JsonProperty("galaxyTwistPower"), Key(6)]
public float TwistPower = 2;
[InspectableField, JsonProperty("radiusPower"), Key(7)]
public float RadiusPower = 1.75f;
[InspectableField, JsonProperty("massFloor"), Key(8)]
public float MassFloor = 1;
[InspectableField, JsonProperty("sunMass"), Key(9)]
public float SunMass = 10000;
[InspectableField, JsonProperty("gasGiantMass"), Key(10)]
public float GasGiantMass = 2000;
[InspectableField, JsonProperty("planetMass"), Key(11)]
public float PlanetMass = 100f;
[InspectableField, JsonProperty("satelliteCreationMassFloor"), Key(12)]
public float SatelliteCreationMassFloor = 100;
[InspectableField, JsonProperty("satelliteCreationProbability"), Key(13)]
public float SatelliteCreationProbability = .25f;
[InspectableField, JsonProperty("binaryCreationProbability"), Key(14)]
public float BinaryCreationProbability = .25f;
[InspectableField, JsonProperty("rosetteProbability"), Key(15)]
public float RosetteProbability = .25f;
// [InspectableField] [JsonProperty("mapLayers")] [Key(16)]
// public Dictionary<string, Guid> MapLayers = new Dictionary<string, Guid>();
[InspectableField, JsonProperty("zoneRadiusMin"), Key(16)]
public float MinimumZoneRadius = 500;
[InspectableField, JsonProperty("zoneRadiusMax"), Key(17)]
public float MaximumZoneRadius = 2000;
[InspectableField, JsonProperty("zoneRadiusExp"), Key(18)]
public float ZoneRadiusExponent = -.75f;
[InspectableField, JsonProperty("zoneMassMin"), Key(19)]
public float MinimumZoneMass = 10000;
[InspectableField, JsonProperty("zoneMassMax"), Key(20)]
public float MaximumZoneMass = 100000;
[InspectableField, JsonProperty("zoneMassExp"), Key(21)]
public float ZoneMassExponent = -.75f;
[InspectableField, JsonProperty("orbitPeriodExponent"), Key(22)]
public float OrbitPeriodExponent = 1.5f;
[InspectableField, JsonProperty("orbitPeriodMultiplier"), Key(23)]
public float OrbitPeriodMultiplier = 1f;
[InspectableField, JsonProperty("beltProbability"), Key(26)]
public float BeltProbability = .05f;
[InspectableField, JsonProperty("beltMassCeiling"), Key(27)]
public float BeltMassCeiling = 500f;
[InspectableField, JsonProperty("beltMassRatio"), Key(28)]
public float BeltMassRatio = 100f;
[InspectableField, JsonProperty("beltMassExponent"), Key(29)]
public float BeltMassExponent = 100f;
[InspectableField, JsonProperty("asteroidSizeMin"), Key(30)]
public float AsteroidSizeMin = 2f;
[InspectableField, JsonProperty("asteroidSizeMax"), Key(31)]
public float AsteroidSizeMax = 10f;
[InspectableField, JsonProperty("asteroidSizeExponent"), Key(32)]
public float AsteroidSizeExponent = 2f;
[InspectableField, JsonProperty("asteroidRotationSpeed"), Key(33)]
public float AsteroidRotationSpeed = 2f;
[InspectableField, JsonProperty("dockingDistance"), Key(34)]
public float DockingDistance = 25;
[InspectableField, JsonProperty("warpDistance"), Key(35)]
public float WarpDistance = 25;
[InspectableField, JsonProperty("targetPersistenceDuration"), Key(37)]
public float TargetPersistenceDuration = 3;
[InspectableField, JsonProperty("heatRadiationPower"), Key(38)]
public float HeatRadiationPower = 1;
[InspectableField, JsonProperty("heatRadiationMultiplier"), Key(39)]
public float HeatRadiationMultiplier = 1;
[InspectableField, JsonProperty("resourceDensityMinimum"), Key(40)]
public float ResourceDensityMinimum = .1f;
[InspectableField, JsonProperty("resourceDensityMaximum"), Key(41)]
public float ResourceDensityMaximum = 1.5f;
[InspectableField, JsonProperty("startingGearQualityMin"), Key(42)]
public float StartingGearQualityMin = .1f;
[InspectableField, JsonProperty("startingGearQualityMax"), Key(43)]
public float StartingGearQualityMax = .5f;
[InspectableField, JsonProperty("asteroidHitpointsMin"), Key(44)]
public float AsteroidHitpointsMin = 10f;
[InspectableField, JsonProperty("asteroidHitpointsMax"), Key(45)]
public float AsteroidHitpointsMax = 200f;
[InspectableField, JsonProperty("asteroidHitpointsPower"), Key(46)]
public float AsteroidHitpointsPower = 2f;
[InspectableField, JsonProperty("asteroidRespawnMin"), Key(47)]
public float AsteroidRespawnMin = 10f;
[InspectableField, JsonProperty("asteroidRespawnMax"), Key(48)]
public float AsteroidRespawnMax = 100f;
[InspectableField, JsonProperty("miningDifficulty"), Key(49)]
public float MiningDifficulty = 500f;
[InspectableField, JsonProperty("messageDuration"), Key(50)]
public float MessageDuration = 4f;
[InspectableField, JsonProperty("significantDigits"), Key(51)]
public int SignificantDigits = 3;
[InspectableField, JsonProperty("productionPersonalityLerp"), Key(52)]
public float ProductionPersonalityLerp = .05f;
public float PlanetRadius(float mass)
{
return pow(mass, 1 / RadiusPower);
}
}
[Inspectable, Serializable, RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GalaxyMapLayerData : DatabaseEntry, INamedEntry
{

View file

@ -1,9 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
public interface IChangeSource
{
event Action OnChanged;
}

View file

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9188eb1236c6f6f42b4c2d04b3111867
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,10 +1,93 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using int2 = Unity.Mathematics.int2;
public class Shape
{
[JsonProperty("name"), Key(0)] public bool[,] Cells;
private bool _dirty = true;
public Shape(int width, int height)
{
Cells = new bool[width, height];
}
public int Width => Cells.GetLength(0);
public int Height => Cells.GetLength(1);
private static int mod(int x, int m) {
int r = x%m;
return r<0 ? r+m : r;
}
public int2 Rotate(int2 position, int rotation)
{
switch (mod(rotation, 4))
{
case 1:
return int2(position.y, Width - 1 - position.x);
case 2:
return int2(Width - 1 - position.x, Height - 1 - position.y);
case 3:
return int2(Height - 1 - position.y, position.x);
default:
return int2(position.x, position.y);
}
}
private int2[] _cachedShapeCoordinates;
[IgnoreMember]
public int2[] Coordinates
{
get
{
if (_dirty) _cachedShapeCoordinates = EnumerateShapeCoordinates().ToArray();
return _cachedShapeCoordinates;
}
}
private IEnumerable<int2> EnumerateShapeCoordinates()
{
for(int x = 0; x < Cells.GetLength(0); x++)
{
for (int y = 0; y < Cells.GetLength(0); y++)
{
if(Cells[x,y]) yield return int2(x, y);
}
}
}
public bool this[int2 pos] {
get { return pos.x >= 0 && pos.y >= 0 && pos.x < Cells.GetLength(0) && pos.y < Cells.GetLength(1) && Cells[pos.x, pos.y]; }
set
{
_dirty = true;
Cells[pos.x, pos.y] = value;
}
}
public Shape Shrink()
{
var shape = new Shape(Width, Height);
foreach(var shapeCoord in Coordinates)
shape[shapeCoord] = (
this[shapeCoord + int2(-1,-1)] && this[shapeCoord + int2(0,-1)] && this[shapeCoord + int2(1,-1)] &&
this[shapeCoord + int2(-1,0)] && this[shapeCoord + int2(1,0)] &&
this[shapeCoord + int2(-1,1)] && this[shapeCoord + int2(0,1)] && this[shapeCoord + int2(1,1)]
);
return shape;
}
}
[MessagePackObject,
Union(0, typeof(SimpleCommodityData)),
@ -23,8 +106,8 @@ public abstract class ItemData : DatabaseEntry, INamedEntry
[InspectableField, JsonProperty("mass"), Key(3)]
public float Mass;
[InspectableField, JsonProperty("size"), Key(4)]
public float Size;
[InspectableField, JsonProperty("shape"), Key(4)]
public Shape Shape;
// Heat needed to change temperature of 1 gram by 1 degree
[InspectableField, JsonProperty("specificHeat"), Key(5)]
@ -35,36 +118,32 @@ public abstract class ItemData : DatabaseEntry, INamedEntry
get => Name;
set => Name = value;
}
}
[RethinkTable("Items"), Inspectable, MessagePackObject]
public class SimpleCommodityData : ItemData
{
// Types of body where this resource can be found
[InspectableField, JsonProperty("resourceBodyType"), Key(6)]
public BodyType ResourceBodyType;
// // Types of body where this resource can be found
// [InspectableField, JsonProperty("resourceBodyType"), Key(6)]
// public BodyType ResourceBodyType;
//
// // Link to map(s) controlling density of resource, multiplied together when more than one
// [InspectableDatabaseLink(typeof(GalaxyMapLayerData)), JsonProperty("resourceDensity"), Key(7)]
// public List<Guid> ResourceDensity = new List<Guid>();
//
// // Controls the lowest value in the resource distribution curve
// [InspectableField, JsonProperty("distribution"), Key(8)]
// public ExponentialLerp Distribution;
//
// // Minimum amount of resources needed for presence to register
// [InspectableField, JsonProperty("floor"), Key(11)]
// public float Floor = 5f;
// Link to map(s) controlling density of resource, multiplied together when more than one
[InspectableDatabaseLink(typeof(GalaxyMapLayerData)), JsonProperty("resourceDensity"), Key(7)]
public List<Guid> ResourceDensity = new List<Guid>();
[InspectableField, JsonProperty("maxStackSize"), Key(6)]
public int MaxStack;
// Controls the lowest value in the resource distribution curve
[InspectableField, JsonProperty("minimum"), Key(8)]
public float Minimum = 1;
// Controls the highest value in the resource distribution curve
[InspectableField, JsonProperty("maximum"), Key(9)]
public float Maximum = 100;
// Controls the shape of the resource distribution curve
[InspectableField, JsonProperty("exponent"), Key(10)]
public float Exponent = -.75f;
// Minimum amount of resources needed for presence to register
[InspectableField, JsonProperty("floor"), Key(11)]
public float Floor = 5f;
[InspectableField, JsonProperty("category"), Key(12)]
[InspectableField, JsonProperty("category"), Key(7)]
public SimpleCommodityCategory Category;
}
@ -83,10 +162,10 @@ public abstract class CraftedItemData : ItemData
[RethinkTable("Items"), Inspectable, MessagePackObject]
public class CompoundCommodityData : CraftedItemData
{
[InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("demandProfile"), Key(7)]
[InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("demandProfile"), Key(7)]
public Dictionary<Guid, float> DemandProfile = new Dictionary<Guid, float>();
[InspectableField, JsonProperty("category"), Key(8)]
[InspectableField, JsonProperty("category"), Key(8)]
public CompoundCommodityCategory Category;
}
@ -95,26 +174,20 @@ public class CompoundCommodityData : CraftedItemData
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<EquippableItemData>))]
public abstract class EquippableItemData : CraftedItemData
{
[InspectableAnimationCurve, JsonProperty("performanceCurve"), Key(7)]
public float4[] HeatPerformanceCurve;
[InspectableField, JsonProperty("behaviors"), Key(7)]
public List<BehaviorData> Behaviors = new List<BehaviorData>();
[TemperatureInspectable, JsonProperty("minTemp"), Key(8)]
[InspectableField, JsonProperty("durability"), Key(8)]
public float Durability;
[TemperatureInspectable, JsonProperty("minTemp"), Key(9)]
public float MinimumTemperature;
[TemperatureInspectable, JsonProperty("maxTemp"), Key(9)]
[TemperatureInspectable, JsonProperty("maxTemp"), Key(10)]
public float MaximumTemperature;
[InspectableField, JsonProperty("durabilityStat"), Key(10), SimplePerformanceStat]
public PerformanceStat Durability = new PerformanceStat();
[InspectableField, JsonProperty("durabilityExponent"), Key(11), SimplePerformanceStat]
public PerformanceStat DurabilityExponent = new PerformanceStat();
[InspectableField, JsonProperty("heatExponent"), Key(12), SimplePerformanceStat]
public PerformanceStat HeatExponent = new PerformanceStat();
[InspectableField, JsonProperty("behaviors"), Key(13)]
public List<BehaviorData> Behaviors = new List<BehaviorData>();
[IgnoreMember]
public abstract HardpointType HardpointType { get; }
@ -122,63 +195,63 @@ public abstract class EquippableItemData : CraftedItemData
[IgnoreMember] private const int STEPS = 64;
[IgnoreMember] private float? _optimum;
[IgnoreMember]
public float OptimalTemperature
{
get
{
if (_optimum==null)
{
var samples = Enumerable.Range(0, STEPS).Select(i => (float) i / STEPS).ToArray();
float max = 0;
_optimum = 0;
foreach (var f in samples)
{
var p = HeatPerformanceCurve?.Evaluate(f)??0;
if (p > max)
{
max = p;
_optimum = f;
}
}
}
return (float) (MinimumTemperature + _optimum * (MaximumTemperature - MinimumTemperature));
}
}
}
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GearData : EquippableItemData
{
[InspectableField, JsonProperty("hardpointType"), Key(14)]
[InspectableField, JsonProperty("hardpointType"), Key(12)]
public HardpointType Hardpoint;
[IgnoreMember] public override HardpointType HardpointType => Hardpoint;
}
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class CargoBayData : EquippableItemData
{
[InspectableField, JsonProperty("interiorShape"), Key(12)]
public Shape InteriorShape;
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Tool;
}
[RethinkTable("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class HullData : EquippableItemData
{
[InspectableField, JsonProperty("hullCapacity"), Key(14)]
public PerformanceStat Capacity = new PerformanceStat();
[InspectableField, JsonProperty("hardpoints"), Key(15)]
[InspectableField, JsonProperty("hardpoints"), Key(12)]
public List<HardpointData> Hardpoints = new List<HardpointData>();
[InspectablePrefab, JsonProperty("prefab"), Key(16)]
[InspectablePrefab, JsonProperty("prefab"), Key(13)]
public string Prefab;
[InspectableField, JsonProperty("hullType"), Key(17)]
[InspectableField, JsonProperty("hullType"), Key(14)]
public HullType HullType;
[IgnoreMember]
public Shape InteriorCells
{
get
{
if (_interiorCells == null)
{
_interiorCells = Shape.Shrink();
}
return _interiorCells;
}
}
private Shape _interiorCells;
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Hull;
}
[RethinkTable("Items"), InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class HardpointData
{
[InspectableField, JsonProperty("type"), Key(0)] public HardpointType Type;
[InspectableField, JsonProperty("type"), Key(0)] public HardpointType Type;
[InspectableField, JsonProperty("position"), Key(1)] public int2 Position;
[InspectableField, JsonProperty("shape"), Key(2)] public Shape Shape;
[InspectableField, JsonProperty("transform"), Key(3)] public string Transform;
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
@ -191,10 +264,10 @@ public class PerformanceStat
[JsonProperty("durabilityDependent"), Key(2)]
public bool DurabilityDependent;
[JsonProperty("heatDependent"), Key(3)]
public bool HeatDependent;
// [JsonProperty("heatDependent"), Key(3)]
// public bool HeatDependent;
[JsonProperty("qualityExponent"), Key(4)]
[JsonProperty("qualityExponent"), Key(3)]
public float QualityExponent;
//[JsonProperty("id"), Key(5)] public Guid ID = Guid.NewGuid();
@ -206,11 +279,11 @@ public class PerformanceStat
[IgnoreMember]
private Dictionary<Entity, Dictionary<IBehavior, float>> ScaleModifiers =>
_scaleModifiers ?? (_scaleModifiers = new Dictionary<Entity, Dictionary<IBehavior, float>>());
_scaleModifiers = _scaleModifiers ?? new Dictionary<Entity, Dictionary<IBehavior, float>>();
[IgnoreMember]
private Dictionary<Entity, Dictionary<IBehavior, float>> ConstantModifiers =>
_constantModifiers ?? (_constantModifiers = new Dictionary<Entity, Dictionary<IBehavior, float>>());
_constantModifiers = _constantModifiers ?? new Dictionary<Entity, Dictionary<IBehavior, float>>();
public Dictionary<IBehavior, float> GetScaleModifiers(Entity entity)
{

View file

@ -9,32 +9,28 @@ using MessagePack;
using MessagePack.Formatters;
using Newtonsoft.Json;
using Unity.Mathematics;
// TODO: USE THIS EVERYWHERE
using static Unity.Mathematics.math;
[Union(0, typeof(SimpleCommodity)),
Union(1, typeof(CompoundCommodity)),
Union(2, typeof(Gear)),
Union(2, typeof(EquippableItem)),
JsonObject(MemberSerialization.OptIn),
JsonConverter(typeof(JsonKnownTypesConverter<ItemInstance>))]
public abstract class ItemInstance : DatabaseEntry
public abstract class ItemInstance
{
[JsonProperty("data"), Key(1)] public Guid Data;
public float Mass => Context.GetMass(this);
public float ThermalMass => Context.GetThermalMass(this);
public float Size => Context.GetSize(this);
[JsonProperty("data"), Key(0)] public Guid Data;
[JsonProperty("rotation"), Key(1)] public int Rotation;
}
[Union(0, typeof(CompoundCommodity)),
Union(1, typeof(Gear)),
Union(1, typeof(EquippableItem)),
JsonObject(MemberSerialization.OptIn),
JsonConverter(typeof(JsonKnownTypesConverter<CraftedItemInstance>))]
public abstract class CraftedItemInstance : ItemInstance
{
[JsonProperty("quality"), Key(2)] public float Quality;
[JsonProperty("ingredients"), Key(3)] public List<Guid> Ingredients = new List<Guid>();
[JsonProperty("ingredients"), Key(3)] public List<ItemInstance> Ingredients = new List<ItemInstance>();
[JsonProperty("blueprint"), Key(4)] public Guid Blueprint;
@ -44,27 +40,16 @@ public abstract class CraftedItemInstance : ItemInstance
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class CompoundCommodity : CraftedItemInstance {}
public class CompoundCommodity : CraftedItemInstance { }
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class SimpleCommodity : ItemInstance
{
[JsonProperty("quantity"), Key(2)] public int Quantity;
public SimpleCommodityData ItemData => Context.GetData(this);
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class Gear : CraftedItemInstance, IChangeSource
public class EquippableItem : CraftedItemInstance
{
[JsonProperty("durability"), Key(7)] public float Durability;
public EquippableItemData ItemData => Context.GetData(this);
public event Action OnChanged;
public void Change()
{
OnChanged?.Invoke();
}
}

View file

@ -10,13 +10,13 @@ using JM.LinqFaster;
using UniRx;
using float4 = Unity.Mathematics.float4;
public class GameContext
public class ItemManager
{
public Random Random = new Random((uint) (DateTime.Now.Ticks%uint.MaxValue));
public Dictionary<string, GalaxyMapLayerData> MapLayers = new Dictionary<string, GalaxyMapLayerData>();
public SimpleCommodityData[] Resources;
public Dictionary<Guid, List<IController>> CorporationControllers = new Dictionary<Guid, List<IController>>();
public Dictionary<Guid, ZoneDefinition> GalaxyZones;
// public Dictionary<string, GalaxyMapLayerData> MapLayers = new Dictionary<string, GalaxyMapLayerData>();
// public SimpleCommodityData[] Resources;
// public Dictionary<Guid, List<IController>> CorporationControllers = new Dictionary<Guid, List<IController>>();
// public Dictionary<Guid, ZoneDefinition> GalaxyZones;
private Action<string> _logger;
@ -25,25 +25,12 @@ public class GameContext
private double _time;
private float _deltaTime;
private GlobalData _globalData;
private Dictionary<Guid, Zone> _zones = new Dictionary<Guid, Zone>();
// private Guid _forceLoadZone;
public GlobalData GlobalData => _globalData ?? (_globalData = Cache.GetAll<GlobalData>().FirstOrDefault());
public DatabaseCache Cache { get; }
// public Guid ForceLoadZone
// {
// get => _forceLoadZone;
// set
// {
// if(_forceLoadZone != Guid.Empty && ZoneEntities[_forceLoadZone].Count == 0)
// UnloadZone(_forceLoadZone);
// _forceLoadZone = value;
// if(!_loadedZones.Contains(_forceLoadZone))
// LoadZone(_forceLoadZone);
// }
// }
// public GlobalData GlobalData => _globalData ?? (_globalData = ItemData.GetAll<GlobalData>().FirstOrDefault());
public DatabaseCache ItemData { get; }
public GameplaySettings GameplaySettings { get; }
public double Time
{
@ -58,18 +45,10 @@ public class GameContext
// private readonly Dictionary<CraftedItemData, int> Tier = new Dictionary<CraftedItemData, int>();
public GameContext(DatabaseCache cache, Action<string> logger)
public ItemManager(DatabaseCache itemData, GameplaySettings settings, Action<string> logger)
{
Cache = cache;
MapLayers = cache.GetAll<GalaxyMapLayerData>().ToDictionary(ml => ml.Name);
Resources = cache.GetAll<SimpleCommodityData>().Where(i => i.ResourceDensity.Any()).ToArray();
ItemData = itemData;
_logger = logger;
// var globalData = Cache.GetAll<GlobalData>().FirstOrDefault();
// if (globalData == null)
// {
// globalData = new GlobalData();
// Cache.Add(globalData);
// }
}
public void Log(string s)
@ -116,137 +95,6 @@ public class GameContext
//
// }
// public Zone GetZone(Guid zone)
// {
// if (_zones.ContainsKey(zone)) return _zones[zone];
//
// // var zoneData = Cache.Get<ZoneData>(zone);
// // if (zoneData == null) throw new ArgumentException("Zone parameter is not a valid zone ID!", nameof(zone));
// //
// // return GetZone(zoneData);
// return null;
// }
//
// public Zone GetZone(ZonePack zonePack)
// {
// var z = new Zone(this, zonePack);
// _zones.Add(zonePack.Data.ID, z);
// return z;
// }
//
// public void UnloadZone(Guid zone)
// {
// _zones.Remove(zone);
// }
// public void Warp(Entity entity, Guid targetZone)
// {
// if (length(entity.Position - WormholePosition(entity.Zone, targetZone)) < GlobalData.WarpDistance)
// {
// var sourceZone = entity.Zone;
//
// // Remove entity from source zone
// ZoneEntities[sourceZone].Remove(entity.ID);
//
// // Unload source zone if empty and unobserved
// if(ForceLoadZone != sourceZone && ZoneEntities[sourceZone].Count == 0)
// UnloadZone(sourceZone);
//
// // Load target zone if not yet loaded
// if(!_loadedZones.Contains(targetZone))
// LoadZone(targetZone);
//
// entity.Zone = targetZone;
// entity.Position = WormholePosition(targetZone, sourceZone);
// ZoneEntities[targetZone][entity.ID] = entity;
// }
// }
public void PlaceMegas()
{
var megas = Cache.GetAll<MegaCorporation>();
var availableZones = Cache.GetAll<ZoneData>()
.Where(z => megas.All(m => m.HomeZone != z.ID))
.ToList();
foreach(var megaPlacement in megas
.OrderBy(m=>m.PlacementType)
.GroupBy(m=>m.PlacementType))
switch (megaPlacement.Key)
{
case MegaPlacementType.Mass:
foreach (var mega in megaPlacement)
{
var zone = availableZones
.MaxBy(z => z.Mass);
availableZones.Remove(zone);
mega.HomeZone = zone.ID;
}
break;
// case MegaPlacementType.Planets:
// foreach (var mega in megaPlacement)
// {
// var zone = availableZones
// .MaxBy(z => z.Planets.Length);
// availableZones.Remove(zone);
// mega.HomeZone = zone.ID;
// }
// break;
// case MegaPlacementType.Resources:
// foreach (var mega in megaPlacement)
// {
// var zone = availableZones
// .MaxBy(z => z.Planets
// .SelectMany(id=>Cache.Get<PlanetData>(id).Resources
// .Select(r=>r.Key))
// .Distinct()
// .Count());
// availableZones.Remove(zone);
// mega.HomeZone = zone.ID;
// }
// break;
case MegaPlacementType.Connected:
foreach (var mega in megaPlacement)
{
var zone = availableZones
.OrderByDescending(z => z.Wormholes.Count)
.ThenBy(z=>megas
.Sum(m=>m.HomeZone==Guid.Empty?0:lengthsq(Cache.Get<ZoneData>(m.HomeZone).Position - z.Position)))
.First();
availableZones.Remove(zone);
mega.HomeZone = zone.ID;
}
break;
case MegaPlacementType.Isolated:
foreach (var mega in megaPlacement)
{
var zone = availableZones
.Where(z=>z.Wormholes.Count==1)
.MaxBy(z =>
{
int soloChain = 0;
var previous = z;
var next = Cache.Get<ZoneData>(z.Wormholes.First());
while (next.Wormholes.Count == 2)
{
var temp = next;
next = Cache.Get<ZoneData>(next.Wormholes.First(w=>w != previous.ID));
previous = temp;
soloChain++;
}
return soloChain;
});
availableZones.Remove(zone);
mega.HomeZone = zone.ID;
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
// public int ItemTier(CraftedItemData itemData)
// {
// if (Tier.ContainsKey(itemData)) return Tier[itemData];
@ -258,22 +106,22 @@ public class GameContext
public ItemData GetData(ItemInstance item)
{
return Cache.Get<ItemData>(item.Data);
return ItemData.Get<ItemData>(item.Data);
}
public SimpleCommodityData GetData(SimpleCommodity item)
{
return Cache.Get<SimpleCommodityData>(item.Data);
return ItemData.Get<SimpleCommodityData>(item.Data);
}
public CraftedItemData GetData(CraftedItemInstance item)
{
return Cache.Get<CraftedItemData>(item.Data);
return ItemData.Get<CraftedItemData>(item.Data);
}
public EquippableItemData GetData(Gear gear)
public EquippableItemData GetData(EquippableItem equippableItem)
{
return Cache.Get<EquippableItemData>(gear.Data);
return ItemData.Get<EquippableItemData>(equippableItem.Data);
}
public float GetMass(ItemInstance item)
@ -290,20 +138,6 @@ public class GameContext
return 0;
}
public float GetSize(ItemInstance item)
{
var data = GetData(item);
switch (item)
{
case CraftedItemInstance _:
return data.Size;
case SimpleCommodity commodity:
return data.Size * commodity.Quantity;
}
return 0;
}
public float GetThermalMass(ItemInstance item)
{
var data = GetData(item);
@ -324,7 +158,7 @@ public class GameContext
if (AffectedStats.ContainsKey(effect)) return AffectedStats[effect];
// Get the data for the item the blueprint is for, return null if not found or not equippable
var blueprintItem = Cache.Get<EquippableItemData>(blueprint.Item);
var blueprintItem = ItemData.Get<EquippableItemData>(blueprint.Item);
if (blueprintItem == null)
{
_logger($"Attempted to get stat effect but Blueprint {blueprint.ID} is not for an equippable item!");
@ -364,7 +198,7 @@ public class GameContext
var craftedIngredients = item.Ingredients.Where(i => i is CraftedItemInstance).ToArray();
if (craftedIngredients.Length > 0)
{
var ingredientQualityWeight = Cache.Get<CraftedItemData>(item.Data).IngredientQualityWeight;
var ingredientQualityWeight = ItemData.Get<CraftedItemData>(item.Data).IngredientQualityWeight;
quality = quality * (1 - ingredientQualityWeight) +
craftedIngredients.Cast<CraftedItemInstance>().Average(CompoundQuality) * ingredientQualityWeight;
}
@ -375,21 +209,21 @@ public class GameContext
}
// Determine quality of either the item itself or the specific ingredient this stat depends on
public float Quality(PerformanceStat stat, Gear item)
public float Quality(PerformanceStat stat, EquippableItem item)
{
var blueprint = Cache.Get<BlueprintData>(item.Blueprint);
var itemData = GetData(item);
var blueprint = ItemData.Get<BlueprintData>(item.Blueprint);
var activeEffects = blueprint.StatEffects.Where(x => GetAffectedStat(blueprint, x) == stat).ToArray();
float quality;
if (!activeEffects.Any())
quality = CompoundQuality(item);
else
{
var ingredientInstances = item.Ingredients.Select(i => Cache.Get<ItemInstance>(i)).ToArray();
var ingredients = ingredientInstances.Where(i => activeEffects.Any(e => e.Ingredient == i.Data)).ToArray();
var ingredients = item.Ingredients.Where(i => activeEffects.Any(e => e.Ingredient == i.Data)).ToArray();
var distinctIngredients = ingredients.Select(i => i.Data).Distinct();
if(distinctIngredients.Count() != activeEffects.Length)
{
_logger($"Item {item.ID} does not have the ingredients specified by the stat effects of its blueprint!");
_logger($"Item {itemData.Name} does not have the ingredients specified by the stat effects of its blueprint!");
return 0;
}
@ -398,7 +232,7 @@ public class GameContext
{
if (i is CraftedItemInstance ci)
sum += CompoundQuality(ci);
else _logger($"Blueprint stat effect for item {item.ID} specifies invalid (non crafted) ingredient!");
else _logger($"Blueprint stat effect for item {itemData.Name} specifies invalid (non crafted) ingredient!");
}
quality = sum / ingredients.Length;
@ -408,7 +242,7 @@ public class GameContext
}
// Returns stat when not equipped
public float Evaluate(PerformanceStat stat, Gear item)
public float Evaluate(PerformanceStat stat, EquippableItem item)
{
var quality = pow(Quality(stat, item), stat.QualityExponent);
@ -421,174 +255,173 @@ public class GameContext
}
// Returns stat using ship temperature and modifiers
public float Evaluate(PerformanceStat stat, Gear item, Entity entity)
public float Evaluate(PerformanceStat stat, EquippableItem item, Entity entity)
{
var itemData = GetData(item);
var heat = !stat.HeatDependent ? 1 : pow(itemData.Performance(entity.Temperature), Evaluate(itemData.HeatExponent,item));
var durability = !stat.DurabilityDependent ? 1 : pow(item.Durability / Evaluate(itemData.Durability, item), Evaluate(itemData.DurabilityExponent,item));
//var heat = !stat.HeatDependent ? 1 : pow(itemData.Performance(entity.Temperature), Evaluate(itemData.HeatExponent,item));
var durability = !stat.DurabilityDependent ? 1 : pow(item.Durability / itemData.Durability, Evaluate(itemData.DurabilityExponent,item));
var quality = pow(Quality(stat, item), stat.QualityExponent);
var scaleModifier = stat.GetScaleModifiers(entity).Values.Aggregate(1.0f, (current, mod) => current * mod);
var constantModifier = stat.GetConstantModifiers(entity).Values.Sum();
var result = lerp(stat.Min, stat.Max, heat * durability * quality) * scaleModifier + constantModifier;
var result = lerp(stat.Min, stat.Max, durability * quality) * scaleModifier + constantModifier;
if (float.IsNaN(result))
return stat.Min;
return result;
}
public Entity CreateEntity(Guid zoneID, Guid corporation, Guid loadout)
{
if (!(Cache.Get(loadout) is LoadoutData loadoutData))
{
_logger("Attempted to spawn invalid loadout ID");
return null;
}
if (!(Cache.Get(loadoutData.Hull) is HullData hullData))
{
_logger("Attempted to spawn loadout with invalid hull ID");
return null;
}
if (!(Cache.Get(zoneID) is ZoneData zoneData))
{
_logger("Attempted to spawn entity with invalid zone ID");
return null;
}
if (!(Cache.Get(corporation) is Corporation corpData))
{
_logger("Attempted to spawn entity with invalid corporation ID");
return null;
}
var gearData = loadoutData.Gear
.Take(hullData.Hardpoints.Count)
.Where(id => id != Guid.Empty)
.Select(id => Cache.Get<GearData>(id))
.ToArray();
if (gearData.Any(g=>g==null))
{
_logger("Attempted to spawn loadout with invalid gear ID");
return null;
}
var gear = gearData
.Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
.ToArray();
if (gear.Any(g=>g==null))
return null;
foreach(var g in gear)
Cache.Add(g);
var cargoData = loadoutData.CompoundCargo
.SelectMany(x => Enumerable.Repeat(Cache.Get<CraftedItemData>(x.Key), x.Value))
.ToArray();
if (cargoData.Any(g=>g==null))
{
_logger("Attempted to spawn loadout with invalid cargo ID");
return null;
}
var cargo = cargoData
.Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
.ToArray();
if (cargo.Any(g=>g==null))
return null;
foreach(var c in cargo)
Cache.Add(c);
var simpleCargo = loadoutData.SimpleCargo?
.Select(x => CreateInstance(x.Key, x.Value))
.ToArray() ?? new SimpleCommodity[0];
if (simpleCargo.Any(g=>g==null))
return null;
var hull = CreateInstance(loadoutData.Hull, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax);
if(hull==null)
return null;
// Get target zone
var zone = _zones[zoneID];
if (hullData.HullType == HullType.Ship)
{
var entity = CreateShip(hull.ID, gear.Select(g => g.ID),
cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), zone, corporation, Guid.Empty, loadoutData.Name);
entity.Active = true;
return entity;
}
if (hullData.HullType == HullType.Station)
{
var distance = lerp(.2f, .8f, Random.NextFloat()) * zoneData.Radius;
var orbit = new OrbitData
{
Context = this,
Distance = new ReactiveProperty<float>(distance),
Parent = zone.Orbits.Values.Select(o=>o.Data)
.First(orbitData => orbitData.Parent == Guid.Empty).ID,
Phase = Random.NextFloat()
};
zone.AddOrbit(orbit);
var entity = new OrbitalEntity(this, hull.ID, gear.Select(g => g.ID),
cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), orbit.ID, zone, corporation)
{
Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}",
Temperature = 293,
Population = 4
};
entity.Active = true;
var parentCorp = Cache.Get<MegaCorporation>(corpData.Parent);
foreach (var attribute in parentCorp.Personality)
entity.Personality[attribute.Key] = attribute.Value;
Cache.Add(entity);
zone.Entities[entity.ID] = entity;
return entity;
}
return null;
}
public Ship CreateShip(Guid hull, IEnumerable<Guid> gear, IEnumerable<Guid> cargo, Zone zone, Guid corporation, Guid homeEntity, string typeName)
{
var ship = new Ship(this, hull, gear, cargo, zone, corporation)
{
Name = $"{typeName} {Random.NextInt(1,255):X}",
HomeEntity = homeEntity
};
Cache.Add(ship);
zone.Entities[ship.ID] = ship;
return ship;
}
// public Entity CreateEntity(Guid zoneID, Guid corporation, Guid loadout)
// {
// if (!(ItemData.Get(loadout) is LoadoutData loadoutData))
// {
// _logger("Attempted to spawn invalid loadout ID");
// return null;
// }
//
// if (!(ItemData.Get(loadoutData.Hull) is HullData hullData))
// {
// _logger("Attempted to spawn loadout with invalid hull ID");
// return null;
// }
//
// if (!(ItemData.Get(zoneID) is ZoneData zoneData))
// {
// _logger("Attempted to spawn entity with invalid zone ID");
// return null;
// }
//
// if (!(ItemData.Get(corporation) is Corporation corpData))
// {
// _logger("Attempted to spawn entity with invalid corporation ID");
// return null;
// }
//
// var gearData = loadoutData.Gear
// .Take(hullData.Hardpoints.Count)
// .Where(id => id != Guid.Empty)
// .Select(id => ItemData.Get<GearData>(id))
// .ToArray();
//
// if (gearData.Any(g=>g==null))
// {
// _logger("Attempted to spawn loadout with invalid gear ID");
// return null;
// }
//
// var gear = gearData
// .Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
// .ToArray();
//
// if (gear.Any(g=>g==null))
// return null;
//
// foreach(var g in gear)
// ItemData.Add(g);
//
// var cargoData = loadoutData.CompoundCargo
// .SelectMany(x => Enumerable.Repeat(ItemData.Get<CraftedItemData>(x.Key), x.Value))
// .ToArray();
//
// if (cargoData.Any(g=>g==null))
// {
// _logger("Attempted to spawn loadout with invalid cargo ID");
// return null;
// }
//
// var cargo = cargoData
// .Select(gd => CreateInstance(gd.ID, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax))
// .ToArray();
//
// if (cargo.Any(g=>g==null))
// return null;
//
// foreach(var c in cargo)
// ItemData.Add(c);
//
// var simpleCargo = loadoutData.SimpleCargo?
// .Select(x => CreateInstance(x.Key, x.Value))
// .ToArray() ?? new SimpleCommodity[0];
//
// if (simpleCargo.Any(g=>g==null))
// return null;
//
// var hull = CreateInstance(loadoutData.Hull, GlobalData.StartingGearQualityMin, GlobalData.StartingGearQualityMax);
//
// if(hull==null)
// return null;
//
// // Get target zone
// var zone = _zones[zoneID];
//
// if (hullData.HullType == HullType.Ship)
// {
// var entity = CreateShip(hull.ID, gear.Select(g => g.ID),
// cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), zone, corporation, Guid.Empty, loadoutData.Name);
// entity.Active = true;
// return entity;
// }
//
// if (hullData.HullType == HullType.Station)
// {
// var distance = lerp(.2f, .8f, Random.NextFloat()) * zoneData.Radius;
// var orbit = new OrbitData
// {
// Context = this,
// Distance = new ReactiveProperty<float>(distance),
// Parent = zone.Orbits.Values.Select(o=>o.Data)
// .First(orbitData => orbitData.Parent == Guid.Empty).ID,
// Phase = Random.NextFloat()
// };
// zone.AddOrbit(orbit);
//
// var entity = new OrbitalEntity(this, hull.ID, gear.Select(g => g.ID),
// cargo.Select(c => c.ID).Concat(simpleCargo.Select(c => c.ID)), orbit.ID, zone, corporation)
// {
// Name = $"{loadoutData.Name} {Random.NextInt(1,255):X}",
// Temperature = 293,
// Population = 4
// };
// entity.Active = true;
// var parentCorp = ItemData.Get<MegaCorporation>(corpData.Parent);
// foreach (var attribute in parentCorp.Personality)
// entity.Personality[attribute.Key] = attribute.Value;
// ItemData.Add(entity);
//
// zone.Entities[entity.ID] = entity;
// return entity;
// }
//
// return null;
// }
//
// public Ship CreateShip(Guid hull, IEnumerable<Guid> gear, IEnumerable<Guid> cargo, Zone zone, Guid corporation, Guid homeEntity, string typeName)
// {
//
// var ship = new Ship(this, hull, gear, cargo, zone, corporation)
// {
// Name = $"{typeName} {Random.NextInt(1,255):X}",
// HomeEntity = homeEntity
// };
// ItemData.Add(ship);
//
// zone.Entities[ship.ID] = ship;
// return ship;
// }
public SimpleCommodity CreateInstance(Guid data, int count)
{
var item = Cache.Get<SimpleCommodityData>(data);
var item = ItemData.Get<SimpleCommodityData>(data);
if (item != null)
{
var newItem = new SimpleCommodity
{
Context = this,
Data = data,
Quantity = count
};
Cache.Add(newItem);
//ItemData.Add(newItem);
return newItem;
}
@ -598,14 +431,14 @@ public class GameContext
public CraftedItemInstance CreateInstance(Guid data, float qualityMin, float qualityMax)
{
var item = Cache.Get<CraftedItemData>(data);
var item = ItemData.Get<CraftedItemData>(data);
if (item == null)
{
_logger("Attempted to create crafted item instance using missing or incorrect item id!");
return null;
}
var blueprint = Cache.GetAll<BlueprintData>().FirstOrDefault(b => b.Item == data);
var blueprint = ItemData.GetAll<BlueprintData>().FirstOrDefault(b => b.Item == data);
if (blueprint == null)
{
_logger("Attempted to create crafted item instance which has no blueprint!");
@ -617,7 +450,7 @@ public class GameContext
var ingredients = new List<ItemInstance>();
foreach (var ingredient in blueprint.Ingredients)
{
var itemData = Cache.Get<ItemData>(ingredient.Key);
var itemData = ItemData.Get<ItemData>(ingredient.Key);
if (itemData is SimpleCommodityData)
{
var itemInstance = CreateInstance(ingredient.Key, ingredient.Value);
@ -651,69 +484,63 @@ public class GameContext
_logger($"Unable to create crafted item ingredient: {invalidIngredient?.Name??"null"} for item {item.Name}");
}
Cache.AddAll(ingredients);
if (item is EquippableItemData equippableItemData)
{
var newGear = new Gear
var newGear = new EquippableItem
{
Context = this,
Data = data,
Ingredients = ingredients.Select(i=>i.ID).ToList(),
Ingredients = ingredients,
Quality = Random.NextFloat(qualityMin, qualityMax),
Blueprint = blueprint.ID,
Name = $"{item.Name}"
};
newGear.Durability = Evaluate(equippableItemData.Durability, newGear);
Cache.Add(newGear);
newGear.Durability = equippableItemData.Durability;
return newGear;
}
var newCommodity = new CompoundCommodity
{
Context = this,
Data = data,
Ingredients = ingredients.Select(i=>i.ID).ToList(),
Ingredients = ingredients,
Quality = Random.NextFloat(qualityMin, qualityMax),
Blueprint = blueprint.ID,
Name = $"{item.Name}"
};
Cache.Add(newCommodity);
return newCommodity;
}
class DijkstraNode
{
public float Cost;
public DijkstraNode Parent;
public ZoneDefinition Zone;
}
public List<ZoneDefinition> FindPath(ZoneDefinition source, ZoneDefinition target, bool bestFirst = false)
{
SortedList<float,DijkstraNode> members = new SortedList<float,DijkstraNode>{{0,new DijkstraNode{Zone = source}}};
List<DijkstraNode> searched = new List<DijkstraNode>();
while (true)
{
var s = members.FirstOrDefault(m => !searched.Contains(m.Value)).Value; // Lowest cost unsearched node
if (s == null) return null; // No vertices left unsearched
if (s.Zone == target) // We found the path
{
Stack<DijkstraNode> path = new Stack<DijkstraNode>(); // Since we start at the end, use a LIFO collection
path.Push(s);
while(path.Peek().Parent!=null) // Keep pushing until we reach the start, which has no parent
path.Push(path.Peek().Parent);
return path.Select(dv => dv.Zone).ToList();
}
// For each adjacent star (filter already visited zones unless heuristic is in use)
foreach (var dijkstraStar in s.Zone.Links.WhereSelectF(i => !bestFirst || members.All(m => m.Value.Zone != GalaxyZones[i]),
// Cost is parent cost plus distance
i => new DijkstraNode {Parent = s, Zone = GalaxyZones[i], Cost = s.Cost + length(s.Zone.Position - GalaxyZones[i].Position)}))
// Add new member to list, sorted by cost plus optional heuristic
members.Add(bestFirst ? dijkstraStar.Cost + length(dijkstraStar.Zone.Position - target.Position) : dijkstraStar.Cost, dijkstraStar);
searched.Add(s);
}
}
// class DijkstraNode
// {
// public float Cost;
// public DijkstraNode Parent;
// public ZoneDefinition Zone;
// }
//
// public List<ZoneDefinition> FindPath(ZoneDefinition source, ZoneDefinition target, bool bestFirst = false)
// {
// SortedList<float,DijkstraNode> members = new SortedList<float,DijkstraNode>{{0,new DijkstraNode{Zone = source}}};
// List<DijkstraNode> searched = new List<DijkstraNode>();
// while (true)
// {
// var s = members.FirstOrDefault(m => !searched.Contains(m.Value)).Value; // Lowest cost unsearched node
// if (s == null) return null; // No vertices left unsearched
// if (s.Zone == target) // We found the path
// {
// Stack<DijkstraNode> path = new Stack<DijkstraNode>(); // Since we start at the end, use a LIFO collection
// path.Push(s);
// while(path.Peek().Parent!=null) // Keep pushing until we reach the start, which has no parent
// path.Push(path.Peek().Parent);
// return path.Select(dv => dv.Zone).ToList();
// }
// // For each adjacent star (filter already visited zones unless heuristic is in use)
// foreach (var dijkstraStar in s.Zone.Links.WhereSelectF(i => !bestFirst || members.All(m => m.Value.Zone != GalaxyZones[i]),
// // Cost is parent cost plus distance
// i => new DijkstraNode {Parent = s, Zone = GalaxyZones[i], Cost = s.Cost + length(s.Zone.Position - GalaxyZones[i].Position)}))
// // Add new member to list, sorted by cost plus optional heuristic
// members.Add(bestFirst ? dijkstraStar.Cost + length(dijkstraStar.Zone.Position - target.Position) : dijkstraStar.Cost, dijkstraStar);
// searched.Add(s);
// }
// }
// public bool MoveCargo(Entity source, Entity target, ItemInstance item, int quantity = int.MaxValue)
// {

View file

@ -46,6 +46,47 @@ public class Float2Formatter : MessagePack.Formatters.IMessagePackFormatter<floa
}
}
public class Int2Formatter : MessagePack.Formatters.IMessagePackFormatter<int2>
{
public void Serialize(ref MessagePackWriter writer, int2 value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
writer.Write(value.x);
writer.Write(value.y);
}
public int2 Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.IsNil)
{
throw new InvalidOperationException("typecode is null, struct not supported");
}
var length = reader.ReadArrayHeader();
var x = default(int);
var y = default(int);
for (int i = 0; i < length; i++)
{
var key = i;
switch (key)
{
case 0:
x = reader.ReadInt32();
break;
case 1:
y = reader.ReadInt32();
break;
default:
reader.Skip();
break;
}
}
var result = int2(x, y);
return result;
}
}
public class Float3Formatter : MessagePack.Formatters.IMessagePackFormatter<float3>
{
public void Serialize(ref MessagePackWriter writer, float3 value, MessagePackSerializerOptions options)

View file

@ -37,25 +37,31 @@ internal static class MathResolverResolverGetFormatterHelper
{
// standard
{ typeof(float2), new Float2Formatter() },
{ typeof(int2), new Int2Formatter() },
{ typeof(float3), new Float3Formatter() },
{ typeof(float4), new Float4Formatter() },
{ typeof(float2?), new StaticNullableFormatter<float2>(new Float2Formatter()) },
{ typeof(int2?), new StaticNullableFormatter<int2>(new Int2Formatter()) },
{ typeof(float3?), new StaticNullableFormatter<float3>(new Float3Formatter()) },
{ typeof(float4?), new StaticNullableFormatter<float4>(new Float4Formatter()) },
// standard + array
{ typeof(float2[]), new ArrayFormatter<float2>() },
{ typeof(int2[]), new ArrayFormatter<int2>() },
{ typeof(float3[]), new ArrayFormatter<float3>() },
{ typeof(float4[]), new ArrayFormatter<float4>() },
{ typeof(float2?[]), new ArrayFormatter<float2?>() },
{ typeof(int2?[]), new ArrayFormatter<float2?>() },
{ typeof(float3?[]), new ArrayFormatter<float3?>() },
{ typeof(float4?[]), new ArrayFormatter<float4?>() },
// standard + list
{ typeof(List<float2>), new ListFormatter<float2>() },
{ typeof(List<int2>), new ListFormatter<int2>() },
{ typeof(List<float3>), new ListFormatter<float3>() },
{ typeof(List<float4>), new ListFormatter<float4>() },
{ typeof(List<float2?>), new ListFormatter<float2?>() },
{ typeof(List<int2?>), new ListFormatter<int2?>() },
{ typeof(List<float3?>), new ListFormatter<float3?>() },
{ typeof(List<float4?>), new ListFormatter<float4?>() },
};

View file

@ -96,7 +96,7 @@ public class GalaxyResponseMessage : Message
{
[Key(0)] public ZoneDefinition[] Zones;
[Key(1)] public GalaxyMapLayerData StarDensity;
[Key(2)] public GlobalData GlobalData;
// [Key(2)] public GlobalData GlobalData;
}
[MessagePackObject]

View file

@ -9,7 +9,7 @@ public class OrbitalEntity : Entity
{
public Guid OrbitData;
public OrbitalEntity(GameContext context, Guid hull, IEnumerable<Guid> gear, IEnumerable<Guid> cargo, Guid orbit, Zone zone, Guid corporation) : base(context, hull, gear, cargo, zone, corporation)
public OrbitalEntity(ItemManager itemManager, Zone zone, EquippableItem hull, Guid orbit) : base(itemManager, zone, hull)
{
OrbitData = orbit;
}

View file

@ -80,3 +80,18 @@ public class ZoneGenerationSettings
public ExponentialLerp GasGiantBandSaturation;
public ExponentialLerp GasGiantBandBrightness;
}
[Serializable, MessagePackObject(keyAsPropertyName: true), JsonObject]
public class GameplaySettings
{
public float WarpDistance = 25;
public float DockingDistance = 25;
public int SignificantDigits = 3;
public float ProductionPersonalityLerp = .05f;
public float MessageDuration = 4f;
public float TargetPersistenceDuration = 3;
public ExponentialLerp StartingGearQuality;
public float HeatRadiationExponent = 1;
public float HeatRadiationMultiplier = 1;
}

View file

@ -17,10 +17,9 @@ public class Ship : Entity
// [IgnoreMember] public Dictionary<Targetable, float> Contacts = new Dictionary<Targetable, float>();
// [IgnoreMember] public Targetable Target;
[JsonProperty("homeEntity"), Key(19)]
public Guid HomeEntity;
public Entity HomeEntity;
public Ship(GameContext context, Guid hull, IEnumerable<Guid> gear, IEnumerable<Guid> cargo, Zone zone, Guid corporation) : base(context, hull, gear, cargo, zone, corporation)
public Ship(ItemManager itemManager, Zone zone, EquippableItem hull) : base(itemManager, zone, hull)
{
}

View file

@ -11,7 +11,7 @@ using Random = Unity.Mathematics.Random;
public class Zone
{
//public HashSet<Guid> Planets = new HashSet<Guid>();
public Dictionary<Guid, Entity> Entities = new Dictionary<Guid, Entity>();
public List<Entity> Entities = new List<Entity>();
//public Dictionary<Guid, OrbitData> Orbits = new Dictionary<Guid, OrbitData>();
public Dictionary<Guid, BodyData> Planets = new Dictionary<Guid, BodyData>();
public Dictionary<Guid, Planet> PlanetInstances = new Dictionary<Guid, Planet>();
@ -55,7 +55,7 @@ public class Zone
}
}
foreach (var entity in pack.Entities) Entities.Add(entity.ID, entity);
foreach (var entity in pack.Entities) Entities.Add(entity);
// TODO: Associate planets with stored entities for planetary colonies
}
@ -65,7 +65,7 @@ public class Zone
return new ZonePack
{
Data = Data,
Entities = Entities.Values.ToList(),
Entities = Entities,
Orbits = Orbits.Values.Select(o=>o.Data).ToList(),
Planets = Planets.Values.ToList()
};
@ -90,7 +90,7 @@ public class Zone
foreach (var asteroids in AsteroidBelts.Keys)
UpdateAsteroidTransforms(asteroids);
foreach (var entity in Entities.Values) entity.Update(deltaTime);
foreach (var entity in Entities) entity.Update(deltaTime);
}
public float2 WormholePosition(ZoneDefinition target)
@ -236,29 +236,30 @@ public class Zone
belt.Damage[asteroid] = 0;
belt.Damage[asteroid] = belt.Damage[asteroid] + damage;
if (!belt.MiningAccumulator.ContainsKey((miner.ID, asteroid)))
belt.MiningAccumulator[(miner.ID, asteroid)] = 0;
belt.MiningAccumulator[(miner.ID, asteroid)] = belt.MiningAccumulator[(miner.ID, asteroid)] + damage;
if (!belt.MiningAccumulator.ContainsKey((miner, asteroid)))
belt.MiningAccumulator[(miner, asteroid)] = 0;
belt.MiningAccumulator[(miner, asteroid)] = belt.MiningAccumulator[(miner, asteroid)] + damage;
if (belt.Damage[asteroid] > asteroidHitpoints)
{
belt.RespawnTimers[asteroid] = _settings.AsteroidRespawnTime.Evaluate(size);
belt.Damage.Remove(asteroid);
belt.MiningAccumulator.Remove((miner.ID, asteroid));
belt.MiningAccumulator.Remove((miner, asteroid));
return;
}
var resourceCount = beltData.Resources.Sum(x => x.Value);
var resource = beltData.Resources.MaxBy(x => pow(x.Value, 1f / penetration) * _random.NextFloat());
if (efficiency * _random.NextFloat() * belt.MiningAccumulator[(miner.ID, asteroid)] * resourceCount / _settings.MiningDifficulty > 1 && miner.OccupiedCapacity < miner.Capacity - 1)
if (efficiency * _random.NextFloat() * belt.MiningAccumulator[(miner, asteroid)] * resourceCount / _settings.MiningDifficulty > 1)
{
belt.MiningAccumulator.Remove((miner.ID, asteroid));
var newSimpleCommodity = new SimpleCommodity
{
Data = resource.Key,
Quantity = 1
};
miner.AddCargo(newSimpleCommodity);
belt.MiningAccumulator.Remove((miner, asteroid));
// var newSimpleCommodity = new SimpleCommodity
// {
// Data = resource.Key,
// Quantity = 1
// };
// TODO: Drop item onto the Grid
//miner.AddCargo(newSimpleCommodity);
}
}
public float GetHeight(float2 position)
@ -393,7 +394,7 @@ public class AsteroidBelt
public float4[] PreviousTransforms; // x, y, rotation, scale
public Dictionary<int, float> RespawnTimers = new Dictionary<int, float>();
public Dictionary<int, float> Damage = new Dictionary<int, float>();
public Dictionary<(Guid, int), float> MiningAccumulator = new Dictionary<(Guid, int), float>();
public Dictionary<(Entity, int), float> MiningAccumulator = new Dictionary<(Entity, int), float>();
public AsteroidBelt(AsteroidBeltData data)
{

View file

@ -11,24 +11,24 @@ using Random = Unity.Mathematics.Random;
public class ZoneGenerator
{
public static ZonePack GenerateZone(
ZoneGenerationSettings settings,
Dictionary<string,GalaxyMapLayerData> mapLayers,
IEnumerable<SimpleCommodityData> resources,
string name,
float2 position)
{
var random = new Random(Convert.ToUInt32(abs(name.GetHashCode())));
var radius = settings.ZoneRadius.Evaluate(random.NextFloat() * mapLayers["Radius"].Evaluate(position, settings.ShapeSettings));
var mass = settings.ZoneMass.Evaluate(random.NextFloat() * mapLayers["Mass"].Evaluate(position, settings.ShapeSettings));
return GenerateZone(settings, mapLayers, resources, name, position, mass, radius, random);
}
// public static ZonePack GenerateZone(
// ZoneGenerationSettings settings,
// Dictionary<string,GalaxyMapLayerData> mapLayers,
// IEnumerable<SimpleCommodityData> resources,
// string name,
// float2 position)
// {
// var random = new Random(Convert.ToUInt32(abs(name.GetHashCode())));
// var radius = settings.ZoneRadius.Evaluate(random.NextFloat() * mapLayers["Radius"].Evaluate(position, settings.ShapeSettings));
// var mass = settings.ZoneMass.Evaluate(random.NextFloat() * mapLayers["Mass"].Evaluate(position, settings.ShapeSettings));
//
// return GenerateZone(settings, mapLayers, resources, name, position, mass, radius, random);
// }
public static ZonePack GenerateZone(
ZoneGenerationSettings settings,
Dictionary<string,GalaxyMapLayerData> mapLayers,
IEnumerable<SimpleCommodityData> resources,
// Dictionary<string,GalaxyMapLayerData> mapLayers,
// IEnumerable<SimpleCommodityData> resources,
float mass,
float radius)
{
@ -36,13 +36,13 @@ public class ZoneGenerator
var position = float2(0f);
var random = new Random(Convert.ToUInt32(abs(name.GetHashCode())));
return GenerateZone(settings, mapLayers, resources, name, position, mass, radius, random);
return GenerateZone(settings, name, position, mass, radius, random);
}
private static ZonePack GenerateZone(
ZoneGenerationSettings settings,
Dictionary<string,GalaxyMapLayerData> mapLayers,
IEnumerable<SimpleCommodityData> resources,
// Dictionary<string,GalaxyMapLayerData> mapLayers,
// IEnumerable<SimpleCommodityData> resources,
string name,
float2 position,
float mass,
@ -92,25 +92,25 @@ public class ZoneGenerator
: Guid.Empty;
// Cache resource densities
var resourceMaps = mapLayers.Values
.ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, settings.ShapeSettings));
// var resourceMaps = mapLayers.Values
// .ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, settings.ShapeSettings));
pack.Planets = planets.Where(p=>!p.Empty).Select(planet =>
{
Dictionary<Guid, float> planetResources = new Dictionary<Guid, float>();
// Dictionary<Guid, float> planetResources = new Dictionary<Guid, float>();
BodyType bodyType = planet.Belt ? BodyType.Asteroid :
planet.Mass > settings.SunMass ? BodyType.Sun :
planet.Mass > settings.GasGiantMass ? BodyType.GasGiant :
planet.Mass > settings.PlanetMass ? BodyType.Planet : BodyType.Planetoid;
foreach (var r in resources)
{
if ((bodyType & r.ResourceBodyType) != 0)
{
float quantity = ResourceValue(ref random, settings, r, r.ResourceDensity.Aggregate(1f, (m, rdm) => m * resourceMaps[rdm]));
if (r.Floor < quantity) planetResources.Add(r.ID, quantity);
}
}
// foreach (var r in resources)
// {
// if ((bodyType & r.ResourceBodyType) != 0)
// {
// float quantity = ResourceValue(ref random, settings, r, r.ResourceDensity.Aggregate(1f, (m, rdm) => m * resourceMaps[rdm]));
// if (r.Floor < quantity) planetResources.Add(r.ID, quantity);
// }
// }
BodyData planetData;
switch (bodyType)
@ -134,7 +134,7 @@ public class ZoneGenerator
planetData.Mass.Value = planet.Mass;
planetData.Orbit = orbitMap[planet].ID;
planetData.Resources = planetResources;
// planetData.Resources = planetResources;
planetData.Name.Value = planetData.ID.ToString().Substring(0, 8);
if (planetData is AsteroidBeltData beltData)
{
@ -199,11 +199,11 @@ public class ZoneGenerator
return pack;
}
static float ResourceValue(ref Random random, ZoneGenerationSettings settings, SimpleCommodityData resource, float density)
{
return random.NextPowerDistribution(resource.Minimum, resource.Maximum, resource.Exponent,
1 / lerp(settings.ResourceDensityMinimum, settings.ResourceDensityMaximum, density));
}
// static float ResourceValue(ref Random random, ZoneGenerationSettings settings, SimpleCommodityData resource, float density)
// {
// return random.NextPowerDistribution(resource.Minimum, resource.Maximum, resource.Exponent,
// 1 / lerp(settings.ResourceDensityMinimum, settings.ResourceDensityMaximum, density));
// }
public static GeneratorPlanet[] GenerateEntities(ZoneGenerationSettings settings, ref Random random, ZoneData zone)
{