Cache *Notify traits in Health where applicable
During heated battles, those TraitsImplementing look-ups in Health might cause bursty CPU load on warhead impacts. Caching the notify traits of the actor + owner can reduce the trait look-ups per impact by more than half.
This commit is contained in:
@@ -32,9 +32,16 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Health : IHealth, ISync, ITick
|
public class Health : IHealth, ISync, ITick, INotifyCreated, INotifyOwnerChanged
|
||||||
{
|
{
|
||||||
public readonly HealthInfo Info;
|
public readonly HealthInfo Info;
|
||||||
|
INotifyDamageStateChanged[] notifyDamageStateChanged;
|
||||||
|
INotifyDamage[] notifyDamage;
|
||||||
|
INotifyDamage[] notifyDamagePlayer;
|
||||||
|
IDamageModifier[] damageModifiers;
|
||||||
|
IDamageModifier[] damageModifiersPlayer;
|
||||||
|
INotifyKilled[] notifyKilled;
|
||||||
|
INotifyKilled[] notifyKilledPlayer;
|
||||||
|
|
||||||
[Sync] int hp;
|
[Sync] int hp;
|
||||||
|
|
||||||
@@ -80,6 +87,24 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INotifyCreated.Created(Actor self)
|
||||||
|
{
|
||||||
|
notifyDamageStateChanged = self.TraitsImplementing<INotifyDamageStateChanged>().ToArray();
|
||||||
|
notifyDamage = self.TraitsImplementing<INotifyDamage>().ToArray();
|
||||||
|
notifyDamagePlayer = self.Owner.PlayerActor.TraitsImplementing<INotifyDamage>().ToArray();
|
||||||
|
damageModifiers = self.TraitsImplementing<IDamageModifier>().ToArray();
|
||||||
|
damageModifiersPlayer = self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>().ToArray();
|
||||||
|
notifyKilled = self.TraitsImplementing<INotifyKilled>().ToArray();
|
||||||
|
notifyKilledPlayer = self.Owner.PlayerActor.TraitsImplementing<INotifyKilled>().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||||
|
{
|
||||||
|
notifyDamagePlayer = newOwner.PlayerActor.TraitsImplementing<INotifyDamage>().ToArray();
|
||||||
|
damageModifiersPlayer = newOwner.PlayerActor.TraitsImplementing<IDamageModifier>().ToArray();
|
||||||
|
notifyKilledPlayer = newOwner.PlayerActor.TraitsImplementing<INotifyKilled>().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public void Resurrect(Actor self, Actor repairer)
|
public void Resurrect(Actor self, Actor repairer)
|
||||||
{
|
{
|
||||||
if (!IsDead)
|
if (!IsDead)
|
||||||
@@ -95,17 +120,21 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
PreviousDamageState = DamageState.Dead,
|
PreviousDamageState = DamageState.Dead,
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var nd in self.TraitsImplementing<INotifyDamage>()
|
foreach (var nd in notifyDamage)
|
||||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<INotifyDamage>()))
|
nd.Damaged(self, ai);
|
||||||
|
foreach (var nd in notifyDamagePlayer)
|
||||||
nd.Damaged(self, ai);
|
nd.Damaged(self, ai);
|
||||||
|
|
||||||
foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>())
|
foreach (var nd in notifyDamageStateChanged)
|
||||||
nd.DamageStateChanged(self, ai);
|
nd.DamageStateChanged(self, ai);
|
||||||
|
|
||||||
if (Info.NotifyAppliedDamage && repairer != null && repairer.IsInWorld && !repairer.IsDead)
|
if (Info.NotifyAppliedDamage && repairer != null && repairer.IsInWorld && !repairer.IsDead)
|
||||||
foreach (var nd in repairer.TraitsImplementing<INotifyAppliedDamage>()
|
{
|
||||||
.Concat(repairer.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>()))
|
foreach (var nd in repairer.TraitsImplementing<INotifyAppliedDamage>())
|
||||||
nd.AppliedDamage(repairer, self, ai);
|
nd.AppliedDamage(repairer, self, ai);
|
||||||
|
foreach (var nd in repairer.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>())
|
||||||
|
nd.AppliedDamage(repairer, self, ai);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers)
|
public void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers)
|
||||||
@@ -119,8 +148,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
// Apply any damage modifiers
|
// Apply any damage modifiers
|
||||||
if (!ignoreModifiers && damage.Value > 0)
|
if (!ignoreModifiers && damage.Value > 0)
|
||||||
{
|
{
|
||||||
var modifiers = self.TraitsImplementing<IDamageModifier>()
|
var modifiers = damageModifiers
|
||||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
.Concat(damageModifiersPlayer)
|
||||||
.Select(t => t.GetDamageModifier(attacker, damage));
|
.Select(t => t.GetDamageModifier(attacker, damage));
|
||||||
|
|
||||||
damage = new Damage(Util.ApplyPercentageModifiers(damage.Value, modifiers), damage.DamageTypes);
|
damage = new Damage(Util.ApplyPercentageModifiers(damage.Value, modifiers), damage.DamageTypes);
|
||||||
@@ -136,23 +165,28 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
PreviousDamageState = oldState,
|
PreviousDamageState = oldState,
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var nd in self.TraitsImplementing<INotifyDamage>()
|
foreach (var nd in notifyDamage)
|
||||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<INotifyDamage>()))
|
nd.Damaged(self, ai);
|
||||||
|
foreach (var nd in notifyDamagePlayer)
|
||||||
nd.Damaged(self, ai);
|
nd.Damaged(self, ai);
|
||||||
|
|
||||||
if (DamageState != oldState)
|
if (DamageState != oldState)
|
||||||
foreach (var nd in self.TraitsImplementing<INotifyDamageStateChanged>())
|
foreach (var nd in notifyDamageStateChanged)
|
||||||
nd.DamageStateChanged(self, ai);
|
nd.DamageStateChanged(self, ai);
|
||||||
|
|
||||||
if (Info.NotifyAppliedDamage && attacker != null && attacker.IsInWorld && !attacker.IsDead)
|
if (Info.NotifyAppliedDamage && attacker != null && attacker.IsInWorld && !attacker.IsDead)
|
||||||
foreach (var nd in attacker.TraitsImplementing<INotifyAppliedDamage>()
|
{
|
||||||
.Concat(attacker.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>()))
|
foreach (var nd in attacker.TraitsImplementing<INotifyAppliedDamage>())
|
||||||
nd.AppliedDamage(attacker, self, ai);
|
nd.AppliedDamage(attacker, self, ai);
|
||||||
|
foreach (var nd in attacker.Owner.PlayerActor.TraitsImplementing<INotifyAppliedDamage>())
|
||||||
|
nd.AppliedDamage(attacker, self, ai);
|
||||||
|
}
|
||||||
|
|
||||||
if (hp == 0)
|
if (hp == 0)
|
||||||
{
|
{
|
||||||
foreach (var nd in self.TraitsImplementing<INotifyKilled>()
|
foreach (var nd in notifyKilled)
|
||||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<INotifyKilled>()))
|
nd.Killed(self, ai);
|
||||||
|
foreach (var nd in notifyKilledPlayer)
|
||||||
nd.Killed(self, ai);
|
nd.Killed(self, ai);
|
||||||
|
|
||||||
if (RemoveOnDeath)
|
if (RemoveOnDeath)
|
||||||
|
|||||||
Reference in New Issue
Block a user