/* * Copyright (C) 2012-2020 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 Framework.Database; using Game.DataStorage; using Game.Entities; using Game.Maps; using Game.Misc; using System.Collections.Generic; namespace Game.PvP { public class OutdoorPvPManager : Singleton { OutdoorPvPManager() { } public void InitOutdoorPvP() { uint oldMSTime = Time.GetMSTime(); // 0 1 SQLResult result = DB.World.Query("SELECT TypeId, ScriptName FROM outdoorpvp_template"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 outdoor PvP definitions. DB table `outdoorpvp_template` is empty."); return; } uint count = 0; do { OutdoorPvPTypes typeId = (OutdoorPvPTypes)result.Read(0); if (Global.DisableMgr.IsDisabledFor(DisableType.OutdoorPVP, (uint)typeId, null)) continue; if (typeId >= OutdoorPvPTypes.Max) { Log.outError(LogFilter.Sql, "Invalid OutdoorPvPTypes value {0} in outdoorpvp_template; skipped.", typeId); continue; } m_OutdoorPvPDatas[typeId] = Global.ObjectMgr.GetScriptId(result.Read(1)); ++count; } while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} outdoor PvP definitions in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); } public void CreateOutdoorPvPForMap(Map map) { for (OutdoorPvPTypes outdoorPvpType = OutdoorPvPTypes.HellfirePeninsula; outdoorPvpType < OutdoorPvPTypes.Max; ++outdoorPvpType) { if (map.GetId() != m_OutdoorMapIds[(int)outdoorPvpType]) continue; if (!m_OutdoorPvPDatas.ContainsKey(outdoorPvpType)) { Log.outError(LogFilter.Sql, "Could not initialize OutdoorPvP object for type ID {0}; no entry in database.", outdoorPvpType); continue; } OutdoorPvP pvp = Global.ScriptMgr.CreateOutdoorPvP(m_OutdoorPvPDatas[outdoorPvpType], map); if (pvp == null) { Log.outError(LogFilter.Outdoorpvp, "Could not initialize OutdoorPvP object for type ID {0}; got NULL pointer from script.", outdoorPvpType); continue; } if (!pvp.SetupOutdoorPvP()) { Log.outError(LogFilter.Outdoorpvp, "Could not initialize OutdoorPvP object for type ID {0}; SetupOutdoorPvP failed.", outdoorPvpType); continue; } m_OutdoorPvPByMap.Add(map, pvp); } } public void DestroyOutdoorPvPForMap(Map map) { m_OutdoorPvPByMap.Remove(map); } public void AddZone(uint zoneid, OutdoorPvP handle) { m_OutdoorPvPMap[(handle.GetMap(), zoneid)] = handle; } public void HandlePlayerEnterZone(Player player, uint zoneid) { var outdoor = GetOutdoorPvPToZoneId(player.GetMap(), zoneid); if (outdoor == null) return; if (outdoor.HasPlayer(player)) return; outdoor.HandlePlayerEnterZone(player, zoneid); Log.outDebug(LogFilter.Outdoorpvp, "Player {0} entered outdoorpvp id {1}", player.GetGUID().ToString(), outdoor.GetTypeId()); } public void HandlePlayerLeaveZone(Player player, uint zoneid) { var outdoor = GetOutdoorPvPToZoneId(player.GetMap(), zoneid); if (outdoor == null) return; // teleport: remove once in removefromworld, once in updatezone if (!outdoor.HasPlayer(player)) return; outdoor.HandlePlayerLeaveZone(player, zoneid); Log.outDebug(LogFilter.Outdoorpvp, "Player {0} left outdoorpvp id {1}", player.GetGUID().ToString(), outdoor.GetTypeId()); } public OutdoorPvP GetOutdoorPvPToZoneId(Map map, uint zoneid) { return m_OutdoorPvPMap.LookupByKey((map, zoneid)); } public void Update(uint diff) { m_UpdateTimer += diff; if (m_UpdateTimer > 1000) { foreach (var (_, outdoor) in m_OutdoorPvPByMap) outdoor.Update(m_UpdateTimer); m_UpdateTimer = 0; } } public bool HandleCustomSpell(Player player, uint spellId, GameObject go) { OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null && pvp.HasPlayer(player)) return pvp.HandleCustomSpell(player, spellId, go); return false; } public bool HandleOpenGo(Player player, GameObject go) { OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null && pvp.HasPlayer(player)) return pvp.HandleOpenGo(player, go); return false; } public void HandleDropFlag(Player player, uint spellId) { OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null && pvp.HasPlayer(player)) pvp.HandleDropFlag(player, spellId); } public void HandlePlayerResurrects(Player player, uint zoneid) { OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null && pvp.HasPlayer(player)) pvp.HandlePlayerResurrects(player, zoneid); } public string GetDefenseMessage(uint zoneId, uint id, Locale locale) { BroadcastTextRecord bct = CliDB.BroadcastTextStorage.LookupByKey(id); if (bct != null) return Global.DB2Mgr.GetBroadcastTextValue(bct, locale); Log.outError(LogFilter.Outdoorpvp, "Can not find DefenseMessage (Zone: {0}, Id: {1}). BroadcastText (Id: {2}) does not exist.", zoneId, id, id); return ""; } // contains all initiated outdoor pvp events // used when initing / cleaning up MultiMap m_OutdoorPvPByMap = new(); // maps the zone ids to an outdoor pvp event // used in player event handling Dictionary<(Map map, uint zoneId), OutdoorPvP> m_OutdoorPvPMap = new(); // Holds the outdoor PvP templates uint[] m_OutdoorMapIds = { 0, 530, 530, 530, 530, 1 }; Dictionary m_OutdoorPvPDatas = new(); // update interval uint m_UpdateTimer; } }