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:
@@ -790,4 +790,12 @@ namespace Framework.Constants
|
||||
Normal = 0,
|
||||
NPE = 1
|
||||
}
|
||||
|
||||
public enum DuelState
|
||||
{
|
||||
Challenged,
|
||||
Countdown,
|
||||
InProgress,
|
||||
Completed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user