Aetheria/Assets/Scripts/ServerShared/Behaviors/Weapon.cs
2026-06-14 23:31:54 +01:00

204 lines
6.4 KiB
C#

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 System.Linq;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[Inspectable]
public abstract class WeaponConfig : RuntimeBehaviorConfig
{
[Inspectable]
public DamageType DamageType;
[Inspectable]
public PerformanceStat Damage = new PerformanceStat();
[InspectableRangedFloat(0,1)]
public PerformanceStat Penetration = new PerformanceStat();
[InspectableRangedFloat(0,1)]
public PerformanceStat DamageSpread = new PerformanceStat();
[Inspectable]
public PerformanceStat MinRange = new PerformanceStat();
[Inspectable]
public PerformanceStat Range = new PerformanceStat();
[InspectableAnimationCurve]
public BezierCurve DamageCurve;
[InspectablePrefab]
public string EffectPrefab;
[InspectablePrefab]
public PerformanceStat Energy = new PerformanceStat();
[InspectablePrefab]
public PerformanceStat Heat = new PerformanceStat();
[InspectablePrefab]
public PerformanceStat Visibility = new PerformanceStat();
public string AmmoItemKey;
public Guid AmmoType => AetheriaRuntimeItemReference.ToLegacyId(AmmoItemKey);
[InspectablePrefab]
public int MagazineSize;
[InspectablePrefab]
public float ReloadTime = 1;
[InspectablePrefab]
public PerformanceStat Spread = new PerformanceStat();
[Inspectable]
public PerformanceStat Velocity = new PerformanceStat();
}
public abstract class Weapon : Behavior, IActivatedBehavior
{
private WeaponConfig _data;
private PerformanceStat _guidedProjectileThrust;
private PerformanceStat _guidedProjectileVelocity;
public abstract float DamagePerSecond { get; }
public abstract float RangeDamagePerSecond(float range);
public abstract int Ammo { get; }
public DamageType DamageType { get; }
public string EffectPrefab { get; }
public string AmmoItemKey { get; }
public Guid AmmoType { get; }
public int MagazineSize { get; }
public bool UsesAmmo => !string.IsNullOrWhiteSpace(AmmoItemKey);
public GuidedProjectileTargetMode GuidedProjectileTargeting { get; private set; }
public bool HasGuidedProjectileProfile => GuidedProjectileTargeting != GuidedProjectileTargetMode.None;
public float4[] GuidedProjectileGuidanceCurve { get; private set; }
public float4[] GuidedProjectileLiftCurve { get; private set; }
public float4[] GuidedProjectileThrustCurve { get; private set; }
public float GuidedProjectileDodgeFrequency { get; private set; }
public float Damage { get; protected set; }
public float Penetration { get; protected set; }
public float DamageSpread { get; protected set; }
public float MinRange { get; protected set; }
public float Range { get; protected set; }
public float Energy { get; protected set; }
public float Heat { get; protected set; }
public float Visibility { get; protected set; }
public float Spread { get; protected set; }
public float Velocity { get; protected set; }
protected bool _firing;
public bool Firing
{
get => _firing;
}
public Weapon(WeaponConfig data, EquippedItem item) : base(data, item)
{
_data = data;
DamageType = data.DamageType;
EffectPrefab = data.EffectPrefab ?? "";
AmmoItemKey = data.AmmoItemKey;
AmmoType = data.AmmoType;
MagazineSize = data.MagazineSize;
InitializeGuidedProjectileProfile(data);
}
public Weapon(WeaponConfig data, ConsumableItemEffect item) : base(data, item)
{
_data = data;
DamageType = data.DamageType;
EffectPrefab = data.EffectPrefab ?? "";
AmmoItemKey = data.AmmoItemKey;
AmmoType = data.AmmoType;
MagazineSize = data.MagazineSize;
InitializeGuidedProjectileProfile(data);
}
private void InitializeGuidedProjectileProfile(WeaponConfig data)
{
if (data is LauncherConfig launcher)
{
GuidedProjectileTargeting = GuidedProjectileTargetMode.TargetEntity;
GuidedProjectileGuidanceCurve = launcher.GuidanceCurve;
GuidedProjectileLiftCurve = launcher.LiftCurve;
GuidedProjectileThrustCurve = launcher.ThrustCurve;
GuidedProjectileDodgeFrequency = launcher.DodgeFrequency;
_guidedProjectileThrust = launcher.Thrust;
_guidedProjectileVelocity = launcher.MissileVelocity;
}
else if (data is GuidedWeaponConfig guidance)
{
GuidedProjectileTargeting = GuidedProjectileTargetMode.LookDirection;
GuidedProjectileGuidanceCurve = guidance.GuidanceCurve;
GuidedProjectileLiftCurve = guidance.LiftCurve;
GuidedProjectileThrustCurve = guidance.ThrustCurve;
GuidedProjectileDodgeFrequency = guidance.DodgeFrequency;
_guidedProjectileThrust = guidance.Thrust;
_guidedProjectileVelocity = guidance.MissileVelocity;
}
}
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);
}
public override bool Execute(float dt)
{
UpdateStats();
return true;
}
public virtual void Activate()
{
_firing = true;
}
public virtual void Deactivate()
{
_firing = false;
}
public float EvaluateRange()
{
return Evaluate(_data.Range);
}
public float EvaluateVelocity()
{
return Evaluate(_data.Velocity);
}
public float EvaluateGuidedProjectileThrust()
{
return _guidedProjectileThrust == null ? 0 : Evaluate(_guidedProjectileThrust);
}
public float EvaluateGuidedProjectileVelocity()
{
return _guidedProjectileVelocity == null ? 0 : Evaluate(_guidedProjectileVelocity);
}
}
public enum GuidedProjectileTargetMode
{
None,
TargetEntity,
LookDirection
}