/// <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); }
//////////////// 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); }); } }