示例#1
0
        /// <summary>
        /// Verify all conditions to pickup a dropped item.
        /// </summary>
        /// <param name="droppedItem">The dropped item.</param>
        private void PickUpDroppedItem(IItemEntity droppedItem)
        {
            // TODO: check if drop belongs to a party.

            if (droppedItem.Drop.HasOwner && droppedItem.Drop.Owner != _player)
            {
                _textPacketFactory.SendDefinedText(_player, DefineText.TID_GAME_PRIORITYITEMPER, $"\"{droppedItem.Object.Name}\"");
                return;
            }

            if (droppedItem.Drop.IsGold)
            {
                int droppedGoldAmount = droppedItem.Drop.Item.Quantity;

                if (_playerDataSystem.IncreaseGold(_player, droppedGoldAmount))
                {
                    _textPacketFactory.SendDefinedText(_player, DefineText.TID_GAME_REAPMONEY, droppedGoldAmount.ToString("###,###,###,###"), _player.PlayerData.Gold.ToString("###,###,###,###"));
                }
            }
            else
            {
                _inventorySystem.CreateItem(_player, droppedItem.Drop.Item, droppedItem.Drop.Item.Quantity);
                _textPacketFactory.SendDefinedText(_player, DefineText.TID_GAME_REAPITEM, $"\"{droppedItem.Object.Name}\"");
            }

            _moverPacketFactory.SendMotion(_player, ObjectMessageType.OBJMSG_PICKUP);
            droppedItem.Delete();
        }
示例#2
0
        /// <inheritdoc />
        public void ChangeFace(IPlayerEntity player, uint objectId, uint faceId, bool useCoupon)
        {
            if (!useCoupon)
            {
                if (player.PlayerData.Gold < _worldServerConfiguration.Customization.ChangeFaceCost)
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LACKMONEY);
                }
                else
                {
                    player.VisualAppearance.FaceId = (int)faceId;
                    _playerDataSystem.DecreaseGold(player, (int)_worldServerConfiguration.Customization.ChangeFaceCost);
                    _customizationPacketFactory.SendChangeFace(player, faceId);
                }
            }
            else
            {
                Item couponItem = player.Inventory.GetItemById(DefineItem.II_SYS_SYS_SCR_FACEOFFFREE);

                if (couponItem == null)
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_WARNNING_COUPON);
                    return;
                }

                _inventorySystem.DeleteItem(player, couponItem, 1);

                _customizationPacketFactory.SendChangeFace(player, faceId);
            }
        }
示例#3
0
        public void UseFoodItem(IPlayerEntity player, Item foodItemToUse)
        {
            foreach (KeyValuePair <DefineAttributes, int> parameter in foodItemToUse.Data.Params)
            {
                if (parameter.Key == DefineAttributes.HP || parameter.Key == DefineAttributes.MP || parameter.Key == DefineAttributes.FP)
                {
                    int currentPoints   = player.Attributes[parameter.Key];
                    int maxPoints       = PlayerHelper.GetMaxPoints(player, parameter.Key);
                    int itemMaxRecovery = foodItemToUse.Data.AbilityMin;

                    if (parameter.Value >= 0)
                    {
                        if (currentPoints >= itemMaxRecovery)
                        {
                            float limitedRecovery = parameter.Value * 0.3f;

                            if (currentPoints + limitedRecovery > maxPoints)
                            {
                                currentPoints = maxPoints;
                            }
                            else
                            {
                                switch (parameter.Key)
                                {
                                case DefineAttributes.HP: _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LIMITHP); break;

                                case DefineAttributes.MP: _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LIMITMP); break;

                                case DefineAttributes.FP: _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LIMITFP); break;
                                }

                                currentPoints += (int)limitedRecovery;
                            }
                        }
                        else
                        {
                            currentPoints = Math.Min(currentPoints + parameter.Value, maxPoints);
                        }
                    }

                    PlayerHelper.SetPoints(player, parameter.Key, currentPoints);
                    _moverPacketFactory.SendUpdateAttributes(player, parameter.Key, player.Attributes[parameter.Key]);
                }
                else
                {
                    // TODO: food triggers a skill.
                    _logger.LogWarning($"Activating a skill throught food.");
                    _textPacketFactory.SendFeatureNotImplemented(player, "skill with food");
                }
            }

            DecreaseItem(player, foodItemToUse);
        }
示例#4
0
        /// <inheritdoc />
        public void BuyItem(IPlayerEntity player, NpcShopItemInfo shopItemInfo, int quantity)
        {
            var npc = player.FindEntity <INpcEntity>(x => x.Object.Name == player.PlayerData.CurrentShopName);

            if (npc == null)
            {
                _logger.LogError($"ShopSystem: Cannot find NPC: {player.PlayerData.CurrentShopName}");
                return;
            }

            if (!npc.NpcData.HasShop)
            {
                _logger.LogError($"ShopSystem: NPC {npc.Object.Name} doesn't have a shop.");
                return;
            }

            if (shopItemInfo.Tab < 0 || shopItemInfo.Tab >= ShopData.DefaultTabCount)
            {
                _logger.LogError($"Attempt to buy an item from {npc.Object.Name} shop tab that is out of range.");
                return;
            }

            ItemContainerComponent shopTab = npc.Shop.ElementAt(shopItemInfo.Tab);

            if (shopItemInfo.Slot < 0 || shopItemInfo.Slot > shopTab.MaxCapacity - 1)
            {
                _logger.LogError($"ShopSystem: Item slot index was out of tab bounds. Slot: {shopItemInfo.Slot}");
                return;
            }

            Item shopItem = shopTab.GetItemAtSlot(shopItemInfo.Slot);

            if (shopItem.Id != shopItemInfo.ItemId)
            {
                _logger.LogError($"ShopSystem: Shop item id doens't match the item id that {player.Object.Name} is trying to buy.");
                return;
            }

            if (player.PlayerData.Gold < shopItem.Data.Cost)
            {
                _logger.LogTrace($"ShopSystem: {player.Object.Name} doens't have enough gold to buy item {shopItem.Data.Name} at {shopItem.Data.Cost}.");
                _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LACKMONEY);
                return;
            }

            int itemsCreatedCount = _inventorySystem.CreateItem(player, shopItem, quantity);

            if (itemsCreatedCount > 0)
            {
                _playerDataSystem.DecreaseGold(player, shopItem.Data.Cost * itemsCreatedCount);
            }
        }
示例#5
0
        /// <inheritdoc />
        public void PutItem(IPlayerEntity player, int itemUniqueId, int quantity, int itemType, int destinationSlot)
        {
            _logger.LogTrace($"Player '{player.Object.Name}' is putting item with unique id '{itemUniqueId}' to trade slot '{destinationSlot}'.");
            ThrowIfPlayerTrade(player, isTrading: false);

            IPlayerEntity target = GetTargetEntity(player, player.Trade.TargetId);

            try
            {
                ThrowIfPlayerTrade(target, isTrading: false);
            }
            catch (InvalidOperationException)
            {
                CancelTradeAndRefund(player);
                CancelTradeAndRefund(target);
                throw;
            }

            if (player.Trade.State != TradeComponent.TradeState.Item || target.Trade.State != TradeComponent.TradeState.Item)
            {
                _tradePacketFactory.SendTradePutError(player);
                return;
            }

            Item inventoryItem = player.Inventory.GetItemAtIndex(itemUniqueId);

            if (inventoryItem == null)
            {
                throw new ArgumentNullException($"Cannot find item with unique id '{itemUniqueId}' in '{player.Object.Name}' inventory.');");
            }

            if (!IsTradeItemValid(player, inventoryItem, out DefineText errorText))
            {
                _textPacketFactory.SendDefinedText(player, errorText);
            }

            int tradingQuantity = Math.Min(quantity, inventoryItem.Quantity);

            if (!player.Trade.Items.IsSlotAvailable(destinationSlot))
            {
                _logger.LogTrace($"Destination slot '{destinationSlot}' is not available for player '{player.Object.Name}'");
                return;
            }

            inventoryItem.ExtraUsed = tradingQuantity;

            player.Trade.Items.SetItemAtIndex(inventoryItem.Clone(), destinationSlot);
            player.Trade.ItemCount++;

            _tradePacketFactory.SendTradePut(player, trader: player, (byte)destinationSlot, (byte)itemType, (byte)inventoryItem.UniqueId, (short)tradingQuantity);
            _tradePacketFactory.SendTradePut(target, trader: player, (byte)destinationSlot, (byte)itemType, (byte)inventoryItem.UniqueId, (short)tradingQuantity);
        }
示例#6
0
        /// <inheritdoc />
        public bool IncreaseGold(IPlayerEntity player, int goldAmount)
        {
            // We cast player gold to long because otherwise it would use Int32 arithmetic and would overflow
            long gold = (long)player.PlayerData.Gold + goldAmount;

            if (gold > int.MaxValue || gold < 0) // Check gold overflow
            {
                _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_TOOMANYMONEY_USE_PERIN);
                return(false);
            }
            else
            {
                player.PlayerData.Gold = (int)gold;
                _moverPacketFactory.SendUpdateAttributes(player, DefineAttributes.GOLD, player.PlayerData.Gold);
            }

            return(true);
        }
示例#7
0
        /// <inheritdoc />
        public void Execute(IPlayerEntity player, object[] parameters)
        {
            _logger.LogTrace($"{player.Object.Name} wants to create an item");

            if (parameters.Length <= 0)
            {
                throw new ArgumentException($"Create item command must have at least one parameter.", nameof(parameters));
            }

            if (!player.Inventory.HasAvailableSlots())
            {
                _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LACKSPACE);
                return;
            }
            int         quantity      = parameters.Length >= 2 ? Convert.ToInt32(parameters[1]) : 1;
            byte        refine        = parameters.Length >= 3 ? Convert.ToByte(parameters[2]) : (byte)0;
            ElementType element       = parameters.Length >= 4 ? (ElementType)Enum.Parse(typeof(ElementType), parameters[3].ToString(), true) : default;
            byte        elementRefine = parameters.Length >= 5 ? Convert.ToByte(parameters[4]) : (byte)0;

            string itemInput = parameters[0].ToString();
            Item   itemToCreate;

            if (!int.TryParse(itemInput, out int itemId))
            {
                itemToCreate = _itemFactory.CreateItem(itemInput, refine, element, elementRefine, player.PlayerData.Id);
            }
            else
            {
                itemToCreate = _itemFactory.CreateItem(itemId, refine, element, elementRefine, player.PlayerData.Id);
            }

            if (itemToCreate != null)
            {
                _inventorySystem.CreateItem(player, itemToCreate, quantity, player.PlayerData.Id);
            }
        }
示例#8
0
        /// <inheritdoc />
        public void UpdateSkills(IPlayerEntity player, IReadOnlyDictionary <int, int> skillsToUpdate)
        {
            int requiredSkillPoints = 0;

            foreach (KeyValuePair <int, int> skill in skillsToUpdate)
            {
                int       skillId     = skill.Key;
                int       skillLevel  = skill.Value;
                SkillInfo playerSkill = player.SkillTree.GetSkill(skillId);

                if (playerSkill == null)
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot find skill with id '{skillId}' for player '{player}'.");
                    return;
                }

                if (playerSkill.Level == skillLevel)
                {
                    // Skill hasn't change
                    continue;
                }

                if (player.Object.Level < playerSkill.Data.RequiredLevel)
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Player need to be level '{playerSkill.Data.RequiredLevel}' to learn this skill.");
                    return;
                }

                if (!CheckRequiredSkill(playerSkill.Data.RequiredSkillId1, playerSkill.Data.RequiredSkillLevel1, skillsToUpdate))
                {
                    SkillData requiredSkill1 = _gameResources.Skills[playerSkill.Data.RequiredSkillId1];

                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Skill '{requiredSkill1.Name}' must be at least Lv.{requiredSkill1.RequiredSkillLevel1}");
                    return;
                }

                if (!CheckRequiredSkill(playerSkill.Data.RequiredSkillId2, playerSkill.Data.RequiredSkillLevel2, skillsToUpdate))
                {
                    SkillData requiredSkill2 = _gameResources.Skills[playerSkill.Data.RequiredSkillId2];

                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Skill '{requiredSkill2.Name}' must be at least Lv.{requiredSkill2.RequiredSkillLevel1}");
                    return;
                }

                if (skillLevel < 0 || skillLevel < playerSkill.Level || skillLevel > playerSkill.Data.MaxLevel)
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. The skill level is out of bounds.");
                    return;
                }

                if (!SkillPointUsage.TryGetValue(playerSkill.Data.JobType, out int requiredSkillPointAmount))
                {
                    _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                    _logger.LogError($"Cannot update skill with '{skillId}' for player '{player}'. Cannot find required skill point for job type '{playerSkill.Data.JobType}'.");
                    return;
                }

                requiredSkillPoints += (skillLevel - playerSkill.Level) * requiredSkillPointAmount;
            }

            if (player.Statistics.SkillPoints < requiredSkillPoints)
            {
                _logger.LogError($"Cannot update skills for player '{player}'. Not enough skill points.");
                _textPacketFactory.SendDefinedText(player, DefineText.TID_RESKILLPOINT_ERROR);
                return;
            }

            player.Statistics.SkillPoints -= (ushort)requiredSkillPoints;

            foreach (KeyValuePair <int, int> skill in skillsToUpdate)
            {
                int skillId    = skill.Key;
                int skillLevel = skill.Value;

                player.SkillTree.SetSkillLevel(skillId, skillLevel);
            }

            _specialEffectPacketFactory.SendSpecialEffect(player, DefineSpecialEffects.XI_SYS_EXCHAN01, false);
            _skillPacketFactory.SendSkillTreeUpdate(player);
        }
示例#9
0
        /// <inheritdoc />
        public int CreateItem(IPlayerEntity player, ItemDescriptor item, int quantity, int creatorId = -1, bool sendToPlayer = true)
        {
            int createdAmount = 0;

            if (item.Data.IsStackable)
            {
                for (var i = 0; i < InventoryContainerComponent.InventorySize; i++)
                {
                    Item inventoryItem = player.Inventory.GetItemAtIndex(i);

                    if (inventoryItem?.Id == item.Id)
                    {
                        if (inventoryItem.Quantity + quantity > item.Data.PackMax)
                        {
                            int boughtQuantity = inventoryItem.Data.PackMax - inventoryItem.Quantity;

                            createdAmount          = boughtQuantity;
                            quantity              -= boughtQuantity;
                            inventoryItem.Quantity = inventoryItem.Data.PackMax;
                        }
                        else
                        {
                            createdAmount           = quantity;
                            inventoryItem.Quantity += quantity;
                            quantity = 0;
                        }

                        if (sendToPlayer)
                        {
                            _inventoryPacketFactory.SendItemUpdate(player, UpdateItemType.UI_NUM, inventoryItem.UniqueId, inventoryItem.Quantity);
                        }
                    }
                }

                if (quantity > 0)
                {
                    int availableSlot = player.Inventory.GetAvailableSlot();

                    if (availableSlot == -1)
                    {
                        _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LACKSPACE);
                    }
                    else
                    {
                        Item newItem = _itemFactory.CreateItem(item.Id, item.Refine, item.Element, item.ElementRefine, creatorId);

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

                        newItem.Quantity = quantity;
                        newItem.Slot     = availableSlot;

                        player.Inventory.SetItemAtSlot(newItem, availableSlot);

                        if (sendToPlayer)
                        {
                            _inventoryPacketFactory.SendItemCreation(player, newItem);
                        }

                        createdAmount += quantity;
                    }
                }
            }
            else
            {
                while (quantity > 0)
                {
                    int availableSlot = player.Inventory.GetAvailableSlot();

                    if (availableSlot == -1)
                    {
                        _textPacketFactory.SendDefinedText(player, DefineText.TID_GAME_LACKSPACE);
                        break;
                    }

                    Item newItem = _itemFactory.CreateItem(item.Id, item.Refine, item.Element, item.ElementRefine, creatorId);

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

                    newItem.Quantity = 1;
                    newItem.Slot     = availableSlot;

                    player.Inventory.SetItemAtSlot(newItem, availableSlot);

                    if (sendToPlayer)
                    {
                        _inventoryPacketFactory.SendItemCreation(player, newItem);
                    }

                    createdAmount++;
                    quantity--;
                }
            }

            return(createdAmount);
        }