Sprite Movement working with AI movement (#33494)
* FINALLY * Update animals.yml
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Movement.Systems;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Client.Movement.Systems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls the switching of motion and standing still animation
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ClientSpriteMovementSystem : SharedSpriteMovementSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
|
private EntityQuery<SpriteComponent> _spriteQuery;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
_spriteQuery = GetEntityQuery<SpriteComponent>();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SpriteMovementComponent, AfterAutoHandleStateEvent>(OnAfterAutoHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAfterAutoHandleState(Entity<SpriteMovementComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||||
|
{
|
||||||
|
if (!_spriteQuery.TryGetComponent(ent, out var sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.IsMoving)
|
||||||
|
{
|
||||||
|
foreach (var (layer, state) in ent.Comp.MovementLayers)
|
||||||
|
{
|
||||||
|
sprite.LayerSetData(layer, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var (layer, state) in ent.Comp.NoMovementLayers)
|
||||||
|
{
|
||||||
|
sprite.LayerSetData(layer, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using Content.Shared.Movement.Components;
|
|
||||||
using Content.Shared.Movement.Events;
|
|
||||||
using Content.Shared.Movement.Systems;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Shared.Timing;
|
|
||||||
|
|
||||||
namespace Content.Client.Movement.Systems;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles setting sprite states based on whether an entity has movement input.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SpriteMovementSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
|
||||||
|
|
||||||
private EntityQuery<SpriteComponent> _spriteQuery;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<SpriteMovementComponent, MoveInputEvent>(OnSpriteMoveInput);
|
|
||||||
_spriteQuery = GetEntityQuery<SpriteComponent>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSpriteMoveInput(EntityUid uid, SpriteMovementComponent component, ref MoveInputEvent args)
|
|
||||||
{
|
|
||||||
if (!_timing.IsFirstTimePredicted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var oldMoving = (SharedMoverController.GetNormalizedMovement(args.OldMovement) & MoveButtons.AnyDirection) != MoveButtons.None;
|
|
||||||
var moving = (SharedMoverController.GetNormalizedMovement(args.Entity.Comp.HeldMoveButtons) & MoveButtons.AnyDirection) != MoveButtons.None;
|
|
||||||
|
|
||||||
if (oldMoving == moving || !_spriteQuery.TryGetComponent(uid, out var sprite))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (moving)
|
|
||||||
{
|
|
||||||
foreach (var (layer, state) in component.MovementLayers)
|
|
||||||
{
|
|
||||||
sprite.LayerSetData(layer, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var (layer, state) in component.NoMovementLayers)
|
|
||||||
{
|
|
||||||
sprite.LayerSetData(layer, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
Content.Server/Movement/Systems/SpriteMovementSystem.cs
Normal file
7
Content.Server/Movement/Systems/SpriteMovementSystem.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.Movement.Systems;
|
||||||
|
|
||||||
|
public sealed class SpriteMovementSystem : SharedSpriteMovementSystem
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -253,7 +253,7 @@ public sealed partial class NPCSteeringSystem
|
|||||||
|
|
||||||
if (!targetCoordinates.IsValid(EntityManager))
|
if (!targetCoordinates.IsValid(EntityManager))
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
steering.Status = SteeringStatus.NoPath;
|
steering.Status = SteeringStatus.NoPath;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -263,7 +263,7 @@ public sealed partial class NPCSteeringSystem
|
|||||||
// Can't make it again.
|
// Can't make it again.
|
||||||
if (ourMap.MapId != targetMap.MapId)
|
if (ourMap.MapId != targetMap.MapId)
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
steering.Status = SteeringStatus.NoPath;
|
steering.Status = SteeringStatus.NoPath;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Shared.Climbing.Systems;
|
|||||||
using Content.Shared.CombatMode;
|
using Content.Shared.CombatMode;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Content.Shared.NPC;
|
using Content.Shared.NPC;
|
||||||
using Content.Shared.NPC.Components;
|
using Content.Shared.NPC.Components;
|
||||||
@@ -207,6 +208,9 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
if (EntityManager.TryGetComponent(uid, out InputMoverComponent? controller))
|
if (EntityManager.TryGetComponent(uid, out InputMoverComponent? controller))
|
||||||
{
|
{
|
||||||
controller.CurTickSprintMovement = Vector2.Zero;
|
controller.CurTickSprintMovement = Vector2.Zero;
|
||||||
|
|
||||||
|
var ev = new SpriteMoveEvent(false);
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
component.PathfindToken?.Cancel();
|
component.PathfindToken?.Cancel();
|
||||||
@@ -270,7 +274,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDirection(InputMoverComponent component, NPCSteeringComponent steering, Vector2 value, bool clear = true)
|
private void SetDirection(EntityUid uid, InputMoverComponent component, NPCSteeringComponent steering, Vector2 value, bool clear = true)
|
||||||
{
|
{
|
||||||
if (clear && value.Equals(Vector2.Zero))
|
if (clear && value.Equals(Vector2.Zero))
|
||||||
{
|
{
|
||||||
@@ -282,6 +286,9 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
component.CurTickSprintMovement = value;
|
component.CurTickSprintMovement = value;
|
||||||
component.LastInputTick = _timing.CurTick;
|
component.LastInputTick = _timing.CurTick;
|
||||||
component.LastInputSubTick = ushort.MaxValue;
|
component.LastInputSubTick = ushort.MaxValue;
|
||||||
|
|
||||||
|
var ev = new SpriteMoveEvent(true);
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -297,7 +304,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
{
|
{
|
||||||
if (Deleted(steering.Coordinates.EntityId))
|
if (Deleted(steering.Coordinates.EntityId))
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
steering.Status = SteeringStatus.NoPath;
|
steering.Status = SteeringStatus.NoPath;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -305,14 +312,14 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
// No path set from pathfinding or the likes.
|
// No path set from pathfinding or the likes.
|
||||||
if (steering.Status == SteeringStatus.NoPath)
|
if (steering.Status == SteeringStatus.NoPath)
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't move at all, just noop input.
|
// Can't move at all, just noop input.
|
||||||
if (!mover.CanMove)
|
if (!mover.CanMove)
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
steering.Status = SteeringStatus.NoPath;
|
steering.Status = SteeringStatus.NoPath;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -341,7 +348,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
|
|
||||||
if (steering.CanSeek && !TrySeek(uid, mover, steering, body, xform, offsetRot, moveSpeed, interest, frameTime, ref forceSteer))
|
if (steering.CanSeek && !TrySeek(uid, mover, steering, body, xform, offsetRot, moveSpeed, interest, frameTime, ref forceSteer))
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, Vector2.Zero);
|
SetDirection(uid, mover, steering, Vector2.Zero);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +361,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
|
|
||||||
if (!forceSteer)
|
if (!forceSteer)
|
||||||
{
|
{
|
||||||
SetDirection(mover, steering, steering.LastSteerDirection, false);
|
SetDirection(uid, mover, steering, steering.LastSteerDirection, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +398,7 @@ public sealed partial class NPCSteeringSystem : SharedNPCSteeringSystem
|
|||||||
|
|
||||||
steering.LastSteerDirection = resultDirection;
|
steering.LastSteerDirection = resultDirection;
|
||||||
DebugTools.Assert(!float.IsNaN(resultDirection.X));
|
DebugTools.Assert(!float.IsNaN(resultDirection.X));
|
||||||
SetDirection(mover, steering, resultDirection, false);
|
SetDirection(uid, mover, steering, resultDirection, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityCoordinates GetCoordinates(PathPoly poly)
|
private EntityCoordinates GetCoordinates(PathPoly poly)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Content.Shared.Movement.Components;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates a sprite layer based on whether an entity is moving via input or not.
|
/// Updates a sprite layer based on whether an entity is moving via input or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||||
public sealed partial class SpriteMovementComponent : Component
|
public sealed partial class SpriteMovementComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -19,4 +19,7 @@ public sealed partial class SpriteMovementComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public Dictionary<string, PrototypeLayerData> NoMovementLayers = new();
|
public Dictionary<string, PrototypeLayerData> NoMovementLayers = new();
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool IsMoving;
|
||||||
}
|
}
|
||||||
|
|||||||
15
Content.Shared/Movement/Events/SpriteMoveEvent.cs
Normal file
15
Content.Shared/Movement/Events/SpriteMoveEvent.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Content.Shared.Movement.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on an entity whenever it should change movement sprite
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly struct SpriteMoveEvent
|
||||||
|
{
|
||||||
|
public readonly bool IsMoving = false;
|
||||||
|
|
||||||
|
public SpriteMoveEvent(bool isMoving)
|
||||||
|
{
|
||||||
|
IsMoving = isMoving;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,6 +96,9 @@ namespace Content.Shared.Movement.Systems
|
|||||||
entity.Comp.HeldMoveButtons = buttons;
|
entity.Comp.HeldMoveButtons = buttons;
|
||||||
RaiseLocalEvent(entity, ref moveEvent);
|
RaiseLocalEvent(entity, ref moveEvent);
|
||||||
Dirty(entity, entity.Comp);
|
Dirty(entity, entity.Comp);
|
||||||
|
|
||||||
|
var ev = new SpriteMoveEvent(entity.Comp.HeldMoveButtons != MoveButtons.None);
|
||||||
|
RaiseLocalEvent(entity, ref ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMoverHandleState(Entity<InputMoverComponent> entity, ref ComponentHandleState args)
|
private void OnMoverHandleState(Entity<InputMoverComponent> entity, ref ComponentHandleState args)
|
||||||
@@ -119,6 +122,9 @@ namespace Content.Shared.Movement.Systems
|
|||||||
var moveEvent = new MoveInputEvent(entity, entity.Comp.HeldMoveButtons);
|
var moveEvent = new MoveInputEvent(entity, entity.Comp.HeldMoveButtons);
|
||||||
entity.Comp.HeldMoveButtons = state.HeldMoveButtons;
|
entity.Comp.HeldMoveButtons = state.HeldMoveButtons;
|
||||||
RaiseLocalEvent(entity.Owner, ref moveEvent);
|
RaiseLocalEvent(entity.Owner, ref moveEvent);
|
||||||
|
|
||||||
|
var ev = new SpriteMoveEvent(entity.Comp.HeldMoveButtons != MoveButtons.None);
|
||||||
|
RaiseLocalEvent(entity, ref ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Movement.Events;
|
||||||
|
|
||||||
|
namespace Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
|
public abstract class SharedSpriteMovementSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SpriteMovementComponent, SpriteMoveEvent>(OnSpriteMoveInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSpriteMoveInput(Entity<SpriteMovementComponent> ent, ref SpriteMoveEvent args)
|
||||||
|
{
|
||||||
|
if (ent.Comp.IsMoving == args.IsMoving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.IsMoving = args.IsMoving;
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2283,24 +2283,10 @@
|
|||||||
# Code unique spider prototypes or combine them all into one spider and get a
|
# Code unique spider prototypes or combine them all into one spider and get a
|
||||||
# random sprite state when you spawn it.
|
# random sprite state when you spawn it.
|
||||||
- type: entity
|
- type: entity
|
||||||
name: tarantula
|
|
||||||
parent: [ SimpleMobBase, MobCombat ]
|
parent: [ SimpleMobBase, MobCombat ]
|
||||||
id: MobGiantSpider
|
id: MobSpiderBase
|
||||||
description: Widely recognized to be the literal worst thing in existence.
|
abstract: true
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
|
||||||
drawdepth: Mobs
|
|
||||||
layers:
|
|
||||||
- map: ["enum.DamageStateVisualLayers.Base", "movement"]
|
|
||||||
state: tarantula
|
|
||||||
sprite: Mobs/Animals/spider.rsi
|
|
||||||
- type: SpriteMovement
|
|
||||||
movementLayers:
|
|
||||||
movement:
|
|
||||||
state: tarantula-moving
|
|
||||||
noMovementLayers:
|
|
||||||
movement:
|
|
||||||
state: tarantula
|
|
||||||
- type: Physics
|
- type: Physics
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
fixtures:
|
fixtures:
|
||||||
@@ -2313,14 +2299,6 @@
|
|||||||
- MobMask
|
- MobMask
|
||||||
layer:
|
layer:
|
||||||
- MobLayer
|
- MobLayer
|
||||||
- type: DamageStateVisuals
|
|
||||||
states:
|
|
||||||
Alive:
|
|
||||||
Base: tarantula
|
|
||||||
Critical:
|
|
||||||
Base: tarantula_dead
|
|
||||||
Dead:
|
|
||||||
Base: tarantula_dead
|
|
||||||
- type: Butcherable
|
- type: Butcherable
|
||||||
spawned:
|
spawned:
|
||||||
- id: FoodMeatSpider
|
- id: FoodMeatSpider
|
||||||
@@ -2332,15 +2310,6 @@
|
|||||||
thresholds:
|
thresholds:
|
||||||
0: Alive
|
0: Alive
|
||||||
90: Dead
|
90: Dead
|
||||||
- type: MeleeWeapon
|
|
||||||
altDisarm: false
|
|
||||||
angle: 0
|
|
||||||
animation: WeaponArcBite
|
|
||||||
soundHit:
|
|
||||||
path: /Audio/Effects/bite.ogg
|
|
||||||
damage:
|
|
||||||
types:
|
|
||||||
Piercing: 6
|
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
melee:
|
melee:
|
||||||
@@ -2402,10 +2371,9 @@
|
|||||||
Burn: -0.07
|
Burn: -0.07
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: tarantula
|
parent: MobSpiderBase
|
||||||
parent: MobGiantSpider
|
id: MobSpiderAngryBase
|
||||||
id: MobGiantSpiderAngry
|
abstract: true
|
||||||
suffix: Angry
|
|
||||||
components:
|
components:
|
||||||
- type: NpcFactionMember
|
- type: NpcFactionMember
|
||||||
factions:
|
factions:
|
||||||
@@ -2424,9 +2392,52 @@
|
|||||||
settings: short
|
settings: short
|
||||||
- type: GhostTakeoverAvailable
|
- type: GhostTakeoverAvailable
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: tarantula
|
||||||
|
parent: MobSpiderBase
|
||||||
|
id: MobGiantSpider
|
||||||
|
description: Widely recognized to be the literal worst thing in existence.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
drawdepth: Mobs
|
||||||
|
layers:
|
||||||
|
- map: ["enum.DamageStateVisualLayers.Base", "movement"]
|
||||||
|
state: tarantula
|
||||||
|
sprite: Mobs/Animals/spider.rsi
|
||||||
|
- type: SpriteMovement
|
||||||
|
movementLayers:
|
||||||
|
movement:
|
||||||
|
state: tarantula-moving
|
||||||
|
noMovementLayers:
|
||||||
|
movement:
|
||||||
|
state: tarantula
|
||||||
|
- type: DamageStateVisuals
|
||||||
|
states:
|
||||||
|
Alive:
|
||||||
|
Base: tarantula
|
||||||
|
Critical:
|
||||||
|
Base: tarantula_dead
|
||||||
|
Dead:
|
||||||
|
Base: tarantula_dead
|
||||||
|
- type: MeleeWeapon
|
||||||
|
altDisarm: false
|
||||||
|
angle: 0
|
||||||
|
animation: WeaponArcBite
|
||||||
|
soundHit:
|
||||||
|
path: /Audio/Effects/bite.ogg
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Piercing: 6
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent:
|
||||||
|
- MobGiantSpider
|
||||||
|
- MobSpiderAngryBase
|
||||||
|
id: MobGiantSpiderAngry
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: clown spider
|
name: clown spider
|
||||||
parent: MobGiantSpiderAngry
|
parent: MobSpiderAngryBase
|
||||||
id: MobClownSpider
|
id: MobClownSpider
|
||||||
description: Combines the two most terrifying things in existence, spiders and clowns.
|
description: Combines the two most terrifying things in existence, spiders and clowns.
|
||||||
components:
|
components:
|
||||||
|
|||||||
Reference in New Issue
Block a user