public static (uint rank, ulong exp) GetRankAndExpFromTotalExp(ulong totalExp) { uint currentRank = 0; while (totalExp > 0) { ulong expNeeded = ExpUtils.GetNextRankExpRequirement(currentRank); try { checked { totalExp -= expNeeded; currentRank++; if (totalExp == 0) { break; } } } catch (OverflowException) { break; } } return(currentRank, totalExp); }
internal void FinishMatch(ClientSession session) { if (this.StartedOn != null) { double now = this.StartedOn.Elapsed.TotalSeconds; if (this.LevelData.Seconds > 0 && this.LevelData.Mode != LevelMode.KingOfTheHat && now > (this.LevelData.Seconds + 5)) //Small threashold { return; } if (this.Players.TryGetValue(session.SocketId, out MatchPlayer player) && !player.Forfiet && player.FinishTime == null) { player.FinishTime = now; this.Clients.SendPacket(new PlayerFinishedOutgoingMessage(session.SocketId, (IReadOnlyCollection <MatchPlayer>) this.Players.Values)); ulong expEarned = ExpUtils.GetExpEarnedForFinishing(now); List <object[]> expArray = new List <object[]>(); if (this.LevelData.Mode == LevelMode.Race) { expArray.Add(new object[] { "Level completed", expEarned }); } else if (this.LevelData.Mode == LevelMode.Deathmatch) { expArray.Add(new object[] { "Fighting spirit", expEarned }); } else if (this.LevelData.Mode == LevelMode.HatAttack) { expArray.Add(new object[] { "Hat owner", expEarned }); } else if (this.LevelData.Mode == LevelMode.CoinFiend) { expArray.Add(new object[] { "Coin meizer", expEarned }); } else if (this.LevelData.Mode == LevelMode.DamageDash) { expArray.Add(new object[] { "Damage dealer", expEarned }); } else if (this.LevelData.Mode == LevelMode.KingOfTheHat) { expArray.Add(new object[] { "Hat holder", expEarned }); } bool firstPlace = true; foreach (MatchPlayer other in this.Players.Values) { if (other != player) { bool defeated = false; switch (this.LevelData.Mode) { case LevelMode.Race: case LevelMode.HatAttack: case LevelMode.KingOfTheHat: defeated = other.Forfiet || other.FinishTime == null; break; case LevelMode.Deathmatch: defeated = other.Forfiet || other.FinishTime != null; break; case LevelMode.CoinFiend: defeated = other.Forfiet || player.Coins > other.Coins; break; case LevelMode.DamageDash: defeated = other.Forfiet || player.Dash > other.Dash; break; } if (defeated) { ulong playerExp = (ulong)Math.Round(ExpUtils.GetExpForDefeatingPlayer(other.UserData.Rank) * ExpUtils.GetPlaytimeMultiplayer(other.FinishTime ?? now) * ExpUtils.GetKeyPressMultiplayer(other.KeyPresses)); if (other.IPAddress == player.IPAddress) { playerExp /= 2; } expEarned += playerExp; expArray.Add(new object[] { "Defeated " + other.UserData.Username, playerExp }); } else { firstPlace = false; } } } ulong baseExp = expEarned; if (firstPlace) { MatchPrize prize = Interlocked.Exchange(ref this.Prize, null); if (prize != null) { bool partExp = false; if (prize.Category == "hat") { if (player.UserData.HasHat((Hat)prize.Id)) { partExp = true; } else { player.UserData.GiveHat((Hat)prize.Id); } } else if (prize.Category == "head") { if (player.UserData.HasHead((Part)prize.Id)) { partExp = true; } else { player.UserData.GiveHead((Part)prize.Id); } } else if (prize.Category == "body") { if (player.UserData.HasBody((Part)prize.Id)) { partExp = true; } else { player.UserData.GiveBody((Part)prize.Id); } } else if (prize.Category == "feet") { if (player.UserData.HasFeet((Part)prize.Id)) { partExp = true; } else { player.UserData.GiveFeet((Part)prize.Id); } } if (!prize.RewardsExpBonus) { partExp = false; } if (partExp) { expEarned += (ulong)Math.Round(baseExp * 0.5); expArray.Add(new object[] { "Prize bonus", "EXP X 1.5" }); } session.SendPacket(new PrizeOutgoingMessage(prize, partExp ? "exp" : "got")); } } float expHatBonus = 0; foreach (MatchPlayerHat hat in player.Hats) { if (!hat.Spawned && hat.Hat == Hat.BaseballCap) { expHatBonus += expHatBonus == 0 ? 1f : 0.1f; } } if (expHatBonus > 0) { expEarned += (ulong)Math.Round(baseExp * expHatBonus); expArray.Add(new object[] { "Exp hat", $"EXP X {expHatBonus + 1}" }); } ulong bonusExpDrained = 0; if (player.UserData.BonusExp > 0) { bonusExpDrained = Math.Min(player.UserData.BonusExp, baseExp); if (bonusExpDrained > 0) { expEarned += bonusExpDrained; expArray.Add(new object[] { "Bonus exp", $"EXP X {(bonusExpDrained / baseExp) + 1}" }); expArray.Add(new object[] { "Bonus exp left", player.UserData.BonusExp - bonusExpDrained }); player.UserData.DrainBonusExp(bonusExpDrained); } } session.SendPackets(new YouFinishedOutgoingMessage(session.UserData.Rank, session.UserData.Exp, ExpUtils.GetNextRankExpRequirement(session.UserData.Rank), expEarned, expArray)); player.UserData.AddExp(expEarned); this.CheckGameState(); } } }