Core/GameObject: Implement ControlZone gameobject type

Port From (https://github.com/TrinityCore/TrinityCore/commit/f96f041c3edadfb5f1f09705fe699c2d7a9ed423)
This commit is contained in:
hondacrx
2024-01-31 20:53:44 -05:00
parent 7545d9395d
commit e2caec12dc
11 changed files with 998 additions and 1270 deletions
+1 -1
View File
@@ -142,7 +142,7 @@ namespace Game.Arenas
break; break;
case DalaranSewersEvents.PipeKnockback: case DalaranSewersEvents.PipeKnockback:
{ {
for (int i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i) for (uint i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i)
{ {
Creature waterSpout = GetBGCreature(i); Creature waterSpout = GetBGCreature(i);
if (waterSpout != null) if (waterSpout != null)
+45 -340
View File
@@ -90,9 +90,6 @@ namespace Game.BattleFields
} }
} }
foreach (var capturePoint in m_capturePoints.Values)
capturePoint.HandlePlayerLeave(player);
m_InvitedPlayers[player.GetTeamId()].Remove(player.GetGUID()); m_InvitedPlayers[player.GetTeamId()].Remove(player.GetGUID());
m_PlayersWillBeKick[player.GetTeamId()].Remove(player.GetGUID()); m_PlayersWillBeKick[player.GetTeamId()].Remove(player.GetGUID());
m_players[player.GetTeamId()].Remove(player.GetGUID()); m_players[player.GetTeamId()].Remove(player.GetGUID());
@@ -121,7 +118,6 @@ namespace Game.BattleFields
OnStartGrouping(); OnStartGrouping();
} }
bool objective_changed = false;
if (IsWarTime()) if (IsWarTime())
{ {
if (m_uiKickAfkPlayersTimer <= diff) if (m_uiKickAfkPlayersTimer <= diff)
@@ -155,13 +151,9 @@ namespace Game.BattleFields
} }
else else
m_uiKickDontAcceptTimer -= diff; m_uiKickDontAcceptTimer -= diff;
foreach (var pair in m_capturePoints)
if (pair.Value.Update(diff))
objective_changed = true;
} }
return objective_changed; return false;
} }
void InvitePlayersInZoneToQueue() void InvitePlayersInZoneToQueue()
@@ -268,6 +260,42 @@ namespace Game.BattleFields
Log.outError(LogFilter.Battlefield, "Battlefield.InitStalker: could not spawn Stalker (Creature entry {0}), zone messeges will be un-available", entry); Log.outError(LogFilter.Battlefield, "Battlefield.InitStalker: could not spawn Stalker (Creature entry {0}), zone messeges will be un-available", entry);
} }
public override void ProcessEvent(WorldObject target, uint eventId, WorldObject invoker)
{
base.ProcessEvent(target, eventId, invoker);
if (invoker != null)
{
GameObject gameobject = invoker.ToGameObject();
if (gameobject != null)
{
if (gameobject.GetGoType() == GameObjectTypes.ControlZone)
{
if (!ControlZoneHandlers.TryGetValue(gameobject.GetEntry(), out BattleFieldControlZoneHandler handler))
return;
var controlzone = gameobject.GetGoInfo().ControlZone;
if (eventId == controlzone.CaptureEventAlliance)
handler.HandleCaptureEventAlliance(gameobject);
else if (eventId == controlzone.CaptureEventHorde)
handler.HandleCaptureEventHorde(gameobject);
else if (eventId == controlzone.ContestedEventAlliance)
handler.HandleContestedEventAlliance(gameobject);
else if (eventId == controlzone.ContestedEventHorde)
handler.HandleContestedEventHorde(gameobject);
else if (eventId == controlzone.NeutralEventAlliance)
handler.HandleNeutralEventAlliance(gameobject);
else if (eventId == controlzone.NeutralEventHorde)
handler.HandleNeutralEventHorde(gameobject);
else if (eventId == controlzone.ProgressEventAlliance)
handler.HandleProgressEventAlliance(gameobject);
else if (eventId == controlzone.ProgressEventHorde)
handler.HandleProgressEventHorde(gameobject);
}
}
}
}
void KickAfkPlayers() void KickAfkPlayers()
{ {
for (byte team = 0; team < 2; ++team) for (byte team = 0; team < 2; ++team)
@@ -439,19 +467,6 @@ namespace Game.BattleFields
Global.CreatureTextMgr.SendChat(stalker, (byte)id, target); Global.CreatureTextMgr.SendChat(stalker, (byte)id, target);
} }
public void AddCapturePoint(BfCapturePoint cp)
{
if (m_capturePoints.ContainsKey(cp.GetCapturePointEntry()))
Log.outError(LogFilter.Battlefield, "Battlefield.AddCapturePoint: CapturePoint {0} already exists!", cp.GetCapturePointEntry());
m_capturePoints[cp.GetCapturePointEntry()] = cp;
}
BfCapturePoint GetCapturePoint(uint entry)
{
return m_capturePoints.LookupByKey(entry);
}
public void RegisterZone(uint zoneId) public void RegisterZone(uint zoneId)
{ {
Global.BattleFieldMgr.AddZone(zoneId, this); Global.BattleFieldMgr.AddZone(zoneId, this);
@@ -730,7 +745,7 @@ namespace Game.BattleFields
protected uint m_DefenderTeam; protected uint m_DefenderTeam;
// Map of the objectives belonging to this OutdoorPvP // Map of the objectives belonging to this OutdoorPvP
Dictionary<uint, BfCapturePoint> m_capturePoints = new(); Dictionary<uint /*control zone entry*/, BattleFieldControlZoneHandler> ControlZoneHandlers = new();
// Players info maps // Players info maps
protected List<ObjectGuid>[] m_players = new List<ObjectGuid>[2]; // Players in zone protected List<ObjectGuid>[] m_players = new List<ObjectGuid>[2]; // Players in zone
@@ -844,328 +859,18 @@ namespace Game.BattleFields
protected BattleField m_Bf; protected BattleField m_Bf;
} }
public class BfCapturePoint class BattleFieldControlZoneHandler : ControlZoneHandler
{ {
public BfCapturePoint(BattleField battlefield) BattleField _battlefield;
{
m_Bf = battlefield;
m_capturePointGUID = ObjectGuid.Empty;
m_team = TeamId.Neutral;
m_value = 0;
m_minValue = 0.0f;
m_maxValue = 0.0f;
m_State = BattleFieldObjectiveStates.Neutral;
m_OldState = BattleFieldObjectiveStates.Neutral;
m_capturePointEntry = 0;
m_neutralValuePct = 0;
m_maxSpeed = 0;
m_activePlayers[0] = new HashSet<ObjectGuid>(); public BattleFieldControlZoneHandler(BattleField battlefield)
m_activePlayers[1] = new HashSet<ObjectGuid>(); {
_battlefield = battlefield;
} }
public virtual bool HandlePlayerEnter(Player player) public BattleField GetBattlefield()
{ {
if (!m_capturePointGUID.IsEmpty()) return _battlefield;
{
GameObject capturePoint = m_Bf.GetGameObject(m_capturePointGUID);
if (capturePoint != null)
{
player.SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldState1, 1);
player.SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldstate2, (uint)(Math.Ceiling((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f)));
player.SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldstate3, m_neutralValuePct);
} }
} }
return m_activePlayers[player.GetTeamId()].Add(player.GetGUID());
}
public virtual void HandlePlayerLeave(Player player)
{
if (!m_capturePointGUID.IsEmpty())
{
GameObject capturePoint = m_Bf.GetGameObject(m_capturePointGUID);
if (capturePoint != null)
player.SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldState1, 0);
}
m_activePlayers[player.GetTeamId()].Remove(player.GetGUID());
}
public virtual void SendChangePhase()
{
if (m_capturePointGUID.IsEmpty())
return;
GameObject capturePoint = m_Bf.GetGameObject(m_capturePointGUID);
if (capturePoint != null)
{
// send this too, sometimes the slider disappears, dunno why :(
SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldState1, 1);
// send these updates to only the ones in this objective
SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldstate2, (uint)Math.Ceiling((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
// send this too, sometimes it resets :S
SendUpdateWorldState(capturePoint.GetGoInfo().ControlZone.worldstate3, m_neutralValuePct);
}
}
public bool SetCapturePointData(GameObject capturePoint)
{
Cypher.Assert(capturePoint != null);
Log.outError(LogFilter.Battlefield, "Creating capture point {0}", capturePoint.GetEntry());
m_capturePointGUID = capturePoint.GetGUID();
m_capturePointEntry = capturePoint.GetEntry();
// check info existence
GameObjectTemplate goinfo = capturePoint.GetGoInfo();
if (goinfo.type != GameObjectTypes.ControlZone)
{
Log.outError(LogFilter.Server, "OutdoorPvP: GO {0} is not capture point!", capturePoint.GetEntry());
return false;
}
// get the needed values from goinfo
m_maxValue = goinfo.ControlZone.maxTime;
m_maxSpeed = m_maxValue / (goinfo.ControlZone.minTime != 0 ? goinfo.ControlZone.minTime : 60);
m_neutralValuePct = goinfo.ControlZone.neutralPercent;
m_minValue = m_maxValue * goinfo.ControlZone.neutralPercent / 100;
if (m_team == TeamId.Alliance)
{
m_value = m_maxValue;
m_State = BattleFieldObjectiveStates.Alliance;
}
else
{
m_value = -m_maxValue;
m_State = BattleFieldObjectiveStates.Horde;
}
return true;
}
GameObject GetCapturePointGo()
{
return m_Bf.GetGameObject(m_capturePointGUID);
}
bool DelCapturePoint()
{
if (!m_capturePointGUID.IsEmpty())
{
GameObject capturePoint = m_Bf.GetGameObject(m_capturePointGUID);
if (capturePoint != null)
{
capturePoint.SetRespawnTime(0); // not save respawn time
capturePoint.Delete();
capturePoint.Dispose();
}
m_capturePointGUID.Clear();
}
return true;
}
public virtual bool Update(uint diff)
{
if (m_capturePointGUID.IsEmpty())
return false;
GameObject capturePoint = m_Bf.GetGameObject(m_capturePointGUID);
if (capturePoint != null)
{
float radius = capturePoint.GetGoInfo().ControlZone.radius;
for (byte team = 0; team < SharedConst.PvpTeamsCount; ++team)
{
foreach (var guid in m_activePlayers[team])
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
{
if (!capturePoint.IsWithinDistInMap(player, radius) || !player.IsOutdoorPvPActive())
HandlePlayerLeave(player);
}
}
}
List<Unit> players = new();
var checker = new AnyPlayerInObjectRangeCheck(capturePoint, radius);
var searcher = new PlayerListSearcher(capturePoint, players, checker);
Cell.VisitWorldObjects(capturePoint, searcher, radius);
foreach (Player player in players)
{
if (player.IsOutdoorPvPActive())
{
if (m_activePlayers[player.GetTeamId()].Add(player.GetGUID()))
HandlePlayerEnter(player);
}
}
}
// get the difference of numbers
float fact_diff = ((float)m_activePlayers[TeamId.Alliance].Count - m_activePlayers[TeamId.Horde].Count) * diff / 1000;
if (MathFunctions.fuzzyEq(fact_diff, 0.0f))
return false;
Team Challenger;
float maxDiff = m_maxSpeed * diff;
if (fact_diff < 0)
{
// horde is in majority, but it's already horde-controlled . no change
if (m_State == BattleFieldObjectiveStates.Horde && m_value <= -m_maxValue)
return false;
if (fact_diff < -maxDiff)
fact_diff = -maxDiff;
Challenger = Team.Horde;
}
else
{
// ally is in majority, but it's already ally-controlled . no change
if (m_State == BattleFieldObjectiveStates.Alliance && m_value >= m_maxValue)
return false;
if (fact_diff > maxDiff)
fact_diff = maxDiff;
Challenger = Team.Alliance;
}
float oldValue = m_value;
uint oldTeam = m_team;
m_OldState = m_State;
m_value += fact_diff;
if (m_value < -m_minValue) // red
{
if (m_value < -m_maxValue)
m_value = -m_maxValue;
m_State = BattleFieldObjectiveStates.Horde;
m_team = TeamId.Horde;
}
else if (m_value > m_minValue) // blue
{
if (m_value > m_maxValue)
m_value = m_maxValue;
m_State = BattleFieldObjectiveStates.Alliance;
m_team = TeamId.Alliance;
}
else if (oldValue * m_value <= 0) // grey, go through mid point
{
// if challenger is ally, then n.a challenge
if (Challenger == Team.Alliance)
m_State = BattleFieldObjectiveStates.NeutralAllianceChallenge;
// if challenger is horde, then n.h challenge
else if (Challenger == Team.Horde)
m_State = BattleFieldObjectiveStates.NeutralHordeChallenge;
m_team = TeamId.Neutral;
}
else // grey, did not go through mid point
{
// old phase and current are on the same side, so one team challenges the other
if (Challenger == Team.Alliance && (m_OldState == BattleFieldObjectiveStates.Horde || m_OldState == BattleFieldObjectiveStates.NeutralHordeChallenge))
m_State = BattleFieldObjectiveStates.HordeAllianceChallenge;
else if (Challenger == Team.Horde && (m_OldState == BattleFieldObjectiveStates.Alliance || m_OldState == BattleFieldObjectiveStates.NeutralAllianceChallenge))
m_State = BattleFieldObjectiveStates.AllianceHordeChallenge;
m_team = TeamId.Neutral;
}
if (MathFunctions.fuzzyNe(m_value, oldValue))
SendChangePhase();
if (m_OldState != m_State)
{
if (oldTeam != m_team)
ChangeTeam(oldTeam);
return true;
}
return false;
}
void SendUpdateWorldState(uint field, uint value)
{
for (byte team = 0; team < SharedConst.PvpTeamsCount; ++team)
{
foreach (var guid in m_activePlayers[team]) // send to all players present in the area
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
player.SendUpdateWorldState(field, value);
}
}
}
void SendObjectiveComplete(uint id, ObjectGuid guid)
{
uint team;
switch (m_State)
{
case BattleFieldObjectiveStates.Alliance:
team = TeamId.Alliance;
break;
case BattleFieldObjectiveStates.Horde:
team = TeamId.Horde;
break;
default:
return;
}
// send to all players present in the area
foreach (var _guid in m_activePlayers[team])
{
Player player = Global.ObjAccessor.FindPlayer(_guid);
if (player != null)
player.KilledMonsterCredit(id, guid);
}
}
bool IsInsideObjective(Player player)
{
return m_activePlayers[player.GetTeamId()].Contains(player.GetGUID());
}
public virtual void ChangeTeam(uint oldTeam) { }
public uint GetCapturePointEntry() { return m_capturePointEntry; }
uint GetTeamId() { return m_team; }
// active Players in the area of the objective, 0 - alliance, 1 - horde
HashSet<ObjectGuid>[] m_activePlayers = new HashSet<ObjectGuid>[SharedConst.PvpTeamsCount];
// Total shift needed to capture the objective
float m_maxValue;
float m_minValue;
// Maximum speed of capture
float m_maxSpeed;
// The status of the objective
float m_value;
protected uint m_team;
// Objective states
BattleFieldObjectiveStates m_OldState;
BattleFieldObjectiveStates m_State;
// Neutral value on capture bar
uint m_neutralValuePct;
// Battlefield this objective belongs to
protected BattleField m_Bf;
// Capture point entry
uint m_capturePointEntry;
// Gameobject related to that capture point
ObjectGuid m_capturePointGUID;
}
} }
+7 -7
View File
@@ -42,7 +42,7 @@ namespace Game.BattleGrounds
{ {
// remove objects and creatures // remove objects and creatures
// (this is done automatically in mapmanager update, when the instance is reset after the reset time) // (this is done automatically in mapmanager update, when the instance is reset after the reset time)
for (var i = 0; i < BgCreatures.Length; ++i) for (uint i = 0; i < BgCreatures.Length; ++i)
DelCreature(i); DelCreature(i);
for (var i = 0; i < BgObjects.Length; ++i) for (var i = 0; i < BgObjects.Length; ++i)
@@ -1348,7 +1348,7 @@ namespace Game.BattleGrounds
return obj; return obj;
} }
public Creature GetBGCreature(int type) public Creature GetBGCreature(uint type)
{ {
if (BgCreatures[type].IsEmpty()) if (BgCreatures[type].IsEmpty())
return null; return null;
@@ -1398,7 +1398,7 @@ namespace Game.BattleGrounds
} }
} }
public virtual Creature AddCreature(uint entry, int type, float x, float y, float z, float o, int teamIndex = TeamId.Neutral, uint respawntime = 0, Transport transport = null) public virtual Creature AddCreature(uint entry, uint type, float x, float y, float z, float o, int teamIndex = TeamId.Neutral, uint respawntime = 0, Transport transport = null)
{ {
Map map = FindBgMap(); Map map = FindBgMap();
if (map == null) if (map == null)
@@ -1445,12 +1445,12 @@ namespace Game.BattleGrounds
return creature; return creature;
} }
public Creature AddCreature(uint entry, int type, Position pos, int teamIndex = TeamId.Neutral, uint respawntime = 0, Transport transport = null) public Creature AddCreature(uint entry, uint type, Position pos, int teamIndex = TeamId.Neutral, uint respawntime = 0, Transport transport = null)
{ {
return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex, respawntime, transport); return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex, respawntime, transport);
} }
public bool DelCreature(int type) public bool DelCreature(uint type)
{ {
if (BgCreatures[type].IsEmpty()) if (BgCreatures[type].IsEmpty())
return true; return true;
@@ -1502,7 +1502,7 @@ namespace Game.BattleGrounds
return false; return false;
} }
public bool AddSpiritGuide(int type, float x, float y, float z, float o, int teamIndex) public bool AddSpiritGuide(uint type, float x, float y, float z, float o, int teamIndex)
{ {
uint entry = (uint)(teamIndex == TeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide); uint entry = (uint)(teamIndex == TeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide);
@@ -1514,7 +1514,7 @@ namespace Game.BattleGrounds
return false; return false;
} }
public bool AddSpiritGuide(int type, Position pos, int teamIndex = TeamId.Neutral) public bool AddSpiritGuide(uint type, Position pos, int teamIndex = TeamId.Neutral)
{ {
return AddSpiritGuide(type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex); return AddSpiritGuide(type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex);
} }
@@ -11,6 +11,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Game.BattleGrounds.Zones; using Game.BattleGrounds.Zones;
using Game.BattleGrounds.Zones.EyeofStorm;
namespace Game.BattleGrounds namespace Game.BattleGrounds
{ {
@@ -353,9 +353,9 @@ namespace Game.BattleGrounds.Zones
if (capturedNodes >= 4) if (capturedNodes >= 4)
CastSpellOnTeam(BattlegroundConst.AbQuestReward4Bases, team); CastSpellOnTeam(BattlegroundConst.AbQuestReward4Bases, team);
Creature trigger = !BgCreatures[node + 7].IsEmpty() ? GetBGCreature(node + 7) : null; // 0-6 spirit guides Creature trigger = !BgCreatures[node + 7].IsEmpty() ? GetBGCreature(node + 7u) : null; // 0-6 spirit guides
if (trigger == null) if (trigger == null)
trigger = AddCreature(SharedConst.WorldTrigger, node + 7, NodePositions[node], GetTeamIndexByTeamId(team)); trigger = AddCreature(SharedConst.WorldTrigger, node + 7u, NodePositions[node], GetTeamIndexByTeamId(team));
//add bonus honor aura trigger creature when node is accupied //add bonus honor aura trigger creature when node is accupied
//cast bonus aura (+50% honor in 25yards) //cast bonus aura (+50% honor in 25yards)
@@ -374,7 +374,7 @@ namespace Game.BattleGrounds.Zones
return; return;
//remove bonus honor aura trigger creature when node is lost //remove bonus honor aura trigger creature when node is lost
DelCreature(node + 7);//null checks are in DelCreature! 0-6 spirit guides DelCreature(node + 7u);//null checks are in DelCreature! 0-6 spirit guides
DelCreature(node); DelCreature(node);
File diff suppressed because it is too large Load Diff
@@ -158,7 +158,7 @@ namespace Game.BattleGrounds.Zones
ShipsStarted = false; ShipsStarted = false;
//Graveyards //Graveyards
for (byte i = 0; i < SAGraveyards.Max; i++) for (uint i = 0; i < SAGraveyards.Max; i++)
{ {
WorldSafeLocsEntry sg = Global.ObjectMgr.GetWorldSafeLoc(SAMiscConst.GYEntries[i]); WorldSafeLocsEntry sg = Global.ObjectMgr.GetWorldSafeLoc(SAMiscConst.GYEntries[i]);
if (sg == null) if (sg == null)
@@ -744,7 +744,7 @@ namespace Game.BattleGrounds.Zones
} }
} }
void CaptureGraveyard(int i, Player source) void CaptureGraveyard(uint i, Player source)
{ {
if (GraveyardStatus[i] == Attackers) if (GraveyardStatus[i] == Attackers)
return; return;
@@ -773,7 +773,7 @@ namespace Game.BattleGrounds.Zones
SAMiscConst.ObjSpawnlocs[flag], 0, 0, 0, 0, BattlegroundConst.RespawnOneDay); SAMiscConst.ObjSpawnlocs[flag], 0, 0, 0, 0, BattlegroundConst.RespawnOneDay);
npc = SACreatureTypes.Rigspark; npc = SACreatureTypes.Rigspark;
Creature rigspark = AddCreature(SAMiscConst.NpcEntries[npc], (int)npc, SAMiscConst.NpcSpawnlocs[npc], Attackers); Creature rigspark = AddCreature(SAMiscConst.NpcEntries[npc], npc, SAMiscConst.NpcSpawnlocs[npc], Attackers);
if (rigspark != null) if (rigspark != null)
rigspark.GetAI().Talk(SATextIds.SparklightRigsparkSpawn); rigspark.GetAI().Talk(SATextIds.SparklightRigsparkSpawn);
@@ -801,7 +801,7 @@ namespace Game.BattleGrounds.Zones
SAMiscConst.ObjSpawnlocs[flag], 0, 0, 0, 0, BattlegroundConst.RespawnOneDay); SAMiscConst.ObjSpawnlocs[flag], 0, 0, 0, 0, BattlegroundConst.RespawnOneDay);
npc = SACreatureTypes.Sparklight; npc = SACreatureTypes.Sparklight;
Creature sparklight = AddCreature(SAMiscConst.NpcEntries[npc], (int)npc, SAMiscConst.NpcSpawnlocs[npc], Attackers); Creature sparklight = AddCreature(SAMiscConst.NpcEntries[npc], npc, SAMiscConst.NpcSpawnlocs[npc], Attackers);
if (sparklight != null) if (sparklight != null)
sparklight.GetAI().Talk(SATextIds.SparklightRigsparkSpawn); sparklight.GetAI().Talk(SATextIds.SparklightRigsparkSpawn);
@@ -322,6 +322,10 @@ namespace Game.Entities
m_invisibility.AddValue(InvisibilityType.Trap, 300); m_invisibility.AddValue(InvisibilityType.Trap, 300);
} }
break; break;
case GameObjectTypes.ControlZone:
m_goTypeImpl = new ControlZone(this);
SetActive(true);
break;
case GameObjectTypes.NewFlag: case GameObjectTypes.NewFlag:
m_goTypeImpl = new GameObjectType.NewFlag(this); m_goTypeImpl = new GameObjectType.NewFlag(this);
if (map.Instanceable()) if (map.Instanceable())
@@ -1594,6 +1598,10 @@ namespace Game.Entities
Log.outError(LogFilter.Spells, $"Spell {spellId} has unhandled action {action} in effect {effectIndex}"); Log.outError(LogFilter.Spells, $"Spell {spellId} has unhandled action {action} in effect {effectIndex}");
break; break;
} }
// Apply side effects of type
if (m_goTypeImpl != null)
m_goTypeImpl.ActivateObject(action, param, spellCaster, spellId, effectIndex);
} }
public void SetGoArtKit(uint kit) public void SetGoArtKit(uint kit)
@@ -3622,6 +3630,15 @@ namespace Game.Entities
return newFlag.GetTakenFromBaseTime(); return newFlag.GetTakenFromBaseTime();
} }
public List<ObjectGuid> GetInsidePlayers()
{
ControlZone controlZone = m_goTypeImpl as ControlZone;
if (controlZone != null)
return controlZone.GetInsidePlayers();
return null;
}
public bool MeetsInteractCondition(Player user) public bool MeetsInteractCondition(Player user)
{ {
if (m_goInfo.GetConditionID1() == 0) if (m_goInfo.GetConditionID1() == 0)
@@ -3943,6 +3960,7 @@ namespace Game.Entities
public virtual void OnStateChanged(GameObjectState oldState, GameObjectState newState) { } public virtual void OnStateChanged(GameObjectState oldState, GameObjectState newState) { }
public virtual void OnRelocated() { } public virtual void OnRelocated() { }
public virtual bool IsNeverVisibleFor(WorldObject seer, bool allowServersideObjects) { return false; } public virtual bool IsNeverVisibleFor(WorldObject seer, bool allowServersideObjects) { return false; }
public virtual void ActivateObject(GameObjectActions action, int param, WorldObject spellCaster = null, uint spellId = 0, int effectIndex = -1) { }
public class CustomCommand public class CustomCommand
{ {
@@ -4478,4 +4496,252 @@ namespace Game.Entities
public GameObjectState? State; public GameObjectState? State;
public bool Despawned; public bool Despawned;
} }
class ControlZone : GameObjectTypeBase
{
TimeSpan _heartbeatRate;
TimeTracker _heartbeatTracker;
List<ObjectGuid> _insidePlayers = new();
int _previousTeamId;
float _value;
bool _contestedTriggered;
public ControlZone(GameObject owner) : base(owner)
{
_value = owner.GetGoInfo().ControlZone.startingValue;
if (owner.GetMap().Instanceable())
_heartbeatRate = TimeSpan.FromSeconds(1);
else if (owner.GetGoInfo().ControlZone.FrequentHeartbeat != 0)
_heartbeatRate = TimeSpan.FromSeconds(2.5);
else
_heartbeatRate = TimeSpan.FromSeconds(5);
_heartbeatTracker = new(_heartbeatRate);
_previousTeamId = GetControllingTeam();
_contestedTriggered = false;
}
public override void Update(uint diff)
{
if (_owner.HasFlag(GameObjectFlags.NotSelectable))
return;
_heartbeatTracker.Update(diff);
if (_heartbeatTracker.Passed())
{
_heartbeatTracker.Reset(_heartbeatRate);
HandleHeartbeat();
}
}
int GetControllingTeam()
{
if (_value < GetMaxHordeValue())
return TeamId.Horde;
if (_value > GetMinAllianceValue())
return TeamId.Alliance;
return TeamId.Neutral;
}
public List<ObjectGuid> GetInsidePlayers() { return _insidePlayers; }
public override void ActivateObject(GameObjectActions action, int param, WorldObject spellCaster, uint spellId, int effectIndex)
{
switch (action)
{
case GameObjectActions.MakeInert:
foreach (ObjectGuid guid in _insidePlayers)
{
Player player = Global.ObjAccessor.GetPlayer(_owner, guid);
if (player != null)
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldState1, 0);
}
_insidePlayers.Clear();
break;
default:
break;
}
}
public void SetValue(float value)
{
_value = MathFunctions.RoundToInterval(ref value, 0.0f, 100.0f);
}
void HandleHeartbeat()
{
// update player list inside control zone
List<Unit> targetList = new();
SearchTargets(targetList);
int oldControllingTeam = GetControllingTeam();
float pointsGained = CalculatePointsPerSecond(targetList) * (float)_heartbeatRate.TotalMilliseconds / 1000.0f;
if (pointsGained == 0)
return;
int oldRoundedValue = (int)_value;
SetValue(_value + pointsGained);
int roundedValue = (int)_value;
if (oldRoundedValue == roundedValue)
return;
int newControllingTeam = GetControllingTeam();
int assaultingTeam = pointsGained > 0 ? TeamId.Alliance : TeamId.Horde;
if (oldControllingTeam != newControllingTeam)
_contestedTriggered = false;
if (oldControllingTeam != TeamId.Alliance && newControllingTeam == TeamId.Alliance)
TriggerEvent(_owner.GetGoInfo().ControlZone.ProgressEventAlliance);
else if (oldControllingTeam != TeamId.Horde && newControllingTeam == TeamId.Horde)
TriggerEvent(_owner.GetGoInfo().ControlZone.ProgressEventHorde);
else if (oldControllingTeam == TeamId.Horde && newControllingTeam == TeamId.Neutral)
TriggerEvent(_owner.GetGoInfo().ControlZone.NeutralEventHorde);
else if (oldControllingTeam == TeamId.Alliance && newControllingTeam == TeamId.Neutral)
TriggerEvent(_owner.GetGoInfo().ControlZone.NeutralEventAlliance);
if (roundedValue == 100 && newControllingTeam == TeamId.Alliance && assaultingTeam == TeamId.Alliance)
TriggerEvent(_owner.GetGoInfo().ControlZone.CaptureEventAlliance);
else if (roundedValue == 0 && newControllingTeam == TeamId.Horde && assaultingTeam == TeamId.Horde)
TriggerEvent(_owner.GetGoInfo().ControlZone.CaptureEventHorde);
if (oldRoundedValue == 100 && assaultingTeam == TeamId.Horde && !_contestedTriggered)
{
TriggerEvent(_owner.GetGoInfo().ControlZone.ContestedEventHorde);
_contestedTriggered = true;
}
else if (oldRoundedValue == 0 && assaultingTeam == TeamId.Alliance && !_contestedTriggered)
{
TriggerEvent(_owner.GetGoInfo().ControlZone.ContestedEventAlliance);
_contestedTriggered = true;
}
foreach (Player player in targetList)
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldstate2, (uint)roundedValue);
}
void SearchTargets(List<Unit> targetList)
{
AnyUnitInObjectRangeCheck check = new(_owner, _owner.GetGoInfo().ControlZone.radius, true);
PlayerListSearcher searcher = new(_owner, targetList, check);
Cell.VisitWorldObjects(_owner, searcher, _owner.GetGoInfo().ControlZone.radius);
HandleUnitEnterExit(targetList);
}
float CalculatePointsPerSecond(List<Unit> targetList)
{
int delta = 0;
foreach (Player player in targetList)
{
if (!player.IsOutdoorPvPActive())
continue;
if (player.GetTeam() == Team.Horde)
delta--;
else
delta++;
}
uint minTime = _owner.GetGoInfo().ControlZone.minTime;
uint maxTime = _owner.GetGoInfo().ControlZone.maxTime;
uint minSuperiority = _owner.GetGoInfo().ControlZone.minSuperiority;
uint maxSuperiority = _owner.GetGoInfo().ControlZone.maxSuperiority;
if (Math.Abs(delta) < minSuperiority)
return 0;
float slope = ((float)minTime - maxTime) / (maxSuperiority - minSuperiority);
float intercept = maxTime - slope * minSuperiority;
float timeNeeded = slope * Math.Abs(delta) + intercept;
float percentageIncrease = 100.0f / timeNeeded;
if (delta < 0)
percentageIncrease *= -1;
return percentageIncrease;
}
void HandleUnitEnterExit(List<Unit> newTargetList)
{
List<ObjectGuid> exitPlayers = new(_insidePlayers);
List<Player> enteringPlayers = new();
foreach (Player unit in newTargetList)
{
if (!exitPlayers.Remove(unit.GetGUID()))
enteringPlayers.Add(unit);
_insidePlayers.Add(unit.GetGUID());
}
foreach (Player player in enteringPlayers)
{
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldState1, 1);
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldstate2, (uint)_value);
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldstate3, _owner.GetGoInfo().ControlZone.neutralPercent);
}
foreach (ObjectGuid exitPlayerGuid in exitPlayers)
{
Player player = Global.ObjAccessor.GetPlayer(_owner, exitPlayerGuid);
if (player != null)
player.SendUpdateWorldState(_owner.GetGoInfo().ControlZone.worldState1, 0);
}
}
float GetMaxHordeValue()
{
// ex: if neutralPercent is 40; then 0 - 30 is Horde Controlled
return 50.0f - _owner.GetGoInfo().ControlZone.neutralPercent / 2.0f;
}
float GetMinAllianceValue()
{
// ex: if neutralPercent is 40; then 70 - 100 is Alliance Controlled
return 50.0f + _owner.GetGoInfo().ControlZone.neutralPercent / 2.0f;
}
void TriggerEvent(uint eventId)
{
if (eventId <= 0)
return;
GameEvents.Trigger(eventId, _owner, null);
}
public uint GetStartingValue()
{
return _owner.GetGoInfo().ControlZone.startingValue;
}
}
class SetControlZoneValue : GameObjectTypeBase.CustomCommand
{
uint? _value;
public SetControlZoneValue(uint? value = null)
{
_value = value;
}
public override void Execute(GameObjectTypeBase type)
{
ControlZone controlZone = type as ControlZone;
if (controlZone != null)
{
uint value = controlZone.GetStartingValue();
if (_value.HasValue)
value = _value.Value;
controlZone.SetValue(value);
}
}
}
} }
+13
View File
@@ -51,4 +51,17 @@ namespace Game.Maps
protected EventMap _events = new(); protected EventMap _events = new();
} }
public class ControlZoneHandler
{
public virtual void HandleCaptureEventHorde(GameObject controlZone) { }
public virtual void HandleCaptureEventAlliance(GameObject controlZone) { }
public virtual void HandleContestedEventHorde(GameObject controlZone) { }
public virtual void HandleContestedEventAlliance(GameObject controlZone) { }
public virtual void HandleProgressEventHorde(GameObject controlZone) { }
public virtual void HandleProgressEventAlliance(GameObject controlZone) { }
public virtual void HandleNeutralEventHorde(GameObject controlZone) { HandleNeutralEvent(controlZone); }
public virtual void HandleNeutralEventAlliance(GameObject controlZone) { HandleNeutralEvent(controlZone); }
public virtual void HandleNeutralEvent(GameObject controlZone) { }
}
} }
+62 -295
View File
@@ -2,18 +2,13 @@
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Constants; using Framework.Constants;
using Framework.Database;
using Game.Chat; using Game.Chat;
using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Groups; using Game.Groups;
using Game.Maps; using Game.Maps;
using Game.Misc;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Numerics; using System.Numerics;
namespace Game.PvP namespace Game.PvP
@@ -36,9 +31,6 @@ namespace Game.PvP
public virtual void HandlePlayerLeaveZone(Player player, uint zone) public virtual void HandlePlayerLeaveZone(Player player, uint zone)
{ {
// inform the objectives of the leaving
foreach (var pair in m_capturePoints)
pair.Value.HandlePlayerLeave(player);
// remove the world state information from the player (we can't keep everyone up to date, so leave out those who are not in the concerning zones) // remove the world state information from the player (we can't keep everyone up to date, so leave out those who are not in the concerning zones)
if (!player.GetSession().PlayerLogout()) if (!player.GetSession().PlayerLogout())
SendRemoveWorldStates(player); SendRemoveWorldStates(player);
@@ -48,15 +40,10 @@ namespace Game.PvP
public virtual void HandlePlayerResurrects(Player player, uint zone) { } public virtual void HandlePlayerResurrects(Player player, uint zone) { }
public virtual bool Update(uint diff) public virtual void Update(uint diff)
{ {
bool objective_changed = false; foreach (var (_, capturePoint) in m_capturePoints)
foreach (var pair in m_capturePoints) capturePoint.Update(diff);
{
if (pair.Value.Update(diff))
objective_changed = true;
}
return objective_changed;
} }
public int GetWorldState(int worldStateId) public int GetWorldState(int worldStateId)
@@ -87,27 +74,18 @@ namespace Game.PvP
// creature kills must be notified, even if not inside objective / not outdoor pvp active // creature kills must be notified, even if not inside objective / not outdoor pvp active
// player kills only count if active and inside objective // player kills only count if active and inside objective
if ((groupGuy.IsOutdoorPvPActive() && IsInsideObjective(groupGuy)) || killed.IsTypeId(TypeId.Unit)) if (groupGuy.IsOutdoorPvPActive() || killed.IsTypeId(TypeId.Unit))
HandleKillImpl(groupGuy, killed); HandleKillImpl(groupGuy, killed);
} }
} }
else else
{ {
// creature kills must be notified, even if not inside objective / not outdoor pvp active // creature kills must be notified, even if not inside objective / not outdoor pvp active
if ((killer.IsOutdoorPvPActive() && IsInsideObjective(killer)) || killed.IsTypeId(TypeId.Unit)) if (killer.IsOutdoorPvPActive() || killed.IsTypeId(TypeId.Unit))
HandleKillImpl(killer, killed); HandleKillImpl(killer, killed);
} }
} }
bool IsInsideObjective(Player player)
{
foreach (var pair in m_capturePoints)
if (pair.Value.IsInsideObjective(player))
return true;
return false;
}
public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go) public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go)
{ {
foreach (var pair in m_capturePoints) foreach (var pair in m_capturePoints)
@@ -140,7 +118,7 @@ namespace Game.PvP
return false; return false;
} }
void BroadcastPacket(ServerPacket packet) public void BroadcastPacket(ServerPacket packet)
{ {
// This is faster than sWorld.SendZoneMessage // This is faster than sWorld.SendZoneMessage
for (int team = 0; team < 2; ++team) for (int team = 0; team < 2; ++team)
@@ -185,26 +163,6 @@ namespace Game.PvP
TeamCastSpell((uint)(teamIndex == TeamId.Alliance ? TeamId.Horde : TeamId.Alliance), spellId2 != 0 ? -(int)spellId2 : -(int)spellId); TeamCastSpell((uint)(teamIndex == TeamId.Alliance ? TeamId.Horde : TeamId.Alliance), spellId2 != 0 ? -(int)spellId2 : -(int)spellId);
} }
public override void OnGameObjectCreate(GameObject go)
{
if (go.GetGoType() != GameObjectTypes.ControlZone)
return;
OPvPCapturePoint cp = GetCapturePoint(go.GetSpawnId());
if (cp != null)
cp.m_capturePoint = go;
}
public override void OnGameObjectRemove(GameObject go)
{
if (go.GetGoType() != GameObjectTypes.ControlZone)
return;
OPvPCapturePoint cp = GetCapturePoint(go.GetSpawnId());
if (cp != null)
cp.m_capturePoint = null;
}
public void SendDefenseMessage(uint zoneId, uint id) public void SendDefenseMessage(uint zoneId, uint id)
{ {
DefenseMessageBuilder builder = new(zoneId, id); DefenseMessageBuilder builder = new(zoneId, id);
@@ -212,6 +170,40 @@ namespace Game.PvP
BroadcastWorker(localizer, zoneId); BroadcastWorker(localizer, zoneId);
} }
public override void ProcessEvent(WorldObject target, uint eventId, WorldObject invoker)
{
if (invoker != null)
{
GameObject gameobject = invoker.ToGameObject();
if (gameobject != null)
{
if (gameobject.GetGoType() == GameObjectTypes.ControlZone)
{
if (!ControlZoneHandlers.TryGetValue(gameobject.GetEntry(), out OutdoorPvPControlZoneHandler handler))
return;
var controlzone = gameobject.GetGoInfo().ControlZone;
if (eventId == controlzone.CaptureEventAlliance)
handler.HandleCaptureEventAlliance(gameobject);
else if (eventId == controlzone.CaptureEventHorde)
handler.HandleCaptureEventHorde(gameobject);
else if (eventId == controlzone.ContestedEventAlliance)
handler.HandleContestedEventAlliance(gameobject);
else if (eventId == controlzone.ContestedEventHorde)
handler.HandleContestedEventHorde(gameobject);
else if (eventId == controlzone.NeutralEventAlliance)
handler.HandleNeutralEventAlliance(gameobject);
else if (eventId == controlzone.NeutralEventHorde)
handler.HandleNeutralEventHorde(gameobject);
else if (eventId == controlzone.ProgressEventAlliance)
handler.HandleProgressEventAlliance(gameobject);
else if (eventId == controlzone.ProgressEventHorde)
handler.HandleProgressEventHorde(gameobject);
}
}
}
}
void BroadcastWorker(IDoWork<Player> _worker, uint zoneId) void BroadcastWorker(IDoWork<Player> _worker, uint zoneId)
{ {
for (uint i = 0; i < SharedConst.PvpTeamsCount; ++i) for (uint i = 0; i < SharedConst.PvpTeamsCount; ++i)
@@ -238,23 +230,11 @@ namespace Game.PvP
public virtual void SendRemoveWorldStates(Player player) { } public virtual void SendRemoveWorldStates(Player player) { }
public void AddCapturePoint(OPvPCapturePoint cp)
{
if (m_capturePoints.ContainsKey(cp.m_capturePointSpawnId))
Log.outError(LogFilter.Outdoorpvp, "OutdoorPvP.AddCapturePoint: CapturePoint {0} already exists!", cp.m_capturePointSpawnId);
m_capturePoints[cp.m_capturePointSpawnId] = cp;
}
OPvPCapturePoint GetCapturePoint(ulong lowguid)
{
return m_capturePoints.LookupByKey(lowguid);
}
public Map GetMap() { return m_map; } public Map GetMap() { return m_map; }
// the map of the objectives belonging to this outdoorpvp // the map of the objectives belonging to this outdoorpvp
public Dictionary<ulong, OPvPCapturePoint> m_capturePoints = new(); public Dictionary<ulong, OPvPCapturePoint> m_capturePoints = new();
protected Dictionary<uint /*control zone entry*/, OutdoorPvPControlZoneHandler> ControlZoneHandlers = new();
List<ObjectGuid>[] m_players = new List<ObjectGuid>[2]; List<ObjectGuid>[] m_players = new List<ObjectGuid>[2];
public OutdoorPvPTypes m_TypeId; public OutdoorPvPTypes m_TypeId;
@@ -263,229 +243,24 @@ namespace Game.PvP
public class OPvPCapturePoint public class OPvPCapturePoint
{ {
uint m_team;
// objective states
public ObjectiveStates OldState { get; set; }
public ObjectiveStates State { get; set; }
// pointer to the OutdoorPvP this objective belongs to
public OutdoorPvP PvP { get; set; }
public OPvPCapturePoint(OutdoorPvP pvp) public OPvPCapturePoint(OutdoorPvP pvp)
{ {
m_team = TeamId.Neutral; m_team = TeamId.Neutral;
OldState = ObjectiveStates.Neutral; OldState = ObjectiveStates.Neutral;
State = ObjectiveStates.Neutral; State = ObjectiveStates.Neutral;
PvP = pvp; PvP = pvp;
m_activePlayers[0] = new HashSet<ObjectGuid>();
m_activePlayers[1] = new HashSet<ObjectGuid>();
} }
public virtual bool HandlePlayerEnter(Player player) public virtual void Update(uint diff) { }
{
if (m_capturePoint != null)
{
player.SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldState1, 1);
player.SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldstate2, (uint)Math.Ceiling((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
player.SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldstate3, m_neutralValuePct);
}
return m_activePlayers[player.GetTeamId()].Add(player.GetGUID());
}
public virtual void HandlePlayerLeave(Player player)
{
if (m_capturePoint != null)
player.SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldState1, 0);
m_activePlayers[player.GetTeamId()].Remove(player.GetGUID());
}
public virtual void SendChangePhase()
{
if (m_capturePoint == null)
return;
// send this too, sometimes the slider disappears, dunno why :(
SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldState1, 1);
// send these updates to only the ones in this objective
SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldstate2, (uint)Math.Ceiling((m_value + m_maxValue) / (2 * m_maxValue) * 100.0f));
// send this too, sometimes it resets :S
SendUpdateWorldState(m_capturePoint.GetGoInfo().ControlZone.worldstate3, m_neutralValuePct);
}
public bool SetCapturePointData(uint entry)
{
Log.outDebug(LogFilter.Outdoorpvp, "Creating capture point {0}", entry);
// check info existence
GameObjectTemplate goinfo = Global.ObjectMgr.GetGameObjectTemplate(entry);
if (goinfo == null || goinfo.type != GameObjectTypes.ControlZone)
{
Log.outError(LogFilter.Outdoorpvp, "OutdoorPvP: GO {0} is not capture point!", entry);
return false;
}
// get the needed values from goinfo
m_maxValue = goinfo.ControlZone.maxTime;
m_maxSpeed = m_maxValue / (goinfo.ControlZone.minTime != 0 ? goinfo.ControlZone.minTime : 60);
m_neutralValuePct = goinfo.ControlZone.neutralPercent;
m_minValue = MathFunctions.CalculatePct(m_maxValue, m_neutralValuePct);
return true;
}
public virtual bool Update(uint diff)
{
if (m_capturePoint == null)
return false;
float radius = m_capturePoint.GetGoInfo().ControlZone.radius;
for (int team = 0; team < 2; ++team)
{
foreach (var playerGuid in m_activePlayers[team].ToList())
{
Player player = Global.ObjAccessor.FindPlayer(playerGuid);
if (player != null)
if (!m_capturePoint.IsWithinDistInMap(player, radius) || !player.IsOutdoorPvPActive())
HandlePlayerLeave(player);
}
}
List<Unit> players = new();
var checker = new AnyPlayerInObjectRangeCheck(m_capturePoint, radius);
var searcher = new PlayerListSearcher(m_capturePoint, players, checker);
Cell.VisitWorldObjects(m_capturePoint, searcher, radius);
foreach (Player player in players)
{
if (player.IsOutdoorPvPActive())
{
if (m_activePlayers[player.GetTeamId()].Add(player.GetGUID()))
HandlePlayerEnter(player);
}
}
// get the difference of numbers
float fact_diff = (float)(m_activePlayers[0].Count - m_activePlayers[1].Count) * diff / 1000;
if (fact_diff == 0.0f)
return false;
Team Challenger;
float maxDiff = m_maxSpeed * diff;
if (fact_diff < 0)
{
// horde is in majority, but it's already horde-controlled . no change
if (State == ObjectiveStates.Horde && m_value <= -m_maxValue)
return false;
if (fact_diff < -maxDiff)
fact_diff = -maxDiff;
Challenger = Team.Horde;
}
else
{
// ally is in majority, but it's already ally-controlled . no change
if (State == ObjectiveStates.Alliance && m_value >= m_maxValue)
return false;
if (fact_diff > maxDiff)
fact_diff = maxDiff;
Challenger = Team.Alliance;
}
float oldValue = m_value;
uint oldTeam = m_team;
OldState = State;
m_value += fact_diff;
if (m_value < -m_minValue) // red
{
if (m_value < -m_maxValue)
m_value = -m_maxValue;
State = ObjectiveStates.Horde;
m_team = TeamId.Horde;
}
else if (m_value > m_minValue) // blue
{
if (m_value > m_maxValue)
m_value = m_maxValue;
State = ObjectiveStates.Alliance;
m_team = TeamId.Alliance;
}
else if (oldValue * m_value <= 0) // grey, go through mid point
{
// if challenger is ally, then n.a challenge
if (Challenger == Team.Alliance)
State = ObjectiveStates.NeutralAllianceChallenge;
// if challenger is horde, then n.h challenge
else if (Challenger == Team.Horde)
State = ObjectiveStates.NeutralHordeChallenge;
m_team = TeamId.Neutral;
}
else // grey, did not go through mid point
{
// old phase and current are on the same side, so one team challenges the other
if (Challenger == Team.Alliance && (OldState == ObjectiveStates.Horde || OldState == ObjectiveStates.NeutralHordeChallenge))
State = ObjectiveStates.HordeAllianceChallenge;
else if (Challenger == Team.Horde && (OldState == ObjectiveStates.Alliance || OldState == ObjectiveStates.NeutralAllianceChallenge))
State = ObjectiveStates.AllianceHordeChallenge;
m_team = TeamId.Neutral;
}
if (m_value != oldValue)
SendChangePhase();
if (OldState != State)
{
if (oldTeam != m_team)
ChangeTeam(oldTeam);
ChangeState();
return true;
}
return false;
}
public void SendUpdateWorldState(uint field, uint value)
{
for (int team = 0; team < 2; ++team)
{
// send to all players present in the area
foreach (var guid in m_activePlayers[team])
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
player.SendUpdateWorldState(field, value);
}
}
}
public void SendObjectiveComplete(uint id, ObjectGuid guid)
{
uint team;
switch (State)
{
case ObjectiveStates.Alliance:
team = 0;
break;
case ObjectiveStates.Horde:
team = 1;
break;
default:
return;
}
// send to all players present in the area
foreach (var playerGuid in m_activePlayers[team])
{
Player player = Global.ObjAccessor.FindPlayer(playerGuid);
if (player != null)
player.KilledMonsterCredit(id, guid);
}
}
public bool IsInsideObjective(Player player)
{
var plSet = m_activePlayers[player.GetTeamId()];
return plSet.Contains(player.GetGUID());
}
public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go) public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go)
{ {
@@ -507,26 +282,18 @@ namespace Game.PvP
public virtual void ChangeState() { } public virtual void ChangeState() { }
public virtual void ChangeTeam(uint oldTeam) { } public virtual void ChangeTeam(uint oldTeam) { }
}
public ulong m_capturePointSpawnId; public class OutdoorPvPControlZoneHandler : ControlZoneHandler
public GameObject m_capturePoint; {
// active players in the area of the objective, 0 - alliance, 1 - horde OutdoorPvP _pvp;
public HashSet<ObjectGuid>[] m_activePlayers = new HashSet<ObjectGuid>[2];
// total shift needed to capture the objective public OutdoorPvPControlZoneHandler(OutdoorPvP pvp)
public float m_maxValue; {
float m_minValue; _pvp = pvp;
// maximum speed of capture }
float m_maxSpeed;
// the status of the objective public T GetOutdoorPvP<T>() where T : OutdoorPvP { return _pvp as T; }
public float m_value;
uint m_team;
// objective states
public ObjectiveStates OldState { get; set; }
public ObjectiveStates State { get; set; }
// neutral value on capture bar
public uint m_neutralValuePct;
// pointer to the OutdoorPvP this objective belongs to
public OutdoorPvP PvP { get; set; }
} }
class DefenseMessageBuilder : MessageBuilder class DefenseMessageBuilder : MessageBuilder
@@ -6,16 +6,55 @@ using Game.Entities;
using Game.Maps; using Game.Maps;
using Game.Networking.Packets; using Game.Networking.Packets;
using Game.Scripting; using Game.Scripting;
using System.Collections.Generic;
namespace Game.PvP namespace Game.PvP.HellfirePeninsula
{ {
class HellfirePeninsulaPvP : OutdoorPvP class HellfirePeninsulaPvP : OutdoorPvP
{ {
// how many towers are controlled
uint m_AllianceTowersControlled;
uint m_HordeTowersControlled;
List<ObjectGuid> _controlZoneGUIDs = new();
public HellfirePeninsulaPvP(Map map) : base(map) public HellfirePeninsulaPvP(Map map) : base(map)
{ {
m_TypeId = OutdoorPvPTypes.HellfirePeninsula; m_TypeId = OutdoorPvPTypes.HellfirePeninsula;
m_AllianceTowersControlled = 0; m_AllianceTowersControlled = 0;
m_HordeTowersControlled = 0; m_HordeTowersControlled = 0;
ControlZoneHandlers[(uint)GameObjectIds.TowerS] = new HellfirePeninsulaControlZoneHandler(this);
GetControlZoneTowerSouthHandler().SetFlagArtKitAlliance(65);
GetControlZoneTowerSouthHandler().SetFlagArtKitHorde(64);
GetControlZoneTowerSouthHandler().SetFlagArtKitNeutral(66);
GetControlZoneTowerSouthHandler().SetTextCaptureAlliance(DefenseMessages.BrokenHillTakenAlliance);
GetControlZoneTowerSouthHandler().SetTextCaptureHorde(DefenseMessages.BrokenHillTakenHorde);
GetControlZoneTowerSouthHandler().SetWorldstateAlliance(WorldStateIds.UiTowerSA);
GetControlZoneTowerSouthHandler().SetWorldstateHorde(WorldStateIds.UiTowerSH);
GetControlZoneTowerSouthHandler().SetWorldstateNeutral(WorldStateIds.UiTowerSN);
GetControlZoneTowerSouthHandler().SetKillCredit((uint)KillCreditIds.TowerS);
ControlZoneHandlers[(uint)GameObjectIds.TowerN] = new HellfirePeninsulaControlZoneHandler(this);
GetControlZoneTowerNorthHandler().SetFlagArtKitAlliance(62);
GetControlZoneTowerNorthHandler().SetFlagArtKitHorde(61);
GetControlZoneTowerNorthHandler().SetFlagArtKitNeutral(63);
GetControlZoneTowerNorthHandler().SetTextCaptureAlliance(DefenseMessages.OverlookTakenAlliance);
GetControlZoneTowerNorthHandler().SetTextCaptureHorde(DefenseMessages.OverlookTakenHorde);
GetControlZoneTowerNorthHandler().SetWorldstateAlliance(WorldStateIds.UiTowerNA);
GetControlZoneTowerNorthHandler().SetWorldstateHorde(WorldStateIds.UiTowerNH);
GetControlZoneTowerNorthHandler().SetWorldstateNeutral(WorldStateIds.UiTowerNN);
GetControlZoneTowerNorthHandler().SetKillCredit((uint)KillCreditIds.TowerN);
ControlZoneHandlers[(uint)GameObjectIds.TowerW] = new HellfirePeninsulaControlZoneHandler(this);
GetControlZoneTowerWestHandler().SetFlagArtKitAlliance(67);
GetControlZoneTowerWestHandler().SetFlagArtKitHorde(68);
GetControlZoneTowerWestHandler().SetFlagArtKitNeutral(69);
GetControlZoneTowerWestHandler().SetTextCaptureAlliance(DefenseMessages.StadiumTakenAlliance);
GetControlZoneTowerWestHandler().SetTextCaptureHorde(DefenseMessages.StadiumTakenHorde);
GetControlZoneTowerWestHandler().SetWorldstateAlliance(WorldStateIds.UiTowerWA);
GetControlZoneTowerWestHandler().SetWorldstateHorde(WorldStateIds.UiTowerWH);
GetControlZoneTowerWestHandler().SetWorldstateNeutral(WorldStateIds.UiTowerWN);
GetControlZoneTowerWestHandler().SetKillCredit((uint)KillCreditIds.TowerW);
} }
public override bool SetupOutdoorPvP() public override bool SetupOutdoorPvP()
@@ -24,8 +63,8 @@ namespace Game.PvP
m_HordeTowersControlled = 0; m_HordeTowersControlled = 0;
// add the zones affected by the pvp buff // add the zones affected by the pvp buff
for (int i = 0; i < HPConst.BuffZones.Length; ++i) for (int i = 0; i < Misc.BuffZones.Length; ++i)
RegisterZone(HPConst.BuffZones[i]); RegisterZone(Misc.BuffZones[i]);
return true; return true;
} }
@@ -34,23 +73,14 @@ namespace Game.PvP
{ {
switch (go.GetEntry()) switch (go.GetEntry())
{ {
case 182175:
AddCapturePoint(new HellfirePeninsulaCapturePoint(this, OutdoorPvPHPTowerType.BrokenHill, go, m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.BrokenHill]));
break;
case 182174:
AddCapturePoint(new HellfirePeninsulaCapturePoint(this, OutdoorPvPHPTowerType.Overlook, go, m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.Overlook]));
break;
case 182173:
AddCapturePoint(new HellfirePeninsulaCapturePoint(this, OutdoorPvPHPTowerType.Stadium, go, m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.Stadium]));
break;
case 183514: case 183514:
m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.BrokenHill] = go.GetSpawnId(); GetControlZoneTowerSouthHandler().SetFlagGuid(go.GetGUID());
break; break;
case 182525: case 182525:
m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.Overlook] = go.GetSpawnId(); GetControlZoneTowerNorthHandler().SetFlagGuid(go.GetGUID());
break; break;
case 183515: case 183515:
m_towerFlagSpawnIds[(int)OutdoorPvPHPTowerType.Stadium] = go.GetSpawnId(); GetControlZoneTowerWestHandler().SetFlagGuid(go.GetGUID());
break; break;
default: default:
break; break;
@@ -65,12 +95,12 @@ namespace Game.PvP
if (player.GetTeam() == Team.Alliance) if (player.GetTeam() == Team.Alliance)
{ {
if (m_AllianceTowersControlled >= 3) if (m_AllianceTowersControlled >= 3)
player.CastSpell(player, OutdoorPvPHPSpells.AllianceBuff, true); player.CastSpell(player, SpellIds.AllianceBuff, true);
} }
else else
{ {
if (m_HordeTowersControlled >= 3) if (m_HordeTowersControlled >= 3)
player.CastSpell(player, OutdoorPvPHPSpells.HordeBuff, true); player.CastSpell(player, SpellIds.HordeBuff, true);
} }
base.HandlePlayerEnterZone(player, zone); base.HandlePlayerEnterZone(player, zone);
} }
@@ -79,31 +109,29 @@ namespace Game.PvP
{ {
// remove buffs // remove buffs
if (player.GetTeam() == Team.Alliance) if (player.GetTeam() == Team.Alliance)
player.RemoveAurasDueToSpell(OutdoorPvPHPSpells.AllianceBuff); player.RemoveAurasDueToSpell(SpellIds.AllianceBuff);
else else
player.RemoveAurasDueToSpell(OutdoorPvPHPSpells.HordeBuff); player.RemoveAurasDueToSpell(SpellIds.HordeBuff);
base.HandlePlayerLeaveZone(player, zone); base.HandlePlayerLeaveZone(player, zone);
} }
public override bool Update(uint diff) public override void Update(uint diff)
{
bool changed = base.Update(diff);
if (changed)
{ {
base.Update(diff);
if (m_AllianceTowersControlled == 3) if (m_AllianceTowersControlled == 3)
TeamApplyBuff(TeamId.Alliance, OutdoorPvPHPSpells.AllianceBuff, OutdoorPvPHPSpells.HordeBuff); TeamApplyBuff(TeamId.Alliance, SpellIds.AllianceBuff, SpellIds.HordeBuff);
else if (m_HordeTowersControlled == 3) else if (m_HordeTowersControlled == 3)
TeamApplyBuff(TeamId.Horde, OutdoorPvPHPSpells.HordeBuff, OutdoorPvPHPSpells.AllianceBuff); TeamApplyBuff(TeamId.Horde, SpellIds.HordeBuff, SpellIds.AllianceBuff);
else else
{ {
TeamCastSpell(TeamId.Alliance, -(int)OutdoorPvPHPSpells.AllianceBuff); TeamCastSpell(TeamId.Alliance, -(int)SpellIds.AllianceBuff);
TeamCastSpell(TeamId.Horde, -(int)OutdoorPvPHPSpells.HordeBuff); TeamCastSpell(TeamId.Horde, -(int)SpellIds.HordeBuff);
} }
SetWorldState(OutdoorPvPHPWorldStates.Count_A, (int)m_AllianceTowersControlled);
SetWorldState(OutdoorPvPHPWorldStates.Count_H, (int)m_HordeTowersControlled); SetWorldState(WorldStateIds.CountA, (int)m_AllianceTowersControlled);
} SetWorldState(WorldStateIds.CountH, (int)m_HordeTowersControlled);
return changed;
} }
public override void SendRemoveWorldStates(Player player) public override void SendRemoveWorldStates(Player player)
@@ -112,30 +140,53 @@ namespace Game.PvP
initWorldStates.MapID = player.GetMapId(); initWorldStates.MapID = player.GetMapId();
initWorldStates.AreaID = player.GetZoneId(); initWorldStates.AreaID = player.GetZoneId();
initWorldStates.SubareaID = player.GetAreaId(); initWorldStates.SubareaID = player.GetAreaId();
initWorldStates.AddState(OutdoorPvPHPWorldStates.Display_A, 0); initWorldStates.AddState(WorldStateIds.DisplayA, 0);
initWorldStates.AddState(OutdoorPvPHPWorldStates.Display_H, 0); initWorldStates.AddState(WorldStateIds.DisplayH, 0);
initWorldStates.AddState(OutdoorPvPHPWorldStates.Count_H, 0); initWorldStates.AddState(WorldStateIds.CountH, 0);
initWorldStates.AddState(OutdoorPvPHPWorldStates.Count_A, 0); initWorldStates.AddState(WorldStateIds.CountA, 0);
for (int i = 0; i < (int)OutdoorPvPHPTowerType.Num; ++i) foreach (var pair in ControlZoneHandlers)
{ {
initWorldStates.AddState(HPConst.Map_N[i], 0); HellfirePeninsulaControlZoneHandler handler = pair.Value as HellfirePeninsulaControlZoneHandler;
initWorldStates.AddState(HPConst.Map_A[i], 0); initWorldStates.AddState(handler.GetWorldStateNeutral(), 0);
initWorldStates.AddState(HPConst.Map_H[i], 0); initWorldStates.AddState(handler.GetWorldStateHorde(), 0);
initWorldStates.AddState(handler.GetWorldStateAlliance(), 0);
} }
player.SendPacket(initWorldStates); player.SendPacket(initWorldStates);
} }
public override void HandleKillImpl(Player killer, Unit killed) public override void HandleKillImpl(Player player, Unit killed)
{ {
if (!killed.IsTypeId(TypeId.Player)) if (!killed.IsPlayer())
return; return;
if (killer.GetTeam() == Team.Alliance && killed.ToPlayer().GetTeam() != Team.Alliance) // need to check if player is inside an capture zone
killer.CastSpell(killer, OutdoorPvPHPSpells.AlliancePlayerKillReward, true); bool isInsideCaptureZone = false;
else if (killer.GetTeam() == Team.Horde && killed.ToPlayer().GetTeam() != Team.Horde) foreach (ObjectGuid guid in _controlZoneGUIDs)
killer.CastSpell(killer, OutdoorPvPHPSpells.HordePlayerKillReward, true); {
GameObject gameObject = GetMap().GetGameObject(guid);
if (gameObject != null)
{
var insidePlayerGuids = gameObject.GetInsidePlayers();
if (!insidePlayerGuids.Empty())
{
if (insidePlayerGuids.Contains(player.GetGUID()))
{
isInsideCaptureZone = true;
break;
}
}
}
}
if (isInsideCaptureZone)
{
if (player.GetTeam() == Team.Alliance && killed.ToPlayer().GetTeam() != Team.Alliance)
player.CastSpell(player, SpellIds.AlliancePlayerKillReward, true);
else if (player.GetTeam() == Team.Horde && killed.ToPlayer().GetTeam() != Team.Horde)
player.CastSpell(player, SpellIds.HordePlayerKillReward, true);
}
} }
public uint GetAllianceTowersControlled() public uint GetAllianceTowersControlled()
@@ -158,131 +209,121 @@ namespace Game.PvP
m_HordeTowersControlled = count; m_HordeTowersControlled = count;
} }
// how many towers are controlled HellfirePeninsulaControlZoneHandler GetControlZoneTowerNorthHandler() { return ControlZoneHandlers[(uint)GameObjectIds.TowerN] as HellfirePeninsulaControlZoneHandler; }
uint m_AllianceTowersControlled; HellfirePeninsulaControlZoneHandler GetControlZoneTowerSouthHandler() { return ControlZoneHandlers[(uint)GameObjectIds.TowerS] as HellfirePeninsulaControlZoneHandler; }
uint m_HordeTowersControlled; HellfirePeninsulaControlZoneHandler GetControlZoneTowerWestHandler() { return ControlZoneHandlers[(uint)GameObjectIds.TowerW] as HellfirePeninsulaControlZoneHandler; }
ulong[] m_towerFlagSpawnIds = new ulong[(int)OutdoorPvPHPTowerType.Num];
} }
class HellfirePeninsulaCapturePoint : OPvPCapturePoint class HellfirePeninsulaControlZoneHandler : OutdoorPvPControlZoneHandler
{ {
public HellfirePeninsulaCapturePoint(OutdoorPvP pvp, OutdoorPvPHPTowerType type, GameObject go, ulong flagSpawnId) : base(pvp) ObjectGuid _flagGuid;
{ uint _textCaptureAlliance;
m_TowerType = (uint)type; uint _textCaptureHorde;
m_flagSpawnId = flagSpawnId; uint _flagArtKitNeutral;
uint _flagArtKitHorde;
uint _flagArtKitAlliance;
int _worldstateNeutral;
int _worldstateHorde;
int _worldstateAlliance;
uint _killCredit;
m_capturePointSpawnId = go.GetSpawnId(); public HellfirePeninsulaControlZoneHandler(HellfirePeninsulaPvP pvp) : base(pvp) { }
m_capturePoint = go;
SetCapturePointData(go.GetEntry()); public override void HandleProgressEventHorde(GameObject controlZone)
{
base.HandleProgressEventHorde(controlZone);
controlZone.SetGoArtKit(1);
controlZone.SendCustomAnim(0);
GameObject flag = controlZone.GetMap().GetGameObject(_flagGuid);
if (flag != null)
flag.SetGoArtKit(_flagArtKitHorde);
controlZone.GetMap().SetWorldStateValue(_worldstateHorde, 1, false);
controlZone.GetMap().SetWorldStateValue(_worldstateAlliance, 0, false);
controlZone.GetMap().SetWorldStateValue(_worldstateNeutral, 0, false);
GetOutdoorPvPHP().SendDefenseMessage(Misc.BuffZones[0], _textCaptureHorde);
var guidSet = controlZone.GetInsidePlayers();
foreach (ObjectGuid guid in guidSet)
{
Player player = Global.ObjAccessor.GetPlayer(controlZone, guid);
if (player != null && player.GetTeam() == Team.Horde)
player.KilledMonsterCredit(_killCredit);
}
} }
public override void ChangeState() public override void HandleProgressEventAlliance(GameObject controlZone)
{ {
uint field = 0; base.HandleProgressEventAlliance(controlZone);
switch (OldState)
controlZone.SetGoArtKit(2);
controlZone.SendCustomAnim(1);
GameObject flag = controlZone.GetMap().GetGameObject(_flagGuid);
if (flag != null)
flag.SetGoArtKit(_flagArtKitAlliance);
controlZone.GetMap().SetWorldStateValue(_worldstateHorde, 0, false);
controlZone.GetMap().SetWorldStateValue(_worldstateAlliance, 1, false);
controlZone.GetMap().SetWorldStateValue(_worldstateNeutral, 0, false);
GetOutdoorPvPHP().SendDefenseMessage(Misc.BuffZones[0], _textCaptureAlliance);
var guidSet = controlZone.GetInsidePlayers();
foreach (ObjectGuid guid in guidSet)
{ {
case ObjectiveStates.Neutral: Player player = Global.ObjAccessor.GetPlayer(controlZone, guid);
field = HPConst.Map_N[m_TowerType]; if (player != null && player.GetTeam() == Team.Alliance)
break; player.KilledMonsterCredit(_killCredit);
case ObjectiveStates.Alliance: }
field = HPConst.Map_A[m_TowerType];
uint alliance_towers = ((HellfirePeninsulaPvP)PvP).GetAllianceTowersControlled();
if (alliance_towers != 0)
((HellfirePeninsulaPvP)PvP).SetAllianceTowersControlled(--alliance_towers);
break;
case ObjectiveStates.Horde:
field = HPConst.Map_H[m_TowerType];
uint horde_towers = ((HellfirePeninsulaPvP)PvP).GetHordeTowersControlled();
if (horde_towers != 0)
((HellfirePeninsulaPvP)PvP).SetHordeTowersControlled(--horde_towers);
break;
case ObjectiveStates.NeutralAllianceChallenge:
field = HPConst.Map_N[m_TowerType];
break;
case ObjectiveStates.NeutralHordeChallenge:
field = HPConst.Map_N[m_TowerType];
break;
case ObjectiveStates.AllianceHordeChallenge:
field = HPConst.Map_A[m_TowerType];
break;
case ObjectiveStates.HordeAllianceChallenge:
field = HPConst.Map_H[m_TowerType];
break;
} }
// send world state update public override void HandleNeutralEventHorde(GameObject controlZone)
if (field != 0)
{ {
PvP.SetWorldState((int)field, 0); base.HandleNeutralEventHorde(controlZone);
field = 0; GetOutdoorPvPHP().SetHordeTowersControlled(GetOutdoorPvPHP().GetHordeTowersControlled() - 1);
} }
uint artkit = 21;
uint artkit2 = HPConst.TowerArtKit_N[m_TowerType]; public override void HandleNeutralEventAlliance(GameObject controlZone)
switch (State)
{ {
case ObjectiveStates.Neutral: base.HandleNeutralEventAlliance(controlZone);
field = HPConst.Map_N[m_TowerType]; GetOutdoorPvPHP().SetAllianceTowersControlled(GetOutdoorPvPHP().GetAllianceTowersControlled() - 1);
break; }
case ObjectiveStates.Alliance:
public override void HandleNeutralEvent(GameObject controlZone)
{ {
field = HPConst.Map_A[m_TowerType]; base.HandleNeutralEvent(controlZone);
artkit = 2; controlZone.SetGoArtKit(21);
artkit2 = HPConst.TowerArtKit_A[m_TowerType]; controlZone.SendCustomAnim(2);
uint alliance_towers = ((HellfirePeninsulaPvP)PvP).GetAllianceTowersControlled(); GameObject flag = controlZone.GetMap().GetGameObject(_flagGuid);
if (alliance_towers < 3) if (flag != null)
((HellfirePeninsulaPvP)PvP).SetAllianceTowersControlled(++alliance_towers); flag.SetGoArtKit(_flagArtKitNeutral);
PvP.SendDefenseMessage(HPConst.BuffZones[0], HPConst.LangCapture_A[m_TowerType]);
break; controlZone.GetMap().SetWorldStateValue(_worldstateHorde, 0, false);
controlZone.GetMap().SetWorldStateValue(_worldstateAlliance, 0, false);
controlZone.GetMap().SetWorldStateValue(_worldstateNeutral, 1, false);
} }
case ObjectiveStates.Horde:
public HellfirePeninsulaPvP GetOutdoorPvPHP()
{ {
field = HPConst.Map_H[m_TowerType]; return GetOutdoorPvP<HellfirePeninsulaPvP>();
artkit = 1;
artkit2 = HPConst.TowerArtKit_H[m_TowerType];
uint horde_towers = ((HellfirePeninsulaPvP)PvP).GetHordeTowersControlled();
if (horde_towers < 3)
((HellfirePeninsulaPvP)PvP).SetHordeTowersControlled(++horde_towers);
PvP.SendDefenseMessage(HPConst.BuffZones[0], HPConst.LangCapture_H[m_TowerType]);
break;
}
case ObjectiveStates.NeutralAllianceChallenge:
field = HPConst.Map_N[m_TowerType];
break;
case ObjectiveStates.NeutralHordeChallenge:
field = HPConst.Map_N[m_TowerType];
break;
case ObjectiveStates.AllianceHordeChallenge:
field = HPConst.Map_A[m_TowerType];
artkit = 2;
artkit2 = HPConst.TowerArtKit_A[m_TowerType];
break;
case ObjectiveStates.HordeAllianceChallenge:
field = HPConst.Map_H[m_TowerType];
artkit = 1;
artkit2 = HPConst.TowerArtKit_H[m_TowerType];
break;
} }
Map map = Global.MapMgr.FindMap(530, 0); public void SetFlagGuid(ObjectGuid guid) { _flagGuid = guid; }
var bounds = map.GetGameObjectBySpawnIdStore().LookupByKey(m_capturePointSpawnId); public void SetTextCaptureHorde(uint text) { _textCaptureHorde = text; }
foreach (var go in bounds) public void SetTextCaptureAlliance(uint text) { _textCaptureAlliance = text; }
go.SetGoArtKit(artkit); public void SetFlagArtKitNeutral(uint artKit) { _flagArtKitNeutral = artKit; }
public void SetFlagArtKitHorde(uint artKit) { _flagArtKitHorde = artKit; }
public void SetFlagArtKitAlliance(uint artKit) { _flagArtKitAlliance = artKit; }
public void SetWorldstateNeutral(int id) { _worldstateNeutral = id; }
public void SetWorldstateHorde(int id) { _worldstateHorde = id; }
public void SetWorldstateAlliance(int id) { _worldstateAlliance = id; }
public void SetKillCredit(uint credit) { _killCredit = credit; }
bounds = map.GetGameObjectBySpawnIdStore().LookupByKey(m_flagSpawnId); public int GetWorldStateNeutral() { return _worldstateNeutral; }
foreach (var go in bounds) public int GetWorldStateHorde() { return _worldstateHorde; }
go.SetGoArtKit(artkit2); public int GetWorldStateAlliance() { return _worldstateAlliance; }
// send world state update
if (field != 0)
PvP.SetWorldState((int)field, 1);
// complete quest objective
if (State == ObjectiveStates.Alliance || State == ObjectiveStates.Horde)
SendObjectiveComplete(HPConst.CreditMarker[m_TowerType], ObjectGuid.Empty);
}
uint m_TowerType;
ulong m_flagSpawnId;
} }
[Script] [Script]
@@ -296,32 +337,10 @@ namespace Game.PvP
} }
} }
struct HPConst struct Misc
{ {
public static uint[] LangCapture_A = { DefenseMessages.BrokenHillTakenAlliance, DefenseMessages.OverlookTakenAlliance, DefenseMessages.StadiumTakenAlliance };
public static uint[] LangCapture_H = { DefenseMessages.BrokenHillTakenHorde, DefenseMessages.OverlookTakenHorde, DefenseMessages.StadiumTakenHorde };
public static uint[] Map_N = { 2485, 2482, 0x9a8 };
public static uint[] Map_A = { 2483, 2480, 2471 };
public static uint[] Map_H = { 2484, 2481, 2470 };
public static uint[] TowerArtKit_A = { 65, 62, 67 };
public static uint[] TowerArtKit_H = { 64, 61, 68 };
public static uint[] TowerArtKit_N = { 66, 63, 69 };
// HP, citadel, ramparts, blood furnace, shattered halls, mag's lair // HP, citadel, ramparts, blood furnace, shattered halls, mag's lair
public static uint[] BuffZones = { 3483, 3563, 3562, 3713, 3714, 3836 }; public static uint[] BuffZones = { 3483, 3563, 3562, 3713, 3714, 3836 };
public static uint[] CreditMarker = { 19032, 19028, 19029 };
public static uint[] CapturePointEventEnter = { 11404, 11396, 11388 };
public static uint[] CapturePointEventLeave = { 11403, 11395, 11387 };
} }
struct DefenseMessages struct DefenseMessages
@@ -334,7 +353,7 @@ namespace Game.PvP
public const uint BrokenHillTakenHorde = 14846; // '|cffffff00Broken Hill has been taken by the Horde!|r' public const uint BrokenHillTakenHorde = 14846; // '|cffffff00Broken Hill has been taken by the Horde!|r'
} }
struct OutdoorPvPHPSpells struct SpellIds
{ {
public const uint AlliancePlayerKillReward = 32155; public const uint AlliancePlayerKillReward = 32155;
public const uint HordePlayerKillReward = 32158; public const uint HordePlayerKillReward = 32158;
@@ -342,7 +361,7 @@ namespace Game.PvP
public const uint HordeBuff = 32049; public const uint HordeBuff = 32049;
} }
enum OutdoorPvPHPTowerType enum TowerType
{ {
BrokenHill = 0, BrokenHill = 0,
Overlook = 1, Overlook = 1,
@@ -350,12 +369,56 @@ namespace Game.PvP
Num = 3 Num = 3
} }
struct OutdoorPvPHPWorldStates struct WorldStateIds
{ {
public const int Display_A = 0x9ba; public const int DisplayA = 0x9ba;
public const int Display_H = 0x9b9; public const int DisplayH = 0x9b9;
public const int Count_H = 0x9ae; public const int CountH = 0x9ae;
public const int Count_A = 0x9ac; public const int CountA = 0x9ac;
public const int UiTowerSA = 2483;
public const int UiTowerSH = 2484;
public const int UiTowerSN = 2485;
public const int UiTowerNA = 2480;
public const int UiTowerNH = 2481;
public const int UiTowerNN = 2482;
public const int UiTowerWA = 2471;
public const int UiTowerWH = 2470;
public const int UiTowerWN = 2472;
}
enum EventIds
{
HP_EVENT_TOWER_W_PROGRESS_HORDE = 11383,
HP_EVENT_TOWER_W_PROGRESS_ALLIANCE = 11387,
HP_EVENT_TOWER_W_NEUTRAL_HORDE = 11386,
HP_EVENT_TOWER_W_NEUTRAL_ALLIANCE = 11385,
HP_EVENT_TOWER_N_PROGRESS_HORDE = 11396,
HP_EVENT_TOWER_N_PROGRESS_ALLIANCE = 11395,
HP_EVENT_TOWER_N_NEUTRAL_HORDE = 11394,
HP_EVENT_TOWER_N_NEUTRAL_ALLIANCE = 11393,
HP_EVENT_TOWER_S_PROGRESS_HORDE = 11404,
HP_EVENT_TOWER_S_PROGRESS_ALLIANCE = 11403,
HP_EVENT_TOWER_S_NEUTRAL_HORDE = 11402,
HP_EVENT_TOWER_S_NEUTRAL_ALLIANCE = 11401
}
enum GameObjectIds
{
TowerW = 182173,
TowerN = 182174,
TowerS = 182175
}
enum KillCreditIds
{
TowerS = 19032,
TowerN = 19028,
TowerW = 19029
} }
} }