public OmniBagMenu(ItemBagMenu IBM, OmniBag Bag, int Columns, int SlotSize, bool ShowLockedSlots, int Padding) { this.IBM = IBM; this.OmniBag = Bag; Bag.OnContentsChanged += Bag_ContentsChanged; this.Padding = Padding; this.ColumnCount = Columns; this.OriginalSlotSize = SlotSize; this.SlotSize = SlotSize; this.ShowLockedSlots = ShowLockedSlots; // Create a placeholder item for every kind of bag the OmniBag can store List <ItemBag> Temp = new List <ItemBag>(); if (BundleBag.ValidSizes.Any(x => x <= this.Bag.Size)) { ContainerSize PlaceholderSize = BundleBag.ValidSizes.OrderByDescending(x => x).First(x => x <= this.Bag.Size); Temp.Add(new BundleBag(PlaceholderSize, false)); } Temp.Add(new Rucksack(Bag.Size, false)); foreach (BagType BagType in ItemBagsMod.BagConfig.BagTypes) { if (BagType.SizeSettings.Any(x => x.Size <= this.Bag.Size)) { ContainerSize PlaceholderSize = BagType.SizeSettings.Select(x => x.Size).OrderByDescending(x => x).First(x => x <= this.Bag.Size); Temp.Add(new BoundedBag(BagType, PlaceholderSize, false)); } } this.Placeholders = new ReadOnlyCollection <ItemBag>(Temp); this.ActualContents = new List <ItemBag>(); for (int i = 0; i < Temp.Count; i++) { ActualContents.Add(null); } UpdateActualContents(); SetTopLeft(Point.Zero, false); InitializeLayout(1); }
public OmniBag(ContainerSize Size) : base(ItemBagsMod.Translate("OmniBagName"), ItemBagsMod.Translate("OmniBagDescription"), Size, null, null, new Vector2(16, 16), 0.5f, 1f) { string SizeName = ItemBagsMod.Translate(string.Format("Size{0}Name", Size.GetDescription())); DescriptionAlias = string.Format("{0}\n({1})\n({2})", ItemBagsMod.Translate("OmniBagDescription"), ItemBagsMod.Translate("CapacityDescription", new Dictionary <string, string>() { { "count", MaxStackSize.ToString() } }), ItemBagsMod.Translate("OmniBagCapacityDescription", new Dictionary <string, string>() { { "size", SizeName } }) ); this.NestedBags = new List <ItemBag>(); LoadTextures(); }
/// <summary>Intended to only be used when instantiating a <see cref="BundleBag"/></summary> protected BoundedBag(string BaseName, string Description, ContainerSize Size, bool Autofill) : base(BaseName, Description, Size, TextureHelpers.JunimoNoteTexture, new Rectangle(0, 244, 16, 16), new Vector2(16, 16), 0.5f, 1f) { this.Autofill = Autofill; this.ExcludedAutofillItems = new Dictionary <string, HashSet <ObjectQuality> >(); }
private static PackageSize GetPackageSize(ContainerSize containerSize) { return((PackageSize)(int)containerSize); }
public static void MonsterDrop_Postfix(GameLocation __instance, Monster monster, int x, int y, Farmer who) { try { MonsterLootSettings LootSettings = MonsterLootSettings; if (who.UniqueMultiplayerID == Game1.player.UniqueMultiplayerID && LootSettings.CanReceiveBagsAsDrops) { // Roll chance at receiving an ItemBag double Chance = LootSettings.GetItemBagDropChance(__instance, monster, out double BaseChance, out double LocationMultiplier, out double ExpMultiplier, out double HPMultiplier); bool Success = Randomizer.NextDouble() <= Chance; string LogMessage; if (Success) { if (MonsterLootSettings.LogDropChancesToConsole) { LogMessage = string.Format("Succeeded drop chance: Location = {0}, monster.ExperienceGained = {1}, monster.MaxHealth = {2}\n" + "BaseChance = {3} ({4}%), LocationMultiplier = {5} (+{6}%), ExpMultiplier = {7}, HPMultiplier = {8} (+{9}%), TotalChance = {10} ({11}%)", __instance.Name, monster.ExperienceGained, monster.MaxHealth, BaseChance, (BaseChance * 100.0).ToString("0.##"), LocationMultiplier, ((LocationMultiplier - 1.0) * 100.0).ToString("0.##"), ExpMultiplier.ToString("#.####"), HPMultiplier, ((HPMultiplier - 1.0) * 100.0).ToString("0.##"), Chance, (Chance * 100.0).ToString("0.###")); Monitor.Log(LogMessage, LogLevel.Info); } int SpawnDirection = Randomizer.Next(4); List <ItemBag> OwnedBags = ItemBag.GetAllBags(true); // Compute the odds of receiving each type of bag bool CanReceiveRucksack = LootSettings.RucksackDropSettings.SizeWeights.Any(size => size.Value > 0); int RucksackWeight = CanReceiveRucksack ? LootSettings.RucksackDropSettings.TypeWeight : 0; bool CanReceiveOmniBag = LootSettings.OmniBagDropSettings.SizeWeights.Any(size => size.Value > 0); int OmniBagWeight = CanReceiveOmniBag ? LootSettings.OmniBagDropSettings.TypeWeight : 0; bool CanReceiveBundleBag = LootSettings.BundleBagDropSettings.SizeWeights.Any(size => BundleBag.ValidSizes.Contains(size.Key) && size.Value > 0 && !IsSizeObsolete(OwnedBags, BundleBag.BundleBagTypeId, size.Key)); int BundleBagWeight = CanReceiveBundleBag ? LootSettings.BundleBagDropSettings.TypeWeight : 0; bool CanReceiveStandardBag = LootSettings.StandardBagDropSettings.SizeWeights.Any(size => size.Value > 0); int StandardBagWeight = CanReceiveStandardBag ? LootSettings.StandardBagDropSettings.TypeWeight : 0; int TotalTypeWeight = RucksackWeight + OmniBagWeight + BundleBagWeight + StandardBagWeight; if (TotalTypeWeight > 0) { ItemBag ChosenBag; // Pick the type of bag to spawn (Rucksack, OmniBag, BundleBag or a standard BoundedBag) int ChosenTypeWeight = Randomizer.Next(0, TotalTypeWeight); if (ChosenTypeWeight < RucksackWeight) { ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.RucksackDropSettings.SizeWeights); // Try to force a non-obsolete bag to spawn if (RollDice(LootSettings.ForceNewBagTypeChance)) { List <ContainerSize> ValidSizes = LootSettings.RucksackDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList(); ContainerSize MaxSize = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max(); while (CurrentSize < MaxSize && IsSizeObsolete(OwnedBags, Rucksack.RucksackTypeId, CurrentSize)) { CurrentSize = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First(); } } // Spawn a Rucksack ChosenBag = new Rucksack(CurrentSize, false); } else if (ChosenTypeWeight < RucksackWeight + OmniBagWeight) { ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.OmniBagDropSettings.SizeWeights); // Try to force a non-obsolete bag to spawn if (RollDice(LootSettings.ForceNewBagTypeChance)) { List <ContainerSize> ValidSizes = LootSettings.OmniBagDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList(); ContainerSize MaxSize = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max(); while (CurrentSize < MaxSize && IsSizeObsolete(OwnedBags, OmniBag.OmniBagTypeId, CurrentSize)) { CurrentSize = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First(); } } // Spawn an OmniBag ChosenBag = new OmniBag(CurrentSize); } else if (ChosenTypeWeight < RucksackWeight + OmniBagWeight + BundleBagWeight) { // Spawn a BundleBag ContainerSize Size = GetWeightedRandomSize(LootSettings.BundleBagDropSettings.SizeWeights.Where(size => BundleBag.ValidSizes.Contains(size.Key) && !IsSizeObsolete(OwnedBags, BundleBag.BundleBagTypeId, size.Key))); ChosenBag = new BundleBag(Size, true); } else { ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.StandardBagDropSettings.SizeWeights); // Get all standard BagTypes that are available in the chosen size List <BagType> StandardTypes = ItemBagsMod.BagConfig.BagTypes.Where(type => type.SizeSettings.Any(sizeCfg => sizeCfg.Size == CurrentSize)).ToList(); // Try to force a non-obsolete bag to spawn if (RollDice(LootSettings.ForceNewBagTypeChance)) { StandardTypes.RemoveAll(type => IsSizeObsolete(OwnedBags, type.Id, CurrentSize)); // If all bag types were obsolete, then keep incrementing the size until we find a non-obsolete bag to spawn if (!StandardTypes.Any()) { List <ContainerSize> ValidSizes = LootSettings.StandardBagDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList(); ContainerSize MaxSize = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max(); while (CurrentSize < MaxSize && !StandardTypes.Any()) { CurrentSize = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First(); StandardTypes = ItemBagsMod.BagConfig.BagTypes.Where(type => type.SizeSettings.Any(sizeCfg => sizeCfg.Size == CurrentSize) && !IsSizeObsolete(OwnedBags, type.Id, CurrentSize)).ToList(); } } } if (StandardTypes.Any()) { // Spawn a standard BoundedBag int ChosenTypeIndex = Randomizer.Next(StandardTypes.Count); ChosenBag = new BoundedBag(StandardTypes[ChosenTypeIndex], CurrentSize, false); } else { ChosenBag = null; } } if (ChosenBag != null) { Game1.createItemDebris(ChosenBag, Game1.player.getStandingPosition(), SpawnDirection, null, -1); } } } else if (MonsterLootSettings.LogDropChancesToConsole) { LogMessage = string.Format("Failed drop chance: Location = {0}, monster.ExperienceGained = {1}, monster.MaxHealth = {2}\n" + "BaseChance = {3} ({4}%), LocationMultiplier = {5} (+{6}%), ExpMultiplier = {7}, HPMultiplier = {8} (+{9}%), TotalChance = {10} ({11}%)", __instance.Name, monster.ExperienceGained, monster.MaxHealth, BaseChance, (BaseChance * 100.0).ToString("0.##"), LocationMultiplier, ((LocationMultiplier - 1.0) * 100.0).ToString("0.##"), ExpMultiplier.ToString("#.####"), HPMultiplier, ((HPMultiplier - 1.0) * 100.0).ToString("0.##"), Chance, (Chance * 100.0).ToString("0.###")); Monitor.Log(LogMessage, LogLevel.Info); } } } catch (Exception ex) { Monitor.Log(string.Format("Unhandled Error in {0}:\n{1}", nameof(MonsterDrop_Postfix), ex), LogLevel.Error); } }
/// <summary>Returns true if there is already a bag within <paramref name="OwnedBags"/> that belongs to the given <paramref name="TypeId"/> and whose size is >= the given <paramref name="Size"/></summary> /// <param name="OwnedBags"></param> private static bool IsSizeObsolete(List <ItemBag> OwnedBags, string TypeId, ContainerSize Size) { return(OwnedBags.Any(x => x.GetTypeId() == TypeId && x.Size >= Size)); }
/// <summary>Must be executed after <see cref="IJsonAssetsAPI.IdsFixed"/> event has fired.<para/> /// Returns all BigCraftable and all Objects that belong to the given mod manifest UniqueID. /// Does not include other types of items such as Hats or Weapons.</summary> internal static List <ModdedItem> GetModdedItems(string ModUniqueId, ContainerSize RequiredSize = ContainerSize.Small) { List <ModdedItem> Items = new List <ModdedItem>(); IModHelper Helper = ItemBagsMod.ModInstance.Helper; if (Helper.ModRegistry.IsLoaded(ItemBagsMod.JAUniqueId)) { IJsonAssetsAPI API = Helper.ModRegistry.GetApi <IJsonAssetsAPI>(ItemBagsMod.JAUniqueId); if (API != null) { List <string> Objects = API.GetAllObjectsFromContentPack(ModUniqueId); if (Objects != null) { // Index all regular Objects by their names Dictionary <string, int> AllObjectIds = new Dictionary <string, int>(); foreach (System.Collections.Generic.KeyValuePair <int, string> KVP in Game1.objectInformation) { string ObjectName = KVP.Value.Split('/').First(); if (!AllObjectIds.ContainsKey(ObjectName)) { AllObjectIds.Add(ObjectName, KVP.Key); } } foreach (string ModdedItemName in Objects) { // Try to guess if the item has multiple different valid qualities, based on the it's category bool HasQualities = true; if (AllObjectIds.TryGetValue(ModdedItemName, out int ItemId)) { Object SampleItem = new Object(ItemId, 1, false, -1, 0); if (SampleItem != null) { HasQualities = CategoriesWithQualities.Contains(SampleItem.Category); } } Items.Add(new ModdedItem(ModdedItemName, false, HasQualities, RequiredSize)); } } //List<string> Crops = API.GetAllCropsFromContentPack(ModUniqueId); //if (Crops != null) // Items.AddRange(Crops.Select(x => new ModdedItem(x, false, false, RequiredSize))); List <string> BigCraftables = API.GetAllBigCraftablesFromContentPack(ModUniqueId); if (BigCraftables != null) { Items.AddRange(BigCraftables.Select(x => new ModdedItem(x, true, false, RequiredSize))); } } } //Possible TODO //If ContentPatcher mod is loaded, try to parse the mod's content.json file and read the modded item's added by "Action"="EditData" and "Target"="Data/ObjectInformation" //For example, the content.json file might have data like this (this is a brief sample from the 'New Fish' mod https://www.nexusmods.com/stardewvalley/mods/3578): //{ // "Action": "EditData", // "Target": "Data/ObjectInformation", // "Entries": { // "1120": "Ladyfish/80/8/Fish -4/Ladyfish/This saltwater fish prefers temperate waters and feeds in large schools.", // "1121": "Tancho Koi/150/5/Fish -4/Tancho Koi/A white carp with a red spot on its head. People appreciate their beauty and usually keep them in aquariums. It would be such a waste to eat or turn into fertilizer./Day Night^Fall", // ... // ... // ... // } //} return(Items); }
public int GetRucksackSlotCount(ContainerSize Size) { return(RucksackSettings.First(x => x.Size == Size).Slots); }
public int GetStandardBagCapacity(ContainerSize Size, BagType Type) { StandardBagSizeConfig SizeCfg = StandardBagSettings.First(x => x.Size == Size); return(SizeCfg.GetCapacity(Type, GlobalCapacityModifier)); }
public bool AllowDowngradeBundleItemQuality(ContainerSize Size) { BundleBagSizeConfig SizeCfg = BundleBagSettings.First(x => x.Size == Size); return(SizeCfg.AllowDowngradeItemQuality); }
public Container(float Units, ContainerSize size = ContainerSize.Full) { this.Amount = Units; this.TotalCapacity = (float)size / 4f; this.Size = size; }
public ResourceContainer(Matter type, float initialAmount, ContainerSize size) : base(initialAmount, size) { this.MatterType = type; }
private void Display_MenuChanged(object sender, MenuChangedEventArgs e) { // Refresh completed Bundles in the community center if (e.OldMenu != null && e.OldMenu is JunimoNoteMenu) { CommunityCenterBundles.Instance = new CommunityCenterBundles(); } if (e.NewMenu is ShopMenu SM) { // Determine if the shop menu belongs to one of our managed shops bool IsModifiableShop = false; BagShop BagShop = BagShop.Pierre; if (SM.portraitPerson?.Name != null) { //TODO test if the Stardew Valley Expanded shops like Isaac/Sophia/Alesia have non-null values for ShopMenu.portraitPerson.Name if (Enum.TryParse(SM.portraitPerson.Name, out BagShop)) { IsModifiableShop = true; } } else if (SM.storeContext != null) { if (SM.storeContext.Equals("Forest", StringComparison.CurrentCultureIgnoreCase)) { if (SM.onPurchase?.GetMethodInfo().Name == "onTravelingMerchantShopPurchase") // nameof(Utility.onTravelingMerchantShopPurchase) { BagShop = BagShop.TravellingCart; } else { BagShop = BagShop.HatMouse; } IsModifiableShop = true; } else if (SM.storeContext.Equals("Town", StringComparison.CurrentCultureIgnoreCase) && SM.potraitPersonDialogue != null && SM.potraitPersonDialogue.Contains("Khadija")) { BagShop = BagShop.Khadija; IsModifiableShop = true; } } // Add Bag items to the shop's stock if (IsModifiableShop) { Dictionary <ISalable, int[]> Stock = SM.itemPriceAndStock; bool ShouldModifyStock = true; if (BagShop == BagShop.Clint) { // Assume user is viewing Clint tool upgrades if the stock doesn't contain Coal if (!Stock.Any(x => x.Key is Object Obj && Obj.Name.Equals("Coal", StringComparison.CurrentCultureIgnoreCase))) { ShouldModifyStock = false; } } if (ShouldModifyStock) { bool HasChangedStock = false; List <ItemBag> OwnedBags = UserConfig.HideObsoleteBagsFromShops ? ItemBag.GetAllBags(true) : new List <ItemBag>(); // Add Bounded Bags to stock foreach (BagType Type in BagConfig.BagTypes) { foreach (BagSizeConfig SizeCfg in Type.SizeSettings) { bool IsSoldByShop = UserConfig.IsSizeVisibleInShops(SizeCfg.Size) && SizeCfg.Sellers.Contains(BagShop); #if DEBUG //IsSoldByShop = true; #endif if (IsSoldByShop) { bool IsObsolete = false; if (UserConfig.HideObsoleteBagsFromShops) { IsObsolete = OwnedBags.Any(x => x is BoundedBag BB && BB.TypeInfo == Type && (int)BB.Size > (int)SizeCfg.Size); } if (!IsObsolete) { BoundedBag SellableInstance = new BoundedBag(Type, SizeCfg.Size, false); int Price = SellableInstance.GetPurchasePrice(); #if DEBUG //Price = 1 + (int)SizeCfg.Size; #endif Stock.Add(SellableInstance, new int[] { Price, ShopMenu.infiniteStock }); HasChangedStock = true; } } } } // Add Bundle Bags to stock foreach (BundleBagSizeConfig SizeCfg in UserConfig.BundleBagSettings) { ContainerSize Size = SizeCfg.Size; if (BundleBag.ValidSizes.Contains(Size) && SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size)) { bool IsObsolete = false; if (UserConfig.HideObsoleteBagsFromShops) { IsObsolete = OwnedBags.Any(x => x is BundleBag BB && (int)BB.Size > (int)Size); } if (!IsObsolete) { BundleBag BundleBag = new BundleBag(Size, true); int Price = BundleBag.GetPurchasePrice(); Stock.Add(BundleBag, new int[] { Price, ShopMenu.infiniteStock }); HasChangedStock = true; } } } // Add Rucksacks to stock foreach (RucksackSizeConfig SizeCfg in UserConfig.RucksackSettings) { ContainerSize Size = SizeCfg.Size; if (SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size)) { bool IsObsolete = false; if (UserConfig.HideObsoleteBagsFromShops) { IsObsolete = OwnedBags.Any(x => x is Rucksack RS && (int)RS.Size > (int)Size); } if (!IsObsolete) { Rucksack Rucksack = new Rucksack(Size, false, AutofillPriority.Low); int Price = Rucksack.GetPurchasePrice(); Stock.Add(Rucksack, new int[] { Price, ShopMenu.infiniteStock }); HasChangedStock = true; } } } // Add Omni Bags to stock foreach (OmniBagSizeConfig SizeCfg in UserConfig.OmniBagSettings) { ContainerSize Size = SizeCfg.Size; if (SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size)) { bool IsObsolete = false; if (UserConfig.HideObsoleteBagsFromShops) { IsObsolete = OwnedBags.Any(x => x is OmniBag OB && (int)OB.Size > (int)Size); } if (!IsObsolete) { OmniBag OmniBag = new OmniBag(Size); int Price = OmniBag.GetPurchasePrice(); Stock.Add(OmniBag, new int[] { Price, ShopMenu.infiniteStock }); HasChangedStock = true; } } } if (HasChangedStock) { SM.setItemPriceAndStock(Stock); } } } } }
/// <summary> /// We'll say two container sizes are close if they're within a half pixel. /// </summary> /// <param name="size"></param> /// <returns></returns> public bool IsCloseTo(ContainerSize size) { return Math.Abs(Size - size.Size) < 0.5; }
/// <summary> /// TreeViewItem calls into this to provide its size in the stacking direction. We use this to compute /// the most common size. /// </summary> /// <param name="length"></param> internal void RegisterContainerSize(double containerSize) { bool found = false; ContainerSize newSize = new ContainerSize(containerSize); ContainerSize mostCommon = newSize; List<ContainerSize> sizes = EnsureContainerSizeCount(); for (int i = 0; i < sizes.Count; i++) { ContainerSize size = sizes[i]; if (size.IsCloseTo(newSize) && size.NumContainers < uint.MaxValue) { size.NumContainers++; found = true; } if (size.NumContainers > mostCommon.NumContainers) { mostCommon = size; } } // Only track the first 5 sizes we see. Container size could have a long tail and that ought to be sufficient. if (!found && sizes.Count < 5) { sizes.Add(newSize); } // Update the estimate ContainerSizeEstimateField.SetValue(this, mostCommon.Size); }
public static Transform CreateCratelike(Matter matter, float amount, Vector3 position, Transform parent = null, ContainerSize size = ContainerSize.Full) { Transform newT = Instantiate(EconomyManager.Instance.GetResourceCratePrefab(matter)); var rc = newT.GetComponent <ResourceComponent>(); rc.data.Container = new ResourceContainer(matter, amount, size); switch (size) { case ContainerSize.Quarter: newT.localScale = HalfSizeQuarterVolume; break; } AfterSpawnCratelike(position, parent, newT); return(newT); }