From b3a404e2e88cb7be21b1e3e977c9a42913d23bce Mon Sep 17 00:00:00 2001 From: hondacrx Date: Tue, 19 Jul 2022 12:14:32 -0400 Subject: [PATCH] Core/OutdoorPvP: Refactor OutdoorPvP creation to be linked to host map creation instead of having globally accessible objects Port From (https://github.com/TrinityCore/TrinityCore/commit/775be0682a794d0a1f62d656f8c6c6dffca8de79) --- Source/Game/Entities/Object/WorldObject.cs | 2 +- Source/Game/Entities/Player/Player.PvP.cs | 2 +- Source/Game/Maps/Map.cs | 4 + Source/Game/OutdoorPVP/OutdoorPvP.cs | 15 +-- Source/Game/OutdoorPVP/OutdoorPvPManager.cs | 115 ++++++++---------- .../OutdoorPVP/Zones/HellfirePeninsulaPvP.cs | 7 +- Source/Game/Scripting/CoreScripts.cs | 2 +- Source/Game/Scripting/ScriptManager.cs | 4 +- 8 files changed, 64 insertions(+), 87 deletions(-) diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index f8d5f64c5..f5a3aa6d6 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1438,7 +1438,7 @@ namespace Game.Entities if (bf != null) return bf; else - return Global.OutdoorPvPMgr.GetZoneScript(GetZoneId()); + return Global.OutdoorPvPMgr.GetOutdoorPvPToZoneId(map, GetZoneId()); } } diff --git a/Source/Game/Entities/Player/Player.PvP.cs b/Source/Game/Entities/Player/Player.PvP.cs index d1c4de97f..c5be07454 100644 --- a/Source/Game/Entities/Player/Player.PvP.cs +++ b/Source/Game/Entities/Player/Player.PvP.cs @@ -765,7 +765,7 @@ namespace Game.Entities } public OutdoorPvP GetOutdoorPvP() { - return Global.OutdoorPvPMgr.GetOutdoorPvPToZoneId(GetZoneId()); + return Global.OutdoorPvPMgr.GetOutdoorPvPToZoneId(GetMap(), GetZoneId()); } } } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 5a03933c9..6fc2b0cef 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -89,6 +89,8 @@ namespace Game.Maps _worldStateValues = Global.WorldStateMgr.GetInitialWorldStatesForMap(this); + Global.OutdoorPvPMgr.CreateOutdoorPvPForMap(this); + Global.ScriptMgr.OnCreateMap(this); } @@ -111,6 +113,8 @@ namespace Game.Maps if (!m_scriptSchedule.Empty()) Global.MapMgr.DecreaseScheduledScriptCount((uint)m_scriptSchedule.Count); + Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(this); + if (m_parentMap == this) m_childTerrainMaps = null; diff --git a/Source/Game/OutdoorPVP/OutdoorPvP.cs b/Source/Game/OutdoorPVP/OutdoorPvP.cs index cf44daf02..fa247e17f 100644 --- a/Source/Game/OutdoorPVP/OutdoorPvP.cs +++ b/Source/Game/OutdoorPVP/OutdoorPvP.cs @@ -35,10 +35,10 @@ namespace Game.PvP // base class for specific outdoor pvp handlers public class OutdoorPvP : ZoneScript { - public OutdoorPvP() + public OutdoorPvP(Map map) { m_TypeId = 0; - m_sendUpdate = true; + m_map = map; m_players[0] = new List(); m_players[1] = new List(); } @@ -285,21 +285,10 @@ namespace Game.PvP public Map GetMap() { return m_map; } - // Hack to store map because this code is just shit - public void SetMapFromZone(uint zone) - { - AreaTableRecord areaTable = CliDB.AreaTableStorage.LookupByKey(zone); - Cypher.Assert(areaTable != null); - Map map = Global.MapMgr.CreateBaseMap(areaTable.ContinentID); - Cypher.Assert(!map.Instanceable()); - m_map = map; - } - // the map of the objectives belonging to this outdoorpvp public Dictionary m_capturePoints = new(); List[] m_players = new List[2]; public OutdoorPvPTypes m_TypeId; - bool m_sendUpdate; Map m_map; } diff --git a/Source/Game/OutdoorPVP/OutdoorPvPManager.cs b/Source/Game/OutdoorPVP/OutdoorPvPManager.cs index e916ad2c5..cf2adf9f6 100644 --- a/Source/Game/OutdoorPVP/OutdoorPvPManager.cs +++ b/Source/Game/OutdoorPVP/OutdoorPvPManager.cs @@ -45,34 +45,40 @@ namespace Game.PvP do { - uint typeId = result.Read(0); + OutdoorPvPTypes typeId = (OutdoorPvPTypes)result.Read(0); - if (Global.DisableMgr.IsDisabledFor(DisableType.OutdoorPVP, typeId, null)) + if (Global.DisableMgr.IsDisabledFor(DisableType.OutdoorPVP, (uint)typeId, null)) continue; - if (typeId >= (int)OutdoorPvPTypes.Max) + if (typeId >= OutdoorPvPTypes.Max) { Log.outError(LogFilter.Sql, "Invalid OutdoorPvPTypes value {0} in outdoorpvp_template; skipped.", typeId); continue; } - OutdoorPvPTypes realTypeId = (OutdoorPvPTypes)typeId; - OutdoorPvPScriptIds[realTypeId] = Global.ObjectMgr.GetScriptId(result.Read(1)); + m_OutdoorPvPDatas[typeId] = Global.ObjectMgr.GetScriptId(result.Read(1)); ++count; } while (result.NextRow()); - OutdoorPvP pvp; + 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 (!OutdoorPvPScriptIds.ContainsKey(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; } - pvp = Global.ScriptMgr.CreateOutdoorPvP(OutdoorPvPScriptIds[outdoorPvpType]); + 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); @@ -85,20 +91,23 @@ namespace Game.PvP continue; } - m_OutdoorPvPSet.Add(pvp); + m_OutdoorPvPByMap.Add(map, pvp); } + } - Log.outInfo(LogFilter.ServerLoading, "Loaded {0} outdoor PvP definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); + public void DestroyOutdoorPvPForMap(Map map) + { + m_OutdoorPvPByMap.Remove(map); } public void AddZone(uint zoneid, OutdoorPvP handle) { - m_OutdoorPvPMap[zoneid] = handle; + m_OutdoorPvPMap[(handle.GetMap(), zoneid)] = handle; } public void HandlePlayerEnterZone(Player player, uint zoneid) { - var outdoor = GetOutdoorPvPToZoneId(zoneid); + var outdoor = GetOutdoorPvPToZoneId(player.GetMap(), zoneid); if (outdoor == null) return; @@ -111,7 +120,7 @@ namespace Game.PvP public void HandlePlayerLeaveZone(Player player, uint zoneid) { - var outdoor = GetOutdoorPvPToZoneId(zoneid); + var outdoor = GetOutdoorPvPToZoneId(player.GetMap(), zoneid); if (outdoor == null) return; @@ -123,15 +132,9 @@ namespace Game.PvP Log.outDebug(LogFilter.Outdoorpvp, "Player {0} left outdoorpvp id {1}", player.GetGUID().ToString(), outdoor.GetTypeId()); } - public OutdoorPvP GetOutdoorPvPToZoneId(uint zoneid) + public OutdoorPvP GetOutdoorPvPToZoneId(Map map, uint zoneid) { - var outdoor = m_OutdoorPvPMap.LookupByKey(zoneid); - if (outdoor == null) - { - // no handle for this zone, return - return null; - } - return outdoor; + return m_OutdoorPvPMap.LookupByKey((map, zoneid)); } public void Update(uint diff) @@ -139,7 +142,7 @@ namespace Game.PvP m_UpdateTimer += diff; if (m_UpdateTimer > 1000) { - foreach (var outdoor in m_OutdoorPvPSet) + foreach (var (_, outdoor) in m_OutdoorPvPByMap) outdoor.Update(m_UpdateTimer); m_UpdateTimer = 0; } @@ -147,69 +150,50 @@ namespace Game.PvP public bool HandleCustomSpell(Player player, uint spellId, GameObject go) { - foreach (var outdoor in m_OutdoorPvPSet) - { - if (outdoor.HandleCustomSpell(player, spellId, go)) - return true; - } + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + return pvp.HandleCustomSpell(player, spellId, go); + return false; } - public ZoneScript GetZoneScript(uint zoneId) - { - var outdoor = GetOutdoorPvPToZoneId(zoneId); - if (outdoor == null) - return null; - - return outdoor; - } - public bool HandleOpenGo(Player player, GameObject go) { - foreach (var outdoor in m_OutdoorPvPSet) - { - if (outdoor.HandleOpenGo(player, go)) - return true; - } + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + return pvp.HandleOpenGo(player, go); + return false; } public void HandleGossipOption(Player player, Creature creature, uint gossipid) { - foreach (var outdoor in m_OutdoorPvPSet) - { - if (outdoor.HandleGossipOption(player, creature, gossipid)) - return; - } + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + pvp.HandleGossipOption(player, creature, gossipid); } public bool CanTalkTo(Player player, Creature creature, GossipMenuItems gso) { - foreach (var outdoor in m_OutdoorPvPSet) - { - if (outdoor.CanTalkTo(player, creature, gso)) - return true; - } + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + return pvp.CanTalkTo(player, creature, gso); + return false; } public void HandleDropFlag(Player player, uint spellId) { - foreach (var outdoor in m_OutdoorPvPSet) - { - if (outdoor.HandleDropFlag(player, spellId)) - return; - } + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + pvp.HandleDropFlag(player, spellId); } public void HandlePlayerResurrects(Player player, uint zoneid) { - var outdoor = GetOutdoorPvPToZoneId(zoneid); - if (outdoor == null) - return; - - if (outdoor.HasPlayer(player)) - outdoor.HandlePlayerResurrects(player, zoneid); + OutdoorPvP pvp = player.GetOutdoorPvP(); + if (pvp != null && pvp.HasPlayer(player)) + pvp.HandlePlayerResurrects(player, zoneid); } public string GetDefenseMessage(uint zoneId, uint id, Locale locale) @@ -224,14 +208,15 @@ namespace Game.PvP // contains all initiated outdoor pvp events // used when initing / cleaning up - List m_OutdoorPvPSet = new(); + MultiMap m_OutdoorPvPByMap = new(); // maps the zone ids to an outdoor pvp event // used in player event handling - Dictionary m_OutdoorPvPMap = new(); + Dictionary<(Map map, uint zoneId), OutdoorPvP> m_OutdoorPvPMap = new(); // Holds the outdoor PvP templates - Dictionary OutdoorPvPScriptIds = new(); + uint[] m_OutdoorMapIds = { 0, 530, 530, 530, 530, 1 }; + Dictionary m_OutdoorPvPDatas = new(); // update interval uint m_UpdateTimer; diff --git a/Source/Game/OutdoorPVP/Zones/HellfirePeninsulaPvP.cs b/Source/Game/OutdoorPVP/Zones/HellfirePeninsulaPvP.cs index af303d0ab..0b9ea8b6c 100644 --- a/Source/Game/OutdoorPVP/Zones/HellfirePeninsulaPvP.cs +++ b/Source/Game/OutdoorPVP/Zones/HellfirePeninsulaPvP.cs @@ -25,7 +25,7 @@ namespace Game.PvP { class HellfirePeninsulaPvP : OutdoorPvP { - public HellfirePeninsulaPvP() + public HellfirePeninsulaPvP(Map map) : base(map) { m_TypeId = OutdoorPvPTypes.HellfirePeninsula; m_AllianceTowersControlled = 0; @@ -36,7 +36,6 @@ namespace Game.PvP { m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; - SetMapFromZone(HPConst.BuffZones[0]); // add the zones affected by the pvp buff for (int i = 0; i < HPConst.BuffZones.Length; ++i) @@ -305,9 +304,9 @@ namespace Game.PvP { public OutdoorPvP_hellfire_peninsula() : base("outdoorpvp_hp") { } - public override OutdoorPvP GetOutdoorPvP() + public override OutdoorPvP GetOutdoorPvP(Map map) { - return new HellfirePeninsulaPvP(); + return new HellfirePeninsulaPvP(map); } } diff --git a/Source/Game/Scripting/CoreScripts.cs b/Source/Game/Scripting/CoreScripts.cs index 9f258fc39..2e8fc5b86 100644 --- a/Source/Game/Scripting/CoreScripts.cs +++ b/Source/Game/Scripting/CoreScripts.cs @@ -469,7 +469,7 @@ namespace Game.Scripting public override bool IsDatabaseBound() { return true; } // Should return a fully valid OutdoorPvP object for the type ID. - public virtual OutdoorPvP GetOutdoorPvP() { return null; } + public virtual OutdoorPvP GetOutdoorPvP(Map map) { return null; } } public class WeatherScript : ScriptObject diff --git a/Source/Game/Scripting/ScriptManager.cs b/Source/Game/Scripting/ScriptManager.cs index 925d717fc..31f9d0d9d 100644 --- a/Source/Game/Scripting/ScriptManager.cs +++ b/Source/Game/Scripting/ScriptManager.cs @@ -729,9 +729,9 @@ namespace Game.Scripting } // OutdoorPvPScript - public OutdoorPvP CreateOutdoorPvP(uint scriptId) + public OutdoorPvP CreateOutdoorPvP(uint scriptId, Map map) { - return RunScriptRet(p => p.GetOutdoorPvP(), scriptId, null); + return RunScriptRet(p => p.GetOutdoorPvP(map), scriptId, null); } // WeatherScript