TrinityCore
Loading...
Searching...
No Matches
battleground_twin_peaks.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 "AreaTrigger.h"
19#include "Battleground.h"
20#include "BattlegroundScript.h"
21#include "GameObject.h"
22#include "GameTime.h"
23#include "Map.h"
24#include "ObjectAccessor.h"
25#include "Player.h"
26#include "ScriptMgr.h"
27#include "SpellAuras.h"
28#include "Timer.h"
29
30namespace TwinPeaks
31{
32 namespace AreaTriggers
33 {
34 static constexpr uint32 CapturePointAlliance = 30;
35 static constexpr uint32 CapturePointHorde = 31;
36 }
37
38 namespace Events
39 {
40 static constexpr uint32 StartBattle = 35912;
41 }
42
43 namespace GameObjects
44 {
45 static constexpr uint32 GhostGate = 180322;
46 static constexpr uint32 Gate1 = 208205;
47 static constexpr uint32 Gate2 = 208207;
48 static constexpr uint32 Gate3 = 208206;
49 static constexpr uint32 Portcullis = 203710;
50 static constexpr uint32 HordeFlag = 227740;
51 static constexpr uint32 AllianceFlag = 227741;
52 static constexpr uint32 WildHammerGate1 = 206653;
53 static constexpr uint32 WildHammerGate2 = 206654;
54 static constexpr uint32 WildHammerGate3 = 206655;
55 }
56
57 namespace Misc
58 {
59 static constexpr uint8 MaxTeamScore = 3;
60 static constexpr uint8 FlagBrutalAssaultStackCount = 5;
61 }
62
63 namespace PvpStats
64 {
65 static constexpr uint32 FlagCaptures = 290;
66 static constexpr uint32 FlagReturns = 291;
67 }
68
69 namespace Sounds
70 {
71 static constexpr uint32 PvpFlagCapturedAlliance = 8173;
72 static constexpr uint32 PvpFlagCapturedHorde = 8213;
73 static constexpr uint32 FlagReturned = 8192;
74 static constexpr uint32 PvpFlagTakenHorde = 8212;
75 static constexpr uint32 PvpFlagTakenAlliance = 8174;
76 static constexpr uint32 FlagsRespawned = 8232;
77 }
78
79 namespace Spells
80 {
81 static constexpr uint32 FocusedAssault = 46392;
82 static constexpr uint32 BrutalAssault = 46393;
83 static constexpr uint32 QuickCapTimer = 183317;
84 static constexpr uint32 CapturedAllianceCosmeticFx = 262508;
85 static constexpr uint32 CapturedHordeCosmeticFx = 262512;
86 }
87
88 namespace Texts
89 {
90 static constexpr uint32 CapturedHordeFlag = 9801;
91 static constexpr uint32 CapturedAllianceFlag = 9802;
92 static constexpr uint32 FlagsPlaced = 9803;
93 static constexpr uint32 AllianceFlagPickedUp = 9804;
94 static constexpr uint32 AllianceFlagDropped = 9805;
95 static constexpr uint32 HordeFlagPickedUp = 9807;
96 static constexpr uint32 HordeFlagDropped = 9806;
97 static constexpr uint32 AllianceFlagReturned = 9808;
98 static constexpr uint32 HordeFlagReturned = 9809;
99 }
100
101 namespace Timers
102 {
103 static constexpr Seconds FlagAssaultTimer = 30s;
104 }
105
106 namespace WorldStates
107 {
108 static constexpr uint32 FlagStateAlliance = 1545;
109 static constexpr uint32 FlagStateHorde = 1546;
110 static constexpr uint32 FlagCapturesAlliance = 1581;
111 static constexpr uint32 FlagCapturesHorde = 1582;
112 static constexpr uint32 FlagControlHorde = 2338;
113 static constexpr uint32 FlagControlAlliance = 2339;
114 static constexpr uint32 Timer = 4248;
115 static constexpr uint32 TimerActive = 4247;
116 static constexpr uint32 DoubleJeopardyAllianceEnabled = 5746;
117 static constexpr uint32 DoubleJeopardyHordeEnabled = 5747;
118 }
119}
120
122{
127
128 void OnUpdate(uint32 diff) override
129 {
131
133 {
135 {
137 {
138 if (battleground->GetTeamScore(TEAM_HORDE) == 0) // No one scored - result is tie
140 else // Horde has more points and thus wins
142 }
143 else if (battleground->GetTeamScore(TEAM_HORDE) == 0) // Alliance has > 0, Horde has 0, alliance wins
145 else if (battleground->GetTeamScore(TEAM_HORDE) == battleground->GetTeamScore(TEAM_ALLIANCE)) // Team score equal, winner is team that scored the last flag
147 else if (battleground->GetTeamScore(TEAM_HORDE) > battleground->GetTeamScore(TEAM_ALLIANCE)) // Last but not least, check who has the higher score
149 else
151 }
152 }
153
154 if (_bothFlagsKept)
155 {
158 {
160 if (_assaultStackCount < std::numeric_limits<uint8>::max())
161 {
163
164 // update assault debuff stacks
165 DoForFlagKeepers([&](Player* player) -> void
166 {
168 });
169 }
170 }
171 }
172 }
173
174 void OnStart() override
175 {
177 for (ObjectGuid door : _doors)
178 {
179 if (GameObject* gameObject = battlegroundMap->GetGameObject(door))
180 {
181 gameObject->UseDoorOrButton();
182 gameObject->DespawnOrUnsummon(3s);
183 }
184 }
185
187 UpdateWorldState(TwinPeaks::WorldStates::Timer, std::chrono::system_clock::to_time_t(GameTime::GetSystemTime() + 15min));
188
189 // players joining later are not eligibles
191 }
192
193 template <std::invocable<Player*> Action>
194 void DoForFlagKeepers(Action const& action) const
195 {
196 for (ObjectGuid flagGUID : _flags)
197 if (GameObject const* flag = battlegroundMap->GetGameObject(flagGUID))
198 if (Player* carrier = ObjectAccessor::FindPlayer(flag->GetFlagCarrierGUID()))
199 action(carrier);
200 }
201
203 {
204 _bothFlagsKept = false;
207 DoForFlagKeepers([&](Player* player) -> void
208 {
210 });
211 }
212
214 {
215 if (_assaultStackCount == 0)
216 return;
217
220 {
223 }
224
225 Aura* aura = player->GetAura(spellId);
226 if (!aura)
227 {
228 player->CastSpell(player, spellId, true);
229 aura = player->GetAura(spellId);
230 }
231
232 if (aura)
234 }
235
241
243 {
244 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
245 return flag->GetFlagState();
246
247 return FlagState(0);
248 }
249
251 {
252 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
253 return flag->GetFlagCarrierGUID();
254
255 return ObjectGuid::Empty;
256 }
257
259 {
260 DoForFlagKeepers([&](Player* player) -> void
261 {
264 if (trigger->GetInsideUnits().contains(player->GetGUID()))
265 if (CanCaptureFlag(trigger, player))
266 OnCaptureFlag(trigger, player);
267 });
268 }
269
270 void UpdateFlagState(uint32 team, FlagState value) const
271 {
272 auto transformValueToOtherTeamControlWorldState = [](FlagState state)
273 {
274 switch (state)
275 {
279 return 1;
280 case FlagState::Taken:
281 return 2;
282 default:
283 return 0;
284 }
285 };
286
287 if (team == ALLIANCE)
288 {
290 UpdateWorldState(TwinPeaks::WorldStates::FlagControlHorde, transformValueToOtherTeamControlWorldState(value));
291 }
292 else
293 {
295 UpdateWorldState(TwinPeaks::WorldStates::FlagControlAlliance, transformValueToOtherTeamControlWorldState(value));
296 }
297 }
298
299 void UpdateTeamScore(TeamId team) const
300 {
301 if (team == TEAM_ALLIANCE)
303 else
305
306 TeamId const otherTeam = GetOtherTeam(team);
307 uint32 const teamScore = battleground->GetTeamScore(team);
308 uint32 const otherTeamScore = battleground->GetTeamScore(otherTeam);
309 if (teamScore == 2 && otherTeamScore == 0)
311 }
312
313 void OnGameObjectCreate(GameObject* gameObject) override
314 {
316 switch (gameObject->GetEntry())
317 {
326 _doors.insert(gameObject->GetGUID());
327 break;
329 _flags[TEAM_ALLIANCE] = gameObject->GetGUID();
330 break;
332 _flags[TEAM_HORDE] = gameObject->GetGUID();
333 break;
334 default:
335 break;
336 }
337 }
338
339 void OnAreaTriggerCreate(AreaTrigger* areaTrigger) override
340 {
342 if (!areaTrigger->IsStaticSpawn())
343 return;
344
345 switch (areaTrigger->GetEntry())
346 {
349 break;
352 break;
353 default:
354 break;
355 }
356 }
357
358 void OnFlagStateChange(GameObject* flagInBase, FlagState oldValue, FlagState newValue, Player* player) override
359 {
360 BattlegroundScript::OnFlagStateChange(flagInBase, oldValue, newValue, player);
361
362 Team const team = flagInBase->GetEntry() == TwinPeaks::GameObjects::HordeFlag ? HORDE : ALLIANCE;
363 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
364
365 UpdateFlagState(team, newValue);
366
367 switch (newValue)
368 {
370 {
372 {
374 if (player)
375 {
376 // flag got returned to base by player interaction
377 battleground->UpdatePvpStat(player, TwinPeaks::PvpStats::FlagReturns, 1); // +1 flag returns
378
379 if (team == ALLIANCE)
380 {
383 }
384 else
385 {
388 }
389 }
390 // Flag respawned due to timeout/capture
391 else if (GetFlagState(otherTeamId) != FlagState::Respawning)
392 {
393 // if other flag is respawning, we will let that one handle the message and sound to prevent double message/sound.
396 }
397
399 }
400 break;
401 }
403 {
406
407 uint32 recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_HORDE_FLAG;
408 if (team == ALLIANCE)
409 {
410 recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_ALLIANCE_FLAG;
412 }
413 else
415
416 player->CastSpell(player, recentlyDroppedSpellId, true);
417 break;
418 }
419 case FlagState::Taken:
420 {
421 if (team == HORDE)
422 {
425 }
426 else
427 {
430 }
431
432 if (GetFlagState(otherTeamId) == FlagState::Taken)
433 _bothFlagsKept = true;
434
436
437 flagInBase->CastSpell(player, TwinPeaks::Spells::QuickCapTimer, true);
439 break;
440 }
443 break;
444 default:
445 break;
446 }
447 }
448
449 bool CanCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
450 {
452 return false;
453
454 Team const team = battleground->GetPlayerTeam(player->GetGUID());
455 TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
456 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
457
458 if (areaTrigger->GetGUID() != _capturePointAreaTriggers[teamId])
459 return false;
460
461 // check if enemy flag's carrier is this player
462 if (GetFlagCarrierGUID(otherTeamId) != player->GetGUID())
463 return false;
464
465 // check that team's flag is in base
466 return GetFlagState(teamId) == FlagState::InBase;
467 }
468
469 void OnCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
470 {
471 BattlegroundScript::OnCaptureFlag(areaTrigger, player);
472
473 Team winner = TEAM_OTHER;
474
475 Team const team = battleground->GetPlayerTeam(player->GetGUID());
476 TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
477 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
478
479 /*
480 1. Update flag states & score world states
481 2. update points
482 3. chat message & sound
483 4. update criterias & achievements
484 5. remove all related auras
485 ?. Reward honor & reputation
486 */
487
488 // 1. update the flag states
489 for (ObjectGuid const& flagGuid : _flags)
490 if (GameObject const* flag = battlegroundMap->GetGameObject(flagGuid))
491 flag->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Respawning, player));
492
493 // 2. update points
495 battleground->AddPoint(team, 1);
496
497 UpdateTeamScore(teamId);
498
499 // 3. chat message & sound
500 if (team == ALLIANCE)
501 {
505 }
506 else
507 {
511 }
512
513 // 4. update criteria's for achievement, player score etc.
514 battleground->UpdatePvpStat(player, TwinPeaks::PvpStats::FlagCaptures, 1); // +1 flag captures
515
516 // 5. Remove all related auras
518
519 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[otherTeamId]))
520 player->RemoveAurasDueToSpell(flag->GetGOInfo()->newflag.pickupSpell, flag->GetGUID());
521
523
525
527
528 // update last flag capture to be used if teamscore is equal
529 SetLastFlagCapture(team);
530
532 winner = team;
533
534 if (winner)
535 {
539
541 }
542 }
543
553
555 {
557 }
558
559private:
563 std::array<ObjectGuid, PVP_TEAMS_COUNT> _flags;
564
567 std::array<ObjectGuid, PVP_TEAMS_COUNT> _capturePointAreaTriggers;
568};
569
@ SPELL_RECENTLY_DROPPED_ALLIANCE_FLAG
@ SPELL_RECENTLY_DROPPED_HORDE_FLAG
@ STATUS_IN_PROGRESS
@ IN_MILLISECONDS
Definition Common.h:38
@ MINUTE
Definition Common.h:32
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
FlagState
Definition GameObject.h:46
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:432
Spells
Definition PlayerAI.cpp:32
#define RegisterBattlegroundMapScript(script_name, mapId)
Definition ScriptMgr.h:1447
@ TEAM_ALLIANCE
@ TEAM_HORDE
constexpr TeamId GetOtherTeam(TeamId team)
@ TEAM_OTHER
@ ALLIANCE
@ HORDE
@ CHAT_MSG_BG_SYSTEM_ALLIANCE
@ CHAT_MSG_BG_SYSTEM_HORDE
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
void AddSC_battleground_twin_peaks()
Action
Sounds
bool IsStaticSpawn() const
void SetStackAmount(uint8 num)
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
Battleground * battleground
void TriggerGameEvent(uint32 gameEventId, WorldObject *source=nullptr, WorldObject *target=nullptr) override
BattlegroundMap * battlegroundMap
virtual void OnUpdate(uint32 diff)
virtual Team GetPrematureWinner()
void UpdateWorldState(int32 worldStateId, int32 value, bool hidden=false) const
void PlaySoundToAll(uint32 SoundID)
uint32 GetTeamScore(TeamId teamId) const
void RewardHonorToTeam(uint32 Honor, Team team)
static TeamId GetTeamIndexByTeamId(Team team)
virtual void EndBattleground(Team winner)
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const *target=nullptr)
BattlegroundStatus GetStatus() const
void AddPoint(Team team, uint32 points=1)
Team GetPlayerTeam(ObjectGuid guid) const
uint32 GetBonusHonorFromKill(uint32 kills) const
void UpdatePvpStat(Player *player, uint32 pvpStatId, uint32 value)
uint32 GetElapsedTime() const
time_t GetFlagTakenFromBaseTime() const
GameObject * GetGameObject(ObjectGuid const &guid)
Definition Map.cpp:3552
AreaTrigger * GetAreaTrigger(ObjectGuid const &guid)
Definition Map.cpp:3517
static ObjectGuid const Empty
Definition ObjectGuid.h:314
uint32 GetEntry() const
Definition Object.h:89
void StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost=Milliseconds::zero())
Definition Player.cpp:27577
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4700
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition Unit.cpp:4241
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
virtual void OnCaptureFlag(AreaTrigger *areaTrigger, Player *player)
Definition ZoneScript.h:109
virtual void OnFlagStateChange(GameObject *flagInBase, FlagState oldValue, FlagState newValue, Player *player)
Definition ZoneScript.h:106
virtual void OnAreaTriggerCreate(AreaTrigger *areaTrigger)
Definition ZoneScript.h:82
virtual void OnGameObjectCreate(GameObject *)
Definition ZoneScript.h:79
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition GameTime.cpp:62
time_t GetGameTime()
Definition GameTime.cpp:52
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
static constexpr uint32 CapturePointHorde
static constexpr uint32 CapturePointAlliance
static constexpr uint32 StartBattle
static constexpr uint32 Portcullis
static constexpr uint32 HordeFlag
static constexpr uint32 Gate1
static constexpr uint32 AllianceFlag
static constexpr uint32 WildHammerGate1
static constexpr uint32 WildHammerGate2
static constexpr uint32 WildHammerGate3
static constexpr uint32 GhostGate
static constexpr uint32 Gate3
static constexpr uint32 Gate2
static constexpr uint8 FlagBrutalAssaultStackCount
static constexpr uint8 MaxTeamScore
static constexpr uint32 FlagCaptures
static constexpr uint32 FlagReturns
static constexpr uint32 PvpFlagCapturedAlliance
static constexpr uint32 PvpFlagTakenHorde
static constexpr uint32 FlagsRespawned
static constexpr uint32 PvpFlagTakenAlliance
static constexpr uint32 FlagReturned
static constexpr uint32 PvpFlagCapturedHorde
static constexpr uint32 CapturedAllianceCosmeticFx
static constexpr uint32 BrutalAssault
static constexpr uint32 QuickCapTimer
static constexpr uint32 FocusedAssault
static constexpr uint32 CapturedHordeCosmeticFx
static constexpr uint32 FlagsPlaced
static constexpr uint32 AllianceFlagReturned
static constexpr uint32 AllianceFlagPickedUp
static constexpr uint32 CapturedHordeFlag
static constexpr uint32 CapturedAllianceFlag
static constexpr uint32 HordeFlagDropped
static constexpr uint32 HordeFlagPickedUp
static constexpr uint32 AllianceFlagDropped
static constexpr uint32 HordeFlagReturned
static constexpr Seconds FlagAssaultTimer
static constexpr uint32 TimerActive
static constexpr uint32 FlagControlAlliance
static constexpr uint32 FlagStateHorde
static constexpr uint32 DoubleJeopardyAllianceEnabled
static constexpr uint32 FlagControlHorde
static constexpr uint32 FlagCapturesHorde
static constexpr uint32 Timer
static constexpr uint32 DoubleJeopardyHordeEnabled
static constexpr uint32 FlagStateAlliance
static constexpr uint32 FlagCapturesAlliance
void Update(int32 diff)
Definition Timer.h:121
bool Passed() const
Definition Timer.h:131
void Reset(int32 expiry)
Definition Timer.h:136
void UpdateFlagState(uint32 team, FlagState value) const
void OnCaptureFlag(AreaTrigger *areaTrigger, Player *player) override
void OnAreaTriggerCreate(AreaTrigger *areaTrigger) override
void RemoveAssaultDebuffFromPlayer(Player *player) const
std::array< ObjectGuid, PVP_TEAMS_COUNT > _capturePointAreaTriggers
void OnUpdate(uint32 diff) override
bool CanCaptureFlag(AreaTrigger *areaTrigger, Player *player) override
void ApplyAssaultDebuffToPlayer(Player *player) const
void DoForFlagKeepers(Action const &action) const
void UpdateTeamScore(TeamId team) const
std::array< ObjectGuid, PVP_TEAMS_COUNT > _flags
FlagState GetFlagState(TeamId team) const
ObjectGuid const & GetFlagCarrierGUID(TeamId team) const
void OnFlagStateChange(GameObject *flagInBase, FlagState oldValue, FlagState newValue, Player *player) override
battleground_twin_peaks(BattlegroundMap *map)
void OnGameObjectCreate(GameObject *gameObject) override