TrinityCore
Loading...
Searching...
No Matches
battleground_warsong_gulch.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 "BattlegroundScript.h"
20#include "Battleground.h"
21#include "BattlegroundMgr.h"
22#include "GameObject.h"
23#include "GameTime.h"
24#include "Map.h"
25#include "ObjectAccessor.h"
26#include "Player.h"
27#include "ScriptMgr.h"
28#include "SpellAuras.h"
29#include "Timer.h"
30
32{
33 static constexpr Seconds FLAG_ASSAULT_TIMER = 30s;
34
40
53
59
61 {
62 EVENT_START_BATTLE = 35912
63 };
64
70
87
103
114
126
127 static constexpr std::array<std::array<uint32, 3>, 2> HONOR_REWARDS =
128 {{
129 { 20, 40, 40 },
130 { 60, 40, 80 }
131 }};
132
150
151 void OnUpdate(uint32 diff) override
152 {
154
156 {
158 {
160 {
161 if (battleground->GetTeamScore(TEAM_HORDE) == 0) // No one scored - result is tie
163 else // Horde has more points and thus wins
165 }
166 else if (battleground->GetTeamScore(TEAM_HORDE) == 0) // Alliance has > 0, Horde has 0, alliance wins
168 else if (battleground->GetTeamScore(TEAM_HORDE) == battleground->GetTeamScore(TEAM_ALLIANCE)) // Team score equal, winner is team that scored the last flag
170 else if (battleground->GetTeamScore(TEAM_HORDE) > battleground->GetTeamScore(TEAM_ALLIANCE)) // Last but not least, check who has the higher score
172 else
174 }
175 }
176
177 if (_bothFlagsKept)
178 {
181 {
183 if (_assaultStackCount < std::numeric_limits<uint8>::max())
184 {
186
187 // update assault debuff stacks
188 DoForFlagKeepers([&](Player* player) -> void
189 {
191 });
192 }
193 }
194 }
195 }
196
197 void OnStart() override
198 {
200 for (ObjectGuid door : _doors)
201 {
202 if (GameObject* gameObject = battlegroundMap->GetGameObject(door))
203 {
204 gameObject->UseDoorOrButton();
205 gameObject->DespawnOrUnsummon(3s);
206 }
207 }
208
210 UpdateWorldState(WORLD_STATE_STATE_TIMER, std::chrono::system_clock::to_time_t(GameTime::GetSystemTime() + 15min));
211
212 // players joining later are not eligibles
214 }
215
229
230 template <std::invocable<Player*> Action>
231 void DoForFlagKeepers(Action const& action) const
232 {
233 for (ObjectGuid flagGUID : _flags)
234 if (GameObject const* flag = battlegroundMap->GetGameObject(flagGUID))
235 if (Player* carrier = ObjectAccessor::FindPlayer(flag->GetFlagCarrierGUID()))
236 action(carrier);
237 }
238
240 {
241 _bothFlagsKept = false;
244 DoForFlagKeepers([&](Player* player) -> void
245 {
247 });
248 }
249
251 {
252 if (_assaultStackCount == 0)
253 return;
254
257 {
259 spellId = SPELL_BRUTAL_ASSAULT;
260 }
261
262 Aura* aura = player->GetAura(spellId);
263 if (!aura)
264 {
265 player->CastSpell(player, spellId, true);
266 aura = player->GetAura(spellId);
267 }
268
269 if (aura)
271 }
272
278
280 {
281 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
282 return flag->GetFlagState();
283
284 return FlagState(0);
285 }
286
288 {
289 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[team]))
290 return flag->GetFlagCarrierGUID();
291
292 return ObjectGuid::Empty;
293 }
294
296 {
297 DoForFlagKeepers([&](Player* player) -> void
298 {
301 if (trigger->GetInsideUnits().contains(player->GetGUID()))
302 if (CanCaptureFlag(trigger, player))
303 OnCaptureFlag(trigger, player);
304 });
305 }
306
307 void UpdateFlagState(uint32 team, FlagState value) const
308 {
309 auto transformValueToOtherTeamControlWorldState = [](FlagState state)
310 {
311 switch (state)
312 {
316 return 1;
317 case FlagState::Taken:
318 return 2;
319 default:
320 return 0;
321 }
322 };
323
324 if (team == ALLIANCE)
325 {
327 UpdateWorldState(WORLD_STATE_FLAG_CONTROL_HORDE, transformValueToOtherTeamControlWorldState(value));
328 }
329 else
330 {
332 UpdateWorldState(WORLD_STATE_FLAG_CONTROL_ALLIANCE, transformValueToOtherTeamControlWorldState(value));
333 }
334 }
335
343
344 void OnGameObjectCreate(GameObject* gameObject) override
345 {
347 switch (gameObject->GetEntry())
348 {
355 _doors.insert(gameObject->GetGUID());
356 break;
358 _flags[TEAM_ALLIANCE] = gameObject->GetGUID();
359 break;
361 _flags[TEAM_HORDE] = gameObject->GetGUID();
362 break;
363 default:
364 break;
365 }
366 }
367
368 void OnAreaTriggerCreate(AreaTrigger* areaTrigger) override
369 {
371 if (!areaTrigger->IsStaticSpawn())
372 return;
373
374 switch (areaTrigger->GetEntry())
375 {
378 break;
381 break;
382 default:
383 break;
384 }
385 }
386
387 void OnFlagStateChange(GameObject* flagInBase, FlagState oldValue, FlagState newValue, Player* player) override
388 {
389 BattlegroundScript::OnFlagStateChange(flagInBase, oldValue, newValue, player);
390
391 Team const team = flagInBase->GetEntry() == OBJECT_HORDE_FLAG_IN_BASE ? HORDE : ALLIANCE;
392 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
393
394 UpdateFlagState(team, newValue);
395
396 switch (newValue)
397 {
399 {
401 {
403 if (player)
404 {
405 // flag got returned to base by player interaction
406 battleground->UpdatePvpStat(player, PVP_STAT_FLAG_RETURNS, 1); // +1 flag returns
407
408 if (team == ALLIANCE)
409 {
412 }
413 else
414 {
417 }
418 }
419 // Flag respawned due to timeout/capture
420 else if (GetFlagState(otherTeamId) != FlagState::Respawning)
421 {
422 // if other flag is respawning, we will let that one handle the message and sound to prevent double message/sound.
425 }
426
428 }
429 break;
430 }
432 {
435
436 uint32 recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_HORDE_FLAG;
437 if (team == ALLIANCE)
438 {
439 recentlyDroppedSpellId = SPELL_RECENTLY_DROPPED_ALLIANCE_FLAG;
441 }
442 else
444
445 player->CastSpell(player, recentlyDroppedSpellId, true);
446 break;
447 }
448 case FlagState::Taken:
449 {
450 if (team == HORDE)
451 {
454 }
455 else
456 {
459 }
460
461 if (GetFlagState(otherTeamId) == FlagState::Taken)
462 _bothFlagsKept = true;
463
465
466 flagInBase->CastSpell(player, SPELL_QUICK_CAP_TIMER, true);
468 break;
469 }
472 break;
473 default:
474 break;
475 }
476 }
477
478 bool CanCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
479 {
481 return false;
482
483 Team const team = battleground->GetPlayerTeam(player->GetGUID());
484 TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
485 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
486
487 if (areaTrigger->GetGUID() != _capturePointAreaTriggers[teamId])
488 return false;
489
490 // check if enemy flag's carrier is this player
491 if (GetFlagCarrierGUID(otherTeamId) != player->GetGUID())
492 return false;
493
494 // check that team's flag is in base
495 return GetFlagState(teamId) == FlagState::InBase;
496 }
497
498 void OnCaptureFlag(AreaTrigger* areaTrigger, Player* player) override
499 {
500 BattlegroundScript::OnCaptureFlag(areaTrigger, player);
501
502 Team winner = TEAM_OTHER;
503
504 Team const team = battleground->GetPlayerTeam(player->GetGUID());
505 TeamId const teamId = Battleground::GetTeamIndexByTeamId(team);
506 TeamId const otherTeamId = Battleground::GetTeamIndexByTeamId(GetOtherTeam(team));
507
508 /*
509 1. Update flag states & score world states
510 2. update points
511 3. chat message & sound
512 4. update criterias & achievements
513 5. remove all related auras
514 ?. Reward honor & reputation
515 */
516
517 // 1. update the flag states
518 for (ObjectGuid const& flagGuid: _flags)
519 if (GameObject const* flag = battlegroundMap->GetGameObject(flagGuid))
520 flag->HandleCustomTypeCommand(GameObjectType::SetNewFlagState(FlagState::Respawning, player));
521
522 // 2. update points
524 battleground->AddPoint(team, 1);
525
526 UpdateTeamScore(teamId);
527
528 // 3. chat message & sound
529 if (team == ALLIANCE)
530 {
535 }
536 else
537 {
542 }
543
544 // 4. update criteria's for achievement, player score etc.
545 battleground->UpdatePvpStat(player, PVP_STAT_FLAG_CAPTURES, 1); // +1 flag captures
546
547 // 5. Remove all related auras
549
550 if (GameObject const* flag = battlegroundMap->GetGameObject(_flags[otherTeamId]))
551 player->RemoveAurasDueToSpell(flag->GetGOInfo()->newflag.pickupSpell, flag->GetGUID());
552
554
556
558
559 // update last flag capture to be used if teamscore is equal
560 SetLastFlagCapture(team);
561
563 winner = team;
564
565 if (winner)
566 {
570
573 }
574 }
575
585
587 {
589 }
590
591private:
595 std::array<ObjectGuid, PVP_TEAMS_COUNT> _flags;
596
599 std::array<ObjectGuid, PVP_TEAMS_COUNT> _capturePointAreaTriggers;
600
604};
605
#define sBattlegroundMgr
@ 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
int32_t int32
Definition Define.h:150
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
#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_warsong_gulch()
Action
bool IsStaticSpawn() const
void SetStackAmount(uint8 num)
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
Battleground * battleground
void TriggerGameEvent(uint32 gameEventId, WorldObject *source=nullptr, WorldObject *target=nullptr) override
BattlegroundMap * battlegroundMap
virtual void OnEnd(Team winner)
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)
BattlegroundTypeId GetTypeID() const
static TeamId GetTeamIndexByTeamId(Team team)
virtual void EndBattleground(Team winner)
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const *target=nullptr)
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, Team team)
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 &)
void Update(int32 diff)
Definition Timer.h:121
bool Passed() const
Definition Timer.h:131
void Reset(int32 expiry)
Definition Timer.h:136
static constexpr std::array< std::array< uint32, 3 >, 2 > HONOR_REWARDS
void DoForFlagKeepers(Action const &action) const
ObjectGuid const & GetFlagCarrierGUID(TeamId team) const
void OnGameObjectCreate(GameObject *gameObject) override
void ApplyAssaultDebuffToPlayer(Player *player) const
void OnFlagStateChange(GameObject *flagInBase, FlagState oldValue, FlagState newValue, Player *player) override
std::array< ObjectGuid, PVP_TEAMS_COUNT > _capturePointAreaTriggers
FlagState GetFlagState(TeamId team) const
void UpdateFlagState(uint32 team, FlagState value) const
void OnAreaTriggerCreate(AreaTrigger *areaTrigger) override
void OnCaptureFlag(AreaTrigger *areaTrigger, Player *player) override
void RemoveAssaultDebuffFromPlayer(Player *player) const
static constexpr Seconds FLAG_ASSAULT_TIMER
battleground_warsong_gulch(BattlegroundMap *map)
bool CanCaptureFlag(AreaTrigger *areaTrigger, Player *player) override
std::array< ObjectGuid, PVP_TEAMS_COUNT > _flags