Generalize ResistanceSets into DamageModifierSets (#4619)
* generalize ResistanceSets into DamageModifierSets * remove unneeded test prototype
This commit is contained in:
@@ -1,27 +1,22 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.Damage.Prototypes
|
||||
namespace Content.Shared.Damage
|
||||
{
|
||||
/// <summary>
|
||||
/// Prototype of damage resistance sets. Can be applied to <see cref="DamageSpecifier"/> using <see
|
||||
/// cref="DamageSpecifier.ApplyResistanceSet(ResistanceSetPrototype)"/>. This can be done several times as the
|
||||
/// A set of coefficients or flat modifiers to damage types.. Can be applied to <see cref="DamageSpecifier"/> using <see
|
||||
/// cref="DamageSpecifier.ApplyModifierSet(DamageSpecifier, DamageModifierSet)"/>. This can be done several times as the
|
||||
/// <see cref="DamageSpecifier"/> is passed to it's final target. By default the receiving <see cref="DamageableComponent"/>, will
|
||||
/// also apply it's own <see cref="ResistanceSetPrototype"/>.
|
||||
/// also apply it's own <see cref="DamageModifierSet"/>.
|
||||
/// </summary>
|
||||
[Prototype("resistanceSet")]
|
||||
[DataDefinition]
|
||||
[Serializable, NetSerializable]
|
||||
public class ResistanceSetPrototype : IPrototype
|
||||
public class DamageModifierSet
|
||||
{
|
||||
[ViewVariables]
|
||||
[DataField("id", required: true)]
|
||||
public string ID { get; } = default!;
|
||||
|
||||
[DataField("coefficients", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<float, DamageTypePrototype>))]
|
||||
public Dictionary<string, float> Coefficients = new();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Content.Shared.Damage
|
||||
{
|
||||
if (_damageDict == null)
|
||||
DeserializeDamage();
|
||||
return _damageDict!;
|
||||
return _damageDict!;
|
||||
}
|
||||
set => _damageDict = value;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ namespace Content.Shared.Damage
|
||||
// This can happen if deserialized before prototypes are loaded.
|
||||
Logger.Error($"Unknown damage group given to DamageSpecifier: {entry.Key}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Simply distribute evenly (except for rounding).
|
||||
// We do this by reducing remaining the # of types and damage every loop.
|
||||
@@ -141,12 +141,12 @@ namespace Content.Shared.Damage
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reduce (or increase) damages by applying a resistance set.
|
||||
/// Reduce (or increase) damages by applying a damage modifier set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only applies resistance to a damage type if it is dealing damage, not healing.
|
||||
/// </remarks>
|
||||
public static DamageSpecifier ApplyResistanceSet(DamageSpecifier damageSpec, ResistanceSetPrototype resistanceSet)
|
||||
public static DamageSpecifier ApplyModifierSet(DamageSpecifier damageSpec, DamageModifierSet modifierSet)
|
||||
{
|
||||
// Make a copy of the given data. Don't modify the one passed to this function. I did this before, and weapons became
|
||||
// duller as you hit walls. Neat, but not intended. And confusing, when you realize your fists don't work no
|
||||
@@ -159,9 +159,9 @@ namespace Content.Shared.Damage
|
||||
|
||||
float newValue = entry.Value;
|
||||
|
||||
if (resistanceSet.FlatReduction.TryGetValue(entry.Key, out var reduction))
|
||||
if (modifierSet.FlatReduction.TryGetValue(entry.Key, out var reduction))
|
||||
{
|
||||
newValue -= reduction;
|
||||
newValue -= reduction;
|
||||
if (newValue <= 0)
|
||||
{
|
||||
// flat reductions cannot heal you
|
||||
@@ -170,7 +170,7 @@ namespace Content.Shared.Damage
|
||||
}
|
||||
}
|
||||
|
||||
if (resistanceSet.Coefficients.TryGetValue(entry.Key, out var coefficient))
|
||||
if (modifierSet.Coefficients.TryGetValue(entry.Key, out var coefficient))
|
||||
{
|
||||
// negative coefficients **can** heal you.
|
||||
newValue = MathF.Round(newValue*coefficient, MidpointRounding.AwayFromZero);
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Content.Shared.Damage
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The supported damage types are specified using a <see cref="DamageContainerPrototype"/>s. DamageContainers
|
||||
/// may also have resistances to certain damage types, defined via a <see cref="ResistanceSetPrototype"/>.
|
||||
/// may also have resistances to certain damage types, defined via a <see cref="DamageModifierSetPrototype"/>.
|
||||
/// </remarks>
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent()]
|
||||
@@ -36,12 +36,16 @@ namespace Content.Shared.Damage
|
||||
public string? DamageContainerID;
|
||||
|
||||
/// <summary>
|
||||
/// This <see cref="ResistanceSetPrototype"/> will be applied to any damage that is dealt to this container,
|
||||
/// This <see cref="DamageModifierSetPrototype"/> will be applied to any damage that is dealt to this container,
|
||||
/// unless the damage explicitly ignores resistances.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Though DamageModifierSets can be deserialized directly, we only want to use the prototype version here
|
||||
/// to reduce duplication.
|
||||
/// </remarks>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("resistanceSet", customTypeSerializer: typeof(PrototypeIdSerializer<ResistanceSetPrototype>))]
|
||||
public string? ResistanceSetID;
|
||||
[DataField("damageModifierSet", customTypeSerializer: typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
|
||||
public string? DamageModifierSetId;
|
||||
|
||||
/// <summary>
|
||||
/// All the damage information is stored in this <see cref="DamageSpecifier"/>.
|
||||
@@ -116,14 +120,14 @@ namespace Content.Shared.Damage
|
||||
public class DamageableComponentState : ComponentState
|
||||
{
|
||||
public readonly Dictionary<string, int> DamageDict;
|
||||
public readonly string? ResistanceSetID;
|
||||
public readonly string? ModifierSetId;
|
||||
|
||||
public DamageableComponentState(
|
||||
Dictionary<string, int> damageDict,
|
||||
string? resistanceSetID)
|
||||
string? modifierSetId)
|
||||
{
|
||||
DamageDict = damageDict;
|
||||
ResistanceSetID = resistanceSetID;
|
||||
ModifierSetId = modifierSetId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Content.Shared.Damage
|
||||
/// </summary>
|
||||
private void DamageableInit(EntityUid uid, DamageableComponent component, ComponentInit _)
|
||||
{
|
||||
if (component.DamageContainerID != null &&
|
||||
if (component.DamageContainerID != null &&
|
||||
_prototypeManager.TryIndex<DamageContainerPrototype>(component.DamageContainerID,
|
||||
out var damageContainerPrototype))
|
||||
{
|
||||
@@ -118,11 +118,11 @@ namespace Content.Shared.Damage
|
||||
}
|
||||
|
||||
// Apply resistances
|
||||
if (!ignoreResistances && damageable.ResistanceSetID != null)
|
||||
if (!ignoreResistances && damageable.DamageModifierSetId != null)
|
||||
{
|
||||
if (_prototypeManager.TryIndex<ResistanceSetPrototype>(damageable.ResistanceSetID, out var resistanceSet))
|
||||
if (_prototypeManager.TryIndex<DamageModifierSetPrototype>(damageable.DamageModifierSetId, out var modifierSet))
|
||||
{
|
||||
damage = DamageSpecifier.ApplyResistanceSet(damage, resistanceSet);
|
||||
damage = DamageSpecifier.ApplyModifierSet(damage, modifierSet);
|
||||
}
|
||||
|
||||
if (damage.Empty)
|
||||
@@ -174,7 +174,7 @@ namespace Content.Shared.Damage
|
||||
|
||||
private void DamageableGetState(EntityUid uid, DamageableComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new DamageableComponentState(component.Damage.DamageDict, component.ResistanceSetID);
|
||||
args.State = new DamageableComponentState(component.Damage.DamageDict, component.DamageModifierSetId);
|
||||
}
|
||||
|
||||
private void DamageableHandleState(EntityUid uid, DamageableComponent component, ref ComponentHandleState args)
|
||||
@@ -184,7 +184,7 @@ namespace Content.Shared.Damage
|
||||
return;
|
||||
}
|
||||
|
||||
component.ResistanceSetID = state.ResistanceSetID;
|
||||
component.DamageModifierSetId = state.ModifierSetId;
|
||||
|
||||
// Has the damage actually changed?
|
||||
DamageSpecifier newDamage = new() { DamageDict = state.DamageDict };
|
||||
@@ -202,7 +202,7 @@ namespace Content.Shared.Damage
|
||||
public class DamageChangedEvent : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the component whose damage was changed.
|
||||
/// This is the component whose damage was changed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Given that nearly every component that cares about a change in the damage, needs to know the
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.Damage.Prototypes
|
||||
{
|
||||
/// <summary>
|
||||
/// A version of DamageModifierSet that can be serialized as a prototype, but is functionally identical.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Done to avoid removing the 'required' tag on the ID and passing around a 'prototype' when we really
|
||||
/// just want normal data to be deserialized.
|
||||
/// </remarks>
|
||||
[Prototype("damageModifierSet")]
|
||||
public class DamageModifierSetPrototype : DamageModifierSet, IPrototype
|
||||
{
|
||||
[ViewVariables]
|
||||
[DataField("id", required: true)]
|
||||
public string ID { get; } = default!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user