A Perk class for a game, named Seismic Stomp, that triggers when the player lands. It computes damage and stun values per level, spawns visual/sound effects, finds nearby enemy objects via scene sphere trace, and applies a jump effect and damage/stun RPCs to each valid enemy.
using System;
using Sandbox;
[Perk( Rarity.Mythic, includedAtStart: false, locked: true, minUnlocksReq: 7, alwaysOfferDebug: false )]
public class PerkJumpLandDamage : Perk
{
private enum Mod { Damage, StunTime };
public override float ImportanceMultiplier => 1.15f;
static PerkJumpLandDamage()
{
Register<PerkJumpLandDamage>(
name: "Seismic Stomp",
imagePath: "textures/icons/vector/jump_land_damage.png",
description: level => $"Do {GetValue( level, Mod.Damage )} dmg and stun enemies for {GetValue( level, Mod.StunTime ).ToString("0.#")}s when you land",
upgradeDescription: level => $"Do {GetValue( level - 1, Mod.Damage )}→{GetValue( level, Mod.Damage )} dmg and stun enemies for {GetValue( level - 1, Mod.StunTime ).ToString( "0.#" )}→{GetValue( level, Mod.StunTime ).ToString( "0.#" )}s when you land"
);
}
public override void Start()
{
base.Start();
}
public override void Refresh()
{
base.Refresh();
}
private static float GetValue( int level, Mod mod, bool isPercent = false )
{
switch ( mod )
{
case Mod.Damage:
default:
return 4f + 3f * level;
case Mod.StunTime:
return 0.3f + 0.2f * level;
}
}
public override void OnLand()
{
base.OnLand();
float radius = PerkDashToJump.LAND_RADIUS * Player.Stats[PlayerStat.RadiusMultiplier];
if( !(Player.Stats[PlayerStat.JumpNotDash] > 0f) )
{
Manager.Instance.SpawnRingRpc( Player.Position2D, radius * 0.95f, new Color( 1f, 0.8f, 0.5f, 0.3f ), 0.2f );
Manager.Instance.PlaySfxNearbyRpc( "slam", Player.Position2D, pitch: Game.Random.Float( 0.95f, 1.05f ), volume: 1f, maxDist: 400f );
}
var jumpDamage = GetValue( Level, Mod.Damage );
var jumpStunTime = GetValue( Level, Mod.StunTime );
var distance = Utils.Map( Level, 1, 3, 80f, 150f );
var height = Utils.Map( Level, 1, 3, 110f, 160f );
var lifetime = Utils.Map( Level, 1, 3, 0.7f, 1.2f );
var traceResults = Player.Scene.Trace.Sphere( radius, Player.Position2D, Player.Position2D ).WithAnyTags( "enemy" ).HitTriggersOnly().RunAll().ToList();
foreach ( var tr in traceResults )
{
var gameObject = tr.GameObject;
var enemy = gameObject.GetComponent<Enemy>();
if ( !enemy.IsValid() || enemy.IsDying || enemy.IsInTheAir || enemy.IsSpawning )
continue;
Vector2 dir = (enemy.Position2D - Player.Position2D).Normal;
if ( jumpDamage > 0f )
{
//var distance = Utils.Map(jumpDamage, )
enemy.JumpRpc( enemy.Position2D + dir * distance * Game.Random.Float( 0.75f, 1.2f ), height: height * Game.Random.Float( 0.75f, 1.25f ), lifetime: lifetime * Game.Random.Float( 0.8f, 1.2f ) );
enemy.DamageOnJumpFinishRpc( jumpDamage, Player, jumpStunTime );
}
}
}
}