Remove damage flags (#4189)
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Damage.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class AddDamageFlagCommand : DamageFlagCommand
|
||||
{
|
||||
public override string Command => "adddamageflag";
|
||||
public override string Description => "Adds a damage flag to your entity or another.";
|
||||
public override string Help => $"Usage: {Command} <flag> / {Command} <entityUid> <flag>";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (!TryGetEntity(shell, player, args, true, out var entity, out var flag, out var damageable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
damageable.AddFlag(flag);
|
||||
shell.WriteLine($"Added damage flag {flag} to entity {entity.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Damage.Commands
|
||||
{
|
||||
public abstract class DamageFlagCommand : IConsoleCommand
|
||||
{
|
||||
public abstract string Command { get; }
|
||||
public abstract string Description { get; }
|
||||
public abstract string Help { get; }
|
||||
|
||||
public abstract void Execute(IConsoleShell shell, string argStr, string[] args);
|
||||
|
||||
public bool TryGetEntity(
|
||||
IConsoleShell shell,
|
||||
IPlayerSession? player,
|
||||
string[] args,
|
||||
bool adding,
|
||||
[NotNullWhen(true)] out IEntity? entity,
|
||||
out DamageFlag flag,
|
||||
[NotNullWhen(true)] out IDamageableComponent? damageable)
|
||||
{
|
||||
entity = null;
|
||||
flag = DamageFlag.None;
|
||||
damageable = null;
|
||||
|
||||
IEntity? parsedEntity;
|
||||
DamageFlag parsedFlag;
|
||||
IDamageableComponent? parsedDamageable;
|
||||
|
||||
switch (args.Length)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
shell.WriteLine("An entity needs to be specified when the command isn't used by a player.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.AttachedEntity == null)
|
||||
{
|
||||
shell.WriteLine("An entity needs to be specified when you aren't attached to an entity.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse(args[0], true, out parsedFlag))
|
||||
{
|
||||
shell.WriteLine($"{args[0]} is not a valid damage flag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
parsedEntity = player.AttachedEntity;
|
||||
flag = parsedFlag;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (!EntityUid.TryParse(args[0], out var id))
|
||||
{
|
||||
shell.WriteLine($"{args[0]} isn't a valid entity id.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var entityManager = IoCManager.Resolve<IEntityManager>();
|
||||
if (!entityManager.TryGetEntity(id, out parsedEntity))
|
||||
{
|
||||
shell.WriteLine($"No entity found with id {id}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse(args[1], true, out parsedFlag))
|
||||
{
|
||||
shell.WriteLine($"{args[1]} is not a valid damage flag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
shell.WriteLine(Help);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parsedEntity.TryGetComponent(out parsedDamageable))
|
||||
{
|
||||
shell.WriteLine($"Entity {parsedEntity.Name} doesn't have a {nameof(IDamageableComponent)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parsedDamageable.HasFlag(parsedFlag) && adding)
|
||||
{
|
||||
shell.WriteLine($"Entity {parsedEntity.Name} already has damage flag {parsedFlag}.");
|
||||
return false;
|
||||
}
|
||||
else if (!parsedDamageable.HasFlag(parsedFlag) && !adding)
|
||||
{
|
||||
shell.WriteLine($"Entity {parsedEntity.Name} doesn't have damage flag {parsedFlag}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
entity = parsedEntity;
|
||||
flag = parsedFlag;
|
||||
damageable = parsedDamageable;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#nullable enable
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
|
||||
namespace Content.Server.Damage.Commands
|
||||
{
|
||||
[AdminCommand(AdminFlags.Fun)]
|
||||
public class RemoveDamageFlagCommand : DamageFlagCommand
|
||||
{
|
||||
public override string Command => "removedamageflag";
|
||||
public override string Description => "Removes a damage flag from your entity or another.";
|
||||
public override string Help => $"Usage: {Command} <flag> / {Command} <entityUid> <flag>";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = shell.Player as IPlayerSession;
|
||||
if (!TryGetEntity(shell, player, args, false, out var entity, out var flag, out var damageable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
damageable.RemoveFlag(flag);
|
||||
shell.WriteLine($"Removed damage flag {flag} from entity {entity.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.GameObjects.Components.Atmos;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Resistances;
|
||||
using Content.Shared.GameTicking;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -35,7 +37,8 @@ namespace Content.Server.Damage
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
damageable.AddFlag(DamageFlag.Invulnerable);
|
||||
damageable.SupportedTypes.Clear();
|
||||
damageable.SupportedClasses.Clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -60,7 +63,15 @@ namespace Content.Server.Damage
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
damageable.RemoveFlag(DamageFlag.Invulnerable);
|
||||
if (old.SupportedTypes != null)
|
||||
{
|
||||
damageable.SupportedTypes.UnionWith(old.SupportedTypes);
|
||||
}
|
||||
|
||||
if (old.SupportedClasses != null)
|
||||
{
|
||||
damageable.SupportedClasses.UnionWith(old.SupportedClasses);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -91,10 +102,21 @@ namespace Content.Server.Damage
|
||||
{
|
||||
Entity = entity;
|
||||
MovedByPressure = entity.IsMovedByPressure();
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
SupportedTypes = damageable.SupportedTypes.ToHashSet();
|
||||
SupportedClasses = damageable.SupportedClasses.ToHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
public IEntity Entity { get; }
|
||||
|
||||
public bool MovedByPressure { get; }
|
||||
|
||||
public HashSet<DamageType>? SupportedTypes { get; }
|
||||
|
||||
public HashSet<DamageClass>? SupportedClasses { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,67 +35,32 @@ namespace Content.Shared.Damage.Components
|
||||
|
||||
private readonly Dictionary<DamageType, int> _damageList = DamageTypeExtensions.ToNewDictionary();
|
||||
|
||||
private readonly HashSet<DamageType> _supportedTypes = new();
|
||||
|
||||
private readonly HashSet<DamageClass> _supportedClasses = new();
|
||||
|
||||
[DataField("flags")]
|
||||
private DamageFlag _flags;
|
||||
|
||||
[DataField("resistances")] public string ResistanceSetId = DefaultResistanceSet;
|
||||
|
||||
// TODO DAMAGE Use as default values, specify overrides in a separate property through yaml for better (de)serialization
|
||||
[ViewVariables] [DataField("damageContainer")] public string DamageContainerId { get; set; } = DefaultDamageContainer;
|
||||
|
||||
[ViewVariables] private ResistanceSet Resistances { get; set; } = new();
|
||||
[ViewVariables] public ResistanceSet Resistances { get; set; } = new();
|
||||
|
||||
// TODO DAMAGE Cache this
|
||||
[ViewVariables] public int TotalDamage => _damageList.Values.Sum();
|
||||
|
||||
[ViewVariables]
|
||||
public IReadOnlyDictionary<DamageClass, int> DamageClasses =>
|
||||
DamageTypeExtensions.ToClassDictionary(_damageList);
|
||||
[ViewVariables] public IReadOnlyDictionary<DamageClass, int> DamageClasses => _damageList.ToClassDictionary();
|
||||
|
||||
[ViewVariables] public IReadOnlyDictionary<DamageType, int> DamageTypes => _damageList;
|
||||
|
||||
public DamageFlag Flags
|
||||
{
|
||||
get => _flags;
|
||||
private set
|
||||
{
|
||||
if (_flags == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
[ViewVariables] public HashSet<DamageType> SupportedTypes { get; } = new();
|
||||
|
||||
_flags = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFlag(DamageFlag flag)
|
||||
{
|
||||
Flags |= flag;
|
||||
}
|
||||
|
||||
public bool HasFlag(DamageFlag flag)
|
||||
{
|
||||
return Flags.HasFlag(flag);
|
||||
}
|
||||
|
||||
public void RemoveFlag(DamageFlag flag)
|
||||
{
|
||||
Flags &= ~flag;
|
||||
}
|
||||
[ViewVariables] public HashSet<DamageClass> SupportedClasses { get; } = new();
|
||||
|
||||
public bool SupportsDamageClass(DamageClass @class)
|
||||
{
|
||||
return _supportedClasses.Contains(@class);
|
||||
return SupportedClasses.Contains(@class);
|
||||
}
|
||||
|
||||
public bool SupportsDamageType(DamageType type)
|
||||
{
|
||||
return _supportedTypes.Contains(type);
|
||||
return SupportedTypes.Contains(type);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
@@ -107,12 +72,12 @@ namespace Content.Shared.Damage.Components
|
||||
// TODO DAMAGE Serialize damage done and resistance changes
|
||||
var damagePrototype = prototypeManager.Index<DamageContainerPrototype>(DamageContainerId);
|
||||
|
||||
_supportedClasses.Clear();
|
||||
_supportedTypes.Clear();
|
||||
SupportedClasses.Clear();
|
||||
SupportedTypes.Clear();
|
||||
|
||||
DamageContainerId = damagePrototype.ID;
|
||||
_supportedClasses.UnionWith(damagePrototype.SupportedClasses);
|
||||
_supportedTypes.UnionWith(damagePrototype.SupportedTypes);
|
||||
SupportedClasses.UnionWith(damagePrototype.SupportedClasses);
|
||||
SupportedTypes.UnionWith(damagePrototype.SupportedTypes);
|
||||
|
||||
var resistancePrototype = prototypeManager.Index<ResistanceSetPrototype>(ResistanceSetId);
|
||||
Resistances = new ResistanceSet(resistancePrototype);
|
||||
@@ -127,7 +92,7 @@ namespace Content.Shared.Damage.Components
|
||||
|
||||
public override ComponentState GetComponentState(ICommonSession player)
|
||||
{
|
||||
return new DamageableComponentState(_damageList, _flags);
|
||||
return new DamageableComponentState(_damageList);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
@@ -145,8 +110,6 @@ namespace Content.Shared.Damage.Components
|
||||
{
|
||||
_damageList[type] = damage;
|
||||
}
|
||||
|
||||
_flags = state.Flags;
|
||||
}
|
||||
|
||||
public int GetDamage(DamageType type)
|
||||
@@ -203,7 +166,7 @@ namespace Content.Shared.Damage.Components
|
||||
|
||||
var damageClass = type.ToClass();
|
||||
|
||||
if (_supportedClasses.Contains(damageClass))
|
||||
if (SupportedClasses.Contains(damageClass))
|
||||
{
|
||||
var old = _damageList[type] = newValue;
|
||||
_damageList[type] = newValue;
|
||||
@@ -227,7 +190,7 @@ namespace Content.Shared.Damage.Components
|
||||
|
||||
public void Heal()
|
||||
{
|
||||
foreach (var type in _supportedTypes)
|
||||
foreach (var type in SupportedTypes)
|
||||
{
|
||||
Heal(type);
|
||||
}
|
||||
@@ -240,11 +203,6 @@ namespace Content.Shared.Damage.Components
|
||||
IEntity? source = null,
|
||||
DamageChangeParams? extraParams = null)
|
||||
{
|
||||
if (amount > 0 && HasFlag(DamageFlag.Invulnerable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SupportsDamageType(type))
|
||||
{
|
||||
return false;
|
||||
@@ -291,11 +249,6 @@ namespace Content.Shared.Damage.Components
|
||||
IEntity? source = null,
|
||||
DamageChangeParams? extraParams = null)
|
||||
{
|
||||
if (amount > 0 && HasFlag(DamageFlag.Invulnerable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SupportsDamageClass(@class))
|
||||
{
|
||||
return false;
|
||||
@@ -374,7 +327,7 @@ namespace Content.Shared.Damage.Components
|
||||
|
||||
public bool SetDamage(DamageType type, int newValue, IEntity? source = null, DamageChangeParams? extraParams = null)
|
||||
{
|
||||
if (newValue >= TotalDamage && HasFlag(DamageFlag.Invulnerable))
|
||||
if (newValue >= TotalDamage)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -405,7 +358,7 @@ namespace Content.Shared.Damage.Components
|
||||
{
|
||||
var data = new List<DamageChangeData>();
|
||||
|
||||
foreach (var type in _supportedTypes)
|
||||
foreach (var type in SupportedTypes)
|
||||
{
|
||||
var damage = GetDamage(type);
|
||||
var datum = new DamageChangeData(type, damage, 0);
|
||||
@@ -457,12 +410,10 @@ namespace Content.Shared.Damage.Components
|
||||
public class DamageableComponentState : ComponentState
|
||||
{
|
||||
public readonly Dictionary<DamageType, int> DamageList;
|
||||
public readonly DamageFlag Flags;
|
||||
|
||||
public DamageableComponentState(Dictionary<DamageType, int> damageList, DamageFlag flags) : base(ContentNetIDs.DAMAGEABLE)
|
||||
public DamageableComponentState(Dictionary<DamageType, int> damageList) : base(ContentNetIDs.DAMAGEABLE)
|
||||
{
|
||||
DamageList = damageList;
|
||||
Flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Acts;
|
||||
using Content.Shared.Damage.Resistances;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Damage.Components
|
||||
@@ -22,29 +23,14 @@ namespace Content.Shared.Damage.Components
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<DamageType, int> DamageTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The damage flags on this component.
|
||||
/// </summary>
|
||||
DamageFlag Flags { get; }
|
||||
HashSet<DamageType> SupportedTypes { get; }
|
||||
|
||||
HashSet<DamageClass> SupportedClasses { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a flag to this component.
|
||||
/// The resistances of this component.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to add.</param>
|
||||
void AddFlag(DamageFlag flag);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not this component has a specific flag.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to check for.</param>
|
||||
/// <returns>True if it has the flag, false otherwise.</returns>
|
||||
bool HasFlag(DamageFlag flag);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a flag from this component.
|
||||
/// </summary>
|
||||
/// <param name="flag">The flag to remove.</param>
|
||||
void RemoveFlag(DamageFlag flag);
|
||||
ResistanceSet Resistances { get; }
|
||||
|
||||
bool SupportsDamageClass(DamageClass @class);
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Damage
|
||||
{
|
||||
[Flags]
|
||||
[Serializable, NetSerializable]
|
||||
public enum DamageFlag
|
||||
{
|
||||
None = 0,
|
||||
Invulnerable = 1 << 0
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Content.Shared.Damage
|
||||
return ToNewDictionary<int>();
|
||||
}
|
||||
|
||||
public static Dictionary<DamageClass, int> ToClassDictionary(IReadOnlyDictionary<DamageType, int> types)
|
||||
public static Dictionary<DamageClass, int> ToClassDictionary(this IReadOnlyDictionary<DamageType, int> types)
|
||||
{
|
||||
var classes = DamageClassExtensions.ToNewDictionary();
|
||||
|
||||
|
||||
@@ -11,30 +11,29 @@ namespace Content.Shared.Damage.Resistances
|
||||
/// Each <see cref="DamageType"/> has a multiplier and flat damage
|
||||
/// reduction value.
|
||||
/// </summary>
|
||||
[NetSerializable]
|
||||
[Serializable]
|
||||
[Serializable, NetSerializable]
|
||||
public class ResistanceSet
|
||||
{
|
||||
[ViewVariables]
|
||||
private Dictionary<DamageType, ResistanceSetSettings> _resistances =
|
||||
new();
|
||||
|
||||
public ResistanceSet()
|
||||
{
|
||||
foreach (var damageType in (DamageType[]) Enum.GetValues(typeof(DamageType)))
|
||||
{
|
||||
_resistances.Add(damageType, new ResistanceSetSettings(1f, 0));
|
||||
Resistances.Add(damageType, new ResistanceSetSettings(1f, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public ResistanceSet(ResistanceSetPrototype data)
|
||||
{
|
||||
ID = data.ID;
|
||||
_resistances = data.Resistances;
|
||||
Resistances = data.Resistances;
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public string ID { get; } = string.Empty;
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<DamageType, ResistanceSetSettings> Resistances { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts input damage with the resistance set values.
|
||||
/// Only applies reduction if the amount is damage (positive), not
|
||||
@@ -46,7 +45,7 @@ namespace Content.Shared.Damage.Resistances
|
||||
{
|
||||
if (amount > 0) // Only apply reduction if it's healing, not damage.
|
||||
{
|
||||
amount -= _resistances[damageType].FlatReduction;
|
||||
amount -= Resistances[damageType].FlatReduction;
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
@@ -54,7 +53,7 @@ namespace Content.Shared.Damage.Resistances
|
||||
}
|
||||
}
|
||||
|
||||
amount = (int) Math.Ceiling(amount * _resistances[damageType].Coefficient);
|
||||
amount = (int) Math.Ceiling(amount * Resistances[damageType].Coefficient);
|
||||
|
||||
return amount;
|
||||
}
|
||||
@@ -64,11 +63,10 @@ namespace Content.Shared.Damage.Resistances
|
||||
/// Settings for a specific damage type in a resistance set. Flat reduction is applied before the coefficient.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public struct ResistanceSetSettings
|
||||
public readonly struct ResistanceSetSettings
|
||||
{
|
||||
[ViewVariables] public float Coefficient { get; private set; }
|
||||
|
||||
[ViewVariables] public int FlatReduction { get; private set; }
|
||||
[ViewVariables] public readonly float Coefficient;
|
||||
[ViewVariables] public readonly int FlatReduction;
|
||||
|
||||
public ResistanceSetSettings(float coefficient, int flatReduction)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user