#mod_development
1 messages · Page 368 of 1
Im porting a 260 line function. I hate it lol
if they had broken it down into smaller useful functions I wouldn't have to -_-
And I’m happy to hear why I’m wrong
700 lines isn't too bad... but yea I start feeling like iv done something wrong when files exceed 1000 lines
I'm not sure there is a right or wrong to that sort of thing, more appropriately "advisable for X reasons" and "inadvisable for X reasons"
Good development enviroments also make large files easier to handle
Sure - if you load files - cache it but otherwise break it up unless it creates a lot of method/function calls
Basic C says don’t call functions in a loop
this was me for carwanna but instead I just decided to rewrite the entire mod because it irked me so bad
so much boilerplate
i've come to believe that rewrites might be more valuable than refactors in a lot of cases
Not gonna lie - I wanna rename files and functions but I feel like I need to own it
if you know how to do something better the old structure is quite likely to hold you back
with the horse mod we kind of ended up in a spiral for a bit where we would refactor things we already refactored because it still wasn't good enough
half the time programming is just redoing things over and over as you get more insight
whereas the ground-up rewrite modules have stayed pretty solid
I’m gonna give the original mod credit forever - I think it’s the right thing to do
If they didn’t do the thing they did I wouldn’t have done the thing I did
there's no downside to thanking someone, even if a mod was purely inspiration it's the nice thing to do
I haven’t put it on the workshop yet but I’ve already put the link in the code
Beyond nice - in my core it feels like the right thing
Speaking of such - I asked myself why there are so many iso objects
ISO means something different for me then I realized ‘Indie Stone Object’
Isometric
The actual game style
yes but i think its ISOmetric
i cant see why they would name it Indie Stone Object when their package name contains their unique stuff
Okay - I’m new here but (inserts opinion)
They seem to really want people to understand why you should name things with your own prefix
I have to imagine there are a huge amount of mods created by people who don’t know the word “instantiating”
But they still created something cool because the entry level was low
it's definitely Isometric but i think some of the people they hired on didn't know that and it ended up assigned to a lot of nonsense
for their lua classes, IS stands for Indie Stone, but most mods name their classes IS.. too 😅
I’ll fight you over this
The IS prefix is just for Indie Stone
Isometric isn’t part of that
/me punches limp plastic bag
IS is yeah
like ISObject or ISPanel, thats to avoid collisions with their loading the lua files
which you can avoid totally by just putting your lua files in a subfolder with your mod name
I’m still not sold on lua unless you have a bunch of automation tools
its one of the best and easiest ways to sandbox
Also they seemed to, I’m new, give a ton of access via lua
There’s a part of me that wants to deep dive that
for example you can't use most of the os things in lua, or any debug things
Just to open source and expose
and you cant just call some java function to get remote code execution on the player's computer
not to mention how easy lua is on a level of just pure language
of course I mean that as in, not exploiting any TIS provided functions
I haven’t seen an eval or whatever yet
I enjoy using Lua*, especially with type annotations. Much quicker and less boilerplate involved (coming from someone who's written a lot of C#, before top level statements were a thing)
*except for the lack of continue
Dotnet 10 has been fun
I think typescript could be a worthy contender (something Jab realised too) but to each language has its downsides
And I’m coming in fresh
I enjoy TS but I'm not entirely sold on transpiling it to Lua, for my own use anyway
As much as I’d like to see some version of ecma - just stay with lua
I think if people want to do it or even just experiment then they certainly should
But I personally agree
I mean the ecosystem out of the box
Imagine people debating over preact for the ui stuff
To clarify, the TypeScript thing isn't a suggestion for what the devs would move to—it was/is a project for transpiling TypeScript to Lua for PZ mods
i'm very fond of lua
I recall a friend who hasn't touched it asking me whether I like it or tolerate it & I came to the same conclusion
Legit Omar - that actually gave me some inspiration
I just don’t want to go from lua to ts
But ts to lua
there's a couple things i definitely don't like about it (how globals work, lack of typing) but overall i find it quite easy to work with and very flexible
I didnt mean TS stuff for implementation stuff, but javascript is easy to sandbox and typescript provides a good type system (i didnt mean transpiling but if TIS could go back, I mean)
Globals should die
Oh I guess it was the thing I said it wasn't lol
I think at the time they added mod support TS must have still been fairly new
It’s the worst thing someone new to programming should learn or see
I think it's just something misunderstood in many languages, although in many still the usual wisdom is “typically, don't”
Global should be an exception
lua 5.5 introduces a keyword that lets you remove globals from a scope entirely (lexically) but it's still global by default
and of course we'll never be using lua 5.5 in pz
i swear as soon as you mod a game once its like cursed forever and almost impossible to play again
ive been getting into deadlock again but all i can think about it making custom skins now whenever i play it
you're cooked
There should never be a variable in scope that you didn’t know about or intend (corporate mind) but I understand games are more fun in that way
The joy of creation just seems to beat the joy of play every time (but man, really need to make some time to play eventually... one more mod change)
i'm strict 'no globals' too, i've just accepted it as an avoidable flaw of the language
you can have language servers tell you off for writing globals which usually catches accidental usages
but i do find the design of 'global by default, local with a keyword' absolutely baffling
I got bit in my early dev life with “change at* a distance”*
no global on other mods makes it very difficult to patch / alter
if they use modules it's fine
I’ve already made modules when I decided I’m taking it over
i'm admittedly guilty of not including plenty of my variables in the module though but if i were using a global instead i'd do exactly the same thing
Lua accessors?
I may have a gap with modules, I never know when I'm isntanciating new stuff and when I'm accessing the instance I want
modules dont need to have an instantiation structure
you can just use modules like any other
You should toy with that until you understand
I took over a mod that’s most important part was a lua table and I broke all of that out into its own file
If it changes again I hope to fix one small file and move on
Simpler than it may seem:
-- ModuleA.lua
local ModuleA = {}
function ModuleA.doThing()
print('did the thing')
end
return ModuleA
-- ModuleB.lua
local ModuleA = require 'ModuleA'
ModuleA.doThing()
Literally what I did
so is it one instance of ModuleA for each require ? Or is it a "singleton" ?
Instances aren't really a thing here
If there's no metatables or otherwise faked “classes” involved it's just a table
I was gonna say assigning is the instance
Oh I misunderstood the question because I read the word instance lol
Yes it's a singleton in that sense
As far as accessing and garbage collection it seems to be handled nearly the same
Unless you say local - it’s a god object
But that's more a question about how require works—once it's called once it'll reuse the return value of the first require (details excluded in this simplified explanation, and the details are also different for Kahlua)
Which is a great feature
And everyone should read that
It’s important
That was literally my low hanging fruit when I was bringing this mod up to date
require does two things:
- run the file if it hasn't been run already
- return whatever the file returned whenever it ran
since tables are always passed by reference in lua, a file that returns a table always returns the same table to all requires
local details = require(“structuredTable.lua)
Didn’t even think about point 1
Cause my file just returns
But another solid point
Also in a game are we thinking about the filesystem that much after it loads?
Generally the file system is just reload state and then* we doing it live
because lua files are functions, load order can be more important than it intuitively should be, and require can be used to manipulate that
Sure - you got an exploit in mind? Otherwise it’s base game then mods - which seems to allow monkey patching - totally cool - then whatever user is the *
running *the gui
I run a server in a container so i refuse to care as much as I should
I imagine it was “manipulate” in the sense of “control,” without the negative connotation—so not something to exploit, necessarily, just something to use to affect the load order
That was my interpretation, anyway
...Outfits are tricky. Am struggling a bit with getting them to 'stick' on a spawned zombie.
Half the time they seem to revert back to randomised attire.
Oh.. so im not supposed to name all my UI files with IS?
and.. timed actions?
Well.. shit.
Anyway, spices now work for my new cooking menu, yay.
now to rewrite how happiness actually works when cooking...
Make it actually based on cooking skill and time spent cooking instead of... how many random ingredients you managed to cram into one meal
Anyway, Good day 1 development of mod.
Now more or less processes cooking like vanilla does.
(though I suspect adding poison is broken since its a private function to addpoision and I have to port that to LUA too but meh)
<player tries to troll other players by poisoning food, gets trolled instead because I never got around to fixing that>
Also, hu at the math for extra items...
local changer = 0;
local extraItems = baseItem:getExtraItems()
if extraItems ~= nil then
for i = 0, extraItems:size()-1 do
if (extraItems:get(i) == usedItem:getFullType()) then
changer = changer + 1;
end
end
end
if extraItems ~= nil and extraItems:size() - 2 > cookingLvl then
changer = changer + extraItems:size() - 2 - cookingLvl * 3;
end
...
baseItem:setUnhappyChange(food:getUnhappyChangeUnmodified() - (5 - changer * 5));
if baseItem:getUnhappyChange() > 25.0 then
baseItem:setUnhappyChange(25.0);
end
Im... Honestly confused by the intent of the middle part.
if extraItems ~= nil and extraItems:size() - 2 > cookingLvl then
changer = changer + extraItems:size() - 2 - cookingLvl * 3;
end
seems to suggest it would increase the penality at very low cooking level... but maybe decrease it at certain higher levels but not if your too high?
like I feel they forgot to math.max(0, extraItems:size() - 2 - cookingLvl * 3)
also, TIL there is: local nutritionBoost = cookingLvl / 15.0 + 1.0;
so in vanilla, level 10 cooking gives you.. 75% more calories?
no
the amount of food you take is also reduced and both multipliers are applied to the nutrition added
it does increase but not nearly as much as that would suggest
at level 10, the amount of nutrition actually goes down from level 9 (by an incredibly insignificant amount)
oh its part of the dumb math where a good cook uses LESS of an ingredient so you STILL HAVE TO CLICK AS MANY TIMES?
balanced out (not perfectly) by
local realUsedHunger = usedHunger - 3 * cookingLvl / 100.0 * usedHunger;
local percentageUsed = math.abs(realUsedHunger / usedItemFood:getHungChange());
you still get 75% more nutrition out of a whole food item but the amount you add to the meal each time is more like +30% iirc
at level 10, which nobody would ever be because cooking is pointless 😅
no you add less of an ingredient as you level up
like the UI says you use 10 hunger right?
yeah that's what i'm saying?
but at level 10 you only use 6 or whatever!!
AND ITS CURSED
because you'll have this stupid 4 leftover!
so your like cool, I'll use the 4
you get more nutrition but you add less so the amount of nutrition compared to base is not as high as the base nutrition multiplier
NOPE now you have a 1 leftover because it 'saved' you 25%
but after you've used the whole thing you will have had the full multiplier's worth of nutrition, it's just divided into more portions than base
and then you just rewrite the entire code from scratch in a fit of rage.
Like I just hate the idea that a good cook can get 'more' nutrition... Except by maybe like, not wasting so much when cutting vegis up? but that'd be like a cooking 0~3 skill issue.
it should be: a good cook can chop shit fast, without giving you food poisoning by chopping his finger off into your food in the process.
you might as well just remove the cooking skill is the issue
Nah, im going to keep cooking, but it will be tied to happyness of meals, and how long it takes to you to safely chop up stuff.
And.. chance of food poisoning, along with how clean you are
Like imagine: an actual reason to wash yourself/your clothing besides RP/looks.
Or change clothing when you get home -_-
the problem is the game doesn't have a real health system so i'm not sure if there's a point to that either
either it kills you (dumb and annoying) or does nothing
Im thinking that, at low cooking skill, especially if you 'rush' things, you'll have a chance of basically ruining a meal at making it add unhappyness instead of cure it. But thats still calories... So do you eat it, or dump it?
Sure, it will definately need some tweaking so it only makes you a bit sick and is like, an annoyance
maybe its own moodle?
thats drops your max HP/speed or something?
it'd have to be it's own thing, being sick doesn't do anything except kill you
Yea thats annoying as hell TBH -_-
good, good, good, dead.
theres no like.. oh im sick, I move slower, puke sometimes, etc.
i mean it bugs me too but when i think about it, it just doesn't make sense for this game to have a health system
It doesn't so much need a health system as just some of the intermediate moodles doing some speed/attack/etc debuffs and maybe drop your max health like being over carry weight does.
and like.... just a BIT at first.. unlike tireness/exhaustion....
I don't want -50% at first tier moodle lol, -20% is fine plz
-20% you can feel but isn't a death sentence... -50% outta nowhere is basically a death sentence since exhaustion per swing stays the same -_-
But id also be Ok with more moodles having debuffs.. Like why not give hunger/thrist some 10/20/30% debuffs to speed/attack.
Can I use the model parameters to rotate the models in game?
I have some time today, and I was planning on tackling this.
I assume I just tweak the rotate value right for attachment points?
Do I need to add a different attachment point for hand slots vs hip slots or back slots??
You can tweak most of those in B42, but you actually might need to adjust the back/hipslots too. Now if you were to make it correctly in blender, you don't need any of those
How do I tweak the back and hip slots? I didn't make these models in blender.
They were made by stalh who died. His mod was no longer working, and I started maintaining the rebuilt mod.
I'll need to learn the 3d model flow too. I wanted to add new armors, but the old armors are not working at the moment.
```
model G11Rifle
{
mesh = HKG11K2/G11Rifle,
texture = HKG11K2/G11Rifle,
attachment muzzle
{
offset = 0.0000 0.2655 0.0302,
rotate = -90.0000 0.0560 -180.0000,
}
attachment rifle_back
{
offset = 0.0000 0.0767 0.0394,
rotate = 0.0000 0.0000 0.0000,
}
attachment rifle_back_bag
{
offset = 0.0000 0.0810 -0.0066,
rotate = 0.0000 0.0000 0.0000,
}
}
Here is example of what i did with Rifle. You find attachment name/bone and adjust it with numbers or attachment editor
I'd recommend searching for vanila model scripts inside game files and see if any of the weapon models have something similar
Honestly i don't recommend doing it this way most of the cases
my gpt chat says that the id in mod.info should match the name of the mod folder, is this true?
It seems that 42.13.2 introduced an issue where mod data gets reset. I don’t know what triggers it. Maybe this is already known, but if anyone has more information, I’d really appreciate it.
Hey, someone know what that mean ?
craftRecipe CraftBarrelEmptyBiofuel
{
time = 600,
SkillRequired = Metalworking:2,
NeedToBeLearn = true,
timedAction = MakingHammer_Surface,
xpAward = Metalworking:100,
AutoLearnAll = Metalworking:10,
Tags = Biofuel,
category = Tools,
inputs
{
item 10 [Base.Plank],
item 4 [Base.Nails],
}
outputs
{
item 1 Base.EmptyBarrelBiofuel
}
}
this looks more like a broken mod behavior than vanilla behavior.
I’ve seen many reports across different mods over the past few weeks. Even a mod I haven’t changed since December has started getting reports. In my experience, it also happens with mod data—for example, I have to set mod custom keybinds again or reapply mod's sandbox options after a few sessions.
Are you playing lately?
afaik, custom keybinds are not related to mod data. same for sandbox options.
yes and since I have reports of problems that I do not reproduce on my mods, I check player mod data a lot and I have seen nothing of the sort.
yeah that's probably not anything to do with you
that would be three separate systems failing at once, somehow all caused by you
Yeah, but I also mean it seems unlikely to be a single global vanilla problem.
Use the documentation
servers just don't handle mods that well currently and also the average server host has always been kind of stupid so i tend to wait for reproduction before i even consider a bug real
damn it. my mod worked perfectly fine on my computer, but now that i put it on the workshop.. nothing...
I apologize for assuming it was something general. I’m probably mixing my own experience (where I clearly have an installation issue) with the reports I’ve been receiving in my mods.
I work as a designer, not as a programmer, so I don’t always know how to handle reports when I receive them.
guys how hard would it be for me to get into making a MP compatible mod that adds bone structures
thought I should ask before I leap into the rabbit hole
it should be a pretty simple thing unless I want to add new functionality assuming I spend the time to make textures, right?
i think the bone structures are currently disabled for mp
wait they exist?
what do you mean by bone structures? like constructions made of bones?
like walls and stuff
yeah that should be fine, shouldn't even need any networking code
I added a mod to my game that lets me get bones from zombies but I'm swimming in bones now and want to make or obtain a mod that lets me make bone walls and stuff
Going full primitive
might need to throw in a skull throne while im at it
turns out it was the stupid case thing - made the file lower case instead of camel case and it loaded just fine
if you cannot craft, check the /module/ because only Base is working atm
hey guys, have an issue with the ZomboidSounds.bank file that is the last roadblock hindering me from releasing my mod
I extract the .wav files using the FMOD Bank Tools application --> I replace the sound files with the ones I want to play in-game and made sure to rename my modded sounds in place of the default noises --> Rebuild the Zomboidsounds.bank file and put it back where it's supposed to go and yet surprisingly enough I go ingame and the zombies don't use my modded sound files, they use the ones that I thought were completely gone and replaced.
I think the issue is stemming from the rebuilding of the .bank file but I'm at a total loss. Any and all help would be appreciated.
If I can't figure out the issue I'll probably just release my mod without the reworked zombie noises so it's not critical that it gets fixed but I'd definitely prefer it.
Sure you replaced the correct files? And grabbed the correct .bank file after the rebuild?
I say this because for every sound zomboid has like 5~10 files -_-
I can tell you the noises I replaced one second
I replaced all of the zombie_sprinter_male_vocal_A and B aggro/death/idle sounds, same with the female versions.
Someone was saying sprinters also have a vocal_C but when I searched the folder there was no vocal_C variant
Ok, so whats the modified date on the .bank file you moved back over?
some of those .bank programs put their output in.. wierd places
Make sure it has changed size(?) or at least date
I should've mentioned that too, the rebuilt .bank that is supposed to contain my new sounds is the exact size, down to the byte, as the original .bank
I can check the modified date hold on.
which mod data? global mod data or of individual objects?
Okay I'm a fucking idiot, I was looking in the bank folder and not the build folder, the audio is good in-game and works as intended. Thank you for the help @willow tulip
NP 🙂 suspected it was something like that.
Hello!
I have a question about modding policy: does implementing a fix/file replacement via my mod on other author's mod that is "On Lockdown" violate mod permissions, if I post it for public (and if not for public, then by link only)? It's just I haven't found any clear information about that anywhere, yet I saw a lot of mods that do stuff like that. Don't really wanna barge in breaking the rules.
I think most modders are completly fine if you create addons/patch to their mods AS long as you still require actuall mod as dependency and not straight up copy/paste whole mod with your change. At least thats how i feel about it, but just to be sure i'd suggest contacting authors as it might be casebycase
I see, thanks for answering. Yeah, it might be casebycase as you said, so I'll contact the mod author then 🙏
- if the fix is just a hook, no problem
- If the fix is the whole mod/code with just few edited lines to comply with a specific PZ version you need author consent
(not to mention your not supposed to use anything without consent, even thumbnail, icons etc if not from the base game or explicitly granted
I personally don't mind any patches, if my original mod is required and i kinda feel honored, if someone uses my stuff for Screenshots/videos but i do appreciate credits
Sorry this is super late response but geez that's sick. Are you ever gonna release it the public because I would love to play a 28 years later inspired mod pacjk
Can't for the life of me get this mod to show up in the menu, it was on there for a bit but seems to have disappeared sometime after I put EmmyLua extension on(probably not actually related). It's got a common folder, I replaced the fields in the root mod.info and the mod.info in the 42 folder its just refusing to work
Oh I see theres a third mfing folder called mods
should be in %UserProfile%/Zomboid/Workshop not the steam folder
I am testing one of my mods in multiplayer and get the following error in the coop-console.txt:
ERROR: General f:9, t:1769896494815, st:1,517,785> GameServer.mainLoopDealWithNetData > Error with packet of type: GameCharacterAttachedItem for 1769896054173276 ERROR: General f:9, t:1769896494816, st:1,517,786> GameServer.mainLoopDealWithNetData> Exception thrown java.lang.NullPointerException: Cannot invoke "zombie.characters.IsoPlayer.getInventory()" because the return value of "zombie.network.fields.character.PlayerID.getPlayer()" is null at ContainerID.findObject(ContainerID.java:390). Message: Stack trace: zombie.network.fields.ContainerID.findObject(ContainerID.java:390) zombie.network.fields.ContainerID.parse(ContainerID.java:316) zombie.network.packets.GameCharacterAttachedItemPacket.parse(GameCharacterAttachedItemPacket.java:83) zombie.network.packets.INetworkPacket.parseServer(INetworkPacket.java:55) zombie.network.PacketTypes$PacketType.onServerPacket(PacketTypes.java:923) zombie.network.GameServer.mainLoopDealWithNetData(GameServer.java:1593) zombie.network.GameServer.main(GameServer.java:897)
Problem is that the error message does not show whether it is triggered by my code and if it is, what line of my code causes the problem. Any idea where this error might come from?
an item that does not exist on the server is being sent to a timed action's constructor
this may be to do with an attached item update rather than a timed action actually
I am indeed manually attaching items (gun to holster) but only on client-side. Maybe that causes the problem (although the gun is created before on server). Strange thing is that vanilla code also does this only client-side from what I've seen (and they even call syncItemFields() on client-side afterwards). But I'll just try doing the same in my code and see what happens...
Do you know where I can find the documentation on CharacterProfessionDefinition? I'm trying to see what other ways I can grab a profession then GetType() which, i'm not entirely sure what type is referring to.
Comes up with nothing when I search it on https://demiurgequantified.github.io/ProjectZomboidLuaDocs/classCharacterCreationProfession.html#ae0c695fdf93b151166af6875817f9bbe
Is there more steps to adding an occupation then defining it then registering it?
Its not showing up
Made a translation page for the text name/desc as well
I haven't messed with then yet but since yours is in a custom module maybe it requires imports base?
Doesn't really seem like it, this is one of the mods i'm using for reference
imports are useless
What I would test rn
- have your registries references in the scripts to lowercase (I've yet to confirm it matters, I think it doesn't as the game puts them in lowercase)
- put your profession definition in the Base module instead
while we recommend custom modules generally, the module a profession is in doesn't matter whatsoever
Is there a known issue when adding a mod to an existing multiplayer game? Just editing the server settings doesn't work for me.
on a server, is there a time after the mods and moddata is loaded that I can have it run a function? Would that be OnServerStarted()? Answered it myself in testing, this function works fine for pulling moddata as the server is ready for clients. 🙂
I just detected that the game in multiplayer doesn't detect my mod at all when I try it via subscription on steam! It works fine singleplayer and in multiplayer when I manually put it into my Zomboid/mods folder! But not in multiplayer via a regular steam subscription! What's going on here?
Is there a known issue in 42.13.2?? Maybe linux related?
Rename all your files to lowercase(maybe), also make sure all your main folders have the proper capitilization
Oh no! what did they do to linux??
Horrible things. but mainly you need to be extra case sensative on linux
like, if your \common folder is \Common, KABOOM.
that and stuff like mod.info may need to be all lowercase(?)
and shared/client/server/etc etc
That should be always correct in my case. Only thing is that some folders and lua files have capital letters in it. Not the the standard folders like server/client/shared but some custom files and folders...
I think those are OK so long as they are not XML files (Someone else will know better)
some mod authors have just lowercased their entire mod -_-;
works fine in singleplayer btw and when I have the mod in my Zomboids/mods folder
you add it to BOTH places in MP right?
the 'used mods' and the 'used steam workshop items'?
and any mods its dependant on?
(to both)
(Iv made that mistake lol)
Only happens when I try to run it via the steam subscription. (In this case, I do not have it in Zomboid/mods or Zomboid/workshop folder ofc).
No, no dependency in my case.
Ok so you went into the server settings editor right?
Yes.
did you your mod to the mod menu, and then, after hitting next (And it lagging for awhile), add it again to the 'steam workshop' list?
on the menu that you'd think is just sandbox settings
It works 'locally' without the 2nd step, but not if your trying to use the steam workshop version/let other people join.
No luck
Currently I only have that registries.lua file and the professions.txt one, is there some sort of file structure or another file I might need that I missed? I'm just tearing apart professionmods that I found that working
Many thanks! That fixed my issue!
So is the common way to enable mods for players? First adding it "normally" and then again in the "steam workshop" list when hosting a game?
Yep!
it has to know what 'workshop items' to use for a mod because.. its apparently too dumb to figure that out from the 1st step like every other game.
Lol! Maybe I write a little extra function which puts it there automatically cause the current situation is not super user friendly I'd say...
Right? would save a lot of time and weirdness
I had one where I didn't add the mod it was dependent on to steam workshop
and then it wouldn't load the other mod, but it would show me all it sandbox settings like it WAS loaded
but they would reset every time I loaded the server and I had no idea why this mods sandbox settings wouldn't save!
Can this work as a linter? Somehow, when I miss entering a newline before {, the game does not load the script correctly.
Yes
Not every syntax mistakes are implemented in the tool yet tho
As for newline before { it really depends what's before {
for my case
Items { not work
but
Items
{
cost me hours to solve the single newline break
Items ?
oh sorry, i mean
item ItemName {
model ModelName {
That does work
hmmm not for me from my end, doesnt load, let me open computer and give screenshot
https://gist.github.com/hashtafak/b2b212ff4441091425b5952213c37e95#file-clue-md
not work for me, it can load, but it does not show in the Script Manager
Keep a single space before { ?
sure, i keep 4 spaces, now back to 1 space, no
LOG : Lua f:2054, t:1769913698547> ISStringListView -> parsing error. out of bounds.
It's usually something pretty obvious
yes, it is so hard to pinpoint which one is causing the errors.
Can always try my extension
And tbh I suggest using it eitherway
Moving over to VSCode is better to manage your project and with all the tools available for PZ dev
Yes, im using VSCode and sticking with it. I also use EmmyLua and ZedScript and pzstudio. But no formatter yet for scripts
Wdym by formatter for scripts ?
omg, my bad. The old extension from @asledgehammer for b41 has formatter errors.
Your version is better, up to date, and correctly formats on save.
Yea
but it again cannot detect the script when i use this: module Base { item RubberChicken_Small {
Tho the format is not something I usually use and it's from the old extension (PZ Script Support)
also cannot detect item RubberChicken_Small {
the { same line cause format for that block on save/format
Haha, I kept searching for PZ stuff on github and used the repo with the most stars before i joined the Discord channel. My bad
The formatter is not up-to-date in the extension, don't trust it
Yea that's fair, my extension is recent so not yet used by that many people
You now have my support.
I've got plans for it haha
Hey, someone know why i dont have my output item in my recipe ?
Missing comma
Suggest you use ZedScripts
hey, so I got question regarding this.
Yea this doesnt work, got any idea why?
registries.lua :
ETWRegistry = ETWRegistry or {}
ETWRegistry.traits = {
GYM_RAT = CharacterTrait.register("ETW:GymRat"),
}
local UNFIT = CharacterTraitDefinition.getCharacterTraitDefinition(CharacterTrait.UNFIT)
-- what I tried
UNFIT:getMutuallyExclusiveTraits():add(ETWRegistry.traits.GYM_RAT)
UNFIT:addMutuallyExclusiveTrait(ETWRegistry.traits.GYM_RAT)
I double-checked https://demiurgequantified.github.io/ProjectZomboidJavaDocs/zombie/characters/traits/CharacterTraitDefinition.html
however when launching the game I get error that
ERROR: General f:0, t:1769918302334> ExceptionLogger.logException> Exception thrown
java.lang.RuntimeException: attempted index: addMutuallyExclusiveTrait of non-table: null at KahluaThread.tableget(KahluaThread.java:1447).
So yea idk where to go from here
According to docs UNFIT:addMutuallyExclusiveTrait(ETWRegistry.traits.GYM_RAT) should work
I am trying to add a hotkey or a mod click on on an item in the loot panel. I cant seem to find any on hover like commands in the api docs.
I am creating a mod for Set Unwanted and am trying to create a faster way to perform the action so you do not have to right click the item each time and go to the right click menu option.
i don't know why you're getting that error, but i would prefer to use CharacterTraitDefinition.setMutualExclusive(CharacterTrait.UNFIT, ETWRegistry.traits.GYM_RAT)
oh i do know actually
don't do it in registries.lua, that's way too early
do it in a regular lua file in shared
ah
registries.lua's job is to create registries for scripts to be able to reference, so the scripts which add those definitions haven't been loaded yet so trying to get the definitions returns null
fair. I had assumption that it might be too early and thats why it returns null but for some reason I was mistakenly confident that I have to do this in registries.lua 
the only thing you have to do in registries.lua is register registries, everything else should be fine later (until we inevitably find some exploit from the fact that registries is crazy early in load order compared to other lua files)
Ye, that fixes it, thanks. Interestingly enough
local ETWRegistries = require ("ETWRegistry")
local ETWTraitsRegistry = ETWRegistries.traits
local UNFIT = CharacterTraitDefinition.getCharacterTraitDefinition(CharacterTrait.UNFIT)
UNFIT:addMutuallyExclusiveTrait(ETWTraitsRegistry.GYM_RAT)
still doesn't work, while
CharacterTraitDefinition.setMutualExclusive(CharacterTrait.UNFIT, ETWTraitsRegistry.GYM_RAT)
works just fine

regardless, setMutualExclusive works so that's good enough for me 
getUsedDelta doesn't seem to work for b42. Any way I can get the ratio of the drainable item?
Hey, someone know how to add fluid to my Base.Pot in the outputs of my recipe ?
craftRecipe MakeMashedVegetable
{
time = 120,
NeedToBeLearn = true,
timedAction = MakingHammer_Surface,
category = Tools,
tags = Distiller_Bench,
inputs
{
item 5 [Base.Potato;Base.Corn;Base.Carrots;Base.Cabbage;Base.Pumpkin;Base.Apple;Base.Tomato;Base.Peach;Base.BerryBlack],
item 1 [Base.Pot] mode:keep,
item 1 [Base.MortarPestle] mode:keep,
}
outputs
{
item 1 Base.Pot,
}
}
Anyone know where the professions icons are stored? I can only find the tailoring one thats sitting in media/textures alone for whatever reason
Inside tiles pack
\ProjectZomboid\medianewtiledefinitions.tiles
Is it actually accessible? Doesn't seem to open for a code editor
Found the raw images online
At your output, there needs to be a ',' at the end of the item line
I did not found a solution, how to add a fluid to an existing container and so I defined a new item as fluid container which contains the fluid and gives the pot if it is empty. E.g. Pot with XY. In the item definition it is possible to define the behaviour. May look into my code. My mod id is XantjiRecycleEverything. The item is bottle with lye.
this is how I add fluid component to the Moats at creation time ```lua
if isoObj and not isoObj:getFluidContainer() then
local f = ComponentType.FluidContainer:CreateComponent();
f:setCapacity(waterMax);
GameEntityFactory.AddComponent(isoObj, true, f);
end
or maybe this works in the craftRecipe: ```
OnCreate = RecipeCodeOnCreate.yourModdedFunction,
Pretty nice, thanks. I need to get into lua scripting first. At the moment I just defined some items and recipes. So I did it this way:
```
item LyeBottle
{
DisplayCategory = Household,
ItemType = base:normal,
Weight = 1.0,
Icon = GlassBottle,
IconFluidMask = GlassBottle_Mask,
WorldStaticModel = BottleCrafted_Ground,
FillFromDispenserSound = GetWaterFromDispenserGlass,
FillFromLakeSound = GetWaterFromLakeBottle,
FillFromTapSound = GetWaterFromTapGlass,
FillFromToiletSound = GetWaterFromToilet,
Tags = base:glass;base:glassbottle,
component FluidContainer
{
ContainerName = Bottle,
Capacity = 1.0,
CustomDrinkSound = DrinkingFromBottleGlass,
Fluids
{
fluid = Lye:1.0,
}
}
}
Then I use a glass bottle as one of the inputs and my bottle as output.
But your way is much smarter 😉
hi there, im working on a mod that requires a fake player to be made and since isoplayers dont render in build 42, does anybody know what could be a workaround on giving player states or how to convert player states to a isozombie compatible state? the bandits mod could do it and i want to know how i could do that for my mod
Anyone considered wrapping the games lua functions and calls to specific game objects?
At least the few you might use in your own mod?
Wdym ?
Do you have an example ?
yeah, im working on one now that isn't really that beneficial, but a good test
local PzNative = {}
function PzNative.getText(string)
return getText(string)
end
return PzNative
im more interested*, for my purposes, to wrap something like player:getStats():get(CharacterStat.HUNGER)
as that was broken from 41 to 42
and having this wrapper makes it easy to fix or version
the big benefit i have is helping my IDE not complain constantly
at the moment
but
Complain about what ?
Jeez don't do that
Because you don't use Umbrella ?
i do have umbrella, but i probably need to toy with it
You didn't properly activate it if it screams at getText
yeah
is it a performance concern with wrapping the calls? basically increasing the number of method/function calls per loop
Yes
It is and just makes your code messy
For things that require multiple function calls, like sure yea you can do that, there's a point
But when it's a function call doing a single function call ... that sounds fucking stupid lmao
Also it technically doesn't remove the problem that your code has no idea what it's fiddling with
sure, in my mind it just makes it easier to deal with broken calls when the api changes
Eh
cause you change it in one place and you're good to go
That's probably the only advantage to it, but Umbrella already does that
Because if Umbrella screams at you: you fix it
And when the API changes, Umbrella updates and Umbrella screams at you for broken functions
So a properly managed code already handles that
damn it
i need to fix umbrella
this is why i asked cause i figured i was being a bit niave and i could see how it can create overhead depending on where and what im calling
The ONLY advantage related to that is not having to change stuff everywhere in the code I suppose, so you only need to change a single function rather than many, but that really doesn't outweight the problems that come with:
- having to constantly check what that function calls to know what API elements it involves
- makes it messy to manage
- adds extra functions calls
Alright - I think I have it working and it’s complaining a lot about existing code so now the fun part is figuring out how much is actually a problem
Yeah I make the same
ok I remember someone saying there's a special plugin or something I should get from visual studio code other than the ones on the wiki?
There's two important ones:
I ended up giving up for now 😅 umbrella wouldnt show up and my github was being wonky so I couldn't clone the repository. I'll try again in a couple days probably
thank you though!
I'd forgotten how much of a pain it is to set up your first environment when modding a game
Don't worry it's not that bad
EmmyLua needs to be reloaded when you've set up your configuration file
yeah, its not a complete pain but be sure to read through everything and clone the repo
i only say clone cause it should be easier to grab updates
for the umbrella stuff
also make sure you get the right plugin - theres a few clones
Guys, do you have a more practical method for writing descriptions for the mods you publish? I do everything by hand and the result is disastrous.
getType() can be applied to a CharacterProfessionDefinition object and yields the corresponding CharacterProfession object (the latter are the things you denote by CharacterProfession.BURGER_FLIPPER for example). The CharacterProfessionDefinition objects can come by using
local professionList = CharacterProfessionDefinition.getProfessions(); for i = 0, professionList:size() - 1 do local profession = professionList:get(i) -- this is a CharacterProfessionDefinition object end
So to get the CharacterProfession from the above, you need to use profession:getType() command to get smth like CharacterProfession.BURGER_FLIPPER which is what you will need most of the time when working on a profession mod.
you mean the description in the steam workshop?
My main problem was trying to use getType on custom occupations since they wont have a constant like burger_flipper
When defining your new professions in your mod's registry, you also assign them a constant. However, getType() can only be applied to the CharacterProfessionDefinition object, not to the CharacterProfession object and the latter is the object which you denote by the constants.
yes
There a simple way to change/remove the default clothes you can pick from the editor when making a character? I need to make sure players on the server show up in crafted clothes
In the vanilla game, there is a lua table in shared/Definitions/ClothingSelectionDefinitions.lua. This table defines which professions get which clothes.
tbh, I started just using a custom template for them. it rlly streamlines things a lot! all of the formatting stuff can take some trial & error until it looks nice enough, but once it’s down for one mod, it can be easily replicated… copy/paste then re-writing stuff to fit for the new mod 
i’ve got my workshop descriptions saved as backups too just in case of steam wonkiness Xd
I think that must be the best method. It's a shame there's no online converter for these things 🙁
At least I don't know any
Imagine: Actually knowing how much food you have at a glance
(looks at every accessible container from where your standing)
Actually I guess this only shows ingredients of certian meals atm.. I could have an overview mode though I guess.
Other cursed ideas include: allowing anything to be an evolved recipe ingredient. Add chips to your roast? why not. Gummy bears in your sandwich? Sure.
i've adopted the trick of 'write as little as possible or else nobody will actually read it' which saves a lot of time writing descriptions
yea, by time your mod gets really complex you need a steam guide for it anyway.
You can put all the details there if you feel the need 😉
i'd just host a wiki or something on pages at that point
that seems like more work then I want lol
it's shockingly easy
In a process of updating my mod I came across func that I used to set player carry weight and it made me sad cuz on my side I have to add all possible weight changes that might come from other mods. So I was thinking about maybe making like a mini-framework that can be used to merge all weight changes from multiple mods without having mod authors do all that extra stuff and that way existing mods don't have to keep adding support for other mods and instead can just say "go tell this other mod that sets weight limit to use the framework"
Base version would be say few tables like
```
baseWeightModifiers = {} -- here ppl can insert changes to base weight, say "-2" or "*1.5"
weightAfterStrModifiers = {} -- same as before but applied to carry weight after str is accounted for
and maybe some form of priority in the tables, so you could make your jacket increase carry weight by +1 before some trait, for example, applies carry weight multiplier of 1.1
Thoughts?
Cuz currently any carry weight changes are just overwritten by whoever fires their set weight func on every tick

sounds cool, that system is annoying enough that mods just don't really touch it
You'd think so but I have 4 mods referenced in my weight limit func cuz ppl were reporting other mods not working (cuz both mods were fighting for setting carry weight)

maybe pzstudio is a good starter kit for you ?
ill check it out, but im having a reasonably good time with Emmy plugin
ive been fixing and refactoring a mod that was apparently made from a mod
so ive been pulling out parts of the original mod that it was derived from that arent needed and trying to pull together this 1000 line file into something more reasonable
Anyone know of a working more that allows the creation of engine parts?
well incase you want to try the alpha version of vscode extension, it create the skeleton for your need, also suggest emmylua, zedscript , stylua ext for you
https://marketplace.visualstudio.com/items?itemName=escapepz.pzstudio
yeah, im running the emmylua extension and got it configured
zedscript i disabled for now because i dont have a need yet
Thanks for the help, no more modern clothes
Does chance actually do anything when it comes to starting clothes? I've never really noticed a difference in what I can pick besides clothes provided by the professions
am i reading correctly - i should set custom properties prior to setmetadata?
it's not what you can pick, it's what you randomly get picked
when deriving
so when i select that profession the initial clothing is based on the chances, and i think hitting the randomise button uses it too, but all clothing is always available
im used to OOP so im trying to merge those ideas with lua so im pretty green
setmetatable? it usually doesn't matter
cause its just a pointer?
ill figure it out - just fighting with some IDE complaints - everything works fine but if it can be better..
you usually need to ignore language server complaints about constructors, they just aren't represented very well
Nice - the metatable stuff is a bunch fun magic
PSA / Looking for modders: I updated Error Magnifier to include per mod error logging, and for good measure added a custom debug report API. You can include useful information along with any errors tied to your mod for an easier time when people report things to you. If this sounds interesting lmk what you think / if you find issues / have ideas, etc.
https://steamcommunity.com/sharedfiles/filedetails/?id=2896041179 👍

example output for Skill Recovery Journal:
```
[SkillRecoveryJournal - Mod Report]
Version = "42.13.1 1267173a2044ba62aa3d0a0e9899b15e9057de5c 2025-12-18 10:34:47 (ZB) (Steam)"
Mode = "SINGLE PLAYER"
SANDBOX = {
RecoveryPercentage = 100
TranscribeSpeed = 1
ReadTimeSpeed = 1
RecoverProfessionAndTraitsBonuses = false
TranscribeTVXP = false
RecoverPassiveSkills = 0
RecoverPhysicalCategorySkills = -1
RecoverCombatSkills = -1
RecoverFirearmSkills = -1
RecoverCraftingSkills = -1
RecoverSurvivalistSkills = -1
RecoverFarmingCategorySkills = -1
KillsTrack = 0
RecoverRecipes = true
RecoveryJournalUsed = false
SecurityFeatures = 1
CraftRecipeNeedLearn = false
CraftRecipe = ""
ModDataTrack = ""
}
CHARACTER = "NONE"
JOURNALS = "NONE"
But yea, iv now got it using multiple ingredients on a single click, yay.
.. without making killer sandwiches
Next step: the 'add water' command for pots, and... Timed actions I guess.
I noticed that all of the cooking things don't work in vanilla if the item isn't in your inventory...
I assume something goes on when the inventory transaction occurs? Like the qued event loses the reference to the food because it moved containers?
... Random mod thought: Calcium oxide (Heated limestone) + carbon (charcoal) = calcium carbonate + water = acetylene.. Renewable welding torch refill method?
A use for glassmaking, to make the glassware to do chemisty?
https://steamcommunity.com/sharedfiles/filedetails/?id=3658756227
Just finished up the first version of this nearby animal UI if anyone fancies a look!
should i use mouseDown or mouseUp for typical click events? i feel like ive always used up
thats a nice UI - maybe in the future you can skill gate some of the stats
or its accuracy
There's debates about this, mouse down is good for responsiveness 
i feel like most things use up
99% of the time yeah
But I saw a video interview with a really old school game dev and he went off the rails about it and its sat with me
I think it depends on the action if it's for gameplay
Shooting a bow and arrow feels right to have it on Up
(immersive to feel like you're holding the pull)
But shooting or swinging feels like it would be mouse down unless there's a similar wind up mechanic
The interview was about menus though 😅
yeah, i just took a break and talked myself into Up - i feel like i only used down for like.. selecting items?
attacking would typically be mouse down you're right
but if im gonna be popping out a menu - i think Up is better for "feel"
wasnt he also the one that came up with the constant that allowed 3d games to be written on that old hardware?
In multiplayer B42, is there a command to check whether a building has been claimed by some player?
it was some vertices calculation or something
No clue, old school game devs were basically wizards
actually true
They abused consoles and PCs to do so much lol
Reminds me more of us modders breaking PZ over and over
im just getting my feet wet at this point
so i keep seeing return true on these click events to prevent propagation (for UI elements) - is that a thing?
More often than not those events are fed back up the chain with the derived UI "classes" (Lua doesn't have classes in the truest sense)
The return value prevents propagation in some contexts, idk about all of them
not sure - im looking through some of the code to see if anything stands out - maybe something about factions?
Best bet would be checking UIElement and UIManager in the Java
Not sure about an entire building, but if you mean safehouses the SafeHouse.getSafeHouse overload that accepts an IsoGridSquare checks whether the square is in a claimed safehouse
before I go too far down the rabbit hole, is there a function call or something I can use to make zombies take damage when they attack a specific structure? Akin to how hitting a window without a weapon would cause you to take damage
Actually I should probably just look at how they did it for windows, huh...
Thanks! Exactly what I need!
do we have a list of functions and language stuff here somewhere? like I'm trying to figure out what "LogicClass" does for a wall for example
JavaDocs
See my pinned message
Which one? the migration? The TIS thingy? The Wiki? 😅
I did go through a couple of the pinned threads and looked across the wiki but I'm a little lost honestly
In pre-42.13 times, we had a global command getCell() which returned the IsoCell around the player (only for single player games). Now I see that we have a command IsoPlayer.getCell(). So, do you think it is save to assume that we can use player:getCell() on server-side to get the cell around the player?
no
all getCell() functions are deprecated wrappers around the global getCell()
there is only ever one cell
IsoCell used to correspond to specific regions on the map, which is why a lot of API implies that objects/squares belong to a specific cell, but it was made global years ago
But what happens then when I call player:getCell() on server? What and where is the IsoCell which is returned?
For context: In single player, I used getCell() to get a list of all zombies around the player when game starts and it always worked fined for me. So I used
local zombies = cell:getZombieList()
if cell then
for i=zombies:size(),1,-1 do
-- do smth with the zombies
end
end```
thank you!
the only IsoCell that exists, there is only one ever
I need to make a dictionary on the wiki for useful pages
things like the zombie list in the server cell may not be reliable, the server does not really use IsoCell the same way the client does
the server really uses entirely separate logic in ServerMap that is not accessible to lua at all
Ok... then I'll probably just disable that feature from my mod on multiplayer altogether. In single player, I used it to make a custom spawn logic for the player when game starts. I used the zombieList from the IsoCell to remove all zombies from the spawn area. But I guess that's not so easy to do in mp on server side anymore.
Sorry for this question, but i think i read the docs, tried pretty much everything and can't see my mod showing up in the mods panel.
So i am in a Mac and i am trying to test my simple mod.
My mod info is in folder MyMod1/42/mod.info
I have zomboid on stream, and i have these 3 folders:
~/Library/Application Support/Steam/steamapps/workshop/content/108600
~/Zomboid/Workshop
~/Zomboid/mods
Tried to put my MyMod1 folder in all the 3:
In the 1st nested in a bogus <workshopid>/<gameid>
In the 2nd either directly or nested in MyMod/Contents/mods
In the 3rd directly
In all cases in the Mods selector panel i never saw my mod.
Where should i put the mod files to actually show up for activation?
Thanks in advance
does your mod have a common folder
no, Just a lua file under 42/media/lua
ahh! Client!
i misses the client folder in between
you need a common folder, it can be empty but it has to exist
Yes! It worked!
I actually had my script under 42/media/lua/client, but forgot to mention.
So the empty common folder was the problem.
Thank you very much!
ugh.. the static analysis is so bad for lua..
but its fine.. its making me create docblocks which is for the best
When using object:setMaxHealth(n) and object:setHealth(n) on server where object is a thumpable (a wall or a door), is there a special sync command I need to use to sync it with the clients? The objects in question are already on the map.
In vanilla, all I can find in such a context is object:transmitCompleteItemToClients() but not sure if this can be applied in my situation since vanilla only seems to use it when the object is newly constructed and added to the map.
There is also the command object:sync() which might be relevant...
object:sync() is generally what's used
it's not clear currently exactly what does and doesn't get synced
transmitCompleteItemToClients might cause issues, at least in b41 this would create a duplicate object on the clients rather than updating the current one
Wasn’t there talk a few days ago of the sync command being called “automatically”?
player stuff often gets synced on its own after a bit, but things like world objects that don't change often usually won't send updates on their own
Right - probably until they are interacted with at the worst or “in sight” at the best
Thanks!
Another question: when I have a thumpable object on the map and I know on client which object it is, how an I identify and access the object on server? Problem is that I cannot send those objects via sendClientCommands.
send the x, y, z and object index
Ah! Object index is pbbly the thing! Already thought about the coordinates but there can be more than one thumpable on a square.
So how do I get the object index? Is this just the index from the list I grab by square:getObjects() ?
And it is guaranteed that the index agrees on server and client for that list?
-- client:
local x = object:getX()
local y = object:getY()
local z = object:getZ()
local i = object:getObjectIndex()
-- server:
local square = getSquare(x, y, z)
if square then
local objects = square:getObjects()
if i < objects:size() then
local object = objects:get(i)
end
end
it is not entirely guaranteed, but this is how the game does it too, so it won't be introducing new issues
the only time they should be different is if the server has added/removed an object and the client doesn't know about it yet
so it should be very rare and only for a moment
Great! Many thanks!
another beginner question - is using
---@type table
o = ISPanel:new(x, y, width, height)
a reasonable fix for the IDE complaints about fields not being able to be injected into...
No that's an awful fix lol
lol
you're basically just turning off type checking when you do that
this is why i ask
Because you remove any intellisense for o
yeah, but im getting complained to about adding properties to ISPanel in the :new method
In a derived UI element ?
yeah, let me scale it down for posting
function StatsUI:new(x, y, width, height)
local isPanel = {}
isPanel = ISPanel:new(x, y, width, height)
setmetatable(isPanel, self)
self.__index = self
isPanel.targetAlpha = 1.0
i get complaints at targetAlpha
You need to define your StatsUI as a class which takes on ISPanel
sure
---@class StatsUI : ISPanel
---@field targetAlpha number
---@field bars StatsBar[]|table
local StatsUI = ISPanel:derive("StatsUI")
i started that way
the usual pattern would be```lua
local o = ISPanel.new(self, x, y, width, height) ---@as StatsUI
gotcha
yeah, already had it once today
i know everyone uses o but i have a disdane for single letter vars outside of like a for loop
so
function StatsUI:new(x, y, width, height)
local isPanel = ISPanel.new(self, x, y, width, height)
setmetatable(isPanel, self)
self.__index = self
isPanel.targetAlpha = 1.0
would be reasonable?
docblock it?
gotcha
---@param x number
---@return StatsUI
function StatsUI:new(x...)
amazing
i generally agree with this, but this is a special exception where o has a strong conventional meaning
the sacred o
o
Updating errorMag with some feedback/ideas I got
- Added handy useful PZ-info dump as standard header.
Includes game version, game-mode, and luachecksum flag.
I've taken to using local this in constructors so I can piss off Java and JS devs who read my Lua code (not really, just because it's like self but dissimilar enough that I won't mix them up)
Basically every question I ask commentors who say stuff is breaking in ways that are unexplainable
Sounds handy
thats such a great idea - i used instance today but thought it could be better
I also added an API for custom debug dumps
instance seems better to me tbh, but honestly names are names at the end of the day
I think I saw this elsewhere, but this means adding arbitrary additional info to dumps, yeah?
=== Zomboid Settings ===
Version: 42.13.1 1267173a2044ba62aa3d0a0e9899b15e9057de5c 2025-12-18 10:34:47 (ZB) (Steam)
Mode: SINGLE PLAYER
[SkillRecoveryJournal - Mod Report]
SANDBOX = {
[...snip...]
}
CHARACTER = "NONE"
JOURNALS = "NONE"
i added one for the horse mod this morning but i haven't merged it yet
Yep, for cases where you have information you'd want readily - hoping/assuming the player uses errorMag
i like this a lot - i might start using it for the same reasons
I made it required for this purpose - for my own sake and sanity
Definitely sounds worth adding compatibility with that, very cool
i'm most tempted to use self but there's enough : constructors out there that it'd get confusing
Yeah, that's the only reason I don't just use that—would certainly be the most Lua-like option
I stand by that players just need guide rails to provide useful reports
and leaning on the guiderail metaphor, guiderails > tour-guides (mod authors repeating themselves)
really stings when a player butchers a stacktrace error and leaves it on a steam comment 😅
Does Zomboid's lua version supports the check if math.type(x) == "integer" then?
and the lack of steam comment search.. and 10 messages per page.. just ugh
Yeah in the same vein as updating errormag to be more proactive -- i've been thinking up something
Kahlua does not have the integer type, it's similar to Lua 5.1
going to see if I can make something of a (semiverified) github issue maker with a template/form from a redirect from steam
I've made github a central place to report issues but it just trims too much fat from the pool of people willing to share information
Unsure if this is what you mean or you've already done this, but GitHub's issue template system is fairly straightforward; I link to https://github.com/omarkmu/pz-omichat/issues/new?template=bug_report.yaml on my mod page
and this is why ive left my mod unlisted for awhile
Can a thumpable object have modData on server?
yeah
Sorry I probably butchered the explanation - I meant a way for non-github accounts to make issues - but not have it be just anonymous
Also unrelated - but I wish there was a workshop policy to disclose AI use and maybe to what degree
alot of mods look... weird... (not even talking about posters which are whatever) the features discussed are just insane sounding + if you look inside it's all garbage
yeah it's been getting worse and worse
yeah, i had to turn it off on VSCode
ive been trying to do some stuff i havent tried before in c# and its so verbose and opinionated
if it wasnt giving* bad answers it was also ruining the discovery
also thanks for ide/instantiation advice - no errors or kinda false alarm warnings now without supressing
Has anyone an idea why vanilla game has the TimedAction ISBuildAction still defined in the client folder? From what I see, this is the action which is executed when players build new stuff like walls, doors etc. Shouldn't such a TimedAction have stuff which is executed on server-side when in multiplayer?
i'm pretty sure it's unused b41 code
So, in B42 single player, it is still the code which is executed when building stuff. Don't know how it behaves in multiplayer though.
Inventory transfer uses some specific transation protocole. it may be similar for that
the building code is really convoluted 😅 hard to see what's used where
it is a special cased type of action in the java side of the game
So they use some custom sync for that and therefore it works although they have it in the client folder?
actions don't *have* to be in shared, it's just generally convenient for them to be
they are still allowed to run entirely on the client
Strange thing is that this action doesn't have a complete() function and the new object seems to be created and added in the perform() function.
What I also found out: on server (!!), they use the command
buildAction = ISBuildAction:new(playerObj, selfCopy, x, y, z, self.north, self:getSprite(), maxTime, containers)
So they may somehow call and execute the whole action on server somehow?
complete() functions are only for networked timed actions, if that function doesn't exist it's a client-only action
Strange is that if it would be client-side only, how do they sync the new objects added by the client with the server game world?
the function returns before creating the object in multiplayer```lua
if isClient() then
if self.item.completionSound ~= nil and self.item.completionSound ~= "" then
self.character:playSound(self.item.completionSound)
end
ISBaseTimedAction.perform(self);
return
end
most likely that server code only actually executes on the client (all build cursors are in server/ despite only running on the client)
there is some custom sync going on that i don't see immediately but it is related to the BuildAction stuff i talked about, that triggers object creation too through an event
Hmmm I see... but where do they create the actual object then when in MP? Or is this somehow done because they add this TimedAction to the queue on server side? So that the server also executes the perform() function?
i think it is only created that way on the client side, the server (by a method i have not worked out yet) creates a BuildAction instead, which has a complete() function (kind of, it is java so it's not exactly the same) that triggers OnProcessAction
it uses createBuildAction in its start() function to tell the server to create this action
The server file ISBuildingObject.lua has this code:
local square = getCell():getGridSquare(x, y, z)
local playerObj = getSpecificPlayer(self.player)
local playerInv = playerObj:getInventory()
-- create build action, early, so we can call startCraftAction before walkTo
local buildAction = nil;
if not self.skipBuildAction then
-- [[ some code ]]--
buildAction = ISBuildAction:new(playerObj, selfCopy, x, y, z, self.north, self:getSprite(), maxTime, containers);
end
-- [[ some code ]] --
if smth then
ISTimedActionQueue.add(buildAction)
else
print("ISBuildingObject -> tryBuild - cannot walkTo target")
self:onActionComplete();
return nil;
end
return buildAction```
so they somehow seem to create and execute the action on server side...?
this is almost definitely running on the client
this is a cursor and cursors do not run on the server, remember that code in the server/ folder is not necessarily server code
Ahh ok... didn't know that... Looks super mysterious to me.
So my problem: To make a mod of mine work in multiplayer, I have to catch the moment where a certain thumpable object has been build by the player and is present on server (the objects in question are doors and walls). In singleplayer, I can simply hook the perform() function from the ISBuildAction but I am afraid now that this might not work in mp...
try hooking Actions.build instead
or perhaps in addition, i think this is probably not used in singleplayer?
Does client's timedactionforceStop get transmitted to server? I got this perform error on server-side whenever I execute a forcestop command on client.
Omg! If they just created this TimedAction with a complete() function as they did for almost all other actions, it would take me 2 minutes to make my mod ready for mp! Now it is complicated, requires super long and repeated multiplayer testing and... #!$!X(!!(!!#$%!!
... Just add a complete function to it? 🙂
Nothing is stopping you from just.. adding another function to the global table that is that TimedAction
you would have to make it load on the server
otherwise the server can't create the action and bad things happen
it would be better to work out how this all really works in mp (i am sure it still goes through lua enough for your needs) than to hack something together like that, that's likely to break with updates
I’m working on a large multiplayer mod that pushes pretty hard into custom ISUI, server-authoritative state, and long-term persistence. Before we lock in some core patterns, I’d really appreciate sanity checks from people who’ve already fought the engine in these areas.
This isn’t a beginner mod, we’re deliberately avoiding "hacks/workaround" where possible and want to build something that survives long-running servers.
-In custom-drawn ISUI panels (not ISScrollingListBox), which mouse callbacks actually fire reliably?
onRightMouseDown
onRightMouseUp
onMouseDown with RMB
Are there known cases where RMB is swallowed by parent containers?
- When multiple ISUIElements overlap, what actually determines which one receives mouse input?
IsbringToTop()enough, or can parents still intercept events?
For “card/list” style UIs, what’s considered the least brittle long-term approach?
ISScrollingListBox- child
ISUIElementrows - manual draw + hit testing
I believe bringtotop should do the work, if I remember right there's counterpart something like "always bring to top" equivalent
The mouse events should work, I'm not aware of any issues
For a list, depends what you want really. If you want a selectable list, yea probably go with that
If you want an list, there might some UI elements specialized in that, else I'd say make a list isuielement if you want interactions with them, also probably more flexible
Thanks it helped confirm we were fighting z-order, not input callbacks themselves.
So what moodle framework is most commonly used? or do people just impliment it themselves?
(Can you impliment custom moodles without conflicting with other moodle mods? easily?)
Eh
People use the moodle framework usually
trying to add 'food poisoning' if your filthy when you cook but realizing the vanilla PZ system is.... realllyyy bad about poison being either nearly unnoticable or deadly
I want more the 'slowly murders you with thrist/hunger/loss of calories/low max HP' kinda sickness, and not the straight up murder you kind
People unsafely adding icons to the left menu is a PITA for making mods isn't it
I just delete any comments saying "doesn't work" or "bug" or posting 1/3 of stacktrace

What exactly do you mean by that?
I guess that they post a small portion of the stack trace error and think its enough
At some point I'll need a therapy with a professional
I have to know what inspired this pattern & similar in PrintMedia code rather than just using tonumber
if key == "width" then
local val2 = loadstring("return " .. value)()
self:setWidth(val2)
elseif key == "height" then
local val2 = loadstring("return " .. value)()
self:setHeight(val2)
end
The only benefit I can imagine is arbitrary expressions, but that sounds less like a benefit and more like a nightmare & it doesn't appear to be used (width and height is always a number, at least in Print_Media_EN)
I just noticed the textures are just getTexture calls
my best guess is partial knowledge of the language.
It seems very odd to imagine someone knows loadstring and not tonumber, so I believe it was an intentional decision
when im troubleshooting a stack trace how do i see the ".... 10 more"?
im in debug mode
If you're in the debugger (F11), you can view the stack directly
thank you
i made too many "clever" changes at once and im trying to see where i got too clever
Someone who's trying to be helpful but doesn't know what to provide will sometimes give like 3-4 lines of a stack trace where the useful bits are further down.
It stings because they're trying to be useful but don't know how -- and if their mental bandwidth for the day is spent you'll probably never get a follow-up
to be fair, so far, the default stack traces for me stop too soon
There's a weird logging issue where they sometimes get sent to print too soon so you may see 2 headers for 1 error
It's something errorMagnifier also corrects
hi guys! i was wondering if the levelup sound is not working for you as well or it's one of our mods! thank you and kudos
Anyway I can check if the player is in Combat Stance?
I know if isSprinting, isWalking, isRunning, isSneaking but what about when player is in Combat Stance?
isAiming()
thank you
That probably won't work cause they have some specific and convoluted extra logic on server-side which is used when building stuff like walls. Just adding a complete() function would probably involve disabling their whole custom logic to avoid conflicts which would be quite complicated I guess.
When hooking their server-building action, I have still problems to set the maxHealth of a building object on server. It seems to have no effect or is not properly synced with the client.
Here is my code where I hook the server-side Actions.build function:
local vanilla_build = Actions.build
function Actions.build(character, args, ...)
local isOldObject = {} -- store walls or doors which are already present so we don't accidently assign them the new hp
local recipeName = nil
local square = nil
if isServer() and args and args.item and args.item.craftRecipe then
recipeName = args.item.craftRecipe:getName()
if character:getDescriptor():getCharacterProfession() == Regs.NewProfs.rasArchitect
and (isWall[recipeName] or isDoor[recipeName]) then
square = getSquare(args.x, args.y, args.z)
if square then
local oldObjects = square:getObjects()
for i=0, oldObjects:size() - 1 do
local object = oldObjects:get(i)
if object:getName() == recipeName then
isOldObject[object] = true -- store old walls or doors
end
end
end
end
end
vanilla_build(character, args, ...) -- execute vanilla code
if square then
local newObjects = square:getObjects()
for i=0, newObjects:size() - 1 do
local object = newObjects:get(i)
if object:getName() == recipeName and not isOldObject[object] then
local newMaxHealth = math.floor(object:getMaxHealth() * 1.2)
local newHealth = math.floor(object:getHealth() * 1.2)
object:setMaxHealth(newMaxHealth) -- extra hp
object:sync()
object:setHealth(newHealth)
object:sync()
break
end
end
end
end```
What works is the setHealth() command. What doesn't work is the setMaxHealth() command. So in the UI, the health of the building object is shown is as 588/490.
The essential part in the above code is the second if-condition with if square then.
add a custom server->client packet to setMaxHealth() on client side
So you think it is only due to wrong syncing?
Yea they prob never considered maxHealth changing
Good idea. Definitely worth a try!
Hmm... problem is that I have to send this to all the clients then and to all the clients who may enter the game at some time in future (and for all the affected objects which have been build at some time). Maybe impossible doing this but requires some complicated and over-the-top coding to just fix such a little issue...
no, only the clients who currently have the object loaded need to know
clients don't know about an object until the server tells them about it, so they will get all information from the server at that time
So you mean that a new client logging in later will automatically get told about the correct maxHealth value from server?
EDIT: Yesss! can confirm that this works. After logging out and in again, the maxHealth is displayed correctly. So it should suffice to only send info to the clients who are actually logged in!
That's probably not too complicated...
it should be fine even if a client isn't near the object, so if the square returns nil it's fine
you only need to update the max health for the clients that currently have that object loaded
Is there an easy way to get exactly those clients? Or wouldn't it be easier to just do it for all clients logged in?
send it to all clients, but if they don't find the object it's fine
Oh good I was worried about that, weird that it syncs it on create
Ohh
You can try this hack that iv used to sync stuff that won't sync:
Just remove the item from the world and readd it.
ie: transmitRemoveItemFromSquare() then transmitCompleteItemToClients()
From what I can tell, the game sends a lot more sync information when an object is first 'added' vs any of the sync functions
of course it does, when an object is added it needs to tell the client literally every single thing about that object
the client doesn't know anything about it
That's a trick I also used in other situations and I already thought about using it here.
So with lua requires - is it from the base “client/server/shared” of your mod? So a file in a child folder of let’s say client like “client/ui” would just require it as though it were in the same folder? It being a file in the root
Seems like something changed and the dot notation wasn’t working
It's relative to the shared, client, or server folder of any mod, or vanilla. When you use require it isn't relative to the current file or even necessarily relative to your mod (which is why I personally put everything in a subfolder of each of those, e.g., shared/ModName/something.lua)
I have a question regarding getting information about food (such as DaysFresh, DaysTotallyRotten, etc...).
I know all this information is in media/scripts/generated/items/food.txt
Do you know of any API way to obtain this information from lua?
I know i can always read this file from Lua and parse this data myself (and maybe there are even builtin Lua functions to facilitate that), but anything already in the API would be even better.
I am not talking about current property values of concrete food items in the game, but values about the type of food.
Yes
did you want every item or a specific item?
Either way it comes down to this API for an 'item script'
declaration: package: zombie.scripting.objects, class: Item
Does an instance of Item relates to a concrete item, or to an item type?
Example.. will we have one instance for Broccoli, or one instance for every Broccoli in the game (or known/visited cells)?
so an instance of Broccoli is an https://demiurgequantified.github.io/ProjectZomboidJavaDocs/zombie/inventory/InventoryItem.html InventoryItem
declaration: package: zombie.inventory, class: InventoryItem
the definition of every broccoli in the game, is an Item
you use inventoryItem:getScriptItem() to get the item from the inventoryItem
Ahh! so InventoryItem is a concrete item and Item is the type
basically.
do note a lot of properties get copyed into inventoryItem when created and won't be updated if you change Item later, but SOME will.
yes, i was trying to understand if those get updated
PS: in item, its getDaysTotallyRotten() and getDaysFresh() for the rotten/stale timers
not all properties have a getter either, and some that don't have a getter do on InventoryItem which means you may need to instance the item to get it 😅
DaysFresh and DaysTotallyRotten. I wouldn´t expect, as it would be a lot of work to be reducing the value of all InventoryItems as time passes
is there a pattern to what requires an instance to get a value? Is it about the visibility modifiers (public/private)?
no it's just random
it's not decided by any logic more than 'did they remember to add one'
DaysTotallyRotten, for example, is both public and has setter/getter. A bit of redundancy there
Ok, so from Item i can get all that data. Is there an API to get all Items in the game?
probably is such method exists, it will be in the GlobalObject
you can get all items from the script manager
You can't access fields from lua(*technically a lie, you can't write fields from LUA and its annoying to read them without Getters)
Yes, i was expecting the getters to be for lua access
public fields are not encouraged in Java language, but i guess here they come in handy
You can, but note there is literally thousands of them.
but it´s good to know Lua accesses them in the "right" way
getAllItems
yes, in this case i am only interested in food, and i would only get them once
the reflection lua can use to access fields doesn't care about accessibility modifiers
local allItems = getScriptManager():getAllItems()
for i=1,allItems:size() do
local item = allItems:get(i-1)
-- do stuff with item
end
i-1 🙁
Interesting... Well i am a professional Java developer since 1998 and soon enough i started using reflection myself, but i use it when in total control
And the reflection java has access to doesn't care about annyyythinggg! uses java reflection in his mod because plant/zombie slowdown and impulse when driving over zombies
Blame the vanilla code I just copy/pasted
ISLiteratureUI:setLists()
That's odd, typically you'd find Java-like patterns in vanilla Lua (sometimes to the detriment of said Lua)—wonder who wrote that one 🤔
I'm still relatively new in Lua. Started it a couple of years ago, playing around with Defold engine. Its a simple and nice language, but i don't master those metatables (yet) and all the tricks
but anyway, i am sure getAllItems() it´s something not to be called all the time. I expect to call it only once, in the start
Ahh! I guess that´s a reference to Lua´s "1-index" approach 😄
local allItems = getScriptManager():getAllItems()
for i=0,allItems:size()-1 do
local item = allItems:get(i)
-- do stuff with item
end
specifically it's a complaint that when looping over java collections you should do for i = 0, list:size() -1 instead of subtracting 1 from i every iteration
only now i noticed. so allItems() returns a Java list (0-based), not a Lua table (1-based)
is the preferred method to save a -1 every loop.
in newer versions of lua it would even crash to do it the other way
indeed. Only computes -1 once
Important to notice the java apis almost exclusively return java based containers
in lua 5.5 control variables are read only
lua code generally returns tables.
Ok but i-1 doesn't alter i
oops 😅
imo the biggest benefit isn't really optimization, just that it's cleaner to look at—you're getting the index at i
still, it's weird if index doesn't-- yeah
Subtraction isn't all that expensive
Some would even say it's a constant time operation (I would say that too, because it's true)
if you're iterating over a collection and the variable specifically claiming to be an index into that collection isn't, that's poor style
Im guessing it also depends on how used to LUA loops starting at 1 is and how used you are to 1 vs 0 based arrays
It´s not, but in a big list anything unnecessary costs too much
Id wager more time has been spent arguing over where to put the -1 then -1 has ever spent executing 😛
I think if you're dealing in something 0-indexed the loop should be 0-indexed, if it's 1-indexed it should be 1 indexed
Exactly lol
LUA is just weird with its 1 based arrays and all people should be subjected to the concept of 0 based indexing if they wish to program.
i don't seriously worry about the cost, subtraction is essentially free, but it's a lot easier to convince people if it's slower than if it just looks bad
off by 1 errors are a beautiful thing that we need to subject the youth of tomorrow to at every opportunity.
I suppose so, but idt an optimization at that extreme of a low level is necessary for something done one time (if it were done for optimization)
I suppose that's fair too 🤔
I wasn't going to put my “Lua, not LUA” correction hat on until it was repeated
But there´s a reason for that. Good/Bad is subjective. It an emotional argument. We try to bring the discussion to a rational argument (and performance is one), but sometimes it just doesn´t pay off
My fav is when you actually benchmark stuff and find the weirdest conclusions.
Yes, i can imagine. Even sorting algos have their own sweetspot. Some are faster for small lists, other for long, and some even for something in the middle
"Ok so turns out we've been doing this wrong all along, it should be
local allItems = getScriptManager():getAllItems()
for i=allItems:size()-1,0,-1 do
local item = allItems:get(i)
-- do stuff with item
end
And they depend on how sorted the data is and how many duplicate values exist, and if you want a 'stable' sort or not. (aka duplicates remain in the same order they started in)
what is the 0 and -1? termination and step? Are we traversing in reverse?
Yes
Its faster to compare against 0 on the x86 and most processors than it is to compare against arbitrary values since there is often a 0 register.
Of course... have fun dealing with cache misses and such.
so of course 'it depends'
every day i thank god that i'm mostly writing gameplay code that doesn't really need to be significantly optimised
Right? iv done raytracing stuff where that kinda stupid 'wtf even is this?' optimization adding 10% actually matters lol
inner loops where the loop is only doing a few math operations, the loop starts becoming a signfiicant cost lol
Another thing that really helps as a programmer is to think of code execution frequency: If your doing an event spawned by a user input, you basically have unlimited time to process it because you know another user input isn't going to happen for 0.5+ seconds. lol
If your doing an event spawned by some NPC that you have 100's of, spamming that event every frame.. Now you have problems and better get that code running fast.
I spent wayy too much time optimizing UI stuff before I realized most UI buttons had a click frequency of <0.1hz -_-;
the problem is we usually think of performance in percentage increases ('it is 20% faster') etc and don't think about what it's 20% of
yea, making the code that eats 1% of your cpu time 99% faster does nothing. Making the code that eats 90% of your cpu time 10% faster is decent gains.
your maths code should be fast, your gameplay code should be pretty
And even then... gains are often situation dependent...
I recall one game dev testing a fix I gave.. saying it only did 5~10% FPS so not worth it...
... Except the most popular mod on the workshop spammed the ever living hell outta the entity that needed culling, meaning with that mod the fix was more like +25~50% FPS
and made the maps 2x bigger (4x area), so there was like 10x as many entities
% of fps is a meaningless statistic in the abstract 😅 the cost of a frame decreases as framerate increases
2D Game was dropping into the 10~30fps range on 1060GTX with cpu/gpu/ram that was WAYYY better then the 'recommended specs'
Not entirely due to that issue, but sure didn't help.
Other fun things it was doing: you know how video cards can.. tile a texture?
And many games, especially 2d ones will use a repeating texture?
Yea.... their engine broke down any polygon with a UV repeat style texture.. into separate draw calls for every repeat of the texture.
This wouldn't have been... that horrible, had one of there 'used absolutely everywhere' signs not had a like 16x16 tile background repeated over 100x300+ pixels
a tile background that was essentially just black + 2% random noise.
did they fix the engine to use shaders to properly UV repeat polygons? Hell no.
They just changed the sign background to be bigger and it increased their FPS by 20~30% on most vanilla ships -_-;
I am currenly trying to modify a building object's maxHealth on server via this construction:
object:removeFromWorld()
object:removeFromSquare()
object:setMaxHealth(newMaxHealth) -- extra hp
object:setHealth(newHealth)
object:setIsThumpable(true)
object:sync()
square:AddTileObject(object)
object:transmitCompleteItemToClients()```
Problem is that for such an object (which is a wooden wall in my case), it somehow hasn't any hit-detection anymore. When I manually hit it with a hammer, there is no hitting sound and the health is not reduced.
I don't think you want the lines:
object:removeFromWorld()
object:removeFromSquare()
but I could be wrong.
I also recommend not bothing with object:sync()
object:setMaxHealth(newMaxHealth) -- extra hp
object:setHealth(newHealth)
object:setIsThumpable(true)
square:transmitRemoveItemFromSquare(object)
object:transmitCompleteItemToClients()
is basically what I would do (though your free to have the remove at the start, it doesn't really matter)
the remove/send process should sync everything
i wouldn't overcomplicate adding/removing objects like this
And you don't actually need to remove/readd to the square on the server side, just tell the client you did.
all you need to add or remove an object is```lua
--add
square:transmitAddObjectToSquare(object, -1)
--remove
square:transmitRemoveItemFromSquare(object)
weird, migration guide says use transmitCompleteItemToClients
transmitAddObjectToSquare is more symetrical though..
transmitAddObjectToSquare adds it to the square for you
then it would be added twice?
code for adding objects in excavation literally just looks like this:```lua
local obj = IsoObject.getNew(square, sprite, nil, false)
square:transmitAddObjectToSquare(obj, -1)
Hes not adding an item, hes editing an existing one and just fake removing/readding it to make the game sync stuff it doesn't normally sync
Hmm nm transmitRemoveItemFromSquare does remove it from the world too
i mean your code actually removes the object from the square doesn't it? isn't that going to be an issue 😅
you want to readd it or the object doesn't exist on the server and all kinds of issues are going to come up but especially 'the object will disappear when you reload the area'
Yea point taken
didn't realize transmitRemoveItemFromSquare actually removes it.
I thought it was like the add/remove container transmits.. wait do they?
they don't
Also prob best not to try and 'sync' something that doesn't currently exist on the client 😛
But yea, Consider trying this @small topaz
square:transmitRemoveItemFromSquare(object)
square:transmitAddObjectToSquare(object, -1)
``` to sync the object
Like a custom sync packet is.. likely the 'best' way, but if this works... its the simplest way.
since you're doing this on object creation the ideal solution would be to find some way to slip between creation and transmission
oh I assumed he was upgrading existing walls or something?
are you upgrading existing walls or creating new ones?
Upgrading existing walls.
Yea, so try what I posted without any other sync code.
btw im pretty sure removeFromWorld tries to delete the object itself.
so, don't call that.
(likely why the object acts like a ghost afterwards)
object:setMaxHealth(newMaxHealth) -- extra hp
object:setHealth(newHealth)
object:setIsThumpable(true)
square:transmitRemoveItemFromSquare(object)
square:transmitAddObjectToSquare(object, -1)
(remove can happen after the settings are made, because changing those settings doesn't sync anything anyway)
and doing the remove/add syncs everything (hopefully)
that's for IsoObject parent class only, it is not sufficient for daughter classes. also if you add many in a row, you calling for too many sync.
is there a way to batch sync objects?
excavation does often create a decent amount of objects at once (~11 additions and 3 deletions can happen in one action) but i didn't think i had any choice but to sync them all separately
So no matter what version and order of commands I try, fake-removal of the object always destroys the hit-detection for me. But manually syncing the maxHealth by sending commands to the client seems to work without destroying the hit-detection. So I just take that as a solution...
However, syncing the maxHealth worked indeed fine with the fake-removal trick but this just introduced the new problem with the hit-detection. Some weird side-effects which I wasn't able to anticipate nor to understand...
There is a way to only sync once the square at least. I'm interested if you wanna make a peer review of Architect mod (ArchitectSave.lua => Arc.buildFromPOD)
Mmm toilet soup.
Still working on the 'add water' menu I guess.
Functionally works to fill your container up from any stationary water source
you find a clean way to make the ui elements?
i was just complaining to myself about how quickly it gets out of hand
alright, misery loves company
ive been trying to abstract away certain parts of it and im like.. should i even be doing this in Lua?
So in singleplayer, the event OnNewGame always fires when character dies and then the game starts with a new character fter selecting "continue with new character". This isn't the case in multiplayer anymore?
What is the event I can use in multiplayer then?
fuck lmao i didnt know about this that explains some of the bug reports i keep getting
just a quick search of the events EmmyLua put together theres an OnCharacterDeath with the note Triggered when any character dies, including zombies, players and animals.
which seems like a lot to hook into, but quick escapes could make it okay?
and it passes in the character that died
i wouldn't worry about it
it's not like hundreds of things die a tick
don't do unnecessary work of course but it'll be fine
albion the* pragmatic one
I haven't any bug reports yet but I guess they will come soon. (My updated mod is online for only a few days.)
It's probably about your character customisation mod? So for me in my mod, characters don't get their modded "body items" equipped after they die and choose "continue with new character". They are just vanilla then. But better test this yourself to be sure. Possible that there is another problem in my code (although I get the exact same problem in two of my mods.)
i need to test it yeah
testing b42 mp is such a fucking pain in the ass though it takes about 10+ minutes just to get past all the loading
Yeah, and even worse that we have to test the spawn mechanics, constantly creating new characters...
is there a quick way to kill your character or do you need to write your own stuff for testing?
getPlayer():die()
maybe reduce health, programatically
add a button and call it a day
is there a way in the lua to detect if -debug is active?
if lua can reach java env i think so
isDebugEnabled()?
really?
pretty close i think
alright, this might change some things for me - though you can join servers with the flag enabled i think so - worth keeping in mind maybe
yes, i just saw some vanilla lua scripts with that function call
isDebugEnabled()
greping into lua scripts, either vanilla or from mods is a good way to search for things
yeah, thats a better way^ than me opening my decompiled source and ctrl+clicking and doing something else while it searches
i also grep in the java decompiled code, but javadocs is better
i havent gotten proficient at reading those yet..
i still end up looking at all damned classes or methods half the time
readind the java sources?
the community maintained javadocs
i thought there was a java version of this https://demiurgequantified.github.io/ProjectZomboidLuaDocs/classISPanel.html
the type hierarchy?
not exactly like that, but... you can see the parent and children classes
example... ifyoi go here, you can see "direct known sublasses" https://demiurgequantified.github.io/ProjectZomboidJavaDocs/zombie/scripting/objects/BaseScriptObject.html
declaration: package: zombie.scripting.objects, class: BaseScriptObject
i plan to merge both of these into one custom site with better presentation eventually but i'm pretty burnt out on tools projects for now
only direct. So there is no fancy diagram with type hierarchy
dude the work already done is amazing
Question: There are several states you can spawn a zombie into, but is that one crawling animation through a window on top of something like a table one of them?
I just tested it a bit more: The event seems to fire as expected but for some reason, it doesn't execute the custom spawn logic for me anymore. So characters do not get equipped their correct items on start... That's even more weird!
So maybe we need to wait even longer before we can send smth to server after we choose "continue with new character"??? my default way to go is waiting 2 ticks...
was this a long time thing that food cooking in a stove does not update its cooking time when far out of sight ? (I guess uloaded)
No. Creating a new character in a mp game via "continue with new character" after death and then putting stuff in the new character's inventory when they spawn.
like a starter kit?
Yeah but also equipping new custom clothing items.
ahh, so the problem is which event you should wait to trigger the requip code, right?
Yes somehow. For me, the thing is that the event OnNewGame fires then but in this particular situation, it doesn't put the new stuff to the inventory
mine is 3 ticks i think but ive not tested if it works yet
maybe that is not a new game
seems like you could use a combo of OnCharacterDeath and OnCreatePlayer but im not sure if you get any information about the player logged in
So the event definitely fires then. I just tested it a few times now...
like if you stored info about the player that died and find a way to link it to the created player you might be able do what you are looking for
im for sure spit-balling and giving a naive answer
i think the problem is not that.. so the event triggers but the callback code doesn't run?
have you done the basic "print" method to see if you see anything in the console?
How does one get the icon of an isoobject? (Like what shows up when you right click it, in the context menu?)
isn't that usually just its world sprite
so isoObject:getSprite(): something?
Situation is really bad. Even if I wait 30 ticks, it simply doesn't send anything to the server...
I am afraid not for what I need to do...
maybe you need to recurse into all the objects
sync player, sync InventoryItems
etc etc
No that won't solve the issue. Problem is for me that in this particular situation, the server will simply not receive or detect client commands.
But here it is: I just waited 1000 ticks and then it worked! XD
voilá! Patience solves it always 😄
@winter bolt if you really can confirm that you have the same problem like me (i.e. server doesn't add/equip correct items after player death and choosing "continue with new character"), try waiting 1000 ticks before you send commands from client to server after the new character has spawned in. That seems to work for me. The event OnNewGame seems to be still the correct event for this. Only the waiting time gets longer.
getTexture(isoObject:getSprite():getName()) thanks.
Behare the toilet seat.
Toilets should have a warning sign "Carefull with the toilet seat when consuming drinks"
not gonna lie - lua is annoying, but it reminds me of my roots with duck/loosely typed languages and the interesting features that kinda let you implement more oop-based patterns
though im curious what the implications of instances are for memory
do they "compile" the lua on launch?
What do you mean by compile, exactly? The Lua is loaded and executed by (modified) Kahlua
Should probably check out the game's version in particular; Kahlua itself is unmaintained
this was already something i ran up against while "type-hinting" Numbers are mapped to Double.
it wasnt an actual code issue, but im very nutty about making sure my IDE knows my intentions
especially in these languages
im not as good at holding long-term states in my head anymore so i need my cheat codes
No
yeah, it looks like its just interpreted and translated to java