Files
CypherCore/Source/Game/OutdoorPVP/OutdoorPvP.cs
T

351 lines
12 KiB
C#

// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Constants;
using Game.Chat;
using Game.Entities;
using Game.Groups;
using Game.Maps;
using Game.Networking;
using Game.Networking.Packets;
using System.Collections.Generic;
using System.Numerics;
namespace Game.PvP
{
// base class for specific outdoor pvp handlers
public class OutdoorPvP : ZoneScript
{
public OutdoorPvP(Map map)
{
m_TypeId = 0;
m_map = map;
m_players[0] = new List<ObjectGuid>();
m_players[1] = new List<ObjectGuid>();
}
public virtual void HandlePlayerEnterZone(Player player, uint zone)
{
m_players[player.GetTeamId()].Add(player.GetGUID());
}
public virtual void HandlePlayerLeaveZone(Player player, uint zone)
{
// 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())
SendRemoveWorldStates(player);
m_players[player.GetTeamId()].Remove(player.GetGUID());
Log.outDebug(LogFilter.Outdoorpvp, "Player {0} left an outdoorpvp zone", player.GetName());
}
public virtual void HandlePlayerResurrects(Player player, uint zone) { }
public virtual void Update(uint diff)
{
foreach (var (_, capturePoint) in m_capturePoints)
capturePoint.Update(diff);
}
public int GetWorldState(int worldStateId)
{
return Global.WorldStateMgr.GetValue(worldStateId, m_map);
}
public void SetWorldState(int worldStateId, int value)
{
Global.WorldStateMgr.SetValue(worldStateId, value, false, m_map);
}
public virtual void HandleKill(Player killer, Unit killed)
{
Group group = killer.GetGroup();
if (group != null)
{
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next())
{
Player groupGuy = refe.GetSource();
if (groupGuy == null)
continue;
// skip if too far away
if (!groupGuy.IsAtGroupRewardDistance(killed))
continue;
// creature kills must be notified, even if not inside objective / not outdoor pvp active
// player kills only count if active and inside objective
if (groupGuy.IsOutdoorPvPActive() || killed.IsTypeId(TypeId.Unit))
HandleKillImpl(groupGuy, killed);
}
}
else
{
// creature kills must be notified, even if not inside objective / not outdoor pvp active
if (killer.IsOutdoorPvPActive() || killed.IsTypeId(TypeId.Unit))
HandleKillImpl(killer, killed);
}
}
public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go)
{
foreach (var pair in m_capturePoints)
if (pair.Value.HandleCustomSpell(player, spellId, go))
return true;
return false;
}
public virtual bool HandleOpenGo(Player player, GameObject go)
{
foreach (var pair in m_capturePoints)
if (pair.Value.HandleOpenGo(player, go) >= 0)
return true;
return false;
}
public virtual bool HandleDropFlag(Player player, uint id)
{
foreach (var pair in m_capturePoints)
if (pair.Value.HandleDropFlag(player, id))
return true;
return false;
}
public virtual bool HandleAreaTrigger(Player player, uint trigger, bool entered)
{
return false;
}
public void BroadcastPacket(ServerPacket packet)
{
// This is faster than sWorld.SendZoneMessage
for (int team = 0; team < 2; ++team)
{
foreach (var guid in m_players[team])
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
player.SendPacket(packet);
}
}
}
public void RegisterZone(uint zoneId)
{
Global.OutdoorPvPMgr.AddZone(zoneId, this);
}
public bool HasPlayer(Player player)
{
return m_players[player.GetTeamId()].Contains(player.GetGUID());
}
public void TeamCastSpell(uint teamIndex, int spellId)
{
foreach (var guid in m_players[teamIndex])
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
{
if (spellId > 0)
player.CastSpell(player, (uint)spellId, true);
else
player.RemoveAura((uint)-spellId); // by stack?
}
}
}
public void TeamApplyBuff(uint teamIndex, uint spellId, uint spellId2)
{
TeamCastSpell(teamIndex, (int)spellId);
TeamCastSpell((uint)(teamIndex == BatttleGroundTeamId.Alliance ? BatttleGroundTeamId.Horde : BatttleGroundTeamId.Alliance), spellId2 != 0 ? -(int)spellId2 : -(int)spellId);
}
public void SendDefenseMessage(uint zoneId, uint id)
{
DefenseMessageBuilder builder = new(zoneId, id);
var localizer = new LocalizedDo(builder);
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)
{
for (uint i = 0; i < SharedConst.PvpTeamsCount; ++i)
{
foreach (var guid in m_players[i])
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
if (player.GetZoneId() == zoneId)
_worker.Invoke(player);
}
}
}
// setup stuff
public virtual bool SetupOutdoorPvP() { return true; }
public virtual void HandleKillImpl(Player killer, Unit killed) { }
// awards rewards for player kill
public virtual void AwardKillBonus(Player player) { }
public OutdoorPvPTypes GetTypeId() { return m_TypeId; }
public virtual void SendRemoveWorldStates(Player player) { }
public Map GetMap() { return m_map; }
// the map of the objectives belonging to this outdoorpvp
public Dictionary<ulong, OPvPCapturePoint> m_capturePoints = new();
protected Dictionary<uint /*control zone entry*/, OutdoorPvPControlZoneHandler> ControlZoneHandlers = new();
List<ObjectGuid>[] m_players = new List<ObjectGuid>[2];
public OutdoorPvPTypes m_TypeId;
Map m_map;
}
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)
{
m_team = BatttleGroundTeamId.Neutral;
OldState = ObjectiveStates.Neutral;
State = ObjectiveStates.Neutral;
PvP = pvp;
}
public virtual void Update(uint diff) { }
public virtual bool HandleCustomSpell(Player player, uint spellId, GameObject go)
{
if (!player.IsOutdoorPvPActive())
return false;
return false;
}
public virtual bool HandleDropFlag(Player player, uint id)
{
return false;
}
public virtual int HandleOpenGo(Player player, GameObject go)
{
return -1;
}
public virtual void ChangeState() { }
public virtual void ChangeTeam(uint oldTeam) { }
}
public class OutdoorPvPControlZoneHandler : ControlZoneHandler
{
OutdoorPvP _pvp;
public OutdoorPvPControlZoneHandler(OutdoorPvP pvp)
{
_pvp = pvp;
}
public T GetOutdoorPvP<T>() where T : OutdoorPvP { return _pvp as T; }
}
class DefenseMessageBuilder : MessageBuilder
{
public DefenseMessageBuilder(uint zoneId, uint id)
{
_zoneId = zoneId;
_id = id;
}
public override PacketSenderOwning<DefenseMessage> Invoke(Locale locale = Locale.enUS)
{
string text = Global.OutdoorPvPMgr.GetDefenseMessage(_zoneId, _id, locale);
PacketSenderOwning<DefenseMessage> defenseMessage = new();
defenseMessage.Data.ZoneID = _zoneId;
defenseMessage.Data.MessageText = text;
return defenseMessage;
}
uint _zoneId; // ZoneId
uint _id; // BroadcastTextId
}
public class go_type
{
public go_type(uint _entry, uint _map, float _x, float _y, float _z, float _o, float _rot0, float _rot1, float _rot2, float _rot3)
{
entry = _entry;
map = _map;
pos = new Position(_x, _y, _z, _o);
rot = new Quaternion(_rot0, _rot1, _rot2, _rot3);
}
public uint entry;
public uint map;
public Position pos;
public Quaternion rot;
}
class creature_type
{
public creature_type(uint _entry, uint _map, float _x, float _y, float _z, float _o)
{
entry = _entry;
map = _map;
pos = new Position(_x, _y, _z, _o);
}
public uint entry;
public uint map;
Position pos;
}
}