Sentry turrets - Part 4: The sentry turret and its primary systems (#35123)
* Initial commit * Removed mention of StationAiTurretComponent (for now) * Prep for moving out of draft * Fixing merge conflict * Re-added new net frequencies to AI turrets * Removed turret control content * Removed unintended change * Final tweaks * Fixed incorrect file name * Improvement to fire mode handling * Addressed review comments * Updated how turret wire panel auto-closing is handled * Ranged NPCs no longer waste shots on stunned targets * Fixed bug in tracking broken state * Addressed review comments * Bug fix * Removed unnecessary event call
This commit is contained in:
121
Content.Client/Turrets/DeployableTurretSystem.cs
Normal file
121
Content.Client/Turrets/DeployableTurretSystem.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using Content.Client.Power;
|
||||
using Content.Shared.Turrets;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Turrets;
|
||||
|
||||
public sealed partial class DeployableTurretSystem : SharedDeployableTurretSystem
|
||||
{
|
||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DeployableTurretComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<DeployableTurretComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||
SubscribeLocalEvent<DeployableTurretComponent, AppearanceChangeEvent>(OnAppearanceChange);
|
||||
}
|
||||
|
||||
private void OnComponentInit(Entity<DeployableTurretComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
ent.Comp.DeploymentAnimation = new Animation
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(ent.Comp.DeploymentLength),
|
||||
AnimationTracks = {
|
||||
new AnimationTrackSpriteFlick() {
|
||||
LayerKey = DeployableTurretVisuals.Turret,
|
||||
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.DeployingState, 0f)}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
ent.Comp.RetractionAnimation = new Animation
|
||||
{
|
||||
Length = TimeSpan.FromSeconds(ent.Comp.RetractionLength),
|
||||
AnimationTracks = {
|
||||
new AnimationTrackSpriteFlick() {
|
||||
LayerKey = DeployableTurretVisuals.Turret,
|
||||
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(ent.Comp.RetractingState, 0f)}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void OnAnimationCompleted(Entity<DeployableTurretComponent> ent, ref AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key != DeployableTurretComponent.AnimationKey)
|
||||
return;
|
||||
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
if (!_appearance.TryGetData<DeployableTurretState>(ent, DeployableTurretVisuals.Turret, out var state))
|
||||
state = ent.Comp.VisualState;
|
||||
|
||||
// Convert to terminal state
|
||||
var targetState = state & DeployableTurretState.Deployed;
|
||||
|
||||
UpdateVisuals(ent, targetState, sprite, args.AnimationPlayer);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(Entity<DeployableTurretComponent> ent, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!TryComp<AnimationPlayerComponent>(ent, out var animPlayer))
|
||||
return;
|
||||
|
||||
if (!_appearance.TryGetData<DeployableTurretState>(ent, DeployableTurretVisuals.Turret, out var state, args.Component))
|
||||
state = DeployableTurretState.Retracted;
|
||||
|
||||
UpdateVisuals(ent, state, args.Sprite, animPlayer);
|
||||
}
|
||||
|
||||
private void UpdateVisuals(Entity<DeployableTurretComponent> ent, DeployableTurretState state, SpriteComponent sprite, AnimationPlayerComponent? animPlayer = null)
|
||||
{
|
||||
if (!Resolve(ent, ref animPlayer))
|
||||
return;
|
||||
|
||||
if (_animation.HasRunningAnimation(ent, animPlayer, DeployableTurretComponent.AnimationKey))
|
||||
return;
|
||||
|
||||
if (state == ent.Comp.VisualState)
|
||||
return;
|
||||
|
||||
var targetState = state & DeployableTurretState.Deployed;
|
||||
var destinationState = ent.Comp.VisualState & DeployableTurretState.Deployed;
|
||||
|
||||
if (targetState != destinationState)
|
||||
targetState = targetState | DeployableTurretState.Retracting;
|
||||
|
||||
ent.Comp.VisualState = state;
|
||||
|
||||
// Toggle layer visibility
|
||||
sprite.LayerSetVisible(DeployableTurretVisuals.Weapon, (targetState & DeployableTurretState.Deployed) > 0);
|
||||
sprite.LayerSetVisible(PowerDeviceVisualLayers.Powered, HasAmmo(ent) && targetState == DeployableTurretState.Retracted);
|
||||
|
||||
// Change the visual state
|
||||
switch (targetState)
|
||||
{
|
||||
case DeployableTurretState.Deploying:
|
||||
_animation.Play((ent, animPlayer), (Animation)ent.Comp.DeploymentAnimation, DeployableTurretComponent.AnimationKey);
|
||||
break;
|
||||
|
||||
case DeployableTurretState.Retracting:
|
||||
_animation.Play((ent, animPlayer), (Animation)ent.Comp.RetractionAnimation, DeployableTurretComponent.AnimationKey);
|
||||
break;
|
||||
|
||||
case DeployableTurretState.Deployed:
|
||||
sprite.LayerSetState(DeployableTurretVisuals.Turret, ent.Comp.DeployedState);
|
||||
break;
|
||||
|
||||
case DeployableTurretState.Retracted:
|
||||
sprite.LayerSetState(DeployableTurretVisuals.Turret, ent.Comp.RetractedState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user