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,
NPE = 1
}
public enum DuelState
{
Challenged,
Countdown,
InProgress,
Completed
}
}
+2 -2
View File
@@ -2080,7 +2080,7 @@ namespace Game.Entities
return ReputationRank.Friendly;
// 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;
// same group - checks dependant only on our faction - skip FFA_PVP for example
@@ -2387,7 +2387,7 @@ namespace Game.Entities
return false;
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;
// 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)
{
if (duel == null || duel.startTimer == 0 || currTime < duel.startTimer + 3)
return;
if (duel != null && duel.State == DuelState.Countdown && duel.StartTime <= currTime)
{
Global.ScriptMgr.OnPlayerDuelStart(this, duel.Opponent);
Global.ScriptMgr.OnPlayerDuelStart(this, duel.opponent);
SetDuelTeam(1);
duel.Opponent.SetDuelTeam(2);
SetDuelTeam(1);
duel.opponent.SetDuelTeam(2);
duel.startTimer = 0;
duel.startTime = currTime;
duel.opponent.duel.startTimer = 0;
duel.opponent.duel.startTime = currTime;
duel.State = DuelState.InProgress;
duel.Opponent.duel.State = DuelState.InProgress;
}
}
void CheckDuelDistance(long currTime)
@@ -414,11 +412,11 @@ namespace Game.Entities
if (!obj)
return;
if (duel.outOfBound == 0)
if (duel.OutOfBoundsTime == 0)
{
if (!IsWithinDistInMap(obj, 50))
{
duel.outOfBound = currTime;
duel.OutOfBoundsTime = currTime + 10;
SendPacket(new DuelOutOfBounds());
}
}
@@ -426,10 +424,10 @@ namespace Game.Entities
{
if (IsWithinDistInMap(obj, 40))
{
duel.outOfBound = 0;
duel.OutOfBoundsTime = 0;
SendPacket(new DuelInBounds());
}
else if (currTime >= (duel.outOfBound + 10))
else if (currTime >= duel.OutOfBoundsTime)
DuelComplete(DuelCompleteType.Fled);
}
}
@@ -440,26 +438,27 @@ namespace Game.Entities
return;
// 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;
duel.isCompleted = true;
duel.opponent.duel.isCompleted = true;
Player opponent = duel.Opponent;
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();
duelCompleted.Started = type != DuelCompleteType.Interrupted;
SendPacket(duelCompleted);
if (duel.opponent.GetSession() != null)
duel.opponent.SendPacket(duelCompleted);
if (opponent.GetSession() != null)
opponent.SendPacket(duelCompleted);
if (type != DuelCompleteType.Interrupted)
{
DuelWinner duelWinner = new();
duelWinner.BeatenName = (type == DuelCompleteType.Won ? duel.opponent.GetName() : GetName());
duelWinner.WinnerName = (type == DuelCompleteType.Won ? GetName() : duel.opponent.GetName());
duelWinner.BeatenName = (type == DuelCompleteType.Won ? opponent.GetName() : GetName());
duelWinner.WinnerName = (type == DuelCompleteType.Won ? GetName() : opponent.GetName());
duelWinner.BeatenVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress();
duelWinner.WinnerVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress();
duelWinner.Fled = type != DuelCompleteType.Won;
@@ -467,41 +466,41 @@ namespace Game.Entities
SendMessageToSet(duelWinner, true);
}
duel.opponent.DisablePvpRules();
opponent.DisablePvpRules();
DisablePvpRules();
Global.ScriptMgr.OnPlayerDuelEnd(duel.opponent, this, type);
Global.ScriptMgr.OnPlayerDuelEnd(opponent, this, type);
switch (type)
{
case DuelCompleteType.Fled:
// if initiator and opponent are on the same team
// 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();
duel.opponent.AttackStop();
AttackStop();
opponent.AttackStop();
}
else
{
if (!duel.initiator.IsPvP())
duel.initiator.AttackStop();
if (!duel.opponent.IsPvP())
duel.opponent.AttackStop();
if (!IsPvP())
AttackStop();
if (!opponent.IsPvP())
opponent.AttackStop();
}
break;
case DuelCompleteType.Won:
UpdateCriteria(CriteriaType.LoseDuel, 1);
duel.opponent.UpdateCriteria(CriteriaType.WinDuel, 1);
opponent.UpdateCriteria(CriteriaType.WinDuel, 1);
// Credit for quest Death's Challenge
if (GetClass() == Class.Deathknight && duel.opponent.GetQuestStatus(12733) == QuestStatus.Incomplete)
duel.opponent.CastSpell(duel.opponent, 52994, true);
if (GetClass() == Class.Deathknight && opponent.GetQuestStatus(12733) == QuestStatus.Incomplete)
opponent.CastSpell(duel.Opponent, 52994, true);
// Honor points after duel (the winner) - ImpConfig
int amount = WorldConfig.GetIntValue(WorldCfg.HonorAfterDuel);
if (amount != 0)
duel.opponent.RewardHonor(null, 1, amount);
opponent.RewardHonor(null, 1, amount);
break;
default:
@@ -510,41 +509,41 @@ namespace Game.Entities
// Victory emote spell
if (type != DuelCompleteType.Interrupted)
duel.opponent.CastSpell(duel.opponent, 52852, true);
opponent.CastSpell(duel.Opponent, 52852, true);
//Remove Duel Flag object
GameObject obj = GetMap().GetGameObject(m_playerData.DuelArbiter);
if (obj)
duel.initiator.RemoveGameObject(obj, true);
duel.Initiator.RemoveGameObject(obj, true);
//remove auras
var itsAuras = duel.opponent.GetAppliedAuras();
var itsAuras = opponent.GetAppliedAuras();
foreach (var pair in itsAuras)
{
Aura aura = pair.Value.GetBase();
if (!pair.Value.IsPositive() && aura.GetCasterGUID() == GetGUID() && aura.GetApplyTime() >= duel.startTime)
duel.opponent.RemoveAura(pair);
if (!pair.Value.IsPositive() && aura.GetCasterGUID() == GetGUID() && aura.GetApplyTime() >= duel.StartTime)
opponent.RemoveAura(pair);
}
var myAuras = GetAppliedAuras();
foreach (var pair in myAuras)
{
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);
}
// cleanup combo points
ClearComboPoints();
duel.opponent.ClearComboPoints();
opponent.ClearComboPoints();
//cleanups
SetDuelArbiter(ObjectGuid.Empty);
SetDuelTeam(0);
duel.opponent.SetDuelArbiter(ObjectGuid.Empty);
duel.opponent.SetDuelTeam(0);
opponent.SetDuelArbiter(ObjectGuid.Empty);
opponent.SetDuelTeam(0);
duel.opponent.duel = null;
opponent.duel = null;
duel = null;
}
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)
{
if (attackedPlayer != null && (attackedPlayer == this || (duel != null && duel.opponent == attackedPlayer)))
if (attackedPlayer != null && (attackedPlayer == this || (duel != null && duel.Opponent == attackedPlayer)))
return;
SetContestedPvPTimer(30000);
+12 -8
View File
@@ -421,15 +421,19 @@ namespace Game.Entities
public class DuelInfo
{
public Player initiator;
public Player opponent;
public long startTimer;
public long startTime;
public long outOfBound;
public bool isMounted;
public bool isCompleted;
public Player Opponent;
public Player Initiator;
public bool IsMounted;
public DuelState State;
public long StartTime;
public long OutOfBoundsTime;
public bool IsDueling() { return opponent != null; }
public DuelInfo(Player opponent, Player initiator, bool isMounted)
{
Opponent = opponent;
Initiator = initiator;
IsMounted = isMounted;
}
}
public class AccessRequirement
+4 -1
View File
@@ -4047,10 +4047,13 @@ namespace Game.Entities
if (base.IsAlwaysDetectableFor(seer))
return true;
if (duel != null && duel.State != DuelState.Challenged && duel.Opponent == seer)
return false;
Player seerPlayer = seer.ToPlayer();
if (seerPlayer != null)
if (IsGroupVisibleFor(seerPlayer))
return !(seerPlayer.duel != null && seerPlayer.duel.startTime != 0 && seerPlayer.duel.opponent == this);
return true;
return false;
}
+2 -2
View File
@@ -699,7 +699,7 @@ namespace Game.Entities
Player myPlayerOwner = 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.SetContestedPvP(targetPlayerOwner);
@@ -879,7 +879,7 @@ namespace Game.Entities
// last damage from non duel opponent or opponent controlled creature
if (plrVictim.duel != null)
{
plrVictim.duel.opponent.CombatStopWithPets(true);
plrVictim.duel.Opponent.CombatStopWithPets(true);
plrVictim.CombatStopWithPets(true);
plrVictim.DuelComplete(DuelCompleteType.Interrupted);
}
+5 -5
View File
@@ -982,7 +982,7 @@ namespace Game.Entities
Player player = ToPlayer();
// 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);
SetControlled(false, UnitState.Root); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
@@ -2422,7 +2422,7 @@ namespace Game.Entities
return 0;
// 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;
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))
{
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)
return 0;
// 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;
duel_wasMounted = true;
@@ -2657,7 +2657,7 @@ namespace Game.Entities
else
he.SetHealth(1);
he.duel.opponent.CombatStopWithPets(true);
he.duel.Opponent.CombatStopWithPets(true);
he.CombatStopWithPets(true);
he.CastSpell(he, 7267, true); // beg
+20 -20
View File
@@ -50,57 +50,57 @@ namespace Game
void HandleDuelResponse(DuelResponse duelResponse)
{
if (duelResponse.Accepted && !duelResponse.Forfeited)
HandleDuelAccepted();
HandleDuelAccepted(duelResponse.ArbiterGUID);
else
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;
Player player = GetPlayer();
Player plTarget = player.duel.opponent;
if (player == player.duel.initiator || !plTarget || player == plTarget || player.duel.startTime != 0 || plTarget.duel.startTime != 0)
Player target = player.duel.Opponent;
if (target.m_playerData.DuelArbiter != arbiterGuid)
return;
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();
player.duel.startTimer = now;
plTarget.duel.startTimer = now;
player.duel.StartTime = now + 3;
target.duel.StartTime = now + 3;
DuelCountdown packet = new(3000);
player.SendPacket(packet);
plTarget.SendPacket(packet);
target.SendPacket(packet);
player.EnablePvpRules();
plTarget.EnablePvpRules();
target.EnablePvpRules();
}
void HandleDuelCancelled()
{
Player player = GetPlayer();
// no duel requested
if (GetPlayer().duel == null)
if (player.duel == null || player.duel.State == DuelState.Completed)
return;
// player surrendered in a duel using /forfeit
if (GetPlayer().duel.startTime != 0)
if (player.duel.State == DuelState.InProgress)
{
GetPlayer().CombatStopWithPets(true);
if (GetPlayer().duel.opponent)
GetPlayer().duel.opponent.CombatStopWithPets(true);
player.CombatStopWithPets(true);
player.duel.Opponent.CombatStopWithPets(true);
GetPlayer().CastSpell(GetPlayer(), 7267, true); // beg
GetPlayer().DuelComplete(DuelCompleteType.Won);
player.CastSpell(GetPlayer(), 7267, true); // beg
player.DuelComplete(DuelCompleteType.Won);
return;
}
GetPlayer().DuelComplete(DuelCompleteType.Interrupted);
player.DuelComplete(DuelCompleteType.Interrupted);
}
}
}
+1 -1
View File
@@ -16,7 +16,6 @@
*/
using Framework.Constants;
using Framework.GameMath;
using Framework.Realm;
using Game.DataStorage;
using Game.Entities;
@@ -25,6 +24,7 @@ using Game.Misc;
using Game.Networking;
using Game.Networking.Packets;
using System.Collections.Generic;
using System.Numerics;
namespace Game
{
+3 -15
View File
@@ -3299,21 +3299,9 @@ namespace Game.Spells
target.SendPacket(packet);
// create duel-info
DuelInfo duel = new();
duel.initiator = caster;
duel.opponent = target;
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;
bool isMounted = (GetSpellInfo().Id == 62875);
caster.duel = new(target, caster, isMounted);
target.duel = new(caster, caster, isMounted);
caster.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.AreaRingOfChampions;
return checkArea && player.duel != null && player.duel.isMounted;
return checkArea && player.duel != null && player.duel.IsMounted;
}
}