Exemple #1
0
        public static void OpenDevice()
        {
            var player = GetLastOpenedBy();

            if (!GetIsPC(player) || GetIsDM(player))
            {
                return;
            }

            var state  = Craft.GetPlayerCraftingState(player);
            var device = OBJECT_SELF;

            state.IsOpeningMenu = false;

            // A recipe isn't selected. Open the menu to pick.
            if (state.SelectedRecipe == RecipeType.Invalid)
            {
                var skillType = (SkillType)GetLocalInt(OBJECT_SELF, "CRAFTING_SKILL_TYPE_ID");
                state.DeviceSkillType = skillType;
                state.IsOpeningMenu   = true;

                Dialog.StartConversation(player, OBJECT_SELF, nameof(RecipeDialog));
            }
            // Recipe has been picked. Spawn the command items into this device's inventory.
            else
            {
                var recipe = Craft.GetRecipe(state.SelectedRecipe);

                uint command;

                // Auto-Craft command: Only available if perk has been purchased.
                // todo: Need to write the mini-game. For now, only auto-craft will be available.
                //if (Perk.GetEffectivePerkLevel(player, _autoCraftPerk[state.DeviceSkillType]) > 0)
                {
                    command = CreateItemOnObject(AutoCraftItemResref, device);
                    SetName(command, $"Auto Craft: {recipe.Quantity}x {recipe.Name}");
                }

                // Craft command
                // todo: Need to write the mini-game. For now, only auto-craft will be available.
                //command = CreateItemOnObject(CraftItemResref, device);
                //SetName(command, $"Craft: {recipe.Quantity}x {recipe.Name}");

                // Load Components command
                command = CreateItemOnObject(LoadComponentsResref, device);
                SetName(command, "Load Components");

                // Select Recipe command
                command = CreateItemOnObject(SelectRecipeResref, device);
                SetName(command, "Select Recipe");
            }
        }
Exemple #2
0
        /// <summary>
        /// Searches a player's inventory for components matching this recipe's requirements.
        /// </summary>
        /// <param name="player">The player to search.</param>
        private static void LoadComponents(uint player)
        {
            var device = OBJECT_SELF;
            var state  = Craft.GetPlayerCraftingState(player);
            var recipe = Craft.GetRecipe(state.SelectedRecipe);

            for (var item = GetFirstItemInInventory(player); GetIsObjectValid(item); item = GetNextItemInInventory(player))
            {
                var resref = GetResRef(item);

                if (recipe.Components.ContainsKey(resref))
                {
                    Item.ReturnItem(device, item);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Retrieves all of the items found on a crafting device which match a recipe's component list.
        /// </summary>
        /// <param name="player">The player object</param>
        /// <param name="device">The crafting device</param>
        /// <returns>A list of item object Ids </returns>
        private static List <uint> GetComponents(uint player, uint device)
        {
            var playerComponents = new List <uint>();
            var model            = Craft.GetPlayerCraftingState(player);
            var recipe           = Craft.GetRecipe(model.SelectedRecipe);

            for (var item = GetFirstItemInInventory(device); GetIsObjectValid(item); item = GetNextItemInInventory(device))
            {
                var resref = GetResRef(item);
                if (recipe.Components.ContainsKey(resref))
                {
                    playerComponents.Add(item);
                }
            }

            return(playerComponents);
        }
Exemple #4
0
        /// <summary>
        /// Determines if the player has all of the necessary components for this recipe.
        /// </summary>
        /// <param name="player">The player to check</param>
        /// <param name="device">The crafting device</param>
        /// <returns>true if player has all components, false otherwise</returns>
        private static bool HasAllComponents(uint player, uint device)
        {
            var state  = Craft.GetPlayerCraftingState(player);
            var recipe = Craft.GetRecipe(state.SelectedRecipe);
            var remainingComponents = recipe.Components.ToDictionary(x => x.Key, y => y.Value);
            var components          = GetComponents(player, device);

            for (var index = components.Count - 1; index >= 0; index--)
            {
                var component = components[index];
                var resref    = GetResRef(component);

                // Item does not need any more of this component type.
                if (!remainingComponents.ContainsKey(resref))
                {
                    continue;
                }

                var quantity = GetItemStackSize(component);

                // Player's component stack size is greater than the amount required.
                if (quantity > remainingComponents[resref])
                {
                    remainingComponents[resref] = 0;
                }
                // Player's component stack size is less than or equal to the amount required.
                else if (quantity <= remainingComponents[resref])
                {
                    remainingComponents[resref] -= quantity;
                }

                if (remainingComponents[resref] <= 0)
                {
                    remainingComponents.Remove(resref);
                }
            }

            return(remainingComponents.Count <= 0);
        }
Exemple #5
0
        public static void LearnRecipes()
        {
            var user = OBJECT_SELF;

            if (!GetIsPC(user) || GetIsDM(user))
            {
                SendMessageToPC(user, "Only players may use this item.");
                return;
            }

            var item           = Object.StringToObject(Events.GetEventData("ITEM_OBJECT_ID"));
            var playerId       = GetObjectUUID(user);
            var dbPlayer       = DB.Get <Player>(playerId);
            var recipeList     = GetLocalString(item, "RECIPES");
            var recipeIds      = recipeList.Split(',');
            var recipesLearned = 0;

            foreach (var recipeId in recipeIds)
            {
                // If it fails to parse, exit early.
                if (!int.TryParse(recipeId, out var convertedId))
                {
                    SendMessageToPC(user, "This recipe book has a configuration problem. Please inform a DM.");
                    return;
                }

                // Id number is zero or negative. Skip as those aren't valid.
                if (convertedId <= 0)
                {
                    SendMessageToPC(user, "This recipe book has a configuration problem. Please inform a DM.");
                    return;
                }

                var recipeType = (RecipeType)convertedId;

                // Ensure this type of recipe has been registered.
                if (!Craft.RecipeExists(recipeType))
                {
                    SendMessageToPC(user, "This recipe has not been registered. Please inform a DM.");
                    return;
                }

                // Player already knows this recipe. Move to the next one.
                if (dbPlayer.UnlockedRecipes.ContainsKey(recipeType))
                {
                    continue;
                }

                recipesLearned++;
                dbPlayer.UnlockedRecipes[recipeType] = DateTime.UtcNow;

                var recipeDetail = Craft.GetRecipe(recipeType);
                var skillDetail  = Skill.GetSkillDetails(recipeDetail.Skill);
                SendMessageToPC(user, $"You learn the {skillDetail.Name} recipe: {recipeDetail.Name}.");
            }

            // Player didn't learn any recipes. Let them know but don't destroy the item.
            if (recipesLearned <= 0)
            {
                SendMessageToPC(user, "You have already learned all of the recipes contained in this book.");
                return;
            }

            DestroyObject(item);
        }
Exemple #6
0
        /// <summary>
        /// Handles the auto-craft procedure. This is an automatic (no mini-game) form of crafting
        /// where success is determined by a player's stats. This simply creates the item on a successful crafting attempt.
        /// </summary>
        /// <param name="player">The player performing the auto-craft.</param>
        private static void AutoCraftItem(uint player)
        {
            var state  = Craft.GetPlayerCraftingState(player);
            var device = OBJECT_SELF;

            float CalculateAutoCraftingDelay()
            {
                var baseDelay = 20f;
                var perk      = _autoCraftPerk[state.DeviceSkillType];

                switch (Perk.GetEffectivePerkLevel(player, perk))
                {
                case 2: baseDelay -= 4; break;

                case 3: baseDelay -= 8; break;

                case 4: baseDelay -= 12; break;

                case 5: baseDelay -= 16; break;
                }

                return(baseDelay);
            }

            void CraftItem(bool isSuccessful)
            {
                var recipe = Craft.GetRecipe(state.SelectedRecipe);

                var playerComponents    = GetComponents(player, device);
                var remainingComponents = recipe.Components.ToDictionary(x => x.Key, y => y.Value);

                for (var index = playerComponents.Count - 1; index >= 0; index--)
                {
                    var component = playerComponents[index];
                    var resref    = GetResRef(component);

                    // Item does not need any more of this component type.
                    if (!remainingComponents.ContainsKey(resref))
                    {
                        continue;
                    }

                    var quantity = GetItemStackSize(component);

                    // Player's component stack size is greater than the amount required.
                    if (quantity > remainingComponents[resref])
                    {
                        SetItemStackSize(component, quantity - remainingComponents[resref]);
                        remainingComponents[resref] = 0;
                    }
                    // Player's component stack size is less than or equal to the amount required.
                    else if (quantity <= remainingComponents[resref])
                    {
                        remainingComponents[resref] -= quantity;
                        DestroyObject(component);
                    }

                    if (remainingComponents[resref] <= 0)
                    {
                        remainingComponents.Remove(resref);
                    }
                }

                if (isSuccessful)
                {
                    CreateItemOnObject(recipe.Resref, player, recipe.Quantity);
                }
            }

            if (!HasAllComponents(player, device))
            {
                SendMessageToPC(player, ColorToken.Red("You are missing some necessary components..."));
                return;
            }

            var craftingDelay = CalculateAutoCraftingDelay();

            state.IsAutoCrafting = true;
            Player.StartGuiTimingBar(player, craftingDelay);
            AssignCommand(player, () => ActionPlayAnimation(Animation.LoopingGetMid, 1f, craftingDelay));
            DelayCommand(craftingDelay, () =>
            {
                // Player logged out.
                if (!GetIsObjectValid(player))
                {
                    Craft.ClearPlayerCraftingState(player);
                    return;
                }

                var chanceToCraft = Craft.CalculateChanceToCraft(player, state.SelectedRecipe);
                var roll          = Random.NextFloat(0f, 100f);

                if (roll <= chanceToCraft)
                {
                    CraftItem(true);
                }
                else
                {
                    CraftItem(false);
                    SendMessageToPC(player, ColorToken.Red("You failed to craft the item..."));
                }

                state.IsAutoCrafting = false;
            });
            ApplyEffectToObject(DurationType.Temporary, EffectCutsceneParalyze(), player, craftingDelay);
        }
Exemple #7
0
        private void RecipePageInit(DialogPage page)
        {
            var model             = GetDataModel <Model>();
            var player            = GetPC();
            var meetsRequirements = true;

            string BuildHeader()
            {
                var recipe   = Craft.GetRecipe(model.SelectedRecipe);
                var category = Craft.GetCategoryDetail(recipe.Category);
                var skill    = Skill.GetSkillDetails(recipe.Skill);

                // Recipe quantity and name.
                var header = $"{ColorToken.Green("Recipe:")} {recipe.Quantity}x {recipe.Name} \n";

                // Associated skill
                header += $"{ColorToken.Green("Craft:")} {skill.Name}\n";

                // Associated category
                header += $"{ColorToken.Green("Category:")} {category.Name}\n";

                // Recipe's description, if available.
                if (!string.IsNullOrWhiteSpace(recipe.Description))
                {
                    header += $"{ColorToken.Green("Description:")} {recipe.Description} \n";
                }

                // Chance to craft
                header += $"{ColorToken.Green("Chance to Auto-Craft:")} {Craft.CalculateChanceToCraft(player, model.SelectedRecipe)}%";

                // List of requirements, if applicable.
                if (recipe.Requirements.Count > 0)
                {
                    header += $"\n{ColorToken.Green("Requirements:")}\n\n";

                    foreach (var req in recipe.Requirements)
                    {
                        // If the player meets the requirement, show it in green. Otherwise show it in red.
                        if (string.IsNullOrWhiteSpace(req.CheckRequirements(player)))
                        {
                            header += $"{ColorToken.Green(req.RequirementText)}\n";
                        }
                        else
                        {
                            header           += $"{ColorToken.Red(req.RequirementText)}\n";
                            meetsRequirements = false;
                        }
                    }
                }

                // List of components
                header += $"\n\n{ColorToken.Green("Components:")}\n\n";

                foreach (var(resref, quantity) in recipe.Components)
                {
                    var name = Cache.GetItemNameByResref(resref);
                    header += $"{quantity}x {name}\n";
                }

                return(header);
            }

            page.Header = BuildHeader();

            if (model.IsFabricator && meetsRequirements)
            {
                page.AddResponse("Select Recipe", () =>
                {
                    var state            = Craft.GetPlayerCraftingState(player);
                    state.SelectedRecipe = model.SelectedRecipe;

                    EndConversation();
                    Player.ForcePlaceableInventoryWindow(player, OBJECT_SELF);
                });
            }
        }