using System.Linq;
using Content.Shared.Damage.Prototypes;
using Content.Shared.Damage.Systems;
using Content.Shared.FixedPoint;
using Content.Shared.Ghost;
using Content.Shared.Mind;
using Content.Shared.Random.Helpers;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Shared.GhostTypes;
public sealed class GhostSpriteStateSystem : EntitySystem
{
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
///
/// It goes through an entity damage and assigns them a sprite according to the highest damage type/s
///
public void SetGhostSprite(Entity ent, EntityUid mind)
{
if (!Resolve(ent, ref ent.Comp))
return;
if (!TryComp(ent, out var appearance) || !HasComp(mind))
return;
var damageTypes = new Dictionary, FixedPoint2>();
ProtoId? specialCase = null;
if (!TryComp(mind, out var storedDamage))
return;
if (storedDamage.DamagePerGroup != null && storedDamage.Damage != null)
{
damageTypes = _damageable.GetDamages(storedDamage.DamagePerGroup, storedDamage.Damage);
}
specialCase = storedDamage.SpecialCauseOfDeath;
Dirty(mind, storedDamage);
var damageTypesSorted = damageTypes.OrderByDescending(x => x.Value).ToDictionary();
if (damageTypesSorted.Count == 0)
return;
var highestType = damageTypesSorted.First().Key; // We only need 1 of the values
// TODO: Replace with RandomPredicted once the engine PR is merged
var seed = SharedRandomExtensions.HashCodeCombine((int)_timing.CurTick.Value, GetNetEntity(ent).Id);
var rand = new System.Random(seed);
ProtoId? spriteState = null;
if (specialCase != null) // Possible special cases like death by an explosion
{
var prototype = _proto.Index(specialCase);
spriteState = specialCase + rand.Next(prototype.NumOfStates);
}
else if (ent.Comp.DamageMap.TryGetValue(highestType, out var spriteAmount))
{
spriteState = highestType + rand.Next(spriteAmount);
}
if (spriteState != null)
_appearance.SetData(ent, GhostVisuals.Damage, ent.Comp.Prefix + spriteState, appearance);
}
}