Core: Updated to 10.0.2

Port From (https://github.com/TrinityCore/TrinityCore/commit/e98e1283ea0034baf6be9aa2ffb386eb5582801b)
This commit is contained in:
hondacrx
2022-12-28 15:25:15 -05:00
parent 2dc12dbb69
commit 989b80b056
100 changed files with 6591 additions and 4112 deletions
@@ -328,7 +328,7 @@ namespace Game.Entities
return;
}
List<uint> bonusListIDs = item.m_itemData.BonusListIDs;
List<uint> bonusListIDs = item.GetBonusListIDs();
foreach (uint bonusId in bonusListIDs)
{
if (bonusId != data.bonusId)
+10 -17
View File
@@ -1363,7 +1363,7 @@ namespace Game.Entities
eqSet.Data.AssignedSpecIndex = result.Read<int>(5);
eqSet.state = EquipmentSetUpdateState.Unchanged;
for (int i = 0; i < EquipmentSlot.End; ++i)
for (int i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
{
ulong guid = result.Read<uint>(6 + i);
if (guid != 0)
@@ -1400,7 +1400,7 @@ namespace Game.Entities
eqSet.Data.IgnoreMask = result.Read<uint>(4);
eqSet.state = EquipmentSetUpdateState.Unchanged;
for (int i = 0; i < EquipmentSlot.End; ++i)
for (int i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
eqSet.Data.Appearances[i] = result.Read<int>(5 + i);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2298,7 +2298,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.IgnoreMask);
stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex);
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter());
stmt.AddValue(j++, GetGUID().GetCounter());
@@ -2312,7 +2312,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon);
stmt.AddValue(j++, eqSet.Data.IgnoreMask);
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Appearances[i]);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2338,7 +2338,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.IgnoreMask);
stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex);
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter());
}
else
@@ -2351,7 +2351,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon);
stmt.AddValue(j++, eqSet.Data.IgnoreMask);
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Appearances[i]);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2680,15 +2680,6 @@ namespace Game.Entities
InitDisplayIds();
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
for (byte slot = EquipmentSlot.Start; slot < EquipmentSlot.End; ++slot)
{
SetInvSlot(slot, ObjectGuid.Empty);
SetVisibleItemSlot(slot, null);
m_items[slot] = null;
}
//Need to call it to initialize m_team (m_team can be calculated from race)
//Other way is to saves m_team into characters table.
SetFactionForRace(GetRace());
@@ -2982,6 +2973,8 @@ namespace Game.Entities
long now = GameTime.GetGameTime();
long logoutTime = logout_time;
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.LogoutTime), logoutTime);
// since last logout (in seconds)
uint time_diff = (uint)(now - logoutTime);
@@ -3431,7 +3424,7 @@ namespace Game.Entities
ss.Clear();
// cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i)
for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
@@ -3577,7 +3570,7 @@ namespace Game.Entities
ss.Clear();
// cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i)
for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
@@ -294,6 +294,7 @@ namespace Game.Entities
public CreatePosition createPosition;
public CreatePosition? createPositionNPE;
public ItemContext itemContext;
public List<PlayerCreateInfoItem> item = new();
public List<uint> customSpells = new();
public List<uint>[] castSpells = new List<uint>[(int)PlayerCreateMode.Max];
+75 -19
View File
@@ -1219,42 +1219,41 @@ namespace Game.Entities
return lastItem;
}
bool StoreNewItemInBestSlots(uint titem_id, uint titem_amount)
bool StoreNewItemInBestSlots(uint itemId, uint amount, ItemContext context)
{
Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", titem_id, titem_amount);
Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", itemId, amount);
ItemContext itemContext = ItemContext.NewCharacter;
var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(titem_id, itemContext);
var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, context);
InventoryResult msg;
// attempt equip by one
while (titem_amount > 0)
while (amount > 0)
{
msg = CanEquipNewItem(ItemConst.NullSlot, out ushort eDest, titem_id, false);
msg = CanEquipNewItem(ItemConst.NullSlot, out ushort eDest, itemId, false);
if (msg != InventoryResult.Ok)
break;
Item item = EquipNewItem(eDest, titem_id, itemContext, true);
Item item = EquipNewItem(eDest, itemId, context, true);
item.SetBonuses(bonusListIDs);
AutoUnequipOffhandIfNeed();
titem_amount--;
--amount;
}
if (titem_amount == 0)
if (amount == 0)
return true; // equipped
// attempt store
List<ItemPosCount> sDest = new();
// store in main bag to simplify second pass (special bags can be not equipped yet at this moment)
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, titem_id, titem_amount);
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, itemId, amount);
if (msg == InventoryResult.Ok)
{
StoreNewItem(sDest, titem_id, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(titem_id), null, itemContext, bonusListIDs);
StoreNewItem(sDest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, context, bonusListIDs);
return true; // stored
}
// item can't be added
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", titem_id, GetRace(), GetClass(), msg);
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", itemId, GetRace(), GetClass(), msg);
return false;
}
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomBonusListId = 0, List<ObjectGuid> allowedLooters = null, ItemContext context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
@@ -1878,7 +1877,7 @@ namespace Game.Entities
pItem.RemoveItemFlag2(ItemFieldFlags2.Equipped);
// remove item dependent auras and casts (only weapon and armor slots)
if (slot < EquipmentSlot.End)
if (slot < ProfessionSlots.End)
{
// update expertise
if (slot == EquipmentSlot.MainHand)
@@ -2789,10 +2788,18 @@ namespace Game.Entities
if (slot < EquipmentSlot.End)
return true;
// profession equipment
if (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End)
return true;
// bag equip slots
if (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd)
return true;
// reagent bag equip slots
if (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd)
return true;
// backpack slots
if (slot >= InventorySlots.ItemStart && slot < InventorySlots.ItemStart + GetInventorySlotCount())
return true;
@@ -3010,7 +3017,7 @@ namespace Game.Entities
// if current back slot non-empty search oldest or free
if (m_items[slot] != null)
{
long oldest_time = m_activePlayerData.BuybackTimestamp[0];
ulong oldest_time = m_activePlayerData.BuybackTimestamp[0];
uint oldest_slot = InventorySlots.BuyBackStart;
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
@@ -3022,7 +3029,7 @@ namespace Game.Entities
break;
}
long i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
ulong i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
if (oldest_time > i_time)
{
oldest_time = i_time;
@@ -3473,7 +3480,7 @@ namespace Game.Entities
DB.Characters.CommitTransaction(trans);
}
public void SetBuybackPrice(uint slot, uint price) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackPrice, (int)slot), price); }
public void SetBuybackTimestamp(uint slot, long timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
public void SetBuybackTimestamp(uint slot, ulong timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
public Item GetItemFromBuyBackSlot(uint slot)
{
@@ -4523,10 +4530,16 @@ namespace Game.Entities
uint freeSlotCount = 0;
if (location.HasFlag(ItemSearchLocation.Equipment))
{
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
for (byte i = ProfessionSlots.Start; i < ProfessionSlots.End; ++i)
if (!GetItemByPos(InventorySlots.Bag0, i))
++freeSlotCount;
}
if (location.HasFlag(ItemSearchLocation.Inventory))
{
int inventoryEnd = InventorySlots.ItemStart + GetInventorySlotCount();
@@ -4565,9 +4578,20 @@ namespace Game.Entities
}
if (location.HasFlag(ItemSearchLocation.ReagentBank))
{
for (byte i = InventorySlots.ReagentBagStart; i < InventorySlots.ReagentBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
if (bag != null)
for (byte j = 0; j < bag.GetBagSize(); ++j)
if (bag.GetItemByPos(j) == null)
++freeSlotCount;
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
}
return freeSlotCount;
}
@@ -4608,7 +4632,8 @@ namespace Game.Entities
public Bag GetBagByPos(byte bag)
{
if ((bag >= InventorySlots.BagStart && bag < InventorySlots.BagEnd)
|| (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd))
|| (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd)
|| (bag >= InventorySlots.ReagentBagStart && bag < InventorySlots.ReagentBagEnd))
{
Item item = GetItemByPos(InventorySlots.Bag0, bag);
if (item != null)
@@ -4624,6 +4649,8 @@ namespace Game.Entities
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
return false;
}
InventoryResult CanStoreItem_InBag(byte bag, List<ItemPosCount> dest, ItemTemplate pProto, ref uint count, bool merge, bool non_specialized, Item pSrcItem, byte skip_bag, byte skip_slot)
@@ -4712,8 +4739,12 @@ namespace Game.Entities
{
if (bag == InventorySlots.Bag0 && (slot < EquipmentSlot.End))
return true;
if (bag == InventorySlots.Bag0 && (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
return false;
}
byte FindEquipSlot(Item item, uint slot, bool swap)
@@ -5246,8 +5277,10 @@ namespace Game.Entities
{
AddTemporarySpell(artifactPowerRank.SpellID);
LearnedSpells learnedSpells = new();
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = artifactPowerRank.SpellID;
learnedSpells.SuppressMessaging = true;
learnedSpells.SpellID.Add(artifactPowerRank.SpellID);
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells);
}
else if (!apply)
@@ -6314,6 +6347,14 @@ namespace Game.Entities
if (!callback(item))
return false;
}
for (byte i = ProfessionSlots.Start; i < ProfessionSlots.End; ++i)
{
Item pItem = GetItemByPos(InventorySlots.Bag0, i);
if (pItem != null)
if (!callback(pItem))
return false;
}
}
if (location.HasAnyFlag(ItemSearchLocation.Inventory))
@@ -6379,6 +6420,21 @@ namespace Game.Entities
if (location.HasAnyFlag(ItemSearchLocation.ReagentBank))
{
for (byte i = InventorySlots.ReagentBagStart; i < InventorySlots.ReagentBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
if (bag != null)
{
for (byte j = 0; j < bag.GetBagSize(); ++j)
{
Item pItem = bag.GetItemByPos(j);
if (pItem != null)
if (!callback(pItem))
return false;
}
}
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
@@ -6471,7 +6527,7 @@ namespace Game.Entities
ForEachItem(ItemSearchLocation.Everywhere, item =>
{
ItemTemplate itemTemplate = item.GetTemplate();
if (itemTemplate != null)
if (itemTemplate != null && itemTemplate.GetInventoryType() < InventoryType.ProfessionTool)
{
ushort dest;
if (item.IsEquipped())
@@ -3114,14 +3114,5 @@ namespace Game.Entities
SendPacket(displayToast);
}
void SendGarrisonOpenTalentNpc(ObjectGuid guid, int garrTalentTreeId, int friendshipFactionId)
{
GarrisonOpenTalentNpc openTalentNpc = new();
openTalentNpc.NpcGUID = guid;
openTalentNpc.GarrTalentTreeID = garrTalentTreeId;
openTalentNpc.FriendshipFactionID = friendshipFactionId;
SendPacket(openTalentNpc);
}
}
}
+10 -6
View File
@@ -2058,10 +2058,12 @@ namespace Game.Entities
// prevent duplicated entires in spell book, also not send if not in world (loading)
if (learning && IsInWorld)
{
LearnedSpells packet = new();
packet.SpellID.Add(spellId);
packet.SuppressMessaging = suppressMessaging;
SendPacket(packet);
LearnedSpells learnedSpells = new();
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = spellId;
learnedSpells.SuppressMessaging = suppressMessaging;
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells);
}
// learn all disabled higher ranks and required spells (recursive)
@@ -3046,8 +3048,10 @@ namespace Game.Entities
void SendSupercededSpell(uint oldSpell, uint newSpell)
{
SupercededSpells supercededSpells = new();
supercededSpells.SpellID.Add(newSpell);
supercededSpells.Superceded.Add(oldSpell);
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = newSpell;
learnedSpellInfo.Superceded = (int)oldSpell;
supercededSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(supercededSpells);
}
@@ -698,6 +698,11 @@ namespace Game.Entities
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
return TalentLearnResult.FailedUnknown;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(talentInfo.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
return TalentLearnResult.FailedCantDoThatRightNow;
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talent != null)
{
+132 -148
View File
@@ -296,7 +296,7 @@ namespace Game.Entities
// original items
foreach (PlayerCreateInfoItem initialItem in info.item)
StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount);
StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount, info.itemContext);
// bags and main-hand weapon must equipped at this moment
// now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon)
@@ -685,7 +685,7 @@ namespace Game.Entities
if (target == this)
{
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -693,23 +693,7 @@ namespace Game.Entities
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.BagStart; i < InventorySlots.BagEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -2329,7 +2313,7 @@ namespace Game.Entities
{
switch (gossipMenuItem.OptionNpc)
{
case GossipOptionNpc.TaxiNode:
case GossipOptionNpc.Taxinode:
if (GetSession().SendLearnNewTaxiNode(creature))
return;
break;
@@ -2337,7 +2321,7 @@ namespace Game.Entities
if (!IsDead())
canTalk = false;
break;
case GossipOptionNpc.BattleMaster:
case GossipOptionNpc.Battlemaster:
if (!creature.CanInteractWithBattleMaster(this, false))
canTalk = false;
break;
@@ -2347,7 +2331,7 @@ namespace Game.Entities
if (!creature.CanResetTalents(this))
canTalk = false;
break;
case GossipOptionNpc.StableMaster:
case GossipOptionNpc.Stablemaster:
case GossipOptionNpc.PetSpecializationMaster:
if (GetClass() != Class.Hunter)
canTalk = false;
@@ -2376,32 +2360,32 @@ namespace Game.Entities
canTalk = false; // Deprecated
break;
case GossipOptionNpc.GuildBanker:
case GossipOptionNpc.SpellClick:
case GossipOptionNpc.WorldPVPQueue:
case GossipOptionNpc.Spellclick:
case GossipOptionNpc.WorldPvPQueue:
case GossipOptionNpc.LFGDungeon:
case GossipOptionNpc.ArtifactRespec:
case GossipOptionNpc.QueueScenario:
case GossipOptionNpc.GarrisonArchitect:
case GossipOptionNpc.GarrisonMission:
case GossipOptionNpc.GarrisonMissionNpc:
case GossipOptionNpc.ShipmentCrafter:
case GossipOptionNpc.GarrisonTradeskill:
case GossipOptionNpc.GarrisonTradeskillNpc:
case GossipOptionNpc.GarrisonRecruitment:
case GossipOptionNpc.AdventureMap:
case GossipOptionNpc.GarrisonTalent:
case GossipOptionNpc.ContributionCollector:
case GossipOptionNpc.IslandsMission:
case GossipOptionNpc.IslandsMissionNpc:
case GossipOptionNpc.UIItemInteraction:
case GossipOptionNpc.WorldMap:
case GossipOptionNpc.Soulbind:
case GossipOptionNpc.ChromieTime:
case GossipOptionNpc.CovenantPreview:
case GossipOptionNpc.ChromieTimeNpc:
case GossipOptionNpc.CovenantPreviewNpc:
case GossipOptionNpc.RuneforgeLegendaryCrafting:
case GossipOptionNpc.NewPlayerGuide:
case GossipOptionNpc.RuneforgeLegendaryUpgrade:
case GossipOptionNpc.CovenantRenown:
case GossipOptionNpc.CovenantRenownNpc:
break; // NYI
default:
Log.outError(LogFilter.Sql, $"Creature entry {creature.GetEntry()} has an unknown gossip option icon {gossipMenuItem.OptionNpc} for menu {gossipMenuItem.MenuId}.");
Log.outError(LogFilter.Sql, $"Creature entry {creature.GetEntry()} has an unknown gossip option icon {gossipMenuItem.OptionNpc} for menu {gossipMenuItem.MenuID}.");
canTalk = false;
break;
}
@@ -2421,45 +2405,7 @@ namespace Game.Entities
}
if (canTalk)
{
string strOptionText;
string strBoxText;
BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItem.OptionBroadcastTextId);
BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItem.BoxBroadcastTextId);
Locale locale = GetSession().GetSessionDbLocaleIndex();
if (optionBroadcastText != null)
strOptionText = Global.DB2Mgr.GetBroadcastTextValue(optionBroadcastText, locale, GetGender());
else
strOptionText = gossipMenuItem.OptionText;
if (boxBroadcastText != null)
strBoxText = Global.DB2Mgr.GetBroadcastTextValue(boxBroadcastText, locale, GetGender());
else
strBoxText = gossipMenuItem.BoxText;
if (locale != Locale.enUS)
{
if (optionBroadcastText == null)
{
// Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, gossipMenuItem.OptionId);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.OptionText, locale, ref strOptionText);
}
if (boxBroadcastText == null)
{
// Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, gossipMenuItem.OptionId);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.BoxText, locale, ref strBoxText);
}
}
menu.GetGossipMenu().AddMenuItem((int)gossipMenuItem.OptionId, gossipMenuItem.OptionNpc, strOptionText, 0, (uint)gossipMenuItem.OptionNpc, strBoxText, gossipMenuItem.BoxMoney, gossipMenuItem.BoxCoded);
menu.GetGossipMenu().AddGossipMenuItemData(gossipMenuItem.OptionId, gossipMenuItem.ActionMenuId, gossipMenuItem.ActionPoiId);
}
menu.GetGossipMenu().AddMenuItem(gossipMenuItem, gossipMenuItem.MenuID, gossipMenuItem.OrderIndex);
}
}
public void SendPreparedGossip(WorldObject source)
@@ -2486,7 +2432,7 @@ namespace Game.Entities
PlayerTalkClass.SendGossipMenu(textId, source.GetGUID());
}
public void OnGossipSelect(WorldObject source, uint gossipListId, uint menuId)
public void OnGossipSelect(WorldObject source, int gossipOptionId, uint menuId)
{
GossipMenu gossipMenu = PlayerTalkClass.GetGossipMenu();
@@ -2494,7 +2440,7 @@ namespace Game.Entities
if (menuId != gossipMenu.GetMenuId())
return;
GossipMenuItem item = gossipMenu.GetItem(gossipListId);
GossipMenuItem item = gossipMenu.GetItem(gossipOptionId);
if (item == null)
return;
@@ -2510,10 +2456,6 @@ namespace Game.Entities
}
}
GossipMenuItemData menuItemData = gossipMenu.GetItemData(gossipListId);
if (menuItemData == null)
return;
long cost = item.BoxMoney;
if (!HasEnoughMoney(cost))
{
@@ -2522,51 +2464,37 @@ namespace Game.Entities
return;
}
if (item.ActionPoiID != 0)
PlayerTalkClass.SendPointOfInterest(item.ActionPoiID);
if (item.ActionMenuID != 0)
{
PrepareGossipMenu(source, item.ActionMenuID);
SendPreparedGossip(source);
}
// types that have their dedicated open opcode dont send WorldPackets::NPC::GossipOptionNPCInteraction
bool handled = true;
switch (gossipOptionNpc)
{
case GossipOptionNpc.None:
{
if (menuItemData.GossipActionPoi != 0)
PlayerTalkClass.SendPointOfInterest(menuItemData.GossipActionPoi);
if (menuItemData.GossipActionMenuId != 0)
{
PrepareGossipMenu(source, menuItemData.GossipActionMenuId);
SendPreparedGossip(source);
}
break;
}
case GossipOptionNpc.Vendor:
GetSession().SendListInventory(guid);
break;
case GossipOptionNpc.TaxiNode:
case GossipOptionNpc.Taxinode:
GetSession().SendTaxiMenu(source.ToCreature());
break;
case GossipOptionNpc.Trainer:
GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, gossipListId));
GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, (uint)gossipOptionId));
break;
case GossipOptionNpc.SpiritHealer:
if (IsDead())
source.ToCreature().CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask)
.SetOriginalCaster(GetGUID()));
break;
case GossipOptionNpc.Binder:
PlayerTalkClass.SendCloseGossip();
SetBindPoint(guid);
break;
case GossipOptionNpc.Banker:
GetSession().SendShowBank(guid);
source.CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCaster(GetGUID()));
handled = false;
break;
case GossipOptionNpc.PetitionVendor:
PlayerTalkClass.SendCloseGossip();
GetSession().SendPetitionShowList(guid);
break;
case GossipOptionNpc.TabardVendor:
PlayerTalkClass.SendCloseGossip();
GetSession().SendTabardVendorActivate(guid);
break;
case GossipOptionNpc.BattleMaster:
case GossipOptionNpc.Battlemaster:
{
BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.GetBattleMasterBG(source.GetEntry());
@@ -2586,13 +2514,25 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents);
break;
case GossipOptionNpc.StableMaster:
case GossipOptionNpc.Stablemaster:
GetSession().SendStablePet(guid);
break;
case GossipOptionNpc.PetSpecializationMaster:
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.PetTalents);
break;
case GossipOptionNpc.GuildBanker:
Guild guild = GetGuild();
if (guild != null)
guild.SendBankList(GetSession(), 0, true);
else
Guild.SendCommandResult(GetSession(), GuildCommandType.ViewTab, GuildCommandError.PlayerNotInGuild);
break;
case GossipOptionNpc.Spellclick:
Unit sourceUnit = source.ToUnit();
if (sourceUnit != null)
sourceUnit.HandleSpellClick(this);
break;
case GossipOptionNpc.DisableXPGain:
PlayerTalkClass.SendCloseGossip();
CastSpell(null, PlayerConst.SpellExperienceEliminated, true);
@@ -2603,9 +2543,6 @@ namespace Game.Entities
RemoveAurasDueToSpell(PlayerConst.SpellExperienceEliminated);
RemovePlayerFlag(PlayerFlags.NoXPGain);
break;
case GossipOptionNpc.Mailbox:
GetSession().SendShowMailBox(guid);
break;
case GossipOptionNpc.SpecializationMaster:
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Specialization);
@@ -2614,22 +2551,74 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs);
break;
case GossipOptionNpc.GarrisonTalent:
case GossipOptionNpc.GarrisonTradeskillNpc: // NYI
break;
case GossipOptionNpc.GarrisonRecruitment: // NYI
break;
case GossipOptionNpc.ChromieTimeNpc: // NYI
break;
case GossipOptionNpc.RuneforgeLegendaryCrafting: // NYI
break;
case GossipOptionNpc.RuneforgeLegendaryUpgrade: // NYI
break;
case GossipOptionNpc.ProfessionsCraftingOrder: // NYI
break;
case GossipOptionNpc.ProfessionsCustomerOrder: // NYI
break;
case GossipOptionNpc.BarbersChoice: // NYI - unknown if needs sending
default:
handled = false;
break;
}
if (!handled)
{
if (item.GossipNpcOptionID.HasValue)
{
GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId);
GossipMenuItemAddon itemAddon = Global.ObjectMgr.GetGossipMenuItemAddon(menuId, gossipListId);
SendGarrisonOpenTalentNpc(guid, itemAddon != null ? itemAddon.GarrTalentTreeID.GetValueOrDefault(0) : 0, addon != null ? addon.FriendshipFactionID : 0);
break;
GossipOptionNPCInteraction npcInteraction = new();
npcInteraction.GossipGUID = source.GetGUID();
npcInteraction.GossipNpcOptionID = item.GossipNpcOptionID.Value;
if (addon != null && addon.FriendshipFactionID != 0)
npcInteraction.FriendshipFactionID = addon.FriendshipFactionID;
SendPacket(npcInteraction);
}
else
{
PlayerInteractionType[] GossipOptionNpcToInteractionType =
{
PlayerInteractionType.None, PlayerInteractionType.Vendor, PlayerInteractionType.TaxiNode,
PlayerInteractionType.Trainer, PlayerInteractionType.SpiritHealer, PlayerInteractionType.Binder,
PlayerInteractionType.Banker, PlayerInteractionType.PetitionVendor, PlayerInteractionType.TabardVendor,
PlayerInteractionType.BattleMaster, PlayerInteractionType.Auctioneer, PlayerInteractionType.TalentMaster,
PlayerInteractionType.StableMaster, PlayerInteractionType.None, PlayerInteractionType.GuildBanker,
PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.None,
PlayerInteractionType.MailInfo, PlayerInteractionType.None, PlayerInteractionType.LFGDungeon,
PlayerInteractionType.ArtifactForge, PlayerInteractionType.None, PlayerInteractionType.SpecializationMaster,
PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.GarrArchitect,
PlayerInteractionType.GarrMission, PlayerInteractionType.ShipmentCrafter, PlayerInteractionType.GarrTradeskill,
PlayerInteractionType.GarrRecruitment, PlayerInteractionType.AdventureMap, PlayerInteractionType.GarrTalent,
PlayerInteractionType.ContributionCollector, PlayerInteractionType.Transmogrifier, PlayerInteractionType.AzeriteRespec,
PlayerInteractionType.IslandQueue, PlayerInteractionType.ItemInteraction, PlayerInteractionType.WorldMap,
PlayerInteractionType.Soulbind, PlayerInteractionType.ChromieTime, PlayerInteractionType.CovenantPreview,
PlayerInteractionType.LegendaryCrafting, PlayerInteractionType.NewPlayerGuide, PlayerInteractionType.LegendaryCrafting,
PlayerInteractionType.Renown, PlayerInteractionType.BlackMarketAuctioneer, PlayerInteractionType.PerksProgramVendor,
PlayerInteractionType.ProfessionsCraftingOrder, PlayerInteractionType.Professions, PlayerInteractionType.ProfessionsCustomerOrder,
PlayerInteractionType.TraitSystem, PlayerInteractionType.BarbersChoice, PlayerInteractionType.MajorFactionRenown
};
PlayerInteractionType interactionType = GossipOptionNpcToInteractionType[(int)gossipOptionNpc];
if (interactionType != PlayerInteractionType.None)
{
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = source.GetGUID();
npcInteraction.InteractionType = interactionType;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
}
case GossipOptionNpc.Transmogrify:
GetSession().SendOpenTransmogrifier(guid);
break;
case GossipOptionNpc.AzeriteRespec:
PlayerTalkClass.SendCloseGossip();
GetSession().SendAzeriteRespecNPC(guid);
break;
default:
break;
}
ModifyMoney(-cost);
@@ -2916,8 +2905,11 @@ namespace Game.Entities
}
public void SetBindPoint(ObjectGuid guid)
{
BinderConfirm packet = new(guid);
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.Binder;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
public void SendBindPointUpdate()
{
@@ -4021,7 +4013,7 @@ namespace Game.Entities
corpse.SetDisplayId(GetNativeDisplayId());
corpse.SetFactionTemplate(CliDB.ChrRacesStorage.LookupByKey(GetRace()).FactionID);
for (byte i = 0; i < EquipmentSlot.End; i++)
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; i++)
{
if (m_items[i] != null)
{
@@ -6240,7 +6232,6 @@ namespace Game.Entities
packet.Reason = victim ? PlayerLogXPReason.Kill : PlayerLogXPReason.NoKill;
packet.Amount = (int)xp;
packet.GroupBonus = group_rate;
packet.ReferAFriendBonusType = (byte)(recruitAFriend ? 1 : 0);
SendPacket(packet);
uint nextLvlXP = GetXPForNextLevel();
@@ -7238,7 +7229,7 @@ namespace Game.Entities
{
if (target == this)
{
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -7246,23 +7237,7 @@ namespace Game.Entities
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.BagStart; i < InventorySlots.BankBagEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -7392,9 +7367,18 @@ namespace Game.Entities
}
//Helpers
public void AddGossipItem(GossipOptionNpc icon, string message, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, "", 0); }
public void AddGossipItem(uint menuId, uint menuItemId, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(menuId, menuItemId, sender, action); }
public void ADD_GOSSIP_ITEM_EXTENDED(GossipOptionNpc icon, string message, uint sender, uint action, string boxmessage, uint boxmoney, bool coded) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, boxmessage, boxmoney, coded); }
public void AddGossipItem(GossipOptionNpc optionNpc, string text, uint sender, uint action)
{
PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, false, 0, "", null, null, sender, action);
}
public void AddGossipItem(GossipOptionNpc optionNpc, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded)
{
PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, coded, popupMoney, popupText, null, null, sender, action);
}
public void AddGossipItem(uint gossipMenuID, uint gossipMenuItemID, uint sender, uint action)
{
PlayerTalkClass.GetGossipMenu().AddMenuItem(gossipMenuID, gossipMenuItemID, sender, action);
}
// This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64)
public void SendGossipMenu(uint titleId, ObjectGuid objGUID) { PlayerTalkClass.SendGossipMenu(titleId, objGUID); }