#mod_development

1 messages ยท Page 87 of 1

drifting ore
#

or do I just delve into mapping ?

cosmic condor
#

better go to mapping

drifting ore
#

alrighty

drifting stump
#

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

thick karma
#

Oof

drifting stump
#

you would need to have an ingame character creator for those custom traits

thick karma
#

Damn.

drifting stump
#

but anyway on that link you have the cool config tech i came up with

thick karma
#

Well, that news saves me a lot of time but will surely disappoint a few users lmao. Thanks for it, nevertheless.

drifting stump
#

the config is a lua function that returns a table with the settings

thick karma
#

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

fast galleon
#

make it easy to patch into

#

or really hardcode everything and say people are not allowed to redistribute

drifting stump
#

wanting to do things and the game just not letting me the way i wanted

finite radish
# fast galleon make it easy to patch into

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

drifting stump
#

very simple solution

#

do not use globals

#

make modules

pulsar heath
#

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

drifting stump
#

you forgot the export

finite radish
pulsar heath
#

forgot the export?

drifting stump
#

here

drifting stump
#

nvm it

pulsar heath
#

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

drifting stump
#

after almost a whole year bitching i finally managed to get people to stop using globals

pulsar heath
#

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

drifting stump
finite radish
#

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

pulsar heath
#

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 ๐Ÿ˜„

drifting stump
#

and modules are usually tables

#

which the global space is too

#

if you didnt know _G is the name of the global table

finite radish
# drifting stump local accesses are faster than global

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

drifting stump
#

in real lua behind the scenes its all C code

finite radish
#

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

drifting stump
#

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

finite radish
#

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?

drifting stump
#

now speaking java

#

if theres a reference to something then it isnt garbage collected

ancient grail
drifting stump
#

since the variable is stored theres a reference to it

#

so it wont ever get gced

finite radish
#

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

ancient grail
drifting stump
ancient grail
#

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

astral dune
#

Glytch3r my dude, that vault lookup code I showed you in DMs was a module, the one you couldn't get to work

drifting ore
ancient grail
ancient grail
#

Its the same thing

drifting ore
#

ah

ancient grail
#

Cuz the files are pack files not png

drifting ore
#

well this whole mapping tool is unwieldly, having a hard time understanding it

ancient grail
#

#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

finite radish
#

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)

drifting ore
ancient grail
#

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

drifting ore
#

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

drifting ore
trail bloom
#

Yo, question anyone know how the debug tiles picker works? There's a tile I found in game but can't find in tiled.

finite radish
trail bloom
#

Thank, now I can use the PZ map as a glorified tile picker

finite radish
#

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)

drifting stump
#

what are you trying to do

worldly stone
#

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

finite radish
#

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

drifting stump
#

i still dont know what youre trying to do

finite radish
#

which part are you unsure about?

drifting stump
#

context

astral dune
#

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

finite radish
#

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)

drifting stump
#

then yeah that would have to be LoadGridSquare

finite radish
#

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

astral dune
#

a lot of functions/methods are poorly named, be careful ๐Ÿ˜„

finite radish
#

tru

bronze yoke
#

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

finite radish
#

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

drifting ore
#

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

pulsar heath
#

if only i had started using modules from the start... damn...

#

changing all the code to work that way... is a damn boring task

pulsar heath
#

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

finite radish
#

it also makes your code less of a clusterfuck and more accessible if people need to patch things up

pulsar heath
#

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

drifting ore
#

Hmm, not sure I follow, then again my code was never big per se

#

So might never had to do it

pulsar heath
#

mine is getting bigger and bigger

drifting ore
#

Yeah I'm working on something bigger now so might take this into account

pulsar heath
#

this way like @finite radish said if less of a clusterfuck easier to use, update, fix and add stuff to it

drifting ore
#

Can you also return tables with modules?

finite radish
pulsar heath
#

everything inside the module

#

will be returned no matter what it is

drifting ore
#

So basically a module is a lua file that has functions the mod requires or anything else basically?

pulsar heath
#

and the module itself is table... for lua everything is a damn table ๐Ÿ˜„

finite radish
#

whoops responded to the wrong comment, but you get the idea

pulsar heath
#

so imagine you have a module
local MyModule = {}

#

in my case

drifting ore
#

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

#

?

finite radish
#

yes, precisely

drifting ore
#

Im using mobile so just typing freehand

bronze yoke
#
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

drifting ore
#

That's very interesting, I'll definitely start using that more

pulsar heath
#

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
drifting ore
#

Might result in more files but less overall code breaking I assume

pulsar heath
#

by requiring the file that has the module

drifting ore
#

Having learned you can put folders in the lua folders helped me a lot lol

pulsar heath
#

i can then do something like
local whatever = require("file")

#

and then call anything in the module just by
whatever.TWEcars(value)

drifting ore
#

Copied that msg link, thanks a lot mess

pulsar heath
#

or the vars,
whatever.TWEtrait = "value i want"

drifting ore
#

I have a huge ass table at the moment and placing it in diff files by category and using modules might be a lifesaver

pulsar heath
#

you can return several modules from the same file

#

instead of
return modulename

drifting ore
#

If you daisy chain modules do they get all the values the previous modules got?

pulsar heath
#

you can return module1, module2

finite radish
#

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? PepoThink

pulsar heath
#

then to access it you need to do
local mymod1, mymod2 = require("file")

drifting ore
pulsar heath
#

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 ๐Ÿ˜„

finite radish
drifting ore
#

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

vestal geode
pulsar heath
#

they load as normal lua

vestal geode
#

Mh, I see. Good to know

pulsar heath
#

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

vestal geode
#

Since i prevented parsing files at runtime but tbh never checked that fact

pulsar heath
#

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

finite radish
drifting ore
#

Trying to edit the normal tooltip and add my own mix to it

finite radish
#

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

pulsar heath
#

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 ๐Ÿ˜›

drifting ore
#

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

fast galleon
vestal geode
drifting ore
#

Ye

fast galleon
#

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)
vestal geode
#

or for all water collector typed map objects

#

It will render an amount bar. That draw stuff works similiar like working with GDI

drifting ore
#

Copied msg link, thanks ๐Ÿ™‚

vestal geode
#

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)

drifting ore
#

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

vestal geode
#

Well, as you know, you learn the most from mistakes lol

drifting ore
#

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

pulsar heath
#

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

drifting ore
#

jesus

pulsar heath
#

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

#

๐Ÿ˜„

#

but now i know the game can handle 9999 zombies

drifting ore
#

bro seeing the game start slowing down the rain

#

you know you fkd up

#

๐Ÿคฃ

pulsar heath
#

yup

drifting ore
#

amazing

pulsar heath
#

im almost sure if i did this 1 year ago the game would probably crash

fast galleon
#

impossible!

pulsar heath
#

what @fast galleon ?

dull moss
#

classic

#

@thick karma is blue now Kpog

pulsar heath
#

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

#

๐Ÿ˜„

dull moss
#

you might wanna scale horde down a bit KekW

#

like to 40

pulsar heath
#

oh... yeah... i have it set to 50

dull moss
#

or something

pulsar heath
#

you can edit the rewards in the app

#

๐Ÿ™‚

dull moss
#

very cool

pulsar heath
#

no settings are needed inside the game

dull moss
fast galleon
pulsar heath
#

you said impossible

#

whats impossible?

dull moss
#

I mean yea if u got interface between PZ and app then you dont need to do shit in-game

pulsar heath
#

to work with twitch a third party app is always needed since the game doesnt have native integration

fast galleon
pulsar heath
#

so i might as well do as much work on the app side and less on the mod side

pulsar heath
#

my brain is so melted that i didnt even recognize the quote ๐Ÿ˜„

drifting ore
#

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

pulsar heath
#

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

vestal geode
#

yea refactoring can be rly annoying

pulsar heath
#

so the lesson learned is: if you gonna do it, do it the right way from the start

vestal geode
#

Yea well... if possible. Sometimes really hard if you don't plan every detail before

pulsar heath
#

a lot of copy paste going on

#

and sometimes i get lost

#

๐Ÿ˜„

#

but the main lua file is getting smaller and smaller

#

almost done ๐Ÿ˜„

vestal geode
thick karma
dull moss
#

DABUDI DABIDAI

pulsar heath
#

stupid question... if i do local myfuction() end

#

that function is only available inside the file where i have it right?

drifting ore
#

afaik yes since it's local

pulsar heath
#

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 ๐Ÿ˜„

drifting ore
#

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 ๐Ÿคฃ

pulsar heath
#

i dont recomend the use of global vars

#

thats one of the reasons im converting my code using the modules aproach

drifting ore
#

oo shit why not

pulsar heath
#

imagine if everyone uses globals

drifting ore
#

overwriting?

pulsar heath
#

the game will have a shit ton of globals

#

and yes theres a risk that someone might overwrite it

drifting ore
#

ah but you're saying moreso it'll be unoptimized af

pulsar heath
#

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.

drifting ore
#

i'll keep that in mind thx

#

bon apetit

#

๐Ÿ™‚

vestal geode
#

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

ancient grail
ancient grail
vestal geode
#

lol

#

prefixing globals at least with your vendor tag or sth like this isn't a bad idea

ancient grail
ancient grail
ancient grail
#

I remember he can let audience spawn zed

drifting ore
#

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

alpine scroll
#

@ancient grail Oh, you are talking about @pulsar heath . I went all the RCON route inspired by his hotkey based mod

ancient grail
#

Yep yep how r u man

drifting ore
#

I wonder what all you do for a living since you're such talented coders

alpine scroll
#

I do code to be fair

drifting ore
#

Man I wish I was in a coding career

alpine scroll
#

Not as releasing programs, but to customize an existing program to deal with what the clients want

vestal geode
#

Working as lead programmer in a computer manufacture

drifting ore
#

Bruh

#

Im so jealous ๐Ÿคฃ๐Ÿคฃ

ancient grail
alpine scroll
#

I'm more like a consultant

drifting ore
#

Not the greatest resume

vestal geode
#

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

ancient grail
#

Im unemployed . Used todo freelance graphics and animation. Niche to pz modding

alpine scroll
#

I started programing when I was working as an Accountant Assistant

#

I went all in with Excel

drifting ore
#

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

alpine scroll
#

Check for accounting jobs

vestal geode
#

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

alpine scroll
#

Say you know nothing about tax or anything but you think you can help at least to make everything faster

ancient grail
drifting ore
#

Oh yeah I def could, I can improve any workflow in excel by miles after what I've seen people here do

drifting ore
alpine scroll
#

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

drifting ore
#

I only know how to improve a workflow because I love, absolutely love learning functions in excel. So many ๐Ÿคค

alpine scroll
#

Turns out, people usually just do what they do because they cant figure out a way to be better

alpine scroll
#

Its like "Well, this works, so I'll do like this forever"

drifting ore
#

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

alpine scroll
#

Just remember that everything you do in company time is company property

drifting ore
#

So if you code a PZ mod it's theirs? ๐Ÿคฃ

ancient grail
#

Croatia is considered to have a high income economy

alpine scroll
drifting ore
ancient grail
#

Based on a site i just looked at

alpine scroll
#

But you shouldn't do pz code during work anyways haha

astral dune
#

for the record if you make a PZ mod its yours

vestal geode
ancient grail
alpine scroll
ancient grail
alpine scroll
#

Its how I do things at least, and it worked pretty well until now

vestal geode
#

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

alpine scroll
#

Not judging anyone who does things differently

ancient grail
#

So how do i recieve twotch data output and send it to rcon

alpine scroll
#

I do have copies of things that I've done too, without any company data ofc

ancient grail
#

Make a scheduled task that will delete it in the future instead ๐Ÿ˜‰

#

Kidding

vestal geode
#

๐Ÿ˜‚

alpine scroll
#

I once did as a joke to make a popup message on my birthday

ancient grail
#

Screw u company that fed me! Im a big boy now

alpine scroll
#

I got a stern talking

#

hahaha

drifting ore
#

Is there a file in the folders with item rarities based on the rarity selection in game?

#

Or is that top sikrit

alpine scroll
#

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

ancient grail
#

U mean the distributions?

drifting ore
#

Hmm, well basically what decides how much of a certain item spawns in the world

fast galleon
#

distributions table * sandbox * other factors

ancient grail
drifting ore
#

I need to find out some values that decide how much for example of a katana will spawn in the world

ancient grail
#

Ow thank you u just made me remember my question!
How do i remove vehicle distribution like the cars themselves

fast galleon
ancient grail
#

For a server to have some vehicles only spawned by admins for event prizes

drifting ore
ancient grail
#

And whats the difference with procedural and regular distrib

vestal geode
#

Rarity is handled by dice system, see \media\lua\server\Items\ProceduralDistributions.lua

fast galleon
#

ProceduralDistributions has the distributions and distributionss has both distributions and procedural

dull moss
#

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

fast galleon
#

one of your integer options seems borked

dull moss
#

ye I also was thinking that based on error I put a letter somewhere by accident

drifting ore
#

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 panic

ancient grail
#

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

drifting ore
#

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?

fast galleon
#

no, they all roll and if chance > random it is added

drifting ore
#

where's the random

#
        SurvivorCrate = {
            rolls = 4,
            items = {
                "Bag_ShotgunBag", 1,
fast galleon
#

rolls happen in java, 4 rolls for each item, each roll is evaluated separately

drifting ore
#

what's the number 1 then

fast galleon
#

~1 / 100

drifting ore
#

also what's the maximum a dice can achieve in java?

#

a number between 0 and 100?

ancient grail
#

So many items and he picked cockroach

drifting ore
#

lmfao

#

it was at the very top

ancient grail
#

๐Ÿชณ๐Ÿชณ

fast galleon
ancient grail
#

If its on sandbox u can always use

local blahblah = sandboxvar.blahblah or 1

fast galleon
#

@drifting ore what do you want to edit? Just know chance for base katana?

drifting ore
#

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

dull moss
vestal geode
#

That second value is the weight

#

So I guess its worth depends on the amount and values of the other items

fast galleon
#

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.

drifting ore
#

Is lootZed an in game feature? never heard of it

#

looking on their forums now it says they added it

fast galleon
devout flint
fast galleon
drifting ore
#

ah yes, just found it, tyvm ๐Ÿ™‚

ancient grail
fast galleon
#

enable cheat, right click container in inventory loot pane

vestal geode
ancient grail
#

Damn he found we slow

#

So there no chance?

#

๐Ÿ˜ฎโ€๐Ÿ’จ

fast galleon
#

he's too fast for us now

vestal geode
ancient grail
#

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

vestal geode
#

ty

ancient grail
#

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

dull moss
#

I just need to prove someone wrong

ancient grail
vestal geode
#

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

drifting ore
#

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

vestal geode
drifting ore
#

Interesting

thick karma
#

@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.)

vestal geode
#

I just use
if not MyClassFile then require 'MyClassFile' end
to prevent that

dull moss
thick karma
#

โค๏ธ

astral dune
#

I'm curious now, if I require "A" and there is an A.lua in \server\ and \shared, which one do I get?? hmm

dull moss
#

having spelling errors in my code hurts me on emotional level

dull moss
astral dune
#

and if I'm in client?

dull moss
#

then you need to specify, no?

astral dune
#

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

pulsar heath
thick karma
#

What I am unclear about is what happens if it hits twice.

bronze yoke
#

iirc i couldn't require a folder in server from client

thick karma
#

Okay good to know. But what if I have X.lua in client and shared, e.g.?

#

and I require("X")

astral dune
#

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

thick karma
#

Oof sound like I'm gonna need to test this ๐Ÿ˜ญ lol

#

So many todos

astral dune
#

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

golden sparrow
#

Had one function in server file and one in shared with same name

#

Was calling the one in shared first

fast galleon
#

Did the second one load too?

golden sparrow
#

I guess the second one got overwritten or smthing

small topaz
#

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:

fast galleon
#

ah same function name or file name

astral dune
#

if they're both global, only the server one would exist in the end, afaik

golden sparrow
#

Could just access the shared one

#

same function name

vestal geode
#

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;
    }
astral dune
#

code block please

vestal geode
#

how was that again? not too familar with discord lol

astral dune
#
//stuff
vestal geode
small topaz
astral dune
#

looks like it should work tbh

thick karma
small topaz
# astral dune looks like it should work tbh

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)

astral dune
#

the function inputs match the vanilla one as well?

vestal geode
devout flint
#

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

small topaz
bronze yoke
astral dune
bronze yoke
#

you can have less weird filenames without worrying about conflicts

astral dune
#

ya, all my filenames are prefixed with the modID, I could probably omit that. Then the requires need the subfolder in them though, right?

bronze yoke
#

yep

small topaz
bronze yoke
#

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)

thick karma
#

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

thick karma
astral dune
#

trying to remember

small topaz
thick karma
#

I mean in general you can do it

small topaz
astral dune
#

ya I guess so, thinking about it more. Lua doesn't support overloading, but you're just replacing it altogether

thick karma
fast galleon
#

strange error usually means you have a nil somewhere? ded

small topaz
#

for easier comparison, I'll post my code again with the original vanilla function in the same file:

bronze yoke
#

what kind of errors are you seeing?

small topaz
#

there must be a stupid mistake I can't see!!!!

small topaz
astral dune
bronze yoke
#

yeah java will get mad

#

because it'll look for a matching overload

thick karma
astral dune
#

does the vanilla function return anything?

small topaz
bronze yoke
#

yeah, sounds like something went nil somewhere

small topaz
#

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

small topaz
vestal geode
#

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"

fast galleon
astral dune
#

there's yer problem then

small topaz
#

thanks guys!

astral dune
#
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
small topaz
#

that's probably it! and I was already sure that I just forgot some tiny detail!! ๐Ÿ˜… I was freaking out!!!

#

many thanks again!!

astral dune
astral dune
unique fog
#

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?

rustic radish
#

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

zinc pilot
#

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?

astral dune
#

way past that now fam

zinc pilot
#

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```
dull moss
#

Chat didn't move

astral dune
zinc pilot
small topaz
#

btw how do you make it so that code fragments are shown in those black boxes when chatting here on discord?

zinc pilot
dull moss
astral dune
zinc pilot
astral dune
#

yes, : means it has a hidden self input ahead of all the others

zinc pilot
#

...only that?

#

really?

astral dune
#

yes

zinc pilot
#

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?

astral dune
#

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

zinc pilot
#

perfect

#

thanks again

fast galleon
#

and have faith that no modder overwrites that file

pulsar heath
#

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!

thick karma
#

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)?

pulsar heath
#

dunno but thats why i use "weird" names

astral dune
#

the code earlier makes it look like it uses the full path, so thats probably not an issue

pulsar heath
#

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

astral dune
#

๐Ÿ˜ฌ

thick karma
pulsar heath
#

?

thick karma
#

Because in vanilla Lua I believe that is not the default behavior.

astral dune
#

is doing

bronze yoke
astral dune
#

hence the ๐Ÿ˜ฌ, that poor global table

#

lol

thick karma
astral dune
#

it gives up if the full path doesn't exist

thick karma
astral dune
#

he said he did it for vars an funcs too

thick karma
#

Oh

bronze yoke
thick karma
#

Omg oof

#

So you just make them all standalone global functions?

#

Not even a module?

astral dune
#

Wanna see some goofy code that I just tried for giggles?

ModId = "TestMod"

_G[ModId] = {}
_G[ModId].test = function() print("'twerks") end

TestMod.test()
pulsar heath
#

even i dont need it, better safe that sorry

thick karma
pulsar heath
astral dune
#

ZomboidFileSystem.instance.getString(var4) must return the contents. Maybe its cached in there

pulsar heath
#

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%

astral dune
pulsar heath
#

i use globals when im developing the mod

thick karma
pulsar heath
#

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

astral dune
thick karma
#

That's not true

#

That's why I'm here

astral dune
#

its absolutely true, unless Kahlua has some bug in that regard

thick karma
astral dune
#

The other main job of require is to avoid loading the same file twice.

thick karma
#

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.

astral dune
#

ya, nobody does that

thick karma
#

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.

drifting ore
#

sounds like a vicious circle that must be dealt with one way or another in most circumstances unless fully local functions

thick karma
#

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.

astral dune
#

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

thick karma
#

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

astral dune
#

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

thick karma
#

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

drifting ore
#

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

thick karma
#

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.

drifting ore
#

you are compounding chance at that point

thick karma
#

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

drifting ore
#

lol can't blame for that

#

hahaha

astral dune
#

Well, start by trying your hardest to force a test file to load multiple times

thick karma
#

That's fair.

astral dune
#

if that happens, then you can have the instantiation of every module-level local variable check to see if its set already

thick karma
#

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.

astral dune
#

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

thick karma
#

_LOADED["foo"], _LOADED["foo.bar"], etc.

golden sparrow
thick karma
#

According to the require doc

thick karma
#

I was responding to someone and asking.

bronze yoke
#

i don't really see anyone using the file extension

golden sparrow
#

It doesn't impact anything it's just not specifiying it's a lua file

bronze yoke
#

wouldn't bother me either way but i think it's prettier without

golden sparrow
#

Mb then replied to fast

astral dune
#

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

thick karma
#

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.

thick karma
#

There are probably other kinds of people who include it

#

But generally, sure.

#

This perfectly realistic distinction you drew concerns me

bronze yoke
#

have you confirmed this is actually the case? i didn't see whether or not you did skim reading this

thick karma
#

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)

astral dune
#

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

thick karma
astral dune
#

what do you mean?

thick karma
#

It's not like Module becomes globally available when another mod requires it.

pulsar heath
#

you guys wanna know another level of stupidity?

#

even higher than b4?

#

i KOed myself

thick karma
#

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

golden sparrow
astral dune
#

hmm, ya I guess as long as Module is local, reloading the file isn't going to know the other Module already exists

thick karma
#

If they're global @golden sparrow

golden sparrow
#

Oh yeah true

thick karma
#

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.

fast galleon
#

what if you force them to load on top if require("foo") and require("foo.lua") then return end

astral dune
#

ya, I suppose you could iterate through and look for a "virtual name" (whatever that is) that might already point at your file

pulsar heath
#

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

thick karma
pulsar heath
#

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

thick karma
#

I'm just gonna check how ISBaseObject shows up in _LOADED

astral dune
#

this issue is more when someone is actually trying to use your mod

thick karma
#

It's gotta be there somehow

pulsar heath
#

if youre just using "standard" names for things... yeah

#

youre gonna have a problem sooner or later

thick karma
pulsar heath
thick karma
#

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)

pulsar heath
#

assuming youre talking about someone "leeching" from your mod

#

thats like winning the lotto 10 times in one day

thick karma
astral dune
# pulsar heath well thats their problem not mine ๐Ÿ˜„

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

bronze yoke
#

idea: just leave a comment saying don't load it with .lua

pulsar heath
#

if ppl really want to require stuff from my mods, they at least should go through the trouble of reading the code

thick karma
#

Fair

pulsar heath
#

i have comments on everything

thick karma
#

@bronze yoke @astral dune

pulsar heath
#

if they are lazy and dont want to see how it works

#

thats not my problem

thick karma
#

True

pulsar heath
#

everytime i read a mod's code from someone else i learn something

#

i learned a lot just by integrating EHE into my mod

thick karma
#

I guess my only resistance to that is feeling bossy lmao

#

I like to let people keep their style

pulsar heath
#

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

drifting ore
#

does anyone know if the ingame posters and paintings are static objects or are spawned randomly ?

thick karma
#

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.

golden sparrow
#

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

pulsar heath
#

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

thick karma
#

Does anyone online today know if the pathfinding code is able to run outside of timed actions?

pulsar heath
#

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

fast galleon
#

funny story I tried to load my file 2nd time and nothing happened

drifting ore
pulsar heath
#

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)```
thick karma
pulsar heath
#

looks so pretty and slim ๐Ÿ™‚

fast galleon
#

require("zxDebugClient"), then require("zxDebugClient.lua")
only one print from when the file was loading

thick karma
#

Nice

#

Good to know

drifting ore
#

crisis averted ๐Ÿ˜„

pulsar heath
#

hmm, anyone knows how to detect if the game is paused?

thick karma
#

So I was hoping this would turn out to be handled better by PZ

fast galleon
#

isGamePaused

pulsar heath
#

thank you

fast galleon
#

zombie.ui.SpeedControls.class, "getCurrentGameSpeed"

pulsar heath
#

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

finite radish
#

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?)

finite radish
#

lmao

#

(also ty)

thick karma
#

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

pulsar heath
#

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 ๐Ÿ˜„

worldly stone
#

Do object ID reset after server reset ?

finite radish
#

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

pulsar heath
#

if you provide the code thats giving the error perhaps

#

i meant the null value

finite radish
#
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

pulsar heath
#

in the log what does it say?

finite radish
pulsar heath
#

wheres the square declaration?

finite radish
#

it's the square returned by the LoadGridsquare event

#

(which that function is added to, I just didn't include that)

pulsar heath
#

check that function then

#

because square appear to be null

#

you can always print(tostring(square))

finite radish
#

...the game is loading a null square? wot

pulsar heath
#

and see what it returns

finite radish
#

wild, i'll give it a shot I guess

pulsar heath
#

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

finite radish
#

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)

finite radish
#

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?

pulsar heath
#

in lua everything is table

#

unless it has only 1 value

finite radish
#

right, but Kahlua is invoking Java when we're talking about the return value of java methods

pulsar heath
#

if you try to index something like myvar = 1

#

it will give that error

finite radish
#

but I'm using pairs, not indexed looping

pulsar heath
#

well the error says youre trying to iterate something that is not a table

finite radish
#

so do I need to initialize the table some other way than local table = {}? I'm confused

pulsar heath
#

and dont think in what java does

#

lua doesnt give a crap about what java does...

finite radish
#

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

pulsar heath
#

the returned objects from java to lua are nothing more than tables with text

#

no definition of type of object or data

finite radish
#

...then why wouldn't pairs or ipairs work with those, instead of needing :size()?

pulsar heath
#

lua doesnt care if its "1" or 1

finite radish
#

right, but Java lists have an index of 0 and lua tables don't

pulsar heath
#

lua index goes from 1

finite radish
#

right, that's what I'm saying

pulsar heath
#

but you dont need to worry about the java side

finite radish
#

so you can't use pairs and ipairs which rely on that behavior, because Java lists aren't inherently built for Lua tables

pulsar heath
#

yes you can use them

#

i've used several times

#

but if the var is not a table

pulsar heath
#

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

finite radish
#

it goes into detail in that section why you specifically can't

pulsar heath
#

it depends on the table structure

#

not all tables are the same

finite radish
#

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

pulsar heath
#

dude...

finite radish
#

it's most likely returning a Lua table rather than a Java list object

pulsar heath
#

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

high cloak
#

is there a way that I can check if a translation key exists or not?

pulsar heath
#

but surelly theres someone who knows more that i do around

pulsar heath
high cloak
#

i see that getTextOrNull exists, guessing it returns nil if theres no key found ?

#

i'll try that

finite radish
high cloak
#

yeah

finite radish
#

if you just want to check for the current language, getTextOrNull should work

high cloak
#

that'll work then

finite radish
#

(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

marsh halo
#

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

astral dune
finite radish
#

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"

astral dune
#

sorry I'm a little distracted, what are you doing to check for null?

finite radish
#

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>

astral dune
#

square:getFloor():getSprite() will fair if getFloor is null, which is what's happening

finite radish
#

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

astral dune
#

you would need to do if square and square:getFloor() and square:getFloor():getSprite etc to check for all the possible nulls

finite radish
#

amazing

#

love lua

astral dune
#

its pretty straightforward

finite radish
#

not if you expect logic KEKW

astral dune
#

unclear on why square.getfloor would return null if its always the bottom one

#

it is logical

finite radish
#

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)

astral dune
#

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

finite radish
#

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.

sour island
#

How confident are you that getFloor returns the floor layer? What if it's outside?

finite radish
#

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 KEKW

#

my brain tripped itself up while trying to adjust to some Lua behavior compared to more OOP-oriented programming patterns I think

sour island
#
 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

astral dune
#

just think of it like java. If you called Dog.getName().toString() would throw the same error if getName() returned null

finite radish
#

(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

sour island
#
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

astral dune
#

some things don't have a sprite I think

sour island
#

then it'd be does 'nil == x'

finite radish
sour island
#

I copy and pasted what you had - oh

#

I mean in the first half of the if statement, you had floor:getSprite

finite radish
#

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)

sour island
#

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

finite radish
#

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

sour island
#

all Lua manager functions are global afaik

finite radish
#

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

sour island
#

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

finite radish
#

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

sour island
#

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

finite radish
#

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

sour island
#

probably

finite radish
#

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

sour island
#

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

finite radish
#

that makes sense, yeah. that's pretty nifty

sour island
#

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

finite radish
#

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?

sour island
#

for my case, I had the square parse the objects on it to find the correct case

slate sable
#

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

sour island
#

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

finite radish
#

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

sour island
#
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

finite radish
#

ooh nice, thanks

#

definitely

sour island
#

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

finite radish
#

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:
astral dune
#

BAR Isn't checking if getfloor is null

finite radish
#

so I'm thinking either

  1. 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
finite radish
#

this table only exists here, I don't have logic anywhere else in the mod even

#

(for now, at least)

astral dune
#

hmm, good point (sorry, raiding so I can only steal glances)

finite radish
#

no worries

sour island
#

could the issue be related to the list? what if it's empty?

finite radish
#

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?

sour island
#

afaik table.insert is efficient - it's using the parameter for position that makes it horrible

finite radish
#

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?

sour island
#

could be - but I imagine the for() wouldn't be getting that far if it had nothing in it

astral dune
#

I would expect square to be null if it was emptyu

sour island
#

I feel like the error would be different - :getFloor() of null or calling non-method

astral dune
#

ya, exactly

finite radish
#

do {} tables have even have a count of 0, or do they end up nil? or both? PepoThink