Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Battlefield.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battlefield.h"
7#include "BattlefieldMgr.h"
8#include "CellImpl.h"
9#include "CreatureTextMgr.h"
10#include "GridNotifiers.h"
11#include "GridNotifiers.h"
12#include "GridNotifiersImpl.h"
13#include "GridNotifiersImpl.h"
14#include "Group.h"
15#include "GroupMgr.h"
16#include "Map.h"
17#include "MapManager.h"
18#include "ObjectAccessor.h"
19#include "ObjectMgr.h"
20#include "WorldPacket.h"
21
23{
24 for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
25 delete itr->second;
26
27 for (GraveyardVect::const_iterator itr = m_GraveyardList.begin(); itr != m_GraveyardList.end(); ++itr)
28 delete* itr;
29}
30
31// Called when a player enters the zone
33{
34 // If battle is started,
35 // If not full of players > invite player to join the war
36 // If full of players > announce to player that BF is full and kick him after a few second if he desn't leave
37 if (IsWarTime())
38 {
39 if (m_PlayersInWar[player->GetTeamId()].size() + m_InvitedPlayers[player->GetTeamId()].size() < m_MaxPlayer) // Vacant spaces
40 InvitePlayerToWar(player);
41 else // No more vacant places
42 {
44 m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
45 InvitePlayerToQueue(player);
46 }
47 }
48 else
49 {
50 // If time left is < 15 minutes invite player to join queue
52 InvitePlayerToQueue(player);
53 }
54
55 // Add player in the list of player in zone
56 m_players[player->GetTeamId()].insert(player->GetGUID());
57 OnPlayerEnterZone(player);
58}
59
60// Called when a player leave the zone
62{
63 if (IsWarTime())
64 {
65 // If the player is participating to the battle
66 if (m_PlayersInWar[player->GetTeamId()].find(player->GetGUID()) != m_PlayersInWar[player->GetTeamId()].end())
67 {
68 m_PlayersInWar[player->GetTeamId()].erase(player->GetGUID());
70 if (Group* group = player->GetGroup()) // Remove the player from the raid group
71 group->RemoveMember(player->GetGUID());
72
73 OnPlayerLeaveWar(player);
74 }
75 }
76
77 for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
78 itr->second->HandlePlayerLeave(player);
79
80 m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
81 m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
82 m_players[player->GetTeamId()].erase(player->GetGUID());
85 OnPlayerLeaveZone(player);
86}
87
89{
90 if (m_Timer <= diff)
91 {
92 // Battlefield ends on time
93 if (IsWarTime())
94 EndBattle(true);
95 else // Time to start a new battle!
97 }
98 else
99 m_Timer -= diff;
100
101 // Invite players a few minutes before the battle's beginning
103 {
104 m_StartGrouping = true;
107 }
108
109 bool objective_changed = false;
110 if (IsWarTime())
111 {
112 if (m_uiKickAfkPlayersTimer <= diff)
113 {
116 }
117 else
119
120 // Kick players who chose not to accept invitation to the battle
121 if (m_uiKickDontAcceptTimer <= diff)
122 {
123 time_t now = time(NULL);
124 for (int team = 0; team < 2; team++)
125 for (PlayerTimerMap::iterator itr = m_InvitedPlayers[team].begin(); itr != m_InvitedPlayers[team].end(); ++itr)
126 if (itr->second <= now)
127 KickPlayerFromBattlefield(itr->first);
128
130 for (int team = 0; team < 2; team++)
131 for (PlayerTimerMap::iterator itr = m_PlayersWillBeKick[team].begin(); itr != m_PlayersWillBeKick[team].end(); ++itr)
132 if (itr->second <= now)
133 KickPlayerFromBattlefield(itr->first);
134
136 }
137 else
139
140 for (BfCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
141 if (itr->second->Update(diff))
142 objective_changed = true;
143 }
144
145
146 if (m_LastResurectTimer <= diff)
147 {
148 for (uint8 i = 0; i < m_GraveyardList.size(); i++)
149 if (GetGraveyardById(i))
150 m_GraveyardList[i]->Resurrect();
152 }
153 else
154 m_LastResurectTimer -= diff;
155
156 return objective_changed;
157}
158
160{
161 for (uint8 team = 0; team < 2; ++team)
162 for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
163 if (Player* player = sObjectAccessor->FindPlayer(*itr))
164 InvitePlayerToQueue(player);
165}
166
168{
169 if (m_PlayersInQueue[player->GetTeamId()].count(player->GetGUID()))
170 return;
171
172 if (m_PlayersInQueue[player->GetTeamId()].size() <= m_MinPlayer || m_PlayersInQueue[GetOtherTeam(player->GetTeamId())].size() >= m_MinPlayer)
174}
175
177{
178 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
179 {
180 for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr)
181 {
182 if (Player* player = sObjectAccessor->FindPlayer(*itr))
183 {
184 if (m_PlayersInWar[player->GetTeamId()].size() + m_InvitedPlayers[player->GetTeamId()].size() < m_MaxPlayer)
185 InvitePlayerToWar(player);
186 else
187 {
188 //Full
189 }
190 }
191 }
192 m_PlayersInQueue[team].clear();
193 }
194}
195
197{
198 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
199 for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
200 {
201 if (Player* player = sObjectAccessor->FindPlayer(*itr))
202 {
203 if (m_PlayersInWar[player->GetTeamId()].count(player->GetGUID()) || m_InvitedPlayers[player->GetTeamId()].count(player->GetGUID()))
204 continue;
205 if (m_PlayersInWar[player->GetTeamId()].size() + m_InvitedPlayers[player->GetTeamId()].size() < m_MaxPlayer)
206 InvitePlayerToWar(player);
207 else // Battlefield is full of players
208 m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
209 }
210 }
211}
212
214{
215 if (!player)
216 return;
217
219 if (player->IsInFlight())
220 return;
221
222 if (player->InArena() || player->GetBattleground())
223 {
224 m_PlayersInQueue[player->GetTeamId()].erase(player->GetGUID());
225 return;
226 }
227
228 // If the player does not match minimal level requirements for the battlefield, kick him
229 if (player->getLevel() < m_MinLevel)
230 {
231 if (m_PlayersWillBeKick[player->GetTeamId()].count(player->GetGUID()) == 0)
232 m_PlayersWillBeKick[player->GetTeamId()][player->GetGUID()] = time(NULL) + 10;
233 return;
234 }
235
236 // Check if player is not already in war
237 if (m_PlayersInWar[player->GetTeamId()].count(player->GetGUID()) || m_InvitedPlayers[player->GetTeamId()].count(player->GetGUID()))
238 return;
239
240 m_PlayersWillBeKick[player->GetTeamId()].erase(player->GetGUID());
241 m_InvitedPlayers[player->GetTeamId()][player->GetGUID()] = time(NULL) + m_TimeForAcceptInvite;
243}
244
245void Battlefield::InitStalker(uint32 entry, float x, float y, float z, float o)
246{
247 if (Creature* creature = SpawnCreature(entry, x, y, z, o, TEAM_NEUTRAL))
248 StalkerGuid = creature->GetGUID();
249 else
250 SF_LOG_ERROR("bg.battlefield", "Battlefield::InitStalker: could not spawn Stalker (Creature entry %u), zone messeges will be un-available", entry);
251}
252
254{
255 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
256 for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
257 if (Player* player = sObjectAccessor->FindPlayer(*itr))
258 if (player->isAFK())
260}
261
263{
264 if (Player* player = sObjectAccessor->FindPlayer(guid))
265 if (player->GetZoneId() == GetZoneId())
266 player->TeleportTo(KickPosition);
267}
268
270{
271 if (m_isActive)
272 return;
273
274 for (int team = 0; team < BG_TEAMS_COUNT; team++)
275 {
276 m_PlayersInWar[team].clear();
277 m_Groups[team].clear();
278 }
279
281 m_isActive = true;
282
285
287
289}
290
291void Battlefield::EndBattle(bool endByTimer)
292{
293 if (!m_isActive)
294 return;
295
296 m_isActive = false;
297
298 m_StartGrouping = false;
299
300 if (!endByTimer)
302
305 else
307
308 OnBattleEnd(endByTimer);
309
310 // Reset battlefield timer
313}
314
316{
317 WorldPacket data(SMSG_PLAY_SOUND, 4 + 9);
318 data.WriteBits(0, 8);
319 data << uint32(SoundID);
320
321 for (int team = 0; team < BG_TEAMS_COUNT; team++)
322 for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
323 if (Player* player = sObjectAccessor->FindPlayer(*itr))
324 player->GetSession()->SendPacket(&data);
325}
326
328{
329 return m_players[player->GetTeamId()].find(player->GetGUID()) != m_players[player->GetTeamId()].end();
330}
331
332// Called in WorldSession::HandleBfQueueInviteResponse
334{
335 // Add player in queue
336 m_PlayersInQueue[player->GetTeamId()].insert(player->GetGUID());
337 // Send notification
339}
340
341// Called in WorldSession::HandleBfExitRequest
343{
344 // Remove player from queue
345 m_PlayersInQueue[player->GetTeamId()].erase(player->GetGUID());
346}
347
348// Called in WorldSession::HandleBfEntryInviteResponse
350{
351 if (!IsWarTime())
352 return;
353
355 {
356 player->GetSession()->SendBfEntered(m_Guid);
357 m_PlayersInWar[player->GetTeamId()].insert(player->GetGUID());
358 m_InvitedPlayers[player->GetTeamId()].erase(player->GetGUID());
359
360 if (player->isAFK())
361 player->ToggleAFK();
362
363 OnPlayerJoinWar(player); //for scripting
364 }
365}
366
368{
369 if (spellId > 0)
370 {
371 for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
372 if (Player* player = sObjectAccessor->FindPlayer(*itr))
373 player->CastSpell(player, uint32(spellId), true);
374 }
375 else
376 {
377 for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
378 if (Player* player = sObjectAccessor->FindPlayer(*itr))
379 player->RemoveAuraFromStack(uint32(-spellId));
380 }
381}
382
384{
385 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
386 for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
387 if (Player* player = sObjectAccessor->FindPlayer(*itr))
388 player->GetSession()->SendPacket(&data);
389}
390
392{
393 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
394 for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr)
395 if (Player* player = sObjectAccessor->FindPlayer(*itr))
396 player->GetSession()->SendPacket(&data);
397}
398
400{
401 for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
402 for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
403 if (Player* player = sObjectAccessor->FindPlayer(*itr))
404 player->GetSession()->SendPacket(&data);
405}
406
408{
409 if (Creature* stalker = GetCreature(StalkerGuid))
410 // FIXME: replaced CHAT_TYPE_END with CHAT_MSG_BG_SYSTEM_NEUTRAL to fix compile, it's a guessed change :/
412}
413
415{
416 if (player)
417 if (Creature* stalker = GetCreature(StalkerGuid))
418 sCreatureTextMgr->SendChat(stalker, (uint8)entry, player);
419}
420
422{
423 for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
424 for (GuidSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
425 if (Player* player = sObjectAccessor->FindPlayer(*itr))
426 player->SendUpdateWorldState(field, value);
427}
428
430{
431 sBattlefieldMgr->AddZone(zoneId, this);
432}
433
435{
436 creature->CombatStop();
437 creature->SetReactState(REACT_PASSIVE);
439 creature->SetPhaseMask(2, true);
440 creature->DisappearAndDie();
441 creature->SetVisible(false);
442}
443
444void Battlefield::ShowNpc(Creature* creature, bool aggressive)
445{
446 creature->SetPhaseMask(1, true);
447 creature->SetVisible(true);
449 if (!creature->IsAlive())
450 creature->Respawn(true);
451 if (aggressive)
453 else
454 {
456 creature->SetReactState(REACT_PASSIVE);
457 }
458}
459
460// ****************************************************
461// ******************* Group System *******************
462// ****************************************************
464{
465 for (GuidSet::const_iterator itr = m_Groups[TeamId].begin(); itr != m_Groups[TeamId].end(); ++itr)
466 if (Group* group = sGroupMgr->GetGroupByGUID(*itr))
467 if (!group->IsFull())
468 return group;
469
470 return NULL;
471}
472
474{
475 for (GuidSet::const_iterator itr = m_Groups[TeamId].begin(); itr != m_Groups[TeamId].end(); ++itr)
476 if (Group* group = sGroupMgr->GetGroupByGUID(*itr))
477 if (group->IsMember(guid))
478 return group;
479
480 return NULL;
481}
482
484{
485 if (!player->IsInWorld())
486 return false;
487
488 if (Group* group = player->GetGroup())
489 group->RemoveMember(player->GetGUID());
490
491 Group* group = GetFreeBfRaid(player->GetTeamId());
492 if (!group)
493 {
494 group = new Group;
495 group->SetBattlefieldGroup(this);
496 group->Create(player);
497 sGroupMgr->AddGroup(group);
498 m_Groups[player->GetTeamId()].insert(group->GetGUID());
499 }
500 else if (group->IsMember(player->GetGUID()))
501 {
502 uint8 subgroup = group->GetMemberGroup(player->GetGUID());
503 player->SetBattlegroundOrBattlefieldRaid(group, subgroup);
504 }
505 else
506 group->AddMember(player);
507
508 return true;
509}
510
511//***************End of Group System*******************
512
513//*****************************************************
514//***************Spirit Guide System*******************
515//*****************************************************
516
517//--------------------
518//-Battlefield Method-
519//--------------------
521{
522 if (id < m_GraveyardList.size())
523 {
524 if (BfGraveyard* graveyard = m_GraveyardList.at(id))
525 return graveyard;
526 else
527 SF_LOG_ERROR("bg.battlefield", "Battlefield::GetGraveyardById Id:%u not existed", id);
528 }
529 else
530 SF_LOG_ERROR("bg.battlefield", "Battlefield::GetGraveyardById Id:%u cant be found", id);
531
532 return NULL;
533}
534
536{
537 BfGraveyard* closestGY = NULL;
538 float maxdist = -1;
539 for (uint8 i = 0; i < m_GraveyardList.size(); i++)
540 {
541 if (m_GraveyardList[i])
542 {
543 if (m_GraveyardList[i]->GetControlTeamId() != player->GetTeamId())
544 continue;
545
546 float dist = m_GraveyardList[i]->GetDistance(player);
547 if (dist < maxdist || maxdist < 0)
548 {
549 closestGY = m_GraveyardList[i];
550 maxdist = dist;
551 }
552 }
553 }
554
555 if (closestGY)
556 return sWorldSafeLocsStore.LookupEntry(closestGY->GetGraveyardId());
557
558 return NULL;
559}
560
562{
563 for (uint8 i = 0; i < m_GraveyardList.size(); i++)
564 {
565 if (!m_GraveyardList[i])
566 continue;
567
568 if (m_GraveyardList[i]->HasNpc(npcGuid))
569 {
570 m_GraveyardList[i]->AddPlayer(playerGuid);
571 break;
572 }
573 }
574}
575
577{
578 for (uint8 i = 0; i < m_GraveyardList.size(); i++)
579 {
580 if (!m_GraveyardList[i])
581 continue;
582
583 if (m_GraveyardList[i]->HasPlayer(playerGuid))
584 {
585 m_GraveyardList[i]->RemovePlayer(playerGuid);
586 break;
587 }
588 }
589}
590
592{
593 ObjectGuid Guid = guid;
594 uint32 time = m_LastResurectTimer; // resurrect every 30 seconds
596
597 data.WriteGuidMask(Guid, 5, 2, 7, 6, 1, 0, 3, 4);
598
599 data.WriteGuidBytes(Guid, 2, 3, 5, 4, 6);
600 data << time;
601 data.WriteGuidBytes(Guid, 7, 0, 1);
602
603 ASSERT(player && player->GetSession());
604 player->GetSession()->SendPacket(&data);
605}
606
607// ----------------------
608// - BfGraveyard Method -
609// ----------------------
610
611void BfGraveyard::Initialize(TeamId startControl, uint32 graveyardId)
612{
613 m_ControlTeam = startControl;
614 m_GraveyardId = graveyardId;
615}
616
618{
619 if (!spirit)
620 {
621 SF_LOG_ERROR("bg.battlefield", "BfGraveyard::SetSpirit: Invalid Spirit.");
622 return;
623 }
624
625 m_SpiritGuide[team] = spirit->GetGUID();
627}
628
630{
631 const WorldSafeLocsEntry* safeLoc = sWorldSafeLocsStore.LookupEntry(m_GraveyardId);
632 return player->GetDistance2d(safeLoc->x, safeLoc->y);
633}
634
636{
637 if (!m_ResurrectQueue.count(playerGuid))
638 {
639 m_ResurrectQueue.insert(playerGuid);
640
641 if (Player* player = sObjectAccessor->FindPlayer(playerGuid))
642 player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true);
643 }
644}
645
647{
648 m_ResurrectQueue.erase(m_ResurrectQueue.find(playerGuid));
649
650 if (Player* player = sObjectAccessor->FindPlayer(playerGuid))
651 player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
652}
653
655{
656 if (m_ResurrectQueue.empty())
657 return;
658
659 for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
660 {
661 // Get player object from his guid
662 Player* player = sObjectAccessor->FindPlayer(*itr);
663 if (!player)
664 continue;
665
666 // Check if the player is in world and on the good graveyard
667 if (player->IsInWorld())
668 if (Creature* spirit = m_Bf->GetCreature(m_SpiritGuide[m_ControlTeam]))
669 spirit->CastSpell(spirit, SPELL_SPIRIT_HEAL, true);
670
671 // Resurect player
672 player->CastSpell(player, SPELL_RESURRECTION_VISUAL, true);
673 player->ResurrectPlayer(1.0f);
674 player->CastSpell(player, 6962, true);
675 player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true);
676
677 sObjectAccessor->ConvertCorpseForPlayer(player->GetGUID());
678 }
679
680 m_ResurrectQueue.clear();
681}
682
683// For changing graveyard control
685{
686 // Guide switching
687 // Note: Visiblity changes are made by phasing
688 /*if (m_SpiritGuide[1 - team])
689 m_SpiritGuide[1 - team]->SetVisible(false);
690 if (m_SpiritGuide[team])
691 m_SpiritGuide[team]->SetVisible(true);*/
692
693 m_ControlTeam = team;
694 // Teleport to other graveyard, player witch were on this graveyard
696}
697
699{
700 WorldSafeLocsEntry const* closestGrave = NULL;
701 for (GuidSet::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
702 {
703 Player* player = sObjectAccessor->FindPlayer(*itr);
704 if (!player)
705 continue;
706
707 if (closestGrave)
708 player->TeleportTo(player->GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation());
709 else
710 {
711 closestGrave = m_Bf->GetClosestGraveYard(player);
712 if (closestGrave)
713 player->TeleportTo(player->GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation());
714 }
715 }
716}
717
719{
720 if (!m_SpiritGuide[0] || !m_SpiritGuide[1])
721 return false;
722
723 if (!m_Bf->GetCreature(m_SpiritGuide[0]) ||
724 !m_Bf->GetCreature(m_SpiritGuide[1]))
725 return false;
726
727 return (m_SpiritGuide[0] == guid || m_SpiritGuide[1] == guid);
728}
729
730// *******************************************************
731// *************** End Spirit Guide system ***************
732// *******************************************************
733// ********************** Misc ***************************
734// *******************************************************
735
737{
738 return SpawnCreature(entry, pos.m_positionX, pos.m_positionY, pos.m_positionZ, pos.m_orientation, team);
739}
740
741Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team)
742{
743 //Get map object
744 Map* map = sMapMgr->CreateBaseMap(m_MapId);
745 if (!map)
746 {
747 SF_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u map not found", entry);
748 return 0;
749 }
750
751 Creature* creature = new Creature;
752 if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, entry, 0, team, x, y, z, o))
753 {
754 SF_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: Can't create creature entry: %u", entry);
755 delete creature;
756 return NULL;
757 }
758
759 creature->SetHomePosition(x, y, z, o);
760
761 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
762 if (!cinfo)
763 {
764 SF_LOG_ERROR("bg.battlefield", "Battlefield::SpawnCreature: entry %u does not exist.", entry);
765 return NULL;
766 }
767 // force using DB speeds -- do we really need this?
768 creature->SetSpeed(MOVE_WALK, cinfo->speed_walk);
769 creature->SetSpeed(MOVE_RUN, cinfo->speed_run);
770
771 // Set creature in world
772 map->AddToMap(creature);
773 creature->setActive(true);
774
775 return creature;
776}
777
778// Method for spawning gameobject on map
779GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z, float o)
780{
781 // Get map object
782 Map* map = sMapMgr->CreateBaseMap(571); // *vomits*
783 if (!map)
784 return 0;
785
786 // Create gameobject
787 GameObject* go = new GameObject;
788 if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, o, 0, 0, 0, 0, 100, GOState::GO_STATE_READY))
789 {
790 SF_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u not found in database! Battlefield not created!", entry);
791 SF_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Cannot create gameobject template %u! Battlefield not created!", entry);
792 delete go;
793 return NULL;
794 }
795
796 for (auto phase : go->GetPhases())
797 go->SetPhased(phase, false, true);
798
799 // Add to world
800 map->AddToMap(go);
801 go->setActive(true);
802
803 return go;
804}
805
807{
808 if (!m_Map)
809 return NULL;
810 return m_Map->GetCreature(GUID);
811}
812
814{
815 if (!m_Map)
816 return NULL;
817 return m_Map->GetGameObject(GUID);
818}
819
820// *******************************************************
821// ******************* CapturePoint **********************
822// *******************************************************
823
825{
827 {
828 if (GameObject* capturePoint = m_Bf->GetGameObject(m_capturePointGUID))
829 {
830 player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
831 player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, uint32(ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f)));
832 player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, m_neutralValuePct);
833 }
834 }
835
836 return m_activePlayers[player->GetTeamId()].insert(player->GetGUID()).second;
837}
838
840{
842 if (GameObject* capturePoint = m_Bf->GetGameObject(m_capturePointGUID))
843 player->SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 0);
844
845 GuidSet::iterator current = m_activePlayers[player->GetTeamId()].find(player->GetGUID());
846
847 if (current == m_activePlayers[player->GetTeamId()].end())
848 return current; // return end()
849
850 m_activePlayers[player->GetTeamId()].erase(current++);
851 return current;
852}
853
855{
857 return;
858
859 if (GameObject* capturePoint = m_Bf->GetGameObject(m_capturePointGUID))
860 {
861 // send this too, sometimes the slider disappears, dunno why :(
862 SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldState1, 1);
863 // send these updates to only the ones in this objective
864 SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate2, (uint32)ceil((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
865 // send this too, sometimes it resets :S
866 SendUpdateWorldState(capturePoint->GetGOInfo()->capturePoint.worldstate3, m_neutralValuePct);
867 }
868}
869
871{
872 ASSERT(capturePoint);
873
874 SF_LOG_DEBUG("bg.battlefield", "Creating capture point %u", capturePoint->GetEntry());
875
876 m_capturePointGUID = MAKE_NEW_GUID(capturePoint->GetGUIDLow(), capturePoint->GetEntry(), HIGHGUID_GAMEOBJECT);
877
878 // check info existence
879 GameObjectTemplate const* goinfo = capturePoint->GetGOInfo();
880 if (goinfo->type != GAMEOBJECT_TYPE_CAPTURE_POINT)
881 {
882 SF_LOG_ERROR("misc", "OutdoorPvP: GO %u is not capture point!", capturePoint->GetEntry());
883 return false;
884 }
885
886 // get the needed values from goinfo
888 m_maxSpeed = m_maxValue / (goinfo->capturePoint.minTime ? goinfo->capturePoint.minTime : 60);
891 m_capturePointEntry = capturePoint->GetEntry();
892 if (m_team == TEAM_ALLIANCE)
893 {
896 }
897 else
898 {
901 }
902
903 return true;
904}
905
910
912{
914 {
915 if (GameObject* capturePoint = m_Bf->GetGameObject(m_capturePointGUID))
916 {
917 capturePoint->SetRespawnTime(0); // not save respawn time
918 capturePoint->Delete();
919 capturePoint = NULL;
920 }
922 }
923
924 return true;
925}
926
928{
930 return false;
931
932 if (GameObject* capturePoint = m_Bf->GetGameObject(m_capturePointGUID))
933 {
934 float radius = capturePoint->GetGOInfo()->capturePoint.radius;
935
936 for (uint8 team = 0; team < 2; ++team)
937 {
938 for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end();)
939 {
940 if (Player* player = sObjectAccessor->FindPlayer(*itr))
941 {
942 if (!capturePoint->IsWithinDistInMap(player, radius) || !player->IsOutdoorPvPActive())
943 itr = HandlePlayerLeave(player);
944 else
945 ++itr;
946 }
947 else
948 ++itr;
949 }
950 }
951
952 std::list<Player*> players;
953 Skyfire::AnyPlayerInObjectRangeCheck checker(capturePoint, radius);
954 Skyfire::PlayerListSearcher<Skyfire::AnyPlayerInObjectRangeCheck> searcher(capturePoint, players, checker);
955 capturePoint->VisitNearbyWorldObject(radius, searcher);
956
957 for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
958 if ((*itr)->IsOutdoorPvPActive())
959 if (m_activePlayers[(*itr)->GetTeamId()].insert((*itr)->GetGUID()).second)
960 HandlePlayerEnter(*itr);
961 }
962
963 // get the difference of numbers
964 float fact_diff = ((float)m_activePlayers[0].size() - (float)m_activePlayers[1].size()) * diff / float(BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL);
965 if (G3D::fuzzyEq(fact_diff, 0.0f))
966 return false;
967
968 uint32 Challenger = 0;
969 float maxDiff = m_maxSpeed * diff;
970
971 if (fact_diff < 0)
972 {
973 // horde is in majority, but it's already horde-controlled -> no change
975 return false;
976
977 if (fact_diff < -maxDiff)
978 fact_diff = -maxDiff;
979
980 Challenger = HORDE;
981 }
982 else
983 {
984 // ally is in majority, but it's already ally-controlled -> no change
986 return false;
987
988 if (fact_diff > maxDiff)
989 fact_diff = maxDiff;
990
991 Challenger = ALLIANCE;
992 }
993
994 float oldValue = m_value;
995 TeamId oldTeam = m_team;
996
998
999 m_value += fact_diff;
1000
1001 if (m_value < -m_minValue) // red
1002 {
1003 if (m_value < -m_maxValue)
1007 }
1008 else if (m_value > m_minValue) // blue
1009 {
1010 if (m_value > m_maxValue)
1014 }
1015 else if (oldValue * m_value <= 0) // grey, go through mid point
1016 {
1017 // if challenger is ally, then n->a challenge
1018 if (Challenger == ALLIANCE)
1020 // if challenger is horde, then n->h challenge
1021 else if (Challenger == HORDE)
1024 }
1025 else // grey, did not go through mid point
1026 {
1027 // old phase and current are on the same side, so one team challenges the other
1033 }
1034
1035 if (G3D::fuzzyNe(m_value, oldValue))
1037
1038 if (m_OldState != m_State)
1039 {
1040 //SF_LOG_ERROR("bg.battlefield", "%u->%u", m_OldState, m_State);
1041 if (oldTeam != m_team)
1042 ChangeTeam(oldTeam);
1043 return true;
1044 }
1045
1046 return false;
1047}
1048
1050{
1051 for (uint8 team = 0; team < 2; ++team)
1052 for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr) // send to all players present in the area
1053 if (Player* player = sObjectAccessor->FindPlayer(*itr))
1054 player->SendUpdateWorldState(field, value);
1055}
1056
1058{
1059 uint8 team;
1060 switch (m_State)
1061 {
1063 team = 0;
1064 break;
1066 team = 1;
1067 break;
1068 default:
1069 return;
1070 }
1071
1072 // send to all players present in the area
1073 for (GuidSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end(); ++itr)
1074 if (Player* player = sObjectAccessor->FindPlayer(*itr))
1075 player->KilledMonsterCredit(id, guid);
1076}
1077
1079{
1080 return m_activePlayers[player->GetTeamId()].find(player->GetGUID()) != m_activePlayers[player->GetTeamId()].end();
1081}
@ BF_START
Definition Battlefield.h:44
@ BF_ALLIANCE_WINS
Definition Battlefield.h:43
@ BF_HORDE_WINS
Definition Battlefield.h:42
@ BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL
Definition Battlefield.h:49
#define sBattlefieldMgr
@ RESURRECTION_INTERVAL
@ SPELL_SPIRIT_HEAL
@ SPELL_SPIRIT_HEAL_MANA
@ SPELL_RESURRECTION_VISUAL
@ SPELL_WAITING_FOR_RESURRECT
#define BG_TEAMS_COUNT
#define sCreatureTextMgr
@ TEXT_RANGE_ZONE
DBCStorage< WorldSafeLocsEntry > sWorldSafeLocsStore(WorldSafeLocsEntryfmt)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
@ GO_STATE_READY
Definition GameObject.h:577
#define sGroupMgr
Definition GroupMgr.h:44
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define sMapMgr
Definition MapManager.h:145
#define sObjectAccessor
@ HIGHGUID_GAMEOBJECT
@ HIGHGUID_UNIT
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ GAMEOBJECT_TYPE_CAPTURE_POINT
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
TeamId
@ TEAM_NEUTRAL
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ ALLIANCE
@ HORDE
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_WALK
Definition Unit.h:555
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FIELD_FLAGS
uint32 m_Timer
GuidSet m_PlayersInQueue[BG_TEAMS_COUNT]
uint32 m_MapId
void BroadcastPacketToQueue(WorldPacket &data) const
GraveyardVect m_GraveyardList
void ShowNpc(Creature *creature, bool aggressive)
void BroadcastPacketToZone(WorldPacket &data) const
void DoPlaySoundToAll(uint32 SoundID)
GuidSet m_players[BG_TEAMS_COUNT]
PlayerTimerMap m_InvitedPlayers[BG_TEAMS_COUNT]
uint32 m_MaxPlayer
void SendWarningToPlayer(Player *player, uint32 entry)
uint32 m_NoWarBattleTime
virtual ~Battlefield()
Destructor.
virtual void SendInitWorldStatesToAll()=0
Send all worldstate data to all player in zone.
void EndBattle(bool endByTimer)
virtual void OnBattleEnd(bool)
Called at the end of battle.
void RemovePlayerFromResurrectQueue(uint64 player_guid)
uint32 m_BattleTime
uint32 GetZoneId() const
bool IsWarTime() const
Return true if battle is start, false if battle is not started.
uint32 m_ZoneId
Group * GetGroupPlayer(uint64 guid, TeamId TeamId)
Return battlefield group where player is.
void InvitePlayersInQueueToWar()
Invite all players in queue to join battle on battle start.
void BroadcastPacketToWar(WorldPacket &data) const
virtual void SendRemoveWorldStates(Player *)
uint32 m_StartGroupingTimer
uint32 m_LastResurectTimer
WorldSafeLocsEntry const * GetClosestGraveYard(Player *player)
virtual bool Update(uint32 diff)
Called every time for update bf data and time.
void InvitePlayersInZoneToQueue()
Invite all players in zone to join the queue, called x minutes before battle start in Update().
GameObject * GetGameObject(uint64 GUID)
void InvitePlayerToQueue(Player *player)
TeamId GetOtherTeam(TeamId team)
void RegisterZone(uint32 zoneid)
void SetDefenderTeam(TeamId team)
void InvitePlayerToWar(Player *player)
GuidSet m_PlayersInWar[BG_TEAMS_COUNT]
uint32 m_uiKickAfkPlayersTimer
void PlayerAcceptInviteToWar(Player *player)
uint64 StalkerGuid
Group * GetFreeBfRaid(TeamId TeamId)
Find a not full battlefield group, if there is no, create one.
void StartBattle()
virtual void OnPlayerJoinWar(Player *)
Called when a player accept to join the battle.
uint32 m_TimeForAcceptInvite
BfGraveyard * GetGraveyardById(uint32 id) const
virtual void OnBattleStart()
Called on start.
void SendAreaSpiritHealerQueryOpcode(Player *player, uint64 guid)
void InvitePlayersInZoneToWar()
Invite all players in zone to join battle on battle start.
GameObject * SpawnGameObject(uint32 entry, float x, float y, float z, float o)
void HideNpc(Creature *creature)
TeamId GetAttackerTeam() const
uint32 m_MinLevel
void InitStalker(uint32 entry, float x, float y, float z, float o)
bool AddOrSetPlayerToCorrectBfGroup(Player *player)
Force player to join a battlefield group.
void KickAfkPlayers()
TeamId GetDefenderTeam() const
void TeamCastSpell(TeamId team, int32 spellId)
uint32 m_MinPlayer
GuidSet m_Groups[BG_TEAMS_COUNT]
virtual void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
virtual void OnPlayerLeaveZone(Player *)
Called when a player leave battlefield zone.
Creature * GetCreature(uint64 GUID)
void PlayerAcceptInviteToQueue(Player *player)
BfCapturePointMap m_capturePoints
uint32 m_uiKickDontAcceptTimer
uint64 m_Guid
void SendWarningToAllInZone(uint32 entry)
virtual void OnStartGrouping()
Called x minutes before battle start when player in zone are invite to join queue.
bool m_StartGrouping
WorldLocation KickPosition
virtual void OnPlayerLeaveWar(Player *)
Called when a player leave the battle.
bool HasPlayer(Player *player) const
void AskToLeaveQueue(Player *player)
PlayerTimerMap m_PlayersWillBeKick[BG_TEAMS_COUNT]
Creature * SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team)
void HandlePlayerLeaveZone(Player *player, uint32 zone)
Called when player (player) leave the zone.
virtual void OnPlayerEnterZone(Player *)
Called when a player enter in battlefield zone.
void KickPlayerFromBattlefield(uint64 guid)
Kick player from battlefield and teleport him to kick-point location.
void SendUpdateWorldState(uint32 field, uint32 value)
Update data of a worldstate to all players present in zone.
void HandlePlayerEnterZone(Player *player, uint32 zone)
Called when player (player) enter in zone.
virtual GuidSet::iterator HandlePlayerLeave(Player *player)
virtual bool HandlePlayerEnter(Player *player)
Battlefield * m_Bf
virtual bool Update(uint32 diff)
BattlefieldObjectiveStates m_OldState
bool SetCapturePointData(GameObject *capturePoint)
virtual void ChangeTeam(TeamId)
Definition Battlefield.h:93
void SendObjectiveComplete(uint32 id, uint64 guid)
bool IsInsideObjective(Player *player) const
GameObject * GetCapturePointGo()
virtual void SendChangePhase()
void SendUpdateWorldState(uint32 field, uint32 value)
uint32 m_capturePointEntry
uint32 m_neutralValuePct
uint64 m_capturePointGUID
GuidSet m_activePlayers[2]
BattlefieldObjectiveStates m_State
void RemovePlayer(uint64 player_guid)
uint64 m_SpiritGuide[2]
GuidSet m_ResurrectQueue
bool HasNpc(uint64 guid)
void AddPlayer(uint64 player_guid)
uint32 m_GraveyardId
void GiveControlTo(TeamId team)
Battlefield * m_Bf
TeamId m_ControlTeam
void SetSpirit(Creature *spirit, TeamId team)
uint32 GetGraveyardId() const
void Initialize(TeamId startcontrol, uint32 gy)
void RelocateDeadPlayers()
float GetDistance(Player *player)
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:626
void Respawn(bool force=false)
void SetReactState(ReactStates st)
Definition Creature.h:460
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData *data=NULL)
Definition Creature.cpp:740
void DisappearAndDie()
Definition Creature.cpp:206
GameObjectTemplate const * GetGOInfo() const
Definition GameObject.h:643
bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit=0)
bool SetPhased(uint32 id, bool update, bool apply) OVERRIDE
Definition Group.h:147
void SetBattlefieldGroup(Battlefield *bf)
Definition Group.cpp:2664
bool AddMember(Player *player)
Definition Group.cpp:353
uint64 GetGUID() const
Definition Group.cpp:2573
uint8 GetMemberGroup(uint64 guid) const
Definition Group.cpp:2651
bool IsMember(uint64 guid) const
Definition Group.cpp:2603
bool RemoveMember(uint64 guid, const RemoveMethod &method=GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker=0, const char *reason=NULL)
Definition Group.cpp:501
bool Create(Player *leader)
Definition Group.cpp:81
Definition Map.h:238
bool AddToMap(T *)
Definition Map.cpp:504
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
uint32 GetGUIDLow() const
Definition Object.h:120
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
uint32 GetEntry() const
Definition Object.h:125
void SendUpdateWorldState(uint32 Field, uint32 Value)
Definition Player.cpp:9734
WorldSession * GetSession() const
Definition Player.h:2417
TeamId GetTeamId() const
Definition Player.h:2531
Battleground * GetBattleground() const
Definition Player.cpp:19212
Group * GetGroup()
Definition Player.h:2972
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
void ToggleAFK()
Definition Player.cpp:2060
bool InArena() const
Definition Player.cpp:19310
bool isAFK() const
Definition Player.h:1333
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition Player.cpp:20119
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:5203
void SetVisible(bool x)
Definition Unit.cpp:4163
void CombatStop(bool includingCast=false)
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
bool IsAlive() const
Definition Unit.h:2032
bool IsInFlight() const
Definition Unit.h:1891
void SetPhaseMask(uint32 newPhaseMask, bool update) override
Definition Unit.cpp:7454
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition Unit.cpp:4318
uint8 getLevel() const
Definition Unit.h:1528
uint32 GetMapId() const
Definition Object.h:546
std::set< uint32 > const & GetPhases() const
Definition Object.h:647
void setActive(bool isActiveObject)
Definition Object.cpp:1542
float GetDistance2d(WorldObject const *obj) const
Definition Object.cpp:1684
void SendBfLeaveMessage(uint64 guid, BFLeaveReason reason=BF_LEAVE_REASON_EXITED)
void SendBfEntered(uint64 guid)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void SendBfQueueInviteResponse(uint64 guid, uint32 zoneId, bool canQueue=true, bool full=false)
void SendBfInvitePlayerToWar(uint64 guid, uint32 zoneId, uint32 time)
void SendBfInvitePlayerToQueue(uint64 guid)
@ SMSG_AREA_SPIRIT_HEALER_TIME
Definition Opcodes.h:515
@ SMSG_PLAY_SOUND
Definition Opcodes.h:883
struct GameObjectTemplate::@046065176235271051340241126110345143267101032070::@155125343144143170177322306114162367114353163373 capturePoint
float m_positionZ
Definition Object.h:289
float m_positionX
Definition Object.h:287
float m_positionY
Definition Object.h:288
float GetOrientation() const
Definition Object.h:331
float m_orientation
Definition Object.h:292
float x
float z
float y