/* * Copyright (C) 2012-2017 CypherCore * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using Framework.Constants; using Game.DataStorage; using Game.Entities; using Game.Network.Packets; using System.Collections.Generic; namespace Game.BattleGrounds { class BgWarsongGluch : Battleground { public BgWarsongGluch() { StartMessageIds[BattlegroundConst.EventIdFirst] = CypherStrings.BgWsStartTwoMinutes; StartMessageIds[BattlegroundConst.EventIdSecond] = CypherStrings.BgWsStartOneMinute; StartMessageIds[BattlegroundConst.EventIdThird] = CypherStrings.BgWsStartHalfMinute; StartMessageIds[BattlegroundConst.EventIdFourth] = CypherStrings.BgWsHasBegun; } public override void PostUpdateImpl(uint diff) { if (GetStatus() == BattlegroundStatus.InProgress) { if (GetElapsedTime() >= 27 * Time.Minute * Time.InMilliseconds) { if (GetTeamScore(TeamId.Alliance) == 0) { if (GetTeamScore(TeamId.Horde) == 0) // No one scored - result is tie EndBattleground(Team.Other); else // Horde has more points and thus wins EndBattleground(Team.Horde); } else if (GetTeamScore(TeamId.Horde) == 0) EndBattleground(Team.Alliance); // Alliance has > 0, Horde has 0, alliance wins else if (GetTeamScore(TeamId.Horde) == GetTeamScore(TeamId.Alliance)) // Team score equal, winner is team that scored the last flag EndBattleground((Team)_lastFlagCaptureTeam); else if (GetTeamScore(TeamId.Horde) > GetTeamScore(TeamId.Alliance)) // Last but not least, check who has the higher score EndBattleground(Team.Horde); else EndBattleground(Team.Alliance); } // first update needed after 1 minute of game already in progress else if (GetElapsedTime() > (_minutesElapsed * Time.Minute * Time.InMilliseconds) + 3 * Time.Minute * Time.InMilliseconds) { ++_minutesElapsed; UpdateWorldState(WSGWorldStates.StateTimer, (uint)(25 - _minutesElapsed)); } if (_flagState[TeamId.Alliance] == WSGFlagState.WaitRespawn) { _flagsTimer[TeamId.Alliance] -= (int)diff; if (_flagsTimer[TeamId.Alliance] < 0) { _flagsTimer[TeamId.Alliance] = 0; RespawnFlag(Team.Alliance, true); } } if (_flagState[TeamId.Alliance] == WSGFlagState.OnGround) { _flagsDropTimer[TeamId.Alliance] -= (int)diff; if (_flagsDropTimer[TeamId.Alliance] < 0) { _flagsDropTimer[TeamId.Alliance] = 0; RespawnFlagAfterDrop(Team.Alliance); _bothFlagsKept = false; } } if (_flagState[TeamId.Horde] == WSGFlagState.WaitRespawn) { _flagsTimer[TeamId.Horde] -= (int)diff; if (_flagsTimer[TeamId.Horde] < 0) { _flagsTimer[TeamId.Horde] = 0; RespawnFlag(Team.Horde, true); } } if (_flagState[TeamId.Horde] == WSGFlagState.OnGround) { _flagsDropTimer[TeamId.Horde] -= (int)diff; if (_flagsDropTimer[TeamId.Horde] < 0) { _flagsDropTimer[TeamId.Horde] = 0; RespawnFlagAfterDrop(Team.Horde); _bothFlagsKept = false; } } if (_bothFlagsKept) { _flagSpellForceTimer += (int)diff; if (_flagDebuffState == 0 && _flagSpellForceTimer >= 10 * Time.Minute * Time.InMilliseconds) //10 minutes { Player player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[0]); if (player) player.CastSpell(player, WSGSpellId.FocusedAssault, true); player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[1]); if (player) player.CastSpell(player, WSGSpellId.FocusedAssault, true); _flagDebuffState = 1; } else if (_flagDebuffState == 1 && _flagSpellForceTimer >= 900000) //15 minutes { Player player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[0]); if (player) { player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); player.CastSpell(player, WSGSpellId.BrutalAssault, true); } player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[1]); if (player) { player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); player.CastSpell(player, WSGSpellId.BrutalAssault, true); } _flagDebuffState = 2; } } else { Player player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[0]); if (player) { player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); } player = Global.ObjAccessor.FindPlayer(m_FlagKeepers[1]); if (player) { player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); } _flagSpellForceTimer = 0; //reset timer. _flagDebuffState = 0; } } } public override void GetPlayerPositionData(List positions) { Player player = Global.ObjAccessor.GetPlayer(GetBgMap(), m_FlagKeepers[TeamId.Alliance]); if (player) { BattlegroundPlayerPosition position = new BattlegroundPlayerPosition(); position.Guid = player.GetGUID(); position.Pos.X = player.GetPositionX(); position.Pos.Y = player.GetPositionY(); position.IconID = BattlegroundConst.PlayerPositionIconAllianceFlag; position.ArenaSlot = BattlegroundConst.PlayerPositionArenaSlotNone; positions.Add(position); } player = Global.ObjAccessor.GetPlayer(GetBgMap(), m_FlagKeepers[TeamId.Horde]); if (player) { BattlegroundPlayerPosition position = new BattlegroundPlayerPosition(); position.Guid = player.GetGUID(); position.Pos.X = player.GetPositionX(); position.Pos.Y = player.GetPositionY(); position.IconID = BattlegroundConst.PlayerPositionIconHordeFlag; position.ArenaSlot = BattlegroundConst.PlayerPositionArenaSlotNone; positions.Add(position); } } public override void StartingEventCloseDoors() { for (int i = WSGObjectTypes.DoorA1; i <= WSGObjectTypes.DoorH4; ++i) { DoorClose(i); SpawnBGObject(i, BattlegroundConst.RespawnImmediately); } for (int i = WSGObjectTypes.AFlag; i <= WSGObjectTypes.Berserkbuff2; ++i) SpawnBGObject(i, BattlegroundConst.RespawnOneDay); UpdateWorldState(WSGWorldStates.StateTimerActive, 1); UpdateWorldState(WSGWorldStates.StateTimer, 25); } public override void StartingEventOpenDoors() { for (int i = WSGObjectTypes.DoorA1; i <= WSGObjectTypes.DoorA6; ++i) DoorOpen(i); for (int i = WSGObjectTypes.DoorH1; i <= WSGObjectTypes.DoorH4; ++i) DoorOpen(i); for (int i = WSGObjectTypes.AFlag; i <= WSGObjectTypes.Berserkbuff2; ++i) SpawnBGObject(i, BattlegroundConst.RespawnImmediately); SpawnBGObject(WSGObjectTypes.DoorA5, BattlegroundConst.RespawnOneDay); SpawnBGObject(WSGObjectTypes.DoorA6, BattlegroundConst.RespawnOneDay); SpawnBGObject(WSGObjectTypes.DoorH3, BattlegroundConst.RespawnOneDay); SpawnBGObject(WSGObjectTypes.DoorH4, BattlegroundConst.RespawnOneDay); // players joining later are not eligibles StartCriteriaTimer(CriteriaTimedTypes.Event, 8563); } public override void AddPlayer(Player player) { base.AddPlayer(player); PlayerScores[player.GetGUID()] = new BattlegroundWGScore(player.GetGUID(), player.GetBGTeam()); } void RespawnFlag(Team Team, bool captured) { if (Team == Team.Alliance) { Log.outDebug(LogFilter.Battleground, "Respawn Alliance flag"); _flagState[TeamId.Alliance] = WSGFlagState.OnBase; } else { Log.outDebug(LogFilter.Battleground, "Respawn Horde flag"); _flagState[TeamId.Horde] = WSGFlagState.OnBase; } if (captured) { //when map_update will be allowed for Battlegrounds this code will be useless SpawnBGObject(WSGObjectTypes.HFlag, BattlegroundConst.RespawnImmediately); SpawnBGObject(WSGObjectTypes.AFlag, BattlegroundConst.RespawnImmediately); SendMessageToAll(CypherStrings.BgWsFPlaced, ChatMsg.BgSystemNeutral); PlaySoundToAll(WSGSound.FlagsRespawned); // flag respawned sound... } _bothFlagsKept = false; } void RespawnFlagAfterDrop(Team team) { if (GetStatus() != BattlegroundStatus.InProgress) return; RespawnFlag(team, false); if (team == Team.Alliance) { SpawnBGObject(WSGObjectTypes.AFlag, BattlegroundConst.RespawnImmediately); SendMessageToAll(CypherStrings.BgWsAllianceFlagRespawned, ChatMsg.BgSystemNeutral); } else { SpawnBGObject(WSGObjectTypes.HFlag, BattlegroundConst.RespawnImmediately); SendMessageToAll(CypherStrings.BgWsHordeFlagRespawned, ChatMsg.BgSystemNeutral); } PlaySoundToAll(WSGSound.FlagsRespawned); GameObject obj = GetBgMap().GetGameObject(GetDroppedFlagGUID(team)); if (obj) obj.Delete(); else Log.outError(LogFilter.Battleground, "unknown droped flag ({0})", GetDroppedFlagGUID(team).ToString()); SetDroppedFlagGUID(ObjectGuid.Empty, GetTeamIndexByTeamId(team)); _bothFlagsKept = false; } void EventPlayerCapturedFlag(Player player) { if (GetStatus() != BattlegroundStatus.InProgress) return; Team winner = 0; player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnterPvpCombat); if (player.GetTeam() == Team.Alliance) { if (!IsHordeFlagPickedup()) return; SetHordeFlagPicker(ObjectGuid.Empty); // must be before aura remove to prevent 2 events (drop+capture) at the same time // horde flag in base (but not respawned yet) _flagState[TeamId.Horde] = WSGFlagState.WaitRespawn; // Drop Horde Flag from Player player.RemoveAurasDueToSpell(WSGSpellId.WarsongFlag); if (_flagDebuffState == 1) player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); else if (_flagDebuffState == 2) player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); if (GetTeamScore(TeamId.Alliance) < WSGTimerOrScore.MaxTeamScore) AddPoint(Team.Alliance, 1); PlaySoundToAll(WSGSound.FlagCapturedAlliance); RewardReputationToTeam(890, m_ReputationCapture, Team.Alliance); } else { if (!IsAllianceFlagPickedup()) return; SetAllianceFlagPicker(ObjectGuid.Empty); // must be before aura remove to prevent 2 events (drop+capture) at the same time // alliance flag in base (but not respawned yet) _flagState[TeamId.Alliance] = WSGFlagState.WaitRespawn; // Drop Alliance Flag from Player player.RemoveAurasDueToSpell(WSGSpellId.SilverwingFlag); if (_flagDebuffState == 1) player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); else if (_flagDebuffState == 2) player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); if (GetTeamScore(TeamId.Horde) < WSGTimerOrScore.MaxTeamScore) AddPoint(Team.Horde, 1); PlaySoundToAll(WSGSound.FlagCapturedHorde); RewardReputationToTeam(889, m_ReputationCapture, Team.Horde); } //for flag capture is reward 2 honorable kills RewardHonorToTeam(GetBonusHonorFromKill(2), player.GetTeam()); SpawnBGObject(WSGObjectTypes.HFlag, WSGTimerOrScore.FlagRespawnTime); SpawnBGObject(WSGObjectTypes.AFlag, WSGTimerOrScore.FlagRespawnTime); if (player.GetTeam() == Team.Alliance) SendMessageToAll(CypherStrings.BgWsCapturedHf, ChatMsg.BgSystemAlliance, player); else SendMessageToAll(CypherStrings.BgWsCapturedAf, ChatMsg.BgSystemHorde, player); UpdateFlagState(player.GetTeam(), WSGFlagState.WaitRespawn); // flag state none UpdateTeamScore(player.GetTeamId()); // only flag capture should be updated UpdatePlayerScore(player, ScoreType.FlagCaptures, 1); // +1 flag captures // update last flag capture to be used if teamscore is equal SetLastFlagCapture(player.GetTeam()); if (GetTeamScore(TeamId.Alliance) == WSGTimerOrScore.MaxTeamScore) winner = Team.Alliance; if (GetTeamScore(TeamId.Horde) == WSGTimerOrScore.MaxTeamScore) winner = Team.Horde; if (winner != 0) { UpdateWorldState(WSGWorldStates.FlagUnkAlliance, 0); UpdateWorldState(WSGWorldStates.FlagUnkHorde, 0); UpdateWorldState(WSGWorldStates.FlagStateAlliance, 1); UpdateWorldState(WSGWorldStates.FlagStateHorde, 1); UpdateWorldState(WSGWorldStates.StateTimerActive, 0); RewardHonorToTeam(Honor[(int)m_HonorMode][(int)WSGRewards.Win], winner); EndBattleground(winner); } else { _flagsTimer[GetTeamIndexByTeamId(player.GetTeam())] = WSGTimerOrScore.FlagRespawnTime; } } public override void EventPlayerDroppedFlag(Player player) { if (GetStatus() != BattlegroundStatus.InProgress) { // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages // just take off the aura if (player.GetTeam() == Team.Alliance) { if (!IsHordeFlagPickedup()) return; if (GetFlagPickerGUID(TeamId.Horde) == player.GetGUID()) { SetHordeFlagPicker(ObjectGuid.Empty); player.RemoveAurasDueToSpell(WSGSpellId.WarsongFlag); } } else { if (!IsAllianceFlagPickedup()) return; if (GetFlagPickerGUID(TeamId.Alliance) == player.GetGUID()) { SetAllianceFlagPicker(ObjectGuid.Empty); player.RemoveAurasDueToSpell(WSGSpellId.SilverwingFlag); } } return; } bool set = false; if (player.GetTeam() == Team.Alliance) { if (!IsHordeFlagPickedup()) return; if (GetFlagPickerGUID(TeamId.Horde) == player.GetGUID()) { SetHordeFlagPicker(ObjectGuid.Empty); player.RemoveAurasDueToSpell(WSGSpellId.WarsongFlag); if (_flagDebuffState == 1) player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); else if (_flagDebuffState == 2) player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); _flagState[TeamId.Horde] = WSGFlagState.OnGround; player.CastSpell(player, WSGSpellId.WarsongFlagDropped, true); set = true; } } else { if (!IsAllianceFlagPickedup()) return; if (GetFlagPickerGUID(TeamId.Alliance) == player.GetGUID()) { SetAllianceFlagPicker(ObjectGuid.Empty); player.RemoveAurasDueToSpell(WSGSpellId.SilverwingFlag); if (_flagDebuffState == 1) player.RemoveAurasDueToSpell(WSGSpellId.FocusedAssault); else if (_flagDebuffState == 2) player.RemoveAurasDueToSpell(WSGSpellId.BrutalAssault); _flagState[TeamId.Alliance] = WSGFlagState.OnGround; player.CastSpell(player, WSGSpellId.SilverwingFlagDropped, true); set = true; } } if (set) { player.CastSpell(player, BattlegroundConst.SpellRecentlyDroppedFlag, true); UpdateFlagState(player.GetTeam(), WSGFlagState.WaitRespawn); if (player.GetTeam() == Team.Alliance) { SendMessageToAll(CypherStrings.BgWsDroppedHf, ChatMsg.BgSystemHorde, player); UpdateWorldState(WSGWorldStates.FlagUnkHorde, 0xFFFFFFFF); } else { SendMessageToAll(CypherStrings.BgWsDroppedAf, ChatMsg.BgSystemAlliance, player); UpdateWorldState(WSGWorldStates.FlagUnkAlliance, 0xFFFFFFFF); } _flagsDropTimer[GetTeamIndexByTeamId(GetOtherTeam(player.GetTeam()))] = WSGTimerOrScore.FlagDropTime; } } public override void EventPlayerClickedOnFlag(Player player, GameObject target_obj) { if (GetStatus() != BattlegroundStatus.InProgress) return; CypherStrings message_id = 0; ChatMsg type = ChatMsg.BgSystemNeutral; //alliance flag picked up from base if (player.GetTeam() == Team.Horde && GetFlagState(Team.Alliance) == WSGFlagState.OnBase && BgObjects[WSGObjectTypes.AFlag] == target_obj.GetGUID()) { message_id = CypherStrings.BgWsPickedupAf; type = ChatMsg.BgSystemHorde; PlaySoundToAll(WSGSound.AllianceFlagPickedUp); SpawnBGObject(WSGObjectTypes.AFlag, BattlegroundConst.RespawnOneDay); SetAllianceFlagPicker(player.GetGUID()); _flagState[TeamId.Alliance] = WSGFlagState.OnPlayer; //update world state to show correct flag carrier UpdateFlagState(Team.Horde, WSGFlagState.OnPlayer); UpdateWorldState(WSGWorldStates.FlagUnkAlliance, 1); player.CastSpell(player, WSGSpellId.SilverwingFlag, true); player.StartCriteriaTimer(CriteriaTimedTypes.SpellTarget, WSGSpellId.SilverwingFlagPicked); if (_flagState[1] == WSGFlagState.OnPlayer) _bothFlagsKept = true; } //horde flag picked up from base if (player.GetTeam() == Team.Alliance && GetFlagState(Team.Horde) == WSGFlagState.OnBase && BgObjects[WSGObjectTypes.HFlag] == target_obj.GetGUID()) { message_id = CypherStrings.BgWsPickedupHf; type = ChatMsg.BgSystemAlliance; PlaySoundToAll(WSGSound.HordeFlagPickedUp); SpawnBGObject(WSGObjectTypes.HFlag, BattlegroundConst.RespawnOneDay); SetHordeFlagPicker(player.GetGUID()); _flagState[TeamId.Horde] = WSGFlagState.OnPlayer; //update world state to show correct flag carrier UpdateFlagState(Team.Alliance, WSGFlagState.OnPlayer); UpdateWorldState(WSGWorldStates.FlagUnkHorde, 1); player.CastSpell(player, WSGSpellId.WarsongFlag, true); player.StartCriteriaTimer(CriteriaTimedTypes.SpellTarget, WSGSpellId.WarsongFlagPicked); if (_flagState[0] == WSGFlagState.OnPlayer) _bothFlagsKept = true; } //Alliance flag on ground(not in base) (returned or picked up again from ground!) if (GetFlagState(Team.Alliance) == WSGFlagState.OnGround && player.IsWithinDistInMap(target_obj, 10) && target_obj.GetGoInfo().entry == WSGObjectEntry.AFlagGround) { if (player.GetTeam() == Team.Alliance) { message_id = CypherStrings.BgWsReturnedAf; type = ChatMsg.BgSystemAlliance; UpdateFlagState(Team.Horde, WSGFlagState.WaitRespawn); RespawnFlag(Team.Alliance, false); SpawnBGObject(WSGObjectTypes.AFlag, BattlegroundConst.RespawnImmediately); PlaySoundToAll(WSGSound.FlagReturned); UpdatePlayerScore(player, ScoreType.FlagReturns, 1); _bothFlagsKept = false; } else { message_id = CypherStrings.BgWsPickedupAf; type = ChatMsg.BgSystemHorde; PlaySoundToAll(WSGSound.AllianceFlagPickedUp); SpawnBGObject(WSGObjectTypes.AFlag, BattlegroundConst.RespawnOneDay); SetAllianceFlagPicker(player.GetGUID()); player.CastSpell(player, WSGSpellId.SilverwingFlag, true); _flagState[TeamId.Alliance] = WSGFlagState.OnPlayer; UpdateFlagState(Team.Horde, WSGFlagState.OnPlayer); if (_flagDebuffState == 1) player.CastSpell(player, WSGSpellId.FocusedAssault, true); else if (_flagDebuffState == 2) player.CastSpell(player, WSGSpellId.BrutalAssault, true); UpdateWorldState(WSGWorldStates.FlagUnkAlliance, 1); } //called in HandleGameObjectUseOpcode: //target_obj.Delete(); } //Horde flag on ground(not in base) (returned or picked up again) if (GetFlagState(Team.Horde) == WSGFlagState.OnGround && player.IsWithinDistInMap(target_obj, 10) && target_obj.GetGoInfo().entry == WSGObjectEntry.HFlagGround) { if (player.GetTeam() == Team.Horde) { message_id = CypherStrings.BgWsReturnedHf; type = ChatMsg.BgSystemHorde; UpdateFlagState(Team.Alliance, WSGFlagState.WaitRespawn); RespawnFlag(Team.Horde, false); SpawnBGObject(WSGObjectTypes.HFlag, BattlegroundConst.RespawnImmediately); PlaySoundToAll(WSGSound.FlagReturned); UpdatePlayerScore(player, ScoreType.FlagReturns, 1); _bothFlagsKept = false; } else { message_id = CypherStrings.BgWsPickedupHf; type = ChatMsg.BgSystemAlliance; PlaySoundToAll(WSGSound.HordeFlagPickedUp); SpawnBGObject(WSGObjectTypes.HFlag, BattlegroundConst.RespawnOneDay); SetHordeFlagPicker(player.GetGUID()); player.CastSpell(player, WSGSpellId.WarsongFlag, true); _flagState[TeamId.Horde] = WSGFlagState.OnPlayer; UpdateFlagState(Team.Alliance, WSGFlagState.OnPlayer); if (_flagDebuffState == 1) player.CastSpell(player, WSGSpellId.FocusedAssault, true); else if (_flagDebuffState == 2) player.CastSpell(player, WSGSpellId.BrutalAssault, true); UpdateWorldState(WSGWorldStates.FlagUnkHorde, 1); } //called in HandleGameObjectUseOpcode: //target_obj.Delete(); } if (message_id == 0) return; SendMessageToAll(message_id, type, player); player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnterPvpCombat); } public override void RemovePlayer(Player player, ObjectGuid guid, Team team) { // sometimes flag aura not removed :( if (IsAllianceFlagPickedup() && m_FlagKeepers[TeamId.Alliance] == guid) { if (!player) { Log.outError(LogFilter.Battleground, "BattlegroundWS: Removing offline player who has the FLAG!!"); SetAllianceFlagPicker(ObjectGuid.Empty); RespawnFlag(Team.Alliance, false); } else EventPlayerDroppedFlag(player); } if (IsHordeFlagPickedup() && m_FlagKeepers[TeamId.Horde] == guid) { if (!player) { Log.outError(LogFilter.Battleground, "BattlegroundWS: Removing offline player who has the FLAG!!"); SetHordeFlagPicker(ObjectGuid.Empty); RespawnFlag(Team.Horde, false); } else EventPlayerDroppedFlag(player); } } void UpdateFlagState(Team team, WSGFlagState value) { if (team == Team.Alliance) UpdateWorldState(WSGWorldStates.FlagStateAlliance, (uint)value); else UpdateWorldState(WSGWorldStates.FlagStateHorde, (uint)value); } void UpdateTeamScore(int team) { if (team == TeamId.Alliance) UpdateWorldState(WSGWorldStates.FlagCapturesAlliance, (uint)GetTeamScore(team)); else UpdateWorldState(WSGWorldStates.FlagCapturesHorde, (uint)GetTeamScore(team)); } public override void HandleAreaTrigger(Player player, uint trigger, bool entered) { //uint SpellId = 0; //uint64 buff_guid = 0; switch (trigger) { case 8965: // Horde Start case 8966: // Alliance Start if (GetStatus() == BattlegroundStatus.WaitJoin && !entered) TeleportPlayerToExploitLocation(player); break; case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in Battleground.Update(). //buff_guid = BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; break; case 3687: // Horde elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in Battleground.Update(). //buff_guid = BgObjects[BG_WS_OBJECT_SPEEDBUFF_2]; break; case 3706: // Alliance elixir of regeneration spawn //buff_guid = BgObjects[BG_WS_OBJECT_REGENBUFF_1]; break; case 3708: // Horde elixir of regeneration spawn //buff_guid = BgObjects[BG_WS_OBJECT_REGENBUFF_2]; break; case 3707: // Alliance elixir of berserk spawn //buff_guid = BgObjects[BG_WS_OBJECT_BERSERKBUFF_1]; break; case 3709: // Horde elixir of berserk spawn //buff_guid = BgObjects[BG_WS_OBJECT_BERSERKBUFF_2]; break; case 3646: // Alliance Flag spawn if (_flagState[TeamId.Horde] != 0 && _flagState[TeamId.Alliance] == 0) if (GetFlagPickerGUID(TeamId.Horde) == player.GetGUID()) EventPlayerCapturedFlag(player); break; case 3647: // Horde Flag spawn if (_flagState[TeamId.Alliance] != 0 && _flagState[TeamId.Horde] == 0) if (GetFlagPickerGUID(TeamId.Alliance) == player.GetGUID()) EventPlayerCapturedFlag(player); break; case 3649: // unk1 case 3688: // unk2 case 4628: // unk3 case 4629: // unk4 break; default: base.HandleAreaTrigger(player, trigger, entered); break; } //if (buff_guid) // HandleTriggerBuff(buff_guid, player); } public override bool SetupBattleground() { bool result = true; result &= AddObject(WSGObjectTypes.AFlag, WSGObjectEntry.AFlag, 1540.423f, 1481.325f, 351.8284f, 3.089233f, 0, 0, 0.9996573f, 0.02617699f, WSGTimerOrScore.FlagRespawnTime / 1000); result &= AddObject(WSGObjectTypes.HFlag, WSGObjectEntry.HFlag, 916.0226f, 1434.405f, 345.413f, 0.01745329f, 0, 0, 0.008726535f, 0.9999619f, WSGTimerOrScore.FlagRespawnTime / 1000); if (!result) { Log.outError(LogFilter.Sql, "BgWarsongGluch: Failed to spawn flag object!"); return false; } // buffs result &= AddObject(WSGObjectTypes.Speedbuff1, Buff_Entries[0], 1449.93f, 1470.71f, 342.6346f, -1.64061f, 0, 0, 0.7313537f, -0.6819983f, BattlegroundConst.BuffRespawnTime); result &= AddObject(WSGObjectTypes.Speedbuff2, Buff_Entries[0], 1005.171f, 1447.946f, 335.9032f, 1.64061f, 0, 0, 0.7313537f, 0.6819984f, BattlegroundConst.BuffRespawnTime); result &= AddObject(WSGObjectTypes.Regenbuff1, Buff_Entries[1], 1317.506f, 1550.851f, 313.2344f, -0.2617996f, 0, 0, 0.1305263f, -0.9914448f, BattlegroundConst.BuffRespawnTime); result &= AddObject(WSGObjectTypes.Regenbuff2, Buff_Entries[1], 1110.451f, 1353.656f, 316.5181f, -0.6806787f, 0, 0, 0.333807f, -0.9426414f, BattlegroundConst.BuffRespawnTime); result &= AddObject(WSGObjectTypes.Berserkbuff1, Buff_Entries[2], 1320.09f, 1378.79f, 314.7532f, 1.186824f, 0, 0, 0.5591929f, 0.8290376f, BattlegroundConst.BuffRespawnTime); result &= AddObject(WSGObjectTypes.Berserkbuff2, Buff_Entries[2], 1139.688f, 1560.288f, 306.8432f, -2.443461f, 0, 0, 0.9396926f, -0.3420201f, BattlegroundConst.BuffRespawnTime); if (!result) { Log.outError(LogFilter.Sql, "BgWarsongGluch: Failed to spawn buff object!"); return false; } // alliance gates result &= AddObject(WSGObjectTypes.DoorA1, WSGObjectEntry.DoorA1, 1503.335f, 1493.466f, 352.1888f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorA2, WSGObjectEntry.DoorA2, 1492.478f, 1457.912f, 342.9689f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorA3, WSGObjectEntry.DoorA3, 1468.503f, 1494.357f, 351.8618f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorA4, WSGObjectEntry.DoorA4, 1471.555f, 1458.778f, 362.6332f, 3.115414f, 0, 0, 0.9999143f, 0.01308903f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorA5, WSGObjectEntry.DoorA5, 1492.347f, 1458.34f, 342.3712f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorA6, WSGObjectEntry.DoorA6, 1503.466f, 1493.367f, 351.7352f, -0.03490669f, 0, 0, 0.01745246f, -0.9998477f, BattlegroundConst.RespawnImmediately); // horde gates result &= AddObject(WSGObjectTypes.DoorH1, WSGObjectEntry.DoorH1, 949.1663f, 1423.772f, 345.6241f, -0.5756807f, -0.01673368f, -0.004956111f, -0.2839723f, 0.9586737f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorH2, WSGObjectEntry.DoorH2, 953.0507f, 1459.842f, 340.6526f, -1.99662f, -0.1971825f, 0.1575096f, -0.8239487f, 0.5073641f, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorH3, WSGObjectEntry.DoorH3, 949.9523f, 1422.751f, 344.9273f, 0.0f, 0, 0, 0, 1, BattlegroundConst.RespawnImmediately); result &= AddObject(WSGObjectTypes.DoorH4, WSGObjectEntry.DoorH4, 950.7952f, 1459.583f, 342.1523f, 0.05235988f, 0, 0, 0.02617695f, 0.9996573f, BattlegroundConst.RespawnImmediately); if (!result) { Log.outError(LogFilter.Sql, "BgWarsongGluch: Failed to spawn door object Battleground not created!"); return false; } WorldSafeLocsRecord sg = CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.MainAlliance); if (sg == null || !AddSpiritGuide(0, sg.Loc.X, sg.Loc.Y, sg.Loc.Z, 3.124139f, TeamId.Alliance)) { Log.outError(LogFilter.Sql, "BgWarsongGluch: Failed to spawn Alliance spirit guide! Battleground not created!"); return false; } sg = CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.MainHorde); if (sg == null || !AddSpiritGuide(1, sg.Loc.X, sg.Loc.Y, sg.Loc.Z, 3.193953f, TeamId.Horde)) { Log.outError(LogFilter.Sql, "BgWarsongGluch: Failed to spawn Horde spirit guide! Battleground not created!"); return false; } return true; } public override void Reset() { //call parent's class reset base.Reset(); m_FlagKeepers[TeamId.Alliance].Clear(); m_FlagKeepers[TeamId.Horde].Clear(); m_DroppedFlagGUID[TeamId.Alliance] = ObjectGuid.Empty; m_DroppedFlagGUID[TeamId.Horde] = ObjectGuid.Empty; _flagState[TeamId.Alliance] = WSGFlagState.OnBase; _flagState[TeamId.Horde] = WSGFlagState.OnBase; m_TeamScores[TeamId.Alliance] = 0; m_TeamScores[TeamId.Horde] = 0; if (Global.BattlegroundMgr.IsBGWeekend(GetTypeID())) { m_ReputationCapture = 45; m_HonorWinKills = 3; m_HonorEndKills = 4; } else { m_ReputationCapture = 35; m_HonorWinKills = 1; m_HonorEndKills = 2; } _minutesElapsed = 0; _lastFlagCaptureTeam = 0; _bothFlagsKept = false; _flagDebuffState = 0; _flagSpellForceTimer = 0; _flagsDropTimer[TeamId.Alliance] = 0; _flagsDropTimer[TeamId.Horde] = 0; _flagsTimer[TeamId.Alliance] = 0; _flagsTimer[TeamId.Horde] = 0; } public override void EndBattleground(Team winner) { // Win reward if (winner == Team.Alliance) RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), Team.Alliance); if (winner == Team.Horde) RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), Team.Horde); // Complete map_end rewards (even if no team wins) RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), Team.Alliance); RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), Team.Horde); base.EndBattleground(winner); } public override void HandleKillPlayer(Player victim, Player killer) { if (GetStatus() != BattlegroundStatus.InProgress) return; EventPlayerDroppedFlag(victim); base.HandleKillPlayer(victim, killer); } public override bool UpdatePlayerScore(Player player, ScoreType type, uint value, bool doAddHonor = true) { if (!base.UpdatePlayerScore(player, type, value, doAddHonor)) return false; switch (type) { case ScoreType.FlagCaptures: // flags captured player.UpdateCriteria(CriteriaTypes.BgObjectiveCapture, 42); break; case ScoreType.FlagReturns: // flags returned player.UpdateCriteria(CriteriaTypes.BgObjectiveCapture, 44); break; default: break; } return true; } public override WorldSafeLocsRecord GetClosestGraveYard(Player player) { //if status in progress, it returns main graveyards with spiritguides //else it will return the graveyard in the flagroom - this is especially good //if a player dies in preparation phase - then the player can't cheat //and teleport to the graveyard outside the flagroom //and start running around, while the doors are still closed if (player.GetTeam() == Team.Alliance) { if (GetStatus() == BattlegroundStatus.InProgress) return CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.MainAlliance); else return CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.FlagRoomAlliance); } else { if (GetStatus() == BattlegroundStatus.InProgress) return CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.MainHorde); else return CliDB.WorldSafeLocsStorage.LookupByKey(WSGGraveyards.FlagRoomHorde); } } public override WorldSafeLocsRecord GetExploitTeleportLocation(Team team) { return CliDB.WorldSafeLocsStorage.LookupByKey(team == Team.Alliance ? ExploitTeleportLocationAlliance : ExploitTeleportLocationHorde); } public override void FillInitialWorldStates(InitWorldStates packet) { packet.AddState(WSGWorldStates.FlagCapturesAlliance, (int)GetTeamScore(TeamId.Alliance)); packet.AddState(WSGWorldStates.FlagCapturesHorde, (int)GetTeamScore(TeamId.Horde)); if (_flagState[TeamId.Alliance] == WSGFlagState.OnGround) packet.AddState(WSGWorldStates.FlagUnkAlliance, -1); else if (_flagState[TeamId.Alliance] == WSGFlagState.OnPlayer) packet.AddState(WSGWorldStates.FlagUnkAlliance, 1); else packet.AddState(WSGWorldStates.FlagUnkAlliance, 0); if (_flagState[TeamId.Horde] == WSGFlagState.OnGround) packet.AddState(WSGWorldStates.FlagUnkHorde, -1); else if (_flagState[TeamId.Horde] == WSGFlagState.OnPlayer) packet.AddState(WSGWorldStates.FlagUnkHorde, 1); else packet.AddState(WSGWorldStates.FlagUnkHorde, 0); packet.AddState(WSGWorldStates.FlagCapturesMax, (int)WSGTimerOrScore.MaxTeamScore); if (GetStatus() == BattlegroundStatus.InProgress) { packet.AddState(WSGWorldStates.StateTimerActive, 1); packet.AddState(WSGWorldStates.StateTimer, 25 - _minutesElapsed); } else packet.AddState(WSGWorldStates.StateTimerActive, 0); if (_flagState[TeamId.Horde] == WSGFlagState.OnPlayer) packet.AddState(WSGWorldStates.FlagStateHorde, 2); else packet.AddState(WSGWorldStates.FlagStateHorde, 1); if (_flagState[TeamId.Alliance] == WSGFlagState.OnPlayer) packet.AddState(WSGWorldStates.FlagStateAlliance, 2); else packet.AddState(WSGWorldStates.FlagStateAlliance, 1); } public override Team GetPrematureWinner() { if (GetTeamScore(TeamId.Alliance) > GetTeamScore(TeamId.Horde)) return Team.Alliance; else if (GetTeamScore(TeamId.Horde) > GetTeamScore(TeamId.Alliance)) return Team.Horde; return base.GetPrematureWinner(); } public override bool CheckAchievementCriteriaMeet(uint criteriaId, Player player, Unit target, uint miscValue) { switch (criteriaId) { case (uint)BattlegroundCriteriaId.SaveTheDay: if (target) { Player playerTarget = target.ToPlayer(); if (playerTarget) return GetFlagState(playerTarget.GetTeam()) == WSGFlagState.OnBase; } return false; } return base.CheckAchievementCriteriaMeet(criteriaId, player, target, miscValue); } public override ObjectGuid GetFlagPickerGUID(int team = -1) { if (team == TeamId.Alliance || team == TeamId.Horde) return m_FlagKeepers[team]; return ObjectGuid.Empty; } void SetAllianceFlagPicker(ObjectGuid guid) { m_FlagKeepers[TeamId.Alliance] = guid; } void SetHordeFlagPicker(ObjectGuid guid) { m_FlagKeepers[TeamId.Horde] = guid; } bool IsAllianceFlagPickedup() { return !m_FlagKeepers[TeamId.Alliance].IsEmpty(); } bool IsHordeFlagPickedup() { return !m_FlagKeepers[TeamId.Horde].IsEmpty(); } WSGFlagState GetFlagState(Team team) { return _flagState[GetTeamIndexByTeamId(team)]; } void SetLastFlagCapture(Team team) { _lastFlagCaptureTeam = (uint)team; } public override void SetDroppedFlagGUID(ObjectGuid guid, int team = -1) { if (team == (int)TeamId.Alliance || team == (int)TeamId.Horde) m_DroppedFlagGUID[team] = guid; } ObjectGuid GetDroppedFlagGUID(Team team) { return m_DroppedFlagGUID[GetTeamIndexByTeamId(team)]; } void AddPoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] += Points; } void SetTeamPoint(Team team, uint Points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = Points; } void RemovePoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= Points; } ObjectGuid[] m_FlagKeepers = new ObjectGuid[2]; // 0 - alliance, 1 - horde ObjectGuid[] m_DroppedFlagGUID = new ObjectGuid[2]; WSGFlagState[] _flagState = new WSGFlagState[2]; // for checking flag state int[] _flagsTimer = new int[2]; int[] _flagsDropTimer = new int[2]; uint _lastFlagCaptureTeam; // Winner is based on this if score is equal uint m_ReputationCapture; uint m_HonorWinKills; uint m_HonorEndKills; int _flagSpellForceTimer; bool _bothFlagsKept; byte _flagDebuffState; // 0 - no debuffs, 1 - focused assault, 2 - brutal assault byte _minutesElapsed; uint[][] Honor = { new uint[] {20, 40, 40 }, // normal honor new uint[] { 60, 40, 80} // holiday }; const uint ExploitTeleportLocationAlliance = 3784; const uint ExploitTeleportLocationHorde = 3785; } class BattlegroundWGScore : BattlegroundScore { public BattlegroundWGScore(ObjectGuid playerGuid, Team team) : base(playerGuid, team) { } public override void UpdateScore(ScoreType type, uint value) { switch (type) { case ScoreType.FlagCaptures: // Flags captured FlagCaptures += value; break; case ScoreType.FlagReturns: // Flags returned FlagReturns += value; break; default: base.UpdateScore(type, value); break; } } public override void BuildPvPLogPlayerDataPacket(out PVPLogData.PlayerData playerData) { base.BuildPvPLogPlayerDataPacket(out playerData); playerData.Stats.Add(FlagCaptures); playerData.Stats.Add(FlagReturns); } public override uint GetAttr1() { return FlagCaptures; } public override uint GetAttr2() { return FlagReturns; } uint FlagCaptures; uint FlagReturns; } #region Constants enum WSGRewards { Win = 0, FlapCap, MapComplete, RewardNum } enum WSGFlagState { OnBase = 0, WaitRespawn = 1, OnPlayer = 2, OnGround = 3 } struct WSGObjectTypes { public const int DoorA1 = 0; public const int DoorA2 = 1; public const int DoorA3 = 2; public const int DoorA4 = 3; public const int DoorA5 = 4; public const int DoorA6 = 5; public const int DoorH1 = 6; public const int DoorH2 = 7; public const int DoorH3 = 8; public const int DoorH4 = 9; public const int AFlag = 10; public const int HFlag = 11; public const int Speedbuff1 = 12; public const int Speedbuff2 = 13; public const int Regenbuff1 = 14; public const int Regenbuff2 = 15; public const int Berserkbuff1 = 16; public const int Berserkbuff2 = 17; public const int Max = 18; } struct WSGObjectEntry { public const uint DoorA1 = 179918; public const uint DoorA2 = 179919; public const uint DoorA3 = 179920; public const uint DoorA4 = 179921; public const uint DoorA5 = 180322; public const uint DoorA6 = 180322; public const uint DoorH1 = 179916; public const uint DoorH2 = 179917; public const uint DoorH3 = 180322; public const uint DoorH4 = 180322; public const uint AFlag = 179830; public const uint HFlag = 179831; public const uint AFlagGround = 179785; public const uint HFlagGround = 179786; } struct WSGWorldStates { public const uint FlagUnkAlliance = 1545; public const uint FlagUnkHorde = 1546; // FlagUnk = 1547; public const uint FlagCapturesAlliance = 1581; public const uint FlagCapturesHorde = 1582; public const uint FlagCapturesMax = 1601; public const uint FlagStateHorde = 2338; public const uint FlagStateAlliance = 2339; public const uint StateTimer = 4248; public const uint StateTimerActive = 4247; } struct WSGSpellId { public const uint WarsongFlag = 23333; public const uint WarsongFlagDropped = 23334; public const uint WarsongFlagPicked = 61266; // Fake Spell; Does Not Exist But Used As Timer Start Event public const uint SilverwingFlag = 23335; public const uint SilverwingFlagDropped = 23336; public const uint SilverwingFlagPicked = 61265; // Fake Spell; Does Not Exist But Used As Timer Start Event public const uint FocusedAssault = 46392; public const uint BrutalAssault = 46393; } struct WSGTimerOrScore { public const uint MaxTeamScore = 3; public const int FlagRespawnTime = 23000; public const int FlagDropTime = 10000; public const uint SpellForceTime = 600000; public const uint SpellBrutalTime = 900000; } struct WSGGraveyards { public const uint FlagRoomAlliance = 769; public const uint FlagRoomHorde = 770; public const uint MainAlliance = 771; public const uint MainHorde = 772; } struct WSGSound { public const uint FlagCapturedAlliance = 8173; public const uint FlagCapturedHorde = 8213; public const uint FlagPlaced = 8232; public const uint FlagReturned = 8192; public const uint HordeFlagPickedUp = 8212; public const uint AllianceFlagPickedUp = 8174; public const uint FlagsRespawned = 8232; } #endregion }