Muzzle flash enhancements (#9527)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using Content.Client.Items;
|
using Content.Client.Items;
|
||||||
using Content.Client.Weapons.Ranged.Components;
|
using Content.Client.Weapons.Ranged.Components;
|
||||||
using Content.Shared.Camera;
|
using Content.Shared.Camera;
|
||||||
|
using Content.Shared.Spawners.Components;
|
||||||
using Content.Shared.Weapons.Ranged;
|
using Content.Shared.Weapons.Ranged;
|
||||||
using Content.Shared.Weapons.Ranged.Components;
|
using Content.Shared.Weapons.Ranged.Components;
|
||||||
using Content.Shared.Weapons.Ranged.Events;
|
using Content.Shared.Weapons.Ranged.Events;
|
||||||
@@ -10,11 +11,11 @@ using Robust.Client.GameObjects;
|
|||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Input;
|
using Robust.Client.Input;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
|
using Robust.Shared.Animations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Input;
|
using Robust.Shared.Input;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Timing;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem;
|
using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem;
|
||||||
|
|
||||||
@@ -26,7 +27,6 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
[Dependency] private readonly AnimationPlayerSystem _animPlayer = default!;
|
[Dependency] private readonly AnimationPlayerSystem _animPlayer = default!;
|
||||||
[Dependency] private readonly EffectSystem _effects = default!;
|
|
||||||
[Dependency] private readonly InputSystem _inputSystem = default!;
|
[Dependency] private readonly InputSystem _inputSystem = default!;
|
||||||
[Dependency] private readonly SharedCameraRecoilSystem _recoil = default!;
|
[Dependency] private readonly SharedCameraRecoilSystem _recoil = default!;
|
||||||
|
|
||||||
@@ -43,10 +43,10 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
{
|
{
|
||||||
overlayManager.AddOverlay(new GunSpreadOverlay(
|
overlayManager.AddOverlay(new GunSpreadOverlay(
|
||||||
EntityManager,
|
EntityManager,
|
||||||
IoCManager.Resolve<IEyeManager>(),
|
_eyeManager,
|
||||||
IoCManager.Resolve<IGameTiming>(),
|
Timing,
|
||||||
IoCManager.Resolve<IInputManager>(),
|
_inputManager,
|
||||||
IoCManager.Resolve<IPlayerManager>(),
|
_player,
|
||||||
this));
|
this));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -63,6 +63,7 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
UpdatesOutsidePrediction = true;
|
UpdatesOutsidePrediction = true;
|
||||||
SubscribeLocalEvent<AmmoCounterComponent, ItemStatusCollectMessage>(OnAmmoCounterCollect);
|
SubscribeLocalEvent<AmmoCounterComponent, ItemStatusCollectMessage>(OnAmmoCounterCollect);
|
||||||
|
SubscribeLocalEvent<GunComponent, MuzzleFlashEvent>(OnMuzzleFlash);
|
||||||
|
|
||||||
// Plays animated effects on the client.
|
// Plays animated effects on the client.
|
||||||
SubscribeNetworkEvent<HitscanEvent>(OnHitscan);
|
SubscribeNetworkEvent<HitscanEvent>(OnHitscan);
|
||||||
@@ -71,6 +72,11 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
InitializeSpentAmmo();
|
InitializeSpentAmmo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnMuzzleFlash(EntityUid uid, GunComponent component, MuzzleFlashEvent args)
|
||||||
|
{
|
||||||
|
CreateEffect(uid, args);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnHitscan(HitscanEvent ev)
|
private void OnHitscan(HitscanEvent ev)
|
||||||
{
|
{
|
||||||
// ALL I WANT IS AN ANIMATED EFFECT
|
// ALL I WANT IS AN ANIMATED EFFECT
|
||||||
@@ -227,8 +233,82 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
PopupSystem.PopupEntity(message, uid.Value, Filter.Entities(user.Value));
|
PopupSystem.PopupEntity(message, uid.Value, Filter.Entities(user.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CreateEffect(EffectSystemMessage message, EntityUid? user = null)
|
protected override void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null)
|
||||||
{
|
{
|
||||||
_effects.CreateEffect(message);
|
if (!Timing.IsFirstTimePredicted || !TryComp<TransformComponent>(uid, out var xform)) return;
|
||||||
|
var ent = Spawn(message.Prototype, xform.Coordinates);
|
||||||
|
|
||||||
|
var effectXform = Transform(ent);
|
||||||
|
effectXform.LocalRotation -= MathF.PI / 2;
|
||||||
|
effectXform.LocalPosition += new Vector2(0f, -0.5f);
|
||||||
|
|
||||||
|
var lifetime = 0.4f;
|
||||||
|
|
||||||
|
if (TryComp<TimedDespawnComponent>(uid, out var despawn))
|
||||||
|
{
|
||||||
|
lifetime = despawn.Lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
var anim = new Animation()
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(lifetime),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackComponentProperty
|
||||||
|
{
|
||||||
|
ComponentType = typeof(SpriteComponent),
|
||||||
|
Property = nameof(SpriteComponent.Color),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.White.WithAlpha(1f), 0),
|
||||||
|
new AnimationTrackProperty.KeyFrame(Color.White.WithAlpha(0f), lifetime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_animPlayer.Play(ent, anim, "muzzle-flash");
|
||||||
|
var light = EnsureComp<PointLightComponent>(uid);
|
||||||
|
|
||||||
|
light.Enabled = true;
|
||||||
|
light.Color = Color.FromHex("#cc8e2b");
|
||||||
|
light.Radius = 2f;
|
||||||
|
light.Energy = 5f;
|
||||||
|
|
||||||
|
var animTwo = new Animation()
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(lifetime),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackComponentProperty
|
||||||
|
{
|
||||||
|
ComponentType = typeof(PointLightComponent),
|
||||||
|
Property = nameof(PointLightComponent.Energy),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(5f, 0),
|
||||||
|
new AnimationTrackProperty.KeyFrame(0f, lifetime)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AnimationTrackComponentProperty
|
||||||
|
{
|
||||||
|
ComponentType = typeof(PointLightComponent),
|
||||||
|
Property = nameof(PointLightComponent.Enabled),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(true, 0),
|
||||||
|
new AnimationTrackProperty.KeyFrame(false, lifetime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var uidPlayer = EnsureComp<AnimationPlayerComponent>(uid);
|
||||||
|
|
||||||
|
_animPlayer.Stop(uid, uidPlayer, "muzzle-flash-light");
|
||||||
|
_animPlayer.Play(uid, uidPlayer, animTwo,"muzzle-flash-light");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace Content.Server.Weapon.Ranged.Systems;
|
|||||||
|
|
||||||
public sealed partial class GunSystem : SharedGunSystem
|
public sealed partial class GunSystem : SharedGunSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly EffectSystem _effects = default!;
|
|
||||||
[Dependency] private readonly StaminaSystem _stamina = default!;
|
[Dependency] private readonly StaminaSystem _stamina = default!;
|
||||||
|
|
||||||
public const float DamagePitchVariation = MeleeWeaponSystem.DamagePitchVariation;
|
public const float DamagePitchVariation = MeleeWeaponSystem.DamagePitchVariation;
|
||||||
@@ -215,17 +214,14 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
|
|
||||||
protected override void Popup(string message, EntityUid? uid, EntityUid? user) {}
|
protected override void Popup(string message, EntityUid? uid, EntityUid? user) {}
|
||||||
|
|
||||||
protected override void CreateEffect(EffectSystemMessage message, EntityUid? user = null)
|
protected override void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null)
|
||||||
{
|
{
|
||||||
// TODO: Fucking bad
|
var filter = Filter.Pvs(uid, entityManager: EntityManager);
|
||||||
|
|
||||||
if (TryComp<ActorComponent>(user, out var actor))
|
if (TryComp<ActorComponent>(user, out var actor))
|
||||||
{
|
filter.RemovePlayer(actor.PlayerSession);
|
||||||
_effects.CreateParticle(message, actor.PlayerSession);
|
|
||||||
}
|
RaiseNetworkEvent(message, filter);
|
||||||
else
|
|
||||||
{
|
|
||||||
_effects.CreateParticle(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayImpactSound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound)
|
public void PlayImpactSound(EntityUid otherEntity, DamageSpecifier? modifiedDamage, SoundSpecifier? weaponSound, bool forceWeaponSound)
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ public class AmmoComponent : Component, IShootable
|
|||||||
{
|
{
|
||||||
// Muzzle flash stored on ammo because if we swap a gun to whatever we may want to override it.
|
// Muzzle flash stored on ammo because if we swap a gun to whatever we may want to override it.
|
||||||
|
|
||||||
[ViewVariables, DataField("muzzleFlash")]
|
[ViewVariables(VVAccess.ReadWrite), DataField("muzzleFlash", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
public ResourcePath? MuzzleFlash = new ResourcePath("Objects/Weapons/Guns/Projectiles/projectiles.rsi/muzzle_bullet.png");
|
public string? MuzzleFlash = "MuzzleFlashEffect";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
17
Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs
Normal file
17
Content.Shared/Weapons/Ranged/Events/MuzzleFlashEvent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.Weapons.Ranged.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised whenever a muzzle flash client-side entity needs to be spawned.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class MuzzleFlashEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public string Prototype;
|
||||||
|
|
||||||
|
public MuzzleFlashEvent(string prototype)
|
||||||
|
{
|
||||||
|
Prototype = prototype;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,13 +49,11 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
|
|
||||||
protected ISawmill Sawmill = default!;
|
protected ISawmill Sawmill = default!;
|
||||||
|
|
||||||
private const float MuzzleFlashLifetime = 1f;
|
|
||||||
private const float InteractNextFire = 0.3f;
|
private const float InteractNextFire = 0.3f;
|
||||||
private const double SafetyNextFire = 0.5;
|
private const double SafetyNextFire = 0.5;
|
||||||
private const float EjectOffset = 0.4f;
|
private const float EjectOffset = 0.4f;
|
||||||
protected const string AmmoExamineColor = "yellow";
|
protected const string AmmoExamineColor = "yellow";
|
||||||
protected const string FireRateExamineColor = "yellow";
|
protected const string FireRateExamineColor = "yellow";
|
||||||
protected const string SafetyExamineColor = "lightgreen";
|
|
||||||
protected const string ModeExamineColor = "cyan";
|
protected const string ModeExamineColor = "cyan";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -345,36 +343,17 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
|
|
||||||
protected void MuzzleFlash(EntityUid gun, AmmoComponent component, EntityUid? user = null)
|
protected void MuzzleFlash(EntityUid gun, AmmoComponent component, EntityUid? user = null)
|
||||||
{
|
{
|
||||||
var sprite = component.MuzzleFlash?.ToString();
|
var sprite = component.MuzzleFlash;
|
||||||
|
|
||||||
// TODO: AAAAA THIS MUZZLE FLASH CODE IS BAD
|
|
||||||
// NEEDS EFFECTS TO NOT BE BAD!
|
|
||||||
if (sprite == null)
|
if (sprite == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var time = Timing.CurTime;
|
var ev = new MuzzleFlashEvent(sprite);
|
||||||
var deathTime = time + TimeSpan.FromSeconds(MuzzleFlashLifetime);
|
|
||||||
// Offset the sprite so it actually looks like it's coming from the gun
|
|
||||||
var offset = new Vector2(0.0f, -0.5f);
|
|
||||||
|
|
||||||
var message = new EffectSystemMessage
|
CreateEffect(gun, ev, user);
|
||||||
{
|
|
||||||
EffectSprite = sprite,
|
|
||||||
Born = time,
|
|
||||||
DeathTime = deathTime,
|
|
||||||
AttachedEntityUid = gun,
|
|
||||||
AttachedOffset = offset,
|
|
||||||
//Rotated from east facing
|
|
||||||
Rotation = -MathF.PI / 2f,
|
|
||||||
Color = Vector4.Multiply(new Vector4(255, 255, 255, 255), 1.0f),
|
|
||||||
ColorDelta = new Vector4(0, 0, 0, -1500f),
|
|
||||||
Shaded = false
|
|
||||||
};
|
|
||||||
|
|
||||||
CreateEffect(message, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void CreateEffect(EffectSystemMessage message, EntityUid? user = null);
|
protected abstract void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null);
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
protected sealed class GunComponentState : ComponentState
|
protected sealed class GunComponentState : ComponentState
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
- type: entity
|
||||||
|
id: MuzzleFlashEffect
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.4
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
drawdepth: Effects
|
||||||
|
layers:
|
||||||
|
- shader: unshaded
|
||||||
|
map: ["enum.EffectLayers.Unshaded"]
|
||||||
|
sprite: Objects/Weapons/Guns/Projectiles/projectiles.rsi
|
||||||
|
state: muzzle_bullet
|
||||||
|
- type: EffectVisuals
|
||||||
|
- type: AnimationPlayer
|
||||||
|
|
||||||
# One bullet to bring them all into the darkness and bind them
|
# One bullet to bring them all into the darkness and bind them
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BaseBullet
|
id: BaseBullet
|
||||||
|
|||||||
Reference in New Issue
Block a user