From b20b3e5adee0b8195ed339d4879db80c285f1a08 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 20 Nov 2010 07:09:39 +0300 Subject: [PATCH] [10757] Implement zone limited pets unsummon at leave allowed zones. * Also remove redundant zone/area args for zone/area update function like UpdateZoneDependentAuras. * Merge Player::*AllControlledUnits functions to Unit version with replace option args by mask arg. * Unit::*AllControlledUnits guardian iteration make working with internal unsummon call suport for guardians case. --- src/game/Player.cpp | 45 +++++++++++++++++++++-------- src/game/Player.h | 31 ++------------------ src/game/SpellAuras.cpp | 2 +- src/game/SpellEffects.cpp | 2 +- src/game/Unit.cpp | 19 ++++++------- src/game/Unit.h | 59 ++++++++++++++++++++++++++------------- src/shared/revision_nr.h | 2 +- 7 files changed, 88 insertions(+), 72 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 2b5def1cd..821195746 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2359,7 +2359,7 @@ void Player::SetGameMaster(bool on) setFaction(35); SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); - CallForAllControlledUnits(SetGameMasterOnHelper(),true,true,true,false); + CallForAllControlledUnits(SetGameMasterOnHelper(), CONTROLED_PET|CONTROLED_TOTEMS|CONTROLED_GUARDIANS|CONTROLED_CHARM); SetFFAPvP(false); ResetContestedPvP(); @@ -2379,7 +2379,7 @@ void Player::SetGameMaster(bool on) setFactionForRace(getRace()); RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); - CallForAllControlledUnits(SetGameMasterOffHelper(getFaction()),true,true,true,false); + CallForAllControlledUnits(SetGameMasterOffHelper(getFaction()), CONTROLED_PET|CONTROLED_TOTEMS|CONTROLED_GUARDIANS|CONTROLED_CHARM); // restore FFA PvP Server state if(sWorld.IsFFAPvPRealm()) @@ -6708,7 +6708,7 @@ void Player::UpdateArea(uint32 newArea) CastSpell(this, 58730, true); */ } - UpdateAreaDependentAuras(newArea); + UpdateAreaDependentAuras(); } void Player::UpdateZone(uint32 newZone, uint32 newArea) @@ -6801,7 +6801,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) if(GetGroup()) SetGroupUpdateFlag(GROUP_UPDATE_FLAG_ZONE); - UpdateZoneDependentAuras(newZone); + UpdateZoneDependentAuras(); + UpdateZoneDependentPets(); } //If players are too far way of duel flag... then player loose the duel @@ -20575,23 +20576,23 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) GetSession()->SendPacket(&data); } -void Player::UpdateZoneDependentAuras( uint32 newZone ) +void Player::UpdateZoneDependentAuras() { // Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update - SpellAreaForAreaMapBounds saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(newZone); + SpellAreaForAreaMapBounds saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(m_zoneUpdateId); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if(itr->second->autocast && itr->second->IsFitToRequirements(this,newZone,0)) + if(itr->second->autocast && itr->second->IsFitToRequirements(this, m_zoneUpdateId, 0)) if (!HasAura(itr->second->spellId, EFFECT_INDEX_0)) CastSpell(this,itr->second->spellId,true); } -void Player::UpdateAreaDependentAuras( uint32 newArea ) +void Player::UpdateAreaDependentAuras() { // remove auras from spells with area limitations for(SpellAuraHolderMap::iterator iter = m_spellAuraHolders.begin(); iter != m_spellAuraHolders.end();) { // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date - if(sSpellMgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this) != SPELL_CAST_OK) + if(sSpellMgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(), GetMapId(), m_zoneUpdateId, m_areaUpdateId, this) != SPELL_CAST_OK) { RemoveSpellAuraHolder(iter->second); iter = m_spellAuraHolders.begin(); @@ -20601,13 +20602,35 @@ void Player::UpdateAreaDependentAuras( uint32 newArea ) } // some auras applied at subzone enter - SpellAreaForAreaMapBounds saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(newArea); + SpellAreaForAreaMapBounds saBounds = sSpellMgr.GetSpellAreaForAreaMapBounds(m_areaUpdateId); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if(itr->second->autocast && itr->second->IsFitToRequirements(this,m_zoneUpdateId,newArea)) + if(itr->second->autocast && itr->second->IsFitToRequirements(this, m_zoneUpdateId, m_areaUpdateId)) if (!HasAura(itr->second->spellId, EFFECT_INDEX_0)) CastSpell(this,itr->second->spellId,true); } +struct UpdateZoneDependentPetsHelper +{ + explicit UpdateZoneDependentPetsHelper(Player* _owner, uint32 zone, uint32 area) : owner(_owner), zone_id(zone), area_id(area) {} + void operator()(Unit* unit) const + { + if (unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->IsPet() && !((Pet*)unit)->IsPermanentPetFor(owner)) + if (uint32 spell_id = unit->GetUInt32Value(UNIT_CREATED_BY_SPELL)) + if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell_id)) + if (sSpellMgr.GetSpellAllowedInLocationError(spellEntry, owner->GetMapId(), zone_id, area_id, owner) != SPELL_CAST_OK) + ((Pet*)unit)->Unsummon(PET_SAVE_AS_DELETED, owner); + } + Player* owner; + uint32 zone_id; + uint32 area_id; +}; + +void Player::UpdateZoneDependentPets() +{ + // check pet (permanent pets ignored), minipet, guardians (including protector) + CallForAllControlledUnits(UpdateZoneDependentPetsHelper(this, m_zoneUpdateId, m_areaUpdateId), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_MINIPET); +} + uint32 Player::GetCorpseReclaimDelay(bool pvp) const { if ((pvp && !sWorld.getConfig(CONFIG_BOOL_DEATH_CORPSE_RECLAIM_DELAY_PVP)) || diff --git a/src/game/Player.h b/src/game/Player.h index 72ec18cfd..67daa22d9 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1215,11 +1215,6 @@ class MANGOS_DLL_SPEC Player : public Unit void RemovePet(PetSaveMode mode); - template - void CallForAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet); - template - bool CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet) const; - uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn void Say(const std::string& text, const uint32 language); @@ -1772,8 +1767,9 @@ class MANGOS_DLL_SPEC Player : public Unit void UpdateZone(uint32 newZone,uint32 newArea); void UpdateArea(uint32 newArea); - void UpdateZoneDependentAuras( uint32 zone_id ); // zones - void UpdateAreaDependentAuras( uint32 area_id ); // subzones + void UpdateZoneDependentAuras(); + void UpdateAreaDependentAuras(); // subzones + void UpdateZoneDependentPets(); void UpdateAfkReport(time_t currTime); void UpdatePvPFlag(time_t currTime); @@ -2758,25 +2754,4 @@ template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas return T(diff); } -template -void Player::CallForAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet) -{ - if (withMiniPet) - if(Unit* mini = GetMiniPet()) - func(mini); - - Unit::CallForAllControlledUnits(func,withTotems,withGuardians,withCharms); -} - -template -bool Player::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet) const -{ - if (withMiniPet) - if(Unit const* mini = GetMiniPet()) - if (func(mini)) - return true; - - return Unit::CheckAllControlledUnits(func,withTotems,withGuardians,withCharms); -} - #endif diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 88cb2a5fd..8957c8acf 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1032,7 +1032,7 @@ void Aura::ReapplyAffectedPassiveAuras() ReapplyAffectedPassiveAuras(GetTarget(), true); // re-apply talents/passives/area auras applied to pet/totems (it affected by player spellmods) - GetTarget()->CallForAllControlledUnits(ReapplyAffectedPassiveAurasHelper(this),true,false,false); + GetTarget()->CallForAllControlledUnits(ReapplyAffectedPassiveAurasHelper(this), CONTROLED_PET|CONTROLED_TOTEMS); // re-apply talents/passives/area auras applied to group members (it affected by player spellmods) if (Group* group = ((Player*)GetTarget())->GetGroup()) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 728de3220..88b31a042 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -6188,7 +6188,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx) { // Is this all to be done at completion? if (Pet* pPet = m_caster->FindGuardianWithEntry(pSpell->EffectMiscValue[EFFECT_INDEX_0])) - pPet->Unsummon(PET_SAVE_NOT_IN_SLOT, m_caster); + pPet->Unsummon(PET_SAVE_AS_DELETED, m_caster); } return; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f0dfc3395..53dedfdf5 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5702,7 +5702,7 @@ struct CombatStopWithPetsHelper void Unit::CombatStopWithPets(bool includingCast) { CombatStop(includingCast); - CallForAllControlledUnits(CombatStopWithPetsHelper(includingCast),false,true,true); + CallForAllControlledUnits(CombatStopWithPetsHelper(includingCast), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_CHARM); } struct IsAttackingPlayerHelper @@ -5716,7 +5716,7 @@ bool Unit::isAttackingPlayer() const if(hasUnitState(UNIT_STAT_ATTACK_PLAYER)) return true; - return CheckAllControlledUnits(IsAttackingPlayerHelper(),true,true,true); + return CheckAllControlledUnits(IsAttackingPlayerHelper(), CONTROLED_PET|CONTROLED_TOTEMS|CONTROLED_GUARDIANS|CONTROLED_CHARM); } void Unit::RemoveAllAttackers() @@ -8093,7 +8093,7 @@ struct UpdateWalkModeHelper void Unit::UpdateWalkMode(Unit* source, bool self) { if (GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->CallForAllControlledUnits(UpdateWalkModeHelper(source), false, true, true, true); + CallForAllControlledUnits(UpdateWalkModeHelper(source), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_CHARM|CONTROLED_MINIPET); else if (self) { bool on = source->GetTypeId() == TYPEID_PLAYER @@ -8112,7 +8112,7 @@ void Unit::UpdateWalkMode(Unit* source, bool self) } } else - CallForAllControlledUnits(UpdateWalkModeHelper(source), false, true, true); + CallForAllControlledUnits(UpdateWalkModeHelper(source), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_CHARM|CONTROLED_MINIPET); } void Unit::UpdateSpeed(UnitMoveType mtype, bool forced, float ratio) @@ -8361,10 +8361,7 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate, bool forced) SendMessageToSet( &data, true ); } - if (GetTypeId() == TYPEID_PLAYER) // need include minpet - ((Player*)this)->CallForAllControlledUnits(SetSpeedRateHelper(mtype,forced),false,true,true,true); - else - CallForAllControlledUnits(SetSpeedRateHelper(mtype,forced),false,true,true); + CallForAllControlledUnits(SetSpeedRateHelper(mtype,forced), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_CHARM|CONTROLED_MINIPET); } void Unit::SetHover(bool on) @@ -10514,7 +10511,7 @@ void Unit::SetPvP( bool state ) else RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); - CallForAllControlledUnits(SetPvPHelper(state),true,true,true); + CallForAllControlledUnits(SetPvPHelper(state), CONTROLED_PET|CONTROLED_TOTEMS|CONTROLED_GUARDIANS|CONTROLED_CHARM); } struct SetFFAPvPHelper @@ -10531,7 +10528,7 @@ void Unit::SetFFAPvP( bool state ) else RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); - CallForAllControlledUnits(SetFFAPvPHelper(state),true,true,true); + CallForAllControlledUnits(SetFFAPvPHelper(state), CONTROLED_PET|CONTROLED_TOTEMS|CONTROLED_GUARDIANS|CONTROLED_CHARM); } void Unit::KnockBackFrom(Unit* target, float horizontalSpeed, float verticalSpeed) @@ -10693,7 +10690,7 @@ void Unit::StopAttackFaction(uint32 faction_id) getHostileRefManager().deleteReferencesForFaction(faction_id); - CallForAllControlledUnits(StopAttackFactionHelper(faction_id),false,true,true); + CallForAllControlledUnits(StopAttackFactionHelper(faction_id), CONTROLED_PET|CONTROLED_GUARDIANS|CONTROLED_CHARM); } void Unit::CleanupDeletedAuras() diff --git a/src/game/Unit.h b/src/game/Unit.h index b8152ad81..bf704ced4 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1110,6 +1110,16 @@ struct CharmInfo GlobalCooldownMgr m_GlobalCooldownMgr; }; +// used in CallForAllControlledUnits/CheckAllControlledUnits +enum ControledUnitMask +{ + CONTROLED_PET = 0x01, + CONTROLED_MINIPET = 0x02, + CONTROLED_GUARDIANS = 0x04, // including PROTECTOR_PET + CONTROLED_CHARM = 0x08, + CONTROLED_TOTEMS = 0x10, +}; + // for clearing special attacks #define REACTIVE_TIMER_START 4000 @@ -1556,9 +1566,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void _RemoveTotem(Totem* totem); // only for call from Totem class template - void CallForAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms); + void CallForAllControlledUnits(Func const& func, uint32 controledMask); template - bool CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) const; + bool CheckAllControlledUnits(Func const& func, uint32 controledMask) const; bool AddSpellAuraHolder(SpellAuraHolder *holder); void AddAuraToModList(Aura *aura); @@ -2017,48 +2027,59 @@ class MANGOS_DLL_SPEC Unit : public WorldObject }; template -void Unit::CallForAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) +void Unit::CallForAllControlledUnits(Func const& func, uint32 controledMask) { - if (Pet* pet = GetPet()) - func(pet); + if (controledMask & CONTROLED_PET) + if (Pet* pet = GetPet()) + func(pet); - if (withGuardians) + if (controledMask & CONTROLED_MINIPET) + if (Unit* mini = GetMiniPet()) + func(mini); + + if (controledMask & CONTROLED_GUARDIANS) { - for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) - if (Pet* guardian = _GetPet(*itr)) + for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end();) + if (Pet* guardian = _GetPet(*(itr++))) func(guardian); } - if (withTotems) + if (controledMask & CONTROLED_TOTEMS) { for (int i = 0; i < MAX_TOTEM_SLOT; ++i) if (Unit *totem = _GetTotem(TotemSlot(i))) func(totem); } - if (withCharms) + if (controledMask & CONTROLED_CHARM) if (Unit* charm = GetCharm()) func(charm); } template -bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) const +bool Unit::CheckAllControlledUnits(Func const& func, uint32 controledMask) const { - if (Pet const* pet = GetPet()) - if (func(pet)) - return true; + if (controledMask & CONTROLED_PET) + if (Pet const* pet = GetPet()) + if (func(pet)) + return true; - if (withGuardians) + if (controledMask & CONTROLED_MINIPET) + if(Unit const* mini = GetMiniPet()) + if (func(mini)) + return true; + + if (controledMask & CONTROLED_GUARDIANS) { - for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) - if (Pet const* guardian = _GetPet(*itr)) + for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end();) + if (Pet const* guardian = _GetPet(*(itr++))) if (func(guardian)) return true; } - if (withTotems) + if (controledMask & CONTROLED_TOTEMS) { for (int i = 0; i < MAX_TOTEM_SLOT; ++i) if (Unit const* totem = _GetTotem(TotemSlot(i))) @@ -2066,7 +2087,7 @@ bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withG return true; } - if (withCharms) + if (controledMask & CONTROLED_CHARM) if (Unit const* charm = GetCharm()) if (func(charm)) return true; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5cc0539c6..464b0dbf2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10756" + #define REVISION_NR "10757" #endif // __REVISION_NR_H__