/// <summary> /// Collects a <see cref="LootItem"/> from an index and notifies the looters /// </summary> public void CollectLootItem(int index, Player collector) { // player trying to loot outside the loot range // possible hacking attempt if (index >= lootItems.Length) { return; } // if the item is already looted return var lootItem = lootItems[index]; if (lootItem.IsLooted) { return; } // if the gold is 0 or the id is 0 // its an invalid item or gold, return if (lootItem.CountOrGold <= 0) { return; } // remember the gold always sits in the 0th index // depending on the index loot gold or item if (index == 0) { collector.GainGold(lootItem.CountOrGold, true); } else { // add the item to the inventory InventoryOperationResult result; var added = collector.Inventory.AddItem(lootItem.ItemId, (byte)lootItem.CountOrGold, out result); // if it cannot be looted then return if (result == InventoryOperationResult.Fail || result == InventoryOperationResult.NoAdditionDueToSpace) { return; } // if we didnt fully add the item? if (result == InventoryOperationResult.PartialAdditionDueToSpace) { // update the item count lootItems[index] = new LootItem(lootItem.ItemId, (byte)(lootItem.CountOrGold - added)); return; } } // notify the looter that he or she has taken the loot item collector.NotifyLootItemTakenFor(lootContainer.owner, index); // mark the item looted lootItems[index].IsLooted = true; // looping thru the items to see whether the player has looted all of his or her items or not for (var i = 0; i < lootItems.Length; i++) { // if there are items to be looted just return if (!lootItems[i].IsLooted) { return; } } // inform the collector to clear loot for the owner collector.NotifyLootClear(lootContainer.owner); // player has looted all the items so just delete the player this.lootContainer.RemoveLoot(collector); }
/// <summary> /// Collects all the loot item and notifies the looter /// </summary> public void CollectAll(Player collector) { var collectedCount = 0; // adding items as a cluster rather than one by one // this will save us the overhead of sending items right after loot collector.BeginInventoryClusterAddition(); var result = InventoryOperationResult.Success; for (var i = 0; i < lootItems.Length; i++) { var lootItem = lootItems[i]; // if its already been looted ? if (lootItem.IsLooted) { continue; } // if the count is 0 there is nothing to loot if (lootItem.CountOrGold <= 0) { continue; } // at index 0 there is always gold if (i == 0) { // loot the gold collector.GainGold(lootItem.CountOrGold, true); } else { // add the item to the inventory var added = collector.Inventory.AddItem(lootItem.ItemId, (byte)lootItem.CountOrGold, out result); // if it cannot be looted then dont do anything if (result == InventoryOperationResult.Fail || result == InventoryOperationResult.NoAdditionDueToSpace) { continue; } // if we didnt fully add the item? if (result == InventoryOperationResult.PartialAdditionDueToSpace) { // update the item count lootItems[i] = new LootItem(lootItem.ItemId, (byte)(lootItem.CountOrGold - added)); continue; } } // ok so we added the item completely // then mark it looted lootItems[i].IsLooted = true; collectedCount++; } // the loot may be empty only if they looted atleast one item if (collectedCount > 0) { var clearLoot = true; // looping thru the items to see whether the player has looted all of his or her items or not for (var i = 0; i < lootItems.Length; i++) { // if the item is looted, continue to the next item if (lootItems[i].IsLooted) { continue; } // making sure we dont clear all loot clearLoot = false; break; } // if we can clear all loot then, well, clear if (clearLoot) { // inform the collector to clear loot for the owner collector.NotifyLootClear(lootContainer.owner); // player has looted all the items so just delete the player this.lootContainer.RemoveLoot(collector); } } if (result != InventoryOperationResult.Success) { // we didnt loot all items on a CollectAll call // so report appropriate error // TODO: Report appropriate error #if MMO_DEBUG Utils.Logger.InfoFormat("Loot.CollectAll({0}). {1}.", collector.Name, result); #endif } //sending the cluster if there are any items added to it collector.EndInventoryClusterAddition(); }
/// <summary> /// Generates loot items /// </summary> static LootItem[] GenerateLoot(short lootGroupId) { LootGroupData lootGroupData; if (!MmoWorld.Instance.ItemCache.TryGetLootGroupData(lootGroupId, out lootGroupData)) { // cannot find loot group. write to logger Utils.Logger.ErrorFormat("[GenerateLoot]: LootGroup (Id={0}) cannot be found", lootGroupId); return(null); } LootItem[] generatedLootItems = null; var possibleLootItems = lootGroupData.LootItems; // choose the lowest possible + 1 (for money) var maxLootSize = 1 + Mathf.Min(possibleLootItems.Length, ServerGameSettings.MAX_ITEMS_PER_LOOT); var addedCount = 0; // only generate gold if the chance is greater than 0 if (lootGroupData.GoldChance > 0) { // generating a chance var chance = (float)Utils.Rnd.NextDouble() * 100; if (chance <= lootGroupData.GoldChance) { // randomly choose between min and max gold // remember to do this before generating any items // because the gold will always be at index 1 whether its generated or not var gold = Utils.Rnd.Next(lootGroupData.MinGold, lootGroupData.MaxGold); if (gold > 0) { // only create the array if we have atleast one loot item generatedLootItems = new LootItem[maxLootSize]; // adding the gold item generatedLootItems[addedCount++ /* 0 */] = new LootItem(gold); } } } for (var i = 0; i < possibleLootItems.Length && addedCount < maxLootSize; i++) { var lootItem = possibleLootItems[i]; // if the drop chance is invalid skip the item if (lootItem.DropChance <= 0) { continue; } // generating a chance var chance = (float)Utils.Rnd.NextDouble() * 100; // skip if the chance is greater if (chance > lootItem.DropChance) { continue; } // if the loot array hasnt been created yet create it if (generatedLootItems == null) { // only create the array if we have atleast one loot item generatedLootItems = new LootItem[maxLootSize]; // if we havent already created the loot array // the first spot wont be there but we need it to contain gold spot whether its generated or not // setting it to 0 and marking it looted will let the loot skip it generatedLootItems[addedCount++ /* 0 */] = new LootItem(0) { IsLooted = true }; } // adding the actual loot item generatedLootItems[addedCount++] = new LootItem(lootItem); } // we added atleast one item ? if (addedCount > 0 && generatedLootItems != null) { // resizes the array to total items size // this way we can eliminate empty slots and save overhead of sending the whole array to the client if (addedCount < generatedLootItems.Length) { Array.Resize(ref generatedLootItems, addedCount); } // set the loot return(generatedLootItems); } // return an empty loot container if they are no loot generated return(new LootItem[0]); }