A Perk class 'CurseDropPerk' that causes the player to drop a random perk when they pick up a healthpack. It chooses a non-curse perk if available, otherwise a different curse, removes it from the player, picks a random far position within spawn bounds, and requests the manager to spawn a perk item via RPC. It also sets visual highlight and icon animation values.
using System;
using System.Linq;
using Sandbox;
[Perk( Rarity.Unique, curse: true, alwaysOfferDebug: false )]
public class CurseDropPerk : Perk
{
static CurseDropPerk()
{
Register<CurseDropPerk>(
name: "Fumble",
imagePath: "textures/icons/vector/curse_drop_perk.png",
description: level => $"Drop a perk to a random location\nwhen you get healthpack"
);
}
public override void Start()
{
base.Start();
HighlightColor = new Color( 0.7f, 0.2f, 0.5f );
HighlightDuration = 0.35f;
HighlightOpacity = 3f;
}
public override void Refresh()
{
base.Refresh();
}
public override void OnGainHealthpack( float amount )
{
base.OnGainHealthpack( amount );
var perkTypeToDrop = GetPerkTypeToDrop();
if ( perkTypeToDrop == null )
return;
var typeIdentity = PerkManager.TypeToIdentity( perkTypeToDrop );
Player.LevelDownPerk( perkTypeToDrop );
var dropPos = GetRandomFarPosition( 300f );
Manager.Instance.SpawnPerkItemAtRpc( typeIdentity, Player.Position2D, dropPos );
Highlight();
IconScale = Game.Random.Float( 1.2f, 1.3f );
IconAngleOffset = Game.Random.Float( 10f, 20f ) * (Game.Random.Int( 0, 1 ) == 0 ? -1f : 1f);
// todo: sfx
}
private TypeDescription GetPerkTypeToDrop()
{
var candidates = Player.Perks
.Where( kvp => !kvp.Value.IsCurse )
.Select( kvp => PerkManager.IdentityToType( kvp.Key ) )
.ToList();
if ( candidates.Count > 0 )
return candidates[Game.Random.Int( 0, candidates.Count - 1 )];
candidates = Player.Perks
.Where( kvp => kvp.Value.IsCurse && kvp.Value.GetType() != typeof( CurseDropPerk ) )
.Select( kvp => PerkManager.IdentityToType( kvp.Key ) )
.ToList();
if ( candidates.Count > 0 )
return candidates[Game.Random.Int( 0, candidates.Count - 1 )];
return null;
}
private Vector2 GetRandomFarPosition( float minDist )
{
var mgr = Manager.Instance;
var playerPos = Player.Position2D;
for ( int i = 0; i < 30; i++ )
{
var pos = new Vector2(
Game.Random.Float( mgr.BOUNDS_MIN_SPAWN.x, mgr.BOUNDS_MAX_SPAWN.x ),
Game.Random.Float( mgr.BOUNDS_MIN_SPAWN.y, mgr.BOUNDS_MAX_SPAWN.y )
);
if ( (pos - playerPos).Length >= minDist )
return pos;
}
return mgr.ClampPosToBounds( playerPos + Utils.GetRandomVector() * minDist );
}
}