Player/PlayerController.Damage.cs
namespace Opium;
public partial class PlayerController
{
/// <summary>
/// Reference to a camera effect that is activated when the player dies.
/// </summary>
[Property] public CameraEffect DeathCameraEffect { get; set; }
[Property] public CameraEffect HitByMeleeCameraEffect { get; set; }
// TODO: Move this to PlayerPostProcessing
[Property, Category( "Screen Effects" )] public RetroCameraVignette VignetteCameraEffect { get; set; }
/// <summary>
/// Can the player take damage?
/// </summary>
[ConVar( "op_god" )] public static bool IsGodMode { get; set; } = false;
[ConCmd( "op_dev_damage" )]
public static void DevDamage( float damage = 1f )
{
var pl = Opium.PlayerController.Local;
pl.GameObject.TakeDamage( Opium.DamageInfo.Bullet( damage, pl.GameObject, pl.GameObject ) );
}
[ConCmd( "op_dev_sethp" )]
public static void DevSetHP( float health = 100f )
{
var pl = Opium.PlayerController.Local;
pl.Health = health;
}
/// <summary>
/// Called when we die.
/// </summary>
/// <param name="damageInfo"></param>
public override void OnKilled( in Sandbox.DamageInfo damageInfo )
{
// Can't die twice.
if ( !IsAlive ) return;
Kill();
}
/// <summary>
/// Called when we take damage.
/// </summary>
/// <param name="damage"></param>
public override void OnDamage( in Sandbox.DamageInfo damage )
{
if ( IsGodMode ) damage.Damage = 0;
if ( ActiveWeapon is MeleeWeapon melee && (melee.BlockAttack?.IsActive ?? false) )
{
damage.Damage *= melee.BlockDamageFactor;
}
if ( HitByMeleeCameraEffect is not null && damage is Opium.DamageInfo dmg && dmg.HasTag( "melee" ) )
{
HitByMeleeCameraEffect.Player = this;
HitByMeleeCameraEffect.Enabled = true;
}
base.OnDamage( damage );
}
/// <summary>
/// Called when we die.
/// </summary>
public void Kill()
{
IsAlive = false;
LockMovement = true;
LockCameraMovement = true;
Inventory.Drop( Inventory.Current );
Inventory.Clear();
if ( DeathCameraEffect is not null )
{
DeathCameraEffect.Enabled = true;
DeathCameraEffect.Player = this;
}
}
float smoothHealth = 100f;
/// <summary>
/// A method that is called every Update to update damage FX on the screen.
/// TODO: Maybe make this driven in UI?
/// </summary>
void UpdateDamageScreenEffect()
{
smoothHealth = smoothHealth.LerpTo( Health, Time.Delta * 5f );
if ( IsAlive )
{
if ( VignetteCameraEffect is not null )
{
var timesinceDmg = TimeSinceLastDamage.Relative.Remap( 0, 1f, 0.4f, 0 );
VignetteCameraEffect.Intensity = smoothHealth.Remap( 100, 0, 0, .5f ) + timesinceDmg;
}
}
else
{
if ( VignetteCameraEffect is not null )
VignetteCameraEffect.Intensity = .75f;
}
}
}