Refactor ExaminableDamage (#38978)
* Remove prototype caching in ExaminableDamageComponent * Replace ExaminableDamagePrototype with LocalizedDatasetPrototype * Allow null
This commit is contained in:
@@ -1,16 +1,18 @@
|
|||||||
using Content.Shared.Damage.Prototypes;
|
using Content.Shared.Dataset;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.Damage.Components;
|
namespace Content.Server.Damage.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This component shows entity damage severity when it is examined by player.
|
/// This component shows entity damage severity when it is examined by player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class ExaminableDamageComponent : Component
|
public sealed partial class ExaminableDamageComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("messages", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<ExaminableDamagePrototype>))]
|
/// <summary>
|
||||||
public string? MessagesProtoId;
|
/// ID of the <see cref="LocalizedDatasetPrototype"/> containing messages to display a different damage levels.
|
||||||
|
/// The first message will be used at 0 damage with the others equally distributed across the range from undamaged to fully damaged.
|
||||||
public ExaminableDamagePrototype? MessagesProto;
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<LocalizedDatasetPrototype>? Messages;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using System.Linq;
|
using Content.Server.Damage.Components;
|
||||||
using Content.Server.Damage.Components;
|
|
||||||
using Content.Server.Destructible;
|
using Content.Server.Destructible;
|
||||||
using Content.Server.Destructible.Thresholds.Triggers;
|
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Damage.Prototypes;
|
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Rounding;
|
using Content.Shared.Rounding;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -12,59 +9,42 @@ namespace Content.Server.Damage.Systems;
|
|||||||
|
|
||||||
public sealed class ExaminableDamageSystem : EntitySystem
|
public sealed class ExaminableDamageSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly DestructibleSystem _destructible = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<ExaminableDamageComponent, ComponentInit>(OnInit);
|
|
||||||
SubscribeLocalEvent<ExaminableDamageComponent, ExaminedEvent>(OnExamine);
|
SubscribeLocalEvent<ExaminableDamageComponent, ExaminedEvent>(OnExamine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, ExaminableDamageComponent component, ComponentInit args)
|
private void OnExamine(Entity<ExaminableDamageComponent> ent, ref ExaminedEvent args)
|
||||||
{
|
{
|
||||||
if (component.MessagesProtoId == null)
|
if (!_prototype.TryIndex(ent.Comp.Messages, out var proto) || proto.Values.Count == 0)
|
||||||
return;
|
return;
|
||||||
component.MessagesProto = _prototype.Index<ExaminableDamagePrototype>(component.MessagesProtoId);
|
|
||||||
|
var percent = GetDamagePercent(ent);
|
||||||
|
var level = ContentHelpers.RoundToNearestLevels(percent, 1, proto.Values.Count - 1);
|
||||||
|
var msg = Loc.GetString(proto.Values[level]);
|
||||||
|
args.PushMarkup(msg, -99);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamine(EntityUid uid, ExaminableDamageComponent component, ExaminedEvent args)
|
/// <summary>
|
||||||
|
/// Returns a value between 0 and 1 representing how damaged the entity is,
|
||||||
|
/// where 0 is undamaged and 1 is fully damaged.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>How damaged the entity is from 0 to 1</returns>
|
||||||
|
private float GetDamagePercent(Entity<ExaminableDamageComponent> ent)
|
||||||
{
|
{
|
||||||
if (component.MessagesProto == null)
|
if (!TryComp<DamageableComponent>(ent, out var damageable))
|
||||||
return;
|
|
||||||
|
|
||||||
var messages = component.MessagesProto.Messages;
|
|
||||||
if (messages.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var level = GetDamageLevel(uid, component);
|
|
||||||
var msg = Loc.GetString(messages[level]);
|
|
||||||
args.PushMarkup(msg,-99);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetDamageLevel(EntityUid uid, ExaminableDamageComponent? component = null,
|
|
||||||
DamageableComponent? damageable = null, DestructibleComponent? destructible = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref component, ref damageable, ref destructible))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (component.MessagesProto == null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
var maxLevels = component.MessagesProto.Messages.Length - 1;
|
|
||||||
if (maxLevels <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
var trigger = (DamageTrigger?) destructible.Thresholds
|
|
||||||
.LastOrDefault(threshold => threshold.Trigger is DamageTrigger)?.Trigger;
|
|
||||||
if (trigger == null)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var damage = damageable.TotalDamage;
|
var damage = damageable.TotalDamage;
|
||||||
var damageThreshold = trigger.Damage;
|
var damageThreshold = _destructible.DestroyedAt(ent);
|
||||||
var fraction = damageThreshold == 0 ? 0f : (float) damage / damageThreshold;
|
|
||||||
|
|
||||||
var level = ContentHelpers.RoundToNearestLevels(fraction, 1, maxLevels);
|
if (damageThreshold == 0)
|
||||||
return level;
|
return 0;
|
||||||
|
|
||||||
|
return (damage / damageThreshold).Float();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using Robust.Shared.Prototypes;
|
|
||||||
|
|
||||||
namespace Content.Shared.Damage.Prototypes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prototype for examinable damage messages.
|
|
||||||
/// </summary>
|
|
||||||
[Prototype]
|
|
||||||
public sealed partial class ExaminableDamagePrototype : IPrototype
|
|
||||||
{
|
|
||||||
[IdDataField]
|
|
||||||
public string ID { get; private set; } = default!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of damage messages IDs sorted by severity.
|
|
||||||
/// First one describes fully intact entity.
|
|
||||||
/// Last one describes almost destroyed.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("messages")]
|
|
||||||
public string[] Messages = {};
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
- type: examinableDamage
|
- type: localizedDataset
|
||||||
id: WindowMessages
|
id: WindowMessages
|
||||||
messages:
|
values:
|
||||||
- comp-window-damaged-1
|
prefix: comp-window-damaged-
|
||||||
- comp-window-damaged-2
|
count: 6
|
||||||
- comp-window-damaged-3
|
|
||||||
- comp-window-damaged-4
|
|
||||||
- comp-window-damaged-5
|
|
||||||
- comp-window-damaged-6
|
|
||||||
|
|||||||
Reference in New Issue
Block a user