From a8bd65987244d7078f3366f1fc1b2c2e5b119a48 Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Tue, 1 Dec 2009 14:14:22 +0100 Subject: [PATCH] [8900] Move most gossip related functions from Creature to Player class Adjust arguments passed in functions accordingly, for easier implementation of gossip for Gameobjects in future. Some additional code cleanup in affected functions. --- src/game/Creature.cpp | 303 ---------------------------------- src/game/Creature.h | 9 +- src/game/NPCHandler.cpp | 27 +-- src/game/Player.cpp | 335 +++++++++++++++++++++++++++++++++++++- src/game/Player.h | 13 ++ src/game/QuestHandler.cpp | 4 +- src/shared/revision_nr.h | 2 +- 7 files changed, 365 insertions(+), 328 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 679951a9f..8cd094a85 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -744,309 +744,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const && pPlayer->getClass() == GetCreatureInfo()->trainer_class; } -void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) -{ - PlayerMenu* pm=pPlayer->PlayerTalkClass; - pm->ClearMenus(); - - // lazy loading single time at use - LoadGossipOptions(); - - for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); ++i ) - { - GossipOption* gso=&*i; - if(gso->GossipId == gossipid) - { - bool cantalking=true; - if(gso->Id==1) - { - uint32 textid=GetNpcTextId(); - GossipText const* gossiptext=sObjectMgr.GetGossipText(textid); - if(!gossiptext) - cantalking=false; - } - else - { - switch (gso->Action) - { - case GOSSIP_OPTION_QUESTGIVER: - pPlayer->PrepareQuestMenu(GetGUID()); - //if (pm->GetQuestMenu()->MenuItemCount() == 0) - cantalking=false; - //pm->GetQuestMenu()->ClearMenu(); - break; - case GOSSIP_OPTION_ARMORER: - cantalking=false; // added in special mode - break; - case GOSSIP_OPTION_SPIRITHEALER: - if( !pPlayer->isDead() ) - cantalking=false; - break; - case GOSSIP_OPTION_VENDOR: - { - VendorItemData const* vItems = GetVendorItems(); - if(!vItems || vItems->Empty()) - { - sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", - GetGUIDLow(),GetEntry()); - cantalking=false; - } - break; - } - case GOSSIP_OPTION_TRAINER: - if(!isCanTrainingOf(pPlayer,false)) - cantalking=false; - break; - case GOSSIP_OPTION_UNLEARNTALENTS: - if(!isCanTrainingAndResetTalentsOf(pPlayer)) - cantalking=false; - break; - case GOSSIP_OPTION_UNLEARNPETSKILLS: - if(!pPlayer->GetPet() || pPlayer->GetPet()->getPetType() != HUNTER_PET || pPlayer->GetPet()->m_spells.size() <= 1 || GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || GetCreatureInfo()->trainer_class != CLASS_HUNTER) - cantalking=false; - break; - case GOSSIP_OPTION_TAXIVENDOR: - if ( pPlayer->GetSession()->SendLearnNewTaxiNode(this) ) - return; - break; - case GOSSIP_OPTION_BATTLEFIELD: - if(!isCanInteractWithBattleMaster(pPlayer,false)) - cantalking=false; - break; - case GOSSIP_OPTION_SPIRITGUIDE: - case GOSSIP_OPTION_INNKEEPER: - case GOSSIP_OPTION_BANKER: - case GOSSIP_OPTION_PETITIONER: - case GOSSIP_OPTION_STABLEPET: - case GOSSIP_OPTION_TABARDDESIGNER: - case GOSSIP_OPTION_AUCTIONEER: - break; // no checks - default: - sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetDBTableGUIDLow(),GetEntry(),gso->Action); - break; - } - } - - //note for future dev: should have database fields for BoxMessage & BoxMoney - if(!gso->OptionText.empty() && cantalking) - { - std::string OptionText = gso->OptionText; - std::string BoxText = gso->BoxText; - int loc_idx = pPlayer->GetSession()->GetSessionDbLocaleIndex(); - if (loc_idx >= 0) - { - NpcOptionLocale const *no = sObjectMgr.GetNpcOptionLocale(gso->Id); - if (no) - { - if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty()) - OptionText=no->OptionText[loc_idx]; - if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty()) - BoxText=no->BoxText[loc_idx]; - } - } - pm->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded); - } - } - } - - ///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-) - if(pm->Empty()) - { - if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER)) - { - isCanTrainingOf(pPlayer,true); // output error message if need - } - if(HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER)) - { - isCanInteractWithBattleMaster(pPlayer,true); // output error message if need - } - } -} - -void Creature::sendPreparedGossip(Player* player) -{ - if(!player) - return; - - // in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag) - if (!HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !player->PlayerTalkClass->GetQuestMenu().Empty()) - { - player->SendPreparedQuest(GetGUID()); - return; - } - - // in case non empty gossip menu (that not included quests list size) show it - // (quest entries from quest menu will be included in list) - player->PlayerTalkClass->SendGossipMenu(GetNpcTextId(), GetGUID()); -} - -void Creature::OnGossipSelect(Player* player, uint32 option) -{ - GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); - - if(option >= gossipmenu.MenuItemCount()) - return; - - uint32 action=gossipmenu.GetItem(option).m_gAction; - uint32 zoneid=GetZoneId(); - uint64 guid=GetGUID(); - - GossipOption const *gossip=GetGossipOption( action ); - if(!gossip) - { - zoneid=0; - gossip=GetGossipOption( action ); - if(!gossip) - return; - } - - switch (gossip->Action) - { - case GOSSIP_OPTION_GOSSIP: - { - uint32 textid = GetGossipTextId(action, zoneid); - if (textid == 0) - textid=GetNpcTextId(); - - player->PlayerTalkClass->CloseGossip(); - player->PlayerTalkClass->SendTalking(textid); - break; - } - case GOSSIP_OPTION_SPIRITHEALER: - if (player->isDead()) - CastSpell(this,17251,true,NULL,NULL,player->GetGUID()); - break; - case GOSSIP_OPTION_QUESTGIVER: - player->PrepareQuestMenu( guid ); - player->SendPreparedQuest( guid ); - break; - case GOSSIP_OPTION_VENDOR: - case GOSSIP_OPTION_ARMORER: - player->GetSession()->SendListInventory(guid); - break; - case GOSSIP_OPTION_STABLEPET: - player->GetSession()->SendStablePet(guid); - break; - case GOSSIP_OPTION_TRAINER: - player->GetSession()->SendTrainerList(guid); - break; - case GOSSIP_OPTION_UNLEARNTALENTS: - player->PlayerTalkClass->CloseGossip(); - player->SendTalentWipeConfirm(guid); - break; - case GOSSIP_OPTION_UNLEARNPETSKILLS: - player->PlayerTalkClass->CloseGossip(); - player->SendPetSkillWipeConfirm(); - break; - case GOSSIP_OPTION_TAXIVENDOR: - player->GetSession()->SendTaxiMenu(this); - break; - case GOSSIP_OPTION_INNKEEPER: - player->PlayerTalkClass->CloseGossip(); - player->SetBindPoint( guid ); - break; - case GOSSIP_OPTION_BANKER: - player->GetSession()->SendShowBank( guid ); - break; - case GOSSIP_OPTION_PETITIONER: - player->PlayerTalkClass->CloseGossip(); - player->GetSession()->SendPetitionShowList( guid ); - break; - case GOSSIP_OPTION_TABARDDESIGNER: - player->PlayerTalkClass->CloseGossip(); - player->GetSession()->SendTabardVendorActivate( guid ); - break; - case GOSSIP_OPTION_AUCTIONEER: - player->GetSession()->SendAuctionHello( guid, this ); - break; - case GOSSIP_OPTION_SPIRITGUIDE: - case GOSSIP_GUARD_SPELLTRAINER: - case GOSSIP_GUARD_SKILLTRAINER: - prepareGossipMenu( player,gossip->Id ); - sendPreparedGossip( player ); - break; - case GOSSIP_OPTION_BATTLEFIELD: - { - BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); - if (bgTypeId == BATTLEGROUND_TYPE_NONE) - { - sLog.outError("a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", player->GetGUIDLow()); - return; - } - player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId ); - break; - } - default: - OnPoiSelect( player, gossip ); - break; - } - -} - -void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) -{ - if(gossip->GossipId==GOSSIP_GUARD_SPELLTRAINER || gossip->GossipId==GOSSIP_GUARD_SKILLTRAINER) - { - Poi_Icon icon = ICON_POI_BLANK; - //need add more case. - switch(gossip->Action) - { - case GOSSIP_GUARD_BANK: - icon=ICON_POI_SMALL_HOUSE; - break; - case GOSSIP_GUARD_RIDE: - icon=ICON_POI_RWHORSE; - break; - case GOSSIP_GUARD_GUILD: - icon=ICON_POI_BLUETOWER; - break; - default: - icon=ICON_POI_GREYTOWER; - break; - } - uint32 textid = GetGossipTextId( gossip->Action, GetZoneId() ); - player->PlayerTalkClass->SendTalking(textid); - // std::string areaname= gossip->OptionText; - // how this could worked player->PlayerTalkClass->SendPointOfInterest( x, y, icon, 2, 15, areaname.c_str() ); - } -} - -uint32 Creature::GetGossipTextId(uint32 action, uint32 zoneid) -{ - QueryResult *result= WorldDatabase.PQuery("SELECT textid FROM npc_gossip_textid WHERE action = '%u' AND zoneid ='%u'", action, zoneid ); - - if(!result) - return 0; - - Field *fields = result->Fetch(); - uint32 id = fields[0].GetUInt32(); - - delete result; - - return id; -} - -uint32 Creature::GetNpcTextId() -{ - if (!m_DBTableGuid) - return DEFAULT_GOSSIP_MESSAGE; - - if(uint32 pos = sObjectMgr.GetNpcGossip(m_DBTableGuid)) - return pos; - - return DEFAULT_GOSSIP_MESSAGE; -} - -GossipOption const* Creature::GetGossipOption( uint32 id ) const -{ - for( GossipOptionList::const_iterator i = m_goptions.begin( ); i != m_goptions.end( ); ++i ) - { - if(i->Action==id ) - return &*i; - } - return NULL; -} - void Creature::LoadGossipOptions() { if(m_gossipOptionLoaded) diff --git a/src/game/Creature.h b/src/game/Creature.h index 6ec94ec29..781acb9ad 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -576,16 +576,9 @@ class MANGOS_DLL_SPEC Creature : public Unit std::string GetScriptName() const; uint32 GetScriptId() const; - void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 ); - void sendPreparedGossip( Player* player ); - void OnGossipSelect(Player* player, uint32 option); - void OnPoiSelect(Player* player, GossipOption const *gossip); - - uint32 GetGossipTextId(uint32 action, uint32 zoneid); - uint32 GetNpcTextId(); void LoadGossipOptions(); - GossipOption const* GetGossipOption( uint32 id ) const; void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); } + GossipOptionList &GetGossipOptionList() { return m_goptions; } void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); } diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 8dd54a60a..e3101cc1b 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -277,8 +277,8 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) if (!Script->GossipHello(_player, pCreature)) { _player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); - pCreature->prepareGossipMenu(_player); - pCreature->sendPreparedGossip(_player); + _player->PrepareGossipMenu(pCreature); + _player->SendPreparedGossip(pCreature); } } @@ -287,39 +287,40 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data ) sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION"); uint32 option; - uint32 unk; + uint32 menuId; uint64 guid; std::string code = ""; - recv_data >> guid >> unk >> option; + recv_data >> guid >> menuId >> option; - if(_player->PlayerTalkClass->GossipOptionCoded( option )) + if (_player->PlayerTalkClass->GossipOptionCoded(option)) { sLog.outBasic("reading string"); recv_data >> code; sLog.outBasic("string read: %s", code.c_str()); } - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + + if (!pCreature) { sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); return; } // remove fake death - if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - if(!code.empty()) + if (!code.empty()) { - if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str())) - unit->OnGossipSelect (_player, option); + if (!Script->GossipSelectWithCode(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str())) + _player->OnGossipSelect(pCreature, option); } else { - if (!Script->GossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option))) - unit->OnGossipSelect (_player, option); + if (!Script->GossipSelect(_player, pCreature, _player->PlayerTalkClass->GossipOptionSender(option), _player->PlayerTalkClass->GossipOptionAction(option))) + _player->OnGossipSelect(pCreature, option); } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f07b4e8a7..77c2e8f86 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12175,6 +12175,338 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created, GetSession()->SendPacket(&data); } +/*********************************************************/ +/*** GOSSIP SYSTEM ***/ +/*********************************************************/ + +void Player::PrepareGossipMenu(WorldObject *pSource, uint32 gossipid) +{ + PlayerMenu* pMenu = PlayerTalkClass; + pMenu->ClearMenus(); + + if (pSource->GetTypeId() != TYPEID_UNIT) + return; + + Creature *pCreature = (Creature*)pSource; + + // lazy loading single time at use + pCreature->LoadGossipOptions(); + + GossipOptionList &iOptList = pCreature->GetGossipOptionList(); + + for(GossipOptionList::iterator i = iOptList.begin( ); i != iOptList.end( ); ++i) + { + GossipOption* gso = &*i; + + if (gso->GossipId == gossipid) + { + bool cantalking = true; + + if (gso->Id == 1) + { + uint32 textid = GetGossipTextId(pSource); + + GossipText const* gossiptext = sObjectMgr.GetGossipText(textid); + + if (!gossiptext) + cantalking = false; + } + else + { + switch(gso->Action) + { + case GOSSIP_OPTION_QUESTGIVER: + PrepareQuestMenu(pSource->GetGUID()); + //if (pm->GetQuestMenu()->MenuItemCount() == 0) + cantalking = false; + //pm->GetQuestMenu()->ClearMenu(); + break; + case GOSSIP_OPTION_ARMORER: + cantalking = false; // added in special mode + break; + case GOSSIP_OPTION_SPIRITHEALER: + if (!isDead()) + cantalking = false; + break; + case GOSSIP_OPTION_VENDOR: + { + VendorItemData const* vItems = pCreature->GetVendorItems(); + if (!vItems || vItems->Empty()) + { + sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", + pCreature->GetGUIDLow(), pCreature->GetEntry()); + cantalking = false; + } + break; + } + case GOSSIP_OPTION_TRAINER: + if (!pCreature->isCanTrainingOf(this, false)) + cantalking = false; + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + if (!pCreature->isCanTrainingAndResetTalentsOf(this)) + cantalking = false; + break; + case GOSSIP_OPTION_UNLEARNPETSKILLS: + if(!GetPet() || GetPet()->getPetType() != HUNTER_PET || GetPet()->m_spells.size() <= 1 || pCreature->GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || pCreature->GetCreatureInfo()->trainer_class != CLASS_HUNTER) + cantalking = false; + break; + case GOSSIP_OPTION_TAXIVENDOR: + if (GetSession()->SendLearnNewTaxiNode(pCreature)) + return; + break; + case GOSSIP_OPTION_BATTLEFIELD: + if (!pCreature->isCanInteractWithBattleMaster(this, false)) + cantalking = false; + break; + case GOSSIP_OPTION_SPIRITGUIDE: + case GOSSIP_OPTION_INNKEEPER: + case GOSSIP_OPTION_BANKER: + case GOSSIP_OPTION_PETITIONER: + case GOSSIP_OPTION_STABLEPET: + case GOSSIP_OPTION_TABARDDESIGNER: + case GOSSIP_OPTION_AUCTIONEER: + break; // no checks + default: + sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u", pCreature->GetDBTableGUIDLow(), pCreature->GetEntry(), gso->Action); + break; + } + } + + //note for future dev: should have database fields for BoxMessage & BoxMoney + if (!gso->OptionText.empty() && cantalking) + { + std::string OptionText = gso->OptionText; + std::string BoxText = gso->BoxText; + int loc_idx = GetSession()->GetSessionDbLocaleIndex(); + + if (loc_idx >= 0) + { + if (NpcOptionLocale const *no = sObjectMgr.GetNpcOptionLocale(gso->Id)) + { + if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty()) + OptionText = no->OptionText[loc_idx]; + + if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty()) + BoxText = no->BoxText[loc_idx]; + } + } + + pMenu->GetGossipMenu().AddMenuItem((uint8)gso->Icon,OptionText, gossipid,gso->Action,BoxText,gso->BoxMoney,gso->Coded); + } + } + } + + ///some gossips aren't handled in normal way ... so we need to do it this way .. TODO: handle it in normal way ;-) + if (pMenu->Empty()) + { + if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER)) + { + // output error message if need + pCreature->isCanTrainingOf(this, true); + } + + if (pCreature->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_BATTLEMASTER)) + { + // output error message if need + pCreature->isCanInteractWithBattleMaster(this, true); + } + } +} + +void Player::SendPreparedGossip(WorldObject *pSource) +{ + if (!pSource || pSource->GetTypeId() != TYPEID_UNIT) + return; + + // in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag) + if (!((Creature*)pSource)->HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !PlayerTalkClass->GetQuestMenu().Empty()) + { + SendPreparedQuest(pSource->GetGUID()); + return; + } + + // in case non empty gossip menu (that not included quests list size) show it + // (quest entries from quest menu will be included in list) + PlayerTalkClass->SendGossipMenu(GetGossipTextId(pSource), pSource->GetGUID()); +} + +void Player::OnGossipSelect(WorldObject* pSource, uint32 option) +{ + GossipMenu& gossipmenu = PlayerTalkClass->GetGossipMenu(); + + if (option >= gossipmenu.MenuItemCount()) + return; + + uint32 action = gossipmenu.GetItem(option).m_gAction; + uint32 zoneid = GetZoneId(); + uint64 guid = pSource->GetGUID(); + + GossipOption const *gossip = GetGossipOption(pSource, action); + + if (!gossip) + { + zoneid = 0; + gossip = GetGossipOption(pSource, action); + + if (!gossip) + return; + } + + switch(gossip->Action) + { + case GOSSIP_OPTION_GOSSIP: + { + uint32 textid = GetGossipTextId(action, zoneid); + + if (textid == 0) + textid = GetGossipTextId(pSource); + + PlayerTalkClass->CloseGossip(); + PlayerTalkClass->SendTalking(textid); + break; + } + case GOSSIP_OPTION_SPIRITHEALER: + if (isDead()) + ((Creature*)pSource)->CastSpell(((Creature*)pSource),17251,true,NULL,NULL,GetGUID()); + break; + case GOSSIP_OPTION_QUESTGIVER: + PrepareQuestMenu(guid); + SendPreparedQuest(guid); + break; + case GOSSIP_OPTION_VENDOR: + case GOSSIP_OPTION_ARMORER: + GetSession()->SendListInventory(guid); + break; + case GOSSIP_OPTION_STABLEPET: + GetSession()->SendStablePet(guid); + break; + case GOSSIP_OPTION_TRAINER: + GetSession()->SendTrainerList(guid); + break; + case GOSSIP_OPTION_UNLEARNTALENTS: + PlayerTalkClass->CloseGossip(); + SendTalentWipeConfirm(guid); + break; + case GOSSIP_OPTION_UNLEARNPETSKILLS: + PlayerTalkClass->CloseGossip(); + SendPetSkillWipeConfirm(); + break; + case GOSSIP_OPTION_TAXIVENDOR: + GetSession()->SendTaxiMenu(((Creature*)pSource)); + break; + case GOSSIP_OPTION_INNKEEPER: + PlayerTalkClass->CloseGossip(); + SetBindPoint(guid); + break; + case GOSSIP_OPTION_BANKER: + GetSession()->SendShowBank(guid); + break; + case GOSSIP_OPTION_PETITIONER: + PlayerTalkClass->CloseGossip(); + GetSession()->SendPetitionShowList(guid); + break; + case GOSSIP_OPTION_TABARDDESIGNER: + PlayerTalkClass->CloseGossip(); + GetSession()->SendTabardVendorActivate(guid); + break; + case GOSSIP_OPTION_AUCTIONEER: + GetSession()->SendAuctionHello(guid, ((Creature*)pSource)); + break; + case GOSSIP_OPTION_SPIRITGUIDE: + case GOSSIP_GUARD_SPELLTRAINER: + case GOSSIP_GUARD_SKILLTRAINER: + PrepareGossipMenu(pSource, gossip->Id); + SendPreparedGossip(pSource); + break; + case GOSSIP_OPTION_BATTLEFIELD: + { + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(pSource->GetEntry()); + + if (bgTypeId == BATTLEGROUND_TYPE_NONE) + { + sLog.outError("a user (guid %u) requested battlegroundlist from a npc who is no battlemaster", GetGUIDLow()); + return; + } + + GetSession()->SendBattlegGroundList(guid, bgTypeId); + break; + } + default: + OnPoiSelect(pSource, gossip); + break; + } +} + +void Player::OnPoiSelect(WorldObject *pSource, GossipOption const *gossip) +{ + if(gossip->GossipId==GOSSIP_GUARD_SPELLTRAINER || gossip->GossipId==GOSSIP_GUARD_SKILLTRAINER) + { + Poi_Icon icon = ICON_POI_BLANK; + //need add more case. + switch(gossip->Action) + { + case GOSSIP_GUARD_BANK: + icon=ICON_POI_SMALL_HOUSE; + break; + case GOSSIP_GUARD_RIDE: + icon=ICON_POI_RWHORSE; + break; + case GOSSIP_GUARD_GUILD: + icon=ICON_POI_BLUETOWER; + break; + default: + icon=ICON_POI_GREYTOWER; + break; + } + uint32 textid = GetGossipTextId(gossip->Action, GetZoneId()); + PlayerTalkClass->SendTalking(textid); + // std::string areaname= gossip->OptionText; + // how this could worked player->PlayerTalkClass->SendPointOfInterest( x, y, icon, 2, 15, areaname.c_str() ); + } +} + +uint32 Player::GetGossipTextId(uint32 action, uint32 zoneid) +{ + QueryResult *result= WorldDatabase.PQuery("SELECT textid FROM npc_gossip_textid WHERE action = '%u' AND zoneid ='%u'", action, zoneid ); + + if (!result) + return 0; + + Field *fields = result->Fetch(); + uint32 id = fields[0].GetUInt32(); + + delete result; + + return id; +} + +uint32 Player::GetGossipTextId(WorldObject *pSource) +{ + if (!pSource || pSource->GetTypeId() != TYPEID_UNIT || !((Creature*)pSource)->GetDBTableGUIDLow()) + return DEFAULT_GOSSIP_MESSAGE; + + if (uint32 pos = sObjectMgr.GetNpcGossip(((Creature*)pSource)->GetDBTableGUIDLow())) + return pos; + + return DEFAULT_GOSSIP_MESSAGE; +} + +GossipOption const* Player::GetGossipOption(WorldObject *pSource, uint32 id) const +{ + if (pSource->GetTypeId() == TYPEID_UNIT) + { + GossipOptionList &iOptlist = ((Creature*)pSource)->GetGossipOptionList(); + + for(GossipOptionList::const_iterator i = iOptlist.begin( ); i != iOptlist.end( ); ++i) + { + if (i->Action == id) + return &*i; + } + } + return NULL; +} + /*********************************************************/ /*** QUEST SYSTEM ***/ /*********************************************************/ @@ -12282,7 +12614,8 @@ void Player::SendPreparedQuest(uint64 guid) // need pet case for some quests if (Creature *pCreature = GetMap()->GetCreatureOrPetOrVehicle(guid)) { - uint32 textid = pCreature->GetNpcTextId(); + uint32 textid = GetGossipTextId(pCreature); + GossipText const* gossiptext = sObjectMgr.GetGossipText(textid); if (!gossiptext) { diff --git a/src/game/Player.h b/src/game/Player.h index dd5864e4c..446b834c5 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1295,6 +1295,19 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 m_stableSlots; + /*********************************************************/ + /*** GOSSIP SYSTEM ***/ + /*********************************************************/ + + void PrepareGossipMenu(WorldObject *pSource, uint32 gossipid = 0); + void SendPreparedGossip(WorldObject *pSource); + void OnGossipSelect(WorldObject *pSource, uint32 option); + void OnPoiSelect(WorldObject *pSource, GossipOption const *gossip); + + uint32 GetGossipTextId(uint32 action, uint32 zoneid); + uint32 GetGossipTextId(WorldObject *pSource); + GossipOption const* GetGossipOption(WorldObject *pSource, uint32 id) const; + /*********************************************************/ /*** QUEST SYSTEM ***/ /*********************************************************/ diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 72a4c3e50..87ef0b093 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -102,8 +102,8 @@ void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) if (Script->GossipHello(_player, pCreature)) return; - pCreature->prepareGossipMenu(_player); - pCreature->sendPreparedGossip(_player); + _player->PrepareGossipMenu(pCreature); + _player->SendPreparedGossip(pCreature); } void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data ) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4f14a1369..40fce86b5 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 "8899" + #define REVISION_NR "8900" #endif // __REVISION_NR_H__