diff --git a/Content.Server/GameObjects/Components/Damage/DamageThreshold.cs b/Content.Server/GameObjects/Components/Damage/DamageThreshold.cs
index cf9596eef9..8cf06a9103 100644
--- a/Content.Server/GameObjects/Components/Damage/DamageThreshold.cs
+++ b/Content.Server/GameObjects/Components/Damage/DamageThreshold.cs
@@ -1,5 +1,7 @@
using System;
using Content.Shared.GameObjects;
+using JetBrains.Annotations;
+using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects
{
@@ -60,5 +62,38 @@ namespace Content.Server.GameObjects
ExcessDamage = excess;
}
}
+
+ public class DamageEventArgs : EventArgs
+ {
+ ///
+ /// Type of damage.
+ ///
+ public DamageType Type { get; }
+
+ ///
+ /// Change in damage.
+ ///
+ public int Damage { get; }
+
+ ///
+ /// The entity that damaged this one.
+ /// Could be null.
+ ///
+ public IEntity Source { get; }
+
+ ///
+ /// The mob entity that damaged this one.
+ /// Could be null.
+ ///
+ public IEntity SourceMob { get; }
+
+ public DamageEventArgs(DamageType type, int damage, IEntity source, IEntity sourceMob)
+ {
+ Type = type;
+ Damage = damage;
+ Source = source;
+ SourceMob = sourceMob;
+ }
+ }
}
diff --git a/Content.Server/GameObjects/Components/Damage/DamageableComponent.cs b/Content.Server/GameObjects/Components/Damage/DamageableComponent.cs
index a933884708..76d34a39af 100644
--- a/Content.Server/GameObjects/Components/Damage/DamageableComponent.cs
+++ b/Content.Server/GameObjects/Components/Damage/DamageableComponent.cs
@@ -5,6 +5,7 @@ using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects;
using Robust.Shared.GameObjects;
+using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -36,6 +37,7 @@ namespace Content.Server.GameObjects
Dictionary> Thresholds = new Dictionary>();
public event EventHandler DamageThresholdPassed;
+ public event EventHandler Damaged;
public override ComponentState GetComponentState()
{
@@ -62,13 +64,14 @@ namespace Content.Server.GameObjects
foreach (var damagebehavior in Owner.GetAllComponents())
{
AddThresholdsFrom(damagebehavior);
+ Damaged += damagebehavior.OnDamaged;
}
RecalculateComponentThresholds();
}
///
- public void TakeDamage(DamageType damageType, int amount)
+ public void TakeDamage(DamageType damageType, int amount, IEntity source = null, IEntity sourceMob = null)
{
if (damageType == DamageType.Total)
{
@@ -88,6 +91,8 @@ namespace Content.Server.GameObjects
_currentDamage[damageType] = Math.Max(0, _currentDamage[damageType] + amount);
UpdateForDamageType(damageType, oldValue);
+ Damaged?.Invoke(this, new DamageEventArgs(damageType, amount, source, sourceMob));
+
if (Resistances.AppliesToTotal(damageType))
{
oldTotalValue = _currentDamage[DamageType.Total];
@@ -97,13 +102,13 @@ namespace Content.Server.GameObjects
}
///
- public void TakeHealing(DamageType damageType, int amount)
+ public void TakeHealing(DamageType damageType, int amount, IEntity source = null, IEntity sourceMob = null)
{
if (damageType == DamageType.Total)
{
throw new ArgumentException("Cannot heal for DamageType.Total");
}
- TakeDamage(damageType, -amount);
+ TakeDamage(damageType, -amount, source, sourceMob);
}
public void HealAllDamage()
@@ -163,6 +168,9 @@ namespace Content.Server.GameObjects
List thresholds = onDamageBehavior.GetAllDamageThresholds();
+ if (thresholds == null)
+ return;
+
foreach (DamageThreshold threshold in thresholds)
{
if (!Thresholds[threshold.DamageType].Contains(threshold))
diff --git a/Content.Server/GameObjects/Components/Mining/AsteroidRockComponent.cs b/Content.Server/GameObjects/Components/Mining/AsteroidRockComponent.cs
index ae0ff93a36..bc11b88107 100644
--- a/Content.Server/GameObjects/Components/Mining/AsteroidRockComponent.cs
+++ b/Content.Server/GameObjects/Components/Mining/AsteroidRockComponent.cs
@@ -33,7 +33,7 @@ namespace Content.Server.GameObjects.Components.Mining
var item = eventArgs.AttackWith;
if (!item.TryGetComponent(out MeleeWeaponComponent meleeWeaponComponent)) return false;
- Owner.GetComponent().TakeDamage(DamageType.Brute, meleeWeaponComponent.Damage);
+ Owner.GetComponent().TakeDamage(DamageType.Brute, meleeWeaponComponent.Damage, item, eventArgs.User);
if (!item.TryGetComponent(out PickaxeComponent pickaxeComponent)) return true;
if (!string.IsNullOrWhiteSpace(pickaxeComponent.MiningSound) &&
diff --git a/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs b/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs
index 94f860ab9e..6d68d59881 100644
--- a/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs
+++ b/Content.Server/GameObjects/Components/Mobs/SpeciesComponent.cs
@@ -184,8 +184,8 @@ namespace Content.Server.GameObjects
bruteDamage += 30;
break;
}
- Owner.GetComponent().TakeDamage(DamageType.Brute, bruteDamage);
- Owner.GetComponent().TakeDamage(DamageType.Heat, burnDamage);
+ Owner.GetComponent().TakeDamage(DamageType.Brute, bruteDamage, eventArgs.Source);
+ Owner.GetComponent().TakeDamage(DamageType.Heat, burnDamage, eventArgs.Source);
}
}
diff --git a/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
index 7b5bd39733..fc66958ece 100644
--- a/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
+++ b/Content.Server/GameObjects/Components/Power/PoweredLightComponent.cs
@@ -73,7 +73,7 @@ namespace Content.Server.GameObjects.Components.Power
void Burn()
{
- damageableComponent.TakeDamage(DamageType.Heat, 20);
+ damageableComponent.TakeDamage(DamageType.Heat, 20, Owner);
}
void Eject()
diff --git a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs
index 519e0f8892..b2b3ca923e 100644
--- a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs
+++ b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs
@@ -71,9 +71,12 @@ namespace Content.Server.GameObjects.Components.Projectiles
{
if (entity.TryGetComponent(out DamageableComponent damage))
{
- foreach (var damageType in _damages)
+ Owner.EntityManager.TryGetEntity(Shooter, out var shooter);
+
+ foreach (var (damageType, amount) in _damages)
{
- damage.TakeDamage(damageType.Key, damageType.Value);
+
+ damage.TakeDamage(damageType, amount, Owner, shooter);
}
}
diff --git a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs
index d07e91b9e9..cbc63c3231 100644
--- a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs
+++ b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs
@@ -31,7 +31,7 @@ namespace Content.Server.GameObjects.Components
{
if (entity.TryGetComponent(out DamageableComponent damage))
{
- damage.TakeDamage(DamageType.Brute, 10);
+ damage.TakeDamage(DamageType.Brute, 10, Owner, User);
}
}
diff --git a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs
index 0a250f9d3c..dcea664899 100644
--- a/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs
+++ b/Content.Server/GameObjects/Components/Temperature/TemperatureComponent.cs
@@ -43,7 +43,7 @@ namespace Content.Server.GameObjects
_secondsSinceLastDamageUpdate += frameTime;
- Owner.TryGetComponent(out DamageableComponent component);
+ Owner.TryGetComponent(out DamageableComponent component);
while (_secondsSinceLastDamageUpdate >= 1)
{
diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs
index def7fc56dc..54249e39ba 100644
--- a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs
@@ -96,7 +96,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
if (entity.TryGetComponent(out DamageableComponent damageComponent))
{
- damageComponent.TakeDamage(DamageType.Brute, Damage);
+ damageComponent.TakeDamage(DamageType.Brute, Damage, Owner, eventArgs.User);
hitEntities.Add(entity);
}
}
diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
index c38281fe28..3ae6d069cd 100644
--- a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
+++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs
@@ -92,15 +92,15 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan
var ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable));
var rayCastResults = IoCManager.Resolve().IntersectRay(user.Transform.MapID, ray, MaxLength, user);
- Hit(rayCastResults, energyModifier);
+ Hit(rayCastResults, energyModifier, user);
AfterEffects(user, rayCastResults, angle, energyModifier);
}
- protected virtual void Hit(RayCastResults ray, float damageModifier)
+ protected virtual void Hit(RayCastResults ray, float damageModifier, IEntity user = null)
{
if (ray.HitEntity != null && ray.HitEntity.TryGetComponent(out DamageableComponent damage))
{
- damage.TakeDamage(DamageType.Heat, (int)Math.Round(_damage * damageModifier, MidpointRounding.AwayFromZero));
+ damage.TakeDamage(DamageType.Heat, (int)Math.Round(_damage * damageModifier, MidpointRounding.AwayFromZero), Owner, user);
//I used Math.Round over Convert.toInt32, as toInt32 always rounds to
//even numbers if halfway between two numbers, rather than rounding to nearest
}
diff --git a/Content.Server/Interfaces/GameObjects/Components/Damage/IDamageableComponent.cs b/Content.Server/Interfaces/GameObjects/Components/Damage/IDamageableComponent.cs
index 4e4116c92f..e45685a46b 100644
--- a/Content.Server/Interfaces/GameObjects/Components/Damage/IDamageableComponent.cs
+++ b/Content.Server/Interfaces/GameObjects/Components/Damage/IDamageableComponent.cs
@@ -17,15 +17,19 @@ namespace Content.Server.Interfaces.GameObjects
///
/// Type of damage being received.
/// Amount of damage being received.
- void TakeDamage(DamageType damageType, int amount);
+ /// Entity that damaged this entity.
+ /// Mob that damaged this entity.
+ void TakeDamage(DamageType damageType, int amount, IEntity source, IEntity sourceMob);
///
/// Handles receiving healing.
/// Converts healing via the resistance set then applies it
/// and informs components of thresholds passed as necessary.
///
- /// Type of damage being received.
- /// Amount of damage being received.
- void TakeHealing(DamageType damageType, int amount);
+ /// Type of healing being received.
+ /// Amount of healing being received.
+ /// Entity that healed this entity.
+ /// Mob that healed this entity.
+ void TakeHealing(DamageType damageType, int amount, IEntity source, IEntity sourceMob);
}
}
diff --git a/Content.Server/Interfaces/GameObjects/IOnDamageBehavior.cs b/Content.Server/Interfaces/GameObjects/IOnDamageBehavior.cs
index c15da0d04c..fdd8b7bb93 100644
--- a/Content.Server/Interfaces/GameObjects/IOnDamageBehavior.cs
+++ b/Content.Server/Interfaces/GameObjects/IOnDamageBehavior.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Content.Server.GameObjects;
namespace Content.Server.Interfaces
@@ -15,13 +16,20 @@ namespace Content.Server.Interfaces
/// Gets a list of all DamageThresholds this component/entity are interested in.
///
/// List of DamageThresholds to be added to DamageableComponent for watching.
- List GetAllDamageThresholds();
+ List GetAllDamageThresholds() => null;
///
/// Damage threshold passed event hookup.
///
/// Damageable component.
/// Damage threshold and whether it's passed in one way or another.
- void OnDamageThresholdPassed(object obj, DamageThresholdPassedEventArgs e);
+ void OnDamageThresholdPassed(object obj, DamageThresholdPassedEventArgs e) { }
+
+ ///
+ /// Called when the entity is damaged.
+ ///
+ /// Damageable component.
+ /// DamageEventArgs
+ void OnDamaged(object obj, DamageEventArgs e) { }
}
}