StandingStateHelper, StunSystem

This commit is contained in:
zumorica
2020-05-13 19:04:50 +02:00
parent 6737200117
commit f968128af7
6 changed files with 199 additions and 78 deletions

View File

@@ -16,7 +16,7 @@ namespace Content.Client.GameObjects.Components.Mobs
{ {
switch (state) switch (state)
{ {
case SharedSpeciesComponent.MobState.Stand: case SharedSpeciesComponent.MobState.Standing:
sprite.Rotation = 0; sprite.Rotation = 0;
break; break;
case SharedSpeciesComponent.MobState.Down: case SharedSpeciesComponent.MobState.Down:

View File

@@ -1,8 +1,14 @@
using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.Mobs;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects.Components; using Robust.Shared.GameObjects.Components;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
namespace Content.Server.GameObjects namespace Content.Server.GameObjects
{ {
@@ -96,10 +102,15 @@ namespace Content.Server.GameObjects
{ {
public void EnterState(IEntity entity) public void EnterState(IEntity entity)
{ {
if(entity.TryGetComponent(out StunnableComponent stun))
stun.CancelAll();
StandingStateHelper.Down(entity);
} }
public void ExitState(IEntity entity) public void ExitState(IEntity entity)
{ {
StandingStateHelper.Standing(entity);
} }
public bool IsConscious => false; public bool IsConscious => false;
@@ -167,11 +178,10 @@ namespace Content.Server.GameObjects
{ {
public void EnterState(IEntity entity) public void EnterState(IEntity entity)
{ {
if (entity.TryGetComponent(out AppearanceComponent appearance)) if(entity.TryGetComponent(out StunnableComponent stun))
{ stun.CancelAll();
var newState = SharedSpeciesComponent.MobState.Down;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState); StandingStateHelper.Down(entity);
}
if (entity.TryGetComponent(out CollidableComponent collidable)) if (entity.TryGetComponent(out CollidableComponent collidable))
{ {
@@ -181,11 +191,7 @@ namespace Content.Server.GameObjects
public void ExitState(IEntity entity) public void ExitState(IEntity entity)
{ {
if (entity.TryGetComponent(out AppearanceComponent appearance)) StandingStateHelper.Standing(entity);
{
var newState = SharedSpeciesComponent.MobState.Stand;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
}
if (entity.TryGetComponent(out CollidableComponent collidable)) if (entity.TryGetComponent(out CollidableComponent collidable))
{ {

View File

@@ -2,9 +2,14 @@ using System;
using System.Threading; using System.Threading;
using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems;
using Content.Server.Interfaces.GameObjects; using Content.Server.Interfaces.GameObjects;
using Content.Server.Mobs;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Mobs;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Timers; using Robust.Shared.Interfaces.Timers;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -13,109 +18,111 @@ using Timer = Robust.Shared.Timers.Timer;
namespace Content.Server.GameObjects.Components.Mobs namespace Content.Server.GameObjects.Components.Mobs
{ {
[RegisterComponent] [RegisterComponent]
public class StunnableComponent : Component, IActionBlocker public class StunnableComponent : Component, IActionBlocker, IAttackHand
{ {
[Dependency] private IEntitySystemManager _entitySystemManager;
[Dependency] private ITimerManager _timerManager; [Dependency] private ITimerManager _timerManager;
private bool _stunned = false; private bool _stunned = false;
private bool _knocked = false; private bool _knocked = false;
private bool _canHelp = true;
private int _stunCapMs = 20000; private float _stunCap = 20f;
private int _knockdownCapMs = 20000; private float _knockdownCap = 20f;
private float _helpKnockdownRemove = 1f;
private float _helpInterval = 1f;
private Timer _stunTimer; private float _stunnedTimer = 0f;
private Timer _knockdownTimer; private float _knockdownTimer = 0f;
private CancellationTokenSource _stunTimerCancellation;
private CancellationTokenSource _knockdownTimerCancellation;
public override string Name => "Stunnable"; public override string Name => "Stunnable";
[ViewVariables] public bool Stunned => _stunned; [ViewVariables] public bool Stunned => _stunned;
[ViewVariables] public bool KnockedDown => _knocked; [ViewVariables] public bool KnockedDown => _knocked;
public void Stun(int milliseconds) public void Stun(float seconds)
{ {
if (_stunTimer != null) seconds = Math.Min(seconds + _stunnedTimer, _stunCap);
{
_stunTimerCancellation.Cancel();
milliseconds += _stunTimer.Time;
}
milliseconds = Math.Min(milliseconds, _stunCapMs); StandingStateHelper.DropAllItemsInHands(Owner);
DropItemsInHands();
_stunned = true; _stunned = true;
_stunTimerCancellation = new CancellationTokenSource(); _stunnedTimer = seconds;
_stunTimer = new Timer(milliseconds, false, OnStunTimerFired);
_timerManager.AddTimer(_stunTimer, _stunTimerCancellation.Token);
} }
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
Timer.Spawn(10000, () => Paralyze(5000)); Timer.Spawn(10000, () => Paralyze(15f));
} }
public void Knockdown(int milliseconds) public void Knockdown(float seconds)
{ {
if (_knockdownTimer != null) seconds = MathF.Min(_knockdownTimer + seconds, _knockdownCap);
{
_knockdownTimerCancellation.Cancel();
milliseconds += _knockdownTimer.Time;
}
if (Owner.TryGetComponent(out AppearanceComponent appearance)) StandingStateHelper.Down(Owner);
{
var state = SharedSpeciesComponent.MobState.Down;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, state);
}
milliseconds = Math.Min(milliseconds, _knockdownCapMs);
DropItemsInHands();
_knocked = true; _knocked = true;
_knockdownTimerCancellation = new CancellationTokenSource(); _knockdownTimer = seconds;
_knockdownTimer = new Timer(milliseconds, false, OnKnockdownTimerFired);
_timerManager.AddTimer(_knockdownTimer, _knockdownTimerCancellation.Token);
} }
private void DropItemsInHands() public void Paralyze(float seconds)
{ {
if (!Owner.TryGetComponent(out IHandsComponent hands)) return; Stun(seconds);
Knockdown(seconds);
foreach (var heldItem in hands.GetAllHeldItems())
{
hands.Drop(heldItem.Owner);
}
} }
private void OnStunTimerFired() /// <summary>
/// Used when
/// </summary>
public void CancelAll()
{ {
_stunned = false;
_stunTimer = null;
_stunTimerCancellation = null;
}
private void OnKnockdownTimerFired()
{
if (Owner.TryGetComponent(out AppearanceComponent appearance))
{
var state = SharedSpeciesComponent.MobState.Stand;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, state);
}
_knocked = false; _knocked = false;
_knockdownTimer = null; _stunned = false;
_knockdownTimerCancellation = null;
_knockdownTimer = 0f;
_stunnedTimer = 0f;
} }
public void Paralyze(int milliseconds) public bool AttackHand(AttackHandEventArgs eventArgs)
{ {
Stun(milliseconds); if (!_canHelp || KnockedDown)
Knockdown(milliseconds); return false;
_canHelp = false;
Timer.Spawn(((int)_helpInterval*1000), () => _canHelp = true);
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>()
.Play("/Audio/effects/thudswoosh.ogg", Owner, AudioHelpers.WithVariation(0.5f));
_knockdownTimer -= _helpKnockdownRemove;
return true;
}
public void Update(float delta)
{
if (_knocked)
{
_knockdownTimer -= delta;
if (_knockdownTimer <= 0f)
{
StandingStateHelper.Standing(Owner);
_knocked = false;
}
}
if (_stunned)
{
_stunnedTimer -= delta;
if (_stunnedTimer <= 0)
{
_stunned = false;
}
}
} }
#region ActionBlockers #region ActionBlockers

View File

@@ -0,0 +1,27 @@
using Content.Server.GameObjects.Components.Mobs;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.EntitySystems
{
public class StunSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
EntityQuery = new TypeEntityQuery(typeof(StunnableComponent));
}
public override void Update(float frameTime)
{
base.Update(frameTime);
foreach (var entity in RelevantEntities)
{
entity.GetComponent<StunnableComponent>().Update(frameTime);
}
}
}
}

View File

@@ -0,0 +1,81 @@
using Content.Server.Interfaces.GameObjects;
using Content.Shared.Audio;
using Content.Shared.GameObjects.Components.Mobs;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Mobs
{
public static class StandingStateHelper
{
/// <summary>
/// Set's the mob standing state to down.
/// </summary>
/// <param name="entity">The mob in question</param>
/// <param name="playSound">Whether to play a sound when falling down or not</param>
/// <param name="dropItems">Whether to make the mob drop all the items on his hands</param>
/// <returns>False if the mob was already downed or couldn't set the state</returns>
public static bool Down(IEntity entity, bool playSound = true, bool dropItems = true)
{
if (!entity.TryGetComponent(out AppearanceComponent appearance)) return false;
appearance.TryGetData<SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var oldState);
var newState = SharedSpeciesComponent.MobState.Down;
if (newState == oldState)
return false;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
if (playSound)
PlaySoundCollection("bodyfall", AudioHelpers.WithVariation(0.5f));
if(dropItems)
DropAllItemsInHands(entity);
return true;
}
/// <summary>
/// Sets the mob's standing state to standing.
/// </summary>
/// <param name="entity">The mob in question.</param>
/// <returns>False if the mob was already standing or couldn't set the state</returns>
public static bool Standing(IEntity entity)
{
if (!entity.TryGetComponent(out AppearanceComponent appearance)) return false;
appearance.TryGetData<SharedSpeciesComponent.MobState>(SharedSpeciesComponent.MobVisuals.RotationState, out var oldState);
var newState = SharedSpeciesComponent.MobState.Standing;
if (newState == oldState)
return false;
appearance.SetData(SharedSpeciesComponent.MobVisuals.RotationState, newState);
return true;
}
public static void DropAllItemsInHands(IEntity entity)
{
if (!entity.TryGetComponent(out IHandsComponent hands)) return;
foreach (var heldItem in hands.GetAllHeldItems())
{
hands.Drop(heldItem.Owner);
}
}
private static void PlaySoundCollection(string name, AudioParams parameters = default)
{
var soundCollection = IoCManager.Resolve<IPrototypeManager>().Index<SoundCollectionPrototype>(name);
var file = IoCManager.Resolve<IRobustRandom>().Pick(soundCollection.PickFiles);
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>()
.Play(file, parameters);
}
}
}

View File

@@ -20,7 +20,7 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// <summary> /// <summary>
/// Mob is standing up /// Mob is standing up
/// </summary> /// </summary>
Stand, Standing,
/// <summary> /// <summary>
/// Mob is laying down /// Mob is laying down