Jump to content

Recommended Posts

Posted (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 by Krougal
Posted

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.

 

 

Posted (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 by Brady_The
  • Thanks 1
Posted
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"} }

Posted (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.

2790_Mn3S4ILXqvK0elArZbG9.png.c338d828e22c67d29d50954fd6556527.png

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 by Brady_The
Posted
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.

Posted (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 by Krougal
Posted

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?

Posted (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 by Krougal
Posted

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

 

Posted

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.

 

Posted

"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.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.