BattlegroundTypeId GetRandomBG(BattlegroundTypeId bgTypeId)
        {
            BattlegroundTemplate bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId);

            if (bgTemplate != null)
            {
                Dictionary <BattlegroundTypeId, float> selectionWeights = new Dictionary <BattlegroundTypeId, float>();

                foreach (var mapId in bgTemplate.BattlemasterEntry.MapId)
                {
                    if (mapId == -1)
                    {
                        break;
                    }

                    BattlegroundTemplate bg = GetBattlegroundTemplateByMapId((uint)mapId);
                    if (bg != null)
                    {
                        selectionWeights.Add(bg.Id, bg.Weight);
                    }
                }

                return(selectionWeights.SelectRandomElementByWeight(i => i.Value).Key);
            }

            return(BattlegroundTypeId.None);
        }
        public void SendBattlegroundList(Player player, ObjectGuid guid, BattlegroundTypeId bgTypeId)
        {
            BattlegroundTemplate bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId);

            if (bgTemplate == null)
            {
                return;
            }

            BattlefieldList battlefieldList = new BattlefieldList();

            battlefieldList.BattlemasterGuid   = guid;
            battlefieldList.BattlemasterListID = (int)bgTypeId;
            battlefieldList.MinLevel           = (byte)bgTemplate.MinLevel;
            battlefieldList.MaxLevel           = (byte)bgTemplate.MaxLevel;
            battlefieldList.PvpAnywhere        = guid.IsEmpty();
            battlefieldList.HasRandomWinToday  = player.GetRandomWinner();
            player.SendPacket(battlefieldList);
        }
        public void LoadBattlegroundTemplates()
        {
            uint oldMSTime = Time.GetMSTime();

            _BattlegroundMapTemplates.Clear();
            _BattlegroundTemplates.Clear();

            //                                         0   1                  2                  3       4       5                 6               7            8       9
            SQLResult result = DB.World.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, HordeStartLoc, StartMaxDist, Weight, ScriptName FROM battleground_template");

            if (result.IsEmpty())
            {
                Log.outError(LogFilter.ServerLoading, "Loaded 0 Battlegrounds. DB table `Battleground_template` is empty.");
                return;
            }

            uint count = 0;

            do
            {
                BattlegroundTypeId bgTypeId = (BattlegroundTypeId)result.Read <uint>(0);
                if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, (uint)bgTypeId, null))
                {
                    continue;
                }

                // can be overwrite by values from DB
                BattlemasterListRecord bl = CliDB.BattlemasterListStorage.LookupByKey(bgTypeId);
                if (bl == null)
                {
                    Log.outError(LogFilter.Battleground, "Battleground ID {0} not found in BattlemasterList.dbc. Battleground not created.", bgTypeId);
                    continue;
                }

                BattlegroundTemplate bgTemplate = new BattlegroundTemplate();
                bgTemplate.Id = bgTypeId;
                bgTemplate.MinPlayersPerTeam = result.Read <ushort>(1);
                bgTemplate.MaxPlayersPerTeam = result.Read <ushort>(2);
                bgTemplate.MinLevel          = result.Read <byte>(3);
                bgTemplate.MaxLevel          = result.Read <byte>(4);
                float dist = result.Read <float>(7);
                bgTemplate.StartMaxDist = dist * dist;
                bgTemplate.Weight       = result.Read <byte>(8);

                bgTemplate.scriptId          = Global.ObjectMgr.GetScriptId(result.Read <string>(9));
                bgTemplate.BattlemasterEntry = bl;

                if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam)
                {
                    Log.outError(LogFilter.Sql, "Table `Battleground_template` for Id {0} has bad values for MinPlayersPerTeam ({1}) and MaxPlayersPerTeam({2})",
                                 bgTemplate.Id, bgTemplate.MinPlayersPerTeam, bgTemplate.MaxPlayersPerTeam);
                    continue;
                }

                if (bgTemplate.MinLevel == 0 || bgTemplate.MaxLevel == 0 || bgTemplate.MinLevel > bgTemplate.MaxLevel)
                {
                    Log.outError(LogFilter.Sql, "Table `Battleground_template` for Id {0} has bad values for LevelMin ({1}) and LevelMax({2})",
                                 bgTemplate.Id, bgTemplate.MinLevel, bgTemplate.MaxLevel);
                    continue;
                }

                if (bgTemplate.Id != BattlegroundTypeId.AA && bgTemplate.Id != BattlegroundTypeId.RB)
                {
                    uint startId = result.Read <uint>(5);
                    if (CliDB.WorldSafeLocsStorage.ContainsKey(startId))
                    {
                        WorldSafeLocsRecord start = CliDB.WorldSafeLocsStorage.LookupByKey(startId);
                        bgTemplate.StartLocation[TeamId.Alliance] = new Position(start.Loc.X, start.Loc.Y, start.Loc.Z, (start.Facing + MathFunctions.PI) / 180);
                    }
                    else
                    {
                        Log.outError(LogFilter.Sql, "Table `Battleground_template` for Id {0} has a non-existed WorldSafeLocs.dbc id {1} in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId);
                        continue;
                    }

                    startId = result.Read <uint>(6);
                    if (CliDB.WorldSafeLocsStorage.ContainsKey(startId))
                    {
                        WorldSafeLocsRecord start = CliDB.WorldSafeLocsStorage.LookupByKey(startId);
                        bgTemplate.StartLocation[TeamId.Horde] = new Position(start.Loc.X, start.Loc.Y, start.Loc.Z, result.Read <float>(8));
                    }
                    else
                    {
                        Log.outError(LogFilter.Sql, "Table `Battleground_template` for Id {0} has a non-existed WorldSafeLocs.dbc id {1} in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId);
                        continue;
                    }
                }

                if (!CreateBattleground(bgTemplate))
                {
                    continue;
                }

                _BattlegroundTemplates[bgTypeId] = bgTemplate;

                if (bgTemplate.BattlemasterEntry.MapId[1] == -1) // in this case we have only one mapId
                {
                    _BattlegroundMapTemplates[(uint)bgTemplate.BattlemasterEntry.MapId[0]] = _BattlegroundTemplates[bgTypeId];
                }

                ++count;
            }while (result.NextRow());

            Log.outInfo(LogFilter.ServerLoading, "Loaded {0} Battlegrounds in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
        }
        // used to create the BG templates
        bool CreateBattleground(BattlegroundTemplate bgTemplate)
        {
            Battleground bg = GetBattlegroundTemplate(bgTemplate.Id);

            if (!bg)
            {
                // Create the BG
                switch (bgTemplate.Id)
                {
                //case BattlegroundTypeId.AV:
                // bg = new BattlegroundAV();
                //break;
                case BattlegroundTypeId.WS:
                    bg = new BgWarsongGluch();
                    break;

                case BattlegroundTypeId.AB:
                    bg = new BgArathiBasin();
                    break;

                case BattlegroundTypeId.NA:
                    bg = new NagrandArena();
                    break;

                case BattlegroundTypeId.BE:
                    bg = new BladesEdgeArena();
                    break;

                case BattlegroundTypeId.EY:
                    bg = new BgEyeofStorm();
                    break;

                case BattlegroundTypeId.RL:
                    bg = new RuinsofLordaeronArena();
                    break;

                case BattlegroundTypeId.SA:
                    bg = new BgStrandOfAncients();
                    break;

                case BattlegroundTypeId.DS:
                    bg = new DalaranSewersArena();
                    break;

                case BattlegroundTypeId.RV:
                    bg = new RingofValorArena();
                    break;

                //case BattlegroundTypeId.IC:
                //bg = new BattlegroundIC();
                //break;
                case BattlegroundTypeId.AA:
                    bg = new Battleground();
                    break;

                case BattlegroundTypeId.RB:
                    bg = new Battleground();
                    bg.SetRandom(true);
                    break;

                /*
                 * case BattlegroundTypeId.TP:
                 * bg = new BattlegroundTP();
                 * break;
                 * case BattlegroundTypeId.BFG:
                 * bg = new BattlegroundBFG();
                 * break;
                 */
                default:
                    return(false);
                }
                bg.SetTypeID(bgTemplate.Id);
            }

            bg.SetMapId((uint)bgTemplate.BattlemasterEntry.MapId[0]);
            bg.SetName(bgTemplate.BattlemasterEntry.Name[Global.WorldMgr.GetDefaultDbcLocale()]);
            bg.SetInstanceID(0);
            bg.SetArenaorBGType(bgTemplate.IsArena());
            bg.SetMinPlayersPerTeam(bgTemplate.MinPlayersPerTeam);
            bg.SetMaxPlayersPerTeam(bgTemplate.MaxPlayersPerTeam);
            bg.SetMinPlayers(bgTemplate.MinPlayersPerTeam * 2);
            bg.SetMaxPlayers(bgTemplate.MaxPlayersPerTeam * 2);
            bg.SetTeamStartPosition(TeamId.Alliance, bgTemplate.StartLocation[TeamId.Alliance]);
            bg.SetTeamStartPosition(TeamId.Horde, bgTemplate.StartLocation[TeamId.Horde]);
            bg.SetStartMaxDist(bgTemplate.StartMaxDist);
            bg.SetLevelRange(bgTemplate.MinLevel, bgTemplate.MaxLevel);
            bg.SetScriptId(bgTemplate.scriptId);
            bg.SetQueueId((ulong)bgTemplate.Id | 0x1F10000000000000);

            if (!bgDataStore.ContainsKey(bg.GetTypeID()))
            {
                bgDataStore[bg.GetTypeID()] = new BattlegroundData();
            }

            bgDataStore[bg.GetTypeID()].Template = bg;

            return(true);
        }
        public void LoadBattlegroundTemplates()
        {
            uint oldMSTime = Time.GetMSTime();

            //                                         0   1                 2              3             4       5
            SQLResult result = DB.World.Query("SELECT ID, AllianceStartLoc, HordeStartLoc, StartMaxDist, Weight, ScriptName FROM battleground_template");

            if (result.IsEmpty())
            {
                Log.outError(LogFilter.ServerLoading, "Loaded 0 Battlegrounds. DB table `Battleground_template` is empty.");
                return;
            }

            uint count = 0;

            do
            {
                BattlegroundTypeId bgTypeId = (BattlegroundTypeId)result.Read <uint>(0);
                if (Global.DisableMgr.IsDisabledFor(DisableType.Battleground, (uint)bgTypeId, null))
                {
                    continue;
                }

                // can be overwrite by values from DB
                BattlemasterListRecord bl = CliDB.BattlemasterListStorage.LookupByKey(bgTypeId);
                if (bl == null)
                {
                    Log.outError(LogFilter.Battleground, "Battleground ID {0} not found in BattlemasterList.dbc. Battleground not created.", bgTypeId);
                    continue;
                }

                BattlegroundTemplate bgTemplate = new BattlegroundTemplate();
                bgTemplate.Id = bgTypeId;
                float dist = result.Read <float>(3);
                bgTemplate.MaxStartDistSq = dist * dist;
                bgTemplate.Weight         = result.Read <byte>(4);

                bgTemplate.ScriptId          = Global.ObjectMgr.GetScriptId(result.Read <string>(5));
                bgTemplate.BattlemasterEntry = bl;

                if (bgTemplate.Id != BattlegroundTypeId.AA && bgTemplate.Id != BattlegroundTypeId.RB)
                {
                    uint startId             = result.Read <uint>(1);
                    WorldSafeLocsEntry start = Global.ObjectMgr.GetWorldSafeLoc(startId);
                    if (start != null)
                    {
                        bgTemplate.StartLocation[TeamId.Alliance] = start;
                    }
                    else if (bgTemplate.StartLocation[TeamId.Alliance] != null) // reload case
                    {
                        Log.outError(LogFilter.Sql, $"Table `battleground_template` for id {bgTemplate.Id} contains a non-existing WorldSafeLocs.dbc id {startId} in field `AllianceStartLoc`. Ignoring.");
                    }
                    else
                    {
                        Log.outError(LogFilter.Sql, $"Table `Battleground_template` for Id {bgTemplate.Id} has a non-existed WorldSafeLocs.dbc id {startId} in field `AllianceStartLoc`. BG not created.");
                        continue;
                    }

                    startId = result.Read <uint>(2);
                    start   = Global.ObjectMgr.GetWorldSafeLoc(startId);
                    if (start != null)
                    {
                        bgTemplate.StartLocation[TeamId.Horde] = start;
                    }
                    else if (bgTemplate.StartLocation[TeamId.Horde] != null) // reload case
                    {
                        Log.outError(LogFilter.Sql, $"Table `battleground_template` for id {bgTemplate.Id} contains a non-existing WorldSafeLocs.dbc id {startId} in field `HordeStartLoc`. Ignoring.");
                    }
                    else
                    {
                        Log.outError(LogFilter.Sql, $"Table `Battleground_template` for Id {bgTemplate.Id} has a non-existed WorldSafeLocs.dbc id {startId} in field `HordeStartLoc`. BG not created.");
                        continue;
                    }
                }

                if (!CreateBattleground(bgTemplate))
                {
                    Log.outError(LogFilter.Battleground, $"Could not create battleground template class ({bgTemplate.Id})!");
                    continue;
                }

                _battlegroundTemplates[bgTypeId] = bgTemplate;

                if (bgTemplate.BattlemasterEntry.MapId[1] == -1) // in this case we have only one mapId
                {
                    _battlegroundMapTemplates[(uint)bgTemplate.BattlemasterEntry.MapId[0]] = _battlegroundTemplates[bgTypeId];
                }

                ++count;
            }while (result.NextRow());

            Log.outInfo(LogFilter.ServerLoading, "Loaded {0} Battlegrounds in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
        }
        // used to create the BG templates
        bool CreateBattleground(BattlegroundTemplate bgTemplate)
        {
            Battleground bg = GetBattlegroundTemplate(bgTemplate.Id);

            if (!bg)
            {
                // Create the BG
                switch (bgTemplate.Id)
                {
                //case BattlegroundTypeId.AV:
                // bg = new BattlegroundAV(bgTemplate);
                //break;
                case BattlegroundTypeId.WS:
                    bg = new BgWarsongGluch(bgTemplate);
                    break;

                case BattlegroundTypeId.AB:
                    bg = new BgArathiBasin(bgTemplate);
                    break;

                case BattlegroundTypeId.NA:
                    bg = new NagrandArena(bgTemplate);
                    break;

                case BattlegroundTypeId.BE:
                    bg = new BladesEdgeArena(bgTemplate);
                    break;

                case BattlegroundTypeId.EY:
                    bg = new BgEyeofStorm(bgTemplate);
                    break;

                case BattlegroundTypeId.RL:
                    bg = new RuinsofLordaeronArena(bgTemplate);
                    break;

                case BattlegroundTypeId.SA:
                    bg = new BgStrandOfAncients(bgTemplate);
                    break;

                case BattlegroundTypeId.DS:
                    bg = new DalaranSewersArena(bgTemplate);
                    break;

                case BattlegroundTypeId.RV:
                    bg = new RingofValorArena(bgTemplate);
                    break;

                //case BattlegroundTypeId.IC:
                //bg = new BattlegroundIC(bgTemplate);
                //break;
                case BattlegroundTypeId.AA:
                    bg = new Battleground(bgTemplate);
                    break;

                case BattlegroundTypeId.RB:
                    bg = new Battleground(bgTemplate);
                    bg.SetRandom(true);
                    break;

                /*
                 * case BattlegroundTypeId.TP:
                 * bg = new BattlegroundTP(bgTemplate);
                 * break;
                 * case BattlegroundTypeId.BFG:
                 * bg = new BattlegroundBFG(bgTemplate);
                 * break;
                 */
                default:
                    return(false);
                }
            }

            bg.SetInstanceID(0);

            if (!bgDataStore.ContainsKey(bg.GetTypeID()))
            {
                bgDataStore[bg.GetTypeID()] = new BattlegroundData();
            }

            bgDataStore[bg.GetTypeID()].Template = bg;

            return(true);
        }