aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/Player.cpp92
-rw-r--r--src/game/Player.h11
-rw-r--r--src/game/Unit.cpp35
3 files changed, 82 insertions, 56 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 12d106ecd13..db91a9abb95 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -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);
- }
}
}
diff --git a/src/game/Player.h b/src/game/Player.h
index 428981cdf34..597d1f67244 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -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);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 435190b8d10..1f7efb01c3e 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -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)