Add OnDamaged method to IOnDamageBehavior (#685)

* Add OnDamaged method to IOnDamageBehavior

* Adds Source, SourceMob to OnDamage.
This commit is contained in:
Víctor Aguilera Puerto
2020-02-13 15:57:40 +01:00
committed by GitHub
parent 3292939756
commit 934f6fb7e2
12 changed files with 80 additions and 22 deletions

View File

@@ -1,5 +1,7 @@
using System; using System;
using Content.Shared.GameObjects; using Content.Shared.GameObjects;
using JetBrains.Annotations;
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Server.GameObjects namespace Content.Server.GameObjects
{ {
@@ -60,5 +62,38 @@ namespace Content.Server.GameObjects
ExcessDamage = excess; ExcessDamage = excess;
} }
} }
public class DamageEventArgs : EventArgs
{
/// <summary>
/// Type of damage.
/// </summary>
public DamageType Type { get; }
/// <summary>
/// Change in damage.
/// </summary>
public int Damage { get; }
/// <summary>
/// The entity that damaged this one.
/// Could be null.
/// </summary>
public IEntity Source { get; }
/// <summary>
/// The mob entity that damaged this one.
/// Could be null.
/// </summary>
public IEntity SourceMob { get; }
public DamageEventArgs(DamageType type, int damage, IEntity source, IEntity sourceMob)
{
Type = type;
Damage = damage;
Source = source;
SourceMob = sourceMob;
}
}
} }

View File

@@ -5,6 +5,7 @@ using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects; using Content.Server.Interfaces.GameObjects;
using Content.Shared.GameObjects; using Content.Shared.GameObjects;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -36,6 +37,7 @@ namespace Content.Server.GameObjects
Dictionary<DamageType, List<DamageThreshold>> Thresholds = new Dictionary<DamageType, List<DamageThreshold>>(); Dictionary<DamageType, List<DamageThreshold>> Thresholds = new Dictionary<DamageType, List<DamageThreshold>>();
public event EventHandler<DamageThresholdPassedEventArgs> DamageThresholdPassed; public event EventHandler<DamageThresholdPassedEventArgs> DamageThresholdPassed;
public event EventHandler<DamageEventArgs> Damaged;
public override ComponentState GetComponentState() public override ComponentState GetComponentState()
{ {
@@ -62,13 +64,14 @@ namespace Content.Server.GameObjects
foreach (var damagebehavior in Owner.GetAllComponents<IOnDamageBehavior>()) foreach (var damagebehavior in Owner.GetAllComponents<IOnDamageBehavior>())
{ {
AddThresholdsFrom(damagebehavior); AddThresholdsFrom(damagebehavior);
Damaged += damagebehavior.OnDamaged;
} }
RecalculateComponentThresholds(); RecalculateComponentThresholds();
} }
/// <inheritdoc /> /// <inheritdoc />
public void TakeDamage(DamageType damageType, int amount) public void TakeDamage(DamageType damageType, int amount, IEntity source = null, IEntity sourceMob = null)
{ {
if (damageType == DamageType.Total) if (damageType == DamageType.Total)
{ {
@@ -88,6 +91,8 @@ namespace Content.Server.GameObjects
_currentDamage[damageType] = Math.Max(0, _currentDamage[damageType] + amount); _currentDamage[damageType] = Math.Max(0, _currentDamage[damageType] + amount);
UpdateForDamageType(damageType, oldValue); UpdateForDamageType(damageType, oldValue);
Damaged?.Invoke(this, new DamageEventArgs(damageType, amount, source, sourceMob));
if (Resistances.AppliesToTotal(damageType)) if (Resistances.AppliesToTotal(damageType))
{ {
oldTotalValue = _currentDamage[DamageType.Total]; oldTotalValue = _currentDamage[DamageType.Total];
@@ -97,13 +102,13 @@ namespace Content.Server.GameObjects
} }
/// <inheritdoc /> /// <inheritdoc />
public void TakeHealing(DamageType damageType, int amount) public void TakeHealing(DamageType damageType, int amount, IEntity source = null, IEntity sourceMob = null)
{ {
if (damageType == DamageType.Total) if (damageType == DamageType.Total)
{ {
throw new ArgumentException("Cannot heal for DamageType.Total"); throw new ArgumentException("Cannot heal for DamageType.Total");
} }
TakeDamage(damageType, -amount); TakeDamage(damageType, -amount, source, sourceMob);
} }
public void HealAllDamage() public void HealAllDamage()
@@ -163,6 +168,9 @@ namespace Content.Server.GameObjects
List<DamageThreshold> thresholds = onDamageBehavior.GetAllDamageThresholds(); List<DamageThreshold> thresholds = onDamageBehavior.GetAllDamageThresholds();
if (thresholds == null)
return;
foreach (DamageThreshold threshold in thresholds) foreach (DamageThreshold threshold in thresholds)
{ {
if (!Thresholds[threshold.DamageType].Contains(threshold)) if (!Thresholds[threshold.DamageType].Contains(threshold))

View File

@@ -33,7 +33,7 @@ namespace Content.Server.GameObjects.Components.Mining
var item = eventArgs.AttackWith; var item = eventArgs.AttackWith;
if (!item.TryGetComponent(out MeleeWeaponComponent meleeWeaponComponent)) return false; if (!item.TryGetComponent(out MeleeWeaponComponent meleeWeaponComponent)) return false;
Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Brute, meleeWeaponComponent.Damage); Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Brute, meleeWeaponComponent.Damage, item, eventArgs.User);
if (!item.TryGetComponent(out PickaxeComponent pickaxeComponent)) return true; if (!item.TryGetComponent(out PickaxeComponent pickaxeComponent)) return true;
if (!string.IsNullOrWhiteSpace(pickaxeComponent.MiningSound) && if (!string.IsNullOrWhiteSpace(pickaxeComponent.MiningSound) &&

View File

@@ -184,8 +184,8 @@ namespace Content.Server.GameObjects
bruteDamage += 30; bruteDamage += 30;
break; break;
} }
Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Brute, bruteDamage); Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Brute, bruteDamage, eventArgs.Source);
Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Heat, burnDamage); Owner.GetComponent<DamageableComponent>().TakeDamage(DamageType.Heat, burnDamage, eventArgs.Source);
} }
} }

View File

@@ -73,7 +73,7 @@ namespace Content.Server.GameObjects.Components.Power
void Burn() void Burn()
{ {
damageableComponent.TakeDamage(DamageType.Heat, 20); damageableComponent.TakeDamage(DamageType.Heat, 20, Owner);
} }
void Eject() void Eject()

View File

@@ -71,9 +71,12 @@ namespace Content.Server.GameObjects.Components.Projectiles
{ {
if (entity.TryGetComponent(out DamageableComponent damage)) 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);
} }
} }

View File

@@ -31,7 +31,7 @@ namespace Content.Server.GameObjects.Components
{ {
if (entity.TryGetComponent(out DamageableComponent damage)) if (entity.TryGetComponent(out DamageableComponent damage))
{ {
damage.TakeDamage(DamageType.Brute, 10); damage.TakeDamage(DamageType.Brute, 10, Owner, User);
} }
} }

View File

@@ -43,7 +43,7 @@ namespace Content.Server.GameObjects
_secondsSinceLastDamageUpdate += frameTime; _secondsSinceLastDamageUpdate += frameTime;
Owner.TryGetComponent<DamageableComponent>(out DamageableComponent component); Owner.TryGetComponent(out DamageableComponent component);
while (_secondsSinceLastDamageUpdate >= 1) while (_secondsSinceLastDamageUpdate >= 1)
{ {

View File

@@ -96,7 +96,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
if (entity.TryGetComponent(out DamageableComponent damageComponent)) if (entity.TryGetComponent(out DamageableComponent damageComponent))
{ {
damageComponent.TakeDamage(DamageType.Brute, Damage); damageComponent.TakeDamage(DamageType.Brute, Damage, Owner, eventArgs.User);
hitEntities.Add(entity); hitEntities.Add(entity);
} }
} }

View File

@@ -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 ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable));
var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user); var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user);
Hit(rayCastResults, energyModifier); Hit(rayCastResults, energyModifier, user);
AfterEffects(user, rayCastResults, angle, energyModifier); 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)) 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 //I used Math.Round over Convert.toInt32, as toInt32 always rounds to
//even numbers if halfway between two numbers, rather than rounding to nearest //even numbers if halfway between two numbers, rather than rounding to nearest
} }

View File

@@ -17,15 +17,19 @@ namespace Content.Server.Interfaces.GameObjects
/// </summary> /// </summary>
/// <param name="damageType">Type of damage being received.</param> /// <param name="damageType">Type of damage being received.</param>
/// <param name="amount">Amount of damage being received.</param> /// <param name="amount">Amount of damage being received.</param>
void TakeDamage(DamageType damageType, int amount); /// <param name="source">Entity that damaged this entity.</param>
/// <param name="sourceMob">Mob that damaged this entity.</param>
void TakeDamage(DamageType damageType, int amount, IEntity source, IEntity sourceMob);
/// <summary> /// <summary>
/// Handles receiving healing. /// Handles receiving healing.
/// Converts healing via the resistance set then applies it /// Converts healing via the resistance set then applies it
/// and informs components of thresholds passed as necessary. /// and informs components of thresholds passed as necessary.
/// </summary> /// </summary>
/// <param name="damageType">Type of damage being received.</param> /// <param name="damageType">Type of healing being received.</param>
/// <param name="amount">Amount of damage being received.</param> /// <param name="amount">Amount of healing being received.</param>
void TakeHealing(DamageType damageType, int amount); /// <param name="source">Entity that healed this entity.</param>
/// <param name="sourceMob">Mob that healed this entity.</param>
void TakeHealing(DamageType damageType, int amount, IEntity source, IEntity sourceMob);
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using Content.Server.GameObjects; using Content.Server.GameObjects;
namespace Content.Server.Interfaces namespace Content.Server.Interfaces
@@ -15,13 +16,20 @@ namespace Content.Server.Interfaces
/// Gets a list of all DamageThresholds this component/entity are interested in. /// Gets a list of all DamageThresholds this component/entity are interested in.
/// </summary> /// </summary>
/// <returns>List of DamageThresholds to be added to DamageableComponent for watching.</returns> /// <returns>List of DamageThresholds to be added to DamageableComponent for watching.</returns>
List<DamageThreshold> GetAllDamageThresholds(); List<DamageThreshold> GetAllDamageThresholds() => null;
/// <summary> /// <summary>
/// Damage threshold passed event hookup. /// Damage threshold passed event hookup.
/// </summary> /// </summary>
/// <param name="obj">Damageable component.</param> /// <param name="obj">Damageable component.</param>
/// <param name="e">Damage threshold and whether it's passed in one way or another.</param> /// <param name="e">Damage threshold and whether it's passed in one way or another.</param>
void OnDamageThresholdPassed(object obj, DamageThresholdPassedEventArgs e); void OnDamageThresholdPassed(object obj, DamageThresholdPassedEventArgs e) { }
/// <summary>
/// Called when the entity is damaged.
/// </summary>
/// <param name="obj">Damageable component.</param>
/// <param name="e">DamageEventArgs</param>
void OnDamaged(object obj, DamageEventArgs e) { }
} }
} }