Sensor Ping
Added ping feature to sensors, pulsing a wave of revealing light into the level Added IEventBehavior interface, used by sensors and weapons, for behaviors containing event subscriptions which need to be reset when EntityInstance is disposed Implemented sensor impact for locked weapons (lock speed varies with sensor acquisition) Added ping cooldown bar to HUD Added spline curve implementations to AetheriaMath, applied better mapping to wormhole transition animation Tweaked loadout generator to prefer larger items to a controllable degree (e.g. very important for cargo bays, less for shop inventory), shop inventory bans non-ship hulls and manages internal space more effectively
This commit is contained in:
parent
fd81bf267e
commit
645fcf4b09
62 changed files with 115821 additions and 79 deletions
|
|
@ -112,4 +112,81 @@ public static class AetheriaMath
|
|||
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
//Returns a position between 4 float3s with Catmull-Rom spline algorithm
|
||||
//http://www.iquilezles.org/www/articles/minispline/minispline.htm
|
||||
public static float GetCatmullRomPosition(float p0, float p1, float p2, float p3, float t)
|
||||
{
|
||||
//The coefficients of the cubic polynomial (except the 0.5f * which I added later for performance)
|
||||
var a = 2f * p1;
|
||||
var b = p2 - p0;
|
||||
var c = 2f * p0 - 5f * p1 + 4f * p2 - p3;
|
||||
var d = -p0 + 3f * p1 - 3f * p2 + p3;
|
||||
|
||||
//The cubic polynomial: a + b * t + c * t^2 + d * t^3
|
||||
var pos = 0.5f * (a + (b * t) + (c * t * t) + (d * t * t * t));
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static float3 GetCatmullRomPosition(float3 p0, float3 p1, float3 p2, float3 p3, float t)
|
||||
{
|
||||
//The coefficients of the cubic polynomial (except the 0.5f * which I added later for performance)
|
||||
var a = 2f * p1;
|
||||
var b = p2 - p0;
|
||||
var c = 2f * p0 - 5f * p1 + 4f * p2 - p3;
|
||||
var d = -p0 + 3f * p1 - 3f * p2 + p3;
|
||||
|
||||
//The cubic polynomial: a + b * t + c * t^2 + d * t^3
|
||||
var pos = 0.5f * (a + (b * t) + (c * t * t) + (d * t * t * t));
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// https://catlikecoding.com/unity/tutorials/curves-and-splines/
|
||||
public static float GetQuadraticSplinePosition(float p0, float p1, float p2, float t)
|
||||
{
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * p0 +
|
||||
2f * oneMinusT * t * p1 +
|
||||
t * t * p2;
|
||||
}
|
||||
|
||||
public static float3 GetQuadraticSplinePosition(float3 p0, float3 p1, float3 p2, float t)
|
||||
{
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * p0 +
|
||||
2f * oneMinusT * t * p1 +
|
||||
t * t * p2;
|
||||
}
|
||||
|
||||
public static float3 GetCubicSplinePosition (float p0, float p1, float p2, float p3, float t) {
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * oneMinusT * p0 +
|
||||
3f * oneMinusT * oneMinusT * t * p1 +
|
||||
3f * oneMinusT * t * t * p2 +
|
||||
t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float3 GetCubicSplinePosition (float3 p0, float3 p1, float3 p2, float3 p3, float t) {
|
||||
t = saturate(t);
|
||||
var oneMinusT = 1f - t;
|
||||
return
|
||||
oneMinusT * oneMinusT * oneMinusT * p0 +
|
||||
3f * oneMinusT * oneMinusT * t * p1 +
|
||||
3f * oneMinusT * t * t * p2 +
|
||||
t * t * t * p3;
|
||||
}
|
||||
|
||||
public static float Smoothstep(float x)
|
||||
{
|
||||
x = saturate(x);
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ public interface IDisposableBehavior
|
|||
void Dispose();
|
||||
}
|
||||
|
||||
public interface IEventBehavior
|
||||
{
|
||||
void ResetEvents();
|
||||
}
|
||||
|
||||
public interface IInitializableBehavior
|
||||
{
|
||||
void Initialize();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class ChargedWeaponData : InstantWeaponData
|
|||
}
|
||||
}
|
||||
|
||||
public class ChargedWeapon : InstantWeapon
|
||||
public class ChargedWeapon : InstantWeapon, IEventBehavior
|
||||
{
|
||||
private ChargedWeaponData _data;
|
||||
private bool _charging;
|
||||
|
|
@ -79,6 +79,7 @@ public class ChargedWeapon : InstantWeapon
|
|||
|
||||
public override void ResetEvents()
|
||||
{
|
||||
base.ResetEvents();
|
||||
OnStartCharging = null;
|
||||
OnStopCharging = null;
|
||||
OnCharged = null;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public class ConstantWeaponData : WeaponData
|
|||
}
|
||||
}
|
||||
|
||||
public class ConstantWeapon : Weapon, IProgressBehavior
|
||||
public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
|
||||
{
|
||||
private ConstantWeaponData _data;
|
||||
private int _ammo = 1;
|
||||
|
|
@ -49,7 +49,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior
|
|||
public event Action OnStartFiring;
|
||||
public event Action OnStopFiring;
|
||||
|
||||
public override void ResetEvents()
|
||||
public void ResetEvents()
|
||||
{
|
||||
OnReloadBegin = null;
|
||||
OnReloadComplete = null;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class InstantWeaponData : WeaponData
|
|||
}
|
||||
}
|
||||
|
||||
public class InstantWeapon : Weapon, IProgressBehavior
|
||||
public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
|
||||
{
|
||||
private InstantWeaponData _data;
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ public class InstantWeapon : Weapon, IProgressBehavior
|
|||
public event Action OnCooldownComplete;
|
||||
public event Action OnFire;
|
||||
|
||||
public override void ResetEvents()
|
||||
public virtual void ResetEvents()
|
||||
{
|
||||
OnReloadBegin = null;
|
||||
OnReloadComplete = null;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ public class LockWeapon : InstantWeapon
|
|||
if (degrees < LockAngle)
|
||||
{
|
||||
var lerp = 1 - unlerp(0, 90, degrees);
|
||||
_lock = saturate(_lock + pow(lerp, DirectionImpact) * delta * LockSpeed);
|
||||
_lock = saturate(_lock + pow(lerp, DirectionImpact) * delta * LockSpeed * pow(Entity.EntityInfoGathered[Entity.Target.Value], SensorImpact));
|
||||
}
|
||||
else _lock = saturate(_lock - delta * Decay);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MessagePack;
|
||||
using Newtonsoft.Json;
|
||||
using Unity.Mathematics;
|
||||
|
|
@ -10,11 +12,32 @@ using static Unity.Mathematics.math;
|
|||
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
|
||||
public class SensorData : BehaviorData
|
||||
{
|
||||
[InspectableField, JsonProperty("sensitivity"), Key(3), RuntimeInspectable]
|
||||
[InspectableField, JsonProperty("sensitivity"), Key(3), RuntimeInspectable]
|
||||
public PerformanceStat Sensitivity = new PerformanceStat();
|
||||
|
||||
[InspectableAnimationCurve, JsonProperty("sensitivityCurve"), Key(4), RuntimeInspectable]
|
||||
[InspectableAnimationCurve, JsonProperty("sensitivityCurve"), Key(4), RuntimeInspectable]
|
||||
public float4[] SensitivityCurve;
|
||||
|
||||
[InspectableField, JsonProperty("pingBoost"), Key(5), RuntimeInspectable]
|
||||
public PerformanceStat PingBoost;
|
||||
|
||||
[InspectableField, JsonProperty("pingEnergy"), Key(6), RuntimeInspectable]
|
||||
public PerformanceStat PingEnergy;
|
||||
|
||||
[InspectableField, JsonProperty("pingVisibility"), Key(7), RuntimeInspectable]
|
||||
public PerformanceStat PingVisibility;
|
||||
|
||||
[InspectableField, JsonProperty("pingRange"), Key(8), RuntimeInspectable]
|
||||
public PerformanceStat PingRange;
|
||||
|
||||
[InspectableField, JsonProperty("pingCooldown"), Key(9), RuntimeInspectable]
|
||||
public PerformanceStat PingCooldown;
|
||||
|
||||
[InspectableField, JsonProperty("pingDuration"), Key(10)]
|
||||
public float PingDuration = 2;
|
||||
|
||||
[InspectableField, JsonProperty("pingRadiusExponent"), Key(11)]
|
||||
public float PingRadiusExponent = .5f;
|
||||
|
||||
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
|
||||
{
|
||||
|
|
@ -22,15 +45,55 @@ public class SensorData : BehaviorData
|
|||
}
|
||||
}
|
||||
|
||||
public class Sensor : IBehavior
|
||||
public class Sensor : IBehavior, IEventBehavior
|
||||
{
|
||||
private SensorData _data;
|
||||
private float _pingCooldown;
|
||||
private float _pingLerp;
|
||||
private bool _pinging;
|
||||
private float _pingRadius;
|
||||
private HashSet<Entity> _pingedEntities = new HashSet<Entity>();
|
||||
|
||||
private Entity Entity { get; }
|
||||
private EquippedItem Item { get; }
|
||||
private ItemManager Context { get; }
|
||||
|
||||
public BehaviorData Data => _data;
|
||||
|
||||
public float Cooldown
|
||||
{
|
||||
get => saturate(_pingCooldown);
|
||||
}
|
||||
|
||||
public float PingRadius
|
||||
{
|
||||
get => _pingRadius;
|
||||
}
|
||||
|
||||
public float PingBrightness => pow(1 - _pingLerp, _data.PingRadiusExponent);
|
||||
|
||||
public event Action OnPingStart;
|
||||
public event Action OnPingEnd;
|
||||
|
||||
public void ResetEvents()
|
||||
{
|
||||
OnPingStart = null;
|
||||
OnPingEnd = null;
|
||||
}
|
||||
|
||||
public void Ping()
|
||||
{
|
||||
if(_pingCooldown < 0 && Item.Entity.TryConsumeEnergy(Item.Evaluate(_data.PingEnergy)))
|
||||
{
|
||||
Item.Entity.VisibilitySources[this] = Item.Evaluate(_data.PingVisibility);
|
||||
_pinging = true;
|
||||
_pingCooldown = 1;
|
||||
_pingLerp = 0;
|
||||
_pingRadius = 0;
|
||||
_pingedEntities.Clear();
|
||||
OnPingStart?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public Sensor(ItemManager context, SensorData data, Entity entity, EquippedItem item)
|
||||
{
|
||||
|
|
@ -42,6 +105,19 @@ public class Sensor : IBehavior
|
|||
|
||||
public bool Execute(float delta)
|
||||
{
|
||||
if (_pinging)
|
||||
{
|
||||
_pingLerp += delta / _data.PingDuration;
|
||||
_pingRadius = lerp(0, Item.Evaluate(_data.PingRange), pow(_pingLerp, _data.PingRadiusExponent));
|
||||
if (_pingLerp > 1)
|
||||
{
|
||||
_pinging = false;
|
||||
OnPingEnd?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
_pingCooldown -= delta / Item.Evaluate(_data.PingCooldown);
|
||||
|
||||
// TODO: Handle Active Detection / Visibility From Reflected Radiance
|
||||
var hardpoint = Entity.Hardpoints[Item.Position.x, Item.Position.y];
|
||||
var forward = hardpoint != null && Entity.HardpointTransforms.ContainsKey(hardpoint) ?
|
||||
|
|
@ -54,35 +130,32 @@ public class Sensor : IBehavior
|
|||
var diff = entity.Position.xz - Entity.Position.xz;
|
||||
var angle = acos(dot(forward, normalize(diff)));
|
||||
var dist = length(diff);
|
||||
float previous;
|
||||
float previous, next;
|
||||
Entity.EntityInfoGathered.TryGetValue(entity, out previous);
|
||||
var next = saturate(
|
||||
previous +
|
||||
entity.Visibility *
|
||||
Item.Evaluate(_data.Sensitivity) *
|
||||
_data.SensitivityCurve.Evaluate(angle / PI) *
|
||||
delta / dist);
|
||||
if (!_pingedEntities.Contains(entity) && dist < _pingRadius)
|
||||
{
|
||||
_pingedEntities.Add(entity);
|
||||
next = saturate(
|
||||
previous +
|
||||
entity.Visibility *
|
||||
Item.Evaluate(_data.Sensitivity) *
|
||||
Item.Evaluate(_data.PingBoost) *
|
||||
dist);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = saturate(
|
||||
previous +
|
||||
entity.Visibility *
|
||||
Item.Evaluate(_data.Sensitivity) *
|
||||
_data.SensitivityCurve.Evaluate(angle / PI) *
|
||||
delta / dist);
|
||||
}
|
||||
next *= 1 - Context.GameplaySettings.TargetInfoDecay * delta;
|
||||
//Context.Log($"{entity.Name} visibility {(int)(previous * 100)}% -> {(int)(next * 100)}%");
|
||||
Entity.EntityInfoGathered[entity] = next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
// var ship = Hardpoint.Ship.Ship.transform;
|
||||
// var contacts =
|
||||
// Physics.OverlapSphere(ship.position, _data.Range.Evaluate(Hardpoint)).Where(c=>c.attachedRigidbody?.GetComponent<Targetable>()!=null).Select(c=>c.attachedRigidbody.GetComponent<Targetable>());
|
||||
// foreach (var contact in contacts)
|
||||
// {
|
||||
// var diff = (contact.transform.position - ship.position).Flatland();
|
||||
// var angle = acos(dot(ship.forward.Flatland().normalized,
|
||||
// diff.normalized)) / (float)PI;
|
||||
// var sens = _data.Sensitivity.Evaluate(Hardpoint) *
|
||||
// Hardpoint.Ship.HullData.VisibilityCurve.Evaluate(saturate(angle));
|
||||
// var vis = contact.Visibility / diff.sqrMagnitude;
|
||||
// if(vis > 1/sens)
|
||||
// Hardpoint.Ship.Contacts[contact] = Time.time;
|
||||
// }
|
||||
//
|
||||
// Hardpoint.Ship.VisibilitySources[this] = _data.Radiance.Evaluate(Hardpoint) / _data.RadianceMasking.Evaluate(Hardpoint);
|
||||
}
|
||||
}
|
||||
|
|
@ -109,8 +109,6 @@ public abstract class Weapon : IActivatedBehavior
|
|||
_itemData = context.GetData(item.EquippableItem);
|
||||
}
|
||||
|
||||
public virtual void ResetEvents(){}
|
||||
|
||||
protected virtual void UpdateStats()
|
||||
{
|
||||
Damage = Item.Evaluate(_data.Damage);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ public abstract class Entity
|
|||
|
||||
public Shield Shield { get; private set; }
|
||||
public Cockpit Cockpit { get; private set; }
|
||||
public Sensor Sensor { get; private set; }
|
||||
public float Heatstroke { get; private set; }
|
||||
|
||||
public float TargetRange { get; private set; }
|
||||
|
|
@ -125,6 +126,7 @@ public abstract class Entity
|
|||
|
||||
public virtual void Activate()
|
||||
{
|
||||
//ItemManager.Log($"Entity {Name} is activating!");
|
||||
_active = true;
|
||||
Heatstroke = 0;
|
||||
foreach (var item in Equipment)
|
||||
|
|
@ -134,6 +136,7 @@ public abstract class Entity
|
|||
initializableBehavior.Initialize();
|
||||
}
|
||||
//foreach(var entity in Zone.Entities) EntityInfoGathered.Add(entity, 0);
|
||||
_subscriptions.Add(Zone.Entities.ObserveAdd().Subscribe(add => EntityInfoGathered.Add(add.Value, 0)));
|
||||
_subscriptions.Add(Zone.Entities.ObserveRemove().Subscribe(remove =>
|
||||
{
|
||||
if (Target.Value == remove.Value) Target.Value = null;
|
||||
|
|
@ -150,6 +153,7 @@ public abstract class Entity
|
|||
|
||||
public virtual void Deactivate()
|
||||
{
|
||||
//ItemManager.Log($"Entity {Name} is deactivating!");
|
||||
foreach(var s in _subscriptions) s.Dispose();
|
||||
_subscriptions.Clear();
|
||||
_active = false;
|
||||
|
|
@ -379,6 +383,8 @@ public abstract class Entity
|
|||
Shield = null;
|
||||
if (b is Cockpit)
|
||||
Cockpit = null;
|
||||
if (b is Sensor)
|
||||
Sensor = null;
|
||||
}
|
||||
|
||||
return item.EquippableItem;
|
||||
|
|
@ -559,6 +565,8 @@ public abstract class Entity
|
|||
Shield = shield;
|
||||
if (b is Cockpit cockpit)
|
||||
Cockpit = cockpit;
|
||||
if (b is Sensor sensor)
|
||||
Sensor = sensor;
|
||||
}
|
||||
|
||||
// equippedItem.OnOnline += () => ItemOnline.OnNext(equippedItem);
|
||||
|
|
@ -585,7 +593,7 @@ public abstract class Entity
|
|||
bay.DockedShip = ship;
|
||||
ship.SetParent(this);
|
||||
Zone.Entities.Remove(ship);
|
||||
Deactivate();
|
||||
ship.Deactivate();
|
||||
ship.Docked.OnNext(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public class LoadoutGenerator
|
|||
|
||||
var emptyShape = entity.UnoccupiedSpace;
|
||||
|
||||
var dockingBayData = RandomItem<DockingBayData>(item => item.Shape.FitsWithin(emptyShape, out _, out _));
|
||||
var dockingBayData = RandomItem<DockingBayData>(2, item => item.Shape.FitsWithin(emptyShape, out _, out _));
|
||||
if (dockingBayData == null) throw new InvalidLoadoutException("No compatible docking bay found for station!");
|
||||
|
||||
dockingBayData.Shape.FitsWithin(emptyShape, out var cargoRotation, out var cargoPosition);
|
||||
|
|
@ -70,7 +70,9 @@ public class LoadoutGenerator
|
|||
}
|
||||
|
||||
var cargo = entity.CargoBays.First();
|
||||
var inventory = RandomItems<EquippableItemData>(16, data => !(data is CargoBayData));
|
||||
var inventory = RandomItems<EquippableItemData>(16, 1,
|
||||
data => !(data is HullData hull && hull.HullType != HullType.Ship) && !(data is CargoBayData))
|
||||
.OrderByDescending(item=>item.Shape.Coordinates.Length);
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
var instance = ItemManager.CreateInstance(item);
|
||||
|
|
@ -93,7 +95,7 @@ public class LoadoutGenerator
|
|||
).FirstOrDefault();
|
||||
}
|
||||
|
||||
public T[] RandomItems<T>(int count, Predicate<T> filter = null) where T : EquippableItemData
|
||||
public T[] RandomItems<T>(int count, float sizeExponent, Predicate<T> filter = null) where T : EquippableItemData
|
||||
{
|
||||
return ItemManager.ItemData.GetAll<T>()
|
||||
.Where(item => Sector.ContainsFaction(item.Manufacturer) &&
|
||||
|
|
@ -101,21 +103,21 @@ public class LoadoutGenerator
|
|||
(filter?.Invoke(item) ?? true))
|
||||
.WeightedRandomElements(ref Random, item =>
|
||||
(Faction == null || item.Manufacturer == Faction.ID ? 1 : Faction.Allegiance[item.Manufacturer]) * // Prioritize items from allied manufacturers
|
||||
item.Shape.Coordinates.Length * item.Shape.Coordinates.Length / // Prioritize larger items
|
||||
pow(item.Shape.Coordinates.Length, sizeExponent) / // Prioritize larger items
|
||||
Zone.Distance[Sector.HomeZones[ItemManager.ItemData.Get<Faction>(item.Manufacturer)]] / // Penalize distance to manufacturer headquarters
|
||||
pow(item.Price, PriceExponent), // Penalize item price to a controllable degree
|
||||
count
|
||||
);
|
||||
}
|
||||
|
||||
public T RandomItem<T>(Predicate<T> filter = null) where T : EquippableItemData
|
||||
public T RandomItem<T>(float sizeExponent, Predicate<T> filter = null) where T : EquippableItemData
|
||||
{
|
||||
return RandomItems(1, filter).FirstOrDefault();
|
||||
return RandomItems(1, sizeExponent, filter).FirstOrDefault();
|
||||
}
|
||||
|
||||
public T RandomItem<T>(HardpointData hardpoint, Predicate<T> filter = null) where T : EquippableItemData
|
||||
public T RandomItem<T>(HardpointData hardpoint, float sizeExponent, Predicate<T> filter = null) where T : EquippableItemData
|
||||
{
|
||||
return RandomItem<T>(item => item.HardpointType == hardpoint.Type &&
|
||||
return RandomItem<T>(sizeExponent, item => item.HardpointType == hardpoint.Type &&
|
||||
(filter?.Invoke(item) ?? true) &&
|
||||
item.Shape.FitsWithin(hardpoint.Shape, hardpoint.Rotation, out _));
|
||||
}
|
||||
|
|
@ -129,7 +131,7 @@ public class LoadoutGenerator
|
|||
{
|
||||
if (hardpoint.Type == HardpointType.ControlModule)
|
||||
{
|
||||
var controllerData = RandomItem<GearData>(hardpoint,
|
||||
var controllerData = RandomItem<GearData>(hardpoint, 2,
|
||||
item => item.Behaviors.Any(b => entity is Ship && b is CockpitData || entity is OrbitalEntity && b is TurretControllerData));
|
||||
if (controllerData == null) throw new InvalidLoadoutException("No compatible controller found for entity!");
|
||||
var controller = ItemManager.CreateInstance(controllerData) as EquippableItem;
|
||||
|
|
@ -143,7 +145,7 @@ public class LoadoutGenerator
|
|||
// If a previously selected item fits, use that one (this is why we must process larger hardpoints first)
|
||||
var itemData = previousItems
|
||||
.FirstOrDefault(i => i.HardpointType == hardpoint.Type && i.Shape.FitsWithin(hardpoint.Shape, hardpoint.Rotation, out _));
|
||||
itemData ??= RandomItem<GearData>(hardpoint);
|
||||
itemData ??= RandomItem<GearData>(hardpoint, 2);
|
||||
if (itemData == null) ItemManager.Log($"No compatible item found for entity {Enum.GetName(typeof(HardpointType), hardpoint.Type)} hardpoint!");
|
||||
else
|
||||
{
|
||||
|
|
@ -160,7 +162,7 @@ public class LoadoutGenerator
|
|||
|
||||
var emptyShape = entity.UnoccupiedSpace;
|
||||
|
||||
var cargoData = RandomItem<CargoBayData>(item =>
|
||||
var cargoData = RandomItem<CargoBayData>(3, item =>
|
||||
!(item is DockingBayData) &&
|
||||
item.Shape.FitsWithin(emptyShape, out _, out _));
|
||||
if (cargoData == null) throw new InvalidLoadoutException("No compatible cargo bay found for entity!");
|
||||
|
|
@ -173,7 +175,7 @@ public class LoadoutGenerator
|
|||
|
||||
emptyShape = entity.UnoccupiedSpace;
|
||||
|
||||
var capacitorData = RandomItem<GearData>(item =>
|
||||
var capacitorData = RandomItem<GearData>(2, item =>
|
||||
item.Behaviors.Any(b => b is CapacitorData) &&
|
||||
item.Shape.FitsWithin(emptyShape, out _, out _));
|
||||
if (capacitorData == null) throw new InvalidLoadoutException("No compatible capacitor found for entity!");
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ public class Ship : Entity
|
|||
{
|
||||
var exitLerp = (_wormholeAnimationProgress - ItemManager.GameplaySettings.WormholeExitCurveStart) /
|
||||
(1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
|
||||
exitLerp *= exitLerp; // Square the interpolation variable to produce curve with zero slope at start
|
||||
exitLerp = AetheriaMath.Smoothstep(exitLerp); // Square the interpolation variable to produce curve with zero slope at start
|
||||
Position.xz = _wormholePosition + normalize(_wormholeExitVelocity) * exitLerp * ItemManager.GameplaySettings.WormholeExitRadius;
|
||||
Rotation = quaternion.LookRotation(
|
||||
lerp(float3(0, 1, 0), forward, exitLerp),
|
||||
|
|
@ -326,7 +326,7 @@ public class Ship : Entity
|
|||
if (_wormholeAnimationProgress < 1 - ItemManager.GameplaySettings.WormholeExitCurveStart)
|
||||
{
|
||||
var enterLerp = _wormholeAnimationProgress / (1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
|
||||
enterLerp *= enterLerp; // Square the interpolation variable to produce curve with zero slope at vertical
|
||||
enterLerp = AetheriaMath.Smoothstep(enterLerp); // Square the interpolation variable to produce curve with zero slope at vertical
|
||||
Position.xz = lerp(_wormholeEntryPosition, _wormholePosition, enterLerp);
|
||||
Rotation = quaternion.LookRotation(
|
||||
lerp(forward, float3(0, -1, 0), enterLerp),
|
||||
|
|
|
|||
Loading…
Reference in a new issue