Refactor ExaminableDamage (#38978)
* Remove prototype caching in ExaminableDamageComponent * Replace ExaminableDamagePrototype with LocalizedDatasetPrototype * Allow null
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Content.Shared.Dataset;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Damage.Components;
|
||||
|
||||
@@ -9,8 +9,10 @@ namespace Content.Server.Damage.Components;
|
||||
[RegisterComponent]
|
||||
public sealed partial class ExaminableDamageComponent : Component
|
||||
{
|
||||
[DataField("messages", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<ExaminableDamagePrototype>))]
|
||||
public string? MessagesProtoId;
|
||||
|
||||
public ExaminableDamagePrototype? MessagesProto;
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </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.Thresholds.Triggers;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Rounding;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -12,59 +9,42 @@ namespace Content.Server.Damage.Systems;
|
||||
|
||||
public sealed class ExaminableDamageSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DestructibleSystem _destructible = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<ExaminableDamageComponent, ComponentInit>(OnInit);
|
||||
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)
|
||||
return;
|
||||
component.MessagesProto = _prototype.Index<ExaminableDamagePrototype>(component.MessagesProtoId);
|
||||
}
|
||||
|
||||
private void OnExamine(EntityUid uid, ExaminableDamageComponent component, ExaminedEvent args)
|
||||
{
|
||||
if (component.MessagesProto == null)
|
||||
if (!_prototype.TryIndex(ent.Comp.Messages, out var proto) || proto.Values.Count == 0)
|
||||
return;
|
||||
|
||||
var messages = component.MessagesProto.Messages;
|
||||
if (messages.Length == 0)
|
||||
return;
|
||||
|
||||
var level = GetDamageLevel(uid, component);
|
||||
var msg = Loc.GetString(messages[level]);
|
||||
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 int GetDamageLevel(EntityUid uid, ExaminableDamageComponent? component = null,
|
||||
DamageableComponent? damageable = null, DestructibleComponent? destructible = null)
|
||||
/// <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 (!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)
|
||||
if (!TryComp<DamageableComponent>(ent, out var damageable))
|
||||
return 0;
|
||||
|
||||
var damage = damageable.TotalDamage;
|
||||
var damageThreshold = trigger.Damage;
|
||||
var fraction = damageThreshold == 0 ? 0f : (float) damage / damageThreshold;
|
||||
var damageThreshold = _destructible.DestroyedAt(ent);
|
||||
|
||||
var level = ContentHelpers.RoundToNearestLevels(fraction, 1, maxLevels);
|
||||
return level;
|
||||
if (damageThreshold == 0)
|
||||
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
|
||||
messages:
|
||||
- comp-window-damaged-1
|
||||
- comp-window-damaged-2
|
||||
- comp-window-damaged-3
|
||||
- comp-window-damaged-4
|
||||
- comp-window-damaged-5
|
||||
- comp-window-damaged-6
|
||||
values:
|
||||
prefix: comp-window-damaged-
|
||||
count: 6
|
||||
|
||||
Reference in New Issue
Block a user