*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:
megamage
2009-05-22 03:12:35 -05:00
parent 5888134e4d
commit 3641be039b
3 changed files with 82 additions and 56 deletions
+43 -49
View File
@@ -6176,19 +6176,8 @@ void Player::UpdateArea(uint32 newArea)
m_areaUpdateId = newArea;
AreaTableEntry const* area = GetAreaEntryByAreaID(newArea);
if(area && (area->flags & AREA_FLAG_ARENA))
{
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);
}
pvpInfo.inFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA);
UpdatePvPState(true);
UpdateAreaDependentAuras(newArea);
}
@@ -6241,29 +6230,18 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
break;
case AREATEAM_NONE:
// 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;
default: // 6 in fact
pvpInfo.inHostileArea = false;
break;
}
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
}
pvpInfo.inNoPvPArea = false;
if((zone->flags & AREA_FLAG_SANCTUARY) || zone->mapid == 609) // in sanctuary
{
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
if(sWorld.IsFFAPvPRealm())
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
pvpInfo.inNoPvPArea = true;
}
else
{
@@ -6275,9 +6253,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_IN_CITY);
InnEnter(time(0),GetMapId(),0,0,0);
if(sWorld.IsFFAPvPRealm())
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
pvpInfo.inNoPvPArea = true;
}
else // anywhere else
{
@@ -6289,23 +6265,18 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
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)
{
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
SetRestType(REST_TYPE_NO);
// Set player to FFA PVP when not in rested environment.
if(sWorld.IsFFAPvPRealm())
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
}
}
}
UpdatePvPState();
// 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(isAlive())
@@ -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)
{
if(!state || ovrride)
{
SetPvP(state);
if(Pet* pet = GetPet())
pet->SetPvP(state);
if(Unit* charmed = GetCharm())
charmed->SetPvP(state);
pvpInfo.endTimer = 0;
}
else
@@ -17836,14 +17837,7 @@ void Player::UpdatePvP(bool state, bool ovrride)
if(pvpInfo.endTimer != 0)
pvpInfo.endTimer = time(NULL);
else
{
SetPvP(state);
if(Pet* pet = GetPet())
pet->SetPvP(state);
if(Unit* charmed = GetCharm())
charmed->SetPvP(state);
}
}
}
+10 -1
View File
@@ -213,9 +213,11 @@ struct PlayerInfo
struct PvPInfo
{
PvPInfo() : inHostileArea(false), endTimer(0) {}
PvPInfo() : inHostileArea(false), inNoPvPArea(false), inFFAPvPArea(false), endTimer(0) {}
bool inHostileArea;
bool inNoPvPArea;
bool inFFAPvPArea;
time_t endTimer;
};
@@ -1423,6 +1425,13 @@ class TRINITY_DLL_SPEC Player : public Unit
void SendInitialActionButtons() const;
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 UpdateZone(uint32 newZone,uint32 newArea);
void UpdateArea(uint32 newArea);
+29 -6
View File
@@ -8341,10 +8341,10 @@ void Unit::SetMinion(Minion *minion, bool apply)
//else if(minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET)
// AddUInt64Value(UNIT_FIELD_CRITTER, minion->GetGUID());
// FIXME: hack, speed must be set only at follow
if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
minion->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
// PvP, FFAPvP
minion->SetByteValue(UNIT_FIELD_BYTES_2, 1, GetByteValue(UNIT_FIELD_BYTES_2, 1));
// FIXME: hack, speed must be set only at follow
if(GetTypeId() == TYPEID_PLAYER && minion->HasSummonMask(SUMMON_MASK_PET))
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
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());
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
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()))
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);
}
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());
}
if(charm->GetTypeId() == TYPEID_PLAYER || IS_PLAYER_GUID(charm->GetOwnerGUID()))
if(charm->GetTypeId() == TYPEID_PLAYER)
{
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
{
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()))
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())
return;
RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
CastStop();
CombatStop(); //TODO: CombatStop(true) may cause crash (interrupt spells)
DeleteThreatList();
@@ -13414,7 +13438,6 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess)
// Set charmed
setFaction(charmer->getFaction());
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
charmer->SetCharm(this, true);
if(GetTypeId() == TYPEID_UNIT)