Static AchievementManager for the HUD. Checks various conditions (damage taken, win/loss streaks, chosen weapon, jackpot, player/AI HP) and unlocks corresponding s&box achievements via Sandbox.Services.Achievements, returning a list of text lines for display including an ASCII banner when any achievements unlocked.
using Keyboard_Warriors_.Models;
using Keyboard_Warriors_.Systems;
using System;
using System.Collections.Generic;
using System.Linq; // 🚀 Required to use .Any() to check the list!
namespace Keyboard_Warriors_.Managers
{
public static class AchievementManager
{
public static List<string> CheckAchievements( bool tookDamage, int winStreak, int lossStreak, Weapon chosenWeapon, Player player, Player ai, ref bool hitJackpot )
{
List<string> unlocked = new List<string>();
// Grab the active GameManager instance out of the scene
var manager = Sandbox.Game.ActiveScene.Get<GameManager>();
// 1. Steel Defense
if ( manager != null && !manager.HasPlayerTakenAnyDamage )
{
// Check if the achievement is NOT already unlocked in s&box's system
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "steel_defense" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "steel_defense" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'Steel Defense'" );
unlocked.Add( "\"This must be the Battle of Trenton. Zero damage taken!\"" );
}
}
// 2. Prisoner Streak
if ( winStreak == 5 )
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "prisoner_streak" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "prisoner_streak" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'Prisoner Streak'" );
unlocked.Add( "\"5 wins in a row? Prisoners could do better!\"" );
}
}
// 3. HAL's Worst Nightmare
if ( winStreak == 10 )
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "hals_nightmare" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "hals_nightmare" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'HAL's Worst Nightmare'" );
unlocked.Add( "\"10 straight wins? AI's are starting to recognize fear!\"" );
}
}
// 4. New Assassin
if ( chosenWeapon?.name == "Dagger" && winStreak == 5 )
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "new_assassin" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "new_assassin" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'New Assassin'" );
unlocked.Add( "\"5 wins with a dagger.. Okay Altair!\"" );
}
}
// 5. Final Breath
if ( player.hp <= 0 && ai.hp <= 0 )
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "final_breath" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "final_breath" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'Final Breath'" );
unlocked.Add( "\"At 0 hp, you let one last strike or events caused the AI down with you. A tie in glory!\"" );
}
}
// 6. Scratch of the Gods
if ( hitJackpot )
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "scratch_of_gods" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "scratch_of_gods" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'Scratch of the Gods'" );
unlocked.Add( "\"You hit the jackpot during battle, the points are yours!\"" );
}
hitJackpot = false;
}
if ( lossStreak == 5 ) // Ensure your method signature now includes 'int lossStreak'
{
if ( !Sandbox.Services.Achievements.All.Any( a => a.Name == "turn_off_on" && a.IsUnlocked ) )
{
Sandbox.Services.Achievements.Unlock( "turn_off_on" );
unlocked.Add( "\n🏆 ACHIEVEMENT UNLOCKED: 'Try Turning It Off and On Again'" );
unlocked.Add( "\"AI: 5 losses in a row... Is all well up there?\"" );
}
}
if ( unlocked.Count > 0 )
{
string bannerLines = @"
_ _____ _ _ _____ _____ _ _ _____ ______ _____ _ _ _____ _ _ _ _ _ ___ _____ _____ _ __ _____ _____ _
/ _ \/ __ \| | | |_ _| ___| | | | ___| \/ || ___| \ | |_ _| | | | | \ | || | | _ / __ \| | / /| ___| _ \ |
/ /_\ \ / \/| |_| | | | | |__ | | | | |__ | . . || |__ | \| | | | | | | | \| || | | | | | / \/| |/ / | |__ | | | | |
| _ | | | _ | | | | __|| | | | __|| |\/| || __|| . ` | | | | | | | . ` || | | | | | | | \ | __|| | | | |
| | | | \__/\| | | |_| |_| |___\ \_/ / |___| | | || |___| |\ | | | | |_| | |\ || |___\ \_/ / \__/\| |\ \| |___| |/ /|_|
\_| |_/\____/\_| |_/\___/\____/ \___/\____/\_| |_/\____/\_| \_/ \_/ \___/\_| \_/\_____/\___/ \____/\_| \_/\____/|___/ (_)
";
// Add each line of the banner to the beginning or end of the return list
foreach ( var line in bannerLines.Split( '\n' ) )
{
unlocked.Add( line );
}
}
return unlocked;
}
}
}