TrinityCore
Loading...
Searching...
No Matches
BattlegroundSA.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "BattlegroundSA.h"
19#include "BattlegroundPackets.h"
20#include "DBCStores.h"
21#include "GameObject.h"
22#include "GameTime.h"
23#include "Log.h"
24#include "Map.h"
25#include "ObjectAccessor.h"
26#include "ObjectMgr.h"
27#include "Player.h"
28#include "ScriptedCreature.h"
29#include "UpdateData.h"
30#include "WorldStatePackets.h"
31
36
38{
39 StartMessageIds[BG_STARTING_EVENT_FOURTH] = 0; // handle by Kanrethad
40
41 BgObjects.resize(BG_SA_MAXOBJ);
43 TimerEnabled = false;
45 SignaledRoundTwo = false;
47 InitSecondRound = false;
48 _gateDestroyed = false;
50 TotalTime = 0;
51 EndRoundTimer = 0;
52 ShipsStarted = false;
54
55 for (uint8 i = 0; i < MAX_GATES; ++i)
57
58 for (uint8 i = 0; i < 2; i++)
59 {
61 RoundScores[i].time = 0;
62 _allVehiclesAlive[i] = true;
63 }
64
68 memset(&GraveyardStatus, 0, sizeof(GraveyardStatus));
69}
70
72
74{
75 TotalTime = 0;
77 for (uint8 i = 0; i <= 5; i++)
79 ShipsStarted = false;
80 _gateDestroyed = false;
84}
85
87{
88 return ResetObjs();
89}
90
92{
93 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
94 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
96
99
100 for (uint8 i = 0; i < BG_SA_MAXOBJ; i++)
101 DelObject(i);
102
103 for (uint8 i = 0; i < BG_SA_MAXNPC; i++)
104 DelCreature(i);
105
107 DelCreature(i);
108
109 for (uint8 i = 0; i < MAX_GATES; ++i)
111
113 {
114 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn Kanrethad, aborted. Entry: {}", BG_SA_NpcEntries[BG_SA_NPC_KANRETHAD]);
115 return false;
116 }
117
118 for (uint8 i = 0; i <= BG_SA_PORTAL_DEFFENDER_RED; i++)
119 {
121 {
122 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn BG_SA_PORTAL_DEFFENDER_RED, Entry: {}", BG_SA_ObjEntries[i]);
123 continue;
124 }
125 }
126
127 for (uint8 i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
128 {
129 uint32 boatid = 0;
130 switch (i)
131 {
132 case BG_SA_BOAT_ONE:
134 break;
135 case BG_SA_BOAT_TWO:
137 break;
138 default:
139 break;
140 }
141 if (!AddObject(i, boatid, BG_SA_ObjSpawnlocs[i].GetPositionX(),
142 BG_SA_ObjSpawnlocs[i].GetPositionY(),
143 BG_SA_ObjSpawnlocs[i].GetPositionZ() + (Attackers ? -3.750f: 0),
144 BG_SA_ObjSpawnlocs[i].GetOrientation(), 0, 0, 0, 0, RESPAWN_ONE_DAY))
145 {
146 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn one of the BG_SA_BOAT, Entry: {}", boatid);
147 continue;
148 }
149 }
150
151 for (uint8 i = BG_SA_SIGIL_1; i <= BG_SA_LEFT_FLAGPOLE; i++)
152 {
154 {
155 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn Sigil, Entry: {}", BG_SA_ObjEntries[i]);
156 continue;
157 }
158 }
159
160 // MAD props for Kiper for discovering those values - 4 hours of his work.
162 GetBGObject(BG_SA_BOAT_TWO)->SetParentRotation(QuaternionData(0.f, 0.f, 1.0f, 0.00001f));
165
166 //Cannons and demolishers - NPCs are spawned
167 //By capturing GYs.
168 for (uint8 i = 0; i < BG_SA_DEMOLISHER_5; i++)
169 {
171 {
172 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn Cannon or demolisher, Entry: {}, Attackers: {}", BG_SA_NpcEntries[i], Attackers == TEAM_ALLIANCE ? "Horde(1)" : "Alliance(0)");
173 continue;
174 }
175 }
176
179
180 for (uint8 i = 0; i <= BG_SA_PORTAL_DEFFENDER_RED; i++)
181 {
183 GetBGObject(i)->SetFaction(defF);
184 }
185
188
189 TotalTime = 0;
190 ShipsStarted = false;
191
192 //Graveyards
193 for (uint8 i = 0; i < BG_SA_MAX_GY; i++)
194 {
195 WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
196
197 if (!sg)
198 {
199 TC_LOG_ERROR("bg.battleground", "SOTA: Can't find GY entry {}", BG_SA_GYEntries[i]);
200 return false;
201 }
202
203 if (i == BG_SA_BEACH_GY)
204 {
207 }
208 else
209 {
212 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn GY: {}", i);
213 }
214 }
215
216 //GY capture points
217 for (uint8 i = BG_SA_CENTRAL_FLAG; i <= BG_SA_LEFT_FLAG; i++)
218 {
219 if (!AddObject(i, (BG_SA_ObjEntries[i] - (Attackers == TEAM_ALLIANCE ? 1 : 0)), BG_SA_ObjSpawnlocs[i], 0, 0, 0, 0, RESPAWN_ONE_DAY))
220 {
221 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn Central Flag Entry: {}", BG_SA_ObjEntries[i] - (Attackers == TEAM_ALLIANCE ? 1 : 0));
222 continue;
223 }
224 GetBGObject(i)->SetFaction(atF);
225 }
226
228
229 for (uint8 i = BG_SA_BOMB; i < BG_SA_MAXOBJ; i++)
230 {
232 {
233 TC_LOG_ERROR("bg.battleground", "SOTA: couldn't spawn SA Bomb Entry: {}", BG_SA_ObjEntries[BG_SA_BOMB] + i);
234 continue;
235 }
236 GetBGObject(i)->SetFaction(atF);
237 }
238
239 //Player may enter BEFORE we set up BG - lets update his worldstates anyway...
243
247
249 {
252
257
260 }
261 else
262 {
265
270
273 }
274
281
282 for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
283 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
284 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
285 SendTransportInit(player);
286
287 // set status manually so preparation is cast correctly in 2nd round too
289
291 return true;
292}
293
295{
296 if (ShipsStarted)
297 return;
298
301
302 for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
303 {
304 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
305 {
306 if (Player* p = ObjectAccessor::FindPlayer(itr->first))
307 {
308 UpdateData data;
309 WorldPacket pkt;
311 data.BuildPacket(&pkt);
312 p->SendDirectMessage(&pkt);
313 }
314 }
315 }
316 ShipsStarted = true;
317}
318
320{
321 if (InitSecondRound)
322 {
323 if (UpdateWaitTimer < diff)
324 {
325 if (!SignaledRoundTwo)
326 {
327 SignaledRoundTwo = true;
328 InitSecondRound = false;
330 }
331 }
332 else
333 {
334 UpdateWaitTimer -= diff;
335 return;
336 }
337 }
338 TotalTime += diff;
339
340 if (Status == BG_SA_WARMUP)
341 {
344 {
347
348 TotalTime = 0;
349 ToggleTimer();
353 }
355 StartShips();
356 return;
357 }
358 else if (Status == BG_SA_SECOND_WARMUP)
359 {
360 if (RoundScores[0].time<BG_SA_ROUNDLENGTH)
362 else
364
365 if (TotalTime >= 60000)
366 {
369
370 TotalTime = 0;
371 ToggleTimer();
375 // status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now
377 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
378 if (Player* p = ObjectAccessor::FindPlayer(itr->first))
379 p->RemoveAurasDueToSpell(SPELL_PREPARATION);
380 }
381 if (TotalTime >= 30000)
382 {
384 {
387 }
388 }
389 StartShips();
390 return;
391 }
392 else if (GetStatus() == STATUS_IN_PROGRESS)
393 {
394 if (Status == BG_SA_ROUND_ONE)
395 {
397 {
402 TotalTime = 0;
405 UpdateWaitTimer = 5000;
406 SignaledRoundTwo = false;
408 InitSecondRound = true;
409 ToggleTimer();
410 ResetObjs();
412 return;
413 }
414 }
415 else if (Status == BG_SA_ROUND_TWO)
416 {
418 {
423 if (RoundScores[0].time == RoundScores[1].time)
425 else if (RoundScores[0].time < RoundScores[1].time)
427 else
429 return;
430 }
431 }
433 {
434 SendTime();
436 }
437 }
438}
439
441
443
445{
446 bool const allyAttacks = Attackers == TEAM_ALLIANCE;
447 bool const hordeAttacks = Attackers == TEAM_HORDE;
448
455
456 packet.Worldstates.emplace_back(BG_SA_BONUS_TIMER, 0);
457 packet.Worldstates.emplace_back(BG_SA_HORDE_ATTACKS, hordeAttacks);
458 packet.Worldstates.emplace_back(BG_SA_ALLY_ATTACKS, allyAttacks);
459
460 // Time will be sent on first update...
461 packet.Worldstates.emplace_back(BG_SA_ENABLE_TIMER, TimerEnabled);
462 packet.Worldstates.emplace_back(BG_SA_TIMER_MINS, 0);
463 packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_TENS, 0);
464 packet.Worldstates.emplace_back(BG_SA_TIMER_SEC_DECS, 0);
465
472
473 packet.Worldstates.emplace_back(BG_SA_HORDE_DEFENCE_TOKEN, allyAttacks);
474 packet.Worldstates.emplace_back(BG_SA_ALLIANCE_DEFENCE_TOKEN, hordeAttacks);
475 packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_HRD, hordeAttacks);
476 packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_HRD, hordeAttacks);
477 packet.Worldstates.emplace_back(BG_SA_RIGHT_ATT_TOKEN_ALL, allyAttacks);
478 packet.Worldstates.emplace_back(BG_SA_LEFT_ATT_TOKEN_ALL, allyAttacks);
479}
480
482{
483 bool const isInBattleground = IsPlayerInBattleground(player->GetGUID());
485 if (!isInBattleground)
486 PlayerScores[player->GetGUID()] = new BattlegroundSAScore(player->GetGUID());
487
488 SendTransportInit(player);
489
490 if (!isInBattleground)
492}
493
494void BattlegroundSA::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*team*/) { }
495
496void BattlegroundSA::HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/)
497{
498 // this is wrong way to implement these things. On official it done by gameobject spell cast.
500 return;
501}
502
504{
505 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
506 {
507 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
508 {
509 // should remove spirit of redemption
510 if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
511 player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
512
513 if (!player->IsAlive())
514 {
515 player->ResurrectPlayer(1.0f);
516 player->SpawnCorpseBones();
517 }
518
519 player->ResetAllPowers();
520 player->CombatStopWithPets(true);
521
522 player->CastSpell(player, SPELL_PREPARATION, true);
523
525 }
526 }
527}
528
530{
531 if (player->GetTeamId() == Attackers)
532 {
533 if (!ShipsStarted)
534 {
536
537 if (urand(0, 1))
538 player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
539 else
540 player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
541 }
542 else
543 player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
544 }
545 else
546 player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
547}
548
549void BattlegroundSA::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker /*= nullptr*/)
550{
551 if (GameObject* go = obj->ToGameObject())
552 {
553 switch (go->GetGoType())
554 {
556 if (invoker)
558 TitanRelicActivated(invoker->ToPlayer());
559 break;
561 {
562 if (GateInfo const* gate = GetGate(obj->GetEntry()))
563 {
564 uint8 gateId = gate->GateId;
565
566 // damaged
567 if (eventId == go->GetGOInfo()->building.damagedEvent)
568 {
570
571 if (Creature* c = obj->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
572 SendChatMessage(c, gate->DamagedText, invoker);
573
575 }
576 // destroyed
577 else if (eventId == go->GetGOInfo()->building.destroyedEvent)
578 {
579 GateStatus[gate->GateId] = BG_SA_GATE_DESTROYED;
580 _gateDestroyed = true;
581
582 if (gateId < 5)
583 DelObject(gateId + 14);
584
585 if (Creature* c = obj->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
586 SendChatMessage(c, gate->DestroyedText, invoker);
587
589
590 bool rewardHonor = true;
591 switch (gateId)
592 {
593 case BG_SA_GREEN_GATE:
595 rewardHonor = false;
596 break;
597 case BG_SA_BLUE_GATE:
599 rewardHonor = false;
600 break;
601 case BG_SA_RED_GATE:
603 rewardHonor = false;
604 break;
607 rewardHonor = false;
608 break;
609 default:
610 break;
611 }
612
613 if (invoker)
614 {
615 if (Unit* unit = invoker->ToUnit())
616 {
617 if (Player* player = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
618 {
620 if (rewardHonor)
622 }
623 }
624 }
625
627 }
628 else
629 break;
630
631 UpdateWorldState(gate->WorldState, GateStatus[gateId]);
632 }
633 break;
634 }
635 default:
636 break;
637 }
638 }
639}
640
642{
643 if (creature->GetEntry() == NPC_DEMOLISHER_SA)
644 {
647 }
648}
649
650/*
651 You may ask what the fuck does it do?
652 Prevents owner overwriting guns faction with own.
653 */
655{
656 if (!BgCreatures[0])
657 return;
658
659 for (uint8 i = BG_SA_GUN_1; i <= BG_SA_GUN_10; i++)
660 {
661 if (Creature* gun = GetBGCreature(i))
662 gun->SetFaction(BG_SA_Factions[Attackers ? TEAM_ALLIANCE : TEAM_HORDE]);
663 }
664
665 for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
666 {
667 if (Creature* dem = GetBGCreature(i))
668 dem->SetFaction(BG_SA_Factions[Attackers]);
669 }
670}
671
673{
674 if (!BgCreatures[0])
675 return;
676
677 // set flags only for the demolishers on the beach, factory ones dont need it
678 for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_4; i++)
679 {
680 if (Creature* dem = GetBGCreature(i))
681 {
682 if (start)
684 else
686 }
687 }
688}
689
691{
692}
693
695{
696 uint32 safeloc = 0;
697 WorldSafeLocsEntry const* ret;
698 WorldSafeLocsEntry const* closest;
699 float dist, nearest;
700 float x, y, z;
701
702 player->GetPosition(x, y, z);
703
704 if (player->GetTeamId() == Attackers)
706 else
708
709 closest = sWorldSafeLocsStore.LookupEntry(safeloc);
710 nearest = player->GetExactDistSq(closest->Loc.X, closest->Loc.Y, closest->Loc.Z);
711
713 {
714 if (GraveyardStatus[i] != player->GetTeamId())
715 continue;
716
717 ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
718 dist = player->GetExactDistSq(ret->Loc.X, ret->Loc.Y, ret->Loc.Z);
719 if (dist < nearest)
720 {
721 closest = ret;
722 nearest = dist;
723 }
724 }
725
726 return closest;
727}
728
730{
731 uint32 end_of_round = (EndRoundTimer - TotalTime);
732 UpdateWorldState(BG_SA_TIMER_MINS, end_of_round/60000);
733 UpdateWorldState(BG_SA_TIMER_SEC_TENS, (end_of_round%60000)/10000);
734 UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round%60000)%10000)/1000);
735}
736
738{
739 switch (objectId)
740 {
743 return false;
744 [[fallthrough]];
747 return false;
748 [[fallthrough]];
749 case BG_SA_LEFT_FLAG:
750 case BG_SA_RIGHT_FLAG:
752 return false;
753 break;
754 default:
755 ABORT();
756 break;
757 }
758
759 return true;
760}
761
763{
764 if (GameObject* go = GetBGObject(objectId))
765 {
766 if (CanInteractWithObject(objectId))
767 go->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
768 else
769 go->SetFlag(GO_FLAG_NOT_SELECTABLE);
770 }
771}
772
779
781{
782 switch (go->GetEntry())
783 {
784 case 191307:
785 case 191308:
788 break;
789 case 191305:
790 case 191306:
793 break;
794 case 191310:
795 case 191309:
798 break;
799 default:
800 return;
801 };
802}
803
805{
806 if (GraveyardStatus[i] == Attackers)
807 return;
808
810 GraveyardStatus[i] = Source->GetTeamId();
811 WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
812 if (!sg)
813 {
814 TC_LOG_ERROR("bg.battleground", "BattlegroundSA::CaptureGraveyard: non-existant GY entry: {}", BG_SA_GYEntries[i]);
815 return;
816 }
817
819 uint32 npc = 0;
820 uint32 flag = 0;
821
822 switch (i)
823 {
825 flag = BG_SA_LEFT_FLAG;
826 DelObject(flag);
827 AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
828 BG_SA_ObjSpawnlocs[flag], 0, 0, 0, 0, RESPAWN_ONE_DAY);
829
830 npc = BG_SA_NPC_RIGSPARK;
831 if (Creature* rigspark = AddCreature(BG_SA_NpcEntries[npc], npc, BG_SA_NpcSpawnlocs[npc], Attackers))
832 rigspark->AI()->Talk(TEXT_SPARKLIGHT_RIGSPARK_SPAWN);
833
834 for (uint8 j = BG_SA_DEMOLISHER_7; j <= BG_SA_DEMOLISHER_8; j++)
835 {
837
838 if (Creature* dem = GetBGCreature(j))
839 dem->SetFaction(BG_SA_Factions[Attackers]);
840 }
841
844
845 if (Creature* c = Source->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
847
848 break;
850 flag = BG_SA_RIGHT_FLAG;
851 DelObject(flag);
852 AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
853 BG_SA_ObjSpawnlocs[flag], 0, 0, 0, 0, RESPAWN_ONE_DAY);
854
856 if (Creature* sparklight = AddCreature(BG_SA_NpcEntries[npc], npc, BG_SA_NpcSpawnlocs[npc], Attackers))
857 sparklight->AI()->Talk(TEXT_SPARKLIGHT_RIGSPARK_SPAWN);
858
859 for (uint8 j = BG_SA_DEMOLISHER_5; j <= BG_SA_DEMOLISHER_6; j++)
860 {
862
863 if (Creature* dem = GetBGCreature(j))
865 }
866
869
870 if (Creature* c = Source->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
872
873 break;
875 flag = BG_SA_CENTRAL_FLAG;
876 DelObject(flag);
877 AddObject(flag, (BG_SA_ObjEntries[flag] - (Source->GetTeamId() == TEAM_ALLIANCE ? 0 : 1)),
878 BG_SA_ObjSpawnlocs[flag], 0, 0, 0, 0, RESPAWN_ONE_DAY);
879
882
883 if (Creature* c = Source->FindNearestCreature(NPC_WORLD_TRIGGER, 500.0f))
885
886 break;
887 default:
888 ABORT();
889 break;
890 };
891}
892
894{
895 if (!clicker)
896 return;
897
899 {
900 if (clicker->GetTeamId() == Attackers)
901 {
902 if (clicker->GetTeamId() == TEAM_ALLIANCE)
904 else
906
907 if (Status == BG_SA_ROUND_ONE)
908 {
911 // Achievement Storm the Beach (1310)
912 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
913 {
914 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
915 if (player->GetTeamId() == Attackers)
916 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
917 }
918
921 TotalTime = 0;
922 ToggleTimer();
923
926
927 UpdateWaitTimer = 5000;
928 SignaledRoundTwo = false;
930 InitSecondRound = true;
931 ResetObjs();
935 }
936 else if (Status == BG_SA_ROUND_TWO)
937 {
940 ToggleTimer();
941 // Achievement Storm the Beach (1310)
942 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
943 {
944 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
945 if (player->GetTeamId() == Attackers && RoundScores[1].winner == Attackers)
946 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
947 }
948
949 if (RoundScores[0].time == RoundScores[1].time)
951 else if (RoundScores[0].time < RoundScores[1].time)
953 else
955 }
956 }
957 }
958}
959
965
967{
968 // honor reward for winning
969 if (winner == ALLIANCE)
971 else if (winner == HORDE)
973
974 // complete map_end rewards (even if no team wins)
977
979}
980
982{
983 for (uint8 i = BG_SA_DEMOLISHER_1; i <= BG_SA_DEMOLISHER_8; i++)
984 {
985 if (!BgCreatures[i].IsEmpty())
986 {
987 if (Creature* Demolisher = GetBGCreature(i))
988 {
989 if (Demolisher->isDead())
990 {
991 // Demolisher is not in list
992 if (DemoliserRespawnList.find(i) == DemoliserRespawnList.end())
993 {
995 }
996 else
997 {
999 {
1000 Demolisher->Relocate(BG_SA_NpcSpawnlocs[i]);
1001 Demolisher->Respawn();
1002 DemoliserRespawnList.erase(i);
1003 }
1004 }
1005 }
1006 }
1007 }
1008 }
1009}
1010
1012{
1013 if (!BgObjects[BG_SA_BOAT_ONE].IsEmpty() || !BgObjects[BG_SA_BOAT_TWO].IsEmpty())
1014 {
1015 UpdateData transData;
1016 if (!BgObjects[BG_SA_BOAT_ONE].IsEmpty())
1018
1019 if (!BgObjects[BG_SA_BOAT_TWO].IsEmpty())
1021
1022 WorldPacket packet;
1023 transData.BuildPacket(&packet);
1024 player->SendDirectMessage(&packet);
1025 }
1026}
1027
1029{
1030 if (!BgObjects[BG_SA_BOAT_ONE].IsEmpty() || !BgObjects[BG_SA_BOAT_TWO].IsEmpty())
1031 {
1032 UpdateData transData;
1033 if (!BgObjects[BG_SA_BOAT_ONE].IsEmpty())
1035 if (!BgObjects[BG_SA_BOAT_TWO].IsEmpty())
1037 WorldPacket packet;
1038 transData.BuildPacket(&packet);
1039 player->SendDirectMessage(&packet);
1040 }
1041}
1042
1043bool BattlegroundSA::CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* source, Unit const* target, uint32 miscValue)
1044{
1045 switch (criteriaId)
1046 {
1050 return source->GetTeamId() != Attackers && !_gateDestroyed;
1051 }
1052
1053 return Battleground::CheckAchievementCriteriaMeet(criteriaId, source, target, miscValue);
1054}
1055
1056bool BattlegroundSA::IsSpellAllowed(uint32 spellId, Player const* /*player*/) const
1057{
1058 switch (spellId)
1059 {
1061 return Attackers == TEAM_HORDE;
1063 return Attackers == TEAM_ALLIANCE;
1064 case SPELL_PREPARATION:
1066 default:
1067 break;
1068 }
1069
1070 return true;
1071}
BG_SA_Graveyards
@ BG_SA_DEFENDER_LAST_GY
@ BG_SA_CENTRAL_CAPTURABLE_GY
@ BG_SA_BEACH_GY
@ BG_SA_MAX_GY
@ BG_SA_LEFT_CAPTURABLE_GY
@ BG_SA_RIGHT_CAPTURABLE_GY
@ BG_SA_BOAT_START
@ BG_SA_WARMUPLENGTH
@ BG_SA_ROUNDLENGTH
@ BG_SA_GATE_DESTROYED
@ BG_SA_GATE_OK
@ BG_SA_GATE_DAMAGED
@ BG_SA_ROUND_ONE
@ BG_SA_NOT_STARTED
@ BG_SA_ROUND_TWO
@ BG_SA_SECOND_WARMUP
@ BG_SA_WARMUP
@ BG_SA_BOAT_ONE_H
@ BG_SA_BOAT_TWO_H
@ BG_SA_BOAT_ONE_A
@ BG_SA_BOAT_TWO_A
@ SPELL_HORDE_CONTROL_PHASE_SHIFT
@ SPELL_END_OF_ROUND
@ SPELL_ALLIANCE_CONTROL_PHASE_SHIFT
const uint32 BG_SA_GYEntries[BG_SA_MAX_GY]
Position const BG_SA_ObjSpawnlocs[BG_SA_MAXOBJ]
@ TEXT_EAST_GRAVEYARD_CAPTURED_A
@ TEXT_ROUND_1_FINISHED
@ TEXT_SPARKLIGHT_RIGSPARK_SPAWN
@ TEXT_SOUTH_GRAVEYARD_CAPTURED_A
@ TEXT_ROUND_STARTED
@ TEXT_WEST_GRAVEYARD_CAPTURED_A
@ TEXT_WEST_GRAVEYARD_CAPTURED_H
@ TEXT_EAST_GRAVEYARD_CAPTURED_H
@ TEXT_SOUTH_GRAVEYARD_CAPTURED_H
uint32 const BG_SA_ObjEntries[BG_SA_MAXOBJ+BG_SA_FLAG_AMOUNT]
@ SOUND_WALL_DESTROYED_HORDE
@ SOUND_WALL_ATTACKED_HORDE
@ SOUND_WALL_DESTROYED_ALLIANCE
@ SOUND_WALL_ATTACKED_ALLIANCE
@ NPC_WORLD_TRIGGER
@ NPC_DEMOLISHER_SA
float const BG_SA_GYOrientation[BG_SA_MAX_GY]
uint32 const BG_SA_Factions[2]
@ BG_SA_ENABLE_TIMER
@ BG_SA_ANCIENT_GATEWS
@ BG_SA_LEFT_ATT_TOKEN_ALL
@ BG_SA_PURPLE_GATEWS
@ BG_SA_TIMER_SEC_TENS
@ BG_SA_RED_GATEWS
@ BG_SA_BLUE_GATEWS
@ BG_SA_CENTER_GY_ALLIANCE
@ BG_SA_RIGHT_ATT_TOKEN_HRD
@ BG_SA_LEFT_GY_ALLIANCE
@ BG_SA_RIGHT_ATT_TOKEN_ALL
@ BG_SA_YELLOW_GATEWS
@ BG_SA_LEFT_GY_HORDE
@ BG_SA_ALLIANCE_DEFENCE_TOKEN
@ BG_SA_RIGHT_GY_ALLIANCE
@ BG_SA_HORDE_DEFENCE_TOKEN
@ BG_SA_LEFT_ATT_TOKEN_HRD
@ BG_SA_CENTER_GY_HORDE
@ BG_SA_GREEN_GATEWS
@ BG_SA_RIGHT_GY_HORDE
@ BG_SA_ALLY_ATTACKS
@ BG_SA_HORDE_ATTACKS
@ BG_SA_TIMER_SEC_DECS
@ BG_SA_BONUS_TIMER
@ BG_SA_TIMER_MINS
@ BG_SA_MAXOBJ
@ BG_SA_YELLOW_GATE
@ BG_SA_BOAT_ONE
@ BG_SA_GREEN_GATE
@ BG_SA_CENTRAL_FLAG
@ BG_SA_SIGIL_1
@ BG_SA_RED_GATE
@ BG_SA_LEFT_FLAGPOLE
@ BG_SA_PURPLE_GATE
@ BG_SA_RIGHT_FLAG
@ BG_SA_BLUE_GATE
@ BG_SA_PORTAL_DEFFENDER_RED
@ BG_SA_BOAT_TWO
@ BG_SA_ANCIENT_GATE
@ BG_SA_LEFT_FLAG
@ BG_SA_TITAN_RELIC
@ BG_SA_BOMB
#define MAX_GATES
@ BG_SA_EVENT_TITAN_RELIC_ACTIVATED
Position const BG_SA_NpcSpawnlocs[BG_SA_MAXNPC]
@ BG_SA_GUN_10
@ BG_SA_DEMOLISHER_1
@ BG_SA_DEMOLISHER_4
@ BG_SA_DEMOLISHER_6
@ BG_SA_DEMOLISHER_7
@ BG_SA_DEMOLISHER_5
@ BG_SA_MAXNPC
@ BG_SA_NPC_RIGSPARK
@ BG_SA_NPC_SPARKLIGHT
@ BG_SA_GUN_1
@ BG_SA_NPC_KANRETHAD
@ BG_SA_DEMOLISHER_8
uint32 const BG_SA_NpcEntries[BG_SA_MAXNPC]
@ BG_SA_TEXT_ROUND_TWO_START_ONE_MINUTE
@ BG_SA_TEXT_ALLIANCE_CAPTURED_TITAN_PORTAL
@ BG_SA_TEXT_ROUND_TWO_START_HALF_MINUTE
@ BG_SA_TEXT_HORDE_CAPTURED_TITAN_PORTAL
@ SCORE_BONUS_HONOR
@ SCORE_DESTROYED_WALL
@ SCORE_DESTROYED_DEMOLISHER
@ BG_CRITERIA_CHECK_DEFENSE_OF_THE_ANCIENTS
@ BG_CRITERIA_CHECK_NOT_EVEN_A_SCRATCH
@ RESPAWN_IMMEDIATELY
@ RESPAWN_ONE_DAY
@ STATUS_WAIT_JOIN
@ STATUS_IN_PROGRESS
@ BG_STARTING_EVENT_FOURTH
@ ACHIEVEMENT_TIMED_TYPE_EVENT
Definition DBCEnums.h:122
@ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET
Definition DBCEnums.h:154
DBCStorage< WorldSafeLocsEntry > sWorldSafeLocsStore(WorldSafeLocsEntryfmt)
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
#define ABORT
Definition Errors.h:74
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ SPELL_PREPARATION
Definition PlayerAI.cpp:174
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
@ GAMEOBJECT_TYPE_GOOBER
@ GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ ALLIANCE
@ HORDE
@ CHAT_MSG_BG_SYSTEM_ALLIANCE
@ CHAT_MSG_BG_SYSTEM_HORDE
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
@ GO_FLAG_NOT_SELECTABLE
@ SPELL_AURA_MOD_SHAPESHIFT
@ SPELL_AURA_SPIRIT_OF_REDEMPTION
@ MOVEMENTFLAG_ONTRANSPORT
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_UNINTERACTIBLE
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
bool TimerEnabled
used for know we are in timer phase or not (used for worldstate update)
GateInfo const * GetGate(uint32 entry)
Return GateInfo, relative to bg data, according to gameobject entry.
void SendTransportInit(Player *player)
Send packet to player for create boats (client part)
void ToggleTimer()
Switch on/off timer worldstate.
BG_SA_Status Status
Statu of battle (Start or not, and what round)
void PostUpdateImpl(uint32 diff) override
Called every time for update battle data -Update timer -Round switch.
TeamId Attackers
Id of attacker team.
uint32 EndRoundTimer
Max time of round.
void EventPlayerClickedOnFlag(Player *source, GameObject *go) override
Called when a player click on flag (graveyard flag)
bool SignaledRoundTwo
for know if warning about second round start has been sent
void EndBattleground(uint32 winner) override
Called on battleground ending.
void DemolisherStartState(bool start)
Set selectable or not demolisher, called on battle start, when boats arrive to dock.
void OverrideGunFaction()
Called on start and between the two round -Update faction of all vehicle.
void Reset() override
void RemovePlayer(Player *player, ObjectGuid guid, uint32 team) override
Called when a player leave battleground.
void StartingEventCloseDoors() override
Called when battle start.
bool SignaledRoundTwoHalfMin
for know if warning about second round start has been sent
void TeleportPlayers()
Called between the two round -Teleport all players to good location.
bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const *source, Unit const *target=nullptr, uint32 miscValue=0) override
void SendTime()
Update timer worldstate.
bool _allVehiclesAlive[PVP_TEAMS_COUNT]
void HandleKillUnit(Creature *creature, Player *killer) override
Called when a player kill a unit in bg.
void DestroyGate(Player *player, GameObject *go) override
Called when a gate is destroy -Give honor to player witch destroy it -Update worldstate -Delete gameo...
void StartingEventOpenDoors() override
BG_SA_RoundScore RoundScores[2]
Score of each round.
void CaptureGraveyard(BG_SA_Graveyards i, Player *Source)
Called when a graveyard is capture -Update spiritguide -Update gameobject (flag) -Update Worldstate -...
uint32 UpdateWaitTimer
5secs before starting the 1min countdown for second round
void HandleAreaTrigger(Player *Source, uint32 Trigger) override
void AddPlayer(Player *player) override
Called when a player join battle.
void UpdateDemolisherSpawns()
Respawn dead demolisher.
BG_SA_GateState GateStatus[MAX_GATES]
Status of each gate (Destroy/Damage/Intact)
WorldSafeLocsEntry const * GetClosestGraveyard(Player *player) override
Return the nearest graveyard where player can respawn.
bool SetupBattleground() override
Called for ini battleground, after that the first player be entered.
bool ShipsStarted
For know if boats has start moving or not yet.
bool InitSecondRound
for know if second round has been init
bool ResetObjs()
Called on setup and between the two round -Delete all gameobject / creature -Respawn all gameobject /...
std::map< uint32, uint32 > DemoliserRespawnList
bool IsSpellAllowed(uint32 spellId, Player const *player) const override
void TeleportToEntrancePosition(Player *player)
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates &packet) override
Called for generate packet contain worldstate data.
void TitanRelicActivated(Player *clicker)
Called when a player clicked on relic.
void StartShips()
Called for start ship movement.
bool CanInteractWithObject(uint32 objectId)
Checks if a player can interact with the given object.
void ProcessEvent(WorldObject *, uint32, WorldObject *=nullptr) override
Called when someone activates an event.
void SendTransportsRemove(Player *player)
Send packet to player for destroy boats (client part)
void UpdateObjectInteractionFlags()
TeamId GraveyardStatus[BG_SA_MAX_GY]
Team witch conntrol each graveyard.
uint32 TotalTime
Totale elapsed time of current round.
virtual void AddPlayer(Player *player)
virtual void EndBattleground(uint32 winner)
virtual Creature * AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId teamId=TEAM_NEUTRAL, uint32 respawntime=0, Transport *transport=nullptr)
void CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
static TeamId GetTeamIndexByTeamId(uint32 Team)
void DoorOpen(uint32 type)
bool DelCreature(uint32 type)
void SpawnBGObject(uint32 type, uint32 respawntime)
virtual bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime=0, GOState goState=GO_STATE_READY)
GuidVector BgObjects
Creature * GetBGCreature(uint32 type, bool logError=true)
BattlegroundMap * GetBgMap() const
virtual bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId=TEAM_NEUTRAL)
GuidVector BgCreatures
void SendChatMessage(Creature *source, uint8 textId, WorldObject *target=nullptr)
void SetStatus(BattlegroundStatus Status)
bool IsPlayerInBattleground(ObjectGuid guid) const
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const *target=nullptr)
bool DelObject(uint32 type)
BattlegroundPlayerMap const & GetPlayers() const
BattlegroundScoreMap PlayerScores
void RewardHonorToTeam(uint32 Honor, uint32 TeamID)
BattlegroundStatus GetStatus() const
virtual bool UpdatePlayerScore(Player *player, uint32 type, uint32 value, bool doAddHonor=true)
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
virtual bool CheckAchievementCriteriaMeet(uint32, Player const *, Unit const *=nullptr, uint32=0)
void UpdateWorldState(uint32 variable, uint32 value)
uint32 GetBonusHonorFromKill(uint32 kills) const
GameObject * GetBGObject(uint32 type, bool logError=true)
void PlaySoundToAll(uint32 soundID)
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]
void Refresh()
void SetParentRotation(QuaternionData const &rotation)
void SetFaction(uint32 faction) override
Definition GameObject.h:286
void UpdateAreaDependentAuras()
Definition Map.cpp:4823
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player const *target) const
Definition Object.cpp:214
static Unit * ToUnit(Object *o)
Definition Object.h:192
static GameObject * ToGameObject(Object *o)
Definition Object.h:198
virtual void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition Object.cpp:170
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void BuildOutOfRangeUpdateBlock(UpdateData *data) const
Definition Object.cpp:226
static Player * ToPlayer(Object *o)
Definition Object.h:180
uint32 GetTeam() const
Definition Player.h:1832
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
TeamId GetTeamId() const
Definition Player.h:1833
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
Definition Unit.h:769
void SetFaction(uint32 faction) override
Definition Unit.h:974
void AddUnitMovementFlag(uint32 f)
Definition Unit.h:1676
bool BuildPacket(WorldPacket *packet)
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2099
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:2203
std::vector< WorldStateInfo > Worldstates
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
void BuildObjectivesBlock(WorldPackets::Battleground::PVPLogData_Player &playerData) override
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetExactDistSq(float x, float y, float z) const
Definition Position.h:113
DBCPosition3D Loc