/// <summary>
        /// Reports all the reasons a given recipe for a givne player will fail with a given set of ingredients (defaults to
        /// the player's inventory).
        /// </summary>
        /// <param name="player"></param>
        /// <param name="recipe"></param>
        /// <param name="missingTile">Returns the tile IDs (crafting stations) needed for the recipe.</param>
        /// <param name="missingItemTypesStacks">Returns the missing item ids and amounts for the recipe.</param>
        /// <param name="availableIngredients"></param>
        /// <returns></returns>
        public static RecipeCraftFailReason GetRecipeFailReasons(Player player, Recipe recipe,
                                                                 out int[] missingTile, out IDictionary <int, int> missingItemTypesStacks,
                                                                 IEnumerable <Item> availableIngredients = null
                                                                 )
        {
            RecipeCraftFailReason reason = 0;
            var missingTileList          = new List <int>();

            missingItemTypesStacks = new Dictionary <int, int>();

            // Get available item ingredients
            if (availableIngredients == null)
            {
                availableIngredients = player.inventory
                                       .Take(58)
                                       .Where(item => !item.IsAir);

                bool?  _;
                Item[] chest = PlayerItemHelpers.GetCurrentlyOpenChest(player, out _);
                if (chest != null)
                {
                    availableIngredients = availableIngredients.Concat(chest);
                }
            }

            // Process ingredients list into id + stack map
            IDictionary <int, int> availIngredientInfo = new Dictionary <int, int>(availableIngredients.Count());

            foreach (Item item in availableIngredients)
            {
                if (availIngredientInfo.ContainsKey(item.netID))
                {
                    availIngredientInfo[item.netID] += item.stack;
                }
                else
                {
                    availIngredientInfo[item.netID] = item.stack;
                }
            }

            // Tiles
            for (int i = 0; i < recipe.requiredTile.Length; i++)
            {
                int reqTileType = recipe.requiredTile[i];
                if (reqTileType == -1)
                {
                    break;
                }

                if (!player.adjTile[reqTileType])
                {
                    missingTileList.Add(reqTileType);
                    reason |= RecipeCraftFailReason.MissingTile;
                }
            }

            // Items
            for (int i = 0; i < recipe.requiredItem.Length; i++)
            {
                Item reqItem = recipe.requiredItem[i];
                if (reqItem == null || reqItem.type == 0)
                {
                    break;
                }

                int  reqStack         = reqItem.stack;
                bool hasCheckedGroups = false;

                foreach (var kv in availIngredientInfo)
                {
                    int itemType  = kv.Key;
                    int itemStack = kv.Value;

                    if (recipe.useWood(itemType, reqItem.type) ||
                        recipe.useSand(itemType, reqItem.type) ||
                        recipe.useIronBar(itemType, reqItem.type) ||
                        recipe.useFragment(itemType, reqItem.type) ||
                        recipe.usePressurePlate(itemType, reqItem.type) ||
                        recipe.AcceptedByItemGroups(itemType, reqItem.type))
                    {
                        reqStack        -= itemStack;
                        hasCheckedGroups = true;
                    }
                }
                if (!hasCheckedGroups && availIngredientInfo.ContainsKey(reqItem.netID))
                {
                    reqStack -= availIngredientInfo[reqItem.netID];
                }

                // Account for missing ingredients:
                if (reqStack > 0)
                {
                    missingItemTypesStacks[reqItem.netID] = reqStack;
                    reason |= RecipeCraftFailReason.MissingItem;
                }
            }

            if (recipe.needWater && !player.adjWater && !player.adjTile[172])
            {
                reason |= RecipeCraftFailReason.NeedsNearbyWater;
            }
            if (recipe.needHoney && !player.adjHoney)
            {
                reason |= RecipeCraftFailReason.NeedsNearbyHoney;
            }
            if (recipe.needLava && !player.adjLava)
            {
                reason |= RecipeCraftFailReason.NeedsNearbyLava;
            }
            if (recipe.needSnowBiome && !player.ZoneSnow)
            {
                reason |= RecipeCraftFailReason.NeedsNearbySnowBiome;
            }

            missingTile = missingTileList.ToArray();
            return(reason);
        }
示例#2
0
        ////////////////

        public override void PreUpdate()
        {
            Player plr = this.player;

            if (plr.whoAmI != Main.myPlayer)
            {
                return;
            }
            if (plr.dead)
            {
                return;
            }

            var  mymod      = (StarvationMod)this.mod;
            int  buffIdx    = plr.FindBuffIndex(BuffID.WellFed);
            bool isStarving = false;

            if (buffIdx == -1)
            {
                if (this.HurtDelay-- < 0)
                {
                    this.HurtDelay = mymod.Config.StarvationHarmRepeatDelayInTicks;
                    this.HungerHurt();
                }
                isStarving = true;
            }
            else
            {
                if (plr.buffTime[buffIdx] > (mymod.Config.WellFedAddedDrainPerTick + 1))
                {
                    float mul      = mymod.Config.AddedWellFedDrainRatePerTickMultiplierPerMaxHealthOver100;
                    float addDrain = mul * (float)Math.Max(0, this.player.statLifeMax - 100);
                    plr.buffTime[buffIdx] -= mymod.Config.WellFedAddedDrainPerTick + (int)addDrain;
                }
            }

            if (isStarving && isStarving != this.IsStarving)
            {
                Main.NewText("You're starving! Find food quickly.", Color.Red);
                if (this.player.statLifeMax == 400 && mymod.Config.CraftableUnlifeCrystal)
                {
                    Main.NewText("Tip: Craft Unlife Crystals to reduce max hunger rate (but also max health).", new Color(96, 96, 96));
                }
            }

            this.IsStarving = isStarving;

            if (Timers.GetTimerTickDuration("StarvationInventoryRotCheck") <= 0)
            {
                Timers.SetTimer("StarvationInventoryRotCheck", 60, () => {
                    if (Main.gamePaused || !LoadHelpers.IsWorldSafelyBeingPlayed())
                    {
                        return(false);
                    }

                    for (int i = 0; i < player.inventory.Length; i++)
                    {
                        Item item = player.inventory[i];
                        if (item == null || item.IsAir)
                        {
                            continue;
                        }

                        if (RotItem.IsRotted(item))
                        {
                            if (!Main.mouseItem.IsAir && i == PlayerItemHelpers.VanillaInventorySelectedSlot)
                            {
                                Main.mouseItem = new Item();
                            }

                            player.inventory[i] = new Item();
                            ItemHelpers.CreateItem(player.Center, ModContent.ItemType <RotItem>(), item.stack, RotItem.Width, RotItem.Height);
                        }
                    }

                    bool?_;
                    Item[] myChest = PlayerItemHelpers.GetCurrentlyOpenChest(player, out _);
                    if (myChest != null)
                    {
                        for (int i = 0; i < myChest.Length; i++)
                        {
                            Item item = myChest[i];
                            if (item == null || item.IsAir)
                            {
                                continue;
                            }

                            if (RotItem.IsRotted(item))
                            {
                                myChest[i] = new Item();
                                ItemHelpers.CreateItem(player.Center, ModContent.ItemType <RotItem>(), item.stack, RotItem.Width, RotItem.Height);
                            }
                        }
                    }

                    return(false);
                });
            }
        }