diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index b0a3a60a9..344837ca8 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -50,11 +50,10 @@ GameObject::GameObject() : WorldObject() m_respawnDelayTime = 25; m_lootState = GO_NOT_READY; m_spawnedByDefault = true; - m_usetimes = 0; + m_useTimes = 0; m_spellId = 0; m_cooldownTime = 0; m_goInfo = NULL; - m_ritualOwner = NULL; m_DBTableGuid = 0; m_rotation = 0; @@ -219,8 +218,7 @@ void GameObject::Update(uint32 /*p_time*/) if (m_respawnTime <= time(NULL)) // timer expired { m_respawnTime = 0; - m_SkillupList.clear(); - m_usetimes = 0; + ClearAllUsesData(); switch (GetGoType()) { @@ -336,9 +334,9 @@ void GameObject::Update(uint32 /*p_time*/) if (uint32 max_charges = goInfo->GetCharges()) { - if (m_usetimes >= max_charges) + if (m_useTimes >= max_charges) { - m_usetimes = 0; + m_useTimes = 0; SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed } } @@ -377,16 +375,11 @@ void GameObject::Update(uint32 /*p_time*/) if(spellId) { - std::set::const_iterator it = m_unique_users.begin(); - std::set::const_iterator end = m_unique_users.end(); - for (; it != end; it++) - { - if (Unit* owner = Unit::GetUnit(*this, uint64(*it))) + for (GuidsSet::const_iterator itr = m_UniqueUsers.begin(); itr != m_UniqueUsers.end(); ++itr) + if (Player* owner = GetMap()->GetPlayer(*itr)) owner->CastSpell(owner, spellId, false, NULL, NULL, GetGUID()); - } - m_unique_users.clear(); - m_usetimes = 0; + ClearAllUsesData(); } SetGoState(GO_STATE_READY); @@ -451,7 +444,12 @@ void GameObject::Refresh() void GameObject::AddUniqueUse(Player* player) { AddUse(); - m_unique_users.insert(player->GetGUIDLow()); + + if (m_firstUser.IsEmpty()) + m_firstUser = player->GetObjectGuid(); + + m_UniqueUsers.insert(player->GetObjectGuid()); + } void GameObject::Delete() @@ -1179,10 +1177,6 @@ void GameObject::Use(Unit* user) GameObjectInfo const* info = GetGOInfo(); - // ritual owner is set for GO's without owner (not summoned) - if (!m_ritualOwner && !owner) - m_ritualOwner = player; - if (owner) { if (owner->GetTypeId() != TYPEID_PLAYER) @@ -1201,8 +1195,16 @@ void GameObject::Use(Unit* user) } else { - if (player != m_ritualOwner && (info->summoningRitual.castersGrouped && !player->IsInSameRaidWith(m_ritualOwner))) - return; + if (!m_firstUser.IsEmpty() && player->GetObjectGuid() != m_firstUser && info->summoningRitual.castersGrouped) + { + if (Group* group = player->GetGroup()) + { + if (!group->IsMember(m_firstUser)) + return; + } + else + return; + } spellCaster = player; } @@ -1217,40 +1219,31 @@ void GameObject::Use(Unit* user) triggered = true; } - // full amount unique participants including original summoner - if (GetUniqueUseCount() == info->summoningRitual.reqParticipants) - { - spellCaster = m_ritualOwner ? m_ritualOwner : spellCaster; - - spellId = info->summoningRitual.spellId; - - if (spellId == 62330) // GO store nonexistent spell, replace by expected - { - // spell have reagent and mana cost but it not expected use its - // it triggered spell in fact casted at currently channeled GO - spellId = 61993; - triggered = true; - } - - // finish owners spell - if (owner) - owner->FinishSpell(CURRENT_CHANNELED_SPELL); - - // can be deleted now, if - if (!info->summoningRitual.ritualPersistent) - SetLootState(GO_JUST_DEACTIVATED); - else - { - // reset ritual for this GO - m_ritualOwner = NULL; - m_unique_users.clear(); - m_usetimes = 0; - } - } - else - { + // full amount unique participants including original summoner, need more + if (GetUniqueUseCount() < info->summoningRitual.reqParticipants) return; - } + + spellCaster = GetMap()->GetPlayer(m_firstUser); + + spellId = info->summoningRitual.spellId; + + if (spellId == 62330) // GO store nonexistent spell, replace by expected + spellId = 61993; + + // spell have reagent and mana cost but it not expected use its + // it triggered spell in fact casted at currently channeled GO + triggered = true; + + // finish owners spell + if (owner) + owner->FinishSpell(CURRENT_CHANNELED_SPELL); + + // can be deleted now, if + if (!info->summoningRitual.ritualPersistent) + SetLootState(GO_JUST_DEACTIVATED); + // reset ritual for this GO + else + ClearAllUsesData(); // go to end function to spell casting break; @@ -1575,4 +1568,14 @@ float GameObject::GetObjectBoundingRadius() const return fabs(dispEntry->unknown12) * GetObjectScale(); return DEFAULT_WORLD_OBJECT_SIZE; +} + +bool GameObject::IsInSkillupList(Player* player) const +{ + return m_SkillupSet.find(player->GetObjectGuid()) != m_SkillupSet.end(); +} + +void GameObject::AddToSkillupList(Player* player) +{ + m_SkillupSet.insert(player->GetObjectGuid()); } \ No newline at end of file diff --git a/src/game/GameObject.h b/src/game/GameObject.h index b2c5abf0f..08e079618 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -667,20 +667,22 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject LootState getLootState() const { return m_lootState; } void SetLootState(LootState s) { m_lootState = s; } - void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); } - bool IsInSkillupList(uint32 PlayerGuidLow) const + void AddToSkillupList(Player* player); + bool IsInSkillupList(Player* player) const; + void ClearSkillupList() { m_SkillupSet.clear(); } + void ClearAllUsesData() { - for (std::list::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i) - if (*i == PlayerGuidLow) return true; - return false; + ClearSkillupList(); + m_useTimes = 0; + m_firstUser.Clear(); + m_UniqueUsers.clear(); } - void ClearSkillupList() { m_SkillupList.clear(); } void AddUniqueUse(Player* player); - void AddUse() { ++m_usetimes; } + void AddUse() { ++m_useTimes; } - uint32 GetUseCount() const { return m_usetimes; } - uint32 GetUniqueUseCount() const { return m_unique_users.size(); } + uint32 GetUseCount() const { return m_useTimes; } + uint32 GetUniqueUseCount() const { return m_UniqueUsers.size(); } void SaveRespawnTime(); @@ -714,11 +716,16 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject bool m_spawnedByDefault; time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction). // For traps this: spell casting cooldown, for doors/buttons: reset time. - std::list m_SkillupList; - Player* m_ritualOwner; // used for GAMEOBJECT_TYPE_SUMMONING_RITUAL where GO is not summoned (no owner) - std::set m_unique_users; - uint32 m_usetimes; + typedef std::set GuidsSet; + + GuidsSet m_SkillupSet; // players that already have skill-up at GO use + + uint32 m_useTimes; // amount uses/charges triggered + + // collected only for GAMEOBJECT_TYPE_SUMMONING_RITUAL + ObjectGuid m_firstUser; // first GO user, in most used cases owner, but in some cases no, for example non-summoned multi-use GAMEOBJECT_TYPE_SUMMONING_RITUAL + GuidsSet m_UniqueUsers; // all players who use item, some items activated after specific amount unique uses uint32 m_DBTableGuid; ///< For new or temporary gameobjects is 0 for saved it is lowguid GameObjectInfo const* m_goInfo; diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 8e2c19126..0d96249c7 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -364,7 +364,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more - go->AddUse(); // if the max usage is reached, will be despawned in next tick + go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index a37dc5e79..5677cdbc8 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3731,9 +3731,9 @@ void Spell::EffectOpenLock(SpellEffectIndex eff_idx) if (gameObjTarget) { // Allow one skill-up until respawned - if (!gameObjTarget->IsInSkillupList(player->GetGUIDLow()) && + if (!gameObjTarget->IsInSkillupList(player) && player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue)) - gameObjTarget->AddToSkillupList(player->GetGUIDLow()); + gameObjTarget->AddToSkillupList(player); } else if (itemTarget) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 76d7796c8..0bbd40ad0 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 "10382" + #define REVISION_NR "10383" #endif // __REVISION_NR_H__