An in-game HealthPack item class. It spawns with properties, rotates visually, is attracted to nearby players below max HP, grants HP on collision, plays a sound, and removes itself.
using System;
using Sandbox;
public class HealthPack : Item
{
public float HpAmount { get; set; } = 20f;
private float _rotateTimeOffset;
private float _personalRotateSpeed;
public override Vector3 SpawnScale => new Vector3( 0.7f );
protected override float AttractRangeFactor => 0f;
protected override float AttractStrengthFactor => 0f;
protected override void OnStart()
{
base.OnStart();
Lifetime = 70f;
ShouldCheckBounds = true;
PushStrength = 500f;
BaseZPos = -8f;
WorldPosition = WorldPosition.WithZ( BaseZPos );
if ( IsProxy )
return;
Deceleration = 0.92f;
_rotateTimeOffset = Game.Random.Float( 0f, 10f );
_personalRotateSpeed = Game.Random.Float( 3f, 5f );
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( Manager.Instance.IsGameOver )
return;
if ( IsProxy )
return;
LocalRotation = Rotation.From( new Angles( 0f, -90f, Utils.FastSin( _rotateTimeOffset + Time.Now * _personalRotateSpeed ) * 7f ) );
foreach ( var player in Manager.Instance.AlivePlayers )
{
if( player.Health < player.GetSyncStat(PlayerStat.MaxHp) )
{
var dist_sqr = (Position2D - player.Position2D).LengthSquared;
var req_dist_sqr = MathF.Pow( player.GetSyncStat(PlayerStat.CoinAttractRange), 2f );
if ( dist_sqr < req_dist_sqr )
{
if ( (player.Position2D - Position2D).LengthSquared > Manager.TOUCH_DIST_REQUIRED_SQR )
Velocity += (player.Position2D - Position2D).Normal * Utils.Map( dist_sqr, req_dist_sqr, 0f, 0f, 1f, EasingType.Linear ) * player.GetSyncStat(PlayerStat.CoinAttractStrength) * Time.Delta;
}
}
}
//if ( !IsFlying )
// ZPos = BaseZPos + 3f + Utils.FastSin( Time.Now * _personalBounceSpeed ) * 4f;
}
public override void Colliding( Thing other, float percent, float dt )
{
base.Colliding( other, percent, dt );
if ( CantBeCollected )
return;
if ( other is Player player )
{
if ( !player.IsDead )
{
player.GainHealthPack( HpAmount );
player.CollectItemEffect();
// play quieter sfx if player is at full hp
if ( !(player.Health < player.GetSyncStat( PlayerStat.MaxHp )) )
Manager.Instance.PlaySfxNearbyRpc( "heal", Position2D, pitch: 0.7f, volume: 0.6f, maxDist: 250f );
Remove();
}
}
}
}