#mod_development
1 messages ยท Page 87 of 1
better go to mapping
alrighty
as for transmitting before clients load it unfortunately cant be done
can only use client/server commands starting from the first tick which is after character creation
Oof
you would need to have an ingame character creator for those custom traits
Damn.
but anyway on that link you have the cool config tech i came up with
Well, that news saves me a lot of time but will surely disappoint a few users lmao. Thanks for it, nevertheless.
the config is a lua function that returns a table with the settings
Nice. Well I'll definitely consider it for other client-server stuff but if I can't intervene with the server settings clientside early enough to mod the trait based on server settings, I think I'm at a bit of a technical wall...
It's release 5 mods at different trait costs (๐คฎ) or just let people republish the mod if they REALLY want to change a trait cost that badly.
Or let people vote on the trait cost on my mod page maybe lol
make it easy to patch into
or really hardcode everything and say people are not allowed to redistribute
this is what made me take a break for several months
wanting to do things and the game just not letting me the way i wanted
speaking of this, do you know what the consensus in the community regarding this? there's the tradeoff of cluttering the fuck out of the global namespace, versus people not being able to use/override your code because it's local
yeah im changing my whole code to work with modules
...
---FILE 1 = lua/client/myStuff.lua
local module = {}
function module.func1() end
function module.func2() end
return module
---FILE 2 = lua/client/myOtherStuff.lua
local myModule = require "myStuff"
local function thing()
myModule.func1()
end
this is the basic theory in modules usage
you forgot the export
how would a module solve that issue? you still can't remove event handler instances without a reference, right?
forgot the export?
here
now im confused ๐
i thought i had it now im doubting myself
hmmm you mean returning the module?
so i didnt forget the export ๐
senpai @sour island taught me the modules thingie
after almost a whole year bitching i finally managed to get people to stop using globals
i was using files just not to use globals
but that meant a lot of reading and writing files, so not a very viable solution in the long term
ah didnt answer about events
modules are passed by reference so you do indeed have the reference to the functions
oh, so the function would effectively be a child of the module reference? that's nice, yeah.
wouldn't there be performance overhead, the larger a module is (or the more modules + module children that exist)? or is it basically negligible?
obviously adding to already bloated events that fire frequently would affect performance way more so that'd be the first area of focus, but still
all i know is that i can make my code more clean and optimized using modules
and a lot easier to use and read
once you go modules you never go back ๐
local accesses are faster than global
and modules are usually tables
which the global space is too
if you didnt know _G is the name of the global table
but wouldn't it be a global access if it's being loaded into what's effectively a global table, as a child member of the module? or is it only a pointer to the local version of the function? I assumed the latter (the local function) was GC'd out and the module's copy is what's used, but that's probably incorrect if what you're saying is true. I'm still trying to get out of C/C#/Rust patterns and back into Lua's quirks, if that isn't entirely obvious
in real lua behind the scenes its all C code
sure, but without the keywords and whatnot (or a previous understanding of what's going on under the hood) it's hard to tell what the behavior is like on a lower level
the way modules work is the reference to the exported variable is saved
whenever something requires it the referece is returned
so its just pointers
okay yeah, that makes more sense. is localized data kept only if it has an existing pointer in the global namespace, or is it ALL kept no matter what until the lua is completely unloaded?
now speaking java
if theres a reference to something then it isnt garbage collected
yeah, I figured that'd fall under java's GC. that's really nice, I was afraid every single local object was remaining allocated, so that's a relief lmao
Can you teach me that
@ancient grail here number 2
Just a note. If your purpose of replacing it is cuz u wanted the poster to show up on places with minimal effort then thats the right path but if you just think its easier to replace than to create well its not.. its better to create your own of this is the case.. just saying
Glytch3r my dude, that vault lookup code I showed you in DMs was a module, the one you couldn't get to work
well if there is a way to replace them without going into mapping, im all ears
I remember this i was there during that discussion
Nope u jave to the tile process just the same
Its the same thing
ah
Cuz the files are pack files not png
well this whole mapping tool is unwieldly, having a hard time understanding it
#mapping has pin posts you should check ot out
That can be true due to its confusing nature and lack of documentation but its not impossible to learn it
I suggest watching daddy dirks youtube
Then ask mapping for questions
i also second that. the map suite is unwieldy as fuck, and very old
the tutorials are necessary unless you're experienced with similar software (and even then, you'd probably still have trouble)
True
yeah I'm watching that but I guess I will skip a bit as I am not creating my own map, just trying to understand how this awful program works ๐
Esp cuz tile zed isnt 100% for pz its used for various games too
I did the same i never intended to make maps but i needed to make tiles
Heres a bit where i got stuck before .
How to spawn it in game
Options are
Create moveables
Lua
Map
Tile picker
I never knew these stuff before and i went crazy trying to learn how to spawn them lol
there is this little "open in tilezed" option on right clich, which I assume is where I can remove it
but it doesnt work lol
trying to remove a few piece of things is enough to melt my brain, never mind adding more lol
Yo, question anyone know how the debug tiles picker works? There's a tile I found in game but can't find in tiled.
use the chunk debugger, it'll tell you exactly which tiles are on the square
Thank, now I can use the PZ map as a glorified tile picker
anyone know if there's a more performant event to use than LoadGridsquare if I'm checking for a specific object? seems like it might be the only option, but I haven't really dug in very far yet either
by "object" I should probably specify, it'd be a tile with a specific sprite (I don't think I'll have any issues there - plenty of examples exist - but it's the frequency of LoadGridsquare looping through like 500-1300 iterations that scares me)
what are you trying to do
Anybody tries to debug the saphs heaters mod ? There's an issue with the moddata in MP after restarting the server and I can't figure it out
just operate on a square whenever it's rendered, if it contains the given tile
i'm assuming LoadGridsquare is called whenever each square in a chunk is loaded, so that'd be the method needed if I'm trying to effectively modify a square whenever it's visible to the player
but if that's just inital load, i.e. when the chunk is written to the save or whatever for the first time, then I imagine that's what ReuseGridsquare is for? not sure.
I'm mainly seeing if there are more performant options though, but I'm guessing there isn't one. just trying to see if I missed anything along the way before I use something an event that's so performance-draining
i still dont know what youre trying to do
which part are you unsure about?
context
if your requirement is "I want to do something when a square is loaded", obviously the answer is to use the event when the square is loaded LoadGridSquare. The question is what are you actually doing, because it could potentially be done differently
I'm not entirely sure where I'm going to take it yet, but just for example let's say I'm replacing all instances of blends_natural_01_64 (dirt) with blends_natural_01_0 (sand, I think, if I'm remembering correctly)
then yeah that would have to be LoadGridSquare
alright. what about ReuseGridsquare? that's a little fuzzy for me still, but I'm guessing it's something along the lines of "when a square is already loaded, but it's updated"
i didn't delve into the source yet to try to decipher it, just going off of assumptions
a lot of functions/methods are poorly named, be careful ๐
tru
i remember hearing it was called before a square unloads, but i never used it so i can't say if that's right or not
ive briefly looked at the reuser code before but I didn't really delve in enough to understand it, I'm guessing it's some sort of buffer
Yall still trying to see if this is possible.. updating a tooltip indirectly by doing it from a lua code instead of editing every script item? Got a lotta items to update and can't figure out how to use the methods getTooltip and setTooltip
Adding smth like at the very bottom of the element of the tooltip, kinda like they have weight: ...
if only i had started using modules from the start... damn...
changing all the code to work that way... is a damn boring task
How come
because now i am creating a separate file for each part of the MOD.
one file for each type of event ( char events, car events, weather events, etc )
easier to add something in the future
it also makes your code less of a clusterfuck and more accessible if people need to patch things up
and for testing
a lot easier... i just add another require to the bit im testing
and have no risk of breaking any of the code thats was previously done
Hmm, not sure I follow, then again my code was never big per se
So might never had to do it
mine is getting bigger and bigger
Yeah I'm working on something bigger now so might take this into account
this way like @finite radish said if less of a clusterfuck easier to use, update, fix and add stuff to it
Can you also return tables with modules?
it's always a good idea to do it
So basically a module is a lua file that has functions the mod requires or anything else basically?
and the module itself is table... for lua everything is a damn table ๐
it's a global lua object that contains references to all the objects within a file
whoops responded to the wrong comment, but you get the idea
So if you make a module for a lua file containing a table, you return it as M for example. When you require the module as local module = require...
How do you get the table values of the table within that module?
M.tablename.value
?
yes, precisely
Im using mobile so just typing freehand
local module = {}
module.foo = "bar"
return module
-- other file
local module = require "file1.lua"
print(module.foo)
it's just a table being passed between the files
That's very interesting, I'll definitely start using that more
in my case
function TWE_Events.TWECars(Mypart)
--do something
end
local TWE_Events.playerChar = getPlayer()
local TWE_Events.pzCalendar = PZCalendar.getInstance()
local TWE_Events.timervalue = 0
local TWE_Events.TWEtrait = ""
function TWE_Events.TWE_TraitCheck()
--do something
end
function TWE_Events.TWE_addTrait()
--do something
end
return TWE_Traits
Might result in more files but less overall code breaking I assume
by requiring the file that has the module
Having learned you can put folders in the lua folders helped me a lot lol
i can then do something like
local whatever = require("file")
and then call anything in the module just by
whatever.TWEcars(value)
Copied that msg link, thanks a lot mess
or the vars,
whatever.TWEtrait = "value i want"
I have a huge ass table at the moment and placing it in diff files by category and using modules might be a lifesaver
If you daisy chain modules do they get all the values the previous modules got?
you can return module1, module2
i wonder, did Lua steal modules from JS, did JS steal modules from Lua, or did they both get the idea from C header files/externs? 
then to access it you need to do
local mymod1, mymod2 = require("file")
Since yall are here, any idea on this?
i refuse to work with UI in pz... melts my brain and dont need it to do the mods i want... so i cant help you there ๐
what issue are you having with setTooltip? seems like that'd cover your bases
I can't understand how it works. I am using it like, local tooltip = item...getTooltip()
local setTip = item:setTooltip(tooltip .. "my value")
I paraphrased it a lot there
but in a nutshell that's how I tried using it
also item:setTooltip("Something")
Did you test whether these files will be preloaded as well when lua initializes? Or will it do it runtime?
they load as normal lua
Mh, I see. Good to know
the game just loads all the lua file inside the client shared or server folder
doesnt care what it is, as long as its .lua
Since i prevented parsing files at runtime but tbh never checked that fact
if you dont want it to load before the game starts you can just name it something else like
myfile.lua change it to myfile.nop
and then require the myfile.nop when you want to load it
in theory that should work
but never tried it to be honest
are you trying to do this in a new UI, or are you trying to edit the item's normal tooltip? because if you call this on the item, it'll only set the normal tooltip
Trying to edit the normal tooltip and add my own mix to it
hmm
yeah you'd have to dig a bit, it looks like the InventoryItem version of setTooltip isn't used at all - in lua or in java
grab the default tooltip and append what you want to it i think
and replace the normal tooltip with the one you edited
but thats me talking, since i have no idea how you can do that ๐
I tried, didn't work :/
I go by my rule of thumb that if I thought of it, it's 10x more difficult than that ๐
I dug around how tooltips are set up in some lua files but they were VERY confusing to say the least lol
if you're looking for particular sprites you can use MapObjects
You mean that hover tooltips?
Ye
not sure who it is or if I'm late
--ISEatFoodAction, remove negative effects from item before self.character:Eat(...) reapply after
local checkDangerousUncookedPatch = function(ISEatFoodAction)
return function(self,...)
if self.item:isbDangerousUncooked() and self.character:HasTrait("_") then --fixme Primitive?
self.item:setbDangerousUncooked(false)
local r = ISEatFoodAction(self,...)
self.item:setbDangerousUncooked(true)
return r
else
return ISEatFoodAction(self,...)
end
end
end
ISEatFoodAction.stop = checkDangerousUncookedPatch(ISEatFoodAction.stop)
ISEatFoodAction.perform = checkDangerousUncookedPatch(ISEatFoodAction.perform)
Maybe it will help you if you take a look in this class:
https://github.com/stuck1a/GartenEdenImprovements/blob/main/media/lua/server/ExtBuilding/BuildingObjects/ISWaterCollector.lua#L74
There I generate the tooltip for my water well
or for all water collector typed map objects
It will render an amount bar. That draw stuff works similiar like working with GDI
Copied msg link, thanks ๐
np. And if you worry about context menu tooltips, you can find an example in the base class ISExtBuildingObject (same dir) of this mod. It generates the tooltips for all derived classes (buildings)
Thanks, gonna check all this out l8er, moved on to another function within the file but this will give me some reading later ๐
just managed to crash my game for the first time with a function
accidentally gave myself about... welll... whatever 30,000 * 50 is
of an item
1,500,000 apparently
that's rich
yikes lol
Well, as you know, you learn the most from mistakes lol
yeah, definitely did, note to self: if using a for loop, it'll give an amount for each iteration of the loop, not once lmfao
what a mistake eh
it looped once and gave me 3000, then I did it again and it did 3000 * 50
XD
i spawned 9999 zombies while i was recording a showcase of the app the mod uses for youtube
the game handled it... but it became a slideshow
jesus
i had set the value of zombies to spawn to 9999 in a previous showcase, where all the game did was make the char say what the reward was set to
after adding the actual code to make the zombies spawn i didnt even remember that i had set it to 9k
๐
The base core of the mod is done. Now need to add the Air Events and the alpha will be ready for public release and testing. Hopefully i will be able to add more events ( car events: flat tire, stall engine, etc ) before the release. And after that keep adding more diversity to the events, both positive and negative. Thanks for watching.
but now i know the game can handle 9999 zombies
yup
amazing
im almost sure if i did this 1 year ago the game would probably crash
impossible!
what @fast galleon ?
heya @dull moss
i changed your code a bit, the one you provided for my traits rewards
local pzCalendar = PZCalendar.getInstance()
local timervalue = 0
local TWEtrait = ""
function TWE_TraitCheck()
local currentTime = pzCalendar:get(Calendar.HOUR_OF_DAY) *60 + pzCalendar:get(Calendar.MINUTE)
if currentTime - timervalue >= startTime then
player:getTraits():remove(TWEtrait);
HaloTextHelper.addTextWithArrow(player, getText("UI_trait_"..TWEtrait), false, HaloTextHelper.getColorRed())
Events.EveryTenMinutes.Remove(TraitCheck)
end
end
function TWE_addTrait()
if not playerChar:HasTrait(TWEtrait) then
playerChar:getTraits():add(TWEtrait);
HaloTextHelper.addTextWithArrow(playerChar, getText("UI_trait_"..TWEtrait), true, HaloTextHelper.getColorGreen())
Events.EveryTenMinutes.Remove(TraitCheck);
Events.EveryTenMinutes.Add(TraitCheck);
end
end```
managed to get the real world time in the game
๐
oh... yeah... i have it set to 50
or something
very cool
no settings are needed inside the game

?
I mean yea if u got interface between PZ and app then you dont need to do shit in-game
to work with twitch a third party app is always needed since the game doesnt have native integration
it's over 9000
so i might as well do as much work on the app side and less on the mod side
dang dbz
my brain is so melted that i didnt even recognize the quote ๐
the amount of melted brains this chat has we could recreate it into a superhuman
frankenstein the man not the code
I went to lay down for an hour earlier just because looking at this code hurt me
after all ive learned here, if i didnt beuatify my code i would be ashamed of myself... even if im feeling a bit of regret of un franksteining my code...
more work thatn writing in the first place ...
yea refactoring can be rly annoying
so the lesson learned is: if you gonna do it, do it the right way from the start
Yea well... if possible. Sometimes really hard if you don't plan every detail before
a lot of copy paste going on
and sometimes i get lost
๐
but the main lua file is getting smaller and smaller
almost done ๐
Sounds familiar ๐
I sent them this application and it worked... https://m.youtube.com/watch?v=BinWA0EenDY
DABUDI DABIDAI
stupid question... if i do local myfuction() end
that function is only available inside the file where i have it right?
afaik yes since it's local
good
im to lazy to run the game to test it... wanna finish the modules 1st ๐
so i can get an error, rage about it, fix it, get another one and keep on raging ๐
big part of me cleaning up my first mod was just making some variables global and then deleting 50% of the code because of the now unnecessary local variables ๐คฃ
i dont recomend the use of global vars
thats one of the reasons im converting my code using the modules aproach
oo shit why not
imagine if everyone uses globals
overwriting?
the game will have a shit ton of globals
and yes theres a risk that someone might overwrite it
ah but you're saying moreso it'll be unoptimized af
yes that too
not to mention its burning resources that can be put elsewhere for a better game experience
the less your mod uses of the available resources the better
well time to have dinner... almost done... better rage with a full belly.
yea the _G already comes overloaded vanilla
And locals are quite faster as well, since no namespace lookup is required
It even makes sense to store a local pointer to any global which is frequently looped within a script. Doing this sometimes for luautils etc
Its mentioned earlier that you can return it right
@thick karma what if they intentionally named the var Unhappyness to prevent being overwritten
lol
prefixing globals at least with your vendor tag or sth like this isn't a bad idea
Why did it click that link omg
Last song syndrome
And you thought hanging here will do u better ๐
Ow right you are making twitch related pz mod.
I wonder sou did the same thing
I remember he can let audience spawn zed
I get anxiety when I hear I started making a mod that someone else already did ๐คฃ
Now I do some google searches for if something exists
@ancient grail Oh, you are talking about @pulsar heath . I went all the RCON route inspired by his hotkey based mod
Yep yep how r u man
I wonder what all you do for a living since you're such talented coders
I do code to be fair
Man I wish I was in a coding career
Not as releasing programs, but to customize an existing program to deal with what the clients want
Working as lead programmer in a computer manufacture
Whats your linenof work if u dont mind me asking
I'm more like a consultant
My job experience so far is parking monitor (3-4 years), supermarket for 2 months, bakery for a month and a half. Unemployed atm but I had some troubles irl so couldn't work for a few years
Not the greatest resume
Ah it somethings rly sucks, having deadlines, reviewing pull requests of unable junior devs. Have to code projects you have to, not you would possibly prefer
Im unemployed . Used todo freelance graphics and animation. Niche to pz modding
I started programing when I was working as an Accountant Assistant
I went all in with Excel
I'd love to get into such a career but have no clue where to even start lol
I LOVE EXCEL
I used to program some stuff in excel VBA
Check for accounting jobs
Working on a giant ecommerce system for about an year. I think only accounting software would interest me even less. But at least almost done
Say you know nothing about tax or anything but you think you can help at least to make everything faster
Damn hope u overcome those trouble . We all have to carry certain hardship im from a third world country so multiply that by 3
Oh yeah I def could, I can improve any workflow in excel by miles after what I've seen people here do
I'm from Croatia, not sure if that counts as well ๐คฃ๐คฃ
Nice sounds like a good gig
But dont go all too cocky. Just say you can try to automate some tasks
I did this because my main job was accounting, so I had tasks that needed to be done
And I am lazy af
So I tried to make it easier for me
I only know how to improve a workflow because I love, absolutely love learning functions in excel. So many ๐คค
Turns out, people usually just do what they do because they cant figure out a way to be better
Ye
Its like "Well, this works, so I'll do like this forever"
Most people I've seen that don't know how to use computers isn't because they're dumb or lazy it's just because they're afraid to fk something up
Just remember that everything you do in company time is company property
So if you code a PZ mod it's theirs? ๐คฃ
Croatia is considered to have a high income economy
TECHNICALLY yes? haha
Tourism babey, that's my school as well
Based on a site i just looked at
But you shouldn't do pz code during work anyways haha
for the record if you make a PZ mod its yours
I'm really glad that my boss doesn't think that way
Hi
I mean, I think if you are paid for your time at the company and you are doing tools for the company during that time, they are tools for the company, ya know?
For now....
Its how I do things at least, and it worked pretty well until now
If I code a nice JS package for a web project I will of course use it private as well lol
On the other site I've also provide libs and stuff I've in free time
Not judging anyone who does things differently
So how do i recieve twotch data output and send it to rcon
Oh, sorry. What I meant was "If you leave, dont go deleting things"
I do have copies of things that I've done too, without any company data ofc
lol yeah sure
๐
I once did as a joke to make a popup message on my birthday
Screw u company that fed me! Im a big boy now
Is there a file in the folders with item rarities based on the rarity selection in game?
Or is that top sikrit
But my boss was kinda cool at the time. It was like my first job, so he was teaching me what was not so good to be done
U mean the distributions?
Hmm, well basically what decides how much of a certain item spawns in the world
those are egenerated in game?
distributions table * sandbox * other factors
U can also use the debug lootzed
So I'm on the lookout for a distro table
I need to find out some values that decide how much for example of a katana will spawn in the world
Ow thank you u just made me remember my question!
How do i remove vehicle distribution like the cars themselves
search in Distributions / ProceduralDistributions
For a server to have some vehicles only spawned by admins for event prizes
Thanks my man
And whats the difference with procedural and regular distrib
Rarity is handled by dice system, see \media\lua\server\Items\ProceduralDistributions.lua
ProceduralDistributions has the distributions and distributionss has both distributions and procedural
so i've been fucking with my sandbox options file and I broke something, anyone knows any way of figuring out what went wrong?
ERROR: General , 1673990893719> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: java.lang.IllegalArgumentException at GameWindow.mainThreadInit line:580. Message: Unhandled java.lang.RuntimeException thrown by thread MainThread.
ERROR: General , 1673990893719> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: java.lang.IllegalArgumentException
at zombie.GameWindow.mainThreadInit(GameWindow.java:580)
at zombie.GameWindow.mainThread(GameWindow.java:489)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException
at zombie.config.IntegerConfigOption.<init>(IntegerConfigOption.java:15)
at zombie.SandboxOptions$IntegerSandboxOption.<init>(SandboxOptions.java:1097)
at zombie.SandboxOptions.newCustomOption(SandboxOptions.java:1946)
at zombie.sandbox.CustomSandboxOptions.initInstance(CustomSandboxOptions.java:56)
at zombie.GameWindow.init(GameWindow.java:1204)
at zombie.GameWindow.mainThreadInit(GameWindow.java:576)
... 2 more
LOG : General , 1673990893720> GameThread exited.
cuz my sandbox settings is 1k lines
one of your integer options seems borked
ye I also was thinking that based on error I put a letter somewhere by accident
So I'm in the distro file, it says there's 4 rolls, per item there's a number asigned from 1 - 4 and at the very top of all this, the containers have a min 0 and max 99 value
I'm at a loss as to what all this means 
Dice rolls each number rolls that item a dice the higher the number the more the dice rolls for it
Im not sure
But this is what ive always thought it was
Its saafe to assume anyways
So if a cockroach has a number of 2, there's 4 rolls. It rolls 4*2 and whichever item has the highest diceroll, that item spawns?
no, they all roll and if chance > random it is added
here
rolls happen in java, 4 rolls for each item, each roll is evaluated separately
what's the number 1 then
~1 / 100
So many items and he picked cockroach
๐ชณ๐ชณ
it's a big formulla, decompile and read ItemPickerJava
Found the bug?
If its on sandbox u can always use
local blahblah = sandboxvar.blahblah or 1
@drifting ore what do you want to edit? Just know chance for base katana?
For a mod I'm writing I just want to take a look at the chances an item spawns, or at least try to understand how it decides the factor
yes, but it's quite weird
That second value is the weight
So I guess its worth depends on the amount and values of the other items
You can start with a value of a similar item and then ingame, refresh the contents of containers to see if it matches your expectations.
And use LootZed to give you an % estimate.
Is lootZed an in game feature? never heard of it
looking on their forums now it says they added it
all items are independent of each other, until the container is full obviously
really cool
it's a debug cheat tool
ah yes, just found it, tyvm ๐
Just turn on debug then powers then tick lootzed
Right click on the contaainer ICON
enable cheat, right click container in inventory loot pane
Just a spontaneous thought: Adjusting the vehicle scripts when OnInitWorld fires? Couldn't find any exposed method or function to manipulate the vehicle spawn process
he's too fast for us now
Alright. Do you know in which Java class the calculation is done?
Is it possible to just have the same file name and shove it on a similar folder but with no contents will that kill the spawn
ItemPickerJava
ty
He already mentioned that tho
Anyone has a snippet of the vehicle distrib line like adding it
Im on mobile just need to provide to the server admins so they can do it
Nvm ill look for it tom thnx guys. Have a good one . ๐ค
No
So this is basically the formula which decides whether a roll succeed, if I did not missinterpret the java source
Rand.Next(10000) <= TraitModifier * 100.0 * LootModifier + ZombieDensityCap * 10.0 == true
Yeah was just using lootzed to try and compare values with the distro and looks like it's way more complicated like you pointed out
Oh sorry, didn't see that. I'm coding on the side
Interesting
@drifting stump Do you have any quick and dirty recommendations for prevention of double-loading of required files? I'm under the impression _LOADED takes the input to require as the key for the stored table to prevent double-load, which allows foo and foo.lua to create separate keys (if people use different formats requiring your mod). I guess I could just check _LOADED manually, but I'm curious if there's a slicker solution. Also, how does require work if its pattern hits multiple files? Does it stop on the first? (I imagine return data merging would be odd.)
I just use
if not MyClassFile then require 'MyClassFile' end
to prevent that
"Claustophobic" "HeartyAppitite" "Unhappyness"
||disclaimer: even though video shows very angry man please don't consider this an offence to PZ devs, just thought it'd be funne cuz it's relatable||
https://www.youtube.com/watch?v=7rGz3E4qxhQ
having spelling errors in my code hurts me on emotional level
Haha banned.
โค๏ธ
I'm curious now, if I require "A" and there is an A.lua in \server\ and \shared, which one do I get?? hmm
having spelling errors in my code hurts me on emotional level
the one in same folder you require it in, i think?
and if I'm in client?
then you need to specify, no?
I don't know, but I don't think so? I'm pretty sure I've required from shared from both client and server before, but I may be misremembering
actually I definitely do, almost all my modules require the base lua in the shared folder for something or other
updating my mod actually... the 1st version i made was like 2 years ago, then EHE came out and i had to update the mod to use it... now... im just updating it to be a better mod and easier to use... the only 2 mods i made for pz were for personal use but so many streamers bugged me to release i ended up being dumb enough to do it...
I believe require depends on a path variable that I would imagine the devs have manually set... it's conceivable it would search every possibly game directory for foo.lua
What I am unclear about is what happens if it hits twice.
iirc i couldn't require a folder in server from client
Okay good to know. But what if I have X.lua in client and shared, e.g.?
and I require("X")
I assume its a recursive search, with some sort of priority between the folders, maybe just alphabetic
since none of my files have matching names, I hadn't thought about it until now
ya, if all the files get flattened out so that, for example, every file in every mod's shared folder all end up on a single virtual shared folder that lua looks in, its certainly possible to have collisions. I might want to move all my files into a subfolder
I did funny mistake earlier
Had one function in server file and one in shared with same name
Was calling the one in shared first
Did the second one load too?
I guess the second one got overwritten or smthing
I have a strange problem when trying to "decorate"/patch a vanilla function. The function I try to patch is in vanilla lua/client/ISUI/ISCraftingUI.lua. I've put the code in my mod's lua/client/ISUI. And get strange errors when playtesting. Anyone an idea? Here is my code:
ah same function name or file name
if they're both global, only the server one would exist in the end, afaik
Here is the Java code of where the require command is handled by the vm
public int call(final LuaCallFrame luaCallFrame, final int n) {
final KahluaTable environment = luaCallFrame.getEnvironment();
final Map map = (Map)luaCallFrame.getThread().tableget(environment, this);
final String stringArg = KahluaUtil.getStringArg(luaCallFrame, 1, "require");
final Result result = map.get(stringArg);
if (result == null) {
this.setState(map, stringArg, Result.LOADING);
final Reader luaSource = this.luaSourceProvider.getLuaSource(stringArg);
if (luaSource == null) {
this.error((Map<String, Result>)map, stringArg, "Does not exist: " + stringArg);
}
try {
final LuaClosure loadis = LuaCompiler.loadis(luaSource, stringArg, environment);
this.setState(map, stringArg, Result.LOADING);
luaCallFrame.getThread().call(loadis, null, null, null);
this.setState(map, stringArg, Result.LOADED);
return 0;
}
catch (final IOException ex) {
this.error((Map<String, Result>)map, stringArg, "Error in: " + stringArg + ": " + ex.getMessage());
}
catch (final RuntimeException ex2) {
final String s = "Error in: " + stringArg + ": " + ex2.getMessage();
this.setState(map, stringArg, Result.error(s));
throw new RuntimeException(s, ex2);
}
}
if (result == Result.LOADING) {
this.error((Map<String, Result>)map, stringArg, "Circular dependency found for: " + stringArg);
}
if (result.state == State.BROKEN) {
KahluaUtil.fail(result.errorMessage);
}
return 0;
}
code block please
how was that again? not too familar with discord lol
//stuff
alright thx
Maybe I just forgot some silly syntax stuff but I am really surprised that it doesn't work since I use this "decorating vanilla functions" quite often...
looks like it should work tbh
I don't think that code shows the path rules they use
I am really freaking out! I have made a test mod containing nothing than those lines of code. The function I am patching is related to the crafting menu. Whenever I open the crafting when the test mod is running, I get hundreds of errors (which are produced by a function I am not touching according to console.txt)
the function inputs match the vanilla one as well?
Yes, but at least that it will check its environment at the very first. iirc it defines three separate env's for server, client and shared
I expect to be able to test my very first mod in the next few days.
Ideally with a release this week-end ๐
Learning modding by tinkering in game files
I think so. Here are the first lines of the vanilla function:
unless your mod fits in a single file per folder i highly recommend doing this
you added a ... to the function signature, don't think you can do that
you can have less weird filenames without worrying about conflicts
ya, all my filenames are prefixed with the modID, I could probably omit that. Then the requires need the subfolder in them though, right?
yep
oof
works for me fine in all in other cases but I'll still try without the dots and see what happens
the only situation i wouldn't make my own folder is if my mod fits in a single file anyway (unless it might not in the future)
So now I need to potentially consider client/foo, client/foo.lua, foo, and foo.lua to target a single file in client if I have foo in client and shared and others want to import either or both
Isn't that valid Lua?
trying to remember
nope, remove the dots does not change anything
I mean in general you can do it
afaik this should usually work (at least I use it always without issues)
ya I guess so, thinking about it more. Lua doesn't support overloading, but you're just replacing it altogether
This causes no issues in the online Lua demo app:
function bob(a,b,c)
print(a + b + c)
end
bob(1,2,3,4,5)
strange error usually means you have a nil somewhere? 
for easier comparison, I'll post my code again with the original vanilla function in the same file:
what kind of errors are you seeing?
there must be a stupid mistake I can't see!!!!
one mom... I make a console.txt
I think stuff like this will break if you're actually calling a marshalled java method, but in this context all we're dealing with is pure lua, so ya it should work
For sure.
What is the name of your file?
does the vanilla function return anything?
here is the error (it repeats as long as I have the craft menu open):
yeah, sounds like something went nil somewhere
the first few lines:
STACK TRACE
function: prerender -- file: ISScrollingListBox.lua line # 426 | Vanilla
ERROR: General , 1673994688860> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: __sub not defined for operands in prerender at KahluaUtil.fail line:82.
ERROR: General , 1673994688860> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: __sub not defined for operands in prerender
it's testModCode.lua
Ah here is the entry point for require
public static Object require(String var0) {
String var1 = var0;
(!var0.endsWith(".lua")) {
= var0 + ".lua";
}
for (int var2 = 0; var2 < LuaManager.paths.size(); ++var2) {
String var3 = (String)LuaManager.paths.get(var2);
String var4 = ZomboidFileSystem.instance.getAbsolutePath(var3 + var1);
if (var4 != null) {
return LuaManager.RunLua(ZomboidFileSystem.instance.getString(var4));
}
}
DebugLog.Lua.warn("require(\"" + var0 + "\") failed");
return null;
}
So before doing any checks for require("A") it will be rewritten to "A.lua"
yes it does
there's yer problem then
require "ISUI/ISCollapsableWindow"
local vanilla_code = ISCraftingUI.drawNonEvolvedIngredient
function ISCraftingUI.drawNonEvolvedIngredient(self, y, item, alt, ...)
return vanilla_code(self, y, item, alt, ...) -- execute vanilla code
end
that's probably it! and I was already sure that I just forgot some tiny detail!! ๐ I was freaking out!!!
many thanks again!!
guess its not recursive, if it just iterates through LuaManager.paths, which looks like an ArrayList from this code
I just return by default when hooking a function like that, worse case scenario it does nothing
hey guys any chance anyone knows why the model not appearing in game?
i tried to mod the envelope but the model not showing in game
oh i found out that my scaling is wrong
do you guys know where i can change it?
is it surface?
When you export your FBX you can adjust the scaling in Blender, it usually needs to be really small, like .01
Can also adjust it in your models txt file
Hello, I'm having some problems overriding a function.
ISInventoryPaneContextMenu.dropItem = function(item, player)
In my overriden function, for some reason, it seems like self gets the item value, and the item gets the player value. Player is just nil. What am I missing?
you can
ty
way past that now fam
just to add some info, this is how I'm handling stuff at the moment
function ISInventoryPaneContextMenu:dropItem(item, player)
if CheckIfItemIsAmputatedLimb(self) == false and CheckIfItemIsInstalledProsthesis(self) == false then
og_ISInventoryPaneContextMenuDropItem(item, player)
end
end```
is the vanilla function ISInventoryPaneContextMenu.dropItem or ISInventoryPaneContextMenu:dropItem ?
that's gonna show how little I know about lua. The first one
btw how do you make it so that code fragments are shown in those black boxes when chatting here on discord?
three ` and another three at the end

if its the first one, you can't use : and there is no self variable
is that the only difference between those operators?
yes, : means it has a hidden self input ahead of all the others
yes
jesus
well, thanks
I thought I was missing something else entirely
makes sense now, thanks
another quick question, having the require when you're overriding functions from another file is not necessary, right?
that's just a precaution, correct?
require is only necessary if
A: you're in a scenario where it may not have loaded yet, which doesn't apply if you're talking about a vanilla file, as they are all loaded before modded files are
B: The functions in the target file are local to that file and returned in a table at the end
and have faith that no modder overwrites that file
uff... finally done... some things i need to check out and change but for now its done
time to test it properly
my main lua file looks so pretty ๐
local myevents = require("TWEEVENTS_Events")
Events.EveryOneMinute.Add(myevents.getreward())```
and its wrong lol
new stupidity record goes for MEEEEEEEE
๐
thank you thank you, i receive this stupidity award and would like to thank me, myself, and i for the amazing level of stupidity i can bring to the chat!
Something else just occurred to me. If the require table uses the lookup string as the key... Then wouldn't another mod using your filename possibly prevent require from working (as expected, in the sense that it returns your file if someone wants it)?
dunno but thats why i use "weird" names
the code earlier makes it look like it uses the full path, so thats probably not an issue
in the mod im working its always TWEEVENTS_something
that way im sure nobody else is using the same name
and i do the same with all the vars and functions
TWE_SomeVAr
TWE_SomFunction
๐ฌ
Oh so PZ ultimately decorates your require with the full path, instead of using the given string as the key?
?
Because in vanilla Lua I believe that is not the default behavior.
I assume thats what
String var3 = (String)LuaManager.paths.get(var2);
String var4 = ZomboidFileSystem.instance.getAbsolutePath(var3 + var1);
is doing
if you just use locals you don't need to do this
What exactly RunLua does with variable 4 is not clear to me but hopefully?
it gives up if the full path doesn't exist
I think M3ss meant filenames not variables.
he said he did it for vars an funcs too
Oh
Wanna see some goofy code that I just tried for giggles?
ModId = "TestMod"
_G[ModId] = {}
_G[ModId].test = function() print("'twerks") end
TestMod.test()
i have values going from one script to another one
even i dont need it, better safe that sorry
Okay but where does this code store what it's loaded?
yes i was talking about filenames mostly
ZomboidFileSystem.instance.getString(var4) must return the contents. Maybe its cached in there
my events mod files all start with TWEVENTS_filename
my stats mod files all start with TWSTATS_filename
the chances of someone having a mod with the same names for the files is almost 0%
Obviously using globals works, and people do it. But Modules and require are best practice for bouncing that data around between files
i use globals when im developing the mod
Word I mean that would be nice if that's how it works. I really didn't want to have to write a personal solution for preventing double-loads.
after that i clean up the code and use only globals when i have no other chance or its to much of a hastle to make a module to hold some value
require by default never loads a file a second time, you need dofile for that to happen. So we may need to worry about overwrites but never having the code loaded twice
its absolutely true, unless Kahlua has some bug in that regard
The other main job of require is to avoid loading the same file twice.
The other main job of require is to avoid loading the same file twice. For that purpose, it keeps a table with the names of all loaded files. If a required file is already in the table, require simply returns. The table keeps the virtual names of the loaded files, not their real names. Therefore, if you load the same file with two different virtual names, it will be loaded twice. For instance, the command require"foo" followed by require"foo.lua", with a path like "?;?.lua", will load the file foo.lua twice.
The table keeps the virtual names of the loaded files, not their real names. Therefore, if you load the same file with two different virtual names, it will be loaded twice.
ya, nobody does that
Not 1 person. 2 people.
One modder who goes, require("foo") because they like it that way, another goes require("foo.lua") because they like it that way
That's my concern here.
sounds like a vicious circle that must be dealt with one way or another in most circumstances unless fully local functions
BTW, this is a concern for me because it borks gamepad decorations by causing double-presses to load them twice.
And most of my mods have gamepad support.
well, you're gonna have to find out what the path is for PZ then, but I don't think it includes .lua does it? Can you do require "foo.lua"?
What I do is not my concern... the unpredictable choice that will be made by a future modder trying to work with my mods is my concern.
I am pretty sure require("foo.lua") is allowed if that's what you're asking
then you're left with doing local value = value or defaultval everywhere I guess. I personally wouldn't worry about other modders doing things with bad form, that's on them
I don't think of require("foo.lua") as bad form
Or is require("foo") bad form?
I don't even know what one would consider bad form here.
They both seem valid in Lua and I don't know of any Lua doc clarifying the "proper" Lua style there.
I am open to being enlightened
i feel like someone smart enough to even use this method is smart enough to think of this also and use something unique
seems like most just get sloppy with global usage
i love that you think this deep into that rabbit hole. not many do
i think you won't run into what you are worried about barely ever if ever though
Well I'm concerned because I am considering converting my modules to local ones but I want to (A) know and (B) mitigate the possible compatibility consequences of that.
you are compounding chance at that point
I know but I am going from X% chance of an issue to (X+?)% chance
Don't like it
Hate it actually
Want to stay at X
Okay, corrected for mathematical accuracy
Well, start by trying your hardest to force a test file to load multiple times
That's fair.
if that happens, then you can have the instantiation of every module-level local variable check to see if its set already
I am aware I could design some tests
I was hoping one of the local evangelists would already know what I'm asking.
Since it seems like an obvious concern after reading the require doc.
you could even do something like
if Module then return end
Module = {}
return Module
I guess you can't do that if you make it local
Yes but Module needs to be one of many possible things
_LOADED["foo"], _LOADED["foo.bar"], etc.
How would that be a bad form
According to the require doc
I would not think it is, Bright
I was responding to someone and asking.
i don't really see anyone using the file extension
It doesn't impact anything it's just not specifiying it's a lua file
wouldn't bother me either way but i think it's prettier without
Mb then replied to fast
someone experienced leaves it off because of course its a lua file, someone inexperienced puts .lua in because they don't know if its necessary or not
For sure, and I like it without, too @bronze yoke, but not everyone favors my style tastes from context to context so I am trying to be proactive.
Exactly my concern.
There are probably other kinds of people who include it
But generally, sure.
This perfectly realistic distinction you drew concerns me
have you confirmed this is actually the case? i didn't see whether or not you did skim reading this
No I haven't tested it in Project Zomboid, I am only referring to the standard doc of require behavior.
I came here to ask because I didn't want to have to write it up in multiple mods just to check conflicting import behavior lol
(if it could be avoided)
I guess you could do something like this
local Module = Module or {}
if Module.loaded then return end
Module.loaded = true
--rest of the stuff
return Module
then double loading won't matter
Module doesn't show up like that when someone else loads it
what do you mean?
It's not like Module becomes globally available when another mod requires it.
you guys wanna know another level of stupidity?
even higher than b4?
i KOed myself
I am concerned about mod A going
local Module = require("foo")
and mod B going
local Module = require("foo.lua")
And then foo.lua loads twice and causes gamepad bugs.
Entirely different mods / workshop items
Idk about this cause you're able to call module function without requiring them from console
hmm, ya I guess as long as Module is local, reloading the file isn't going to know the other Module already exists
If they're global @golden sparrow
Oh yeah true
Exactly
So I would need to use Lua's built-in _LOADED as described in the doc above
I imagine
To make sure before loading my file.
what if you force them to load on top if require("foo") and require("foo.lua") then return end
ya, I suppose you could iterate through and look for a "virtual name" (whatever that is) that might already point at your file
i only care about one thing... does it work or doesnt? If it works... all fine... dont care how it gets to where it is as long as it works
What? Wouldn't that just guarantee the problem? I'm confused...
plus if you use your own naming logic you will not have a problem
i doubt theres someone else that will have a naming logic equal to yours
I'm just gonna check how ISBaseObject shows up in _LOADED
this issue is more when someone is actually trying to use your mod
It's gotta be there somehow
if youre just using "standard" names for things... yeah
youre gonna have a problem sooner or later
Me too, but I want it to work under as many conditions as reasonably possible. If I can write 4 lines to prevent a confusing and potentially config-bugging controller issue, I will do it.
well thats their problem not mine ๐
This issue transcends naming
Even if your mod were called MyNameIsTheMostUniqueModNameInTheWorldBruuuuuh, someone could require("MyNameIsTheMostUniqueModNameInTheWorldBruuuuuh") or require("MyNameIsTheMostUniqueModNameInTheWorldBruuuuuh.lua")
(which causes a problem according to Lua doc by double-loading)
assuming youre talking about someone "leeching" from your mod
thats like winning the lotto 10 times in one day
If by leeching you mean importing, yes.
thats what I'm saying ya, save the ulcer and just expect other people to sort out their own bugs when they require your code in a way that would bork it. Maybe leave a comment at the top to let them know not to use .lua in require
of course, this all assumes that actually causes a problem in PZ, which we don't know
idea: just leave a comment saying don't load it with .lua
if ppl really want to require stuff from my mods, they at least should go through the trouble of reading the code
Fair
i have comments on everything
@bronze yoke @astral dune
True
everytime i read a mod's code from someone else i learn something
i learned a lot just by integrating EHE into my mod
I guess my only resistance to that is feeling bossy lmao
I like to let people keep their style
if i was lazy and just tried to brute force the use of the functions without understanding how and why and when
it wouldnt work
but sure, if you have doubts ask the dev the mod
i dont mind when ppl ask me questions
just not vague ones
if i know how to provide a solution i will, if i dont i just say i dont knows
does anyone know if the ingame posters and paintings are static objects or are spawned randomly ?
lol @astral dune
_LOADED is nil from Zomboid
No idea how they track their requirements but not that.
Just tried from Zomboid console to see how vanilla stuff gets tracked during require. Apparently not like that.
That would be cool if there was method to access and set zombies pathfinding distance ๐ฆ
I want to make a mod around zombies seeing for less distance in fog but I can't find a way to do it
here i was thinking i did something wrong
goin' from one version of the mod to another one
even reverted all the way back to the frankenstein code
and didnt work... no errors, nothing, but it didnt work
so... almost 2 hours later...
i figured out whats was wrong...
if i freeze the game time... it wont trigger the events... DUUUUUUH
..... this its way to stupid even for me
Does anyone online today know if the pathfinding code is able to run outside of timed actions?
now i went back to the latest version with the modules and stuff...
unfroze the game time
and it works...
this means... break time... before i do something even more stupid...
which is almost impossible
but just in case...
funny story I tried to load my file 2nd time and nothing happened
honestly just overwrite the vanilla tiles if your plan is to overwrite them anyways. unless your intention is to make your own tiles at this point.
and the final version of my main lua file
local myevents = require("TWEEVENTS_Events")
local MyEventsTable = {}
function getreward()
local ReadReward = getFileReader("rewards.txt",true)
json_string = ReadReward:readLine()
ReadReward:close()
if json_string ~= nil then
local viewer = json_string:match('"Viewer": "(.-)",')
local status = json_string:match('"Status": "(.-)",')
local title = json_string:match('"title": "(.-)",')
local zombies = json_string:match('"zombies": (.-),')
local zedquant = json_string:match('"zedquant": (.-),')
local gifts = json_string:match('"gifts": (.-),')
local helicopter = json_string:match('"helicopter": (.-)}')
MyEventsTable = {
["viewer"] = viewer,
["status"] = status,
["title"] = title,
["zombies"] = zombies,
["zedquant"] = zedquant,
["gifts"] = gifts,
["helicopter"] = helicopter,
}
local EmptyRewardFile = getFileWriter("rewards.txt", false, false)
EmptyRewardFile:write("")
EmptyRewardFile:close()
processEvent(MyEventsTable)
else
end
end
Events.EveryOneMinute.Add(getreward)```
You mean you tried to double-require using two different paths?
looks so pretty and slim ๐
require("zxDebugClient"), then require("zxDebugClient.lua")
only one print from when the file was loading
crisis averted ๐
hmm, anyone knows how to detect if the game is paused?
I mean as soon as I saw _LOADED was nil I knew all bets were off re. the online doc
So I was hoping this would turn out to be handled better by PZ
getGameSpeed
isGamePaused
thank you
zombie.ui.SpeedControls.class, "getCurrentGameSpeed"
just to add a anti cheat measure into the temporary traits thingie
im using the computer time and not the game
so if someone pauses for X time, the trait will be removed without him suffering with the negative trait
so ill detect a pause and add the time the game is paused to the time left for the negative trait to expire
or i could just use the game time...
....
na
this way i dont have to worry about the value of a day relative to real world time
if I'm using a Java method as the condition for an if statement, does Lua's typical conditional behavior apply? i.e. do I need to check for null, or will it automatically get handled as nil (and return false?)
It'll be handled as nil
i saw that before the edit, I'm sorry to hear that
lmao
(also ty)
lol I swear I borked my Zomboid controller files somehow and it appeared to happen RIGHT after I required my own dang mod (purely to see what would happen), and I am sure it's just a coincidence but I had to share the absurdity.
I just restarted PC and gamepad still won't connect. Verifying files.
maybe I accidentally brushed delete feeshin around shortly before this happened and deleted some crucial game file...
But yeah, very strange.
Oh yeah, borkage survived PC restart AND validation
Lovely
Fixed by deleting joypad config files.
Mysterious
Gonna try to replicate ๐คช
Unrelated
I wonder how I borked it...
borking stuff is more that a science
its a way of life
when you want to bork it, it refuses to bork
when you less expect it, it will bork!
Misterious are the ways of borking ๐
Do object ID reset after server reset ?
does anyone know how I could be getting a null value from something that I'm specifically checking via an if statement? I'm really confused
local testTheseTiles = {}
local function LoadGridsquare(square)
if square:getFloor():getSprite() and square:getFloor():getSprite() == getSprite("blends_natural_01_64") then
testTheseTiles[#testTheseTiles+1] = square
end
end
local function fubar()
for _, v in pairs(testTheseTiles) do
v:getFloor():setSprite(getSprite("blends_natural_01_0"))
end
end```
(this isn't meant to be neat or optimized or final by any means, just testing atm)
also worth noting that those funcs are passed into the proper event handlers, so I'm at a loss basically
in the log what does it say?
wheres the square declaration?
it's the square returned by the LoadGridsquare event
(which that function is added to, I just didn't include that)
check that function then
because square appear to be null
you can always print(tostring(square))
...the game is loading a null square? wot
and see what it returns
wild, i'll give it a shot I guess
dont know crap about maping and anything related to it, but from the log thats what i see... square is null
oh wait youre iterating on the fubar function
basically what that callback does, is whenever the game loads a square (a single isometric square on the map, which can contain multiple tiles on different layers) it fires that event
the getFloor() gets the floor layer, which is always the base layer more or less
the :getSprite() gets the actual sprite image that's loaded for the tile (in this case, a dirt tile)
the getSprite(<string>) function, I'm assuming - because the vanilla Lua uses this exact syntax - is a global function that returns the tile sprite from the string of the filename (and that's the correct filename)
i am, yeah. is that the issue?

I'm aware of the "lua can't iterate over java lists" and shit like that, but in this case isn't my table a Lua object not a Java enumerable?
or does the fact that it contains Java objects make that irrelevant?
right, but Kahlua is invoking Java when we're talking about the return value of java methods
well the error says youre trying to iterate something that is not a table
so do I need to initialize the table some other way than local table = {}? I'm confused

but... but it does. like, it drops typing, but the returned objects and their structure is still important
which is why you can't use pairs or ipairs with a return value that's a Java object instead of a lua table
the returned objects from java to lua are nothing more than tables with text
no definition of type of object or data
...then why wouldn't pairs or ipairs work with those, instead of needing :size()?
lua doesnt care if its "1" or 1
right, but Java lists have an index of 0 and lua tables don't
lua index goes from 1
right, that's what I'm saying
but you dont need to worry about the java side
so you can't use pairs and ipairs which rely on that behavior, because Java lists aren't inherently built for Lua tables
local globalModData = getExpandedHeliEventsModData()
local scheduledEvents = globalModData.EventsOnSchedule
for i, event in ipairs(scheduledEvents) do
print("Event " .. i .. ":")
print("Start Day: " .. event.startDay)
print("Start Time: " .. event.startTime)
print("Preset: " .. event.preset)
print("Triggered: " .. tostring(event.triggered))
end
this is what i used to get all the events EHE has
no its not incorrect and thats a good guide
im just saying from the error you get
thats what i see
okay, but it disagrees with what you just said about "yes you can use them"
it goes into detail in that section why you specifically can't
also I'm not seeing EventsOnSchedule in the vanilla code, either the Lua or the Java, so I think that code you posted isn't an example of what I'm describing
dude...
it's most likely returning a Lua table rather than a Java list object
i guess my english isnt good enough for you to understand what im saying
so, from my limited know how about PZ modding
that error happens when you try to iterate a non table
thats all i can tell you
all data inside lua no matter where it comes, if it has keys and values will be treated as a table
even if only has values, it will still be a table
as long as its an array of values
or whatever
local mycar = getSpecificPlayer(0):getVehicle()
local TireSet = { "TireRearRight", "TireRearLeft"," TireFrontRight", "TireFrontLeft"}
local WhichTire = ZombRand(1,5)
if mycar ~= nil then
for i = mycar:getPartCount()-1,0,-1 do
local part = mycar:getPartByIndex(i)
local cat = part:getCategory()
local item = part:getId()
if item ~= nil then
if Mypart == "Engine" and item == Mypart then
part:setCondition(0)
end
if Mypart == "FlatTire" then
if TireSet[WhichTire] == item then
VehicleUtils.RemoveTire(part, true)
end
end
end
if Mypart == "GasTank" and item == Mypart then
part:setContainerContentAmount(0)
end
if Mypart == "Muffler" and item == Mypart then
part:setCondition(0)
end
if Mypart == "Battery" and item == Mypart then
part:setCondition(0)
end
end
end
end
this is the code i use to handle an object from java
dunno if it helps you understand what im saying or not
is there a way that I can check if a translation key exists or not?
but surelly theres someone who knows more that i do around
dunno... messing around with translations for the 1st time as well
i see that getTextOrNull exists, guessing it returns nil if theres no key found ?
i'll try that
do you only want to check it while the language in question is loaded? if not, I think it'll be considerably trickier
yeah
if you just want to check for the current language, getTextOrNull should work
that'll work then
(at least, in theory, from looking at the Java code. you might have to use the Translator object if things don't work out immediately)
e.g. local lang = Translator.getLanguage():name(); but there's a lot of functionality there
I'm not really a modder however i was wondering if a mod i had an idea for was at all possible
i had this idea mostly for RP servers or if you want to give MP more of a challenge in where speaking over Voip would attract zombies as if you were whisper shouting
This error looks to me that square:getFloor() is returning null. if square was nil then it would say getFloor of non-table
right, but how is that getting past the conditional in the first function?
that's why I'm confused
because I'm specifically checking for nil (or null, since someone affirmed above that they're handled identically by Kahlua) before the object is added to the table
unless I'm somehow misunderstanding the usage of "and"
sorry I'm a little distracted, what are you doing to check for null?
if square:getFloor():getSprite() and square:getFloor():getSprite() == getSprite("blends_natural_01_64") then
<then add it to the table that gets iterated over in the second function>
square:getFloor():getSprite() will fair if getFloor is null, which is what's happening
I assumed that if you tried to do getSprite() on a null return (from getFloor()) that it'd also be null/nil, and thus it'd return false
so what that guy said above about Lua handling null as nil isn't correct, then?

or is it specifically because it's second in the call chain? that'd be incredibly stupid but if what you're saying is true that's like... probably what is happening
you would need to do if square and square:getFloor() and square:getFloor():getSprite etc to check for all the possible nulls
its pretty straightforward
not if you expect logic 
unclear on why square.getfloor would return null if its always the bottom one
it is logical
it's not logical to expect :getSprite() on a null object returning anything other than null
(which it is, but Kahlua is the failure here - it's not converting that specific null value to nil, apparently)
its illogical to think calling a null.somefunction would work, lmao
same kind of thing that would throw a nullpointerexception in other languages
getsprite(nil) you should expect to return nil, but nil.getsprite() will say index of non-table, because nil isn't a table
I think I get what you're saying now, yeah - I guess I was expecting the Lua to return a nil value on anything run on a null function, but you're right that it'd follow that it'd just throw an error instead, rather than return a value based on a function that can't be found on the parent object.
How confident are you that getFloor returns the floor layer? What if it's outside?
not at all, I actually had a check for getFloor() but I misled myself into thinking that it was redundant since I'd need to check the validity of :getSprite() anyways 
my brain tripped itself up while trying to adjust to some Lua behavior compared to more OOP-oriented programming patterns I think
public IsoObject getFloor() {
for(int var1 = 0; var1 < this.Objects.size(); ++var1) {
IsoObject var2 = (IsoObject)this.Objects.get(var1);
if (var2.sprite != null && var2.sprite.getProperties().Is(IsoFlagType.solidfloor)) {
return var2;
}
}
return null;
}
if grass/dirt/gravel aren't isoflag solidfloor they wouldn't be returned
just think of it like java. If you called Dog.getName().toString() would throw the same error if getName() returned null
they are, it's just a tile properties issue - anything that's a "full" floor tile that exists on the base layer has the isFloor() property
(at least I think it's called isFloor(), but the explanation stands either way)
if I tried to pass something like blends_natural_01_1 though it wouldn't work - because that tileset also contains overlays for the border blends, and those aren't floor tiles
local testTheseTiles = {}
local function LoadGridsquare(square)
if not square then return end --something is very broken here
local sqFloor = square:getFloor()
if sqFloor and sqFloor:getSprite() == getSprite("blends_natural_01_64") then
table.insert(testTheseTiles,square)
end
end
idk if you have to validate getSprite as having a returned value
some things don't have a sprite I think
then it'd be does 'nil == x'
do you mean :getSprite() or getSprite()? (gotta love these conventions, thanks TIS)
I copy and pasted what you had - oh
I mean in the first half of the if statement, you had floor:getSprite
right, but those are two different funcs
one is from the sprite manager, the other is from the square
(the sprite manager one is global)
(or static, fuck it idk)
I mean, you had floor:getSprite() and is floor:getSprite() == X
the first check isn't needed
that being said - what are you trying to get at?
perhaps there's another route - that's less of a headache
oh I think I see what you're saying, you wouldn't need to check getSprite() because a non-null getFloor() value is always going to have a sprite
all Lua manager functions are global afaik
I'm going to try using clientside sprite reassignment to create animated map tiles
getting it to not kick the game in the balls performance-wise is the hard part, but I'm pretty sure it'll be entirely feasible aside from that
I've worked on a commission for implementing 10 years later but in specific zones
you're going to lag for real-time placements of more than 1 tile
it's kind of inevitable
that's what I was worried about, yeah. I thought "maybe I can run this on the render loop rather than on tick, to allow it to match framerate somewhat" but I think it's going to be messy as fuck
but hey, I'm gonna give it a shot - because the only alternative is shadercode, and fuck that
I optimized what I had to do - it wasn't too terrible by the end - but the person wanted additional grime so I tried to stack 3 sets of grime
on every single possible tile
placing fauna everywhere was fine
jesus. I wrote a map manipulator tool in .NET that modifies the binaries and replaces/places/removes tiles, I think that'd be the better option in your case
probably
like you'd end up with a large download (since you're reuploading large swaths of the vanilla cells) but it'd be Lua-less, so no performance impact
what I sent the guy used a table using isoflagtypes as keys and sprites as values
ran through a tile looking for the most appropriate flag type and grabbed a random sprite from the values
also on loadSquare
that makes sense, yeah. that's pretty nifty
only an issue once though - the first person to explore the region would brunt the lag for everyone else
๐
it was also not noticeable even when teleporting though - but I have a pretty beefy CPU
In your case though you couldn't do setSprite though right? since you'd want the behavior of the actual tile not just the sprite? or are the properties swapped out when that's called?
for my case, I had the square parse the objects on it to find the correct case
How do I take the vanilla trait lua and change the cost of the traits and put it into a mod format without redbox errors showing up I tried just changing the numbers but it did work however there was redbox errors this file is from the base game unchanged
there was an issue with floors for example being rendered under doors
so loadsquare can handle a bit of logic to it
just gotta be mindful of how much
---@param isoGridSquare IsoGridSquare
local function applyBiome(isoGridSquare, x, y, z, outside)
local biomes = isoGridSquare:getModData()["BIOME"]
for id,_ in pairs(biomes) do
local biome = BIOMES[id]
if (ZombRand(101) <= biome.chance) then
for flag,sprites in pairs(biome) do
if IsoFlagType[flag] then
local object = ifFlagTypeGetObject(isoGridSquare, IsoFlagType[flag])
if object then
local specialOverrideExceptions = {"IsoCurtain","IsoDoor","IsoWindow","IsoBarricade","IsoLightSwitch"}
---Vanilla has a getFloor but it causes layering issues if there's objects over the floor - like walls
---@param isoGridSquare IsoGridSquare
local function ifFlagTypeGetObject(isoGridSquare, isoFlagType)
local isoObjects = isoGridSquare:getObjects()
local objWithFlagFound
local lastSpriteObject
if isoFlagType == IsoFlagType.solidfloor and isoGridSquare:getProperties():Is("BlocksPlacement") then return end
for i=0, isoObjects:size()-1 do
---@type IsoObject
local isoObj = isoObjects:get(i)
if isoObj then
local isoObjSprite = isoObj:getSprite()
local isoObjSpriteName = isoObjSprite:getName()
if isoObjSprite and isoObjSpriteName then
if isoObj:getType()==IsoObjectType.wall and string.find(isoObjSpriteName, "roofs") then
else
if isoObjSprite:getProperties():Is(isoFlagType) then
objWithFlagFound = true
lastSpriteObject = i
end
if objWithFlagFound then
if (not isoGridSquare:getProperties():Is("IsMoveAble")) then
lastSpriteObject = i
end
for _,type in pairs(specialOverrideExceptions) do
if instanceof(isoObj, type) then
lastSpriteObject = i
end
end
end
end
end
end
end
if objWithFlagFound and lastSpriteObject then
return isoObjects:get(lastSpriteObject)
end
end```
oh hey, I mention getFloor
heh
wrote this in august

hmm yeah, I'll probably have to take a similar approach if this gets off the ground - I don't plan on the only animated tiles being floor tiles, so the object approach will be the likely bet
local function applySpriteToObject(sprite, isoObject)
if not isoObject:getAttachedAnimSprite() then
isoObject:setAttachedAnimSprite(ArrayList.new(4))
end
---@type IsoSprite
local isoSprite = getSprite(sprite)
isoSprite:setName(sprite)
---@type IsoSpriteInstance
local isoSpriteInstance = IsoSpriteInstance.get(isoSprite)
---@type ArrayList
local isoObjectAttachedAnimSprite = isoObject:getAttachedAnimSprite()
if isoObjectAttachedAnimSprite then
isoObjectAttachedAnimSprite:add(isoSpriteInstance)
return isoSpriteInstance
end
end
this might help
it cuts down on the isoObjects
I also wrote overwrites for cutting/removing plants to check the attached sprites
vines already do it that way
okay @sour island still pretty confused here, this is what my code looks like now:
testTheseTiles = {}
local function foo(square)
if not square then return nil end
if square:getFloor() and square:getFloor():getSprite() and square:getFloor():getSprite() == getSprite("blends_natural_01_64") then
testTheseTiles[#testTheseTiles+1] = square
end
end
local function bar()
for _, v in pairs(testTheseTiles) do
v:getFloor():setSprite(getSprite("blends_natural_01_0"))
end
end
Events.LoadGridsquare.Add(foo);
Events.EveryOneMinute.Add(bar);```
(I did like what you did with some of the cleanup of the code you posted above, but this is just a quick messy edit)
anyways, I'm now checking the validity of: the square, the floor, the sprite, and that the sprite matches the one I want it to
and I'm still getting the following:
BAR Isn't checking if getfloor is null
so I'm thinking either
- it's the other
getSprite, from the sprite manager, but I don't think that makes sense since I'm using identical syntax to the vanilla code in that regard (and those tiles obviously exist)
or 2) since the square stored in the table is a reference, either the reference is changing or the square is changing
but it's iterating over a table whose members can only be ones that were already filtered by foo
this table only exists here, I don't have logic anywhere else in the mod even
(for now, at least)
hmm, good point (sorry, raiding so I can only steal glances)
no worries
could the issue be related to the list? what if it's empty?
there's not really a difference between testTheseTiles[#testTheseTiles+1] = square and table.insert(testTheseTiles,square) right? stackoverflow indicated the former is maybe slightly faster, but I'm not married to anything
hmm maybe, since they're being called by two different event handlers?
afaik table.insert is efficient - it's using the parameter for position that makes it horrible
would if #testTheseTiles > 0 be the move if the list is the issue?
or do you mean the list that the sprite manager is using?
could be - but I imagine the for() wouldn't be getting that far if it had nothing in it
I would expect square to be null if it was emptyu
I feel like the error would be different - :getFloor() of null or calling non-method
ya, exactly
do {} tables have even have a count of 0, or do they end up nil? or both? 







