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);
        }
Example #3
0
    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();
                }
            }
        }