From 9e6390d88dca78a7f3982d4e063e84ece67b8b21 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 27 Oct 2008 16:43:31 +0300 Subject: [PATCH] Load npc_options at server startup, use cached data at creature gossip menu init. Also new .reload table command added. Note: currently it will not affect creatures that have gossim memu created at command use moment. --- src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Creature.cpp | 42 +++++++++++---------------------------- src/game/Creature.h | 2 +- src/game/Level3.cpp | 9 +++++++++ src/game/ObjectMgr.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ src/game/ObjectMgr.h | 5 +++++ src/game/World.cpp | 3 +++ 8 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 86e96d5bf..d0cdfc25c 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -228,6 +228,7 @@ ChatCommand * ChatHandler::getCommandTable() { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL }, { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, + { "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL }, { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL }, { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index c91f0b673..6006bfa76 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -183,6 +183,7 @@ class ChatHandler bool HandleReloadLootTemplatesSkinningCommand(const char* args); bool HandleReloadMangosStringCommand(const char* args); bool HandleReloadNpcGossipCommand(const char* args); + bool HandleReloadNpcOptionCommand(const char* args); bool HandleReloadNpcTrainerCommand(const char* args); bool HandleReloadNpcVendorCommand(const char* args); bool HandleReloadQuestAreaTriggersCommand(const char* args); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 34f7b1ee9..783a1a7c1 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -668,12 +668,9 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) // lazy loading single time at use LoadGossipOptions(); - GossipOption* gso; - GossipOption* ingso; - for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) { - gso=&*i; + GossipOption* gso=&*i; if(gso->GossipId == gossipid) { bool cantalking=true; @@ -746,11 +743,9 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) } } - if(!gso->Option.empty() && cantalking ) - { //note for future dev: should have database fields for BoxMessage & BoxMoney - pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->Option, gossipid,gso->Action,"",0,false); - ingso=gso; - } + //note for future dev: should have database fields for BoxMessage & BoxMoney + if(!gso->OptionText.empty() && cantalking) + pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,gso->OptionText, gossipid,gso->Action,"",0,false); } } @@ -797,8 +792,8 @@ void Creature::OnGossipSelect(Player* player, uint32 option) uint32 action=gossipmenu.GetItem(option).m_gAction; uint32 zoneid=GetZoneId(); uint64 guid=GetGUID(); + GossipOption const *gossip=GetGossipOption( action ); - uint32 textid; if(!gossip) { zoneid=0; @@ -806,7 +801,8 @@ void Creature::OnGossipSelect(Player* player, uint32 option) if(!gossip) return; } - textid=GetGossipTextId( action, zoneid); + + uint32 textid=GetGossipTextId( action, zoneid); if(textid==0) textid=GetNpcTextId(); @@ -895,7 +891,7 @@ void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) Map const* map=MapManager::Instance().GetBaseMap( mapid ); uint16 areaflag=map->GetAreaFlag(GetPositionX(),GetPositionY()); uint32 zoneid=Map::GetZoneId(areaflag,mapid); - std::string areaname= gossip->Option; + std::string areaname= gossip->OptionText; /* uint16 pflag; @@ -989,24 +985,10 @@ void Creature::LoadGossipOptions() uint32 npcflags=GetUInt32Value(UNIT_NPC_FLAGS); - QueryResult *result = WorldDatabase.PQuery( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option WHERE (npcflag & %u)<>0", npcflags ); - - if(!result) - return; - - GossipOption go; - do - { - Field *fields = result->Fetch(); - go.Id= fields[0].GetUInt32(); - go.GossipId = fields[1].GetUInt32(); - go.NpcFlag=fields[2].GetUInt32(); - go.Icon=fields[3].GetUInt32(); - go.Action=fields[4].GetUInt32(); - go.Option=fields[5].GetCppString(); - addGossipOption(go); - }while( result->NextRow() ); - delete result; + CacheNpcOptionList const& noList = objmgr.GetNpcOptions (); + for (CacheNpcOptionList::const_iterator i = noList.begin (); i != noList.end (); ++i) + if(i->NpcFlag & npcflags) + addGossipOption(*i); m_gossipOptionLoaded = true; } diff --git a/src/game/Creature.h b/src/game/Creature.h index 5d0ff9cf7..678c6e14a 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -109,7 +109,7 @@ struct GossipOption uint32 NpcFlag; uint32 Icon; uint32 Action; - std::string Option; + std::string OptionText; }; enum CreatureFlagsExtra diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index fbf235738..71e67ecdf 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -100,6 +100,7 @@ bool ChatHandler::HandleReloadAllLootCommand(const char*) bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/) { HandleReloadNpcGossipCommand("a"); + HandleReloadNpcOptionCommand("a"); HandleReloadNpcTrainerCommand("a"); HandleReloadNpcVendorCommand("a"); return true; @@ -345,6 +346,14 @@ bool ChatHandler::HandleReloadMangosStringCommand(const char*) return true; } +bool ChatHandler::HandleReloadNpcOptionCommand(const char*) +{ + sLog.outString( "Re-Loading `npc_option` Table!" ); + objmgr.LoadNpcOptions(); + SendGlobalSysMessage("DB table `npc_option` reloaded."); + return true; +} + bool ChatHandler::HandleReloadNpcGossipCommand(const char*) { sLog.outString( "Re-Loading `npc_gossip` Table!" ); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 9720564bf..eeee3a4a0 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6882,6 +6882,51 @@ void ObjectMgr::LoadNpcTextId() sLog.outString( ">> Loaded %d NpcTextId ", count ); } +void ObjectMgr::LoadNpcOptions() +{ + m_mCacheNpcOptionList.clear(); // For reload case + + QueryResult *result = WorldDatabase.Query( "SELECT id,gossip_id,npcflag,icon,action,option_text FROM npc_option"); + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `npc_option`, table is empty!"); + return; + } + + barGoLink bar( result->GetRowCount() ); + + uint32 count = 0; + + do + { + bar.step(); + + Field* fields = result->Fetch(); + + GossipOption go; + go.Id = fields[0].GetUInt32(); + go.GossipId = fields[1].GetUInt32(); + go.NpcFlag = fields[2].GetUInt32(); + go.Icon = fields[3].GetUInt32(); + go.Action = fields[4].GetUInt32(); + go.OptionText = fields[5].GetCppString(); + + m_mCacheNpcOptionList.push_back(go); + + ++count; + + } while (result->NextRow()); + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %d npc_option entries", count ); +} + void ObjectMgr::AddVendorItem( uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 extendedcost ) { VendorItemData& vList = m_mCacheVendorItemMap[entry]; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 982b9a4a9..e7a03d3a4 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -229,6 +229,7 @@ struct PlayerCondition // NPC gossip text id typedef HM_NAMESPACE::hash_map CacheNpcTextIdMap; +typedef std::list CacheNpcOptionList; typedef HM_NAMESPACE::hash_map CacheVendorItemMap; typedef HM_NAMESPACE::hash_map CacheTrainerSpellMap; @@ -544,6 +545,7 @@ class ObjectMgr void LoadWeatherZoneChances(); void LoadGameTele(); + void LoadNpcOptions(); void LoadNpcTextId(); void LoadVendors(); void LoadTrainerSpell(); @@ -712,6 +714,8 @@ class ObjectMgr bool AddGameTele(GameTele& data); bool DeleteGameTele(std::string name); + CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; } + uint32 GetNpcGossip(uint32 entry) const { CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry); @@ -850,6 +854,7 @@ class ObjectMgr typedef std::vector ConditionStore; ConditionStore mConditions; + CacheNpcOptionList m_mCacheNpcOptionList; CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheVendorItemMap m_mCacheVendorItemMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap; diff --git a/src/game/World.cpp b/src/game/World.cpp index 1496e7be3..135493f7d 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1111,6 +1111,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Npc Text Id..." ); objmgr.LoadNpcTextId(); // must be after load Creature and NpcText + sLog.outString( "Loading Npc Options..." ); + objmgr.LoadNpcOptions(); + sLog.outString( "Loading vendors..." ); objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate