*Set pvp flags for units controlled by player.
*Reset pvp flags when unit is uncharmed. *Remove walk flag when unit is charmed. --HG-- branch : trunk
This commit is contained in:
+45
-51
@@ -6176,19 +6176,8 @@ void Player::UpdateArea(uint32 newArea)
|
|||||||
m_areaUpdateId = newArea;
|
m_areaUpdateId = newArea;
|
||||||
|
|
||||||
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
|
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
|
||||||
|
pvpInfo.inFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
|
||||||
if(area && (area->flags & AREA_FLAG_ARENA))
|
UpdatePvPState(true);
|
||||||
{
|
|
||||||
if(!isGameMaster())
|
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// remove ffa flag only if not ffapvp realm
|
|
||||||
// removal in sanctuaries and capitals is handled in zone update
|
|
||||||
if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && !sWorld.IsFFAPvPRealm())
|
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateAreaDependentAuras(newArea);
|
UpdateAreaDependentAuras(newArea);
|
||||||
}
|
}
|
||||||
@@ -6241,29 +6230,18 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
|||||||
break;
|
break;
|
||||||
case AREATEAM_NONE:
|
case AREATEAM_NONE:
|
||||||
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
|
// overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this
|
||||||
pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround();
|
pvpInfo.inHostileArea = sWorld.IsPvPRealm() || InBattleGround() || (zone->flags & AREA_FLAG_OUTDOOR_PVP);
|
||||||
break;
|
break;
|
||||||
default: // 6 in fact
|
default: // 6 in fact
|
||||||
pvpInfo.inHostileArea = false;
|
pvpInfo.inHostileArea = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pvpInfo.inHostileArea) // in hostile area
|
pvpInfo.inNoPvPArea = false;
|
||||||
{
|
|
||||||
if(!IsPvP() || pvpInfo.endTimer != 0)
|
|
||||||
UpdatePvP(true, true);
|
|
||||||
}
|
|
||||||
else // in friendly area
|
|
||||||
{
|
|
||||||
if(IsPvP() && !HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_IN_PVP) && pvpInfo.endTimer == 0)
|
|
||||||
pvpInfo.endTimer = time(0); // start toggle-off
|
|
||||||
}
|
|
||||||
|
|
||||||
if((zone->flags & AREA_FLAG_SANCTUARY) || zone->mapid == 609) // in sanctuary
|
if((zone->flags & AREA_FLAG_SANCTUARY) || zone->mapid == 609) // in sanctuary
|
||||||
{
|
{
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
|
||||||
if(sWorld.IsFFAPvPRealm())
|
pvpInfo.inNoPvPArea = true;
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -6275,9 +6253,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
|||||||
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
||||||
SetRestType(REST_TYPE_IN_CITY);
|
SetRestType(REST_TYPE_IN_CITY);
|
||||||
InnEnter(time(0),GetMapId(),0,0,0);
|
InnEnter(time(0),GetMapId(),0,0,0);
|
||||||
|
pvpInfo.inNoPvPArea = true;
|
||||||
if(sWorld.IsFFAPvPRealm())
|
|
||||||
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
}
|
||||||
else // anywhere else
|
else // anywhere else
|
||||||
{
|
{
|
||||||
@@ -6289,22 +6265,17 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
|
|||||||
{
|
{
|
||||||
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
||||||
SetRestType(REST_TYPE_NO);
|
SetRestType(REST_TYPE_NO);
|
||||||
|
|
||||||
if(sWorld.IsFFAPvPRealm())
|
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // not in tavern (leave city then)
|
else // not in tavern (leave city then)
|
||||||
{
|
{
|
||||||
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
|
||||||
SetRestType(REST_TYPE_NO);
|
SetRestType(REST_TYPE_NO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set player to FFA PVP when not in rested environment.
|
UpdatePvPState();
|
||||||
if(sWorld.IsFFAPvPRealm())
|
|
||||||
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove items with area/map limitations (delete only for alive player to allow back in ghost mode)
|
// remove items with area/map limitations (delete only for alive player to allow back in ghost mode)
|
||||||
// if player resurrected at teleport this will be applied in resurrect code
|
// if player resurrected at teleport this will be applied in resurrect code
|
||||||
@@ -17819,16 +17790,46 @@ void Player::UpdateHomebindTime(uint32 time)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::UpdatePvPState(bool onlyFFA)
|
||||||
|
{
|
||||||
|
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
|
||||||
|
if(!pvpInfo.inNoPvPArea && !isGameMaster()
|
||||||
|
&& (pvpInfo.inFFAPvPArea || sWorld.IsFFAPvPRealm()))
|
||||||
|
{
|
||||||
|
if(!HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
|
||||||
|
{
|
||||||
|
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||||
|
for(ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||||
|
(*itr)->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
|
||||||
|
{
|
||||||
|
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
||||||
|
for(ControlList::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;
|
||||||
|
|
||||||
|
if(pvpInfo.inHostileArea) // in hostile area
|
||||||
|
{
|
||||||
|
if(!IsPvP() || pvpInfo.endTimer != 0)
|
||||||
|
UpdatePvP(true, true);
|
||||||
|
}
|
||||||
|
else // in friendly area
|
||||||
|
{
|
||||||
|
if(IsPvP() && !HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_IN_PVP) && pvpInfo.endTimer == 0)
|
||||||
|
pvpInfo.endTimer = time(0); // start toggle-off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Player::UpdatePvP(bool state, bool ovrride)
|
void Player::UpdatePvP(bool state, bool ovrride)
|
||||||
{
|
{
|
||||||
if(!state || ovrride)
|
if(!state || ovrride)
|
||||||
{
|
{
|
||||||
SetPvP(state);
|
SetPvP(state);
|
||||||
if(Pet* pet = GetPet())
|
|
||||||
pet->SetPvP(state);
|
|
||||||
if(Unit* charmed = GetCharm())
|
|
||||||
charmed->SetPvP(state);
|
|
||||||
|
|
||||||
pvpInfo.endTimer = 0;
|
pvpInfo.endTimer = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -17836,14 +17837,7 @@ void Player::UpdatePvP(bool state, bool ovrride)
|
|||||||
if(pvpInfo.endTimer != 0)
|
if(pvpInfo.endTimer != 0)
|
||||||
pvpInfo.endTimer = time(NULL);
|
pvpInfo.endTimer = time(NULL);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
SetPvP(state);
|
SetPvP(state);
|
||||||
|
|
||||||
if(Pet* pet = GetPet())
|
|
||||||
pet->SetPvP(state);
|
|
||||||
if(Unit* charmed = GetCharm())
|
|
||||||
charmed->SetPvP(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -213,9 +213,11 @@ struct PlayerInfo
|
|||||||
|
|
||||||
struct PvPInfo
|
struct PvPInfo
|
||||||
{
|
{
|
||||||
PvPInfo() : inHostileArea(false), endTimer(0) {}
|
PvPInfo() : inHostileArea(false), inNoPvPArea(false), inFFAPvPArea(false), endTimer(0) {}
|
||||||
|
|
||||||
bool inHostileArea;
|
bool inHostileArea;
|
||||||
|
bool inNoPvPArea;
|
||||||
|
bool inFFAPvPArea;
|
||||||
time_t endTimer;
|
time_t endTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1423,6 +1425,13 @@ class TRINITY_DLL_SPEC Player : public Unit
|
|||||||
void SendInitialActionButtons() const;
|
void SendInitialActionButtons() const;
|
||||||
|
|
||||||
PvPInfo pvpInfo;
|
PvPInfo pvpInfo;
|
||||||
|
void UpdatePvPState(bool onlyFFA = false);
|
||||||
|
void SetPvP(bool state)
|
||||||
|
{
|
||||||
|
Unit::SetPvP(state);
|
||||||
|
for(ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
|
||||||
|
(*itr)->SetPvP(state);
|
||||||
|
}
|
||||||
void UpdatePvP(bool state, bool ovrride=false);
|
void UpdatePvP(bool state, bool ovrride=false);
|
||||||
void UpdateZone(uint32 newZone,uint32 newArea);
|
void UpdateZone(uint32 newZone,uint32 newArea);
|
||||||
void UpdateArea(uint32 newArea);
|
void UpdateArea(uint32 newArea);
|
||||||
|
|||||||
+29
-6
@@ -8341,10 +8341,10 @@ void Unit::SetMinion(Minion *minion, bool apply)
|
|||||||
//else if(minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET)
|
//else if(minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET)
|
||||||
// AddUInt64Value(UNIT_FIELD_CRITTER, minion->GetGUID());
|
// AddUInt64Value(UNIT_FIELD_CRITTER, minion->GetGUID());
|
||||||
|
|
||||||
// FIXME: hack, speed must be set only at follow
|
// PvP, FFAPvP
|
||||||
if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
|
minion->SetByteValue(UNIT_FIELD_BYTES_2, 1, GetByteValue(UNIT_FIELD_BYTES_2, 1));
|
||||||
minion->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
|
|
||||||
|
|
||||||
|
// FIXME: hack, speed must be set only at follow
|
||||||
if(GetTypeId() == TYPEID_PLAYER && minion->HasSummonMask(SUMMON_MASK_PET))
|
if(GetTypeId() == TYPEID_PLAYER && minion->HasSummonMask(SUMMON_MASK_PET))
|
||||||
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
|
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
|
||||||
minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
|
minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
|
||||||
@@ -8411,13 +8411,24 @@ void Unit::SetCharm(Unit* charm, bool apply)
|
|||||||
sLog.outCrash("Player %s is trying to charm unit %u, but it already has a charmed unit %u", GetName(), charm->GetEntry(), GetCharmGUID());
|
sLog.outCrash("Player %s is trying to charm unit %u, but it already has a charmed unit %u", GetName(), charm->GetEntry(), GetCharmGUID());
|
||||||
|
|
||||||
charm->m_ControlledByPlayer = true;
|
charm->m_ControlledByPlayer = true;
|
||||||
|
// TODO: maybe we can use this flag to check if controlled by player
|
||||||
|
charm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
charm->m_ControlledByPlayer = false;
|
charm->m_ControlledByPlayer = false;
|
||||||
|
|
||||||
|
// PvP, FFAPvP
|
||||||
|
charm->SetByteValue(UNIT_FIELD_BYTES_2, 1, GetByteValue(UNIT_FIELD_BYTES_2, 1));
|
||||||
|
|
||||||
if(!charm->AddUInt64Value(UNIT_FIELD_CHARMEDBY, GetGUID()))
|
if(!charm->AddUInt64Value(UNIT_FIELD_CHARMEDBY, GetGUID()))
|
||||||
sLog.outCrash("Unit %u is being charmed, but it already has a charmer %u", charm->GetEntry(), charm->GetCharmerGUID());
|
sLog.outCrash("Unit %u is being charmed, but it already has a charmer %u", charm->GetEntry(), charm->GetCharmerGUID());
|
||||||
|
|
||||||
|
if(charm->HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE))
|
||||||
|
{
|
||||||
|
charm->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||||
|
charm->SendMovementFlagUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
m_Controlled.insert(charm);
|
m_Controlled.insert(charm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -8428,10 +8439,24 @@ void Unit::SetCharm(Unit* charm, bool apply)
|
|||||||
sLog.outCrash("Player %s is trying to uncharm unit %u, but it has another charmed unit %u", GetName(), charm->GetEntry(), GetCharmGUID());
|
sLog.outCrash("Player %s is trying to uncharm unit %u, but it has another charmed unit %u", GetName(), charm->GetEntry(), GetCharmGUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(charm->GetTypeId() == TYPEID_PLAYER || IS_PLAYER_GUID(charm->GetOwnerGUID()))
|
if(charm->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
charm->m_ControlledByPlayer = true;
|
charm->m_ControlledByPlayer = true;
|
||||||
|
charm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||||
|
((Player*)charm)->UpdatePvPState();
|
||||||
|
}
|
||||||
|
else if(Player *player = charm->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||||
|
{
|
||||||
|
charm->m_ControlledByPlayer = true;
|
||||||
|
charm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||||
|
charm->SetByteValue(UNIT_FIELD_BYTES_2, 1, player->GetByteValue(UNIT_FIELD_BYTES_2, 1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
charm->m_ControlledByPlayer = false;
|
charm->m_ControlledByPlayer = false;
|
||||||
|
charm->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||||
|
charm->SetByteValue(UNIT_FIELD_BYTES_2, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if(!charm->RemoveUInt64Value(UNIT_FIELD_CHARMEDBY, GetGUID()))
|
if(!charm->RemoveUInt64Value(UNIT_FIELD_CHARMEDBY, GetGUID()))
|
||||||
sLog.outCrash("Unit %u is being uncharmed, but it has another charmer %u", charm->GetEntry(), charm->GetCharmerGUID());
|
sLog.outCrash("Unit %u is being uncharmed, but it has another charmer %u", charm->GetEntry(), charm->GetCharmerGUID());
|
||||||
@@ -13389,7 +13414,6 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
|
|||||||
if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport())
|
if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
|
||||||
CastStop();
|
CastStop();
|
||||||
CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells)
|
CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells)
|
||||||
DeleteThreatList();
|
DeleteThreatList();
|
||||||
@@ -13414,7 +13438,6 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
|
|||||||
|
|
||||||
// Set charmed
|
// Set charmed
|
||||||
setFaction(charmer->getFaction());
|
setFaction(charmer->getFaction());
|
||||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
|
||||||
charmer->SetCharm(this, true);
|
charmer->SetCharm(this, true);
|
||||||
|
|
||||||
if(GetTypeId() == TYPEID_UNIT)
|
if(GetTypeId() == TYPEID_UNIT)
|
||||||
|
|||||||
Reference in New Issue
Block a user