Core/Battlegrounds: Move to scripts And a lot of misc commits i couldn't recover.

Port From (https://github.com/TrinityCore/TrinityCore/commit/d0d5d309bb5877dc2fcb27f6cb123707a31ec1e8)
This commit is contained in:
Hondacrx
2024-08-04 15:18:22 -04:00
parent bca02a24b0
commit e9b21a91be
139 changed files with 8322 additions and 8700 deletions
+17 -5
View File
@@ -506,14 +506,26 @@ namespace Game.Achievements
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
uint titleId = reward.TitleId[achievement.Id == 1793 ? (int)_owner.GetNativeGender() : (_owner.GetTeam() == Team.Alliance ? 0 : 1)];
if (titleId != 0)
uint titleId = 0;
if (achievement.Id == 1793)
titleId = reward.TitleId[(int)_owner.GetNativeGender()];
else
{
CharTitlesRecord titleEntry = CliDB.CharTitlesStorage.LookupByKey(titleId);
if (titleEntry != null)
_owner.SetTitle(titleEntry);
switch (_owner.GetTeam())
{
case Team.Alliance:
titleId = reward.TitleId[0];
break;
case Team.Horde:
titleId = reward.TitleId[1];
break;
}
}
var titleEntry = CliDB.CharTitlesStorage.LookupByKey(titleId);
if (titleEntry != null)
_owner.SetTitle(titleEntry);
// mail
if (reward.SenderCreatureId != 0)
{
+2 -4
View File
@@ -1254,8 +1254,7 @@ namespace Game.Achievements
}
case ModifierTreeType.PlayerMeetsCondition: // 2
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(reqValue);
if (playerCondition == null || !ConditionManager.IsPlayerMeetingCondition(referencePlayer, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(referencePlayer, reqValue))
return false;
break;
}
@@ -1520,8 +1519,7 @@ namespace Game.Achievements
if (refe == null || !refe.IsPlayer())
return false;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(reqValue);
if (playerCondition == null || !ConditionManager.IsPlayerMeetingCondition(refe.ToPlayer(), playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(refe.ToPlayer(), reqValue))
return false;
break;
}
+7 -7
View File
@@ -102,7 +102,7 @@ namespace Game.Arenas
{
// if the player was a match participant, calculate rating
ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(bgPlayer.Team)));
ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(SharedConst.GetOtherTeam(bgPlayer.Team)));
ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(bgPlayer.Team));
// left a rated match while the encounter was in progress, consider as loser
@@ -110,9 +110,9 @@ namespace Game.Arenas
{
Player player = _GetPlayer(guid, bgPlayer.OfflineRemoveTime != 0, "Arena.RemovePlayerAtLeave");
if (player != null)
loserArenaTeam.MemberLost(player, GetArenaMatchmakerRating(GetOtherTeam(bgPlayer.Team)));
loserArenaTeam.MemberLost(player, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(bgPlayer.Team)));
else
loserArenaTeam.OfflineMemberLost(guid, GetArenaMatchmakerRating(GetOtherTeam(bgPlayer.Team)));
loserArenaTeam.OfflineMemberLost(guid, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(bgPlayer.Team)));
}
}
}
@@ -147,14 +147,14 @@ namespace Game.Arenas
// In case of arena draw, follow this logic:
// winnerArenaTeam => ALLIANCE, loserArenaTeam => HORDE
ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Alliance : winner));
ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Horde : GetOtherTeam(winner)));
ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Horde : SharedConst.GetOtherTeam(winner)));
if (winnerArenaTeam != null && loserArenaTeam != null && winnerArenaTeam != loserArenaTeam)
{
// In case of arena draw, follow this logic:
// winnerMatchmakerRating => ALLIANCE, loserMatchmakerRating => HORDE
loserTeamRating = loserArenaTeam.GetRating();
loserMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Horde : GetOtherTeam(winner));
loserMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Horde : SharedConst.GetOtherTeam(winner));
winnerTeamRating = winnerArenaTeam.GetRating();
winnerMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Alliance : winner);
@@ -168,7 +168,7 @@ namespace Game.Arenas
loserTeamRating, loserChange, loserMatchmakerRating, loserMatchmakerChange);
SetArenaMatchmakerRating(winner, (uint)(winnerMatchmakerRating + winnerMatchmakerChange));
SetArenaMatchmakerRating(GetOtherTeam(winner), (uint)(loserMatchmakerRating + loserMatchmakerChange));
SetArenaMatchmakerRating(SharedConst.GetOtherTeam(winner), (uint)(loserMatchmakerRating + loserMatchmakerChange));
// bg team that the client expects is different to TeamId
// alliance 1, horde 0
@@ -176,7 +176,7 @@ namespace Game.Arenas
byte loserTeam = (byte)(winner == Team.Alliance ? PvPTeamId.Horde : PvPTeamId.Alliance);
_arenaTeamScores[winnerTeam].Assign(winnerTeamRating, (uint)(winnerTeamRating + winnerChange), winnerMatchmakerRating, GetArenaMatchmakerRating(winner));
_arenaTeamScores[loserTeam].Assign(loserTeamRating, (uint)(loserTeamRating + loserChange), loserMatchmakerRating, GetArenaMatchmakerRating(GetOtherTeam(winner)));
_arenaTeamScores[loserTeam].Assign(loserTeamRating, (uint)(loserTeamRating + loserChange), loserMatchmakerRating, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(winner)));
Log.outDebug(LogFilter.Arena, "Arena match Type: {0} for Team1Id: {1} - Team2Id: {2} ended. WinnerTeamId: {3}. Winner rating: +{4}, Loser rating: {5}",
GetArenaType(), GetArenaTeamIdByIndex(BattleGroundTeamId.Alliance), GetArenaTeamIdByIndex(BattleGroundTeamId.Horde), winnerArenaTeam.GetId(), winnerChange, loserChange);
@@ -1,93 +0,0 @@
// 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.BattleGrounds;
using Game.Entities;
using Game.Networking.Packets;
using System;
namespace Game.Arenas
{
public class BladesEdgeArena : Arena
{
public BladesEdgeArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
taskScheduler.Update(diff);
}
public override void StartingEventCloseDoors()
{
for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door4; ++i)
SpawnBGObject(i, BattlegroundConst.RespawnImmediately);
for (int i = BladeEdgeObjectTypes.Buff1; i <= BladeEdgeObjectTypes.Buff2; ++i)
SpawnBGObject(i, BattlegroundConst.RespawnOneDay);
}
public override void StartingEventOpenDoors()
{
for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door4; ++i)
DoorOpen(i);
taskScheduler.Schedule(TimeSpan.FromSeconds(5), task =>
{
for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door2; ++i)
DelObject(i);
});
for (int i = BladeEdgeObjectTypes.Buff1; i <= BladeEdgeObjectTypes.Buff2; ++i)
SpawnBGObject(i, 60);
}
public override bool SetupBattleground()
{
bool result = true;
result &= AddObject(BladeEdgeObjectTypes.Door1, BladeEfgeGameObjects.Door1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, BattlegroundConst.RespawnImmediately);
result &= AddObject(BladeEdgeObjectTypes.Door2, BladeEfgeGameObjects.Door2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, BattlegroundConst.RespawnImmediately);
result &= AddObject(BladeEdgeObjectTypes.Door3, BladeEfgeGameObjects.Door3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, BattlegroundConst.RespawnImmediately);
result &= AddObject(BladeEdgeObjectTypes.Door4, BladeEfgeGameObjects.Door4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, BattlegroundConst.RespawnImmediately);
if (!result)
{
Log.outError(LogFilter.Sql, "BatteGroundBE: Failed to spawn door object!");
return false;
}
result &= AddObject(BladeEdgeObjectTypes.Buff1, BladeEfgeGameObjects.Buff1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120);
result &= AddObject(BladeEdgeObjectTypes.Buff2, BladeEfgeGameObjects.Buff2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120);
if (!result)
{
Log.outError(LogFilter.Sql, "BladesEdgeArena: Failed to spawn buff object!");
return false;
}
return true;
}
}
struct BladeEdgeObjectTypes
{
public const int Door1 = 0;
public const int Door2 = 1;
public const int Door3 = 2;
public const int Door4 = 3;
public const int Buff1 = 4;
public const int Buff2 = 5;
public const int Max = 6;
}
struct BladeEfgeGameObjects
{
public const uint Door1 = 183971;
public const uint Door2 = 183973;
public const uint Door3 = 183970;
public const uint Door4 = 183972;
public const uint Buff1 = 184663;
public const uint Buff2 = 184664;
}
}
-239
View File
@@ -1,239 +0,0 @@
// 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 Framework.Dynamic;
using Game.BattleGrounds;
using Game.Entities;
using Game.Networking.Packets;
using System;
namespace Game.Arenas
{
class DalaranSewersArena : Arena
{
uint _pipeKnockBackTimer;
uint _pipeKnockBackCount;
public DalaranSewersArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate)
{
_events = new EventMap();
}
public override void StartingEventCloseDoors()
{
for (int i = DalaranSewersObjectTypes.Door1; i <= DalaranSewersObjectTypes.Door2; ++i)
SpawnBGObject(i, BattlegroundConst.RespawnImmediately);
}
public override void StartingEventOpenDoors()
{
for (int i = DalaranSewersObjectTypes.Door1; i <= DalaranSewersObjectTypes.Door2; ++i)
DoorOpen(i);
for (int i = DalaranSewersObjectTypes.Buff1; i <= DalaranSewersObjectTypes.Buff2; ++i)
SpawnBGObject(i, 60);
_events.ScheduleEvent(DalaranSewersEvents.WaterfallWarning, DalaranSewersData.WaterfallTimerMin, DalaranSewersData.WaterfallTimerMax);
//_events.ScheduleEvent(DalaranSewersEvents.PipeKnockback, DalaranSewersData.PipeKnockbackFirstDelay);
_pipeKnockBackCount = 0;
_pipeKnockBackTimer = DalaranSewersData.PipeKnockbackFirstDelay;
SpawnBGObject(DalaranSewersObjectTypes.Water2, BattlegroundConst.RespawnImmediately);
DoorOpen(DalaranSewersObjectTypes.Water1); // Turn off collision
DoorOpen(DalaranSewersObjectTypes.Water2);
// Remove effects of Demonic Circle Summon
foreach (var pair in GetPlayers())
{
Player player = _GetPlayer(pair, "BattlegroundDS::StartingEventOpenDoors");
if (player != null)
player.RemoveAurasDueToSpell(DalaranSewersSpells.DemonicCircle);
}
}
public override bool SetupBattleground()
{
bool result = true;
result &= AddObject(DalaranSewersObjectTypes.Door1, DalaranSewersGameObjects.Door1, 1350.95f, 817.2f, 20.8096f, 3.15f, 0, 0, 0.99627f, 0.0862864f, BattlegroundConst.RespawnImmediately);
result &= AddObject(DalaranSewersObjectTypes.Door2, DalaranSewersGameObjects.Door2, 1232.65f, 764.913f, 20.0729f, 6.3f, 0, 0, 0.0310211f, -0.999519f, BattlegroundConst.RespawnImmediately);
if (!result)
{
Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn door object!");
return false;
}
// buffs
result &= AddObject(DalaranSewersObjectTypes.Buff1, DalaranSewersGameObjects.Buff1, 1291.7f, 813.424f, 7.11472f, 4.64562f, 0, 0, 0.730314f, -0.683111f, 120);
result &= AddObject(DalaranSewersObjectTypes.Buff2, DalaranSewersGameObjects.Buff2, 1291.7f, 768.911f, 7.11472f, 1.55194f, 0, 0, 0.700409f, 0.713742f, 120);
if (!result)
{
Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn buff object!");
return false;
}
result &= AddObject(DalaranSewersObjectTypes.Water1, DalaranSewersGameObjects.Water1, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120);
result &= AddObject(DalaranSewersObjectTypes.Water2, DalaranSewersGameObjects.Water2, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120);
result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.WaterfallKnockback, 1292.587f, 790.2205f, 7.19796f, 3.054326f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null;
result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.PipeKnockback1, 1369.977f, 817.2882f, 16.08718f, 3.106686f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null;
result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.PipeKnockback2, 1212.833f, 765.3871f, 16.09484f, 0.0f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null;
if (!result)
{
Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn collision object!");
return false;
}
return true;
}
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case DalaranSewersEvents.WaterfallWarning:
// Add the water
DoorClose(DalaranSewersObjectTypes.Water2);
_events.ScheduleEvent(DalaranSewersEvents.WaterfallOn, DalaranSewersData.WaterWarningDuration);
break;
case DalaranSewersEvents.WaterfallOn:
// Active collision and start knockback timer
DoorClose(DalaranSewersObjectTypes.Water1);
_events.ScheduleEvent(DalaranSewersEvents.WaterfallOff, DalaranSewersData.WaterfallDuration);
_events.ScheduleEvent(DalaranSewersEvents.WaterfallKnockback, DalaranSewersData.WaterfallKnockbackTimer);
break;
case DalaranSewersEvents.WaterfallOff:
// Remove collision and water
DoorOpen(DalaranSewersObjectTypes.Water1);
DoorOpen(DalaranSewersObjectTypes.Water2);
_events.CancelEvent(DalaranSewersEvents.WaterfallKnockback);
_events.ScheduleEvent(DalaranSewersEvents.WaterfallWarning, DalaranSewersData.WaterfallTimerMin, DalaranSewersData.WaterfallTimerMax);
break;
case DalaranSewersEvents.WaterfallKnockback:
{
// Repeat knockback while the waterfall still active
Creature waterSpout = GetBGCreature(DalaranSewersCreatureTypes.WaterfallKnockback);
if (waterSpout != null)
waterSpout.CastSpell(waterSpout, DalaranSewersSpells.WaterSpout, true);
_events.ScheduleEvent(eventId, DalaranSewersData.WaterfallKnockbackTimer);
}
break;
case DalaranSewersEvents.PipeKnockback:
{
for (uint i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i)
{
Creature waterSpout = GetBGCreature(i);
if (waterSpout != null)
waterSpout.CastSpell(waterSpout, DalaranSewersSpells.Flush, true);
}
}
break;
}
});
if (_pipeKnockBackCount < DalaranSewersData.PipeKnockbackTotalCount)
{
if (_pipeKnockBackTimer < diff)
{
for (uint i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i)
{
Creature waterSpout = GetBGCreature(i);
if (waterSpout != null)
waterSpout.CastSpell(waterSpout, DalaranSewersSpells.Flush, true);
}
++_pipeKnockBackCount;
_pipeKnockBackTimer = DalaranSewersData.PipeKnockbackDelay;
}
else
_pipeKnockBackTimer -= diff;
}
}
public override void SetData(uint dataId, uint value)
{
base.SetData(dataId, value);
if (dataId == DalaranSewersData.PipeKnockbackCount)
_pipeKnockBackCount = value;
}
public override uint GetData(uint dataId)
{
if (dataId == DalaranSewersData.PipeKnockbackCount)
return _pipeKnockBackCount;
return base.GetData(dataId);
}
}
struct DalaranSewersEvents
{
public const int WaterfallWarning = 1; // Water starting to fall, but no LoS Blocking nor movement blocking
public const uint WaterfallOn = 2; // LoS and Movement blocking active
public const uint WaterfallOff = 3;
public const uint WaterfallKnockback = 4;
public const uint PipeKnockback = 5;
}
struct DalaranSewersObjectTypes
{
public const int Door1 = 0;
public const int Door2 = 1;
public const int Water1 = 2; // Collision
public const int Water2 = 3;
public const int Buff1 = 4;
public const int Buff2 = 5;
public const int Max = 6;
}
struct DalaranSewersGameObjects
{
public const uint Door1 = 192642;
public const uint Door2 = 192643;
public const uint Water1 = 194395; // Collision
public const uint Water2 = 191877;
public const uint Buff1 = 184663;
public const uint Buff2 = 184664;
}
struct DalaranSewersCreatureTypes
{
public const int WaterfallKnockback = 0;
public const int PipeKnockback1 = 1;
public const int PipeKnockback2 = 2;
public const int Max = 3;
}
struct DalaranSewersData
{
// These values are NOT blizzlike... need the correct data!
public static TimeSpan WaterfallTimerMin = TimeSpan.FromSeconds(30);
public static TimeSpan WaterfallTimerMax = TimeSpan.FromSeconds(60);
public static TimeSpan WaterWarningDuration = TimeSpan.FromSeconds(5);
public static TimeSpan WaterfallDuration = TimeSpan.FromSeconds(30);
public static TimeSpan WaterfallKnockbackTimer = TimeSpan.FromSeconds(1.5);
public static uint PipeKnockbackFirstDelay = 5000;
public static uint PipeKnockbackDelay = 3000;
public const uint PipeKnockbackTotalCount = 2;
public const uint PipeKnockbackCount = 1;
public const uint NpcWaterSpout = 28567;
}
struct DalaranSewersSpells
{
public const uint Flush = 57405; // Visual And Target Selector For The Starting Knockback From The Pipe
public const uint FlushKnockback = 61698; // Knockback Effect For Previous Spell (Triggered, Not Needed To Be Cast)
public const uint WaterSpout = 58873; // Knockback Effect Of The Central Waterfall
public const uint DemonicCircle = 48018; // Demonic Circle Summon
}
}
-90
View File
@@ -1,90 +0,0 @@
// 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.BattleGrounds;
using Game.Entities;
using Game.Networking.Packets;
using System;
namespace Game.Arenas
{
public class NagrandArena : Arena
{
public NagrandArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
taskScheduler.Update(diff);
}
public override void StartingEventCloseDoors()
{
for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door4; ++i)
SpawnBGObject(i, BattlegroundConst.RespawnImmediately);
}
public override void StartingEventOpenDoors()
{
for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door4; ++i)
DoorOpen(i);
taskScheduler.Schedule(TimeSpan.FromSeconds(5), task =>
{
for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door2; ++i)
DelObject(i);
});
for (int i = NagrandArenaObjectTypes.Buff1; i <= NagrandArenaObjectTypes.Buff2; ++i)
SpawnBGObject(i, 60);
}
public override bool SetupBattleground()
{
bool result = true;
result &= AddObject(NagrandArenaObjectTypes.Door1, NagrandArenaObjects.Door1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, BattlegroundConst.RespawnImmediately);
result &= AddObject(NagrandArenaObjectTypes.Door2, NagrandArenaObjects.Door2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, BattlegroundConst.RespawnImmediately);
result &= AddObject(NagrandArenaObjectTypes.Door3, NagrandArenaObjects.Door3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, BattlegroundConst.RespawnImmediately);
result &= AddObject(NagrandArenaObjectTypes.Door4, NagrandArenaObjects.Door4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, BattlegroundConst.RespawnImmediately);
if (!result)
{
Log.outError(LogFilter.Sql, "NagrandArena: Failed to spawn door object!");
return false;
}
result &= AddObject(NagrandArenaObjectTypes.Buff1, NagrandArenaObjects.Buff1, 4009.189941f, 2895.250000f, 13.052700f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120);
result &= AddObject(NagrandArenaObjectTypes.Buff2, NagrandArenaObjects.Buff2, 4103.330078f, 2946.350098f, 13.051300f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120);
if (!result)
{
Log.outError(LogFilter.Sql, "NagrandArena: Failed to spawn buff object!");
return false;
}
return true;
}
}
struct NagrandArenaObjectTypes
{
public const int Door1 = 0;
public const int Door2 = 1;
public const int Door3 = 2;
public const int Door4 = 3;
public const int Buff1 = 4;
public const int Buff2 = 5;
public const int Max = 6;
}
struct NagrandArenaObjects
{
public const uint Door1 = 183978;
public const uint Door2 = 183980;
public const uint Door3 = 183977;
public const uint Door4 = 183979;
public const uint Buff1 = 184663;
public const uint Buff2 = 184664;
}
}
-225
View File
@@ -1,225 +0,0 @@
// 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 Framework.Dynamic;
using Game.BattleGrounds;
using Game.Entities;
using Game.Networking.Packets;
using System;
namespace Game.Arenas
{
class RingofValorArena : Arena
{
public RingofValorArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate)
{
_events = new EventMap();
}
public override bool SetupBattleground()
{
bool result = true;
result &= AddObject(RingofValorObjectTypes.Elevator1, RingofValorGameObjects.Elevator1, 763.536377f, -294.535767f, 0.505383f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Elevator2, RingofValorGameObjects.Elevator2, 763.506348f, -273.873352f, 0.505383f, 0.000000f, 0, 0, 0, 0);
if (!result)
{
Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn elevator object!");
return false;
}
result &= AddObject(RingofValorObjectTypes.Buff1, RingofValorGameObjects.Buff1, 735.551819f, -284.794678f, 28.276682f, 0.034906f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Buff2, RingofValorGameObjects.Buff2, 791.224487f, -284.794464f, 28.276682f, 2.600535f, 0, 0, 0, 0);
if (!result)
{
Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn buff object!");
return false;
}
result &= AddObject(RingofValorObjectTypes.Fire1, RingofValorGameObjects.Fire1, 743.543457f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Fire2, RingofValorGameObjects.Fire2, 782.971802f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Firedoor1, RingofValorGameObjects.Firedoor1, 743.711060f, -284.099609f, 27.542587f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Firedoor2, RingofValorGameObjects.Firedoor2, 783.221252f, -284.133362f, 27.535686f, 0.000000f, 0, 0, 0, 0);
if (!result)
{
Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn fire/firedoor object!");
return false;
}
result &= AddObject(RingofValorObjectTypes.Gear1, RingofValorGameObjects.Gear1, 763.664551f, -261.872986f, 26.686588f, 0.000000f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Gear2, RingofValorGameObjects.Gear2, 763.578979f, -306.146149f, 26.665222f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Pulley1, RingofValorGameObjects.Pulley1, 700.722290f, -283.990662f, 39.517582f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Pulley2, RingofValorGameObjects.Pulley2, 826.303833f, -283.996429f, 39.517582f, 0.000000f, 0, 0, 0, 0);
if (!result)
{
Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn gear/pully object!");
return false;
}
result &= AddObject(RingofValorObjectTypes.Pilar1, RingofValorGameObjects.Pilar1, 763.632385f, -306.162384f, 25.909504f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Pilar2, RingofValorGameObjects.Pilar2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Pilar3, RingofValorGameObjects.Pilar3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.Pilar4, RingofValorGameObjects.Pilar4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.PilarCollision1, RingofValorGameObjects.PilarCollision1, 763.632385f, -306.162384f, 30.639660f, 3.141593f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.PilarCollision2, RingofValorGameObjects.PilarCollision2, 723.644287f, -284.493256f, 32.382710f, 0.000000f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.PilarCollision3, RingofValorGameObjects.PilarCollision3, 763.611145f, -261.856750f, 30.639660f, 0.000000f, 0, 0, 0, 0);
result &= AddObject(RingofValorObjectTypes.PilarCollision4, RingofValorGameObjects.PilarCollision4, 802.211609f, -284.493256f, 32.382710f, 3.141593f, 0, 0, 0, 0);
if (!result)
{
Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn pilar object!");
return false;
}
return true;
}
public override void StartingEventOpenDoors()
{
// Buff respawn
SpawnBGObject(RingofValorObjectTypes.Buff1, 90);
SpawnBGObject(RingofValorObjectTypes.Buff2, 90);
// Elevators
DoorOpen(RingofValorObjectTypes.Elevator1);
DoorOpen(RingofValorObjectTypes.Elevator2);
_events.ScheduleEvent(RingofValorEvents.OpenFences, TimeSpan.FromSeconds(20));
// Should be false at first, TogglePillarCollision will do it.
TogglePillarCollision(true);
}
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case RingofValorEvents.OpenFences:
// Open fire (only at game start)
for (byte i = RingofValorObjectTypes.Fire1; i <= RingofValorObjectTypes.Firedoor2; ++i)
DoorOpen(i);
_events.ScheduleEvent(RingofValorEvents.CloseFire, TimeSpan.FromSeconds(5));
break;
case RingofValorEvents.CloseFire:
for (byte i = RingofValorObjectTypes.Fire1; i <= RingofValorObjectTypes.Firedoor2; ++i)
DoorClose(i);
// Fire got closed after five seconds, leaves twenty seconds before toggling pillars
_events.ScheduleEvent(RingofValorEvents.SwitchPillars, TimeSpan.FromSeconds(20));
break;
case RingofValorEvents.SwitchPillars:
TogglePillarCollision(true);
_events.Repeat(TimeSpan.FromSeconds(25));
break;
}
});
}
void TogglePillarCollision(bool enable)
{
// Toggle visual pillars, pulley, gear, and collision based on previous state
for (int i = RingofValorObjectTypes.Pilar1; i <= RingofValorObjectTypes.Gear2; ++i)
{
if (enable)
DoorOpen(i);
else
DoorClose(i);
}
for (byte i = RingofValorObjectTypes.Pilar2; i <= RingofValorObjectTypes.Pulley2; ++i)
{
if (enable)
DoorClose(i);
else
DoorOpen(i);
}
for (byte i = RingofValorObjectTypes.Pilar1; i <= RingofValorObjectTypes.PilarCollision4; ++i)
{
GameObject go = GetBGObject(i);
if (go != null)
{
if (i >= RingofValorObjectTypes.PilarCollision1)
{
GameObjectState state = ((go.GetGoInfo().Door.startOpen != 0) == enable) ? GameObjectState.Active : GameObjectState.Ready;
go.SetGoState(state);
}
foreach (var guid in GetPlayers().Keys)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
go.SendUpdateToPlayer(player);
}
}
}
}
}
struct RingofValorEvents
{
public const int OpenFences = 0;
public const int SwitchPillars = 1;
public const int CloseFire = 2;
}
struct RingofValorObjectTypes
{
public const int Buff1 = 1;
public const int Buff2 = 2;
public const int Fire1 = 3;
public const int Fire2 = 4;
public const int Firedoor1 = 5;
public const int Firedoor2 = 6;
public const int Pilar1 = 7;
public const int Pilar3 = 8;
public const int Gear1 = 9;
public const int Gear2 = 10;
public const int Pilar2 = 11;
public const int Pilar4 = 12;
public const int Pulley1 = 13;
public const int Pulley2 = 14;
public const int PilarCollision1 = 15;
public const int PilarCollision2 = 16;
public const int PilarCollision3 = 17;
public const int PilarCollision4 = 18;
public const int Elevator1 = 19;
public const int Elevator2= 20;
public const int Max = 21;
}
struct RingofValorGameObjects
{
public const uint Buff1 = 184663;
public const uint Buff2 = 184664;
public const uint Fire1 = 192704;
public const uint Fire2 = 192705;
public const uint Firedoor2 = 192387;
public const uint Firedoor1 = 192388;
public const uint Pulley1 = 192389;
public const uint Pulley2 = 192390;
public const uint Gear1 = 192393;
public const uint Gear2 = 192394;
public const uint Elevator1 = 194582;
public const uint Elevator2 = 194586;
public const uint PilarCollision1 = 194580; // Axe
public const uint PilarCollision2 = 194579; // Arena
public const uint PilarCollision3 = 194581; // Lightning
public const uint PilarCollision4 = 194578; // Ivory
public const uint Pilar1 = 194583; // Axe
public const uint Pilar2 = 194584; // Arena
public const uint Pilar3 = 194585; // Lightning
public const uint Pilar4 = 194587; // Ivory
}
}
@@ -1,84 +0,0 @@
// 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.BattleGrounds;
using Game.Entities;
using Game.Networking.Packets;
using System;
namespace Game.Arenas
{
class RuinsofLordaeronArena : Arena
{
public RuinsofLordaeronArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
taskScheduler.Update(diff);
}
public override bool SetupBattleground()
{
bool result = true;
result &= AddObject(RuinsofLordaeronObjectTypes.Door1, RuinsofLordaeronObjectTypes.Door1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f);
result &= AddObject(RuinsofLordaeronObjectTypes.Door2, RuinsofLordaeronObjectTypes.Door2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f);
if (!result)
{
Log.outError(LogFilter.Sql, "RuinsofLordaeronArena: Failed to spawn door object!");
return false;
}
result &= AddObject(RuinsofLordaeronObjectTypes.Buff1, RuinsofLordaeronObjectTypes.Buff1, 1328.719971f, 1632.719971f, 36.730400f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120);
result &= AddObject(RuinsofLordaeronObjectTypes.Buff2, RuinsofLordaeronObjectTypes.Buff2, 1243.300049f, 1699.170044f, 34.872601f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120);
if (!result)
{
Log.outError(LogFilter.Sql, "RuinsofLordaeronArena: Failed to spawn buff object!");
return false;
}
return true;
}
public override void StartingEventCloseDoors()
{
for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i)
SpawnBGObject(i, BattlegroundConst.RespawnImmediately);
}
public override void StartingEventOpenDoors()
{
for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i)
DoorOpen(i);
taskScheduler.Schedule(TimeSpan.FromSeconds(5), task =>
{
for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i)
DelObject(i);
});
for (int i = RuinsofLordaeronObjectTypes.Buff1; i <= RuinsofLordaeronObjectTypes.Buff2; ++i)
SpawnBGObject(i, 60);
}
}
struct RuinsofLordaeronObjectTypes
{
public const int Door1 = 0;
public const int Door2 = 1;
public const int Buff1 = 2;
public const int Buff2 = 3;
public const int Max = 4;
}
struct RuinsofLordaeronGameObjects
{
public const uint Door1 = 185918;
public const uint Door2 = 185917;
public const uint Buff1 = 184663;
public const uint Buff2 = 184664;
}
}
-9
View File
@@ -1,9 +0,0 @@
// 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.
namespace Game.Arenas
{
class TigersPeak
{
}
}
@@ -1,9 +0,0 @@
// 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.
namespace Game.Arenas
{
class TolvironArena
{
}
}
+1 -2
View File
@@ -174,7 +174,7 @@ namespace Game.BattleFields
if (m_PlayersInQueue[player.GetTeamId()].Contains(player.GetGUID()))
return;
if (m_PlayersInQueue[player.GetTeamId()].Count <= m_MinPlayer || m_PlayersInQueue[GetOtherTeam(player.GetTeamId())].Count >= m_MinPlayer)
if (m_PlayersInQueue[player.GetTeamId()].Count <= m_MinPlayer || m_PlayersInQueue[SharedConst.GetOtherTeam(player.GetTeamId())].Count >= m_MinPlayer)
PlayerAcceptInviteToQueue(player);
}
@@ -705,7 +705,6 @@ namespace Game.BattleFields
// Battlefield - generic methods
public uint GetDefenderTeam() { return m_DefenderTeam; }
public uint GetAttackerTeam() { return 1 - m_DefenderTeam; }
public int GetOtherTeam(int teamIndex) { return (teamIndex == BattleGroundTeamId.Horde ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde); }
void SetDefenderTeam(uint team) { m_DefenderTeam = team; }
// Called on start
+26 -338
View File
@@ -40,15 +40,8 @@ namespace Game.BattleGrounds
public virtual void Dispose()
{
// remove objects and creatures
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
for (uint i = 0; i < BgCreatures.Length; ++i)
DelCreature(i);
for (var i = 0; i < BgObjects.Length; ++i)
DelObject(i);
Global.BattlegroundMgr.RemoveBattleground(GetTypeID(), GetInstanceID());
// unload map
if (m_Map != null)
{
@@ -207,7 +200,7 @@ namespace Game.BattleGrounds
}
}
public virtual Team GetPrematureWinner()
public Team GetPrematureWinner()
{
Team winner = Team.Other;
if (GetPlayersCountByTeam(Team.Alliance) >= GetMinPlayersPerTeam())
@@ -286,19 +279,12 @@ namespace Game.BattleGrounds
return;
}
// Setup here, only when at least one player has ported to the map
if (!SetupBattleground())
{
EndNow();
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();
GetBgMap().GetBattlegroundScript().OnPrepareStage1();
SetStartDelayTime(StartDelayTimes[BattlegroundConst.EventIdFirst]);
// First start warning - 2 or 1 Minute
if (StartMessageIds[BattlegroundConst.EventIdFirst] != 0)
@@ -308,6 +294,7 @@ namespace Game.BattleGrounds
else if (GetStartDelayTime() <= (int)StartDelayTimes[BattlegroundConst.EventIdSecond] && !m_Events.HasAnyFlag(BattlegroundEventFlags.Event2))
{
m_Events |= BattlegroundEventFlags.Event2;
GetBgMap().GetBattlegroundScript().OnPrepareStage2();
if (StartMessageIds[BattlegroundConst.EventIdSecond] != 0)
SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdSecond], ChatMsg.BgSystemNeutral);
}
@@ -315,6 +302,7 @@ namespace Game.BattleGrounds
else if (GetStartDelayTime() <= (int)StartDelayTimes[BattlegroundConst.EventIdThird] && !m_Events.HasAnyFlag(BattlegroundEventFlags.Event3))
{
m_Events |= BattlegroundEventFlags.Event3;
GetBgMap().GetBattlegroundScript().OnPrepareStage3();
if (StartMessageIds[BattlegroundConst.EventIdThird] != 0)
SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdThird], ChatMsg.BgSystemNeutral);
}
@@ -323,7 +311,7 @@ namespace Game.BattleGrounds
{
m_Events |= BattlegroundEventFlags.Event4;
StartingEventOpenDoors();
GetBgMap().GetBattlegroundScript().OnStart();
if (StartMessageIds[BattlegroundConst.EventIdFourth] != 0)
SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdFourth], ChatMsg.RaidBossEmote);
@@ -740,6 +728,8 @@ namespace Game.BattleGrounds
player.SendPacket(pvpMatchComplete);
player.UpdateCriteria(CriteriaType.ParticipateInBattleground, player.GetMapId());
GetBgMap().GetBattlegroundScript().OnEnd(winner);
}
}
@@ -1027,6 +1017,8 @@ namespace Game.BattleGrounds
// setup BG group membership
PlayerAddedToBGCheckIfBGIsRunning(player);
AddOrSetPlayerToCorrectBgGroup(player, team);
GetBgMap().GetBattlegroundScript().OnPlayerJoined(player, isInBattleground);
}
// this method adds player to his team's bg group, or sets his correct group if player is already in bg group
@@ -1104,8 +1096,8 @@ namespace Game.BattleGrounds
// 1 player is logging out, if it is the last alive, then end arena!
if (IsArena() && player.IsAlive())
if (GetAlivePlayersCountByTeam(player.GetBGTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player.GetBGTeam())) != 0)
EndBattleground(GetOtherTeam(player.GetBGTeam()));
if (GetAlivePlayersCountByTeam(player.GetBGTeam()) <= 1 && GetPlayersCountByTeam(SharedConst.GetOtherTeam(player.GetBGTeam())) != 0)
EndBattleground(SharedConst.GetOtherTeam(player.GetBGTeam()));
}
}
@@ -1241,7 +1233,7 @@ namespace Game.BattleGrounds
return PlayerScores.LookupByKey(player.GetGUID());
}
public virtual bool UpdatePlayerScore(Player player, ScoreType type, uint value, bool doAddHonor = true)
public bool UpdatePlayerScore(Player player, ScoreType type, uint value, bool doAddHonor = true)
{
var bgScore = PlayerScores.LookupByKey(player.GetGUID());
if (bgScore == null) // player not found...
@@ -1262,99 +1254,6 @@ namespace Game.BattleGrounds
score.UpdatePvpStat(pvpStatId, value);
}
public bool AddObject(int type, uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready)
{
Map map = FindBgMap();
if (map == null)
return false;
Quaternion rotation = new(rotation0, rotation1, rotation2, rotation3);
// Temporally add safety check for bad spawns and send log (object rotations need to be rechecked in sniff)
if (rotation0 == 0 && rotation1 == 0 && rotation2 == 0 && rotation3 == 0)
{
Log.outDebug(LogFilter.Battleground, $"Battleground.AddObject: gameoobject [entry: {entry}, object type: {type}] for BG (map: {GetMapId()}) has zeroed rotation fields, " +
"orientation used temporally, but please fix the spawn");
rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(o, 0.0f, 0.0f));
}
// Must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go.LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// So we must create it specific for this instance
GameObject go = GameObject.CreateGameObject(entry, GetBgMap(), new Position(x, y, z, o), rotation, 255, goState);
if (go == null)
{
Log.outError(LogFilter.Battleground, $"Battleground.AddObject: cannot create gameobject (entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return false;
}
// Add to world, so it can be later looked up from HashMapHolder
if (!map.AddToMap(go))
return false;
BgObjects[type] = go.GetGUID();
return true;
}
public bool AddObject(int type, uint entry, Position pos, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready)
{
return AddObject(type, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), rotation0, rotation1, rotation2, rotation3, respawnTime, goState);
}
// Some doors aren't despawned so we cannot handle their closing in gameobject.update()
// It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
public void DoorClose(int type)
{
GameObject obj = GetBgMap().GetGameObject(BgObjects[type]);
if (obj != null)
{
// If doors are open, close it
if (obj.GetLootState() == LootState.Activated && obj.GetGoState() != GameObjectState.Ready)
{
obj.SetLootState(LootState.Ready);
obj.SetGoState(GameObjectState.Ready);
}
}
else
Log.outError(LogFilter.Battleground, $"Battleground.DoorClose: door gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
}
public void DoorOpen(int type)
{
GameObject obj = GetBgMap().GetGameObject(BgObjects[type]);
if (obj != null)
{
obj.SetLootState(LootState.Activated);
obj.SetGoState(GameObjectState.Active);
}
else
Log.outError(LogFilter.Battleground, $"Battleground.DoorOpen: door gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
}
public GameObject GetBGObject(int type)
{
if (BgObjects[type].IsEmpty())
return null;
GameObject obj = GetBgMap().GetGameObject(BgObjects[type]);
if (obj == null)
Log.outError(LogFilter.Battleground, $"Battleground.GetBGObject: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return obj;
}
public Creature GetBGCreature(uint type)
{
if (BgCreatures[type].IsEmpty())
return null;
Creature creature = GetBgMap().GetCreature(BgCreatures[type]);
if (creature == null)
Log.outError(LogFilter.Battleground, $"Battleground.GetBGCreature: creature (type: {type}, {BgCreatures[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return creature;
}
public uint GetMapId()
{
return (uint)_battlegroundTemplate.BattlemasterEntry.MapId[0];
@@ -1364,168 +1263,11 @@ namespace Game.BattleGrounds
{
m_Map = map;
if (map != null)
{
_pvpStatIds = Global.DB2Mgr.GetPVPStatIDsForMap(map.GetId());
OnMapSet(map);
}
else
_pvpStatIds = null;
}
public void SpawnBGObject(int type, uint respawntime)
{
Map map = FindBgMap();
if (map != null)
{
GameObject obj = map.GetGameObject(BgObjects[type]);
if (obj != null)
{
if (respawntime != 0)
{
obj.SetLootState(LootState.JustDeactivated);
{
GameObjectOverride goOverride = obj.GetGameObjectOverride();
if (goOverride != null)
if (goOverride.Flags.HasFlag(GameObjectFlags.NoDespawn))
{
// This function should be called in GameObject::Update() but in case of
// GO_FLAG_NODESPAWN flag the function is never called, so we call it here
obj.SendGameObjectDespawn();
}
}
}
else if (obj.GetLootState() == LootState.JustDeactivated)
{
// Change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
obj.SetLootState(LootState.Ready);
}
obj.SetRespawnTime((int)respawntime);
map.AddToMap(obj);
}
}
}
public virtual Creature AddCreature(uint entry, uint type, float x, float y, float z, float o, int teamIndex = BattleGroundTeamId.Neutral, uint respawntime = 0, Transport transport = null)
{
Map map = FindBgMap();
if (map == null)
return null;
if (Global.ObjectMgr.GetCreatureTemplate(entry) == null)
{
Log.outError(LogFilter.Battleground, $"Battleground.AddCreature: creature template (entry: {entry}) does not exist for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return null;
}
if (transport != null)
{
Creature transCreature = transport.SummonPassenger(entry, new Position(x, y, z, o), TempSummonType.ManualDespawn);
if (transCreature != null)
{
BgCreatures[type] = transCreature.GetGUID();
return transCreature;
}
return null;
}
Position pos = new(x, y, z, o);
Creature creature = Creature.CreateCreature(entry, map, pos);
if (creature == null)
{
Log.outError(LogFilter.Battleground, $"Battleground.AddCreature: cannot create creature (entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return null;
}
creature.SetHomePosition(pos);
if (!map.AddToMap(creature))
return null;
BgCreatures[type] = creature.GetGUID();
if (respawntime != 0)
creature.SetRespawnDelay(respawntime);
return creature;
}
public Creature AddCreature(uint entry, uint type, Position pos, int teamIndex = BattleGroundTeamId.Neutral, uint respawntime = 0, Transport transport = null)
{
return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex, respawntime, transport);
}
public bool DelCreature(uint type)
{
if (BgCreatures[type].IsEmpty())
return true;
Creature creature = GetBgMap().GetCreature(BgCreatures[type]);
if (creature != null)
{
creature.AddObjectToRemoveList();
BgCreatures[type].Clear();
return true;
}
Log.outError(LogFilter.Battleground, $"Battleground.DelCreature: creature (type: {type}, {BgCreatures[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
BgCreatures[type].Clear();
return false;
}
public bool DelObject(int type)
{
if (BgObjects[type].IsEmpty())
return true;
GameObject obj = GetBgMap().GetGameObject(BgObjects[type]);
if (obj != null)
{
obj.SetRespawnTime(0); // not save respawn time
obj.Delete();
BgObjects[type].Clear();
return true;
}
Log.outError(LogFilter.Battleground, $"Battleground.DelObject: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
BgObjects[type].Clear();
return false;
}
bool RemoveObjectFromWorld(uint type)
{
if (BgObjects[type].IsEmpty())
return true;
GameObject obj = GetBgMap().GetGameObject(BgObjects[type]);
if (obj != null)
{
obj.RemoveFromWorld();
BgObjects[type].Clear();
return true;
}
Log.outInfo(LogFilter.Battleground, $"Battleground::RemoveObjectFromWorld: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
return false;
}
public bool AddSpiritGuide(uint type, float x, float y, float z, float o, int teamIndex)
{
uint entry = (uint)(teamIndex == BattleGroundTeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide);
if (AddCreature(entry, type, x, y, z, o) != null)
return true;
Log.outError(LogFilter.Battleground, $"Battleground.AddSpiritGuide: cannot create spirit guide (type: {type}, entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!");
EndNow();
return false;
}
public bool AddSpiritGuide(uint type, Position pos, int teamIndex = BattleGroundTeamId.Neutral)
{
return AddSpiritGuide(type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex);
}
public void SendMessageToAll(CypherStrings entry, ChatMsg msgType, Player source = null)
{
if (entry == 0)
@@ -1598,9 +1340,18 @@ namespace Game.BattleGrounds
victim.SetUnitFlag(UnitFlags.Skinnable);
RewardXPAtKill(killer, victim);
}
BattlegroundScript script = GetBgMap().GetBattlegroundScript();
if (script != null)
script.OnPlayerKilled(victim, killer);
}
public virtual void HandleKillUnit(Creature creature, Unit killer) { }
public virtual void HandleKillUnit(Creature victim, Unit killer)
{
BattlegroundScript script = GetBgMap().GetBattlegroundScript();
if (script != null)
script.OnUnitKilled(victim, killer);
}
// Return the player's team based on Battlegroundplayer info
// Used in same faction arena matches mainly
@@ -1612,11 +1363,6 @@ namespace Game.BattleGrounds
return Team.Other;
}
public Team GetOtherTeam(Team team)
{
return team != 0 ? ((team == Team.Alliance) ? Team.Horde : Team.Alliance) : Team.Other;
}
public bool IsPlayerInBattleground(ObjectGuid guid)
{
return m_Players.ContainsKey(guid);
@@ -1658,15 +1404,6 @@ namespace Game.BattleGrounds
return count;
}
public int GetObjectType(ObjectGuid guid)
{
for (int i = 0; i < BgObjects.Length; ++i)
if (BgObjects[i] == guid)
return i;
Log.outError(LogFilter.Battleground, $"Battleground.GetObjectType: player used gameobject ({guid}) which is not in internal data for BG (map: {GetMapId()}, instance id: {m_InstanceID}), cheating?");
return -1;
}
public void SetBgRaid(Team team, Group bg_raid)
{
Group old_raid = m_BgRaids[GetTeamIndexByTeamId(team)];
@@ -1677,23 +1414,6 @@ namespace Game.BattleGrounds
m_BgRaids[GetTeamIndexByTeamId(team)] = bg_raid;
}
public virtual WorldSafeLocsEntry GetClosestGraveyard(Player player)
{
return Global.ObjectMgr.GetClosestGraveyard(player, GetPlayerTeam(player.GetGUID()), player);
}
public override void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null)
{
ProcessEvent(target, gameEventId, source);
GameEvents.TriggerForMap(gameEventId, GetBgMap(), source, target);
foreach (var guid in GetPlayers().Keys)
{
Player player = Global.ObjAccessor.FindPlayer(guid);
if (player != null)
GameEvents.TriggerForPlayer(gameEventId, player);
}
}
public void SetBracket(PvpDifficultyRecord bracketEntry)
{
_pvpDifficultyEntry = bracketEntry;
@@ -1714,17 +1434,6 @@ namespace Game.BattleGrounds
return 0;
}
public virtual void HandleAreaTrigger(Player player, uint trigger, bool entered)
{
Log.outDebug(LogFilter.Battleground, "Unhandled AreaTrigger {0} in Battleground {1}. Player coords (x: {2}, y: {3}, z: {4})",
trigger, player.GetMapId(), player.GetPositionX(), player.GetPositionY(), player.GetPositionZ());
}
public virtual bool SetupBattleground()
{
return true;
}
public string GetName()
{
return _battlegroundTemplate.BattlemasterEntry.Name[Global.WorldMgr.GetDefaultDbcLocale()];
@@ -1801,13 +1510,9 @@ namespace Game.BattleGrounds
return m_Players.LookupByKey(playerGuid);
}
// Called when valid BattlegroundMap is assigned to the battleground
public virtual void OnMapSet(BattlegroundMap map) { }
public virtual void StartingEventCloseDoors() { }
public virtual void StartingEventOpenDoors() { }
public virtual void DestroyGate(Player player, GameObject go) { }
public void AddPoint(Team team, uint points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] += points; }
public void SetTeamPoint(Team team, uint points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = points; }
void RemovePoint(Team team, uint points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= points; }
public uint GetInstanceID() { return m_InstanceID; }
public BattlegroundStatus GetStatus() { return m_Status; }
@@ -1878,14 +1583,6 @@ namespace Game.BattleGrounds
public void SetArenaMatchmakerRating(Team team, uint MMR) { m_ArenaTeamMMR[GetTeamIndexByTeamId(team)] = MMR; }
public uint GetArenaMatchmakerRating(Team team) { return m_ArenaTeamMMR[GetTeamIndexByTeamId(team)]; }
// Battleground events
public virtual void EventPlayerDroppedFlag(Player player) { }
public virtual void EventPlayerClickedOnFlag(Player player, GameObject target_obj) { }
public override void ProcessEvent(WorldObject obj, uint eventId, WorldObject invoker = null) { }
public virtual void HandlePlayerResurrect(Player player) { }
public virtual WorldSafeLocsEntry GetExploitTeleportLocation(Team team) { return null; }
public virtual bool HandlePlayerUnderMap(Player player) { return false; }
@@ -1895,12 +1592,6 @@ namespace Game.BattleGrounds
bool CanAwardArenaPoints() { return GetMinLevel() >= 71; }
public virtual ObjectGuid GetFlagPickerGUID(int teamIndex = -1) { return ObjectGuid.Empty; }
public virtual void SetDroppedFlagGUID(ObjectGuid guid, int teamIndex = -1) { }
public virtual void HandleQuestComplete(uint questid, Player player) { }
public virtual bool CanActivateGO(int entry, uint team) { return true; }
public virtual bool IsSpellAllowed(uint spellId, Player player) { return true; }
public virtual void RemovePlayer(Player player, ObjectGuid guid, Team team) { }
public virtual bool PreUpdateImpl(uint diff) { return true; }
@@ -1930,9 +1621,6 @@ namespace Game.BattleGrounds
public uint[] m_TeamScores = new uint[SharedConst.PvpTeamsCount];
protected ObjectGuid[] BgObjects;// = new Dictionary<int, ObjectGuid>();
protected ObjectGuid[] BgCreatures;// = new Dictionary<int, ObjectGuid>();
public uint[] Buff_Entries = { BattlegroundConst.SpeedBuff, BattlegroundConst.RegenBuff, BattlegroundConst.BerserkerBuff };
// Battleground
@@ -3,13 +3,7 @@
using Framework.Constants;
using Framework.Database;
using Game.BattleGrounds.Zones;
using Game.BattleGrounds.Zones.AlteracValley;
using Game.BattleGrounds.Zones.ArathisBasin;
using Game.BattleGrounds.Zones.EyeofStorm;
using Game.BattleGrounds.Zones.IsleOfConquest;
using Game.BattleGrounds.Zones.StrandOfAncients;
using Game.BattleGrounds.Zones.WarsongGluch;
using Game.Arenas;
using Game.DataStorage;
using Game.Entities;
using Game.Networking.Packets;
@@ -201,6 +195,60 @@ namespace Game.BattleGrounds
return null;
}
public void LoadBattlegroundScriptTemplate()
{
uint oldMSTime = Time.GetMSTime();
// 0 1 2
SQLResult result = DB.World.Query("SELECT MapId, BattlemasterListId, ScriptName FROM battleground_scripts");
if (result.IsEmpty())
{
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 battleground scripts. DB table `battleground_scripts` is empty!");
return;
}
uint count = 0;
do
{
uint mapID = result.Read<uint>(0);
var mapEntry = CliDB.MapStorage.LookupByKey(mapID);
if (mapEntry == null || !mapEntry.IsBattlegroundOrArena())
{
Log.outError(LogFilter.Sql, $"BattlegroundMgr::LoadBattlegroundScriptTemplate: bad mapid {mapID}! Map doesn't exist or is not a battleground/arena!");
continue;
}
BattlegroundTypeId bgTypeId = (BattlegroundTypeId)result.Read<uint>(1);
if (bgTypeId != BattlegroundTypeId.None && !_battlegroundTemplates.ContainsKey(bgTypeId))
{
Log.outError(LogFilter.Sql, $"BattlegroundMgr::LoadBattlegroundScriptTemplate: bad battlemasterlist id {bgTypeId}! Battleground doesn't exist or is not supported in battleground_template!");
continue;
}
BattlegroundScriptTemplate scriptTemplate = new();
scriptTemplate.MapId = mapID;
scriptTemplate.Id = bgTypeId;
scriptTemplate.ScriptId = Global.ObjectMgr.GetScriptId(result.Read<string>(2));
_battlegroundScriptTemplates[(mapID, bgTypeId)] = scriptTemplate;
++count;
} while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} battleground scripts in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}
public BattlegroundScriptTemplate FindBattlegroundScriptTemplate(uint mapId, BattlegroundTypeId bgTypeId)
{
BattlegroundScriptTemplate scriptTemplate = _battlegroundScriptTemplates.LookupByKey((mapId, bgTypeId));
if (scriptTemplate != null)
return scriptTemplate;
// fall back to 0 for no specific battleground type id
return _battlegroundScriptTemplates.LookupByKey((mapId, BattlegroundTypeId.None));
}
uint CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
{
if (IsArenaType(bgTypeId))
@@ -250,56 +298,10 @@ namespace Game.BattleGrounds
}
Battleground bg = null;
// create a copy of the BG template
switch (bgTypeId)
{
case BattlegroundTypeId.AV:
bg = new BgAlteracValley(bg_template);
break;
case BattlegroundTypeId.WS:
case BattlegroundTypeId.WgCtf:
bg = new BgWarsongGluch(bg_template);
break;
case BattlegroundTypeId.AB:
case BattlegroundTypeId.DomAb:
bg = new BgArathiBasin(bg_template);
break;
case BattlegroundTypeId.NA:
bg = new BgNagrandArena(bg_template);
break;
case BattlegroundTypeId.BE:
bg = new BgBladesEdgeArena(bg_template);
break;
case BattlegroundTypeId.EY:
bg = new BgEyeofStorm(bg_template);
break;
case BattlegroundTypeId.RL:
bg = new BgRuinsOfLordaernon(bg_template);
break;
case BattlegroundTypeId.SA:
bg = new BgStrandOfAncients(bg_template);
break;
case BattlegroundTypeId.DS:
bg = new BgDalaranSewers(bg_template);
break;
case BattlegroundTypeId.RV:
bg = new BgTheRingOfValor(bg_template);
break;
case BattlegroundTypeId.IC:
bg = new BgIsleofConquest(bg_template);
break;
case BattlegroundTypeId.TP:
bg = new BgTwinPeaks(bg_template);
break;
case BattlegroundTypeId.BFG:
bg = new BgBattleforGilneas(bg_template);
break;
case BattlegroundTypeId.RB:
case BattlegroundTypeId.AA:
case BattlegroundTypeId.RandomEpic:
default:
return null;
}
if (bg_template.IsArena())
bg = new Arena(bg_template);
else
bg = new Battleground(bg_template);
bg.SetBracket(bracketEntry);
bg.SetInstanceID(Global.MapMgr.GenerateInstanceId());
@@ -723,6 +725,7 @@ namespace Game.BattleGrounds
Dictionary<uint, BattlegroundTypeId> mBattleMastersMap = new();
Dictionary<BattlegroundTypeId, BattlegroundTemplate> _battlegroundTemplates = new();
Dictionary<uint, BattlegroundTemplate> _battlegroundMapTemplates = new();
Dictionary<(uint, BattlegroundTypeId), BattlegroundScriptTemplate> _battlegroundScriptTemplates = new();
struct ScheduledQueueUpdate
{
@@ -808,4 +811,11 @@ namespace Game.BattleGrounds
return BattlemasterEntry.MaxLevel;
}
}
public class BattlegroundScriptTemplate
{
public uint MapId;
public BattlegroundTypeId Id;
public uint ScriptId;
}
}
@@ -0,0 +1,136 @@
// 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 Game.Maps;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Framework.Constants;
using Game.Entities;
using System.Numerics;
namespace Game.BattleGrounds
{
public class BattlegroundScript : ZoneScript
{
protected BattlegroundMap battlegroundMap;
protected Battleground battleground;
public BattlegroundScript(BattlegroundMap map)
{
battlegroundMap = map;
battleground = map.GetBG();
}
public virtual Team GetPrematureWinner()
{
Team winner = Team.Other;
if (battleground.GetPlayersCountByTeam(Team.Alliance) >= battleground.GetMinPlayersPerTeam())
winner = Team.Alliance;
else if (battleground.GetPlayersCountByTeam(Team.Horde) >= battleground.GetMinPlayersPerTeam())
winner = Team.Horde;
return winner;
}
public override void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null)
{
ProcessEvent(target, gameEventId, source);
GameEvents.TriggerForMap(gameEventId, battlegroundMap, source, target);
foreach (var (playerGuid, _) in battleground.GetPlayers())
{
Player player = Global.ObjAccessor.FindPlayer(playerGuid);
if (player != null)
GameEvents.TriggerForPlayer(gameEventId, player);
}
}
public void UpdateWorldState(int worldStateId, int value, bool hidden = false)
{
Global.WorldStateMgr.SetValue(worldStateId, value, hidden, battlegroundMap);
}
public void UpdateWorldState(int worldStateId, bool value, bool hidden = false)
{
Global.WorldStateMgr.SetValue(worldStateId, value ? 1 : 0, hidden, battlegroundMap);
}
public virtual void OnInit() { }
public virtual void OnUpdate(uint diff) { }
public virtual void OnPrepareStage1() { }
public virtual void OnPrepareStage2() { }
public virtual void OnPrepareStage3() { }
public virtual void OnStart() { }
public virtual void OnEnd(Team winner) { }
public virtual void OnPlayerJoined(Player player, bool inBattleground) { }
public virtual void OnPlayerLeft(Player player) { }
public virtual void OnPlayerKilled(Player victim, Player killer) { }
public virtual void OnUnitKilled(Creature victim, Unit killer) { }
}
public class ArenaScript : BattlegroundScript
{
public ArenaScript(BattlegroundMap map) : base(map) { }
public GameObject CreateObject(uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GameObjectState goState = GameObjectState.Ready)
{
Quaternion rot = new(rotation0, rotation1, rotation2, rotation3);
// Temporally add safety check for bad spawns and send log (object rotations need to be rechecked in sniff)
if (rotation0 == 0 && rotation1 == 0 && rotation2 == 0 && rotation3 == 0)
{
Log.outDebug(LogFilter.Battleground, $"Battleground::AddObject: gameoobject [entry: {entry}] for BG (map: {battlegroundMap.GetId()}) has zeroed rotation fields, " +
"orientation used temporally, but please fix the spawn");
rot = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(o, 0.0f, 0.0f));
}
// Must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// So we must create it specific for this instance
GameObject go = GameObject.CreateGameObject(entry, battlegroundMap, new Position(x, y, z, o), rot, 255, goState);
if (go == null)
{
Log.outError(LogFilter.Battleground, $"Battleground::AddObject: cannot create gameobject (entry: {entry}) for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!");
return null;
}
if (!battlegroundMap.AddToMap(go))
{
go.Dispose();
return null;
}
return go;
}
public Creature CreateCreature(uint entry, float x, float y, float z, float o)
{
if (Global.ObjectMgr.GetCreatureTemplate(entry) == null)
{
Log.outError(LogFilter.Battleground, $"Battleground::AddCreature: creature template (entry: {entry}) does not exist for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!");
return null;
}
Position pos = new(x, y, z, o);
Creature creature = Creature.CreateCreature(entry, battlegroundMap, pos);
if (creature == null)
{
Log.outError(LogFilter.Battleground, $"Battleground::AddCreature: cannot create creature (entry: {entry}) for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!");
return null;
}
creature.SetHomePosition(pos);
if (!battlegroundMap.AddToMap(creature))
{
creature.Dispose();
return null;
}
return creature;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,658 +0,0 @@
// 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.Entities;
using Game.Maps;
using System;
using System.Collections.Generic;
namespace Game.BattleGrounds.Zones.ArathisBasin
{
class BgArathiBasin : Battleground
{
TimeTracker _pointsTimer;
uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount];
uint[] m_ReputationScoreTics = new uint[SharedConst.PvpTeamsCount];
bool m_IsInformedNearVictory;
uint m_HonorTics;
uint m_ReputationTics;
List<ObjectGuid> _gameobjectsToRemoveOnMatchStart = new();
List<ObjectGuid> _creaturesToRemoveOnMatchStart = new();
List<ObjectGuid> _doors = new();
List<ObjectGuid> _capturePoints = new();
public BgArathiBasin(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate)
{
m_IsInformedNearVictory = false;
_pointsTimer = new TimeTracker(MiscConst.TickInterval);
for (byte i = 0; i < SharedConst.PvpTeamsCount; ++i)
{
m_HonorScoreTics[i] = 0;
m_ReputationScoreTics[i] = 0;
}
m_HonorTics = 0;
m_ReputationTics = 0;
}
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() == BattlegroundStatus.InProgress)
{
// Accumulate points
_pointsTimer.Update(diff);
if (_pointsTimer.Passed())
{
_pointsTimer.Reset(MiscConst.TickInterval);
_CalculateTeamNodes(out var ally, out var horde);
int[] points = [ally, horde];
for (int team = 0; team < SharedConst.PvpTeamsCount; ++team)
{
if (points[team] == 0)
continue;
m_TeamScores[team] += MiscConst.TickPoints[points[team]];
m_HonorScoreTics[team] += MiscConst.TickPoints[points[team]];
m_ReputationScoreTics[team] += MiscConst.TickPoints[points[team]];
if (m_ReputationScoreTics[team] >= m_ReputationTics)
{
if (team == BattleGroundTeamId.Alliance)
RewardReputationToTeam(509, 10, Team.Alliance);
else
RewardReputationToTeam(510, 10, Team.Horde);
m_ReputationScoreTics[team] -= m_ReputationTics;
}
if (m_HonorScoreTics[team] >= m_HonorTics)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BattleGroundTeamId.Alliance) ? Team.Alliance : Team.Horde);
m_HonorScoreTics[team] -= m_HonorTics;
}
if (!m_IsInformedNearVictory && m_TeamScores[team] > MiscConst.WarningNearVictoryScore)
{
if (team == BattleGroundTeamId.Alliance)
{
SendBroadcastText((uint)ABBattlegroundBroadcastTexts.AllianceNearVictory, ChatMsg.BgSystemNeutral);
PlaySoundToAll((uint)SoundIds.NearVictoryAlliance);
}
else
{
SendBroadcastText((uint)ABBattlegroundBroadcastTexts.HordeNearVictory, ChatMsg.BgSystemNeutral);
PlaySoundToAll((uint)SoundIds.NearVictoryHorde);
}
m_IsInformedNearVictory = true;
}
if (m_TeamScores[team] > MiscConst.MaxTeamScore)
m_TeamScores[team] = MiscConst.MaxTeamScore;
if (team == BattleGroundTeamId.Alliance)
UpdateWorldState(WorldStateIds.ResourcesAlly, (int)m_TeamScores[team]);
else
UpdateWorldState(WorldStateIds.ResourcesHorde, (int)m_TeamScores[team]);
// update achievement flags
// we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources
int otherTeam = (team + 1) % SharedConst.PvpTeamsCount;
if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500)
{
if (team == BattleGroundTeamId.Alliance)
UpdateWorldState(WorldStateIds.Had500DisadvantageHorde, 1);
else
UpdateWorldState(WorldStateIds.Had500DisadvantageAlliance, 1);
}
}
UpdateWorldState(WorldStateIds.OccupiedBasesAlly, ally);
UpdateWorldState(WorldStateIds.OccupiedBasesHorde, horde);
}
// Test win condition
if (m_TeamScores[BattleGroundTeamId.Alliance] >= MiscConst.MaxTeamScore)
EndBattleground(Team.Alliance);
else if (m_TeamScores[BattleGroundTeamId.Horde] >= MiscConst.MaxTeamScore)
EndBattleground(Team.Horde);
}
}
public override void StartingEventOpenDoors()
{
// Achievement: Let's Get This Done
TriggerGameEvent((uint)ABEventIds.StartBattle);
}
void _CalculateTeamNodes(out int alliance, out int horde)
{
alliance = 0;
horde = 0;
BattlegroundMap map = FindBgMap();
if (map != null)
{
foreach (ObjectGuid guid in _capturePoints)
{
GameObject capturePoint = map.GetGameObject(guid);
if (capturePoint != null)
{
int wsValue = map.GetWorldStateValue((int)capturePoint.GetGoInfo().CapturePoint.worldState1);
switch ((BattlegroundCapturePointState)wsValue)
{
case BattlegroundCapturePointState.AllianceCaptured:
++alliance;
break;
case BattlegroundCapturePointState.HordeCaptured:
++horde;
break;
default:
break;
}
}
}
}
}
public override Team GetPrematureWinner()
{
// How many bases each team owns
_CalculateTeamNodes(out var ally, out var horde);
if (ally > horde)
return Team.Alliance;
else if (horde > ally)
return Team.Horde;
// If the values are equal, fall back to the original result (based on number of players on each team)
return base.GetPrematureWinner();
}
public override void ProcessEvent(WorldObject source, uint eventId, WorldObject invoker)
{
Player player = invoker.ToPlayer();
switch ((ABEventIds)eventId)
{
case ABEventIds.StartBattle:
{
foreach (ObjectGuid guid in _creaturesToRemoveOnMatchStart)
{
Creature creature = GetBgMap().GetCreature(guid);
if (creature != null)
creature.DespawnOrUnsummon();
}
foreach (ObjectGuid guid in _gameobjectsToRemoveOnMatchStart)
{
GameObject gameObject = GetBgMap().GetGameObject(guid);
if (gameObject != null)
gameObject.DespawnOrUnsummon();
}
foreach (ObjectGuid guid in _doors)
{
GameObject gameObject = GetBgMap().GetGameObject(guid);
if (gameObject != null)
{
gameObject.UseDoorOrButton();
gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3));
}
}
break;
}
case ABEventIds.ContestedBlacksmithAlliance:
UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 1);
UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedBlacksmithAlliance:
UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2);
UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureBlacksmithAlliance:
UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
break;
case ABEventIds.ContestedBlacksmithHorde:
UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0);
UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 1);
PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedBlacksmithHorde:
UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0);
UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureBlacksmithHorde:
UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
break;
case ABEventIds.ContestedFarmAlliance:
UpdateWorldState(WorldStateIds.FarmAllianceControlState, 1);
UpdateWorldState(WorldStateIds.FarmHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedFarmAlliance:
UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2);
UpdateWorldState(WorldStateIds.FarmHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureFarmAlliance:
UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
break;
case ABEventIds.ContestedFarmHorde:
UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0);
UpdateWorldState(WorldStateIds.FarmHordeControlState, 1);
PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedFarmHorde:
UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0);
UpdateWorldState(WorldStateIds.FarmHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureFarmHorde:
UpdateWorldState(WorldStateIds.FarmHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
break;
case ABEventIds.ContestedGoldMineAlliance:
UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 1);
UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedGoldMineAlliance:
UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2);
UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureGoldMineAlliance:
UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
break;
case ABEventIds.ContestedGoldMineHorde:
UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0);
UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 1);
PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedGoldMineHorde:
UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0);
UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureGoldMineHorde:
UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
break;
case ABEventIds.ContestedLumberMillAlliance:
UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 1);
UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedLumberMillAlliance:
UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2);
UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureLumberMillAlliance:
UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
break;
case ABEventIds.ContestedLumberMillHorde:
UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0);
UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 1);
PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedLumberMillHorde:
UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0);
UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureLumberMillHorde:
UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
break;
case ABEventIds.ContestedStablesAlliance:
UpdateWorldState(WorldStateIds.StablesAllianceControlState, 1);
UpdateWorldState(WorldStateIds.StablesHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedStablesAlliance:
UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2);
UpdateWorldState(WorldStateIds.StablesHordeControlState, 0);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureStablesAlliance:
UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance);
break;
case ABEventIds.ContestedStablesHorde:
UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0);
UpdateWorldState(WorldStateIds.StablesHordeControlState, 1);
PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1);
break;
case ABEventIds.DefendedStablesHorde:
UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0);
UpdateWorldState(WorldStateIds.StablesHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
if (player != null)
UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1);
break;
case ABEventIds.CaptureStablesHorde:
UpdateWorldState(WorldStateIds.StablesHordeControlState, 2);
PlaySoundToAll((uint)SoundIds.NodeCapturedHorde);
break;
default:
Log.outWarn(LogFilter.Battleground, $"BattlegroundAB::ProcessEvent: Unhandled event {eventId}.");
break;
}
}
public override void OnCreatureCreate(Creature creature)
{
switch ((CreatureIds)creature.GetEntry())
{
case CreatureIds.TheBlackBride:
case CreatureIds.RadulfLeder:
_creaturesToRemoveOnMatchStart.Add(creature.GetGUID());
break;
default:
break;
}
}
public override void OnGameObjectCreate(GameObject gameObject)
{
if (gameObject.GetGoInfo().type == GameObjectTypes.CapturePoint)
_capturePoints.Add(gameObject.GetGUID());
switch ((GameobjectIds)gameObject.GetEntry())
{
case GameobjectIds.GhostGate:
_gameobjectsToRemoveOnMatchStart.Add(gameObject.GetGUID());
break;
case GameobjectIds.AllianceDoor:
case GameobjectIds.HordeDoor:
_doors.Add(gameObject.GetGUID());
break;
default:
break;
}
}
public override bool SetupBattleground()
{
UpdateWorldState(WorldStateIds.ResourcesMax, MiscConst.MaxTeamScore);
UpdateWorldState(WorldStateIds.ResourcesWarning, MiscConst.WarningNearVictoryScore);
return true;
}
public override void Reset()
{
//call parent's class reset
base.Reset();
for (var i = 0; i < SharedConst.PvpTeamsCount; ++i)
{
m_TeamScores[i] = 0;
m_HonorScoreTics[i] = 0;
m_ReputationScoreTics[i] = 0;
}
_pointsTimer.Reset(MiscConst.TickInterval);
m_IsInformedNearVictory = false;
bool isBGWeekend = Global.BattlegroundMgr.IsBGWeekend(GetTypeID());
m_HonorTics = isBGWeekend ? MiscConst.ABBGWeekendHonorTicks : MiscConst.NotABBGWeekendHonorTicks;
m_ReputationTics = isBGWeekend ? MiscConst.ABBGWeekendReputationTicks : MiscConst.NotABBGWeekendReputationTicks;
_creaturesToRemoveOnMatchStart.Clear();
_gameobjectsToRemoveOnMatchStart.Clear();
_doors.Clear();
_capturePoints.Clear();
}
public override void EndBattleground(Team winner)
{
// Win reward
if (winner == Team.Alliance)
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance);
if (winner == Team.Horde)
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde);
// Complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde);
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance);
base.EndBattleground(winner);
}
public override WorldSafeLocsEntry GetClosestGraveyard(Player player)
{
return Global.ObjectMgr.GetClosestGraveyard(player.GetWorldLocation(), player.GetTeam(), player);
}
public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team)
{
return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde);
}
}
#region Constants
struct MiscConst
{
public const uint NotABBGWeekendHonorTicks = 260;
public const uint ABBGWeekendHonorTicks = 160;
public const uint NotABBGWeekendReputationTicks = 160;
public const uint ABBGWeekendReputationTicks = 120;
public const int WarningNearVictoryScore = 1400;
public const int MaxTeamScore = 1500;
public const uint ExploitTeleportLocationAlliance = 3705;
public const uint ExploitTeleportLocationHorde = 3706;
// Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes
public static TimeSpan TickInterval = TimeSpan.FromSeconds(2);
public static uint[] TickPoints = { 0, 10, 10, 10, 10, 30 };
}
enum ABEventIds
{
StartBattle = 9158, // Achievement: Let'S Get This Done
ContestedStablesHorde = 28523,
CaptureStablesHorde = 28527,
DefendedStablesHorde = 28525,
ContestedStablesAlliance = 28522,
CaptureStablesAlliance = 28526,
DefendedStablesAlliance = 28524,
ContestedBlacksmithHorde = 8876,
CaptureBlacksmithHorde = 8773,
DefendedBlacksmithHorde = 8770,
ContestedBlacksmithAlliance = 8874,
CaptureBlacksmithAlliance = 8769,
DefendedBlacksmithAlliance = 8774,
ContestedFarmHorde = 39398,
CaptureFarmHorde = 39399,
DefendedFarmHorde = 39400,
ContestedFarmAlliance = 39401,
CaptureFarmAlliance = 39402,
DefendedFarmAlliance = 39403,
ContestedGoldMineHorde = 39404,
CaptureGoldMineHorde = 39405,
DefendedGoldMineHorde = 39406,
ContestedGoldMineAlliance = 39407,
CaptureGoldMineAlliance = 39408,
DefendedGoldMineAlliance = 39409,
ContestedLumberMillHorde = 39387,
CaptureLumberMillHorde = 39388,
DefendedLumberMillHorde = 39389,
ContestedLumberMillAlliance = 39390,
CaptureLumberMillAlliance = 39391,
DefendedLumberMillAlliance = 39392
}
struct WorldStateIds
{
public const int OccupiedBasesHorde = 1778;
public const int OccupiedBasesAlly = 1779;
public const int ResourcesAlly = 1776;
public const int ResourcesHorde = 1777;
public const int ResourcesMax = 1780;
public const int ResourcesWarning = 1955;
public const int StableIcon = 1842; // Stable Map Icon (None)
public const int StableStateAlience = 1767; // Stable Map State (Alience)
public const int StableStateHorde = 1768; // Stable Map State (Horde)
public const int StableStateConAli = 1769; // Stable Map State (Con Alience)
public const int StableStateConHor = 1770; // Stable Map State (Con Horde)
public const int FarmIcon = 1845; // Farm Map Icon (None)
public const int FarmStateAlience = 1772; // Farm State (Alience)
public const int FarmStateHorde = 1773; // Farm State (Horde)
public const int FarmStateConAli = 1774; // Farm State (Con Alience)
public const int FarmStateConHor = 1775; // Farm State (Con Horde)
public const int BlacksmithIcon = 1846; // Blacksmith Map Icon (None)
public const int BlacksmithStateAlience = 1782; // Blacksmith Map State (Alience)
public const int BlacksmithStateHorde = 1783; // Blacksmith Map State (Horde)
public const int BlacksmithStateConAli = 1784; // Blacksmith Map State (Con Alience)
public const int BlacksmithStateConHor = 1785; // Blacksmith Map State (Con Horde)
public const int LumbermillIcon = 1844; // Lumber Mill Map Icon (None)
public const int LumbermillStateAlience = 1792; // Lumber Mill Map State (Alience)
public const int LumbermillStateHorde = 1793; // Lumber Mill Map State (Horde)
public const int LumbermillStateConAli = 1794; // Lumber Mill Map State (Con Alience)
public const int LumbermillStateConHor = 1795; // Lumber Mill Map State (Con Horde)
public const int GoldmineIcon = 1843; // Gold Mine Map Icon (None)
public const int GoldmineStateAlience = 1787; // Gold Mine Map State (Alience)
public const int GoldmineStateHorde = 1788; // Gold Mine Map State (Horde)
public const int GoldmineStateConAli = 1789; // Gold Mine Map State (Con Alience
public const int GoldmineStateConHor = 1790; // Gold Mine Map State (Con Horde)
public const int Had500DisadvantageAlliance = 3644;
public const int Had500DisadvantageHorde = 3645;
public const int FarmIconNew = 8808; // Farm Map Icon
public const int LumberMillIconNew = 8805; // Lumber Mill Map Icon
public const int BlacksmithIconNew = 8799; // Blacksmith Map Icon
public const int GoldMineIconNew = 8809; // Gold Mine Map Icon
public const int StablesIconNew = 5834; // Stable Map Icon
public const int FarmHordeControlState = 17328;
public const int FarmAllianceControlState = 17325;
public const int LumberMillHordeControlState = 17330;
public const int LumberMillAllianceControlState = 17326;
public const int BlacksmithHordeControlState = 17327;
public const int BlacksmithAllianceControlState = 17324;
public const int GoldMineHordeControlState = 17329;
public const int GoldMineAllianceControlState = 17323;
public const int StablesHordeControlState = 17331;
public const int StablesAllianceControlState = 17322;
}
// Object id templates from DB
enum GameobjectIds
{
CapturePointStables = 227420,
CapturePointBlacksmith = 227522,
CapturePointFarm = 227536,
CapturePointGoldMine = 227538,
CapturePointLumberMill = 227544,
GhostGate = 180322,
AllianceDoor = 322273,
HordeDoor = 322274
}
enum CreatureIds
{
TheBlackBride = 150501,
RadulfLeder = 150505
}
struct ABBattlegroundNodes
{
public const int NodeStables = 0;
public const int NodeBlacksmith = 1;
public const int NodeFarm = 2;
public const int NodeLumberMill = 3;
public const int NodeGoldMine = 4;
public const int DynamicNodesCount = 5; // Dynamic Nodes That Can Be Captured
public const int SpiritAliance = 5;
public const int SpiritHorde = 6;
public const int AllCount = 7; // All Nodes (Dynamic And Static)
}
enum ABBattlegroundBroadcastTexts
{
AllianceNearVictory = 10598,
HordeNearVictory = 10599
}
enum SoundIds
{
NodeClaimed = 8192,
NodeCapturedAlliance = 8173,
NodeCapturedHorde = 8213,
NodeAssaultedAlliance = 8212,
NodeAssaultedHorde = 8174,
NearVictoryAlliance = 8456,
NearVictoryHorde = 8457
}
enum ArathiBasinPvpStats
{
BasesAssaulted = 926,
BasesDefended = 927,
}
#endregion
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgBattleforGilneas : Battleground
{
public BgBattleforGilneas(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgBladesEdgeArena : Battleground
{
public BgBladesEdgeArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgDalaranSewers : Battleground
{
public BgDalaranSewers(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgDeepwindGorge : Battleground
{
public BgDeepwindGorge(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,803 +0,0 @@
// 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.Entities;
using Game.Entities.GameObjectType;
using Game.Maps;
using Game.Spells;
using System;
using System.Collections.Generic;
namespace Game.BattleGrounds.Zones.EyeofStorm
{
class BgEyeofStorm : Battleground
{
uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount];
uint m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured
TimeTracker _pointsTimer;
uint m_HonorTics;
Dictionary<uint, BgEyeOfStormControlZoneHandler> _controlZoneHandlers = new();
List<ObjectGuid> _doorGUIDs = new();
ObjectGuid _flagGUID;
// Focused/Brutal Assault
bool _assaultEnabled;
TimeTracker _flagAssaultTimer;
byte _assaultStackCount;
public BgEyeofStorm(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate)
{
m_HonorScoreTics = [0, 0];
m_FlagCapturedBgObjectType = 0;
m_HonorTics = 0;
_pointsTimer = new(MiscConst.PointsTickTime);
_assaultEnabled = false;
_assaultStackCount = 0;
_flagAssaultTimer = new(MiscConst.FlagAssaultTimer);
}
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() == BattlegroundStatus.InProgress)
{
_pointsTimer.Update(diff);
if (_pointsTimer.Passed())
{
_pointsTimer.Reset(MiscConst.PointsTickTime);
byte baseCountAlliance = GetControlledBaseCount(BattleGroundTeamId.Alliance);
byte baseCountHorde = GetControlledBaseCount(BattleGroundTeamId.Horde);
if (baseCountAlliance > 0)
AddPoints(Team.Alliance, MiscConst.TickPoints[baseCountAlliance - 1]);
if (baseCountHorde > 0)
AddPoints(Team.Horde, MiscConst.TickPoints[baseCountHorde - 1]);
}
if (_assaultEnabled)
{
_flagAssaultTimer.Update(diff);
if (_flagAssaultTimer.Passed())
{
_flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer);
_assaultStackCount++;
// update assault debuff stacks
DoForFlagKeepers(player => ApplyAssaultDebuffToPlayer(player));
}
}
}
}
public override void StartingEventOpenDoors()
{
foreach (ObjectGuid door in _doorGUIDs)
{
GameObject gameObject = GetBgMap().GetGameObject(door);
if (gameObject != null)
{
gameObject.UseDoorOrButton();
gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3));
}
}
// Achievement: Flurry
TriggerGameEvent(MiscConst.EventStartBattle);
}
void AddPoints(Team Team, uint Points)
{
int team_index = GetTeamIndexByTeamId(Team);
m_TeamScores[team_index] += Points;
m_HonorScoreTics[team_index] += Points;
if (m_HonorScoreTics[team_index] >= m_HonorTics)
{
RewardHonorToTeam(GetBonusHonorFromKill(1), Team);
m_HonorScoreTics[team_index] -= m_HonorTics;
}
UpdateTeamScore(team_index);
}
byte GetControlledBaseCount(int teamId)
{
byte baseCount = 0;
foreach (var controlZoneHandler in _controlZoneHandlers)
{
uint point = controlZoneHandler.Value.GetPoint();
switch (teamId)
{
case BattleGroundTeamId.Alliance:
if (GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1)
baseCount++;
break;
case BattleGroundTeamId.Horde:
if (GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1)
baseCount++;
break;
default:
break;
}
}
return baseCount;
}
void DoForFlagKeepers(Action<Player> action)
{
GameObject flag = GetBgMap().GetGameObject(_flagGUID);
if (flag != null)
{
Player carrier = Global.ObjAccessor.FindPlayer(flag.GetFlagCarrierGUID());
if (carrier != null)
action(carrier);
}
}
void ResetAssaultDebuff()
{
_assaultEnabled = false;
_assaultStackCount = 0;
_flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer);
DoForFlagKeepers(RemoveAssaultDebuffFromPlayer);
}
void ApplyAssaultDebuffToPlayer(Player player)
{
if (_assaultStackCount == 0)
return;
uint spellId = MiscConst.SpellFocusedAssault;
if (_assaultStackCount >= MiscConst.FlagBrutalAssaultStackCount)
{
player.RemoveAurasDueToSpell(MiscConst.SpellFocusedAssault);
spellId = MiscConst.SpellBrutalAssault;
}
Aura aura = player.GetAura(spellId);
if (aura == null)
{
player.CastSpell(player, spellId, true);
aura = player.GetAura(spellId);
}
if (aura != null)
aura.SetStackAmount(_assaultStackCount);
}
void RemoveAssaultDebuffFromPlayer(Player player)
{
player.RemoveAurasDueToSpell(MiscConst.SpellFocusedAssault);
player.RemoveAurasDueToSpell(MiscConst.SpellBrutalAssault);
}
void UpdateTeamScore(int team)
{
uint score = GetTeamScore(team);
if (score >= ScoreIds.MaxTeamScore)
{
score = ScoreIds.MaxTeamScore;
if (team == BattleGroundTeamId.Alliance)
EndBattleground(Team.Alliance);
else
EndBattleground(Team.Horde);
}
if (team == BattleGroundTeamId.Alliance)
UpdateWorldState(WorldStateIds.AllianceResources, (int)score);
else
UpdateWorldState(WorldStateIds.HordeResources, (int)score);
}
public override void EndBattleground(Team winner)
{
// Win reward
if (winner == Team.Alliance)
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance);
if (winner == Team.Horde)
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde);
// Complete map reward
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance);
RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde);
base.EndBattleground(winner);
}
void UpdatePointsCount(uint teamId)
{
if (teamId == BattleGroundTeamId.Alliance)
UpdateWorldState(WorldStateIds.AllianceBase, GetControlledBaseCount(BattleGroundTeamId.Alliance));
else
UpdateWorldState(WorldStateIds.HordeBase, GetControlledBaseCount(BattleGroundTeamId.Horde));
}
public override void OnGameObjectCreate(GameObject gameobject)
{
switch (gameobject.GetEntry())
{
case GameobjectIds.ADoorEyEntry:
case GameobjectIds.HDoorEyEntry:
_doorGUIDs.Add(gameobject.GetGUID());
break;
case GameobjectIds.Flag2EyEntry:
_flagGUID = gameobject.GetGUID();
break;
default:
break;
}
}
public override bool CanCaptureFlag(AreaTrigger areaTrigger, Player player)
{
if (areaTrigger.GetEntry() != MiscConst.AreatriggerCaptureFlag)
return false;
GameObject flag = GetBgMap().GetGameObject(_flagGUID);
if (flag != null)
{
if (flag.GetFlagCarrierGUID() != player.GetGUID())
return false;
}
GameObject controlzone = player.FindNearestGameObjectWithOptions(40.0f, new FindGameObjectOptions() { StringId = "bg_eye_of_the_storm_control_zone" });
if (controlzone != null)
{
uint point = _controlZoneHandlers[controlzone.GetEntry()].GetPoint();
switch (GetPlayerTeam(player.GetGUID()))
{
case Team.Alliance:
return GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1;
case Team.Horde:
return GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1;
default:
return false;
}
}
return false;
}
public override void OnCaptureFlag(AreaTrigger areaTrigger, Player player)
{
if (areaTrigger.GetEntry() != MiscConst.AreatriggerCaptureFlag)
return;
uint baseCount = GetControlledBaseCount(GetTeamIndexByTeamId(GetPlayerTeam(player.GetGUID())));
GameObject gameObject = GetBgMap().GetGameObject(_flagGUID);
if (gameObject != null)
gameObject.HandleCustomTypeCommand(new SetNewFlagState(FlagState.Respawning, player));
Team team = GetPlayerTeam(player.GetGUID());
if (team == Team.Alliance)
{
SendBroadcastText(BroadcastTextIds.AllianceCapturedFlag, ChatMsg.BgSystemAlliance, player);
PlaySoundToAll(SoundIds.FlagCapturedAlliance);
}
else
{
SendBroadcastText(BroadcastTextIds.HordeCapturedFlag, ChatMsg.BgSystemHorde, player);
PlaySoundToAll(SoundIds.FlagCapturedHorde);
}
if (baseCount > 0)
AddPoints(team, MiscConst.FlagPoints[baseCount - 1]);
UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.OnBase);
UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.OnBase);
UpdatePvpStat(player, MiscConst.PvpStatFlagCaptures, 1);
player.RemoveAurasDueToSpell(MiscConst.SpellNetherstormFlag);
player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive);
}
public override void OnFlagStateChange(GameObject flagInBase, FlagState oldValue, FlagState newValue, Player player)
{
switch (newValue)
{
case FlagState.InBase:
ResetAssaultDebuff();
break;
case FlagState.Dropped:
player.CastSpell(player, BattlegroundConst.SpellRecentlyDroppedNeutralFlag, true);
RemoveAssaultDebuffFromPlayer(player);
UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.WaitRespawn);
UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.WaitRespawn);
if (GetPlayerTeam(player.GetGUID()) == Team.Alliance)
SendBroadcastText(BroadcastTextIds.FlagDropped, ChatMsg.BgSystemAlliance);
else
SendBroadcastText(BroadcastTextIds.FlagDropped, ChatMsg.BgSystemHorde);
break;
case FlagState.Taken:
if (GetPlayerTeam(player.GetGUID()) == Team.Alliance)
{
UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.OnPlayer);
PlaySoundToAll(SoundIds.FlagPickedUpAlliance);
SendBroadcastText(BroadcastTextIds.TakenFlag, ChatMsg.BgSystemAlliance, player);
}
else
{
UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.OnPlayer);
PlaySoundToAll(SoundIds.FlagPickedUpHorde);
SendBroadcastText(BroadcastTextIds.TakenFlag, ChatMsg.BgSystemHorde, player);
}
ApplyAssaultDebuffToPlayer(player);
_assaultEnabled = true;
player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive);
break;
case FlagState.Respawning:
ResetAssaultDebuff();
break;
default:
break;
}
UpdateWorldState(WorldStateIds.NetherstormFlag, (int)newValue);
}
public override bool SetupBattleground()
{
UpdateWorldState(WorldStateIds.MaxResources, (int)ScoreIds.MaxTeamScore);
_controlZoneHandlers[GameobjectIds.FrTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.FelReaver);
_controlZoneHandlers[GameobjectIds.BeTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.BloodElf);
_controlZoneHandlers[GameobjectIds.DrTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.DraeneiRuins);
_controlZoneHandlers[GameobjectIds.HuTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.MageTower);
return true;
}
public override void Reset()
{
//call parent's class reset
base.Reset();
m_TeamScores[BattleGroundTeamId.Alliance] = 0;
m_TeamScores[BattleGroundTeamId.Horde] = 0;
m_HonorScoreTics = [0, 0];
m_FlagCapturedBgObjectType = 0;
bool isBGWeekend = Global.BattlegroundMgr.IsBGWeekend(GetTypeID());
m_HonorTics = isBGWeekend ? MiscConst.EYWeekendHonorTicks : MiscConst.NotEYWeekendHonorTicks;
}
public override void HandleKillPlayer(Player player, Player killer)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
base.HandleKillPlayer(player, killer);
EventPlayerDroppedFlag(player);
}
public void EventTeamLostPoint(uint teamId, uint point, WorldObject controlZone)
{
if (teamId == BattleGroundTeamId.Alliance)
{
SendBroadcastText(MiscConst.m_LosingPointTypes[point].MessageIdAlliance, ChatMsg.BgSystemAlliance, controlZone);
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 0);
}
else if (teamId == BattleGroundTeamId.Horde)
{
SendBroadcastText(MiscConst.m_LosingPointTypes[point].MessageIdHorde, ChatMsg.BgSystemHorde, controlZone);
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex, 0);
}
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateControlIndex, 1);
UpdatePointsCount(teamId);
}
public void EventTeamCapturedPoint(uint teamId, uint point, WorldObject controlZone)
{
if (teamId == BattleGroundTeamId.Alliance)
{
SendBroadcastText(MiscConst.m_CapturingPointTypes[point].MessageIdAlliance, ChatMsg.BgSystemAlliance, controlZone);
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 1);
}
else if (teamId == BattleGroundTeamId.Horde)
{
SendBroadcastText(MiscConst.m_CapturingPointTypes[point].MessageIdHorde, ChatMsg.BgSystemHorde, controlZone);
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex, 1);
}
UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateControlIndex, 0);
UpdatePointsCount(teamId);
}
public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team)
{
return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde);
}
public override Team GetPrematureWinner()
{
if (GetTeamScore(BattleGroundTeamId.Alliance) > GetTeamScore(BattleGroundTeamId.Horde))
return Team.Alliance;
else if (GetTeamScore(BattleGroundTeamId.Horde) > GetTeamScore(BattleGroundTeamId.Alliance))
return Team.Horde;
return base.GetPrematureWinner();
}
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 BgEyeOfStormControlZoneHandler handler))
return;
var controlzone = gameobject.GetGoInfo().ControlZone;
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 RemovePoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= Points; }
void SetTeamPoint(Team team, uint Points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = Points; }
}
struct BgEyeOfStormPointIconsStruct
{
public BgEyeOfStormPointIconsStruct(uint worldStateControlIndex, int worldStateAllianceControlledIndex, int worldStateHordeControlledIndex, uint worldStateAllianceStatusBarIcon, uint worldStateHordeStatusBarIcon)
{
WorldStateControlIndex = worldStateControlIndex;
WorldStateAllianceControlledIndex = worldStateAllianceControlledIndex;
WorldStateHordeControlledIndex = worldStateHordeControlledIndex;
WorldStateAllianceStatusBarIcon = worldStateAllianceStatusBarIcon;
WorldStateHordeStatusBarIcon = worldStateHordeStatusBarIcon;
}
public uint WorldStateControlIndex;
public int WorldStateAllianceControlledIndex;
public int WorldStateHordeControlledIndex;
public uint WorldStateAllianceStatusBarIcon;
public uint WorldStateHordeStatusBarIcon;
}
struct BgEyeOfStormLosingPointStruct
{
public BgEyeOfStormLosingPointStruct(int _SpawnNeutralObjectType, int _DespawnObjectTypeAlliance, uint _MessageIdAlliance, int _DespawnObjectTypeHorde, uint _MessageIdHorde)
{
SpawnNeutralObjectType = _SpawnNeutralObjectType;
DespawnObjectTypeAlliance = _DespawnObjectTypeAlliance;
MessageIdAlliance = _MessageIdAlliance;
DespawnObjectTypeHorde = _DespawnObjectTypeHorde;
MessageIdHorde = _MessageIdHorde;
}
public int SpawnNeutralObjectType;
public int DespawnObjectTypeAlliance;
public uint MessageIdAlliance;
public int DespawnObjectTypeHorde;
public uint MessageIdHorde;
}
struct BgEyeOfStormCapturingPointStruct
{
public BgEyeOfStormCapturingPointStruct(int _DespawnNeutralObjectType, int _SpawnObjectTypeAlliance, uint _MessageIdAlliance, int _SpawnObjectTypeHorde, uint _MessageIdHorde, uint _GraveyardId)
{
DespawnNeutralObjectType = _DespawnNeutralObjectType;
SpawnObjectTypeAlliance = _SpawnObjectTypeAlliance;
MessageIdAlliance = _MessageIdAlliance;
SpawnObjectTypeHorde = _SpawnObjectTypeHorde;
MessageIdHorde = _MessageIdHorde;
GraveyardId = _GraveyardId;
}
public int DespawnNeutralObjectType;
public int SpawnObjectTypeAlliance;
public uint MessageIdAlliance;
public int SpawnObjectTypeHorde;
public uint MessageIdHorde;
public uint GraveyardId;
}
class BgEyeOfStormControlZoneHandler : ControlZoneHandler
{
BgEyeofStorm _battleground;
uint _point;
public BgEyeOfStormControlZoneHandler(BgEyeofStorm bg, uint point)
{
_battleground = bg;
_point = point;
}
public override void HandleProgressEventHorde(GameObject controlZone)
{
_battleground.EventTeamCapturedPoint(BattleGroundTeamId.Horde, _point, controlZone);
}
public override void HandleProgressEventAlliance(GameObject controlZone)
{
_battleground.EventTeamCapturedPoint(BattleGroundTeamId.Alliance, _point, controlZone);
}
public override void HandleNeutralEventHorde(GameObject controlZone)
{
_battleground.EventTeamLostPoint(BattleGroundTeamId.Horde, _point, controlZone);
}
public override void HandleNeutralEventAlliance(GameObject controlZone)
{
_battleground.EventTeamLostPoint(BattleGroundTeamId.Alliance, _point, controlZone);
}
public uint GetPoint() { return _point; }
}
#region Constants
struct MiscConst
{
public static TimeSpan PointsTickTime = TimeSpan.FromSeconds(2);
public static TimeSpan FlagAssaultTimer = TimeSpan.FromSeconds(30);
public static ushort FlagBrutalAssaultStackCount = 5;
public const uint EventStartBattle = 13180; // Achievement: Flurry
public const uint NotEYWeekendHonorTicks = 260;
public const uint EYWeekendHonorTicks = 160;
public const uint SpellNetherstormFlag = 34976;
// Focused/Brutal Assault
public const uint SpellFocusedAssault = 46392;
public const uint SpellBrutalAssault = 46393;
public const uint ExploitTeleportLocationAlliance = 3773;
public const uint ExploitTeleportLocationHorde = 3772;
public static byte[] TickPoints = { 1, 2, 5, 10 };
public static uint[] FlagPoints = { 75, 85, 100, 500 };
public const uint AreatriggerCaptureFlag = 33;
public const uint PvpStatFlagCaptures = 183;
public static BgEyeOfStormPointIconsStruct[] m_PointsIconStruct =
{
new BgEyeOfStormPointIconsStruct(WorldStateIds.FelReaverUncontrol, WorldStateIds.FelReaverAllianceControl, WorldStateIds.FelReaverHordeControl, WorldStateIds.FelReaverAllianceControlState, WorldStateIds.FelReaverHordeControlState),
new BgEyeOfStormPointIconsStruct(WorldStateIds.BloodElfUncontrol, WorldStateIds.BloodElfAllianceControl, WorldStateIds.BloodElfHordeControl, WorldStateIds.BloodElfAllianceControlState, WorldStateIds.BloodElfHordeControlState),
new BgEyeOfStormPointIconsStruct(WorldStateIds.DraeneiRuinsUncontrol, WorldStateIds.DraeneiRuinsAllianceControl, WorldStateIds.DraeneiRuinsHordeControl, WorldStateIds.DraeneiRuinsAllianceControlState, WorldStateIds.DraeneiRuinsHordeControlState),
new BgEyeOfStormPointIconsStruct(WorldStateIds.MageTowerUncontrol, WorldStateIds.MageTowerAllianceControl, WorldStateIds.MageTowerHordeControl, WorldStateIds.MageTowerAllianceControlState, WorldStateIds.MageTowerHordeControlState)
};
public static BgEyeOfStormLosingPointStruct[] m_LosingPointTypes =
{
new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerFelReaverCenter, ObjectTypes.ABannerFelReaverCenter, BroadcastTextIds.AllianceLostFelReaverRuins, ObjectTypes.HBannerFelReaverCenter, BroadcastTextIds.HordeLostFelReaverRuins),
new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerBloodElfCenter, ObjectTypes.ABannerBloodElfCenter, BroadcastTextIds.AllianceLostBloodElfTower, ObjectTypes.HBannerBloodElfCenter, BroadcastTextIds.HordeLostBloodElfTower),
new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerDraeneiRuinsCenter, ObjectTypes.ABannerDraeneiRuinsCenter, BroadcastTextIds.AllianceLostDraeneiRuins, ObjectTypes.HBannerDraeneiRuinsCenter, BroadcastTextIds.HordeLostDraeneiRuins),
new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerMageTowerCenter, ObjectTypes.ABannerMageTowerCenter, BroadcastTextIds.AllianceLostMageTower, ObjectTypes.HBannerMageTowerCenter, BroadcastTextIds.HordeLostMageTower)
};
public static BgEyeOfStormCapturingPointStruct[] m_CapturingPointTypes =
{
new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerFelReaverCenter, ObjectTypes.ABannerFelReaverCenter, BroadcastTextIds.AllianceTakenFelReaverRuins, ObjectTypes.HBannerFelReaverCenter, BroadcastTextIds.HordeTakenFelReaverRuins, GaveyardIds.FelReaver),
new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerBloodElfCenter, ObjectTypes.ABannerBloodElfCenter, BroadcastTextIds.AllianceTakenBloodElfTower, ObjectTypes.HBannerBloodElfCenter, BroadcastTextIds.HordeTakenBloodElfTower, GaveyardIds.BloodElf),
new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerDraeneiRuinsCenter, ObjectTypes.ABannerDraeneiRuinsCenter, BroadcastTextIds.AllianceTakenDraeneiRuins, ObjectTypes.HBannerDraeneiRuinsCenter, BroadcastTextIds.HordeTakenDraeneiRuins, GaveyardIds.DraeneiRuins),
new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerMageTowerCenter, ObjectTypes.ABannerMageTowerCenter, BroadcastTextIds.AllianceTakenMageTower, ObjectTypes.HBannerMageTowerCenter, BroadcastTextIds.HordeTakenMageTower, GaveyardIds.MageTower)
};
}
struct BroadcastTextIds
{
public const uint AllianceTakenFelReaverRuins = 17828;
public const uint HordeTakenFelReaverRuins = 17829;
public const uint AllianceLostFelReaverRuins = 17835;
public const uint HordeLostFelReaverRuins = 17836;
public const uint AllianceTakenBloodElfTower = 17819;
public const uint HordeTakenBloodElfTower = 17823;
public const uint AllianceLostBloodElfTower = 17831;
public const uint HordeLostBloodElfTower = 17832;
public const uint AllianceTakenDraeneiRuins = 17827;
public const uint HordeTakenDraeneiRuins = 17826;
public const uint AllianceLostDraeneiRuins = 17833;
public const uint HordeLostDraeneiRuins = 17834;
public const uint AllianceTakenMageTower = 17824;
public const uint HordeTakenMageTower = 17825;
public const uint AllianceLostMageTower = 17837;
public const uint HordeLostMageTower = 17838;
public const uint TakenFlag = 18359;
public const uint FlagDropped = 18361;
public const uint FlagReset = 18364;
public const uint AllianceCapturedFlag = 18375;
public const uint HordeCapturedFlag = 18384;
}
struct WorldStateIds
{
public const int AllianceResources = 1776;
public const int HordeResources = 1777;
public const int MaxResources = 1780;
public const int AllianceBase = 2752;
public const int HordeBase = 2753;
public const int DraeneiRuinsHordeControl = 2733;
public const int DraeneiRuinsAllianceControl = 2732;
public const int DraeneiRuinsUncontrol = 2731;
public const int MageTowerAllianceControl = 2730;
public const int MageTowerHordeControl = 2729;
public const int MageTowerUncontrol = 2728;
public const int FelReaverHordeControl = 2727;
public const int FelReaverAllianceControl = 2726;
public const int FelReaverUncontrol = 2725;
public const int BloodElfHordeControl = 2724;
public const int BloodElfAllianceControl = 2723;
public const int BloodElfUncontrol = 2722;
public const int ProgressBarPercentGrey = 2720; //100 = Empty (Only Grey); 0 = Blue|Red (No Grey)
public const int ProgressBarStatus = 2719; //50 Init!; 48 ... Hordak Bere .. 33 .. 0 = Full 100% Hordacky; 100 = Full Alliance
public const int ProgressBarShow = 2718; //1 Init; 0 Druhy Send - Bez Messagu; 1 = Controlled Aliance
public const int NetherstormFlag = 8863;
//Set To 2 When Flag Is Picked Up; And To 1 If It Is Dropped
public const int NetherstormFlagStateAlliance = 9808;
public const int NetherstormFlagStateHorde = 9809;
public const int DraeneiRuinsHordeControlState = 17362;
public const int DraeneiRuinsAllianceControlState = 17366;
public const int MageTowerHordeControlState = 17361;
public const int MageTowerAllianceControlState = 17368;
public const int FelReaverHordeControlState = 17364;
public const int FelReaverAllianceControlState = 17367;
public const int BloodElfHordeControlState = 17363;
public const int BloodElfAllianceControlState = 17365;
}
struct SoundIds
{
//strange ids, but sure about them
public const uint FlagPickedUpAlliance = 8212;
public const uint FlagCapturedHorde = 8213;
public const uint FlagPickedUpHorde = 8174;
public const uint FlagCapturedAlliance = 8173;
public const uint FlagReset = 8192;
}
struct GameobjectIds
{
public const uint ADoorEyEntry = 184719; //Alliance Door
public const uint HDoorEyEntry = 184720; //Horde Door
public const uint Flag1EyEntry = 184493; //Netherstorm Flag (Generic)
public const uint Flag2EyEntry = 208977; //Netherstorm Flag (Flagstand)
public const uint ABannerEyEntry = 184381; //Visual Banner (Alliance)
public const uint HBannerEyEntry = 184380; //Visual Banner (Horde)
public const uint NBannerEyEntry = 184382; //Visual Banner (Neutral)
public const uint BeTowerCapEyEntry = 184080; //Be Tower Cap Pt
public const uint FrTowerCapEyEntry = 184081; //Fel Reaver Cap Pt
public const uint HuTowerCapEyEntry = 184082; //Human Tower Cap Pt
public const uint DrTowerCapEyEntry = 184083; //Draenei Tower Cap Pt
public const uint SpeedBuffFelReaverEyEntry = 184970;
public const uint RestorationBuffFelReaverEyEntry = 184971;
public const uint BerserkBuffFelReaverEyEntry = 184972;
public const uint SpeedBuffBloodElfEyEntry = 184964;
public const uint RestorationBuffBloodElfEyEntry = 184965;
public const uint BerserkBuffBloodElfEyEntry = 184966;
public const uint SpeedBuffDraeneiRuinsEyEntry = 184976;
public const uint RestorationBuffDraeneiRuinsEyEntry = 184977;
public const uint BerserkBuffDraeneiRuinsEyEntry = 184978;
public const uint SpeedBuffMageTowerEyEntry = 184973;
public const uint RestorationBuffMageTowerEyEntry = 184974;
public const uint BerserkBuffMageTowerEyEntry = 184975;
}
struct GaveyardIds
{
public const int MainAlliance = 1103;
public const uint MainHorde = 1104;
public const uint FelReaver = 1105;
public const uint BloodElf = 1106;
public const uint DraeneiRuins = 1107;
public const uint MageTower = 1108;
}
struct Points
{
public const int FelReaver = 0;
public const int BloodElf = 1;
public const int DraeneiRuins = 2;
public const int MageTower = 3;
public const int PlayersOutOfPoints = 4;
public const int PointsMax = 4;
}
struct ObjectTypes
{
public const int DoorA = 0;
public const int DoorH = 1;
public const int ABannerFelReaverCenter = 2;
public const int ABannerFelReaverLeft = 3;
public const int ABannerFelReaverRight = 4;
public const int ABannerBloodElfCenter = 5;
public const int ABannerBloodElfLeft = 6;
public const int ABannerBloodElfRight = 7;
public const int ABannerDraeneiRuinsCenter = 8;
public const int ABannerDraeneiRuinsLeft = 9;
public const int ABannerDraeneiRuinsRight = 10;
public const int ABannerMageTowerCenter = 11;
public const int ABannerMageTowerLeft = 12;
public const int ABannerMageTowerRight = 13;
public const int HBannerFelReaverCenter = 14;
public const int HBannerFelReaverLeft = 15;
public const int HBannerFelReaverRight = 16;
public const int HBannerBloodElfCenter = 17;
public const int HBannerBloodElfLeft = 18;
public const int HBannerBloodElfRight = 19;
public const int HBannerDraeneiRuinsCenter = 20;
public const int HBannerDraeneiRuinsLeft = 21;
public const int HBannerDraeneiRuinsRight = 22;
public const int HBannerMageTowerCenter = 23;
public const int HBannerMageTowerLeft = 24;
public const int HBannerMageTowerRight = 25;
public const int NBannerFelReaverCenter = 26;
public const int NBannerFelReaverLeft = 27;
public const int NBannerFelReaverRight = 28;
public const int NBannerBloodElfCenter = 29;
public const int NBannerBloodElfLeft = 30;
public const int NBannerBloodElfRight = 31;
public const int NBannerDraeneiRuinsCenter = 32;
public const int NBannerDraeneiRuinsLeft = 33;
public const int NBannerDraeneiRuinsRight = 34;
public const int NBannerMageTowerCenter = 35;
public const int NBannerMageTowerLeft = 36;
public const int NBannerMageTowerRight = 37;
public const int TowerCapFelReaver = 38;
public const int TowerCapBloodElf = 39;
public const int TowerCapDraeneiRuins = 40;
public const int TowerCapMageTower = 41;
public const int FlagNetherstorm = 42;
public const int FlagFelReaver = 43;
public const int FlagBloodElf = 44;
public const int FlagDraeneiRuins = 45;
public const int FlagMageTower = 46;
//Buffs
public const int SpeedbuffFelReaver = 47;
public const int RegenbuffFelReaver = 48;
public const int BerserkbuffFelReaver = 49;
public const int SpeedbuffBloodElf = 50;
public const int RegenbuffBloodElf = 51;
public const int BerserkbuffBloodElf = 52;
public const int SpeedbuffDraeneiRuins = 53;
public const int RegenbuffDraeneiRuins = 54;
public const int BerserkbuffDraeneiRuins = 55;
public const int SpeedbuffMageTower = 56;
public const int RegenbuffMageTower = 57;
public const int BerserkbuffMageTower = 58;
public const int Max = 59;
}
struct ScoreIds
{
public const uint WarningNearVictoryScore = 1400;
public const uint MaxTeamScore = 1500;
}
enum EYFlagState
{
OnBase = 0,
WaitRespawn = 1,
OnPlayer = 2,
OnGround = 3
}
#endregion
}
File diff suppressed because it is too large Load Diff
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgNagrandArena : Battleground
{
public BgNagrandArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgRuinsOfLordaernon : Battleground
{
public BgRuinsOfLordaernon(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgSilvershardMines : Battleground
{
public BgSilvershardMines(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
File diff suppressed because it is too large Load Diff
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgTempleofKotmogu : Battleground
{
public BgTempleofKotmogu(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgTheRingOfValor : Battleground
{
public BgTheRingOfValor(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,10 +0,0 @@
// 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.
namespace Game.BattleGrounds.Zones
{
class BgTwinPeaks : Battleground
{
public BgTwinPeaks(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { }
}
}
@@ -1,648 +0,0 @@
// 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.Entities;
using Game.Entities.GameObjectType;
using Game.Spells;
using System;
using System.Collections.Generic;
namespace Game.BattleGrounds.Zones.WarsongGluch
{
class BgWarsongGluch : Battleground
{
Team _lastFlagCaptureTeam; // Winner is based on this if score is equal
uint m_ReputationCapture;
uint m_HonorWinKills;
uint m_HonorEndKills;
bool _bothFlagsKept;
List<ObjectGuid> _doors = new();
ObjectGuid[] _flags = new ObjectGuid[2];
TimeTracker _flagAssaultTimer;
byte _assaultStackCount;
ObjectGuid[] _capturePointAreaTriggers = new ObjectGuid[2];
public BgWarsongGluch(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate)
{
StartMessageIds[BattlegroundConst.EventIdSecond] = (uint)BroadcastTextIds.StartOneMinute;
StartMessageIds[BattlegroundConst.EventIdThird] = (uint)BroadcastTextIds.StartHalfMinute;
StartMessageIds[BattlegroundConst.EventIdFourth] = (uint)BroadcastTextIds.BattleHasBegun;
_flagAssaultTimer = new(MiscConst.FlagAssaultTimer);
}
public override void PostUpdateImpl(uint diff)
{
if (GetStatus() == BattlegroundStatus.InProgress)
{
if (GetElapsedTime() >= 17 * Time.Minute * Time.InMilliseconds)
{
if (GetTeamScore(BattleGroundTeamId.Alliance) == 0)
{
if (GetTeamScore(BattleGroundTeamId.Horde) == 0) // No one scored - result is tie
EndBattleground(Team.Other);
else // Horde has more points and thus wins
EndBattleground(Team.Horde);
}
else if (GetTeamScore(BattleGroundTeamId.Horde) == 0)
EndBattleground(Team.Alliance); // Alliance has > 0, Horde has 0, alliance wins
else if (GetTeamScore(BattleGroundTeamId.Horde) == GetTeamScore(BattleGroundTeamId.Alliance)) // Team score equal, winner is team that scored the last flag
EndBattleground((Team)_lastFlagCaptureTeam);
else if (GetTeamScore(BattleGroundTeamId.Horde) > GetTeamScore(BattleGroundTeamId.Alliance)) // Last but not least, check who has the higher score
EndBattleground(Team.Horde);
else
EndBattleground(Team.Alliance);
}
}
if (_bothFlagsKept)
{
_flagAssaultTimer.Update(diff);
if (_flagAssaultTimer.Passed())
{
_flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer);
_assaultStackCount++;
// update assault debuff stacks
DoForFlagKeepers(ApplyAssaultDebuffToPlayer);
}
}
}
void DoForFlagKeepers(Action<Player> action)
{
foreach (ObjectGuid flagGUID in _flags)
{
GameObject flag = GetBgMap().GetGameObject(flagGUID);
if (flag != null)
{
Player carrier = Global.ObjAccessor.FindPlayer(flag.GetFlagCarrierGUID());
if (carrier != null)
action(carrier);
}
}
}
void ResetAssaultDebuff()
{
_bothFlagsKept = false;
_assaultStackCount = 0;
_flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer);
DoForFlagKeepers(RemoveAssaultDebuffFromPlayer);
}
void ApplyAssaultDebuffToPlayer(Player player)
{
if (_assaultStackCount == 0)
return;
uint spellId = (uint)SpellIds.FocusedAssault;
if (_assaultStackCount >= MiscConst.FlagBrutalAssaultStackCount)
{
player.RemoveAurasDueToSpell((uint)SpellIds.FocusedAssault);
spellId = (uint)SpellIds.BrutalAssault;
}
Aura aura = player.GetAura(spellId);
if (aura == null)
{
player.CastSpell(player, spellId, true);
aura = player.GetAura(spellId);
}
if (aura != null)
aura.SetStackAmount(_assaultStackCount);
}
void RemoveAssaultDebuffFromPlayer(Player player)
{
player.RemoveAurasDueToSpell((uint)SpellIds.FocusedAssault);
player.RemoveAurasDueToSpell((uint)SpellIds.BrutalAssault);
}
public override void StartingEventOpenDoors()
{
foreach (ObjectGuid door in _doors)
{
GameObject gameObject = GetBgMap().GetGameObject(door);
if (gameObject != null)
{
gameObject.UseDoorOrButton();
gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3));
}
}
UpdateWorldState((int)WorldStateIds.StateTimerActive, 1);
UpdateWorldState((int)WorldStateIds.StateTimer, (int)(GameTime.GetGameTime() + 15 * Time.Minute));
// players joining later are not eligibles
TriggerGameEvent(8563);
}
FlagState GetFlagState(int team)
{
GameObject gameObject = FindBgMap().GetGameObject(_flags[team]);
if (gameObject != null)
return gameObject.GetFlagState();
return 0;
}
ObjectGuid GetFlagCarrierGUID(int team)
{
GameObject gameObject = FindBgMap().GetGameObject(_flags[team]);
if (gameObject != null)
return gameObject.GetFlagCarrierGUID();
return ObjectGuid.Empty;
}
void HandleFlagRoomCapturePoint()
{
DoForFlagKeepers(player =>
{
int team = GetTeamIndexByTeamId(GetPlayerTeam(player.GetGUID()));
AreaTrigger trigger = GetBgMap().GetAreaTrigger(_capturePointAreaTriggers[team]);
if (trigger != null && trigger.GetInsideUnits().Contains(player.GetGUID()))
if (CanCaptureFlag(trigger, player))
OnCaptureFlag(trigger, player);
});
}
void UpdateFlagState(Team team, FlagState value)
{
int transformValueToOtherTeamControlWorldState(FlagState value)
{
switch (value)
{
case FlagState.InBase:
case FlagState.Dropped:
case FlagState.Respawning:
return 1;
case FlagState.Taken:
return 2;
default:
return 0;
}
};
if (team == Team.Horde)
{
UpdateWorldState((int)WorldStateIds.FlagStateAlliance, (int)value);
UpdateWorldState((int)WorldStateIds.FlagControlHorde, transformValueToOtherTeamControlWorldState(value));
}
else
{
UpdateWorldState((int)WorldStateIds.FlagStateHorde, (int)value);
UpdateWorldState((int)WorldStateIds.FlagControlAlliance, transformValueToOtherTeamControlWorldState(value));
}
}
void UpdateTeamScore(int team)
{
if (team == BattleGroundTeamId.Alliance)
UpdateWorldState((int)WorldStateIds.FlagCapturesAlliance, (int)GetTeamScore(team));
else
UpdateWorldState((int)WorldStateIds.FlagCapturesHorde, (int)GetTeamScore(team));
}
public override bool SetupBattleground()
{
return true;
}
public override void Reset()
{
//call parent's class reset
base.Reset();
m_TeamScores[BattleGroundTeamId.Alliance] = 0;
m_TeamScores[BattleGroundTeamId.Horde] = 0;
if (Global.BattlegroundMgr.IsBGWeekend(GetTypeID()))
{
m_ReputationCapture = 45;
m_HonorWinKills = 3;
m_HonorEndKills = 4;
}
else
{
m_ReputationCapture = 35;
m_HonorWinKills = 1;
m_HonorEndKills = 2;
}
_lastFlagCaptureTeam = Team.Other;
_bothFlagsKept = false;
_doors.Clear();
_flags.Clear();
_assaultStackCount = 0;
_flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer);
_capturePointAreaTriggers.Clear();
}
public override void EndBattleground(Team winner)
{
// Win reward
if (winner == Team.Alliance)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), Team.Alliance);
if (winner == Team.Horde)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorWinKills), Team.Horde);
// Complete map_end rewards (even if no team wins)
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), Team.Alliance);
RewardHonorToTeam(GetBonusHonorFromKill(m_HonorEndKills), Team.Horde);
base.EndBattleground(winner);
}
public override void HandleKillPlayer(Player victim, Player killer)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return;
EventPlayerDroppedFlag(victim);
base.HandleKillPlayer(victim, killer);
}
public override WorldSafeLocsEntry GetClosestGraveyard(Player player)
{
return Global.ObjectMgr.GetClosestGraveyard(player, player.GetBGTeam(), player);
}
public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team)
{
return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde);
}
public override Team GetPrematureWinner()
{
if (GetTeamScore(BattleGroundTeamId.Alliance) > GetTeamScore(BattleGroundTeamId.Horde))
return Team.Alliance;
else if (GetTeamScore(BattleGroundTeamId.Horde) > GetTeamScore(BattleGroundTeamId.Alliance))
return Team.Horde;
return base.GetPrematureWinner();
}
public override void OnGameObjectCreate(GameObject gameObject)
{
switch ((GameobjectIds)gameObject.GetEntry())
{
case GameobjectIds.AllianceDoor:
case GameobjectIds.Portcullis009:
case GameobjectIds.Portcullis002:
case GameobjectIds.CollisionPcSize:
case GameobjectIds.HordeGate1:
case GameobjectIds.HordeGate2:
_doors.Add(gameObject.GetGUID());
break;
case GameobjectIds.AllianceFlagInBase:
_flags[BattleGroundTeamId.Alliance] = gameObject.GetGUID();
break;
case GameobjectIds.HordeFlagInBase:
_flags[BattleGroundTeamId.Horde] = gameObject.GetGUID();
break;
default:
break;
}
}
public override void OnAreaTriggerCreate(AreaTrigger areaTrigger)
{
if (!areaTrigger.IsStaticSpawn())
return;
switch (areaTrigger.GetEntry())
{
case MiscConst.AtCapturePointAlliance:
_capturePointAreaTriggers[BattleGroundTeamId.Alliance] = areaTrigger.GetGUID();
break;
case MiscConst.AtCapturePointHorde:
_capturePointAreaTriggers[BattleGroundTeamId.Horde] = areaTrigger.GetGUID();
break;
default:
break;
}
}
public override void OnFlagStateChange(GameObject flagInBase, FlagState oldValue, FlagState newValue, Player player)
{
Team team = flagInBase.GetEntry() == (uint)GameobjectIds.HordeFlagInBase ? Team.Horde : Team.Alliance;
int otherTeamId = GetTeamIndexByTeamId(GetOtherTeam(team));
UpdateFlagState(team, newValue);
switch (newValue)
{
case FlagState.InBase:
{
if (GetStatus() == BattlegroundStatus.InProgress)
{
ResetAssaultDebuff();
if (player != null)
{
// flag got returned to base by player interaction
UpdatePvpStat(player, MiscConst.PvpStatFlagReturns, 1); // +1 flag returns
if (team == Team.Alliance)
{
SendBroadcastText((uint)BroadcastTextIds.AllianceFlagReturned, ChatMsg.BgSystemAlliance, player);
PlaySoundToAll((uint)SoundIds.FlagReturned);
}
else
{
SendBroadcastText((uint)BroadcastTextIds.HordeFlagReturned, ChatMsg.BgSystemHorde, player);
PlaySoundToAll((uint)SoundIds.FlagReturned);
}
}
// Flag respawned due to timeout/capture
else if (GetFlagState(otherTeamId) != FlagState.Respawning)
{
// if other flag is respawning, we will let that one handle the message and sound to prevent double message/sound.
SendBroadcastText((uint)BroadcastTextIds.FlagsPlaced, ChatMsg.BgSystemNeutral);
PlaySoundToAll((uint)SoundIds.FlagsRespawned);
}
HandleFlagRoomCapturePoint();
}
break;
}
case FlagState.Dropped:
{
player.RemoveAurasDueToSpell((uint)SpellIds.QuickCapTimer);
RemoveAssaultDebuffFromPlayer(player);
uint recentlyDroppedSpellId = BattlegroundConst.SpellRecentlyDroppedHordeFlag;
if (team == Team.Alliance)
{
recentlyDroppedSpellId = BattlegroundConst.SpellRecentlyDroppedAllianceFlag;
SendBroadcastText((uint)BroadcastTextIds.AllianceFlagDropped, ChatMsg.BgSystemAlliance, player);
}
else
SendBroadcastText((uint)BroadcastTextIds.HordeFlagDropped, ChatMsg.BgSystemHorde, player);
player.CastSpell(player, recentlyDroppedSpellId, true);
break;
}
case FlagState.Taken:
{
if (team == Team.Horde)
{
SendBroadcastText((uint)BroadcastTextIds.HordeFlagPickedUp, ChatMsg.BgSystemHorde, player);
PlaySoundToAll((uint)SoundIds.HordeFlagPickedUp);
}
else
{
SendBroadcastText((uint)BroadcastTextIds.AllianceFlagPickedUp, ChatMsg.BgSystemAlliance, player);
PlaySoundToAll((uint)SoundIds.AllianceFlagPickedUp);
}
if (GetFlagState(otherTeamId) == FlagState.Taken)
_bothFlagsKept = true;
ApplyAssaultDebuffToPlayer(player);
flagInBase.CastSpell(player, (uint)SpellIds.QuickCapTimer, true);
player.StartCriteria(CriteriaStartEvent.BeSpellTarget, (uint)SpellIds.QuickCapTimer, TimeSpan.FromSeconds(GameTime.GetGameTime() - flagInBase.GetFlagTakenFromBaseTime()));
break;
}
case FlagState.Respawning:
ResetAssaultDebuff();
break;
default:
break;
}
}
public override bool CanCaptureFlag(AreaTrigger areaTrigger, Player player)
{
if (GetStatus() != BattlegroundStatus.InProgress)
return false;
Team team = GetPlayerTeam(player.GetGUID());
int teamId = GetTeamIndexByTeamId(team);
int otherTeamId = GetTeamIndexByTeamId(GetOtherTeam(team));
if (areaTrigger.GetGUID() != _capturePointAreaTriggers[teamId])
return false;
// check if enemy flag's carrier is this player
if (GetFlagCarrierGUID(otherTeamId) != player.GetGUID())
return false;
// check that team's flag is in base
return GetFlagState(teamId) == FlagState.InBase;
}
public override void OnCaptureFlag(AreaTrigger areaTrigger, Player player)
{
Team winner = Team.Other;
Team team = GetPlayerTeam(player.GetGUID());
int teamId = GetTeamIndexByTeamId(team);
int otherTeamId = GetTeamIndexByTeamId(GetOtherTeam(team));
/*
1. Update flag states & score world states
2. udpate points
3. chat message & sound
4. update criterias & achievements
5. remove all related auras
?. Reward honor & reputation
*/
// 1. update the flag states
for (byte i = 0; i < _flags.Length; i++)
{
GameObject gameObject1 = GetBgMap().GetGameObject(_flags[i]);
if (gameObject1 != null)
gameObject1.HandleCustomTypeCommand(new SetNewFlagState(FlagState.Respawning, player));
}
// 2. update points
if (GetTeamScore(teamId) < MiscConst.MaxTeamScore)
AddPoint(team, 1);
UpdateTeamScore(teamId);
// 3. chat message & sound
if (team == Team.Alliance)
{
SendBroadcastText((uint)BroadcastTextIds.CapturedHordeFlag, ChatMsg.BgSystemHorde, player);
PlaySoundToAll((uint)SoundIds.FlagCapturedAlliance);
RewardReputationToTeam(890, m_ReputationCapture, Team.Alliance);
player.CastSpell(player, (uint)SpellIds.CapturedAllianceCosmeticFx);
}
else
{
SendBroadcastText((uint)BroadcastTextIds.CapturedAllianceFlag, ChatMsg.BgSystemAlliance, player);
PlaySoundToAll((uint)SoundIds.FlagCapturedHorde);
RewardReputationToTeam(889, m_ReputationCapture, Team.Horde);
player.CastSpell(player, (uint)SpellIds.CapturedHordeCosmeticFx);
}
// 4. update criteria's for achievement, player score etc.
UpdatePvpStat(player, MiscConst.PvpStatFlagCaptures, 1); // +1 flag captures
// 5. Remove all related auras
RemoveAssaultDebuffFromPlayer(player);
GameObject gameObject = GetBgMap().GetGameObject(_flags[otherTeamId]);
if (gameObject != null)
player.RemoveAurasDueToSpell(gameObject.GetGoInfo().NewFlag.pickupSpell, gameObject.GetGUID());
player.RemoveAurasDueToSpell((uint)SpellIds.QuickCapTimer);
player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive);
RewardHonorToTeam(GetBonusHonorFromKill(2), team);
// update last flag capture to be used if teamscore is equal
SetLastFlagCapture(team);
if (GetTeamScore(teamId) == MiscConst.MaxTeamScore)
winner = team;
if (winner != Team.Other)
{
UpdateWorldState((int)WorldStateIds.FlagStateAlliance, 1);
UpdateWorldState((int)WorldStateIds.FlagStateHorde, 1);
UpdateWorldState((int)WorldStateIds.StateTimerActive, 0);
RewardHonorToTeam(MiscConst.Honor[Global.BattlegroundMgr.IsBGWeekend(GetTypeID()) ? 1 : 0][(int)Rewards.Win], winner);
EndBattleground(winner);
}
}
void SetLastFlagCapture(Team team) { _lastFlagCaptureTeam = team; }
void AddPoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] += Points; }
void SetTeamPoint(Team team, uint Points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = Points; }
void RemovePoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= Points; }
}
#region Constants
struct MiscConst
{
public const uint MaxTeamScore = 3;
public const uint FlagRespawnTime = 23000;
public const uint FlagDropTime = 10000;
public const uint SpellForceTime = 600000;
public const uint SpellBrutalTime = 900000;
public const uint ExploitTeleportLocationAlliance = 7051;
public const uint ExploitTeleportLocationHorde = 7050;
public const uint AtCapturePointAlliance = 30;
public const uint AtCapturePointHorde = 31;
public const uint WsEventStartBattle = 35912;
public static TimeSpan FlagAssaultTimer = TimeSpan.FromSeconds(30);
public const ushort FlagBrutalAssaultStackCount = 5;
public static uint[][] Honor =
{
[20, 40, 40], // Normal Honor
[60, 40, 80] // Holiday
};
public const uint PvpStatFlagCaptures = 928;
public const uint PvpStatFlagReturns = 929;
}
enum BroadcastTextIds
{
StartOneMinute = 10015,
StartHalfMinute = 10016,
BattleHasBegun = 10014,
CapturedHordeFlag = 9801,
CapturedAllianceFlag = 9802,
FlagsPlaced = 9803,
AllianceFlagPickedUp = 9804,
AllianceFlagDropped = 9805,
HordeFlagPickedUp = 9807,
HordeFlagDropped = 9806,
AllianceFlagReturned = 9808,
HordeFlagReturned = 9809,
}
enum SoundIds
{
FlagCapturedAlliance = 8173,
FlagCapturedHorde = 8213,
FlagPlaced = 8232,
FlagReturned = 8192,
HordeFlagPickedUp = 8212,
AllianceFlagPickedUp = 8174,
FlagsRespawned = 8232
}
enum SpellIds
{
WarsongFlag = 23333,
WarsongFlagDropped = 23334,
//WarsongFlagPicked = 61266,
SilverwingFlag = 23335,
SilverwingFlagDropped = 23336,
//SilverwingFlagPicked = 61265,
FocusedAssault = 46392,
BrutalAssault = 46393,
QuickCapTimer = 183317, // Serverside
//Carrierdebuffs
CapturedAllianceCosmeticFx = 262508,
CapturedHordeCosmeticFx = 262512,
}
enum WorldStateIds
{
FlagStateAlliance = 1545,
FlagStateHorde = 1546,
FlagStateNeutral = 1547, // Unused
HordeFlagCountPickedUp = 17712, // Brawl
AllianceFlagCountPickedUp = 17713, // Brawl
FlagCapturesAlliance = 1581,
FlagCapturesHorde = 1582,
FlagCapturesMax = 1601,
FlagCapturesMaxNew = 17303,
FlagControlHorde = 2338,
FlagControlAlliance = 2339,
StateTimer = 4248,
StateTimerActive = 4247
}
enum GameobjectIds
{
// Doors
AllianceDoor = 309704,
Portcullis009 = 309705, // Doodad7neBlackrookPortcullis009
Portcullis002 = 309883, // Doodad7neBlackrookPortcullis002
CollisionPcSize = 242273,
HordeGate1 = 352709,
HordeGate2 = 352710,
// Flags
AllianceFlagInBase = 227741,
HordeFlagInBase = 227740
}
enum Rewards
{
Win = 0,
FlagCap,
MapComplete,
RewardNum
}
#endregion
}
+9 -8
View File
@@ -90,15 +90,15 @@ namespace Game.Chat
public static ChannelManager ForTeam(Team team)
{
if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionChannel))
return allianceChannelMgr; // cross-faction
return neutralChannelMgr; // cross-faction
if (team == Team.Alliance)
return allianceChannelMgr;
if (team == Team.Horde)
return hordeChannelMgr;
return null;
return team switch
{
Team.Alliance => allianceChannelMgr,
Team.Horde => hordeChannelMgr,
Team.PandariaNeutral => neutralChannelMgr,
_ => null
};
}
public static Channel GetChannelForPlayerByNamePart(string namePart, Player playerSearcher)
@@ -239,5 +239,6 @@ namespace Game.Chat
static ChannelManager allianceChannelMgr = new(Team.Alliance);
static ChannelManager hordeChannelMgr = new(Team.Horde);
static ChannelManager neutralChannelMgr = new(Team.PandariaNeutral);
}
}
+5 -15
View File
@@ -683,17 +683,11 @@ namespace Game.Chat
if (linked == "linked")
{
Battleground bg = player.GetBattleground();
if (bg != null)
nearestLoc = bg.GetClosestGraveyard(player);
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(player.GetMap(), player.GetZoneId());
if (bf != null)
nearestLoc = bf.GetClosestGraveyard(player);
else
{
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(player.GetMap(), player.GetZoneId());
if (bf != null)
nearestLoc = bf.GetClosestGraveyard(player);
else
nearestLoc = Global.ObjectMgr.GetClosestGraveyard(player, player.GetTeam(), player);
}
nearestLoc = Global.ObjectMgr.GetClosestGraveyard(player, player.GetTeam(), player);
}
else
{
@@ -788,11 +782,7 @@ namespace Game.Chat
return false;
}
var playerConditionEntry = CliDB.PlayerConditionStorage.LookupByKey(playerConditionId);
if (playerConditionEntry == null)
return false;
if (ConditionManager.IsPlayerMeetingCondition(target, playerConditionEntry))
if (ConditionManager.IsPlayerMeetingCondition(target, playerConditionId))
handler.SendSysMessage($"PlayerCondition {playerConditionId} met");
else
handler.SendSysMessage($"PlayerCondition {playerConditionId} not met");
+1 -1
View File
@@ -123,7 +123,7 @@ namespace Game.Chat
if (normalizePlayerName(*playerNameArg))
{
if (Player * player = ObjectAccessor::FindPlayerByName(*playerNameArg))
if (Player * player = Global.ObjAccessor.FindPlayerByName(*playerNameArg))
{
handler->GetSession()->GetPlayer()->RemoveFromWhisperWhiteList(player->GetGUID());
handler->PSendSysMessage(LANG_COMMAND_WHISPEROFFPLAYER, playerNameArg->c_str());
+1 -2
View File
@@ -839,8 +839,7 @@ namespace Game.Chat
{
if (a.GetMovementGeneratorType() == MovementGeneratorType.Follow)
{
FollowMovementGenerator followMovement = a as FollowMovementGenerator;
return followMovement != null && followMovement.GetTarget() == player;
return a is FollowMovementGenerator followMovement && followMovement.GetTarget() == player;
}
return false;
});
+3 -29
View File
@@ -17,35 +17,10 @@ namespace Game.Chat
if (info == null)
return default;
ChatCommandResult errorResult = ChatCommandResult.FromErrorMessage(handler.GetCypherString(CypherStrings.CmdparserLinkdataInvalid));
// store value
switch (Type.GetTypeCode(type))
{
case TypeCode.UInt32:
{
if (!uint.TryParse(info.Data, out uint tempValue))
return errorResult;
value = tempValue;
break;
}
case TypeCode.UInt64:
{
if (!ulong.TryParse(info.Data, out ulong tempValue))
return errorResult;
value = tempValue;
break;
}
case TypeCode.String:
{
value = info.Data;
break;
}
default:
return errorResult;
}
HyperlinkDataTokenizer t = new(info.Data, true);
if (!t.TryConsumeTo(out value, type))
return new ChatCommandResult(handler.GetCypherString(CypherStrings.CmdparserLinkdataInvalid));
// finally, skip any potential delimiters
var (token, next) = info.Tail.Tokenize();
@@ -101,7 +76,6 @@ namespace Game.Chat
static byte toHex(char c) { return (byte)((c >= '0' && c <= '9') ? c - '0' + 0x10 : (c >= 'a' && c <= 'f') ? c - 'a' + 0x1a : 0x00); }
//|color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r
public static HyperlinkInfo ParseHyperlink(string currentString)
{
if (currentString.IsEmpty())
+89 -126
View File
@@ -2,7 +2,11 @@
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.IO;
using Game.DataStorage;
using Game.Entities;
using Game.Spells;
using System;
using System.Collections.Generic;
namespace Game.Chat
{
@@ -14,136 +18,95 @@ namespace Game.Chat
_allowEmptyTokens = allowEmptyTokens;
}
public bool TryConsumeTo(out byte val)
public bool TryConsumeTo(out dynamic val, Type type)
{
val = default;
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
switch (Type.GetTypeCode(type))
{
case TypeCode.SByte:
val = _arg.NextByte(":");
return true;
case TypeCode.Int16:
val = _arg.NextUInt16(":");
return true;
case TypeCode.Int32:
val = _arg.NextUInt32(":");
return true;
case TypeCode.Int64:
val = _arg.NextUInt64(":");
return true;
case TypeCode.Byte:
val = _arg.NextByte(":");
return true;
case TypeCode.UInt16:
val = _arg.NextUInt16(":");
return true;
case TypeCode.UInt32:
val = _arg.NextUInt32(":");
return true;
case TypeCode.UInt64:
val = _arg.NextUInt64(":");
return true;
case TypeCode.Single:
val = _arg.NextSingle(":");
return true;
case TypeCode.Double:
val = _arg.NextDouble(":");
return true;
case TypeCode.String:
val = _arg.NextString(":");
return true;
case TypeCode.Object:
{
switch (type.Name)
{
case nameof(AchievementRecord):
val = CliDB.AchievementStorage.LookupByKey(_arg.NextUInt32(":"));
if (val != null)
return true;
break;
case nameof(CurrencyTypesRecord):
val = CliDB.CurrencyTypesStorage.LookupByKey(_arg.NextUInt32(":"));
if (val != null)
return true;
break;
case nameof(GameTele):
val = Global.ObjectMgr.GetGameTele(_arg.NextUInt32(":"));
if (val != null)
return true;
break;
case nameof(ItemTemplate):
val = Global.ObjectMgr.GetItemTemplate(_arg.NextUInt32(":"));
if (val != null)
return true;
break;
case nameof(Quest):
val = Global.ObjectMgr.GetQuestTemplate(_arg.NextUInt32(":"));
if (val != null)
return true;
break;
case nameof(SpellInfo):
val = Global.SpellMgr.GetSpellInfo(_arg.NextUInt32(":"), Framework.Constants.Difficulty.None);
if (val != null)
return true;
break;
case nameof(ObjectGuid):
val = ObjectGuid.FromString(_arg.NextString(":"));
if (val != ObjectGuid.FromStringFailed)
return true;
break;
default:
return false;
}
break;
}
}
val = _arg.NextByte(":");
return true;
}
public bool TryConsumeTo(out ushort val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextUInt16(":");
return true;
}
public bool TryConsumeTo(out uint val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextUInt32(":");
return true;
}
public bool TryConsumeTo(out ulong val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextUInt64(":");
return true;
}
public bool TryConsumeTo(out sbyte val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextSByte(":");
return true;
}
public bool TryConsumeTo(out short val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt16(":");
return true;
}
public bool TryConsumeTo(out int val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt32(":");
return true;
}
public bool TryConsumeTo(out long val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt64(":");
return true;
}
public bool TryConsumeTo(out float val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextSingle(":");
return true;
}
public bool TryConsumeTo(out ObjectGuid val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = ObjectGuid.FromString(_arg.NextString(":"));
return true;
}
public bool TryConsumeTo(out string val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextString(":");
return true;
}
public bool TryConsumeTo(out bool val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextBoolean(":");
return true;
return false;
}
public bool IsEmpty() { return _arg.Empty(); }
@@ -151,4 +114,4 @@ namespace Game.Chat
StringArguments _arg;
bool _allowEmptyTokens;
}
}
}
@@ -19,7 +19,7 @@ namespace Game.Collision
void InitEmpty()
{
tree= new uint[3];
tree = new uint[3];
objects = Array.Empty<uint>();
bounds = AxisAlignedBox.Zero();
// create space for the first node
@@ -76,7 +76,7 @@ namespace Game.Collision
rightOrig = right; // save this for later
float nodeL = float.PositiveInfinity;
float nodeR = float.NegativeInfinity;
for (int i = left; i <= right; )
for (int i = left; i <= right;)
{
int obj = (int)dat.indices[i];
float minb = dat.primBound[obj].Lo.GetAt(axis);
@@ -306,6 +306,7 @@ namespace Game.Collision
}
public uint PrimCount() { return (uint)objects.Length; }
public AxisAlignedBox bound() { return bounds; }
public void IntersectRay(Ray r, WorkerCallback intersectCallback, ref float maxDist, bool stopAtFirst = false)
{
@@ -410,7 +411,7 @@ namespace Game.Collision
while (n > 0)
{
bool hit = intersectCallback.Invoke(r, objects[offset], ref maxDist, stopAtFirst);
if (stopAtFirst && hit)
if (stopAtFirst && hit)
return;
--n;
++offset;
+21 -16
View File
@@ -40,34 +40,41 @@ namespace Game.Collision
public class WModelAreaCallback : WorkerCallback
{
public WModelAreaCallback(List<GroupModel> vals, Vector3 down)
List<GroupModel> prims;
public GroupModel[] hit = new GroupModel[3];
public WModelAreaCallback(List<GroupModel> vals)
{
prims = vals;
hit = null;
zDist = float.PositiveInfinity;
zVec = down;
}
List<GroupModel> prims;
public GroupModel hit;
public float zDist;
Vector3 zVec;
public override void Invoke(Vector3 point, uint entry)
public override bool Invoke(Ray ray, uint entry, ref float distance, bool stopAtFirstHit)
{
float group_Z;
if (prims[(int)entry].IsInsideObject(point, zVec, out group_Z))
GroupModel.InsideResult result = prims[(int)entry].IsInsideObject(ray, out float group_Z);
if ( result != GroupModel.InsideResult.OutOfBounds)
{
if (group_Z < zDist)
if (result != GroupModel.InsideResult.MaybeInside)
{
zDist = group_Z;
hit = prims[(int)entry];
if (group_Z < distance)
{
distance = group_Z;
hit[(int)result] = prims[(int)entry];
return true;
}
}
else
hit[(int)result] = prims[(int)entry];
}
return false;
}
}
public class WModelRayCallBack : WorkerCallback
{
List<GroupModel> models;
public bool hit;
public WModelRayCallBack(List<GroupModel> mod)
{
models = mod;
@@ -79,8 +86,6 @@ namespace Game.Collision
if (result) hit = true;
return hit;
}
List<GroupModel> models;
public bool hit;
}
public class GModelRayCallback : WorkerCallback
+66 -16
View File
@@ -251,19 +251,56 @@ namespace Game.Collision
return callback.hit;
}
public bool IsInsideObject(Vector3 pos, Vector3 down, out float z_dist)
bool IsInsideOrAboveBound(AxisAlignedBox bounds, Vector3 point)
{
z_dist = 0f;
if (triangles.Empty() || !iBound.contains(pos))
return false;
return point.X >= bounds.Lo.X
&& point.Y >= bounds.Lo.Y
&& point.Z >= bounds.Lo.Z
&& point.X <= bounds.Hi.X
&& point.Y <= bounds.Hi.Y;
}
Vector3 rPos = pos - 0.1f * down;
float dist = float.PositiveInfinity;
Ray ray = new(rPos, down);
bool hit = IntersectRay(ray, ref dist, false);
if (hit)
z_dist = dist - 0.1f;
return hit;
public enum InsideResult
{
Inside = 0,
MaybeInside = 1,
Above = 2,
OutOfBounds = -1
}
public InsideResult IsInsideObject(Ray ray, out float z_dist)
{
z_dist = 0;
if (triangles.Empty() || !IsInsideOrAboveBound(iBound, ray.Origin))
return InsideResult.OutOfBounds;
if (meshTree.bound().Hi.Z >= ray.Origin.Z)
{
float dist = float.PositiveInfinity;
if (IntersectRay(ray, ref dist, false))
{
z_dist = dist - 0.1f;
return InsideResult.Inside;
}
if (meshTree.bound().contains(ray.Origin))
return InsideResult.MaybeInside;
}
else
{
// some group models don't have any floor to intersect with
// so we should attempt to intersect with a model part below this group
// then find back where we originated from (in WorldModel::GetLocationInfo)
float dist = float.PositiveInfinity;
float delta = ray.Origin.Z - meshTree.bound().Hi.Z;
if (IntersectRay(ray.bumpedRay(delta), ref dist, false))
{
z_dist = dist - 0.1f + delta;
return InsideResult.Above;
}
}
return InsideResult.OutOfBounds;
}
public bool GetLiquidLevel(Vector3 pos, out float liqHeight)
@@ -321,13 +358,26 @@ namespace Game.Collision
if (groupModels.Empty())
return false;
WModelAreaCallback callback = new(groupModels, down);
groupTree.IntersectPoint(p, callback);
if (callback.hit != null)
WModelAreaCallback callback = new(groupModels);
Ray r = new(p - down * 0.1f, down);
float zDist = groupTree.bound().extent().Length();
groupTree.IntersectRay(r, callback, ref zDist, false);
if (callback.hit[(int)GroupModel.InsideResult.Inside] != null)
{
info.rootId = (int)RootWMOID;
info.hitModel = callback.hit;
dist = callback.zDist;
info.hitModel = callback.hit[(int)GroupModel.InsideResult.Inside];
dist = zDist;
return true;
}
// some group models don't have any floor to intersect with
// so we should attempt to intersect with a model part below the group `p` is in (stored in GroupModel::ABOVE)
// then find back where we originated from (GroupModel::MAYBE_INSIDE)
if (callback.hit[(int)GroupModel.InsideResult.MaybeInside] != null && callback.hit[(int)GroupModel.InsideResult.Above] != null)
{
info.rootId = (int)RootWMOID;
info.hitModel = callback.hit[(int)GroupModel.InsideResult.MaybeInside];
dist = zDist;
return true;
}
return false;
+2 -6
View File
@@ -66,7 +66,7 @@ namespace Game.Conditions
BattlegroundMap bgMap = map.ToBattlegroundMap();
if (bgMap != null)
{
ZoneScript zoneScript = bgMap.GetBG();
ZoneScript zoneScript = bgMap.GetBattlegroundScript();
switch ((InstanceInfo)ConditionValue3)
{
case InstanceInfo.Data:
@@ -446,11 +446,7 @@ namespace Game.Conditions
case ConditionTypes.PlayerCondition:
{
if (player != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(ConditionValue1);
if (playerCondition != null)
condMeets = ConditionManager.IsPlayerMeetingCondition(player, playerCondition);
}
condMeets = ConditionManager.IsPlayerMeetingCondition(player, ConditionValue1);
break;
}
case ConditionTypes.PrivateObject:
+57 -5
View File
@@ -505,6 +505,41 @@ namespace Game
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.Graveyard])
AddToGraveyardData(id, conditions);
bool isPlayerConditionIdUsedByCondition(int playerConditionId, List<Condition> conditions, Dictionary<ConditionSourceType, Dictionary<ConditionId, List<Condition>>> store)
{
return conditions.Any(condition =>
{
if (condition.ConditionType == ConditionTypes.PlayerCondition)
{
if (condition.ConditionValue1 == playerConditionId)
return true;
var playerCondList = store[ConditionSourceType.PlayerCondition].LookupByKey(new ConditionId(0, (int)condition.ConditionValue1, 0));
if (playerCondList != null)
if (isPlayerConditionIdUsedByCondition(playerConditionId, playerCondList, store))
return true;
}
else if (condition.ReferenceId != 0)
{
var refList = store[ConditionSourceType.ReferenceCondition].LookupByKey(new ConditionId(condition.ReferenceId, 0, 0));
if (refList != null)
if (isPlayerConditionIdUsedByCondition(playerConditionId, refList, store))
return true;
}
return false;
});
}
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.PlayerCondition])
{
if (isPlayerConditionIdUsedByCondition(id.SourceEntry, conditions, ConditionStorage))
{
Log.outError(LogFilter.Sql, $"[Condition SourceType: CONDITION_SOURCE_TYPE_PLAYER_CONDITION, SourceGroup: {id.SourceGroup}, SourceEntry: {id.SourceEntry}, SourceId: {id.SourceId}] " +
$"has a circular reference to player condition id {id.SourceEntry}, removed all conditions for this SourceEntry!");
conditions.Clear();
}
}
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} conditions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
}
@@ -1086,10 +1121,6 @@ namespace Game
return false;
}
break;
case ConditionSourceType.GossipMenu:
case ConditionSourceType.GossipMenuOption:
case ConditionSourceType.SmartEvent:
break;
case ConditionSourceType.Graveyard:
if (Global.ObjectMgr.FindGraveyardData((uint)cond.SourceEntry, cond.SourceGroup) == null)
{
@@ -1183,6 +1214,11 @@ namespace Game
}
break;
}
case ConditionSourceType.GossipMenu:
case ConditionSourceType.GossipMenuOption:
case ConditionSourceType.SmartEvent:
case ConditionSourceType.PlayerCondition:
break;
default:
Log.outError(LogFilter.Sql, $"{cond.ToString()} Invalid ConditionSourceType in `condition` table, ignoring.");
return false;
@@ -1892,6 +1928,21 @@ namespace Game
return 0;
}
public static bool IsPlayerMeetingCondition(Player player, uint conditionId)
{
if (conditionId == 0)
return true;
if (!Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.PlayerCondition, conditionId, player))
return false;
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(conditionId);
if (playerCondition != null)
return IsPlayerMeetingCondition(player, playerCondition);
return true;
}
public static bool IsPlayerMeetingCondition(Player player, PlayerConditionRecord condition)
{
ContentTuningLevels? levels = Global.DB2Mgr.GetContentTuningData(condition.ContentTuningID, player.m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
@@ -2957,7 +3008,8 @@ namespace Game
"AreaTrigger Client Triggered",
"Trainer Spell",
"Object Visibility (by ID)",
"Spawn Group"
"Spawn Group",
"Player Condition"
};
public ConditionTypeInfo[] StaticConditionTypeData =
+2 -2
View File
@@ -26,6 +26,8 @@ namespace Game.DataStorage
public uint CriteriaTree;
public ushort SharesCriteria;
public int CovenantID;
public int HiddenBeforeDisplaySeason; // hidden in UI before this DisplaySeason is active
public int LegacyAfterTimeEvent; // category changes clientside to Legacy after this TimeEvent is passed
}
public sealed class AchievementCategoryRecord
@@ -54,8 +56,6 @@ namespace Game.DataStorage
public ushort BattleMasterListID;
public byte PriorityMin;
public byte PriorityMax;
public int ItemID;
public uint ItemQuantity;
public ushort CurrencyType;
public uint CurrencyQuantity;
public ushort UiMapID;
@@ -285,7 +285,7 @@ namespace Game.Entities
public class AreaTriggerSpawn : SpawnData
{
public AreaTriggerId Id;
public new AreaTriggerId Id;
public uint? SpellForVisuals;
public AreaTriggerSpawn() : base(SpawnObjectType.AreaTrigger) { }
+7 -3
View File
@@ -2588,11 +2588,15 @@ namespace Game.Entities
// Send a message to LocalDefense channel for players opposition team in the zone
public void SendZoneUnderAttackMessage(Player attacker)
{
Team enemy_team = attacker.GetTeam();
ZoneUnderAttack packet = new();
packet.AreaID = (int)GetAreaId();
Global.WorldMgr.SendGlobalMessage(packet, null, (enemy_team == Team.Alliance ? Team.Horde : Team.Alliance));
packet.Write();
Team enemyTeam = attacker.GetTeam();
if (enemyTeam != Team.Alliance)
Global.WorldMgr.SendGlobalMessage(packet, null, Team.Alliance);
if (enemyTeam != Team.Horde)
Global.WorldMgr.SendGlobalMessage(packet, null, Team.Horde);
}
public void SetCanMelee(bool canMelee, bool fleeFromMelee = false)
+71 -125
View File
@@ -290,9 +290,10 @@ namespace Game.Entities
m_goValue.FishingHole.MaxOpens = RandomHelper.URand(GetGoInfo().FishingHole.minRestock, GetGoInfo().FishingHole.maxRestock);
break;
case GameObjectTypes.DestructibleBuilding:
m_goValue.Building.Health = 20000;//goinfo.DestructibleBuilding.intactNumHits + goinfo.DestructibleBuilding.damagedNumHits;
m_goValue.Building.MaxHealth = m_goValue.Building.Health;
m_goValue.Building.DestructibleHitpoint = Global.ObjectMgr.GetDestructibleHitpoint(GetGoInfo().DestructibleBuilding.HealthRec);
m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint != null ? m_goValue.Building.DestructibleHitpoint.GetMaxHealth() : 0;
SetGoAnimProgress(255);
// yes, even after the updatefield rewrite this garbage hack is still in client
SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), new Quaternion(goInfo.DestructibleBuilding.DestructibleModelRec, 0f, 0f, 0f));
break;
@@ -1366,13 +1367,24 @@ namespace Game.Entities
}
}
public bool CanActivateForPlayer(Player target)
{
if (!MeetsInteractCondition(target))
return false;
if (!ActivateToQuest(target))
return false;
return true;
}
public bool ActivateToQuest(Player target)
{
if (target.HasQuestForGO((int)GetEntry()))
return true;
if (!Global.ObjectMgr.IsGameObjectForQuests(GetEntry()))
return false;
return true;
switch (GetGoType())
{
@@ -1393,9 +1405,6 @@ namespace Game.Entities
|| LootStorage.Gameobject.HaveQuestLootForPlayer(GetGoInfo().Chest.chestPersonalLoot, target)
|| LootStorage.Gameobject.HaveQuestLootForPlayer(GetGoInfo().Chest.chestPushLoot, target))
{
Battleground bg = target.GetBattleground();
if (bg != null)
return bg.CanActivateGO((int)GetEntry(), (uint)bg.GetPlayerTeam(target.GetGUID()));
return true;
}
break;
@@ -1406,6 +1415,12 @@ namespace Game.Entities
return true;
break;
}
case GameObjectTypes.SpellFocus:
{
if (target.GetQuestStatus(GetGoInfo().SpellFocus.questID) == QuestStatus.Incomplete)
return true;
break;
}
case GameObjectTypes.Goober:
{
if (target.GetQuestStatus(GetGoInfo().Goober.questID) == QuestStatus.Incomplete)
@@ -1701,10 +1716,6 @@ namespace Game.Entities
if (player == null)
return;
Battleground bg = player.GetBattleground();
if (bg != null && !bg.CanActivateGO((int)GetEntry(), (uint)bg.GetPlayerTeam(user.GetGUID())))
return;
GameObjectTemplate info = GetGoInfo();
if (loot == null && info.GetLootId() != 0)
{
@@ -2250,7 +2261,6 @@ namespace Game.Entities
break;
}
case GameObjectTypes.FlagStand: // 24
{
if (!user.IsTypeId(TypeId.Player))
@@ -2260,29 +2270,15 @@ namespace Game.Entities
if (player.CanUseBattlegroundObject(this))
{
// in Battlegroundcheck
Battleground bg = player.GetBattleground();
if (bg == null)
return;
if (player.GetVehicle() != null)
return;
player.RemoveAurasByType(AuraType.ModStealth);
player.RemoveAurasByType(AuraType.ModInvisibility);
// BG flag click
// AB:
// 15001
// 15002
// 15003
// 15004
// 15005
bg.EventPlayerClickedOnFlag(player, this);
return; //we don;t need to delete flag ... it is despawned!
}
break;
}
case GameObjectTypes.FishingHole: // 25
{
if (!user.IsTypeId(TypeId.Player))
@@ -2290,7 +2286,7 @@ namespace Game.Entities
Player player = user.ToPlayer();
Loot loot = new Loot(GetMap(), GetGUID(), LootType.Fishinghole, null);
Loot loot = new(GetMap(), GetGUID(), LootType.Fishinghole, null);
loot.FillLoot(GetGoInfo().GetLootId(), LootStorage.Gameobject, player, true, false, LootModes.Default, ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player));
m_personalLoot[player.GetGUID()] = loot;
@@ -2298,7 +2294,6 @@ namespace Game.Entities
player.UpdateCriteria(CriteriaType.CatchFishInFishingHole, GetGoInfo().entry);
return;
}
case GameObjectTypes.FlagDrop: // 26
{
if (!user.IsTypeId(TypeId.Player))
@@ -2308,11 +2303,6 @@ namespace Game.Entities
if (player.CanUseBattlegroundObject(this))
{
// in Battlegroundcheck
Battleground bg = player.GetBattleground();
if (bg == null)
return;
if (player.GetVehicle() != null)
return;
@@ -2325,24 +2315,8 @@ namespace Game.Entities
// EotS:
// 184142 - Netherstorm Flag
GameObjectTemplate info = GetGoInfo();
if (info != null)
{
switch (info.entry)
{
case 179785: // Silverwing Flag
case 179786: // Warsong Flag
if (bg.GetTypeID() == BattlegroundTypeId.WS)
bg.EventPlayerClickedOnFlag(player, this);
break;
case 184142: // Netherstorm Flag
if (bg.GetTypeID() == BattlegroundTypeId.EY)
bg.EventPlayerClickedOnFlag(player, this);
break;
}
if (info.FlagDrop.eventID != 0)
GameEvents.Trigger(info.FlagDrop.eventID, player, this);
}
if (info != null && info.FlagDrop.eventID != 0)
GameEvents.Trigger(info.FlagDrop.eventID, player, this);
//this cause to call return, all flags must be deleted here!!
spellId = 0;
Delete();
@@ -2462,10 +2436,9 @@ namespace Game.Entities
return;
Player player = user.ToPlayer();
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(info.ItemForge.conditionID1);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
return;
if (!MeetsInteractCondition(player))
return;
switch (info.ItemForge.ForgeType)
{
@@ -2743,7 +2716,7 @@ namespace Game.Entities
public void SetLocalRotation(float qx, float qy, float qz, float qw)
{
Quaternion rotation = new Quaternion(qx, qy, qz, qw);
Quaternion rotation = new(qx, qy, qz, qw);
rotation = Quaternion.Multiply(rotation, 1.0f / MathF.Sqrt(Quaternion.Dot(rotation, rotation)));
m_localRotation.X = rotation.X;
@@ -2880,7 +2853,7 @@ namespace Game.Entities
public void ModifyHealth(int change, WorldObject attackerOrHealer = null, uint spellId = 0)
{
if (m_goValue.Building.MaxHealth == 0 || change == 0)
if (m_goValue.Building.DestructibleHitpoint == null || change == 0)
return;
// prevent double destructions of the same object
@@ -2889,13 +2862,13 @@ namespace Game.Entities
if (m_goValue.Building.Health + change <= 0)
m_goValue.Building.Health = 0;
else if (m_goValue.Building.Health + change >= m_goValue.Building.MaxHealth)
m_goValue.Building.Health = m_goValue.Building.MaxHealth;
else if (m_goValue.Building.Health + change >= m_goValue.Building.DestructibleHitpoint.GetMaxHealth())
m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth();
else
m_goValue.Building.Health += (uint)change;
// Set the health bar, value = 255 * healthPct;
SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.MaxHealth);
SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.DestructibleHitpoint.GetMaxHealth());
// dealing damage, send packet
Player player = attackerOrHealer != null ? attackerOrHealer.GetCharmerOrOwnerPlayerOrPlayerItself() : null;
@@ -2917,9 +2890,9 @@ namespace Game.Entities
if (m_goValue.Building.Health == 0)
newState = GameObjectDestructibleState.Destroyed;
else if (m_goValue.Building.Health < m_goValue.Building.MaxHealth / 2)
else if (m_goValue.Building.Health < m_goValue.Building.DestructibleHitpoint.DamagedNumHits)
newState = GameObjectDestructibleState.Damaged;
else if (m_goValue.Building.Health == m_goValue.Building.MaxHealth)
else if (m_goValue.Building.Health == m_goValue.Building.DestructibleHitpoint.GetMaxHealth())
newState = GameObjectDestructibleState.Intact;
if (newState == GetDestructibleState())
@@ -2938,9 +2911,9 @@ namespace Game.Entities
case GameObjectDestructibleState.Intact:
RemoveFlag(GameObjectFlags.Damaged | GameObjectFlags.Destroyed);
SetDisplayId(m_goInfo.displayId);
if (setHealth)
if (setHealth && m_goValue.Building.DestructibleHitpoint != null)
{
m_goValue.Building.Health = m_goValue.Building.MaxHealth;
m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth();
SetGoAnimProgress(255);
}
EnableCollision(true);
@@ -2959,12 +2932,13 @@ namespace Game.Entities
if (modelData != null)
if (modelData.State1Wmo != 0)
modelId = modelData.State1Wmo;
SetDisplayId(modelId);
if (setHealth)
if (setHealth && m_goValue.Building.DestructibleHitpoint != null)
{
m_goValue.Building.Health = 10000;//m_goInfo.DestructibleBuilding.damagedNumHits;
uint maxHealth = m_goValue.Building.MaxHealth;
m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.DamagedNumHits;
uint maxHealth = m_goValue.Building.DestructibleHitpoint.GetMaxHealth();
// in this case current health is 0 anyway so just prevent crashing here
if (maxHealth == 0)
maxHealth = 1;
@@ -2978,14 +2952,6 @@ namespace Game.Entities
GameEvents.Trigger(GetGoInfo().DestructibleBuilding.DestroyedEvent, attackerOrHealer, this);
GetAI().Destroyed(attackerOrHealer, m_goInfo.DestructibleBuilding.DestroyedEvent);
Player player = attackerOrHealer != null ? attackerOrHealer.GetCharmerOrOwnerPlayerOrPlayerItself() : null;
if (player != null)
{
Battleground bg = player.GetBattleground();
if (bg != null)
bg.DestroyGate(player, this);
}
RemoveFlag(GameObjectFlags.Damaged);
SetFlag(GameObjectFlags.Destroyed);
@@ -2994,6 +2960,7 @@ namespace Game.Entities
if (modelData != null)
if (modelData.State2Wmo != 0)
modelId = modelData.State2Wmo;
SetDisplayId(modelId);
if (setHealth)
@@ -3018,9 +2985,9 @@ namespace Game.Entities
SetDisplayId(modelId);
// restores to full health
if (setHealth)
if (setHealth & m_goValue.Building.DestructibleHitpoint != null)
{
m_goValue.Building.Health = m_goValue.Building.MaxHealth;
m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth();
SetGoAnimProgress(255);
}
EnableCollision(true);
@@ -3318,8 +3285,7 @@ namespace Game.Entities
public List<uint> GetPauseTimes()
{
GameObjectType.Transport transport = m_goTypeImpl as GameObjectType.Transport;
if (transport != null)
if (m_goTypeImpl is GameObjectType.Transport transport)
return transport.GetPauseTimes();
return null;
@@ -3655,8 +3621,7 @@ namespace Game.Entities
if (GetGoType() != GameObjectTypes.NewFlag)
return 0;
GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag;
if (newFlag == null)
if (m_goTypeImpl is not GameObjectType.NewFlag newFlag)
return 0;
return newFlag.GetState();
@@ -3667,8 +3632,7 @@ namespace Game.Entities
if (GetGoType() != GameObjectTypes.NewFlag)
return ObjectGuid.Empty;
GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag;
if (newFlag == null)
if (m_goTypeImpl is not GameObjectType.NewFlag newFlag)
return ObjectGuid.Empty;
return newFlag.GetCarrierGUID();
@@ -3679,8 +3643,7 @@ namespace Game.Entities
if (GetGoType() != GameObjectTypes.NewFlag)
return 0;
GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag;
if (newFlag == null)
if (m_goTypeImpl is not GameObjectType.NewFlag newFlag)
return 0;
return newFlag.GetTakenFromBaseTime();
@@ -3688,8 +3651,7 @@ namespace Game.Entities
public List<ObjectGuid> GetInsidePlayers()
{
ControlZone controlZone = m_goTypeImpl as ControlZone;
if (controlZone != null)
if (m_goTypeImpl is ControlZone controlZone)
return controlZone.GetInsidePlayers();
return null;
@@ -3697,15 +3659,7 @@ namespace Game.Entities
public bool MeetsInteractCondition(Player user)
{
if (m_goInfo.GetConditionID1() == 0)
return true;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(m_goInfo.GetConditionID1());
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(user, playerCondition))
return false;
return true;
return ConditionManager.IsPlayerMeetingCondition(user, m_goInfo.GetConditionID1());
}
PerPlayerState GetOrCreatePerPlayerStates(ObjectGuid guid)
@@ -3797,17 +3751,17 @@ namespace Game.Entities
public GameObjectTypes GetGoType() { return (GameObjectTypes)(sbyte)m_gameObjectData.TypeID; }
public void SetGoType(GameObjectTypes type) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.TypeID), (sbyte)type); }
public GameObjectState GetGoState() { return (GameObjectState)(sbyte)m_gameObjectData.State; }
uint GetGoArtKit() { return m_gameObjectData.ArtKit; }
byte GetGoAnimProgress() { return m_gameObjectData.PercentHealth; }
public uint GetGoArtKit() { return m_gameObjectData.ArtKit; }
public byte GetGoAnimProgress() { return m_gameObjectData.PercentHealth; }
public void SetGoAnimProgress(uint animprogress) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.PercentHealth), (byte)animprogress); }
public LootState GetLootState() { return m_lootState; }
public LootModes GetLootMode() { return m_LootMode; }
bool HasLootMode(LootModes lootMode) { return Convert.ToBoolean(m_LootMode & lootMode); }
void SetLootMode(LootModes lootMode) { m_LootMode = lootMode; }
void AddLootMode(LootModes lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(LootModes lootMode) { m_LootMode &= ~lootMode; }
void ResetLootMode() { m_LootMode = LootModes.Default; }
public bool HasLootMode(LootModes lootMode) { return Convert.ToBoolean(m_LootMode & lootMode); }
public void SetLootMode(LootModes lootMode) { m_LootMode = lootMode; }
public void AddLootMode(LootModes lootMode) { m_LootMode |= lootMode; }
public void RemoveLootMode(LootModes lootMode) { m_LootMode &= ~lootMode; }
public void ResetLootMode() { m_LootMode = LootModes.Default; }
public void AddToSkillupList(ObjectGuid PlayerGuid) { m_SkillupList.Add(PlayerGuid); }
public bool IsInSkillupList(ObjectGuid PlayerGuid)
@@ -3818,17 +3772,17 @@ namespace Game.Entities
return false;
}
void ClearSkillupList() { m_SkillupList.Clear(); }
public void ClearSkillupList() { m_SkillupList.Clear(); }
public void AddUse() { ++m_usetimes; }
public uint GetUseCount() { return m_usetimes; }
uint GetUniqueUseCount() { return (uint)m_unique_users.Count; }
public uint GetUniqueUseCount() { return (uint)m_unique_users.Count; }
List<ObjectGuid> GetTapList() { return m_tapList; }
void SetTapList(List<ObjectGuid> tapList) { m_tapList = tapList; }
public List<ObjectGuid> GetTapList() { return m_tapList; }
public void SetTapList(List<ObjectGuid> tapList) { m_tapList = tapList; }
bool HasLootRecipient() { return !m_tapList.Empty(); }
public bool HasLootRecipient() { return !m_tapList.Empty(); }
public override uint GetLevelForTarget(WorldObject target)
{
@@ -4006,14 +3960,9 @@ namespace Game.Entities
}
// Base class for GameObject type specific implementations
public class GameObjectTypeBase
public class GameObjectTypeBase(GameObject owner)
{
protected GameObject _owner;
public GameObjectTypeBase(GameObject owner)
{
_owner = owner;
}
protected GameObject _owner = owner;
public virtual void Update(uint diff) { }
public virtual void OnStateChanged(GameObjectState oldState, GameObjectState newState) { }
@@ -4057,7 +4006,7 @@ namespace Game.Entities
public struct building
{
public uint Health;
public uint MaxHealth;
public DestructibleHitpoint DestructibleHitpoint;
}
//42 GAMEOBJECT_TYPE_CAPTURE_POINT
public struct capturePoint
@@ -4149,12 +4098,12 @@ namespace Game.Entities
uint now = GameTime.GetGameTimeMS();
uint period = GetTransportPeriod();
uint newProgress = 0;
uint newProgress;
if (_stopFrames.Empty())
newProgress = now % period;
else
{
int stopTargetTime = 0;
int stopTargetTime;
if (_owner.GetGoState() == GameObjectState.TransportActive)
stopTargetTime = 0;
else
@@ -4179,7 +4128,7 @@ namespace Game.Entities
progressPct = pathPctBetweenStops * timeSinceStopProgressPct + stopSourcePathPct;
if (progressPct > 1.0f)
progressPct = progressPct - 1.0f;
progressPct = -1.0f;
}
else
{
@@ -4379,8 +4328,7 @@ namespace Game.Entities
{
foreach (WorldObject passenger in _passengers)
{
float x, y, z, o;
passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o);
passenger.m_movementInfo.transport.pos.GetPosition(out float x, out float y, out float z, out float o);
CalculatePassengerPosition(ref x, ref y, ref z, ref o);
ITransport.UpdatePassengerPosition(this, _owner.GetMap(), passenger, x, y, z, o, true);
}
@@ -4529,7 +4477,7 @@ namespace Game.Entities
public long GetTakenFromBaseTime() { return _takenFromBaseTime; }
}
class SetNewFlagState : GameObjectTypeBase.CustomCommand
public class SetNewFlagState : GameObjectTypeBase.CustomCommand
{
FlagState _state;
Player _player;
@@ -4542,8 +4490,7 @@ namespace Game.Entities
public override void Execute(GameObjectTypeBase type)
{
NewFlag newFlag = type as NewFlag;
if (newFlag != null)
if (type is NewFlag newFlag)
newFlag.SetState(_state, _player);
}
}
@@ -4793,8 +4740,7 @@ namespace Game.Entities
public override void Execute(GameObjectTypeBase type)
{
ControlZone controlZone = type as ControlZone;
if (controlZone != null)
if (type is ControlZone controlZone)
{
uint value = controlZone.GetStartingValue();
if (_value.HasValue)
@@ -267,6 +267,15 @@ namespace Game.Entities
}
}
public uint GetQuestID() => type switch
{
GameObjectTypes.Chest => Chest.questID,
GameObjectTypes.Generic => Generic.questID,
GameObjectTypes.SpellFocus => SpellFocus.questID,
GameObjectTypes.Goober => Goober.questID,
_ => 0
};
public uint GetConditionID1() => type switch
{
GameObjectTypes.Door => Door.conditionID1,
@@ -1648,4 +1657,13 @@ namespace Game.Entities
public GameObjectData() : base(SpawnObjectType.GameObject) { }
}
public class DestructibleHitpoint
{
public uint Id;
public uint IntactNumHits;
public uint DamagedNumHits;
public uint GetMaxHealth() { return IntactNumHits + DamagedNumHits; }
}
}
+1 -5
View File
@@ -296,11 +296,7 @@ namespace Game.Entities
public bool CanUseEssences()
{
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(PlayerConst.PlayerConditionIdUnlockedAzeriteEssences);
if (condition != null)
return ConditionManager.IsPlayerMeetingCondition(GetOwner(), condition);
return false;
return ConditionManager.IsPlayerMeetingCondition(GetOwner(), PlayerConst.PlayerConditionIdUnlockedAzeriteEssences);
}
public bool HasUnlockedEssenceSlot(byte slot)
+15 -22
View File
@@ -72,10 +72,8 @@ namespace Game.Entities
if (itemProto.GetArtifactID() != artifactAppearanceSet.ArtifactID)
continue;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactAppearance.UnlockPlayerConditionID);
if (playerCondition != null)
if (owner == null || !ConditionManager.IsPlayerMeetingCondition(owner, playerCondition))
continue;
if (owner == null || !ConditionManager.IsPlayerMeetingCondition(owner, artifactAppearance.UnlockPlayerConditionID))
continue;
SetModifier(ItemModifier.ArtifactAppearanceId, artifactAppearance.Id);
SetAppearanceModId(artifactAppearance.ItemAppearanceModifierID);
@@ -591,13 +589,9 @@ namespace Game.Entities
if (_bonusData.GemRelicType[e - EnchantmentSlot.Sock1] != -1)
{
ArtifactPowerPickerRecord artifactPowerPicker = CliDB.ArtifactPowerPickerStorage.LookupByKey(enchant.EffectArg[i]);
if (artifactPowerPicker != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactPowerPicker.PlayerConditionID);
if (playerCondition == null || (owner != null && ConditionManager.IsPlayerMeetingCondition(owner, playerCondition)))
if (artifactPower.Label == _bonusData.GemRelicType[e - EnchantmentSlot.Sock1])
power.CurrentRankWithBonus += (byte)enchant.EffectPointsMin[i];
}
if (artifactPowerPicker != null && owner != null && ConditionManager.IsPlayerMeetingCondition(owner, artifactPowerPicker.PlayerConditionID))
if (artifactPower.Label == _bonusData.GemRelicType[e - EnchantmentSlot.Sock1])
power.CurrentRankWithBonus += (byte)enchant.EffectPointsMin[i];
}
break;
default:
@@ -793,7 +787,7 @@ namespace Game.Entities
return !IsInBag() && (m_slot < EquipmentSlot.End
|| (m_slot >= ProfessionSlots.Start && m_slot < ProfessionSlots.End));
}
public bool CanBeTraded(bool mail = false, bool trade = false)
{
if (m_lootGenerated)
@@ -876,7 +870,7 @@ namespace Game.Entities
return cost;
}
bool HasEnchantRequiredSkill(Player player)
{
// Check all enchants for required skill
@@ -995,11 +989,11 @@ namespace Game.Entities
{
var oldEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(slot));
if (oldEnchant != null && !oldEnchant.HasFlag(SpellItemEnchantmentFlags.DoNotLog))
owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant.Id, (uint)slot);
owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant.Id, (uint)slot);
var newEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(id);
if (newEnchant != null && !newEnchant.HasFlag(SpellItemEnchantmentFlags.DoNotLog))
owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot);
owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot);
}
ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner);
@@ -2059,7 +2053,7 @@ namespace Game.Entities
return itemModifiedAppearanceId;
}
public uint GetVisibleSecondaryModifiedAppearanceId(Player owner)
{
uint itemModifiedAppearanceId = GetModifier(ItemConst.SecondaryAppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
@@ -2068,7 +2062,7 @@ namespace Game.Entities
return itemModifiedAppearanceId;
}
public uint GetVisibleEnchantmentId(Player owner)
{
uint enchantmentId = GetModifier(ItemConst.IllusionModifierSlotBySpec[owner.GetActiveTalentGroup()]);
@@ -2290,8 +2284,7 @@ namespace Game.Entities
ArtifactPowerPickerRecord artifactPowerPicker = CliDB.ArtifactPowerPickerStorage.LookupByKey(enchant.EffectArg[i]);
if (artifactPowerPicker != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactPowerPicker.PlayerConditionID);
if (playerCondition == null || ConditionManager.IsPlayerMeetingCondition(owner, playerCondition))
if (ConditionManager.IsPlayerMeetingCondition(owner, artifactPowerPicker.PlayerConditionID))
{
for (int artifactPowerIndex = 0; artifactPowerIndex < m_itemData.ArtifactPowers.Size(); ++artifactPowerIndex)
{
@@ -2413,7 +2406,7 @@ namespace Game.Entities
{
return $"{base.GetDebugInfo()}\nOwner: {GetOwnerGUID()} Count: {GetCount()} BagSlot: {GetBagSlot()} Slot: {GetSlot()} Equipped: {IsEquipped()}";
}
public static Item NewItemOrBag(ItemTemplate proto)
{
if (proto.GetInventoryType() == InventoryType.Bag)
@@ -2685,8 +2678,8 @@ namespace Game.Entities
public void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; }
public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; }
public override Loot GetLootForPlayer(Player player) { return loot; }
public override Loot GetLootForPlayer(Player player) { return loot; }
//Static
public static bool ItemCanGoIntoBag(ItemTemplate pProto, ItemTemplate pBagProto)
@@ -50,6 +50,9 @@ namespace Game.Entities
public static ItemContext GetContextForPlayer(MapDifficultyRecord mapDifficulty, Player player)
{
if (mapDifficulty == null)
return ItemContext.None;
ItemContext evalContext(ItemContext currentContext, ItemContext newContext)
{
if (newContext == ItemContext.None)
@@ -81,11 +84,7 @@ namespace Game.Entities
bool meetsPlayerCondition = false;
if (player != null)
{
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(itemContextPickerEntry.PlayerConditionID);
if (playerCondition != null)
meetsPlayerCondition = ConditionManager.IsPlayerMeetingCondition(player, playerCondition);
}
meetsPlayerCondition = ConditionManager.IsPlayerMeetingCondition(player, itemContextPickerEntry.PlayerConditionID);
if ((itemContextPickerEntry.Flags & 0x1) != 0)
meetsPlayerCondition = !meetsPlayerCondition;
@@ -112,29 +112,33 @@ namespace Game.Entities
ushort pathProgress = 0xFFFF;
switch (gameObject.GetGoType())
{
case GameObjectTypes.Button:
case GameObjectTypes.Goober:
if (gameObject.GetGoInfo().GetQuestID() != 0 || gameObject.GetGoInfo().GetConditionID1() != 0)
{
if (gameObject.CanActivateForPlayer(receiver))
{
dynFlags |= GameObjectDynamicLowFlags.Highlight;
if (gameObject.GetGoStateFor(receiver.GetGUID()) != GameObjectState.Active)
dynFlags |= GameObjectDynamicLowFlags.Activate;
}
}
break;
case GameObjectTypes.QuestGiver:
if (gameObject.ActivateToQuest(receiver))
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Chest:
if (gameObject.ActivateToQuest(receiver))
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
else if (receiver.IsGameMaster())
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Goober:
if (gameObject.ActivateToQuest(receiver))
{
dynFlags |= GameObjectDynamicLowFlags.Highlight;
if (gameObject.GetGoStateFor(receiver.GetGUID()) != GameObjectState.Active)
dynFlags |= GameObjectDynamicLowFlags.Activate;
}
else if (receiver.IsGameMaster())
dynFlags |= GameObjectDynamicLowFlags.Activate;
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle;
break;
case GameObjectTypes.Generic:
if (gameObject.ActivateToQuest(receiver))
dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
case GameObjectTypes.SpellFocus:
if (gameObject.GetGoInfo().GetQuestID() != 0 || gameObject.GetGoInfo().GetConditionID1() != 0)
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
break;
case GameObjectTypes.Transport:
case GameObjectTypes.MapObjTransport:
@@ -150,7 +154,7 @@ namespace Game.Entities
dynFlags &= ~GameObjectDynamicLowFlags.NoInterract;
break;
case GameObjectTypes.GatheringNode:
if (gameObject.ActivateToQuest(receiver))
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
if (gameObject.GetGoStateFor(receiver.GetGUID()) == GameObjectState.Active)
dynFlags |= GameObjectDynamicLowFlags.Depleted;
@@ -159,7 +163,7 @@ namespace Game.Entities
break;
}
if (!gameObject.MeetsInteractCondition(receiver))
if (!receiver.IsGameMaster() && !gameObject.MeetsInteractCondition(receiver))
dynFlags |= GameObjectDynamicLowFlags.NoInterract;
unitDynFlags = ((uint)pathProgress << 16) | (uint)dynFlags;
@@ -2789,22 +2793,25 @@ namespace Game.Entities
public UpdateField<uint> HonorLevel = new(0, 30);
public UpdateField<long> LogoutTime = new(0, 31);
public UpdateFieldString Name = new(32, 33);
public UpdateField<int> Field_B0 = new(32, 34);
public UpdateField<int> Field_B4 = new(32, 35);
public UpdateField<int> Field_1AC = new(32, 34);
public UpdateField<int> Field_1B0 = new(32, 35);
public UpdateField<int> CurrentBattlePetSpeciesID = new(32, 36);
public UpdateField<CTROptions> CtrOptions = new(32, 37);
public UpdateField<int> CovenantID = new(32, 38);
public UpdateField<int> SoulbindID = new(32, 39);
public UpdateField<DungeonScoreSummary> DungeonScore = new(32, 40);
public OptionalUpdateField<DeclinedNames> DeclinedNames = new(32, 41);
public UpdateField<CustomTabardInfo> PersonalTabard = new(32, 42);
public UpdateFieldArray<byte> PartyType = new(2, 43, 44);
public UpdateFieldArray<QuestLog> QuestLog = new(175, 46, 47);
public UpdateFieldArray<VisibleItem> VisibleItems = new(19, 222, 223);
public UpdateFieldArray<float> AvgItemLevel = new(6, 242, 243);
public UpdateFieldArray<uint> Field_3120 = new(19, 249, 250);
public UpdateField<ObjectGuid> SpectateTarget = new(32, 41);
public UpdateField<int> Field_200 = new(32, 42);
public OptionalUpdateField<DeclinedNames> DeclinedNames = new(32, 43);
public UpdateField<CustomTabardInfo> PersonalTabard = new(32, 44);
public UpdateFieldArray<byte> PartyType = new(2, 45, 46);
public UpdateFieldArray<QuestLog> QuestLog = new(175, 48, 49);
public UpdateFieldArray<VisibleItem> VisibleItems = new(19, 224, 225);
public UpdateFieldArray<float> AvgItemLevel = new(6, 244, 245);
public UpdateFieldArray<ItemInstance> VisibleEquipableSpells = new(16, 251, 252);
public UpdateFieldArray<uint> Field_3120 = new(19, 268, 269);
public PlayerData() : base(0, TypeId.Player, 269) { }
public PlayerData() : base(0, TypeId.Player, 288) { }
public void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Player owner, Player receiver)
{
@@ -2854,12 +2861,14 @@ namespace Game.Entities
data.WriteUInt32(HonorLevel);
data.WriteInt64(LogoutTime);
data.WriteInt32(ArenaCooldowns.Size());
data.WriteInt32(Field_B0);
data.WriteInt32(Field_B4);
data.WriteInt32(Field_1AC);
data.WriteInt32(Field_1B0);
data.WriteInt32(CurrentBattlePetSpeciesID);
((CTROptions)CtrOptions).WriteCreate(data, owner, receiver);
data.WriteInt32(CovenantID);
data.WriteInt32(SoulbindID);
data.WritePackedGuid(SpectateTarget);
data.WriteInt32(Field_200);
data.WriteInt32(VisualItemReplacements.Size());
for (int i = 0; i < 19; ++i)
{
@@ -2899,6 +2908,10 @@ namespace Game.Entities
data.WriteBits(DeclinedNames.HasValue(), 1);
DungeonScore._value.Write(data);
data.WriteString(Name);
for (int i = 0; i < 16; ++i)
{
VisibleEquipableSpells[i].Write(data);
}
if (DeclinedNames.HasValue())
{
DeclinedNames.GetValue().WriteCreate(data, owner, receiver);
@@ -2908,7 +2921,7 @@ namespace Game.Entities
public void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Player owner, Player receiver)
{
UpdateMask allowedMaskForTarget = new(269, [0xFFFFFFDDu, 0x00003FFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xC0000000u, 0xFFFFFFFFu, 0x00001FFFu]);
UpdateMask allowedMaskForTarget = new(288, [0xFFFFFFDDu, 0x0000FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFFu, 0xFFFFFFFFu]);
AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver);
}
@@ -2916,12 +2929,12 @@ namespace Game.Entities
public void AppendAllowedFieldsMaskForFlag(UpdateMask allowedMaskForTarget, UpdateFieldFlag fieldVisibilityFlags)
{
if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.PartyMember))
allowedMaskForTarget.OR(new UpdateMask(269, new[] { 0x00000022u, 0xFFFFC000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x3FFFFFFFu, 0x00000000u, 0x00000000u }));
allowedMaskForTarget.OR(new UpdateMask(288, [0x00000022u, 0xFFFF0000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000000u, 0x00000000u]));
}
public void FilterDisallowedFieldsMaskForFlag(UpdateMask changesMask, UpdateFieldFlag fieldVisibilityFlags)
{
UpdateMask allowedMaskForTarget = new(269, new[] { 0xFFFFFFDDu, 0x00003FFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xC0000000u, 0xFFFFFFFFu, 0x00001FFFu });
UpdateMask allowedMaskForTarget = new(288, [0xFFFFFFDDu, 0x0000FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFFu, 0xFFFFFFFFu]);
AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
changesMask.AND(allowedMaskForTarget);
}
@@ -3137,11 +3150,11 @@ namespace Game.Entities
{
if (changesMask[34])
{
data.WriteInt32(Field_B0);
data.WriteInt32(Field_1AC);
}
if (changesMask[35])
{
data.WriteInt32(Field_B4);
data.WriteInt32(Field_1B0);
}
if (changesMask[36])
{
@@ -3159,13 +3172,21 @@ namespace Game.Entities
{
data.WriteInt32(SoulbindID);
}
if (changesMask[41])
{
data.WritePackedGuid(SpectateTarget);
}
if (changesMask[42])
{
data.WriteInt32(Field_200);
}
if (changesMask[44])
{
PersonalTabard.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
if (changesMask[33])
{
data.WriteBits(Name.GetValue().GetByteCount(), 32);
data.WriteBits(Name.GetValue().GetByteCount(), 6);
}
data.WriteBits(DeclinedNames.HasValue(), 1);
data.FlushBits();
@@ -3177,7 +3198,7 @@ namespace Game.Entities
{
data.WriteString(Name);
}
if (changesMask[41])
if (changesMask[43])
{
if (DeclinedNames.HasValue())
{
@@ -3185,21 +3206,21 @@ namespace Game.Entities
}
}
}
if (changesMask[43])
if (changesMask[45])
{
for (int i = 0; i < 2; ++i)
{
if (changesMask[44 + i])
if (changesMask[46 + i])
{
data.WriteUInt8(PartyType[i]);
}
}
}
if (changesMask[46])
if (changesMask[48])
{
for (int i = 0; i < 175; ++i)
{
if (changesMask[47 + i])
if (changesMask[49 + i])
{
if (noQuestLogChangesMask)
QuestLog[i].WriteCreate(data, owner, receiver);
@@ -3208,36 +3229,46 @@ namespace Game.Entities
}
}
}
if (changesMask[222])
if (changesMask[224])
{
for (int i = 0; i < 19; ++i)
{
if (changesMask[223 + i])
if (changesMask[225 + i])
{
VisibleItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
}
if (changesMask[242])
if (changesMask[244])
{
for (int i = 0; i < 6; ++i)
{
if (changesMask[243 + i])
if (changesMask[245 + i])
{
data.WriteFloat(AvgItemLevel[i]);
}
}
}
if (changesMask[249])
if (changesMask[268])
{
for (int i = 0; i < 19; ++i)
{
if (changesMask[250 + i])
if (changesMask[269 + i])
{
data.WriteUInt32(Field_3120[i]);
}
}
}
if (changesMask[251])
{
for (int i = 0; i < 16; ++i)
{
if (changesMask[252 + i])
{
VisibleEquipableSpells[i].Write(data);
}
}
}
data.FlushBits();
}
@@ -3275,19 +3306,22 @@ namespace Game.Entities
ClearChangesMask(HonorLevel);
ClearChangesMask(LogoutTime);
ClearChangesMask(Name);
ClearChangesMask(Field_B0);
ClearChangesMask(Field_B4);
ClearChangesMask(Field_1AC);
ClearChangesMask(Field_1B0);
ClearChangesMask(CurrentBattlePetSpeciesID);
ClearChangesMask(CtrOptions);
ClearChangesMask(CovenantID);
ClearChangesMask(SoulbindID);
ClearChangesMask(DungeonScore);
ClearChangesMask(SpectateTarget);
ClearChangesMask(Field_200);
ClearChangesMask(DeclinedNames);
ClearChangesMask(PersonalTabard);
ClearChangesMask(PartyType);
ClearChangesMask(QuestLog);
ClearChangesMask(VisibleItems);
ClearChangesMask(AvgItemLevel);
ClearChangesMask(VisibleEquipableSpells);
ClearChangesMask(Field_3120);
_changesMask.ResetAll();
}
+7 -2
View File
@@ -451,13 +451,14 @@ namespace Game.Entities
bool hasMoveCurveID = createProperties != null && createProperties.MoveCurveId != 0;
bool hasAreaTriggerSphere = shape.IsSphere();
bool hasAreaTriggerBox = shape.IsBox();
bool hasAreaTriggerPolygon = createProperties != null && shape.IsPolygon();
bool hasAreaTriggerPolygon = shape.IsPolygon();
bool hasAreaTriggerCylinder = shape.IsCylinder();
bool hasDisk = shape.IsDisk();
bool hasBoundedPlane = shape.IsBoundedPlane();
bool hasAreaTriggerSpline = areaTrigger.HasSplines();
bool hasOrbit = areaTrigger.HasOrbit();
bool hasMovementScript = false;
bool hasPositionalSoundKitID = false;
data.WriteBit(hasAbsoluteOrientation);
data.WriteBit(hasDynamicShape);
@@ -471,6 +472,7 @@ namespace Game.Entities
data.WriteBit(hasMorphCurveID);
data.WriteBit(hasFacingCurveID);
data.WriteBit(hasMoveCurveID);
data.WriteBit(hasPositionalSoundKitID);
data.WriteBit(hasAreaTriggerSphere);
data.WriteBit(hasAreaTriggerBox);
data.WriteBit(hasAreaTriggerPolygon);
@@ -506,6 +508,9 @@ namespace Game.Entities
if (hasMoveCurveID)
data.WriteUInt32(createProperties.MoveCurveId);
if (hasPositionalSoundKitID)
data.WriteUInt32(0);
if (hasAreaTriggerSphere)
{
data.WriteFloat(shape.SphereDatas.Radius);
@@ -1522,7 +1527,7 @@ namespace Game.Entities
BattlegroundMap bgMap = map.ToBattlegroundMap();
if (bgMap != null)
return (ZoneScript)bgMap.GetBG();
return (ZoneScript)bgMap.GetBattlegroundScript();
if (!map.IsBattlegroundOrArena())
{
@@ -233,7 +233,7 @@ namespace Game.Entities
{
return _heirlooms.ContainsKey(itemId);
}
public void UpgradeHeirloom(uint itemId, uint castItem)
{
Player player = _owner.GetPlayer();
@@ -386,12 +386,8 @@ namespace Game.Entities
_mounts[spellId] = flags;
// Mount condition only applies to using it, should still learn it.
if (mount.PlayerConditionID != 0)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mount.PlayerConditionID);
if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
return false;
}
if (!ConditionManager.IsPlayerMeetingCondition(player, mount.PlayerConditionID))
return false;
if (!learned)
{
@@ -859,7 +855,7 @@ namespace Game.Entities
} while (knownTransmogIllusions.NextRow());
}
_transmogIllusions = new(blocks);
// Static illusions known by every player
@@ -919,7 +915,7 @@ namespace Game.Entities
{
return transmogIllusionId < _transmogIllusions.Count && _transmogIllusions.Get((int)transmogIllusionId);
}
public bool HasToy(uint itemId) { return _toys.ContainsKey(itemId); }
public Dictionary<uint, ToyFlags> GetAccountToys() { return _toys; }
public Dictionary<uint, HeirloomData> GetAccountHeirlooms() { return _heirlooms; }
+1 -1
View File
@@ -457,7 +457,7 @@ namespace Game.Entities
case DuelCompleteType.Fled:
// if initiator and opponent are on the same team
// or initiator and opponent are not PvP enabled, forcibly stop attacking
if (GetTeam() == opponent.GetTeam())
if (GetEffectiveTeam() == opponent.GetEffectiveTeam())
{
AttackStop();
opponent.AttackStop();
+2 -4
View File
@@ -3612,10 +3612,8 @@ namespace Game.Entities
if (GetSession().GetCollectionMgr().HasTransmogIllusion(transmogIllusion.Id))
continue;
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(transmogIllusion.UnlockConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
continue;
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)transmogIllusion.UnlockConditionID))
continue;
GetSession().GetCollectionMgr().AddTransmogIllusion(transmogIllusion.Id);
}
+1 -1
View File
@@ -252,7 +252,7 @@ namespace Game.Entities
case 1:
return IsInSameRaidWith(p);
case 2:
return GetTeam() == p.GetTeam();
return GetEffectiveTeam() == p.GetEffectiveTeam();
case 3:
return false;
}
+5 -10
View File
@@ -2865,8 +2865,7 @@ namespace Game.Entities
var limitConditions = Global.DB2Mgr.GetItemLimitCategoryConditions(limitEntry.Id);
foreach (ItemLimitCategoryConditionRecord limitCondition in limitConditions)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(limitCondition.PlayerConditionID);
if (playerCondition == null || ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (ConditionManager.IsPlayerMeetingCondition(this, limitCondition.PlayerConditionID))
limit += (byte)limitCondition.AddQuantity;
}
@@ -3273,14 +3272,10 @@ namespace Game.Entities
return false;
}
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(crItem.PlayerConditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, crItem.PlayerConditionId))
{
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
{
SendEquipError(InventoryResult.ItemLocked);
return false;
}
SendEquipError(InventoryResult.ItemLocked);
return false;
}
// check current item amount if it limited
@@ -6130,7 +6125,7 @@ namespace Game.Entities
Guild guild = GetGuild();
if (guild != null)
guild.AddGuildNews(GuildNews.ItemLooted, GetGUID(), 0, item.itemid);
}
}
// if aeLooting then we must delay sending out item so that it appears properly stacked in chat
if (aeResult == null || newitem == null)
+1 -1
View File
@@ -370,7 +370,7 @@ namespace Game.Entities
var mapDifficultyConditions = Global.DB2Mgr.GetMapDifficultyConditions(mapDiff.Id);
foreach (var pair in mapDifficultyConditions)
{
if (!ConditionManager.IsPlayerMeetingCondition(this, pair.Item2))
if (!ConditionManager.IsPlayerMeetingCondition(this, pair.Item2.Id))
{
failedMapDifficultyXCondition = pair.Item1;
break;
+29 -18
View File
@@ -1174,10 +1174,8 @@ namespace Game.Entities
{
foreach (QuestRewardDisplaySpell displaySpell in quest.RewardDisplaySpell)
{
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
continue;
if (!ConditionManager.IsPlayerMeetingCondition(this, displaySpell.PlayerConditionId))
continue;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(displaySpell.SpellId, GetMap().GetDifficultyID());
Unit caster = this;
@@ -1588,7 +1586,7 @@ namespace Game.Entities
return true;
}
public bool SatisfyQuestReputation(Quest qInfo, bool msg)
public bool SatisfyQuestMinReputation(Quest qInfo, bool msg)
{
uint fIdMin = qInfo.RequiredMinRepFaction; //Min required rep
if (fIdMin != 0 && GetReputationMgr().GetReputation(fIdMin) < qInfo.RequiredMinRepValue)
@@ -1601,6 +1599,11 @@ namespace Game.Entities
return false;
}
return true;
}
public bool SatisfyQuestMaxReputation(Quest qInfo, bool msg)
{
uint fIdMax = qInfo.RequiredMaxRepFaction; //Max required rep
if (fIdMax != 0 && GetReputationMgr().GetReputation(fIdMax) >= qInfo.RequiredMaxRepValue)
{
@@ -1615,6 +1618,11 @@ namespace Game.Entities
return true;
}
bool SatisfyQuestReputation(Quest qInfo, bool msg)
{
return SatisfyQuestMinReputation(qInfo, msg) && SatisfyQuestMaxReputation(qInfo, msg);
}
public bool SatisfyQuestStatus(Quest qInfo, bool msg)
{
if (GetQuestStatus(qInfo.Id) == QuestStatus.Rewarded)
@@ -3297,21 +3305,24 @@ namespace Game.Entities
ObjectFieldData objMask = new();
GameObjectFieldData goMask = new();
if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())))
if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())) || gameObject.GetGoInfo().GetConditionID1() != 0)
objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
switch (gameObject.GetGoType())
else
{
case GameObjectTypes.QuestGiver:
case GameObjectTypes.Chest:
case GameObjectTypes.Goober:
case GameObjectTypes.Generic:
case GameObjectTypes.GatheringNode:
if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry()))
objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
break;
default:
break;
switch (gameObject.GetGoType())
{
case GameObjectTypes.QuestGiver:
case GameObjectTypes.Chest:
case GameObjectTypes.Generic:
case GameObjectTypes.SpellFocus:
case GameObjectTypes.Goober:
case GameObjectTypes.GatheringNode:
if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry()))
objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
break;
default:
break;
}
}
if (objMask.GetUpdateMask().IsAnySet() || goMask.GetUpdateMask().IsAnySet())
@@ -256,7 +256,7 @@ namespace Game.Entities
{
return CliDB.ChrSpecializationStorage.LookupByKey((uint)GetPrimarySpecialization());
}
public byte GetActiveTalentGroup() { return _specializationInfo.ActiveGroup; }
void SetActiveTalentGroup(byte group) { _specializationInfo.ActiveGroup = group; }
@@ -742,10 +742,8 @@ namespace Game.Entities
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
return TalentLearnResult.FailedUnknown;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(talentInfo.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
return TalentLearnResult.FailedCantDoThatRightNow;
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)talentInfo.PlayerConditionID))
return TalentLearnResult.FailedCantDoThatRightNow;
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talent != null)
+14 -44
View File
@@ -1327,11 +1327,8 @@ namespace Game.Entities
// Check award condition
if (currency.AwardConditionID != 0)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(currency.AwardConditionID);
if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)currency.AwardConditionID))
return;
}
bool isGainOnRefund = false;
@@ -2446,12 +2443,6 @@ namespace Game.Entities
// stop taxi flight at summon
FinishTaxiFlight();
// drop flag at summon
// this code can be reached only when GM is summoning player who carries flag, because player should be immune to summoning spells when he carries flag
Battleground bg = GetBattleground();
if (bg != null)
bg.EventPlayerDroppedFlag(this);
m_summon_expire = 0;
UpdateCriteria(CriteriaType.AcceptSummon, 1);
@@ -4250,13 +4241,6 @@ namespace Game.Entities
UpdateZone(newzone, newarea);
OutdoorPvPMgr.HandlePlayerResurrects(this, newzone);
if (InBattleground())
{
Battleground bg = GetBattleground();
if (bg != null)
bg.HandlePlayerResurrect(this);
}
// update visibility
UpdateObjectVisibility();
@@ -4454,22 +4438,14 @@ namespace Game.Entities
}
WorldSafeLocsEntry closestGrave = null;
// Special handle for Battlegroundmaps
Battleground bg = GetBattleground();
if (bg != null)
closestGrave = bg.GetClosestGraveyard(this);
var bf = BattleFieldMgr.GetBattlefieldToZoneId(GetMap(), GetZoneId());
if (bf != null)
closestGrave = bf.GetClosestGraveyard(this);
else
{
var bf = BattleFieldMgr.GetBattlefieldToZoneId(GetMap(), GetZoneId());
if (bf != null)
closestGrave = bf.GetClosestGraveyard(this);
else
{
InstanceScript instance = GetInstanceScript();
if (instance != null)
closestGrave = ObjectMgr.GetWorldSafeLoc(instance.GetEntranceLocation());
}
InstanceScript instance = GetInstanceScript();
if (instance != null)
closestGrave = ObjectMgr.GetWorldSafeLoc(instance.GetEntranceLocation());
}
if (closestGrave == null)
@@ -4985,12 +4961,7 @@ namespace Game.Entities
public bool MeetPlayerCondition(uint conditionId)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(conditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
return false;
return true;
return ConditionManager.IsPlayerMeetingCondition(this, conditionId);
}
bool IsInFriendlyArea()
@@ -5143,6 +5114,8 @@ namespace Game.Entities
return Team.Alliance;
case 1:
return Team.Horde;
case 2:
return Team.PandariaNeutral;
}
return Team.Alliance;
@@ -5157,10 +5130,10 @@ namespace Game.Entities
return BattleGroundTeamId.Neutral;
}
public Team GetTeam() { return m_team; }
public int GetTeamId() { return m_team == Team.Alliance ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde; }
public int GetTeamId() { return SharedConst.GetTeamIdForTeam(m_team); }
public Team GetEffectiveTeam() { return HasPlayerFlagEx(PlayerFlagsEx.MercenaryMode) ? (GetTeam() == Team.Alliance ? Team.Horde : Team.Alliance) : GetTeam(); }
public int GetEffectiveTeamId() { return GetEffectiveTeam() == Team.Alliance ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde; }
public Team GetEffectiveTeam() { return HasPlayerFlagEx(PlayerFlagsEx.MercenaryMode) ? SharedConst.GetOtherTeam(GetTeam()) : GetTeam(); }
public int GetEffectiveTeamId() { return SharedConst.GetTeamIdForTeam(GetEffectiveTeam()); }
//Money
public ulong GetMoney() { return m_activePlayerData.Coinage; }
@@ -6318,11 +6291,8 @@ namespace Game.Entities
// Check award condition
if (currencyRecord.AwardConditionID != 0)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(currencyRecord.AwardConditionID);
if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)currencyRecord.AwardConditionID))
continue;
}
SetupCurrency.Record record = new();
record.Type = currencyRecord.Id;
+36 -40
View File
@@ -363,7 +363,7 @@ namespace Game.Entities
break;
}
}
public virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, out float minDamage, out float maxDamage)
{
minDamage = 0f;
@@ -802,7 +802,7 @@ namespace Game.Entities
return damage;
}
// player or player's pet resilience (-1%)
uint GetDamageReduction(uint damage) { return GetCombatRatingDamageReduction(CombatRating.ResiliencePlayerDamage, 1.0f, 100.0f, damage); }
@@ -946,7 +946,7 @@ namespace Game.Entities
float chance = GetUnitCriticalChanceDone(attackType);
return victim.GetUnitCriticalChanceTaken(this, attackType, chance);
}
float GetUnitDodgeChance(WeaponAttackType attType, Unit victim)
{
int levelDiff = (int)(victim.GetLevelForTarget(this) - GetLevelForTarget(victim));
@@ -1085,7 +1085,7 @@ namespace Game.Entities
}
return Math.Max(resistMech, 0);
}
public void ApplyModManaCostMultiplier(float manaCostMultiplier, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ManaCostMultiplier), manaCostMultiplier, apply); }
public void ApplyModManaCostModifier(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ManaCostModifier, (int)school), mod, apply); }
@@ -1545,34 +1545,34 @@ namespace Game.Entities
case CombatRating.HasteMelee:
case CombatRating.HasteRanged:
case CombatRating.HasteSpell:
{
// explicit affected values
float multiplier = GetRatingMultiplier(cr);
float oldVal = ApplyRatingDiminishing(cr, oldRating * multiplier);
float newVal = ApplyRatingDiminishing(cr, amount * multiplier);
switch (cr)
{
// explicit affected values
float multiplier = GetRatingMultiplier(cr);
float oldVal = ApplyRatingDiminishing(cr, oldRating * multiplier);
float newVal = ApplyRatingDiminishing(cr, amount * multiplier);
switch (cr)
{
case CombatRating.HasteMelee:
ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, newVal, true);
ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, newVal, true);
if (GetClass() == Class.Deathknight)
UpdateAllRunesRegen();
break;
case CombatRating.HasteRanged:
ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, newVal, true);
break;
case CombatRating.HasteSpell:
ApplyCastTimePercentMod(oldVal, false);
ApplyCastTimePercentMod(newVal, true);
break;
default:
break;
}
break;
case CombatRating.HasteMelee:
ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, newVal, true);
ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, newVal, true);
if (GetClass() == Class.Deathknight)
UpdateAllRunesRegen();
break;
case CombatRating.HasteRanged:
ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, oldVal, false);
ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, newVal, true);
break;
case CombatRating.HasteSpell:
ApplyCastTimePercentMod(oldVal, false);
ApplyCastTimePercentMod(newVal, true);
break;
default:
break;
}
break;
}
case CombatRating.Expertise:
if (affectStats)
{
@@ -1667,14 +1667,10 @@ namespace Game.Entities
continue;
}
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(corruptionEffect.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)corruptionEffect.PlayerConditionID))
{
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
{
RemoveAura(corruptionEffect.Aura);
continue;
}
RemoveAura(corruptionEffect.Aura);
continue;
}
CastSpell(this, corruptionEffect.Aura, true);
@@ -1766,7 +1762,7 @@ namespace Game.Entities
}
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), value);
}
float[] dodge_cap =
{
65.631440f, // Warrior
@@ -1997,7 +1993,7 @@ namespace Game.Entities
return Stats.Intellect;
}
public override void UpdateMaxHealth()
{
UnitMods unitMod = UnitMods.Health;
@@ -2112,7 +2108,7 @@ namespace Game.Entities
return base.GetCreatePowerValue(power);
}
public override bool UpdateStats(Stats stat)
{
return true;
+10 -6
View File
@@ -154,14 +154,18 @@ namespace Game.Entities
foreach (var edge in path)
{
var To = m_nodesByVertex[(int)edge.To];
TaxiNodeFlags requireFlag = (player.GetTeam() == Team.Alliance) ? TaxiNodeFlags.ShowOnAllianceMap : TaxiNodeFlags.ShowOnHordeMap;
if (!To.HasFlag(requireFlag))
bool isVisibleForFaction = player.GetTeam() switch
{
Team.Horde => To.HasFlag(TaxiNodeFlags.ShowOnHordeMap),
Team.Alliance => To.HasFlag(TaxiNodeFlags.ShowOnAllianceMap),
_ => false
};
if (!isVisibleForFaction)
continue;
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(To.ConditionID);
if (condition != null)
if (!ConditionManager.IsPlayerMeetingCondition(player, condition))
continue;
if (!ConditionManager.IsPlayerMeetingCondition(player, To.ConditionID))
continue;
shortestPath.Add(GetNodeIDFromVertexID(edge.To));
}
+2 -7
View File
@@ -868,13 +868,8 @@ namespace Game.Entities
continue;
Player thisPlayer = ToPlayer();
if (thisPlayer != null)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountCapability.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(thisPlayer, playerCondition))
continue;
}
if (thisPlayer != null && !ConditionManager.IsPlayerMeetingCondition(thisPlayer, (uint)mountCapability.PlayerConditionID))
continue;
return mountCapability;
}
+1 -2
View File
@@ -110,8 +110,7 @@ namespace Game.Entities
if (player.IsQuestRewarded(vignette.Data.VisibleTrackingQuestID))
return false;
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(vignette.Data.PlayerConditionID);
if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(player, vignette.Data.PlayerConditionID))
return false;
return true;
-5
View File
@@ -672,11 +672,6 @@ namespace Game.Entities
Player player = Passenger.ToPlayer();
if (player != null)
{
// drop flag
Battleground bg = player.GetBattleground();
if (bg != null)
bg.EventPlayerDroppedFlag(player);
player.StopCastingCharm();
player.StopCastingBindSight();
player.SendOnCancelExpectedVehicleRideAura();
+60 -5
View File
@@ -158,7 +158,7 @@ namespace Game
{
if (value == null)
value = "";
data[(int)locale] = value;
}
public static void GetLocaleString(StringArray data, Locale locale, ref string value)
@@ -4118,6 +4118,10 @@ namespace Game
got.BarberChair.SitAnimKit = 0;
}
break;
case GameObjectTypes.DestructibleBuilding:
if (got.DestructibleBuilding.HealthRec != 0 && GetDestructibleHitpoint(got.DestructibleBuilding.HealthRec) == null)
Log.outError(LogFilter.Sql, $"GameObject (Entry: {entry}) Has non existing Destructible Hitpoint Record {got.DestructibleBuilding.HealthRec}.");
break;
case GameObjectTypes.GarrisonBuilding:
{
int transportMap = got.GarrisonBuilding.SpawnMap;
@@ -4647,6 +4651,12 @@ namespace Game
continue;
}
case GameObjectTypes.SpellFocus:
{
if (pair.Value.SpellFocus.questID > 0) //quests objects
break;
continue;
}
case GameObjectTypes.Goober:
{
if (pair.Value.Goober.questID > 0) //quests objects
@@ -4673,6 +4683,33 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} GameObjects for quests in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
}
public void LoadDestructibleHitpoints()
{
uint oldMSTime = Time.GetMSTime();
_destructibleHitpointStorage.Clear(); // need for reload case
// 0 1 2
SQLResult result = DB.World.Query("SELECT Id, IntactNumHits, DamagedNumHits FROM destructible_hitpoint");
if (result.IsEmpty())
return;
do
{
uint id = result.Read<uint>(0);
DestructibleHitpoint data = new();
data.Id = id;
data.IntactNumHits = result.Read<uint>(1);
data.DamagedNumHits = result.Read<uint>(2);
_destructibleHitpointStorage.Add(id, data);
} while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, $"Loaded {_destructibleHitpointStorage.Count} destructible_hitpoint records in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}
public void AddGameObjectToGrid(GameObjectData data)
{
AddSpawnDataToGrid(data);
@@ -4833,6 +4870,11 @@ namespace Game
return difficulties;
}
public DestructibleHitpoint GetDestructibleHitpoint(uint entry)
{
return _destructibleHitpointStorage.LookupByKey(entry);
}
//Items
public void LoadItemTemplates()
{
@@ -5172,8 +5214,11 @@ namespace Game
if (vItem.PlayerConditionId != 0 && !CliDB.PlayerConditionStorage.ContainsKey(vItem.PlayerConditionId))
{
Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` has Item (Entry: {0}) with invalid PlayerConditionId ({1}) for vendor ({2}), ignore", vItem.item, vItem.PlayerConditionId, vendorentry);
return false;
if (!Global.ConditionMgr.HasConditionsForNotGroupedEntry(ConditionSourceType.PlayerCondition, vItem.PlayerConditionId))
{
Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` has Item (Entry: {0}) with serverside PlayerConditionId ({1}) for vendor ({2}) without conditions, ignore", vItem.item, vItem.PlayerConditionId, vendorentry);
return false;
}
}
if (vItem.ExtendedCost != 0 && !CliDB.ItemExtendedCostStorage.ContainsKey(vItem.ExtendedCost))
@@ -10426,10 +10471,19 @@ namespace Game
float dist = 10000;
uint id = 0;
TaxiNodeFlags requireFlag = (team == Team.Alliance) ? TaxiNodeFlags.ShowOnAllianceMap : TaxiNodeFlags.ShowOnHordeMap;
var isVisibleForFaction = (TaxiNodesRecord node) =>
{
return team switch
{
Team.Horde => node.HasFlag(TaxiNodeFlags.ShowOnHordeMap),
Team.Alliance => node.HasFlag(TaxiNodeFlags.ShowOnAllianceMap),
_ => false
};
};
foreach (var node in CliDB.TaxiNodesStorage.Values)
{
if (node.ContinentID != mapid || !node.HasFlag(requireFlag) || node.HasFlag(TaxiNodeFlags.IgnoreForFindNearest))
if (node.ContinentID != mapid || !isVisibleForFaction(node) || node.HasFlag(TaxiNodeFlags.IgnoreForFindNearest))
continue;
uint field = (node.Id - 1) / 8;
@@ -10890,6 +10944,7 @@ namespace Game
Dictionary<ulong, GameObjectAddon> _gameObjectAddonStorage = new();
MultiMap<uint, uint> _gameObjectQuestItemStorage = new();
List<uint> _gameObjectForQuestStorage = new();
Dictionary<uint, DestructibleHitpoint> _destructibleHitpointStorage = new();
//Item
Dictionary<uint, ItemTemplate> ItemTemplateStorage = new();
+1 -3
View File
@@ -672,15 +672,13 @@ namespace Game.Guilds
SendCommandResult(session, GuildCommandType.RemovePlayer, GuildCommandError.RankTooHigh_S, name);
else
{
DeleteMember(null, guid, false, true);
_LogEvent(GuildEventLogTypes.UninvitePlayer, player.GetGUID().GetCounter(), guid.GetCounter());
Player pMember = Global.ObjAccessor.FindConnectedPlayer(guid);
SendEventPlayerLeft(pMember, player, true);
SendCommandResult(session, GuildCommandType.RemovePlayer, GuildCommandError.Success, name);
// After call to DeleteMember pointer to member becomes invalid
DeleteMember(null, guid, false, true);
}
}
}
+2 -4
View File
@@ -161,10 +161,8 @@ namespace Game
if (artifactAppearanceSet == null || artifactAppearanceSet.ArtifactID != artifact.GetTemplate().GetArtifactID())
return;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactAppearance.UnlockPlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition))
return;
if (!ConditionManager.IsPlayerMeetingCondition(_player, artifactAppearance.UnlockPlayerConditionID))
return;
artifact.SetAppearanceModId(artifactAppearance.ItemAppearanceModifierID);
artifact.SetModifier(ItemModifier.ArtifactAppearanceId, artifactAppearance.Id);
+25 -6
View File
@@ -36,7 +36,7 @@ namespace Game
realmListTicket.Ticket.WriteCString("WorldserverRealmListTicket");
SendPacket(realmListTicket);
}
}
public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, IMessage response)
{
@@ -52,7 +52,7 @@ namespace Game
SendPacket(bnetResponse);
}
public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, BattlenetRpcErrorCode status)
public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, BattlenetRpcErrorCode status)
{
Response bnetResponse = new();
bnetResponse.BnetStatus = status;
@@ -63,16 +63,35 @@ namespace Game
SendPacket(bnetResponse);
}
public void SendBattlenetRequest(uint serviceHash, uint methodId, IMessage request, Action<CodedInputStream> callback)
public void SendBattlenetRequest(OriginalHash serviceHash, uint methodId, IMessage request, bool client, bool server, Action<CodedInputStream> callback)
{
_battlenetResponseCallbacks[_battlenetRequestToken] = callback;
SendBattlenetRequest(serviceHash, methodId, request);
SendBattlenetRequest(serviceHash, methodId, request, client, server);
}
public void SendBattlenetRequest(uint serviceHash, uint methodId, IMessage request)
public void SendBattlenetRequest(NameHash serviceHash, uint methodId, IMessage request, bool client, bool server, Action<CodedInputStream> callback)
{
_battlenetResponseCallbacks[_battlenetRequestToken] = callback;
SendBattlenetRequest(serviceHash, methodId, request, client, server);
}
public void SendBattlenetRequest(OriginalHash serviceHash, uint methodId, IMessage request, bool client = true, bool server = true)
{
Notification notification = new();
notification.Method.Type = MathFunctions.MakePair64(methodId, serviceHash);
notification.Method.Type = MathFunctions.MakePair64(methodId | (client ? 0x40000000 : 0u) | (server ? 0x80000000 : 0u), (uint)serviceHash);
notification.Method.ObjectId = 1;
notification.Method.Token = _battlenetRequestToken++;
if (request.CalculateSize() != 0)
notification.Data.WriteBytes(request.ToByteArray());
SendPacket(notification);
}
public void SendBattlenetRequest(NameHash serviceHash, uint methodId, IMessage request, bool client = true, bool server = true)
{
Notification notification = new();
notification.Method.Type = MathFunctions.MakePair64(methodId | (client ? 0x40000000 : 0u) | (server ? 0x80000000 : 0u), (uint)serviceHash);
notification.Method.ObjectId = 1;
notification.Method.Token = _battlenetRequestToken++;
+4 -8
View File
@@ -1394,10 +1394,8 @@ namespace Game
if (!MeetsChrCustomizationReq(req, (Race)packet.CustomizedRace, _player.GetClass(), false, packet.Customizations))
return;
var condition = CliDB.PlayerConditionStorage.LookupByKey(conditionalChrModel.PlayerConditionID);
if (condition != null)
if (!ConditionManager.IsPlayerMeetingCondition(_player, condition))
return;
if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)conditionalChrModel.PlayerConditionID))
return;
}
if (!ValidateAppearance(_player.GetRace(), _player.GetClass(), (Gender)packet.NewSex, packet.Customizations))
@@ -1632,10 +1630,8 @@ namespace Game
if (illusion.ItemVisual == 0 || !illusion.HasFlag(SpellItemEnchantmentFlags.AllowTransmog))
return false;
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogUseConditionID);
if (condition != null)
if (!ConditionManager.IsPlayerMeetingCondition(_player, condition))
return false;
if (!ConditionManager.IsPlayerMeetingCondition(_player, illusion.TransmogUseConditionID))
return false;
if (illusion.ScalingClassRestricted > 0 && illusion.ScalingClassRestricted != (byte)_player.GetClass())
return false;
+2 -7
View File
@@ -251,9 +251,6 @@ namespace Game
return;
}
Battleground bg = player.GetBattleground();
if (bg != null)
bg.HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered);
OutdoorPvP pvp = player.GetOutdoorPvP();
if (pvp != null)
@@ -452,10 +449,8 @@ namespace Game
UISplashScreenRecord splashScreen = null;
foreach (var itr in CliDB.UISplashScreenStorage.Values)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(itr.CharLevelConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition))
continue;
if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)itr.CharLevelConditionID))
continue;
splashScreen = itr;
}
+1 -2
View File
@@ -756,8 +756,7 @@ namespace Game
// far teleport case
if (GetPlayer().GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Flight)
{
FlightPathMovementGenerator flight = GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() as FlightPathMovementGenerator;
if (flight != null)
if (GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() is FlightPathMovementGenerator flight)
{
bool shouldTeleport = curDestNode != null && curDestNode.ContinentID != GetPlayer().GetMapId();
if (!shouldTeleport)
+2 -4
View File
@@ -440,10 +440,8 @@ namespace Game
VendorItemPkt item = new();
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(vendorItem.PlayerConditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition))
item.PlayerConditionFailed = (int)playerCondition.Id;
if (!ConditionManager.IsPlayerMeetingCondition(_player, vendorItem.PlayerConditionId))
item.PlayerConditionFailed = (int)vendorItem.PlayerConditionId;
if (vendorItem.Type == ItemVendorType.Item)
{
+8 -5
View File
@@ -348,10 +348,6 @@ namespace Game
{
if (GetPlayer().CanRewardQuest(quest, packet.Choice.LootItemType, packet.Choice.Item.ItemID, true)) // Then check if player can receive the reward item (if inventory is not full, if player doesn't have too many unique items, and so on). If not, the client will close the gossip window
{
Battleground bg = _player.GetBattleground();
if (bg != null)
bg.HandleQuestComplete(packet.QuestID, _player);
GetPlayer().RewardQuest(quest, packet.Choice.LootItemType, packet.Choice.Item.ItemID, obj);
}
}
@@ -650,13 +646,20 @@ namespace Game
continue;
}
if (!receiver.SatisfyQuestReputation(quest, false))
if (!receiver.SatisfyQuestMinReputation(quest, false))
{
sender.SendPushToPartyResponse(receiver, QuestPushReason.LowFaction);
receiver.SendPushToPartyResponse(sender, QuestPushReason.LowFactionToRecipient, quest);
continue;
}
if (!receiver.SatisfyQuestMaxReputation(quest, false))
{
sender.SendPushToPartyResponse(receiver, QuestPushReason.HighFaction);
receiver.SendPushToPartyResponse(sender, QuestPushReason.HighFactionToRecipient, quest);
continue;
}
if (!receiver.SatisfyQuestDependentQuests(quest, false))
{
sender.SendPushToPartyResponse(receiver, QuestPushReason.Prerequisite);
+2 -11
View File
@@ -191,15 +191,7 @@ namespace Game
var mountDisplays = Global.DB2Mgr.GetMountDisplays(mount.Id);
if (mountDisplays != null)
{
List<MountXDisplayRecord> usableDisplays = mountDisplays.Where(mountDisplay =>
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID);
if (playerCondition != null)
return ConditionManager.IsPlayerMeetingCondition(GetPlayer(), playerCondition);
return true;
}).ToList();
List<MountXDisplayRecord> usableDisplays = mountDisplays.Where(mountDisplay => ConditionManager.IsPlayerMeetingCondition(GetPlayer(), mountDisplay.PlayerConditionID)).ToList();
if (!usableDisplays.Empty())
preferredMountDisplay = usableDisplays.SelectRandom().CreatureDisplayInfoID;
}
@@ -221,8 +213,7 @@ namespace Game
[WorldPacketHandler(ClientOpcodes.TaxiRequestEarlyLanding, Processing = PacketProcessing.ThreadSafe)]
void HandleTaxiRequestEarlyLanding(TaxiRequestEarlyLanding taxiRequestEarlyLanding)
{
FlightPathMovementGenerator flight = GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() as FlightPathMovementGenerator;
if (flight != null)
if (GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() is FlightPathMovementGenerator flight)
{
if (GetPlayer().m_taxi.RequestEarlyLanding())
{
@@ -129,14 +129,10 @@ namespace Game
return;
}
var condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.UnlockConditionID);
if (condition != null)
if (!ConditionManager.IsPlayerMeetingCondition(player, (uint)illusion.UnlockConditionID))
{
if (!ConditionManager.IsPlayerMeetingCondition(player, condition))
{
Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID);
return;
}
Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID);
return;
}
illusionItems[itemTransmogrified] = (uint)transmogItem.SpellItemEnchantmentID;
+45 -12
View File
@@ -60,17 +60,10 @@ namespace Game.Maps
m_terrain.LoadMMapInstance(GetId(), GetInstanceId());
_worldStateValues = Global.WorldStateMgr.GetInitialWorldStatesForMap(this);
Global.OutdoorPvPMgr.CreateOutdoorPvPForMap(this);
Global.BattleFieldMgr.CreateBattlefieldsForMap(this);
Global.ScriptMgr.OnCreateMap(this);
}
public void Dispose()
{
Global.ScriptMgr.OnDestroyMap(this);
// Delete all waiting spawns
// This doesn't delete from database.
UnloadAllRespawnInfos();
@@ -86,9 +79,6 @@ namespace Game.Maps
if (!m_scriptSchedule.Empty())
Global.MapMgr.DecreaseScheduledScriptCount((uint)m_scriptSchedule.Count);
Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(this);
Global.BattleFieldMgr.DestroyBattlefieldsForMap(this);
m_terrain.UnloadMMapInstance(GetId(), GetInstanceId());
}
@@ -5273,6 +5263,10 @@ namespace Game.Maps
public class BattlegroundMap : Map
{
Battleground m_bg;
BattlegroundScript _battlegroundScript;
uint _scriptId;
public BattlegroundMap(uint id, uint expiry, uint InstanceId, Difficulty spawnMode)
: base(id, expiry, InstanceId, spawnMode)
{
@@ -5285,6 +5279,37 @@ namespace Game.Maps
m_VisibilityNotifyPeriod = IsBattleArena() ? Global.WorldMgr.GetVisibilityNotifyPeriodInArenas() : Global.WorldMgr.GetVisibilityNotifyPeriodInBG();
}
string GetScriptName()
{
return Global.ObjectMgr.GetScriptName(_scriptId);
}
public void InitScriptData()
{
if (_battlegroundScript != null)
return;
Cypher.Assert(GetBG() != null, "Battleground not set yet!");
BattlegroundScriptTemplate scriptTemplate = Global.BattlegroundMgr.FindBattlegroundScriptTemplate(GetId(), GetBG().GetTypeID());
if (scriptTemplate != null)
{
_scriptId = scriptTemplate.ScriptId;
_battlegroundScript = Global.ScriptMgr.CreateBattlegroundData(this);
}
// Make sure every battleground has a default script
if (_battlegroundScript == null)
{
if (IsBattleArena())
_battlegroundScript = new ArenaScript(this);
else
_battlegroundScript = new BattlegroundScript(this);
}
_battlegroundScript.OnInit();
}
public override TransferAbortParams CannotEnter(Player player)
{
if (player.GetMap() == this)
@@ -5327,10 +5352,18 @@ namespace Game.Maps
player.TeleportTo(player.GetBattlegroundEntryPoint());
}
public override void Update(uint diff)
{
base.Update(diff);
_battlegroundScript.OnUpdate(diff);
}
public Battleground GetBG() { return m_bg; }
public void SetBG(Battleground bg) { m_bg = bg; }
Battleground m_bg;
public uint GetScriptId() { return _scriptId; }
public BattlegroundScript GetBattlegroundScript() { return _battlegroundScript; }
}
public class TransferAbortParams
@@ -5396,7 +5429,7 @@ namespace Game.Maps
public float FloorZ;
public bool outdoors = true;
public ZLiquidStatus LiquidStatus;
public WmoLocation? wmoLocation;
public WmoLocation wmoLocation;
public LiquidData LiquidInfo;
}
+22 -5
View File
@@ -99,6 +99,7 @@ namespace Game.Entities
Cypher.Assert(map.IsBattlegroundOrArena());
map.SetBG(bg);
bg.SetBgMap(map);
map.InitScriptData();
map.InitSpawnGroupState();
if (WorldConfig.GetBoolValue(WorldCfg.BattlegroundMapLoadGrids))
@@ -198,7 +199,7 @@ namespace Game.Entities
if (map == null)
{
map = CreateInstance(mapId, newInstanceId, instanceLock, difficulty, player.GetTeamId(), group);
map = CreateInstance(mapId, newInstanceId, instanceLock, difficulty, SharedConst.GetTeamIdForTeam(Global.CharacterCacheStorage.GetCharacterTeamByGuid(instanceOwnerGuid)), group);
if (group != null)
group.SetRecentInstance(mapId, instanceOwnerGuid, newInstanceId);
else
@@ -224,8 +225,14 @@ namespace Game.Entities
}
if (map != null)
{
i_maps[(map.GetId(), map.GetInstanceId())] = map;
Global.ScriptMgr.OnCreateMap(map);
Global.OutdoorPvPMgr.CreateOutdoorPvPForMap(map);
Global.BattleFieldMgr.CreateBattlefieldsForMap(map);
}
return map;
}
}
@@ -320,6 +327,10 @@ namespace Game.Entities
map.UnloadAll();
Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(map);
Global.BattleFieldMgr.DestroyBattlefieldsForMap(map);
Global.ScriptMgr.OnDestroyMap(map);
// Free up the instance id and allow it to be reused for normal dungeons, bgs and arenas
if (map.IsBattlegroundOrArena() || (map.IsDungeon() && !map.GetMapDifficulty().HasResetSchedule()))
FreeInstanceId(map.GetInstanceId());
@@ -337,11 +348,17 @@ namespace Game.Entities
public void UnloadAll()
{
// first unload maps
foreach (var pair in i_maps)
pair.Value.UnloadAll();
foreach (var (_, map) in i_maps)
{
map.UnloadAll();
foreach (var pair in i_maps)
pair.Value.Dispose();
Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(map);
Global.BattleFieldMgr.DestroyBattlefieldsForMap(map);
Global.ScriptMgr.OnDestroyMap(map);
}
foreach (var (_, map) in i_maps)
map.Dispose();
i_maps.Clear();
+3 -2
View File
@@ -9,6 +9,9 @@ namespace Game.Maps
{
public class ZoneScript
{
protected EventMap _events = new();
protected TaskScheduler _scheduler = new();
public virtual void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null)
{
if (source != null)
@@ -48,8 +51,6 @@ namespace Game.Maps
public virtual bool CanCaptureFlag(AreaTrigger areaTrigger, Player player) { return false; }
public virtual void OnCaptureFlag(AreaTrigger areaTrigger, Player player) { }
protected EventMap _events = new();
}
public class ControlZoneHandler
@@ -243,8 +243,7 @@ namespace Game.Movement
if (target.GetMotionMaster().GetCurrentMovementGeneratorType() != MovementGeneratorType.Chase)
return false;
ChaseMovementGenerator movement = target.GetMotionMaster().GetCurrentMovementGenerator() as ChaseMovementGenerator;
if (movement != null)
if (target.GetMotionMaster().GetCurrentMovementGenerator() is ChaseMovementGenerator movement)
return movement.GetTarget() == owner;
return false;
+1 -2
View File
@@ -148,8 +148,7 @@ namespace Game.Movement
{
case MovementGeneratorType.Chase:
case MovementGeneratorType.Follow:
var followInformation = movement as FollowMovementGenerator;
if (followInformation != null)
if (movement is FollowMovementGenerator followInformation)
{
Unit target = followInformation.GetTarget();
if (target != null)
@@ -19,6 +19,7 @@ namespace Game.Networking.Packets
public AuctionHouseFilterMask Filters;
public byte[] KnownPets;
public sbyte MaxPetLevel;
public uint Unused1026;
public AddOnInfo? TaintedBy;
public string Name;
public Array<AuctionListFilterClass> ItemClassFilters = new(7);
@@ -37,6 +38,7 @@ namespace Game.Networking.Packets
Filters = (AuctionHouseFilterMask)_worldPacket.ReadUInt32();
uint knownPetSize = _worldPacket.ReadUInt32();
MaxPetLevel = _worldPacket.ReadInt8();
Unused1026 = _worldPacket.ReadUInt32();
uint sizeLimit = CliDB.BattlePetSpeciesStorage.GetNumRows() / 8 + 1;
if (knownPetSize >= sizeLimit)
@@ -326,12 +326,6 @@ namespace Game.Networking.Packets
public struct RaceLimitDisableInfo
{
enum blah
{
Server,
Level
}
public int RaceID;
public int BlockReason;
@@ -386,6 +380,7 @@ namespace Game.Networking.Packets
bool hasTemplateSet = _worldPacket.HasBit();
CreateInfo.IsTrialBoost = _worldPacket.HasBit();
CreateInfo.UseNPE = _worldPacket.HasBit();
CreateInfo.Unused1026 = _worldPacket.HasBit();
CreateInfo.RaceId = (Race)_worldPacket.ReadUInt8();
CreateInfo.ClassId = (Class)_worldPacket.ReadUInt8();
@@ -1144,6 +1139,7 @@ namespace Game.Networking.Packets
public uint? TemplateSet;
public bool IsTrialBoost;
public bool UseNPE;
public bool Unused1026;
public string Name;
// Server side data
@@ -43,7 +43,7 @@ namespace Game.Networking.Packets
public override void Read()
{
PlayerGuid = _worldPacket.ReadPackedGuid();
DataType = (AccountDataTypes)_worldPacket.ReadBits<uint>(4);
DataType = (AccountDataTypes)_worldPacket.ReadInt32();
}
public ObjectGuid PlayerGuid;
@@ -56,10 +56,10 @@ namespace Game.Networking.Packets
public override void Write()
{
_worldPacket.WritePackedGuid(Player);
_worldPacket.WriteInt64(Time);
_worldPacket.WriteUInt32(Size);
_worldPacket.WriteBits(DataType, 4);
_worldPacket.WritePackedGuid(Player);
_worldPacket.WriteInt32((int)DataType);
if (CompressedData == null)
_worldPacket.WriteUInt32(0);
@@ -84,10 +84,10 @@ namespace Game.Networking.Packets
public override void Read()
{
PlayerGuid = _worldPacket.ReadPackedGuid();
Time = _worldPacket.ReadInt64();
Size = _worldPacket.ReadUInt32();
DataType = (AccountDataTypes)_worldPacket.ReadBits<uint>(4);
PlayerGuid = _worldPacket.ReadPackedGuid();
DataType = (AccountDataTypes)_worldPacket.ReadInt32();
uint compressedSize = _worldPacket.ReadUInt32();
if (compressedSize != 0)
@@ -93,13 +93,22 @@ namespace Game.Networking.Packets
Standing = standing;
}
public FactionStandingData(int index, int standing, int factionId)
{
Index = index;
Standing = standing;
FactionID = factionId;
}
public void Write(WorldPacket data)
{
data.WriteInt32(Index);
data.WriteInt32(Standing);
data.WriteInt32(FactionID);
}
int Index;
int Standing;
int FactionID;
}
}
@@ -65,9 +65,11 @@ namespace Game.Networking.Packets
public override void Read()
{
SceneInstanceID = _worldPacket.ReadUInt32();
TimePassed = _worldPacket.ReadInt32();
}
public uint SceneInstanceID;
public int TimePassed;
}
class ScenePlaybackCanceled : ClientPacket
@@ -77,8 +79,10 @@ namespace Game.Networking.Packets
public override void Read()
{
SceneInstanceID = _worldPacket.ReadUInt32();
TimePassed = _worldPacket.ReadInt32();
}
public uint SceneInstanceID;
public int TimePassed;
}
}
@@ -264,7 +264,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled);
_worldPacket.WriteBit(false); // unused, 10.0.2
_worldPacket.WriteBit(IsBoostEnabled);
_worldPacket.WriteBit(TrialBoostEnabled);
_worldPacket.WriteBit(TokenBalanceEnabled);
_worldPacket.WriteBit(LiveRegionCharacterListEnabled);
@@ -275,7 +275,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(Unknown901CheckoutRelated);
_worldPacket.WriteBit(false); // unused, 10.0.2
_worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue);
_worldPacket.WriteBit(false); // unused, 10.0.2
_worldPacket.WriteBit(IsNameReservationEnabled);
_worldPacket.WriteBit(LaunchETA.HasValue);
_worldPacket.WriteBit(AddonsDisabled);
_worldPacket.WriteBit(Unused1000);
@@ -309,6 +309,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds);
_worldPacket.WriteInt32(DebugTimeEvents.Count);
_worldPacket.WriteInt32(Unused1007);
_worldPacket.WriteUInt32(EventRealmQueues);
if (LaunchETA.HasValue)
_worldPacket.WriteInt32(LaunchETA.Value);
@@ -336,6 +337,7 @@ namespace Game.Networking.Packets
public bool IsExpansionPreorderInStore; // NYI
public bool KioskModeEnabled; // NYI
public bool CompetitiveModeEnabled; // NYI
public bool IsBoostEnabled; // classic only
public bool TrialBoostEnabled; // NYI
public bool TokenBalanceEnabled; // NYI
public bool LiveRegionCharacterListEnabled; // NYI
@@ -343,6 +345,7 @@ namespace Game.Networking.Packets
public bool LiveRegionAccountCopyEnabled; // NYI
public bool LiveRegionKeyBindingsCopyEnabled;
public bool Unknown901CheckoutRelated; // NYI
public bool IsNameReservationEnabled; // classic only
public bool AddonsDisabled;
public bool Unused1000;
public bool AccountSaveDataExportEnabled;
@@ -366,6 +369,7 @@ namespace Game.Networking.Packets
public int? LaunchETA;
public List<DebugTimeEventInfo> DebugTimeEvents = new();
public int Unused1007;
public uint EventRealmQueues;
public string RealmHiddenAlert;
}
+33 -38
View File
@@ -9,6 +9,7 @@ using Framework.Networking;
using Game.Networking.Packets;
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Game.Networking
{
@@ -75,12 +76,12 @@ namespace Game.Networking
PreparedStatement stmt = LoginDatabase.GetPreparedStatement(LoginStatements.SEL_IP_INFO);
stmt.AddValue(0, ip_address);
stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().Address.GetAddressBytes(), 0));
stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().GetAddressBytes(), 0));
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback));
}
void CheckIpCallback(SQLResult result)
async void CheckIpCallback(SQLResult result)
{
if (!result.IsEmpty())
{
@@ -109,24 +110,18 @@ namespace Game.Networking
ByteBuffer packet = new();
packet.WriteString(ServerConnectionInitialize);
packet.WriteString("\n");
AsyncWrite(packet.GetData());
await AsyncWrite(packet.GetData());
}
void InitializeHandler(SocketAsyncEventArgs args)
async Task InitializeHandler(byte[] data, int receivedLength)
{
if (args.SocketError != SocketError.Success)
{
CloseSocket();
return;
}
if (args.BytesTransferred > 0)
if (receivedLength > 0)
{
if (_packetBuffer.GetRemainingSpace() > 0)
{
// need to receive the header
int readHeaderSize = Math.Min(args.BytesTransferred, _packetBuffer.GetRemainingSpace());
_packetBuffer.Write(args.Buffer, 0, readHeaderSize);
int readHeaderSize = Math.Min(receivedLength, _packetBuffer.GetRemainingSpace());
_packetBuffer.Write(data, 0, readHeaderSize);
if (_packetBuffer.GetRemainingSpace() > 0)
{
@@ -165,25 +160,25 @@ namespace Game.Networking
_packetBuffer.Resize(0);
_packetBuffer.Reset();
HandleSendAuthSession();
AsyncRead();
await AsyncRead();
return;
}
}
}
public override void ReadHandler(SocketAsyncEventArgs args)
public async override void ReadHandler(byte[] data, int receivedLength)
{
if (!IsOpen())
return;
int currentReadIndex = 0;
while (currentReadIndex < args.BytesTransferred)
while (currentReadIndex < receivedLength)
{
if (_headerBuffer.GetRemainingSpace() > 0)
{
// need to receive the header
int readHeaderSize = Math.Min(args.BytesTransferred - currentReadIndex, _headerBuffer.GetRemainingSpace());
_headerBuffer.Write(args.Buffer, currentReadIndex, readHeaderSize);
int readHeaderSize = Math.Min(receivedLength - currentReadIndex, _headerBuffer.GetRemainingSpace());
_headerBuffer.Write(data, currentReadIndex, readHeaderSize);
currentReadIndex += readHeaderSize;
if (_headerBuffer.GetRemainingSpace() > 0)
@@ -201,8 +196,8 @@ namespace Game.Networking
if (_packetBuffer.GetRemainingSpace() > 0)
{
// need more data in the payload
int readDataSize = Math.Min(args.BytesTransferred - currentReadIndex, _packetBuffer.GetRemainingSpace());
_packetBuffer.Write(args.Buffer, currentReadIndex, readDataSize);
int readDataSize = Math.Min(receivedLength - currentReadIndex, _packetBuffer.GetRemainingSpace());
_packetBuffer.Write(data, currentReadIndex, readDataSize);
currentReadIndex += readDataSize;
if (_packetBuffer.GetRemainingSpace() > 0)
@@ -221,7 +216,7 @@ namespace Game.Networking
}
}
AsyncRead();
await AsyncRead();
}
bool ReadHeader()
@@ -254,7 +249,7 @@ namespace Game.Networking
return ReadDataHandlerResult.Error;
}
PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpAddress(), _connectType, true);
PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpEndPoint(), _connectType, true);
ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode();
@@ -346,7 +341,7 @@ namespace Game.Networking
return ReadDataHandlerResult.Ok;
}
public void SendPacket(ServerPacket packet)
public async void SendPacket(ServerPacket packet)
{
if (!IsOpen())
return;
@@ -356,7 +351,7 @@ namespace Game.Networking
var data = packet.GetData();
ServerOpcodes opcode = packet.GetOpcode();
PacketLog.Write(data, (uint)opcode, GetRemoteIpAddress(), _connectType, false);
PacketLog.Write(data, (uint)opcode, GetRemoteIpEndPoint(), _connectType, false);
ByteBuffer buffer = new();
@@ -368,7 +363,7 @@ namespace Game.Networking
byte[] compressedData;
uint compressedSize = CompressPacket(data, opcode, out compressedData);
buffer.WriteUInt32(ZLib.adler32(0x9827D8F1, compressedData, compressedSize));
buffer.WriteUInt32(ZLib.adler32(0x9827D8F1, compressedData, compressedSize));
buffer.WriteBytes(compressedData, compressedSize);
packetSize = (int)(compressedSize + 12);
@@ -392,7 +387,7 @@ namespace Game.Networking
header.Write(byteBuffer);
byteBuffer.WriteBytes(data);
AsyncWrite(byteBuffer.GetData());
await AsyncWrite(byteBuffer.GetData());
}
public void SetWorldSession(WorldSession session)
@@ -464,7 +459,7 @@ namespace Game.Networking
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthSessionCallback, authSession));
}
void HandleAuthSessionCallback(AuthSession authSession, SQLResult result)
async void HandleAuthSessionCallback(AuthSession authSession, SQLResult result)
{
// Stop if the account is not found
if (result.IsEmpty())
@@ -540,7 +535,7 @@ namespace Game.Networking
{
// As we don't know if attempted login process by ip works, we update last_attempt_ip right away
stmt = LoginDatabase.GetPreparedStatement(LoginStatements.UPD_LAST_ATTEMPT_IP);
stmt.AddValue(0, address.Address.ToString());
stmt.AddValue(0, address.ToString());
stmt.AddValue(1, authSession.RealmJoinTicket);
DB.Login.Execute(stmt);
// This also allows to check for possible "hack" attempts on account
@@ -582,7 +577,7 @@ namespace Game.Networking
//Re-check ip locking (same check as in auth).
if (account.battleNet.IsLockedToIP) // if ip is locked
{
if (account.battleNet.LastIP != address.Address.ToString())
if (account.battleNet.LastIP != address.ToString())
{
SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked);
Log.outDebug(LogFilter.Network, "HandleAuthSession: Sent Auth Response (Account IP differs).");
@@ -643,7 +638,7 @@ namespace Game.Networking
{
// Update the last_ip in the database
stmt = LoginDatabase.GetPreparedStatement(LoginStatements.UPD_LAST_IP);
stmt.AddValue(0, address.Address.ToString());
stmt.AddValue(0, address.ToString());
stmt.AddValue(1, authSession.RealmJoinTicket);
DB.Login.Execute(stmt);
}
@@ -659,7 +654,7 @@ namespace Game.Networking
//_worldSession.InitWarden(_sessionKey);
_queryProcessor.AddCallback(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback));
AsyncRead();
await AsyncRead();
}
void LoadSessionPermissionsCallback(SQLResult result)
@@ -690,7 +685,7 @@ namespace Game.Networking
_queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthContinuedSessionCallback, authSession));
}
void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result)
async void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result)
{
if (result.IsEmpty())
{
@@ -728,7 +723,7 @@ namespace Game.Networking
Buffer.BlockCopy(encryptKeyGen.Digest, 0, _encryptKey, 0, 16);
SendPacket(new EnterEncryptedMode(_encryptKey, true));
AsyncRead();
await AsyncRead();
}
void HandleConnectToFailed(ConnectToFailed connectToFailed)
@@ -752,11 +747,11 @@ namespace Game.Networking
_worldSession.SendConnectToInstance(ConnectToSerial.WorldAttempt5);
break;
case ConnectToSerial.WorldAttempt5:
{
Log.outError(LogFilter.Network, "{0} failed to connect 5 times to world socket, aborting login", _worldSession.GetPlayerInfo());
_worldSession.AbortLogin(LoginFailureReason.NoWorld);
break;
}
{
Log.outError(LogFilter.Network, "{0} failed to connect 5 times to world socket, aborting login", _worldSession.GetPlayerInfo());
_worldSession.AbortLogin(LoginFailureReason.NoWorld);
break;
}
default:
return;
}
+11 -10
View File
@@ -133,8 +133,11 @@ namespace Game
if (playerConditionId != 0 && !CliDB.PlayerConditionStorage.ContainsKey(playerConditionId))
{
Log.outError(LogFilter.Sql, $"Table `quest_reward_display_spell` has non-existing PlayerCondition ({playerConditionId}) set for quest {Id}. and spell {spellId} Set to 0.");
playerConditionId = 0;
if (!Global.ConditionMgr.HasConditionsForNotGroupedEntry(ConditionSourceType.PlayerCondition, playerConditionId))
{
Log.outError(LogFilter.Sql, $"Table `quest_reward_display_spell` has serverside PlayerCondition ({playerConditionId}) set for quest {Id}. and spell {spellId} without conditions. Set to 0.");
playerConditionId = 0;
}
}
if (type >= QuestCompleteSpellType.Max)
@@ -481,7 +484,7 @@ namespace Game
return false;
}
public void BuildQuestRewards(QuestRewards rewards, Player player)
{
rewards.ChoiceItemCount = GetRewChoiceItemsCount();
@@ -495,10 +498,8 @@ namespace Game
var displaySpellIndex = 0;
foreach (QuestRewardDisplaySpell displaySpell in RewardDisplaySpell)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
continue;
if (!ConditionManager.IsPlayerMeetingCondition(player, displaySpell.PlayerConditionId))
continue;
rewards.SpellCompletionDisplayID[displaySpellIndex] = (int)displaySpell.SpellId;
if (++displaySpellIndex >= rewards.SpellCompletionDisplayID.Length)
@@ -811,7 +812,7 @@ namespace Game
public bool IsDailyOrWeekly() { return Flags.HasAnyFlag(QuestFlags.Daily | QuestFlags.Weekly); }
public bool IsDFQuest() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.DfQuest); }
public bool IsPushedToPartyOnAccept() { return HasSpecialFlag(QuestSpecialFlags.AutoPushToParty); }
public uint GetRewChoiceItemsCount() { return _rewChoiceItemsCount; }
public uint GetRewItemsCount() { return _rewItemsCount; }
public uint GetRewCurrencyCount() { return _rewCurrencyCount; }
@@ -1013,7 +1014,7 @@ namespace Game
}
public struct QuestRewardDisplaySpell
{
{
public uint SpellId;
public uint PlayerConditionId;
public QuestCompleteSpellType Type;
@@ -1077,7 +1078,7 @@ namespace Game
}
return false;
}
public bool IsStoringFlag()
{
switch (Type)
+13 -13
View File
@@ -242,6 +242,19 @@ namespace Game.Scripting
Global.ScriptMgr.AddScript(this);
}
// Gets an BattlegroundScript object for this battleground.
public virtual BattlegroundScript GetBattlegroundScript(BattlegroundMap map) { return null; }
}
class GenericBattlegroundMapScript<Script> : BattlegroundMapScript where Script : BattlegroundScript
{
public GenericBattlegroundMapScript(string name, uint mapId) : base(name, mapId) { }
public override BattlegroundScript GetBattlegroundScript(BattlegroundMap map)
{
return (Script)Activator.CreateInstance(typeof(Script), new object[] { map });
}
}
public class ItemScript : ScriptObject
@@ -430,19 +443,6 @@ namespace Game.Scripting
public virtual BattleField GetBattlefield(Map map) { return null; }
}
public class BattlegroundScript : ScriptObject
{
public BattlegroundScript(string name) : base(name)
{
Global.ScriptMgr.AddScript(this);
}
public override bool IsDatabaseBound() { return true; }
// Should return a fully valid Battlegroundobject for the type ID.
public virtual Battleground GetBattleground() { return null; }
}
public class OutdoorPvPScript : ScriptObject
{
public OutdoorPvPScript(string name) : base(name)
+4 -4
View File
@@ -608,11 +608,11 @@ namespace Game.Scripting
}
//BattlegroundScript
public Battleground CreateBattleground(BattlegroundTypeId typeId)
public BattlegroundScript CreateBattlegroundData(BattlegroundMap map)
{
// @todo Implement script-side Battlegrounds.
Cypher.Assert(false);
return null;
Cypher.Assert(map != null);
return RunScriptRet<BattlegroundMapScript, BattlegroundScript>(p => p.GetBattlegroundScript(map), map.GetScriptId(), null);
}
// OutdoorPvPScript
+1 -1
View File
@@ -46,7 +46,7 @@ namespace Game
_battlePetMgr = new BattlePetMgr(this);
_collectionMgr = new CollectionMgr(this);
m_Address = sock.GetRemoteIpAddress().Address.ToString();
m_Address = sock.GetRemoteIpAddress().ToString();
ResetTimeOutTime(false);
DB.Login.Execute("UPDATE account SET online = 1 WHERE id = {0};", GetAccountId()); // One-time query
}
+2 -12
View File
@@ -2152,11 +2152,7 @@ namespace Game.Spells
{
Player playerTarget = target.ToPlayer();
if (playerTarget != null)
{
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID);
if (playerCondition != null)
return ConditionManager.IsPlayerMeetingCondition(playerTarget, playerCondition);
}
return ConditionManager.IsPlayerMeetingCondition(playerTarget, mountDisplay.PlayerConditionID);
return true;
}).ToList();
@@ -2886,13 +2882,7 @@ namespace Game.Spells
Player player = target.ToPlayer();
if (!apply && player != null && GetSpellInfo().HasAuraInterruptFlag(SpellAuraInterruptFlags.StealthOrInvis))
{
if (player.InBattleground())
{
Battleground bg = player.GetBattleground();
if (bg != null)
bg.EventPlayerDroppedFlag(player);
}
else
if (!player.InBattleground())
Global.OutdoorPvPMgr.HandleDropFlag(player, GetSpellInfo().Id);
}
}
+1 -24
View File
@@ -1217,19 +1217,7 @@ namespace Game.Spells
if (goInfo.GetNoDamageImmune() != 0 && player.HasUnitFlag(UnitFlags.Immune))
return;
if (goInfo.type == GameObjectTypes.FlagStand)
{
//CanUseBattlegroundObject() already called in CheckCast()
// in Battlegroundcheck
Battleground bg = player.GetBattleground();
if (bg != null)
{
if (bg.GetTypeID() == BattlegroundTypeId.EY)
bg.EventPlayerClickedOnFlag(player, gameObjTarget);
return;
}
}
else if (m_spellInfo.Id == 1842 && gameObjTarget.GetGoInfo().type == GameObjectTypes.Trap && gameObjTarget.GetOwner() != null)
if (m_spellInfo.Id == 1842 && gameObjTarget.GetGoInfo().type == GameObjectTypes.Trap && gameObjTarget.GetOwner() != null)
{
gameObjTarget.SetLootState(LootState.JustDeactivated);
return;
@@ -2611,17 +2599,6 @@ namespace Game.Spells
// Wild object not have owner and check clickable by players
map.AddToMap(go);
if (go.GetGoType() == GameObjectTypes.FlagDrop)
{
Player player = m_caster.ToPlayer();
if (player != null)
{
Battleground bg = player.GetBattleground();
if (bg != null)
bg.SetDroppedFlagGUID(go.GetGUID(), bg.GetPlayerTeam(player.GetGUID()) == Team.Alliance ? BattleGroundTeamId.Horde : BattleGroundTeamId.Alliance);
}
}
GameObject linkedTrap = go.GetLinkedTrap();
if (linkedTrap != null)
{
+3 -6
View File
@@ -3181,10 +3181,8 @@ namespace Game.Spells
{
foreach (SpellXSpellVisualRecord visual in _visuals)
{
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(visual.CasterPlayerConditionID);
if (playerCondition != null)
if (caster == null || !caster.IsPlayer() || !ConditionManager.IsPlayerMeetingCondition(caster.ToPlayer(), playerCondition))
continue;
if (caster == null || !caster.IsPlayer() || !ConditionManager.IsPlayerMeetingCondition(caster.ToPlayer(), visual.CasterPlayerConditionID))
continue;
var unitCondition = CliDB.UnitConditionStorage.LookupByKey(visual.CasterUnitConditionID);
if (unitCondition != null)
@@ -3753,8 +3751,7 @@ namespace Game.Spells
if (ShowFutureSpellPlayerConditionID == 0)
return false;
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(ShowFutureSpellPlayerConditionID);
return playerCondition == null || ConditionManager.IsPlayerMeetingCondition(player, playerCondition);
return ConditionManager.IsPlayerMeetingCondition(player, ShowFutureSpellPlayerConditionID);
}
public bool HasLabel(uint labelId)
-7
View File
@@ -5010,13 +5010,6 @@ namespace Game.Entities
if (player == null || (auraSpell > 0 && !player.HasAura((uint)auraSpell)) || (auraSpell < 0 && player.HasAura((uint)-auraSpell)))
return false;
if (player != null)
{
Battleground bg = player.GetBattleground();
if (bg != null)
return bg.IsSpellAllowed(spellId, player);
}
// Extra conditions -- leaving the possibility add extra conditions...
switch (spellId)
{
+2 -2
View File
@@ -168,13 +168,13 @@ public struct WowTime : IComparable<WowTime>
public int CompareTo(WowTime other)
{
var compareFieldIfSet = int (int left1, int right1) =>
static int compareFieldIfSet(int left1, int right1)
{
if (left1 < 0 || right1 < 0)
return 0;
return left1.CompareTo(right1);
};
}
var cmp = compareFieldIfSet(_year, other._year);
if (cmp == -1)
+1 -1
View File
@@ -487,7 +487,7 @@ namespace Game
public static implicit operator byte[](WardenInitModuleRequest request)
{
ByteBuffer buffer = new ByteBuffer();
ByteBuffer buffer = new();
buffer.WriteUInt8((byte)request.Command1);
buffer.WriteUInt16(request.Size1);
buffer.WriteUInt32(request.CheckSumm1);
+7 -2
View File
@@ -538,6 +538,7 @@ namespace Game
Global.ObjectMgr.LoadPageTexts();
Log.outInfo(LogFilter.ServerLoading, "Loading GameObject Template...");
Global.ObjectMgr.LoadDestructibleHitpoints();
Global.ObjectMgr.LoadGameObjectTemplate();
Log.outInfo(LogFilter.ServerLoading, "Loading Game Object template addons...");
@@ -1074,6 +1075,7 @@ namespace Game
// Initialize Battlegrounds
Log.outInfo(LogFilter.ServerLoading, "Starting BattlegroundSystem");
Global.BattlegroundMgr.LoadBattlegroundTemplates();
Global.BattlegroundMgr.LoadBattlegroundScriptTemplate();
// Initialize outdoor pvp
Log.outInfo(LogFilter.ServerLoading, "Starting Outdoor PvP System");
@@ -1334,11 +1336,14 @@ namespace Game
if (WorldConfig.GetBoolValue(WorldCfg.PreserveCustomChannels))
{
ChannelManager mgr1 = ChannelManager.ForTeam(Team.Alliance);
ChannelManager mgr1 = ChannelManager.ForTeam(Team.PandariaNeutral);
mgr1.SaveToDB();
ChannelManager mgr2 = ChannelManager.ForTeam(Team.Horde);
ChannelManager mgr2 = ChannelManager.ForTeam(Team.Alliance);
if (mgr1 != mgr2)
mgr2.SaveToDB();
ChannelManager mgr3 = ChannelManager.ForTeam(Team.Horde);
if (mgr1 != mgr3)
mgr3.SaveToDB();
}
}