Damageable Refactor 3: Revenge of the Instamerge (#4524)
* Add DamageType And DamageGroup Prototypes * Remove DamageTypePrototype Field "name" as its redundant * Change I/DamageableComponent to use prototypes * Update DamageContainer, ReisistanceSet and DamageChangeData * Change Barotrauma Component to use DamageType from DamageSystem * Update AsteroidRockComponent * update some more components * update some more components * Fix m o r e c o m p o n e n t s and their damageType * all thats left is bug/missing node hunting then verification. * push changes * update submodule * Merge fixes * push DGP for example * update damagecomponent across shared and server * fix a few bugs * Fix Merge issues * Refactor damageablecomponent update (#4406) * Fixing merge. I messed up part of the merge. this should fix it? * Barotrauma now uses prototypeManager As System.Runtime.CompilerServices also has a [Dependency], I think I had to use the full path [Robust.Shared.IoC.Dependency] * FlammableComponent now uses prototypeManager * SuicideCommands now use prototypeManager * Changed many files to use prototypeManager to resolve damaege prototypes Yeah.... prototype references would be very nice. maybe this was all a waste of time. * Grouping prototypeManager.Index with datafield definitions This will make it easier to eventually add prototype references * removed unused variable * Moved lines around. Lines now consistent with other TODO PROTOTYPE blocks * Grouping more prototypeManager.Index with datafield definitions * Removed unnecessary code * Added more prototypeManager indexing These ones weren't pointed out by DrSmug. But I think this is all of them? That or my regex is shit. * Remove redundant _damage field * Remove redundant _currentTemperature * Moved variables down * Added prototypeManager indexing to TemperatureComponent * WeaponComponent/System now use ProtptypeManager And as far as I can tell damageType is required, and therefore should never have been null anyway? * Make ranged weapon clumsy fire effects datafields And yes, the order in which the clumsy effects occur is very important. * Made damage on vital body part loss a datafield * Renamed several damageGroup variables to group * Capitalised DamageListToDamageGroup * Make radiation and explosion damage types datafields * Renamed _supportedDamageGroupIDs and _supportedDamageTypeIDs * Fixed mistakes Frogot to remove prototypeManager index DamageTypeTrigger, and wrong variable visibility in TemperatureComponent * Added necessary code Is something tragically wrong? * MeleeWeapon damageType is not actually required * Fixing someone else's mistakes A search comes up with nothing in the yaml files, and its not a required field. So no one uses it? Hopefully? * Changed and renamed damageTypeToDamageGroup Previously would incorrectly return the total container damage for each group, not the total in the group * renaming varitables * Renamed variable DamageClasses * Added dictionary converting functions * Added ID-keyed dictionaries * Making MedicalScanner use ID dictionaries, instead of prototype dictionaries Oh oh no. I've been able to avoid UI & networking up until now. I have no Idea what I am doing. * Fix Medical Scanner * Summary (required) The joke here is that this fixes the empty summary. * Removed DamageableComponent.GetDamageGroup/Type * Renamed "damage classes" to groups. * Update ChangeDamage description * Replaced Heal() with SettAllDamage() Heal() was just a confusing name, * More Class -> Group renaming * Replace Class with Group in yaml files DamageClassTrigger does not appear in any yaml? only in testing? DamageTypeTrigger appears only in human.yaml? HealthChangeMetabolism is Mostly in medicine.yml and one in soad.yaml Why the hell is Cola metabolizable by plants? Who is pouring cola on their plants!?!? * Fix _prototypeManager being null errors. * Changing comments Where are the prototype references * MetabolismComponent doesn't give free heals anymore. * Changes HungerComponent healing. Previously I think it would actually damage you. Only did this as I though it was causing the fast healing. Turns out that was just BREATHING. * Generalised a function in DamageableComponent and moved it to DamageGroupPrototype previously DamageTypesDictToDamageGroupDict was private to DamageableComponent, but was also quite general (nearly a static function). As this sort of function may be needed by other components using DamageGroupPrototypes in the future, I moved it there as a static function instead. * modified DamageableComponent.ChangeDamage() ignoreResistances was renamed to ignoreDamageResistances to make it clearer that it had no effect on healing. Now uses default argument for ignoreDamageResistances, so when healing you are not forced to specify an argument that does nothing. Also made some general changes to ignoreResistances() * Changed class->group and added missing damage type functionality to DamageContainerPrototypes * Added Comments to damage.yml * Misc Changes to DamageableComponent * Differentiated between group support and group applicability So far, every damage type is a member of one, and only one, damage group. So this change has no real effect so far. * Added proposed alternative to ChangeDamage() * fixed error in DamageGroupPrototype * Changes to DamageableComponent Lots of changes to comments. Some variables renamed in IDamageableComponent and DamageableComponent (also required renaming in other files) Some minor logic changes, mostly for incorrect descirptions of boolean return values. Also further differentiating between ApplicableGroups and SupportedGroups... if that will ever even matter * Generalised MedicalScannerComponent If needed, can print miscellaneous damage types now * Fixed HealthChangeMetabolism bug * Changing Comments around * More questions * Made Barotrauma default to blunt * Fix RejuvenateTest.cs * Comments * Coments and variable names * fix some master-merge issues * Removed redundant fields * Misc changes for readbility of PR diff * Consistent naming * Fixed atmos damage bug * Removed Ranting * Fixed Hunger after I broke it * Fixing Bugs * Removed stupid question * Removed more stupid questions * Fix potential null errors. * Made boolean return values consistent Also renamed several functions, to make it clear they return a bool. Docs were also updated. * Removed IoCManager.InjectDependencies() * Removed unnecessary 'suffocation' prefix * Fixed Spelling Also removed accidentally left in logger call * Fixed Medical Scanner * Apply suggestions from code review Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> * Changing comments and whitespaces * Made damage thresholds trigger datafields required * So many typos * Changes to DamageableComponents Changed documentation in IDamageableComponent Made testing code more readable. Relabelled groups as 'Applicable' either 'Fully Supported' * Removed function and degeneralised * Update DamageableComponent.cs Removed unused parameters Fixed Networking * Added IoCManager.Resolve * Now using alternative TryChangeDamage() * Removed function from DamageGroupPrototype * Removing comments * Remove bad if statement? * Fix damageChanged ordering * Fix hurt server command * Changed //TODO PROTOTYPE blocks Now use PrototypeManager differently. Wherever possible, only retrieve the prototype once. Also added default damage types to some more datafields * Update Content.Shared/Damage/Container/DamageContainerPrototype.cs Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> * renamed _accumulatedHealth -> _accumulatedDamage and added TODOs * Another class-> group * Fix bug in generalisation of damage container prototypes * Addes Tests to make sure I dont keep adding bugs to my own code. * Changed Return values when setting * Removed unused class * Added more tests, split tests into three files * Made damage types public and VV read-write-able * Minor changes to DamageableComponent Replaced internal use of GetDamagePerType with _damageDict and removed some unnecessary fields * Fix Suicide, by adding IoC Resolve() * Fix DamageGroupTrigger bug * Fix typos in tests * Change comments./docstrings & spacing * Merge tests, use test prototypes Co-authored-by: Leon Friedrich <60421075+leonsfriedrich@users.noreply.github.com> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> * Fix merge issues Co-authored-by: Silver <Silvertorch5@gmail.com> Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> Co-authored-by: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Co-authored-by: Leon Friedrich <60421075+leonsfriedrich@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Content.Server.Alert;
|
||||
using Content.Server.Pressure;
|
||||
@@ -7,6 +7,10 @@ using Content.Shared.Atmos;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Atmos.Components
|
||||
{
|
||||
@@ -18,6 +22,17 @@ namespace Content.Server.Atmos.Components
|
||||
{
|
||||
public override string Name => "Barotrauma";
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")] private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Update(float airPressure)
|
||||
{
|
||||
@@ -40,11 +55,11 @@ namespace Content.Server.Atmos.Components
|
||||
// Low pressure.
|
||||
case var p when p <= Atmospherics.WarningLowPressure:
|
||||
pressure *= lowPressureMultiplier;
|
||||
|
||||
if(pressure > Atmospherics.WarningLowPressure)
|
||||
if (pressure > Atmospherics.WarningLowPressure)
|
||||
goto default;
|
||||
|
||||
damageable.ChangeDamage(DamageType.Blunt, Atmospherics.LowPressureDamage, false, Owner);
|
||||
// Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear.
|
||||
damageable.TryChangeDamage(DamageType, Atmospherics.LowPressureDamage,true);
|
||||
|
||||
if (status == null) break;
|
||||
|
||||
@@ -66,7 +81,8 @@ namespace Content.Server.Atmos.Components
|
||||
|
||||
var damage = (int) MathF.Min((pressure / Atmospherics.HazardHighPressure) * Atmospherics.PressureDamageCoefficient, Atmospherics.MaxHighPressureDamage);
|
||||
|
||||
damageable.ChangeDamage(DamageType.Blunt, damage, false, Owner);
|
||||
// Deal damage and ignore resistances. Resistance to pressure damage should be done via pressure protection gear.
|
||||
damageable.TryChangeDamage(DamageType, damage,true);
|
||||
|
||||
if (status == null) break;
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ using Robust.Shared.Localization;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Atmos.Components
|
||||
{
|
||||
@@ -43,6 +45,18 @@ namespace Content.Server.Atmos.Components
|
||||
[DataField("canResistFire")]
|
||||
public bool CanResistFire { get; private set; } = false;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Heat"!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
public void Extinguish()
|
||||
{
|
||||
if (!OnFire) return;
|
||||
@@ -92,7 +106,7 @@ namespace Content.Server.Atmos.Components
|
||||
{
|
||||
// TODO ATMOS Fire resistance from armor
|
||||
var damage = Math.Min((int) (FireStacks * 2.5f), 10);
|
||||
damageable.ChangeDamage(DamageClass.Burn, damage, false);
|
||||
damageable.TryChangeDamage(DamageType, damage, false);
|
||||
}
|
||||
|
||||
AdjustFireStacks(-0.1f * (_resisting ? 10f : 1f));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Damage;
|
||||
|
||||
namespace Content.Server.Body
|
||||
@@ -10,7 +10,7 @@ namespace Content.Server.Body
|
||||
}
|
||||
|
||||
// TODO BODY: Remove and pretend it never existed
|
||||
public class BodyDamageChangeParams : DamageChangeParams, IBodyHealthChangeParams
|
||||
public class BodyDamageChangeParams : IBodyHealthChangeParams
|
||||
{
|
||||
public BodyDamageChangeParams(BodyPartType part)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,8 @@ using Content.Shared.Atmos;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Content.Shared.MobState;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Robust.Shared.GameObjects;
|
||||
@@ -34,10 +36,6 @@ namespace Content.Server.Body.Respiratory
|
||||
private bool _isShivering;
|
||||
private bool _isSweating;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("suffocationDamage")] private int _suffocationDamage = 1;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("suffocationDamageRecovery")] private int _suffocationDamageRecovery = 1;
|
||||
|
||||
[ViewVariables] [DataField("needsGases")] public Dictionary<Gas, float> NeedsGases { get; set; } = new();
|
||||
|
||||
[ViewVariables] [DataField("producesGases")] public Dictionary<Gas, float> ProducesGases { get; set; } = new();
|
||||
@@ -94,6 +92,22 @@ namespace Content.Server.Body.Respiratory
|
||||
|
||||
[ViewVariables] public bool Suffocating { get; private set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("suffocationDamage")] private int _damage = 1;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("suffocationDamageRecovery")] private int _damageRecovery = 1;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Asphyxiation"!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
private Dictionary<Gas, float> NeedsAndDeficit(float frameTime)
|
||||
{
|
||||
var needs = new Dictionary<Gas, float>(NeedsGases);
|
||||
@@ -349,7 +363,7 @@ namespace Content.Server.Body.Respiratory
|
||||
return;
|
||||
}
|
||||
|
||||
damageable.ChangeDamage(DamageType.Asphyxiation, _suffocationDamage, false);
|
||||
damageable.TryChangeDamage(DamageType, _damage, false);
|
||||
}
|
||||
|
||||
private void StopSuffocation()
|
||||
@@ -358,7 +372,7 @@ namespace Content.Server.Body.Respiratory
|
||||
|
||||
if (Owner.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
damageable.ChangeDamage(DamageType.Asphyxiation, -_suffocationDamageRecovery, false);
|
||||
damageable.TryChangeDamage(DamageType, -_damageRecovery, false);
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ServerAlertsComponent? alertsComponent))
|
||||
|
||||
@@ -17,6 +17,7 @@ using Robust.Shared.Enums;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chat.Commands
|
||||
{
|
||||
@@ -34,21 +35,22 @@ namespace Content.Server.Chat.Commands
|
||||
var kind = suicide.Suicide(target, chat);
|
||||
if (kind != SuicideKind.Special)
|
||||
{
|
||||
damageableComponent.SetDamage(kind switch
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
damageableComponent.TrySetDamage(kind switch
|
||||
{
|
||||
SuicideKind.Blunt => DamageType.Blunt,
|
||||
SuicideKind.Slash => DamageType.Slash,
|
||||
SuicideKind.Piercing => DamageType.Piercing,
|
||||
SuicideKind.Heat => DamageType.Heat,
|
||||
SuicideKind.Shock => DamageType.Shock,
|
||||
SuicideKind.Cold => DamageType.Cold,
|
||||
SuicideKind.Poison => DamageType.Poison,
|
||||
SuicideKind.Radiation => DamageType.Radiation,
|
||||
SuicideKind.Asphyxiation => DamageType.Asphyxiation,
|
||||
SuicideKind.Bloodloss => DamageType.Bloodloss,
|
||||
_ => DamageType.Blunt
|
||||
SuicideKind.Blunt => prototypeManager.Index<DamageTypePrototype>("Blunt"),
|
||||
SuicideKind.Slash => prototypeManager.Index<DamageTypePrototype>("Slash"),
|
||||
SuicideKind.Piercing => prototypeManager.Index<DamageTypePrototype>("Piercing"),
|
||||
SuicideKind.Heat => prototypeManager.Index<DamageTypePrototype>("Heat"),
|
||||
SuicideKind.Shock => prototypeManager.Index<DamageTypePrototype>("Shock"),
|
||||
SuicideKind.Cold => prototypeManager.Index<DamageTypePrototype>("Cold"),
|
||||
SuicideKind.Poison => prototypeManager.Index<DamageTypePrototype>("Poison"),
|
||||
SuicideKind.Radiation => prototypeManager.Index<DamageTypePrototype>("Radiation"),
|
||||
SuicideKind.Asphyxiation => prototypeManager.Index<DamageTypePrototype>("Asphyxiation"),
|
||||
SuicideKind.Bloodloss => prototypeManager.Index<DamageTypePrototype>("Bloodloss"),
|
||||
_ => prototypeManager.Index<DamageTypePrototype>("Blunt")
|
||||
},
|
||||
200, source);
|
||||
200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +119,7 @@ namespace Content.Server.Chat.Commands
|
||||
var selfMessage = Loc.GetString("suicide-command-default-text-self");
|
||||
owner.PopupMessage(selfMessage);
|
||||
|
||||
dmgComponent.SetDamage(DamageType.Piercing, 200, owner);
|
||||
dmgComponent.TrySetDamage(IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("Piercing"), 200);
|
||||
|
||||
// Prevent the player from returning to the body.
|
||||
// Note that mind cannot be null because otherwise owner would be null.
|
||||
|
||||
@@ -5,6 +5,9 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -12,7 +15,7 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// Default metabolism for medicine reagents. Attempts to find a DamageableComponent on the target,
|
||||
/// and to update its damage values.
|
||||
/// </summary>
|
||||
public class HealthChange : ReagentEffect
|
||||
public class HealthChange : ReagentEffect, ISerializationHooks
|
||||
{
|
||||
/// <summary>
|
||||
/// How much damage is changed when 1u of the reagent is metabolized.
|
||||
@@ -20,35 +23,45 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("healthChange")]
|
||||
public float AmountToChange { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Class of damage changed, Brute, Burn, Toxin, Airloss.
|
||||
/// </summary>
|
||||
[DataField("damageClass")]
|
||||
public DamageClass DamageType { get; set; } = DamageClass.Brute;
|
||||
// TODO DAMAGE UNITS When damage units support decimals, get rid of this.
|
||||
// See also _accumulatedDamage in ThirstComponent and HungerComponent
|
||||
private float _accumulatedDamage;
|
||||
|
||||
private float _accumulatedHealth;
|
||||
/// <summary>
|
||||
/// Damage group to change.
|
||||
/// </summary>
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove ISerializationHooks, if no longer needed.
|
||||
[DataField("damageGroup", required: true)]
|
||||
private readonly string _damageGroupID = default!;
|
||||
public DamageGroupPrototype DamageGroup = default!;
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
DamageGroup = IoCManager.Resolve<IPrototypeManager>().Index<DamageGroupPrototype>(_damageGroupID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes damage if a DamageableComponent can be found.
|
||||
/// </summary>
|
||||
public override void Metabolize(IEntity solutionEntity, Solution.ReagentQuantity amount)
|
||||
{
|
||||
if (solutionEntity.TryGetComponent(out IDamageableComponent? health))
|
||||
if (solutionEntity.TryGetComponent(out IDamageableComponent? damageComponent))
|
||||
{
|
||||
health.ChangeDamage(DamageType, (int)AmountToChange, true);
|
||||
float decHealthChange = (float) (AmountToChange - (int) AmountToChange);
|
||||
_accumulatedHealth += decHealthChange;
|
||||
damageComponent.TryChangeDamage(DamageGroup, (int)AmountToChange, true);
|
||||
|
||||
if (_accumulatedHealth >= 1)
|
||||
float decHealthChange = (float) (AmountToChange - (int) AmountToChange);
|
||||
_accumulatedDamage += decHealthChange;
|
||||
|
||||
if (_accumulatedDamage >= 1)
|
||||
{
|
||||
health.ChangeDamage(DamageType, 1, true);
|
||||
_accumulatedHealth -= 1;
|
||||
damageComponent.TryChangeDamage(DamageGroup, 1, true);
|
||||
_accumulatedDamage -= 1;
|
||||
}
|
||||
|
||||
else if(_accumulatedHealth <= -1)
|
||||
else if(_accumulatedDamage <= -1)
|
||||
{
|
||||
health.ChangeDamage(DamageType, -1, true);
|
||||
_accumulatedHealth += 1;
|
||||
damageComponent.TryChangeDamage(DamageGroup, -1, true);
|
||||
_accumulatedDamage += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
@@ -9,6 +10,7 @@ using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Damage.Commands
|
||||
{
|
||||
@@ -19,22 +21,24 @@ namespace Content.Server.Damage.Commands
|
||||
public string Description => "Ouch";
|
||||
public string Help => $"Usage: {Command} <type/?> <amount> (<entity uid/_>) (<ignoreResistances>)";
|
||||
|
||||
private readonly IPrototypeManager _prototypeManager = default!;
|
||||
public HurtCommand() {
|
||||
_prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
}
|
||||
|
||||
private string DamageTypes()
|
||||
{
|
||||
var msg = new StringBuilder();
|
||||
foreach (var dClass in Enum.GetNames(typeof(DamageClass)))
|
||||
|
||||
foreach (var damageGroup in _prototypeManager.EnumeratePrototypes<DamageGroupPrototype>())
|
||||
{
|
||||
msg.Append($"\n{dClass}");
|
||||
|
||||
var types = Enum.Parse<DamageClass>(dClass).ToTypes();
|
||||
|
||||
if (types.Count > 0)
|
||||
msg.Append($"\n{damageGroup.ID}");
|
||||
if (damageGroup.DamageTypes.Any())
|
||||
{
|
||||
msg.Append(": ");
|
||||
msg.AppendJoin('|', types);
|
||||
msg.AppendJoin('|', damageGroup.DamageTypes);
|
||||
}
|
||||
}
|
||||
|
||||
return $"Damage Types:{msg}";
|
||||
}
|
||||
|
||||
@@ -85,6 +89,8 @@ namespace Content.Server.Damage.Commands
|
||||
string[] args,
|
||||
[NotNullWhen(true)] out Damage? func)
|
||||
{
|
||||
|
||||
|
||||
if (!int.TryParse(args[1], out var amount))
|
||||
{
|
||||
shell.WriteLine($"{args[1]} is not a valid damage integer.");
|
||||
@@ -93,42 +99,42 @@ namespace Content.Server.Damage.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Enum.TryParse<DamageClass>(args[0], true, out var damageClass))
|
||||
if (_prototypeManager.TryIndex<DamageGroupPrototype>(args[0], out var damageGroup))
|
||||
{
|
||||
func = (damageable, ignoreResistances) =>
|
||||
{
|
||||
if (!damageable.DamageClasses.ContainsKey(damageClass))
|
||||
if (!damageable.ApplicableDamageGroups.Contains(damageGroup))
|
||||
{
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} can not be damaged with damage class {damageClass}");
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} can not be damaged with damage group {damageGroup}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!damageable.ChangeDamage(damageClass, amount, ignoreResistances))
|
||||
if (!damageable.TryChangeDamage(damageGroup, amount, ignoreResistances))
|
||||
{
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} received no damage.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Damaged entity {damageable.Owner.Name} with id {damageable.Owner.Uid} for {amount} {damageClass} damage{(ignoreResistances ? ", ignoring resistances." : ".")}");
|
||||
shell.WriteLine($"Damaged entity {damageable.Owner.Name} with id {damageable.Owner.Uid} for {amount} {damageGroup} damage{(ignoreResistances ? ", ignoring resistances." : ".")}");
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
// Fall back to DamageType
|
||||
else if (Enum.TryParse<DamageType>(args[0], true, out var damageType))
|
||||
else if (_prototypeManager.TryIndex<DamageTypePrototype>(args[0], out var damageType))
|
||||
{
|
||||
func = (damageable, ignoreResistances) =>
|
||||
{
|
||||
if (!damageable.DamageTypes.ContainsKey(damageType))
|
||||
if (!damageable.IsSupportedDamageType(damageType))
|
||||
{
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} can not be damaged with damage class {damageType}");
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} can not be damaged with damage type {damageType}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!damageable.ChangeDamage(damageType, amount, ignoreResistances))
|
||||
if (!damageable.TryChangeDamage(damageType, amount, ignoreResistances))
|
||||
{
|
||||
shell.WriteLine($"Entity {damageable.Owner.Name} with id {damageable.Owner.Uid} received no damage.");
|
||||
|
||||
@@ -136,9 +142,10 @@ namespace Content.Server.Damage.Commands
|
||||
}
|
||||
|
||||
shell.WriteLine($"Damaged entity {damageable.Owner.Name} with id {damageable.Owner.Uid} for {amount} {damageType} damage{(ignoreResistances ? ", ignoring resistances." : ".")}");
|
||||
};
|
||||
|
||||
};
|
||||
return true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -3,6 +3,9 @@ using Content.Shared.Damage;
|
||||
using Content.Shared.Sound;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Damage.Components
|
||||
{
|
||||
@@ -14,8 +17,6 @@ namespace Content.Server.Damage.Components
|
||||
{
|
||||
public override string Name => "DamageOnHighSpeedImpact";
|
||||
|
||||
[DataField("damage")]
|
||||
public DamageType Damage { get; set; } = DamageType.Blunt;
|
||||
[DataField("minimumSpeed")]
|
||||
public float MinimumSpeed { get; set; } = 20f;
|
||||
[DataField("baseDamage")]
|
||||
@@ -34,5 +35,17 @@ namespace Content.Server.Damage.Components
|
||||
public float DamageCooldown { get; set; } = 2f;
|
||||
|
||||
internal TimeSpan LastHit = TimeSpan.Zero;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Damage.Components
|
||||
{
|
||||
@@ -11,20 +14,31 @@ namespace Content.Server.Damage.Components
|
||||
{
|
||||
public override string Name => "DamageOnLand";
|
||||
|
||||
[DataField("damageType")]
|
||||
private DamageType _damageType = DamageType.Blunt;
|
||||
|
||||
[DataField("amount")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
private int _amount = 1;
|
||||
|
||||
[DataField("ignoreResistances")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
private bool _ignoreResistances;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
void ILand.Land(LandEventArgs eventArgs)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IDamageableComponent? damageable)) return;
|
||||
|
||||
damageable.ChangeDamage(_damageType, _amount, _ignoreResistances, eventArgs.User);
|
||||
if (!Owner.TryGetComponent(out IDamageableComponent? damageable))
|
||||
return;
|
||||
damageable.TryChangeDamage(DamageType, _amount, _ignoreResistances);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Tools.Components;
|
||||
using Content.Shared.Damage;
|
||||
@@ -7,12 +7,16 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.Tool;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Damage.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class DamageOnToolInteractComponent : Component, IInteractUsing
|
||||
{
|
||||
|
||||
public override string Name => "DamageOnToolInteract";
|
||||
|
||||
[DataField("damage")]
|
||||
@@ -21,6 +25,23 @@ namespace Content.Server.Damage.Components
|
||||
[DataField("tools")]
|
||||
private List<ToolQuality> _tools = new();
|
||||
|
||||
// TODO PROTOTYPE Replace these datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("weldingDamageType")]
|
||||
private readonly string _weldingDamageTypeID = "Heat";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype WeldingDamageType = default!;
|
||||
[DataField("defaultDamageType")]
|
||||
private readonly string _defaultDamageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DefaultDamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
WeldingDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_weldingDamageTypeID);
|
||||
DefaultDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_defaultDamageTypeID);
|
||||
}
|
||||
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Using.TryGetComponent<ToolComponent>(out var tool))
|
||||
@@ -44,17 +65,15 @@ namespace Content.Server.Damage.Components
|
||||
|
||||
protected bool CallDamage(InteractUsingEventArgs eventArgs, ToolComponent tool)
|
||||
{
|
||||
if (eventArgs.Target.TryGetComponent<IDamageableComponent>(out var damageable))
|
||||
{
|
||||
damageable.ChangeDamage(tool.HasQuality(ToolQuality.Welding)
|
||||
? DamageType.Heat
|
||||
: DamageType.Blunt,
|
||||
Damage, false, eventArgs.User);
|
||||
if (!eventArgs.Target.TryGetComponent<IDamageableComponent>(out var damageable))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
damageable.TryChangeDamage(tool.HasQuality(ToolQuality.Welding)
|
||||
? WeldingDamageType
|
||||
: DefaultDamageType,
|
||||
Damage);
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ using Content.Shared.Damage;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Damage.Components
|
||||
{
|
||||
@@ -11,13 +13,21 @@ namespace Content.Server.Damage.Components
|
||||
{
|
||||
public override string Name => "DamageOtherOnHit";
|
||||
|
||||
[DataField("damageType")]
|
||||
public DamageType DamageType { get; } = DamageType.Blunt;
|
||||
|
||||
[DataField("amount")]
|
||||
public int Amount { get; } = 1;
|
||||
|
||||
[DataField("ignoreResistances")]
|
||||
public bool IgnoreResistances { get; } = false;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
public DamageTypePrototype DamageType { get; set; } = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Content.Server.Damage
|
||||
if (ComponentManager.TryGetComponent(uid, out StunnableComponent? stun) && _robustRandom.Prob(component.StunChance))
|
||||
stun.Stun(component.StunSeconds);
|
||||
|
||||
damageable.ChangeDamage(component.Damage, damage, false, args.OtherFixture.Body.Owner);
|
||||
damageable.TryChangeDamage(component.DamageType, damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Content.Server.Damage
|
||||
if (!args.Target.TryGetComponent(out IDamageableComponent? damageable))
|
||||
return;
|
||||
|
||||
damageable.ChangeDamage(component.DamageType, component.Amount, component.IgnoreResistances, args.User);
|
||||
damageable.TryChangeDamage(component.DamageType, component.Amount, component.IgnoreResistances);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Atmos.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Atmos.Components;
|
||||
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;
|
||||
@@ -43,8 +42,9 @@ namespace Content.Server.Damage
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
damageable.SupportedTypes.Clear();
|
||||
damageable.SupportedClasses.Clear();
|
||||
damageable.SupportedDamageTypes.Clear();
|
||||
damageable.FullySupportedDamageGroups.Clear();
|
||||
damageable.ApplicableDamageGroups.Clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -69,14 +69,19 @@ namespace Content.Server.Damage
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
if (old.SupportedTypes != null)
|
||||
if (old.SupportedDamageTypes != null)
|
||||
{
|
||||
damageable.SupportedTypes.UnionWith(old.SupportedTypes);
|
||||
damageable.SupportedDamageTypes.UnionWith(old.SupportedDamageTypes);
|
||||
}
|
||||
|
||||
if (old.SupportedClasses != null)
|
||||
if (old.SupportedDamageGroups != null)
|
||||
{
|
||||
damageable.SupportedClasses.UnionWith(old.SupportedClasses);
|
||||
damageable.FullySupportedDamageGroups.UnionWith(old.SupportedDamageGroups);
|
||||
}
|
||||
|
||||
if (old.ApplicableDamageGroups != null)
|
||||
{
|
||||
damageable.ApplicableDamageGroups.UnionWith(old.ApplicableDamageGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +116,9 @@ namespace Content.Server.Damage
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
SupportedTypes = damageable.SupportedTypes.ToHashSet();
|
||||
SupportedClasses = damageable.SupportedClasses.ToHashSet();
|
||||
SupportedDamageTypes = damageable.SupportedDamageTypes.ToHashSet();
|
||||
SupportedDamageGroups = damageable.FullySupportedDamageGroups.ToHashSet();
|
||||
ApplicableDamageGroups = damageable.ApplicableDamageGroups.ToHashSet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,9 +126,11 @@ namespace Content.Server.Damage
|
||||
|
||||
public bool MovedByPressure { get; }
|
||||
|
||||
public HashSet<DamageType>? SupportedTypes { get; }
|
||||
public HashSet<DamageTypePrototype>? SupportedDamageTypes { get; }
|
||||
|
||||
public HashSet<DamageClass>? SupportedClasses { get; }
|
||||
public HashSet<DamageGroupPrototype>? SupportedDamageGroups { get; }
|
||||
|
||||
public HashSet<DamageGroupPrototype>? ApplicableDamageGroups { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Content.Server.Damage
|
||||
{
|
||||
if (target.TryGetComponent(out IDamageableComponent? damage))
|
||||
{
|
||||
damage.Heal();
|
||||
damage.TrySetAllDamage(0);
|
||||
}
|
||||
|
||||
if (target.TryGetComponent(out IMobStateComponent? mobState))
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Server.Destructible.Thresholds.Triggers
|
||||
{
|
||||
/// <summary>
|
||||
/// A trigger that will activate when the amount of damage received
|
||||
/// of the specified class is above the specified threshold.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public class DamageClassTrigger : IThresholdTrigger
|
||||
{
|
||||
/// <summary>
|
||||
/// The class to check the damage of.
|
||||
/// </summary>
|
||||
[DataField("class")]
|
||||
public DamageClass? Class { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of damage at which this threshold will trigger.
|
||||
/// </summary>
|
||||
[DataField("damage")]
|
||||
public int Damage { get; set; }
|
||||
|
||||
public bool Reached(IDamageableComponent damageable, DestructibleSystem system)
|
||||
{
|
||||
if (Class == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return damageable.TryGetDamage(Class.Value, out var damageReceived) &&
|
||||
damageReceived >= Damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Destructible.Thresholds.Triggers
|
||||
{
|
||||
/// <summary>
|
||||
/// A trigger that will activate when the amount of damage received
|
||||
/// of the specified class is above the specified threshold.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataDefinition]
|
||||
public class DamageGroupTrigger : IThresholdTrigger
|
||||
{
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// While you're at it, maybe also combine damageGroup and damage into a dictionary, and allow it to test a sum
|
||||
// of damage types?
|
||||
[DataField("damageGroup", required: true)]
|
||||
private string _damageGroupID { get; set; } = default!;
|
||||
public DamageGroupPrototype DamageGroup => IoCManager.Resolve<IPrototypeManager>().Index<DamageGroupPrototype>(_damageGroupID);
|
||||
|
||||
/// <summary>
|
||||
/// The amount of damage at which this threshold will trigger.
|
||||
/// </summary>
|
||||
[DataField("damage", required: true)]
|
||||
public int Damage { get; set; } = default!;
|
||||
|
||||
public bool Reached(IDamageableComponent damageable, DestructibleSystem system)
|
||||
{
|
||||
if (DamageGroup == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return damageable.TryGetDamage(DamageGroup, out var damageReceived) &&
|
||||
damageReceived >= Damage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace Content.Server.Destructible.Thresholds.Triggers
|
||||
/// <summary>
|
||||
/// The amount of damage at which this threshold will trigger.
|
||||
/// </summary>
|
||||
[DataField("damage")]
|
||||
public int Damage { get; set; }
|
||||
[DataField("damage", required: true)]
|
||||
public int Damage { get; set; } = default!;
|
||||
|
||||
public bool Reached(IDamageableComponent damageable, DestructibleSystem system)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Destructible.Thresholds.Triggers
|
||||
{
|
||||
@@ -13,20 +15,24 @@ namespace Content.Server.Destructible.Thresholds.Triggers
|
||||
[DataDefinition]
|
||||
public class DamageTypeTrigger : IThresholdTrigger
|
||||
{
|
||||
[DataField("type")]
|
||||
public DamageType? Type { get; set; }
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// While you're at it, maybe also combine damageGroup and damage into a dictionary, and allow it to test a sum
|
||||
// of damage types?
|
||||
[DataField("damageType", required:true)]
|
||||
public string _damageTypeID { get; set; } = default!;
|
||||
public DamageTypePrototype DamageType => IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
|
||||
[DataField("damage")]
|
||||
public int Damage { get; set; }
|
||||
[DataField("damage", required: true)]
|
||||
public int Damage { get; set; } = default!;
|
||||
|
||||
public bool Reached(IDamageableComponent damageable, DestructibleSystem system)
|
||||
{
|
||||
if (Type == null)
|
||||
if (DamageType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return damageable.TryGetDamage(Type.Value, out var damageReceived) &&
|
||||
return damageable.TryGetDamage(DamageType, out var damageReceived) &&
|
||||
damageReceived >= Damage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Timer = Robust.Shared.Timing.Timer;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.Doors.Components
|
||||
{
|
||||
@@ -45,6 +47,18 @@ namespace Content.Server.Doors.Components
|
||||
[DataField("tryOpenDoorSound")]
|
||||
private SoundSpecifier _tryOpenDoorSound = new SoundPathSpecifier("/Audio/Effects/bang.ogg");
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
public override DoorState State
|
||||
{
|
||||
get => base.State;
|
||||
@@ -536,7 +550,7 @@ namespace Content.Server.Doors.Components
|
||||
hitsomebody = true;
|
||||
CurrentlyCrushing.Add(e.Owner.Uid);
|
||||
|
||||
damage.ChangeDamage(DamageType.Blunt, DoorCrushDamage, false, Owner);
|
||||
damage.TryChangeDamage(DamageType, DoorCrushDamage);
|
||||
stun.Paralyze(DoorStunTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ using Robust.Server.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.GameTicking.Presets
|
||||
{
|
||||
@@ -66,7 +67,8 @@ namespace Content.Server.GameTicking.Presets
|
||||
if (playerEntity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
//todo: what if they dont breathe lol
|
||||
damageable.SetDamage(DamageType.Asphyxiation, 200, playerEntity);
|
||||
//cry deeply
|
||||
damageable.TrySetDamage(IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>("Asphyxiation"), 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ using Robust.Server.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
@@ -38,6 +39,7 @@ namespace Content.Server.GameTicking.Presets
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public string PDAPrototypeName => "CaptainPDA";
|
||||
public string BeltPrototypeName => "ClothingBeltJanitorFilled";
|
||||
@@ -192,11 +194,11 @@ namespace Content.Server.GameTicking.Presets
|
||||
{
|
||||
if (mobState.IsCritical())
|
||||
{
|
||||
// TODO: This is copy/pasted from ghost code. Really, IDamagableComponent needs a method to reliably kill the target.
|
||||
// TODO: This is copy/pasted from ghost code. Really, IDamageableComponent needs a method to reliably kill the target.
|
||||
if (entity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
{
|
||||
//todo: what if they dont breathe lol
|
||||
damageable.ChangeDamage(DamageType.Asphyxiation, 100, true);
|
||||
damageable.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>("Asphyxiation"), 100, true);
|
||||
}
|
||||
}
|
||||
else if (!mobState.IsDead())
|
||||
|
||||
@@ -20,6 +20,7 @@ using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
@@ -77,6 +78,19 @@ namespace Content.Server.Light.Components
|
||||
|
||||
[ViewVariables] private ContainerSlot _lightBulbContainer = default!;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Heat";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
_lightBulbContainer = ContainerHelpers.EnsureContainer<ContainerSlot>(Owner, "light_bulb");
|
||||
}
|
||||
|
||||
[ViewVariables]
|
||||
public LightBulbComponent? LightBulb
|
||||
{
|
||||
@@ -126,7 +140,7 @@ namespace Content.Server.Light.Components
|
||||
void Burn()
|
||||
{
|
||||
Owner.PopupMessage(eventArgs.User, Loc.GetString("powered-light-component-burn-hand"));
|
||||
damageableComponent.ChangeDamage(DamageType.Heat, 20, false, Owner);
|
||||
damageableComponent.TryChangeDamage(DamageType, 20);
|
||||
SoundSystem.Play(Filter.Pvs(Owner), _burnHandSound.GetSound(), Owner);
|
||||
}
|
||||
|
||||
@@ -249,13 +263,6 @@ namespace Content.Server.Light.Components
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_lightBulbContainer = ContainerHelpers.EnsureContainer<ContainerSlot>(Owner, "light_bulb");
|
||||
}
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Interaction.Helpers;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Medical.Components
|
||||
{
|
||||
@@ -18,7 +20,12 @@ namespace Content.Server.Medical.Components
|
||||
{
|
||||
public override string Name => "Healing";
|
||||
|
||||
[DataField("heal")] public Dictionary<DamageType, int> Heal { get; private set; } = new();
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// This also requires changing the dictionary type, and removing a _prototypeManager.Index() call.
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[DataField("heal", required: true )]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Dictionary<string, int> Heal = new();
|
||||
|
||||
async Task<bool> IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
|
||||
{
|
||||
@@ -48,9 +55,9 @@ namespace Content.Server.Medical.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var (type, amount) in Heal)
|
||||
foreach (var (damageTypeID, amount) in Heal)
|
||||
{
|
||||
damageable.ChangeDamage(type, -amount, true);
|
||||
damageable.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>(damageTypeID), -amount, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -99,8 +99,8 @@ namespace Content.Server.Medical.Components
|
||||
private static readonly MedicalScannerBoundUserInterfaceState EmptyUIState =
|
||||
new(
|
||||
null,
|
||||
new Dictionary<DamageClass, int>(),
|
||||
new Dictionary<DamageType, int>(),
|
||||
new Dictionary<string, int>(),
|
||||
new Dictionary<string, int>(),
|
||||
false);
|
||||
|
||||
private MedicalScannerBoundUserInterfaceState GetUserInterfaceState()
|
||||
@@ -121,12 +121,13 @@ namespace Content.Server.Medical.Components
|
||||
return EmptyUIState;
|
||||
}
|
||||
|
||||
var classes = new Dictionary<DamageClass, int>(damageable.DamageClasses);
|
||||
var types = new Dictionary<DamageType, int>(damageable.DamageTypes);
|
||||
// Get dictionaries of damage, by fully supported damage groups and types
|
||||
var groups = new Dictionary<string, int>(damageable.GetDamagePerFullySupportedGroupIDs);
|
||||
var types = new Dictionary<string, int>(damageable.GetDamagePerTypeIDs);
|
||||
|
||||
if (_bodyContainer.ContainedEntity?.Uid == null)
|
||||
{
|
||||
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types, true);
|
||||
return new MedicalScannerBoundUserInterfaceState(body.Uid, groups, types, true);
|
||||
}
|
||||
|
||||
var cloningSystem = EntitySystem.Get<CloningSystem>();
|
||||
@@ -134,7 +135,7 @@ namespace Content.Server.Medical.Components
|
||||
mindComponent.Mind != null &&
|
||||
cloningSystem.HasDnaScan(mindComponent.Mind);
|
||||
|
||||
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types, scanned);
|
||||
return new MedicalScannerBoundUserInterfaceState(body.Uid, groups, types, scanned);
|
||||
}
|
||||
|
||||
private void UpdateUserInterface()
|
||||
|
||||
@@ -7,9 +7,12 @@ using Content.Shared.Mining;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Mining.Components
|
||||
{
|
||||
@@ -21,10 +24,16 @@ namespace Content.Server.Mining.Components
|
||||
public override string Name => "AsteroidRock";
|
||||
private static readonly string[] SpriteStates = {"0", "1", "2", "3", "4"};
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt"!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(AsteroidRockVisuals.State, _random.Pick(SpriteStates));
|
||||
@@ -37,7 +46,7 @@ namespace Content.Server.Mining.Components
|
||||
if (!item.TryGetComponent(out MeleeWeaponComponent? meleeWeaponComponent))
|
||||
return false;
|
||||
|
||||
Owner.GetComponent<IDamageableComponent>().ChangeDamage(DamageType.Blunt, meleeWeaponComponent.Damage, false, item);
|
||||
Owner.GetComponent<IDamageableComponent>().TryChangeDamage(DamageType, meleeWeaponComponent.Damage);
|
||||
|
||||
if (!item.TryGetComponent(out PickaxeComponent? pickaxeComponent))
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Alert;
|
||||
using Content.Shared.Alert;
|
||||
@@ -14,6 +14,7 @@ using Robust.Shared.Players;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Nutrition.Components
|
||||
{
|
||||
@@ -22,6 +23,10 @@ namespace Content.Server.Nutrition.Components
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
// TODO DAMAGE UNITS When damage units support decimals, get rid of this.
|
||||
// See also _accumulatedDamage in ThirstComponent and HealthChange.
|
||||
private float _accumulatedDamage;
|
||||
|
||||
// Base stuff
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float BaseDecayRate
|
||||
@@ -29,7 +34,7 @@ namespace Content.Server.Nutrition.Components
|
||||
get => _baseDecayRate;
|
||||
set => _baseDecayRate = value;
|
||||
}
|
||||
[DataField("base_decay_rate")]
|
||||
[DataField("baseDecayRate")]
|
||||
private float _baseDecayRate = 0.1f;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
@@ -59,11 +64,11 @@ namespace Content.Server.Nutrition.Components
|
||||
public Dictionary<HungerThreshold, float> HungerThresholds => _hungerThresholds;
|
||||
private readonly Dictionary<HungerThreshold, float> _hungerThresholds = new()
|
||||
{
|
||||
{HungerThreshold.Overfed, 600.0f},
|
||||
{HungerThreshold.Okay, 450.0f},
|
||||
{HungerThreshold.Peckish, 300.0f},
|
||||
{HungerThreshold.Starving, 150.0f},
|
||||
{HungerThreshold.Dead, 0.0f},
|
||||
{ HungerThreshold.Overfed, 600.0f },
|
||||
{ HungerThreshold.Okay, 450.0f },
|
||||
{ HungerThreshold.Peckish, 300.0f },
|
||||
{ HungerThreshold.Starving, 150.0f },
|
||||
{ HungerThreshold.Dead, 0.0f },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<HungerThreshold, AlertType> HungerThresholdAlertTypes = new()
|
||||
@@ -73,6 +78,18 @@ namespace Content.Server.Nutrition.Components
|
||||
{ HungerThreshold.Starving, AlertType.Starving },
|
||||
};
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt"!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
public void HungerThresholdEffect(bool force = false)
|
||||
{
|
||||
if (_currentHungerThreshold != _lastHungerThreshold || force)
|
||||
@@ -177,6 +194,7 @@ namespace Content.Server.Nutrition.Components
|
||||
|
||||
if (_currentHungerThreshold != HungerThreshold.Dead)
|
||||
return;
|
||||
// --> Current Hunger is below dead threshold
|
||||
|
||||
if (!Owner.TryGetComponent(out IDamageableComponent? damageable))
|
||||
return;
|
||||
@@ -186,7 +204,14 @@ namespace Content.Server.Nutrition.Components
|
||||
|
||||
if (!mobState.IsDead())
|
||||
{
|
||||
damageable.ChangeDamage(DamageType.Blunt, 2, true);
|
||||
// --> But they are not dead yet.
|
||||
var damage = 2 * frametime;
|
||||
_accumulatedDamage += damage - ((int) damage);
|
||||
damageable.TryChangeDamage(DamageType, (int) damage);
|
||||
if (_accumulatedDamage >= 1) {
|
||||
_accumulatedDamage -= 1;
|
||||
damageable.TryChangeDamage(DamageType, 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Alert;
|
||||
using Content.Shared.Alert;
|
||||
@@ -14,6 +14,7 @@ using Robust.Shared.Players;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Nutrition.Components
|
||||
{
|
||||
@@ -22,6 +23,10 @@ namespace Content.Server.Nutrition.Components
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
// TODO DAMAGE UNITS When damage units support decimals, get rid of this.
|
||||
// See also _accumulatedDamage in HungerComponent and HealthChange.
|
||||
private float _accumulatedDamage;
|
||||
|
||||
// Base stuff
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float BaseDecayRate
|
||||
@@ -29,7 +34,7 @@ namespace Content.Server.Nutrition.Components
|
||||
get => _baseDecayRate;
|
||||
set => _baseDecayRate = value;
|
||||
}
|
||||
[DataField("base_decay_rate")]
|
||||
[DataField("baseDecayRate")]
|
||||
private float _baseDecayRate = 0.1f;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
@@ -72,6 +77,18 @@ namespace Content.Server.Nutrition.Components
|
||||
{ThirstThreshold.Parched, AlertType.Parched},
|
||||
};
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
public void ThirstThresholdEffect(bool force = false)
|
||||
{
|
||||
if (_currentThirstThreshold != _lastThirstThreshold || force)
|
||||
@@ -174,6 +191,7 @@ namespace Content.Server.Nutrition.Components
|
||||
|
||||
if (_currentThirstThreshold != ThirstThreshold.Dead)
|
||||
return;
|
||||
// --> Current Hunger is below dead threshold
|
||||
|
||||
if (!Owner.TryGetComponent(out IDamageableComponent? damageable))
|
||||
return;
|
||||
@@ -183,7 +201,15 @@ namespace Content.Server.Nutrition.Components
|
||||
|
||||
if (!mobState.IsDead())
|
||||
{
|
||||
damageable.ChangeDamage(DamageType.Blunt, 2, true);
|
||||
// --> But they are not dead yet.
|
||||
var damage = 2 * frametime;
|
||||
_accumulatedDamage += damage - ((int) damage);
|
||||
damageable.TryChangeDamage(DamageType, (int) damage);
|
||||
if (_accumulatedDamage >= 1)
|
||||
{
|
||||
_accumulatedDamage -= 1;
|
||||
damageable.TryChangeDamage(DamageType, 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
||||
{
|
||||
comp.OnUpdate(_accumulatedFrameTime);
|
||||
}
|
||||
_accumulatedFrameTime -= 1;
|
||||
_accumulatedFrameTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.Projectiles.Components
|
||||
{
|
||||
@@ -25,26 +27,18 @@ namespace Content.Server.Projectiles.Components
|
||||
public override string Name => "Hitscan";
|
||||
public CollisionGroup CollisionMask => (CollisionGroup) _collisionMask;
|
||||
|
||||
|
||||
[DataField("layers")] //todo WithFormat.Flags<CollisionLayer>()
|
||||
private int _collisionMask = (int) CollisionGroup.Opaque;
|
||||
|
||||
public float Damage
|
||||
{
|
||||
get => _damage;
|
||||
set => _damage = value;
|
||||
}
|
||||
[DataField("damage")]
|
||||
private float _damage = 10f;
|
||||
public DamageType DamageType => _damageType;
|
||||
[DataField("damageType")]
|
||||
private DamageType _damageType = DamageType.Heat;
|
||||
public float MaxLength => 20.0f;
|
||||
public float Damage { get; set; } = 10f;
|
||||
public float MaxLength => 20.0f;
|
||||
|
||||
private TimeSpan _startTime;
|
||||
private TimeSpan _deathTime;
|
||||
|
||||
public float ColorModifier { get; set; } = 1.0f;
|
||||
[DataField("spriteName")]
|
||||
[DataField("spriteName")]
|
||||
private string _spriteName = "Objects/Weapons/Guns/Projectiles/laser.png";
|
||||
[DataField("muzzleFlash")]
|
||||
private string? _muzzleFlash;
|
||||
@@ -53,6 +47,19 @@ namespace Content.Server.Projectiles.Components
|
||||
[DataField("soundHitWall")]
|
||||
private SoundSpecifier _soundHitWall = new SoundPathSpecifier("/Audio/Weapons/Guns/Hits/laser_sear_wall.ogg");
|
||||
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Piercing";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
|
||||
public void FireEffects(IEntity user, float distance, Angle angle, IEntity? hitEntity = null)
|
||||
{
|
||||
var effectSystem = EntitySystem.Get<EffectSystem>();
|
||||
|
||||
@@ -13,14 +13,12 @@ namespace Content.Server.Projectiles.Components
|
||||
[ComponentReference(typeof(SharedProjectileComponent))]
|
||||
public class ProjectileComponent : SharedProjectileComponent
|
||||
{
|
||||
[DataField("damages")] private Dictionary<DamageType, int> _damages = new();
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<DamageType, int> Damages
|
||||
{
|
||||
get => _damages;
|
||||
set => _damages = value;
|
||||
}
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// This also requires changing the dictionary type and modifying ProjectileSystem.cs, which uses it.
|
||||
// While thats being done, also replace "damages" -> "damageTypes" For consistency.
|
||||
[DataField("damages")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Dictionary<string, int> Damages { get; set; } = new();
|
||||
|
||||
[DataField("deleteOnCollide")]
|
||||
public bool DeleteOnCollide { get; } = true;
|
||||
|
||||
@@ -7,12 +7,17 @@ using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.IoC;
|
||||
using Content.Shared.Damage;
|
||||
|
||||
namespace Content.Server.Projectiles
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal sealed class ProjectileSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -49,9 +54,9 @@ namespace Content.Server.Projectiles
|
||||
{
|
||||
EntityManager.TryGetEntity(component.Shooter, out var shooter);
|
||||
|
||||
foreach (var (damageType, amount) in component.Damages)
|
||||
foreach (var (damageTypeID, amount) in component.Damages)
|
||||
{
|
||||
damage.ChangeDamage(damageType, amount, false, shooter);
|
||||
damage.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>(damageTypeID), amount);
|
||||
}
|
||||
|
||||
component.DamagedEntity = true;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Content.Server.Repairable
|
||||
{
|
||||
if (!await welder.UseTool(eventArgs.User, Owner, _doAfterDelay, ToolQuality.Welding, _fuelCost))
|
||||
return false;
|
||||
damageable.Heal();
|
||||
damageable.TrySetAllDamage(0);
|
||||
|
||||
Owner.PopupMessage(eventArgs.User,
|
||||
Loc.GetString("comp-repairable-repair",
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Content.Server.Spawners.Components
|
||||
[DataField("job_id")]
|
||||
private string? _jobId;
|
||||
|
||||
[field: ViewVariables(VVAccess.ReadWrite)]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("spawn_type")]
|
||||
public SpawnPointType SpawnType { get; } = SpawnPointType.Unset;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using Content.Server.Alert;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Atmos;
|
||||
@@ -8,6 +8,8 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Temperature.Components
|
||||
{
|
||||
@@ -22,11 +24,21 @@ namespace Content.Server.Temperature.Components
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Temperature";
|
||||
|
||||
[ViewVariables] public float CurrentTemperature { get => _currentTemperature; set => _currentTemperature = value; }
|
||||
[DataField("heatDamageThreshold")]
|
||||
private float _heatDamageThreshold = default;
|
||||
[DataField("coldDamageThreshold")]
|
||||
private float _coldDamageThreshold = default;
|
||||
[DataField("tempDamageCoefficient")]
|
||||
private float _tempDamageCoefficient = 1;
|
||||
[DataField("currentTemperature")]
|
||||
public float CurrentTemperature { get; set; } = Atmospherics.T20C;
|
||||
[DataField("specificHeat")]
|
||||
private float _specificHeat = Atmospherics.MinimumHeatCapacity;
|
||||
|
||||
[ViewVariables] public float HeatDamageThreshold => _heatDamageThreshold;
|
||||
[ViewVariables] public float ColdDamageThreshold => _coldDamageThreshold;
|
||||
[ViewVariables] public float TempDamageCoefficient => _tempDamageCoefficient;
|
||||
[ViewVariables] public float SpecificHeat => _specificHeat;
|
||||
[ViewVariables] public float HeatCapacity {
|
||||
get
|
||||
{
|
||||
@@ -39,33 +51,25 @@ namespace Content.Server.Temperature.Components
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables] public float SpecificHeat => _specificHeat;
|
||||
|
||||
[DataField("heatDamageThreshold")]
|
||||
private float _heatDamageThreshold = default;
|
||||
[DataField("coldDamageThreshold")]
|
||||
private float _coldDamageThreshold = default;
|
||||
[DataField("tempDamageCoefficient")]
|
||||
private float _tempDamageCoefficient = 1;
|
||||
[DataField("currentTemperature")]
|
||||
private float _currentTemperature = Atmospherics.T20C;
|
||||
[DataField("specificHeat")]
|
||||
private float _specificHeat = Atmospherics.MinimumHeatCapacity;
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("coldDamageType")]
|
||||
private readonly string _coldDamageTypeID = "Cold";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype ColdDamageType = default!;
|
||||
[DataField("hotDamageType")]
|
||||
private readonly string _hotDamageTypeID = "Heat";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype HotDamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
ColdDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_coldDamageTypeID);
|
||||
HotDamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_hotDamageTypeID);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var tempDamage = 0;
|
||||
DamageType? damageType = null;
|
||||
if (CurrentTemperature >= _heatDamageThreshold)
|
||||
{
|
||||
tempDamage = (int) Math.Floor((CurrentTemperature - _heatDamageThreshold) * _tempDamageCoefficient);
|
||||
damageType = DamageType.Heat;
|
||||
}
|
||||
else if (CurrentTemperature <= _coldDamageThreshold)
|
||||
{
|
||||
tempDamage = (int) Math.Floor((_coldDamageThreshold - CurrentTemperature) * _tempDamageCoefficient);
|
||||
damageType = DamageType.Cold;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out ServerAlertsComponent? status))
|
||||
{
|
||||
@@ -108,10 +112,19 @@ namespace Content.Server.Temperature.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (!damageType.HasValue) return;
|
||||
|
||||
if (!Owner.TryGetComponent(out IDamageableComponent? component)) return;
|
||||
component.ChangeDamage(damageType.Value, tempDamage, false);
|
||||
|
||||
if (CurrentTemperature >= _heatDamageThreshold)
|
||||
{
|
||||
int tempDamage = (int) Math.Floor((CurrentTemperature - _heatDamageThreshold) * _tempDamageCoefficient);
|
||||
component.TryChangeDamage(HotDamageType, tempDamage, false);
|
||||
}
|
||||
else if (CurrentTemperature <= _coldDamageThreshold)
|
||||
{
|
||||
int tempDamage = (int) Math.Floor((_coldDamageThreshold - CurrentTemperature) * _tempDamageCoefficient);
|
||||
component.TryChangeDamage(ColdDamageType, tempDamage, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,8 @@ using Content.Shared.Sound;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Weapon.Melee.Components
|
||||
{
|
||||
@@ -48,15 +50,23 @@ namespace Content.Server.Weapon.Melee.Components
|
||||
[DataField("damage")]
|
||||
public int Damage { get; set; } = 5;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("damageType")]
|
||||
public DamageType DamageType { get; set; } = DamageType.Blunt;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("clickAttackEffect")]
|
||||
public bool ClickAttackEffect { get; set; } = true;
|
||||
|
||||
public TimeSpan LastAttackTime;
|
||||
public TimeSpan CooldownEnd;
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// Also remove Initialize override, if no longer needed.
|
||||
[DataField("damageType")]
|
||||
private readonly string _damageTypeID = "Blunt";
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public DamageTypePrototype DamageType = default!;
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
DamageType = IoCManager.Resolve<IPrototypeManager>().Index<DamageTypePrototype>(_damageTypeID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace Content.Server.Weapon.Melee
|
||||
public sealed class MeleeWeaponSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IGameTiming _gameTiming = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -88,7 +90,7 @@ namespace Content.Server.Weapon.Melee
|
||||
|
||||
if (target.TryGetComponent(out IDamageableComponent? damageableComponent))
|
||||
{
|
||||
damageableComponent.ChangeDamage(comp.DamageType, comp.Damage, false, owner);
|
||||
damageableComponent.TryChangeDamage(comp.DamageType, comp.Damage);
|
||||
}
|
||||
|
||||
SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), target);
|
||||
@@ -157,7 +159,7 @@ namespace Content.Server.Weapon.Melee
|
||||
{
|
||||
if (entity.TryGetComponent<IDamageableComponent>(out var damageComponent))
|
||||
{
|
||||
damageComponent.ChangeDamage(comp.DamageType, comp.Damage, false, owner);
|
||||
damageComponent.TryChangeDamage(comp.DamageType, comp.Damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
|
||||
{
|
||||
if (energyRatio < 1.0)
|
||||
{
|
||||
var newDamages = new Dictionary<DamageType, int>(projectileComponent.Damages.Count);
|
||||
var newDamages = new Dictionary<string, int>(projectileComponent.Damages.Count);
|
||||
foreach (var (damageType, damage) in projectileComponent.Damages)
|
||||
{
|
||||
newDamages.Add(damageType, (int) (damage * energyRatio));
|
||||
|
||||
@@ -399,7 +399,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
|
||||
if (!result.HitEntity.TryGetComponent(out IDamageableComponent? damageable))
|
||||
return;
|
||||
|
||||
damageable.ChangeDamage(hitscan.DamageType, (int)Math.Round(hitscan.Damage, MidpointRounding.AwayFromZero), false, Owner);
|
||||
damageable.TryChangeDamage(hitscan.DamageType, (int)Math.Round(hitscan.Damage, MidpointRounding.AwayFromZero));
|
||||
//I used Math.Round over Convert.toInt32, as toInt32 always rounds to
|
||||
//even numbers if halfway between two numbers, rather than rounding to nearest
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Content.Server.Weapon.Ranged
|
||||
{
|
||||
@@ -55,6 +57,17 @@ namespace Content.Server.Weapon.Ranged
|
||||
|
||||
[DataField("clumsyWeaponShotSound")]
|
||||
private SoundSpecifier _clumsyWeaponShotSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg");
|
||||
|
||||
// TODO PROTOTYPE Replace this datafield variable with prototype references, once they are supported.
|
||||
// This also requires changing the dictionary type and modifying TryFire(), which uses it.
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("clumsyDamage")]
|
||||
public Dictionary<string, int> ClumsyDamage { get; set; } = new()
|
||||
{
|
||||
{ "Blunt", 10 },
|
||||
{ "Heat", 5 }
|
||||
};
|
||||
|
||||
public Func<bool>? WeaponCanFireHandler;
|
||||
public Func<IEntity, bool>? UserCanFireHandler;
|
||||
@@ -168,25 +181,30 @@ namespace Content.Server.Weapon.Ranged
|
||||
|
||||
if (ClumsyCheck && ClumsyComponent.TryRollClumsy(user, ClumsyExplodeChance))
|
||||
{
|
||||
SoundSystem.Play(
|
||||
//Wound them
|
||||
if (user.TryGetComponent(out IDamageableComponent? health))
|
||||
{
|
||||
foreach (KeyValuePair<string, int> damage in ClumsyDamage)
|
||||
{
|
||||
health.TryChangeDamage(_prototypeManager.Index<DamageTypePrototype>(damage.Key), damage.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Knock them down
|
||||
if (user.TryGetComponent(out StunnableComponent? stun))
|
||||
{
|
||||
stun.Paralyze(3f);
|
||||
}
|
||||
|
||||
// Apply salt to the wound ("Honk!")
|
||||
SoundSystem.Play(
|
||||
Filter.Pvs(Owner), _clumsyWeaponHandlingSound.GetSound(),
|
||||
Owner.Transform.Coordinates, AudioParams.Default.WithMaxDistance(5));
|
||||
|
||||
SoundSystem.Play(
|
||||
Filter.Pvs(Owner), _clumsyWeaponShotSound.GetSound(),
|
||||
Owner.Transform.Coordinates, AudioParams.Default.WithMaxDistance(5));
|
||||
|
||||
if (user.TryGetComponent(out IDamageableComponent? health))
|
||||
{
|
||||
health.ChangeDamage(DamageType.Blunt, 10, false, user);
|
||||
health.ChangeDamage(DamageType.Heat, 5, false, user);
|
||||
}
|
||||
|
||||
if (user.TryGetComponent(out StunnableComponent? stun))
|
||||
{
|
||||
stun.Paralyze(3f);
|
||||
}
|
||||
|
||||
|
||||
user.PopupMessage(Loc.GetString("server-ranged-weapon-component-try-fire-clumsy"));
|
||||
|
||||
Owner.Delete();
|
||||
|
||||
Reference in New Issue
Block a user