Merge MaNGOS, Gossip System. Autor NoFantasy.

* DB support required
* Closes #859

--HG--
branch : trunk
This commit is contained in:
win32
2009-12-20 13:35:08 +02:00
parent 31c6b10a19
commit 7c9f6b4bc3
77 changed files with 1138 additions and 849 deletions
+2 -1
View File
@@ -458,6 +458,8 @@ ChatCommand * ChatHandler::getCommandTable()
{ "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL },
{ "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL },
{ "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL },
{ "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },
@@ -474,7 +476,6 @@ ChatCommand * ChatHandler::getCommandTable()
{ "mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMailCommand, "", NULL },
{ "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
{ "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
{ "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL },
{ "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL},
{ "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL },
{ "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL },
+2 -1
View File
@@ -364,6 +364,8 @@ class TRINITY_DLL_SPEC ChatHandler
bool HandleReloadGameGraveyardZoneCommand(const char* args);
bool HandleReloadGameObjectScriptsCommand(const char* args);
bool HandleReloadGameTeleCommand(const char* args);
bool HandleReloadGossipMenuCommand(const char* args);
bool HandleReloadGossipMenuOptionCommand(const char* args);
bool HandleReloadGOQuestRelationsCommand(const char* args);
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
bool HandleReloadItemEnchantementsCommand(const char* args);
@@ -392,7 +394,6 @@ class TRINITY_DLL_SPEC ChatHandler
bool HandleReloadLootTemplatesSpellCommand(const char* args);
bool HandleReloadTrinityStringCommand(const char* args);
bool HandleReloadNpcGossipCommand(const char* args);
bool HandleReloadNpcOptionCommand(const char* args);
bool HandleReloadNpcTrainerCommand(const char* args);
bool HandleReloadNpcVendorCommand(const char* args);
bool HandleReloadPageTextsCommand(const char* args);
-367
View File
@@ -136,7 +136,6 @@ Unit(),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_gossipOptionLoaded(false),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL)
@@ -888,372 +887,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class;
}
void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid )
{
//Prevent gossip from NPCs that are possessed.
Unit* Charmed = Unit::GetCharmer();
if (Charmed)
return;
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=objmgr.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_LEARNDUALSPEC:
if(!(pPlayer->GetSpecsCount() == 1 && isCanTrainingAndResetTalentsOf(pPlayer) && !(pPlayer->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL))))
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
case GOSSIP_OPTION_OUTDOORPVP:
if ( !sOutdoorPvPMgr.CanTalkTo(pPlayer,this,(*gso)) )
cantalking = false;
break;
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 = objmgr.GetNpcOptionLocale(gso->Id);
if (no)
{
if (no->OptionText.size() > loc_idx && !no->OptionText[loc_idx].empty())
OptionText=no->OptionText[loc_idx];
if (no->BoxText.size() > 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;
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) // if world event npc then
gameeventmgr.HandleWorldEventGossip(player, this); // update world state with progress
// 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_OUTDOORPVP:
sOutdoorPvPMgr.HandleGossipOption(player, GetGUID(), option);
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_LEARNDUALSPEC:
if(player->GetSpecsCount() == 1 && !(player->getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL)))
{
if (player->GetMoney() < 10000000)
{
player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
player->PlayerTalkClass->CloseGossip();
break;
}
else
{
player->ModifyMoney(-10000000);
// Cast spells that teach dual spec
// Both are also ImplicitTarget self and must be cast by player
player->CastSpell(player,63680,true,NULL,NULL,player->GetGUID());
player->CastSpell(player,63624,true,NULL,NULL,player->GetGUID());
// Should show another Gossip text with "Congratulations..."
player->PlayerTalkClass->CloseGossip();
}
}
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());
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()
{
// don't cache / use cache in case it's a world event announcer
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT)
if(uint32 textid = gameeventmgr.GetNpcTextId(m_DBTableGuid))
return textid;
if (!m_DBTableGuid)
return DEFAULT_GOSSIP_MESSAGE;
if(uint32 pos = objmgr.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::ResetGossipOptions()
{
m_gossipOptionLoaded = false;
m_goptions.clear();
}
void Creature::LoadGossipOptions()
{
if(m_gossipOptionLoaded)
return;
uint32 npcflags=GetUInt32Value(UNIT_NPC_FLAGS);
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;
}
void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, uint32 MovementFlags, uint8 type)
{
/* uint32 timeElap = getMSTime();
+2 -116
View File
@@ -39,104 +39,6 @@ class Player;
class WorldSession;
class CreatureGroup;
enum Gossip_Option
{
GOSSIP_OPTION_NONE = 0, //UNIT_NPC_FLAG_NONE = 0,
GOSSIP_OPTION_GOSSIP = 1, //UNIT_NPC_FLAG_GOSSIP = 1,
GOSSIP_OPTION_QUESTGIVER = 2, //UNIT_NPC_FLAG_QUESTGIVER = 2,
GOSSIP_OPTION_VENDOR = 3, //UNIT_NPC_FLAG_VENDOR = 4,
GOSSIP_OPTION_TAXIVENDOR = 4, //UNIT_NPC_FLAG_TAXIVENDOR = 8,
GOSSIP_OPTION_TRAINER = 5, //UNIT_NPC_FLAG_TRAINER = 16,
GOSSIP_OPTION_SPIRITHEALER = 6, //UNIT_NPC_FLAG_SPIRITHEALER = 32,
GOSSIP_OPTION_SPIRITGUIDE = 7, //UNIT_NPC_FLAG_SPIRITGUIDE = 64,
GOSSIP_OPTION_INNKEEPER = 8, //UNIT_NPC_FLAG_INNKEEPER = 128,
GOSSIP_OPTION_BANKER = 9, //UNIT_NPC_FLAG_BANKER = 256,
GOSSIP_OPTION_PETITIONER = 10, //UNIT_NPC_FLAG_PETITIONER = 512,
GOSSIP_OPTION_TABARDDESIGNER = 11, //UNIT_NPC_FLAG_TABARDDESIGNER = 1024,
GOSSIP_OPTION_BATTLEFIELD = 12, //UNIT_NPC_FLAG_BATTLEFIELDPERSON = 2048,
GOSSIP_OPTION_AUCTIONEER = 13, //UNIT_NPC_FLAG_AUCTIONEER = 4096,
GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE = 8192,
GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER = 16384,
GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_UNLEARNPETSKILLS = 17, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_LEARNDUALSPEC = 18, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_OUTDOORPVP = 19 //added by code (option for outdoor pvp creatures)
};
enum Gossip_Guard
{
GOSSIP_GUARD_BANK = 32,
GOSSIP_GUARD_RIDE = 33,
GOSSIP_GUARD_GUILD = 34,
GOSSIP_GUARD_INN = 35,
GOSSIP_GUARD_MAIL = 36,
GOSSIP_GUARD_AUCTION = 37,
GOSSIP_GUARD_WEAPON = 38,
GOSSIP_GUARD_STABLE = 39,
GOSSIP_GUARD_BATTLE = 40,
GOSSIP_GUARD_SPELLTRAINER = 41,
GOSSIP_GUARD_SKILLTRAINER = 42
};
enum Gossip_Guard_Spell
{
GOSSIP_GUARD_SPELL_WARRIOR = 64,
GOSSIP_GUARD_SPELL_PALADIN = 65,
GOSSIP_GUARD_SPELL_HUNTER = 66,
GOSSIP_GUARD_SPELL_ROGUE = 67,
GOSSIP_GUARD_SPELL_PRIEST = 68,
GOSSIP_GUARD_SPELL_UNKNOWN1 = 69,
GOSSIP_GUARD_SPELL_SHAMAN = 70,
GOSSIP_GUARD_SPELL_MAGE = 71,
GOSSIP_GUARD_SPELL_WARLOCK = 72,
GOSSIP_GUARD_SPELL_UNKNOWN2 = 73,
GOSSIP_GUARD_SPELL_DRUID = 74
};
enum Gossip_Guard_Skill
{
GOSSIP_GUARD_SKILL_ALCHEMY = 80,
GOSSIP_GUARD_SKILL_BLACKSMITH = 81,
GOSSIP_GUARD_SKILL_COOKING = 82,
GOSSIP_GUARD_SKILL_ENCHANT = 83,
GOSSIP_GUARD_SKILL_FIRSTAID = 84,
GOSSIP_GUARD_SKILL_FISHING = 85,
GOSSIP_GUARD_SKILL_HERBALISM = 86,
GOSSIP_GUARD_SKILL_LEATHER = 87,
GOSSIP_GUARD_SKILL_MINING = 88,
GOSSIP_GUARD_SKILL_SKINNING = 89,
GOSSIP_GUARD_SKILL_TAILORING = 90,
GOSSIP_GUARD_SKILL_ENGINERING = 91
};
enum GossipOptionIcon
{
GOSSIP_ICON_CHAT = 0, //white chat bubble
GOSSIP_ICON_VENDOR = 1, //brown bag
GOSSIP_ICON_TAXI = 2, //flight
GOSSIP_ICON_TRAINER = 3, //book
GOSSIP_ICON_INTERACT_1 = 4, //interaction wheel
GOSSIP_ICON_INTERACT_2 = 5, //interaction wheel
GOSSIP_ICON_MONEY_BAG = 6, //brown bag with yellow dot
GOSSIP_ICON_TALK = 7, //white chat bubble with black dots
GOSSIP_ICON_TABARD = 8, //tabard
GOSSIP_ICON_BATTLE = 9, //two swords
GOSSIP_ICON_DOT = 10 //yellow dot
};
struct GossipOption
{
uint32 Id;
uint32 GossipId;
uint32 NpcFlag;
uint32 Icon;
uint32 Action;
uint32 BoxMoney;
bool Coded;
std::string OptionText;
std::string BoxText;
};
enum CreatureFlagsExtra
{
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
@@ -176,6 +78,7 @@ struct CreatureInfo
char* Name;
char* SubName;
char* IconName;
uint32 GossipMenuId;
uint32 minlevel;
uint32 maxlevel;
uint32 minhealth;
@@ -268,7 +171,7 @@ struct CreatureLocale
std::vector<std::string> SubName;
};
struct NpcOptionLocale
struct GossipMenuItemsLocale
{
std::vector<std::string> OptionText;
std::vector<std::string> BoxText;
@@ -461,8 +364,6 @@ struct TrainerSpellData
void Clear() { spellList.clear(); }
};
typedef std::list<GossipOption> GossipOptionList;
typedef std::map<uint32,time_t> CreatureSpellCooldowns;
// max different by z coordinate for creature aggro reaction
@@ -582,18 +483,6 @@ class TRINITY_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();
void ResetGossipOptions();
GossipOption const* GetGossipOption( uint32 id ) const;
void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); }
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }
void TextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(textId,TargetGuid,IsBossEmote); }
@@ -760,9 +649,6 @@ class TRINITY_DLL_SPEC Creature : public Unit
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
float m_respawnradius;
bool m_gossipOptionLoaded;
GossipOptionList m_goptions;
ReactStates m_reactState; // for AI, not charmInfo
void RegenerateMana();
void RegenerateHealth();
+1 -1
View File
@@ -1180,7 +1180,7 @@ void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
npcflag |= ci->npcflag;
cr->SetUInt32Value(UNIT_NPC_FLAGS,npcflag);
// reset gossip options, since the flag change might have added / removed some
cr->ResetGossipOptions();
//cr->ResetGossipOptions();
// update to world
cr->SendUpdateObjectToAllExcept(NULL);
}
+8 -3
View File
@@ -979,13 +979,13 @@ void GameObject::Use(Unit* user)
case GAMEOBJECT_TYPE_QUESTGIVER: //2
{
if(user->GetTypeId() != TYPEID_PLAYER)
if (user->GetTypeId() != TYPEID_PLAYER)
return;
Player* player = (Player*)user;
player->PrepareQuestMenu( GetGUID() );
player->SendPreparedQuest( GetGUID() );
player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID);
player->SendPreparedGossip(this);
return;
}
//Sitting: Wooden bench, chairs enzz
@@ -1090,6 +1090,11 @@ void GameObject::Use(Unit* user)
data << GetGUID();
player->GetSession()->SendPacket(&data);
}
else if (info->questgiver.gossipID)
{
player->PrepareGossipMenu(this, info->goober.gossipID);
player->SendPreparedGossip(this);
}
// possible quest objective for active quests
player->CastedCreatureOrGO(info->id, GetGUID(), 0);
+9
View File
@@ -491,6 +491,15 @@ struct GameObjectInfo
default: return 0;
}
}
uint32 GetGossipMenuId() const
{
switch(type)
{
case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.gossipID;
case GAMEOBJECT_TYPE_GOOBER: return goober.gossipID;
default: return 0;
}
}
};
class OPvPCapturePoint;
+21 -8
View File
@@ -29,6 +29,7 @@
GossipMenu::GossipMenu()
{
m_gItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use
m_gMenuId = 0;
}
GossipMenu::~GossipMenu()
@@ -46,13 +47,24 @@ void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSe
gItem.m_gMessage = Message;
gItem.m_gCoded = Coded;
gItem.m_gSender = dtSender;
gItem.m_gAction = dtAction;
gItem.m_gOptionId = dtAction;
gItem.m_gBoxMessage = BoxMessage;
gItem.m_gBoxMoney = BoxMoney;
m_gItems.push_back(gItem);
}
void GossipMenu::AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script)
{
GossipMenuItemData pItemData;
pItemData.m_gAction_menu = action_menu;
pItemData.m_gAction_poi = action_poi;
pItemData.m_gAction_script = action_script;
m_gItemsData.push_back(pItemData);
}
void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded)
{
AddMenuItem( Icon, Message, 0, 0, "", 0, Coded);
@@ -79,7 +91,7 @@ uint32 GossipMenu::MenuItemAction( unsigned int ItemId )
{
if ( ItemId >= m_gItems.size() ) return 0;
return m_gItems[ ItemId ].m_gAction;
return m_gItems[ ItemId ].m_gOptionId;
}
bool GossipMenu::MenuItemCoded( unsigned int ItemId )
@@ -92,6 +104,7 @@ bool GossipMenu::MenuItemCoded( unsigned int ItemId )
void GossipMenu::ClearMenu()
{
m_gItems.clear();
m_gItemsData.clear();
}
PlayerMenu::PlayerMenu( WorldSession *session ) : pSession(session)
@@ -124,13 +137,13 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection )
return mGossipMenu.MenuItemCoded( Selection );
}
void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID )
void PlayerMenu::SendGossipMenu(uint32 TitleTextId, uint64 objectGUID)
{
WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size
data << uint64(npcGUID);
data << uint32(0); // new 2.4.0
data << uint32( TitleTextId );
data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x10
WorldPacket data(SMSG_GOSSIP_MESSAGE, (100)); // guess size
data << uint64(objectGUID);
data << uint32(mGossipMenu.GetMenuId()); // new 2.4.0
data << uint32(TitleTextId);
data << uint32(mGossipMenu.MenuItemCount()); // max count 0x10
for (uint32 iI = 0; iI < mGossipMenu.MenuItemCount(); ++iI )
{
+65 -2
View File
@@ -30,6 +30,47 @@ class WorldSession;
#define GOSSIP_MAX_MENU_ITEMS 64 // client supported items unknown, but provided number must be enough
#define DEFAULT_GOSSIP_MESSAGE 0xffffff
enum Gossip_Option
{
GOSSIP_OPTION_NONE = 0, //UNIT_NPC_FLAG_NONE (0)
GOSSIP_OPTION_GOSSIP = 1, //UNIT_NPC_FLAG_GOSSIP (1)
GOSSIP_OPTION_QUESTGIVER = 2, //UNIT_NPC_FLAG_QUESTGIVER (2)
GOSSIP_OPTION_VENDOR = 3, //UNIT_NPC_FLAG_VENDOR (128)
GOSSIP_OPTION_TAXIVENDOR = 4, //UNIT_NPC_FLAG_TAXIVENDOR (8192)
GOSSIP_OPTION_TRAINER = 5, //UNIT_NPC_FLAG_TRAINER (16)
GOSSIP_OPTION_SPIRITHEALER = 6, //UNIT_NPC_FLAG_SPIRITHEALER (16384)
GOSSIP_OPTION_SPIRITGUIDE = 7, //UNIT_NPC_FLAG_SPIRITGUIDE (32768)
GOSSIP_OPTION_INNKEEPER = 8, //UNIT_NPC_FLAG_INNKEEPER (65536)
GOSSIP_OPTION_BANKER = 9, //UNIT_NPC_FLAG_BANKER (131072)
GOSSIP_OPTION_PETITIONER = 10, //UNIT_NPC_FLAG_PETITIONER (262144)
GOSSIP_OPTION_TABARDDESIGNER = 11, //UNIT_NPC_FLAG_TABARDDESIGNER (524288)
GOSSIP_OPTION_BATTLEFIELD = 12, //UNIT_NPC_FLAG_BATTLEFIELDPERSON (1048576)
GOSSIP_OPTION_AUCTIONEER = 13, //UNIT_NPC_FLAG_AUCTIONEER (2097152)
GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE (4194304)
GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER (4096)
GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (16) (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_UNLEARNPETSKILLS = 17, //UNIT_NPC_FLAG_TRAINER (16) (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_LEARNDUALSPEC = 18, //UNIT_NPC_FLAG_TRAINER (16) (bonus option for GOSSIP_OPTION_TRAINER)
GOSSIP_OPTION_OUTDOORPVP = 19, //added by code (option for outdoor pvp creatures)
GOSSIP_OPTION_MAX
};
enum GossipOptionIcon
{
GOSSIP_ICON_CHAT = 0, //white chat bubble
GOSSIP_ICON_VENDOR = 1, //brown bag
GOSSIP_ICON_TAXI = 2, //flight
GOSSIP_ICON_TRAINER = 3, //book
GOSSIP_ICON_INTERACT_1 = 4, //interaction wheel
GOSSIP_ICON_INTERACT_2 = 5, //interaction wheel
GOSSIP_ICON_MONEY_BAG = 6, //brown bag with yellow dot
GOSSIP_ICON_TALK = 7, //white chat bubble with black dots
GOSSIP_ICON_TABARD = 8, //tabard
GOSSIP_ICON_BATTLE = 9, //two swords
GOSSIP_ICON_DOT = 10, //yellow dot
GOSSIP_ICON_MAX
};
//POI icons. Many more exist, list not complete.
enum Poi_Icon
{
@@ -82,13 +123,22 @@ struct GossipMenuItem
bool m_gCoded;
std::string m_gMessage;
uint32 m_gSender;
uint32 m_gAction;
uint32 m_gOptionId;
std::string m_gBoxMessage;
uint32 m_gBoxMoney;
};
typedef std::vector<GossipMenuItem> GossipMenuItemList;
struct GossipMenuItemData
{
uint32 m_gAction_menu;
uint32 m_gAction_poi;
uint32 m_gAction_script;
};
typedef std::vector<GossipMenuItemData> GossipMenuItemDataList;
struct QuestMenuItem
{
uint32 m_qId;
@@ -110,6 +160,11 @@ class TRINITY_DLL_SPEC GossipMenu
void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false);
void AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded = false);
void SetMenuId(uint32 menu_id) { m_gMenuId = menu_id; }
uint32 GetMenuId() { return m_gMenuId; }
void AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script);
unsigned int MenuItemCount() const
{
return m_gItems.size();
@@ -125,6 +180,11 @@ class TRINITY_DLL_SPEC GossipMenu
return m_gItems[ Id ];
}
GossipMenuItemData const& GetItemData(unsigned int indexId)
{
return m_gItemsData[indexId];
}
uint32 MenuItemSender( unsigned int ItemId );
uint32 MenuItemAction( unsigned int ItemId );
bool MenuItemCoded( unsigned int ItemId );
@@ -132,7 +192,10 @@ class TRINITY_DLL_SPEC GossipMenu
void ClearMenu();
protected:
GossipMenuItemList m_gItems;
GossipMenuItemList m_gItems;
GossipMenuItemDataList m_gItemsData;
uint32 m_gMenuId;
};
class QuestMenu
+16 -9
View File
@@ -597,7 +597,6 @@ bool ChatHandler::HandleReloadAllLootCommand(const char*)
bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/)
{
HandleReloadNpcGossipCommand("a");
HandleReloadNpcOptionCommand("a");
HandleReloadNpcTrainerCommand("a");
HandleReloadNpcVendorCommand("a");
HandleReloadPointsOfInterestCommand("a");
@@ -773,6 +772,22 @@ bool ChatHandler::HandleReloadCreatureQuestInvRelationsCommand(const char*)
return true;
}
bool ChatHandler::HandleReloadGossipMenuCommand(const char*)
{
sLog.outString( "Re-Loading `gossip_menu` Table!" );
objmgr.LoadGossipMenu();
SendGlobalSysMessage("DB table `gossip_menu` reloaded.");
return true;
}
bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*)
{
sLog.outString( "Re-Loading `gossip_menu_option` Table!" );
objmgr.LoadGossipMenuItems();
SendGlobalSysMessage("DB table `gossip_menu_option` reloaded.");
return true;
}
bool ChatHandler::HandleReloadGOQuestRelationsCommand(const char*)
{
sLog.outString( "Loading Quests Relations... (`gameobject_questrelation`)" );
@@ -925,14 +940,6 @@ bool ChatHandler::HandleReloadTrinityStringCommand(const char*)
return true;
}
bool ChatHandler::HandleReloadNpcOptionCommand(const char*)
{
sLog.outString( "Re-Loading `npc_option` Table!" );
objmgr.LoadNpcOptions();
SendGlobalGMSysMessage("DB table `npc_option` reloaded.");
return true;
}
bool ChatHandler::HandleReloadNpcGossipCommand(const char*)
{
sLog.outString( "Re-Loading `npc_gossip` Table!" );
+10 -10
View File
@@ -79,14 +79,14 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
{
sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
uint32 option;
uint32 unk;
uint32 gossipListId;
uint32 menuId;
uint64 guid;
std::string code = "";
recv_data >> guid >> unk >> option;
recv_data >> guid >> menuId >> gossipListId;
if(_player->PlayerTalkClass->GossipOptionCoded( option ))
if(_player->PlayerTalkClass->GossipOptionCoded(gossipListId))
{
// recheck
sLog.outBasic("reading string");
@@ -128,21 +128,21 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
{
if(unit)
{
if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) )
unit->OnGossipSelect( _player, option );
if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str()) )
_player->OnGossipSelect(unit, gossipListId, menuId);
}
else
Script->GOSelectWithCode( _player, go, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str());
Script->GOSelectWithCode( _player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId), code.c_str());
}
else
{
if(unit)
{
if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) )
unit->OnGossipSelect( _player, option );
if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId)) )
_player->OnGossipSelect(unit, gossipListId, menuId);
}
else
Script->GOSelect( _player, go, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ));
Script->GOSelect( _player, go, _player->PlayerTalkClass->GossipOptionSender(gossipListId), _player->PlayerTalkClass->GossipOptionAction(gossipListId));
}
}
+4 -4
View File
@@ -291,11 +291,11 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
}
}
if(!Script->GossipHello( _player, unit ))
if(!Script->GossipHello(_player, unit))
{
_player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
unit->prepareGossipMenu(_player);
unit->sendPreparedGossip(_player);
_player->TalkedToCreature(unit->GetEntry(), unit->GetGUID());
_player->PrepareGossipMenu(unit, unit->GetCreatureInfo()->GossipMenuId);
_player->SendPreparedGossip(unit);
}
}
+194 -29
View File
@@ -45,6 +45,7 @@
#include "Util.h"
#include "WaypointManager.h"
#include "InstanceData.h" //for condition_instance_data
#include "GossipDef.h"
INSTANTIATE_SINGLETON_1(ObjectMgr);
@@ -53,6 +54,7 @@ ScriptMapMap sQuestStartScripts;
ScriptMapMap sSpellScripts;
ScriptMapMap sGameObjectScripts;
ScriptMapMap sEventScripts;
ScriptMapMap sGossipScripts;
ScriptMapMap sWaypointScripts;
bool normalizePlayerName(std::string& name)
@@ -377,14 +379,14 @@ void ObjectMgr::LoadCreatureLocales()
void ObjectMgr::LoadNpcOptionLocales()
{
mNpcOptionLocaleMap.clear(); // need for reload case
mGossipMenuItemsLocaleMap.clear(); // need for reload case
QueryResult *result = WorldDatabase.Query("SELECT entry,"
QueryResult *result = WorldDatabase.Query("SELECT menu_id,id,"
"option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2,"
"option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4,"
"option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6,"
"option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 "
"FROM locales_npc_option");
"FROM locales_gossip_menu_option");
if(!result)
{
@@ -393,7 +395,7 @@ void ObjectMgr::LoadNpcOptionLocales()
bar.step();
sLog.outString();
sLog.outString(">> Loaded 0 npc_option locale strings. DB table `locales_npc_option` is empty.");
sLog.outString(">> Loaded 0 gossip_menu_option locale strings. DB table `locales_npc_option` is empty.");
return;
}
@@ -404,9 +406,10 @@ void ObjectMgr::LoadNpcOptionLocales()
Field *fields = result->Fetch();
bar.step();
uint32 entry = fields[0].GetUInt32();
uint16 menuId = fields[0].GetUInt16();
uint16 id = fields[1].GetUInt16();
NpcOptionLocale& data = mNpcOptionLocaleMap[entry];
GossipMenuItemsLocale& data = mGossipMenuItemsLocaleMap[MAKE_PAIR32(menuId,id)];
for (uint8 i = 1; i < MAX_LOCALE; ++i)
{
@@ -440,7 +443,7 @@ void ObjectMgr::LoadNpcOptionLocales()
delete result;
sLog.outString();
sLog.outString( ">> Loaded %lu npc_option locale strings", (unsigned long)mNpcOptionLocaleMap.size() );
sLog.outString( ">> Loaded %lu gossip_menu_option locale strings", (unsigned long)mGossipMenuItemsLocaleMap.size() );
}
void ObjectMgr::LoadPointOfInterestLocales()
@@ -4696,6 +4699,13 @@ void ObjectMgr::LoadWaypointScripts()
}
}
void ObjectMgr::LoadGossipScripts()
{
LoadScripts(sGossipScripts, "gossip_scripts");
// checks are done in LoadGossipMenuItems
}
void ObjectMgr::LoadItemTexts()
{
QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text");
@@ -8293,23 +8303,21 @@ void ObjectMgr::LoadNpcTextId()
sLog.outString( ">> Loaded %d NpcTextId ", count );
}
void ObjectMgr::LoadNpcOptions()
void ObjectMgr::LoadGossipMenu()
{
m_mCacheNpcOptionList.clear(); // For reload case
m_mGossipMenusMap.clear();
QueryResult *result = WorldDatabase.Query(
// 0 1 2 3 4 5 6 7 8
"SELECT id,gossip_id,npcflag,icon,action,box_money,coded,option_text,box_text "
"FROM npc_option");
QueryResult* result = WorldDatabase.Query("SELECT entry, text_id, "
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2 FROM gossip_menu");
if( !result )
if(!result)
{
barGoLink bar( 1 );
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded `npc_option`, table is empty!");
sLog.outErrorDb(">> Loaded `gossip_menu`, table is empty!");
return;
}
@@ -8323,26 +8331,183 @@ void ObjectMgr::LoadNpcOptions()
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.BoxMoney = fields[5].GetUInt32();
go.Coded = fields[6].GetUInt8()!=0;
go.OptionText = fields[7].GetCppString();
go.BoxText = fields[8].GetCppString();
GossipMenus gMenu;
m_mCacheNpcOptionList.push_back(go);
gMenu.entry = fields[0].GetUInt32();
gMenu.text_id = fields[1].GetUInt32();
ConditionType cond_1 = (ConditionType)fields[2].GetUInt32();
uint32 cond_1_val_1 = fields[3].GetUInt32();
uint32 cond_1_val_2 = fields[4].GetUInt32();
ConditionType cond_2 = (ConditionType)fields[5].GetUInt32();
uint32 cond_2_val_1 = fields[6].GetUInt32();
uint32 cond_2_val_2 = fields[7].GetUInt32();
if (!GetGossipText(gMenu.text_id))
{
sLog.outErrorDb("Table gossip_menu entry %u are using non-existing text_id %u", gMenu.entry, gMenu.text_id);
continue;
}
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
{
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 1 for id %u", gMenu.entry, gMenu.text_id);
continue;
}
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
{
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 2 for id %u", gMenu.entry, gMenu.text_id);
continue;
}
gMenu.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
gMenu.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu));
++count;
}
while(result->NextRow());
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString( ">> Loaded %d npc_option entries", count );
sLog.outString( ">> Loaded %u gossip_menu entries", count);
}
void ObjectMgr::LoadGossipMenuItems()
{
m_mGossipMenuItemsMap.clear();
QueryResult *result = WorldDatabase.Query(
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
"cond_1, cond_1_val_1, cond_1_val_2, "
"cond_2, cond_2_val_1, cond_2_val_2, "
"cond_3, cond_3_val_1, cond_3_val_2 "
"FROM gossip_menu_option");
if (!result)
{
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded gossip_menu_option, table is empty!");
return;
}
barGoLink bar(result->GetRowCount());
uint32 count = 0;
std::set<uint32> gossipScriptSet;
for(ScriptMapMap::const_iterator itr = sGossipScripts.begin(); itr != sGossipScripts.end(); ++itr)
gossipScriptSet.insert(itr->first);
do
{
bar.step();
Field* fields = result->Fetch();
GossipMenuItems gMenuItem;
gMenuItem.menu_id = fields[0].GetUInt32();
gMenuItem.id = fields[1].GetUInt32();
gMenuItem.option_icon = fields[2].GetUInt8();
gMenuItem.option_text = fields[3].GetCppString();
gMenuItem.option_id = fields[4].GetUInt32();
gMenuItem.npc_option_npcflag = fields[5].GetUInt32();
gMenuItem.action_menu_id = fields[6].GetUInt32();
gMenuItem.action_poi_id = fields[7].GetUInt32();
gMenuItem.action_script_id = fields[8].GetUInt32();
gMenuItem.box_coded = fields[9].GetUInt8() != 0;
gMenuItem.box_money = fields[10].GetUInt32();
gMenuItem.box_text = fields[11].GetCppString();
ConditionType cond_1 = (ConditionType)fields[12].GetUInt32();
uint32 cond_1_val_1 = fields[13].GetUInt32();
uint32 cond_1_val_2 = fields[14].GetUInt32();
ConditionType cond_2 = (ConditionType)fields[15].GetUInt32();
uint32 cond_2_val_1 = fields[16].GetUInt32();
uint32 cond_2_val_2 = fields[17].GetUInt32();
ConditionType cond_3 = (ConditionType)fields[18].GetUInt32();
uint32 cond_3_val_1 = fields[19].GetUInt32();
uint32 cond_3_val_2 = fields[20].GetUInt32();
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 1 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 2 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (!PlayerCondition::IsValid(cond_3, cond_3_val_1, cond_3_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 3 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (gMenuItem.option_icon >= GOSSIP_ICON_MAX)
{
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_icon);
gMenuItem.option_icon = GOSSIP_ICON_CHAT;
}
if (gMenuItem.option_id >= GOSSIP_OPTION_MAX)
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_id);
if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id))
{
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_poi_id);
gMenuItem.action_poi_id = 0;
}
if (gMenuItem.action_script_id)
{
if (gMenuItem.option_id != GOSSIP_OPTION_GOSSIP)
{
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u but option_id is not GOSSIP_OPTION_GOSSIP, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id);
continue;
}
if (sGossipScripts.find(gMenuItem.action_script_id) == sGossipScripts.end())
{
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `gossip_scripts`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.action_script_id);
continue;
}
gossipScriptSet.erase(gMenuItem.action_script_id);
}
gMenuItem.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
gMenuItem.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
gMenuItem.cond_3 = GetConditionId(cond_3, cond_3_val_1, cond_3_val_2);
m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem));
++count;
}
while(result->NextRow());
delete result;
if (!gossipScriptSet.empty())
{
for(std::set<uint32>::const_iterator itr = gossipScriptSet.begin(); itr != gossipScriptSet.end(); ++itr)
sLog.outErrorDb("Table `gossip_scripts` contain unused script, id %u.", *itr);
}
sLog.outString();
sLog.outString(">> Loaded %u gossip_menu_option entries", count);
}
void ObjectMgr::AddVendorItem( uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 extendedcost, bool savetodb)
+56 -12
View File
@@ -74,7 +74,6 @@ struct GameTele
};
typedef UNORDERED_MAP<uint32, GameTele > GameTeleMap;
typedef std::list<GossipOption> CacheNpcOptionList;
struct ScriptInfo
{
@@ -97,6 +96,7 @@ extern ScriptMapMap sQuestStartScripts;
extern ScriptMapMap sSpellScripts;
extern ScriptMapMap sGameObjectScripts;
extern ScriptMapMap sEventScripts;
extern ScriptMapMap sGossipScripts;
extern ScriptMapMap sWaypointScripts;
struct SpellClickInfo
@@ -163,7 +163,7 @@ typedef UNORDERED_MAP<uint32,QuestLocale> QuestLocaleMap;
typedef UNORDERED_MAP<uint32,NpcTextLocale> NpcTextLocaleMap;
typedef UNORDERED_MAP<uint32,PageTextLocale> PageTextLocaleMap;
typedef UNORDERED_MAP<int32,TrinityStringLocale> TrinityStringLocaleMap;
typedef UNORDERED_MAP<uint32,NpcOptionLocale> NpcOptionLocaleMap;
typedef UNORDERED_MAP<uint32,GossipMenuItemsLocale> GossipMenuItemsLocaleMap;
typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap;
typedef std::multimap<uint32,uint32> QuestRelations;
@@ -217,6 +217,38 @@ struct PointOfInterest
std::string icon_name;
};
struct GossipMenuItems
{
uint32 menu_id;
uint32 id;
uint8 option_icon;
std::string option_text;
uint32 option_id;
uint32 npc_option_npcflag;
uint32 action_menu_id;
uint32 action_poi_id;
uint32 action_script_id;
bool box_coded;
uint32 box_money;
std::string box_text;
uint16 cond_1;
uint16 cond_2;
uint16 cond_3;
};
struct GossipMenus
{
uint32 entry;
uint32 text_id;
uint16 cond_1;
uint16 cond_2;
};
typedef std::multimap<uint32,GossipMenus> GossipMenusMap;
typedef std::pair<GossipMenusMap::const_iterator, GossipMenusMap::const_iterator> GossipMenusMapBounds;
typedef std::multimap<uint32,GossipMenuItems> GossipMenuItemsMap;
typedef std::pair<GossipMenuItemsMap::const_iterator, GossipMenuItemsMap::const_iterator> GossipMenuItemsMapBounds;
#define WEATHER_SEASONS 4
struct WeatherSeasonChances
{
@@ -277,7 +309,6 @@ struct PlayerCondition
// NPC gossip text id
typedef UNORDERED_MAP<uint32, uint32> CacheNpcTextIdMap;
typedef std::list<GossipOption> CacheNpcOptionList;
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
@@ -537,6 +568,7 @@ class ObjectMgr
void LoadQuestStartScripts();
void LoadEventScripts();
void LoadSpellScripts();
void LoadGossipScripts();
void LoadWaypointScripts();
void LoadTransportEvents();
@@ -596,8 +628,11 @@ class ObjectMgr
void LoadWeatherZoneChances();
void LoadGameTele();
void LoadNpcOptions();
void LoadNpcTextId();
void LoadGossipMenu();
void LoadGossipMenuItems();
void LoadVendors();
void LoadTrainerSpell();
void LoadGMTickets();
@@ -715,10 +750,10 @@ class ObjectMgr
if(itr==mPageTextLocaleMap.end()) return NULL;
return &itr->second;
}
NpcOptionLocale const* GetNpcOptionLocale(uint32 entry) const
GossipMenuItemsLocale const* GetGossipMenuItemsLocale(uint32 entry) const
{
NpcOptionLocaleMap::const_iterator itr = mNpcOptionLocaleMap.find(entry);
if(itr==mNpcOptionLocaleMap.end()) return NULL;
GossipMenuItemsLocaleMap::const_iterator itr = mGossipMenuItemsLocaleMap.find(entry);
if(itr==mGossipMenuItemsLocaleMap.end()) return NULL;
return &itr->second;
}
PointOfInterestLocale const* GetPointOfInterestLocale(uint32 poi_id) const
@@ -805,8 +840,6 @@ class ObjectMgr
bool AddGameTele(GameTele& data);
bool DeleteGameTele(const std::string& name);
CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; }
uint32 GetNpcGossip(uint32 entry) const
{
CacheNpcTextIdMap::const_iterator iter = m_mCacheNpcTextIdMap.find(entry);
@@ -871,6 +904,16 @@ class ObjectMgr
return NULL;
}
GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const
{
return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId));
}
GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const
{
return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId));
}
void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false);
void _AddOrUpdateGMTicket(GM_Ticket &ticket);
void RemoveGMTicket(uint64 ticketGuid, int64 source = -1, bool permanently = false);
@@ -928,7 +971,9 @@ class ObjectMgr
RepOnKillMap mRepOnKill;
PointOfInterestMap mPointsOfInterest;
GossipMenusMap m_mGossipMenusMap;
GossipMenuItemsMap m_mGossipMenuItemsMap;
PointOfInterestMap mPointsOfInterest;
WeatherZoneMap mWeatherZoneMap;
@@ -997,7 +1042,7 @@ class ObjectMgr
NpcTextLocaleMap mNpcTextLocaleMap;
PageTextLocaleMap mPageTextLocaleMap;
TrinityStringLocaleMap mTrinityStringLocaleMap;
NpcOptionLocaleMap mNpcOptionLocaleMap;
GossipMenuItemsLocaleMap mGossipMenuItemsLocaleMap;
PointOfInterestLocaleMap mPointOfInterestLocaleMap;
RespawnTimes mCreatureRespawnTimes;
RespawnTimes mGORespawnTimes;
@@ -1006,7 +1051,6 @@ class ObjectMgr
typedef std::vector<PlayerCondition> ConditionStore;
ConditionStore mConditions;
CacheNpcOptionList m_mCacheNpcOptionList;
CacheNpcTextIdMap m_mCacheNpcTextIdMap;
CacheVendorItemMap m_mCacheVendorItemMap;
CacheTrainerSpellMap m_mCacheTrainerSpellMap;
+2 -2
View File
@@ -506,7 +506,7 @@ bool OutdoorPvP::HandleGossipOption(Player * plr, uint64 guid, uint32 id)
return false;
}
bool OutdoorPvP::CanTalkTo(Player * plr, Creature * c, GossipOption &gso)
bool OutdoorPvP::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso)
{
for (OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
if(itr->second->CanTalkTo(plr, c, gso))
@@ -529,7 +529,7 @@ bool OPvPCapturePoint::HandleGossipOption(Player * plr, uint64 guid, uint32 id)
return false;
}
bool OPvPCapturePoint::CanTalkTo(Player * plr, Creature * c, GossipOption &gso)
bool OPvPCapturePoint::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso)
{
return false;
}
+3 -3
View File
@@ -81,7 +81,7 @@ class GameObject;
class WorldPacket;
class Creature;
class Unit;
struct GossipOption;
struct GossipMenuItems;
typedef std::set<Player*> PlayerSet;
@@ -117,7 +117,7 @@ public:
virtual bool HandleGossipOption(Player *plr, uint64 guid, uint32 gossipid);
virtual bool CanTalkTo(Player * plr, Creature * c, GossipOption &gso);
virtual bool CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso);
virtual bool HandleDropFlag(Player * plr, uint32 spellId);
@@ -217,7 +217,7 @@ public:
virtual bool HandleGossipOption(Player *plr, uint64 guid, uint32 gossipid);
virtual bool CanTalkTo(Player * plr, Creature * c, GossipOption &gso);
virtual bool CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso);
void TeamApplyBuff(TeamId team, uint32 spellId, uint32 spellId2 = 0);
protected:
-77
View File
@@ -616,86 +616,9 @@ void OPvPCapturePointEP_PWT::SummonFlightMaster(uint32 team)
m_FlightMasterSpawned = team;
DelCreature(EP_PWT_FLIGHTMASTER);
AddCreature(EP_PWT_FLIGHTMASTER,EP_PWT_FlightMaster.entry,team,EP_PWT_FlightMaster.map,EP_PWT_FlightMaster.x,EP_PWT_FlightMaster.y,EP_PWT_FlightMaster.z,EP_PWT_FlightMaster.o);
Creature * c = HashMapHolder<Creature>::Find(m_Creatures[EP_PWT_FLIGHTMASTER]);
if(c)
{
GossipOption gso;
gso.Action = GOSSIP_OPTION_OUTDOORPVP;
gso.GossipId = 0;
gso.OptionText.assign(objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_NPT));
gso.Id = 50;
gso.Icon = 0;
gso.NpcFlag = 0;
c->addGossipOption(gso);
gso.Action = GOSSIP_OPTION_OUTDOORPVP;
gso.GossipId = 0;
gso.OptionText.assign(objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_EWT));
gso.Id = 50;
gso.Icon = 0;
gso.NpcFlag = 0;
c->addGossipOption(gso);
gso.Action = GOSSIP_OPTION_OUTDOORPVP;
gso.GossipId = 0;
gso.OptionText.assign(objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_EP_FLIGHT_CGT));
gso.Id = 50;
gso.Icon = 0;
gso.NpcFlag = 0;
c->addGossipOption(gso);
}
}
}
bool OPvPCapturePointEP_PWT::CanTalkTo(Player * p, Creature * c, GossipOption &gso)
{
if( p->GetTeam() == m_FlightMasterSpawned &&
c->GetGUID() == m_Creatures[EP_PWT_FLIGHTMASTER] &&
gso.Id == 50 )
return true;
return false;
}
bool OPvPCapturePointEP_PWT::HandleGossipOption(Player *plr, uint64 guid, uint32 gossipid)
{
std::map<uint64,uint32>::iterator itr = m_CreatureTypes.find(guid);
if(itr != m_CreatureTypes.end())
{
Creature * cr = HashMapHolder<Creature>::Find(guid);
if(!cr)
return true;
if(itr->second == EP_PWT_FLIGHTMASTER)
{
uint32 src = EP_PWT_Taxi;
uint32 dst = 0;
switch(gossipid)
{
case 0:
dst = EP_NPT_Taxi;
break;
case 1:
dst = EP_EWT_Taxi;
break;
default:
dst = EP_CGT_Taxi;
break;
}
std::vector<uint32> nodes;
nodes.resize(2);
nodes[0] = src;
nodes[1] = dst;
plr->PlayerTalkClass->CloseGossip();
plr->ActivateTaxiPathTo(nodes, cr);
// leave the opvp, seems like moveinlineofsight isn't called when entering a taxi
HandlePlayerLeave(plr);
}
return true;
}
return false;
}
// ep
OutdoorPvPEP::OutdoorPvPEP()
{
-2
View File
@@ -246,8 +246,6 @@ public:
// used when player is activated/inactivated in the area
bool HandlePlayerEnter(Player * plr);
void HandlePlayerLeave(Player * plr);
bool HandleGossipOption(Player *plr, uint64 guid, uint32 gossipid);
bool CanTalkTo(Player * plr, Creature * c, GossipOption &gso);
protected:
void SummonFlightMaster(uint32 team);
void UpdateTowerState();
+1 -1
View File
@@ -231,7 +231,7 @@ void OutdoorPvPMgr::HandleGossipOption(Player *plr, uint64 guid, uint32 gossipid
}
}
bool OutdoorPvPMgr::CanTalkTo(Player * plr, Creature * c, GossipOption & gso)
bool OutdoorPvPMgr::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso)
{
for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr)
{
+1 -1
View File
@@ -62,7 +62,7 @@ public:
void HandleGossipOption(Player * player, uint64 guid, uint32 gossipid);
bool CanTalkTo(Player * player, Creature * creature, GossipOption & gso);
bool CanTalkTo(Player * player, Creature * creature, GossipMenuItems gso);
void HandleDropFlag(Player * plr, uint32 spellId);
+1 -7
View File
@@ -326,22 +326,16 @@ void OPvPCapturePointZM_GraveYard::SetBeaconState(uint32 controlling_faction)
UpdateTowerState();
}
bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player * plr, Creature * c, GossipOption & gso)
bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso)
{
uint64 guid = c->GetGUID();
std::map<uint64,uint32>::iterator itr = m_CreatureTypes.find(guid);
if(itr != m_CreatureTypes.end())
{
if(itr->second == ZM_ALLIANCE_FIELD_SCOUT && plr->GetTeam() == ALLIANCE && m_BothControllingFaction == ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A)
{
gso.OptionText.assign(objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_GOSSIP_ALLIANCE));
return true;
}
else if(itr->second == ZM_HORDE_FIELD_SCOUT && plr->GetTeam() == HORDE && m_BothControllingFaction == HORDE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_H)
{
gso.OptionText.assign(objmgr.GetTrinityStringForDBCLocale(LANG_OPVP_ZM_GOSSIP_HORDE));
return true;
}
}
return false;
}
+1 -1
View File
@@ -188,7 +188,7 @@ public:
void SetBeaconState(uint32 controlling_team); // not good atm
bool HandleGossipOption(Player * plr, uint64 guid, uint32 gossipid);
bool HandleDropFlag(Player * plr, uint32 spellId);
bool CanTalkTo(Player * plr, Creature * c, GossipOption &gso);
bool CanTalkTo(Player * plr, Creature * c, GossipMenuItems gso);
private:
uint32 m_GraveYardState;
protected:
+387 -1
View File
@@ -12729,6 +12729,392 @@ void Player::SendNewItem(Item *item, uint32 count, bool received, bool created,
GetSession()->SendPacket(&data);
}
/*********************************************************/
/*** GOSSIP SYSTEM ***/
/*********************************************************/
void Player::PrepareGossipMenu(WorldObject *pSource, uint32 menuId)
{
PlayerMenu* pMenu = PlayerTalkClass;
pMenu->ClearMenus();
pMenu->GetGossipMenu().SetMenuId(menuId);
GossipMenuItemsMapBounds pMenuItemBounds = objmgr.GetGossipMenuItemsMapBounds(menuId);
// if default menuId and no menu options exist for this, use options from default options
if (pMenuItemBounds.first == pMenuItemBounds.second && menuId == GetDefaultGossipMenuForSource(pSource))
pMenuItemBounds = objmgr.GetGossipMenuItemsMapBounds(0);
for(GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
{
bool bCanTalk = true;
if (itr->second.cond_1 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_1))
continue;
if (itr->second.cond_2 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
continue;
if (itr->second.cond_3 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_3))
continue;
if (pSource->GetTypeId() == TYPEID_UNIT)
{
Creature *pCreature = (Creature*)pSource;
uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
if (!(itr->second.npc_option_npcflag & npcflags))
continue;
switch(itr->second.option_id)
{
case GOSSIP_OPTION_QUESTGIVER:
PrepareQuestMenu(pSource->GetGUID());
bCanTalk = false;
break;
case GOSSIP_OPTION_ARMORER:
bCanTalk = false; // added in special mode
break;
case GOSSIP_OPTION_SPIRITHEALER:
if (!isDead())
bCanTalk = 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());
bCanTalk = false;
}
break;
}
case GOSSIP_OPTION_TRAINER:
if (!pCreature->isCanTrainingOf(this, false))
bCanTalk = false;
break;
case GOSSIP_OPTION_LEARNDUALSPEC:
if(!(GetSpecsCount() == 1 && pCreature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL))))
bCanTalk = false;
break;
case GOSSIP_OPTION_UNLEARNTALENTS:
if (!pCreature->isCanTrainingAndResetTalentsOf(this))
bCanTalk = 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)
bCanTalk = false;
break;
case GOSSIP_OPTION_TAXIVENDOR:
if (GetSession()->SendLearnNewTaxiNode(pCreature))
return;
break;
case GOSSIP_OPTION_BATTLEFIELD:
if (!pCreature->isCanInteractWithBattleMaster(this, false))
bCanTalk = false;
break;
case GOSSIP_OPTION_STABLEPET:
if (getClass() != CLASS_HUNTER)
bCanTalk = false;
break;
case GOSSIP_OPTION_GOSSIP:
case GOSSIP_OPTION_SPIRITGUIDE:
case GOSSIP_OPTION_INNKEEPER:
case GOSSIP_OPTION_BANKER:
case GOSSIP_OPTION_PETITIONER:
case GOSSIP_OPTION_TABARDDESIGNER:
case GOSSIP_OPTION_AUCTIONEER:
break; // no checks
case GOSSIP_OPTION_OUTDOORPVP:
if (!sOutdoorPvPMgr.CanTalkTo(this, pCreature, itr->second))
bCanTalk = false;
break;
default:
sLog.outErrorDb("Creature entry %u have unknown gossip option %u for menu %u", pCreature->GetEntry(), itr->second.option_id, itr->second.menu_id);
bCanTalk = false;
break;
}
}
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
{
GameObject *pGo = (GameObject*)pSource;
switch(itr->second.option_id)
{
case GOSSIP_OPTION_QUESTGIVER:
if (pGo->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER)
PrepareQuestMenu(pSource->GetGUID());
bCanTalk = false;
break;
case GOSSIP_OPTION_GOSSIP:
if (pGo->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER && pGo->GetGoType() != GAMEOBJECT_TYPE_GOOBER)
bCanTalk = false;
break;
default:
bCanTalk = false;
break;
}
}
if (bCanTalk)
{
std::string strOptionText = itr->second.option_text;
std::string strBoxText = itr->second.box_text;
int loc_idx = GetSession()->GetSessionDbLocaleIndex();
if (loc_idx >= 0)
{
uint32 idxEntry = MAKE_PAIR32(menuId, itr->second.id);
if (GossipMenuItemsLocale const *no = objmgr.GetGossipMenuItemsLocale(idxEntry))
{
if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty())
strOptionText = no->OptionText[loc_idx];
if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty())
strBoxText = no->BoxText[loc_idx];
}
}
pMenu->GetGossipMenu().AddMenuItem(itr->second.option_icon, strOptionText, 0, itr->second.option_id, strBoxText, itr->second.box_money, itr->second.box_coded);
pMenu->GetGossipMenu().AddGossipMenuItemData(itr->second.action_menu_id, itr->second.action_poi_id, itr->second.action_script_id);
}
}
// 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)
return;
if (pSource->GetTypeId() == TYPEID_UNIT)
{
// 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;
}
}
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
{
// probably need to find a better way here
if (!PlayerTalkClass->GetGossipMenu().GetMenuId() && !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)
uint32 textId = GetGossipTextId(pSource);
if (uint32 menuId = PlayerTalkClass->GetGossipMenu().GetMenuId())
textId = GetGossipTextId(menuId);
PlayerTalkClass->SendGossipMenu(textId, pSource->GetGUID());
}
void Player::OnGossipSelect(WorldObject* pSource, uint32 gossipListId, uint32 menuId)
{
GossipMenu& gossipmenu = PlayerTalkClass->GetGossipMenu();
if (gossipListId >= gossipmenu.MenuItemCount())
return;
// if not same, then something funky is going on
if (menuId != gossipmenu.GetMenuId())
return;
uint32 gossipOptionId = gossipmenu.GetItem(gossipListId).m_gOptionId;
uint64 guid = pSource->GetGUID();
if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
{
if (gossipOptionId > GOSSIP_OPTION_QUESTGIVER)
{
sLog.outError("Player guid %u request invalid gossip option for GameObject entry %u", GetGUIDLow(), pSource->GetEntry());
return;
}
}
GossipMenuItemData pMenuData = gossipmenu.GetItemData(gossipListId);
switch(gossipOptionId)
{
case GOSSIP_OPTION_GOSSIP:
{
if (pMenuData.m_gAction_menu)
{
PrepareGossipMenu(pSource, pMenuData.m_gAction_menu);
SendPreparedGossip(pSource);
}
if (pMenuData.m_gAction_poi)
PlayerTalkClass->SendPointOfInterest(pMenuData.m_gAction_poi);
if (pMenuData.m_gAction_script)
{
if (pSource->GetTypeId() == TYPEID_UNIT)
GetMap()->ScriptsStart(sGossipScripts, pMenuData.m_gAction_script, this, pSource);
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
GetMap()->ScriptsStart(sGossipScripts, pMenuData.m_gAction_script, pSource, this);
}
break;
}
case GOSSIP_OPTION_OUTDOORPVP:
sOutdoorPvPMgr.HandleGossipOption(this, pSource->GetGUID(), gossipListId);
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_LEARNDUALSPEC:
if(GetSpecsCount() == 1 && !(getLevel() < sWorld.getConfig(CONFIG_MIN_DUALSPEC_LEVEL)))
{
if (GetMoney() < 10000000)
{
SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0);
PlayerTalkClass->CloseGossip();
break;
}
else
{
ModifyMoney(-10000000);
// Cast spells that teach dual spec
// Both are also ImplicitTarget self and must be cast by player
this->CastSpell(this, 63680, true, NULL, NULL, this->GetGUID());
this->CastSpell(this, 63624, true, NULL, NULL, this->GetGUID());
// Should show another Gossip text with "Congratulations..."
PlayerTalkClass->CloseGossip();
}
}
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:
PrepareGossipMenu(pSource);
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;
}
}
}
uint32 Player::GetGossipTextId(WorldObject *pSource)
{
if (!pSource || pSource->GetTypeId() != TYPEID_UNIT || !((Creature*)pSource)->GetDBTableGUIDLow())
return DEFAULT_GOSSIP_MESSAGE;
if (uint32 pos = objmgr.GetNpcGossip(((Creature*)pSource)->GetDBTableGUIDLow()))
return pos;
return DEFAULT_GOSSIP_MESSAGE;
}
uint32 Player::GetGossipTextId(uint32 menuId)
{
uint32 textId = DEFAULT_GOSSIP_MESSAGE;
if (!menuId)
return textId;
GossipMenusMapBounds pMenuBounds = objmgr.GetGossipMenusMapBounds(menuId);
for(GossipMenusMap::const_iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
{
if (objmgr.IsPlayerMeetToCondition(this, itr->second.cond_1) && objmgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
textId = itr->second.text_id;
}
return textId;
}
uint32 Player::GetDefaultGossipMenuForSource(WorldObject *pSource)
{
if (pSource->GetTypeId() == TYPEID_UNIT)
return ((Creature*)pSource)->GetCreatureInfo()->GossipMenuId;
else if (pSource->GetTypeId() == TYPEID_GAMEOBJECT)
return((GameObject*)pSource)->GetGOInfo()->GetGossipMenuId();
return 0;
}
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
@@ -12837,7 +13223,7 @@ void Player::SendPreparedQuest(uint64 guid)
Creature *pCreature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this,guid);
if (pCreature)
{
uint32 textid = pCreature->GetNpcTextId();
uint32 textid = GetGossipTextId(pCreature);
GossipText const* gossiptext = objmgr.GetGossipText(textid);
if (!gossiptext)
{
+12
View File
@@ -1246,6 +1246,18 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_stableSlots;
/*********************************************************/
/*** GOSSIP SYSTEM ***/
/*********************************************************/
void PrepareGossipMenu(WorldObject *pSource, uint32 menuId = 0);
void SendPreparedGossip(WorldObject *pSource);
void OnGossipSelect(WorldObject *pSource, uint32 gossipListId, uint32 menuId);
uint32 GetGossipTextId(uint32 menuId);
uint32 GetGossipTextId(WorldObject *pSource);
uint32 GetDefaultGossipMenuForSource(WorldObject *pSource);
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
+2 -2
View File
@@ -104,8 +104,8 @@ void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data )
if(Script->GossipHello( _player, pCreature ) )
return;
pCreature->prepareGossipMenu(_player);
pCreature->sendPreparedGossip(_player);
_player->PrepareGossipMenu(pCreature, pCreature->GetCreatureInfo()->GossipMenuId);
_player->SendPreparedGossip(pCreature);
}
void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data )
+8 -2
View File
@@ -1547,8 +1547,14 @@ 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 Gossip scripts...");
objmgr.LoadGossipScripts(); // must be before gossip menu options
sLog.outString("Loading Gossip menu...");
objmgr.LoadGossipMenu();
sLog.outString("Loading Gossip menu options...");
objmgr.LoadGossipMenuItems();
sLog.outString("Loading Vendors...");
objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate