Core/Loot: Implemented currency loot
Port From (https://github.com/TrinityCore/TrinityCore/commit/3e28ee080a1cf3c7cd332a8d1e0808505b4ea9d4)
This commit is contained in:
@@ -1454,5 +1454,6 @@ namespace Framework.Constants
|
||||
{
|
||||
Item = 0,
|
||||
Reference = 1,
|
||||
Currency = 2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ namespace Framework.Constants
|
||||
CommandNpcShowlootLabel2 = 293,
|
||||
CommandNpcShowlootSublabel = 294,
|
||||
CommandNpcShowlootEntry2 = 295,
|
||||
// 296 Free
|
||||
CommandNpcShowLootCurrency = 296,
|
||||
|
||||
// End
|
||||
CommandWanderDistance = 297,
|
||||
|
||||
@@ -663,10 +663,10 @@ namespace Framework.Database
|
||||
PrepareStatement(CharStatements.DEL_CHAR_CUF_PROFILES, "DELETE FROM character_cuf_profiles WHERE guid = ?");
|
||||
|
||||
// Items that hold loot or money
|
||||
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS, "SELECT container_id, item_id, item_count, item_index, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids FROM item_loot_items");
|
||||
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_ITEMS, "SELECT container_id, item_type, item_id, item_count, item_index, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids FROM item_loot_items");
|
||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEMS, "DELETE FROM item_loot_items WHERE container_id = ?");
|
||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEM, "DELETE FROM item_loot_items WHERE container_id = ? AND item_id = ? AND item_count = ? AND item_index = ?");
|
||||
PrepareStatement(CharStatements.INS_ITEMCONTAINER_ITEMS, "INSERT INTO item_loot_items (container_id, item_id, item_count, item_index, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_ITEM, "DELETE FROM item_loot_items WHERE container_id = ? AND item_type = ? AND item_id = ? AND item_count = ? AND item_index = ?");
|
||||
PrepareStatement(CharStatements.INS_ITEMCONTAINER_ITEMS, "INSERT INTO item_loot_items (container_id, item_type, item_id, item_count, item_index, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_bonus, context, bonus_list_ids) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
PrepareStatement(CharStatements.SEL_ITEMCONTAINER_MONEY, "SELECT container_id, money FROM item_loot_money");
|
||||
PrepareStatement(CharStatements.DEL_ITEMCONTAINER_MONEY, "DELETE FROM item_loot_money WHERE container_id = ?");
|
||||
PrepareStatement(CharStatements.INS_ITEMCONTAINER_MONEY, "INSERT INTO item_loot_money (container_id, money) VALUES (?, ?)");
|
||||
|
||||
@@ -611,11 +611,8 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
[Command("currency", RBACPermissions.CommandModifyCurrency)]
|
||||
static bool HandleModifyCurrencyCommand(CommandHandler handler, StringArguments args)
|
||||
static bool HandleModifyCurrencyCommand(CommandHandler handler, CurrencyTypesRecord currency, int amount)
|
||||
{
|
||||
if (args.Empty())
|
||||
return false;
|
||||
|
||||
Player target = handler.GetSelectedPlayerOrSelf();
|
||||
if (target == null)
|
||||
{
|
||||
@@ -624,15 +621,7 @@ namespace Game.Chat
|
||||
return false;
|
||||
}
|
||||
|
||||
uint currencyId = args.NextUInt32();
|
||||
if (!CliDB.CurrencyTypesStorage.ContainsKey(currencyId))
|
||||
return false;
|
||||
|
||||
uint amount = args.NextUInt32();
|
||||
if (amount == 0)
|
||||
return false;
|
||||
|
||||
target.ModifyCurrency(currencyId, (int)amount, CurrencyGainSource.Cheat, CurrencyDestroyReason.Cheat);
|
||||
target.ModifyCurrency(currency.Id, amount, CurrencyGainSource.Cheat, CurrencyDestroyReason.Cheat);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -316,23 +316,23 @@ namespace Game.Chat
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!creatureTarget.IsDead())
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNotDeadOrNoLoot, creatureTarget.GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
Loot loot = creatureTarget._loot;
|
||||
if (creatureTarget.IsDead() || loot == null || loot.IsLooted())
|
||||
if ((loot == null || loot.IsLooted()) && creatureTarget.m_personalLoot.Count(p => p.Value.IsLooted()) == 0)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNotDeadOrNoLoot, creatureTarget.GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootHeader, creatureTarget.GetName(), creatureTarget.GetEntry());
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootMoney, loot.gold / MoneyConstants.Gold, (loot.gold % MoneyConstants.Gold) / MoneyConstants.Silver, loot.gold % MoneyConstants.Silver);
|
||||
|
||||
if (all.Equals("all", StringComparison.OrdinalIgnoreCase)) // nonzero from strcmp <. not equal
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count);
|
||||
foreach (LootItem item in loot.items)
|
||||
if (!item.is_looted)
|
||||
_ShowLootEntry(handler, item.itemid, item.count);
|
||||
}
|
||||
if (loot != null)
|
||||
_ShowLootContents(handler, all == "all", loot);
|
||||
else
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count);
|
||||
@@ -340,10 +340,11 @@ namespace Game.Chat
|
||||
if (!item.is_looted && !item.freeforall && item.conditions.IsEmpty())
|
||||
_ShowLootEntry(handler, item.itemid, item.count);
|
||||
|
||||
if (!loot.GetPlayerFFAItems().Empty())
|
||||
foreach (var (lootOwner, personalLoot) in creatureTarget.m_personalLoot)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, "FFA items per allowed player");
|
||||
_IterateNotNormalLootMap(handler, loot.GetPlayerFFAItems(), loot.items);
|
||||
var character = Global.CharacterCacheStorage.GetCharacterCacheByGuid(lootOwner);
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, $"Personal loot for {(character != null ? character.Name : "")}");
|
||||
_ShowLootContents(handler, all == "all", personalLoot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +516,7 @@ namespace Game.Chat
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _ShowLootEntry(CommandHandler handler, uint itemId, byte itemCount, bool alternateString = false)
|
||||
static void _ShowLootEntry(CommandHandler handler, uint itemId, uint itemCount, bool alternateString = false)
|
||||
{
|
||||
string name = "Unknown item";
|
||||
|
||||
@@ -526,6 +527,18 @@ namespace Game.Chat
|
||||
handler.SendSysMessage(alternateString ? CypherStrings.CommandNpcShowlootEntry2 : CypherStrings.CommandNpcShowlootEntry,
|
||||
itemCount, ItemConst.ItemQualityColors[(int)(itemTemplate != null ? itemTemplate.GetQuality() : ItemQuality.Poor)], itemId, name, itemId);
|
||||
}
|
||||
|
||||
static void _ShowLootCurrencyEntry(CommandHandler handler, uint currencyId, uint count, bool alternateString = false)
|
||||
{
|
||||
CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(currencyId);
|
||||
string name = "Unknown currency";
|
||||
if (currency != null)
|
||||
name = currency.Name;
|
||||
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowLootCurrency, alternateString ? 6 : 3 /*number of bytes from following string*/, "\u2500\u2500",
|
||||
count, ItemConst.ItemQualityColors[currency != null ? currency.Quality : (int)ItemQuality.Poor], currencyId, count, name, currencyId);
|
||||
}
|
||||
|
||||
static void _IterateNotNormalLootMap(CommandHandler handler, MultiMap<ObjectGuid, NotNormalLootItem> map, List<LootItem> items)
|
||||
{
|
||||
foreach (var key in map.Keys)
|
||||
@@ -542,7 +555,67 @@ namespace Game.Chat
|
||||
{
|
||||
LootItem item = items[it.LootListId];
|
||||
if (!it.is_looted && !item.is_looted)
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
_ShowLootEntry(handler, item.itemid, item.count, true);
|
||||
break;
|
||||
case LootItemType.Currency:
|
||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _ShowLootContents(CommandHandler handler, bool all, Loot loot)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootMoney, loot.gold / MoneyConstants.Gold, (loot.gold % MoneyConstants.Gold) / MoneyConstants.Silver, loot.gold % MoneyConstants.Silver);
|
||||
|
||||
if (!all)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count);
|
||||
foreach (LootItem item in loot.items)
|
||||
{
|
||||
if (!item.is_looted)
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
_ShowLootEntry(handler, item.itemid, item.count);
|
||||
break;
|
||||
case LootItemType.Currency:
|
||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count);
|
||||
foreach (LootItem item in loot.items)
|
||||
{
|
||||
if (!item.is_looted && !item.freeforall && item.conditions.IsEmpty())
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
_ShowLootEntry(handler, item.itemid, item.count);
|
||||
break;
|
||||
case LootItemType.Currency:
|
||||
_ShowLootCurrencyEntry(handler, item.itemid, item.count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!loot.GetPlayerFFAItems().Empty())
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, "FFA items per allowed player");
|
||||
_IterateNotNormalLootMap(handler, loot.GetPlayerFFAItems(), loot.items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6066,26 +6066,18 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
switch (item.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
List<ItemPosCount> dest = new();
|
||||
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
|
||||
if (msg == InventoryResult.Ok)
|
||||
if (msg != InventoryResult.Ok)
|
||||
{
|
||||
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context);
|
||||
if (ffaItem != null)
|
||||
{
|
||||
//freeforall case, notify only one player of the removal
|
||||
ffaItem.is_looted = true;
|
||||
SendNotifyLootItemRemoved(loot.GetGUID(), loot.GetOwnerGUID(), lootSlot);
|
||||
SendEquipError(msg, null, null, item.itemid);
|
||||
return;
|
||||
}
|
||||
else //not freeforall, notify everyone
|
||||
loot.NotifyItemRemoved(lootSlot, GetMap());
|
||||
|
||||
//if only one person is supposed to loot the item, then set it to looted
|
||||
if (!item.freeforall)
|
||||
item.is_looted = true;
|
||||
|
||||
--loot.unlootedCount;
|
||||
|
||||
Item newitem = StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context);
|
||||
if (newitem != null && (newitem.GetQuality() > ItemQuality.Epic || (newitem.GetQuality() == ItemQuality.Epic && newitem.GetItemLevel(this) >= GuildConst.MinNewsItemLevel)))
|
||||
{
|
||||
Guild guild = GetGuild();
|
||||
@@ -6102,19 +6094,36 @@ namespace Game.Entities
|
||||
UpdateCriteria(CriteriaType.LootAnyItem, item.itemid, item.count);
|
||||
}
|
||||
else
|
||||
aeResult.Add(newitem, item.count, SharedConst.GetLootTypeForClient(loot.loot_type), loot.GetDungeonEncounterId());
|
||||
|
||||
// LootItem is being removed (looted) from the container, delete it from the DB.
|
||||
if (loot.loot_type == LootType.Item)
|
||||
Global.LootItemStorage.RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item.itemid, item.count, item.LootListId);
|
||||
aeResult.Add(newitem, (byte)item.count, SharedConst.GetLootTypeForClient(loot.loot_type), loot.GetDungeonEncounterId());
|
||||
|
||||
if (newitem != null)
|
||||
ApplyItemLootedSpell(newitem, true);
|
||||
else
|
||||
ApplyItemLootedSpell(Global.ObjectMgr.GetItemTemplate(item.itemid));
|
||||
break;
|
||||
case LootItemType.Currency:
|
||||
ModifyCurrency(item.itemid, (int)item.count, CurrencyGainSource.Loot);
|
||||
break;
|
||||
}
|
||||
else
|
||||
SendEquipError(msg, null, null, item.itemid);
|
||||
|
||||
if (ffaItem != null)
|
||||
{
|
||||
//freeforall case, notify only one player of the removal
|
||||
ffaItem.is_looted = true;
|
||||
SendNotifyLootItemRemoved(loot.GetGUID(), loot.GetOwnerGUID(), lootSlot);
|
||||
}
|
||||
else //not freeforall, notify everyone
|
||||
loot.NotifyItemRemoved(lootSlot, GetMap());
|
||||
|
||||
//if only one person is supposed to loot the item, then set it to looted
|
||||
if (!item.freeforall)
|
||||
item.is_looted = true;
|
||||
|
||||
--loot.unlootedCount;
|
||||
|
||||
// LootItem is being removed (looted) from the container, delete it from the DB.
|
||||
if (loot.loot_type == LootType.Item)
|
||||
Global.LootItemStorage.RemoveStoredLootItemForContainer(lootWorldObjectGuid.GetCounter(), item.type, item.itemid, item.count, item.LootListId);
|
||||
}
|
||||
|
||||
public Dictionary<ObjectGuid, Loot> GetAELootView() { return m_AELootView; }
|
||||
|
||||
@@ -2873,6 +2873,39 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool HasQuestForCurrency(uint currencyId)
|
||||
{
|
||||
bool isCompletableObjective(QuestObjectiveStatusData objectiveStatus)
|
||||
{
|
||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(objectiveStatus.QuestStatusPair.QuestID);
|
||||
QuestObjective objective = Global.ObjectMgr.GetQuestObjective(objectiveStatus.ObjectiveId);
|
||||
if (qInfo == null || objective == null || !IsQuestObjectiveCompletable(objectiveStatus.QuestStatusPair.Status.Slot, qInfo, objective))
|
||||
return false;
|
||||
|
||||
// hide quest if player is in raid-group and quest is no raid quest
|
||||
if (GetGroup() != null && GetGroup().IsRaidGroup() && !qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
||||
if (!InBattleground()) //there are two ways.. we can make every bg-quest a raidquest, or add this code here.. i don't know if this can be exploited by other quests, but i think all other quests depend on a specific area.. but keep this in mind, if something strange happens later
|
||||
return false;
|
||||
|
||||
if (!IsQuestObjectiveComplete(objectiveStatus.QuestStatusPair.Status.Slot, qInfo, objective))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
bool hasObjectiveTypeForCurrency(QuestObjectiveType type) => m_questObjectiveStatus.LookupByKey((type, currencyId)).Any(isCompletableObjective);
|
||||
if (hasObjectiveTypeForCurrency(QuestObjectiveType.Currency))
|
||||
return true;
|
||||
|
||||
if (hasObjectiveTypeForCurrency(QuestObjectiveType.HaveCurrency))
|
||||
return true;
|
||||
|
||||
if (hasObjectiveTypeForCurrency(QuestObjectiveType.ObtainCurrency))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetQuestObjectiveData(QuestObjective objective)
|
||||
{
|
||||
ushort slot = FindQuestSlot(objective.QuestID);
|
||||
|
||||
@@ -427,11 +427,17 @@ namespace Game
|
||||
|
||||
if (req.LootListID >= loot.items.Count)
|
||||
{
|
||||
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterOther);
|
||||
Log.outDebug(LogFilter.Loot, $"MasterLootItem: Player {GetPlayer().GetName()} might be using a hack! (slot {req.LootListID}, size {loot.items.Count})");
|
||||
return;
|
||||
}
|
||||
|
||||
LootItem item = loot.items[req.LootListID];
|
||||
if (item.type != LootItemType.Item)
|
||||
{
|
||||
_player.SendLootError(req.Object, loot.GetOwnerGUID(), LootError.MasterOther);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemPosCount> dest = new();
|
||||
InventoryResult msg = target.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
|
||||
@@ -452,7 +458,7 @@ namespace Game
|
||||
// now move item from loot to target inventory
|
||||
Item newitem = target.StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs);
|
||||
if (newitem != null)
|
||||
aeResult.Add(newitem, item.count, loot.loot_type, loot.GetDungeonEncounterId());
|
||||
aeResult.Add(newitem, (byte)item.count, loot.loot_type, loot.GetDungeonEncounterId());
|
||||
else
|
||||
target.ApplyItemLootedSpell(Global.ObjectMgr.GetItemTemplate(item.itemid));
|
||||
|
||||
|
||||
+142
-39
@@ -16,19 +16,47 @@ namespace Game.Loots
|
||||
{
|
||||
public class LootItem
|
||||
{
|
||||
public uint itemid;
|
||||
public uint LootListId;
|
||||
public uint randomBonusListId;
|
||||
public List<uint> BonusListIDs = new();
|
||||
public ItemContext context;
|
||||
public ConditionsReference conditions; // additional loot condition
|
||||
public List<ObjectGuid> allowedGUIDs = new();
|
||||
public ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list!
|
||||
public uint count;
|
||||
public LootItemType type;
|
||||
public bool is_looted;
|
||||
public bool is_blocked;
|
||||
public bool freeforall; // free for all
|
||||
public bool is_underthreshold;
|
||||
public bool is_counted;
|
||||
public bool needs_quest; // quest drop
|
||||
public bool follow_loot_rules;
|
||||
|
||||
public LootItem() { }
|
||||
public LootItem(LootStoreItem li)
|
||||
{
|
||||
itemid = li.itemid;
|
||||
conditions = li.conditions;
|
||||
|
||||
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemid);
|
||||
freeforall = proto != null && proto.HasFlag(ItemFlags.MultiDrop);
|
||||
follow_loot_rules = !li.needs_quest || (proto != null && proto.FlagsCu.HasAnyFlag(ItemFlagsCustom.FollowLootRules));
|
||||
|
||||
needs_quest = li.needs_quest;
|
||||
|
||||
switch (li.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
randomBonusListId = ItemEnchantmentManager.GenerateItemRandomBonusListId(itemid);
|
||||
type = LootItemType.Item;
|
||||
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemid);
|
||||
freeforall = proto != null && proto.HasFlag(ItemFlags.MultiDrop);
|
||||
follow_loot_rules = !li.needs_quest || (proto != null && proto.HasFlag(ItemFlagsCustom.FollowLootRules));
|
||||
break;
|
||||
case LootStoreItemType.Currency:
|
||||
type = LootItemType.Currency;
|
||||
freeforall = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,10 +67,35 @@ namespace Game.Loots
|
||||
/// <returns></returns>
|
||||
public bool AllowedForPlayer(Player player, Loot loot)
|
||||
{
|
||||
return AllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions);
|
||||
switch (type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
return ItemAllowedForPlayer(player, loot, itemid, needs_quest, follow_loot_rules, false, conditions);
|
||||
case LootItemType.Currency:
|
||||
return CurrencyAllowedForPlayer(player, itemid, needs_quest, conditions);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AllowedForPlayer(Player player, Loot loot, uint itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck, ConditionsReference conditions)
|
||||
public static bool AllowedForPlayer(Player player, LootStoreItem lootStoreItem, bool strictUsabilityCheck)
|
||||
{
|
||||
switch (lootStoreItem.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
return ItemAllowedForPlayer(player, null, lootStoreItem.itemid, lootStoreItem.needs_quest,
|
||||
!lootStoreItem.needs_quest || Global.ObjectMgr.GetItemTemplate(lootStoreItem.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
strictUsabilityCheck, lootStoreItem.conditions);
|
||||
case LootStoreItemType.Currency:
|
||||
return CurrencyAllowedForPlayer(player, lootStoreItem.itemid, lootStoreItem.needs_quest, lootStoreItem.conditions);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ItemAllowedForPlayer(Player player, Loot loot, uint itemid, bool needs_quest, bool follow_loot_rules, bool strictUsabilityCheck, ConditionsReference conditions)
|
||||
{
|
||||
// DB conditions check
|
||||
if (!conditions.Meets(player))
|
||||
@@ -96,6 +149,30 @@ namespace Game.Loots
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CurrencyAllowedForPlayer(Player player, uint currencyId, bool needs_quest, ConditionsReference conditions)
|
||||
{
|
||||
// DB conditions check
|
||||
if (!conditions.Meets(player))
|
||||
return false;
|
||||
|
||||
CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(currencyId);
|
||||
if (currency == null)
|
||||
return false;
|
||||
|
||||
// not show loot for not own team
|
||||
if (currency.HasFlag(CurrencyTypesFlags.IsHordeOnly) && player.GetTeam() != Team.Horde)
|
||||
return false;
|
||||
|
||||
if (currency.HasFlag(CurrencyTypesFlags.IsAllianceOnly) && player.GetTeam() != Team.Alliance)
|
||||
return false;
|
||||
|
||||
// check quest requirements
|
||||
if (needs_quest && !player.HasQuestForCurrency(currencyId))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddAllowedLooter(Player player)
|
||||
{
|
||||
allowedGUIDs.Add(player.GetGUID());
|
||||
@@ -174,23 +251,6 @@ namespace Game.Loots
|
||||
}
|
||||
|
||||
public List<ObjectGuid> GetAllowedLooters() { return allowedGUIDs; }
|
||||
|
||||
public uint itemid;
|
||||
public uint LootListId;
|
||||
public uint randomBonusListId;
|
||||
public List<uint> BonusListIDs = new();
|
||||
public ItemContext context;
|
||||
public ConditionsReference conditions; // additional loot condition
|
||||
public List<ObjectGuid> allowedGUIDs = new();
|
||||
public ObjectGuid rollWinnerGUID; // Stores the guid of person who won loot, if his bags are full only he can see the item in loot list!
|
||||
public byte count;
|
||||
public bool is_looted;
|
||||
public bool is_blocked;
|
||||
public bool freeforall; // free for all
|
||||
public bool is_underthreshold;
|
||||
public bool is_counted;
|
||||
public bool needs_quest; // quest drop
|
||||
public bool follow_loot_rules;
|
||||
}
|
||||
|
||||
public class NotNormalLootItem
|
||||
@@ -630,7 +690,7 @@ namespace Game.Loots
|
||||
for (uint i = 0; i < loot.items.Count; ++i)
|
||||
{
|
||||
LootItem disenchantLoot = loot.LootItemInSlot(i, player);
|
||||
if (disenchantLoot != null)
|
||||
if (disenchantLoot != null && disenchantLoot.type == LootItemType.Item)
|
||||
player.SendItemRetrievalMail(disenchantLoot.itemid, disenchantLoot.count, disenchantLoot.context);
|
||||
}
|
||||
}
|
||||
@@ -659,6 +719,10 @@ namespace Game.Loots
|
||||
|
||||
// Inserts the item into the loot (called by LootTemplate processors)
|
||||
public void AddItem(LootStoreItem item)
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
{
|
||||
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(item.itemid);
|
||||
if (proto == null)
|
||||
@@ -678,6 +742,19 @@ namespace Game.Loots
|
||||
items.Add(generatedLoot);
|
||||
count -= proto.GetMaxStackSize();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LootStoreItemType.Currency:
|
||||
{
|
||||
LootItem generatedLoot = new(item);
|
||||
generatedLoot.count = RandomHelper.URand(item.mincount, item.maxcount);
|
||||
generatedLoot.LootListId = (uint)items.Count;
|
||||
items.Add(generatedLoot);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoStore(Player player, byte bag, byte slot, bool broadcast = false, bool createdByPlayer = false)
|
||||
@@ -699,6 +776,9 @@ namespace Game.Loots
|
||||
if (!lootItem.rollWinnerGUID.IsEmpty() && lootItem.rollWinnerGUID != GetGUID())
|
||||
continue;
|
||||
|
||||
switch (lootItem.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
List<ItemPosCount> dest = new();
|
||||
InventoryResult msg = player.CanStoreNewItem(bag, slot, dest, lootItem.itemid, lootItem.count);
|
||||
if (msg != InventoryResult.Ok && slot != ItemConst.NullSlot)
|
||||
@@ -712,14 +792,6 @@ namespace Game.Loots
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffaitem != null)
|
||||
ffaitem.is_looted = true;
|
||||
|
||||
if (!lootItem.freeforall)
|
||||
lootItem.is_looted = true;
|
||||
|
||||
--unlootedCount;
|
||||
|
||||
Item pItem = player.StoreNewItem(dest, lootItem.itemid, true, lootItem.randomBonusListId, null, lootItem.context, lootItem.BonusListIDs);
|
||||
if (pItem != null)
|
||||
{
|
||||
@@ -728,6 +800,19 @@ namespace Game.Loots
|
||||
}
|
||||
else
|
||||
player.ApplyItemLootedSpell(Global.ObjectMgr.GetItemTemplate(lootItem.itemid));
|
||||
|
||||
break;
|
||||
case LootItemType.Currency:
|
||||
player.ModifyCurrency(lootItem.itemid, (int)lootItem.count, CurrencyGainSource.Loot);
|
||||
break;
|
||||
}
|
||||
if (ffaitem != null)
|
||||
ffaitem.is_looted = true;
|
||||
|
||||
if (!lootItem.freeforall)
|
||||
lootItem.is_looted = true;
|
||||
|
||||
--unlootedCount;
|
||||
}
|
||||
|
||||
return allLooted;
|
||||
@@ -783,7 +868,7 @@ namespace Game.Loots
|
||||
|
||||
foreach (LootItem item in items)
|
||||
{
|
||||
if (!item.follow_loot_rules || item.freeforall)
|
||||
if (!item.follow_loot_rules || item.freeforall || item.type != LootItemType.Item)
|
||||
continue;
|
||||
|
||||
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(item.itemid);
|
||||
@@ -1014,12 +1099,8 @@ namespace Game.Loots
|
||||
return true;
|
||||
|
||||
var ffaItems = GetPlayerFFAItems().LookupByKey(player.GetGUID());
|
||||
if (ffaItems != null)
|
||||
{
|
||||
bool hasFfaItem = ffaItems.Any(ffaItem => !ffaItem.is_looted);
|
||||
if (hasFfaItem)
|
||||
if (ffaItems != null && ffaItems.Any(ffaItem => !ffaItem.is_looted))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1046,12 +1127,34 @@ namespace Game.Loots
|
||||
if (!uiType.HasValue)
|
||||
continue;
|
||||
|
||||
switch (item.type)
|
||||
{
|
||||
case LootItemType.Item:
|
||||
{
|
||||
LootItemData lootItem = new();
|
||||
lootItem.LootListID = (byte)item.LootListId;
|
||||
lootItem.UIType = uiType.Value;
|
||||
lootItem.Quantity = item.count;
|
||||
lootItem.Loot = new(item);
|
||||
packet.Items.Add(lootItem);
|
||||
break;
|
||||
}
|
||||
case LootItemType.Currency:
|
||||
{
|
||||
LootCurrency lootCurrency = new();
|
||||
lootCurrency.CurrencyID = item.itemid;
|
||||
lootCurrency.Quantity = item.count;
|
||||
lootCurrency.LootListID = (byte)item.LootListId;
|
||||
lootCurrency.UIType = (byte)uiType.Value;
|
||||
|
||||
// fake visible quantity for SPELL_AURA_MOD_CURRENCY_CATEGORY_GAIN_PCT - handled in Player::ModifyCurrency
|
||||
lootCurrency.Quantity = (uint)((float)lootCurrency.Quantity * viewer.GetTotalAuraMultiplierByMiscValue(AuraType.ModCurrencyCategoryGainPct, CliDB.CurrencyTypesStorage.LookupByKey(item.itemid).CategoryID));
|
||||
packet.Currencies.Add(lootCurrency);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,18 +35,19 @@ namespace Game.Loots
|
||||
StoredLootContainer storedContainer = _lootItemStorage[key];
|
||||
|
||||
LootItem lootItem = new();
|
||||
lootItem.itemid = result.Read<uint>(1);
|
||||
lootItem.count = result.Read<byte>(2);
|
||||
lootItem.LootListId = result.Read<uint>(3);
|
||||
lootItem.follow_loot_rules = result.Read<bool>(4);
|
||||
lootItem.freeforall = result.Read<bool>(5);
|
||||
lootItem.is_blocked = result.Read<bool>(6);
|
||||
lootItem.is_counted = result.Read<bool>(7);
|
||||
lootItem.is_underthreshold = result.Read<bool>(8);
|
||||
lootItem.needs_quest = result.Read<bool>(9);
|
||||
lootItem.randomBonusListId = result.Read<uint>(10);
|
||||
lootItem.context = (ItemContext)result.Read<byte>(11);
|
||||
StringArray bonusLists = new(result.Read<string>(12), ' ');
|
||||
lootItem.type = (LootItemType)result.Read<sbyte>(1);
|
||||
lootItem.itemid = result.Read<uint>(2);
|
||||
lootItem.count = result.Read<byte>(3);
|
||||
lootItem.LootListId = result.Read<uint>(4);
|
||||
lootItem.follow_loot_rules = result.Read<bool>(5);
|
||||
lootItem.freeforall = result.Read<bool>(6);
|
||||
lootItem.is_blocked = result.Read<bool>(7);
|
||||
lootItem.is_counted = result.Read<bool>(8);
|
||||
lootItem.is_underthreshold = result.Read<bool>(9);
|
||||
lootItem.needs_quest = result.Read<bool>(10);
|
||||
lootItem.randomBonusListId = result.Read<uint>(11);
|
||||
lootItem.context = (ItemContext)result.Read<byte>(12);
|
||||
StringArray bonusLists = new(result.Read<string>(13), ' ');
|
||||
|
||||
foreach (string str in bonusLists)
|
||||
lootItem.BonusListIDs.Add(uint.Parse(str));
|
||||
@@ -177,12 +178,12 @@ namespace Game.Loots
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
public void RemoveStoredLootItemForContainer(ulong containerId, uint itemId, uint count, uint itemIndex)
|
||||
public void RemoveStoredLootItemForContainer(ulong containerId, LootItemType type, uint itemId, uint count, uint itemIndex)
|
||||
{
|
||||
if (!_lootItemStorage.ContainsKey(containerId))
|
||||
return;
|
||||
|
||||
_lootItemStorage[containerId].RemoveItem(itemId, count, itemIndex);
|
||||
_lootItemStorage[containerId].RemoveItem(type, itemId, count, itemIndex);
|
||||
}
|
||||
|
||||
public void AddNewStoredLoot(ulong containerId, Loot loot, Player player)
|
||||
@@ -248,25 +249,26 @@ namespace Game.Loots
|
||||
|
||||
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.INS_ITEMCONTAINER_ITEMS);
|
||||
|
||||
// container_id, item_id, item_count, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, rnd_suffix
|
||||
// container_id, item_type, item_id, item_count, item_index, follow_rules, ffa, blocked, counted, under_threshold, needs_quest, rnd_prop, rnd_suffix
|
||||
stmt.AddValue(0, _containerId);
|
||||
stmt.AddValue(1, lootItem.itemid);
|
||||
stmt.AddValue(2, lootItem.count);
|
||||
stmt.AddValue(3, lootItem.LootListId);
|
||||
stmt.AddValue(4, lootItem.follow_loot_rules);
|
||||
stmt.AddValue(5, lootItem.freeforall);
|
||||
stmt.AddValue(6, lootItem.is_blocked);
|
||||
stmt.AddValue(7, lootItem.is_counted);
|
||||
stmt.AddValue(8, lootItem.is_underthreshold);
|
||||
stmt.AddValue(9, lootItem.needs_quest);
|
||||
stmt.AddValue(10, lootItem.randomBonusListId);
|
||||
stmt.AddValue(11, (uint)lootItem.context);
|
||||
stmt.AddValue(1, (sbyte)lootItem.type);
|
||||
stmt.AddValue(2, lootItem.itemid);
|
||||
stmt.AddValue(3, lootItem.count);
|
||||
stmt.AddValue(4, lootItem.LootListId);
|
||||
stmt.AddValue(5, lootItem.follow_loot_rules);
|
||||
stmt.AddValue(6, lootItem.freeforall);
|
||||
stmt.AddValue(7, lootItem.is_blocked);
|
||||
stmt.AddValue(8, lootItem.is_counted);
|
||||
stmt.AddValue(9, lootItem.is_underthreshold);
|
||||
stmt.AddValue(10, lootItem.needs_quest);
|
||||
stmt.AddValue(11, lootItem.randomBonusListId);
|
||||
stmt.AddValue(12, (uint)lootItem.context);
|
||||
|
||||
StringBuilder bonusListIDs = new();
|
||||
foreach (int bonusListID in lootItem.BonusListIDs)
|
||||
bonusListIDs.Append(bonusListID + ' ');
|
||||
|
||||
stmt.AddValue(12, bonusListIDs.ToString());
|
||||
stmt.AddValue(13, bonusListIDs.ToString());
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
@@ -295,7 +297,7 @@ namespace Game.Loots
|
||||
DB.Characters.Execute(stmt);
|
||||
}
|
||||
|
||||
public void RemoveItem(uint itemId, uint count, uint itemIndex)
|
||||
public void RemoveItem(LootItemType type, uint itemId, uint count, uint itemIndex)
|
||||
{
|
||||
var bounds = _lootItems.LookupByKey(itemId);
|
||||
foreach (var itr in bounds)
|
||||
@@ -310,9 +312,10 @@ namespace Game.Loots
|
||||
// Deletes a single item associated with an openable item from the DB
|
||||
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_ITEMCONTAINER_ITEM);
|
||||
stmt.AddValue(0, _containerId);
|
||||
stmt.AddValue(1, itemId);
|
||||
stmt.AddValue(2, count);
|
||||
stmt.AddValue(3, itemIndex);
|
||||
stmt.AddValue(1, (sbyte)type);
|
||||
stmt.AddValue(2, itemId);
|
||||
stmt.AddValue(3, count);
|
||||
stmt.AddValue(4, itemIndex);
|
||||
DB.Characters.Execute(stmt);
|
||||
}
|
||||
|
||||
|
||||
@@ -512,6 +512,14 @@ namespace Game.Loots
|
||||
}
|
||||
case LootStoreItemType.Reference:
|
||||
return RandomHelper.randChance(chance * (rate ? WorldConfig.GetFloatValue(WorldCfg.RateDropItemReferenced) : 1.0f));
|
||||
case LootStoreItemType.Currency:
|
||||
{
|
||||
CurrencyTypesRecord currency = CliDB.CurrencyTypesStorage.LookupByKey(itemid);
|
||||
|
||||
float qualityModifier = currency != null && rate && QualityToRate[currency.Quality] != WorldCfg.Max ? WorldConfig.GetFloatValue(QualityToRate[currency.Quality]) : 1.0f;
|
||||
|
||||
return RandomHelper.randChance(chance * qualityModifier);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -523,7 +531,7 @@ namespace Game.Loots
|
||||
{
|
||||
if (mincount == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: wrong mincount ({3}) - skipped", store.GetName(), entry, itemid, mincount);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: wrong mincount ({mincount}) - skipped");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -533,38 +541,64 @@ namespace Game.Loots
|
||||
ItemTemplate proto = Global.ObjectMgr.GetItemTemplate(itemid);
|
||||
if (proto == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: item does not exist - skipped", store.GetName(), entry, itemid);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: item does not exist - skipped");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chance == 0 && groupid == 0) // Zero chance is allowed for grouped entries only
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: equal-chanced grouped entry, but group not defined - skipped", store.GetName(), entry, itemid);
|
||||
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.000001f) // loot with low chance
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: low chance ({3}) - skipped",
|
||||
store.GetName(), entry, itemid, chance);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: low chance ({chance}) - skipped");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (maxcount < mincount) // wrong max count
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: max count ({3}) less that min count ({4}) - skipped", store.GetName(), entry, itemid, maxcount, mincount);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: max count ({maxcount}) less that min count ({mincount}) - skipped");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case LootStoreItemType.Reference:
|
||||
if (needs_quest)
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: quest chance will be treated as non-quest chance", store.GetName(), entry, itemid);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: quest chance will be treated as non-quest chance");
|
||||
else if (chance == 0) // no chance for the reference
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table '{0}' entry {1} item {2}: zero chance is specified for a reference, skipped", store.GetName(), entry, itemid);
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: zero chance is specified for a reference, skipped");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case LootStoreItemType.Currency:
|
||||
{
|
||||
if (!CliDB.CurrencyTypesStorage.HasRecord(itemid))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: currency does not exist - 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 (maxcount < mincount) // wrong max count
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} ItemType {type} Item {itemid}: MaxCount ({maxcount}) less that MinCount ({mincount}) - skipped");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log.outError(LogFilter.Sql, $"Table '{store.GetName()}' Entry {entry} Item {itemid}: invalid ItemType {type}, skipped");
|
||||
return false;
|
||||
@@ -757,12 +791,10 @@ namespace Game.Loots
|
||||
switch (item.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
case LootStoreItemType.Currency:
|
||||
// Plain entries (not a reference, not grouped)
|
||||
// Chance is already checked, just add
|
||||
if (personalLooter == null
|
||||
|| LootItem.AllowedForPlayer(personalLooter, null, item.itemid, item.needs_quest,
|
||||
!item.needs_quest || Global.ObjectMgr.GetItemTemplate(item.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
true, item.conditions))
|
||||
if (personalLooter == null || LootItem.AllowedForPlayer(personalLooter, item, true))
|
||||
loot.AddItem(item);
|
||||
break;
|
||||
case LootStoreItemType.Reference:
|
||||
@@ -813,13 +845,7 @@ namespace Game.Loots
|
||||
{
|
||||
// Plain entries (not a reference, not grouped)
|
||||
// Chance is already checked, just add
|
||||
var lootersForItem = getLootersForItem(looter =>
|
||||
{
|
||||
return LootItem.AllowedForPlayer(looter, null, item.itemid, item.needs_quest,
|
||||
!item.needs_quest || Global.ObjectMgr.GetItemTemplate(item.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
true, item.conditions);
|
||||
});
|
||||
|
||||
var lootersForItem = getLootersForItem(looter => LootItem.AllowedForPlayer(looter, item, true));
|
||||
if (!lootersForItem.Empty())
|
||||
{
|
||||
Player chosenLooter = lootersForItem.SelectRandom();
|
||||
@@ -860,6 +886,16 @@ namespace Game.Loots
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LootStoreItemType.Currency:
|
||||
{
|
||||
// Plain entries (not a reference, not grouped)
|
||||
// Chance is already checked, just add
|
||||
var lootersForItem = getLootersForItem(looter => LootItem.AllowedForPlayer(looter, item, true));
|
||||
|
||||
foreach (Player looter in lootersForItem)
|
||||
personalLoot[looter].AddItem(item);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -901,9 +937,7 @@ namespace Game.Loots
|
||||
switch (lootStoreItem.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
if (LootItem.AllowedForPlayer(player, null, lootStoreItem.itemid, lootStoreItem.needs_quest,
|
||||
!lootStoreItem.needs_quest || Global.ObjectMgr.GetItemTemplate(lootStoreItem.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
strictUsabilityCheck, lootStoreItem.conditions))
|
||||
if (LootItem.AllowedForPlayer(player, lootStoreItem, strictUsabilityCheck))
|
||||
return true; // active quest drop found
|
||||
break;
|
||||
case LootStoreItemType.Reference:
|
||||
@@ -931,6 +965,22 @@ namespace Game.Loots
|
||||
// Copies the conditions list from a template item to a LootItem
|
||||
foreach (var item in Entries)
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
if (li.type != LootItemType.Item)
|
||||
continue;
|
||||
break;
|
||||
case LootStoreItemType.Reference:
|
||||
continue;
|
||||
case LootStoreItemType.Currency:
|
||||
if (li.type != LootItemType.Currency)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (item.itemid != li.itemid)
|
||||
continue;
|
||||
|
||||
@@ -957,6 +1007,7 @@ namespace Game.Loots
|
||||
switch (item.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
case LootStoreItemType.Currency:
|
||||
if (item.needs_quest)
|
||||
return true; // quest drop found
|
||||
break;
|
||||
@@ -1009,6 +1060,10 @@ namespace Game.Loots
|
||||
if (Referenced.HasQuestDropForPlayer(store, player, item.groupid))
|
||||
return true;
|
||||
break;
|
||||
case LootStoreItemType.Currency:
|
||||
if (player.HasQuestForCurrency(item.itemid))
|
||||
return true; // active quest drop found
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1124,10 +1179,24 @@ namespace Game.Loots
|
||||
|
||||
public bool HasQuestDropForPlayer(Player player)
|
||||
{
|
||||
if (ExplicitlyChanced.Any(item => player.HasQuestForItem(item.itemid)))
|
||||
var hasQuestForLootItem = (LootStoreItem item) =>
|
||||
{
|
||||
switch (item.type)
|
||||
{
|
||||
case LootStoreItemType.Item:
|
||||
return player.HasQuestForItem(item.itemid);
|
||||
case LootStoreItemType.Currency:
|
||||
return player.HasQuestForCurrency(item.itemid);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (ExplicitlyChanced.Any(hasQuestForLootItem))
|
||||
return true;
|
||||
|
||||
if (EqualChanced.Any(item => player.HasQuestForItem(item.itemid)))
|
||||
if (EqualChanced.Any(hasQuestForLootItem))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1239,15 +1308,11 @@ namespace Game.Loots
|
||||
public bool HasDropForPlayer(Player player, bool strictUsabilityCheck)
|
||||
{
|
||||
foreach (LootStoreItem lootStoreItem in ExplicitlyChanced)
|
||||
if (LootItem.AllowedForPlayer(player, null, lootStoreItem.itemid, lootStoreItem.needs_quest,
|
||||
!lootStoreItem.needs_quest || Global.ObjectMgr.GetItemTemplate(lootStoreItem.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
strictUsabilityCheck, lootStoreItem.conditions))
|
||||
if (LootItem.AllowedForPlayer(player, lootStoreItem, strictUsabilityCheck))
|
||||
return true;
|
||||
|
||||
foreach (LootStoreItem lootStoreItem in EqualChanced)
|
||||
if (LootItem.AllowedForPlayer(player, null, lootStoreItem.itemid, lootStoreItem.needs_quest,
|
||||
!lootStoreItem.needs_quest || Global.ObjectMgr.GetItemTemplate(lootStoreItem.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
strictUsabilityCheck, lootStoreItem.conditions))
|
||||
if (LootItem.AllowedForPlayer(player, lootStoreItem, strictUsabilityCheck))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1268,9 +1333,7 @@ namespace Game.Loots
|
||||
if ((item.lootmode & _lootMode) == 0)
|
||||
return true;
|
||||
|
||||
if (_personalLooter != null && !LootItem.AllowedForPlayer(_personalLooter, null, item.itemid, item.needs_quest,
|
||||
!item.needs_quest || Global.ObjectMgr.GetItemTemplate(item.itemid).HasFlag(ItemFlagsCustom.FollowLootRules),
|
||||
true, item.conditions))
|
||||
if (_personalLooter != null && !LootItem.AllowedForPlayer(_personalLooter, item, true))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user