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); }
//Called by UserManager after updating total exp to database and returning its result internal void SetTotalExp(ulong totalExp) { this.TotalExp = totalExp; //Lets recalc rank and exp, tho dont keep instantly update these to database if they are wrong, wait for AddExp to correct it (uint rank, ulong exp) = ExpUtils.GetRankAndExpFromTotalExp(totalExp); this.Rank = rank; this.Exp = exp; //Update to redis RedisConnection.GetDatabase().HashSetAsync($"users:{this.Id}", new HashEntry[] { new HashEntry("total_exp", totalExp), new HashEntry("rank", rank), new HashEntry("exp", exp), }, CommandFlags.FireAndForget); }
public virtual void AddExp(ulong exp) { if (exp == 0 || this.TotalExp == ulong.MaxValue) { return; } try { checked { this.TotalExp += exp; } } catch (StackOverflowException) { this.TotalExp = ulong.MaxValue; } (uint rank, ulong expLeft) = ExpUtils.GetRankAndExpFromTotalExp(this.TotalExp); this.Rank = rank; this.Exp = expLeft; }
private void PrepareInner() { List <ColumnClause> ColumnsLocal = GetAllColumns(); HashSet <string> uniqCols = new HashSet <string>(); int i2 = 0; foreach (var cs in ColumnsLocal) { string s = cs.ExtractAlias(); if (!string.IsNullOrEmpty(s) && !uniqCols.Contains(s)) { cs.InternalDbAlias = s; } if (string.IsNullOrEmpty(cs.InternalDbAlias)) { while (true) { string nm = "col" + i2.ToString(); if (uniqCols.Contains(nm)) { i2++; continue; } cs.InternalDbAlias = nm; uniqCols.Add(cs.InternalDbAlias); break; } } } if (GroupBys != null && GroupBys.Count > 0) { //подготовка group by. В колонках пока не поддерживаются агрегатные функции for (int i = 0; i < GroupBys.Count; i++) { GroupByClause gb = GroupBys[i]; if (gb.Expression != null) { gb.Expression.Prepare(); } } //сверяем выражения в groupby и колонках. Всё что в колонках должно быть groupby /* * for (int i = 0; i < Columns.Length; i++) * { * ColumnSelect cs = Columns[i]; * string s1 = cs.ColumnExpressionStr.ToLower().Trim(); * var arr = GroupBys.Where(a => a.ExpressionStr.ToLower().Trim() == s1).ToArray(); * if (arr.Length == 0) throw new Exception(string.Format("Column {0} not found in groupby expression")); * }*/ } if (WhereExpr != null) { WhereExpr.Prepare(); ExpUtils.CheckWhere(WhereExpr); } if (Having != null) { Having.Prepare(); } if (OrderBys != null && OrderBys.Count > 0) { //подготовка group by. В колонках пока не поддерживаются агрегатные функции for (int i = 0; i < OrderBys.Count; i++) { OrderByClause gb = OrderBys[i]; if (gb.Expression != null) { gb.Expression.Prepare(); } } } }
public static ulong GetExpEarnedForFinishing(double finishTime) => (ulong)Math.Round(ExpUtils.EXP_FOR_FINISHING * ExpUtils.GetPlaytimeMultiplayer(finishTime));
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(); } } }