ui/GameOverResultPanel.razor

A Razor UI component for the game's end-of-run results panel. It collects player ResultStats, decides which stat rows to show, builds a list of ResultStatData entries (titles, icons, colors) and renders a scrollable table of per-player values and avatars, with mouse-wheel scrolling and selectable player avatars.

NetworkingFile Access
@namespace Sandbox
@using Sandbox;
@using Sandbox.UI;
@using System;
@inherits Panel
@attribute [StyleSheet("GameOverResultPanel.razor.scss")]

<root>
@{
		// var player = Manager.Instance.LocalPlayer;
		// if(!player.IsValid())
		// 	return;

		var players = Scene.GetAll<Player>().ToList();
		var isVictory = Manager.Instance.IsBossDead;

		var showKills = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NumKills));
		var showMinibossKills = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NumMinibossKills));

		var showTotalDmgDealt = players.Any(p => (p.ResultStats.ContainsKey(ResultStat.DmgDealtTotal) && p.ResultStats.ContainsKey(ResultStat.DmgDealtBullet) && p.ResultStats[ResultStat.DmgDealtTotal] > p.ResultStats[ResultStat.DmgDealtBullet]) || !p.ResultStats.ContainsKey(ResultStat.DmgDealtBullet));
		var dealtBulletSplash = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtBulletSplash));
		var dealtFire = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtFire));
		var dealtPoison = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtPoison));
		var dealtExplosion = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtExplosion));
		var dealtThorns = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtThorns));
		var dealtDashSlash = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtDashSlash));
		var dealtOrbitingBlade = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtOrbitingBlade));
		var dealtBoomerang = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtBoomerang));
		var dealtSpear = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtSpear));
		var dealtPunch = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtPunch));
		var dealtRadiation = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtRadiation));
		var dealtAcid = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtAcid));
		var dealtShock = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtShock));
		var dealtXpShrapnel = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtXpShrapnel));
		var dealtMark = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtMark));
		var dealtOther = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtOther));
		var dealtToBoss = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgDealtToBoss));

		var healed = players.Any(p => p.ResultStats.ContainsKey(ResultStat.HpHealed));
		var healedOther = players.Any(p => p.ResultStats.ContainsKey(ResultStat.HpHealedOther));
		var gainedArmor = players.Any(p => p.ResultStats.ContainsKey(ResultStat.ArmorGained));

		var didPerkNew = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NewPerk));
		var didPerkLevel = players.Any(p => p.ResultStats.ContainsKey(ResultStat.PerkLeveledUp));
		var didCurse = players.Any(p => p.ResultStats.ContainsKey(ResultStat.CursesGot));

		var didReroll = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NumTimesReroll));
		var didBanish = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NumTimesBanish));
		var didHealthPack = players.Any(p => p.ResultStats.ContainsKey(ResultStat.HealthpacksGot));
		var didMagnet = players.Any(p => p.ResultStats.ContainsKey(ResultStat.MagnetsGot));
		var didBarrel = players.Any(p => p.ResultStats.ContainsKey(ResultStat.BarrelsDestroyed));
		var didChest = players.Any(p => p.ResultStats.ContainsKey(ResultStat.ChestsOpened));
		var didEvilChest = players.Any(p => p.ResultStats.ContainsKey(ResultStat.EvilChestsOpened));

		var didDash = players.Any(p => p.ResultStats.ContainsKey(ResultStat.TimesDashed));
		var didDodge = players.Any(p => p.ResultStats.ContainsKey(ResultStat.TimesDodged));
		var didExplosion = players.Any(p => p.ResultStats.ContainsKey(ResultStat.ExplosionsCaused));
		var didLostShield = players.Any(p => p.ResultStats.ContainsKey(ResultStat.ShieldsLost));
		var didChained = players.Any(p => p.ResultStats.ContainsKey(ResultStat.TimesChained));
		var didCrit = players.Any(p => p.ResultStats.ContainsKey(ResultStat.Crit));
		var didExecute = players.Any(p => p.ResultStats.ContainsKey(ResultStat.NumEnemiesExecuted));
		var didFreeze = players.Any(p => p.ResultStats.ContainsKey(ResultStat.EnemiesFrozen));

		var showTotalDmgTaken = players.Any(p => (p.ResultStats.ContainsKey(ResultStat.DmgTakenTotal) && p.ResultStats.ContainsKey(ResultStat.DmgTakenMelee) && p.ResultStats[ResultStat.DmgTakenTotal] > p.ResultStats[ResultStat.DmgTakenMelee]) || !p.ResultStats.ContainsKey(ResultStat.DmgTakenMelee));
		var tookSelf = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenSelf));
		var tookBullet = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenBullet));
		var tookProjectile = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenProjectile));
		var tookFlyingSkull = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenProjectileHoming));
		var tookFire = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFire));
		var tookPoison = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenPoison));
		var tookExplosion = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenExplosion));
		var tookSpikerHead = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenSpikerHead));
		var tookAcid = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenAcid));
		var tookShock = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenShock));
		var tookShockwave = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenShock));
		var tookLava = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenLavaPuddle));
		var tookOther = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenOther));
		var tookZombie = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromZombie));
		var tookZombieElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromZombieElite));
		var tookExploder = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromExploder));
		var tookExploderElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromExploderElite));
		var tookExploderMini = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromExploderMini));
		var tookSpitter = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromSpitter));
		var tookSpitterElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromSpitterElite));
		var tookSpiker = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromSpiker));
		var tookSpikerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromSpikerElite));
		var tookCharger = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromCharger));
		var tookChargerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromChargerElite));
		var tookRunner = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromRunner));
		var tookRunnerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromRunnerElite));
		var tookBarrelExploding = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromBarrelExploding));
		var tookChestEvil = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromChestEvil));
		var tookFence = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromFence));
		var tookMiniboss = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromMiniboss));
		var tookBoss = players.Any(p => p.ResultStats.ContainsKey(ResultStat.DmgTakenFromBoss));

		var diedZombie = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByZombie));
		var diedZombieElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByZombieElite));
		var diedExploder = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByExploder));
		var diedExploderElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByExploderElite));
		var diedExploderMini = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByExploderMini));
		var diedSpitter = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledBySpitter));
		var diedSpitterElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledBySpitterElite));
		var diedSpiker = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledBySpiker));
		var diedSpikerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledBySpikerElite));
		var diedCharger = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByCharger));
		var diedChargerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByChargerElite));
		var diedRunner = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByRunner));
		var diedRunnerElite = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByRunnerElite));
		var diedBarrelExploding = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByBarrelExploding));
		var diedChestEvil = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByChestEvil));
		var diedFence = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByFence));
		var diedMiniboss = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByMiniboss));
		var diedBoss = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledByBoss));
		var diedSelf = players.Any(p => p.ResultStats.ContainsKey(ResultStat.KilledBySelf));

		ResultStatsToShow.Clear();

		// Testing: Override all bools to true
		// showKills = true;
		// showMinibossKills = true;
		// showTotalDmgDealt = true;
		// dealtBulletSplash = true;
		// dealtFire = true;
		// dealtPoison = true;
		// dealtExplosion = true;
		// dealtThorns = true;
		// dealtDashSlash = true;
		// dealtOrbitingBlade = true;
		// dealtBoomerang = true;
		// dealtSpear = true;
		// dealtPunch = true;
		// dealtRadiation = true;
		// dealtAcid = true;
		// dealtShock = true;
		// dealtXpShrapnel = true;
		// dealtOther = true;
		// dealtToBoss = true;
		// showTotalDmgTaken = true;
		// tookSelf = true;
		// tookBullet = true;
		// tookProjectile = true;
		// tookFlyingSkull = true;
		// tookFire = true;
		// tookPoison = true;
		// tookExplosion = true;
		// tookSpikerHead = true;
		// tookAcid = true;
		// tookShock = true;
		// tookShockwave = true;
		// tookLava = true;
		// tookOther = true;
		// tookBoss = true;
		// healed = true;
		// healedOther = true;
		// gainedArmor = true;
		// didPerkNew = true;
		// didPerkLevel = true;
		// didCurse = true;
		// didReroll = true;
		// didBanish = true;
		// didHealthPack = true;
		// didMagnet = true;
		// didBarrel = true;
		// didChest = true;
		// didEvilChest = true;
		// didDash = true;
		// didDodge = true;
		// didExplosion = true;
		// didLostShield = true;
		// didChained = true;
		// didCrit = true;
		// didExecute = true;
		// didFreeze = true;

		// tookZombie = true;
		// tookZombieElite = true;
		// tookExploder = true;
		// tookExploderElite = true;
		// tookExploderMini = true;
		// tookSpitter = true;
		// tookSpitterElite = true;
		// tookSpiker = true;
		// tookSpikerElite = true;
		// tookCharger = true;
		// tookChargerElite = true;
		// tookRunner = true;
		// tookRunnerElite = true;
		// tookBarrelExploding = true;
		// tookChestEvil = true;
		// tookFence = true;
		// tookMiniboss = true;
		// tookBoss = true;

		// ResultStatsToShow.Add(new ResultStatData("Kills", new Color(0.25f, 0.2f, 0.3f)));
		if(showKills) ResultStatsToShow.Add(new ResultStatData("Enemy Kills", ResultStat.NumKills, new Color(0.8f), "kill"));
		if(showMinibossKills) ResultStatsToShow.Add(new ResultStatData("Miniboss Kills", ResultStat.NumMinibossKills, new Color(0.9f, 0.5f, 0.5f), "kill_miniboss"));
		if(players.Count > 1) ResultStatsToShow.Add(new ResultStatData("Deaths", ResultStat.NumDeaths, new Color(0.5f, 0.4f, 0.4f), "death"));

		if(!isVictory)
		{
			ResultStatsToShow.Add(new ResultStatData("Killed By", new Color(0.3f, 0.2f, 0.2f)));

			if(players.Count > 1)
			{
				if(diedZombie) ShowEnemyDamageResultStat(ResultStat.KilledByZombie);
				if(diedZombieElite) ShowEnemyDamageResultStat(ResultStat.KilledByZombieElite);
				if(diedExploder) ShowEnemyDamageResultStat(ResultStat.KilledByExploder);
				if(diedExploderElite) ShowEnemyDamageResultStat(ResultStat.KilledByExploderElite);
				if(diedExploderMini) ShowEnemyDamageResultStat(ResultStat.KilledByExploderMini);
				if(diedSpitter) ShowEnemyDamageResultStat(ResultStat.KilledBySpitter);
				if(diedSpitterElite) ShowEnemyDamageResultStat(ResultStat.KilledBySpitterElite);
				if(diedSpiker) ShowEnemyDamageResultStat(ResultStat.KilledBySpiker);
				if(diedSpikerElite) ShowEnemyDamageResultStat(ResultStat.KilledBySpikerElite);
				if(diedCharger) ShowEnemyDamageResultStat(ResultStat.KilledByCharger);
				if(diedChargerElite) ShowEnemyDamageResultStat(ResultStat.KilledByChargerElite);
				if(diedRunner) ShowEnemyDamageResultStat(ResultStat.KilledByRunner);
				if(diedRunnerElite) ShowEnemyDamageResultStat(ResultStat.KilledByRunnerElite);
				if(diedMiniboss) ShowEnemyDamageResultStat(ResultStat.KilledByMiniboss);
				if(diedBoss) ShowEnemyDamageResultStat(ResultStat.KilledByBoss);
				if(diedSelf) ShowEnemyDamageResultStat(ResultStat.KilledBySelf);
				if(diedBarrelExploding) ShowEnemyDamageResultStat(ResultStat.KilledByBarrelExploding);
				if(diedChestEvil) ShowEnemyDamageResultStat(ResultStat.KilledByChestEvil);
				if(diedFence) ShowEnemyDamageResultStat(ResultStat.KilledByFence);
			}
			else 
			{
				var player = players[0];
				var resultStatKillerType = player.LastKilledBy;

				ResultStatsToShow.Add(new ResultStatData(Player.GetNameForEnemyResultStat(resultStatKillerType), ResultStat.None, Player.GetResultStatColorForEnemy(resultStatKillerType), Player.GetResultStatIconForEnemy(resultStatKillerType)));
			}

			// ResultStatsToShow.Add(new ResultStatData(ResultStat.KilledBy));

			// var resultStatKillerType = Player.GetEnemyDamageResultStat(EnemyType.Zombie);
			// ResultStatsToShow.Add(new ResultStatData(Player.GetNameForEnemyResultStat(resultStatKillerType), ResultStat.None, Player.GetResultStatColorForEnemy(resultStatKillerType), Player.GetResultStatIconForEnemy(resultStatKillerType)));
		}

		ResultStatsToShow.Add(new ResultStatData("Damage Dealt", new Color(0.1f, 0.1f, 0.3f)));
		if(showTotalDmgDealt) ResultStatsToShow.Add(new ResultStatData("Total", ResultStat.DmgDealtTotal, _colorTotal, "total"));
		ResultStatsToShow.Add(new ResultStatData("Bullet", ResultStat.DmgDealtBullet, _colorDefault, "bullet"));
		if(dealtBulletSplash) ResultStatsToShow.Add(new ResultStatData("Bullet Splash", ResultStat.DmgDealtBulletSplash, new Color(0.5f, 0.5f, 1f), "splash"));
		if(dealtFire) ResultStatsToShow.Add(new ResultStatData("Fire", ResultStat.DmgDealtFire, new Color(1f, 0.25f, 0f), "fire"));
		if(dealtPoison) ResultStatsToShow.Add(new ResultStatData("Poison", ResultStat.DmgDealtPoison, new Color(0f, 1f, 0f), "droplet"));
		if(dealtExplosion) ResultStatsToShow.Add(new ResultStatData("Explosion", ResultStat.DmgDealtExplosion, new Color(0.75f, 0f, 0f), "explosion"));
		if(dealtThorns) ResultStatsToShow.Add(new ResultStatData("Thorns", ResultStat.DmgDealtThorns, new Color(0f, 0.7f, 0f), "thorns2"));
		if(dealtDashSlash) ResultStatsToShow.Add(new ResultStatData("Dash Slash", ResultStat.DmgDealtDashSlash, new Color(0.75f, 0.75f, 1f), "dash_slash"));
		if(dealtOrbitingBlade) ResultStatsToShow.Add(new ResultStatData("Buzzsaw", ResultStat.DmgDealtOrbitingBlade, new Color(0.8f), "buzzsaw"));
		if(dealtBoomerang) ResultStatsToShow.Add(new ResultStatData("Boomerang", ResultStat.DmgDealtBoomerang, new Color(0.9f), "boomerang"));
		if(dealtSpear) ResultStatsToShow.Add(new ResultStatData("Spear", ResultStat.DmgDealtSpear, new Color(0.7f, 0.2f, 0.2f), "spear"));
		if(dealtPunch) ResultStatsToShow.Add(new ResultStatData("Punch", ResultStat.DmgDealtPunch, new Color(1f, 0.5f, 0.6f), "punch"));
		if(dealtRadiation) ResultStatsToShow.Add(new ResultStatData("Radiation", ResultStat.DmgDealtRadiation, new Color(0.65f, 1f, 0.3f), "radiation"));
		if(dealtAcid) ResultStatsToShow.Add(new ResultStatData("Acid", ResultStat.DmgDealtAcid, new Color(1f, 1f, 0.4f), "acid"));
		if(dealtShock) ResultStatsToShow.Add(new ResultStatData("Shock", ResultStat.DmgDealtShock, new Color(1f, 1f, 0f), "shock"));
		if(dealtXpShrapnel) ResultStatsToShow.Add(new ResultStatData("XP Shrapnel", ResultStat.DmgDealtXpShrapnel, new Color(0.4f, 0.4f, 1f), "xp_dmg"));
		if(dealtMark) ResultStatsToShow.Add(new ResultStatData("Mark", ResultStat.DmgDealtMark, new Color(0.75f, 0.4f, 1f), "mark"));
		if(dealtOther) ResultStatsToShow.Add(new ResultStatData("Other", ResultStat.DmgDealtOther, new Color(0.6f), "other"));
		if(dealtToBoss) ResultStatsToShow.Add(new ResultStatData("To Boss", ResultStat.DmgDealtToBoss, new Color(0f, 0.75f, 1f), "boss"));
		ResultStatsToShow.Add(new ResultStatData("Highest Damage Attack", ResultStat.LargestDmgDealt, new Color(0.6f, 0.6f, 0.7f), "largest_dmg"));

		if(healed || healedOther || gainedArmor) ResultStatsToShow.Add(new ResultStatData("Health", new Color(0.1f, 0.3f, 0.1f)));
		if(healed) ResultStatsToShow.Add(new ResultStatData("HP Healed", ResultStat.HpHealed, new Color(0.5f, 1f, 0.5f), "heal"));
		if(players.Count > 1 && healedOther) ResultStatsToShow.Add(new ResultStatData("Healed Ally", ResultStat.HpHealedOther, new Color(0.2f, 1f, 0.2f), "heal_other"));
		if(gainedArmor) ResultStatsToShow.Add(new ResultStatData("Armor Gained", ResultStat.ArmorGained, new Color(0.85f), "armor"));

		if(didReroll || didReroll || didBanish || didHealthPack || didMagnet || didBarrel || didChest || didEvilChest) ResultStatsToShow.Add(new ResultStatData("Items", new Color(0.3f, 0.3f, 0.3f)));
		if(didReroll) ResultStatsToShow.Add(new ResultStatData("Rerolls Used", ResultStat.NumTimesReroll, new Color(1f), "reroll"));
		if(didBanish) ResultStatsToShow.Add(new ResultStatData("Banishes Used", ResultStat.NumTimesBanish, new Color(0.8f, 0.4f, 0.7f), "banish"));
		if(didHealthPack) ResultStatsToShow.Add(new ResultStatData("Health Packs Collected", ResultStat.HealthpacksGot, new Color(0.5f, 1f, 0.5f), "health_pack"));
		if(didMagnet) ResultStatsToShow.Add(new ResultStatData("Magnets Collected", ResultStat.MagnetsGot, new Color(1f, 0.5f, 0.5f), "magnet"));
		if(didBarrel) ResultStatsToShow.Add(new ResultStatData("Barrels Destroyed", ResultStat.BarrelsDestroyed, new Color(0.494f, 0.467f, 0.188f), "barrel"));
		if(didChest) ResultStatsToShow.Add(new ResultStatData("Chests Opened", ResultStat.ChestsOpened, new Color(0.75f, 0.7f, 0.5f), "chest"));
		if(didEvilChest) ResultStatsToShow.Add(new ResultStatData("Evil Chests Opened", ResultStat.EvilChestsOpened, new Color(0.7f, 0f, 0f), "chest_evil"));

		ResultStatsToShow.Add(new ResultStatData("Actions", new Color(0.3f, 0.3f, 0.1f)));
		if(didDash) ResultStatsToShow.Add(new ResultStatData("Dashed", ResultStat.TimesDashed, new Color(0.6f, 0.8f, 0.7f), "dash"));
		if(didDodge) ResultStatsToShow.Add(new ResultStatData("Dodged", ResultStat.TimesDodged, new Color(1f), "dodge"));
		ResultStatsToShow.Add(new ResultStatData("Bullets Created", ResultStat.BulletCreated, _colorDefault, "bullet"));
		ResultStatsToShow.Add(new ResultStatData("Reloaded", ResultStat.NumTimesReloaded, new Color(1f, 0.5f, 0.5f), "reload"));
		if(didExplosion) ResultStatsToShow.Add(new ResultStatData("Explosions Caused", ResultStat.ExplosionsCaused, new Color(0.75f, 0f, 0f), "explosion"));
		if(didLostShield) ResultStatsToShow.Add(new ResultStatData("Shields Lost", ResultStat.ShieldsLost, new Color(1f, 1f, 0f), "shield"));
		if(didChained) ResultStatsToShow.Add(new ResultStatData("Chained By Enemies", ResultStat.TimesChained, new Color(0.9f, 0.9f, 1f), "chain"));
		if(didCrit) ResultStatsToShow.Add(new ResultStatData("Crits", ResultStat.Crit, new Color(0.9f, 0.9f, 0.3f), "crit"));
		if(didExecute) ResultStatsToShow.Add(new ResultStatData("Enemies Executed", ResultStat.NumEnemiesExecuted, new Color(1f, 0.8f, 0f), "execute"));
		if(didFreeze) ResultStatsToShow.Add(new ResultStatData("Enemies Frozen", ResultStat.EnemiesFrozen, new Color(0.7f, 0.7f, 1f), "freeze"));
		ResultStatsToShow.Add(new ResultStatData("Meters Moved", ResultStat.MetersMoved, new Color(0.5f, 0.5f, 0.7f), "move"));

		if(didPerkNew || didPerkNew || didCurse) ResultStatsToShow.Add(new ResultStatData("Perks", new Color(0.2f, 0.2f, 0.3f)));
		if(didPerkNew) ResultStatsToShow.Add(new ResultStatData("New Perk", ResultStat.NewPerk, new Color(0.9f, 1f, 0.75f), "perk_new"));
		if(didPerkLevel) ResultStatsToShow.Add(new ResultStatData("Perk Level-up", ResultStat.PerkLeveledUp, new Color(0.8f, 1f, 1f), "perk_lvl"));
		if(didCurse) ResultStatsToShow.Add(new ResultStatData("Curse", ResultStat.CursesGot, new Color(0.6f, 0.2f, 1f), "curse"));

		ResultStatsToShow.Add(new ResultStatData("Damage Taken", new Color(0.3f, 0.1f, 0.1f)));
		if(showTotalDmgTaken) ResultStatsToShow.Add(new ResultStatData("Total", ResultStat.DmgTakenTotal, _colorTotal, "total"));
		if(tookSelf) ResultStatsToShow.Add(new ResultStatData("Self", ResultStat.DmgTakenSelf, new Color(1f, 0f, 1f), "self-dmg"));
		if(tookBullet) ResultStatsToShow.Add(new ResultStatData("Bullet", ResultStat.DmgTakenBullet, _colorDefault, "bullet"));
		ResultStatsToShow.Add(new ResultStatData("Melee", ResultStat.DmgTakenMelee, new Color(1f, 0f, 0f), "melee"));
		if(tookProjectile) ResultStatsToShow.Add(new ResultStatData("Projectile", ResultStat.DmgTakenProjectile, _colorDefault, "projectile"));
		if(tookFlyingSkull) ResultStatsToShow.Add(new ResultStatData("Flying Skull", ResultStat.DmgTakenProjectileHoming, new Color(0.6f, 0f, 0.5f), "flying_skull"));
		if(tookSpikerHead) ResultStatsToShow.Add(new ResultStatData("Spiker Head", ResultStat.DmgTakenSpikerHead, new Color(1f, 0f, 0.6f), "spiker_head"));
		if(tookFire) ResultStatsToShow.Add(new ResultStatData("Fire", ResultStat.DmgTakenFire, new Color(1f, 0.25f, 0f), "fire"));
		if(tookPoison) ResultStatsToShow.Add(new ResultStatData("Poison", ResultStat.DmgTakenPoison, new Color(0f, 1f, 0f), "droplet"));
		if(tookExplosion) ResultStatsToShow.Add(new ResultStatData("Explosion", ResultStat.DmgTakenExplosion, new Color(0.75f, 0f, 0f), "explosion"));
		if(tookAcid) ResultStatsToShow.Add(new ResultStatData("Acid", ResultStat.DmgTakenAcid, new Color(1f, 1f, 0.4f), "acid"));
		if(tookLava) ResultStatsToShow.Add(new ResultStatData("Lava", ResultStat.DmgTakenLavaPuddle, new Color(1f, 0.2f, 0f), "acid"));
		if(tookShock) ResultStatsToShow.Add(new ResultStatData("Shock", ResultStat.DmgTakenShock, new Color(1f, 1f, 0f), "shock"));
		if(tookShockwave) ResultStatsToShow.Add(new ResultStatData("Shockwave", ResultStat.DmgTakenShockwave, new Color(1f, 0.5f, 0f), "shockwave"));
		if(tookOther) ResultStatsToShow.Add(new ResultStatData("Other", ResultStat.DmgTakenOther, new Color(0.6f), "other"));

		if(tookZombie || tookZombieElite || tookExploder || tookExploder || tookExploderElite || tookExploderMini || tookSpitter || tookSpitterElite || tookSpiker || tookSpikerElite || tookCharger || tookChargerElite || tookRunner || tookRunnerElite || tookMiniboss || tookBoss || tookBarrelExploding || tookChestEvil || tookFence)
			ResultStatsToShow.Add(new ResultStatData("Damage Taken (By Enemy Type)", new Color(0.3f, 0.1f, 0.1f)));
		if(tookZombie) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromZombie);
		if(tookZombieElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromZombieElite);
		if(tookExploder) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromExploder);
		if(tookExploderElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromExploderElite);
		if(tookExploderMini) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromExploderMini);
		if(tookSpitter) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromSpitter);
		if(tookSpitterElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromSpitterElite);
		if(tookSpiker) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromSpiker);
		if(tookSpikerElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromSpikerElite);
		if(tookCharger) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromCharger);
		if(tookChargerElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromChargerElite);
		if(tookRunner) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromRunner);
		if(tookRunnerElite) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromRunnerElite);
		if(tookMiniboss) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromMiniboss);
		if(tookBoss) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromBoss);
		if(tookBarrelExploding) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromBarrelExploding);
		if(tookChestEvil) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromChestEvil);
		if(tookFence) ShowEnemyDamageResultStat(ResultStat.DmgTakenFromFence);
	}

	<div class="flat list" style="height: 80px; margin-bottom: 8px;">
		<div class="title_container">
			<div class="title"></div>
		</div>

		<div class="avatars">
			@foreach(var player in players)
			{
				var brightness = player == Manager.Instance.SelectedPlayer ? 2f : (Manager.Instance.SelectedPlayer == null ? 1f : 0.3f);
				<div class="avatar" style="background-image: url( avatar:@player.Network.Owner.SteamId ); filter: brightness(@brightness);" [email protected] onclick=@(() => ClickPlayerIcon(player))>
					<div class="playerlevel">@player.Level</div>
				</div> 
			}
		</div>
	</div>


	@for(int i = StartIndex; i < StartIndex + MAX_ROWS; i++)
	{
		if(i < 0 || i >= ResultStatsToShow.Count)
			continue;

		var data = ResultStatsToShow[i];

		@if(data.resultStat == ResultStat.Divider)
		{
			<div class="flat list" style="background-color: @((i % 2 == 0 ? data.color.WithAlpha(0.3f) : data.color.WithAlpha(0.6f)).Rgba);">
				<label class="bold stat_name" style="font-size:14px; color: @(Color.Lerp(data.color, Color.White, (i % 2 == 0 ? 0.3f : 0.2f)).Rgba);">@(data.title)</label>
			</div>
		}
		// else if( data.resultStat == ResultStat.KilledBy )
		// {
			
		// }
		else
		{
			<div class="flat list" style="background-color: @((i % 2 == 0 ? new Color(0, 0, 0, 0.4f) : new Color(0, 0, 0, 0.7f)).Rgba);">
				<div>
					<div class="icon_container">
						<label class="icon" style="background-color:@(data.color.Rgba); mask-image:@($"url(/textures/ui/stats/{data.icon}.png)")"></label>
					</div>

					<label class="bold stat_name" style="font-size:@(data.title.Length > 15 ? Math.Round(Utils.Map(data.title.Length, 15, 36, 14f, 10f, EasingType.SineIn)) : 14)px; color:@(Color.Lerp(data.color, Color.White, (i % 2 == 0 ? 0.5f : 0.4f)).Rgba);">@(data.title)</label>
				</div>

				<div class="values">
					@foreach(var player in players)
					{
						if(data.resultStat == ResultStat.None)
						{
							// <label class="bold stat_value" style="color:@(data.color.Rgba); font-size:16px;"></label>
							continue;
						}

						// if(data.resultStat == ResultStat.KilledBy && players.Count == 1 && player.EnemyTypeLastKilledBy != EnemyType.None)
						// {
						// 	var resultStatKillerType = Player.GetEnemyDamageResultStat(player.EnemyTypeLastKilledBy);
						// 	ResultStatsToShow.Add(new ResultStatData(Player.GetNameForEnemyResultStat(resultStatKillerType), ResultStat.None, Player.GetResultStatColorForEnemy(resultStatKillerType), Player.GetResultStatIconForEnemy(resultStatKillerType)));

						// 	continue;
						// }

						var amount = player.GetResultsStatAmount(data.resultStat);
						amount = MathX.FloorToInt(amount);

						var amountStr = amount.ToString("N0");

						var fontSize = 16f;
						if(amount >= 1000000000f)
							fontSize = 10f;
						else if(amount >= 100000000f)
							fontSize = 11f;
						else if(amount >= 10000000f)
							fontSize = 12f;
						else if(amount >= 1000000f)
							fontSize = 14f;

						// var textOpacity = amountStr == "0" ? 0.3f : 1f;
						// var color = data.color.WithAlpha(textOpacity).Rgba;
						var color = amountStr == "0" 
							? Color.Lerp(data.color, new Color(0.5f), 0.75f).WithAlpha(0.5f).Rgba
							: data.color.Rgba;

						<label class="bold stat_value" style="color:@(color); font-size:@(fontSize)px;">@(amountStr)</label>
					}
				</div>
			</div>
		}
	}

	@if(ResultStatsToShow.Count > MAX_ROWS)
	{
		var visibleRowHeight = MAX_ROWS * 31f;
		var heightPercent = (MAX_ROWS / (float)ResultStatsToShow.Count);
		var topOffset = 90f + StartIndex * 30f * heightPercent;
		var scrollbarHeight = visibleRowHeight * heightPercent;

		<div class="scrollbar" style="top:@(topOffset)px; height:@(scrollbarHeight)px;"></div>
	}
	else
	{
		StartIndex = 0;
	}
</root>

@code
{
	public struct ResultStatData
	{
		public string title;
		public ResultStat resultStat;
		public Color color;
		public string icon;

		public ResultStatData(string _title, ResultStat _resultStat, Color _color, string _icon)
		{
			title = _title;
			resultStat = _resultStat;
			color = _color;
			icon = _icon;
		}

		public ResultStatData(string _title, Color _color)
		{
			title = _title;
			resultStat = ResultStat.Divider;
			color = _color;
		}

		public ResultStatData(ResultStat _resultStat)
		{
			resultStat = _resultStat;
		}
	}

	public List<ResultStatData> ResultStatsToShow { get; set; } = new();
	public static int StartIndex { get; set; }
	// private const int MAX_ROWS = 23;
	private const int MAX_ROWS = 24;

	Color _colorDefault;
	Color _colorGood;
	Color _colorBad;
	Color _iconColorDefault;
	Color _colorTotal;

	public GameOverResultPanel()
	{
		_colorDefault = new Color(0.9f, 1f, 0.95f, 0.8f);
		_colorGood = new Color(0f, 1f, 0f, 0.8f);
		_colorBad = new Color(1f, 0f, 0f, 0.8f);
		_iconColorDefault = new Color(0.91f, 1f, 0.96f, 0.5f);
		_colorTotal = new Color(0.55f, 0.55f, 0.55f, 0.9f);
	}

	protected override int BuildHash()
	{
		return System.HashCode.Combine(
			StartIndex,
			RealTime.Now // todo:
		);
	}

	public void ClickPlayerIcon( Player player )
	{
		if(Manager.Instance.SelectedPlayer == player)
			Manager.Instance.SelectedPlayer = null;
		else
			Manager.Instance.SelectedPlayer = player;
	}

	public override void OnMouseWheel([Description("The scroll wheel delta. Positive values are scrolling down, negative - up.")] Vector2 value)
	{
		base.OnMouseWheel(value.y);

		//Log.Info($"OnMouseWheel {value} -> {StartIndex} .... {StatDatasToShow.Count} .... {StatDatasToShow.Count - MAX_ROWS}");

		if(ResultStatsToShow.Count > MAX_ROWS)
			StartIndex = Math.Clamp(StartIndex + (int)value.y, 0, ResultStatsToShow.Count - MAX_ROWS);

		// Manager.Instance.LocalPlayer.AddResultsStat(ResultStat.DmgTakenMelee, (100000f + Game.Random.Float(0f, 3250000f)) * -value.y);
	}

	void ShowEnemyDamageResultStat( ResultStat resultStat )
	{
		ResultStatsToShow.Add(new ResultStatData(Player.GetNameForEnemyResultStat(resultStat), resultStat, Player.GetResultStatColorForEnemy(resultStat), Player.GetResultStatIconForEnemy(resultStat)));
	}
}