Stop weapon behaviors retaining configs

This commit is contained in:
Meta Vens 2026-06-15 18:27:29 +01:00
commit 6d459c406b
8 changed files with 180 additions and 76 deletions

View file

@ -56,7 +56,18 @@ public class ChargedWeaponConfig : InstantWeaponConfig
public class ChargedWeapon : InstantWeapon
{
private ChargedWeaponConfig _data;
private readonly PerformanceStat _chargeTime;
private readonly PerformanceStat _chargeEnergy;
private readonly PerformanceStat _chargeHeat;
private readonly bool _canFireEarly;
private readonly float _failureCharge;
private readonly float _failureDamage;
private readonly float _chargeFiringDamageMultiplier;
private readonly float _chargeFiringSpreadMultiplier;
private readonly float _chargeFiringBurstCountMultiplier;
private readonly float _chargeFiringVisibilityMultiplier;
private readonly float _chargeFiringVelocityMultiplier;
private readonly float _chargeFiringHeatMultiplier;
private bool _charging;
private bool _charged;
private float _charge;
@ -66,12 +77,12 @@ public class ChargedWeapon : InstantWeapon
public float ChargeEnergy { get; protected set; }
public float ChargeHeat { get; protected set; }
public override float DamagePerSecond => Damage * _data.ChargeFiringDamageMultiplier / (Cooldown + ChargeTime);
public override float DamagePerSecond => Damage * _chargeFiringDamageMultiplier / (Cooldown + ChargeTime);
public override float RangeDamagePerSecond(float range)
{
return Damage *
_data.ChargeFiringDamageMultiplier *
_data.DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) /
_chargeFiringDamageMultiplier *
DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) /
(Cooldown + ChargeTime);
}
@ -100,26 +111,48 @@ public class ChargedWeapon : InstantWeapon
public ChargedWeapon(ChargedWeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
_chargeTime = data.ChargeTime;
_chargeEnergy = data.ChargeEnergy;
_chargeHeat = data.ChargeHeat;
_canFireEarly = data.CanFireEarly;
_failureCharge = data.FailureCharge;
_failureDamage = data.FailureDamage;
_chargeFiringDamageMultiplier = data.ChargeFiringDamageMultiplier;
_chargeFiringSpreadMultiplier = data.ChargeFiringSpreadMultiplier;
_chargeFiringBurstCountMultiplier = data.ChargeFiringBurstCountMultiplier;
_chargeFiringVisibilityMultiplier = data.ChargeFiringVisibilityMultiplier;
_chargeFiringVelocityMultiplier = data.ChargeFiringVelocityMultiplier;
_chargeFiringHeatMultiplier = data.ChargeFiringHeatMultiplier;
}
public ChargedWeapon(ChargedWeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
_chargeTime = data.ChargeTime;
_chargeEnergy = data.ChargeEnergy;
_chargeHeat = data.ChargeHeat;
_canFireEarly = data.CanFireEarly;
_failureCharge = data.FailureCharge;
_failureDamage = data.FailureDamage;
_chargeFiringDamageMultiplier = data.ChargeFiringDamageMultiplier;
_chargeFiringSpreadMultiplier = data.ChargeFiringSpreadMultiplier;
_chargeFiringBurstCountMultiplier = data.ChargeFiringBurstCountMultiplier;
_chargeFiringVisibilityMultiplier = data.ChargeFiringVisibilityMultiplier;
_chargeFiringVelocityMultiplier = data.ChargeFiringVelocityMultiplier;
_chargeFiringHeatMultiplier = data.ChargeFiringHeatMultiplier;
}
protected override void UpdateStats()
{
base.UpdateStats();
ChargeTime = Evaluate(_data.ChargeTime);
ChargeEnergy = Evaluate(_data.ChargeEnergy);
ChargeHeat = Evaluate(_data.ChargeHeat);
Damage *= lerp(1, _data.ChargeFiringDamageMultiplier, saturate(_charge));
Heat *= lerp(1, _data.ChargeFiringHeatMultiplier, saturate(_charge));
Spread *= lerp(1, _data.ChargeFiringSpreadMultiplier, saturate(_charge));
BurstCount *= lerp(1, _data.ChargeFiringBurstCountMultiplier, saturate(_charge));
Visibility *= lerp(1, _data.ChargeFiringVisibilityMultiplier, saturate(_charge));
Velocity *= lerp(1, _data.ChargeFiringVelocityMultiplier, saturate(_charge));
ChargeTime = Evaluate(_chargeTime);
ChargeEnergy = Evaluate(_chargeEnergy);
ChargeHeat = Evaluate(_chargeHeat);
Damage *= lerp(1, _chargeFiringDamageMultiplier, saturate(_charge));
Heat *= lerp(1, _chargeFiringHeatMultiplier, saturate(_charge));
Spread *= lerp(1, _chargeFiringSpreadMultiplier, saturate(_charge));
BurstCount *= lerp(1, _chargeFiringBurstCountMultiplier, saturate(_charge));
Visibility *= lerp(1, _chargeFiringVisibilityMultiplier, saturate(_charge));
Velocity *= lerp(1, _chargeFiringVelocityMultiplier, saturate(_charge));
}
public override bool Execute(float dt)
@ -137,7 +170,7 @@ public class ChargedWeapon : InstantWeapon
OnCharged?.Invoke();
}
}
if (_data.FailureCharge > 1 && _charge > _data.FailureCharge)
if (_failureCharge > 1 && _charge > _failureCharge)
{
_charging = false;
_cooldown = 1;
@ -145,7 +178,7 @@ public class ChargedWeapon : InstantWeapon
_charge = 0;
OnFailed?.Invoke();
Item.FireAudioEvent(ChargedWeaponAudioEvent.Fail);
CauseDamage(_data.FailureDamage);
CauseDamage(_failureDamage);
}
}
return base.Execute(dt);
@ -166,7 +199,7 @@ public class ChargedWeapon : InstantWeapon
{
if (_charging)
{
if (_data.CanFireEarly || _charge > 1)
if (_canFireEarly || _charge > 1)
{
Trigger();
_charge = 0;

View file

@ -25,7 +25,7 @@ public class ConstantWeaponConfig : WeaponConfig
public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
private ConstantWeaponConfig _data;
private readonly float _ammoIntervalDuration;
private int _ammo = 1;
private float _ammoInterval;
private float _reload;
@ -47,7 +47,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public override float DamagePerSecond => Damage;
public override float RangeDamagePerSecond(float range)
{
return Damage * _data.DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range)));
return Damage * DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range)));
}
public event Action OnReloadBegin;
@ -65,12 +65,12 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public ConstantWeapon(ConstantWeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
_ammoIntervalDuration = data.AmmoInterval;
}
public ConstantWeapon(ConstantWeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
_ammoIntervalDuration = data.AmmoInterval;
}
public override bool Execute(float dt)
@ -78,17 +78,17 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
base.Execute(dt);
if (_firing)
{
if (!Entity.TryConsumeEnergy(Evaluate(_data.Energy) * dt))
if (!Entity.TryConsumeEnergy(Energy * dt))
{
_firing = false;
OnStopFiring?.Invoke();
return false;
}
if (!string.IsNullOrWhiteSpace(_data.AmmoItemKey))
if (!string.IsNullOrWhiteSpace(AmmoItemKey))
{
if (_reloading)
{
_reload -= dt / _data.ReloadTime;
_reload -= dt / ReloadTime;
if (_reload < 0)
{
_reloading = false;
@ -97,21 +97,21 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
return false;
}
_ammoInterval -= dt / _data.AmmoInterval;
_ammoInterval -= dt / _ammoIntervalDuration;
if (_ammoInterval < 0)
{
_ammoInterval = 1;
if (_data.MagazineSize > 1 && _ammo > 0) _ammo--;
if (MagazineSize > 1 && _ammo > 0) _ammo--;
else
{
var cargo = Entity.FindItemInCargo(_data.AmmoItemKey);
var cargo = Entity.FindItemInCargo(AmmoItemKey);
if (cargo != null)
{
var item = cargo.GetFirstItem(_data.AmmoItemKey);
var item = cargo.GetFirstItem(AmmoItemKey);
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
if(_data.MagazineSize > 1)
if(MagazineSize > 1)
{
_reloading = true;
_reload = 1;
@ -127,8 +127,8 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
}
CauseWearDamage(dt);
AddHeat(Evaluate(_data.Heat) * dt);
Entity.VisibilitySources[this] = Evaluate(_data.Visibility);
AddHeat(Heat * dt);
Entity.VisibilitySources[this] = Visibility;
}
return true;
}

View file

@ -32,7 +32,10 @@ public class InstantWeaponConfig : WeaponConfig
public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
private InstantWeaponConfig _data;
private readonly PerformanceStat _count;
private readonly PerformanceStat _burstTime;
private readonly PerformanceStat _cooldownDuration;
private readonly bool _singleAmmoBurst;
protected int _burstRemaining;
private float _burstTimer;
@ -52,7 +55,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public override float DamagePerSecond => Damage / Cooldown;
public override float RangeDamagePerSecond(float range)
{
return Damage * _data.DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) / Cooldown;
return Damage * DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) / Cooldown;
}
public override int Ammo
@ -81,13 +84,19 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
public InstantWeapon(InstantWeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
_count = data.Count;
_burstTime = data.BurstTime;
_cooldownDuration = data.Cooldown;
_singleAmmoBurst = data.SingleAmmoBurst;
_ammo = data.MagazineSize;
}
public InstantWeapon(InstantWeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
_count = data.Count;
_burstTime = data.BurstTime;
_cooldownDuration = data.Cooldown;
_singleAmmoBurst = data.SingleAmmoBurst;
_ammo = data.MagazineSize;
}
@ -95,7 +104,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
// If 1 ammo is consumed per burst, perform ammo and energy consumption here
// UseAmmo returns false when triggering reload; cancel firing if that is the case
if(_data.SingleAmmoBurst && (!Entity.TryConsumeEnergy(Energy) || !UseAmmo())) return;
if(_singleAmmoBurst && (!Entity.TryConsumeEnergy(Energy) || !UseAmmo())) return;
_burstRemaining = (int) BurstCount;
_burstInterval = BurstTime / _burstRemaining;
@ -107,9 +116,9 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
protected override void UpdateStats()
{
base.UpdateStats();
BurstCount = Evaluate(_data.Count);
BurstTime = Evaluate(_data.BurstTime);
Cooldown = Evaluate(_data.Cooldown);
BurstCount = Evaluate(_count);
BurstTime = Evaluate(_burstTime);
Cooldown = Evaluate(_cooldownDuration);
Damage /= (int) BurstCount;
Heat /= (int) BurstCount;
@ -118,7 +127,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
private bool UseAmmo()
{
if (_data.MagazineSize <= 1) return true;
if (MagazineSize <= 1) return true;
if (_ammo > 0)
{
@ -127,12 +136,12 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
}
var hasAmmo = true;
if (!string.IsNullOrWhiteSpace(_data.AmmoItemKey))
if (!string.IsNullOrWhiteSpace(AmmoItemKey))
{
var cargo = Entity.FindItemInCargo(_data.AmmoItemKey);
var cargo = Entity.FindItemInCargo(AmmoItemKey);
if (cargo != null)
{
var item = cargo.GetFirstItem(_data.AmmoItemKey);
var item = cargo.GetFirstItem(AmmoItemKey);
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
}
@ -155,13 +164,13 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
base.Execute(dt);
if (_coolingDown)
{
_cooldown -= dt / (_data.MagazineSize > 0 && _ammo == 0 ? _data.ReloadTime : Cooldown);
_cooldown -= dt / (MagazineSize > 0 && _ammo == 0 ? ReloadTime : Cooldown);
if (_cooldown < 0)
{
_coolingDown = false;
if (_data.MagazineSize > 0 && _ammo == 0)
if (MagazineSize > 0 && _ammo == 0)
{
_ammo = _data.MagazineSize;
_ammo = MagazineSize;
OnReloadComplete?.Invoke();
}
else
@ -175,7 +184,7 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
{
// If multiple ammo is consumed per burst, perform ammo and energy consumption here
// UseAmmo returns false when triggering reload; cancel firing if that is the case
if (!_data.SingleAmmoBurst && (!Entity.TryConsumeEnergy(Energy) || !UseAmmo()))
if (!_singleAmmoBurst && (!Entity.TryConsumeEnergy(Energy) || !UseAmmo()))
{
_burstRemaining = 0;
return false;

View file

@ -34,7 +34,11 @@ public class LockWeaponConfig : InstantWeaponConfig
public class LockWeapon : InstantWeapon
{
private LockWeaponConfig _data;
private readonly PerformanceStat _lockSpeed;
private readonly PerformanceStat _sensorImpact;
private readonly PerformanceStat _lockAngle;
private readonly PerformanceStat _directionImpact;
private readonly PerformanceStat _decay;
private float _lock;
private bool _locking;
private Entity _target;
@ -64,11 +68,19 @@ public class LockWeapon : InstantWeapon
public LockWeapon(LockWeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
_lockSpeed = data.LockSpeed;
_sensorImpact = data.SensorImpact;
_lockAngle = data.LockAngle;
_directionImpact = data.DirectionImpact;
_decay = data.Decay;
}
public LockWeapon(LockWeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
_lockSpeed = data.LockSpeed;
_sensorImpact = data.SensorImpact;
_lockAngle = data.LockAngle;
_directionImpact = data.DirectionImpact;
_decay = data.Decay;
}
public override bool Execute(float dt)
@ -81,11 +93,11 @@ public class LockWeapon : InstantWeapon
if (Entity.Target.Value != null && Entity.Target.Value.IsHostileTo(Entity))
{
LockSpeed = Evaluate(_data.LockSpeed);
SensorImpact = Evaluate(_data.SensorImpact);
LockAngle = Evaluate(_data.LockAngle);
DirectionImpact = Evaluate(_data.DirectionImpact);
Decay = Evaluate(_data.Decay);
LockSpeed = Evaluate(_lockSpeed);
SensorImpact = Evaluate(_sensorImpact);
LockAngle = Evaluate(_lockAngle);
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)

View file

@ -59,7 +59,16 @@ public abstract class WeaponConfig : RuntimeBehaviorConfig
public abstract class Weapon : Behavior, IActivatedBehavior
{
private WeaponConfig _data;
private readonly PerformanceStat _damage;
private readonly PerformanceStat _penetration;
private readonly PerformanceStat _damageSpread;
private readonly PerformanceStat _minRange;
private readonly PerformanceStat _range;
private readonly PerformanceStat _energy;
private readonly PerformanceStat _heat;
private readonly PerformanceStat _visibility;
private readonly PerformanceStat _spread;
private readonly PerformanceStat _velocity;
private PerformanceStat _guidedProjectileThrust;
private PerformanceStat _guidedProjectileVelocity;
@ -70,6 +79,8 @@ public abstract class Weapon : Behavior, IActivatedBehavior
public string EffectPrefab { get; }
public string AmmoItemKey { get; }
public int MagazineSize { get; }
protected float ReloadTime { get; }
protected BezierCurve DamageCurve { get; }
public bool UsesAmmo => !string.IsNullOrWhiteSpace(AmmoItemKey);
public GuidedProjectileTargetMode GuidedProjectileTargeting { get; private set; }
public bool HasGuidedProjectileProfile => GuidedProjectileTargeting != GuidedProjectileTargetMode.None;
@ -98,21 +109,43 @@ public abstract class Weapon : Behavior, IActivatedBehavior
public Weapon(WeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
_damage = data.Damage;
_penetration = data.Penetration;
_damageSpread = data.DamageSpread;
_minRange = data.MinRange;
_range = data.Range;
_energy = data.Energy;
_heat = data.Heat;
_visibility = data.Visibility;
_spread = data.Spread;
_velocity = data.Velocity;
DamageType = data.DamageType;
DamageCurve = data.DamageCurve;
EffectPrefab = data.EffectPrefab ?? "";
AmmoItemKey = data.AmmoItemKey;
MagazineSize = data.MagazineSize;
ReloadTime = data.ReloadTime;
InitializeGuidedProjectileProfile(data);
}
public Weapon(WeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
_damage = data.Damage;
_penetration = data.Penetration;
_damageSpread = data.DamageSpread;
_minRange = data.MinRange;
_range = data.Range;
_energy = data.Energy;
_heat = data.Heat;
_visibility = data.Visibility;
_spread = data.Spread;
_velocity = data.Velocity;
DamageType = data.DamageType;
DamageCurve = data.DamageCurve;
EffectPrefab = data.EffectPrefab ?? "";
AmmoItemKey = data.AmmoItemKey;
MagazineSize = data.MagazineSize;
ReloadTime = data.ReloadTime;
InitializeGuidedProjectileProfile(data);
}
@ -142,16 +175,16 @@ public abstract class Weapon : Behavior, IActivatedBehavior
protected virtual void UpdateStats()
{
Damage = Evaluate(_data.Damage);
Penetration = Evaluate(_data.Penetration);
DamageSpread = Evaluate(_data.DamageSpread);
MinRange = Evaluate(_data.MinRange);
Range = Evaluate(_data.Range);
Energy = Evaluate(_data.Energy);
Heat = Evaluate(_data.Heat);
Visibility = Evaluate(_data.Visibility);
Spread = Evaluate(_data.Spread);
Velocity = Evaluate(_data.Velocity);
Damage = Evaluate(_damage);
Penetration = Evaluate(_penetration);
DamageSpread = Evaluate(_damageSpread);
MinRange = Evaluate(_minRange);
Range = Evaluate(_range);
Energy = Evaluate(_energy);
Heat = Evaluate(_heat);
Visibility = Evaluate(_visibility);
Spread = Evaluate(_spread);
Velocity = Evaluate(_velocity);
}
public override bool Execute(float dt)
@ -172,12 +205,12 @@ public abstract class Weapon : Behavior, IActivatedBehavior
public float EvaluateRange()
{
return Evaluate(_data.Range);
return Evaluate(_range);
}
public float EvaluateVelocity()
{
return Evaluate(_data.Velocity);
return Evaluate(_velocity);
}
public float EvaluateGuidedProjectileThrust()