Damage visualizer for simple mobs (#1332)
Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com> Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using DrawDepth = Content.Shared.GameObjects.DrawDepth;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Mobs
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class DamageStateVisualizer : AppearanceVisualizer
|
||||
{
|
||||
private DamageStateVisualData _data = DamageStateVisualData.Normal;
|
||||
private Dictionary<DamageStateVisualData, string> _stateMap = new Dictionary<DamageStateVisualData,string>();
|
||||
private int? _originalDrawDepth = null;
|
||||
|
||||
public override void LoadData(YamlMappingNode node)
|
||||
{
|
||||
base.LoadData(node);
|
||||
if (node.TryGetNode("normal", out var normal))
|
||||
{
|
||||
_stateMap.Add(DamageStateVisualData.Normal, normal.AsString());
|
||||
}
|
||||
|
||||
if (node.TryGetNode("crit", out var crit))
|
||||
{
|
||||
_stateMap.Add(DamageStateVisualData.Crit, crit.AsString());
|
||||
}
|
||||
|
||||
if (node.TryGetNode("dead", out var dead))
|
||||
{
|
||||
_stateMap.Add(DamageStateVisualData.Dead, dead.AsString());
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnChangeData(AppearanceComponent component)
|
||||
{
|
||||
base.OnChangeData(component);
|
||||
var sprite = component.Owner.GetComponent<ISpriteComponent>();
|
||||
if (!component.TryGetData(DamageStateVisuals.State, out DamageStateVisualData data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_data == data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_data = data;
|
||||
|
||||
if (_stateMap.TryGetValue(_data, out var state))
|
||||
{
|
||||
sprite.LayerSetState(DamageStateVisualLayers.Base, state);
|
||||
}
|
||||
|
||||
// So they don't draw over mobs anymore
|
||||
if (_data == DamageStateVisualData.Dead)
|
||||
{
|
||||
_originalDrawDepth = sprite.DrawDepth;
|
||||
sprite.DrawDepth = (int) DrawDepth.FloorObjects;
|
||||
}
|
||||
else if (_originalDrawDepth != null)
|
||||
{
|
||||
sprite.DrawDepth = _originalDrawDepth.Value;
|
||||
_originalDrawDepth = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DamageStateVisualLayers
|
||||
{
|
||||
Base
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ namespace Content.Server.AI.Utility.AiLogic
|
||||
_planner = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AiActionSystem>();
|
||||
if (SelfEntity.TryGetComponent(out DamageableComponent damageableComponent))
|
||||
{
|
||||
damageableComponent.DamageThresholdPassed += DeathHandle;
|
||||
damageableComponent.DamageThresholdPassed += DamageThresholdHandle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,22 +125,25 @@ namespace Content.Server.AI.Utility.AiLogic
|
||||
// TODO: If DamageableComponent removed still need to unsubscribe?
|
||||
if (SelfEntity.TryGetComponent(out DamageableComponent damageableComponent))
|
||||
{
|
||||
damageableComponent.DamageThresholdPassed -= DeathHandle;
|
||||
damageableComponent.DamageThresholdPassed -= DamageThresholdHandle;
|
||||
}
|
||||
|
||||
var currentOp = CurrentAction?.ActionOperators.Peek();
|
||||
currentOp?.Shutdown(Outcome.Failed);
|
||||
}
|
||||
|
||||
private void DeathHandle(object sender, DamageThresholdPassedEventArgs eventArgs)
|
||||
private void DamageThresholdHandle(object sender, DamageThresholdPassedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.DamageThreshold.ThresholdType == ThresholdType.Death)
|
||||
if (!SelfEntity.TryGetComponent(out SpeciesComponent speciesComponent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (speciesComponent.CurrentDamageState is DeadState)
|
||||
{
|
||||
_isDead = true;
|
||||
}
|
||||
|
||||
// TODO: If we get healed - double-check what it should be
|
||||
if (eventArgs.DamageThreshold.ThresholdType == ThresholdType.None)
|
||||
else
|
||||
{
|
||||
_isDead = false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Server.Mobs;
|
||||
using Content.Shared.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
|
||||
@@ -25,6 +27,8 @@ namespace Content.Server.GameObjects
|
||||
{
|
||||
public void EnterState(IEntity entity)
|
||||
{
|
||||
entity.TryGetComponent(out AppearanceComponent appearanceComponent);
|
||||
appearanceComponent?.SetData(DamageStateVisuals.State, DamageStateVisualData.Normal);
|
||||
}
|
||||
|
||||
public void ExitState(IEntity entity)
|
||||
@@ -104,6 +108,8 @@ namespace Content.Server.GameObjects
|
||||
if(entity.TryGetComponent(out StunnableComponent stun))
|
||||
stun.CancelAll();
|
||||
|
||||
entity.TryGetComponent(out AppearanceComponent appearanceComponent);
|
||||
appearanceComponent?.SetData(DamageStateVisuals.State, DamageStateVisualData.Crit);
|
||||
StandingStateHelper.Down(entity);
|
||||
}
|
||||
|
||||
@@ -186,6 +192,8 @@ namespace Content.Server.GameObjects
|
||||
stun.CancelAll();
|
||||
|
||||
StandingStateHelper.Down(entity);
|
||||
entity.TryGetComponent(out AppearanceComponent appearanceComponent);
|
||||
appearanceComponent?.SetData(DamageStateVisuals.State, DamageStateVisualData.Dead);
|
||||
|
||||
if (entity.TryGetComponent(out ICollidableComponent collidable))
|
||||
{
|
||||
|
||||
@@ -634,6 +634,10 @@ namespace Content.Server.GameObjects.EntitySystems.AI.Steering
|
||||
// God there's so many ways to do this
|
||||
// err for now we'll just assume the first entity is the center and just add a vector for it
|
||||
var collisionEntity = _entityManager.GetEntity(uid);
|
||||
|
||||
//Pathfinding updates are deferred so this may not be done yet.
|
||||
if (collisionEntity.Deleted) continue;
|
||||
|
||||
// if we're moving in the same direction then ignore
|
||||
// So if 2 entities are moving towards each other and both detect a collision they'll both move in the same direction
|
||||
// i.e. towards the right
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Mobs
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public enum DamageStateVisuals
|
||||
{
|
||||
State
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DamageStateVisualData
|
||||
{
|
||||
Normal,
|
||||
Crit,
|
||||
Dead
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Hacky for the stress test so don't even consider adding to this
|
||||
- type: entity
|
||||
save: false
|
||||
name: Xeno
|
||||
name: Xeno hunter
|
||||
id: XenoMob_Content
|
||||
description: They mostly come at night. Mostly.
|
||||
drawdepth: Mobs
|
||||
@@ -14,15 +14,16 @@
|
||||
- left
|
||||
- right
|
||||
- type: MovementSpeedModifier
|
||||
# Organs
|
||||
- type: InteractionOutline
|
||||
- type: Sprite
|
||||
drawdepth: Mobs
|
||||
sprite: Mobs/Species/xeno.rsi
|
||||
state: running
|
||||
layers:
|
||||
- map: ["enum.DamageStateVisualLayers.Base"]
|
||||
state: running
|
||||
sprite: Mobs/Species/xeno_hunter.rsi
|
||||
- type: Icon
|
||||
sprite: Mobs/Species/xeno.rsi
|
||||
state: running
|
||||
sprite: Mobs/Species/xeno_hunter.rsi
|
||||
state: standing
|
||||
- type: Clickable
|
||||
- type: Physics
|
||||
mass: 85
|
||||
@@ -48,13 +49,16 @@
|
||||
- type: Damageable
|
||||
- type: CombatMode
|
||||
- type: Teleportable
|
||||
- type: CharacterInfo
|
||||
- type: FootstepSound
|
||||
- type: HumanoidAppearance
|
||||
- type: Stunnable
|
||||
- type: AnimationPlayer
|
||||
- type: UnarmedCombat
|
||||
range: 1.5
|
||||
arcwidth: 0
|
||||
arc: claw
|
||||
damage: 90
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: DamageStateVisualizer2D
|
||||
normal: running
|
||||
dead: dead
|
||||
|
||||
BIN
Resources/Textures/Mobs/Species/xeno_hunter.rsi/dead.png
Normal file
BIN
Resources/Textures/Mobs/Species/xeno_hunter.rsi/dead.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -14,6 +14,20 @@
|
||||
{
|
||||
"name": "standing",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "dead",
|
||||
"directions": 1
|
||||
},
|
||||
{
|
||||
"name": "sleeping",
|
||||
"directions": 1,
|
||||
"delays": [
|
||||
[
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
BIN
Resources/Textures/Mobs/Species/xeno_hunter.rsi/sleeping.png
Normal file
BIN
Resources/Textures/Mobs/Species/xeno_hunter.rsi/sleeping.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user