MenuManager component for the main menu. It spawns and updates decorative menu enemies, controls menu player sprite animations, and selects sprites based on difficulty and saved stats.
public sealed class MenuManager : Component
{
public static MenuManager Instance { get; private set; }
[Property] public GameObject MenuZombiePrefab { get; set; }
[Property] public Sprite2D MenuPlayerSprite { get; set; }
[Property] public Sprite NormalSprite { get; set; }
[Property] public Sprite EasySprite { get; set; }
[Property] public Sprite Difficulty1Sprite { get; set; }
[Property] public Sprite Difficulty2Sprite { get; set; }
[Property] public Sprite Difficulty3Sprite { get; set; }
[Property] public Sprite Difficulty4Sprite { get; set; }
[Property] public Sprite Difficulty5Sprite { get; set; }
[Property] public Sprite Difficulty6Sprite { get; set; }
[Property] public Sprite Difficulty7Sprite { get; set; }
[Property] public Sprite Difficulty8Sprite { get; set; }
[Property] public Sprite Difficulty9Sprite { get; set; }
[Property] public Sprite Difficulty10Sprite { get; set; }
[Property] public Sprite Difficulty11Sprite { get; set; }
[Property] public Sprite Difficulty12Sprite { get; set; }
[Property] public Sprite Difficulty13Sprite { get; set; }
[Property] public Sprite Difficulty14Sprite { get; set; }
[Property] public Sprite Difficulty15Sprite { get; set; }
public TimeSince ElapsedTime { get; set; }
private TimeSince _timeSinceEnemySpawn;
private float _nextSpawnDelay;
public const float Y_MIN = -40f;
public const float Y_MAX = 15f;
public const float Z_NEAR = -10f;
public const float Z_FAR = -100f;
public int HighestDifficultyBeaten { get; set; }
private TimeSince _timeSinceChangeDifficulty;
private int _changeDifficultyRand;
private int _lastDifficulty;
protected override void OnAwake()
{
base.OnAwake();
Instance = this;
ElapsedTime = 0f;
_timeSinceEnemySpawn = 0f;
_nextSpawnDelay = 0.01f;
//Log.Info( $"victory_elapsed_time: {Sandbox.Services.Stats.LocalPlayer.Get( "victory_elapsed_time" ).Min}" );
//var leaderboard = Sandbox.Services.Leaderboards.GetFromStat( "end_time" );
//leaderboard.SetAggregationMax();
//leaderboard.SetSortDescending();
//leaderboard.Refresh();
//foreach (var entry in leaderboard.Entries)
//{
// Log.Info( $"{entry.DisplayName}: {entry.Value}" );
//}
HighestDifficultyBeaten = GetHighestDifficultyBeaten();
//HighestDifficultyBeaten = 14;
//Log.Info( $"HighestDifficultyBeaten: {HighestDifficultyBeaten}" );
MenuPlayerSprite.PlaybackSpeed = 0.66f;
var selectedDifficulty = Math.Clamp( (int)Sandbox.Services.Stats.LocalPlayer.Get( "selected_difficulty" ).LastValue, Manager.MinDifficulty, Manager.MaxDifficulty );
_lastDifficulty = selectedDifficulty;
SetDifficulty( selectedDifficulty );
}
protected override void OnStart()
{
for ( int i = 0; i < Game.Random.Int( 3, 15 ); i++ )
SpawnRandomStartingEnemy();
}
protected override void OnUpdate()
{
if ( _timeSinceEnemySpawn > _nextSpawnDelay )
{
SpawnRandomEnemy();
_timeSinceEnemySpawn = 0f;
_nextSpawnDelay = Game.Random.Float( 0.1f, 2f );
}
if ( _timeSinceChangeDifficulty < 0.25f )
{
if ( _changeDifficultyRand == 0 )
MenuPlayerSprite.PlayAnimation( "attack_idle" );
else if ( _changeDifficultyRand == 1 )
MenuPlayerSprite.PlayAnimation( "hurt_idle" );
else
MenuPlayerSprite.PlayAnimation( "hurt_attack_idle" );
}
else
{
MenuPlayerSprite.PlayAnimation( "idle" );
}
}
void SpawnRandomStartingEnemy()
{
bool flipped = Game.Random.Int( 0, 1 ) == 0;
float y = GetRandomYPos();
float x = Game.Random.Float( -80f, 80f );
SpawnEnemy( TypeLibrary.GetType( typeof( MenuZombie ) ), new Vector3( x, y, 0f ), flipped );
}
void SpawnRandomEnemy()
{
bool flipped = Game.Random.Int( 0, 1 ) == 0;
float y = GetRandomYPos();
float x = Game.Random.Float( 100f, 120f ) * Utils.Map( y, Y_MIN, Y_MAX, 1.5f, 1f ) * (flipped ? -1f : 1f);
SpawnEnemy( TypeLibrary.GetType( typeof( MenuZombie ) ), new Vector3( x, y, 0f ), flipped );
//var sfx = Sound.Play( "zombie.dirt", new Vector3( x, y, 100f ) );
//if ( sfx != null )
//{
// sfx.Volume = Utils.Map( y, MenuManager.Y_MIN, MenuManager.Y_MAX, 0.7f, 0.2f ) * Utils.Map( ElapsedTime, 0f, 1.25f, 0f, 1f );
// sfx.Pitch = Game.Random.Float( 0.6f, 0.8f );
//}
}
public float GetRandomYPos()
{
return Utils.Map( Game.Random.Float( 0f, 1f ), 0f, 1f, Y_MAX, Y_MIN, EasingType.QuartIn );
}
void SpawnEnemy( TypeDescription type, Vector3 pos, bool flipped )
{
GameObject enemyObj = null;
MenuEnemy enemy;
if ( type == TypeLibrary.GetType( typeof( MenuZombie ) ) ) { enemyObj = MenuZombiePrefab.Clone( pos ); }
enemy = enemyObj.Components.Get<MenuEnemy>();
enemy.WorldPosition = pos;
enemyObj.Name = type.ToString();
//Log.Info( enemy.Sprite );
enemy.Sprite.SpriteFlags = flipped ? SpriteFlags.HorizontalFlip : SpriteFlags.None;
enemy.IsFlipped = flipped;
enemy.SpeedModifier = Game.Random.Float( 4f, 5f ) * Utils.Map( pos.y, Y_MIN, Y_MAX, 1f, 0.1f );
}
int GetHighestDifficultyBeaten()
{
for ( int difficulty = Manager.MaxDifficulty; difficulty >= 0; difficulty-- )
{
//Log.Info( $"victory_elapsed_time: {Sandbox.Services.Stats.LocalPlayer.Get( "victory_elapsed_time" ).Min}" );
var victoryTime = Sandbox.Services.Stats.LocalPlayer.Get( Manager.GetStatName( difficulty ) ).Min;
if ( victoryTime > 0f )
{
return difficulty;
}
}
return -1;
}
public void SetDifficulty( int difficulty )
{
if ( difficulty < 0 ) MenuPlayerSprite.Sprite = EasySprite;
else if ( difficulty == 0 ) MenuPlayerSprite.Sprite = NormalSprite;
else if ( difficulty == 1 ) MenuPlayerSprite.Sprite = Difficulty1Sprite;
else if ( difficulty == 2 ) MenuPlayerSprite.Sprite = Difficulty2Sprite;
else if ( difficulty == 3 ) MenuPlayerSprite.Sprite = Difficulty3Sprite;
else if ( difficulty == 4 ) MenuPlayerSprite.Sprite = Difficulty4Sprite;
else if ( difficulty == 5 ) MenuPlayerSprite.Sprite = Difficulty5Sprite;
else if ( difficulty == 6 ) MenuPlayerSprite.Sprite = Difficulty6Sprite;
else if ( difficulty == 7 ) MenuPlayerSprite.Sprite = Difficulty7Sprite;
else if ( difficulty == 8 ) MenuPlayerSprite.Sprite = Difficulty8Sprite;
else if ( difficulty == 9 ) MenuPlayerSprite.Sprite = Difficulty9Sprite;
else if ( difficulty == 10 ) MenuPlayerSprite.Sprite = Difficulty10Sprite;
else if ( difficulty == 11 ) MenuPlayerSprite.Sprite = Difficulty11Sprite;
else if ( difficulty == 12 ) MenuPlayerSprite.Sprite = Difficulty12Sprite;
else if ( difficulty == 13 ) MenuPlayerSprite.Sprite = Difficulty13Sprite;
else if ( difficulty == 14 ) MenuPlayerSprite.Sprite = Difficulty14Sprite;
else if ( difficulty == 15 ) MenuPlayerSprite.Sprite = Difficulty15Sprite;
_timeSinceChangeDifficulty = 0f;
_changeDifficultyRand = Game.Random.Int( 0, 2 );
if ( _lastDifficulty != difficulty )
{
if ( difficulty >= 4 && _lastDifficulty < 4 )
{
foreach ( var zombie in Scene.GetAll<MenuZombie>() )
zombie.Sprite.Sprite = Game.Random.Float( 0f, 1f ) < 0.75f ? zombie.EvolvedSprite : zombie.EvolvedBloodySprite;
}
else if ( difficulty < 4 && _lastDifficulty >= 4 )
{
foreach ( var zombie in Scene.GetAll<MenuZombie>() )
zombie.Sprite.Sprite = zombie.NormalSprite;
}
_lastDifficulty = difficulty;
}
}
}