Core/Player: Clean up duel related code. Fix a check for abusive client behavior, code style.

Port From (https://github.com/TrinityCore/TrinityCore/commit/7c062db94b1c2d28329c5f0ddc2fee74a6c07c35)
This commit is contained in:
hondacrx
2021-11-15 19:56:36 -05:00
parent 30af4577f8
commit c48696da32
11 changed files with 103 additions and 101 deletions
@@ -790,4 +790,12 @@ namespace Framework.Constants
Normal = 0, Normal = 0,
NPE = 1 NPE = 1
} }
public enum DuelState
{
Challenged,
Countdown,
InProgress,
Completed
}
} }
+2 -2
View File
@@ -2080,7 +2080,7 @@ namespace Game.Entities
return ReputationRank.Friendly; return ReputationRank.Friendly;
// duel - always hostile to opponent // duel - always hostile to opponent
if (selfPlayerOwner.duel != null && selfPlayerOwner.duel.opponent == targetPlayerOwner && selfPlayerOwner.duel.startTime != 0) if (selfPlayerOwner.duel != null && selfPlayerOwner.duel.Opponent == targetPlayerOwner && selfPlayerOwner.duel.State == DuelState.InProgress)
return ReputationRank.Hostile; return ReputationRank.Hostile;
// same group - checks dependant only on our faction - skip FFA_PVP for example // same group - checks dependant only on our faction - skip FFA_PVP for example
@@ -2387,7 +2387,7 @@ namespace Game.Entities
return false; return false;
if (playerAffectingAttacker && playerAffectingTarget) if (playerAffectingAttacker && playerAffectingTarget)
if (playerAffectingAttacker.duel != null && playerAffectingAttacker.duel.opponent == playerAffectingTarget && playerAffectingAttacker.duel.startTime != 0) if (playerAffectingAttacker.duel != null && playerAffectingAttacker.duel.Opponent == playerAffectingTarget && playerAffectingAttacker.duel.State == DuelState.InProgress)
return true; return true;
// PvP case - can't attack when attacker or target are in sanctuary // PvP case - can't attack when attacker or target are in sanctuary
+45 -46
View File
@@ -390,18 +390,16 @@ namespace Game.Entities
void UpdateDuelFlag(long currTime) void UpdateDuelFlag(long currTime)
{ {
if (duel == null || duel.startTimer == 0 || currTime < duel.startTimer + 3) if (duel != null && duel.State == DuelState.Countdown && duel.StartTime <= currTime)
return; {
Global.ScriptMgr.OnPlayerDuelStart(this, duel.Opponent);
Global.ScriptMgr.OnPlayerDuelStart(this, duel.opponent); SetDuelTeam(1);
duel.Opponent.SetDuelTeam(2);
SetDuelTeam(1); duel.State = DuelState.InProgress;
duel.opponent.SetDuelTeam(2); duel.Opponent.duel.State = DuelState.InProgress;
}
duel.startTimer = 0;
duel.startTime = currTime;
duel.opponent.duel.startTimer = 0;
duel.opponent.duel.startTime = currTime;
} }
void CheckDuelDistance(long currTime) void CheckDuelDistance(long currTime)
@@ -414,11 +412,11 @@ namespace Game.Entities
if (!obj) if (!obj)
return; return;
if (duel.outOfBound == 0) if (duel.OutOfBoundsTime == 0)
{ {
if (!IsWithinDistInMap(obj, 50)) if (!IsWithinDistInMap(obj, 50))
{ {
duel.outOfBound = currTime; duel.OutOfBoundsTime = currTime + 10;
SendPacket(new DuelOutOfBounds()); SendPacket(new DuelOutOfBounds());
} }
} }
@@ -426,10 +424,10 @@ namespace Game.Entities
{ {
if (IsWithinDistInMap(obj, 40)) if (IsWithinDistInMap(obj, 40))
{ {
duel.outOfBound = 0; duel.OutOfBoundsTime = 0;
SendPacket(new DuelInBounds()); SendPacket(new DuelInBounds());
} }
else if (currTime >= (duel.outOfBound + 10)) else if (currTime >= duel.OutOfBoundsTime)
DuelComplete(DuelCompleteType.Fled); DuelComplete(DuelCompleteType.Fled);
} }
} }
@@ -440,26 +438,27 @@ namespace Game.Entities
return; return;
// Check if DuelComplete() has been called already up in the stack and in that case don't do anything else here // Check if DuelComplete() has been called already up in the stack and in that case don't do anything else here
if (duel.isCompleted || duel.opponent.duel.isCompleted) if (duel.State == DuelState.Completed)
return; return;
duel.isCompleted = true; Player opponent = duel.Opponent;
duel.opponent.duel.isCompleted = true; duel.State = DuelState.Completed;
opponent.duel.State = DuelState.Completed;
Log.outDebug(LogFilter.Player, "Duel Complete {0} {1}", GetName(), duel.opponent.GetName()); Log.outDebug(LogFilter.Player, $"Duel Complete {GetName()} {opponent.GetName()}");
DuelComplete duelCompleted = new(); DuelComplete duelCompleted = new();
duelCompleted.Started = type != DuelCompleteType.Interrupted; duelCompleted.Started = type != DuelCompleteType.Interrupted;
SendPacket(duelCompleted); SendPacket(duelCompleted);
if (duel.opponent.GetSession() != null) if (opponent.GetSession() != null)
duel.opponent.SendPacket(duelCompleted); opponent.SendPacket(duelCompleted);
if (type != DuelCompleteType.Interrupted) if (type != DuelCompleteType.Interrupted)
{ {
DuelWinner duelWinner = new(); DuelWinner duelWinner = new();
duelWinner.BeatenName = (type == DuelCompleteType.Won ? duel.opponent.GetName() : GetName()); duelWinner.BeatenName = (type == DuelCompleteType.Won ? opponent.GetName() : GetName());
duelWinner.WinnerName = (type == DuelCompleteType.Won ? GetName() : duel.opponent.GetName()); duelWinner.WinnerName = (type == DuelCompleteType.Won ? GetName() : opponent.GetName());
duelWinner.BeatenVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress(); duelWinner.BeatenVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress();
duelWinner.WinnerVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress(); duelWinner.WinnerVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress();
duelWinner.Fled = type != DuelCompleteType.Won; duelWinner.Fled = type != DuelCompleteType.Won;
@@ -467,41 +466,41 @@ namespace Game.Entities
SendMessageToSet(duelWinner, true); SendMessageToSet(duelWinner, true);
} }
duel.opponent.DisablePvpRules(); opponent.DisablePvpRules();
DisablePvpRules(); DisablePvpRules();
Global.ScriptMgr.OnPlayerDuelEnd(duel.opponent, this, type); Global.ScriptMgr.OnPlayerDuelEnd(opponent, this, type);
switch (type) switch (type)
{ {
case DuelCompleteType.Fled: case DuelCompleteType.Fled:
// if initiator and opponent are on the same team // if initiator and opponent are on the same team
// or initiator and opponent are not PvP enabled, forcibly stop attacking // or initiator and opponent are not PvP enabled, forcibly stop attacking
if (duel.initiator.GetTeam() == duel.opponent.GetTeam()) if (GetTeam() == opponent.GetTeam())
{ {
duel.initiator.AttackStop(); AttackStop();
duel.opponent.AttackStop(); opponent.AttackStop();
} }
else else
{ {
if (!duel.initiator.IsPvP()) if (!IsPvP())
duel.initiator.AttackStop(); AttackStop();
if (!duel.opponent.IsPvP()) if (!opponent.IsPvP())
duel.opponent.AttackStop(); opponent.AttackStop();
} }
break; break;
case DuelCompleteType.Won: case DuelCompleteType.Won:
UpdateCriteria(CriteriaType.LoseDuel, 1); UpdateCriteria(CriteriaType.LoseDuel, 1);
duel.opponent.UpdateCriteria(CriteriaType.WinDuel, 1); opponent.UpdateCriteria(CriteriaType.WinDuel, 1);
// Credit for quest Death's Challenge // Credit for quest Death's Challenge
if (GetClass() == Class.Deathknight && duel.opponent.GetQuestStatus(12733) == QuestStatus.Incomplete) if (GetClass() == Class.Deathknight && opponent.GetQuestStatus(12733) == QuestStatus.Incomplete)
duel.opponent.CastSpell(duel.opponent, 52994, true); opponent.CastSpell(duel.Opponent, 52994, true);
// Honor points after duel (the winner) - ImpConfig // Honor points after duel (the winner) - ImpConfig
int amount = WorldConfig.GetIntValue(WorldCfg.HonorAfterDuel); int amount = WorldConfig.GetIntValue(WorldCfg.HonorAfterDuel);
if (amount != 0) if (amount != 0)
duel.opponent.RewardHonor(null, 1, amount); opponent.RewardHonor(null, 1, amount);
break; break;
default: default:
@@ -510,41 +509,41 @@ namespace Game.Entities
// Victory emote spell // Victory emote spell
if (type != DuelCompleteType.Interrupted) if (type != DuelCompleteType.Interrupted)
duel.opponent.CastSpell(duel.opponent, 52852, true); opponent.CastSpell(duel.Opponent, 52852, true);
//Remove Duel Flag object //Remove Duel Flag object
GameObject obj = GetMap().GetGameObject(m_playerData.DuelArbiter); GameObject obj = GetMap().GetGameObject(m_playerData.DuelArbiter);
if (obj) if (obj)
duel.initiator.RemoveGameObject(obj, true); duel.Initiator.RemoveGameObject(obj, true);
//remove auras //remove auras
var itsAuras = duel.opponent.GetAppliedAuras(); var itsAuras = opponent.GetAppliedAuras();
foreach (var pair in itsAuras) foreach (var pair in itsAuras)
{ {
Aura aura = pair.Value.GetBase(); Aura aura = pair.Value.GetBase();
if (!pair.Value.IsPositive() && aura.GetCasterGUID() == GetGUID() && aura.GetApplyTime() >= duel.startTime) if (!pair.Value.IsPositive() && aura.GetCasterGUID() == GetGUID() && aura.GetApplyTime() >= duel.StartTime)
duel.opponent.RemoveAura(pair); opponent.RemoveAura(pair);
} }
var myAuras = GetAppliedAuras(); var myAuras = GetAppliedAuras();
foreach (var pair in myAuras) foreach (var pair in myAuras)
{ {
Aura aura = pair.Value.GetBase(); Aura aura = pair.Value.GetBase();
if (!pair.Value.IsPositive() && aura.GetCasterGUID() == duel.opponent.GetGUID() && aura.GetApplyTime() >= duel.startTime) if (!pair.Value.IsPositive() && aura.GetCasterGUID() == opponent.GetGUID() && aura.GetApplyTime() >= duel.StartTime)
RemoveAura(pair); RemoveAura(pair);
} }
// cleanup combo points // cleanup combo points
ClearComboPoints(); ClearComboPoints();
duel.opponent.ClearComboPoints(); opponent.ClearComboPoints();
//cleanups //cleanups
SetDuelArbiter(ObjectGuid.Empty); SetDuelArbiter(ObjectGuid.Empty);
SetDuelTeam(0); SetDuelTeam(0);
duel.opponent.SetDuelArbiter(ObjectGuid.Empty); opponent.SetDuelArbiter(ObjectGuid.Empty);
duel.opponent.SetDuelTeam(0); opponent.SetDuelTeam(0);
duel.opponent.duel = null; opponent.duel = null;
duel = null; duel = null;
} }
public void SetDuelArbiter(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.DuelArbiter), guid); } public void SetDuelArbiter(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.DuelArbiter), guid); }
@@ -578,7 +577,7 @@ namespace Game.Entities
public void SetContestedPvP(Player attackedPlayer = null) public void SetContestedPvP(Player attackedPlayer = null)
{ {
if (attackedPlayer != null && (attackedPlayer == this || (duel != null && duel.opponent == attackedPlayer))) if (attackedPlayer != null && (attackedPlayer == this || (duel != null && duel.Opponent == attackedPlayer)))
return; return;
SetContestedPvPTimer(30000); SetContestedPvPTimer(30000);
+12 -8
View File
@@ -421,15 +421,19 @@ namespace Game.Entities
public class DuelInfo public class DuelInfo
{ {
public Player initiator; public Player Opponent;
public Player opponent; public Player Initiator;
public long startTimer; public bool IsMounted;
public long startTime; public DuelState State;
public long outOfBound; public long StartTime;
public bool isMounted; public long OutOfBoundsTime;
public bool isCompleted;
public bool IsDueling() { return opponent != null; } public DuelInfo(Player opponent, Player initiator, bool isMounted)
{
Opponent = opponent;
Initiator = initiator;
IsMounted = isMounted;
}
} }
public class AccessRequirement public class AccessRequirement
+4 -1
View File
@@ -4047,10 +4047,13 @@ namespace Game.Entities
if (base.IsAlwaysDetectableFor(seer)) if (base.IsAlwaysDetectableFor(seer))
return true; return true;
if (duel != null && duel.State != DuelState.Challenged && duel.Opponent == seer)
return false;
Player seerPlayer = seer.ToPlayer(); Player seerPlayer = seer.ToPlayer();
if (seerPlayer != null) if (seerPlayer != null)
if (IsGroupVisibleFor(seerPlayer)) if (IsGroupVisibleFor(seerPlayer))
return !(seerPlayer.duel != null && seerPlayer.duel.startTime != 0 && seerPlayer.duel.opponent == this); return true;
return false; return false;
} }
+2 -2
View File
@@ -699,7 +699,7 @@ namespace Game.Entities
Player myPlayerOwner = GetCharmerOrOwnerPlayerOrPlayerItself(); Player myPlayerOwner = GetCharmerOrOwnerPlayerOrPlayerItself();
Player targetPlayerOwner = target.GetCharmerOrOwnerPlayerOrPlayerItself(); Player targetPlayerOwner = target.GetCharmerOrOwnerPlayerOrPlayerItself();
if (myPlayerOwner && targetPlayerOwner && !(myPlayerOwner.duel != null && myPlayerOwner.duel.opponent == targetPlayerOwner)) if (myPlayerOwner && targetPlayerOwner && !(myPlayerOwner.duel != null && myPlayerOwner.duel.Opponent == targetPlayerOwner))
{ {
myPlayerOwner.UpdatePvP(true); myPlayerOwner.UpdatePvP(true);
myPlayerOwner.SetContestedPvP(targetPlayerOwner); myPlayerOwner.SetContestedPvP(targetPlayerOwner);
@@ -879,7 +879,7 @@ namespace Game.Entities
// last damage from non duel opponent or opponent controlled creature // last damage from non duel opponent or opponent controlled creature
if (plrVictim.duel != null) if (plrVictim.duel != null)
{ {
plrVictim.duel.opponent.CombatStopWithPets(true); plrVictim.duel.Opponent.CombatStopWithPets(true);
plrVictim.CombatStopWithPets(true); plrVictim.CombatStopWithPets(true);
plrVictim.DuelComplete(DuelCompleteType.Interrupted); plrVictim.DuelComplete(DuelCompleteType.Interrupted);
} }
+5 -5
View File
@@ -982,7 +982,7 @@ namespace Game.Entities
Player player = ToPlayer(); Player player = ToPlayer();
// If the player is on mounted duel and exits the mount, he should immediatly lose the duel // If the player is on mounted duel and exits the mount, he should immediatly lose the duel
if (player && player.duel != null && player.duel.isMounted) if (player && player.duel != null && player.duel.IsMounted)
player.DuelComplete(DuelCompleteType.Fled); player.DuelComplete(DuelCompleteType.Fled);
SetControlled(false, UnitState.Root); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT SetControlled(false, UnitState.Root); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
@@ -2422,7 +2422,7 @@ namespace Game.Entities
return 0; return 0;
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
if (victim.ToPlayer().duel.opponent == attacker.GetControllingPlayer()) if (victim.ToPlayer().duel.Opponent == attacker.GetControllingPlayer())
damage = health - 1; damage = health - 1;
duel_hasEnded = true; duel_hasEnded = true;
@@ -2430,13 +2430,13 @@ namespace Game.Entities
else if (victim.IsVehicle() && damage >= (health - 1) && victim.GetCharmer() != null && victim.GetCharmer().IsTypeId(TypeId.Player)) else if (victim.IsVehicle() && damage >= (health - 1) && victim.GetCharmer() != null && victim.GetCharmer().IsTypeId(TypeId.Player))
{ {
Player victimRider = victim.GetCharmer().ToPlayer(); Player victimRider = victim.GetCharmer().ToPlayer();
if (victimRider != null && victimRider.duel != null && victimRider.duel.isMounted) if (victimRider != null && victimRider.duel != null && victimRider.duel.IsMounted)
{ {
if (!attacker) if (!attacker)
return 0; return 0;
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
if (victimRider.duel.opponent == attacker.GetControllingPlayer()) if (victimRider.duel.Opponent == attacker.GetControllingPlayer())
damage = health - 1; damage = health - 1;
duel_wasMounted = true; duel_wasMounted = true;
@@ -2657,7 +2657,7 @@ namespace Game.Entities
else else
he.SetHealth(1); he.SetHealth(1);
he.duel.opponent.CombatStopWithPets(true); he.duel.Opponent.CombatStopWithPets(true);
he.CombatStopWithPets(true); he.CombatStopWithPets(true);
he.CastSpell(he, 7267, true); // beg he.CastSpell(he, 7267, true); // beg
+20 -20
View File
@@ -50,57 +50,57 @@ namespace Game
void HandleDuelResponse(DuelResponse duelResponse) void HandleDuelResponse(DuelResponse duelResponse)
{ {
if (duelResponse.Accepted && !duelResponse.Forfeited) if (duelResponse.Accepted && !duelResponse.Forfeited)
HandleDuelAccepted(); HandleDuelAccepted(duelResponse.ArbiterGUID);
else else
HandleDuelCancelled(); HandleDuelCancelled();
} }
void HandleDuelAccepted() void HandleDuelAccepted(ObjectGuid arbiterGuid)
{ {
if (GetPlayer().duel == null) // ignore accept from duel-sender Player player = GetPlayer();
if (player.duel == null || player == player.duel.Initiator || player.duel.State != DuelState.Challenged)
return; return;
Player player = GetPlayer(); Player target = player.duel.Opponent;
Player plTarget = player.duel.opponent; if (target.m_playerData.DuelArbiter != arbiterGuid)
if (player == player.duel.initiator || !plTarget || player == plTarget || player.duel.startTime != 0 || plTarget.duel.startTime != 0)
return; return;
Log.outDebug(LogFilter.Network, "Player 1 is: {0} ({1})", player.GetGUID().ToString(), player.GetName()); Log.outDebug(LogFilter.Network, "Player 1 is: {0} ({1})", player.GetGUID().ToString(), player.GetName());
Log.outDebug(LogFilter.Network, "Player 2 is: {0} ({1})", plTarget.GetGUID().ToString(), plTarget.GetName()); Log.outDebug(LogFilter.Network, "Player 2 is: {0} ({1})", target.GetGUID().ToString(), target.GetName());
long now = GameTime.GetGameTime(); long now = GameTime.GetGameTime();
player.duel.startTimer = now; player.duel.StartTime = now + 3;
plTarget.duel.startTimer = now; target.duel.StartTime = now + 3;
DuelCountdown packet = new(3000); DuelCountdown packet = new(3000);
player.SendPacket(packet); player.SendPacket(packet);
plTarget.SendPacket(packet); target.SendPacket(packet);
player.EnablePvpRules(); player.EnablePvpRules();
plTarget.EnablePvpRules(); target.EnablePvpRules();
} }
void HandleDuelCancelled() void HandleDuelCancelled()
{ {
Player player = GetPlayer();
// no duel requested // no duel requested
if (GetPlayer().duel == null) if (player.duel == null || player.duel.State == DuelState.Completed)
return; return;
// player surrendered in a duel using /forfeit // player surrendered in a duel using /forfeit
if (GetPlayer().duel.startTime != 0) if (player.duel.State == DuelState.InProgress)
{ {
GetPlayer().CombatStopWithPets(true); player.CombatStopWithPets(true);
if (GetPlayer().duel.opponent) player.duel.Opponent.CombatStopWithPets(true);
GetPlayer().duel.opponent.CombatStopWithPets(true);
GetPlayer().CastSpell(GetPlayer(), 7267, true); // beg player.CastSpell(GetPlayer(), 7267, true); // beg
GetPlayer().DuelComplete(DuelCompleteType.Won); player.DuelComplete(DuelCompleteType.Won);
return; return;
} }
GetPlayer().DuelComplete(DuelCompleteType.Interrupted); player.DuelComplete(DuelCompleteType.Interrupted);
} }
} }
} }
+1 -1
View File
@@ -16,7 +16,6 @@
*/ */
using Framework.Constants; using Framework.Constants;
using Framework.GameMath;
using Framework.Realm; using Framework.Realm;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
@@ -25,6 +24,7 @@ using Game.Misc;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics;
namespace Game namespace Game
{ {
+3 -15
View File
@@ -3299,21 +3299,9 @@ namespace Game.Spells
target.SendPacket(packet); target.SendPacket(packet);
// create duel-info // create duel-info
DuelInfo duel = new(); bool isMounted = (GetSpellInfo().Id == 62875);
duel.initiator = caster; caster.duel = new(target, caster, isMounted);
duel.opponent = target; target.duel = new(caster, caster, isMounted);
duel.startTime = 0;
duel.startTimer = 0;
duel.isMounted = (GetSpellInfo().Id == 62875); // Mounted Duel
caster.duel = duel;
DuelInfo duel2 = new();
duel2.initiator = caster;
duel2.opponent = caster;
duel2.startTime = 0;
duel2.startTimer = 0;
duel2.isMounted = (GetSpellInfo().Id == 62875); // Mounted Duel
target.duel = duel2;
caster.SetDuelArbiter(go.GetGUID()); caster.SetDuelArbiter(go.GetGUID());
target.SetDuelArbiter(go.GetGUID()); target.SetDuelArbiter(go.GetGUID());
+1 -1
View File
@@ -264,7 +264,7 @@ namespace Scripts.World.Achievements
player.GetAreaId() == AreaIds.AreaRingOfHordeValiants || player.GetAreaId() == AreaIds.AreaRingOfHordeValiants ||
player.GetAreaId() == AreaIds.AreaRingOfChampions; player.GetAreaId() == AreaIds.AreaRingOfChampions;
return checkArea && player.duel != null && player.duel.isMounted; return checkArea && player.duel != null && player.duel.IsMounted;
} }
} }