I would recommend starting with Argus as an example because it's pretty simple: https://github.com/waywardgame/argus
#General mod help
1 messages · Page 1 of 1 (latest)
You see the @Register.item part?
That's what you want
The public itemArgus: ItemType; below it is marking a "field" for your registered item's ID to be injected into
Worry about the actual collecting of blood later, for right now just try to get familiar with creating an item using this syntax
@Register.item("bottleOfBlood", {
})
public itemBottleOfBlood: ItemType;
Start with this, add properties to the item description as necessary
You can use Debug Tools to give yourself a bottle of blood — make sure Debug Tools is installed and enabled, then use Alt + P to "inspect" yourself, and there's an "Add Item" dropdown that you can select your bottle of blood in
This is all you should need, besides putting your item texture in the right place
Should be static/image/item/bottleofblood.png
If you want your item to be able to appear on the ground, you'll also need to provide an _8.png version (8x8)
https://waywardgame.github.io/interfaces/game_item_IItem.IItemDescription.html Here's documentation on everything that can go into the item's description
Documentation for Wayward Types Viewer
should the class be named after the mod or the item/items?
Whats it just kindof a container?
Yeah, it's basically just the "scripts" container for your mod
You can put "event handlers" there, so that you can run code on specific events happening, like for example, the player doing an action, or pressing a button on their keyboard, or an item being destroyed, etc
Can I just auto import stuff as I write?
Argus has all these but I shouldnt need all this to import the item
yeah, you shouldn't need most of those
When you type something and there's a red squiggle under it, hover over it and see what the error says
If it says something like this, then you need to import something
You can probably ignore that for now
It's a little complicated
It starts mattering when you're registering multiple things and need their descriptions to reference each other
Focus on just getting the item working for now
okay
the code looks good, how do I call the sprite? I dont see where argus references a png
That "bottleOfBlood" in the code I gave you is setting the name of the registered item. All images in the game are loaded via paths made with those, and sometimes also with the mod name included
For items it's always static/image/itemname.png
It's converted to lowercase and stripped of special characters for the path
so does the capitilization of letters have to match between my png and the code?
oh
so it doesnt matter
yeah
you could actually make the registration name something crazy like "BoTtLE. $%&@#$%@#$of () BLOOD" and I think it would still turn into the string bottleofblood.png lol
With that code it should load in then and be spawnable with the debug tools?
yep!
alright thanks! let me try
if there's any issues it should also warn you about them in the console
so you might want to have that open
(toggle developer tools in the developer section of options, if you haven't opened it before)
the file says it failed to load the mod
oh
There should be an out folder created
lmfao
🤪
In general you don't want to copy files from other mods
Use the wayward +mod create commands
They're set up to help give you a template
okay, argus doesnt have one so I wasnt sure
It's because when you download a mod it's not set up for development
It's set up to be used
I see
It can be set up for both at the same time
When you publish the mod later, it'll only publish the files that allow it to be used
Check the log, there's still something wrong
found 0 errors watching for file changes...
Typescript not erroring doesn't mean there's not something wrong still
Theres no errors
There is definitely going to be a mod loading error
Since that's what the tooltip says
how do I see that
It will be somewhere in the log
Open the Developer Tools and look through it
Some tips to make debugging faster:
- In
launch_options.json(in the Wayward steam folder), set"devtools"totrueinstead offalse. This will make it always open the Developer Tools on every launch - Press F5 to reload the game without having to close it and click Play in Steam again. (Ctrl + F5 reloads & opens most recent save.)
theres no mod.js file it looks like?
What file do you have instead?
Do you have any files?
Send me your mod.json and your tsconfig.json
I have a feeling you're just using argus's tsconfig.json which is not going to work
If you want, you could try deleting the tsconfig.json and running ../../bin/wayward +mod create . +script in the VSCode terminal, which should recreate the tsconfig.json without touching any of the rest of your files
Idk why they sent as embedded code sorry
the mod json was in there idk what the issue is
You need to change your mod.json to say "file": "out/Bloodrites"
ohhh
Because you renamed the .ts file it changed the output to Bloodrites.js instead of Mod.js yeah
I thought that looked weird
Or well I guess you were probably referencing argus
Yeah I was lol
The initial setup is always the hardest part for first time modders
Should get a bit easier from here I think. More complicated stuff, but also easier to figure out what the problem is
Anytime you jump into something new its always a process
Im glad you guys take the time to help
many devs do not
A big part of the fun of making a game is helping people experience it how they want to experience it. If that includes modifying it, I'm all for helping there where I can, too
It's why every so often we do things like add game options for things that were done by old mods that aren't maintained anymore, or we decide to change how something works so that people stop feeling like they need to mod it, or when a technical change makes one kind of mod a whole lot more difficult, sometimes we just straight up add support for it into the base game in a way that allows a mod to just toggle it on
I have examples for all three of these
The way doors work now. The fact that in Runekeeper due to the container UI rework, mods that showed item stacks on tiles as container UI no longer worked, so I just straight up added support for those to the base game so that mods can just turn it on
All the work you guys do shows. The game has come such a long way
I have progress here but no image
I expected it not to have a title because I never gave it one
Im still not understanding how im supposed to name it though
That’s done with the lang/english.json file
Sorry for going afk had some irl stuff going on
Argus will have an example of how that works
I'm guessing now you want to have glass bottles have a collect blood action that you can use on puddles of blood?
If you do I can give you a place to start in like 30 mins, have to brb again
Yeah, I'd like to try doing that next
No worries. I'll probably be here.
Okay so
There's a couple new things you'll need to learn for this
- Creating a custom action
- Registering your custom action to an action type
- Injecting into vanilla descriptions (to add your custom action type to the glass bottle description)
That will make it so you can right click on a glass bottle while facing a puddle of blood and it'll allow you to use your "Collect Blood" action or whatever
Coincidentally, Argus contains the first two of those things
With its action "See All"
To start with, copy a blank version of its action into your Mod class. You'll need some extra things on it that Argus didn't need so I'm going to give you a slightly modified version
@Register.action("CollectBlood", new Action(ActionArgument.ItemInventory)
.setUsableBy(EntityType.Human)
.setCanUse((action, item) => {
// this handler will be for returning whether the action is usable right now.
// ie, if the player is actually facing blood.
// in multiplayer, this code happens in all of the following situations:
// - when the player is hovering the mouse over the action,
// so that the action can display the red text if you can't use it
// - when the player clicks on it when it's assigned to an action slot.
// if it's not usable in this situation, the client doesn't even send the attempt to the server.
// - when you actually use the action, it calls this on both the clients and the host/server,
// as one final check to make sure this is legal.
})
.setHandler((action, item) => {
// this is called when the player actually attempts to collect the blood.
// in multiplayer, to keep the clients and the host/server in sync, this code happens for both.
}))
public readonly actionCollectBlood: ActionType;
This actually takes care of 1. and 2., we just need to fill in the canUse and handler
It's to prevent use on items that are like in a chest or on the ground
There's also ActionArgument.ItemNearby (accepts any nearby item as well, ie chests/ground) and ActionArgument.Item which is any item, even if it's halfway across the map (more useful for debug-type actions)
Thats a little confusing that its called inventory
just so I can use actions with it?
I'm confused
me too lol
We're saying that this action will require an item that's in your inventory in order to be called
Actual verification that the item passed in can collect blood will be in canUse
No, no worries, I probably phrased something wrong
Miscommunications are common for this kind of thing, there's a lot going on
Do you want to add the action to glass bottles now or do you want to actually implement the action itself first?
If we add it to glass bottles first then you can see it appear in the right click menu in-game before starting to implement it
I think you might need to add return { usable: true }; to the end of the canUse handler for us to do that though
Looks good, will need the bit I said in my last message in the canUse for now though
Nice!
but the action is a string
?
Action:ModBloodRitesCollectBlood
Oh does it show up on literally every item?
That's funny I didn't know it worked like that
No, just those two. Shouldnt it just say "collect blood"
or is that done in the lang
Wait why are you adding collect blood to containers that already have blood?
oh true
Yes it's done in the lang, look at how Argus translates its SeeAll action
It's in an "action" dictionary
Action:ModBloodRitesCollectBlood is telling you Dictionary:TranslationName
do I just call the normal glass bottle and add the action to that?
I'm not sure what that means, probably not. There's something new you have to do for that
like how do I give a preexisting item an action
Yes I know what you want
inject into vanilla i guess
ok
Okay I'm pretty sure you should have access to this, I just checked when it was added I think it was before we switched over to working on Runekeeper
// an "override" is for injecting into vanilla descriptions
@Register.override(() => ({
// the "object" is the thing you're injecting into.
// you will be replacing a single property inside the object with a new value.
// when your mod is disabled, it will automatically be un-injected and reset to the original value.
object: itemDescriptions[ItemType.GlassBottle],
// here we're injecting into "use", ie the list (array) of actions on the bottle
property: "use",
// here we say what value we want it to have. we're giving it a brand new array of actions
value: [
// this line *looks* complicated, but in actuality it's pretty simple.
// all it's doing is including everything that was already in the vanilla glass bottle "use" array.
// the ?? [] bit is just saying "if there wasn't a use array, make a new one."
// it basically just stops it from being like:
// "aaaaa i just tried to put everything of <undefined> into this array, that doesn't make sense!!!!!"
...itemDescriptions[ItemType.GlassBottle].use ?? [],
// now we add our action.
Registry<BloodRites>().get("actionCollectBlood"),
],
}))
public readonly glassBottleDescription: IItemDescription;
Im trying to import IItemdescriptions but its not working
I tried using the directory from the guide you sent
When auto-import doesn't work, you'll have to look up the path on the wiki
I believe the path you want is game/item/IItem
https://waywardgame.github.io/interfaces/game_item_IItem.IItemDescription.html
Documentation for Wayward Types Viewer
how do I auto import
If that doesn't work try game/game/item/IItem
Sometimes when you type a name it'll suggest importing it
It'll be just one of the little suggestion popups as you type
It'll say "auto import from xyz" or whatever
Sometimes that doesn't work though
auto import looks something like this, though ignore these paths, they're runekeeper ones (we changed the way some stuff works)
The IItemdescriptions works it says its value is never read
how do I embed again?
code
```ts
// paste code here
```
import Mod from "mod/Mod";
import Register, {Registry} from "mod/ModRegistry";
import { EntityType } from "game/entity/IEntity";
import { Action } from "game/entity/action/Action";
import { ActionType, ActionArgument } from "game/entity/action/IAction"
import { IItemGroupDescription } from "game/item/IItem";
import { ItemType} from "game/item/IItem";
export default class BloodRites extends Mod {
@Mod.instance<BloodRites>("Glassbottleofblood")
public static readonly INSTANCE: BloodRites;
@Register.item("Glassbottleofblood",{
})
public itemGlassbottleofblood: ItemType;
@Register.item("Clayjugofblood",{
})
public itemClayjugofblood: ItemType;
@Register.action("CollectBlood", new Action(ActionArgument.ItemInventory)
.setUsableBy(EntityType.Human)
.setCanUse((action, item) => {
return { usable: true };
})
.setHandler((action, item) => {
}))
public readonly actionCollectBlood: ActionType;
}
@Register.override(() => ({
object: itemDescriptions[ItemType.GlassBottle],
property: "use",
value: [ itemDescriptions[ItemType.GlassBottle].use ?? [],
Registry<BloodRites>().get("actionCollectBlood"),
],
}))
public readonly glassBottleDescription: IItemDescription;
- You have not imported the name
itemDescriptions - You imported
IItemGroupDescriptioninstead ofIItemDescription
https://waywardgame.github.io/variables/game_item_ItemDescriptions.itemDescriptions.html this is itemdescriptions
Documentation for Wayward Types Viewer
game/item/ItemDescriptions
you also removed the ... here
you also put @Register.override outside of your Mod class
I think that's everything

Yep it works! 🙂
Up to you 
neat
I would recommend white for UX — the icons look how they do so that a player seeing an icon can quickly be like "oh that's an action icon. that's a skill icon" etc
But if you wanna do something different I can't and won't stop you 
If you want to know where to put the icon, look at the warnings or errors in the Developer Tools console
Should give you the path it's trying to load somewhere
something like static/image/ui/icon/action/something.png maybe?
yep!
Actually displaying textures are a mixture of:
- The game canvas (the terrain, trees, doodads, the player, creatures, the fog, etc), which was all written from scratch, mostly by Sassafrass afaik but with lots of stuff maintained/updated by Spacetech, and a tiny amount of stuff by me and Drathy
- The iconography in the UI — all the UI, really — is all displayed like a webpage. It uses the same technologies. HTML, CSS, etc. So it's kinda just having a script put an element on the screen and pointing it to the path it thinks your resource will be at
quite smalll right? 8x8?
if it helps here's all the base game action iconography
I think that's all the time I have to help for the day, I can help you with the collect blood action tmrw
Is this your first time doing any programming?
If so probably good to do it without being overwhelmed by all the other stuff we've already done
No not quite my first. I do stuff with godot mostly
Ah gotcha!
Nice!!
Thanks again for your help today. I should probably head to bed myself 🤣
No worries!
Feel free to ping me here if there's a good time tmrw, I can be available
I'd love to continue learning tomorrow. I will talk to you then 😄
My bedtime is in like 2 hours (11pm) so our availability seems to line up decently well
Oh yeah thats great. It's 5am for me; I regularly stay up late.
Hey Chiri, I've been working more by myself on trying to complete the recipe for the bottles of blood and I think I'm definitely getting somewhere but I had a question about one thing:
The "1, 1" at the end; what does that mean?
They seem like random parameters to me , does it correspond to a specific item type?
Hover over RecipeComponent or ctrl click on it and see what the second and third parameters are called
If you still don’t understand give me a ping
I may have fallen back to sleep tho so actually I’ll check regardless in like an hour maybe idk
I cant figure out how to put blood in the recipe, its not in the itemtypegroup or anything only liquid and liquid container. Why wouldn't all "Liquid" be under the same umbrella?
You’ll have to register a new item group for blood
If you want it to be classified as a liquid as well you’ll have to also add it to the liquid group
The code can’t just randomly guess what your item is, gotta categorise it 
to register an item group you’re looking for @Register.itemGroup
Should take a name for the group + a list of things in the group
Or you can add items to the group via the group property on the item description
Either works
Either way to reference the other thing you’ll have to use that Registry get syntax again
Like what you did to get the action type for use
You’ll already need the item description property group to add it to the liquid group so probably want to do it that way
You shouldn’t need any other parameters there
Ctrl click on itemGroup and send me a screenshot of it
Sorry i’m just still on mobile
It says name: string and description:
the item group perameters?
Yeah
To hopefully make it easier for you to figure stuff like this out in the future
It’s okay it takes time to learn this stuff
Okay, so you need a name, which you have, which is a string. You also need an IItemGroupDescription. We need to figure out what that means now. Ctrl click on that
Can you screenshot it and send it to me? And we’ll figure out what you need from that
I’m not sure yet
oh
I haven’t messed with groups in a long time and usually am looking stuff up while helping and i’m on mobile atm
I don’t mind helping I just need screenshots of types
And I’ll walk you through my thought process
Okay perfect
So a couple things
see how this says it’s an interface?
An interface describes an “object”
Basically a generic container of any number of properties
The item description is also an object
The thing we return in the Register.override is also an object
It’s specifically the stuff that looks like this
{
property: value,
other property: other value,
}
In your code
So our goal is to, for the second parameter in itemGroup, make an object that matches what IItemGroupDescription is saying
Let’s look at the properties in it
See how the first one, default, has : but the other two have ?: ?
That means the first one is required for an object to match, but the other two are optional
So all we need to do is make an object that has a default property in it
The variables right?
It’s the entire thing I sent you there
That itself is an object
{} is an empty object
right
So what you want here is
{ default: <we need an item type to put here> }
So to explain what that is
You know how some recipes use item groups as ingredients?
And you know how crafted items can be disassembled to get back the components that crafted it?
If a player receives a naturally created item that is something that can be crafted from item groups, then disassembles it, each item group ingredient of the recipe gives its default item
So like say a creature drops, or a merchant sells, something that you can craft with an item group. And then you disassemble it. And it gives you the default items that make it up
So every group in the game as a result is required to have a default item
oh alright
Basically in your case you just need to choose one of your containers of blood to return
Once you’ve decided, you’re looking for that Registry get syntax
The same way we added your custom action to the use array
I'll start with the glass first
so
I'll want it to return to being a glass bottle right?
well
Register.itemGroup(“Blood”, { default: Registry whatever blah blah (“itemGlassBottle”) })
I can never remember the syntax lol
Don’t copy that it has smart quotes
lol
If you crafted something with a different item in a group it’ll return the same item when its disassembled
It’s only when its a natural item that it returns defaults
So you just choose whatever for the default
Would probably have an easier time just copying the existing example we have for that one 
Registry<BloodRites>().get("itemGlassBottleOfBlood")
or whatever
(I just moved to pc)
that is me not knowing the syntax
oh
When I add that theres another issue... ugh
Because remember the itemGroup definition said it was looking for the parameters name: string, description: IItemGroupDescription. There's no such thing as labelling parameters when you're calling a function, so you just need to do itemGroup(string, IItemDescription)
ie, itemGroup("Blood", { default: Registry<BloodRites>().get("itemGlassBottleOfBlood") })
Show me the issue
Do you have the field after it?
public itemGroupBlood: ItemTypeGroup;
?
Because every time you use a @Register decorator like this, you need to be giving it a field to inject the registration into
This is horrible ive been doing this all day with nothing to show for it 🤪 🤪 🤪
Look for your glass bottle field
The field is only the line that starts with public
It's not complicated it's just stuff you're not familiar with
That's normal when you're learning something new
If you start typing a string in the .get() it'll also give you a suggestion for the right field name
I have a feeling you're just getting lost though because the stuff hasn't really been sticking
Feeling like syntax soup or whatever
looks like last time you sent me the code it was "itemGlassbottleofblood", you didn't capitalise every word like I'm used to
Nice!!
Now we just need to add your two containers to the group
Once we do it for one we can just copy it to the other
So looking in the documentation again
https://waywardgame.github.io/interfaces/game_item_IItem.IItemDescription.html
Documentation for Wayward Types Viewer
One of the fields listed at the top is group
Clicking on it takes you to this
https://waywardgame.github.io/interfaces/game_item_IItem.IItemDescription.html#group
Documentation for Wayward Types Viewer
So inside the item description — remember the description is the object {} inside the @Register.item decorator call
We need to add a group property
It will be a list of all the groups we want the item to be in
@Register.item("Glassbottleofblood", {
group: [
// we can put base game groups here
// or reference groups that we've registered with the same Registry().get syntax
],
})
public itemGlassbottleofblood: ItemType;
So you can just directly list Registry<BloodRites>().get("itemGroupBlood") inside that group list/array.
This is saying "when my itemGroupBlood is registered, put its ID here"
Other groups you might want to add:
ItemTypeGroup.ContainerWithLiquid,
ItemTypeGroup.FireExtinguisher,
ItemTypeGroup.Liquid,
what does countainer with liquid do
lemme check
Actually you can skip that one
It's only used in consume item checks
So unless you're also adding vampirism probably not necessary

Perhaps once I get a better grasp... but I wont spoil.
alright so thats done
but how does it know what blood is
Not sure what you're asking exactly
if I face blood on the ground
How does the game know that the blood I just added is there to gather
Oh, for your collect blood action? We still have to finish that
oh
We need to add a canUse handler that will return that the action is usable if you're facing blood, and that it's not if you're not facing blood (with a message saying that you're not facing blood)
I keep getting ahead of myself my bad haha
There are a lot of moving parts in the mod you want to make
So yeah it's going to be a very steep learning curve
It'll be okay though it's trial by fire and then once you pass it should be a bit easier
You'll have your own code as an example, then
nods
Okay so as a reminder this is what I sent yesterday, sending it again because I think you took out all the comments
@Register.action("CollectBlood", new Action(ActionArgument.ItemInventory)
.setUsableBy(EntityType.Human)
.setCanUse((action, item) => {
// this handler will be for returning whether the action is usable right now.
// ie, if the player is actually facing blood.
// in multiplayer, this code happens in all of the following situations:
// - when the player is hovering the mouse over the action,
// so that the action can display the red text if you can't use it
// - when the player clicks on it when it's assigned to an action slot.
// if it's not usable in this situation, the client doesn't even send the attempt to the server.
// - when you actually use the action, it calls this on both the clients and the host/server,
// as one final check to make sure this is legal.
})
.setHandler((action, item) => {
// this is called when the player actually attempts to collect the blood.
// in multiplayer, to keep the clients and the host/server in sync, this code happens for both.
}))
public readonly actionCollectBlood: ActionType;
So right now we're working on the first one, this bit
The typical way a canUse handler is written is:
- A series of checks, seeing each one finding a reason why it's not possible to do the action
- When it's not possible, exiting from the canUse handler by returning the message why it's not usable
- Finally, when all checks have passed, that means that it is usable, so we then return that it is usable
- Along with this, we also return custom data that our action needs to operate. In this case, since multiple puddles of blood can be on the same tile, we should return the specific puddle of blood that the action will collect
We're going to start a bit slow by just assigning some variables
const player = action.executor;
The entity that executed an action is always put inside action.executor, so just for convenience we'll put them in a variable
const tile = player.facingTile;
The tile we're interacting with is the tile the player is facing, so we'll save a reference to that
Does it matter where I put these constants or does everything just compile as it is?
Put them in order in the canUse handler
oh okay I see
There shouldn't be any red squiggles, just a yellow squiggle under tile because it's not used yet
Now that we have those variables, in order to get the list of "Tile Events" on the tile, we access tile.events
In your case though, you specifically want a tile event that is TileEventType.Blood, so we're going to have to filter down the events into ones of the correct type
Don't put this in your code yet
const bloodTileEvents = tile.events
.filter(event => event.type === TileEventType.Blood);
This is saying:
- Given the list of all the events on the tile
- Filter down that list into just the ones that satisfy the given function
- The function we give it only returns
true(ie, that it should keep the event) whenevent.typeisTileEventType.Blood
- The function we give it only returns
Does that make sense so far?
Yes the function oly returns true when the specified tile event type is correct
only*
Yep
Okay so now that we have a list of tile events that are blood, we just need to get the first one. And that's the one we'll be using for collecting. This code can go in your canUse handler
const blood = tile.events
.filter(event => event.type === TileEventType.Blood)
.first(); // use the first from the list of blood tile events, or `undefined` if there's no blood
So now we have something that we can actually check — this blood variable will either be a blood Tile Event, or it will be undefined if there wasn't any blood
In the case of undefined, we'll need to exit out of the can use handler with a message for the player saying there's no blood
if (blood === undefined) {
return {
usable: false,
// our message will go here.
// unfortunately first we have to register it, and then do something new to access it.
// for now, we'll use a placeholder message:
message: Message.NothingHereToFill,
};
}
Once you've put that in your can use handler, can you show me what it looks like so I can verify it's correct?
https://waywardgame.github.io/ If auto import isn't working, you can always click on the magnifying glass button here and search for it to find the correct path
Documentation for Wayward Types Viewer
it's this second one my cursor is over
Documentation for Wayward Types Viewer
I think I might be misunderstanding what your error is. I'll have an easier time understanding it if you show me the error rather than rephrasing it
Ahhhh
Okay in that case make the .filter line start with ?
?.filter(
That means "if the previous thing was undefined don't do the rest of this line and make the entire expression undefined instead"
Which makes sense — if there's no events, it should be undefined anyway since that's what we're checking for
Did you put this in your code too?
should it be on message
I'm not sure what that means
If you send me what your code looks like right now I can show you where to put it
Everything I've sent you should go in order though
should be
// initial variables
// getting the blood tile event, or undefined if there isn't one
// returning that the action can't be used if blood is undefined
// returning that the action can be used
okay 2 things
- you still need to import
Message - you have the order wrong. you have:
// returning that the action can be used (this needs to be last)
// initial variables
// getting the blood tile event, or undefined if there isn't one
// returning that the action can't be used if blood is undefined
Wince you're returning that the action can be used at the top, the game will never run the rest of the code, it will always be like "yep seems good!" If you saved the file right now, typescript might even automatically remove the rest of the code because it never gets used lmfao
okay TBF! i wasn't referring to what i sent last night when i said that 
wait do you still not understand what's in the wrong spot?
it's the return { usable: true }; at the start
that should be at the end
Im so confused
.setCanUse((action, item) => {
const player = action.executor;
const tile = player.facingTile;
const blood = tile.events
?.filter(event => event.type === TileEventType.Blood)
.first();
if (blood === undefined) {
return {
usable: false,
message: Message.NothingHereToFill,
};
}
return { usable: true };
})
no worries 
I will say, with a mod with as much going on as yours having a bit more programming experience would probably help
I'll help you get it done and hopefully you are picking some things up
But I have a feeling you're going to get stuck on things like this quite a few times 
What can I use to practice?
Any scripting language, really
Any language that requires using an IDE like vscode
Which definitely looks similar to typescript
Looks cool honestly
I like it, I have another side project going on that haha
I think the biggest difference in Typescript is the ordering of things and the fact that there's a lot more instances of putting things inside things
Like for example classes in gdscript looks like a per-file thing?
whereas in ts you can have as many in a file as you like, they're all inside {}
While Im doing this theres nothing visually that tells me x and y aside from you, we're not using a game engine I think is the main difference
This is like homebrew lol
Not sure what you mean
Its kinda hard to explain
If you hover over things it should be giving you tons of info about what's there
And if you ctrl click on things you can look at the inner definitions
in godot for example
I can drag an image into the engine into a sprite node, give it a collisionshape (or not) and its in
adding stuff visually is very simple
oh, yeah
well that i knew 
i thought we were more talking about the gdscript part though?
In Gdscript the entire doc is included as a sidebar with a hotkey
You still have to script regularly though, yeah
whatever functions you wanna add
How often are you making like actual functions and classes in gdscript? or are you just doing things like visually clicking on a dropdown and saying "call this gdscript function when this happens" and it automatically calls one very small isolated block of code that you've written
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html like how often do you have gdscript files that have as much going on as this
Godot Engine documentation
GDScript is a high-level, object-oriented, imperative, and gradually typed programming language built for Godot. It uses an indentation-based syntax similar to languages like Python. Its goal is to...
this looks very familiar to me, and it's stuff i can get behind, esp. the fact that it simplifies class syntax down into what just looks like a normal script context
you just know that it's a class because it's a single file representing the class
i'm wondering whether there's cases where you just kinda define a function visually in godot and so all you have is like this, but maybe even simpler than this since this is showcasing a bunch of possible syntax
anyway.
fwiw we do want to do things like json modding and a visual editor eventually
it's just that that will take a lot of development time
and it's development time specifically centred on me (since i'm the ui developer) and i am generally swamped
Sorry I was trying to set something up to show you my project lol
aw it didnt play his animations
obs didnt record the debug window lol
There we go
At the end of the day all the modding stuff is secondary
It'll come when and if it comes
Until then I don't mind learning, maybe you could give me a bit of an easier mod idea to do as a challenge. The feeling that comes along with code working is unmatched
At this point you're pretty close to having something that works
As difficult as some of the concepts can be for me to grasp I think its fun
You might as well finish this
I wish there was a way to just force myself to understand lol
I think if you want a good thing to learn, just adding variants on existing items or tweaking numbers on existing items are going to be your best options for getting really familiar with the way registering new stuff and referencing new stuff works
Basically, mods that primarily use @Register.item and @Register.override and that's it
Just getting familiar with writing those over and over and tweaking them?
Pretty much yeah
The more you do it the more you'll run into weird typos and things you need to import and weird errors and stuff, and the more you'll understand how to get yourself out of weird states and errors you don't understand
You have to fail repeatedly doing the simplest level of things for your mind to really wrap around it completely
And unfortunately the simplest level of thing in wayward is not the easiest
How long did it take you to fully understand? I feel like you could really teach this stuff lol
I started learning programming at like 10 years old and I'm 27. I started working in C# and Java around 17, and JS & TS at like 18-19. I joined the Wayward team at 20 or 21 I think. I set up the current modding system about 4-5 years ago, when I was 22-23
oh okay you're around my age. Im 25
It does tend to be harder to learn this stuff the older you start — mostly just because it's harder to get the sheer number of hours to catch up, and it starts to feel impossible to invest as much time as you need into it to not be behind anymore — but in actuality, everyone can do it
It's the same as any skill
Yeah, I didnt start at 10 unfortunately, it's been an off and on thing for me since like 14 but I really enjoy it
I've done so many little unfinished things with so many languages
But sometimes I feel like I still have the most basic understanding
There are lots of people who think "coding is magic I can never do it" but yet they don't think the same about other languages, like spoken ones. And they also don't think it about other kinds of problem solving, like sudoku and crosswords and puzzle games with fresh new kinds of mechanics. You just have to be ready to be stuck on a problem for a long time, making sure you're really learning and understanding why something didn't work each time you mess something up. And you have to be committed to it long-term, too. Committed to being okay with messing up repeatedly and learning from those mistakes so that you can really wrap your head around it.
I've been giving the answers to most of the stuff you've run into, which does make it harder for things to stick, but at the very least it should make it a bit easier for you to be like "wait I've run into this exact problem before" and then figure it out your own way next time
Yeah, I should be able to at least look back on it as a reference
"When this happened it needed to be imported" etc
Yep
Whenever you're using something that starts with a capital letter, that you didn't make, you need to import it
There are very few things that you'll need that don't start with capital letters
The only examples I can think of are the descriptions like itemDescriptions
mhm
Okay anyway
Did you update your .canUse handler to the one I gave you?
If you test that in-game it should now only allow you to use the action when you're facing blood
Yes
let me see
Zero errors, running wayward...
ey!
it does work
high-five
lol
Nice!!
Now all that's left is the action handler
We need to make it actually turn your container into one of blood
And also remove the blood tile event
right so it disappears
So the other thing canUse handlers do, to prevent you needing to do the same checks or find the same things multiple times, is they can give stuff to the handler itself
In this case we want to give the blood tile event from the canUse handler to the main handler
In order to do that we need to tell .setCanUse that the resulting usable: true object will also come along with blood: TileEvent
To do that, we're going to make our own interface
interface ICollectBloodCanUse extends IActionUsable {
blood: TileEvent;
}
This needs to be above your class
Between it and your imports
You will need to import both IActionUsable and TileEvent probably
If they don't auto import try searching for them with the magnifying glass on the docs website I linked previously
IActionUsable looks easy to find. TileEvent is a bit harder, so I'll give you that one — I had to try adding a slash in the front to find it, since there's a bunch of other files that have a tileEvent in them it shows those first for some reason.
It let me auto import
Oh nice
yee
Okay in that case
If you ctrl + click on IActionUsable you can see what's defined inside it
That's what .setCanUse expects by default for the action being usable
Our interface extends'ing it means that it's a combination of all of the potential properties in IActionUsable, plus any properties that we define
interface and namespace?
It should have the properties usable, usableOnMove, and displayLevel inside of it
Okay cool
So now that we have that interface we have to tell .setCanUse to expect that interface as the output instead of just the normal IActionUsable
The initial line should now be
.setCanUse<ICollectBloodCanUse>((action, item) => {
It should make it get REALLY angry
Because you're not returning a blood: TileEvent along with usable: true yet
Lastly, we change the last line of the can use handler to return { usable: true, blood };
put that after the blood. tileevent?
.setCanUse<ICollectBloodCanUse>((action, item) => {
replace the existing .setCanUse line
<ICollectBloodCanUse> is just being added to it
that's all
It's something called a "type parameter"
should just be this now
that will make it not error at the top anymore
I'm sorry I need to see the actual code to know what these are referring to
sure
I straight up never use the problems panel personally
The lack of context makes it too hard to use imo
lol why did you put that return inside the interface
it's for the canuse handler
the interface is just for describing what an object looks like
return means nothing in that context
return is for functions
.setCanUse is being given a function
that is the can use handler
We told .setCanUse what the object we're returning is going to look like
Now we need to actually return an object that looks like that
Aha
That return statement I gave you is to replace return { usable: true };
got it
Nice 
:p
Okay so
Im a little slow Hah
Nw
After all of that now your main handler will have access to that same blood tile event
It will be available in action.use.blood
const blood = action.use.blood;
For now, let's just remove the blood because it's simpler
Don't use any of the following code, it's examples again
This grabs the current island that this blood is on. It's basically like a "world" if that makes sense
const island = blood.island;
This gets the full list of tile events:
const tileEvents = island.tileEvents;
This removes the given tile event from the island:
tileEvents.remove(blood);
To simplify this line, we can instead do
blood.island.tileEvents.remove(blood);
So your entire main handler atm should be:
const blood = action.use.blood;
blood.island.tileEvents.remove(blood);
Also, I have no idea why you can't just do blood.remove(), I guess we just never added support for that for some reason
Would be much less confusing lol
wait how is that simpler? lol
instead of just having tile events
Because it's all on one line instead of storing a bunch of variables that only get used once
If you think it's more understandable to save every variable you can
oh so if I didnt do that they'd have to be included seperately?
it's either
const blood = action.use.blood;
blood.island.tileEvents.remove(blood);
or
const blood = action.use.blood;
const island = blood.island;
const tileEvents = island.tileEvents;
tileEvents.remove(blood);
Up to you which you prefer
When you have that in your main handler give it a test and it should remove blood tile events
It won't be turning the glass bottle into one of blood yet, of course, we still have to implement that
do I change the already existing blood constant?
the main handler, not the can use handler
.setCanUse(() => {
// you already did this
})
.setHandler(() => {
// put new stuff here
})
oh that's weird
Oh
We changed the way that part works in runekeeper my bad
const canUse = action.canUse();
if (!canUse.usable) {
return;
}
const blood = canUse.blood;
blood.island.tileEvents.remove(blood);
See you can tell we're still trying to simplify this stuff 
It's a slow process
Nice!!
Usually stuff vanishes right away, no?
After removing
oh
Also should probably add action.setPassTurn()
The vanilla GatherLiquid action also does action.setDelay(Delay.LongPause);
set pass turn? does that just tell it to pass a tick?
yeah
yeah
it's not technically necessary but i'd recommend it
you can run into some weird bugs by missing semicolons sometimes

So all that's left now is converting the item into your blood variant
For now let's just make this action always turn the item into the glass bottle of blood
After that works we'll add support for respecting the input container type
Yeah I didnt do anything for clay yet
I figured I'd finish the second one on my own once we're finished
try to use what I've learned
They'll be using the same action so I need to help a bit with it
You'll be able to copy the glass bottle description and override stuff though for other container types
Okay so we unfortunately have to do one new thing
As usual lmfao
haha
So technically, that action? That's actually not inside of your Mod class
It looks like it is, but technically it's not
So it doesn't actually have access to the stuff that you've registered
And that Registry().get() thing doesnt work here, either, unfortunately — the way that works is it's secretly a placeholder value that gets turned into the real value on mod initialisation. So using that placeholder value somewhere else makes no sense because other places in the game don't know how to turn the placeholder value into the real ID
So instead, we need to set up a new way for this action to get access to your Mod's "instance"
So far you've been registering a whole bunch of new things and their IDs have been getting injected into properties on your mod instance. That's why we need the instance, it allows you to get at all those IDs
Argus actually does this I think
Yeah it does
It's the @Mod.instance thing
@Mod.instance<BloodRites>()
public static readonly INSTANCE: BloodRites;
Should work to do this
We'll find out later
Once you've got that lemme know
Should just be anywhere inside your class
Alongside all your other @Register.whatever stuff
Yep got it

item.changeInto(BloodRites.INSTANCE.itemGlassbottleofblood);

At this point I'd recommend trying to work out what properties your item description needs, and then once you're done with that start copying stuff over to clay jugs and coconut containers and stuff
waterskins
wait no wrong version sec
properties like weight, skill, etc?
If you wanna see how any item does anything, most of it is in this file
this is every item description in the game
Oh sweet thanks so much
I'd recommend looking at the various liquid filled containers to see what properties they have
You're truly a LEGEND
I'm seeing inheritWeight, durability, returnOnUseAndDecay, keepDurabilityOnCraft, repairable, use, onUse, worth, tier (this is for using it as a liquid in a recipe), noCraftingQualityBonus, createOnBreak as properties you should care about
might be some others
If you get stuck on any or want more details about how they work lemme know
Thanks so much, Chiri!
no worries!
one last tip btw, maybe make a backup every time you get something major working, in case you get stuck and typescript gets super angry at you again
good idea
(switched to work account (they look the same) if you get really stuck you can ping me on this one, but otherwise I won't see unreads till later)
good luck!
How is this set up for different items using the same action?
We just need something new that returns a different container of blood based on input container
I’ll help you with it later
Just woke up the first time a few mins ago
Yeah no worries take your time😁
Okay I can take a bit of time to help now
Ok
wait why did you rename the blood tile event in your canuse to Bloodbottle lol
Probably changed the wrong thing
You shoiuld change that back to blood so it makes a bit more sense
Okay continuing to type guide now
I have the backup you told me to make I was just tinkering ng with it trying to figure out what I should do
So normally I would say the the cleanest way to know how to convert between multiple data types is to set up some kind of record/map somewhere. The idea would be you set up a record where, given an item type, it would return the "blood" item type.
In your case, however, you can't do that, because your blood containers are dynamic/registered IDs. So we have to do something a little different.
My recommendation is to make a new method in your class, with a switch statement, that returns a different registered blood container ID for each raw container item type it's given.
public getBloodContainerType(rawContainerType: ItemType) {
switch (rawContainerType) {
case ItemType.GlassBottle: return this.itemGlassbottleofblood;
case ItemType.ClayJug: return this.itemClayjugofblood;
// if no other container types are applicable, return undefined:
default: return undefined;
}
}
This method would then be used in your can use handler, and if the raw container can't be converted into a valid blood container type (ie, the method returns undefined), then it would say it's not usable.
const bloodContainerType = BloodRites.INSTANCE.getBloodContainerType(item.type);
if (bloodContainerType === undefined) {
// not providing a message I believe means it won't display this action at all in the UI for invalid containers
return { usable: false };
}
And then in your ICollectBloodCanUse, add bloodContainerType: ItemType;
interface ICollectBloodCanUse {
blood: TileEvent;
bloodContainerType: ItemType;
}
And then at the end of your can use handler:
return { usable: true, blood, bloodContainerType };
And then in your main handler:
item.changeInto(canUse.bloodContainerType);
That should be everything right?
yep
If you can figure out where to put all that stuff it should work
The last few things are replacing the previous code you had, mind
Look for the lines that are doing similar things and see how they were updated
Awesome
I'll get to work on that, thanks. After all new items can just be added to the method right?
yep, that getBloodContainerType method can be extended forever
After this stuff you shouldn't need to touch the collect blood action itself again
all that would go in here right?
I say where each part goes directly above the code in question
A method just goes anywhere in your class
So not in something else, just in the class
Same place you'd put a new registration
For the rest of it, just look at where I say to put it
Try to understand what I'm telling you, and what the code is doing
It's less a "here's all the code you need, figure out where to put it" and more, I have explained all of this and what it's for, so you should be somewhat understanding what each piece is for already and understand why you're putting it in each place
If you don't understand one of the things I said in particular, ask me about that
idk you called two things handlers and theres only one thing named "handler", and its not being explained in the context of the code; anyone whos pretty new would be confused.
I understand you getting a little confused sometimes, I have a lot more random knowledge than you, I just need to know which parts are confusing so that I can help better than telling you exactly what to do
As far as handlers are concerned, I have mentioned this previously, every time I've talked about the code block inside .setCanUse, I've called it the "can use handler"
And I've always called the other one the "main handler"
A handler is just a name for a generic function that gets passed to something to handle a specific situation, idk, it's just a programming term
so this constant
const bloodContainerType = BloodRites.INSTANCE.getBloodContainerType(item.type);
if (bloodContainerType === undefined) {
// not providing a message I believe means it won't display this action at all in the UI for invalid containers
return { usable: false };
}
would go below the blood one
yep! or above it. Doesn't matter too much which
It's doing the same kind of thing as the blood one, it's just doing another check to verify that the action makes sense in this situation
I think personally I would put it above the blood one? But it really doesn't matter. I think it's my personal taste that tells me to put it above lol
I'm going to need a bit more context to know what the problem is :p
Argument of type '(action: IActionHandlerApi<Human<number>, IActionUsable>, item: Item) => { usable: false; message?: undefined; blood?: undefined; } | { ...; } | { ...; }' is not assignable to parameter of type '(actionApi: IActionHandlerApi<Human<number>, IActionUsable>, args_0: Item) => IActionNotUsable | ICollectBloodCanUse'.
Type '{ usable: false; message?: undefined; blood?: undefined; } | { usable: false; message: Message.NothingHereToFill; blood?: undefined; } | { usable: true; blood: TileEvent; message?: undefined; }' is not assignable to type 'IActionNotUsable | ICollectBloodCanUse'.
Type '{ usable: true; blood: TileEvent; message?: undefined; }' is not assignable to type 'IActionNotUsable | ICollectBloodCanUse'.
Property 'bloodContainerType' is missing in type '{ usable: true; blood: TileEvent; message?: undefined; }' but required in type 'ICollectBloodCanUse'.
That last line is the part that matters
So it's saying bloodContainerType is required in ICollectBloodCanUse
Because you added that like I said
So now you have to include that in the result when it is usable
So after the checks you have the main result object right?
the { usable: true, blood } I think
Thanks. Sorry if im frustrating to teach lol
No worries, I just wanted to make sure you were actually learning rather than me just only giving you the answers haha
I feel like I am retaining things. It'll just take more time and practice
Regarding this, because it might be helpful in the future — very often TypeScript will give a gigantic error like this but the only part that actually matters is the last line
It's really annoying but fwiw it is consistent
Thats good to know
The clay jug still wont pick up blood for some reason
is it something with the itemgroup?
did you inject the action into clay jug's use using another @Register.override?
yep that looks good
hmm..
let me try building cause I did have to change a thing
hmm
it turned the clay jug to a glass bottle lol
with blood
Can I see your whole file?
lol you could have just sent the single file...
oh sorry
you never updated the changeInto line
I thought you meant the whole thing
The last line I sent here
the itemchangeinto line?
yeah
nice!!
Im trying to reverse engineer the previous things we did to now make the player pour the blood back onto the ground
create(type: TileEventType, tile: Tile): TileEvent | undefined;
I see this is a thing you can do. could you explain these perameters more?
the type is the type of tile event. if you ctrl click on it and then ctrl click on TileEventType you can see the full list. tile is the position in the world that you create the tile event on
TileEventType is also something called an "enum", in case you've never used those in gdscript. It's basically like a list of possible values. In typescript you use one of them with EnumName.ThingInEnum, IE, TileEventType.Blood
Previously we've checked if an existing tile event type is TileEventType.Blood
so the tile is island?
What is blood in this situation?
I don't have much context
Are you making like a pour blood action?
so you have an item which is, like, for example, a glass bottle of blood?
okay gotcha
am I on the right track?
Somewhat
I'm going to try to guide you to the answers this time instead of giving them to you
nods
So let's first think about blood in particular. If you hover it, what does it say it is?
blood is a tileEvent
anything that has to do with occupying a tile?
Hmm, kinda?
I would define it something like a temporary "thing" going on on a tile
All puddles are tile events
Fire is a tile event
The fact that a meltable tile (ie, snow) is near a fire source puts an invisible "melting" tile event on the tile
oh ok
So when you're doing this action, you're trying to make a blood tile event, right?
Because the player is pouring it out?
right
And you're trying to make that tile event on the same island as the island of.... a blood tile event?
When the player is trying to pour out blood, you are currently doing "okay, let's use the blood tile event in front of them. yeah let's get its island. now let's make a blood tile event"
ok
I have no idea if that means you understand
it removes the blood
I'm not sure what you mean
Your goal here is pour blood
You're trying to make the blood appear on the ground
That is a blood tile event
Yeah. Does it make sense that you're looking for a blood tile event in front of you in order to pour out a blood container?
Yep!
with different statements
yeah
So what I would do first is just remove the stuff from IPourCanUse and the pour can use handler that won't be relevant for pouring
Which means going through and really understanding what each of them were for, and whether you need them for pouring
You already know now that you don't need blood
so i dont need IPourCanUse at all?
Maybe, not sure yet
Also, if you want, I just found an easier way to do this that doesn't require a second action at all
oh?
The normal pour action supports it already
interesting
All it requires is adding some new stuff to your blood container item descriptions
let's look at this vanilla description as an example
itemDescriptions[ItemType.ClayJugOfSeawater] = {
inheritWeight: ItemType.ClayJug,
use: [ActionType.Pour, ActionType.PourOnYourself, ActionType.DrinkItem],
durability: 10,
returnOnUseAndDecay: {
type: ItemType.ClayJug,
damaged: true,
whenCrafted: true,
},
repairable: false,
onUse: {
[ActionType.DrinkItem]: [0, -15, 1, -2],
[ActionType.Pour]: TileEventType.PuddleOfSeawater,
[ActionType.PourOnYourself]: TileEventType.PuddleOfSeawater,
},
worth: 50,
tier: {
[ItemTypeGroup.Liquid]: 1,
},
spawnOnMerchant: [BiomeType.Arid],
createOnBreak: {
tileEventType: TileEventType.PuddleOfSeawater,
},
createTileEventOnCraft: TileEventType.PuddleOfSeawater,
noCraftingQualityBonus: true,
group: [ItemTypeGroup.ContainerWithLiquid, ItemTypeGroup.ContainerOfSeawater, ItemTypeGroup.FireExtinguisher, ItemTypeGroup.Liquid],
};
onUse: {
[ActionType.DrinkItem]: [0, -15, 1, -2],
[ActionType.Pour]: TileEventType.PuddleOfSeawater,
[ActionType.PourOnYourself]: TileEventType.PuddleOfSeawater,
},
this bit?
Yeah, plus a couple other things in here
Also use, returnOnUseAndDecay, createOnBreak, and createTileEventOnCraft
Just saw that
Yeah I suppose it's redundant to have it say pour blood
we already know
Since pour already exists
I didnt even think of that
yep
Unfortunately can't do it with fill, that one's hardcoded
Luckily pour isn't though
fill container/gather liquid/whatever
Anyway how will it know that it's blood it's pouring out?
the bloodtileevent isnt like stored in the bottle right?
oh
I guess it is nice
I should've run it before I asked, sorry
I even fixed a bug where when I collected blood with the clay jug it showed an icon of both the glass bottle of blood and the clay jug of blood above the players head, now it only displays the clay variant 😄
This all looks right to me however only the clay jug and class bottle allow for the action of collection when facing blood, for the new two it only shows collecting as a use the item is allowed to use if that makes sense
I already did the definitions for them and everything
idk I give up; as far as I can see everything matches up fine, there's no errors in Visual studio, and the only errors the wayward console throws are weight errors which were there before anyway.
Sorry wasn’t available last night. I’ll take a look in a few hours
Don't be sorry. it's okay 
Oh my god Im so dumb 🤣 🤣
:p
nw!
I keep getting this error in the wayward console and no matter what I do; weight, inheritweight, the weight is never changed to what i'd like it to be. The game keeps switching it to some default.
I cant see any other ways to change weight those two should be the only ones, right? weight and inheritweight
@main merlin I dunno how to help with this one
looking at code, static weightTree(, inheritWeight works only for depth 1, eg. it takes weight property from referrenced item, or calculates it from its recipe if weight is not available, but does not recursively check for inheritWeight if neither weight or recipe are present
from your screenshot, you inherit from *OfGoatMilk, which has neither weight or recipe defined, so you could try something that has recipe like ClayJugOfDesalinatedWater, or just straight up empty container ClayJug
How come I get the same type of error with the regular weight modifier in that case?
So I want the weight to increase just slightly when the texture is switched from the items non filled variant to the filled one. And then decrease back to the regular empty weight when poured out
For example the regular clay jug is ±1.2 I believe, when I tried setting the regular weight of the filled variant I get a basically identical error in the wayward console.
dont know, maybe weight calculation fails at some point due to unexpected combination of parameters, returning wrong numbers for min and max weight
in general weight parameter is set for raw resources like Granite, and crafted items calculate their weight according to recipes
inheritWeight is used by items that change state, like lit/unlit torch or filled/empty container, with no change in weight except for cages contaning monsters
there is reducedWeight parameter, that is used to reduce weight of product to lower value than its components allow, but it is always used with positive number for weight reduction
you could try using inheritWeight with empty container and reducedWeight with -0.2 or something to increase weight, but it might increase it by 0.2 permanently with each filling
Well I definitely don't want the weight to go up permanently, that doesn't make any sense. There's gotta be a way to make this work properly.
From what you said it sounds like I would in fact need inherit weight, so what exactly is the issue with the code
I mean this is bs. It should apply the weight I assign to it. Period
If I want it to be 100 fricking pounds I should be able to do that
Since you craft the item it can’t work like that
The crafting system of the game is entirely based on the weights of ingredients
That’s why groups need default items I’m pretty sure, so that item weights can be determined based on it
Hmm, actually, you didn’t add a recipe.. there must be some other weight property it’s based on then
Yeah there's no "recipe" it just looks to see if blood is available to pick up
I’m not sure I don’t really understand how weight is done right now tbqh
Rip
Part of the reason I pinged Drathy
Thanks for trying lol
I'll just leave it til drathy sees. It's not really breaking anything. Just a personal preference thing to have it have different weights
I'm noticing something very strange about weight of items in general now that I'm messing with it. I have three regular waterskins both spawned in with their qualities set to "normal", yet all three of them differ from each other in weight. Two of them even have the same durability but one of them weighs more than the other for some reason. This is with all the weight modifiers removed from my code.
there is a random variance between all items
if there's no recipe/inheritWeight set, you should be able to set the weight to whatever you want
I can do that but then when the liquid is dumped out the weight isn't corrected which doesn't make sense
So for instance say the glass bottle is ±1 and I set the glass bottle of blood to be ±1.3, it does change it but when I pour out the liquid the glass container will still return as the filled bottles weight
ah, true
there's no system for this currently - as mentioned, everything is based on crafting component weights
How does the container of milk work? Since that’s not crafted?
Oh, okay. I'll just leave it and let everything default out then lol
it uses inheritWeight
So does that mean milk is weightless?
all liquids are
Interesting
Ah gotcha
That makes more sense
