View difference between Paste ID: X4p7ek54 and BM7Gm8Md
SHOW: | | - or go back to the newest paste.
1
 cmake/compiler/msvc/settings.cmake                 |   2 +-
2
 .../CrossFactionBG/world.AVFix.sql                 |   3 +
3
 src/server/game/Battlegrounds/Arena.cpp            |   4 +-
4
 src/server/game/Battlegrounds/Battleground.cpp     |  47 ++-
5
 src/server/game/Battlegrounds/Battleground.h       |   2 +-
6
 src/server/game/Battlegrounds/BattlegroundMgr.cpp  |   2 +-
7
 .../game/Battlegrounds/BattlegroundQueue.cpp       |  85 ++++--
8
 src/server/game/Battlegrounds/BattlegroundQueue.h  |  11 +-
9
 .../game/Battlegrounds/Zones/BattlegroundAB.cpp    |   2 +-
10
 .../game/Battlegrounds/Zones/BattlegroundAV.cpp    |  19 +-
11
 .../game/Battlegrounds/Zones/BattlegroundWS.cpp    |   3 +-
12
 src/server/game/CMakeLists.txt                     |   2 +
13
 src/server/game/Cfbg/Cfbg.cpp                      | 326 +++++++++++++++++++++
14
 src/server/game/Cfbg/Cfbg.h                        |  35 +++
15
 src/server/game/Entities/Player/Player.cpp         |  99 +++++--
16
 src/server/game/Entities/Player/Player.h           |  37 ++-
17
 src/server/game/Entities/Unit/Unit.cpp             |  17 +-
18
 src/server/game/Entities/Unit/Unit.h               |   4 +-
19
 src/server/game/Handlers/BattleGroundHandler.cpp   |   4 +-
20
 src/server/game/Handlers/CharacterHandler.cpp      |   3 +
21
 src/server/game/Handlers/ChatHandler.cpp           |  18 +-
22
 src/server/game/Handlers/MiscHandler.cpp           |  15 +
23
 src/server/game/Handlers/QueryHandler.cpp          |   2 +-
24
 src/server/game/World/World.cpp                    |   2 +
25
 src/server/game/World/World.h                      |   1 +
26
 src/server/worldserver/worldserver.conf.dist       |  12 +
27
 26 files changed, 658 insertions(+), 99 deletions(-)
28
 create mode 100644 sql/TrinityCore-Patches/CrossFactionBG/world.AVFix.sql
29
 create mode 100644 src/server/game/Cfbg/Cfbg.cpp
30
 create mode 100644 src/server/game/Cfbg/Cfbg.h
31
32
diff --git a/cmake/compiler/msvc/settings.cmake b/cmake/compiler/msvc/settings.cmake
33
index a455e97..e483eb9 100644
34
--- a/cmake/compiler/msvc/settings.cmake
35
+++ b/cmake/compiler/msvc/settings.cmake
36
@@ -1,7 +1,7 @@
37
 # set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)
38
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
39
 
40
-set(MSVC_EXPECTED_VERSION 18.0)
41
+set(MSVC_EXPECTED_VERSION 16.0)
42
 
43
 if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MSVC_EXPECTED_VERSION)
44
   message(FATAL_ERROR "MSVC: TrinityCore requires version ${MSVC_EXPECTED_VERSION} (MSVC 2013) to build but found ${CMAKE_CXX_COMPILER_VERSION}")
45
diff --git a/sql/TrinityCore-Patches/CrossFactionBG/world.AVFix.sql b/sql/TrinityCore-Patches/CrossFactionBG/world.AVFix.sql
46
new file mode 100644
47
index 0000000..a0c7eb9
48
--- /dev/null
49
+++ b/sql/TrinityCore-Patches/CrossFactionBG/world.AVFix.sql
50
@@ -0,0 +1,3 @@
51
+UPDATE creature_template SET faction = 1 WHERE entry IN (4255,4257,5134,5135,5139,11948,11949,11997,12050,12096,12127,13086,13096,13138,13216,13257,13296,13298,13299,13317,13318,13319,13320,13326,13327,13331,13422,13437,13438,13439,13442,13443,13447,13546,13576,13577,13598,13617,13797,14187,14188,14284,14762,14763,14765,14766,14768,14769,12047,13396,13358,13080,13078);
52
+
53
+UPDATE creature_template SET faction = 2 WHERE entry IN (2225,3343,3625,10364,10367,11946,11947,11998,12051,12052,12053,12097,12121,12122,13088,13089,13097,13137,13140,13143,13144,13145,13146,13147,13152,13153,13154,13176,13179,13180,13181,13218,13236,13284,13316,13359,13377,13397,13425,13428,13441,13448,13536,13539,13545,13597,13616,13618,13798,14185,14186,14282,14285,14772,14773,14774,14775,14776,14777,13332,13099,13079);
54
diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp
55
index f523ec6..512b0b2 100644
56
--- a/src/server/game/Battlegrounds/Arena.cpp
57
+++ b/src/server/game/Battlegrounds/Arena.cpp
58
@@ -40,9 +40,9 @@ Arena::Arena()
59
 void Arena::AddPlayer(Player* player)
60
 {
61
     Battleground::AddPlayer(player);
62
-    PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetBGTeam());
63
+    PlayerScores[player->GetGUIDLow()] = new ArenaScore(player->GetGUID(), player->GetTeam());
64
 
65
-    if (player->GetBGTeam() == ALLIANCE)        // gold
66
+    if (player->GetTeam() == ALLIANCE)        // gold
67
     {
68
         if (player->GetTeam() == HORDE)
69
             player->CastSpell(player, SPELL_HORDE_GOLD_FLAG, true);
70
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
71
index 3fb91ee..20ee989 100644
72
--- a/src/server/game/Battlegrounds/Battleground.cpp
73
+++ b/src/server/game/Battlegrounds/Battleground.cpp
74
@@ -287,7 +287,7 @@ inline void Battleground::_CheckSafePositions(uint32 diff)
75
             if (Player* player = ObjectAccessor::FindPlayer(itr->first))
76
             {
77
                 Position pos = player->GetPosition();
78
-                Position const* startPos = GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(player->GetBGTeam()));
79
+                Position const* startPos = GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(player->GetTeam()));
80
                 if (pos.GetExactDistSq(startPos) > maxDist)
81
                 {
82
                     TC_LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending %s back to start location (map: %u) (possible exploit)", player->GetName().c_str(), GetMapId());
83
@@ -493,7 +493,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
84
                     WorldPacket status;
85
                     BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
86
                     uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
87
-                    sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), player->GetBGTeam());
88
+                    sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), player->GetTeam());
89
                     player->SendDirectMessage(&status);
90
 
91
                     player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
92
@@ -661,22 +661,34 @@ void Battleground::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
93
             UpdatePlayerScore(player, SCORE_BONUS_HONOR, Honor);
94
 }
95
 
96
-void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID)
97
+void Battleground::RewardReputationToTeam(uint32 a_faction_id, uint32 h_faction_id, uint32 Reputation, uint32 TeamID)
98
 {
99
-    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
100
-    if (!factionEntry)
101
+    FactionEntry const* a_factionEntry = sFactionStore.LookupEntry(a_faction_id);
102
+    FactionEntry const* h_factionEntry = sFactionStore.LookupEntry(h_faction_id);
103
+
104
+    if (!a_factionEntry || !h_factionEntry)
105
         return;
106
 
107
     for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
108
     {
109
-        Player* player = _GetPlayerForTeam(TeamID, itr, "RewardReputationToTeam");
110
-        if (!player)
111
+       if (itr->second.OfflineRemoveTime)
112
             continue;
113
 
114
-        uint32 repGain = Reputation;
115
-        AddPct(repGain, player->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN));
116
-        AddPct(repGain, player->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, faction_id));
117
-        player->GetReputationMgr().ModifyReputation(factionEntry, repGain);
118
+        Player* plr = ObjectAccessor::FindPlayer(itr->first);
119
+
120
+        if (!plr)
121
+        {
122
+            TC_LOG_ERROR("bg.battleground", "BattleGround:RewardReputationToTeam: %u not found!", itr->first);
123
+            continue;
124
+        }
125
+
126
+        //uint32 team = plr->GetTeam();
127
+
128
+        //if (team == TeamId)
129
+        if (Player* plr = _GetPlayerForTeam(TeamID, itr, "RewardReputationToTeam"))
130
+            {
131
+            plr->GetReputationMgr().ModifyReputation(plr->GetOTeam() == ALLIANCE ? a_factionEntry : h_factionEntry, Reputation);
132
+            }
133
     }
134
 }
135
 
136
@@ -829,7 +841,7 @@ void Battleground::EndBattleground(uint32 winner)
137
         player->SendDirectMessage(&pvpLogData);
138
 
139
         WorldPacket data;
140
-        sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetBGTeam());
141
+        sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetTeam());
142
         player->SendDirectMessage(&data);
143
         player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
144
     }
145
@@ -945,6 +957,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen
146
 
147
     if (player)
148
     {
149
+        player->FitPlayerInTeam(false, this);
150
         // Do next only if found in battleground
151
         player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE);  // We're not in BG.
152
         // reset destination bg team
153
@@ -1013,7 +1026,7 @@ void Battleground::AddPlayer(Player* player)
154
 
155
     // score struct must be created in inherited class
156
 
157
-    uint32 team = player->GetBGTeam();
158
+    uint32 team = player->GetTeam();
159
 
160
     BattlegroundPlayer bp;
161
     bp.OfflineRemoveTime = 0;
162
@@ -1064,6 +1077,8 @@ void Battleground::AddPlayer(Player* player)
163
     // setup BG group membership
164
     PlayerAddedToBGCheckIfBGIsRunning(player);
165
     AddOrSetPlayerToCorrectBgGroup(player, team);
166
+
167
+    player->FitPlayerInTeam(true, this);
168
 }
169
 
170
 // this method adds player to his team's bg group, or sets his correct group if player is already in bg group
171
@@ -1133,8 +1148,8 @@ void Battleground::EventPlayerLoggedOut(Player* player)
172
 
173
         // 1 player is logging out, if it is the last, then end arena!
174
         if (isArena())
175
-            if (GetAlivePlayersCountByTeam(player->GetBGTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetBGTeam())))
176
-                EndBattleground(GetOtherTeam(player->GetBGTeam()));
177
+            if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
178
+                EndBattleground(GetOtherTeam(player->GetTeam()));
179
     }
180
 }
181
 
182
@@ -1735,7 +1750,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player)
183
     BuildPvPLogDataPacket(data);
184
     player->SendDirectMessage(&data);
185
 
186
-    sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam());
187
+    sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetTeam());
188
     player->SendDirectMessage(&data);
189
 }
190
 
191
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
192
index 001c33c..c4633c3 100644
193
--- a/src/server/game/Battlegrounds/Battleground.h
194
+++ b/src/server/game/Battlegrounds/Battleground.h
195
@@ -354,7 +354,7 @@ class Battleground
196
         void CastSpellOnTeam(uint32 SpellID, uint32 TeamID);
197
         void RemoveAuraOnTeam(uint32 SpellID, uint32 TeamID);
198
         void RewardHonorToTeam(uint32 Honor, uint32 TeamID);
199
-        void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID);
200
+        void RewardReputationToTeam(uint32 a_faction_id, uint32 h_faction_id, uint32 Reputation, uint32 TeamId);
201
         void UpdateWorldState(uint32 Field, uint32 Value);
202
         void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player);
203
         virtual void EndBattleground(uint32 winner);
204
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
205
index f5ee169..8a5713c 100644
206
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
207
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
208
@@ -695,7 +695,7 @@ void BattlegroundMgr::SendToBattleground(Player* player, uint32 instanceId, Batt
209
     if (Battleground* bg = GetBattleground(instanceId, bgTypeId))
210
     {
211
         uint32 mapid = bg->GetMapId();
212
-        uint32 team = player->GetBGTeam();
213
+        uint32 team = player->GetTeam();
214
         if (team == 0)
215
             team = player->GetTeam();
216
 
217
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
218
index 46fbd43..fe62027 100644
219
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
220
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
221
@@ -154,6 +154,10 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, Battlegr
222
         index += BG_TEAMS_COUNT;
223
     if (ginfo->Team == HORDE)
224
         index++;
225
+
226
+    if (sWorld->getBoolConfig(BATTLEGROUND_CROSSFACTION_ENABLED) && ArenaType == 0)
227
+        index = BG_QUEUE_MIXED;                      // BG_QUEUE_*_* -> BG_QUEUE_MIXED
228
+
229
     TC_LOG_DEBUG("bg.battleground", "Adding Group to BattlegroundQueue bgTypeId : %u, bracket_id : %u, index : %u", BgTypeId, bracketId, index);
230
 
231
     uint32 lastOnlineTime = getMSTime();
232
@@ -198,33 +202,58 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, Battlegr
233
         {
234
             if (Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(ginfo->BgTypeId))
235
             {
236
-                uint32 MinPlayers = bg->GetMinPlayersPerTeam();
237
-                uint32 qHorde = 0;
238
-                uint32 qAlliance = 0;
239
-                uint32 q_min_level = bracketEntry->minLevel;
240
-                uint32 q_max_level = bracketEntry->maxLevel;
241
-                GroupsQueueType::const_iterator itr;
242
-                for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr)
243
-                    if (!(*itr)->IsInvitedToBGInstanceGUID)
244
-                        qAlliance += (*itr)->Players.size();
245
-                for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].end(); ++itr)
246
-                    if (!(*itr)->IsInvitedToBGInstanceGUID)
247
-                        qHorde += (*itr)->Players.size();
248
-
249
-                // Show queue status to player only (when joining queue)
250
-                if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
251
+                if (sWorld->getBoolConfig(BATTLEGROUND_CROSSFACTION_ENABLED))
252
                 {
253
-                    ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bg->GetName().c_str(), q_min_level, q_max_level,
254
-                        qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
255
+                    char const* bgName = bg->GetName().c_str();
256
+                    uint32 MinPlayers = bg->GetMinPlayersPerTeam()*2;
257
+                    uint32 qPlayers = 0;
258
+                    uint32 q_min_level = bracketEntry->minLevel;
259
+                    uint32 q_max_level = bracketEntry->maxLevel;
260
+                    for (GroupsQueueType::const_iterator itr = m_QueuedGroups[bracketId][BG_QUEUE_MIXED].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_MIXED].end(); ++itr)
261
+                        if (!(*itr)->IsInvitedToBGInstanceGUID)
262
+                            qPlayers += (*itr)->Players.size();
263
+
264
+                    if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
265
+                    {
266
+                        ChatHandler(leader->GetSession()).PSendSysMessage("Queue status for %s (Lvl: %u to %u) Queued players: %u (Need at least %u more)", bgName, q_min_level, q_max_level, qPlayers, MinPlayers - qPlayers);
267
+                    }
268
+                    else
269
+                    {
270
+                        std::ostringstream ss;
271
+                        ss << "|cffff0000[BG Queue Announcer]:|r " << bgName << " -- [" << q_min_level << "-" << q_max_level << "] " << qPlayers << "/" << MinPlayers;
272
+                        sWorld->SendGlobalText(ss.str().c_str(), NULL);
273
+                    }
274
                 }
275
-                // System message
276
                 else
277
                 {
278
-                    sWorld->SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bg->GetName().c_str(), q_min_level, q_max_level,
279
-                        qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
280
+                    std::string bgName = bg->GetName().c_str();
281
+                    uint32 MinPlayers = bg->GetMinPlayersPerTeam();
282
+                    uint32 qHorde = 0;
283
+                    uint32 qAlliance = 0;
284
+                    uint32 q_min_level = bracketEntry->minLevel;
285
+                    uint32 q_max_level = bracketEntry->maxLevel;
286
+                    GroupsQueueType::const_iterator itr;
287
+                    for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr)
288
+                        if (!(*itr)->IsInvitedToBGInstanceGUID)
289
+                            qAlliance += (*itr)->Players.size();
290
+                    for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE].end(); ++itr)
291
+                        if (!(*itr)->IsInvitedToBGInstanceGUID)
292
+                            qHorde += (*itr)->Players.size();
293
+
294
+                    // Show queue status to player only (when joining queue)
295
+                    if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
296
+                    {
297
+                        ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bg->GetName().c_str(), q_min_level, q_max_level,
298
+                            qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
299
+                    }
300
+                    // System message
301
+                    else
302
+                    {
303
+                        sWorld->SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bg->GetName().c_str(), q_min_level, q_max_level,
304
+                            qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
305
+                    }
306
                 }
307
-            }
308
-        }
309
+            }        }
310
         //release mutex
311
     }
312
 
313
@@ -308,7 +337,7 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
314
     {
315
         //we must check premade and normal team's queue - because when players from premade are joining bg,
316
         //they leave groupinfo so we can't use its players size to find out index
317
-        for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_TEAMS_COUNT)
318
+        for (uint8 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; ++j)
319
         {
320
             GroupsQueueType::iterator k = m_QueuedGroups[bracket_id_tmp][j].begin();
321
             for (; k != m_QueuedGroups[bracket_id_tmp][j].end(); ++k)
322
@@ -497,6 +526,10 @@ void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId
323
     int32 hordeFree = bg->GetFreeSlotsForTeam(HORDE);
324
     int32 aliFree   = bg->GetFreeSlotsForTeam(ALLIANCE);
325
 
326
+    if (!bg->isArena())
327
+        if (FillXPlayersToBG(bracket_id, bg, false))
328
+            return;
329
+
330
     //iterator for iterating through bg queue
331
     GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].begin();
332
     //count of groups in queue - used to stop cycles
333
@@ -745,7 +778,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
334
     if (m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE].empty() &&
335
         m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE].empty() &&
336
         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE].empty() &&
337
-        m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].empty())
338
+        m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE].empty() &&
339
+        m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].empty())
340
         return;
341
 
342
     // battleground with free slot for player should be always in the beggining of the queue
343
@@ -836,7 +870,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
344
     {
345
         // if there are enough players in pools, start new battleground or non rated arena
346
         if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)
347
-            || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam)))
348
+            || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam))
349
+            || CheckCrossFactionMatch(bracket_id, bg_template))
350
         {
351
             // we successfully created a pool
352
             Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, false);
353
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
354
index 051ed06..3973434 100644
355
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
356
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
357
@@ -42,6 +42,7 @@ struct GroupQueueInfo                                       // stores informatio
358
 {
359
     std::map<ObjectGuid, PlayerQueueInfo*> Players;         // player queue info map
360
     uint32  Team;                                           // Player team (ALLIANCE/HORDE)
361
+    uint32  OTeam;                                          // Player team (ALLIANCE/HORDE)
362
     BattlegroundTypeId BgTypeId;                            // battleground type id
363
     bool    IsRated;                                        // rated
364
     uint8   ArenaType;                                      // 2v2, 3v3, 5v5 or 0 when BG
365
@@ -60,9 +61,10 @@ enum BattlegroundQueueGroupTypes
366
     BG_QUEUE_PREMADE_ALLIANCE   = 0,
367
     BG_QUEUE_PREMADE_HORDE      = 1,
368
     BG_QUEUE_NORMAL_ALLIANCE    = 2,
369
-    BG_QUEUE_NORMAL_HORDE       = 3
370
+    BG_QUEUE_NORMAL_HORDE       = 3,
371
+    BG_QUEUE_MIXED              = 4
372
 };
373
-#define BG_QUEUE_GROUP_TYPES_COUNT 4
374
+#define BG_QUEUE_GROUP_TYPES_COUNT 5
375
 
376
 class Battleground;
377
 class BattlegroundQueue
378
@@ -74,6 +76,11 @@ class BattlegroundQueue
379
         void BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType = 0, bool isRated = false, uint32 minRating = 0);
380
         void UpdateEvents(uint32 diff);
381
 
382
+        bool FillXPlayersToBG(BattlegroundBracketId bracket_id, Battleground* bg, bool start = false);
383
+        typedef std::multimap<int32, GroupQueueInfo*> QueuedGroupMap;
384
+        int32 PreAddPlayers(QueuedGroupMap m_PreGroupMap, int32 MaxAdd, uint32 MaxInTeam);
385
+        bool CheckCrossFactionMatch(BattlegroundBracketId bracket_id, Battleground* bg);
386
+
387
         void FillPlayersToBG(Battleground* bg, BattlegroundBracketId bracket_id);
388
         bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam);
389
         bool CheckNormalMatch(Battleground* bg_template, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers);
390
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
391
index 6828532..6b0c34c 100644
392
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
393
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
394
@@ -141,7 +141,7 @@ void BattlegroundAB::PostUpdateImpl(uint32 diff)
395
 
396
                 if (m_ReputationScoreTics[team] >= m_ReputationTics)
397
                 {
398
-                    (team == TEAM_ALLIANCE) ? RewardReputationToTeam(509, 10, ALLIANCE) : RewardReputationToTeam(510, 10, HORDE);
399
+                    RewardReputationToTeam(509, 510, 10, team == ALLIANCE ? ALLIANCE : HORDE);
400
                     m_ReputationScoreTics[team] -= m_ReputationTics;
401
                 }
402
 
403
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
404
index 0490923..85bdda1 100644
405
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
406
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
407
@@ -89,7 +89,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
408
     if (entry == BG_AV_CreatureInfo[AV_NPC_A_BOSS])
409
     {
410
         CastSpellOnTeam(23658, HORDE); //this is a spell which finishes a quest where a player has to kill the boss
411
-        RewardReputationToTeam(729, BG_AV_REP_BOSS, HORDE);
412
+        RewardReputationToTeam(729, 730, BG_AV_REP_BOSS, killer->GetTeam() == ALLIANCE ? ALLIANCE : HORDE);
413
         RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), HORDE);
414
         EndBattleground(HORDE);
415
         DelCreature(AV_CPLACE_TRIGGER17);
416
@@ -97,7 +97,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
417
     else if (entry == BG_AV_CreatureInfo[AV_NPC_H_BOSS])
418
     {
419
         CastSpellOnTeam(23658, ALLIANCE); //this is a spell which finishes a quest where a player has to kill the boss
420
-        RewardReputationToTeam(730, BG_AV_REP_BOSS, ALLIANCE);
421
+        RewardReputationToTeam(729, 730, BG_AV_REP_BOSS, killer->GetTeam() == ALLIANCE ? ALLIANCE : HORDE);
422
         RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_BOSS), ALLIANCE);
423
         EndBattleground(ALLIANCE);
424
         DelCreature(AV_CPLACE_TRIGGER19);
425
@@ -110,7 +110,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
426
             return;
427
         }
428
         m_CaptainAlive[0]=false;
429
-        RewardReputationToTeam(729, BG_AV_REP_CAPTAIN, HORDE);
430
+        RewardReputationToTeam(729, 730, BG_AV_REP_CAPTAIN, killer->GetTeam() == ALLIANCE ? ALLIANCE : HORDE);
431
         RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), HORDE);
432
         UpdateScore(ALLIANCE, (-1)*BG_AV_RES_CAPTAIN);
433
         //spawn destroyed aura
434
@@ -129,7 +129,7 @@ void BattlegroundAV::HandleKillUnit(Creature* unit, Player* killer)
435
             return;
436
         }
437
         m_CaptainAlive[1]=false;
438
-        RewardReputationToTeam(730, BG_AV_REP_CAPTAIN, ALLIANCE);
439
+        RewardReputationToTeam(729, 730, BG_AV_REP_CAPTAIN, killer->GetTeam() == ALLIANCE ? ALLIANCE : HORDE);
440
         RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_CAPTAIN), ALLIANCE);
441
         UpdateScore(HORDE, (-1)*BG_AV_RES_CAPTAIN);
442
         //spawn destroyed aura
443
@@ -151,6 +151,7 @@ void BattlegroundAV::HandleQuestComplete(uint32 questid, Player* player)
444
     if (GetStatus() != STATUS_IN_PROGRESS)
445
         return;//maybe we should log this, cause this must be a cheater or a big bug
446
     uint8 team = GetTeamIndexByTeamId(player->GetTeam());
447
+    uint8 oteam = GetTeamIndexByTeamId(GetOtherTeam(player->GetTeam()));
448
     /// @todo add reputation, events (including quest not available anymore, next quest available, go/npc de/spawning)and maybe honor
449
     TC_LOG_DEBUG("bg.battleground", "BG_AV Quest %i completed", questid);
450
     switch (questid)
451
@@ -175,21 +176,21 @@ void BattlegroundAV::HandleQuestComplete(uint32 questid, Player* player)
452
         case AV_QUEST_A_COMMANDER1:
453
         case AV_QUEST_H_COMMANDER1:
454
             m_Team_QuestStatus[team][1]++;
455
-            RewardReputationToTeam(team, 1, player->GetTeam());
456
+            RewardReputationToTeam(team, oteam, 1, player->GetTeam());
457
             if (m_Team_QuestStatus[team][1] == 30)
458
                 TC_LOG_DEBUG("bg.battleground", "BG_AV Quest %i completed (need to implement some events here", questid);
459
             break;
460
         case AV_QUEST_A_COMMANDER2:
461
         case AV_QUEST_H_COMMANDER2:
462
             m_Team_QuestStatus[team][2]++;
463
-            RewardReputationToTeam(team, 1, player->GetTeam());
464
+            RewardReputationToTeam(team, oteam, 1, player->GetTeam());
465
             if (m_Team_QuestStatus[team][2] == 60)
466
                 TC_LOG_DEBUG("bg.battleground", "BG_AV Quest %i completed (need to implement some events here", questid);
467
             break;
468
         case AV_QUEST_A_COMMANDER3:
469
         case AV_QUEST_H_COMMANDER3:
470
             m_Team_QuestStatus[team][3]++;
471
-            RewardReputationToTeam(team, 1, player->GetTeam());
472
+            RewardReputationToTeam(team, oteam, 1, player->GetTeam());
473
             if (m_Team_QuestStatus[team][3] == 120)
474
                 TC_LOG_DEBUG("bg.battleground", "BG_AV Quest %i completed (need to implement some events here", questid);
475
             break;
476
@@ -471,7 +472,7 @@ void BattlegroundAV::EndBattleground(uint32 winner)
477
             rep[i]   += BG_AV_REP_SURVIVING_CAPTAIN;
478
         }
479
         if (rep[i] != 0)
480
-            RewardReputationToTeam(i == 0 ? 730 : 729, rep[i], i == 0 ? ALLIANCE : HORDE);
481
+            RewardReputationToTeam(729, 730, 10, i == ALLIANCE ? ALLIANCE : HORDE);
482
         if (kills[i] != 0)
483
             RewardHonorToTeam(GetBonusHonorFromKill(kills[i]), i == 0 ? ALLIANCE : HORDE);
484
     }
485
@@ -576,7 +577,7 @@ void BattlegroundAV::EventPlayerDestroyedPoint(BG_AV_Nodes node)
486
             SpawnBGObject(BG_AV_OBJECT_BURN_DUNBALDAR_SOUTH + i + (tmp * 10), RESPAWN_IMMEDIATELY);
487
 
488
         UpdateScore((owner == ALLIANCE) ? HORDE : ALLIANCE, -1 * BG_AV_RES_TOWER);
489
-        RewardReputationToTeam(owner == ALLIANCE ? 730 : 729, BG_AV_REP_TOWER, owner);
490
+        RewardReputationToTeam(729, 730, BG_AV_REP_TOWER, owner);
491
         RewardHonorToTeam(GetBonusHonorFromKill(BG_AV_KILL_TOWER), owner);
492
 
493
         SpawnBGObject(BG_AV_OBJECT_TAURA_A_DUNBALDAR_SOUTH+GetTeamIndexByTeamId(owner)+(2*tmp), RESPAWN_ONE_DAY);
494
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
495
index 5991fd1..4162d71 100644
496
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
497
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
498
@@ -309,7 +309,6 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
499
         if (GetTeamScore(TEAM_ALLIANCE) < BG_WS_MAX_TEAM_SCORE)
500
             AddPoint(ALLIANCE, 1);
501
         PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_ALLIANCE);
502
-        RewardReputationToTeam(890, m_ReputationCapture, ALLIANCE);
503
     }
504
     else
505
     {
506
@@ -328,8 +327,8 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
507
         if (GetTeamScore(TEAM_HORDE) < BG_WS_MAX_TEAM_SCORE)
508
             AddPoint(HORDE, 1);
509
         PlaySoundToAll(BG_WS_SOUND_FLAG_CAPTURED_HORDE);
510
-        RewardReputationToTeam(889, m_ReputationCapture, HORDE);
511
     }
512
+    RewardReputationToTeam(890, 889, m_ReputationCapture, player->GetTeam());
513
     //for flag capture is reward 2 honorable kills
514
     RewardHonorToTeam(GetBonusHonorFromKill(2), player->GetTeam());
515
 
516
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
517
index d748be4..f65045c 100644
518
--- a/src/server/game/CMakeLists.txt
519
+++ b/src/server/game/CMakeLists.txt
520
@@ -49,6 +49,7 @@ file(GLOB_RECURSE sources_Tickets Tickets/*.cpp Tickets/*.h)
521
 file(GLOB_RECURSE sources_Warden Warden/*.cpp Warden/*.h)
522
 file(GLOB_RECURSE sources_Weather Weather/*.cpp Weather/*.h)
523
 file(GLOB_RECURSE sources_World World/*.cpp World/*.h)
524
+file(GLOB_RECURSE sources_Cfbg Cfbg/*.cpp Cfbg/*.h)
525
 
526
 # Create game-libary
527
 
528
@@ -100,6 +101,7 @@ set(game_STAT_SRCS
529
   ${sources_Warden}
530
   ${sources_Weather}
531
   ${sources_World}
532
+  ${sources_Cfbg}
533
 )
534
 
535
 include_directories(
536
diff --git a/src/server/game/Cfbg/Cfbg.cpp b/src/server/game/Cfbg/Cfbg.cpp
537
new file mode 100644
538
index 0000000..6f06e5d
539
--- /dev/null
540
+++ b/src/server/game/Cfbg/Cfbg.cpp
541
@@ -0,0 +1,326 @@
542
+#include "Cfbg.h"
543
+#include "Battleground.h"
544
+#include "BattlegroundMgr.h"
545
+#include "Player.h"
546
+#include "Chat.h"
547
+#include "BattlegroundQueue.h"
548
+
549
+/*####################################################################################
550
+###############################CROSSFACTION BATTLEGROUNDS#############################
551
+####################################################################################*/
552
+
553
+uint8 Unit::getRace(bool forceoriginal) const
554
+{
555
+    if (GetTypeId() == TYPEID_PLAYER)
556
+    {
557
+        Player* pPlayer = ((Player*)this);
558
+
559
+        if (forceoriginal)
560
+            return pPlayer->getORace();
561
+
562
+        if (pPlayer->InArena())
563
+            return GetByteValue(UNIT_FIELD_BYTES_0, 0);
564
+
565
+        if (!pPlayer->IsPlayingNative())
566
+            return pPlayer->getFRace();
567
+    }
568
+
569
+    return GetByteValue(UNIT_FIELD_BYTES_0, 0);
570
+}
571
+
572
+bool Player::SendRealNameQuery()
573
+{
574
+    if (IsPlayingNative())
575
+        return false;
576
+
577
+    WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8 + 1 + 1 + 1 + 1 + 1 + 10));
578
+    data.appendPackGUID(GetGUID());                             // player guid
579
+    data << uint8(0);                                       // added in 3.1; if > 1, then end of packet
580
+    data << GetName();                                   // played name
581
+    data << uint8(0);                                       // realm name for cross realm BG usage
582
+    data << uint8(getORace());
583
+    data << uint8(getGender());
584
+    data << uint8(getClass());
585
+    data << uint8(0);                                   // is not declined
586
+    GetSession()->SendPacket(&data);
587
+
588
+    return true;
589
+}
590
+
591
+void Player::SetFakeRaceAndMorph()
592
+{
593
+m_FakeRace = GetOTeam() == ALLIANCE ? RACE_BLOODELF : RACE_HUMAN;
594
+}
595
+
596
+bool Player::SendBattleGroundChat(uint32 msgtype, std::string message)
597
+{
598
+    // Select distance to broadcast to.
599
+    float distance = msgtype == CHAT_MSG_SAY ? sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY) : sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL);
600
+
601
+    if (Battleground* pBattleGround = GetBattleground())
602
+    {
603
+        if (pBattleGround->isArena()) // Only fake chat in BG's. CFBG should not interfere with arenas.
604
+            return false;
605
+
606
+        for (Battleground::BattlegroundPlayerMap::const_iterator itr = pBattleGround->GetPlayers().begin(); itr != pBattleGround->GetPlayers().end(); ++itr)
607
+        {
608
+            if (Player* pPlayer = ObjectAccessor::FindPlayer(itr->first))
609
+            {
610
+                if (GetDistance2d(pPlayer->GetPositionX(), pPlayer->GetPositionY()) <= distance)
611
+                {
612
+                    WorldPacket data(SMSG_MESSAGECHAT, 200);
613
+
614
+                    if (GetTeam() == pPlayer->GetTeam())
615
+                        BuildPlayerChat(&data, msgtype, message, LANG_UNIVERSAL);
616
+                    else if (msgtype != CHAT_MSG_EMOTE)
617
+                       BuildPlayerChat(&data, msgtype, message, pPlayer->GetTeam() == ALLIANCE ? LANG_ORCISH : LANG_COMMON);
618
+
619
+                    pPlayer->GetSession()->SendPacket(&data);
620
+                }
621
+            }
622
+        }
623
+        return true;
624
+    }
625
+    else
626
+        return false;
627
+}
628
+
629
+void Player::MorphFit(bool value)
630
+{
631
+    if (!IsPlayingNative() && value)
632
+    {
633
+        if (GetOTeam() == HORDE)
634
+        {
635
+            if (getGender() == GENDER_MALE)
636
+            {
637
+                SetDisplayId(19723);
638
+                SetNativeDisplayId(19723);
639
+            }
640
+            else
641
+            {
642
+                SetDisplayId(19724);
643
+                SetNativeDisplayId(19724);
644
+            }
645
+        }
646
+        else
647
+        {
648
+            if (getGender() == GENDER_MALE)
649
+            {
650
+                SetDisplayId(20578);
651
+                SetNativeDisplayId(20578);
652
+            }
653
+            else
654
+            {
655
+                SetDisplayId(20579);
656
+                SetNativeDisplayId(20579);
657
+            }
658
+        }
659
+    }
660
+    else
661
+        InitDisplayIds();
662
+}
663
+
664
+void Player::FitPlayerInTeam(bool action, Battleground* pBattleGround)
665
+{
666
+    if (!pBattleGround)
667
+        pBattleGround = GetBattleground();
668
+
669
+    if ((!pBattleGround || pBattleGround->isArena()) && action)
670
+        return;
671
+
672
+    if(!IsPlayingNative() && action)
673
+        setFactionForRace(getRace());
674
+    else
675
+        setFactionForRace(getORace());
676
+
677
+    if (action)
678
+        SetForgetBGPlayers(true);
679
+    else
680
+        SetForgetInListPlayers(true);
681
+
682
+    MorphFit(action);
683
+
684
+    if (pBattleGround && action)
685
+        SendChatMessage("%sYou are playing for the %s%s in this %s", MSG_COLOR_WHITE, GetTeam() == ALLIANCE ? MSG_COLOR_DARKBLUE"alliance" : MSG_COLOR_RED"horde", MSG_COLOR_WHITE, pBattleGround->GetName().c_str());
686
+}
687
+
688
+void Player::DoForgetPlayersInList()
689
+{
690
+    // m_FakePlayers is filled from a vector within the battleground
691
+    // they were in previously so all players that have been in that BG will be invalidated.
692
+    for (FakePlayers::const_iterator itr = m_FakePlayers.begin(); itr != m_FakePlayers.end(); ++itr)
693
+    {
694
+        WorldPacket data(SMSG_INVALIDATE_PLAYER, 8);
695
+        data << *itr;
696
+        GetSession()->SendPacket(&data);
697
+        ObjectGuid guid(*itr);
698
+        if (Player* pPlayer = ObjectAccessor::FindPlayer(guid))
699
+            GetSession()->SendNameQueryOpcode(pPlayer->GetGUID());
700
+    }
701
+    m_FakePlayers.clear();
702
+}
703
+
704
+void Player::DoForgetPlayersInBG(Battleground* pBattleGround)
705
+{
706
+    for (Battleground::BattlegroundPlayerMap::const_iterator itr = pBattleGround->GetPlayers().begin(); itr != pBattleGround->GetPlayers().end(); ++itr)
707
+    {
708
+        // Here we invalidate players in the bg to the added player
709
+        WorldPacket data1(SMSG_INVALIDATE_PLAYER, 8);
710
+        data1 << itr->first;
711
+        GetSession()->SendPacket(&data1);
712
+
713
+        if (Player* pPlayer = ObjectAccessor::FindPlayer(itr->first))
714
+        {
715
+            GetSession()->SendNameQueryOpcode(pPlayer->GetGUID()); // Send namequery answer instantly if player is available
716
+            // Here we invalidate the player added to players in the bg
717
+            WorldPacket data2(SMSG_INVALIDATE_PLAYER, 8);
718
+            data2 << GetGUID();
719
+            pPlayer->GetSession()->SendPacket(&data2);
720
+            pPlayer->GetSession()->SendNameQueryOpcode(GetGUID());
721
+        }
722
+    }
723
+}
724
+
725
+bool BattlegroundQueue::CheckCrossFactionMatch(BattlegroundBracketId bracket_id, Battleground* bg)
726
+{
727
+    if (!sWorld->getBoolConfig(BATTLEGROUND_CROSSFACTION_ENABLED) || bg->isArena())
728
+        return false; // Only do this if crossbg's are enabled.
729
+
730
+    // Here we will add all players to selectionpool, later we check if there are enough and launch a bg.
731
+    FillXPlayersToBG(bracket_id, bg, true);
732
+
733
+    if (sBattlegroundMgr->isTesting() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
734
+        return true;
735
+
736
+    uint8 MPT = bg->GetMinPlayersPerTeam();
737
+    if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() < MPT || m_SelectionPools[TEAM_HORDE].GetPlayerCount() < MPT)
738
+        return false;
739
+
740
+    return true;
741
+}
742
+
743
+// This function will invite players in the least populated faction, which makes battleground queues much faster.
744
+// This function will return true if cross faction battlegrounds are enabled, otherwise return false,
745
+// which is useful in FillPlayersToBG. Because then we can interrupt the regular invitation if cross faction bg's are enabled.
746
+bool BattlegroundQueue::FillXPlayersToBG(BattlegroundBracketId bracket_id, Battleground* bg, bool start)
747
+{
748
+    uint8 queuedPeople = 0;
749
+    for (GroupsQueueType::const_iterator itr = m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].end(); ++itr)
750
+        if (!(*itr)->IsInvitedToBGInstanceGUID)
751
+            queuedPeople += (*itr)->Players.size();
752
+
753
+    if (sWorld->getBoolConfig(BATTLEGROUND_CROSSFACTION_ENABLED) && (sBattlegroundMgr->isTesting() || queuedPeople >= bg->GetMinPlayersPerTeam()*2 || !start))
754
+    {
755
+        int32 aliFree   = start ? bg->GetMaxPlayersPerTeam() : bg->GetFreeSlotsForTeam(ALLIANCE);
756
+        int32 hordeFree = start ? bg->GetMaxPlayersPerTeam() : bg->GetFreeSlotsForTeam(HORDE);
757
+        // Empty selection pools. They will be refilled from queued groups.
758
+        m_SelectionPools[TEAM_ALLIANCE].Init();
759
+        m_SelectionPools[TEAM_HORDE].Init();
760
+        int32 valiFree = aliFree;
761
+        int32 vhordeFree = hordeFree;
762
+        int32 diff = 0;
763
+
764
+
765
+        // Add teams to their own factions as far as possible.
766
+        if (start)
767
+        {
768
+            QueuedGroupMap m_PreGroupMap_a, m_PreGroupMap_h;
769
+            int32 m_SmallestOfTeams = 0;
770
+            int32 queuedAlliance = 0;
771
+            int32 queuedHorde = 0;
772
+
773
+            for (GroupsQueueType::const_iterator itr = m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].end(); ++itr)
774
+            {
775
+                if ((*itr)->IsInvitedToBGInstanceGUID)
776
+                    continue;
777
+
778
+                bool alliance = (*itr)->OTeam == ALLIANCE;
779
+
780
+                if (alliance)
781
+                {
782
+                    m_PreGroupMap_a.insert(std::make_pair((*itr)->Players.size(), *itr));
783
+                    queuedAlliance += (*itr)->Players.size();
784
+                }
785
+                else
786
+                {
787
+                    m_PreGroupMap_h.insert(std::make_pair((*itr)->Players.size(), *itr));
788
+                    queuedHorde += (*itr)->Players.size();
789
+                }
790
+            }
791
+
792
+            m_SmallestOfTeams = std::min(std::min(aliFree, queuedAlliance), std::min(hordeFree, queuedHorde));
793
+
794
+            valiFree -= PreAddPlayers(m_PreGroupMap_a, m_SmallestOfTeams, aliFree);
795
+            vhordeFree -= PreAddPlayers(m_PreGroupMap_h, m_SmallestOfTeams, hordeFree);
796
+        }
797
+
798
+        QueuedGroupMap m_QueuedGroupMap;
799
+
800
+        for (GroupsQueueType::const_iterator itr = m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_MIXED].end(); ++itr)
801
+            m_QueuedGroupMap.insert(std::make_pair((*itr)->Players.size(), *itr));
802
+
803
+        for (QueuedGroupMap::reverse_iterator itr = m_QueuedGroupMap.rbegin(); itr != m_QueuedGroupMap.rend(); ++itr)
804
+        {
805
+            GroupsQueueType allypool = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups;
806
+            GroupsQueueType hordepool = m_SelectionPools[TEAM_HORDE].SelectedGroups;
807
+
808
+            GroupQueueInfo* ginfo = itr->second;
809
+
810
+            // If player already was invited via pre adding (add to own team first) or he was already invited to a bg, skip.
811
+            if (ginfo->IsInvitedToBGInstanceGUID ||
812
+                std::find(allypool.begin(), allypool.end(), ginfo) != allypool.end() ||
813
+                std::find(hordepool.begin(), hordepool.end(), ginfo) != hordepool.end() ||
814
+                (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= bg->GetMinPlayersPerTeam() &&
815
+                m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= bg->GetMinPlayersPerTeam()))
816
+                continue;
817
+
818
+            diff = abs(valiFree - vhordeFree);
819
+            bool moreAli = valiFree < vhordeFree;
820
+
821
+            if (diff > 0)
822
+                ginfo->Team = moreAli ? HORDE : ALLIANCE;
823
+
824
+            bool alliance = ginfo->Team == ALLIANCE;
825
+
826
+            if (m_SelectionPools[alliance ? TEAM_ALLIANCE : TEAM_HORDE].AddGroup(ginfo, alliance ? aliFree : hordeFree))
827
+                alliance ? valiFree -= ginfo->Players.size() : vhordeFree -= ginfo->Players.size();
828
+        }
829
+
830
+        return true;
831
+    }
832
+    return false;
833
+}
834
+
835
+int32 BattlegroundQueue::PreAddPlayers(QueuedGroupMap m_PreGroupMap, int32 MaxAdd, uint32 MaxInTeam)
836
+{
837
+    int32 LeftToAdd = MaxAdd;
838
+    uint32 Added = 0;
839
+
840
+    for (QueuedGroupMap::reverse_iterator itr = m_PreGroupMap.rbegin(); itr != m_PreGroupMap.rend(); ++itr)
841
+    {
842
+        int32 PlayerSize = itr->first;
843
+        bool alliance = itr->second->OTeam == ALLIANCE;
844
+
845
+        if (PlayerSize <= LeftToAdd && m_SelectionPools[alliance ? TEAM_ALLIANCE : TEAM_HORDE].AddGroup(itr->second, MaxInTeam))
846
+            LeftToAdd -= PlayerSize, Added -= PlayerSize;
847
+    }
848
+
849
+    return LeftToAdd;
850
+}
851
+
852
+void Player::SendChatMessage(const char *format, ...)
853
+{
854
+    if (!IsInWorld())
855
+        return;
856
+
857
+    if (format)
858
+    {
859
+        va_list ap;
860
+        char str [2048];
861
+        va_start(ap, format);
862
+        vsnprintf(str, 2048, format, ap);
863
+        va_end(ap);
864
+
865
+        ChatHandler(GetSession()).SendSysMessage(str);
866
+    }
867
+}
868
diff --git a/src/server/game/Cfbg/Cfbg.h b/src/server/game/Cfbg/Cfbg.h
869
new file mode 100644
870
index 0000000..45567f8
871
--- /dev/null
872
+++ b/src/server/game/Cfbg/Cfbg.h
873
@@ -0,0 +1,35 @@
874
+#ifndef _CUSTOM_H
875
+#define _CUSTOM_H
876
+
877
+#define MSG_COLOR_LIGHTRED     "|cffff6060"
878
+#define MSG_COLOR_LIGHTBLUE    "|cff00ccff"
879
+#define MSG_COLOR_ANN_GREEN    "|c1f40af20"
880
+#define MSG_COLOR_RED          "|cffff0000"
881
+#define MSG_COLOR_GOLD         "|cffffcc00"
882
+#define MSG_COLOR_SUBWHITE     "|cffbbbbbb"
883
+#define MSG_COLOR_MAGENTA      "|cffff00ff"
884
+#define MSG_COLOR_YELLOW       "|cffffff00"
885
+#define MSG_COLOR_CYAN         "|cff00ffff"
886
+#define MSG_COLOR_DARKBLUE     "|cff0000ff"
887
+
888
+#define MSG_COLOR_GREY         "|cff9d9d9d"
889
+#define MSG_COLOR_WHITE        "|cffffffff"
890
+#define MSG_COLOR_GREEN        "|cff1eff00"
891
+#define MSG_COLOR_BLUE         "|cff0080ff"
892
+#define MSG_COLOR_PURPLE       "|cffb048f8"
893
+#define MSG_COLOR_ORANGE       "|cffff8000"
894
+
895
+#define MSG_COLOR_DRUID        "|cffff7d0a"
896
+#define MSG_COLOR_HUNTER       "|cffabd473"
897
+#define MSG_COLOR_MAGE         "|cff69ccf0"
898
+#define MSG_COLOR_PALADIN      "|cfff58cba"
899
+#define MSG_COLOR_PRIEST       "|cffffffff"
900
+#define MSG_COLOR_ROGUE        "|cfffff569"
901
+#define MSG_COLOR_SHAMAN       "|cff0070de"
902
+#define MSG_COLOR_WARLOCK      "|cff9482c9"
903
+#define MSG_COLOR_WARRIOR      "|cffc79c6e"
904
+#define MSG_COLOR_DEATH_KNIGHT "|cffc41f3b"
905
+#define MSG_COLOR_MONK         "|cff00ff96"
906
+
907
+#define LIMIT_UINT32 2147483647
908
+#endif
909
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
910
index f8f569d..afc5e7c 100644
911
--- a/src/server/game/Entities/Player/Player.cpp
912
+++ b/src/server/game/Entities/Player/Player.cpp
913
@@ -659,6 +659,12 @@ void KillRewarder::Reward()
914
 
915
 Player::Player(WorldSession* session): Unit(true)
916
 {
917
+    m_FakeRace = 0;
918
+    m_RealRace = 0;
919
+    m_FakeMorph = 0;
920
+    m_ForgetBGPlayers = false;
921
+    m_ForgetInListPlayers = false;
922
+
923
     m_speakTime = 0;
924
     m_speakCount = 0;
925
 
926
@@ -1012,6 +1018,12 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
927
     uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16);
928
 
929
     SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
930
+
931
+    SetORace();
932
+    m_team = TeamForRace(getORace());
933
+    SetFakeRaceAndMorph(); // m_team must be set before this can be used.
934
+    setFactionForRace(getORace());
935
+
936
     InitDisplayIds();
937
     if (sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP)
938
     {
939
@@ -3041,7 +3053,7 @@ void Player::GiveLevel(uint8 level)
940
         guild->UpdateMemberData(this, GUILD_MEMBER_DATA_LEVEL, level);
941
 
942
     PlayerLevelInfo info;
943
-    sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), level, &info);
944
+    sObjectMgr->GetPlayerLevelInfo(getORace(), getClass(), level, &info);
945
 
946
     PlayerClassLevelInfo classInfo;
947
     sObjectMgr->GetPlayerClassLevelInfo(getClass(), level, &classInfo);
948
@@ -3179,7 +3191,7 @@ void Player::InitStatsForLevel(bool reapplyMods)
949
     sObjectMgr->GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo);
950
 
951
     PlayerLevelInfo info;
952
-    sObjectMgr->GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info);
953
+    sObjectMgr->GetPlayerLevelInfo(getORace(), getClass(), getLevel(), &info);
954
 
955
     SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
956
     SetUInt32Value(PLAYER_NEXT_LEVEL_XP, sObjectMgr->GetXPForLevel(getLevel()));
957
@@ -5233,7 +5245,7 @@ void Player::CreateCorpse()
958
         return;
959
     }
960
 
961
-    _uf = GetUInt32Value(UNIT_FIELD_BYTES_0);
962
+    _uf = getORace();
963
     _pb = GetUInt32Value(PLAYER_BYTES);
964
     _pb2 = GetUInt32Value(PLAYER_BYTES_2);
965
 
966
@@ -6917,10 +6929,10 @@ uint32 Player::TeamForRace(uint8 race)
967
 
968
 void Player::setFactionForRace(uint8 race)
969
 {
970
-    m_team = TeamForRace(race);
971
+    SetBGTeam(TeamForRace(race));
972
 
973
     ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(race);
974
-    setFaction(rEntry ? rEntry->FactionID : 0);
975
+    setFaction(rEntry ? rEntry->FactionID : getFaction());
976
 }
977
 
978
 ReputationRank Player::GetReputationRank(uint32 faction) const
979
@@ -7022,6 +7034,27 @@ void Player::RewardReputation(Unit* victim, float rate)
980
     if (!Rep)
981
         return;
982
 
983
+    uint32 repfaction1 = Rep->RepFaction1;
984
+    uint32 repfaction2 = Rep->RepFaction2;
985
+
986
+    if (!IsPlayingNative())
987
+    {
988
+        if (GetOTeam() == ALLIANCE)
989
+        {
990
+            if (repfaction1 == 729)
991
+                repfaction1 = 730;
992
+            if (repfaction2 == 729)
993
+                repfaction2 = 730;
994
+        }
995
+        else
996
+        {
997
+            if (repfaction1 == 730)
998
+                repfaction1 = 729;
999
+            if (repfaction2 == 730)
1000
+                repfaction2 = 729;
1001
+        }
1002
+    }
1003
+
1004
     uint32 ChampioningFaction = 0;
1005
 
1006
     if (GetChampioningFaction())
1007
@@ -7036,23 +7069,23 @@ void Player::RewardReputation(Unit* victim, float rate)
1008
 
1009
     uint32 team = GetTeam();
1010
 
1011
-    if (Rep->RepFaction1 && (!Rep->TeamDependent || team == ALLIANCE))
1012
+    if (repfaction1 && (!Rep->TeamDependent || team == ALLIANCE))
1013
     {
1014
-        int32 donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue1, ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
1015
+        int32 donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue1, ChampioningFaction ? ChampioningFaction : repfaction1);
1016
         donerep1 = int32(donerep1 * rate);
1017
 
1018
-        FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
1019
+        FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : repfaction1);
1020
         uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1);
1021
         if (factionEntry1 && current_reputation_rank1 <= Rep->ReputationMaxCap1)
1022
             GetReputationMgr().ModifyReputation(factionEntry1, donerep1);
1023
     }
1024
 
1025
-    if (Rep->RepFaction2 && (!Rep->TeamDependent || team == HORDE))
1026
+    if (repfaction2 && (!Rep->TeamDependent || team == HORDE))
1027
     {
1028
-        int32 donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue2, ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
1029
+        int32 donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue2, ChampioningFaction ? ChampioningFaction : repfaction2);
1030
         donerep2 = int32(donerep2 * rate);
1031
 
1032
-        FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
1033
+        FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : repfaction2);
1034
         uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2);
1035
         if (factionEntry2 && current_reputation_rank2 <= Rep->ReputationMaxCap2)
1036
             GetReputationMgr().ModifyReputation(factionEntry2, donerep2);
1037
@@ -7147,7 +7180,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
1038
         if (!victim || victim == this || victim->GetTypeId() != TYPEID_PLAYER)
1039
             return false;
1040
 
1041
-        if (GetBGTeam() == victim->ToPlayer()->GetBGTeam())
1042
+        if (GetTeam() == victim->ToPlayer()->GetTeam())
1043
             return false;
1044
 
1045
         return true;
1046
@@ -7495,7 +7528,7 @@ void Player::UpdateArea(uint32 newArea)
1047
 
1048
     // previously this was in UpdateZone (but after UpdateArea) so nothing will break
1049
     pvpInfo.IsInNoPvPArea = false;
1050
-    if (area && area->IsSanctuary())    // in sanctuary
1051
+    if(area && area->IsSanctuary() || GetAreaId() == 4413)    // in sanctuary
1052
     {
1053
         SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
1054
         pvpInfo.IsInNoPvPArea = true;
1055
@@ -12028,13 +12061,13 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
1056
     if (!proto)
1057
         return EQUIP_ERR_ITEM_NOT_FOUND;
1058
 
1059
-    if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE)
1060
+    if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetOTeam() != HORDE)
1061
         return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
1062
 
1063
-    if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE)
1064
+    if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetOTeam() != ALLIANCE)
1065
         return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
1066
 
1067
-    if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0)
1068
+    if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getORaceMask()) == 0)
1069
         return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
1070
 
1071
     if (proto->RequiredSkill != 0)
1072
@@ -17315,6 +17348,11 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
1073
         return false;
1074
     }
1075
 
1076
+    SetORace();
1077
+    m_team = TeamForRace(getORace());
1078
+    SetFakeRaceAndMorph(); // m_team must be set before this can be used.
1079
+    setFactionForRace(getORace());//Need to call it to initialize m_team (m_team can be calculated from race)
1080
+
1081
     SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
1082
     SetUInt32Value(PLAYER_XP, fields[7].GetUInt32());
1083
 
1084
@@ -17361,10 +17399,6 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
1085
     TC_LOG_DEBUG("entities.player.loading", "Load Basic value of player %s is: ", m_name.c_str());
1086
     outDebugValues();
1087
 
1088
-    //Need to call it to initialize m_team (m_team can be calculated from race)
1089
-    //Other way is to saves m_team into characters table.
1090
-    setFactionForRace(getRace());
1091
-
1092
     // load home bind and check in same time class/race pair, it used later for restore broken positions
1093
     if (!_LoadHomeBind(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_HOME_BIND)))
1094
         return false;
1095
@@ -19285,7 +19319,7 @@ void Player::SaveToDB(bool create /*=false*/)
1096
         stmt->setUInt32(index++, GetGUIDLow());
1097
         stmt->setUInt32(index++, GetSession()->GetAccountId());
1098
         stmt->setString(index++, GetName());
1099
-        stmt->setUInt8(index++, getRace());
1100
+        stmt->setUInt8(index++, getORace());
1101
         stmt->setUInt8(index++, getClass());
1102
         stmt->setUInt8(index++, getGender());
1103
         stmt->setUInt8(index++, getLevel());
1104
@@ -19390,7 +19424,7 @@ void Player::SaveToDB(bool create /*=false*/)
1105
         // Update query
1106
         stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER);
1107
         stmt->setString(index++, GetName());
1108
-        stmt->setUInt8(index++, getRace());
1109
+        stmt->setUInt8(index++, getORace());
1110
         stmt->setUInt8(index++, getClass());
1111
         stmt->setUInt8(index++, getGender());
1112
         stmt->setUInt8(index++, getLevel());
1113
@@ -20629,6 +20663,18 @@ void Player::StopCastingCharm()
1114
     }
1115
 }
1116
 
1117
+void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const
1118
+{
1119
+    *data << uint8(msgtype);
1120
+    *data << uint32(language);
1121
+    *data << uint64(GetGUID());
1122
+    *data << uint32(0);                                      // constant unknown time
1123
+    *data << uint64(GetGUID());
1124
+    *data << uint32(text.length() + 1);
1125
+    *data << text;
1126
+    *data << uint8(GetChatTag());
1127
+}
1128
+
1129
 void Player::Say(std::string const& text, Language language, WorldObject const* /*= nullptr*/)
1130
 {
1131
     std::string _text(text);
1132
@@ -22435,11 +22481,6 @@ void Player::SetBGTeam(uint32 team)
1133
     SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? 1 : 0));
1134
 }
1135
 
1136
-uint32 Player::GetBGTeam() const
1137
-{
1138
-    return m_bgData.bgTeam ? m_bgData.bgTeam : GetTeam();
1139
-}
1140
-
1141
 void Player::LeaveBattleground(bool teleportToEntryPoint)
1142
 {
1143
     if (Battleground* bg = GetBattleground())
1144
@@ -22515,7 +22556,7 @@ void Player::ReportedAfkBy(Player* reporter)
1145
 
1146
 WorldLocation Player::GetStartPosition() const
1147
 {
1148
-    PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
1149
+    PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getORace(), getClass());
1150
     uint32 mapId = info->mapId;
1151
     if (getClass() == CLASS_DEATH_KNIGHT && HasSpell(50977))
1152
         mapId = 0;
1153
@@ -23215,7 +23256,7 @@ void Player::LearnCustomSpells()
1154
 void Player::LearnDefaultSkills()
1155
 {
1156
     // learn default race/class skills
1157
-    PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
1158
+    PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(true), getClass());
1159
     for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr)
1160
     {
1161
         uint32 skillId = itr->SkillId;
1162
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
1163
index 8ed561b..ade04b5 100644
1164
--- a/src/server/game/Entities/Player/Player.h
1165
+++ b/src/server/game/Entities/Player/Player.h
1166
@@ -1098,6 +1098,35 @@ class Player : public Unit, public GridObject<Player>
1167
     public:
1168
         explicit Player(WorldSession* session);
1169
         ~Player();
1170
+        private:
1171
+        bool m_ForgetBGPlayers;
1172
+        bool m_ForgetInListPlayers;
1173
+        uint8 m_FakeRace;
1174
+        uint8 m_RealRace;
1175
+        uint32 m_FakeMorph;
1176
+    public:
1177
+        typedef std::vector<uint64> FakePlayers;
1178
+        void SendChatMessage(const char *format, ...);
1179
+        void FitPlayerInTeam(bool action, Battleground* pBattleGround = NULL);
1180
+        void DoForgetPlayersInList();
1181
+        void DoForgetPlayersInBG(Battleground* pBattleGround);
1182
+        uint8 getORace() const { return m_RealRace; }
1183
+        void SetORace() { m_RealRace = GetByteValue(UNIT_FIELD_BYTES_0, 0); }; // SHOULD ONLY BE CALLED ON LOGIN
1184
+        void SetFakeRace(); // SHOULD ONLY BE CALLED ON LOGIN
1185
+        void SetFakeRaceAndMorph(); // SHOULD ONLY BE CALLED ON LOGIN
1186
+        uint32 GetFakeMorph() { return m_FakeMorph; };
1187
+        uint8 getFRace() const { return m_FakeRace; }
1188
+        void SetForgetBGPlayers(bool value) { m_ForgetBGPlayers = value; }
1189
+        bool ShouldForgetBGPlayers() { return m_ForgetBGPlayers; }
1190
+        void SetForgetInListPlayers(bool value) { m_ForgetInListPlayers = value; }
1191
+        bool ShouldForgetInListPlayers() { return m_ForgetInListPlayers; }
1192
+        bool SendBattleGroundChat(uint32 msgtype, std::string message);
1193
+        void MorphFit(bool value);
1194
+        bool IsPlayingNative() const { return GetTeam() == m_team; }
1195
+        uint32 GetOTeam() const { return m_team; }
1196
+        uint32 GetTeam() const { return m_bgData.bgTeam && GetBattleground() ? m_bgData.bgTeam : m_team; }
1197
+        bool SendRealNameQuery();
1198
+        FakePlayers m_FakePlayers;
1199
 
1200
         void CleanupsBeforeDelete(bool finalCleanup = true) override;
1201
 
1202
@@ -1152,7 +1181,7 @@ class Player : public Unit, public GridObject<Player>
1203
         PlayerSocial *GetSocial() { return m_social; }
1204
 
1205
         PlayerTaxi m_taxi;
1206
-        void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
1207
+        void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getORace(), getClass(), getLevel()); }
1208
         bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = NULL, uint32 spellid = 0);
1209
         bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0);
1210
         void CleanupAfterTaxiFlight();
1211
@@ -1220,6 +1249,8 @@ class Player : public Unit, public GridObject<Player>
1212
         void TextEmote(std::string const& text, WorldObject const* = nullptr, bool = false) override;
1213
         /// Handles whispers from Addons and players based on sender, receiver's guid and language.
1214
         void Whisper(std::string const& text, Language language, Player* receiver, bool = false) override;
1215
+        /// Constructs the player Chat data for the specific functions to use
1216
+        void BuildPlayerChat(WorldPacket* data, uint8 msgtype, std::string const& text, uint32 language) const;
1217
 
1218
         /*********************************************************/
1219
         /***                    STORAGE SYSTEM                 ***/
1220
@@ -1929,8 +1960,7 @@ class Player : public Unit, public GridObject<Player>
1221
         void CheckAreaExploreAndOutdoor(void);
1222
 
1223
         static uint32 TeamForRace(uint8 race);
1224
-        uint32 GetTeam() const { return m_team; }
1225
-        TeamId GetTeamId() const { return m_team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE; }
1226
+        TeamId GetTeamId() const { return GetTeam() == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE; }
1227
         void setFactionForRace(uint8 race);
1228
 
1229
         void InitDisplayIds();
1230
@@ -2075,7 +2105,6 @@ class Player : public Unit, public GridObject<Player>
1231
         void SetBattlegroundEntryPoint();
1232
 
1233
         void SetBGTeam(uint32 team);
1234
-        uint32 GetBGTeam() const;
1235
 
1236
         void LeaveBattleground(bool teleportToEntryPoint = true);
1237
         bool CanJoinToBattleground(Battleground const* bg) const;
1238
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
1239
index a3b8adf..d94c2c2 100644
1240
--- a/src/server/game/Entities/Unit/Unit.cpp
1241
+++ b/src/server/game/Entities/Unit/Unit.cpp
1242
@@ -16000,7 +16000,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
1243
 void Unit::RestoreFaction()
1244
 {
1245
     if (GetTypeId() == TYPEID_PLAYER)
1246
-        ToPlayer()->setFactionForRace(getRace());
1247
+        ToPlayer()->setFactionForRace(ToPlayer()->getRace());
1248
     else
1249
     {
1250
         if (HasUnitTypeMask(UNIT_MASK_MINION))
1251
@@ -16751,6 +16751,21 @@ uint32 Unit::GetModelForTotem(PlayerTotemType totemType)
1252
             }
1253
             break;
1254
         }
1255
+        default: // One standard for other races.
1256
+        {        // THANKS L30m4nc3r for this
1257
+            switch (totemType)
1258
+            {
1259
+                case SUMMON_TYPE_TOTEM_FIRE:    // fire
1260
+                    return 4589;
1261
+                case SUMMON_TYPE_TOTEM_EARTH:   // earth
1262
+                    return 4588;
1263
+                case SUMMON_TYPE_TOTEM_WATER:   // water
1264
+                    return 4587;
1265
+                case SUMMON_TYPE_TOTEM_AIR:     // air
1266
+                    return 4590;
1267
+            }
1268
+            break;
1269
+        }
1270
     }
1271
     return 0;
1272
 }
1273
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
1274
index 63a984f..f4cdcbc 100644
1275
--- a/src/server/game/Entities/Unit/Unit.h
1276
+++ b/src/server/game/Entities/Unit/Unit.h
1277
@@ -1356,8 +1356,10 @@ class Unit : public WorldObject
1278
         uint8 getLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); }
1279
         uint8 getLevelForTarget(WorldObject const* /*target*/) const override { return getLevel(); }
1280
         void SetLevel(uint8 lvl);
1281
-        uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); }
1282
+        uint8 getRace(bool forceoriginal = false) const;
1283
+        uint8 getORace() { return getRace(true); }
1284
         uint32 getRaceMask() const { return 1 << (getRace()-1); }
1285
+        uint32 getORaceMask() const { return 1 << (getRace(true) - 1); }
1286
         uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
1287
         uint32 getClassMask() const { return 1 << (getClass()-1); }
1288
         uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
1289
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
1290
index ce8ae92..e822f3a 100644
1291
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
1292
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
1293
@@ -41,7 +41,7 @@
1294
 // 04
1295
 // 05
1296
 // 06
1297
-// 07
1298
+#include "Cfbg/Cfbg.h"
1299
 // 08
1300
 // 09
1301
 // 10
1302
@@ -566,7 +566,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/)
1303
             {
1304
                 // this line is checked, i only don't know if GetStartTime is changing itself after bg end!
1305
                 // send status in Battleground
1306
-                sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetBGTeam());
1307
+                sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetTeam());
1308
                 SendPacket(&data);
1309
                 continue;
1310
             }
1311
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
1312
index 56f4216..da9f28d 100644
1313
--- a/src/server/game/Handlers/CharacterHandler.cpp
1314
+++ b/src/server/game/Handlers/CharacterHandler.cpp
1315
@@ -1066,6 +1066,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
1316
     //
1317
     // End of prepatch
1318
     delete holder;
1319
+
1320
+    if (pCurrChar->GetTeam() != pCurrChar->GetOTeam())
1321
+        pCurrChar->FitPlayerInTeam(pCurrChar->GetBattleground() && !pCurrChar->GetBattleground()->isArena() ? true : false, pCurrChar->GetBattleground());
1322
 }
1323
1324
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
1325
index b33f236..e931e92 100644
1326
--- a/src/server/game/Handlers/ChatHandler.cpp
1327
+++ b/src/server/game/Handlers/ChatHandler.cpp
1328
@@ -48,6 +48,18 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
1329
     recvData >> type;
1330
     recvData >> lang;
1331
 
1332
+    if (sWorld->getBoolConfig(BATTLEGROUND_CROSSFACTION_ENABLED) && lang != LANG_ADDON)
1333
+    {
1334
+        switch (type)
1335
+        {
1336
+        case CHAT_MSG_BATTLEGROUND:
1337
+        case CHAT_MSG_BATTLEGROUND_LEADER:
1338
+            lang = LANG_UNIVERSAL;
1339
+        default:
1340
+            break;
1341
+        }
1342
+    }
1343
+
1344
     if (type >= MAX_CHAT_MSG_TYPE)
1345
     {
1346
         TC_LOG_ERROR("network", "CHAT: Wrong message type received: %u", type);
1347
@@ -55,7 +67,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
1348
         return;
1349
     }
1350
 
1351
-    if (lang == LANG_UNIVERSAL && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
1352
+    if (lang == CHAT_MSG_AFK && type != CHAT_MSG_DND)
1353
     {
1354
         TC_LOG_ERROR("network", "CMSG_MESSAGECHAT: Possible hacking-attempt: %s tried to send a message in universal language", GetPlayerInfo().c_str());
1355
         SendNotification(LANG_UNKNOWN_LANGUAGE);
1356
@@ -253,6 +265,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
1357
                 return;
1358
             }
1359
 
1360
+            if (!GetPlayer()->IsGameMaster())
1361
+                if (GetPlayer()->SendBattleGroundChat(type, msg))
1362
+                    return;
1363
+
1364
             if (type == CHAT_MSG_SAY)
1365
                 sender->Say(msg, Language(lang));
1366
             else if (type == CHAT_MSG_EMOTE)
1367
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
1368
index bede3b4..2d0af0f 100644
1369
--- a/src/server/game/Handlers/MiscHandler.cpp
1370
+++ b/src/server/game/Handlers/MiscHandler.cpp
1371
@@ -1428,6 +1428,21 @@ void WorldSession::HandleSetTitleOpcode(WorldPacket& recvData)
1372
 
1373
 void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
1374
 {
1375
+    Battleground* bg = _player->GetBattleground();
1376
+    if (bg)
1377
+    {
1378
+        if (_player->ShouldForgetBGPlayers() && bg)
1379
+        {
1380
+            _player->DoForgetPlayersInBG(bg);
1381
+            _player->SetForgetBGPlayers(false);
1382
+        }
1383
+    }
1384
+    else if (_player->ShouldForgetInListPlayers())
1385
+    {
1386
+        _player->DoForgetPlayersInList();
1387
+        _player->SetForgetInListPlayers(false);
1388
+    }
1389
+
1390
     TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESP");
1391
 
1392
     uint32 counter, clientTicks;
1393
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
1394
index 661ecf4..fd9f356 100644
1395
--- a/src/server/game/Handlers/QueryHandler.cpp
1396
+++ b/src/server/game/Handlers/QueryHandler.cpp
1397
@@ -48,7 +48,7 @@ void WorldSession::SendNameQueryOpcode(ObjectGuid guid)
1398
     data << uint8(0);                               // name known
1399
     data << nameData->m_name;                       // played name
1400
     data << uint8(0);                               // realm name - only set for cross realm interaction (such as Battlegrounds)
1401
-    data << uint8(nameData->m_race);
1402
+    data << uint8(player ? player->getRace() : nameData->m_race);
1403
     data << uint8(nameData->m_gender);
1404
     data << uint8(nameData->m_class);
1405
 
1406
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
1407
index e1bd35b..984ce3e 100644
1408
--- a/src/server/game/World/World.cpp
1409
+++ b/src/server/game/World/World.cpp
1410
@@ -1046,6 +1046,8 @@ void World::LoadConfigSettings(bool reload)
1411
 
1412
     m_int_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfigMgr->GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE);
1413
 
1414
+    m_bool_configs[BATTLEGROUND_CROSSFACTION_ENABLED]                = sConfigMgr->GetBoolDefault("CrossfactionBG.enable", true);
1415
+
1416
     if (int32 clientCacheId = sConfigMgr->GetIntDefault("ClientCacheVersion", 0))
1417
     {
1418
         // overwrite DB/old value
1419
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
1420
index 05d0fcc..a667dca 100644
1421
--- a/src/server/game/World/World.h
1422
+++ b/src/server/game/World/World.h
1423
@@ -86,6 +86,7 @@ enum WorldTimers
1424
 enum WorldBoolConfigs
1425
 {
1426
     CONFIG_DURABILITY_LOSS_IN_PVP = 0,
1427
+    BATTLEGROUND_CROSSFACTION_ENABLED,
1428
     CONFIG_ADDON_CHANNEL,
1429
     CONFIG_ALLOW_PLAYER_COMMANDS,
1430
     CONFIG_CLEAN_CHARACTER_DB,
1431
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
1432
index 2c516ca..c2ebd16 100644
1433
--- a/src/server/worldserver/worldserver.conf.dist
1434
+++ b/src/server/worldserver/worldserver.conf.dist
1435
@@ -3231,6 +3231,18 @@ PacketSpoof.BanDuration = 86400
1436
 #
1437
 ###################################################################################################
1438
 
1439
+###################################################################################################
1440
+#
1441
+# CROSSFACTION BG CONFIG
1442
+#
1443
+#    CrossfactionBG.enable = 1 - Mixed battleground enabled.
1444
+#    CrossfactionBG.enable = 0 - Mixed battleground disabled.
1445
+
1446
+CrossfactionBG.enable = 1
1447
+
1448
+#
1449
+###################################################################################################