Magic staves + wands (#9070)

This commit is contained in:
Kara
2022-07-14 19:45:27 -07:00
committed by GitHub
parent 9608005db0
commit ad7889e8a9
85 changed files with 1299 additions and 34 deletions

View File

@@ -0,0 +1,44 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Weapons.Ranged.Components;
/// <summary>
/// Simply provides a certain capacity of entities that cannot be reloaded through normal means and have
/// no special behavior like cycling, magazine
/// </summary>
[RegisterComponent]
public sealed class BasicEntityAmmoProviderComponent : AmmoProviderComponent
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("proto", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Proto = default!;
/// <summary>
/// Max capacity.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("capacity")]
public int? Capacity = null;
/// <summary>
/// Actual ammo left. Initialized to capacity unless they are non-null and differ.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("count")]
public int? Count = null;
}
[Serializable, NetSerializable]
public sealed class BasicEntityAmmoProviderComponentState : ComponentState
{
public int? Capacity;
public int? Count;
public BasicEntityAmmoProviderComponentState(int? capacity, int? count)
{
Capacity = capacity;
Count = count;
}
}

View File

@@ -0,0 +1,96 @@
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Robust.Shared.GameStates;
namespace Content.Shared.Weapons.Ranged.Systems;
public abstract partial class SharedGunSystem
{
protected virtual void InitializeBasicEntity()
{
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, ComponentInit>(OnBasicEntityInit);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, TakeAmmoEvent>(OnBasicEntityTakeAmmo);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, GetAmmoCountEvent>(OnBasicEntityAmmoCount);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, ComponentGetState>(OnBasicEntityGetState);
SubscribeLocalEvent<BasicEntityAmmoProviderComponent, ComponentHandleState>(OnBasicEntityHandleState);
}
private void OnBasicEntityGetState(EntityUid uid, BasicEntityAmmoProviderComponent component, ref ComponentGetState args)
{
args.State = new BasicEntityAmmoProviderComponentState(component.Capacity, component.Count);
}
private void OnBasicEntityHandleState(EntityUid uid, BasicEntityAmmoProviderComponent component, ref ComponentHandleState args)
{
if (args.Current is BasicEntityAmmoProviderComponentState state)
{
component.Capacity = state.Capacity;
component.Count = state.Count;
}
}
private void OnBasicEntityInit(EntityUid uid, BasicEntityAmmoProviderComponent component, ComponentInit args)
{
if (component.Count is null)
{
component.Count = component.Capacity;
Dirty(component);
}
UpdateBasicEntityAppearance(component);
}
private void OnBasicEntityTakeAmmo(EntityUid uid, BasicEntityAmmoProviderComponent component, TakeAmmoEvent args)
{
for (int i = 0; i < args.Shots; i++)
{
if (component.Count <= 0)
return;
if (component.Count != null)
{
component.Count--;
}
var ent = Spawn(component.Proto, args.Coordinates);
args.Ammo.Add(EnsureComp<AmmoComponent>(ent));
}
UpdateBasicEntityAppearance(component);
Dirty(component);
}
private void OnBasicEntityAmmoCount(EntityUid uid, BasicEntityAmmoProviderComponent component, ref GetAmmoCountEvent args)
{
args.Capacity = component.Capacity ?? int.MaxValue;
args.Count = component.Count ?? int.MaxValue;
}
private void UpdateBasicEntityAppearance(BasicEntityAmmoProviderComponent component)
{
if (!Timing.IsFirstTimePredicted || !TryComp<AppearanceComponent>(component.Owner, out var appearance)) return;
appearance.SetData(AmmoVisuals.HasAmmo, component.Count != 0);
appearance.SetData(AmmoVisuals.AmmoCount, component.Count ?? int.MaxValue);
appearance.SetData(AmmoVisuals.AmmoMax, component.Capacity ?? int.MaxValue);
}
#region Public API
public bool UpdateBasicEntityAmmoCount(EntityUid uid, int count, BasicEntityAmmoProviderComponent? component = null)
{
if (!Resolve(uid, ref component))
return false;
if (count > component.Capacity)
return false;
component.Count = count;
Dirty(component);
UpdateBasicEntityAppearance(component);
return true;
}
#endregion
}

View File

@@ -83,6 +83,7 @@ public abstract partial class SharedGunSystem
protected void UpdateBatteryAppearance(EntityUid uid, BatteryAmmoProviderComponent component)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance)) return;
appearance.SetData(AmmoVisuals.HasAmmo, component.Shots != 0);
appearance.SetData(AmmoVisuals.AmmoCount, component.Shots);
appearance.SetData(AmmoVisuals.AmmoMax, component.Capacity);
}

View File

@@ -142,6 +142,7 @@ public abstract partial class SharedGunSystem
{
// Copy the magazine's appearance data
appearance?.SetData(AmmoVisuals.MagLoaded, magLoaded);
appearance?.SetData(AmmoVisuals.HasAmmo, count != 0);
appearance?.SetData(AmmoVisuals.AmmoCount, count);
appearance?.SetData(AmmoVisuals.AmmoMax, capacity);
}

View File

@@ -220,7 +220,9 @@ public partial class SharedGunSystem
private void UpdateRevolverAppearance(RevolverAmmoProviderComponent component)
{
if (!TryComp<AppearanceComponent>(component.Owner, out var appearance)) return;
appearance.SetData(AmmoVisuals.AmmoCount, GetRevolverCount(component));
var count = GetRevolverCount(component);
appearance.SetData(AmmoVisuals.HasAmmo, count != 0);
appearance.SetData(AmmoVisuals.AmmoCount, count);
appearance.SetData(AmmoVisuals.AmmoMax, component.Capacity);
}

View File

@@ -73,6 +73,7 @@ public abstract partial class SharedGunSystem : EntitySystem
InitializeChamberMagazine();
InitializeMagazine();
InitializeRevolver();
InitializeBasicEntity();
// Interactions
SubscribeLocalEvent<GunComponent, GetVerbsEvent<AlternativeVerb>>(OnAltVerb);
@@ -389,5 +390,6 @@ public enum AmmoVisuals : byte
Spent,
AmmoCount,
AmmoMax,
HasAmmo, // used for generic visualizers. c# stuff can just check ammocount != 0
MagLoaded,
}