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
181 lines
No EOL
5.5 KiB
C#
181 lines
No EOL
5.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using MessagePack;
|
|
using Newtonsoft.Json;
|
|
using Unity.Mathematics;
|
|
using static Unity.Mathematics.math;
|
|
|
|
[InspectableField, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
|
|
public class InstantWeaponData : WeaponData
|
|
{
|
|
[InspectableField, JsonProperty("count"), Key(17)]
|
|
public PerformanceStat Count = new PerformanceStat();
|
|
|
|
[InspectableField, JsonProperty("burstTime"), Key(18)]
|
|
public PerformanceStat BurstTime = new PerformanceStat();
|
|
|
|
[InspectableField, JsonProperty("cooldown"), Key(19), RuntimeInspectable]
|
|
public PerformanceStat Cooldown = new PerformanceStat();
|
|
|
|
[InspectablePrefab, JsonProperty("ammoInterval"), Key(20)]
|
|
public bool SingleAmmoBurst;
|
|
|
|
public override IBehavior CreateInstance(ItemManager context, Entity entity, EquippedItem item)
|
|
{
|
|
return new InstantWeapon(context, this, entity, item);
|
|
}
|
|
}
|
|
|
|
public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
|
|
{
|
|
private InstantWeaponData _data;
|
|
|
|
protected int _burstRemaining;
|
|
private float _burstTimer;
|
|
private float _burstInterval;
|
|
protected float _cooldown; // Normalized
|
|
private int _ammo = 0;
|
|
protected bool _coolingDown;
|
|
|
|
public float BurstCount { get; protected set; }
|
|
public float BurstTime { get; protected set; }
|
|
public float Cooldown { get; protected set; }
|
|
public virtual bool CanFire
|
|
{
|
|
get => !_coolingDown;
|
|
}
|
|
|
|
public override float DamagePerSecond => Damage / Cooldown;
|
|
public override float RangeDamagePerSecond(float range)
|
|
{
|
|
return Damage * _data.DamageCurve.Evaluate(saturate(unlerp(MinRange, Range, range))) / Cooldown;
|
|
}
|
|
|
|
public override int Ammo
|
|
{
|
|
get => _ammo;
|
|
}
|
|
public virtual float Progress => saturate(_cooldown);
|
|
|
|
public event Action OnReloadBegin;
|
|
public event Action OnReloadComplete;
|
|
public event Action OnCooldownComplete;
|
|
public event Action OnFire;
|
|
|
|
public virtual void ResetEvents()
|
|
{
|
|
OnReloadBegin = null;
|
|
OnReloadComplete = null;
|
|
OnCooldownComplete = null;
|
|
OnFire = null;
|
|
}
|
|
|
|
public InstantWeapon(ItemManager context, InstantWeaponData data, Entity entity, EquippedItem item) : base(context,data,entity,item)
|
|
{
|
|
_data = data;
|
|
}
|
|
|
|
protected void Trigger()
|
|
{
|
|
// If 1 ammo is consumed per burst, perform ammo consumption here
|
|
// UseAmmo returns false when triggering reload; cancel firing if that is the case
|
|
if(_data.SingleAmmoBurst && !UseAmmo()) return;
|
|
|
|
_burstRemaining = (int) BurstCount;
|
|
_burstInterval = BurstTime / _burstRemaining;
|
|
_burstTimer = 0;
|
|
_cooldown = 1;
|
|
_coolingDown = true;
|
|
}
|
|
|
|
protected override void UpdateStats()
|
|
{
|
|
base.UpdateStats();
|
|
BurstCount = Item.Evaluate(_data.Count);
|
|
BurstTime = Item.Evaluate(_data.BurstTime);
|
|
Cooldown = Item.Evaluate(_data.Cooldown);
|
|
|
|
Damage /= (int) BurstCount;
|
|
Heat /= (int) BurstCount;
|
|
Energy /= (int) BurstCount;
|
|
}
|
|
|
|
private bool UseAmmo()
|
|
{
|
|
if (_data.AmmoType != Guid.Empty)
|
|
{
|
|
if (_data.MagazineSize > 1 && _ammo > 0) _ammo--;
|
|
else
|
|
{
|
|
var cargo = Entity.FindItemInCargo(_data.AmmoType);
|
|
if (cargo != null)
|
|
{
|
|
var item = cargo.ItemsOfType[_data.AmmoType][0];
|
|
if (item is SimpleCommodity simpleCommodity)
|
|
cargo.Remove(simpleCommodity, 1);
|
|
|
|
if(_data.MagazineSize > 1)
|
|
{
|
|
OnReloadBegin?.Invoke();
|
|
_cooldown = 1;
|
|
_coolingDown = true;
|
|
_firing = false;
|
|
}
|
|
}
|
|
_burstRemaining = 0;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool Execute(float delta)
|
|
{
|
|
base.Execute(delta);
|
|
if (_coolingDown)
|
|
{
|
|
_cooldown -= delta / (_data.AmmoType != Guid.Empty && _ammo == 0 ? _data.ReloadTime : Cooldown);
|
|
if (_cooldown < 0)
|
|
{
|
|
_coolingDown = false;
|
|
if (_data.AmmoType != Guid.Empty && _ammo == 0)
|
|
{
|
|
_ammo = _data.MagazineSize;
|
|
OnReloadComplete?.Invoke();
|
|
}
|
|
else
|
|
OnCooldownComplete?.Invoke();
|
|
}
|
|
}
|
|
|
|
_burstTimer += delta;
|
|
while (_burstRemaining > 0 && _burstTimer > 0)
|
|
{
|
|
if (!Entity.TryConsumeEnergy(Energy))
|
|
{
|
|
_burstRemaining = 0;
|
|
return false;
|
|
}
|
|
// If 1 ammo is consumed per shot in the burst, perform ammo consumption here
|
|
// UseAmmo returns false when triggering reload; cancel firing if that is the case
|
|
if (!_data.SingleAmmoBurst && !UseAmmo()) return false;
|
|
|
|
_burstRemaining--;
|
|
_burstTimer -= _burstInterval;
|
|
OnFire?.Invoke();
|
|
Item.EquippableItem.Durability -= Item.Wear;
|
|
Item.AddHeat(Heat);
|
|
Entity.VisibilitySources[this] = Visibility;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public override void Activate()
|
|
{
|
|
if(CanFire)
|
|
Trigger();
|
|
base.Activate();
|
|
}
|
|
} |