#mod_development
1 messages · Page 161 of 1
Oh, I'm running the mod locally not direct from the workshop
in the mods folder you just create a folder and put your mod.info, media etc into there
it is, imo, bad to mess with workshop files directly since an update can wipe all the changes.
it's way less annoying than Workshop
that's exactly what i'm trying to do
Workshop isn't where workshop mods are downloaded to, it's where you put them to upload
they're still local mods
^ looks like albion explained it
i knew that's not where mods are downloaded to but i didn't realize that's where i uploaded them, rather where i could tinker with it and then upload to steam workshop once final
it can be done that way but working from mods and then moving it to Workshop when you're ready to upload saves you from the annoying workshop structure until you have to
i'm still confused how the folder structure should be when i'm ready to upload but i suppose i'll cross that bridge when i'm done
it's usually Workshop/myMod containing the preview.png, the workshop.txt and the Contents/mods/myMod which is the actual mod folder
Hm, does anyone know how many ticks are in Events.EveryOneMinute?
I actually don't even remember how long 1 in-game minute is irl time...
usually it's 2.5 seconds, but day length can be changed
so it's not a consistent amount of time
and rarely a consistent amount of ticks
Yeah, i'm looking at this function that is running on Events.OnRenderTick
from what I can tell, its anywhere between 40-100+ ticks a second., which is a bit absurd.
were you trying to convert it to something that runs less often? i think you mentioned it earlier
Will be nice when I get my vscode extension's linter working for detecting things like invalid data types.
lua linting?
all i see is pain
This is what I've been working toward since end of January / February.
What if I put in an invalid type for that item? I should highlight it and notify that it's invalid.
It's going to be a fully capable / competent linter for the PZ script format.
It'll tell you if you're missing a comma or a curly brace.
Names where not needed, vice versa.
Case-sensitive property names vs not.
a part of me wonders if .json files can be used instead for that thing
Why not YAML?
Less to type.
I was planning to write a language to compile to ZedScript however YAML works.
That's been my current plan.
You can write tools ontop of what ZedScript provides, such as inheritance models.
I have 50 different shotgun items that all shares 75% of the same properties.. Why not create a BaseShotgun Item with abstract: true?
Why. Not. Make. It. Make. Sense.
I'll admit I am not too familiar with yaml given my experience has mostly dealt with json objects with brackets and braces for everything.
I guess if you have a chatgpt subscription, you can try some prompt engineering to help you build it.
Made the mod a while back, impressed the VO the guy made for it
someone tell me why this won't work
When you're asking for help, it's good to provide more context; instead of "this won't work", context + an explanation of expected and actual behavior is helpful
You could word this more nicely
Use case: attach tags to traits that you create by slapping a good old "||" at the end of the description, and hook into the trait lua to get just the description as normal. And then create a new function for said trait called getTags which returns a table of all tags listed at the end of the description.
sorry, was in the middle of typing. Didn't expect people to respond so fast!
I usually do when people talk to me demandingly.
sorry! wasn't trying to be demanding salbhalsjbgalbga
It's not an actual error. Just a draft of some code that I haven't run yet
Ok. Just think about how others hear or read it before pressing the Enter key. 👍
I'm looking at it really jadedly
I mean, from the top, it looks like you're trying to call the function before it was created...?
which is why i said "tell me why this wont work" 😅
You've provided the context well, but you're missing the expected & actual behavior still. Is there an error? Does it silently fail? Stuff like that
I'm guessing it's an override of a class metatable function
it might also help if you remember to end getDescription with parenthesis ();
I was more or less trying to see if this is even possible
but i could be wrong.
with TypeScript you get to see syntax errors when compiling. =)
i figured giving draft code would be most helpful instead of trying to describe
#ad
No :S
🤦🏾
That's a type stub for a Java class
fuck
you can do stuff like this using metatables, but i'm not actually sure how to access nested classes
You may be able to override it using __classmetatables, though, assuming it's not used Java-side
I'm not sure either, now that I think about it
For my purposes, all I need is this to be present in the lua
but no. Sorry for making y'all think I was demanding help. I'll work on this a little more and be more careful when I type messages in here
i think capsid adds the underscores and that's not actually how they get exposed (since print(TraitFactory_Trait) is no good)
Why do people use capsid?
intellisense?
EmyLua?
A quick glance suggests TraitFactory.Trait, but I haven't read it closely enough to be sure about that. If you can access the class as TraitFactory.Trait, then you can patch its metatable by getting __classmetatables[TraitFactory.Trait.class].__index. I don't know whether that's possible & don't have time atm to confirm
it's not TraitFactory.Trait
I've only seen issues when Capsid is mentioned here..
capsid needs a little maintenance
The exposing code suggests it creates a table structure for nested items
I can write an exporter adjacent to PipeWrench typings for the same data.
...or I was looking at the wrong method 😄
If people want I can eliminate Capsid.
i tried _G["TraitFactory.Trait"] and that was no good either
I'll need the name of a tool from PZ.
Anyone know a good name for generated Lua annotations project?
pz specific for the modding community?
Oh, you want to name a project after a tool in PZ.
Yes. This is the trend for naming my projects for PZ tools for the past decade.
Well... I'd imagine one of the stationary tool would qualify.
Repair items too.
Those are tools.
I've used Sledgehammer, DuctTape, WoodGlue, PipeWrench, Screwdriver so far.
I'd prefer context-related usage, you're creating a project that is supposed to add context details to what I assume is PZ code.
regrettably, calculators do not exist in PZ cause math is lost in a zombie apocalypse.
zombie.characters.traits["TraitFactory$Trait"] works
but not _G["TraitFactory$Trait"] strangely
Welcome to Internal Java notation.
Paint Brush?
that's the closest thing i can think of to make something prettier
at least within PZ.
_G['TraitFactory$Trait'] !== zombie.characters.traits["TraitFactory$Trait"]
_G['TraitFactory$Trait'] === TraitFactory$Trait
I could call it ToiletPaper
the exposer usually puts classes into _G though
maybe it doesn't get put there because it doesn't have any statics
Illegal character escape
It's the same thing as calling it as a global var.
Only diff is that you can call variables this way as global is itself a table.
I use it too.
i'm not really sure what you're trying to tell me here
i'm using _G["TraitFactory$Trait"] because lua doesn't like $ outside of a string, even if i'm trying to index a table
it would be the same as TraitFactory$Trait if that didn't make lua mad
I'm saying it's used exactly for this reason.
Thought saying it would help others understand.
oh, i see
This makes me wonder whether all fully qualified names are present & the simple class names exist for names that can be represented with Lua variables
Desperately need to focus on work rn but I want to read through the exposer to find out 😢
Going for the name Candle.
Bet ya I can get Candle developed to replace Capsid tonight.
Setting up the environment right now.
#LearningExperience
I need to look at the API for Emmylua..
https://github.com/cocolabs/pz-zdoc does exist as well, as a heads-up, but it's out of date (still working if you mess around with the batch file a bit)
I only need to know what files that EmmyLua digests.
Ah, I missed that you're talking about creating an IntelliJ plugin
Not an IntelliJ plugin but whatever that Capsid feeds to EmmyLua.
I think this is it.
Oh, in that case the above is a reference worth looking at—it does the same
If the files that it creates can be zipped and sent to me then I can begin work on it. =)
would be sick to have a tstl plugin that generate the emmylua comments about the classes
I don't use capsid myself
EmmyLua has poor documentation AFAICS
Possible to do.
I stick with the LuaCATS fork
Link and link to their generated files?
@red tiger i realized that pzpw can also work for lua mods without any ts
Yes because of copying lua files.
yeah
For the stubs I use locally I used pz-zdoc plus a quick-n-dirty Python script to process the output to be a bit better
I think they're a bit distinct from LuaDoc but yeah, nothing too fancy
Yeah if people are sick and tired of Capsid I can deprecate it.
EmmyLua is providing what TypeScript does.
well capsid is just unmaintained afaik
Over 2 years since last commit.
a dream of mine has been to get it to grab parameter names from the reference site
but i can't work out any of this gradle plugin stuff so i never worked on it
2 birds one stone.
I plan to do this for PipeWrench.
I could prioritize this task.
How much is this in demand?
I prioritize what projects I develop based on the needs of the community.
pipewrench with more docs?
Parameter names would definitely be nice, I've wanted to improve pz-zdoc as well
Co had something that was making the code beautifull
PipeWrench, (Now Candle), and the pz-zdoc?
If your annotations are compatible with LuaCATS I'll happily use (and perhaps contribute to) Candle instead 😄
Do you have a copy of these files that I can take a look at?
It'd speed up the process. =)
I don't want to run capsid.
Sure, I'll zip them up
Note that mine are specific to LuaCATS though; capsid ones won't have some of the stuff mine do

Just to clarify it's not a coding thing but more id have to make a texture that is big enough for both male and female texture/uvs, I can't just put a line of code in that says one or the other right?
Use the brushtool cheat
Then when you right click theres an option to copy and sldo writes the time name
Yep, Thanx. it's what I did after Poltergeist explanations 😄

Huh..
EmmyLua doesn't support generic args for field declarations.
All the more the reason to use PipeWrench.
I'm struggling with setUsedDelta on an item I'm adding to my inventory.
Do I create a local variable that stores an item and modify the setUsedDelta, and then add it?
@red tiger Seems there is a problem with using IS objects in pw.
This doesnt work:
const cursor = new ISPlace3DItemCursor(player, [item]);
This works:
const cursor: ISPlace3DItemCursor = _G.ISPlace3DItemCursor.new(player, [item]);
It's been known for a while.
Document it somewhere for the time being.
Flaws from a sketchy transpiler that I had no time to write.
Exports.ISPlace3DItemCursor = loadstring("return _G['ISPlace3DItemCursor']")()
yet it should work
Generics are on the todo for LuaCATS, but same thing there. EmmyLua is doomed to not support them forever, probably
No worry.
Already made progress.
I think I am blind, but I'm interested in pz typescript. PipeWrench is what I am after?
so I'm trying to modify a mod, I have this
any ideas it still can't be wore the same time as a backpack?
item RuBag
{
WeightReduction = 50,
Weight = 0.5,
Type = Container,
Capacity = 10,
DisplayName = RuBag,
Icon = rbao1,
MetalValue = 15,
ClothingItem = RuBag,
CanBeEquipped = FannyPackFront,
BodyLocation = FannyPackFront,
ClothingItemExtra = RuBag,
BloodLocation = Bag,
ClothingItemExtraOption = FannyPack_WearBack,
OpenSound = OpenKitB,
CloseSound = CloseKitB,
PutInSound = PutItemInBag,
WorldStaticModel = GunCase_Ground,
}
Yes. I wrote it. Konijima has a friendly environment for it.
pzpw
im trying to make it take up the fanny pack location
but it conflict both fanny pack and backpack
That's perfect. Is there a tutorial or just clickaroo on konjima for some links?
@thin hornet
@wanton pier
I phrased this poorly, let me try again. Why is ClothingItemExtra set to RuBag?
I have my own basic environment but pzpw should be better for people overall.
Awesome! Thanks for going out of your way. ❤️
No problem.
I see it also doesn't have clothingExtraSubmenu, when comparing with the vanilla fanny pack, but I wouldn't think that'd cause this issue. I'd say take a look at Bag_FannyPackFront in media/scripts/clothing/clothing_bags.txt and compare
Does anyone here have any experience using the setUsedDelta for result items in recipes?
Arsenal mod overwrote the base game Gunpowder to give it a 0.005 useDelta, but when I try to add more than one GunPowder as a result item it simply returns a full one.
I'm kind of stuck in the weeds on the proper way to manipulate an items usedDelta before adding it to a players inventory.
can you show how you're trying?
@bronze yoke But of course!
So here's the recipe:
recipe Gather x1 Gun Powder
{
Bullets22/Bullets357/Bullets38/Bullets380/Bullets44/Bullets45/Bullets4570/Bullets45LC/Bullets50MAG/Bullets57/Bullets9mm,
Time:5.0,
OnCreate:GatherGunPowder,
Result:GunPowder,
RemoveResultItem:false,
Category:Omni Ammunition,
NeedToBeLearn:false,
CanBeDoneFromFloor:true,
}
And here's the code I was attempting.
function GatherGunPowder(items,result,player)
result:setUsedDelta()=0.005
end
When I gather a single round, say a "Bullets22" it returns an entire Gunpowder.
So this might be a little silly but I tried using the advice from here, but it doesn't seem to be working. No errors that I can see
local originalGetTraitDescription = zombie.characters.traits["TraitFactory$Trait"].getDescription;
zombie.characters.traits["TraitFactory$Trait"].getDescription = function(self)
local descAndTags = originalGetTraitDescription(self);
local indexOfTagsBegin = strFind(descAndTags, "||");
if indexOfTagsBegin == not nil
then
local description = strSub(descAndTags, 0, indexOfTagsBegin);
return description;
else
print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
return descAndTags;
end
end
zombie.characters.traits["TraitFactory$Trait"].getTags = function(self)
local descAndTags = originalGetTraitDescription(self);
local indexOfTagsBegin = strFind(descAndTags, "||");
local lastComma = 1;
local tagTable = {};
if indexOfTagsBegin == not nil
then
local tags = strSub(descAndTags, indexOfTagsBegin);
for i=1, strlen(tags)
do
if tags[i] == '' or tags[i] == ','
then
table.insert(tagTable, strSub(tags, lastComma, i));
lastComma = i;
end
end
else
print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
return tagTable;
end
return tagTable;
end
Here's what I got
you have to follow this sort of pattern```lua
local metatable = getmetatable(zombie.characters.traits["TraitFactory$Trait"].class).__index
local old_getDesc = metatable.getDesc
metatable.getDesc =
(well assigning metatable to a variable is strictly unnecessary but who wants to write all that out every time)
true lol
thank you
Capsid seems to export items that aren't exposed. That can confuse the modder..
I said I was going to get an initial working copy of Lua definitions. Going to do it..
My current test file is ~365K lines long.
Haha lol
--- @public
--- @static
---
--- Method Parameters:
--- - (RoomDef arg0, int arg1): IsoDeadBody
--- - (int arg0, int arg1, int arg2, IsoDirections arg3, int arg4): IsoDeadBody
--- - (IsoGridSquare arg0, IsoDirections arg1, int arg2, int arg3, String arg4): IsoDeadBody
--- - (int arg0, int arg1, int arg2, IsoDirections arg3, int arg4, int arg5): IsoDeadBody
--- - (float arg0, float arg1, float arg2, float arg3, boolean arg4, int arg5, int arg6, String arg7): IsoDeadBody
---
--- @param arg1 RoomDef | int | IsoGridSquare | float
--- @param arg2 int | int | IsoDirections | float
--- @param arg3 int | int | int | float
--- @param arg4 IsoDirections | int | IsoDirections | float
--- @param arg5 int | String | int | boolean
--- @param arg6 int | int
--- @param arg7 int
--- @param arg8 String
function RZSTrapperCamp.createRandomDeadBody(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) end
Not too crazy..
@bronze yoke I tried the code you mentioned, but it's still showing up as a full item. I don't think result:setUsedDelta(0.005) works the way I think it does.
--- @public
--- @static
---
--- Additional Methods:
--- @overload fun(arg0: int, arg1: int, arg2: int, arg3: IsoDirections, arg4: int)
--- @overload fun(arg0: IsoGridSquare, arg1: IsoDirections, arg2: int, arg3: int, arg4: String)
--- @overload fun(arg0: int, arg1: int, arg2: int, arg3: IsoDirections, arg4: int, arg5: int)
--- @overload fun(arg0: float, arg1: float, arg2: float, arg3: float, arg4: boolean, arg5: int, arg6: int, arg7: String)
---
--- @param arg0 RoomDef
--- @param arg1 int
--- @return IsoDeadBody
function RZSTrapperCamp.createRandomDeadBody(arg0, arg1) end
What a journey that was..
Okay.. This thing is fuckin evil
Will split it up tomorrow and begin looking at debugging but I essentially just wrote an exporter for what Capsid does.
@frank elbow @bronze yoke
It's past 1 AM and I did what I said I would. I did it in one sitting.
Going to grab something and lie down.
Another urban legend has come to Kentucky https://steamcommunity.com/sharedfiles/filedetails/?id=2976887243
Nice! Some of those aliases should be classes + some other minor stuff I see at first glance, but nonetheless well done esp. for how quick it was
Do I remember right in that someone mentioned a mod that can show loot table odds in-game?
Loot table odds?
Like the probability of items spawned in containers? You can already do that in vanilla with LootZed
Oh, that's it "LootZed"!
I assumed it was a mod
But yeah, that's what I want to do - how do I use it? Is it a -debug option?
Ah found it, it's in the Cheats menu when you have -debug on, thanks.
Errr, does LootZed work correctly? It seems to think all these kitchen cabinets have the same loot table when they don't...
Like it's showing me just the "Bottles" one, even though this is a CannedFood one
Oh I see
there's a drop down you have to manually change for sub types, nvm
Is there an event for something like "OnContainerOpen" that triggers for the client when they open something. More accurately I want to know when they loot a zombie
AFAIK, there is no such thing as a container opening event (there could be something like that, but for vehicles only). There is a container update though. If you are interested in the fact that a container becomes available to a player, it is nearly strictly related to position. (nearly because passage must also not be blocked and not in a restricted area)
Basically, I was hoping I could somehow dull a zombie's corpse if you've seen it's inventory. I guess if you got close enough to it that'd work too? But I imagine if you melee killed it, you wouldn't know you've looted it as you were already right next to it.
ItemContainers have an isExplored method, but I believe that'll be true if anyone has seen its inventory. Maybe you could override ISInventoryPane.update and use getPlayerLoot to check the container, but I haven't used the latter so idk whether it has the information you need for that
What I mean is something like:
local ISInventoryPane_update = ISInventoryPane.update
function ISInventoryPane:update()
ISInventoryPane_update(self)
local loot = getPlayerLoot(self.player)
if not loot then
return
end
-- do something with the return value of getPlayerLoot
end
See client/ISUI/ISInventoryPane.lua for examples of getPlayerLoot—unfamiliar with its structure myself, so it may not end up having what you need
Thanks, having a look around now
It may be wiser to choose a different method to override after a quick glance through myself, but the general idea should be the same. Maybe an event instead, if none fit
getPlayerLoot will return an ISInventoryPage or nil
so backpack borders has this:
-- Add background and border to new buttons
ISInventoryPage.addContainerButton_pre_backpack_borders = ISInventoryPage.addContainerButton;
function ISInventoryPage:addContainerButton(...)
local button = self:addContainerButton_pre_backpack_borders(...);
button:setBorderRGBA(0.6, 0.6, 0.6, 0.5)
button:setBackgroundRGBA(0.12, 0.12, 0.12, 0.7)
return button;
end
I wonder if I can do similar and see if the "button" is a zombie's inventory container
how easy is it to make your own true music mod?
Bleh, looks like this is just gui stuff and has no info on the actual container... Though looking in Zomboid's lua, I do see button.inventory 🤔
I know that those are bugs. Likely a easy fix.
<@&671452400221159444>
Phisher scam bot in channel.
ty
If youre end user
Should ask here
#mod_support
This is for when you develop your own mods
But to answer the question:
IBrRus wrote s guide for that im sure
You should just follow it
It should be straight forward and i bet theres no coding experiences required
ok
Why am I getting Object tried to call nil when I have it wrapped in if button.container ~= nil then 🤔 ?
oh my bad, I copied that after I made sanity changes
it was originally just if container ~= nil then
Alternatively you can just check with if not button.container then
Error:
function: mGuvLevelOverhaulAddContainerButton -- file: mGuv_LevelOverhaul_MarkZombiesAsLooted.lua line # 10
LOG : General , 1684336472787> Object tried to call nil in mGuvLevelOverhaulAddContainerButton
ERROR: General , 1684336472787> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in mGuvLevelOverhaulAddContainerButton
File:
require "ISUI/ISInventoryPage"
local originalAddContainerButton = ISInventoryPage.addContainerButton;
function mGuvLevelOverhaulAddContainerButton(container, texture, name, tooltip)
print("A");
-- is it a zombie? If so what can we do
if container ~= nil then
print("AA");
local name = container:getName(); -- this is line 10
-- etc
Container may not have a function called getName()
oh is -that- what that error means?
That's not clear at all. I thought it was saying container was nil
What is container?
No idea
lol
this is me probing based on what I saw elsewhere
Looking at the zomboid code it should be a ItemContainer, I don't know why I'm getting nil
and then why my nil check fails me
Oh whoops, I pulled getName off InventoryContainer not ItemContainer
Is there a way to skip current iterations of a loop like continue in other languages? What about break to get out of a loop?
So you invert your condition to continue.
noooo rip clean code
This is how you get around this issue.
yeah it's kind of gross
i'm lua's strongest warrior but the lack of continue is gross
I opened one mod's lua to get some ideas and it's like 20 levels of nested ifs, rather than flipping conditions and early returning
but looks like it's part because you can't continue properly
Or just be a real programmer and use TypeScript.
I'll wait.. for Lua people to burn me alive for that statement.

I mean I am, but I'm also hand writing lua to learn it at the same time
Lua is real programming guys.. cmon...
so I can read others code, the ts stuff is great but I still need to understand lua lol
I'm also working on forwarding what PIpeWrench defines with types to Lua through EmmyLua.
We help people here.
Also too much caffeine today.
Here is my guideline to help you write cleaner code.
https://github.com/shadowhunter100/Project_Zomboid_ModTools/blob/main/Cows Coding Guidelines.md
Mmmmmmmmmmm
PZWiki page when?
Okay, I tried running the game with this pattern and descriptions still contain the "||" and commas after. I even tried to call the modified getDescription inside of EveryOneMinute, and the game gave me nothing--no locals, nothing for me to look at... just an error that doesn't seem to have anything to do with the function
I'm gonna see if I can pull up said error again
Holding back the trigger on a lot of tutorials.
no idea, I don't know who to talk to
you can just put it on there
are you still comparing number to no nil?
If you need help with that, #pzwiki_editing has people in there working on the wiki daily.
no, that was a couple of traits ago haha
I'm onto the unholy task of hooking into the getDescription() function of traits and seeing if I can use the description to hold tags related to the trait itself
For my purposes I'm trying to limit what anthro species can be chosen based on what traits you have
with said tags
I'm certain that if anyone made like, a buff model replacer the same technique could be useful
because it should be
if indexOfTagsBegin ~= nil then
if indexOfTagsBegin == not nil
then
is like
if 1 == true
then
fixed. thank you Mx. Ghost.
my goodness, I should also make parenthesis required in those if () then blocks.
Same issue. I find it really odd that I have no locals popping up
Do you guys think I'm tackling this the wrong way? Maybe there's an easier way to connect tags with traits?
you have no locals because the error is on the line above, you seem to use different names for the function.
old vs original
needs more brackets
wait is there really no like... regular way to add to an array? Uh, table? Whatever they call it lol
no var[] = x, var.push/insert/add/etc, all I see is... var[#var+1] = x
Daily reminder that PZ Lua is not real Lua. It's closest to Lua 5.1 but is incomplete. Any features in Lua 5.2+ aren't available in PZ.
Always keep this in mind when looking up Lua tutorials or features.
I hope they update the lua in the near future
I do too..
For now I pick on it and have fun making tools to bypass writing actual Lua to do things with PZ.
Imagine they had like a modders vote or smth where they would ask modders what they would like to see implemented/exposed to help them mod
Business: If something works, it's good enough.
It's why I don't ask. I simply do.
One day I'll release my core utilities mod. =)
Hahaha Imagine a result that didn't please the devs or several of the modders
Can I set custom params with DoParam? If so, how do I read them back out?
yeah, any unrecognised parameter set by doparam or the item script is added as default moddata
i'm unsure if default moddata is accessible on the item level but you can grab them from inventoryitems with item:getModData().myParameter
ah okay, if I use getModData can I set things with that too?
Cos I might as well just stick with that as it's my own item
yeah, moddata is just generic per-object storage
Oh I see, hmm. I'm more wishing to change the base of the item
I don't know how to describe, like I was modifying the Item {} definition from a items.txt
that's what doparam does
Hmm, but it ends up on getModData that gets serialised if it's a custom param 😅 ?
i never considered that actually, that's kind of obnoxious
custom parameters are going to be saved for every single instance of the item
also default moddata doesn't get applied to existing items, which might be important for your mod
Yeah, I heard about that
it might make sense to just store whatever data you wanted to in a table
e.g. myParams = {["Base.Apple"] = 5, ["Base.Orange"] = 7}
literally rewriting to that now 😅 basically making it a look up via item type, rather than attaching it to the item
@bronze yoke Is it okay if I message you with a question about your mods?
sure!
Wait is this the data you will store on an items moddata? You are storing a table of items?
Hmmmm sounds useful for random supply box kind of mod
no, i just meant to not use moddata and just use a lookup table instead since it didn't seem to really fit the use case
you could do a supply box mod like that but it seems wasteful to use moddata for it
and probably wouldn't offer any utility of its own
can't believe MS included a browser in their XML viewer
question, is there a mod that displays the square in which a throwable is supposed to land?
been messing around and attracting hordes, but the molly doesn't seem to go where I click :(
Are there any mods adding quests/tasks to the game?
No, because NPCs do not exist in the current build
you don't npcs for tasks
looks like someone built a task system:https://steamcommunity.com/sharedfiles/filedetails/?id=2970272534&searchtext=task
it's in Chinese though
Is it not possible to mod the erosion system? I'm finding the decompiled Java for it a nightmare to try to make sense of, and it doesn't look like much is possible with lua (short of trying to write a new erosion system from scratch to go on top of the existing one). I wanted to try to uncap erosion so trees and etc don't stop growing once you hit 100% growth, but nothing I look at is giving me a clue how I would go about doing that.
Anyone have a tutorial or documentation on how to use lua files on tiles?
This may sound mildly insane but I'm thinking about getting back onto the Ultimate Farming Patch grind to get it working better than ever.
So here's my question - how possible would it be to just use a metatable here to store all the data necessary in between mods without requiring individual patchers?
Nothing is "impossible", it's only the question of sanity, time, and how desperate you want something to work between the builds.
To my knowledge, metatables are able to detect edits made within themselves, so if I can turn the global farmingconf table into a meta, I could theoretically get it to hook onto new additions / changes and just cram that all into data.
This approach has it's own problems and it's all theoretical thoguh

The alternative approach is just making individual "patcher" mods that require a very specific mod load order to function.
Though those would also theoretically allow me to make little edits and save to a specific "code" for a custom farming "priority" order.
the general rule of thumb is complexities grow exponentially per variable; I'm unsure how many variables and tables... then mods you plan to "hook up" together.
cause you also have to deal with mod loads ordering
The entire point of UFP is to act as a framework for farming compatibility to turn it more into an unintentionally soulfilcher-type system, but this is the only way I can think of keeping it lightweight and up-to-date.
In other words, it forces farming mods to play nice by yoinking their necessary farming data and ordering it in a specific way so they can all be friends.
All of this will have to be done-over by the time 42 releases but I have a feeling that could be a bit.
Aaa sorry hehe
I'm just off the walls, both in a good and bad way.
The last rendition of this mod had ~4K lines of manual data entry for mod support.

I'd.. like to get that down a bit.
And also let the community introduce mods they want rather easily.
Hm? That depends on how you plan to restructure the project...
I'm thinking of a "sandwich" style.
You have the Core mod which comes last since it would handle all of the conversions over to a Soul Filcher type system
Then you would have individual patchers that save the data in between mods and wipe the slate clean
So like
- Vanilla
- Vanilla Patcher (Saves all vanilla data.)
- Soul Filcher's
- Soul Filcher's Patcher (Saves all SF data.)
- CORE
relatively easy order to maintain.
Also, sorry for the ping @nimble spoke, but thank you for existing and making mods for this game.
You are literally one of the reasons I started modding.
I appreciate that. I'm glad you're fine and back on the saddle
Yeee!
Awesome Time is hands down one of my favorite mods on the workshop.
Anywho, I have a horrible amount of work to do!1
Can't wait to restructure my ENTIRE MOD!
I assume you hit a roadblock, what was it?
Oh, I just realized that manual data entry isn't worth it like, at all.
So automating as much of it as humanly possible to save on the workload and theoretically increase mod update compatibility tenfold would be nice.
(And also reduce the file size, which ain't much but hey, it's something.)
It only took 11 mods worth of farming data to figure that out!
blame lua code
If I can get this system up and running, it should take significantly less time to get mods to play nice with the framework, and I wouldn't have to worry about a single update ruining the stats associated with the crops.
Really all I can blame is myself, I chose to do the data entry route at the start LOL
I didn't think UFP would get anywhere it did.
It was originally just a Mo Crops / Soul Filcher's patch
Hence the "MoFilchers" name in the files.
Sadly farming mods could have been totally compatible, as that was my goal with the mod, but other modders didn't follow up. Hopefully that will be solved in b42
Yeye
I wouldn't have to do any of this if they had just adapted to your system
But oh well, I guess people like their mods being standalone..?
Or simply don't care enough about compatibility
sure. Players who enjoy farming mods always try to use several of them, you can make their mod lists less janky
The other reason behind this patcher is because it implements a few fixes / features to vanilla too which can't otherwise be used with most other farming mods.
Namely a fix I plan on giving to cures which my girlfriend noticed of all people, you tend to use a bit more cure than is actually necessary to get rid of crop disease.
(If the crop disease isn't a perfect increment of 5 you could be wasting some cure on every spritz.)
Are there other things in these farming mods that need to be patched or just the growth function / context menu?
Mostly growth function and context, however Le Gourmet does change a lot up.
The system allows you to adjust to LG's "Learn to Sow" system if you want it to, so crops aren't left entirely unplantable due to not knowing a recipe from seed packets.
(The sow menus required you know how to plant the crop, which is learned from seed packets. This broke compatibility with virtually every other farming mod.)
It also allows for "refunding" from LG's crops - and potentially other crops. Stuff like twigs and sheet rope that went into planting it are given back when you harvest, assuming it doesn't reset back to a previous stage.
I'd focus on making the other mods compatible first, so at least it is useful before B42. Trying to include LG may take you too long
Perhaps.
I'll focus on that for now, I'll drop in LG support if I can find the time.
The only thing I might need to figure out for convenience is how to like..
Potentially to get specific parts of a mod to load first, then other parts of the mod to load last.
So like, the CORE I could theoretically get up top if I can get only it's necessary global functions and data loaded.
Then let all of the patchers add to that.
Then when it's done, I just figure out how to get Core to run after everything else is done.
Hooking to different functions may be one way.
sounds.... like a nightmare
Yes!

All else fails I just make a proper sandwich and just have two core mods. One for initial load and one for wrap-up.
Though I'd rather keep it all in one mod if possible because I have a feeling people will be at my throat otherwise.
You don't need the second mod if you find proper events so you can run whatever you want later
Yeye
I question if this all is even that good of an idea anymore but oh well, worth a shot at least.
Good way to learn and at least grow from my mistakes.
the idea is good, I think you can get it working in time
Thank you.
Maybe I can even get it done tonight if I power through.
It took me about a week to figure it out the first time, should only be faster the second.
..especially with less data entry.
do clothing item xmls all have to be 1 word?
what do you mean?
i don't think you can have spaces if that's what you mean
but theres an example of one of my xmls
gothca
Jeez
this is for dev testing saves not real ones though lol
also wow
if you have a mohawk and you equip a helmet, it flattens your hair
i never knew that
Thats good to know!
on a sidenote, the armor mod ive been working on is almost done
haven't been posting here as frequently
yeah heres without the nvgs
i actually used a mando helmet tutorial to help model it
since it is very similar
ah..btw are your clothes just clothing or do they like add stats or gui stuff?
theres only one piece of clothing there
that's the jacket
the rest are like accessories
shoulder pads, bracers, helmet, tactical belt, backpack
the pads and helmet have protection stats
NVGs add nightvision functionality
no idea how to make mods but if someone wanted to pick the idea up, for a long time in an internet forum ive been a part of the idea that lifting will remove your depression has been around, so making a mod that decreases unhappiness when lifting weights would be cool
me omw to fix suicidal ideation from being in the apocalypse through sheer gainz
How can I check if I messed something up in scripts for my mod?
I meant like these
gotcha im just trying to figure out hat I messed up cause its frozen at scripts
Going to pretty up the repo tomorrow.
This is a replacement for Capsid.
The types are already provided by the repo so there's no need to decompile PZ
@thin hornet
I'm so thrilled.
I met my goal and the results look great.
That's super cool @red tiger
Thanks. The goal was to write it all in one go.
Hopefully this will drastically improve the setup process for modders who would otherwise need to operate Capsid and decompile PZ.
yeah, capsid is kind of a pain to get working and this is a step up in other ways too
i hugely recommend people switch to this when they can
Id like to place Candle in central repositories that people use for EmmyLua
wrong link
Is table.isempty(t) included in Candle?
by Omar
https://github.com/Project-Zomboid-Community-Modding/pz-community-modding
github actions for scheduled updates like Chuck does in this repository
You can probably customise the steamcmd scripts used to make this happen.
Thank you for the insight! its what i need, trying to use arma-uploader but doesnt seems work for me.
honestly iam on setting with steamcmd right now, but i'll try the github actions then
Hey so I have a drop model but when I put the clothing on the ground it just drops the icon
item Jacket_samurai_classic
{
Type = Clothing,
DisplayName = Samurai Jacket classic,
ClothingItem = Jacket_samurai_classic,
BodyLocation = Jacket,
BloodLocation = Jacket,
Icon = SteamGuideJacket,
RunSpeedModifier = 0.98,
CombatSpeedModifier = 0.97,
ScratchDefense = 60,
BiteDefense = 30,
Insulation = 0.4,
WindResistance = 0.8,
WaterResistance = 0.6,
Weight = 2,
FabricType = Cotton,
WorldStaticModel = Samurai Jacket_ground,
}
Did I mis code something
its work right now, thanks for the insight from repo that your share. I can update my mod even on mobile tho.
Yo modern phones are strong af
World static model shouldnt have spaces afaik
Samurai space jacket underscore ground
Is there a reliable way to get an emitter from an IsoObject?
Hmm, I am trying to recursively search a container (well 'backpack' as the game seems to call it) by looping through all its contents, and checking if the item can contain items.
My check to see if it is a container works, but when I get the items in the container I get nil?
I'm testing it with a first aid kid, so little unsure what's going wrong.
I check containers (all kinds) a lot in Autoloot mod, client/Autoloot.lua & client/Autodrop.lua
Ah thanks, yeah, if you're auto looting you'll be doing very similar to me. Will check it out.
(I'm highlighting containers with certain items in - so basically the same without actually grabbing the item)
Is it good practice to put all my loose global functions/variables in like a 'Module', like mGuvsStuff = {} mGuvsStuff.SomeGlobal = 'foo', rather than just having SomeGlobal loose
I'm not fluent in lua but I tried to do so after reading fwolf's guide. I may be wrong to do so. https://github.com/FWolfe/Zomboid-Modding-Guide
I see it as reducing the chance of causing a collision with another mod so a positive.
Though if someone somehow collided with your module name, it'd overwrite it all 😅
I prefer an unwanted total override to an unwanted partial override 😄
True
Darn, I just did some digging to see if I could custom set the background for item line entries in your inventory, like how Frozen/Hot stuff does.
Super hard coded 😦
there is also a green progression when there is an action on an item. maybe it is easier to use.
Hey guys!
I've developed a mod, but I'm struggling to pinpoint an error the server console for the dedicated server I'm using keeps throwing up at me.
It's claiming an OnEat function I set up (OnEat_Zombex) can't be found, but for the life of me I can't figure out why.
I have it defined in the items.txt correctly and there's no syntax errors I can identify. Just a shot in the dark here but wondering if there's another reason the server console might be unable to find the function that is a little less obvious?
(I only recently learnt this forum existed, so hiiiii! And thank you for taking the time to read)
syntax error, client only function
Thank you! Appreciate that. I’ll dig back through it all again
could be also set local and you you try to use it from another file (out of scope error)
I know it's too early in the morning for pedantry, but that is not a syntax error 😄
I grabbed an original method, overwrote it, then called the original from inside my overwrite: and the original blows up. If I had to guess, it looks like something happened to self - and I don't know lua enough to know how to fix that 😅
Can you show a snippet of the code in question?
sure I'll grab the important parts
require "ISUI/ISInventoryPage"
local mGuvBaseISInventoryPage = {};
mGuvBaseISInventoryPage.refreshBackpacks = ISInventoryPage.refreshBackpacks;
function mGuvOverwriteLootingUI()
-- Overwrite original - refreshBackpacks
function ISInventoryPage:refreshBackpacks(...)
-- Call original - refreshBackpacks
mGuvBaseISInventoryPage.refreshBackpacks(...); -- THIS BLOWS UP
-- Check every backpack button
for k,containerButton in ipairs(self.backpacks) do
-- Skip if it doesn't have an inventory
if containerButton.inventory ~= self.inventory then
local bestRarity = GetRarestRarityFromItems(containerButton.inventory:getItems());
-- Only highlight if it wasn't trash
if bestRarity.Name ~= "Trash" then
-- Set the background of the UI icon
containerButton:setBackgroundRGBA(bestRarity.Color:getR(), bestRarity.Color:getG(), bestRarity.Color:getB(), 0.7)
end
end
end
end
end
-- Run last so the backpack borders and sorting mod still work
local loadAfterEverythingElse = function()
Events.OnLoad.Add(function()
mGuvOverwriteLootingUI();
end)
end
Events.OnLoad.Add(loadAfterEverythingElse);
Yeah, you're not forwarding the self variable to the call
How do I do that?
The colon, :, essentially is syntactic sugar for a self parameter. That is, these two are effectively equivalent:
function x:y() end
function x.y(self) end
The self parameter will be implicitly (well, explicitly but sugared) available in the first call. You just need to pass self as the first parameter, since the function expects that
I understand scoping/self, just not sure how to fix it in lua. JavaScript lets you use things like apply and bind to set what this is that context
oh, I see. So it's sort of automatically sending self as the first param
But using the wrong self, as it just grabs the current context
not the original
Yeah, it'll treat the first parameter as self if you don't pass it
x:y() is also equivalent to x.y(x) so it's easy to miss this detail when you're used to calls looking like that
Yeah
mGuvBaseISInventoryPage.refreshBackpacks I did that instead of mGuvBaseISInventoryPage:refreshBackpacks?
Oh. No
Cos that doesn't look right now I see it as a .
Varargs (...) doesn't include self when you declare it with the colon
Sorry, still not following. I'm close to understanding but not sure what to do with the information
Penny for your 🤔 thoughts, Poltergeist? (asking because of the reaction) If I've said something that sounds strange please do explain
What part is unclear?
Where/what I need to change betwen : and . - or where I need to drop self in haha
I understand the problem but not the syntax
In the call to the original function, you should pass self
function x:y() end --y function in x table
function x(self, y) end --global x function
Yup
@novel swallow
https://pzwiki.net/wiki/Lua_Functions
never too early for that 😄
Perfect, that showed me the syntax to line up with what @frank elbow was saying - thanks both, it's working now 👍
Though you have just shown me yet another oddity with lua 😅 but I get the need for this kind of control over self with something so dynamic
Hey! Just joined, wondering if someone can help point me in the right direction for a mod I want to start on. Currently am using FearTheSun, which turns most zombies docile during the day, but I am finding docile zombies are a little too docile. Want to make them a bit more dangerous when fighting many close together.
Is there some script file that controls how zombies act on a moment to moment basis that I should be looking at, or some way to listen for an attack event, grab the position, find all the docile zombies near that and set them to not be docile?
Any help or guidance would be much appreciated, thank you!
ai tends to be heavily hardcoded
it depends how fearthesun makes them 'docile' in the first place though
if that is something that can easily be flicked off then you can use the OnHitZombie or WeaponSwing events
Sweet, that seems like it will work then. I will look into that, thanks!
If I define a module style thing (thing = {}; thing.x = function() print("foo"); end in say /mods/mymod/test.lua and I want to use it in /mods/mymod/other.lua, do I have to import it or anything?
Tried it the most basic why (similar to example provided) and it error'd
Oh wait, ignore me.
It worked fine. I read the wrong error.
Why is the "Errors list" in game so confusing D:
I'd be better off just tail -fing console.txt
I changed it but it still shows up as the icon
pain
Hey modders. Letting you know that I now have a project targeting the replacement of Capsid. The files come pre-compiled and requires no steps other than placing the files in your EmmyLua environment.
I'm in the process of cleanup, fixes, and improvements.
This is me providing a lot of the same benefits of PipeWrench (TypeScript environment) to the Lua modders.
I have a vscode extension for scripts called ZedScript. If you use vscode, it should help a little with scripting.
(It's a WIP extension)
hello! I am looking to add sandbox options to my mod, where do I go to get started? (my thanks in advance!)
I do have vscode, I hope it helps
Where do I get that script?
vscode has a marketplace button on the left side. Type in ZedScript.
There was an example mod at some point. If it isn't pinned or available I can share it
please do!
Can someone pin that? I'd imagine more modders will need it in the future.
it's pinned on the wiki
So does this look right?
Syntax-wise yes.
That is the right extension since mine is the only one in existence atm.
can anyone help me create custom presets inside a mod's page in sandbox? I'm so lost
what do you mean? like a sandbox option that is a list of options, or a preset for all the settings on that page?
i want to change recoil force and other values and save them in some established presets in the "weapon presets" option
that just isn't a thing i'm afraid
so you change the recoil and stuff for each weapon
fuck
you could have the weapon presets option just override whatever the user puts in on the lua side but you can't have it change the actual settings
per-mod presets are something i'd looked into creating but i wasn't really experienced enough when i tried it, maybe i'll give it another go sometime
so basically, i can set the presets myself but the user won't be able to customize them, unless they change the code
yeah, pretty much - you could have it load from a config file or something but that seems totally overkill
yeah, i was worried it wasn't a thing since no mod has it, damn. Thx anyways
Well maybe you can help me with something else, when i create a new option it always goes at the bottom. I dont know what i did before but i did manage to put them at the top or between, but now i can't
i think they just appear in the order they're defined in the sandbox-options.txt
yes, they do but since i can't edit the mod's file i have to do it from mine
i created the same options and put mine in between in hope they overwrite the originals but they just duplicate
i tried this at first and it worked, but now they just go at the bottom
I'm trying to make a recipe that uses the moveable Broken Glass as a ingredient, but it's not working. my module already imports Base, and Base has items with the same ID as the moveables. I tried specifying the movable by saying Moveables.brokenglass_1_0 instead of importing Moveables, but it doesn't work. can anyone help?
i have a mod installed that adds recipes using them that refers to them that way
Moveables.brokenglass_1_0/Moveables.brokenglass_1_1/Moveables.brokenglass_1_2/Moveables.brokenglass_1_3,
did you just import base or base and moveables?
that mod only imports base
okay thanks
Base and Moveables will be two different items. Often Base is from debug spawns and people who make recipes that give Base instead of Moveables.
Hi, I'm still hyped by Soul's quest system. I added a quest to Ring mod. https://steamcommunity.com/sharedfiles/filedetails/?id=2973057711
i now have it outputting an MD reference file https://github.com/demiurgeQuantified/PZEventDoc/blob/develop/reference/Events.md
👀
Umbrella EmmyLua Project
Does getPlayer have different behavior if you are a client?
getPlayer() always returns the local player 1
So, even if I'm a client, get player will always get my player, right?
yeah
Okay thanks
it will not get other local players if playing in splitscreen
That is good enough for me
Does anyone know a clean way to force some code to happen on the next tick?
You'd have to store the params in a table and count the delay
I tried, this and did not work
local event
event = function()
getPlayer():resetModelNextFrame();
sendVisual(getPlayer());
Events.OnTick.remove(event)
end
Events.OnTick.Add(event)
Remove should be capitalised
I use a table with timestamps and params to run things later
Can you give me an example?
Is this for 1 function or many?
For one function please
did it move anywhere?
local delayedCall = {}
delayedCall.events = {}
function delayedCall.addEvent(ticks, ...)
local event = {ticks=ticks, args=table.pack(...)}
table.insert(delayedCall.events, event)
end
function delayedCall.parseCalls()
for k,event in pairs(delayedCall.events) do
if event and event.ticks then
if event.ticks > 0 then
event.ticks = event.ticks-1
else
local args = table.unpack(event.args)
print("event.ticks: "..event.ticks, args)
delayedCall.events[k] = nil
end
end
end
end
Events.OnTick.Add(delayedCall.parseCalls)
This snippet is untested, but I've done something similar to this for my zombie AI
Thank you! I'll give it a shot and let you know 🤗
Not really happy with leaving the entries going nil, but ending entries of nil get removed -- so eventually the table should shrink to {}
oh typo
ticks=1 -> ticks=ticks
using ... should mean you can add as many arguments you want
they all get packed/unpacked
direct references can't be saved tho - so be mindful
Okay thank you, this makes sense
I'll look into it in a bit, because another bug just happened
And I think it's related to the sendVisual
Yeah, I need a way to get my workflow to occur when PRs are merged
I was using something that checks the branch's name as hotfix but this is kind of tedious if the person doesnt know
So I figured there might be a way to scan the PR's title or body
Then I could edit it as needed
Was looking at this: https://github.com/marketplace/actions/check-pull-request-rewiew-comments
Ah, nope, sorry mate,that's very much out of my knowledge of github actions
That's ok
nothing as of yet, partly due to uni but we wanna try again over the summer
Is it common for zomboid to not sync clothings between clients?
Merged to any branches, or a particular one? https://github.com/orgs/community/discussions/26724 suggests restricting direct push to main/master + triggering on push
It's for community projects
I have the action triggered on schedule for fridays at midnight
but I also wanted to make a caveat for hotfixes
the action uploads the project to workshop
rn what I have is that it fires on push if the branch has hotfix in the name
seems to fire multiple times because of this tho
Strange. I've only used GH Actions for testing & linting so I'm not too sure
Question, can I have 2 workflows? I see that it's named main.yml
I was wondering if that pertains to the branch name
Yeah, you should be able to include multiple workflows. I don't remember the naming scheme for the files, but I had one for unit tests & one for making sure the example file runs correctly on one project, for example
Just checked and it's just called test.yml in that project, so I think that's just used as the workflow name (if not specified with name:)
ah ok
OMFG I FUCKING DID IT
TRANSMOG SYNC IN MP
All because of ONE line of code
sendClothing(player); instead of sendVisual(player);
wooooooooooo
For LUA Modders
https://github.com/Konijima/project-zomboid-studio
how do i delete an inventory item?
and is there a way to detect when an item is being consumed or deleted before it happens?
container:Remove(item) if it's on the player
container:removeItemOnServer(item) if it's not and it's on MP
thanks
Nitpick: "Lua", not "LUA"*. I'd also recommend use of the LuaLS extension rather than EmmyLua, but that's neither here nor there. Looks useful 😄
* I don't make a habit of prescribing how things ought to be written, for the record. I think there's good reason in this case, though; see the "What's in a name?" section on https://www.lua.org/about.html
i saw that as well, i'm gonna check it out later. i've been doing all my modding in notepad++ so far
Hey, if it works it works. I didn't even use Intellisense for years but now I'm a sucker for a nice IDE
oh right thanks
Here's how quick it is to get started
Can anyone explain this behavior to me?
Changed a metatable entry to point to a new function. Said function runs fine when called in game, but seems to run the old function and not the new. No errors
Specific details pls
wait a minute
is there a set metatable function??
give me a minute you may have been my rubber duck haha
what are you trying to change the metatable for? the metatables are a lua thing, so if you change a metatable it won't change what happens when that method is called from java
**local metatable = getmetatable(zombie.characters.traits["TraitFactory$Trait"].class).__index
local originalGetTraitDescription = metatable.getDescription;
metatable.getDescription = function(self)**
local descAndTags = originalGetTraitDescription(self);
local indexOfTagsBegin = strFind(descAndTags, "||");
if indexOfTagsBegin ~= nil
then
local description = strSub(descAndTags, 0, indexOfTagsBegin);
return description;
else
print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
return descAndTags;
end
end
**metatable.getTags = function(self)**
local descAndTags = originalGetTraitDescription(self);
local indexOfTagsBegin = strFind(descAndTags, "||");
local lastComma = 1;
local tagTable = {};
if indexOfTagsBegin ~= nil
then
local tags = strSub(descAndTags, indexOfTagsBegin);
for i=1, strlen(tags)
do
if tags[i] == '' or tags[i] == ','
then
table.insert(tagTable, strSub(tags, lastComma, i));
lastComma = i;
end
end
else
print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
return tagTable;
end
return tagTable;
end
**setmetatable(zombie.characters.traits["TraitFactory$Trait"].class, metatable)**
Okay, I'm not facing the same issue anymore. Now i'm getting an error saying "Could not set metatable for object"
I've bolded the important lines above, but include the whole bit where i'm modifying it for context
or... put asterisks around them in the lua, not bolded them I guess
This is for Trait descriptions, at least when it gets shown to the player which, as far as i've seen, is all lua. My goal here is to add tags to the end of descriptions for use in filtering visuals on the character
🤔 do you guys think this solution is too hacky? I wanted to bundle this into its own mod so other modders could use the tagging idea but. Maybe it's not best-est practice
Have you tried __classmetatables[zombie.characters.traits["TraitFactory$Trait"].class].__index? Setting the metatable wouldn't be the solution anyhow; if it worked it'd just set it to the same metatable
I'm not intimately familiar with the exposer code so I'm uncertain as to what metatable would be associated with Class objects, but I've used __classmetatables successfully
I think it'd maybe be cleaner to offer a way to define tags for traits that doesn't bundle them in descriptions, so implementers could have your mod as a soft dependency
you could just use a table, i'm not really sure what the benefit to this description method is
I'll do this then. Thank you both
So I was trying out ChatGPT and asked it how I could create a list of presets containing diferent values for some options of my mod and it throwed this:
Events.OnFillWorldObjectContextMenu.Add(function(player, context, worldobjects)
local sandboxOptions = SandboxOptions.getOptions()
local enumOption = {
name = "MyEnumOption",
label = "My Enum Option",
tooltip = "This is an example enum option with presets",
type = "enum",
values = {
{ text = "Presets 1", value = { "Advanced_trajectory.fireoffset" = 10 } },
{ text = "Presets 2", value = { "Advanced_trajectory.fireoffset" = 11 } },
}
}
table.insert(targetPage.options, enumOption)
end
SandboxOptions.setOptions(sandboxOptions)
end)```
What's the error here?
Don't rely on chatGPT too much for Lua code, mostly because ChatGPT isn't as well-trained on LUA as other major programming languages.
Also PZ has its own flavor of Lua, which makes it even more difficult to debug.
On a personal note, I always add a semi-color ; to mark the end of a statement... it's clear the gpt generated code has no closure.
oh thx, i know i can't rely too much on it, just wanted to learn a bit by asking questions. Don't want to bother too much here
what i dont understand are the missing symbols
they all seems to close
well, someone told me that what i wanted to do was impossible so it probably doesn't have solution anyways
It's been asked many (many many) times. I finally made an Auto Eat mod. Yes, despite the fact Chuck already made one. Tech details in the description. https://steamcommunity.com/sharedfiles/filedetails/?id=2977628726
just wondering if there is any way I can determine if a door is metal
I could try and hardcode a value for each door, but I want to keep compatibility
at worse you could check the spriteName and compare to a list of metal-made doors. but this won't work for mods you have not specifically taken into account
you could parse the recipes to find those allowing to create the door and check if metal is used for its creation
You could try to use getThumpSound()
---@param door: IsoDoor
function isMetalDoor(door)
local thumpSound = door:getThumpSound()
local isMetal = thumpSound == "ZombieThumpMetal" or thumpSound == "ZombieThumpGarageDoor"
return isMetal
end
Another question, how do I save data, like number of uses on an item for example
That begs another question, do you intend to load said saved data? Saving and Loading are 2 different actions.
The way I've learned was to use getFileWriter or getModFileWriter to create the potential save file https://projectzomboid.com/modding/zombie/Lua/LuaManager.GlobalObject.html#getFileWriter(java.lang.String,boolean,boolean)
https://projectzomboid.com/modding/zombie/Lua/LuaManager.GlobalObject.html#getModFileWriter(java.lang.String,java.lang.String,boolean,boolean)
then using the respective getFileReader and getModFileReader to load the potential save file.
https://projectzomboid.com/modding/zombie/Lua/LuaManager.GlobalObject.html#getFileReader(java.lang.String,boolean)
https://projectzomboid.com/modding/zombie/Lua/LuaManager.GlobalObject.html#getModFileReader(java.lang.String,java.lang.String,boolean)
Other people may have better ideas.
Also, you can use Events.OnPostSave.Add(<function>) to save the data whenever the game saves.
Believe me, don't write and save shi* more than you need to while the game is running - it will really ruin your in-game performance.
Disclosure: I did that to debug a few things, so I learned the hard way.
You can save into global modData or into player modData.
If you want that data to die with the player character i suggest using the player modData. If that data needs to be networked use the globalModData
@pseudo jetty @lone nest
--- Quick example
local playerModData = getPlayer():getModData() -- get player mod data
playerModData.itemUseCount = playerModData.itemUseCount or {} -- set the table to save the item usage count
playerModData.itemUseCount[itemFullType] = (playerModData.itemUseCount[itemFullType] or 0) + 1; -- increment that number
---
--- Function to increment a local player item usage count
function addPlayerItemUsesCount(playerNum, itemFullType, amount)
local player = getSpecificPlayer(playerNum)
if player then
local playerModData = player:getModData()
playerModData.itemUseCount = playerModData.itemUseCount or {}
playerModData.itemUseCount[itemFullType] = (playerModData.itemUseCount[itemFullType] or 0) + amount;
end
end
--- Function to get a local player item usage count
function getPlayerItemUsesCount(playerNum, itemFullType)
local count = 0
local player = getSpecificPlayer(playerNum)
if player then
local playerModData = player:getModData()
if playerModData.itemUseCount and playerModData.itemUseCount[itemFullType] then
count = playerModData.itemUseCount[itemFullType]
end
end
return count
end
player dies, the item usage count dies with it.
If I remember correctly, this event isn't actually triggered on every save. I believe it was just when quitting. I'll have to check on that
Does anyone have info on Zombie HP and Damage Calculation from firearms? After probing guns, I see they have a lot of stats. Crits are kinda throwing me too, as whatever mod I have that's logging damage, is saying this thing crits from anywhere between like 1.2 to 8+ damage
Even though it's a gun that, by default, only does 0.3 - 0.6 damage
Probably doesn't help this is Gunfighter/Brita's too, so who knows what that changed
the damage might depend on the hit body part
i saw some code about that, seems like the game does track that even though it's not in your control at all
hmm, it looks like the super big hits only happen when they're downed
i think the game is pretty much always saving data whenever it becomes irrelevant, quitting is just when it does a 'full save'
And now I just did loads of damage without a crit, interesting... It must be body parts.
or some weird brita thing
yeah going to try the same tests without brita/gun fighter
nope, that's vanilla 😅 So there's min/max damage, crit multiplier, crit chance AND then also body part hits it seems
as you can miss a crit yet still over kill in a single shot, with 0 aiming skill and the worse weapon
hmmm, doesn't seem like bodypart is actually used for damage calculations
No? Weird. I'm seeing some huge numbers on weak guns without critting
PZStudio Update 1.1.0
Effortlessly create and maintain Lua mods for Project Zomboid with this intuitive tool.
Require:
NodeJS LTS: https://nodejs.org/en
Commands:
Install Globally: npm install -g pzstudio
New Project: pzstudio new "My New Mod"
Move into project: cd "My New Mod"
Set output dir: pzstudio outdir "C:\Users\Konijima\Zomboid\Workshop"
Build: pzstudio build
Build & Watch: pzstudio watch
Creates a project in a single command, you then focus on developping your mods.
The build commands generate and structure your output mod into your Workshop directory.
No more manually copying and setup when making a mod.
Yeah—it's the OnPostSave event that's misleading because it actually fires on exit. Just double-checked and it's only triggered from GameWindow.exit and IngameState.updateInternal (when exiting)
yeah, that's what i saw when i was writing the event schema
Oh, I should've just checked that 😄
i'm not sure if i specified that in my documentation, it might just say something useless like 'fires after saving'
It says saving & exiting, which could have the interpretation of firing on either but I think the intended interpretation is more likely to be understood
As someone who’s just dipping toe into modding and experienced hiccups earlier on than I had anticipated (but I guess that’s always the case with programming) I’m kinda excited to try it!
If you have question, issues or suggestion don't hesitate to write to me.
I provite an option to mute a sound in my mod. But there is a kind of a bug in multiplayer. How to mute specific sound for the player AND the same sound from other players? And how to not mute the sound from other players, if the player did not mute this sound?
instead of letting the sound manager handle the networking, play the sound locally only and use commands to tell other clients to play the sound, which they can ignore if it's muted
Good morning.
fascinating, Hm... i wish documentation was/is better... I'd like to better understand how it works.
When Events.LoadGridSquare.Add(<function>) is called, How often is said function called?
- Does it attempt to load ALL known squares the player has explored? (Which worsens the more the player plays)
- Or the entire PZ map squares? (Certainly hope not)
it is called for every square in a chunk when the chunk is loaded
chunks are only loaded within a certain range around the player
depending on the cell size that means you have up to 13 ?, 26? chunks loading at the same time. Chunks are 10 x 10 x 8 as well, though not everything has a square object and will not call this event.
@low yarrow this is a more appropriate place for the topic but ya the API takes the speed counter of the vehicle and replaces the model based on how high the speed counter is
which makes it hard to notice that it is only switching between 4 static models
Hey what decides if a ground model spawns or not? its just in scripts right?
ya the ground model is just the model that appears when the item is dropped
For some reason its not working on my mod. I just see the icon
which is more helpful on weapon's and ect, to where the model in your hands wouldnt look that good when placed on the ground
I know its not the model, I swapped it with the model of another mod to see
interesting... is there a way to limit the range or calls?
then the games probably not detecting your models and just defaults to the icon
I think
for example, only load the the specified squares given the square input?
im having a similar issue too where the game isnt detecting my ground model and idk why
do you mean forcing squares to load or only calling your event on certain squares loading? well the answer to both is no anyway
Damn, alright, hm. here I was hoping to feed a square parameter and remove the event right away to speed things up
there are some apis that have a single loadgridsquare handler that then call functions you add to them for certain squares but there's no direct way of limiting loadgridsquare calls
Oh? that might work for me on a single load square
i haven't used any of them so i can't direct you to them unfortunately
they should be a decent performance save though
nvm the game seems to want to now idk why lol
No problem, I just need to know which APIs are available! I'll be happy to share what I find through my pain and suffering.
WHAT HOW
what did you change in your code?
I have been testing this.
https://steamcommunity.com/workshop/filedetails/?id=2969455858
What are the other options?
i was referring to things the community has made, i don't think the game has anything like that
b42 is promised to have a loadchunk or something so *eventually*...
my games giving me mixed signals
the model changed, but I tried to change it again and now those changes arent applying
I have the ground pooling from the correct model, but any changes I do with the actual model itself doesnt appear ingame.
not even the scale change applied
it use to be 0.13, i changed it to 0.012
and it still shows as 0.13
I have no clue why that stuff just isnt working
restarted my game multiple times and none of the changes I do even work
Thats where I'm at right now
I can make changes to other stuff but ground is unaffected no matter what I do
even though if you are debug mode you shouldnt have to even make a new save to see changes, it happens in real time
Yeah! Thats how I was able to test defense changes and model names (when I typed it in wrong)
worked fine for other weapon's, but when i try to replicate exactly what I did, it just doesnt work
shouldnt be, this is my model for a rifle that let me change the ground model position
and this is the ground for a axe that wont let me
Yeah those are the same...
ya exactly
SameZ!
module Base
{
item Jacket_01-Black
{
Type = Clothing,
DisplayName = KP Jacket (Black),
ClothingItem = Jacket_01-Black,
BodyLocation = Jacket,
BloodLocation = Jacket,
Icon = Jacket_01-Black_Icon,
RunSpeedModifier = 0.98,
CombatSpeedModifier = 0.97,
ScratchDefense = 60,
BiteDefense = 30,
Insulation = 0.4,
WindResistance = 0.8,
WaterResistance = 0.6,
Weight = 2,
FabricType = Cotton,
WorldStaticModel = Samurai_Jacket_ground,
}
}
This works
but this doesn't
module Base
{
item Jacket_samurai_classic
{
Type = Clothing,
DisplayName = Samurai Jacket classic,
ClothingItem = Jacket_samurai_classic,
BodyLocation = Jacket,
BloodLocation = Jacket,
Icon = SteamGuideJacket,
RunSpeedModifier = 0.98,
CombatSpeedModifier = 0.97,
ScratchDefense = 60,
BiteDefense = 30,
Insulation = 0.4,
WindResistance = 0.8,
WaterResistance = 0.6,
Weight = 2,
FabricType = Cotton,
WorldStaticModel = Samurai_Jacket_ground,
}
}
is anyone please able to assist us?
i'm as confused as you are
might be possible that the formatting is whats causing the issue
Sorry guys, quick question. What is exactly a 'timed action'? How would you define it?
An action that can be inserted into a character's action queue that may either take a certain amount of time (thus, timed) or be indefinite
ill give it a try
Thanks. So like, opening a can would be a timed action, and it takes defined amount of time (not in seconds afaik). Does anyone know what exactly is the metric for this number? If it is not seconds, what is it(?)
I don't know whether there's a metric that it uses; it's based on ingame time which can vary
Actually wait whats wrong with the formatting?
I tried to move my model into the static folder itself instead of a sub folder in static, and it still doesnt work
the spacing is really inconsistent, but the parser should trim all the spacing out anyway
this
i'd recommend changing that for readability's sake but it shouldn't be causing your issues
idk i remember one time it caused issues for me
Discussed this a bit before here #mod_development message (and I was equally vague then unfortunately)
it's really odd
Thanks a lot Omar! Very helpful.
the one place i can find the timer for timed actions being used implies that 1 time is 1.25 seconds, but a simple test will show that's clearly not correct
I remembered seeing that it used a multiplier in GameTime but I didn't have the time to dig in and get an exact answer
And I'm currently not at my home computer to do so either
yeah, that multiplier should be a delta that adds up to 0.8 a second
but timed action time is clearly much faster than real time, not slower
the read action can scale it to real in-game time
if I haven't made any errors it's like this
o.maxTime = minutes * 2 * getGameTime():getMinutesPerDay()
* sorry, that's in-game time that I was targeting
yeah, offhandedly that seems to add up
.....that fixed the ground issue
just gotta figure out why mine doesnt work
ye its just how brackets work, they wont read anything on the same space as it, it has to be tab spaced once to the side or something like that
You use vscode to do zedscript yet you don't use my extension..
i had no idea the parser actually required it, i thought i'd seen the code behind that, i was just doing it for readability

huh?
just use notepad like a chad
That makes sense but that really sucks lol now I just have to fix the floating model lol
Good luck with that.
oof, its just tweaking the model from there
my model isnt being read at all and i have no clue why
Have you tried swapping the names to make sure it works with the other weapons code?
just as a double check I mean
ok so it is something wrong with my code
tried to make the model one of my rifles and it didnt work
ah, i crossed some wires - that delta does just add up to 48 a second (which follows the formula posted)
Brightside its just this one weapons code then
nah its all of em lol
I tried with other weapons and it didnt work
oh
wait so is this bugged too?
thats the thing
that one isnt
all my rifles arent bugged
but the melee weapon's are
Okays thats really weird..
Can someone please link me documentations on how to create buttons and panels?
I see ISPanel, ISButton, etc... but there are no documentation on what events/functions are available
fml
NONE
of my 2 recent mods work
not mods
items
could it be that some of my files are fbx and others are .x
You’d have to look through vanilla code there is no clear documentation of what those doe

But both IsButton and ISPanel have all the necessary calls needed to make a custom ui
There is also ISScrollinglistbox to have a scrollable window with items in it
Thanks, now I'm trying to find vanilla code, where do I start?
if I'm interested in making a mod, is the this the best place to start learning? - https://pzwiki.net/wiki/Modding#New_modding_page,_under_construction
Look through anything that uses ui and buttons honestly
ISItemsListViewer (found in AdminPanel Folder) uses ISPanel, ISComboBox, ISTabPanel and ISButton for example.
Could it do with worldstatic model
and the wsm being the normal one you made in bledner
I can rotate it in the script?
I need a drink.
cuase of me?
Hi, is there a way to force the reload of a texture ? (when I do getTexture it works on a cache memory while I changed the pic source)
this would avoid to restart the game each time I do minor changes
Texture.reload("pathToMyTexture.png")
Have you tried it successfully. I may be wrong, but it seemed not to work.
it works for me
ok, thanx:)
So in the vein of our convo the other day I wanted to add trait tags in a different way, so I made this:
TraitTags = {}
local function sanitizeTags(tagString)
--remove all spaces
local workString = tagString:gsub("%s+", "");
--remove control characters
workString = workString:gsub("%c", "");
--remove hexadecimals
workString = workString:gsub("%x", "");
--remove.... zero...?
workString = workString:gsub("%z", "");
workString = workString:gsub(",", " ");
--remove all punctuation and symbols
workString = workString:gsub("%p", "");
--replace spaces with commas
workString = workString:gsub(" ", ",");
return workString;
end
--Uses alphanumberic symbols and commas only.
function TraitTags:add(traitName, tags)
local sanitizedTags = sanitizeTags(tags);
local tagTable = {};
local prevComma = 0;
local currChar = '';
if TraitFactory:getTrait(traitName)
then
if string.len(sanitizedTags) > 0
then
print("Trait Tags: inserting table entry "..traitName.." to TraitTags.");
table.insert(TraitTags, traitName);
print("Trait Tags: adding tags "..sanitizedTags.." to "..traitName" entry.");
for i = 1, string.len(sanitizedTags) do
currChar = sanitizedTags:sub(i,i)
if currChar == ','
then
table.insert(tagTable, sanitizedTags:sub(prevComma + 1, i));
prevComma = i;
elseif i >= string.len(sanitizedTags)
then
table.insert(tagTable, sanitizedTags:sub(prevComma + 1, i));
end
end
table.insert(traitName, tagTable);
else
print("Trait Tags: No tags detected for "..traitName..", skipping...");
end
else
print("Trait Tags: Cannot find trait "..traitName..", skipping...");
end
end
function TraitTags:remove(traitName)
if TraitTags[traitName]
then
table.remove(TraitTags, traitName)
else
print("Trait Tags: No entry found for "..traitName..", cannot remove. Skipping...")
end
end
function TraitTags:getTagTable(traitName)
if TraitTags[traitName]
then
return TraitTags[traitName]
else
print("Trait Tags: No entry found for "..traitName..", cannot get tag table. Skipping...")
end
end
function TraitTags:toString()
local returnString = "";
for trait, tagTable in ipairs(TraitTags)
do
returnString = returnString + trait + ": "
for _, tag in ipairs(tagTable)
do
returnString = returnString + tag + ", "
end
returnString = returnString:sub(1, string.len(returnString) - 2);
returnString = returnString + "; "
end
return returnString;
end
function TraitTags:tagTableToString(traitName)
local returnString = "";
if TraitTags[traitName]
then
for _, tag in ipairs(TraitTags[traitName])
do
returnString = returnString + tag + ", "
end
returnString = returnString:sub(1, string.len(returnString) - 2);
return returnString;
else
print("Trait Tags: No entry found for "..traitName..", cannot stringify tag table. Skipping...")
end
end
I wanna set this up as a dependency for my AnthroTraits mod--how do I do that? I don't see anything about that in the chat history or on the wiki
at least, that I can see. I can't test this until I figure that out hahaha
Also if any of you sees something that's glaringly wrong your input would be appreciated
You can add a require= line to your mod.info to specify mod IDs to require. I'm not sure about the equivalent to specify that on the Steam workshop
Ah. "Add/Remove Required Items" on the workshop page for that
As for code review, a few things:
- I would argue against making your module global. You can return it and expect implementers to require it
- Some of the
gsubcalls insanitizeTagscan be consolidated;workString = workString:gsub("[%c%x%z]", ""). I wonder, though: why are you removing hexadecimal characters, anyway? That will get rid of 0-9 and a-f- Actually, after a second look... if your goal is just to get rid of all characters other than alphanumeric characters and commas, you can use a negated character set instead to replace all of the logic in that function. i.e.,
tagString:gsub('[^%w,]', '')
- Actually, after a second look... if your goal is just to get rid of all characters other than alphanumeric characters and commas, you can use a negated character set instead to replace all of the logic in that function. i.e.,
- This is not a review comment, but a clarification:
%zis for the null character,'\0' - In
add, you could negate your conditions and use early returns to decrease the nesting level. That is:
if #sanitizedTags == 0 then
-- print and return
end
-- continue
(this pattern is possible for all if statements in that function except the one in the loop)
- You can use
string.splitfor your comma splitting logic inadd table.removeinremovecan be replaced withTraitTags[traitName] = nil, but no problem keeping it as-is- You're using
+intoString; I think you meant... Also, it would be best to add the elements to a table then usetable.concat, rather than concatenating repeatedly. This will create unnecessary intermediate strings. Not a big deal, just an easy improvement tagTableToString: see previous note
Meant to reply
Hey, how do I get a zombie to turn towards a specific square, or position?
IsoGameCharacter has a faceLocation method which may be what you're looking for, but I don't know how well it interacts with the AI (that is, the AI may make it stop trying to face that location)
i need help
Rather than simply declaring that you need help, it's nice to describe what exactly you need help with 😄 We can skip the "what do you need help with?" and get straight to trying to help
i usally wait till somone answers me aha
but my items wont apear ingame
its been like this for a month
its actually 2 items
but i may know the issue
When you say they don't appear ingame, do you mean they just won't spawn, or that they don't show up in the item spawner in debug mode?
item spawner
i just want to confirm i cna use .fbx and .x