#mod_development
1 messages ยท Page 56 of 1
what do you mean "not project zomboid"
it's a totally separate application
he was literally reading the maps and rendering them into 3d.
i cannot wait for this it looks so good
tore off the "---" and "STACK TRACE"
still stuck on getting it to scroll and buttons
@thick karma knows a lot about ui after their previous few projects
that is some dope error reporting.
they're offline rn anyway
also still sick lol - so everything is taking me longer
rip, sorry to hear that
UI is so tedious as is
i know that feeling, i had no adhd meds for a bit and was in a similar state
thus the slow pace of releases from me lately
lol
bon appetit
This is how vanilla declares the workshop item listbox (which you can scroll through using mouse wheel):
local label = ISLabel:new(24, 24, fontHgt, getText("UI_ServerSettings_ListOfMods"), 1, 1, 1, 1, UIFont.Medium, true)
self:addChild(label)
self.listbox = ServerSettingsScreenModsListBox:new(24, label:getBottom() + 4, math.min(self.width - 24 * 2, 400), self.height - 24 * 2)
self.listbox:initialise()
self.listbox:instantiate()
self.listbox:setAnchorLeft(true)
self.listbox:setAnchorRight(false)
self.listbox:setAnchorTop(true)
self.listbox:setAnchorBottom(false)
self.listbox:setFont("Medium", 4)
self.listbox.drawBorder = true
self.listbox:setHeight(self.listbox.itemheight * 8)
self.listbox:ignoreHeightChange()
self.listbox.vscroll:setHeight(self.listbox.height)
self:addChild(self.listbox)
I am not sure if functions are manually added or inherent to listboxes, but following this trail should lead to mouse wheel behaviors.
Okay that comes down to an ISScrollingListBox (in ISScrollingListBox.lua)
function ISScrollingListBox:onMouseWheel(del)
local yScroll = self.smoothScrollTargetY or self:getYScroll()
local topRow = self:rowAt(0, -yScroll)
if self.items[topRow] then
if not self.smoothScrollTargetY then self.smoothScrollY = self:getYScroll() end
local y = self:topOfItem(topRow)
if del < 0 then
if yScroll == -y and topRow > 1 then
local prev = self:prevVisibleIndex(topRow)
y = self:topOfItem(prev)
end
self.smoothScrollTargetY = -y;
else
self.smoothScrollTargetY = -(y + self.items[topRow].height);
end
else
self:setYScroll(self:getYScroll() - (del*18));
end
return true;
end
I think mouse wheel scrolling would be built into whatever you do if you derive it from an ISScrollingListBox
@sour island
Good luck, that would be dope to have 4 separate scrollable windows for checking different errors without being in the debug menu (where I'll inevitably forget to uncheck the pause game box and get disconnected for the 1203034994th time).
I have this:
function errorMagnifier.popupPanel:onMouseWheel(del)
print("onMouseWheel : "..del)
if del < 0 then
errorMagnifier.currentlyViewing = math.max(1, errorMagnifier.currentlyViewing-1)
else
errorMagnifier.currentlyViewing = math.min(#errorMagnifier.parsedErrorsKeyed, errorMagnifier.currentlyViewing+1)
end
errorMagnifier.errorPanelPopulate()
return true
end
``` Where `onMouseWheel` is from UIElement
The idea was that scrolling over the panels would slide them from n out of x
The panels don't trigger onMouseOver though
also, the buttons (clipboards) don't seem to trigger
function errorMagnifier.getErrorOntoClipboard(popup)
local errorText = errorMagnifier.parsedErrorsKeyed[popup.currentErrorNum]
print("firing getErrorOntoClipboard "..tostring(errorText~=nil))
if errorText then Clipboard.setClipboard(errorText) end
end
popup.clipboardButton = ISButton:new(popupX+popupWidth-26, (popupY-(popupYOffset*i))+10+fontHeight, 22, 22, "", popup, errorMagnifier.getErrorOntoClipboard)
this farming patch is easily the most tedious thing i've ever made
I thought the magnet fishing was bad with sorting out all of vanilla's "metal" items, but noOoo
oh thats curious, how did you manage to determine if an Item has metal in it? the InventoryItem.hasMetal() function was wildly unreliable when I tried it
I had to do it manually because it was highly unreliable.

I thought it was bad then, but never have I ever had to copy paste this freaking much just to format data correctly
a whitelist?
Basically
bummer
Then I got to do basically the same thing
but x100
for every single modded and vanilla plant
Because all of their data wasn't formatted in a way that could be used accurately or well.
I love how gourmet evolution code is almost entirely hardcoded!!
I love having to reprogram half the farming framework just so these can all play nice!!
snake's mod pack moment
I'm gonna try and contact him
with literally all the data I had to copy paste
so he can add
dynamic support on his end
so I never have to touch ANY of this again

All because of snake's, I had to implement:
A seed sowing "learning" fix and option because incompatible plants literally could never be planted.
A refund option for sticks and sheet rope because why isn't this a thing by default.
Reworked data for all of the growing, rotting, drying, etc systems to accept formatted data rather than being hardcoded.
A "resprite" option for those who prefer snake's sprites over vanilla or alternatives (like myself)
And more
I hope to god this was worth it
does that just reference MetalValue?
cuz i didnt know about that function and checking MetalValue would have been my go-to
I can't remember, I just remember a bat had metal and a katana didn't so I just walked away
pat
a
What's nice is it doesn't necessarily require any of the mods supported.
They're all optional.
im certainly curious
I may personally not use Gourmet Revolution since it overrides a lot, but I may plan on using MoCrops and Filcher's along with Green Fire together.
will it support wheat mod? https://steamcommunity.com/sharedfiles/filedetails/?id=2837444753 
Wheat is already in Filcher and Gourmet, but perhaps
Probably in the future though because I have
no motivation to add any more mods atm

i do like this wheat sprite a lot, not sure what filcher or gourmet one looks like
mod literally has nothing but wheat despite its name
so if another mod has wheat there's not a ton of value add there
x3
just messin with u
patpat
it was a joke D:
What's nice about this mod is it has a built-in priority system, so if you prefer how one mod does crops over another, you'll just use those.
aaA
NO I CLICKED TUTORIAL
WHY
oh god i hate when that happens
mb u shud make a mod that remove tutorial button
:)
can go with the "disable welcome message" in my list of mods that i keep on loadup
hehe
the agony
or a "are you sure you want to start the tutorial?" tbh, from the devs
would be nice
what if I prefer one crop from one mod and a different crop from another? ๐ค
Well TOO BAD!!
then you can burn
lol
i did teach pwrcosmic a good way to do a highly configurable thingy
but
Fr though if there's no corresponding crop from the "top" mod it keeps going down in priority.
So if a mod has a unique crop, it will exclusively use that mod's code.
Im probably gonna have to reverify my game files after this
Is there a way to get a player from a number
I think I have the player number but not the funny player
uhhh,getSpecificPlayer() for singleplayer and getPlayerFromOnlineID() for MP, IIRC
How can I quickly delete all objects that are placed on top of a IsoGridSquare?
I think you can parse using getObjects
I was thinking to use that, but I'm already doing lua loops on thousands of squares I don't really want to add one more heavy loop ๐ฆ
I mean, you can just parse through those once each and removeFromSquare and removeFromWorld
you're trying to make an explosion?
did you try the vanilla explode() ?
Yep, it works well, but does not delete walls and stuff
does burn them though
This is done combing, IsoFireManager.explode and my own custom replacement
Yes it does, but it looks bad when some tiles are still standing, and these tiles have no burned style
you could try to delay the square runs if you're worried about performance
rather than trying to fit them in one tick
What do you mean? ๐ค
if possible starting with the center area, then each following tick run the next ring
SS13 does this for their explosions
as their engine is single thread and clunky as fuck
Interesting ๐ค
makes for an interesting effect
This grass and dead tree is not a object right?
I did a commission basically creating 10-years later but zoned - alot of that is handled via attached sprites but they should still be isobojects
Cool! Off topic question then, do you know how to force spawn erosion on a building? ๐ค
oh I found this for squares 'ClearTileObjectsExceptFloor()'
the system just placed lists of sprites at random based on tile properties
it didn't touch the erosion system
Okay thank you ๐
It works*!
There is the minor issue of the flying pole lol
it's probably a square above
I'm also getting a new interesting error ๐ค Apparently calling square:BurnWalls(true) creates this problem
STACK TRACE
-----------------------------------------
Callframe at: BurnWalls
function: BurnSimple -- file: Everythingburneddown.server.lua line # 21 | MOD: EverythingBurnedDown
function: BurnSquare -- file: Everythingburneddown.server.lua line # 107 | MOD: EverythingBurnedDown
function: OnLoadGridSquare -- file: Everythingburneddown.server.lua line # 132 | MOD: EverythingBurnedDown
ERROR: General , 1669770616518> ExceptionLogger.logException> Exception thrown java.lang.reflect.InvocationTargetException at GeneratedMethodAccessor858.invoke.
ERROR: General , 1669770616518> DebugLogStream.printException> Stack trace:
java.lang.reflect.InvocationTargetException
at jdk.internal.reflect.GeneratedMethodAccessor858.invoke(Unknown Source)
scanning for squares above shouldn't cause issues being there aren't that many I assume
that error implies you're calling a method that doesnt exsist
I guess I just need to add something like
-- Burn multi floor buildings
local upperSquare = getCell():getGridSquare(square:getX(), square:getY(), square:getZ() + 1);
if upperSquare then
BurnSquare(upperSquare, explosionEffect)
end
That does not exist? But IsoGridSquare has that method O.o
whats the whole error?
Caused by: java.lang.NullPointerException: Cannot invoke "zombie.iso.IsoGridSquare.getSpecialObjects()" because "<local2>" is null
I am confused, what does this mean? ๐ค
I'm not sure what local2 exactly refers to - but it's always local2 in these types of errors
based on how vanilla applies burnwalls they run IsoFire.CanAddFire(square, true) first
๐ค
there's only like 3 instances of burnwalls getting used, they check for canaddfire or if the cell exsists
perhaps the issue is related
@sour island what are the ui elements child to
a button
the button in the bottom right is parent of the panels and other buttons
could that be the issue?
yeahhhhhhhhh
hm
youre interacting out of the parent so it doesnt register
parent ui shouldnt encompass all the childs
@sour island I added the Iso fire check, and I'm getting only 2 error (less than the original), but still local2 error ๐
self.preview = ISUI3DScene:new(self.x + self.width, self.y, 400 * FONT_SCALE, self.height)
self.preview:initialise()
self.parent:addChild(self.preview)
what i did to have a "child" out of the parent
I'll just toss them on addUIManager
keep in mind in my case the ui did have a parent which might not be the case if its not a child to anything
thanks for the heads up
I have it conditonal based on font height
0,0 is top left right?
seems to work, I just need to mess with the x/y locations again
yeah top left
I've somehow managed to misplace a print.
Is there a way to find what file a print originates from?
you could edit the function from finger print to not cut that information off
is mousewheel's del by 1's, 1 /-1?
So, apparently ClearTileObjectsExceptFloor works, but it does not transmit to the clients or something similiar.
And even if the sprite is gone, if I walk where a tree was located, I still cannot see through it
hm
So, I decided to switch from using that function to using my own loop and iterate the objects, and now I randomly get this error ๐
New function below
local function BurnMax(square)
local floor = square:getFloor();
square:Burn(true)
local objects = square:getObjects();
local size = objects:size() - 1
for i = 0, size do
local object = objects:get(i);
if object ~= floor then
square:transmitRemoveItemFromSquare(object)
end
end
-- Has issues does not sync :(
-- square:ClearTileObjectsExceptFloor()
if not floor or square:getZ() > 0 then
return
end
floor:setSpriteFromName("floors_burnt_01_0");
end
Oh it's because I'm iterating over the objects list while I'm removing elements ๐
New fix and bedtime
local function BurnMax(square)
local floor = square:getFloor();
square:Burn(true)
-- getLuaTileObjectList
local objects = square:getLuaTileObjectList();
for index, object in ipairs(objects) do
if object ~= floor then
square:transmitRemoveItemFromSquare(object)
end
end
-- Has issues does not sync :(
-- square:ClearTileObjectsExceptFloor()
if not floor or square:getZ() > 0 then
return
end
floor:setSpriteFromName("floors_burnt_01_0");
end
more specifically, getSpecificPlayer() for local stuff and getPlayerFromOnlineID() for networking - getSpecificPlayer() is still used more often in multiplayer
Alright, so it's effectively done.
Just gotta make sure some recipes are good, but other than that I think we're set.
Actually, I wonder if doing recipe patches would cause more problems than it solves (?)
attempted index: printException of non-table: null
works like a charm
made them a bit shorter as the more useful info is at the top anyway even on long errors
ya, the hard part is always finding where the top of the stacktrace is
in the console logs
I've never used getSpecificPlayer(), p.sure that getPlayerFromOnlineID() works fine locally
or client-side, rather
it doesn't really make a difference afaik but getSpecificPlayer() is generally preferred
I haven't tested anything in singleplayer though, which will eventually bite me
yeah, i have no idea if online id is even set in singleplayer
preferred by whom? I'm a rebel, a visionary. Also "specific player" just sounds weird
vanilla code and every mod i've ever looked at
plus some snippets wouldn't even work with online id
for i = 0 to 3 do
local player = getSpecificPlayer(i)
-- etc etc
end
```would be really annoying with online ids
it's mostly a style thing but i think there's a reason for it
I actually don't know what would happen if you call getPlayerFromOnlineID on a client, if your id is 5 or 9. Probably works fine
huh?
my OnlineID is always 0, which is also my specific player, because I'm testing alone on a locally hosted server. A lot of the stuff I do probably works fine because of this. I can call getPlayerFromOnlineID on the client and always get a valid return, since there is no chance of me calling it with an ID that doesn't correspond to a player on my client
who is the current clothing nerd?
speaking of which, just found an edge case where I hit a parked vehicle hard enough for it to then crash into a wall. My code tried to tell the non existent driver of the parked car that he'd driven into something
how can i make a single held item play the masking anims of two items? like i want both hands to play the holdumbrella animation. but with one umbrella.
I-I think..
I think I'm finally done.

Aaaand so I thought
Does anyone know how to set the amount of items required in a recipe via lua?
I need to replace a source with another.
This is supersurvivor right?
Try to make the item 2 handed or create another item like umbrella but with no image
....
you can only play one anim mask per item. i need to know how to merge them into one.
this would be so much easier if player animations weren't fricking voodoo.
You can duplicate the xml file and modify it tho
What exactly does it do if a recipe has "IsHidden:true" in its code?
If I understand correctly, it makes it so it doesn't pop up until you can perform it?
Anyone know where strings passsed to DebugLog.Vehicle.trace() would end up? There are a bunch of these DebugLogStreams, for everything from Animation to recipes to Unit Tests, but I can't tell where the output is going
I feel like I have to change the log level somehow to have trace messages show up
I would imagine they go into the debug log file in your savedir
(the one under %APPDATA%)
that said, I suspect trace level messages aren't logged unless you've turned on something in the debug options menu in the lua debugger screen
nice job!
I thank
Probably the most painful mod by far unless I get cooperation with the big farming devs
ive never seen that done, i always see people get the online player list and iterate through it
you've never seen getSpecificPlayer?
ive seen it but i thought it was meant for coop :P
shouted out to me even tho i didn't do squat on that one? ur really nice :)
dammit my nitro ran out
i see that used on the server but never the client
this is what i would think immediately in those situations
why would you want to iterate through other players on the client
i guess that's the situation that i havent run into lol
you wouldn't! that's the whole point of this snippet
far too many mods just use getPlayer() in place of getSpecificPlayer(), so quite a lot of them will straight up not work in coop... negatively affecting possibly as many as ten active pz users
all that stuff is still active in mp though
coop can be disabled on servers in the unstable build now, but previously it wasn't a choice
are u saying ppl playing coop can join a dedicated server?
or just that the junk was active for no reason
yeah you can play online in coop
Metal Gear Zolid
all the skills
love it
can't wait to see how can a human being lift a fridge all by themselves with that animation
hi can anyone help with how to check if an item or vehicle exist?
this is what i have so far
function SceneZ.init_SpawnRides()
for _, v in pairs(getScriptManager():getAllVehicleScripts()) do
if v == "Base.78amgeneralM35A2" then
local spwnv1 = "Base.78amgeneralM35A2"
print("spwnv1: ", v)
end
if v == "Base.92amgeneralM998" then
local spwnv2 = "Base.92amgeneralM998"
print("spwnv2: ", v)
end
if not spwnv1 then
local spwnv1 = "Base.SUV"
print("spwnv1: ", spwnv1)
end
if not spwnv2 then
local spwnv2 = "Base.SUV"
print("spwnv2: ", spwnv2)
end
end
SceneZ.spawnRides(spwnv1, spwnv2)
end
but i think i could have achieved the same thing with something like
getScriptManager():FindItem(recipe:getResult():getFullType())
but im not sure
i havent really done much of testing with scriptmanager and its kind of hard to understand for me
for single tile objects like fridges or washing machines I would make an animation of the character lifting it on their backs
tho grabbing a washing machine like this is pure chad energy
you can just do
local item = getScriptManager():getItem('Base.Whatever')
if item then
```most likely the same logic applies to vehicles
An ability to understand how in the world Java and Lua code are mixed up and still work together

actually, why did dev use Khalua in the first place
0there! thank you
if not getScriptManager():getItem('Base.78amgeneralM35A2') then
local spwnV1 = "Base.SUV"
else
local spwnV1 = "Base.78amgeneralM35A2"
end
like so? thank you! ๐
you should use getVehicle not getItem!
oiw yeah
can you change a vehicles script while IN the vehicle?
like say i was in a truck, wanted to hit a button and then i was in a van.
nah this is just check if the server has 78amgeneralM35A2 installed
oh i know.
i meant more in general.
like how you can right click on a car and change script.
why is it that my rifle has WeaponReloadType = boltactionnomag, but it wont let me reload the rifle with just bullets since i dont want a detachable and reloadable mag
couldn't you just use getActivatedMods then?
if he holds a mannequin like that, it's gonna look moderately indecent
Too many diffent items
Try to copy the shotgun properties
Remove the cliptype
hugging mannequins animation when
to reduce sadness
this is returning an error i tried alot of other possible combination non workled
what's the error?
sounds like you have some weird code, show me the lines that are causing the error
did not have __call metatable set i think means you are trying to call a non-function as a function
Hi, anyone know where the files for VHS tapes are stored? Hopefully looking to find a flat transcript of the different tapes for a project I'm working on, alongside pointers on programs or guides to make other VHS tapes as well. Thanks!
what does it take to make pz mods
what cs skills
what language or whatever do i need to study/know to do pz modding
lua
it's not really so simple as what skills you need though, what skills you have will change what kinds of mods you can make
i gave up for now i need to stop working. its my moms bday.. lol
ill just require the mod to have those mods
how do i do that again? lol on the mod id?
heyyo i have a question about lua
if i write a function in example.lua, can i use that function in a different example2.lua? if so, do i need to put a header
If you use
function```
And not
```local function```
You should be able to
You can also add
```require "example.lua" ```
On the header
tysm ๐ 
Did you initialise() and instantiate() the buttons?
Before adding them as children to the panel?
Perhaps glancing at InventoryPane would help since that's an ingame element with mouse wheel scrolling that autoactivates on mouseover (iirc)
(or possible InventoryPage, not sure which will handle the scrolling)
he had child elements off parent
No, do not always avoid using globals. Sometimes modders need to tap into your mod to ensure cross-compatibility, and if you make every possible thing local, they can't. Using well (uniquely) named global tables makes it much easier for other modders to make your mod play nicely with theirs. Making all your stuff local will make this hard on people.
PositionXY got replaced recently by my own mod for making exactly this mistake @gaunt meteor
sigh another one
If you want your mod to be replaced for lack of compatibility, make everything local
How do you export from someone else's mod?
^
If they have no export statements?
then theyre local
but why would you declare a global when you can instead export a local
Right and if the modder is wrong about whether that local variable will ever be needed outside they're mod, and they didn't return it to offer it for export?
Can you force export of local stuff a modder forgot to export?
then it wouldnt be global in the first place
Because declaring everything in a global table saves time and avoids possible mistake of forgetting to export a crucial local that other modders will need
that is just straight up terrible coding
Does anyone know why the loot distributions do multiple rolls with smaller chances instead of just one roll and a static chance? What is the benefit here
What do you mean it wouldn't be global? That's the entire problem. If the variable isn't global and the variable isn't returned/exported (so tmk cannot be imported), AND some other modder needs that variable, they are screwed right?
so youre arguing everything should be global?
I think you guys are on the same page - just misunderstanding eachother
name your variables whatever you want as long as it's inside of 1 global variable
nay
than can then be leveraged as needed
via return and require?
yes
In modding when people are often doing things other modders may need, making variables that are important to your flow accessible to other modders increases convenience for making mods cross compatible TREMENDOUSLY. Whether you value that or not is up to you. @gaunt meteor
I haven't ever used that technique but probably should
would make naming issues almost impossible
Return and require is fine too IFF you're ALWAYS correct about what other modders may need to use in your mod, AND you don't forget anything you know they may need from your mod.
unless people are hardoverwriting based on filenames
since you clearly dont understand
local YourWouldBeGlobal = {}
--do everything in that var
return YourWouldBeGlobal
then just require that file and you achieved the same thing while not polluting the global space and keeping everything local
another advantage
But if they are WRONG because they're a new programmer and they THINK someone won't need something they WILL need, they just created an unnecessary hassle for people trying to make their mod play nicely with others
just put everything under that var
if you're tying the variables under the 1 local it's all accessible
it's as easy as including 'return X' at the bottom on the file
Will it still overwrite if u put it on a folder? I dont think so
I understand you perfectly, and you're very arrogant and insulting right now.. I know you can return for exports. Many new modders will forget to export things other people need, or underestimate external needs, and thus the crucial variables will often not be exported by newbs in the habit of using export.
i dont get why global usage is so common in pz modding
its against lua design and not used in other scenes
myLua/genericLuaName.lua
if the folder path is the same yes it will
"instead of teaching people how to do things properly i will instead make terrible coding practices"
then name the folder something like the number steam gave u as workshop id
if the file occupies the same location and has the same name you can overwrite it
@gaunt meteor Just think for yourself and decide what's best for your mod. You've been warned about the consequences of forgetting to export something others need. There are many working ways to do that.
it's the nuclear option to fixing mods
Any ideas
export in this case would just be exporting the 1 local module though? If people aren't housing all their functions under 1 thing they can't use require anyway
Correct, you would have to return a table of everything you want people to be able to import
But that could be the entire mod
You don't really have to make a conscious decision
I have everything under errorMagnifier
the only issues would be if I lazily put locals floating in the file
which would also be an issue even if you don't export
if errorMagnifier was global outright, any locals floating around it in the file can't be accessed
I think you're both on the same page lol
No he is concerned about the singular global variable conflicting with other globals or just crowding _G
that's a valid concern
Yes, it could cause an issue if your global name gets taken later
return/require also creates globals on a mod's demand - if they need it
so it is safer
but that can be avoided if you use return/require instead
Sort of but imo pointlessly
it doesnt create globals
the exported value is stored
global space never polluted and preserves localized access
I mean you could make it a global but yes, I just meant there's a clear intention to use it
it's not just there because
Right you could theoretically turn an import into a global if you needed it
picking a unique name is by far the easier approach for newer modders - but it also requires them to be aware of this issue and make what could be an awkwardly long name
and I don't think 'make your main module local and return it at the end' is that much harder
I probably would have written some stuff differently if I had known tbh
Yes, as long as you don't forget to include anything in the returned local, same thing. Unfortunately, when a lot of new modders receive the unqualified advice "make everything local" with no warnings, they go like this:
end```
All over their damn mods
Fair, I just don't have time for educating every new modder on every nuance, and wrapping stuff in safely named globals is often much easier for them to understand than dependency management.
Is there a way to be able to deterrmine if its global
Like
--somecode to convert all the var declared within this lua as something else```
Idk just a thought . I think its not possible lol
global space is a table
you can check if a value is present
if _G["test"] then
end
anyway dont get what youre saying there
I think he's saying hijack's someones code to refactor it dynamically lol
ughhhh
As long as they're housing it in a global that's better than having every function be global
There's definitely degrees of headache
Also I got the debug scroller working
local Module = {}
if _G["badGlobal"] then
Module = badGlobal
_G["badGlobal"] = nil
end
return Module
imho new PZ modders should familiarise themselves with vanilla style
there you go that should do it
Vanilla style isn't that great tbh
alot of it is simply old
some of it is locked behind locals like Burryaga is concerned about
there's also a tendency to toss everything under 1 function in a giant if chain - making adjusting results require working backwards
or if you're new and not sure - replacing the whole thing
which creates massive conflicts
No
Its like the variable name
u want to use checks first if it exist
If jt does replace the variable to someother name
btw cool corollary of this you can locally override the global space to increase performance
is there a significant increase of performance?
in normal lua locals are about 5x faster than globals
Definitely both understanding vanilla and improving on vanilla are crucial abilities @sour island @fast galleon ... I had to fix 2 vanilla bugs and add a missing vanilla feature within a half dozen mods. Also two of my mods are arguably bugfixes themselves.
Vanilla code = important but mediocre

Two of my children were forcibly adopted by TIS
in kahlua might be even larger
Is there a way to profile Lua?
regardless 5x increase for adding 5 letters is literally free performance
you can do
local start = os.clock()
for i=1,1000000 do
-- operation test here
end
print(os.clock() - start)
hm
I have forced runtimes in this mod atm, and since putting the module as local - it does actually boot faster
also prints in kahlua are terrible for performance
like really really bad
we should ask the devs for access to loggers
someone put a print in server/client command on a popular enough mod
I get asked about it as it only outputs the command's name
debug.log is exposed I think - but I'm not sure what that one entails
remember a while ago someone removing all prints from item tweaker and it suddenly booted really fast
it's definitely a heavy process - putting it in isoloadsquare will brick your game for a while
I made a mod that overloads print to include the coroutine's stack trace file
Would stopping prints altogether actually benefit performance?
or rerouting them to a logger via this method
worth testing the performance of a logger
because currently prints are quite harmful
Is it inherit to lua or kahlua or pz?
kahlua i think
does concatenating a string or using multiple arguments factor in?
I could see either one being an issue
not sure what happens behind the scenes with multiple arguments but string concat in java isnt great
multiple arguments actually lets you print booleans as is afaik, so it might just be java's string handling
I wonder if the performance is just the concats
I wonder if Khalua is the sole reason why performance is so bad 
not the sole reason but its a good part
oh yeah iirc kahlua is like really old and has never been updated in decade isn't it
Could this be a reason my locally hosted modded server crashes me to desktop when I try loading with debug mode?
probably not
@sour island 10k prints ran in about 5s
100k local var accesses ran in 6ms
gimme a global name
function launchEquippedItem(playerObj)
Is a global function in vanilla
ISButton will do
yeah any of the UI elements
sure ill use that
oh, is there an exposed os.clock for PZ?
use os.time
Seems to be throwing up exceptions
Sorry misread, trying
not throwing errors but currently hanging - so looks like it's working
local _aStart = os.time()
for i=1,1000000 do print("just_string") end
local _aTiming = os.time()-_aStart
local _bStart = os.time()
for i=1,1000000 do print("concat".."string") end
local _bTiming = os.time()-_bStart
local _cStart = os.time()
for i=1,1000000 do print(true,"bString") end
local _cTiming = os.time()-_bStart
print("just_string: ",_aTiming)
print("concat..string: ",_bTiming)
print("true,\"bString\":",_cTiming)
did 1mil now
locals were 56ms
globals 83ms
going to drop to 100
do 10k
my CPU is 55% lol
but I think it just hung
heh
ate the 10k p well
LOG : General , 1669817565011> [errorMagnifier] just_string: 1.4900000095367432 LOG : General , 1669817565011> [errorMagnifier] concat..string: 1.1410000324249268 LOG : General , 1669817565011> [errorMagnifier] true,"bString": 1.2229998111724854
Not what I expected
How did just a string take more time than concating two strings?
I would only think it can pick up on the .. and skip identifying the argument
I jumped it to 25k
LOG : General , 1669817810546> [errorMagnifier] just_string: 3.4670000076293945 LOG : General , 1669817810546> [errorMagnifier] concat..string: 2.989000082015991 LOG : General , 1669817810546> [errorMagnifier] true,"bString": 2.9619998931884766 LOG : General , 1669817810546> [errorMagnifier] "concat string with "..tostring(true) 2.944000005722046
hmmmmmm why are your times that low tho
I have a AMD Ryzen 5 5600X - you?
3700x
I'm also running my other mod that modifies print
this difference would be over 10 years of cpu
local print_original = print
function _G.print(...)
local coroutine = getCurrentCoroutine()
local count = getCallframeTop(coroutine)
local printText
for i= count - 1, 0, -1 do
local o = getCoroutineCallframeStack(coroutine,i)
if o ~= nil then
local s = KahluaUtil.rawTostring2(o)
if s then
local modFile = s:match(".* | MOD: (.*)")
if modFile and modFile~="fingerPrint" then
printText = "\["..modFile.."\]"
end
end
end
end
if printText then
print_original(printText,...)
else
print_original(...)
end
end
Does converting it to local actually help?
yes
damn I need to rename that mod
it has to do a global access in each loop iteration
no longer just for debugging
while in yours its a local access
actual performance boosting
its the same as doing local print = print
So this would be a decent stop gap until the devs work out the log exposure
the just string thing is confusing tho
I wonder if I can snap it in two
Not familiar enough with the use of (...) how would I grab arguments from that?
running with your print is slower for me like it should
since its doing a whole bunch more
Oh I see that now
Ah
I don't have a just string in that case, it becomes a multiple arguments
But also heftier than the multiple arguments unfortunately
regardless i still have way way worse performance
That is true
but I could remove the additional feature of showing mod file origin
for much more perfornace
LOG : General , 1669818466940> [errorMagnifier] PRINT TESTS: runs:25000 LOG : General , 1669818466941> [errorMagnifier] just_string: 3.381999969482422 LOG : General , 1669818466941> [errorMagnifier] concat..string: 2.9769999980926514 LOG : General , 1669818466941> [errorMagnifier] true,"bString": 3.0290000438690186 LOG : General , 1669818466941> [errorMagnifier] "concat string with "..tostring(true) 3.0299999713897705 LOG : General , 1669818466941> [errorMagnifier] "String1","String2" 3.0220000743865967
seems using (arg1, ...) is slightly more taxing
anyone know if a "always a show on tv" mod is possible?
Did a few more tests and can't say I'm seeing differences
Not sure why my timings are faster - I am using os.time
`local test suite - global print
(just_string,) 2.367000102996826
(concatstring,) 2.312000036239624
(true,bString,) 2.299999952316284
(concat string with ts() true,) 2.251999855041504
(String1,String2,) 2.2690000534057617
global test suite - global print
(just_string,) 2.382000207901001
(concatstring,) 2.2769999504089355
(true,bString,) 2.307999849319458
(concat string with ts() true,) 2.3510000705718994
(String1,String2,) 2.240999937057495
local test suite - modified print
(just_string,) 3.4630000591278076
(concatstring,) 3.2130000591278076
(true,bString,) 3.30899977684021
(concat string with ts() true,) 3.302000045776367
(String1,String2,) 3.200000047683716
global test suite - modified print
(just_string,) 3.2960000038146973
(concatstring,) 3.0199999809265137
(true,bString,) 3.062999963760376
(concat string with ts() true,) 3.077000141143799
(String1,String2,) 3.0929999351501465
global test suite - local print
(just_string,) 2.4040000438690186
(concatstring,) 2.2809998989105225
(true,bString,) 2.25600004196167
(concat string with ts() true,) 2.3420000076293945
(String1,String2,) 2.319000005722046
`
tried local/global tests as well
the modified print is the print with additional features
perhaps I did something wrong with how I tested
I'll hold off on advertising performance boosting - the modified print has benefits outside of it anyway
there has to be something wonky going on because the performance is too different from mine and the values between operations are very similar while in mine they were as expected
this is what I wrote up for testing - perhaps there's something here that already cuts performance load?
local printTesting = {}
printTesting.testRuns = 25000
printTesting.results = {}
function printTesting.printResults()
print("PRINT TESTS: runs:"..printTesting.testRuns)
for _,result in pairs(printTesting.results) do print(result) end
printTesting.results = {}
end
function printTesting.printTest(...)
local _start = os.time()
for i=1,printTesting.testRuns do print(...) end
local _timing = os.time()-_start
local argString = "("
local args = {...}
for _,arg in ipairs(args) do argString = argString..tostring(arg).."," end
argString = argString..")"
table.insert(printTesting.results,argString.." ".._timing)
end
printTesting.printTest("just_string")
printTesting.printTest("concat".."string")
printTesting.printTest(true,"bString")
printTesting.printTest("concat string with ts() "..tostring(true))
printTesting.printTest("String1","String2")
printTesting.printResults()
did you test on a server or singleplayer
and pasting the code in the console?
yeah
using the vanilla jvm?
I'm not sure what that is, so I would assume yes
so clearly not custom args as well
local print_original = print
function _G.print(...)
print_original(...)
end
``` When I did replace the print
it is in debug mode
and the cache is pointed to a folder on my desktop rather than the user/Zomboid folder
i do see an issue with your tests tho
oh?
printTesting.printTest("concat".."string")
this one is a single arg
it will first concat then pass that
ah
so essentially same as passing a string
still tho, I'm not seeing much improvement between global and local prints
it all runs well tho
How are you testing things?
exactly the same
similar enough lua code? off PZ?
i pasted your code in the console in singleplayer
What did you get?
^
I wasn't aware you can do that
trying it now, definitely taking alot longer
So this is going through the java -> lua -> java?
Yeah my game is locked up
Did you try adding line by line to the console? @sour island
You have to condense things into a single line using semi-colons
I just dumped it in
Probably didn't load correctly if you didn't make it a single line
Hmm when I enter line by line, locals get forgotten
So Idk what implications that will have but yeah debug console is forgetful
Tyrir taught us all this awhile back when a command wasn't working correctly because I tried declaring a local in console and using it later
Yeah, I'd say the performance ditch is from the console - but print is also pretty bad to abuse
the only local is the main module
everything else is housed
Locals in the console cease to exist at EOL
Reminds me of how I was parsing Java's distributions in a long for loop on accident
even though the ui doesnt show more than 1 line you can indeed paste multiple
so yes you can paste a whole code block and it will work
Fair enough same difference to me because I can't go to a new line without hitting enter... Pasting in carriage returns submits lines, does it not?
equivalent of the console in normal code would be having it all within a do end
nope
well now we know
console for some reason is incredibly slower
i think i know why
no i do not
first is with global print, 2nd with local
doesn't actually help print's performance ๐ฆ
Wait, first is global and somehow faster?
Is it possible they optimize Lua on load by making locally accessible copies of global things in each file? Such that trying to do so again just slows you down?
Isn't Lua's entire ideology to make everything local so it's faster to index-
I pasted this into console:
local print_original = print
function _G.print(...)
print_original(...)
end
local printTesting = {}
printTesting.testRuns = 1000
printTesting.results = {}
function printTesting.printResults()
print("PRINT TESTS: runs:"..printTesting.testRuns)
for _,result in pairs(printTesting.results) do print(result) end
printTesting.results = {}
end
function printTesting.printTest(...)
local _start = os.time()
for i=1,printTesting.testRuns do print(...) end
local _timing = os.time()-_start
local argString = "("
local args = {...}
for _,arg in ipairs(args) do argString = argString..tostring(arg).."," end
argString = argString..")"
table.insert(printTesting.results,argString.." ".._timing)
end
printTesting.printTest("just_string")
printTesting.printTest("concat".."string")
printTesting.printTest(true,"bString")
printTesting.printTest("concat string with ts() "..tostring(true))
printTesting.printTest("String1","String2")
printTesting.printResults()
Ohhh I see nevermind.
Guessing in the dark, I'm not sure. Doesn't really add up that locals would be generally faster in Lua but slower here unless perhaps we're unwittingly already working in locals
My guess would be the console is doing something unwieldy with the string
I thought at most you can run functions from it - I didn't think you can just dump whole blocks
ah i see the issue
print is still global
however the print_original call is local
I wonder how much better this game runs if using 5800X3D
so if I replace print() with that it should help
this game must prob be CPU bottlenecked ig
just do local print = print
well yeah the bottleneck is not the var access but the prints themselves
however if you do
local print = print
for i=1,100000 do
local var = print
end
vs
for i=1,100000 do
local var = print
end
you will see a difference
for benchmarking dont use os.time, use os.clock
time uses real time, and is effected by system load (background process, OS stuff etc)
clock only counts the cpu time used in the running process (not effected by background stuff)
doesnt have clock
kahlua doesnt?
zomboid kahlua doesnt at least
huh, could have sworn i used it benchmarking, but that was 5+ years ago so might be remembering wrong
there's a few things specific to PZ
I think a few os. are not exposed and math.random is locked out
Maybe you benchmarked functions externally
There's probably a getmiliseconds that is system time - there's like 3 get times mentioning ms
Doable i think
AMAZING!
looks great
for the record, I avoid doing globals either like so
Module = {}
local string = string
local math = math
local print = print
local etc = etc
setfenv(1, Module)
local function PrivateFunction() end
function PublicFunction() end
return Module
or like so
Module = {}
local function PrivateFunction() end
function Module.PublicFunction() end
return Module
Haven't decided which I like best. Technically the former is faster simply because of putting global things into locals, but I could do that in the latter too if I wanted
is it possible to disable sneak while holding an object?
What does setfenv(1, Module) do?
It changes the environment to be the Module table instead of the _G table, so anything you write as a global actually ends up in Module instead
downside is you can't access globals anymore, which is why you have to make local references to any global you want to access
before doing the setfenv
Cool stuff ๐ฎ
I like it because the declaring locals at the top reminds me of import so it feels more normal than just calling random functions out of nowhere, lol
and its faster
ugh
the final roadblock is that errors are being segmented
but they're being segmented differently depending on the type of error
I thought it would be a simple combine every 2
but _len not operands print stack trace headers before and after
where as other errors only print after
--
Hi, is there any function to get All Vehicles?
since you guys mentioned earlier that you fixed vanilla errors... this is vanilla error...
made a ogg file might fix it?
Probably would
do you know what the performance cost of bringing a global into the local space is like? i've heard this is a concern but i'm a lot less worried about it if locals are *that* much faster
from the tests i did a global access is slower by about 50%
ya its usually worthwhile to bring them into local
least local to the file
if its going to be used in a very time consuming / long loop, then occasionally local to the function (but not local to the loop)
the cost of assigning it to a local is irrelevant
thanks, will keep that in mind
any globals used in a file i'll declare local at the top, both the java functions and "built in" lua functions like pairs and ipairs etc
the downside though, if you declare local at the top, and a file loaded later overwrites a global then you wont have a reference to the overwrite, just the original (which can be a bonus, depending on how you look at it)
things like that fingerprint mod might not work as intended
is that why some vanilla prints get picked up as prints originating from the mod?
I had to put in an exception for itself
cant really say, havent actually looked at the mod
Fun fact almost the entire code is on the poster
local print_original = print
function _G.print(...)
local coroutine = getCurrentCoroutine()
local count = getCallframeTop(coroutine)
local printText
for i= count - 1, 0, -1 do
local o = getCoroutineCallframeStack(coroutine,i)
if o ~= nil then
local s = KahluaUtil.rawTostring2(o)
if s then
local modFile = s:match(".* | MOD: (.*)")
if modFile and modFile~="fingerPrint" then
printText = "\["..modFile.."\]"
end
end
end
end
if printText then
print_original(printText,...)
else
print_original(...)
end
end
anyone know how to make a VHS tape?
interesting, but no that wouldnt be why (since vanilla doesnt pull print or any other globals into local), i was referring to other mods potentially bypassing your new print function
Hello fellow modders, I ran into the issue, so basicly my mod spawns items from other mods in containers (but it shouldn't) it should distribute some items from my mod. It gives an error related with Suburban distribution. I'm not a programmer... yet. So I looked into code from other mods and changed it to work for me, but I don't understand how some part's of it works. Here's the code(and screenshots of it) can you help me please?
What does this do? ๐ค
Yes! Looks great too
That's chuck's fingerPrint mod, it adds the name of the mod calling print to the printed statement, so you can see where console spam is coming from
๐ฎ That's so cool!
but ya, any mod that makes a local reference to print before fingerprint loads would bypass it
yeah I named it lowercase so it ideally loads later in case anyone overwrites print for whatever reason - but maybe I need it to load first?
You can add a _ to the name to load it even earlier
I would assume no one would be messing with print tbh
I'd like to get this damn debugging tool working
I wish you good luck 
i'd load first, then do a confirmation check later to ensure your overwrite is still valid
Then call an airstrike on whoever is trying to override the print
--676 - header-java-header
--900 - header-java-header
--805 - java-header
--492 - attempted-header-java-header
function errorMagnifier.isJavaException(str)
if not str then return end
local result = string.match(str, "at se.krka.kahlua.vm.KahluaThread.luaMainloop%(KahluaThread.java:(.-)%)")
return result
end
``` Dirtiest solution I could think of
Basically grabs the error line # and smooshes the "errors" before or after depending on the format
seems though I missed one
are there any good modlists?
You could go based on most popular - or shop around the workshop.
should cover any other cases for this type of error I hope
basically a house of cards
are you printing the same error multiple times or group them them?
I thought you were grouping them at first
they're stacked hence the x2
the problem is the vanilla game segments what they consider to be errors
there are headers and bodys so to speak
each is stored as an error - I think unintentionally
the java exception info is also it's own error entry
rn I'm trying to find a throughline to keep the actual errors in 1 piece
this refers to the specific line in kaulualoop where the exception is called
--900 - header-java-header
--805 - java-header
--492 - attempted-header-java-header```
676/900 prints a header before and after - the ===STACK TRACE===
492 - prints the line 'attempted index of null' followed by the header than the java info than another header
callframes are similar but no header it seems
but the file name is dumped after the java info - so I just flip it to keep it uniform
the priority is keeping the MOD: X line at the top
the default if none of the cases are met is just dumping it in pieces
hopefully nothing gets garbled together
seems to be ok with this arrangement so far
wait no
last 2 seem to be duplicates which shouldn't happen
types 676 don't have a before header - must have read it wrong
there's a lua manager exposure of kahluaThread
but only for getAllErrors and errorCount
so no way to intercept the exceptions as they're being written
Might consider grouping them by mod id, if that info is available
Ah okay
I could but I'd need to confirm the errors are being pieced properly
On the 9th of July 1993 in a desperate measure to stop the Knox virus, the US government decided to deploy napalm bombs on the town of Muldraugh, KY
Random generated nuke/napalm explosions in the cities with tile destruction and with some performance tricks here and there
lol
I think its randomly chnging the tile
What you're asking would involve lots of math probably
Yeah I'm trying to work with the edges but math is not my strong skill, I'm open to get help from someone who can tho
I'm trying to use a gaussian blur to blur the border of the explosions
Also, did anyone ever seen this bug? The walls are gone, but the game still draws the line as they are there O.o
that's normal
any buildings taht aren't player made have "rooms"
that have their own lighting
and if u walk into it it gets weird even if they are demo'd
How do you get a perk if you know it's internal ID
Damn ๐ฆ is there a way around that?
delete the room :)
not sure if u can do that dynamically
usually is not a thing one does
Like the room definition? ๐ค
there's like.. data structures that hold such things
i dont know if they can happen on the fly
never looked into that
IsoBuilding has a rooms var ๐ค
nice, with negative levels you can make craters probably
Negative levels? ๐ค
negative levels don't exist yet, they coming when basements will be released
Oh that thing
For now I just want a better way to make my circle look better ๐ฆ
Also, there are burn (metal) fence tiles, but the game does not use them, only the wood ones ๐ฆ
I wonder if negative levels will eventually lead to topography ... Looking forward to jumping cars off ramps
they'd need to resolve moving sideways on stairs
Goddammit writing peformant lua code to randomly nuke a town is quite tough my PZ sometimes lags like hell (when I teleport)
they might be a one off somewhere
they like to do that.
Maybe, but I wish they actually made that burnt fences turned into their burned version instead of staying pristine ๐ฆ
understood.
anyone know of a mod or two that for sure throw errors?
I can send you the one I'm working right now lol, I always get atleast some local2` errors
Does anyone know what causes some tiles to make corpses half disappear?
I'm working with these tiles
floors_burnt_01_0
floors_burnt_01_8
floors_burnt_01_13
floors_burnt_01_14
floors_burnt_01_15
Does PZ lua support classes?
It's actually only happening with these sprites ๐ it works normal with floors_burnt_01_0\
floors_burnt_01_8
floors_burnt_01_13
floors_burnt_01_14
floors_burnt_01_15
I thought pz used a lua emulator so a lot of the lua syntax isn't supported?
Some syntax is not supported, such as goto, but a lot is. What syntax are you hoping to use?
first its not an emulator its an interpreter
and to interpret a language it would have to support its syntax
afaik goto isn't supported cause it's 5.1 lua?
indeed
would there be a big gain if kahlua was updated to current Lua?
Seems like the latest version is faster from what I've read. Also, goto statements would look better to me personally than this weird repeat until true shit we've got going on.
idk if any more syntax beyond gotos has been added tbh
I'm curious, what's goto do?
Interesting
(You can mark like 30 lines down and skip code)
any performance gains would be in how the interpreter is coded & compiled. its likely not going to make a difference in kahlua
are you placing tiles on top of corpse, hiding it? object order matters.
That tile is the floor tile
ok, but the square has also a corpse below that tile?
No, it's all floor tiles
dunno, you could check if those tiles return isFloor as true.
I'm not gonna get into them but there are lots of good reasons that almost no modern languages support goto , haha . Lua really just needed a continue keyword tbh, I'm thankful the repeat until true thing works so well
the inclusion of a goto but not a continue boggles the mind
anyone know if there's a way to open a text file from in game?
looking to add a open log button too
@weak sierra I was trying to fix the borders and, it works, just... backwards lol
hmm void
rico said "kaboom"
There is a showFolderInDesktop but I'm not sure if I can call cahedir off of it

os.execute is exposed?
ah
only this os.date os.difftime os.time
I hate that we can't just access the cacheDir directly...
idk why you got that, but mine have this
private ZomboidFileSystem() {
this.loadList = new ArrayList<String>();
this.modIdToDir = new HashMap<String, String>();
this.modDirToMod = new HashMap<String, ChooseGameInfo.Mod>();
this.ActiveFileMap = new HashMap<String, String>();
this.RelativeMap = new ConcurrentHashMap<String, String>();
this.IgnoreActiveFileMap = ThreadLocal.withInitial(() -> Boolean.FALSE);
this.CanonicalURIMap = new ConcurrentHashMap<String, URI>();
this.mods = new ArrayList<String>();
this.LoadedPacks = new HashSet<String>();
this.m_fileGuidTable = null;
this.m_fileGuidTableWatcherActive = false;
this.m_modFileWatcher = new PredicatedFileWatcher(this::isModFile, this::onModFileChanged);
this.m_watchedModFolders = new HashSet<String>();
this.m_modsChangedTime = 0L;
}
yep
I recommend Procyon, very good https://github.com/mstrobel/procyon
I use the pz libraries thing for the lua auto complete
weird
function: openLogsInExplorer -- file: errorMagnifier_Main.lua line # 153 | MOD: errorMagnifier function: onMouseUp -- file: ISButton.lua line # 56 | Vanilla java.lang.RuntimeException: Object tried to call nil in openLogsInExplorer at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:82) at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:973) at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:163) at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1980) at se.krka.kahlua.vm.KahluaThread.pcallBoolean(KahluaThread.java:1924) at se.krka.kahlua.integration.LuaCaller.protectedCallBoolean(LuaCaller.java:104) at zombie.ui.UIElement.onMouseUp(UIElement.java:1228) at zombie.ui.UIManager.update(UIManager.java:816) at zombie.GameWindow.logic(GameWindow.java:262) at zombie.core.profiling.AbstractPerformanceProfileProbe.invokeAndMeasure(AbstractPerformanceProfileProbe.java:71) at zombie.GameWindow.frameStep(GameWindow.java:765) at zombie.GameWindow.run_ez(GameWindow.java:681) at zombie.GameWindow.mainThread(GameWindow.java:495) at java.base/java.lang.Thread.run(Unknown Source)
ironic I'm using my mod on itself, also included `` when you click on the clipboard for the sake of pasting
that purple indicates it's a global - but not defined in the lua exposure - as that'd be red
not sure why as I've used it before and it looks exposed
ah I used the luafilwriter before
this isn't exposed I don't think
so this is gonna be a crazy idea and im purely here to ask if anyone would like to work on it. but a working windows computer like when you click "use pc" it pulls up a ui that is skinned as a old computer and you can actually click the applications and stuff, this system goes way deeper into a bigger system so if you'd like a gun project let me know i have a few other amazing modders working on stuff.
id pay ofc, i have another idea as well if that isn't youre cup of tea but a simple way to play people in games. like play pool with "you're friend" but it simply just displays over the head whats happening
So, does anyone know if it is possible to make an item tint-able like clothing?
@sour island Just doing a quick look through, I saw you bringing up item tints as well- did you have any luck on that?
hm?
like, making an item tintable, other than clothing
Saw you asking about it awhile ago, and I am trying to figure something similar out myself
not sure but should be doable
I made prefabbed icons
I personally don't like colored overlays
Gotcha, my issue is that I am trying to have multiple color options for an item- Basically *?* and *!* indicators that will work like a piece of paper for server admins to write stuff on for players to notice in RP and what not.
I just feel like making 20+ new, unique items for the sake of color variation seems like the worst way to do it. I just cant figure out a different way
The way I do it in namedLiterature is using modData and catching the item on interactions
set's a temp icon
the game doesnt save icons normally
this would give you variations on icons without having multiple scripted objects
which I think you have to do anyway if you use TINTS and want consistent colors
but is there a way to change the world model too? Because the goal would be for them to be placed on the ground as well as in inventories
not at the moment
Or- Not the model, but the texture used
worldmodel is loaded right from script - I asked for that to be changed a while ago
you could use lua to generate multiple models off 1
but they can't be set
I dont know if you can change texture
Damn... Because right now, I have world models, and 9 clear color variations. But that means 18 different, identical, items, the only difference being their color
Which is rough
I agree
๐ฎ local cacheDir = Core.getMyDocumentFolder()
ayy there's something useful
is map to map (server to another server) so traveling between lousiville and westpoint via them on different servers possible on pz.
keeping persistence with characters, and vehicles.
Hi, is there a way to hide cloth patching on costumes but without using the invisible patching mod?
I am looking for a way to hide cloth patching but only on my costume mod
What would be the point? The servers run the world fine
And in a way they already do p2p
so. haha i actually run a big pz server, and i want to make it where we can run multiple cities at once for my server idea to work ie. 100 players in each instance.
so i can split the pz map up in regions, and have a server dedicated to each region.
How many concurrent players do you have?
i know this sounds stupid probably to like a normal pz player.... and i 100% understand but its just what im creating and it would help me as i develop my server in the long run. simply just my crazy ideas but if instancing between towns and having multiple servers running at once
The way MP networking runs it is kind of instanced
so we are in wip stages, but over 500 members. and alot are waiting for the server to be more developed
players nearby are basically p2p
sometimes 30 people
far enough away and it's basically SP
but id like to instance each town.
you want a server per town?
to make the map smaller than it is and have players go to other server's towns?
yes, so if you'd like i can invite you to the server and you can talk with one of my main devs he says pz needs something
im sorry i just pay him hes the brains and albion and glytch i pay them and they some how make stuff possible for the server.
he said "Essentially what Foxhole does but for Project Zomboid"
but yes this
not really feasible. for any kind of transfering between servers, you'd have to move data from one database to the other with some backend scripts, since the databases are sqlite, its probably not going to react too friendly having data written to it while the server is also running
yes he said we needs a different sq and pz is on sqlite
The only bottleneck to the server is the server syncing a large amount of people
I'd wager you could have a very large number with no issues until they started getting closer
and that would mostly be down to p2p ping
well, see i wouldn't need to instance if pz would allow me to do 1000 players but they barely support 200 well not even really.
if it was running mysql or another database it 'could' be possible
i would totally pay for a system that could run 1000 players... if pz would also make it possible.
is there a player cap?
what issues did you see with 200 players on similar ping?
actually not many desync issues around 100 players.
the server is actually running on a better server now then it was previously.
so i may have less, but i think pz has a limit of 200 players unless it can be overwritten??
think i may just have to inform the game devs that allowing instancing, not sure how hard it is considering its lua and gmod allows for it. i can imagine its not super hard/
the fact that they both use lua as a scripting language doesnt make any difference. its mostly the java that would need changing, as well as the database code. its not going to be a small scale change
sorry im not big on that stuff haha. figured though its always way more then what i think. LOL
The in-game limit on maxplayers seems to be 100 but you can call on 'setMaxPlayers' in lua, could probably set it to 1000 to see what breaks
I don't think server-to-server will ever be a thing - very little payoff
i'd be the only person to use it so i understand. but still hopefully we see it one day because it would be awesome! for me at least. and im sure my server would love it, because it would allow us to have more people and operate freely.
I'd suggest looking into lifting the cap first and seeing what breaks
you could also get creative with spawn points being on a cooldown to avoid too many players there - with additional points to spread players out
so its like a gta5 rp type server haha, so theres no zombies or zombie lore. so its simply just Kentucky sim LOL. but for real its literally like the sims. so i want players all in one area i don't mind that.
but i want every town to be able to operate freely. without having issues, having 50-100 people in each city i fear will destroy the server. but there is a hard cap at 100 it wont let me go above it, how ever back in my early days of doing this i used nitrado and i was able to push 200 players. and it was capped on nitrado at that soooo i know its possible to push 200 players.
just not sure myself how they did it but im sure its possible to maybe go past 200? maybe nitrado bottle necked it at that and i can remove that cap since i host the server now. or well my server manager does
I was able to get the cacheDir from root but I can't get i to open using showFolderInDesktop - found a use here in vanilla lua
function ConfigPanel:onBrowseFiles(button)
local selected = LoadGameScreen.instance.listbox.items[LoadGameScreen.instance.listbox.selected]
local folder = getAbsoluteSaveFolderName(selected.text)
showFolderInDesktop(folder)
end
Hard to see what's not working
function errorMagnifier.openLogsInExplorer()
local cacheDir = Core.getMyDocumentFolder()
print("dir:"..cacheDir)
showFolderInDesktop(cacheDir)
end
my server manager is coming me personally i have no idea what i'm looking at.
this isn't related to your request
OH haha
looks like 'isDesktopOpenSupported' is flagged as false
hmm
no clue how to get that as true
last time i looked at code related with player caps the game was hard capped at 200
the server logic itself only handles up to 200 connections
could you have 800 players with splitscreen then? ๐จ
ughhhhhhh good question
are splitscreen players handled through the same connection?
if so then yes
yes
thanks i hate it
?
servers can disable co-op now
- Added AllowCoop server option to allow or disallow splitscreen clients.
Hey everyone. What is the best way to loop through all the squares around a player? Obviously, I need to get the current cell with getPlayer():getCell(), and the current square with getPlayer():getSquare(), then I can get the X, Y, Z of the square and using some for loops. But my question is how to handle if the range of the search space crosses a cell. I guess I am unsure how I can traverse cells safely.
how large of a range are you aiming for?
Only 20 tiles from the player
if thats the case, i will buy a warehouse dedicated to my rp server and force everyone into a desk at pcs and make them play in the warehouse together like some fucked up horror movie metaverse type shit
Probably this can help you
---Returns a table of IsoGridSquare around of initial square.
---@param p1 IsoGridSquare
---@param p2 number
---@return table
self.getSquareAround = function(p1, p2)
local t = {};
local x = p1:getX();
local y = p1:getY();
for x = x - p2, x + p2 do
for y = y - p2, y + p2 do
local square = getCell():getGridSquare(x, y, p1:getZ());
if square then
table.insert(t, square);
end
end
end
return t;
end
Oh, so I don't really need to worry that a gridSquare could be technically in a different cell?
dunno, I never checked that
yeah does anyone know why this works? because it does, every mod uses stuff like this
maybe getCell() is actually some dynamic area around the player or something? or IsoCell:getGridSquare() is happy to just get a square from another cell?
Sounds like getGridSquare() is smart enough to know to reference another cell
Well thanks y'all, appreciate the help. Hope to publish my first mod soon ๐
even the vanilla code does this. I wouldn't assume it actually works until I try something across a cell boundary though, this could easily be an edge case nobody checks and doesn't work

