mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-15 18:10:26 +00:00
feat(Core/PvP): Set 30 sec timer before turn off FFA PvP flag. (#5090)
This commit is contained in:
@@ -1617,6 +1617,7 @@ void Player::Update(uint32 p_time)
|
||||
time_t now = time(nullptr);
|
||||
|
||||
UpdatePvPFlag(now);
|
||||
UpdateFFAPvPFlag(now);
|
||||
|
||||
UpdateContestedPvP(p_time);
|
||||
|
||||
@@ -7730,28 +7731,8 @@ void Player::UpdateArea(uint32 newArea)
|
||||
m_areaUpdateId = newArea;
|
||||
|
||||
AreaTableEntry const* area = sAreaTableStore.LookupEntry(newArea);
|
||||
bool oldFFAPvPArea = pvpInfo.IsInFFAPvPArea;
|
||||
pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
|
||||
UpdatePvPState(true);
|
||||
|
||||
// xinef: check if we were in ffa arena and we left
|
||||
if (oldFFAPvPArea && !pvpInfo.IsInFFAPvPArea)
|
||||
{
|
||||
// xinef: iterate attackers
|
||||
AttackerSet toRemove;
|
||||
AttackerSet const& attackers = getAttackers();
|
||||
for (AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end(); ++itr)
|
||||
if (!(*itr)->IsValidAttackTarget(this))
|
||||
toRemove.insert(*itr);
|
||||
|
||||
for (AttackerSet::const_iterator itr = toRemove.begin(); itr != toRemove.end(); ++itr)
|
||||
(*itr)->AttackStop();
|
||||
|
||||
// xinef: remove our own victim
|
||||
if (Unit* victim = GetVictim())
|
||||
if (!IsValidAttackTarget(victim))
|
||||
AttackStop();
|
||||
}
|
||||
UpdateFFAPvPState(false);
|
||||
|
||||
UpdateAreaDependentAuras(newArea);
|
||||
|
||||
@@ -21158,18 +21139,50 @@ void Player::UpdatePvPFlag(time_t currTime)
|
||||
{
|
||||
if (!IsPvP())
|
||||
return;
|
||||
|
||||
if (pvpInfo.EndTimer == 0 || pvpInfo.IsHostile)
|
||||
return;
|
||||
|
||||
if (currTime < (pvpInfo.EndTimer + 300 + 5))
|
||||
{
|
||||
if (currTime > (pvpInfo.EndTimer + 4) && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER))
|
||||
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePvP(false);
|
||||
}
|
||||
|
||||
void Player::UpdateFFAPvPFlag(time_t currTime)
|
||||
{
|
||||
if (!IsFFAPvP() || sWorld->IsFFAPvPRealm() || !pvpInfo.FFAPvPEndTimer || currTime < pvpInfo.FFAPvPEndTimer + 30)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pvpInfo.FFAPvPEndTimer = time_t(0);
|
||||
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
|
||||
// xinef: iterate attackers
|
||||
AttackerSet toRemove;
|
||||
AttackerSet const& attackers = getAttackers();
|
||||
for (AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end(); ++itr)
|
||||
if (!(*itr)->IsValidAttackTarget(this))
|
||||
toRemove.insert(*itr);
|
||||
|
||||
for (AttackerSet::const_iterator itr = toRemove.begin(); itr != toRemove.end(); ++itr)
|
||||
(*itr)->AttackStop();
|
||||
|
||||
// xinef: remove our own victim
|
||||
if (Unit* victim = GetVictim())
|
||||
if (!IsValidAttackTarget(victim))
|
||||
AttackStop();
|
||||
}
|
||||
|
||||
void Player::UpdateDuelFlag(time_t currTime)
|
||||
{
|
||||
if (!duel || duel->startTimer == 0 || currTime < duel->startTimer + 3)
|
||||
@@ -22747,29 +22760,9 @@ void Player::UpdateHomebindTime(uint32 time)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdatePvPState(bool onlyFFA)
|
||||
void Player::UpdatePvPState()
|
||||
{
|
||||
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
|
||||
// no, we shouldn't, those are checked for affecting player by client
|
||||
if (!pvpInfo.IsInNoPvPArea && !IsGameMaster()
|
||||
&& (pvpInfo.IsInFFAPvPArea || sWorld->IsFFAPvPRealm()))
|
||||
{
|
||||
if (!IsFFAPvP())
|
||||
{
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||
(*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
}
|
||||
}
|
||||
else if (IsFFAPvP())
|
||||
{
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
}
|
||||
|
||||
if (onlyFFA)
|
||||
return;
|
||||
UpdateFFAPvPState();
|
||||
|
||||
if (pvpInfo.IsHostile) // in hostile area
|
||||
{
|
||||
@@ -22783,6 +22776,63 @@ void Player::UpdatePvPState(bool onlyFFA)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateFFAPvPState(bool reset /*= true*/)
|
||||
{
|
||||
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
|
||||
// no, we shouldn't, those are checked for affecting player by client
|
||||
if (!pvpInfo.IsInNoPvPArea && !IsGameMaster() && (pvpInfo.IsInFFAPvPArea || sWorld->IsFFAPvPRealm()))
|
||||
{
|
||||
if (!IsFFAPvP())
|
||||
{
|
||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||
(*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
}
|
||||
|
||||
if (pvpInfo.IsInFFAPvPArea)
|
||||
{
|
||||
pvpInfo.FFAPvPEndTimer = time_t(0);
|
||||
}
|
||||
}
|
||||
else if (IsFFAPvP())
|
||||
{
|
||||
if ((pvpInfo.IsInNoPvPArea || IsGameMaster()) || reset || !pvpInfo.EndTimer)
|
||||
{
|
||||
pvpInfo.FFAPvPEndTimer = time_t(0);
|
||||
|
||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||
(*itr)->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||
|
||||
// xinef: iterate attackers
|
||||
AttackerSet toRemove;
|
||||
AttackerSet const& attackers = getAttackers();
|
||||
for (AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end(); ++itr)
|
||||
if (!(*itr)->IsValidAttackTarget(this))
|
||||
toRemove.insert(*itr);
|
||||
|
||||
for (AttackerSet::const_iterator itr = toRemove.begin(); itr != toRemove.end(); ++itr)
|
||||
(*itr)->AttackStop();
|
||||
|
||||
// xinef: remove our own victim
|
||||
if (Unit* victim = GetVictim())
|
||||
if (!IsValidAttackTarget(victim))
|
||||
AttackStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not in FFA PvP Area
|
||||
// Not FFA PvP realm
|
||||
// Not FFA PvP timer already set
|
||||
// Being recently in PvP combat
|
||||
if (!pvpInfo.IsInFFAPvPArea && !sWorld->IsFFAPvPRealm() && !pvpInfo.FFAPvPEndTimer)
|
||||
{
|
||||
pvpInfo.FFAPvPEndTimer = sWorld->GetGameTime() + sWorld->getIntConfig(CONFIG_FFA_PVP_TIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdatePvP(bool state, bool _override)
|
||||
{
|
||||
if (!state || _override)
|
||||
@@ -22795,6 +22845,7 @@ void Player::UpdatePvP(bool state, bool _override)
|
||||
pvpInfo.EndTimer = time(nullptr);
|
||||
SetPvP(state);
|
||||
}
|
||||
|
||||
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,7 +309,8 @@ struct PvPInfo
|
||||
bool IsInHostileArea{false}; ///> Marks if player is in an area which forces PvP flag
|
||||
bool IsInNoPvPArea{false}; ///> Marks if player is in a sanctuary or friendly capital city
|
||||
bool IsInFFAPvPArea{false}; ///> Marks if player is in an FFAPvP area (such as Gurubashi Arena)
|
||||
time_t EndTimer{0}; ///> Time when player unflags himself for PvP (flag removed after 5 minutes)
|
||||
time_t EndTimer{0}; ///> Time when player unflags himself for PvP (flag removed after 5 minutes)
|
||||
time_t FFAPvPEndTimer{0}; ///> Time when player unflags himself for FFA PvP (flag removed after 30 sec)
|
||||
};
|
||||
|
||||
struct DuelInfo
|
||||
@@ -1843,7 +1844,8 @@ public:
|
||||
bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type);
|
||||
|
||||
PvPInfo pvpInfo;
|
||||
void UpdatePvPState(bool onlyFFA = false);
|
||||
void UpdatePvPState();
|
||||
void UpdateFFAPvPState(bool reset = true);
|
||||
void SetPvP(bool state)
|
||||
{
|
||||
Unit::SetPvP(state);
|
||||
@@ -1864,6 +1866,7 @@ public:
|
||||
|
||||
void UpdateAfkReport(time_t currTime);
|
||||
void UpdatePvPFlag(time_t currTime);
|
||||
void UpdateFFAPvPFlag(time_t currTime);
|
||||
void UpdateContestedPvP(uint32 currTime);
|
||||
void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;}
|
||||
void ResetContestedPvP()
|
||||
|
||||
@@ -378,6 +378,7 @@ enum WorldIntConfigs
|
||||
CONFIG_TOGGLE_XP_COST,
|
||||
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
|
||||
CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID,
|
||||
CONFIG_FFA_PVP_TIMER,
|
||||
INT_CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -1240,6 +1240,8 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_int_configs[CONFIG_ITEMDELETE_QUALITY] = sConfigMgr->GetOption<int32>("ItemDelete.Quality", 3);
|
||||
m_int_configs[CONFIG_ITEMDELETE_ITEM_LEVEL] = sConfigMgr->GetOption<int32>("ItemDelete.ItemLevel", 80);
|
||||
|
||||
m_int_configs[CONFIG_FFA_PVP_TIMER] = sConfigMgr->GetOption<int32>("FFAPvPTimer", 30);
|
||||
|
||||
///- Read the "Data" directory from the config file
|
||||
std::string dataPath = sConfigMgr->GetOption<std::string>("DataDir", "./");
|
||||
if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\'))
|
||||
|
||||
@@ -3680,6 +3680,13 @@ ICC.Buff.Alliance = 73828
|
||||
|
||||
Item.SetItemTradeable = 1
|
||||
|
||||
#
|
||||
# FFAPvPTimer
|
||||
# Description: Specify time offset when player unset FFAPvP flag when leaving FFAPvP area. (e.g. Gurubashi Arena)
|
||||
# Default: 30 sec
|
||||
|
||||
FFAPvPTimer = 30
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
Reference in New Issue
Block a user