Damage rework (#2525)

* Make damage work through messages and events, make destructible not inherit ruinable or reference damageable

* Copy sound logic to destructible component for now

* Fix typo

* Fix prototype error

* Remove breakable component damageable reference

* Remove breakable construction reference

* Remove ruinable component

* Move thresholds to individual components and away from damageable

* Add threshold property to damageable component code

* Add thresholds to destructible component, add states to damageable, remove damage container, fix up mob states

* Being alive isn't normal

* Fix not reading the id

* Merge fixes

* YAML fixes

* Grammar moment

* Remove unnecessary dependency

* Update thresholds doc

* Change naming of thresholds to states in MobStateComponent

* Being alive is once again normal

* Make DamageState a byte

* Bring out classes structs and enums from DestructibleComponent

* Add test for destructible thresholds

* Merge fixes

* More merge fixes and fix rejuvenate test

* Remove IMobState.IsConscious

* More merge fixes someone please god review this shit already

* Fix rejuvenate test

* Update outdated destructible in YAML

* Fix repeatedly entering the current state

* Fix repeatedly entering the current state, add Threshold.TriggersOnce and expand test

* Update saltern
This commit is contained in:
DrSmugleaf
2020-12-07 14:52:55 +01:00
committed by GitHub
parent 9a187629ba
commit 02bca4c0d8
133 changed files with 3195 additions and 5897 deletions

View File

@@ -9,20 +9,17 @@ using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.Components.Mobs.State
{
public class CriticalState : SharedCriticalState
public class CriticalMobState : SharedCriticalMobState
{
public override void EnterState(IEntity entity)
{
base.EnterState(entity);
if (entity.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(DamageStateVisuals.State, DamageState.Critical);
}
if (entity.TryGetComponent(out ServerAlertsComponent status))
{
status.ShowAlert(AlertType.HumanCrit); //Todo: combine humancrit-0 and humancrit-1 into a gif and display it
}
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.AddOverlay(SharedOverlayID.GradientCircleMaskOverlay);
@@ -38,12 +35,12 @@ namespace Content.Server.GameObjects.Components.Mobs.State
public override void ExitState(IEntity entity)
{
base.ExitState(entity);
if (entity.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.ClearOverlays();
}
}
public override void UpdateState(IEntity entity) { }
}
}

View File

@@ -10,10 +10,12 @@ using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.Components.Mobs.State
{
public class DeadState : SharedDeadState
public class DeadMobState : SharedDeadMobState
{
public override void EnterState(IEntity entity)
{
base.EnterState(entity);
if (entity.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(DamageStateVisuals.State, DamageState.Dead);
@@ -44,6 +46,8 @@ namespace Content.Server.GameObjects.Components.Mobs.State
public override void ExitState(IEntity entity)
{
base.ExitState(entity);
if (entity.TryGetComponent(out IPhysicsComponent physics))
{
physics.CanCollide = true;
@@ -54,7 +58,5 @@ namespace Content.Server.GameObjects.Components.Mobs.State
overlay.ClearOverlays();
}
}
public override void UpdateState(IEntity entity) { }
}
}

View File

@@ -1,71 +1,22 @@
using System.Collections.Generic;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.Components.Mobs.State;
using Robust.Shared.GameObjects;
namespace Content.Server.GameObjects.Components.Mobs.State
{
[RegisterComponent]
[ComponentReference(typeof(SharedMobStateManagerComponent))]
public class MobStateManagerComponent : SharedMobStateManagerComponent
[ComponentReference(typeof(SharedMobStateComponent))]
[ComponentReference(typeof(IMobStateComponent))]
public class MobStateComponent : SharedMobStateComponent
{
private readonly Dictionary<DamageState, IMobState> _behavior = new()
{
{DamageState.Alive, new NormalState()},
{DamageState.Critical, new CriticalState()},
{DamageState.Dead, new DeadState()}
};
private DamageState _currentDamageState;
protected override IReadOnlyDictionary<DamageState, IMobState> Behavior => _behavior;
public override IMobState CurrentMobState { get; protected set; }
public override DamageState CurrentDamageState
{
get => _currentDamageState;
protected set
{
if (_currentDamageState == value)
{
return;
}
if (_currentDamageState != DamageState.Invalid)
{
CurrentMobState.ExitState(Owner);
}
_currentDamageState = value;
CurrentMobState = Behavior[CurrentDamageState];
CurrentMobState.EnterState(Owner);
Dirty();
}
}
public override void OnRemove()
{
// TODO: Might want to add an OnRemove() to IMobState since those are where these components are being used
base.OnRemove();
if (Owner.TryGetComponent(out ServerAlertsComponent status))
{
status.ClearAlert(AlertType.HumanHealth);
}
if (Owner.TryGetComponent(out ServerOverlayEffectsComponent overlay))
{
overlay.ClearOverlays();
}
}
public override ComponentState GetComponentState()
{
return new MobStateManagerComponentState(CurrentDamageState);
base.OnRemove();
}
}
}

View File

@@ -0,0 +1,56 @@
#nullable enable
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs.State;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.Components.Mobs.State
{
public class NormalMobState : SharedNormalMobState
{
public override void EnterState(IEntity entity)
{
base.EnterState(entity);
EntitySystem.Get<StandingStateSystem>().Standing(entity);
if (entity.TryGetComponent(out AppearanceComponent? appearance))
{
appearance.SetData(DamageStateVisuals.State, DamageState.Alive);
}
}
public override void UpdateState(IEntity entity, int threshold)
{
base.UpdateState(entity, threshold);
if (!entity.TryGetComponent(out IDamageableComponent? damageable))
{
return;
}
if (!entity.TryGetComponent(out ServerAlertsComponent? alerts))
{
return;
}
if (!entity.TryGetComponent(out IMobStateComponent? stateComponent))
{
return;
}
short modifier = 0;
if (stateComponent.TryGetEarliestIncapacitatedState(threshold, out _, out var earliestThreshold))
{
modifier = (short) (damageable.TotalDamage / (earliestThreshold / 7f));
}
alerts.ShowAlert(AlertType.HumanHealth, modifier);
}
}
}

View File

@@ -1,73 +0,0 @@
using Content.Server.GameObjects.Components.Damage;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Alert;
using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Mobs.State;
using Robust.Server.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects.Components.Mobs.State
{
public class NormalState : SharedNormalState
{
public override void EnterState(IEntity entity)
{
EntitySystem.Get<StandingStateSystem>().Standing(entity);
if (entity.TryGetComponent(out AppearanceComponent appearance))
{
appearance.SetData(DamageStateVisuals.State, DamageState.Alive);
}
UpdateState(entity);
}
public override void ExitState(IEntity entity) { }
public override void UpdateState(IEntity entity)
{
if (!entity.TryGetComponent(out ServerAlertsComponent status))
{
return;
}
if (!entity.TryGetComponent(out IDamageableComponent damageable))
{
status.ShowAlert(AlertType.HumanHealth, 0);
return;
}
// TODO
switch (damageable)
{
case RuinableComponent ruinable:
{
if (!ruinable.Thresholds.TryGetValue(DamageState.Dead, out var threshold))
{
return;
}
var modifier = (short) (ruinable.TotalDamage / (threshold / 7f));
status.ShowAlert(AlertType.HumanHealth, modifier);
break;
}
default:
{
if (!damageable.Thresholds.TryGetValue(DamageState.Critical, out var threshold))
{
return;
}
var modifier = (short) (damageable.TotalDamage / (threshold / 7f));
status.ShowAlert(AlertType.HumanHealth, modifier);
break;
}
}
}
}
}