diff options
-rw-r--r-- | src/game/Player.cpp | 92 | ||||
-rw-r--r-- | src/game/Player.h | 11 | ||||
-rw-r--r-- | src/game/Unit.cpp | 35 |
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) |