Core/Loot: Implemented automatic flagging of tracking quests from loot
Port From (https://github.com/TrinityCore/TrinityCore/commit/d913e38cbab9521c80d826417093d22b2c4a1c1a)
This commit is contained in:
@@ -1509,8 +1509,9 @@ namespace Framework.Constants
|
|||||||
|
|
||||||
public enum LootStoreItemType
|
public enum LootStoreItemType
|
||||||
{
|
{
|
||||||
Item = 0,
|
Item = 0,
|
||||||
Reference = 1,
|
Reference = 1,
|
||||||
Currency = 2,
|
Currency = 2,
|
||||||
|
TrackingQuest = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ namespace Framework.Constants
|
|||||||
CommandNpcShowlootMoney = 292,
|
CommandNpcShowlootMoney = 292,
|
||||||
CommandNpcShowlootLabel2 = 293,
|
CommandNpcShowlootLabel2 = 293,
|
||||||
CommandNpcShowlootSublabel = 294,
|
CommandNpcShowlootSublabel = 294,
|
||||||
CommandNpcShowlootEntry2 = 295,
|
CommandNpcShowlootTrackingQuest = 295,
|
||||||
CommandNpcShowLootCurrency = 296,
|
CommandNpcShowLootCurrency = 296,
|
||||||
|
|
||||||
// End
|
// End
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ namespace Framework.Constants
|
|||||||
public enum LootItemType
|
public enum LootItemType
|
||||||
{
|
{
|
||||||
Item = 0,
|
Item = 0,
|
||||||
Currency = 1
|
Currency = 1,
|
||||||
|
TrackingQuest = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LootError
|
public enum LootError
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ namespace Game.Chat
|
|||||||
if (itemTemplate != null)
|
if (itemTemplate != null)
|
||||||
name = itemTemplate.GetName(handler.GetSessionDbcLocale());
|
name = itemTemplate.GetName(handler.GetSessionDbcLocale());
|
||||||
|
|
||||||
handler.SendSysMessage(alternateString ? CypherStrings.CommandNpcShowlootEntry2 : CypherStrings.CommandNpcShowlootEntry,
|
handler.SendSysMessage(CypherStrings.CommandNpcShowlootEntry, alternateString ? 6 : 3 /*number of bytes from following string*/, "\xE2\x94\x80\xE2\x94\x80",
|
||||||
itemCount, ItemConst.ItemQualityColors[(int)(itemTemplate != null ? itemTemplate.GetQuality() : ItemQuality.Poor)], itemId, name, itemId);
|
itemCount, ItemConst.ItemQualityColors[(int)(itemTemplate != null ? itemTemplate.GetQuality() : ItemQuality.Poor)], itemId, name, itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,6 +539,23 @@ namespace Game.Chat
|
|||||||
count, ItemConst.ItemQualityColors[currency != null ? currency.Quality : (int)ItemQuality.Poor], currencyId, count, name, currencyId);
|
count, ItemConst.ItemQualityColors[currency != null ? currency.Quality : (int)ItemQuality.Poor], currencyId, count, name, currencyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _ShowLootTrackingQuestCurrencyEntry(CommandHandler handler, uint questId, bool alternateString = false)
|
||||||
|
{
|
||||||
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||||
|
string name = "Unknown quest";
|
||||||
|
if (quest != null)
|
||||||
|
{
|
||||||
|
name = quest.LogTitle;
|
||||||
|
if (handler.GetSessionDbcLocale() != Locale.enUS)
|
||||||
|
{
|
||||||
|
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(questId);
|
||||||
|
if (localeData != null)
|
||||||
|
ObjectManager.GetLocaleString(localeData.LogTitle, handler.GetSessionDbcLocale(), ref name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.SendSysMessage(CypherStrings.CommandNpcShowlootTrackingQuest, alternateString ? 6 : 3 /*number of bytes from following string*/, "\xE2\x94\x80\xE2\x94\x80", questId, name, questId);
|
||||||
|
}
|
||||||
|
|
||||||
static void _IterateNotNormalLootMap(CommandHandler handler, MultiMap<ObjectGuid, NotNormalLootItem> map, List<LootItem> items)
|
static void _IterateNotNormalLootMap(CommandHandler handler, MultiMap<ObjectGuid, NotNormalLootItem> map, List<LootItem> items)
|
||||||
{
|
{
|
||||||
foreach (var key in map.Keys)
|
foreach (var key in map.Keys)
|
||||||
@@ -564,6 +581,9 @@ namespace Game.Chat
|
|||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count, true);
|
_ShowLootCurrencyEntry(handler, item.itemid, item.count, true);
|
||||||
break;
|
break;
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
_ShowLootTrackingQuestCurrencyEntry(handler, item.itemid, true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +609,9 @@ namespace Game.Chat
|
|||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
||||||
break;
|
break;
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
_ShowLootTrackingQuestCurrencyEntry(handler, item.itemid);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -608,6 +631,9 @@ namespace Game.Chat
|
|||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
||||||
break;
|
break;
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
_ShowLootTrackingQuestCurrencyEntry(handler, item.itemid);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6104,6 +6104,9 @@ namespace Game.Entities
|
|||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
ModifyCurrency(item.itemid, (int)item.count, CurrencyGainSource.Loot);
|
ModifyCurrency(item.itemid, (int)item.count, CurrencyGainSource.Loot);
|
||||||
break;
|
break;
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
// nothing to do, already handled
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffaItem != null)
|
if (ffaItem != null)
|
||||||
@@ -6212,7 +6215,7 @@ namespace Game.Entities
|
|||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
|
|
||||||
// add 'this' player as one of the players that are looting 'loot'
|
// add 'this' player as one of the players that are looting 'loot'
|
||||||
loot.OnLootOpened(GetMap(), GetGUID());
|
loot.OnLootOpened(GetMap(), this);
|
||||||
m_AELootView[loot.GetGUID()] = loot;
|
m_AELootView[loot.GetGUID()] = loot;
|
||||||
|
|
||||||
if (loot.loot_type == LootType.Corpse && !loot.GetOwnerGUID().IsItem())
|
if (loot.loot_type == LootType.Corpse && !loot.GetOwnerGUID().IsItem())
|
||||||
|
|||||||
+69
-11
@@ -54,6 +54,10 @@ namespace Game.Loots
|
|||||||
type = LootItemType.Currency;
|
type = LootItemType.Currency;
|
||||||
freeforall = true;
|
freeforall = true;
|
||||||
break;
|
break;
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
type = LootItemType.TrackingQuest;
|
||||||
|
freeforall = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -73,6 +77,8 @@ namespace Game.Loots
|
|||||||
return ItemAllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions);
|
return ItemAllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions);
|
||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
return CurrencyAllowedForPlayer(player, itemid, needs_quest, conditions);
|
return CurrencyAllowedForPlayer(player, itemid, needs_quest, conditions);
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
return TrackingQuestAllowedForPlayer(player, itemid, conditions);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -89,6 +95,8 @@ namespace Game.Loots
|
|||||||
strictUsabilityCheck, lootStoreItem.conditions);
|
strictUsabilityCheck, lootStoreItem.conditions);
|
||||||
case LootStoreItemType.Currency:
|
case LootStoreItemType.Currency:
|
||||||
return CurrencyAllowedForPlayer(player, lootStoreItem.itemid, lootStoreItem.needs_quest, lootStoreItem.conditions);
|
return CurrencyAllowedForPlayer(player, lootStoreItem.itemid, lootStoreItem.needs_quest, lootStoreItem.conditions);
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
return TrackingQuestAllowedForPlayer(player, lootStoreItem.itemid, lootStoreItem.conditions);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -173,6 +181,18 @@ namespace Game.Loots
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TrackingQuestAllowedForPlayer(Player player, uint questId, ConditionsReference conditions)
|
||||||
|
{
|
||||||
|
// DB conditions check
|
||||||
|
if (!conditions.Meets(player))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (player.IsQuestCompletedBitSet(questId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void AddAllowedLooter(Player player)
|
public void AddAllowedLooter(Player player)
|
||||||
{
|
{
|
||||||
allowedGUIDs.Add(player.GetGUID());
|
allowedGUIDs.Add(player.GetGUID());
|
||||||
@@ -781,6 +801,14 @@ namespace Game.Loots
|
|||||||
items.Add(generatedLoot);
|
items.Add(generatedLoot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
{
|
||||||
|
LootItem generatedLoot = new(item);
|
||||||
|
generatedLoot.count = 1;
|
||||||
|
generatedLoot.LootListId = (uint)items.Count;
|
||||||
|
items.Add(generatedLoot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -834,6 +862,11 @@ namespace Game.Loots
|
|||||||
case LootItemType.Currency:
|
case LootItemType.Currency:
|
||||||
player.ModifyCurrency(lootItem.itemid, (int)lootItem.count, CurrencyGainSource.Loot);
|
player.ModifyCurrency(lootItem.itemid, (int)lootItem.count, CurrencyGainSource.Loot);
|
||||||
break;
|
break;
|
||||||
|
case LootItemType.TrackingQuest:
|
||||||
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(lootItem.itemid);
|
||||||
|
if (quest != null)
|
||||||
|
player.RewardQuest(quest, LootItemType.Item, 0, player, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (ffaitem != null)
|
if (ffaitem != null)
|
||||||
ffaitem.is_looted = true;
|
ffaitem.is_looted = true;
|
||||||
@@ -847,6 +880,22 @@ namespace Game.Loots
|
|||||||
return allLooted;
|
return allLooted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoStoreTrackingQuests(Player player, List<NotNormalLootItem> ffaItems)
|
||||||
|
{
|
||||||
|
foreach (NotNormalLootItem ffaItem in ffaItems)
|
||||||
|
{
|
||||||
|
if (items[ffaItem.LootListId].type != LootItemType.TrackingQuest)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
--unlootedCount;
|
||||||
|
ffaItem.is_looted = true;
|
||||||
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(items[ffaItem.LootListId].itemid);
|
||||||
|
if (quest != null)
|
||||||
|
player.RewardQuest(quest, LootItemType.Item, 0, player, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void LootMoney()
|
public void LootMoney()
|
||||||
{
|
{
|
||||||
gold = 0;
|
gold = 0;
|
||||||
@@ -965,7 +1014,13 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ffaItems.Empty())
|
if (!ffaItems.Empty())
|
||||||
|
{
|
||||||
|
// TODO: flag immediately for loot that is supposed to be mailed if unlooted, otherwise flag when sending SMSG_LOOT_RESPONSE
|
||||||
|
//if (_mailUnlootedItems)
|
||||||
|
// AutoStoreTrackingQuests(player, *ffaItems);
|
||||||
|
|
||||||
PlayerFFAItems[player.GetGUID()] = ffaItems;
|
PlayerFFAItems[player.GetGUID()] = ffaItems;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NotifyItemRemoved(byte lootListId, Map map)
|
public void NotifyItemRemoved(byte lootListId, Map map)
|
||||||
@@ -999,9 +1054,9 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnLootOpened(Map map, ObjectGuid looter)
|
public void OnLootOpened(Map map, Player looter)
|
||||||
{
|
{
|
||||||
AddLooter(looter);
|
AddLooter(looter.GetGUID());
|
||||||
if (!_wasOpened)
|
if (!_wasOpened)
|
||||||
{
|
{
|
||||||
_wasOpened = true;
|
_wasOpened = true;
|
||||||
@@ -1033,19 +1088,21 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
else if (_lootMethod == LootMethod.MasterLoot)
|
else if (_lootMethod == LootMethod.MasterLoot)
|
||||||
{
|
{
|
||||||
if (looter == _lootMaster)
|
if (looter.GetGUID() == _lootMaster)
|
||||||
{
|
{
|
||||||
Player lootMaster = Global.ObjAccessor.GetPlayer(map, looter);
|
MasterLootCandidateList masterLootCandidateList = new();
|
||||||
if (lootMaster != null)
|
masterLootCandidateList.LootObj = GetGUID();
|
||||||
{
|
masterLootCandidateList.Players = _allowedLooters;
|
||||||
MasterLootCandidateList masterLootCandidateList = new();
|
looter.SendPacket(masterLootCandidateList);
|
||||||
masterLootCandidateList.LootObj = GetGUID();
|
|
||||||
masterLootCandidateList.Players = _allowedLooters;
|
|
||||||
lootMaster.SendPacket(masterLootCandidateList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flag tracking quests as completed after all items were scanned for this player (some might depend on this quest not being completed)
|
||||||
|
//if (!_mailUnlootedItems)
|
||||||
|
var ffaItems = PlayerFFAItems.LookupByKey(looter.GetGUID());
|
||||||
|
if (ffaItems != null)
|
||||||
|
AutoStoreTrackingQuests(looter, ffaItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasAllowedLooter(ObjectGuid looter)
|
public bool HasAllowedLooter(ObjectGuid looter)
|
||||||
@@ -1163,6 +1220,7 @@ namespace Game.Loots
|
|||||||
LootItemData lootItem = new();
|
LootItemData lootItem = new();
|
||||||
lootItem.LootListID = (byte)item.LootListId;
|
lootItem.LootListID = (byte)item.LootListId;
|
||||||
lootItem.UIType = uiType.Value;
|
lootItem.UIType = uiType.Value;
|
||||||
|
lootItem.Type = (byte)item.type;
|
||||||
lootItem.Quantity = item.count;
|
lootItem.Quantity = item.count;
|
||||||
lootItem.Loot = new(item);
|
lootItem.Loot = new(item);
|
||||||
packet.Items.Add(lootItem);
|
packet.Items.Add(lootItem);
|
||||||
|
|||||||
@@ -532,6 +532,8 @@ namespace Game.Loots
|
|||||||
|
|
||||||
return RandomHelper.randChance(chance * qualityModifier);
|
return RandomHelper.randChance(chance * qualityModifier);
|
||||||
}
|
}
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
return RandomHelper.randChance(chance);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -611,6 +613,40 @@ namespace Game.Loots
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
{
|
||||||
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(itemid);
|
||||||
|
if (quest == null)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: quest does not exist - skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!quest.HasFlag(QuestFlags.TrackingEvent))
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: quest is not a tracking flag - skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chance == 0 && groupid == 0) // Zero chance is allowed for grouped entries only
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: equal-chanced grouped entry, but group not defined - skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chance != 0 && chance < 0.0001f) // loot with low chance
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: low chance ({chance}) - skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mincount != 1 || maxcount != 0) // wrong count
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: tracking quest has count other than 1 (MinCount {maxcount} MaxCount {mincount}) - skipped");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} Item {itemid}: invalid ItemType {type}, skipped");
|
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} Item {itemid}: invalid ItemType {type}, skipped");
|
||||||
return false;
|
return false;
|
||||||
@@ -804,6 +840,7 @@ namespace Game.Loots
|
|||||||
{
|
{
|
||||||
case LootStoreItemType.Item:
|
case LootStoreItemType.Item:
|
||||||
case LootStoreItemType.Currency:
|
case LootStoreItemType.Currency:
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
// Plain entries (not a reference, not grouped)
|
// Plain entries (not a reference, not grouped)
|
||||||
// Chance is already checked, just add
|
// Chance is already checked, just add
|
||||||
if (personalLooter == null || LootItem.AllowedForPlayer(personalLooter, item, true))
|
if (personalLooter == null || LootItem.AllowedForPlayer(personalLooter, item, true))
|
||||||
@@ -899,6 +936,7 @@ namespace Game.Loots
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LootStoreItemType.Currency:
|
case LootStoreItemType.Currency:
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
{
|
{
|
||||||
// Plain entries (not a reference, not grouped)
|
// Plain entries (not a reference, not grouped)
|
||||||
// Chance is already checked, just add
|
// Chance is already checked, just add
|
||||||
@@ -949,6 +987,8 @@ namespace Game.Loots
|
|||||||
switch (lootStoreItem.type)
|
switch (lootStoreItem.type)
|
||||||
{
|
{
|
||||||
case LootStoreItemType.Item:
|
case LootStoreItemType.Item:
|
||||||
|
case LootStoreItemType.Currency:
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
if (LootItem.AllowedForPlayer(player, lootStoreItem, strictUsabilityCheck))
|
if (LootItem.AllowedForPlayer(player, lootStoreItem, strictUsabilityCheck))
|
||||||
return true; // active quest drop found
|
return true; // active quest drop found
|
||||||
break;
|
break;
|
||||||
@@ -989,6 +1029,10 @@ namespace Game.Loots
|
|||||||
if (li.type != LootItemType.Currency)
|
if (li.type != LootItemType.Currency)
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
case LootStoreItemType.TrackingQuest:
|
||||||
|
if (li.type != LootItemType.TrackingQuest)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user