diff options
author | megamage <none@none> | 2009-06-15 23:07:43 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-06-15 23:07:43 -0500 |
commit | 00f4a31b735f327b715ff12d82f78de33c95539e (patch) | |
tree | eedf5857ff1a8be6bbbb7eb98b005565a07b9cb5 /src | |
parent | 572a9191d970b9b960555c8a5d31efd3160a8b44 (diff) |
[8016] Work at npc click table data use. Author: VladimirMangos
* New fields in `npc_spellclick_spells` for allow set npc spell click mode from quest to infinity
or to another quest, or from reward quest.
* Not expect (and forbid set UNIT_NPC_FLAG_SPELLCLICK in DB and set it at `npc_spellclick_spells` loading.
* Apply some speedups for creature checks affected by spel click state
*Also add target position of 51852. By Roland
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/ObjectMgr.cpp | 62 | ||||
-rw-r--r-- | src/game/ObjectMgr.h | 17 | ||||
-rw-r--r-- | src/game/Player.cpp | 25 | ||||
-rw-r--r-- | src/game/SpellHandler.cpp | 6 | ||||
-rw-r--r-- | src/game/Unit.h | 2 |
5 files changed, 84 insertions, 28 deletions
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 20ace65d79b..867da4401d3 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -110,6 +110,25 @@ LanguageDesc const* GetLanguageDescByID(uint32 lang) return NULL; } +bool SpellClickInfo::IsFitToRequirements(Player const* player) const +{ + if(questStart) + { + // not in expected required quest state + if(!player || (!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)) + return false; + } + + if(questEnd) + { + // not in expected forbidden quest state + if(!player || player->GetQuestRewardStatus(questEnd)) + return false; + } + + return true; +} + ObjectMgr::ObjectMgr() { m_hiCharGuid = 1; @@ -699,6 +718,12 @@ void ObjectMgr::LoadCreatureTemplates() if(cInfo->rangeattacktime == 0) const_cast<CreatureInfo*>(cInfo)->rangeattacktime = BASE_ATTACK_TIME; + if(cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK) + { + sLog.outErrorDb("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it expect to be set by code base at `npc_spellclick_spells` content.",cInfo->Entry,UNIT_NPC_FLAG_SPELLCLICK); + const_cast<CreatureInfo*>(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; + } + if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE) sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type); @@ -6567,8 +6592,8 @@ void ObjectMgr::LoadNPCSpellClickSpells() uint32 count = 0; mSpellClickInfoMap.clear(); - - QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_id, quest_status, cast_flags FROM npc_spellclick_spells"); + // 0 1 2 3 4 5 + QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags FROM npc_spellclick_spells"); if(!result) { @@ -6607,28 +6632,45 @@ void ObjectMgr::LoadNPCSpellClickSpells() continue; } - uint32 quest = fields[2].GetUInt32(); + uint32 quest_start = fields[2].GetUInt32(); // quest might be 0 to enable spellclick independent of any quest - if (quest) + if (quest_start) { - if(mQuestTemplates.find(quest) == mQuestTemplates.end()) + if(mQuestTemplates.find(quest_start) == mQuestTemplates.end()) { - sLog.outErrorDb("Table npc_spellclick_spells references unknown quest %u. Skipping entry.", spellid); + sLog.outErrorDb("Table npc_spellclick_spells references unknown start quest %u. Skipping entry.", quest_start); continue; } } - uint32 queststatus = fields[3].GetUInt32(); + bool quest_start_active = fields[3].GetBool(); + + uint32 quest_end = fields[4].GetUInt32(); + // quest might be 0 to enable spellclick active infinity after start quest + if (quest_end) + { + if(mQuestTemplates.find(quest_end) == mQuestTemplates.end()) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown end quest %u. Skipping entry.", quest_end); + continue; + } + + } - uint8 castFlags = fields[4].GetUInt8(); + uint8 castFlags = fields[5].GetUInt8(); SpellClickInfo info; info.spellId = spellid; - info.questId = quest; - info.questStatus = queststatus; + info.questStart = quest_start; + info.questStartCanActive = quest_start_active; + info.questEnd = quest_end; info.castFlags = castFlags; mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info)); + + // mark creature template as spell clickable + const_cast<CreatureInfo*>(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK; + ++count; } while (result->NextRow()); diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index a508c573ef6..0c032bc8ec3 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -102,12 +102,17 @@ extern ScriptMapMap sWaypointScripts; struct SpellClickInfo { uint32 spellId; - uint32 questId; - uint32 questStatus; + uint32 questStart; // quest start (quest must be active or rewarded for spell apply) + uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) + bool questStartCanActive; // if true then quest start can be active (not only rewarded) uint8 castFlags; + + // helpers + bool IsFitToRequirements(Player const* player) const; }; typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoMap; +typedef std::pair<SpellClickInfoMap::const_iterator,SpellClickInfoMap::const_iterator> SpellClickInfoMapBounds; struct AreaTrigger { @@ -585,7 +590,6 @@ class ObjectMgr void LoadReputationOnKill(); void LoadPointsOfInterest(); - SpellClickInfoMap mSpellClickInfoMap; void LoadNPCSpellClickSpells(); void LoadWeatherZoneChances(); @@ -828,6 +832,11 @@ class ObjectMgr int GetOrNewIndexForLocale(LocaleConstant loc); + SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const + { + return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id)); + } + ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const { return ItemRequiredTargetMapBounds(m_ItemRequiredTarget.lower_bound(uiItemEntry),m_ItemRequiredTarget.upper_bound(uiItemEntry)); @@ -921,6 +930,8 @@ class ObjectMgr ScriptNameMap m_scriptNames; + SpellClickInfoMap mSpellClickInfoMap; + ItemRequiredTargetMap m_ItemRequiredTarget; typedef std::vector<LocaleConstant> LocalForIndex; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 19e5c7e02d2..af7057518fb 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19186,18 +19186,20 @@ void Player::UpdateForQuestWorldObjects() Creature *obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr); if(!obj) continue; + // check if this unit requires quest specific flags + if(!obj->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK)) + continue; - SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap; - for(SpellClickInfoMap::const_iterator itr = map.lower_bound(obj->GetEntry()); itr != map.upper_bound(obj->GetEntry()); ++itr) + SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(obj->GetEntry()); + for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { - if(itr->second.questId != 0) + if(itr->second.questStart || itr->second.questEnd) { obj->BuildCreateUpdateBlockForPlayer(&udata,this); break; } } - } } udata.BuildPacket(&packet); @@ -20754,16 +20756,17 @@ void Player::ResummonPetTemporaryUnSummonedIfAny() bool Player::canSeeSpellClickOn(Creature const *c) const { - SpellClickInfoMap::const_iterator lower = objmgr.mSpellClickInfoMap.lower_bound(c->GetEntry()); - SpellClickInfoMap::const_iterator upper = objmgr.mSpellClickInfoMap.upper_bound(c->GetEntry()); - if(lower == upper) + if(!c->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_SPELLCLICK)) + return false; + + SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(c->GetEntry()); + if(clickPair.first == clickPair.second) return true; - for(SpellClickInfoMap::const_iterator itr = lower; itr != upper; ++itr) - { - if(itr->second.questId == 0 || GetQuestStatus(itr->second.questId) == itr->second.questStatus) + for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) + if(itr->second.IsFitToRequirements(this)) return true; - } + return false; } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 1a9bc13eab8..74313eaa38b 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -522,10 +522,10 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) if(!unit) return; - SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap; - for(SpellClickInfoMap::const_iterator itr = map.lower_bound(unit->GetEntry()); itr != map.upper_bound(unit->GetEntry()); ++itr) + SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(unit->GetEntry()); + for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) { - if(itr->second.questId == 0 || _player->GetQuestStatus(itr->second.questId) == itr->second.questStatus) + if(itr->second.IsFitToRequirements(_player)) { Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; diff --git a/src/game/Unit.h b/src/game/Unit.h index 00478a74acd..ce1c0265268 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -614,7 +614,7 @@ enum NPCFlags UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100% UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode - UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click) + UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures }; |