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,21 @@
using Content.Shared.Polymorph;
using Content.Shared.Sound;
using Content.Shared.Whitelist;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Polymorph.Components;
[RegisterComponent]
public sealed class PolymorphOnCollideComponent : Component
{
[DataField("polymorph", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<PolymorphPrototype>))]
public string Polymorph = default!;
[DataField("whitelist", required: true)]
public EntityWhitelist Whitelist = default!;
[DataField("blacklist")]
public EntityWhitelist? Blacklist;
public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg");
}

View File

@@ -0,0 +1,65 @@
using Content.Server.Polymorph.Components;
using Content.Shared.Projectiles;
using Content.Shared.Sound;
using Robust.Shared.Audio;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
namespace Content.Server.Polymorph.Systems;
public partial class PolymorphableSystem
{
// Need to do this so we don't get a collection enumeration error in physics by polymorphing
// an entity we're colliding with
private Queue<PolymorphQueuedData> _queuedPolymorphUpdates = new();
public override void Update(float frameTime)
{
base.Update(frameTime);
while (_queuedPolymorphUpdates.TryDequeue(out var data))
{
if (Deleted(data.Ent))
continue;
var ent = PolymorphEntity(data.Ent, data.Polymorph);
if (ent != null)
{
SoundSystem.Play(data.Sound.GetSound(), Filter.Pvs(ent.Value, entityManager: EntityManager),
ent.Value, data.Sound.Params);
}
}
}
private void InitializeCollide()
{
SubscribeLocalEvent<PolymorphOnCollideComponent, StartCollideEvent>(OnPolymorphCollide);
}
private void OnPolymorphCollide(EntityUid uid, PolymorphOnCollideComponent component, StartCollideEvent args)
{
if (args.OurFixture.ID != SharedProjectileSystem.ProjectileFixture)
return;
var other = args.OtherFixture.Body.Owner;
if (!component.Whitelist.IsValid(other)
|| component.Blacklist != null && component.Blacklist.IsValid(other))
return;
_queuedPolymorphUpdates.Enqueue(new (other, component.Sound, component.Polymorph));
}
}
struct PolymorphQueuedData
{
public EntityUid Ent;
public SoundSpecifier Sound;
public string Polymorph;
public PolymorphQueuedData(EntityUid ent, SoundSpecifier sound, string polymorph)
{
Ent = ent;
Sound = sound;
Polymorph = polymorph;
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.Actions;
using Content.Server.Body.Components;
using Content.Server.Buckle.Components;
using Content.Server.Inventory;
using Content.Server.Mind.Commands;
@@ -12,8 +13,11 @@ using Content.Shared.Damage;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Polymorph;
using Robust.Server.Containers;
using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Physics.Dynamics;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
@@ -39,6 +43,7 @@ namespace Content.Server.Polymorph.Systems
SubscribeLocalEvent<PolymorphableComponent, ComponentStartup>(OnStartup);
SubscribeLocalEvent<PolymorphableComponent, PolymorphActionEvent>(OnPolymorphActionEvent);
InitializeCollide();
InitializeMap();
}

View File

@@ -15,6 +15,9 @@ namespace Content.Server.Projectiles.Components
[DataField("deleteOnCollide")]
public bool DeleteOnCollide { get; } = true;
[DataField("ignoreResistances")]
public bool IgnoreResistances { get; } = false;
// Get that juicy FPS hit sound
[DataField("soundHit")] public SoundSpecifier? SoundHit;

View File

@@ -40,7 +40,7 @@ namespace Content.Server.Projectiles
var otherEntity = args.OtherFixture.Body.Owner;
var modifiedDamage = _damageableSystem.TryChangeDamage(otherEntity, component.Damage);
var modifiedDamage = _damageableSystem.TryChangeDamage(otherEntity, component.Damage, component.IgnoreResistances);
component.DamagedEntity = true;
if (modifiedDamage is not null && EntityManager.EntityExists(component.Shooter))

View File

@@ -0,0 +1,33 @@
using Content.Shared.Sound;
using Robust.Shared.Audio;
namespace Content.Server.Weapon.Ranged.Components;
/// <summary>
/// Responsible for handling recharging a basic entity ammo provider over time.
/// </summary>
[RegisterComponent]
public sealed class RechargeBasicEntityAmmoComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("minRechargeCooldown")]
public float MinRechargeCooldown = 30f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("maxRechargeCooldown")]
public float MaxRechargeCooldown = 45f;
[DataField("rechargeSound")]
public SoundSpecifier RechargeSound = new SoundPathSpecifier("/Audio/Magic/forcewall.ogg")
{
Params = AudioParams.Default.WithVolume(-5f)
};
[DataField("accumulatedFrametime")]
public float AccumulatedFrameTime;
/// <summary>
/// Number of seconds until the next recharge.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public float NextRechargeTime = 0f;
}

View File

@@ -0,0 +1,75 @@
using Content.Server.Weapon.Ranged.Components;
using Content.Shared.Examine;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Systems;
using Robust.Shared.Audio;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Weapon.Ranged.Systems;
public sealed class RechargeBasicEntityAmmoSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedGunSystem _gun = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<RechargeBasicEntityAmmoComponent, ExaminedEvent>(OnExamined);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var (recharge, ammo) in
EntityQuery<RechargeBasicEntityAmmoComponent, BasicEntityAmmoProviderComponent>())
{
if (ammo.Count is null || ammo.Count == ammo.Capacity)
continue;
recharge.AccumulatedFrameTime += frameTime;
if (recharge.AccumulatedFrameTime < recharge.NextRechargeTime)
return;
recharge.AccumulatedFrameTime -= recharge.NextRechargeTime;
UpdateCooldown(recharge);
if (_gun.UpdateBasicEntityAmmoCount(ammo.Owner, ammo.Count.Value + 1, ammo))
{
SoundSystem.Play(recharge.RechargeSound.GetSound(), Filter.Pvs(recharge.Owner), recharge.Owner,
recharge.RechargeSound.Params);
}
}
}
private void OnInit(EntityUid uid, RechargeBasicEntityAmmoComponent component, ComponentInit args)
{
UpdateCooldown(component);
}
private void OnExamined(EntityUid uid, RechargeBasicEntityAmmoComponent component, ExaminedEvent args)
{
if (!TryComp<BasicEntityAmmoProviderComponent>(uid, out var ammo)
|| ammo.Count == ammo.Capacity)
{
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-full"));
return;
}
var timeLeft = component.NextRechargeTime - component.AccumulatedFrameTime;
args.PushMarkup(Loc.GetString("recharge-basic-entity-ammo-can-recharge", ("seconds", Math.Round(timeLeft, 1))));
}
private void UpdateCooldown(RechargeBasicEntityAmmoComponent component)
{
component.NextRechargeTime = _random.NextFloat(component.MinRechargeCooldown, component.MaxRechargeCooldown);
}
}