Sync daemon authority migration

This commit is contained in:
Meta Vens 2026-06-21 09:37:54 +01:00
commit 39a0dc8737
295 changed files with 25121 additions and 7360 deletions

View file

@ -2,15 +2,16 @@
* 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 Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
using cfloat2 = CultMath.float2;
using cfloat3 = CultMath.float3;
public class AetherDrive : Behavior
{
private readonly float3 _rotorDiameter;
private readonly float3 _rotorMass;
private readonly cfloat3 _rotorDiameter;
private readonly cfloat3 _rotorMass;
private readonly PerformanceStat _maximumRpm;
private readonly float3 _couplingLambda;
private readonly cfloat3 _couplingLambda;
private readonly PerformanceStat _lambdaMultiplier;
private readonly PerformanceStat _couplingEfficiency;
private readonly PerformanceStat _torque;
@ -19,15 +20,15 @@ public class AetherDrive : Behavior
private readonly PerformanceStat _passiveCoupling;
private readonly uint _rpmAudioParameter;
private readonly uint _torqueRatioAudioParameter;
private float3 _axis;
private cfloat3 _axis;
public float3 Thrust { get; private set; }
public float3 Rpm { get; private set; }
public cfloat3 Thrust { get; private set; }
public cfloat3 Rpm { get; private set; }
public float MaximumRpm { get; private set; }
public float2 ThrustDirection { get; private set; }
public cfloat2 ThrustDirection { get; private set; }
public string Particles { get; }
public float3 Axis
public cfloat3 Axis
{
get => _axis;
set => _axis = clamp(value, -1, 1);
@ -83,16 +84,17 @@ public class AetherDrive : Behavior
{
var rotorSpeed = Rpm * _rotorDiameter / 100;
var forward = normalize(Entity.Direction);
var right = forward.Rotate(ItemRotation.Clockwise);
var forward = normalize(Entity.CultDirection);
var right = AetheriaMath.Rotate(Entity.CultDirection, ItemRotation.Clockwise);
var velocity = Entity.CultVelocity;
var speed = float2(dot(Entity.Velocity, forward), dot(Entity.Velocity, right));
var speed = float2(dot(velocity, forward), dot(velocity, right));
var couplingEfficiency = Evaluate(_couplingEfficiency);
var efficiency = float3(saturate(1 - speed / max(rotorSpeed.xy, 1) * sign(_axis.xy)) * couplingEfficiency, 1);
Thrust = (Rpm - AetheriaMath.Decay(Rpm, _couplingLambda, dt)) * _rotorMass * efficiency;
var couplingLambda = _couplingLambda * Item.Evaluate(_lambdaMultiplier) * max(abs(_axis), Evaluate(_passiveCoupling));
var couplingLambda = _couplingLambda * Evaluate(_lambdaMultiplier) * max(abs(_axis), Evaluate(_passiveCoupling));
var previousRpm = Rpm;
Rpm = AetheriaMath.Decay(Rpm, couplingLambda, dt);
var rpmLoss = previousRpm - Rpm;
@ -102,13 +104,14 @@ public class AetherDrive : Behavior
AddHeat((heat.x + heat.y + heat.z)*ItemManager.GameplaySettings.AetherHeatMultiplier);
ThrustDirection = forward * (_axis.x * force.x / Entity.Mass) + right * (_axis.y * force.y / Entity.Mass);
Entity.Velocity += ThrustDirection;
Entity.CultVelocity += ThrustDirection;
Entity.Direction = mul(Entity.Direction,
Unity.Mathematics.float2x2.Rotate(force.z * _axis.z * ItemManager.GameplaySettings.AetherTorqueMultiplier / Entity.Mass));
Entity.CultDirection = AetheriaMath.Rotate(
Entity.CultDirection,
force.z * _axis.z * ItemManager.GameplaySettings.AetherTorqueMultiplier / Entity.Mass);
if(float.IsNaN(Entity.Velocity.x))
ItemManager.Log("FUCK FUCK FUCK FUCK");
if(float.IsNaN(Entity.CultVelocity.x))
ItemManager.Log("AetherDrive produced NaN velocity.");
MaximumRpm = Evaluate(_maximumRpm);
var torqueProfile = float3(
@ -136,11 +139,11 @@ public class AetherDrive : Behavior
}
public void RestoreRuntimeState(
float3 axis,
float3 thrust,
float3 rpm,
cfloat3 axis,
cfloat3 thrust,
cfloat3 rpm,
float maximumRpm,
float2 thrustDirection)
cfloat2 thrustDirection)
{
Axis = axis;
Thrust = thrust;

View file

@ -1,9 +1,3 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class AutoWeapon : InstantWeapon
{

View file

@ -7,9 +7,9 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using GameCult.Aetheria.State.Unity;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static Unity.Mathematics.noise;
using static CultMath.math;
using cfloat3 = CultMath.float3;
using cfloat4 = CultMath.float4;
public abstract class Behavior
{
@ -23,7 +23,7 @@ public abstract class Behavior
protected Entity Entity => Item?.Entity ?? Consumable.Entity;
public float Temperature => Item?.Temperature ?? Consumable.Entity.MaxTemp;
public float3 Direction
public cfloat3 Direction
{
get
{
@ -36,12 +36,13 @@ public abstract class Behavior
}
else
{
var itemDirection = Entity.Direction.Rotate(Item.EquippableItem.Rotation);
return float3(itemDirection.x, 0, itemDirection.y);
var itemDirection = AetheriaMath.Rotate(Entity.CultDirection, Item.EquippableItem.Rotation);
return new cfloat3(itemDirection.x, 0, itemDirection.y);
}
}
return float3(Entity.Direction.x, 0, Entity.Direction.y);
var entityDirection = Entity.CultDirection;
return new cfloat3(entityDirection.x, 0, entityDirection.y);
}
}
@ -65,6 +66,18 @@ public abstract class Behavior
public float Evaluate(PerformanceStat stat) => Item?.Evaluate(stat) ?? Consumable.Evaluate(stat);
public float Evaluate(PerformanceStat stat, StatConditionMask condition, float value) =>
Item?.Evaluate(stat, condition, value) ?? Consumable.Evaluate(stat, condition, value);
public float Evaluate(
PerformanceStat stat,
StatConditionMask firstCondition,
float firstValue,
StatConditionMask secondCondition,
float secondValue) =>
Item?.Evaluate(stat, firstCondition, firstValue, secondCondition, secondValue) ??
Consumable.Evaluate(stat, firstCondition, firstValue, secondCondition, secondValue);
public bool TryGetPerformanceStat(string statName, out PerformanceStat stat)
{
if (!string.IsNullOrWhiteSpace(statName) &&
@ -82,6 +95,7 @@ public abstract class Behavior
if (!string.IsNullOrWhiteSpace(statName) && stat != null)
{
_performanceStats[statName] = stat;
Item?.RegisterPerformanceStat(Kind, statName, stat);
}
}
@ -208,7 +222,7 @@ public sealed class RuntimeBehaviorDefinition
return _fields.TryGetValue(key, out var value) ? checked((uint)value.NumberValue) : fallback;
}
public float3 Float3(int key, float3 fallback = default)
public cfloat3 Float3(int key, cfloat3 fallback = default)
{
return _fields.TryGetValue(key, out var value) ? ToFloat3(value) : fallback;
}
@ -228,7 +242,9 @@ public sealed class RuntimeBehaviorDefinition
public PerformanceStat PerformanceStat(int key, PerformanceStat fallback)
{
return _fields.TryGetValue(key, out var value) ? ToPerformanceStat(value) : fallback;
return _fields.TryGetValue(key, out var value)
? AetheriaRuntimeBehaviorValueReader.ReadPerformanceStat(value)
: fallback;
}
public BezierCurve BezierCurve(int key, BezierCurve fallback)
@ -238,15 +254,12 @@ public sealed class RuntimeBehaviorDefinition
return fallback;
}
return new BezierCurve
{
Keys = value.Children.Count > 0
? value.Children[0].Children.Select(ToFloat4).ToArray()
: Array.Empty<float4>()
};
return global::BezierCurve.FromKeys(value.Children.Count > 0
? value.Children[0].Children.Select(ToBezierKey)
: Enumerable.Empty<(float, float, float, float)>());
}
public float4[] Float4Array(int key, float4[] fallback)
public cfloat4[] Float4Array(int key, cfloat4[] fallback)
{
return _fields.TryGetValue(key, out var value)
? value.Children.Select(ToFloat4).ToArray()
@ -260,49 +273,29 @@ public sealed class RuntimeBehaviorDefinition
return fallback;
}
return new StatReference
{
Target = ChildString(value, 1),
Stat = ChildString(value, 2)
};
return AetheriaRuntimeBehaviorValueReader.ReadStatReference(value);
}
public T Enum<T>(int key, T fallback) where T : struct
{
if (!_fields.TryGetValue(key, out var value))
{
return fallback;
}
if (!string.IsNullOrWhiteSpace(value.StringValue) &&
System.Enum.TryParse(value.StringValue, true, out T parsed))
{
return parsed;
}
return (T)System.Enum.ToObject(typeof(T), checked((int)value.NumberValue));
return _fields.TryGetValue(key, out var value)
? AetheriaRuntimeBehaviorValueReader.ReadEnum(value, fallback)
: fallback;
}
private static PerformanceStat ToPerformanceStat(AetheriaRuntimeBehaviorValue value)
private static cfloat4 ToFloat4(AetheriaRuntimeBehaviorValue value)
{
return new PerformanceStat
{
Min = ChildFloat(value, 0),
Max = ChildFloat(value, 1),
HeatExponentMultiplier = ChildFloat(value, 2),
DurabilityExponentMultiplier = ChildFloat(value, 3),
QualityExponent = ChildFloat(value, 4)
};
return new cfloat4(ChildFloat(value, 0), ChildFloat(value, 1), ChildFloat(value, 2), ChildFloat(value, 3));
}
private static float4 ToFloat4(AetheriaRuntimeBehaviorValue value)
private static (float, float, float, float) ToBezierKey(AetheriaRuntimeBehaviorValue value)
{
return new float4(ChildFloat(value, 0), ChildFloat(value, 1), ChildFloat(value, 2), ChildFloat(value, 3));
return (ChildFloat(value, 0), ChildFloat(value, 1), ChildFloat(value, 2), ChildFloat(value, 3));
}
private static float3 ToFloat3(AetheriaRuntimeBehaviorValue value)
private static cfloat3 ToFloat3(AetheriaRuntimeBehaviorValue value)
{
return new float3(ChildFloat(value, 0), ChildFloat(value, 1), ChildFloat(value, 2));
return new cfloat3(ChildFloat(value, 0), ChildFloat(value, 1), ChildFloat(value, 2));
}
private static float ChildFloat(AetheriaRuntimeBehaviorValue value, int index)
@ -314,4 +307,9 @@ public sealed class RuntimeBehaviorDefinition
{
return value.Children.Count > index ? value.Children[index].StringValue ?? "" : "";
}
private static AetheriaRuntimeBehaviorValue ChildValue(AetheriaRuntimeBehaviorValue value, int index)
{
return value != null && value.Children.Count > index ? value.Children[index] : null;
}
}

View file

@ -2,9 +2,7 @@
* 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.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class Capacitor : Behavior
{

View file

@ -1,8 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class ChargedWeapon : InstantWeapon
{
@ -30,9 +29,9 @@ public class ChargedWeapon : InstantWeapon
public override float DamagePerSecond => Damage * _chargeFiringDamageMultiplier / (Cooldown + ChargeTime);
public override float RangeDamagePerSecond(float range)
{
return Damage *
_chargeFiringDamageMultiplier *
DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) /
return EvaluateRangeDamage(range, StatConditionMask.Charge, saturate(_charge)) *
lerp(1, _chargeFiringDamageMultiplier, saturate(_charge)) *
_chargeFiringDamageMultiplier /
(Cooldown + ChargeTime);
}
@ -106,7 +105,8 @@ public class ChargedWeapon : InstantWeapon
ChargeTime = Evaluate(_chargeTime);
ChargeEnergy = Evaluate(_chargeEnergy);
ChargeHeat = Evaluate(_chargeHeat);
Damage *= lerp(1, _chargeFiringDamageMultiplier, saturate(_charge));
Damage = EvaluateDamage(StatConditionMask.Charge, saturate(_charge)) *
lerp(1, _chargeFiringDamageMultiplier, saturate(_charge));
Heat *= lerp(1, _chargeFiringHeatMultiplier, saturate(_charge));
Spread *= lerp(1, _chargeFiringSpreadMultiplier, saturate(_charge));
BurstCount *= lerp(1, _chargeFiringBurstCountMultiplier, saturate(_charge));

View file

@ -2,10 +2,6 @@
* 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.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class Cockpit : Behavior
{
public Cockpit(RuntimeBehaviorDefinition definition, EquippedItem item) : base(definition, item)

View file

@ -3,8 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
@ -30,7 +29,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public override float DamagePerSecond => Damage;
public override float RangeDamagePerSecond(float range)
{
return Damage * DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range)));
return EvaluateRangeDamage(range);
}
public event Action OnReloadBegin;

View file

@ -2,10 +2,7 @@
* 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.Linq;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class Cooldown : Behavior, IAlwaysUpdatedBehavior, IProgressBehavior
{

View file

@ -2,10 +2,6 @@
* 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.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class HeatStorage : Behavior
{
public HeatStorage(RuntimeBehaviorDefinition definition, EquippedItem item) : base(definition, item)

View file

@ -1,8 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
@ -29,7 +28,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public override float DamagePerSecond => Damage / Cooldown;
public override float RangeDamagePerSecond(float range)
{
return Damage * DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) / Cooldown;
return EvaluateRangeDamage(range) / Cooldown;
}
public override int Ammo

View file

@ -1,8 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class LockWeapon : InstantWeapon
{
@ -82,10 +79,11 @@ public class LockWeapon : InstantWeapon
DirectionImpact = Evaluate(_directionImpact);
Decay = Evaluate(_decay);
var degrees = acos(dot(normalize(Entity.Target.Value.Position - Entity.Position), normalize(Entity.LookDirection))) * 57.2958f;
if (degrees < LockAngle)
var targetDirection = Entity.Target.Value.CultPosition - Entity.CultPosition;
var angleDegrees = AetheriaMath.AngleDegrees(targetDirection, Entity.CultLookDirection);
if (angleDegrees < LockAngle)
{
var lerp = 1 - unlerp(0, 90, degrees);
var lerp = 1 - unlerp(0, 90, angleDegrees);
_lock = saturate(_lock + pow(lerp, DirectionImpact) * dt * LockSpeed * pow(Entity.EntityInfoGathered[Entity.Target.Value], SensorImpact));
}
else _lock = saturate(_lock - dt * Decay);

View file

@ -2,10 +2,7 @@
* 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.Linq;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class MiningTool : Behavior
{
@ -45,10 +42,11 @@ public class MiningTool : Behavior
public override bool Execute(float dt)
{
Range = Evaluate(_range);
if (Entity.Zone.TryGetAsteroidBelt(AsteroidBeltBodyKey, out var belt) &&
!string.IsNullOrWhiteSpace(AsteroidBeltBodyKey) &&
if (!string.IsNullOrWhiteSpace(AsteroidBeltBodyKey) &&
Entity.Zone.TryGetAsteroidBelt(AsteroidBeltBodyKey, out var belt) &&
Entity.Zone.AsteroidExists(AsteroidBeltBodyKey, Asteroid) &&
length(Entity.Position.xz - belt.Transforms[Asteroid].xy) - belt.Transforms[Asteroid].w < Range)
Entity.Zone.TryGetCultAsteroidTransform(AsteroidBeltBodyKey, Asteroid, out var asteroidPosition, out var asteroidRadius) &&
length(Entity.CultPositionXZ - asteroidPosition) - asteroidRadius < Range)
{
Entity.Zone.MineAsteroid(
Entity,

View file

@ -2,8 +2,7 @@
* 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 Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class Radiator : Behavior, IAlwaysUpdatedBehavior, IInitializableBehavior
{

View file

@ -6,8 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class Reactor : Behavior, IOrderedBehavior, IDisposable
{

View file

@ -2,9 +2,6 @@
* 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 Unity.Mathematics;
using static Unity.Mathematics.math;
public class Reflector : Behavior
{
private readonly PerformanceStat _crossSection;
@ -23,7 +20,7 @@ public class Reflector : Behavior
public override bool Execute(float dt)
{
Entity.VisibilitySources[this] = Evaluate(_crossSection) * Entity.Zone.GetLight(Entity.Position.xz);
Entity.VisibilitySources[this] = Evaluate(_crossSection) * Entity.Zone.GetLight(Entity.CultPositionXZ);
return true;
}

View file

@ -3,9 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Linq;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class ResourceScanner : Behavior, IAlwaysUpdatedBehavior
{
@ -60,9 +58,8 @@ public class ResourceScanner : Behavior, IAlwaysUpdatedBehavior
{
if (Entity.Zone.TryGetAsteroidBelt(ScanTargetBodyKey, out var belt))
{
if (Asteroid > -1 &&
belt.ContainsAsteroid(Asteroid) &&
length(Entity.Position.xz - belt.Transforms[Asteroid].xy) < Range)
if (Entity.Zone.TryGetCultAsteroidTransform(ScanTargetBodyKey, Asteroid, out var asteroidPosition, out _) &&
length(Entity.CultPositionXZ - asteroidPosition) < Range)
{
_scanTime += dt;
if (_scanTime > ScanDuration)
@ -75,7 +72,7 @@ public class ResourceScanner : Behavior, IAlwaysUpdatedBehavior
}
else if (Entity.Zone.TryGetPlanet(ScanTargetBodyKey, out var planet))
{
if(length(Entity.Position.xz - Entity.Zone.GetOrbitPosition(planet.OrbitKey)) < Range)
if(length(Entity.CultPositionXZ - AetheriaMath.ToCult(Entity.Zone.GetOrbitPosition(planet.OrbitKey))) < Range)
{
_scanTime += dt;
if (_scanTime > ScanDuration)

View file

@ -4,8 +4,7 @@
using System;
using System.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class Sensor : Behavior, IEventBehavior
{
@ -117,12 +116,13 @@ public class Sensor : Behavior, IEventBehavior
// TODO: Handle Active Detection / Visibility From Reflected Radiance
var forward = Direction.xz;
var entityPosition = Entity.CultPositionXZ;
foreach (var entity in Entity.Zone.Entities)
{
if (entity == Entity) continue;
var diff = entity.Position.xz - Entity.Position.xz;
var angle = acos(dot(forward, normalize(diff)));
var diff = entity.CultPositionXZ - entityPosition;
var angle = AetheriaMath.AngleRadians(forward, diff);
var dist = length(diff);
float previous, next;
Entity.EntityInfoGathered.TryGetValue(entity, out previous);

View file

@ -2,9 +2,6 @@
* 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 Unity.Mathematics;
using static Unity.Mathematics.math;
public class Shield : Behavior, IProgressBehavior
{
public float Efficiency { get; private set; }

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Collections.Generic;
using System.Linq;
using GameCult.Aetheria.State.Unity;
@ -14,14 +15,14 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
private readonly StatModifierType _type;
private readonly string _requiredBehaviorKind;
private PerformanceStat[] _stats;
private StatModifierTarget[] _targets;
private bool _applied;
private bool _executed;
public bool Applied => _applied;
public bool Executed => _executed;
public int TargetStatCount => _stats?.Length ?? 0;
public int TargetStatCount => _targets?.Length ?? 0;
public StatModifier(RuntimeBehaviorDefinition definition, EquippedItem item) : base(definition, item)
{
@ -47,13 +48,19 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
public void Initialize()
{
_stats = Entity.Equipment
.Where(HasRequiredBehavior)
.SelectMany(gear => gear.Behaviors ?? Array.Empty<Behavior>())
.Where(behavior => BehaviorKindMatches(behavior.Kind, _targetBehaviorKind))
.Select(FindTargetStat)
.Where(stat => stat != null)
.ToArray();
var targets = new List<StatModifierTarget>();
foreach (var gear in Entity.Equipment.Where(HasRequiredBehavior))
foreach (var behavior in gear.Behaviors ?? Array.Empty<Behavior>())
{
if (!BehaviorKindMatches(behavior.Kind, _targetBehaviorKind))
continue;
var stat = FindTargetStat(behavior);
if (stat != null)
targets.Add(new StatModifierTarget(gear, stat));
}
_targets = targets.ToArray();
}
private PerformanceStat FindTargetStat(Behavior behavior)
@ -91,17 +98,21 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
private void ApplyModifier()
{
_applied = true;
foreach (var stat in _stats)
(_type == StatModifierType.Constant
? stat.GetConstantModifiers(Entity)
: stat.GetScaleModifiers(Entity))[this] = Evaluate(_modifier);
RefreshModifier();
}
private void RemoveModifier()
{
_applied = false;
foreach (var stat in _stats)
(_type == StatModifierType.Constant ? stat.GetConstantModifiers(Entity) : stat.GetScaleModifiers(Entity)).Remove(this);
foreach (var target in _targets ?? Array.Empty<StatModifierTarget>())
target.Item.RemoveStatModifier(target.Stat, this, _type);
}
private void RefreshModifier()
{
var value = Evaluate(_modifier);
foreach (var target in _targets ?? Array.Empty<StatModifierTarget>())
target.Item.SetStatModifier(target.Stat, this, _type, value);
}
public override bool Execute(float dt)
@ -120,6 +131,8 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
{
if(_executed && !_applied)
ApplyModifier();
else if(_executed && _applied)
RefreshModifier();
if(!_executed && _applied)
RemoveModifier();
_executed = false;
@ -127,14 +140,28 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
public void RestoreRuntimeState(bool applied, bool executed)
{
if (_stats == null)
if (_targets == null)
Initialize();
if (applied && !_applied)
ApplyModifier();
if (applied && _applied)
RefreshModifier();
if (!applied && _applied)
RemoveModifier();
_executed = executed;
}
private readonly struct StatModifierTarget
{
public StatModifierTarget(EquippedItem item, PerformanceStat stat)
{
Item = item;
Stat = stat;
}
public EquippedItem Item { get; }
public PerformanceStat Stat { get; }
}
}
public enum StatModifierType

View file

@ -2,8 +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 Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
using cfloat2 = CultMath.float2;
public class Thruster : Behavior, IAnalogBehavior
{
@ -40,7 +40,7 @@ public class Thruster : Behavior, IAnalogBehavior
var hullCenter = hullShape.CenterOfMass;
var itemCenter = hullShape.Inset(itemShape, item.Position, item.EquippableItem.Rotation).CenterOfMass;
var toCenter = hullCenter - itemCenter;
Torque = -dot(normalize(toCenter), float2(1, 0).Rotate(item.EquippableItem.Rotation));
Torque = -dot(normalize(toCenter), AetheriaMath.Rotate(new cfloat2(1, 0), item.EquippableItem.Rotation));
Thrust = Evaluate(_thrust);
}
@ -65,9 +65,10 @@ public class Thruster : Behavior, IAnalogBehavior
if(_input > .01f && Entity.TryConsumeEnergy(_input * Evaluate(_energyUsage)))
{
Thrust = Evaluate(_thrust);
Entity.Velocity -= Direction.xz * _input * Thrust / Entity.Mass * dt;
Entity.Direction = mul(Entity.Direction,
Unity.Mathematics.float2x2.Rotate(_input * Torque * Thrust * ItemManager.GameplaySettings.TorqueMultiplier / Entity.Mass * dt));
Entity.CultVelocity -= Direction.xz * _input * Thrust / Entity.Mass * dt;
Entity.CultDirection = AetheriaMath.Rotate(
Entity.CultDirection,
_input * Torque * Thrust * ItemManager.GameplaySettings.TorqueMultiplier / Entity.Mass * dt);
AddHeat(_input * Evaluate(_heat) * dt);
var vis = _input * Evaluate(_visibility);
if (!Entity.VisibilitySources.TryGetValue(this, out var existingVisibility) || vis > existingVisibility)

View file

@ -5,9 +5,9 @@
using System.Collections.Generic;
using System.Linq;
using UniRx;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using float3 = Unity.Mathematics.float3;
using static CultMath.math;
using cfloat3 = CultMath.float3;
public class TurretController : Behavior, IInitializableBehavior
{
private List<Weapon> _weapons = new List<Weapon>();
@ -44,27 +44,29 @@ public class TurretController : Behavior, IInitializableBehavior
{
if (Entity.Target.Value != null)
{
var diff = Entity.Target.Value.Position - Entity.Position;
var entityPosition = Entity.CultPosition;
var targetPosition = Entity.Target.Value.CultPosition;
var diff = targetPosition - entityPosition;
if (_predictShots)
{
var targetHull = Entity.ItemManager.GetRuntimeItem(Entity.Target.Value.Hull);
var targetVelocity = float3(Entity.Target.Value.Velocity.x, 0, Entity.Target.Value.Velocity.y);
var targetVelocity = new cfloat3(Entity.Target.Value.CultVelocity.x, 0, Entity.Target.Value.CultVelocity.y);
var predictedPosition = AetheriaMath.FirstOrderIntercept(
Entity.Position, float3.zero, _shotSpeed,
Entity.Target.Value.Position, targetVelocity
entityPosition, cfloat3.zero, _shotSpeed,
targetPosition, targetVelocity
);
predictedPosition.y = Entity.Zone.GetHeight(predictedPosition.xz) + (float)(targetHull?.HullGridOffset ?? 0);
Entity.LookDirection = normalize(predictedPosition - Entity.Position);
Entity.CultLookDirection = normalize(predictedPosition - entityPosition);
}
else
Entity.LookDirection = normalize(diff);
Entity.CultLookDirection = normalize(diff);
var dist = length(diff);
foreach (var x in _weapons)
{
var fire = dot(
x.Direction,
Entity.LookDirection) > .99f;
Entity.CultLookDirection) > .99f;
if (x.EvaluateRange() > dist && fire)
{
x.Activate();

View file

@ -2,8 +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 Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class VelocityConversion : Behavior
{
private readonly PerformanceStat _lambda;
@ -22,7 +22,8 @@ public class VelocityConversion : Behavior
public override bool Execute(float dt)
{
Entity.Velocity = AetheriaMath.Damp(Entity.Velocity, Entity.Direction * length(Entity.Velocity), Evaluate(_lambda), dt);
var velocity = Entity.CultVelocity;
Entity.CultVelocity = AetheriaMath.Damp(velocity, Entity.CultDirection * length(velocity), Evaluate(_lambda), dt);
return true;
}
}

View file

@ -2,8 +2,7 @@
* 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 Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
public class VelocityLimit : Behavior
{
@ -28,8 +27,9 @@ public class VelocityLimit : Behavior
public override bool Execute(float dt)
{
Limit = Evaluate(_topSpeed);
if (length(Entity.Velocity) > Limit)
Entity.Velocity = normalize(Entity.Velocity) * Limit;
var velocity = Entity.CultVelocity;
if (length(velocity) > Limit)
Entity.CultVelocity = normalize(velocity) * Limit;
return true;
}

View file

@ -4,8 +4,8 @@
using System.Collections.Generic;
using System.Linq;
using Unity.Mathematics;
using static Unity.Mathematics.math;
using static CultMath.math;
using float4 = CultMath.float4;
public abstract class Weapon : Behavior, IActivatedBehavior
{
@ -156,6 +156,25 @@ public abstract class Weapon : Behavior, IActivatedBehavior
Velocity = Evaluate(_velocity);
}
protected float EvaluateRangeDamage(float range)
{
var normalizedRange = saturate(unlerp(MinRange, Range, range));
return Evaluate(_damage, StatConditionMask.Range, normalizedRange) *
DamageCurve.Evaluate(normalizedRange);
}
protected float EvaluateRangeDamage(float range, StatConditionMask condition, float value)
{
var normalizedRange = saturate(unlerp(MinRange, Range, range));
return Evaluate(_damage, StatConditionMask.Range, normalizedRange, condition, value) *
DamageCurve.Evaluate(normalizedRange);
}
protected float EvaluateDamage(StatConditionMask condition, float value)
{
return Evaluate(_damage, condition, value);
}
public override bool Execute(float dt)
{
UpdateStats();

View file

@ -2,10 +2,6 @@
* 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.Collections.Generic;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public class Wear : Behavior
{
private readonly bool _perSecond;