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 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
{
/// <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.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<DamageType, List<DamageThreshold>> Thresholds = new Dictionary<DamageType, List<DamageThreshold>>();
public event EventHandler<DamageThresholdPassedEventArgs> DamageThresholdPassed;
public event EventHandler<DamageEventArgs> Damaged;
public override ComponentState GetComponentState()
{
@@ -62,13 +64,14 @@ namespace Content.Server.GameObjects
foreach (var damagebehavior in Owner.GetAllComponents<IOnDamageBehavior>())
{
AddThresholdsFrom(damagebehavior);
Damaged += damagebehavior.OnDamaged;
}
RecalculateComponentThresholds();
}
/// <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)
{
@@ -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
}
/// <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)
{
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<DamageThreshold> thresholds = onDamageBehavior.GetAllDamageThresholds();
if (thresholds == null)
return;
foreach (DamageThreshold threshold in thresholds)
{
if (!Thresholds[threshold.DamageType].Contains(threshold))

View File

@@ -33,7 +33,7 @@ namespace Content.Server.GameObjects.Components.Mining
var item = eventArgs.AttackWith;
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 (!string.IsNullOrWhiteSpace(pickaxeComponent.MiningSound) &&

View File

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

View File

@@ -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()

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

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

View File

@@ -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);
}
}

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 rayCastResults = IoCManager.Resolve<IPhysicsManager>().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
}

View File

@@ -17,15 +17,19 @@ namespace Content.Server.Interfaces.GameObjects
/// </summary>
/// <param name="damageType">Type 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>
/// Handles receiving healing.
/// Converts healing via the resistance set then applies it
/// and informs components of thresholds passed as necessary.
/// </summary>
/// <param name="damageType">Type of damage being received.</param>
/// <param name="amount">Amount of damage being received.</param>
void TakeHealing(DamageType damageType, int amount);
/// <param name="damageType">Type of healing being received.</param>
/// <param name="amount">Amount of healing being received.</param>
/// <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;
namespace Content.Server.Interfaces
@@ -15,13 +16,20 @@ namespace Content.Server.Interfaces
/// Gets a list of all DamageThresholds this component/entity are interested in.
/// </summary>
/// <returns>List of DamageThresholds to be added to DamageableComponent for watching.</returns>
List<DamageThreshold> GetAllDamageThresholds();
List<DamageThreshold> GetAllDamageThresholds() => null;
/// <summary>
/// Damage threshold passed event hookup.
/// </summary>
/// <param name="obj">Damageable component.</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) { }
}
}