Core/PacketIO: Handle QueryCountdownTimer

* Add it to battleground
* Base implementation countdowns in Group
* Fix timer sync between groups in battlegrounds
Port From (https://github.com/TrinityCore/TrinityCore/commit/6ed8b5c9077aba788ff5bc51f2652109bfea6175)
This commit is contained in:
hondacrx
2024-02-06 15:51:24 -05:00
parent 95c3dd2a66
commit 43db82ae61
6 changed files with 109 additions and 50 deletions
+7
View File
@@ -166,4 +166,11 @@ namespace Framework.Constants
Max Max
} }
public enum CountdownTimerType
{
Pvp = 0,
ChallengeMode = 1,
PlayerCountdown = 2
}
} }
@@ -1888,13 +1888,6 @@ namespace Framework.Constants
Max Max
} }
public enum TimerType
{
Pvp = 0,
ChallengerMode = 1,
PlayerCountdown = 2
}
public enum GameError : uint public enum GameError : uint
{ {
System = 0, System = 0,
+13 -34
View File
@@ -130,10 +130,7 @@ namespace Game.BattleGrounds
// Update start time and reset stats timer // Update start time and reset stats timer
SetElapsedTime(GetElapsedTime() + diff); SetElapsedTime(GetElapsedTime() + diff);
if (GetStatus() == BattlegroundStatus.WaitJoin) if (GetStatus() == BattlegroundStatus.WaitJoin)
{
m_ResetStatTimer += diff; m_ResetStatTimer += diff;
m_CountdownTimer += diff;
}
PostUpdateImpl(diff); PostUpdateImpl(diff);
} }
@@ -278,26 +275,6 @@ namespace Game.BattleGrounds
} }
} }
// Send packet every 10 seconds until the 2nd field reach 0
if (m_CountdownTimer >= 10000)
{
uint countdownMaxForBGType = IsArena() ? BattlegroundConst.ArenaCountdownMax : BattlegroundConst.BattlegroundCountdownMax;
StartTimer timer = new();
timer.Type = TimerType.Pvp;
timer.TimeLeft = countdownMaxForBGType - (GetElapsedTime() / 1000);
timer.TotalTime = countdownMaxForBGType;
foreach (var guid in GetPlayers().Keys)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
player.SendPacket(timer);
}
m_CountdownTimer = 0;
}
if (!m_Events.HasAnyFlag(BattlegroundEventFlags.Event1)) if (!m_Events.HasAnyFlag(BattlegroundEventFlags.Event1))
{ {
m_Events |= BattlegroundEventFlags.Event1; m_Events |= BattlegroundEventFlags.Event1;
@@ -316,6 +293,11 @@ namespace Game.BattleGrounds
return; return;
} }
_preparationStartTime = GameTime.GetGameTime();
foreach (Group group in m_BgRaids)
if (group != null)
group.StartCountdown(CountdownTimerType.Pvp, TimeSpan.FromSeconds((int)StartDelayTimes[BattlegroundConst.EventIdFirst] / 1000), _preparationStartTime);
StartingEventCloseDoors(); StartingEventCloseDoors();
SetStartDelayTime(StartDelayTimes[BattlegroundConst.EventIdFirst]); SetStartDelayTime(StartDelayTimes[BattlegroundConst.EventIdFirst]);
// First start warning - 2 or 1 Minute // First start warning - 2 or 1 Minute
@@ -1017,18 +999,8 @@ namespace Game.BattleGrounds
else else
{ {
if (GetStatus() == BattlegroundStatus.WaitJoin) // not started yet if (GetStatus() == BattlegroundStatus.WaitJoin) // not started yet
{
player.CastSpell(player, BattlegroundConst.SpellPreparation, true); // reduces all mana cost of spells. player.CastSpell(player, BattlegroundConst.SpellPreparation, true); // reduces all mana cost of spells.
uint countdownMaxForBGType = IsArena() ? BattlegroundConst.ArenaCountdownMax : BattlegroundConst.BattlegroundCountdownMax;
StartTimer timer = new();
timer.Type = TimerType.Pvp;
timer.TimeLeft = countdownMaxForBGType - (GetElapsedTime() / 1000);
timer.TotalTime = countdownMaxForBGType;
player.SendPacket(timer);
}
if (bp.Mercenary) if (bp.Mercenary)
{ {
if (bp.Team == Team.Horde) if (bp.Team == Team.Horde)
@@ -1062,6 +1034,11 @@ namespace Game.BattleGrounds
group = new Group(); group = new Group();
SetBgRaid(team, group); SetBgRaid(team, group);
group.Create(player); group.Create(player);
TimeSpan countdownMaxForBGType = TimeSpan.FromSeconds((int)StartDelayTimes[BattlegroundConst.EventIdFirst] / 1000);
if (_preparationStartTime != 0)
group.StartCountdown(CountdownTimerType.Pvp, countdownMaxForBGType, _preparationStartTime);
else
group.StartCountdown(CountdownTimerType.Pvp, countdownMaxForBGType);
} }
else // raid already exist else // raid already exist
{ {
@@ -1952,7 +1929,6 @@ namespace Game.BattleGrounds
BattlegroundStatus m_Status; BattlegroundStatus m_Status;
uint m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use uint m_ClientInstanceID; // the instance-id which is sent to the client and without any other internal use
uint m_StartTime; uint m_StartTime;
uint m_CountdownTimer;
uint m_ResetStatTimer; uint m_ResetStatTimer;
uint m_ValidStartPositionTimer; uint m_ValidStartPositionTimer;
int m_EndTime; // it is set to 120000 when bg is ending and it decreases itself int m_EndTime; // it is set to 120000 when bg is ending and it decreases itself
@@ -1994,6 +1970,9 @@ namespace Game.BattleGrounds
List<uint> _pvpStatIds = new(); List<uint> _pvpStatIds = new();
List<BattlegroundPlayerPosition> _playerPositions = new(); List<BattlegroundPlayerPosition> _playerPositions = new();
// Time when the first message "the battle will begin in 2minutes" is send (or 1m for arenas)
long _preparationStartTime;
#endregion #endregion
} }
+49
View File
@@ -1394,6 +1394,25 @@ namespace Game.Groups
} }
} }
public void StartCountdown(CountdownTimerType timerType, TimeSpan duration, long? startTime = null)
{
if (timerType < 0 || (int)timerType >= _countdowns.Length)
return;
if (_countdowns[(int)timerType] == null)
_countdowns[(int)timerType] = new();
_countdowns[(int)timerType].StartCountdown(duration, startTime);
}
public CountdownInfo GetCountdownInfo(CountdownTimerType timerType)
{
if (timerType < 0 || (int)timerType >= _countdowns.Length)
return null;
return _countdowns[(int)timerType];
}
public void SetLootMethod(LootMethod method) public void SetLootMethod(LootMethod method)
{ {
m_lootMethod = method; m_lootMethod = method;
@@ -1961,6 +1980,8 @@ namespace Game.Groups
// Raid markers // Raid markers
RaidMarker[] m_markers = new RaidMarker[MapConst.RaidMarkersCount]; RaidMarker[] m_markers = new RaidMarker[MapConst.RaidMarkersCount];
uint m_activeMarkers; uint m_activeMarkers;
CountdownInfo[] _countdowns = new CountdownInfo[3];
} }
public class MemberSlot public class MemberSlot
@@ -1986,4 +2007,32 @@ namespace Game.Groups
public WorldLocation Location; public WorldLocation Location;
public ObjectGuid TransportGUID; public ObjectGuid TransportGUID;
} }
public class CountdownInfo
{
long _startTime;
long _endTime;
public long GetTimeLeft()
{
return Math.Max(_endTime - GameTime.GetGameTime(), 0);
}
public void StartCountdown(TimeSpan duration, long? startTime)
{
_startTime = startTime.HasValue ? startTime.Value : GameTime.GetGameTime();
_endTime = (long)(_startTime + duration.TotalSeconds);
}
public bool IsRunning()
{
return _endTime > GameTime.GetGameTime();
}
public long GetTotalTime()
{
return _endTime - _startTime;
}
}
} }
+19
View File
@@ -465,6 +465,25 @@ namespace Game
SendPacket(splashScreenShowLatest); SendPacket(splashScreenShowLatest);
} }
[WorldPacketHandler(ClientOpcodes.QueryCountdownTimer, Processing = PacketProcessing.Inplace)]
void HandleQueryCountdownTimer(QueryCountdownTimer queryCountdownTimer)
{
Group group = _player.GetGroup();
if (group == null)
return;
CountdownInfo info = group.GetCountdownInfo(queryCountdownTimer.TimerType);
if (info == null)
return;
StartTimer startTimer = new();
startTimer.Type = queryCountdownTimer.TimerType;
startTimer.TimeLeft = info.GetTimeLeft();
startTimer.TotalTime = info.GetTotalTime();
_player.SendPacket(startTimer);
}
[WorldPacketHandler(ClientOpcodes.ChatUnregisterAllAddonPrefixes)] [WorldPacketHandler(ClientOpcodes.ChatUnregisterAllAddonPrefixes)]
void HandleUnregisterAllAddonPrefixes(ChatUnregisterAllAddonPrefixes packet) void HandleUnregisterAllAddonPrefixes(ChatUnregisterAllAddonPrefixes packet)
{ {
+15 -3
View File
@@ -394,7 +394,7 @@ namespace Game.Networking.Packets
public bool IsTournamentRealm; public bool IsTournamentRealm;
public bool XRealmPvpAlert; public bool XRealmPvpAlert;
public bool BlockExitingLoadingScreen; // when set to true, sending SMSG_UPDATE_OBJECT with CreateObject Self bit = true will not hide loading screen public bool BlockExitingLoadingScreen; // when set to true, sending SMSG_UPDATE_OBJECT with CreateObject Self bit = true will not hide loading screen
// instead it will be done after this packet is sent again with false in this bit and SMSG_UPDATE_OBJECT Values for player // instead it will be done after this packet is sent again with false in this bit and SMSG_UPDATE_OBJECT Values for player
public uint? RestrictedAccountMaxLevel; public uint? RestrictedAccountMaxLevel;
public ulong? RestrictedAccountMaxMoney; public ulong? RestrictedAccountMaxMoney;
public uint? InstanceGroupSize; public uint? InstanceGroupSize;
@@ -1156,7 +1156,7 @@ namespace Game.Networking.Packets
Enable = _worldPacket.HasBit(); Enable = _worldPacket.HasBit();
} }
public bool Enable; public bool Enable;
} }
class AccountHeirloomUpdate : ServerPacket class AccountHeirloomUpdate : ServerPacket
@@ -1277,7 +1277,19 @@ namespace Game.Networking.Packets
public long TotalTime; public long TotalTime;
public long TimeLeft; public long TimeLeft;
public TimerType Type; public CountdownTimerType Type;
}
class QueryCountdownTimer : ClientPacket
{
public CountdownTimerType TimerType;
public QueryCountdownTimer(WorldPacket packet) : base(packet) { }
public override void Read()
{
TimerType = (CountdownTimerType)_worldPacket.ReadInt32();
}
} }
class ConversationLineStarted : ClientPacket class ConversationLineStarted : ClientPacket