示例#1
0
    public void Craft()
    {
        // should only be called while CRAFTING and if recipe still valid
        // (no one should touch 'craftingRecipe', but let's just be sure.
        // -> we already validated everything in CmdCraft. let's just craft.
        if (player.state == "CRAFTING" &&
            currentRecipe != null &&
            currentRecipe.result != null)
        {
            // enough space?
            Item result = new Item(currentRecipe.result);
            if (inventory.CanAdd(result, 1))
            {
                // remove the ingredients from inventory in any case
                foreach (ScriptableItemAndAmount ingredient in currentRecipe.ingredients)
                {
                    if (ingredient.amount > 0 && ingredient.item != null)
                    {
                        inventory.Remove(new Item(ingredient.item), ingredient.amount);
                    }
                }

                // roll the dice to decide if we add the result or not
                // IMPORTANT: we use rand() < probability to decide.
                // => UnityEngine.Random.value is [0,1] inclusive:
                //    for 0% probability it's fine because it's never '< 0'
                //    for 100% probability it's not because it's not always '< 1', it might be == 1
                //    and if we use '<=' instead then it won't work for 0%
                // => C#'s Random value is [0,1) exclusive like most random
                //    functions. this works fine.
                if (new System.Random().NextDouble() < currentRecipe.probability)
                {
                    // add result item to inventory
                    inventory.Add(new Item(currentRecipe.result), 1);
                    TargetCraftingSuccess();
                }
                else
                {
                    TargetCraftingFailed();
                }

                // clear indices afterwards
                // note: we set all to -1 instead of calling .Clear because
                //       that would clear all the slots in host mode.
                // (don't clear in host mode, otherwise it clears the crafting
                //  UI for the player and we have to drag items into it again)
                if (!isLocalPlayer)
                {
                    for (int i = 0; i < ScriptableRecipe.recipeSize; ++i)
                    {
                        indices[i] = -1;
                    }
                }

                // clear recipe
                currentRecipe = null;
            }
        }
    }
示例#2
0
    [HideInInspector] public CraftingState craftingState = CraftingState.None; // // client sided

    // craft the current combination of items and put result into inventory
    public void Craft(int[] indices)
    {
        // validate: between 1 and 6, all valid, no duplicates?
        if (health.current > 0 &&
            0 < indices.Length && indices.Length <= ScriptableRecipe.recipeSize &&
            indices.All(index => 0 <= index && index < inventory.slots.Count && inventory.slots[index].amount > 0) &&
            !indices.ToList().HasDuplicates())
        {
            // build list of item templates from indices
            List <ItemSlot> items = indices.Select(index => inventory.slots[index]).ToList();

            // find recipe
            ScriptableRecipe recipe = ScriptableRecipe.dict.Values.ToList().Find(r => r.CanCraftWith(items)); // good enough for now
            if (recipe != null && recipe.result != null)
            {
                // enough space?
                Item result = new Item(recipe.result);
                if (inventory.CanAdd(result, 1))
                {
                    // remove the ingredients from inventory in any case
                    foreach (ScriptableItemAndAmount ingredient in recipe.ingredients)
                    {
                        if (ingredient.amount > 0 && ingredient.item != null)
                        {
                            inventory.Remove(new Item(ingredient.item), ingredient.amount);
                        }
                    }

                    // roll the dice to decide if we add the result or not
                    // IMPORTANT: we use rand() < probability to decide.
                    // => UnityEngine.Random.value is [0,1] inclusive:
                    //    for 0% probability it's fine because it's never '< 0'
                    //    for 100% probability it's not because it's not always '< 1', it might be == 1
                    //    and if we use '<=' instead then it won't work for 0%
                    // => C#'s Random value is [0,1) exclusive like most random
                    //    functions. this works fine.
                    if (new System.Random().NextDouble() < recipe.probability)
                    {
                        // add result item to inventory
                        inventory.Add(result, 1);
                        craftingState = CraftingState.Success;
                    }
                    else
                    {
                        craftingState = CraftingState.Failed;
                    }
                }
            }
        }
    }
示例#3
0
 public void SetCrafterRecipe(ScriptableRecipe rec)
 {
     if (typeSelected == 4)
     {
         //instead of directly setting the recipe, call a function on the crafter so that I can activate other shit when it changes recipe.
         if (obj)
         {
             obj.GetComponent <Crafting>().ChangeRecipe(rec);
         }
     }
     else
     {
         //if you don't have a crafter selected, say "No crater selected. This message should never be seen"
         print("No crafter selected. This message should never be seen");
     }
 }
示例#4
0
    public void CmdCraft(string recipeName, int[] clientIndices)
    {
        // validate: between 1 and 6, all valid, no duplicates?
        // -> can be IDLE or MOVING (in which case we reset the movement)
        if ((player.state == "IDLE" || player.state == "MOVING") &&
            clientIndices.Length == ScriptableRecipe.recipeSize)
        {
            // find valid indices that are not '-1' and make sure there are no
            // duplicates
            List <int> validIndices = clientIndices.Where(index => 0 <= index && index < inventory.slots.Count && inventory.slots[index].amount > 0).ToList();
            if (validIndices.Count > 0 && !validIndices.HasDuplicates())
            {
                // find recipe
                if (ScriptableRecipe.All.TryGetValue(recipeName, out ScriptableRecipe recipe) &&
                    recipe.result != null)
                {
                    // enough space?
                    Item result = new Item(recipe.result);
                    if (inventory.CanAdd(result, 1))
                    {
                        // cache recipe so we don't have to search for it again
                        // in Craft()
                        currentRecipe = recipe;

                        // store the crafting indices on the server. no need for
                        // a SyncList and unnecessary broadcasting.
                        // we already have a 'craftingIndices' variable anyway.
                        indices = clientIndices.ToList();

                        // start crafting
                        requestPending = true;
                        endTime        = NetworkTime.time + recipe.craftingTime;
                    }
                }
            }
        }
    }
    static void CreateRecipes()
    {
        XmlDocument xData = new XmlDocument();

        xData.Load("Assets/XML/RecipesXML.xml");

        XmlNodeList xRecipeList = xData.SelectNodes("root/recipe");

        foreach (XmlNode xRecipe in xRecipeList)
        {
            ScriptableRecipe recipeObj = new ScriptableRecipe();
            recipeObj.name        = xRecipe.Attributes["name"].Value.Replace(" ", "_");
            recipeObj.description = xRecipe.Attributes["description"].Value;

            XmlNodeList xIngredients = xRecipe.SelectNodes("ingredient");

            foreach (XmlNode xIngredient in xIngredients)
            {
                RecipeIngredients recipeIngr = new RecipeIngredients();
                recipeIngr.ingredient = (Ingredients)Enum.Parse(typeof(Ingredients), xIngredient.Attributes["name"].Value.Replace(" ", "_"));
                recipeIngr.quantity   = Convert.ToSingle(xIngredient.Attributes["quantity"].Value);
                recipeObj.ingredients.Add(recipeIngr);

                ScriptableIngredient scriptableIngr = AssetDatabase.LoadAssetAtPath("Assets/ScriptableObjects/Ingredients/" + xIngredient.Attributes["name"].Value.Replace(" ", "_") + ".asset", typeof(ScriptableIngredient)) as ScriptableIngredient;

                recipeObj.value += scriptableIngr.cost * recipeIngr.quantity;
            }

            string codeText    = File.ReadAllText("Assets/Scripts/Recipes.cs");
            int    markerIndex = codeText.LastIndexOf("//#RECIPE#");
            File.WriteAllText("Assets/Scripts/Recipes.cs", codeText.Insert(markerIndex, recipeObj.name + ",\n\t"));

            AssetDatabase.CreateAsset(recipeObj, "Assets/ScriptableObjects/Recipes/" + recipeObj.name + ".asset");
            AssetDatabase.Refresh();
        }
    }
示例#6
0
    public void ChangeRecipe(ScriptableRecipe r)
    {
        recipe = r;
        recipeDisplay.sprite = r.img;
        recipeDisplay.color  = r.imgColor;
        //also set a stored default recipe so that it is easier to make a lot of the same machine
        if (r)
        {
            info.storedRecipe = r;
        }
        //set recipe string list and int list
        currentRecipe           = new List <string> ();
        currentAmounts          = new List <int> ();
        currentRecipe.Capacity  = recipe.input.Count;
        currentAmounts.Capacity = recipe.input.Count;

        for (int i = 0; i < recipe.input.Count; i++)
        {
            string temp = recipe.input[i].Split(',')[0];
            currentAmounts.Add(int.Parse(temp) + 1);
            currentRecipe.Add(recipe.input[i].Split(',')[1]);
        }
        //the way this works means that you must order your recipes as "1,sand 2,rock etc"
    }
示例#7
0
    void Update()
    {
        Player player = Player.localPlayer;

        if (player)
        {
            // hotkey (not while typing in chat, etc.)
            if (Input.GetKeyDown(hotKey) && !UIUtils.AnyInputActive())
            {
                panel.SetActive(!panel.activeSelf);
            }

            // only update the panel if it's active
            if (panel.activeSelf)
            {
                // instantiate/destroy enough slots
                UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, player.crafting.indices.Count, ingredientContent);

                // refresh all
                for (int i = 0; i < player.crafting.indices.Count; ++i)
                {
                    UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
                    slot.dragAndDropable.name = i.ToString(); // drag and drop index
                    int itemIndex = player.crafting.indices[i];

                    if (0 <= itemIndex && itemIndex < player.inventory.slots.Count &&
                        player.inventory.slots[itemIndex].amount > 0)
                    {
                        ItemSlot itemSlot = player.inventory.slots[itemIndex];

                        // refresh valid item

                        // only build tooltip while it's actually shown. this
                        // avoids MASSIVE amounts of StringBuilder allocations.
                        slot.tooltip.enabled = true;
                        if (slot.tooltip.IsVisible())
                        {
                            slot.tooltip.text = itemSlot.ToolTip();
                        }
                        slot.dragAndDropable.dragable = true;

                        // use durability colors?
                        if (itemSlot.item.maxDurability > 0)
                        {
                            if (itemSlot.item.durability == 0)
                            {
                                slot.image.color = brokenDurabilityColor;
                            }
                            else if (itemSlot.item.DurabilityPercent() < lowDurabilityThreshold)
                            {
                                slot.image.color = lowDurabilityColor;
                            }
                            else
                            {
                                slot.image.color = Color.white;
                            }
                        }
                        else
                        {
                            slot.image.color = Color.white;  // reset for no-durability items
                        }
                        slot.image.sprite = itemSlot.item.image;

                        slot.amountOverlay.SetActive(itemSlot.amount > 1);
                        slot.amountText.text = itemSlot.amount.ToString();
                    }
                    else
                    {
                        // reset the index because it's invalid
                        player.crafting.indices[i] = -1;

                        // refresh invalid item
                        slot.tooltip.enabled          = false;
                        slot.dragAndDropable.dragable = false;
                        slot.image.color  = Color.clear;
                        slot.image.sprite = null;
                        slot.amountOverlay.SetActive(false);
                    }
                }

                // find valid indices => item templates => matching recipe
                List <int> validIndices = player.crafting.indices.Where(
                    index => 0 <= index && index < player.inventory.slots.Count &&
                    player.inventory.slots[index].amount > 0
                    ).ToList();
                List <ItemSlot>  items  = validIndices.Select(index => player.inventory.slots[index]).ToList();
                ScriptableRecipe recipe = ScriptableRecipe.Find(items);
                if (recipe != null)
                {
                    // refresh valid recipe
                    Item item = new Item(recipe.result);
                    // only build tooltip while it's actually shown. this
                    // avoids MASSIVE amounts of StringBuilder allocations.
                    resultSlotToolTip.enabled = true;
                    if (resultSlotToolTip.IsVisible())
                    {
                        resultSlotToolTip.text = new ItemSlot(item).ToolTip(); // ItemSlot so that {AMOUNT} is replaced too
                    }
                    resultSlotImage.color  = Color.white;
                    resultSlotImage.sprite = recipe.result.image;

                    // show progress bar while crafting
                    // (show 100% if craft time = 0 because it's just better feedback)
                    progressSlider.gameObject.SetActive(player.state == "CRAFTING");
                    double startTime   = player.crafting.endTime - recipe.craftingTime;
                    double elapsedTime = NetworkTime.time - startTime;
                    progressSlider.value = recipe.craftingTime > 0 ? (float)elapsedTime / recipe.craftingTime : 1;
                }
                else
                {
                    // refresh invalid recipe
                    resultSlotToolTip.enabled = false;
                    resultSlotImage.color     = Color.clear;
                    resultSlotImage.sprite    = null;
                    progressSlider.gameObject.SetActive(false);
                }

                // craft result
                // (no recipe != null check because it will be null if those were
                //  the last two ingredients in our inventory)
                if (player.crafting.state == CraftingState.Success)
                {
                    resultText.color = successColor;
                    resultText.text  = "Success!";
                }
                else if (player.crafting.state == CraftingState.Failed)
                {
                    resultText.color = failedColor;
                    resultText.text  = "Failed :(";
                }
                else
                {
                    resultText.text = "";
                }

                // craft button with 'Try' prefix to let people know that it might fail
                // (disabled while in progress)
                craftButton.GetComponentInChildren <Text>().text = recipe != null &&
                                                                   recipe.probability < 1 ? "Try Craft" : "Craft";
                craftButton.interactable = recipe != null &&
                                           player.state != "CRAFTING" &&
                                           player.crafting.state != CraftingState.InProgress &&
                                           player.inventory.CanAdd(new Item(recipe.result), 1);
                craftButton.onClick.SetListener(() => {
                    player.crafting.state = CraftingState.InProgress; // wait for result

                    // pass original array so server can copy it to it's own
                    // craftingIndices. we pass original one and not only the valid
                    // indicies because then in host mode we would make the crafting
                    // indices array smaller by only copying the valid indices,
                    // hence losing crafting slots
                    player.crafting.CmdCraft(recipe.name, player.crafting.indices.ToArray());
                });
            }
        }
        else
        {
            panel.SetActive(false);
        }
    }
示例#8
0
    void Update()
    {
        GameObject player = Player.player;

        if (!player)
        {
            return;
        }

        PlayerCrafting crafting  = player.GetComponent <PlayerCrafting>();
        Inventory      inventory = player.GetComponent <Inventory>();

        // instantiate/destroy enough slots
        UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, crafting.indices.Count, ingredientContent);

        // refresh all
        for (int i = 0; i < crafting.indices.Count; ++i)
        {
            UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
            slot.dragAndDropable.name = i.ToString(); // drag and drop index
            int itemIndex = crafting.indices[i];

            if (0 <= itemIndex && itemIndex < inventory.slots.Count &&
                inventory.slots[itemIndex].amount > 0)
            {
                ItemSlot itemSlot = inventory.slots[itemIndex];

                // refresh valid item
                slot.tooltip.enabled          = true;
                slot.tooltip.text             = itemSlot.ToolTip();
                slot.dragAndDropable.dragable = true;
                slot.image.color  = Color.white;
                slot.image.sprite = itemSlot.item.image;
                slot.amountOverlay.SetActive(itemSlot.amount > 1);
                slot.amountText.text = itemSlot.amount.ToString();
            }
            else
            {
                // reset the index because it's invalid
                crafting.indices[i] = -1;

                // refresh invalid item
                slot.tooltip.enabled          = false;
                slot.dragAndDropable.dragable = false;
                slot.image.color  = Color.clear;
                slot.image.sprite = null;
                slot.amountOverlay.SetActive(false);
            }
        }

        // find valid indices => item templates => matching recipe
        List <int> validIndices = crafting.indices.Where(
            index => 0 <= index && index < inventory.slots.Count &&
            inventory.slots[index].amount > 0
            ).ToList();
        List <ItemSlot>  items  = validIndices.Select(index => inventory.slots[index]).ToList();
        ScriptableRecipe recipe = ScriptableRecipe.dict.Values.ToList().Find(r => r.CanCraftWith(items)); // good enough for now

        if (recipe != null)
        {
            // refresh valid recipe
            Item item = new Item(recipe.result);
            resultSlotToolTip.enabled = true;
            resultSlotToolTip.text    = new ItemSlot(item).ToolTip(); // ItemSlot so that {AMOUNT} is replaced too
            resultSlotImage.color     = Color.white;
            resultSlotImage.sprite    = recipe.result.image;
        }
        else
        {
            // refresh invalid recipe
            resultSlotToolTip.enabled = false;
            resultSlotImage.color     = Color.clear;
            resultSlotImage.sprite    = null;
        }

        // craft result
        // (no recipe != null check because it will be null if those were
        //  the last two ingredients in our inventory)
        if (crafting.craftingState == CraftingState.Success)
        {
            resultText.color = successColor;
            resultText.text  = "Success!";
        }
        else if (crafting.craftingState == CraftingState.Failed)
        {
            resultText.color = failedColor;
            resultText.text  = "Failed :(";
        }
        else
        {
            resultText.text = "";
        }

        // craft button with 'Try' prefix to let people know that it might fail
        // (disabled while in progress)
        craftButton.GetComponentInChildren <Text>().text = recipe != null &&
                                                           recipe.probability < 1 ? "Try Craft" : "Craft";
        craftButton.interactable = recipe != null &&
                                   crafting.craftingState != CraftingState.InProgress &&
                                   inventory.CanAdd(new Item(recipe.result), 1);
        craftButton.onClick.SetListener(() => {
            crafting.craftingState = CraftingState.InProgress; // wait for result
            crafting.Craft(validIndices.ToArray());
        });
    }
示例#9
0
    void Update()
    {
        Player player = Utils.ClientLocalPlayer();
        if (!player) return;

        // hotkey (not while typing in chat, etc.)
        if (Input.GetKeyDown(hotKey) && !UIUtils.AnyInputActive())
            panel.SetActive(!panel.activeSelf);

        // only update the panel if it's active
        if (panel.activeSelf)
        {
            // instantiate/destroy enough slots
            UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, player.craftingIndices.Count, ingredientContent);

            // refresh all
            for (int i = 0; i < player.craftingIndices.Count; ++i)
            {
                UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent<UICraftingIngredientSlot>();
                slot.dragAndDropable.name = i.ToString(); // drag and drop index
                int itemIndex = player.craftingIndices[i];

                if (0 <= itemIndex && itemIndex < player.inventory.Count &&
                    player.inventory[itemIndex].amount > 0)
                {
                    ItemSlot itemSlot = player.inventory[itemIndex];

                    // refresh valid item
                    slot.tooltip.enabled = true;
                    slot.tooltip.text = itemSlot.ToolTip();
                    slot.dragAndDropable.dragable = true;
                    slot.image.color = Color.white;
                    slot.image.sprite = itemSlot.item.image;
                }
                else
                {
                    // reset the index because it's invalid
                    player.craftingIndices[i] = -1;

                    // refresh invalid item
                    slot.tooltip.enabled = false;
                    slot.dragAndDropable.dragable = false;
                    slot.image.color = Color.clear;
                    slot.image.sprite = null;
                }
            }

            // find valid indices => item templates => matching recipe
            List<int> validIndices = player.craftingIndices.Where(
                index => 0 <= index && index < player.inventory.Count &&
                       player.inventory[index].amount > 0
            ).ToList();
            List<ScriptableItem> items = validIndices.Select(index => player.inventory[index].item.data).ToList();
            ScriptableRecipe recipe = ScriptableRecipe.dict.Values.ToList().Find(r => r.CanCraftWith(items)); // good enough for now
            if (recipe != null)
            {
                // refresh valid recipe
                resultSlotToolTip.enabled = true;
                resultSlotToolTip.text = new Item(recipe.result).ToolTip();
                resultSlotImage.color = Color.white;
                resultSlotImage.sprite = recipe.result.image;
            }
            else
            {
                // refresh invalid recipe
                resultSlotToolTip.enabled = false;
                resultSlotImage.color = Color.clear;
                resultSlotImage.sprite = null;
            }

            // craft button
            craftButton.interactable = recipe != null && player.InventoryCanAdd(new Item(recipe.result), 1);
            craftButton.onClick.SetListener(() => {
                player.CmdCraft(validIndices.ToArray());
            });
        }

        // addon system hooks
        Utils.InvokeMany(typeof(UICrafting), this, "Update_");
    }