New Mining Controller Behavior and Mining Tool Behavior, tweaked a bunch of asteroid related stuff
This commit is contained in:
hyperion51 2020-05-28 04:50:40 +01:00
commit 399b933a38
22 changed files with 609 additions and 58 deletions

View file

@ -1245,6 +1245,7 @@
<e p="AgentBehavior.cs" t="Include" />
<e p="AgentTask.cs" t="Include" />
<e p="Locomotion.cs" t="Include" />
<e p="Mining.cs" t="Include" />
<e p="StationTowing.cs" t="Include" />
<e p="VelocityMatch.cs" t="Include" />
</e>
@ -1260,6 +1261,8 @@
<e p="Hitscan.cs" t="Include" />
<e p="ItemUsage.cs" t="Include" />
<e p="Launcher.cs" t="Include" />
<e p="MiningController.cs" t="Include" />
<e p="MiningTool.cs" t="Include" />
<e p="PatrolController.cs" t="Include" />
<e p="ProjectileWeapon.cs" t="Include" />
<e p="Radiance.cs" t="Include" />

View file

@ -8,6 +8,7 @@ using UnityEngine;
[MessagePackObject,
Union(0, typeof(StationTowing)),
Union(1, typeof(Mining)),
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<DatabaseEntry>))]
public abstract class AgentTask : DatabaseEntry
{
@ -25,6 +26,7 @@ public abstract class AgentTask : DatabaseEntry
public enum TaskType
{
None,
Mine,
Haul,
Tow,

View file

@ -0,0 +1,24 @@
using System;
using System.Collections;
using System.Collections.Generic;
using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
[MessagePackObject,
JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter<DatabaseEntry>))]
public class Mining : AgentTask
{
[IgnoreMember] public override TaskType Type => TaskType.Mine;
[JsonProperty("asteroids"), Key(4)]
public Guid Asteroids;
// public StationTowing(Guid zone, Guid station, Guid orbitParent, float orbitDistance)
// {
// Zone = zone;
// Station = station;
// OrbitParent = orbitParent;
// OrbitDistance = orbitDistance;
// }
}

View file

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

View file

@ -89,6 +89,8 @@ public abstract class PersistentBehaviorData
Union(22, typeof(VisibilityData)),
Union(23, typeof(ThermotoggleData)),
Union(24, typeof(EnergyDrawData)),
Union(25, typeof(MiningControllerData)),
Union(26, typeof(MiningToolData)),
JsonConverter(typeof(JsonKnownTypesConverter<BehaviorData>)), JsonObject(MemberSerialization.OptIn)]
public abstract class BehaviorData
{

View file

@ -41,12 +41,12 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
protected bool MatchVelocity;
protected List<SimplifiedZoneData> Path;
protected Guid Task;
protected bool Moving;
private GameContext _context;
private Entity _entity;
private ControllerData _controllerData;
private MovementPhase _movementPhase;
private bool _moving;
private Action _onFinishMoving;
public ControllerBase(GameContext context, ControllerData data, Entity entity)
@ -67,7 +67,7 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
public void AssignTask(Guid task)
{
Task = task;
_moving = false;
Moving = false;
}
public bool Update(float delta)
@ -79,18 +79,17 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
return false;
// No task is assigned, but we're not home, go home!
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
if (!_moving)
if (!Moving)
{
if (Zone == homeEntity.Zone) MoveTo(homeEntity, true, () =>
_context.SetParent(_entity, homeEntity));
else MoveTo(homeEntity.Zone, () => MoveTo(homeEntity, true, () =>
_context.SetParent(_entity, homeEntity)));
GoHome();
}
}
if (_moving)
if (Moving)
{
if(_entity.Parent!=Guid.Empty)
_context.RemoveParent(_entity);
var distance = length(TargetPosition() - _entity.Position);
if (MatchVelocity)
{
@ -108,8 +107,8 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
VelocityMatch.Clear();
VelocityMatch.OnMatch += () =>
{
_moving = false;
_onFinishMoving();
Moving = false;
_onFinishMoving?.Invoke();
};
}
}
@ -124,7 +123,7 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
Locomotion.Update(delta);
if (distance < _controllerData.TargetDistance)
{
_moving = false;
Moving = false;
_onFinishMoving();
}
}
@ -133,13 +132,39 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
return true;
}
public void FinishTask()
{
if (Task == Guid.Empty)
return;
var task = _context.Cache.Get(Task);
_context.Cache.Delete(task);
_context.Cache.Get<Corporation>(_entity.Corporation).Tasks.Remove(task.ID);
Task = Guid.Empty;
}
public void GoHome(Action onFinish = null)
{
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
if (Zone == homeEntity.Zone) MoveTo(homeEntity, true, () =>
{
_context.SetParent(_entity, homeEntity);
onFinish?.Invoke();
});
else MoveTo(homeEntity.Zone, () => MoveTo(homeEntity, true, () =>
{
_context.SetParent(_entity, homeEntity);
onFinish?.Invoke();
}));
}
public void MoveTo(Entity entity, bool matchVelocity = true, Action onFinish = null)
{
TargetPosition = () => entity.Position;
TargetVelocity = () => entity.Velocity;
MatchVelocity = matchVelocity;
_movementPhase = MovementPhase.Locomotion;
_moving = true;
Moving = true;
_onFinishMoving = onFinish;
}
@ -149,7 +174,7 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
TargetVelocity = () => float2.zero;
MatchVelocity = matchVelocity;
_movementPhase = MovementPhase.Locomotion;
_moving = true;
Moving = true;
_onFinishMoving = onFinish;
}
@ -159,7 +184,7 @@ public abstract class ControllerBase : IBehavior, IController, IInitializableBeh
TargetVelocity = velocity;
MatchVelocity = true;
_movementPhase = MovementPhase.Locomotion;
_moving = true;
Moving = true;
_onFinishMoving = onFinish;
}

View file

@ -109,7 +109,7 @@ public class Factory : IBehavior, IPersistentBehavior
else
{
var simpleCommodityData = blueprintItemData as SimpleCommodityData;
var simpleCommodityInstance = Entity.Cargo.FirstOrDefault(i => i == simpleCommodityData.ID);
var simpleCommodityInstance = Entity.Cargo.FirstOrDefault(i => Context.Cache.Get<ItemInstance>(i).Data == simpleCommodityData.ID);
if (simpleCommodityInstance == Guid.Empty)
{
var newSimpleCommodity = new SimpleCommodity

View file

@ -24,6 +24,7 @@ public class Hitscan : IBehavior
private float _firingVisibility;
public BehaviorData Data => _data;
public float Range { get; private set; }
public Hitscan(GameContext context, HitscanData c, Entity entity, Gear item)
{
@ -36,6 +37,7 @@ public class Hitscan : IBehavior
public bool Update(float delta)
{
// TODO: Implement hitscan weapons!
Range = Context.Evaluate(_data.Range, Item, Entity);
return true;
}

View file

@ -0,0 +1,130 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MessagePack;
using Newtonsoft.Json;
using Unity.Mathematics;
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)
{
return new MiningController(context, this, entity, item);
}
}
public class MiningController : ControllerBase, 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 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)
{
_context = context;
_data = data;
_entity = entity;
_item = item;
}
public new void Initialize()
{
_miningTool = _entity.GetBehaviors<MiningTool>().First();
_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 = _context.GetAsteroidTransform(miningTask.Asteroids, _asteroid);
if (length(_entity.Position - asteroidTransform.xy) - asteroidTransform.w > _miningTool.Range)
{
_context.Log($"Mining Controller {_entity.Name} is out of range, moving to target asteroid.");
MoveTo(() => _context.GetAsteroidTransform(miningTask.Asteroids, _asteroid).xy,
() => _context.GetAsteroidVelocity(miningTask.Asteroids, _asteroid));
_toolSwitch.Activated = false;
}
else
{
if (_context.AsteroidExists(miningTask.Asteroids, _asteroid))
{
_miningTool.AsteroidBelt = miningTask.Asteroids;
_miningTool.Asteroid = _asteroid;
_toolSwitch.Activated = true;
}
else NextAsteroid();
}
}
else
{
_context.Log($"Mining Controller {_entity.Name} is out of cargo space. Returning home to offload cargo.");
GoHome(() =>
{
var homeEntity = _context.Cache.Get<Entity>(HomeEntity);
if (!_entity.Cargo.ToArray().All(ii =>
_context.MoveCargo(_entity, homeEntity, _context.Cache.Get<ItemInstance>(ii))))
{
_context.Log($"Mining Controller {_entity.Name} has run out of cargo space in parent. Closing Task.");
FinishTask();
_taskStarted = false;
}
});
}
}
}
}
return base.Update(delta);
}
private void NextAsteroid()
{
var miningTask = _context.Cache.Get<Mining>(Task);
_asteroid = _context.NearestAsteroid(miningTask.Asteroids, _entity.Position);
_context.Log($"Mining Controller {_entity.Name} selecting new asteroid.");
}
public PersistentBehaviorData Store()
{
return new MiningControllerPersistence
{
Task = Task
};
}
public void Restore(PersistentBehaviorData data)
{
var miningControllerPersistence = data as MiningControllerPersistence;
Task = miningControllerPersistence.Task;
}
}
public class MiningControllerPersistence : PersistentBehaviorData
{
[JsonProperty("task"), Key(0)]
public Guid Task;
}

View file

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

View file

@ -0,0 +1,71 @@
using System;
using System.Linq;
using MessagePack;
using Newtonsoft.Json;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(10)]
public class MiningToolData : BehaviorData
{
[InspectableField, JsonProperty("dps"), Key(1)]
public PerformanceStat DamagePerSecond = new PerformanceStat();
[InspectableField, JsonProperty("efficiency"), Key(2)]
public PerformanceStat Efficiency = new PerformanceStat();
[InspectableField, JsonProperty("penetration"), Key(3)]
public PerformanceStat Penetration = new PerformanceStat();
[InspectableField, JsonProperty("range"), Key(4)]
public PerformanceStat Range = new PerformanceStat();
public override IBehavior CreateInstance(GameContext context, Entity entity, Gear item)
{
return new MiningTool(context, this, entity, item);
}
}
public class MiningTool : IBehavior
{
public Guid AsteroidBelt;
public int Asteroid;
private MiningToolData _data;
private Entity Entity { get; }
private Gear Item { get; }
private GameContext Context { get; }
public BehaviorData Data => _data;
public float Range { get; private set; }
public MiningTool(GameContext context, MiningToolData data, Entity entity, Gear item)
{
_data = data;
Entity = entity;
Item = item;
Context = context;
}
public bool Update(float delta)
{
Range = Context.Evaluate(_data.Range, Item, Entity);
var asteroidTransform = Context.GetAsteroidTransform(AsteroidBelt, Asteroid);
if (AsteroidBelt != Guid.Empty &&
Context.AsteroidExists(AsteroidBelt, Asteroid) &&
length(Entity.Position - asteroidTransform.xy) - asteroidTransform.w < Range)
{
Context.MineAsteroid(
Entity,
AsteroidBelt,
Asteroid,
Context.Evaluate(_data.DamagePerSecond, Item, Entity) * delta,
Context.Evaluate(_data.Efficiency, Item, Entity),
Context.Evaluate(_data.Penetration, Item, Entity));
return true;
}
return false;
}
}

View file

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

View file

@ -17,7 +17,7 @@ public class PatrolControllerData : ControllerData
public class PatrolController : IBehavior, IController, IInitializableBehavior
{
public TaskType TaskType => TaskType.Tow;
public TaskType TaskType => TaskType.None;
public bool Available => false;
public Guid Zone => _entity.Zone;
public BehaviorData Data => _data;
@ -26,7 +26,6 @@ public class PatrolController : IBehavior, IController, IInitializableBehavior
private GameContext _context;
private Entity _entity;
private Gear _item;
private Guid _towingTask;
private Locomotion _locomotion;
private Guid _targetOrbit;

View file

@ -22,7 +22,7 @@ public class Switch : IBehavior
public BehaviorData Data => _data;
private bool Activated { get; set; }
public bool Activated { get; set; }
public Switch(GameContext context, SwitchData data, Entity entity, Gear item)
{

View file

@ -40,9 +40,6 @@ public class TowingController : ControllerBase, IBehavior, IPersistentBehavior
var towingTask = _context.Cache.Get<StationTowing>(Task);
if (towingTask != null)
{
if(_entity.Parent!=Guid.Empty)
_context.RemoveParent(_entity);
if (!_taskStarted)
{
MoveTo(towingTask.Zone, () =>
@ -66,7 +63,7 @@ public class TowingController : ControllerBase, IBehavior, IPersistentBehavior
var orbit = _context.CreateOrbit(towingTask.OrbitParent, _entity.Position);
target.OrbitData = orbit.ID;
Task = Guid.Empty;
FinishTask();
_taskStarted = false;
});
});

View file

@ -45,6 +45,15 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR
[IgnoreMember] public float OccupiedCapacity { get; private set; }
[IgnoreMember] public float SpecificHeat { get; private set; }
[IgnoreMember] public float Visibility => VisibilitySources.Values.Sum();
public float Capacity
{
get
{
var hull = Context.Cache.Get<Gear>(Hull);
var hullData = Context.Cache.Get<HullData>(hull.Data);
return Context.Evaluate(hullData.Capacity, hull, this);
}
}
[IgnoreMember] public string EntryName
{
@ -168,6 +177,21 @@ public abstract class Entity : DatabaseEntry, IMessagePackSerializationCallbackR
return -1;
}
public int GetSwitch<T>() where T : class, IBehavior
{
var s = Behaviors
.FirstOrDefault(x => x.Value.Any(g => g is Switch) && x.Value.Any(g => g is T))
.Value.First(g => g is Switch) as Switch;
return Switches.FirstOrDefault(kvp => kvp.Value == s).Key;
}
public Switch GetSwitch(IBehavior behavior)
{
return Behaviors
.FirstOrDefault(x => x.Value.Any(g => g == behavior))
.Value.First(g => g is Switch) as Switch;
}
public void AddHeat(float heat)
{
if (Parent != Guid.Empty)

View file

@ -30,7 +30,10 @@ public class GameContext
private Dictionary<Guid, float2> _orbitVelocities = new Dictionary<Guid, float2>();
private Dictionary<Guid, float2> _orbitPositions = new Dictionary<Guid, float2>();
private Dictionary<Guid, float2> _previousOrbitPositions = new Dictionary<Guid, float2>();
private Dictionary<Guid, float3[]> _asteroidPositions = new Dictionary<Guid, float3[]>();
private Dictionary<Guid, float4[]> _asteroidTransforms = new Dictionary<Guid, float4[]>(); // x, y, rotation, scale
private Dictionary<Guid, float4[]> _previousAsteroidTransforms = new Dictionary<Guid, float4[]>(); // x, y, rotation, scale
private Dictionary<(Guid, int), float> _asteroidRespawnTimers = new Dictionary<(Guid, int), float>();
private Dictionary<(Guid, int), float> _asteroidDamage = new Dictionary<(Guid, int), float>();
private Dictionary<Guid, bool> _asteroidPositionsUpdated = new Dictionary<Guid, bool>();
private Guid _forceLoadZone;
private Type[] _statObjects;
@ -104,7 +107,7 @@ public class GameContext
: float2.zero;
}
foreach (var asteroids in _asteroidPositions.Keys)
foreach (var asteroids in _asteroidTransforms.Keys)
_asteroidPositionsUpdated[asteroids] = false;
foreach (var corporation in Cache.GetAll<Corporation>())
@ -232,26 +235,82 @@ public class GameContext
return _orbitVelocities.ContainsKey(orbit) ? _orbitVelocities[orbit] : float2.zero;
}
public float3[] GetAsteroidTransforms(Guid planetDataID)
public int NearestAsteroid(Guid planetDataID, float2 position)
{
var planetData = Cache.Get<PlanetData>(planetDataID);
if (!_asteroidPositions.ContainsKey(planetDataID))
var asteroidPositions = GetAsteroidTransforms(planetDataID);
int nearest = 0;
float nearestDistance = Single.MaxValue;
for (int i = 0; i < planetData.Asteroids.Length; i++)
{
_asteroidPositions[planetDataID] = new float3[planetData.Asteroids.Length];
var dist = lengthsq(asteroidPositions[i].xy - position);
if (AsteroidExists(planetDataID, i) && dist < nearestDistance)
{
nearest = i;
nearestDistance = dist;
}
}
return nearest;
}
public bool AsteroidExists(Guid planetDataID, int asteroid) =>
!_asteroidRespawnTimers.ContainsKey((planetDataID, asteroid));
public float2 GetAsteroidVelocity(Guid planetDataID, int asteroid)
{
UpdateAsteroidTransforms(planetDataID);
if (!_previousAsteroidTransforms.ContainsKey(planetDataID))
return float2.zero;
return (_asteroidTransforms[planetDataID][asteroid].xy - _previousAsteroidTransforms[planetDataID][asteroid].xy) / _deltaTime;
}
public float4 GetAsteroidTransform(Guid planetDataID, int asteroid)
{
UpdateAsteroidTransforms(planetDataID);
return _asteroidTransforms[planetDataID][asteroid];
}
public float4[] GetAsteroidTransforms(Guid planetDataID)
{
UpdateAsteroidTransforms(planetDataID);
return _asteroidTransforms[planetDataID];
}
private void UpdateAsteroidTransforms(Guid planetDataID)
{
var planetData = Cache.Get<PlanetData>(planetDataID);
if (!_asteroidTransforms.ContainsKey(planetDataID))
{
_asteroidTransforms[planetDataID] = new float4[planetData.Asteroids.Length];
_asteroidPositionsUpdated[planetDataID] = false;
}
if (_asteroidPositionsUpdated[planetDataID])
return _asteroidPositions[planetDataID];
return;
if (!_previousAsteroidTransforms.ContainsKey(planetDataID))
_previousAsteroidTransforms[planetDataID] = new float4[planetData.Asteroids.Length];
Array.Copy(_asteroidTransforms[planetDataID], _previousAsteroidTransforms[planetDataID], planetData.Asteroids.Length);
var orbitData = Cache.Get<OrbitData>(planetData.Orbit);
var orbitPosition = GetOrbitPosition(orbitData.Parent);
for (var i = 0; i < planetData.Asteroids.Length; i++)
{
_asteroidPositions[planetDataID][i] = float3(
OrbitData.Evaluate((float) frac(Time / OrbitalPeriod(planetData.Asteroids[i].x) * GlobalData.OrbitSpeedMultiplier +
planetData.Asteroids[i].y)) * planetData.Asteroids[i].x,
(float) (Time * planetData.Asteroids[i].w % 360.0));
_asteroidTransforms[planetDataID][i] = float4(
OrbitData.Evaluate((float) frac(Time / OrbitalPeriod(planetData.Asteroids[i].Distance) * GlobalData.OrbitSpeedMultiplier +
planetData.Asteroids[i].Phase)) * planetData.Asteroids[i].Distance + orbitPosition,
(float) (Time * planetData.Asteroids[i].RotationSpeed % 360.0),
_asteroidRespawnTimers.ContainsKey((planetDataID, i)) ? 0 : planetData.Asteroids[i].Size);
}
return _asteroidPositions[planetDataID];
_asteroidPositionsUpdated[planetDataID] = true;
}
public OrbitData CreateOrbit(Guid parent, float2 position)
@ -274,11 +333,9 @@ public class GameContext
Phase = storedPhase,
Zone = parentOrbit.Zone
};
_lastCreatedOrbit = orbit;
Cache.Add(orbit);
return orbit;
}
private OrbitData _lastCreatedOrbit;
public float OrbitalPeriod(float distance)
{
@ -812,4 +869,133 @@ public class GameContext
parent.RecalculateMass();
child.Parent = Guid.Empty;
}
public void MineAsteroid(Entity miner, Guid asteroidBelt, int asteroid, float damage, float efficiency, float penetration)
{
var planetData = Cache.Get<PlanetData>(asteroidBelt);
var asteroidTransform = GetAsteroidTransform(asteroidBelt, asteroid);
var hpLerp = unlerp(GlobalData.AsteroidSizeMin, GlobalData.AsteroidSizeMax, asteroidTransform.w);
var asteroidHitpoints = lerp(GlobalData.AsteroidHitpointsMin, GlobalData.AsteroidHitpointsMax, pow(hpLerp, GlobalData.AsteroidHitpointsPower));
if (!_asteroidDamage.ContainsKey((asteroidBelt, asteroid)))
_asteroidDamage[(asteroidBelt, asteroid)] = 0;
_asteroidDamage[(asteroidBelt, asteroid)] = _asteroidDamage[(asteroidBelt, asteroid)] + damage;
if (_asteroidDamage[(asteroidBelt, asteroid)] > asteroidHitpoints)
_asteroidRespawnTimers[(asteroidBelt, asteroid)] =
lerp(GlobalData.AsteroidRespawnMin, GlobalData.AsteroidRespawnMax, hpLerp);
var resource = planetData.Resources.MaxBy(x => pow(x.Value, 1f / penetration) * Random.NextFloat());
if (resource.Value * efficiency * Random.NextFloat() > 1 && miner.OccupiedCapacity < miner.Capacity - 1)
{
var simpleCommodityTarget = miner.Cargo
.Select(i => Cache.Get<ItemInstance>(i))
.FirstOrDefault(i => i.Data == resource.Key) as SimpleCommodity;
if (simpleCommodityTarget == null)
{
var newSimpleCommodity = new SimpleCommodity
{
Context = this,
Data = resource.Key,
Quantity = 1
};
Cache.Add(newSimpleCommodity);
miner.Cargo.Add(newSimpleCommodity.ID);
miner.RecalculateMass();
}
else
{
simpleCommodityTarget.Quantity++;
miner.RecalculateMass();
}
}
}
public bool MoveCargo(Entity source, Entity target, ItemInstance item, int quantity = int.MaxValue)
{
if (item is CraftedItemInstance craftedItemInstance)
{
var craftedItemData = Cache.Get<CraftedItemData>(craftedItemInstance.Data);
if (target.Capacity - target.OccupiedCapacity > craftedItemData.Size)
{
// Target has the cargo capacity for the item, simply move the instance
source.Cargo.Remove(item.ID);
target.Cargo.Add(item.ID);
source.RecalculateMass();
target.RecalculateMass();
return true;
}
return false;
}
if (item is SimpleCommodity simpleCommoditySource)
{
quantity = min(quantity, simpleCommoditySource.Quantity);
var simpleCommodityData = Cache.Get<SimpleCommodityData>(simpleCommoditySource.Data);
var spareCapacity = (int) (target.Capacity - target.OccupiedCapacity);
var simpleCommodityTarget = target.Cargo
.Select(i => Cache.Get<ItemInstance>(i))
.FirstOrDefault(i => i.Data == simpleCommodityData.ID) as SimpleCommodity;
var success = spareCapacity >= quantity;
quantity = min(quantity, spareCapacity);
if (simpleCommodityTarget == null)
{
if (quantity == simpleCommoditySource.Quantity)
{
// Target has the cargo capacity to hold the full quantity,
// and the target has no matching item instance;
// simply move the existing item instance to the target
source.Cargo.Remove(simpleCommoditySource.ID);
target.Cargo.Add(simpleCommoditySource.ID);
source.RecalculateMass();
target.RecalculateMass();
return success;
}
else
{
// Target has the cargo capacity to hold the desired quantity
// and the target has no matching item instance;
// Create a new item instance on the target and decrement the quantity of the source instance
var newSimpleCommodity = new SimpleCommodity
{
Context = this,
Data = simpleCommodityData.ID,
Quantity = simpleCommoditySource.Quantity
};
Cache.Add(newSimpleCommodity);
target.Cargo.Add(newSimpleCommodity.ID);
simpleCommoditySource.Quantity -= quantity;
source.RecalculateMass();
target.RecalculateMass();
return success;
}
}
else
{
if (quantity == simpleCommoditySource.Quantity)
{
// Target has the cargo capacity to hold the full quantity,
// and there is already a matching item instance;
// delete the source entity's item instance and increment the target's quantity
source.Cargo.Remove(simpleCommoditySource.ID);
Cache.Delete(simpleCommoditySource);
simpleCommodityTarget.Quantity += quantity;
source.RecalculateMass();
target.RecalculateMass();
return success;
}
else
{
// Target has the cargo capacity to hold the desired quantity,
// and there is already a matching item instance;
// decrement the source's quantity and increment the target's quantity
simpleCommoditySource.Quantity -= quantity;
simpleCommodityTarget.Quantity += quantity;
source.RecalculateMass();
target.RecalculateMass();
return success;
}
}
}
return false;
}
}

View file

@ -139,6 +139,21 @@ public class GlobalData : DatabaseEntry
[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;
public float PlanetRadius(float mass)
{

View file

@ -94,7 +94,7 @@ public class PlanetData : DatabaseEntry, INamedEntry
public Dictionary<Guid, float> Resources = new Dictionary<Guid, float>();
[JsonProperty("asteroids"), Key(7)]
public float4[] Asteroids; // Distance, Phase, Size, RotationSpeed
public Asteroid[] Asteroids; // Distance, Phase, Size, RotationSpeed
// [JsonProperty("radius")] [Key(5)]
// public float GravityRadius;
@ -106,6 +106,15 @@ public class PlanetData : DatabaseEntry, INamedEntry
}
}
[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class Asteroid
{
public float Distance;
public float Phase;
public float Size;
public float RotationSpeed;
}
[RethinkTable("Galaxy"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class OrbitData : DatabaseEntry
{

View file

@ -104,11 +104,15 @@ public class ZoneGenerator
{
planetData.Asteroids =
Enumerable.Range(0, (int) (pow(planetData.Mass, context.GlobalData.BeltMassExponent) / context.GlobalData.BeltMassRatio * orbitMap[planet].Distance))
.Select(_ => float4(context.Random.NextFloat(orbitMap[planet].Distance * .5f, orbitMap[planet].Distance * 1.5f),
context.Random.NextFloat(),
pow(context.Random.NextFloat(), context.GlobalData.AsteroidSizeExponent) * (context.GlobalData.AsteroidSizeMax - context.GlobalData.AsteroidSizeMin) + context.GlobalData.AsteroidSizeMin,
context.Random.NextFloat() * context.GlobalData.AsteroidRotationSpeed))
.ToArray();
.Select(_ => new Asteroid
{
Distance = context.Random.NextFloat(orbitMap[planet].Distance * .5f, orbitMap[planet].Distance * 1.5f),
Phase = context.Random.NextFloat(),
Size = pow(context.Random.NextFloat(), context.GlobalData.AsteroidSizeExponent) *
(context.GlobalData.AsteroidSizeMax - context.GlobalData.AsteroidSizeMin) +
context.GlobalData.AsteroidSizeMin,
RotationSpeed = context.Random.NextFloat() * context.GlobalData.AsteroidRotationSpeed
}).ToArray();
}
return planetData;
}).ToArray();

View file

@ -371,7 +371,7 @@ public class StrategyGameManager : MonoBehaviour
foreach (var belt in _zoneBelts)
{
belt.Value.Transform.position = float3(_context.GetOrbitPosition(belt.Key) * ZoneSizeScale, .15f);
//belt.Value.Transform.position = float3(_context.GetOrbitPosition(belt.Key) * ZoneSizeScale, .15f);
belt.Value.Update();
}
@ -543,15 +543,31 @@ public class StrategyGameManager : MonoBehaviour
ContextMenu.Clear();
if (targetObject is PlanetData planet)
{
ContextMenu.AddOption("Test Option 1", () => Debug.Log("Test Option 1 Selected"));
ContextMenu.AddOption("Test Option 2", () => Debug.Log("Test Option 2 Selected"));
ContextMenu.AddDropdown("Test Dropdown", new []
if (planet.Belt)
{
("Dropdown Option 1", (Action) (() => Debug.Log("Dropdown Option 1 Selected"))),
("Dropdown Option 2", (Action) (() => Debug.Log("Dropdown Option 2 Selected"))),
("Dropdown Option 3", (Action) (() => Debug.Log("Dropdown Option 3 Selected")))
});
ContextMenu.AddOption("Test Option 3", () => Debug.Log("Test Option 3 Selected"));
ContextMenu.AddOption("Create Mining Task", () =>
{
var task = new Mining
{
Asteroids = clickTarget,
Context = _context,
Priority = 0,
Reserved = false,
Zone = _populatedZone
};
_cache.Add(task);
_cache.Get<Corporation>(_playerCorporation).Tasks.Add(task.ID);
});
}
// ContextMenu.AddOption("Test Option 1", () => Debug.Log("Test Option 1 Selected"));
// ContextMenu.AddOption("Test Option 2", () => Debug.Log("Test Option 2 Selected"));
// ContextMenu.AddDropdown("Test Dropdown", new []
// {
// ("Dropdown Option 1", (Action) (() => Debug.Log("Dropdown Option 1 Selected"))),
// ("Dropdown Option 2", (Action) (() => Debug.Log("Dropdown Option 2 Selected"))),
// ("Dropdown Option 3", (Action) (() => Debug.Log("Dropdown Option 3 Selected")))
// });
// ContextMenu.AddOption("Test Option 3", () => Debug.Log("Test Option 3 Selected"));
}
else if (targetObject is Ship ship)
{
@ -617,7 +633,7 @@ public class StrategyGameManager : MonoBehaviour
hullData.HullType == HullType.Station ? "Colony" :
"Weapons Platform");
PropertiesPanel.AddProperty("Hull", () => $"{hullData.Name}");
PropertiesPanel.AddProperty("Capacity", () => $"{entity.OccupiedCapacity}/{_context.Evaluate(hullData.Capacity, hull, entity)}");
PropertiesPanel.AddProperty("Capacity", () => $"{entity.OccupiedCapacity}/{entity.Capacity}");
PropertiesPanel.AddProperty("Mass", () => $"{entity.Mass}");
PropertiesPanel.AddProperty("Temperature", () => $"{entity.Temperature:0}°K");
PropertiesPanel.AddProperty("Energy", () => $"{entity.Energy:0}/{entity.GetBehaviors<Reactor>().First().Capacitance:0}");
@ -986,9 +1002,11 @@ public class AsteroidBelt
private Vector2[] _uvs;
private int[] _indices;
private Guid _data;
private Guid _orbit;
private GameContext _context;
private Mesh _mesh;
private float _zoneScale;
private float _size;
public AsteroidBelt(GameContext context, MeshFilter meshFilter, MeshCollider collider, Guid data, int spritesheetWidth, int spritesheetHeight, float zoneScale)
{
@ -999,6 +1017,8 @@ public class AsteroidBelt
_collider = collider;
_zoneScale = zoneScale;
var planetData = context.Cache.Get<PlanetData>(data);
var orbitData = context.Cache.Get<OrbitData>(planetData.Orbit);
_orbit = orbitData.Parent;
_vertices = new Vector3[planetData.Asteroids.Length*4];
_normals = new Vector3[planetData.Asteroids.Length*4];
_uvs = new Vector2[planetData.Asteroids.Length*4];
@ -1009,8 +1029,8 @@ public class AsteroidBelt
// vertex order: bottom left, top left, top right, bottom right
for (var i = 0; i < planetData.Asteroids.Length; i++)
{
if (planetData.Asteroids[i].x > maxDist)
maxDist = planetData.Asteroids[i].x;
if (planetData.Asteroids[i].Distance > maxDist)
maxDist = planetData.Asteroids[i].Distance;
var spriteX = Random.Range(0, spritesheetWidth);
var spriteY = Random.Range(0, spritesheetHeight);
@ -1038,6 +1058,7 @@ public class AsteroidBelt
_mesh.triangles = _indices;
_mesh.normals = _normals;
_mesh.bounds = new Bounds(Vector3.zero, Vector3.one * maxDist);
_size = maxDist;
_filter.mesh = _mesh;
//_collider.sharedMesh = _mesh;
@ -1051,12 +1072,13 @@ public class AsteroidBelt
{
var rotation = Quaternion.Euler(0, 0, asteroidTransforms[i].z);
var position = (Vector3) (Vector2) asteroidTransforms[i].xy * _zoneScale;
_vertices[i * 4] = rotation * new Vector3(-planetData.Asteroids[i].z,-planetData.Asteroids[i].z,0) + position;
_vertices[i * 4 + 1] = rotation * new Vector3(-planetData.Asteroids[i].z,planetData.Asteroids[i].z,0) + position;
_vertices[i * 4 + 2] = rotation * new Vector3(planetData.Asteroids[i].z,planetData.Asteroids[i].z,0) + position;
_vertices[i * 4 + 3] = rotation * new Vector3(planetData.Asteroids[i].z,-planetData.Asteroids[i].z,0) + position;
_vertices[i * 4] = rotation * new Vector3(-asteroidTransforms[i].w * _zoneScale,-asteroidTransforms[i].w * _zoneScale,0) + position;
_vertices[i * 4 + 1] = rotation * new Vector3(-asteroidTransforms[i].w * _zoneScale,asteroidTransforms[i].w * _zoneScale,0) + position;
_vertices[i * 4 + 2] = rotation * new Vector3(asteroidTransforms[i].w * _zoneScale,asteroidTransforms[i].w * _zoneScale,0) + position;
_vertices[i * 4 + 3] = rotation * new Vector3(asteroidTransforms[i].w * _zoneScale,-asteroidTransforms[i].w * _zoneScale,0) + position;
}
_mesh.bounds = new Bounds((Vector2) _context.GetOrbitPosition(_orbit) * _zoneScale, Vector3.one * (_size * _zoneScale * 2));
_mesh.vertices = _vertices;
_collider.sharedMesh = _mesh;
}

View file

@ -64,6 +64,7 @@
<Compile Include="Assets\Scripts\ServerShared\Agents\AgentBehavior.cs" />
<Compile Include="Assets\Scripts\ServerShared\Agents\AgentTask.cs" />
<Compile Include="Assets\Scripts\ServerShared\Agents\Locomotion.cs" />
<Compile Include="Assets\Scripts\ServerShared\Agents\Mining.cs" />
<Compile Include="Assets\Scripts\ServerShared\Agents\StationTowing.cs" />
<Compile Include="Assets\Scripts\ServerShared\Agents\VelocityMatch.cs" />
<Compile Include="Assets\Scripts\ServerShared\Attributes.cs" />
@ -77,6 +78,8 @@
<Compile Include="Assets\Scripts\ServerShared\Behaviors\Hitscan.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\ItemUsage.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\Launcher.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\MiningController.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\MiningTool.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\PatrolController.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\ProjectileWeapon.cs" />
<Compile Include="Assets\Scripts\ServerShared\Behaviors\Radiance.cs" />