mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
Merge remote branch 'origin/master' into 330
This commit is contained in:
commit
922544739b
27 changed files with 756 additions and 531 deletions
|
|
@ -4044,6 +4044,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
|||
CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",guid);
|
||||
|
|
@ -8644,16 +8645,16 @@ bool Player::IsBagPos( uint16 pos )
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Player::IsValidPos( uint8 bag, uint8 slot )
|
||||
bool Player::IsValidPos( uint8 bag, uint8 slot, bool explicit_pos )
|
||||
{
|
||||
// post selected
|
||||
if(bag == NULL_BAG)
|
||||
if(bag == NULL_BAG && !explicit_pos)
|
||||
return true;
|
||||
|
||||
if (bag == INVENTORY_SLOT_BAG_0)
|
||||
{
|
||||
// any post selected
|
||||
if (slot == NULL_SLOT)
|
||||
if (slot == NULL_SLOT && !explicit_pos)
|
||||
return true;
|
||||
|
||||
// equipment
|
||||
|
|
@ -8691,7 +8692,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
|
|||
return false;
|
||||
|
||||
// any post selected
|
||||
if (slot == NULL_SLOT)
|
||||
if (slot == NULL_SLOT && !explicit_pos)
|
||||
return true;
|
||||
|
||||
return slot < pBag->GetBagSize();
|
||||
|
|
@ -8705,7 +8706,7 @@ bool Player::IsValidPos( uint8 bag, uint8 slot )
|
|||
return false;
|
||||
|
||||
// any post selected
|
||||
if (slot == NULL_SLOT)
|
||||
if (slot == NULL_SLOT && !explicit_pos)
|
||||
return true;
|
||||
|
||||
return slot < pBag->GetBagSize();
|
||||
|
|
@ -8997,8 +8998,9 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
|
|||
if (bag==skip_bag)
|
||||
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
|
||||
|
||||
// skip not existed bag or self targeted bag
|
||||
Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, bag );
|
||||
if (!pBag)
|
||||
if (!pBag || pBag==pSrcItem)
|
||||
return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
|
||||
|
||||
ItemPrototype const* pBagProto = pBag->GetProto();
|
||||
|
|
@ -12172,6 +12174,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 ***/
|
||||
/*********************************************************/
|
||||
|
|
@ -12279,7 +12613,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)
|
||||
{
|
||||
|
|
@ -14954,9 +15289,9 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
|
|||
|
||||
bool success = true;
|
||||
|
||||
// the item/bag is not in a bag
|
||||
if (!bag_guid)
|
||||
{
|
||||
// the item is not in a bag
|
||||
item->SetContainer( NULL );
|
||||
item->SetSlot(slot);
|
||||
|
||||
|
|
@ -14992,13 +15327,20 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff)
|
|||
bagMap[item_guid] = (Bag*)item;
|
||||
}
|
||||
}
|
||||
// the item/bag in a bag
|
||||
else
|
||||
{
|
||||
item->SetSlot(NULL_SLOT);
|
||||
// the item is in a bag, find the bag
|
||||
std::map<uint64, Bag*>::const_iterator itr = bagMap.find(bag_guid);
|
||||
if(itr != bagMap.end() && slot < itr->second->GetBagSize())
|
||||
itr->second->StoreItem(slot, item, true );
|
||||
{
|
||||
ItemPosCountVec dest;
|
||||
if( CanStoreItem( itr->second->GetSlot(), slot, dest, item, false ) == EQUIP_ERR_OK )
|
||||
item = StoreItem(dest, item, true);
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
success = false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue