Krougal Posted August 10, 2025 Report Posted August 10, 2025 (edited) Does anyone know how to work with the "freshHours" value of an item? I released a mod and a user pointed out to me that "FYI this resets the "perishable" time on hides, which is probably an unintended way to extend the shelf-life of these items." Is there a way for me to get the current value of the stack and pass it onto the new created hides? I searched through the assets to see if I could find an example of this, but came up with nothing. My Google-Fu was too weak to produce anything either. I'd only need to do it for the raw hide. Trying to keep the mod what I consider "fair and balanced" so I'd like to fix it, but I guess it isn't the end of the world if I can't. Edited August 10, 2025 by Krougal
Krougal Posted August 11, 2025 Author Report Posted August 11, 2025 Bueller...Bueller...Bueller... I take it no one has worked with this one. When you combine hides or food, the timer gets averaged. I just don't know where it is doing it from. I can't really think of any other instances in the game.
Echo Weaver Posted August 11, 2025 Report Posted August 11, 2025 My success on this subforum hasn't been impressive. The modding channel on the official Discord server is super active though.
Brady_The Posted August 11, 2025 Report Posted August 11, 2025 (edited) On 8/10/2025 at 8:30 AM, Krougal said: Is there a way for me to get the current value of the stack and pass it onto the new created hides? I can't say for sure that this will work for hides (its function might be limited via code), but you could try "copyAttributesFrom". (In Vanilla it is mainly used for armour repair recipes.) Edited August 11, 2025 by Brady_The 1
Krougal Posted August 11, 2025 Author Report Posted August 11, 2025 6 hours ago, Brady_The said: I can't say for sure that this will work for hides (its function might be limited via code), but you could try "copyAttributesFrom". (In Vanilla it is mainly used for armour repair recipes.) That did the trick. Thanks again! "output": { "type": "item", "code": "game:hide-raw-small", "quantity": 2, "attributes": { "label": "freshHours"} }
Brady_The Posted August 11, 2025 Report Posted August 11, 2025 (edited) 1 hour ago, Krougal said: Man, all the hours put in trying to figure out how to lower the timer on a piece of hide so I can try the recipe, I could have jut let one start rotting. I can't seem to target it to do a setattr in game, and I tried doing this: Hide contents { "ingredientPattern": "H", "ingredients": { "H": { "type": "item", "code": "game:hide-raw-medium" } }, "shapeless": true, "copyAttributesFrom": 'H', "width": 1, "height": 1, "output": { "type": "item", "code": "game:hide-raw-medium", "attributes": { "label": "freshHours" } [20]} }, To quickly make one to test with, but the game doesn't like that either. I will figure this out! Try "transitionedHours" instead. "freshHours" is the amount of time the hide will stay fresh (5 * 24 = 120). "label" is the wrong key to use. It's a variable custom to the crate. Or maybe not. I'd probably start with Quote This was nonsense. This is all just theoretical. I wish I could help more, but my extremely-soon-to-be-replaced-computer makes surfing an obnoxiously annoying past-time. I can pretty much forget about doing any modding. 7 minutes ago, Krougal said: That did the trick. Thanks again! "output": { "type": "item", "code": "game:hide-raw-small", "quantity": 2, "attributes": { "label": "freshHours"} } Or forget anything I wrote instead. If it works, it works. Edited August 11, 2025 by Brady_The
Krougal Posted August 11, 2025 Author Report Posted August 11, 2025 Yeah, transitionedHours is supposedly the amount of time it takes for the item to fully rot once it isn't fresh anymore.
Brady_The Posted August 11, 2025 Report Posted August 11, 2025 11 minutes ago, Krougal said: Yeah, transitionedHours is supposedly the amount of time it takes for the item to fully rot once it isn't fresh anymore. I don't think so. In the above screenshot I advanced the time by 23 hours 4 times. On the other hand I have no idea what these times are actually used for in the code.
Krougal Posted August 11, 2025 Author Report Posted August 11, 2025 (edited) 8 minutes ago, Brady_The said: I don't think so. In the above screenshot I advanced the time by 23 hours 4 times. On the other hand I have no idea what these times are actually used for in the code. It's "supposed" to kick in after the freshHours expire, but I haven't tried messing with it. I wound up taking one of my old trash saves and setting the food rot speed to 10x so I could make sure it was working right. Now I just need to decide how to handle the raw-hide pants & mantle recipe conflict on large and huge hides. Well, I forgot I left the game on the side with the inventory open and I had some start spoiling. I cut them and it copied the spoiled status over too, so I guess there is more to it with the freshHours, since I am not explicitly copying anything else over. Edited August 11, 2025 by Krougal
Krougal Posted August 15, 2025 Author Report Posted August 15, 2025 Ok, so now I noticed an issue where the newly created small hides will not stack with "natural" small hides. Kinda defeats the purpose of this mod. Anyone got any ideas?
Krougal Posted August 17, 2025 Author Report Posted August 17, 2025 (edited) Actually @Brady_The how did you get all that debug info? I went into dev mode and selected top 2 options, but I don't get all the info you were showing. Nevermind, Reddit to the rescue. Debug mode, and then hold shift while hovering over item. From that, I am thinking I don't need to copy either of these values, I'm thinking it is "createdTotalHours" and "lastUpdatedTotalHours" that need to be copied. Or maybe just the "transitionedHours" SMH! That is the prop you said to try, I didn't realize there were transitionHours and transitionedHours Edited August 17, 2025 by Krougal
Krougal Posted August 17, 2025 Author Report Posted August 17, 2025 Wow, it does not like this. "output": { "type": "item", "code": "game:hide-raw-small", "quantity": 2, "attributes": { "transitionstate": "createdTotalHours", "transitionstate": "lastUpdatedTotalHours", "transitionstate": "transitionedHours" } } Just putting the hide and knife in the grid causes an instant crash: Spoiler System.Exception: Cannot merge attributes! Expected attributeId 6 instead of 5! Existing: Vintagestory.API.Datastructures.TreeAttribute, new: transitionedHours at Vintagestory.API.Datastructures.TreeAttribute.MergeAttribute(TreeAttribute dstTree, String srcKey, IAttribute srcAttr) in VintagestoryApi\Datastructures\AttributeTree\TreeAttribute.cs:line 1025 at Vintagestory.API.Datastructures.TreeAttribute.MergeTree(TreeAttribute dstTree, TreeAttribute srcTree) in VintagestoryApi\Datastructures\AttributeTree\TreeAttribute.cs:line 1008 at Vintagestory.API.Datastructures.TreeAttribute.MergeTree(ITreeAttribute sourceTree) in VintagestoryApi\Datastructures\AttributeTree\TreeAttribute.cs:line 997 at Vintagestory.API.Common.GridRecipe.GenerateOutputStack(ItemSlot[] inputSlots, ItemSlot outputSlot) in VintagestoryApi\Common\Crafting\GridRecipe.cs:line 788 at Vintagestory.Common.InventoryCraftingGrid.FoundMatch(GridRecipe recipe) in VintagestoryLib\Common\GameContent\Inventory\InventoryCraftingGrid.cs:line 191 at Vintagestory.Common.InventoryCraftingGrid.FindMatchingRecipe() in VintagestoryLib\Common\GameContent\Inventory\InventoryCraftingGrid.cs:line 178 at Vintagestory.Common.InventoryCraftingGrid.OnItemSlotModified(ItemSlot slot) in VintagestoryLib\Common\GameContent\Inventory\InventoryCraftingGrid.cs:line 141 at Vintagestory.API.Common.InventoryBase.DidModifyItemSlot(ItemSlot slot, ItemStack extractedStack) in VintagestoryApi\Common\Inventory\InventoryBase.cs:line 492 at Vintagestory.Common.InventoryCraftingGrid.DidModifyItemSlot(ItemSlot slot, ItemStack extractedStack) in VintagestoryLib\Common\GameContent\Inventory\InventoryCraftingGrid.cs:line 146 at Vintagestory.API.Common.ItemSlot.OnItemSlotModified(ItemStack sinkStack) in VintagestoryApi\Common\Inventory\ItemSlot.cs:line 427 at Vintagestory.API.Common.ItemSlot.ActivateSlotLeftClick(ItemSlot sourceSlot, ItemStackMoveOperation& op) in VintagestoryApi\Common\Inventory\ItemSlot.cs:line 332 at Vintagestory.API.Common.ItemSlot.ActivateSlot(ItemSlot sourceSlot, ItemStackMoveOperation& op) in VintagestoryApi\Common\Inventory\ItemSlot.cs:line 292 at Vintagestory.API.Common.InventoryBase.ActivateSlot(Int32 slotId, ItemSlot sourceSlot, ItemStackMoveOperation& op) in VintagestoryApi\Common\Inventory\InventoryBase.cs:line 461 at Vintagestory.Common.InventoryCraftingGrid.ActivateSlot(Int32 slotId, ItemSlot sourceSlot, ItemStackMoveOperation& op) in VintagestoryLib\Common\GameContent\Inventory\InventoryCraftingGrid.cs:line 129 at Vintagestory.API.Client.GuiElementItemSlotGridBase.SlotClick(ICoreClientAPI api, Int32 slotId, EnumMouseButton mouseButton, Boolean shiftPressed, Boolean ctrlPressed, Boolean altPressed) in VintagestoryApi\Client\UI\Elements\Impl\Interactive\Inventory\GuiElementItemSlotGridBase.cs:line 988 at Vintagestory.API.Client.GuiElementItemSlotGridBase.OnMouseDownOnElement(ICoreClientAPI api, MouseEvent args) in VintagestoryApi\Client\UI\Elements\Impl\Interactive\Inventory\GuiElementItemSlotGridBase.cs:line 786 at Vintagestory.API.Client.GuiElementItemSlotGridBase.OnMouseDown(ICoreClientAPI api, MouseEvent mouse) in VintagestoryApi\Client\UI\Elements\Impl\Interactive\Inventory\GuiElementItemSlotGridBase.cs:line 754 at Vintagestory.API.Client.GuiComposer.OnMouseDown(MouseEvent mouseArgs) in VintagestoryApi\Client\UI\GuiComposer.cs:line 470 at Vintagestory.Client.NoObf.GuiDialogInventory.OnMouseDown(MouseEvent args) in VintagestoryLib\Client\Systems\Gui\Dialogs\GuiDialogInventory.cs:line 551 at Vintagestory.Client.NoObf.GuiManager.OnMouseDown(MouseEvent args) in VintagestoryLib\Client\Systems\Gui\GuiManager.cs:line 401 at Vintagestory.Client.NoObf.ClientMain.UpdateMouseButtonState(EnumMouseButton button, Boolean down) in VintagestoryLib\Client\ClientMain.cs:line 1962 at Vintagestory.Client.HotkeyManager.TriggerHotKey(KeyEvent keyEventargs, IWorldAccessor world, IPlayer player, Boolean allowCharacterControls, Boolean isGlobal, Boolean fallBack, Boolean keyup) in VintagestoryLib\Client\HotkeyManager.cs:line 403 at Vintagestory.Client.HotkeyManager.TriggerHotKey(KeyEvent keyEventargs, IWorldAccessor world, IPlayer player, Boolean allowCharacterControls, Boolean keyUp) in VintagestoryLib\Client\HotkeyManager.cs:line 394 at Vintagestory.Client.HotkeyManager.OnMouseButton(ClientMain game, EnumMouseButton button, Int32 modifiers, Boolean buttonDown) in VintagestoryLib\Client\HotkeyManager.cs:line 574 at Vintagestory.Client.NoObf.ClientMain.OnMouseDownRaw(MouseEvent args) in VintagestoryLib\Client\ClientMain.cs:line 1932 at Vintagestory.Client.GuiScreenRunningGame.OnMouseDown(MouseEvent args) in VintagestoryLib\Client\MainMenu\Screens\GuiScreenRunningGame.cs:line 339 at Vintagestory.Client.ScreenManager.OnMouseDown(MouseEvent e) in VintagestoryLib\Client\ScreenManager.cs:line 913 at Vintagestory.Client.NoObf.ClientPlatformWindows.Mouse_ButtonDown(MouseButtonEventArgs e) in VintagestoryLib\Client\ClientPlatform\Input.cs:line 203 at OpenTK.Windowing.Desktop.NativeWindow.OnMouseDown(MouseButtonEventArgs e) at OpenTK.Windowing.Desktop.NativeWindow.MouseButtonCallback(Window* window, MouseButton button, InputAction action, KeyModifiers mods) --- End of stack trace from previous location --- at OpenTK.Windowing.Desktop.NativeWindow.RethrowCallbackExceptionsIfNeeded() at OpenTK.Windowing.Desktop.NativeWindow.ProcessWindowEvents(Boolean waitForEvents) at OpenTK.Windowing.Desktop.GameWindow.Run() at Vintagestory.Client.ClientProgram.Start(ClientProgramArgs args, String[] rawArgs) in VintagestoryLib\Client\ClientProgram.cs:line 337 at Vintagestory.Client.ClientProgram.<>c__DisplayClass10_0.<.ctor>b__1() in VintagestoryLib\Client\ClientProgram.cs:line 133 at Vintagestory.ClientNative.CrashReporter.Start(ThreadStart start) in VintagestoryLib\Client\ClientPlatform\ClientNative\CrashReporter.cs:line 95
Krougal Posted August 17, 2025 Author Report Posted August 17, 2025 FFS! The crate label example is horrible. Considering that "label: paper-empty" doesn't even exist until you combine the crate with parchment, copy doesn't really make sense. This is actually setting label to paper-empty. As I understand now looking at it in debug mode. So it needs to be "transitionedHours: var" but possibly preceeded by "transitionstate" somehow. I don't know how to get a var either, since there is absolutely nothing about working with attributes I can find for debug mode and outside documentation is pretty sketch too. My Google searches are starting to refer back to my own posts, which is always amusing but not helpful. So I've puzzled out part of it, but still not there.
Krougal Posted August 18, 2025 Author Report Posted August 18, 2025 "output": { "type": "item", "code": "game:hide-raw-small", "quantity": 2, "copyAttributesFrom": "H", "attributes": { "transitionstate": { "createdTotalHours": null, "lastUpdatedHours": null, "transitionedHours": null }} } You'd think this would work, but no, it crashes the game on load. Neither ChatGPT nor Grok could help me. I'm about ready to give up.
Recommended Posts