예제 #1
0
        public CreateItemResult Execute(
            DelegateSpawnDropItem delegateSpawnDropItem,
            DropItemContext dropItemContext,
            double probabilityMultiplier)
        {
            this.Freeze();

            var result = new CreateItemResult()
            {
                IsEverythingCreated = true
            };

            using var selectedEntries = Api.Shared.GetTempList <Entry>();
            this.SelectRandomEntries(selectedEntries);

            // execute selected entries
            foreach (var entry in selectedEntries)
            {
                ExecuteEntry(entry,
                             dropItemContext,
                             out var entryResult,
                             probabilityMultiplier,
                             delegateSpawnDropItem);
                result.MergeWith(entryResult);
            }

            return(result);
        }
예제 #2
0
        public bool ServerGather(IStaticWorldObject worldObject, ICharacter character)
        {
            //MOD
            PublicState publicState = GetPublicState(worldObject);

            var lootDroplist = publicState.ProtoCharacterMob.LootDroplist;

            var dropItemContext = new DropItemContext(character, worldObject);

            CreateItemResult dropItemResultFinal = new CreateItemResult();

            var level = publicState.Level;

            for (int i = 0; i < level; i++)
            {
                CreateItemResult dropItemResult;

                var attemptRemains = 200;
                do
                {
                    dropItemResult = lootDroplist.TryDropToCharacterOrGround(character,
                                                                             character.TilePosition,
                                                                             dropItemContext,
                                                                             out _);

                    dropItemResultFinal.MergeWith(dropItemResult);
                }
                // ensure that at least something is spawned...
                // perhaps that's not a good idea, but we have an attempts limit
                while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0);
            }

            if (!dropItemResultFinal.IsEverythingCreated)
            {
                Logger.Warning("Not all loot items were provided by "
                               + worldObject
                               + " - there is not enough space in inventory and around the character");
            }

            // probably the attempts limit exceeded and nothing is spawned
            // we don't consider this as an issue as the probability of this is too rare

            Logger.Info(worldObject + " was gathered", character);
            Server.World.DestroyObject(worldObject);

            NotificationSystem.ServerSendItemsNotification(character, dropItemResultFinal);
            character.ServerAddSkillExperience <SkillHunting>(SkillHunting.ExperienceForGather * level);
            return(true);
        }
예제 #3
0
        public static CreateItemResult TrySpawnToContainer(
            IReadOnlyOutputItems outputItems,
            IItemsContainer toContainer)
        {
            var itemsService = Api.Server.Items;
            var result       = new CreateItemResult()
            {
                IsEverythingCreated = true
            };
            var character = toContainer.Owner as ICharacter;

            foreach (var outputItem in outputItems.Items)
            {
                var count = GenerateCount(outputItem);
                if (count == 0)
                {
                    continue;
                }

                CreateItemResult createItemResult;
                if (character is not null)
                {
                    createItemResult = itemsService.CreateItem(outputItem.ProtoItem,
                                                               character,
                                                               count);
                }
                else
                {
                    createItemResult = itemsService.CreateItem(outputItem.ProtoItem,
                                                               toContainer,
                                                               count);
                }

                result.MergeWith(createItemResult);
            }

            return(result);
        }
예제 #4
0
        private static TradingResult ServerExecuteTrade(
            TradingStationLot lot,
            IItemsContainerProvider sellerContainers,
            IItemsContainerProvider buyerContainers,
            bool isPlayerBuying)
        {
            // find items to buy by other party
            if (!SharedTryFindItemsOfType(sellerContainers, lot.ProtoItem, lot.LotQuantity, out var itemsToSell))
            {
                return(isPlayerBuying
                           ? TradingResult.ErrorNotEnoughItemsOnStation
                           : TradingResult.ErrorNotEnoughItemsOnPlayer);
            }

            // try to find money to pay to other party
            var countCoinPenny = (uint)lot.PriceCoinPenny;
            var countCoinShiny = (uint)lot.PriceCoinShiny;

            if (!SharedTryFindItemsOfType(buyerContainers,
                                          ProtoItemCoinPenny.Value,
                                          countCoinPenny,
                                          out _) ||
                !SharedTryFindItemsOfType(buyerContainers,
                                          ProtoItemCoinShiny.Value,
                                          countCoinShiny,
                                          out _))
            {
                return(isPlayerBuying
                           ? TradingResult.ErrorNotEnoughMoneyOnStation
                           : TradingResult.ErrorNotEnoughMoneyOnPlayer);
            }

            // ensure there is enough space to store the sold items
            if (!ServerItems.CanCreateItem(buyerContainers, lot.ProtoItem, lot.LotQuantity))
            {
                return(isPlayerBuying
                           ? TradingResult.ErrorNotEnoughSpaceOnPlayerForPurchasedItem
                           : TradingResult.ErrorNotEnoughSpaceOnStationForSoldItem);
            }

            // try create money in the source containers
            var sourceContainerResult = new CreateItemResult()
            {
                IsEverythingCreated = true
            };

            if (lot.PriceCoinPenny > 0)
            {
                sourceContainerResult.MergeWith(
                    ServerItems.CreateItem(ProtoItemCoinPenny.Value,
                                           sellerContainers,
                                           countCoinPenny));
            }

            if (lot.PriceCoinShiny > 0)
            {
                sourceContainerResult.MergeWith(
                    ServerItems.CreateItem(ProtoItemCoinShiny.Value,
                                           sellerContainers,
                                           countCoinShiny));
            }

            if (!sourceContainerResult.IsEverythingCreated)
            {
                sourceContainerResult.Rollback();
                // TODO: check this
                return(isPlayerBuying
                           ? TradingResult.ErrorNotEnoughSpaceOnStationForSoldItem
                           : TradingResult.ErrorNotEnoughSpaceOnPlayerForPurchasedItem);
            }

            // try moving (bought) items
            var itemsCountToDestroyRemains = (int)lot.LotQuantity;

            foreach (var item in itemsToSell)
            {
                if (itemsCountToDestroyRemains <= 0)
                {
                    break;
                }

                ServerItems.MoveOrSwapItem(item,
                                           buyerContainers,
                                           out var movedCount,
                                           countToMove: (ushort)itemsCountToDestroyRemains);
                itemsCountToDestroyRemains -= movedCount;
            }

            if (itemsCountToDestroyRemains > 0)
            {
                // should be impossible
                Logger.Error(
                    "Cannot move all sold items! But we've verified that the sellerContainers have them all...");
            }

            if (countCoinPenny > 0)
            {
                ServerItems.DestroyItemsOfType(buyerContainers, ProtoItemCoinPenny.Value, countCoinPenny, out _);
            }

            if (countCoinShiny > 0)
            {
                ServerItems.DestroyItemsOfType(buyerContainers, ProtoItemCoinShiny.Value, countCoinShiny, out _);
            }

            Logger.Important($"Successfully completed trading transaction: {lot}");
            return(TradingResult.Success);
        }
예제 #5
0
        public override CreateItemResult ServerCreateItem(
            ICharacter character,
            IProtoItem protoItem,
            uint countToSpawn = 1)
        {
            if (character == null)
            {
                throw new ArgumentNullException(nameof(character));
            }

            if (protoItem == null)
            {
                throw new ArgumentNullException(nameof(protoItem));
            }

            if (countToSpawn == 0)
            {
                throw new Exception("Cannot add item to character: item count is 0");
            }

            var countToSpawnRemains = countToSpawn;
            var privateState        = GetPrivateState(character);
            var containerHotbar     = privateState.ContainerHotbar;
            var containerInventory  = privateState.ContainerInventory;
            var serverItemsService  = Server.Items;
            var result = new CreateItemResult();

            // define a function for spawning item at specified container
            bool TrySpawnItem(IItemsContainer container, bool onlyToExistingStacks)
            {
                var createItemResult = serverItemsService.CreateItem(
                    protoItem,
                    container,
                    countToSpawnRemains,
                    slotId: null,
                    onlyAddToExistingStacks: onlyToExistingStacks);

                if (createItemResult.TotalCreatedCount == 0)
                {
                    // cannot create item
                    return(false);
                }

                // something created (perhaps all)
                result.MergeWith(createItemResult);
                countToSpawnRemains = (ushort)(countToSpawnRemains - createItemResult.TotalCreatedCount);
                var isEverythingCreated = countToSpawnRemains == 0;

                return(isEverythingCreated);
            }

            // 1. Try to add to existing stacks in hotbar.
            // 3. Try to add to existing stacks or spawn as new stacks in inventory.
            // 3. Try to spawn as new stacks in hotbar.
            // TODO: 4. Try to spawn on the ground. (actually implemented separately via scripting)
            if (TrySpawnItem(containerHotbar, onlyToExistingStacks: true) ||
                TrySpawnItem(containerInventory, onlyToExistingStacks: false) ||
                TrySpawnItem(containerHotbar, onlyToExistingStacks: false))
            {
                // all items are created!
                result.IsEverythingCreated = true;
            }

            return(result);
        }