swb_player/PlayerBase.Health.cs
namespace SWB.Player;
public partial class PlayerBase
{
[Property] public int MaxHealth { get; set; } = 100;
[Sync] public int Health { get; set; } = 100;
[Sync] public int Kills { get; set; }
[Sync] public int Deaths { get; set; }
[Sync] public bool GodMode { get; set; }
public bool IsAlive => Health > 0;
public void OnDamage( in DamageInfo info )
{
if ( info is not Shared.DamageInfo )
{
TakeDamage( Shared.DamageInfo.FromDamageInfo( info ) );
return;
}
info.Shape = null; // Remove physics shape to avoid issues with networking
info.Hitbox = null; // Remove hitbox to avoid issues with networking
TakeDamage( info as Shared.DamageInfo );
}
[Rpc.Broadcast]
public virtual void TakeDamage( Shared.DamageInfo info )
{
if ( !this.IsValid() || IsProxy || !IsAlive || GodMode )
return;
if ( info.Tags.Has( "head" ) )
info.Damage *= 2;
// GAME HOOK (not stock SWB): let anything attached to this player
// reduce the damage before it lands. Armour uses this.
//
// It has to be here rather than anywhere else, because the next
// three lines subtract the damage AND decide whether it killed you.
// Giving health back afterwards would work on every shot except the
// lethal one, which is the only one that matters.
var mitigator = Components.Get<IDamageMitigator>();
if ( mitigator is not null )
info.Damage = mitigator.Mitigate( info.Damage );
Health -= (int)info.Damage;
if ( info.HitFlinch > 0 )
DoHitFlinch( info.HitFlinch );
if ( info.MovementImpact.Duration > 0 )
ApplyMovementImpact( info.MovementImpact );
if ( Health <= 0 )
OnDeath( info );
}
}