*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; 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,23 +6265,18 @@ 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.
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) // 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
if(isAlive()) 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) 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
View File
@@ -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
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) //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)