#mod_development
1 messages ยท Page 32 of 1
yea. You might have already added it to your utilities functions though. I think I mentioned it to you before
.
yee I should definitely save it for future use
ArendemethUtils.printR if you have that
https://pastebin.com/rTxAnu1b Here's my output when used on a cardboard box item
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
LOG : General , 1665273317300> [setName] => function 0x766473375
It apparently has a setName function, so not sure why wouldn't it work
what is the "correct" way to make part of the map load
getOrCreateGridSquare enough?
Are the two objects the same type? ```lua
print(tostring(objectThatWorks:getClass()))
print(tostring(objectThatDoesnt:getClass()))
LOG : General , 1665273629998> class zombie.inventory.types.ComboItem
LOG : General , 1665273639307> PRINTING CLASS
LOG : General , 1665273639307> class zombie.inventory.types.Moveable
LOG : General , 1665273649082> PRINTING CLASS
LOG : General , 1665273649083> class zombie.inventory.types.ComboItem
LOG : General , 1665273654990> PRINTING CLASS
LOG : General , 1665273654991> class zombie.inventory.types.Clothing```
LOG : General , 1665273639307> PRINTING CLASS LOG : General , 1665273639307> class zombie.inventory.types.Moveable
This is the object that doesn't work
.Moveable
rest are working
Maybe check that type's implementation of setName and whatever method prints the name
and compare it to ones that do work
i tried to simply print its name
using getName
it does print it fine
Can it be an overall code limitation? Simply trying to change the name in debug mode using the vanilla "Edit Item" button doesn't work either
I'm not convinced of that yet. I'd want to figure out how the object names are created, where/when they added to the UI, from which java method the names come for the types that work and don't work. From understanding that, you could surmise if there is some limitation that makes modifying the name difficult/impossible
would've been easier if I had known of any vanilla feature that somehow changes such items names as you go, but can't think of one lol
imma try searching through the vanilla files tho
hmm
local option = subMenu:addOption(Translator.getMoveableDisplayName(v.moveProps.name), _data, self.disassemble, v );
that looks like something
Ah, you could check the type and use that for Moveables
vanilla pz gives something is isinstance() to compare java types I think
I am not sure I am using the function quite correctly in the first place
print(getMoveableDisplayName(item:getName()))
print(getMoveableDisplayName(item))```
Neither of those work
print(item:getMovableFullName()) works
now to set it..
SetMovableFullName doesn't work ofc, why would it ๐คฆโโ๏ธ
There is setCustomName and getCustomNameFull in this, I see. Wonder if those are any use here
when it's in the mood to work
i've had to tostring and do string comparisons a few times due to it just failing
:p
Are you looking for a way to print the names and modify them? Or set them so that they are printed by other vanilla code later on? Or considering both?
gonna try them
I am just looking for a way to change the item name in-game
there's tons of mods that do that
for a container tho? i think uh
what was it called..
there's a mod that does it but i can't recall the name
organized storage or soemthing?
it didn't retain data properly tho, so after a relog on mp it's gone
He's looking for a way to change moveables (things like table pieces when you pick them up). Their names aren't modified by the methods he's using atm
wat? I don't recall finding any mod that does that at all
mm
maybe im confused
i found the mod that i thought did it, but i think i misunderstood the purpose of the mod when i was a noob
it just sets categories for containers
nvm
it's so irritating to have the mod being alive for a good while and believing its bug free due to how simple it is but no, it must always have some kind of a bug ๐คฆโโ๏ธ
aa its okay, appreciate it tho
i had a mod up for over a month with a couple thousand subscribers before someone told me an entire feature didn't work and spat out errors constantly
nothing is ever safe
closest u can get to safe is testing the shit out of it urself
and using it constantly
but yeah almost any piece of software always has something lurking
yeah, i can't remember if it was a last minute change causing it or what, but it was an optional feature that i didn't actually personally want, so i never caught it after release
oof I had something similar and I was like, "dude this mod had thousands and I am only getting to know about this "MAJOR" bug now
ye definitely
Doesn't look like setCustomName is the way to go either
I'd look at the implementation of Translator.getMoveableDisplayName() and how you might be able to set (if necessary) v.moveProps.name
Is it possible to display the list of items include in this category "zombie.inventory.types.DrainableComboItem" with a simple loop and a print?
@hollow current Hey, for admins, isn't there already a way to rename any item? I remember messing with that a long time ago in earlier pz builds. Is that not suitable to use here?
I will try it but I assume it works the same way as Vanilla Debug "Edit Item"
Oh, okay. Probably the same behavior, that. Didn't know you looked into that
local function getMoveableDisplayName(obj)
if not obj then return nil end
if not obj:getSprite() then return nil end
local props = obj:getSprite():getProperties()
if props:Is("CustomName") then
local name = props:Val("CustomName")
if props:Is("GroupName") then
name = props:Val("GroupName") .. " " .. name
end
return Translator.getMoveableDisplayName(name)
end
return nil
end
It's getting the name from the sprite properties
That's for ISWorldObjectContextMenu. Are you wanting to change it there? Or just in the inv context menu?
Something like that no ?
local items = getWorldObjects()
for i = 0, items:size() - 1 do
local item = items:get(i)
print(item:getName())
end
the part I hate most about coding... writing the same function multiple times to hook it up to someone else's code
actually @hearty dew you seem to know fancy ways to call things, is there any Lua/KahLua function to do something like callOnInstance(instance, methodname)?
The inv context menu, yk the objects that appear in your inventory
That's basically how the mod works
You mean in lua given a string containing the name of the function to call on an object, how do you call it on an object? Or talking about calling methods in java?
thin is, getting name using the usual function works anyways
The first option yeah. Most of the code in every one of these functions is the same, it's just the set new value line that's different.
it's the setName that has the issue
If in lua, lua local obj = blah local fn_name = "dothings" obj[fn_name]()
if you need to provide self (like obj:dothings() does magically), you would do ```lua
objfn_name
and can pass other args after it
obj[fn_name](obj, foo, var)
How to i install mods
So I could do either of these?
inventoryItem:setMaxRange(protoval);
inventoryItem["setMaxRange"](inventorItem, protoval);
right
bless
god that's gonna save me so much time, item prototypes have 330 some-odd parameters 
#mod_support for support with using mods
They should rename this channel #mod_development maybe. It is a bit confusing as it :p
heh
ya, comes up a lot
What's the implementation that does the rename atm? Basically calling setName()?
Yes, item:setName(button.parent.entry:getText());
And do you do anything to display the name? Or just rely on setting it atm (which doesn't work for Moveables)?
What do you mean with displaying the name? You mean actually having the name take effect after setting it?
Yea, in theory you could intercept and modify the functions that render lines in the inventory pane. Just wondering if you are doing that or not
is there anything special about functions like tonumber or can I assign those to variables just like any other function?
not really, the code just uses setName then refreshes backpacks
ISRenameEverything.onRenameItem = function(item, player)
local modal = ISTextBox:new(0, 0, 280, 180, getText("ContextMenu_label"), item:getName(), nil, ISRenameEverything.onRenameItemClick, player, getSpecificPlayer(player), item);
modal:initialise();
modal:addToUIManager();
end
function ISRenameEverything:onRenameItemClick(button, player, item)
if button.internal == "OK" then
if button.parent.entry:getText() and button.parent.entry:getText() ~= "" then
item:setName(button.parent.entry:getText());
local pdata = getPlayerData(player:getPlayerNum());
pdata.playerInventory:refreshBackpacks();
pdata.lootInventory:refreshBackpacks();
end
end
end```
Yall got some recomended beginner mods?
Don't think there is anything special about it besides it being set in _G to be used as a global since it is part of the lua standard library. But should be able to overwrite it just like any other global
I need to do the reverse of that. Storing the conversion function with each parameter
so sounds good
like ```lua
local fn = tostring
Yea, that's fine
sick
is there a mod that adds the option to lock/unlock windows
to help deal with zombies that can open doors/windows
not to the best of my knowledge, but you'll have better luck asking in #mod_support. This channel is for questions regarding development of mods ๐
oh gotcha my bad
Sorry if this is a dumb question, but is there any sort of documentation where I can find things such as everything you can do with getCore()? I've been scouring the internet all day and haven't found anything ๐
Core looks like its mostly just getting information about the game window
setting options too, although I'd be careful assuming that works outside SP
For the record, this ended up working, I just had to make sure it was called server-side
Is there such a thing as client side only mods in multiplayer for things like UI that don't affect gameplay or does the mod list have to match the server exactly?
as far as I know, part of logging into a server is syncing your lua/scripts with the server
Is anyone working on a storm api mod?
not me but I did recompile part of the game to fix a bug that was bothering me ๐ฉ
Do all the images I store in the root folder of my mod (the folder with workshop.txt) get added to the image slideshow on the mod page?
Is there a guide to styling the workshop page?
@signal frost No, I do not believe images put there will automatically be added to the slideshow. I just use the "Add/edit Images and Video" option on the Workshop page to add those.
Here's the Workshop style help: https://steamcommunity.com/comment/WorkshopItem/formattinghelp
Legend, thanks so much
Is there some property of IsoZombie that will let me know if a certain zombie created by the server is the same one that gets killed by the client? I had hoped getOnlineID would be the same between Server and Client but it appears the value is 'nil' when the zombie reaches the client's OnZombieDeath event, if it was ever even set on the client.
function ISInventoryPane:renderdetails(doDragged)
If I'm reading that mile long function correctly, it is using getName() for all items for the display in the inv pane
public String getName() {
if (this.isBroken()) {
return Translator.getText("IGUI_ItemNaming", (Object)this.brokenString, (Object)this.name);
}
if (this.isTaintedWater()) {
return Translator.getText("IGUI_ItemNameTaintedWater", (Object)this.name);
}
if (this.getRemoteControlID() != -1) {
return Translator.getText("IGUI_ItemNameControllerLinked", (Object)this.name);
}
if (this.getMechanicType() > 0) {
return Translator.getText("IGUI_ItemNameMechanicalType", (Object)this.name, (Object)Translator.getText(invokedynamic(makeConcatWithConstants:(I)Ljava/lang/String;, this.getMechanicType())));
}
return this.name;
}
public void setName(String substring) {
if (substring.length() > 256) {
substring = substring.substring(0, Math.min(substring.length(), 256));
}
this.name = substring;
}
That's zombie.inventory.InventoryItem.java
@Override
public String getName() {
if ("Moveable Object".equals(this.movableFullName)) {
return this.name;
}
if (this.movableFullName.equals(this.name)) {
return Translator.getMoveableDisplayName(this.customNameFull);
}
return invokedynamic(makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;, Translator.getMoveableDisplayName(this.movableFullName), this.customNameFull.substring(this.movableFullName.length()));
}
That's zombie.inventory.types.Moveable.java
so, why would it work with getName() but not setName()?
Did anyone ever see this happening?
When I equip my custom bag, the character walks like it's injured wtfffff
public Moveable(final String s, final String s2, final String s3, final String s4) {
super(s, s2, s3, s4);
this.worldSprite = "";
this.isLight = false;
this.lightUseBattery = false;
this.lightHasBattery = false;
this.lightBulbItem = "Base.LightBulb";
this.lightPower = 0.0f;
this.lightDelta = 2.5E-4f;
this.lightR = 1.0f;
this.lightG = 1.0f;
this.lightB = 1.0f;
this.isMultiGridAnchor = false;
this.customNameFull = "Moveable Object";
this.movableFullName = "Moveable Object";
this.canBeDroppedOnFloor = false;
this.hasReadWorldSprite = false;
this.customItem = null;
this.cat = ItemType.Moveable;
}
the ctor
public boolean ReadFromWorldSprite(final String s) {
...
String val = "Moveable Object";
if (properties.Is("CustomName")) {
if (properties.Is("GroupName")) {
val = invokedynamic(makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;, properties.Val("GroupName"), properties.Val("CustomName"));
}
else {
val = properties.Val("CustomName");
}
}
this.movableFullName = val;
this.name = val;
this.customNameFull = val;
...
}
a method that seems to set those 3 name fields based on sprite info
I don't have any idea why this would happen, I have no code that does this ๐ค
getname seems to be the best option, but I think item["name"] works just as well
setName() simply sets this.name. But for Moveables, getName() only uses the value of this.name when this.movableFullName is "Moveable Object" (in other words, there is no sprite name that it found.
but I might be jumping in and providing feedback on the wrong thing 
I bet if you set this.movableFullName via reflection (only works in debug mode, unfortunately) on the item when it is a Moveable the user is trying to rename, the renames would show up as expected
Apparently, for some odd reason, if you make a bag with 0 capacity and you wear it, it will make your character limp WTF LOL, This is such a weird thing
but wouldn't work outside of debug mode
Diff for reference
Those fields aren't easily modified (Could maybe do some shenanigans by calling ReadFromWorldSprite() to change the names..) and getName() uses those fields as the result in favor of this.name.. hmm.. I'm trying to think of a clean way to solve this
Nice feature. I think it may be exploited in a mod idea.
The Named literature mod solves a problem similar to yours by overwriting the entire ISInventoryPane:renderdetails() function, but that kind of sucks bc it breaks other mods that try to patch that function
For example, if you took that approach, your mod would be incompatible with Named Literature
It's tricky though because the call to getName() is in the middle of that massive function
Why overwriting if it's possible to inject?
You might be able to prefix patch the function and modify the item list so that later calls to getName return what you want
That seems like that best option I can think of
๐
I'm curious now ๐
You might also be able to modify getName in the metatable for Moveable types. I haven't looked into how kahlua creates and manages them. Idk if each object has its own table or if it is shared between instances and thus modifiable for all Moveable types
What do you need? To override the name of an item?
Yes. @hollow current has a mod where the user can edit an item's name via the inventory context menu. It calls setName on the item. It works, except for Moveable types because the Moveable does this for its getName implementation, instead of using the same field other InventoryItems use
do -- simple injection
local m = __classmetatables[zombie.inventory.types.Moveable.class].__index
local old_fn = m.getName
m.getName = function(self, ...)
-- check custom name here
if self:hasModData() and self:getModData().custom_name then
return self:getModData().custom_name
end
return old_fn(self, ...)
end
end```
what is this deep magic
Oh, cool. There ya go @hollow current . Looks like you can change it via the metatable :)
Wasn't sure if they were shared across class instances, but since they are, that should work
oh. this looks.. a bit beyond my understanding. What's a metatable?
thanks nonetheless tho
lua metatable stuff is still a bit impenetrable for me as well
Basically, you will use that to change the behavior of getName on the lua side to do what you want
metatables are just tables that describe how other tables work
@hearty dew Actually I wrote a kind of code auto generation for myself. That's why it's so fast and without testing)
this works because the java function is being called from the lua side, and you're tricking the lua userdata version of moveables to use your function instead of going back to the java, is that right?
how.. do I exactly use that code with an item object? and how do i use it to set names? I am kind of confused ngl ๐
Still calls the java side, but you can modify the result (patching it is the term often used)
This is Lua code. Put it in a lua file in the "client" folder
isn't it only called in the code presented if the if statement in there evaluates to false?
hey, does calling tostring() on a string add a period to the end or something?
Ofc you need to understand what it does, because it's only additional code to main code that does the main renaming job
You will set moddata on the object where you are calling setName currently. Then this patch from star will get the mod data and return it when getName is called
so I should put this within a function, then call that function when I use setName on a moveable object?
nevermind, it looks like the game's version of print() adds it
@astral dune Actually I'd implement the idea by another way.
In main renaming code something like this:
RENAMED_OBJECTS[item] = 'new_name'
And in injection code something like this:
if RENAMED_OBJECTS[self] then
return RENAMED_OBJECTS[self]
end
This should work on the client only and will be compatible with multilingual stuff.
The custom name in mod data will be transferred to the server and to any client that uses the item later. That's why it's not the best way.
You'd need to run that code after __classmetatables is set (which is probably setup before any mod code is loaded). Just create a new client lua file and put it in there outside of any function and see if that works
If successful, any subsequent calls to getName() will run that implementation of getName instead of the original
so, just literally copy paste the code into a lua file in client folder and leave everything else as is?
No, you still have to provide the custom name. By default the implementation calls the original function, i.e. does nothing. It's just a wrap function
if self:hasModData() and self:getModData().custom_name then
return self:getModData().custom_name```
That `getName` implementation checks whether there is `custom_name` mod data on the item. If so, it returns that instead of calling into java. You need to set the `custom_name` mod data instead of where you call `setName` now
You are putting the user-entered name into mod data, instead of setting/getting it in the java side, if that makes more sense
As I said, this is not the most optimized way, imo. But I guess at the first time it should just work, shouldn't it?
oo i see, that makes more sense now
I have never worked with mod data, how do I exactly set it?
:getModData() returns a table
will try it and come back if I face an issue
that's for global mod data, it's not exactly the same
oh
Btw, I search in all subscribed mods. No one injects like this (except my mods). This is very strange.... because it's very powerful.
instead of item:setName(button.parent.entry:getText());, we use item:getModData().custom_name = button.parent.entry:getText()
Anyone know how to programmatically add new outfits to the outfit lists? I know how to do it using XMLs that the game reads in, but I could use a way to do it in lua while the game is running.
okay wow that works
Thanks so much!
quick question though. So if I understand this correctly, if the mod is unloaded, the items will shift back to their names, right?
no, moddata is just a table
Yes, but custom_name property will remain in modded items
Does it need special implementation in MP?
probably not
Just realized I've spent a couple days attempting to attach an update function to the engine when it already has one that can easily be patched ๐คฆโโ๏ธ
i didn't realise you could do this, this could be a massive efficiency boost to one of my mods
I seee, so I guess the best course of action is to have normal items names changed using the native setName() function, and using moddata for moveable items
what are you thinking of doing with it, albion?
i have a mod that lets players spread the infection between each other by proximity
Yes, if you want your mod to be friendly with international (multilingual) servers. In this case you should switch from modData way to client side renaming, e.g. using a global table. See my posts and code example above.
i could replace the every minute checks for infection with just a hook onto the setInfected() function
interdasting
I see, thanks so much for the time. Would it be okay if you could reference me to the message? can't seem to find it
isn't this the mod that lets you rename items yourself? how could you possibly make that multilingual?
^ Good question, would like to see the global table example tho for any future need
Actually if you always override modData on client side, it should work anyway. It's just that your code will do unnecessary actions, drive more data between the client and the server, that's okay.
oh shit, arendameth is here
I can yell about a bug 
hey arendameth, in the current version renamable-in-vanilla items have two rename options in their right-click
for everything has a name
hours searching for a solution for a bug for Everything has a Name mod and someone already giving me a new bug to fix 
i guess it shouldn't be too complex

suffering from success
it was a mod I wanted for a while (and I think a lot of other people wanted too)
...any chance of getting it to work on containers?
like, crates and stuff
stationary objects? or the issue with moveable objects like cardboard boxes? If the latter, that issue was just fixed, in the process of polishing the code before updating
@sour island In the named literature mod, you could use an approach like this to patch the getName method on items to avoid overwriting the entire implementation of ISInventoryPane:renderdetails
Moveables, I suppose. Crates, cardboard boxes, shelves, etc
sounds like you already got it working so
bless you
there is already a mod to name them when they're placed in the world, and I believe the names are stored on the movables when picked up, although they're not displayed
if Arendameth was feeling cheeky, he could use the same moddata() key that the other mod is using for surprise compatibility
Having them displayed is what I want. Manage Containers technically lets you name them but it doesn't show anywhere except in the mod
wait what slow down
yes, but there is another
display names where?
I'd like them displayed in the name of the container, so like, here
where it currently says garbage
I was just saying there is another mod, called What Did You Put In Here that lets you name movable containers that are placed in the world, and I believe those names are retained on the movables when they're picked up so they have the same name when placed down again. Assuming that name is stored in the modData, you could potentially use the same key value so that when someone picks up a moveable named by that mod, it will show it in the inventory
also would the most optimal way to check if an item is moveable to check for classes? like so?
local item_class = tostring(item:getClass())
if item_class == "class zombie.inventory.types.Moveable" then
print("True")
end```
I will look at that
hmm that like a really solid idea, I will definitely give it a go
As for that, it involves some java reflection, so maybe not
oh sick I found this once and couldn't find it for ages, this works for my purposes fine
its been a lifesaver for me, especially when trying to sort all the Brita ammo, lol
actually, if you want to do this, I'd suggest instanceof(item, "classname") which returns a boolean
yup that definitely looks way more clean, ty
you could also do some cheeky thing like
if nil ~= item.getMoveableFullName then
end
which checks for the existence of the function and should be nil for everything but moveables
dunno which is more performant in the end
my assumption is that that field is populated during the transition to Lua and should be more performant
I think I should be using it like so:
function ISRenameEverything:onRenameItemClick(button, player, item)
if button.internal == "OK" then
if button.parent.entry:getText() and button.parent.entry:getText() ~= "" then
if instanceof(item, "Moveable") then
item:getModData().custom_name = button.parent.entry:getText()
else
item:setName(button.parent.entry:getText());
end
local pdata = getPlayerData(player:getPlayerNum());
pdata.playerInventory:refreshBackpacks();
pdata.lootInventory:refreshBackpacks();
end
end
end``` because I will also check for instances of certain items like maps to avoid double rename option
I assume the ... in this snippet are supposed to be replaced by the actual function signature, and not valid code?
Any idea what are all the objects that are renamable in vanilla?
hm
... stores any number of arguments
there's gotta be a flag for it
how would you read from them if you don't have names?
it's a table
is this the equivalent of using _ for when you don't need them
oh speaking of arendameth do you allow any rename length? I could swear I can use names longer than 28 now
Maps are definitely renameable in vanilla and have a MapItem class so there's that
not really the code doesn't have rename length limit
okay, good and bad news
good news: lua/client/ISUI/ISInventoryPaneContextMenu has all the rename flags
bad news: it's just doing comparisons to instanceofs
Is there an event to check the appearance of another player in multiplayer on client side? ๐ค๐ค๐ค
i have a function in one of my mods that passes on any arguments given to it, and it basically works like this
function whatever(functionToCall, ...)
local args = {...}
functionToCall(unpack(args))
end
good news again: looks like there's only two instances that allow renames
ah I see. I'll have to look more into unpack
unpack just returns all the values of a table
MapItem aaaand..
ISRenameEverything.createMenu = function(player, context, items)
local canBeRenamed = nil;
for i, v in ipairs(items) do
local item = v;
if not instanceof(v, "InventoryItem") then
item = v.items[1];
end
if not instanceof(item, "MapItem") then
canBeRenamed = item;
end
end
if canBeRenamed then
context:addOption(getText("ContextMenu_renameButton"), canBeRenamed, ISRenameEverything.onRenameItem, player);
end
end```
so it's: food, which has its own flag, maps, which has no flag but just does its own check, and those two lines which do some type checks
so it looks like you really just need to add the keys and keyrings then
sort of
food lets you rename it under really specific situations
some cooked meals and stuff i think
Well, neat. Thanks to what we all learned here today, I no longer have to overwrite the entire /server/vehicles/vehiclecommands.lua file

How to get nearest players in mp?
so if I'm following this right, addoption takes the text, the item to target with it, the function to call, and then 10 optional parameters?
If I wanted to have someone make my car in the game, how would I go about that? like commisioning a mod maker
No idea about 10 optional parameters, but yes
Yes
Sorry, missed that question in the convo
no worries
oki so, I am trying to avoid the double rename option for keys. Initially, I'd check for their class, but they use InventoryContainer, which isn't ideal because the same class applies for other items like fanny packs
what's the most optimum way to check for the type of an item after its class?
I can get the list of players AND vehicles using getCell():getObjectList(), also using getCell():getLuaObjectList(). But how to get the list of players only?
The java implementation of getName() we looked at earlier truncated after 256 characters iirc. Didn't notice anything else limiting the length of an item name
Isn't that a good thing? Fanny packs can be renamed by default.
I'm curious about this too. I need it for something I'm doing. The best option I've come across atm is to iterate over getOnlinePlayers (and hopefully compare distance to find closest). Not sure if there is something better atm, and haven't even tried it out yet
They can?
I could have sworn there was a getOnlinePlayers() function or something
it depends on the range you want, you can loop through nearby squares and check them for players or loop through all players and test for distance
Yeah, all equipable containers can be renamed to my knowledge.
which one is more efficient depends on your application
Oh yea that's definitely true
But how to check that the player object is valid? I guess the data shouldn't come to client if the player is too far.
regarding the java hooking discussion, are some classes just not exposed this way? ```lua
local zombiesZoneDefinition = __classmetatables[zombie.characters.ZombiesZoneDefinition.class].__index
another_player:getSquare() returns an object even if a mile from me.
Yea, there is an Expose class that exposes specific classes to kahlua
that sucks u_u some other related classes were exposed so i'll see if i can do what i wanted in them instead
This java method exposes the classes @bronze yoke
any idea what's the full class meta table name for world contains?
It's the java full name. Can look those up in the pz java doc or looking at ProjectZomboid/zombie
Or can use ArendamethUtils.printR(__classmetatables, 6) :p
soo, regarding that, I assume that'd be the correct way to do it?
do -- simple injection
local m = __classmetatables[zombie.inventory.types.Moveable.class].__index
local old_fn = m.getName
m.getName = function(self, ...)
-- check custom name here
if self:hasModData() then
if self:getModData().custom_name then
return self:getModData().custom_name
elseif self:getModData().wdypihName then --wdypihName is the value used by the other mod
return self:getModData().wdypihName
end
return old_fn(self, ...)
end
end```
What does the 6 refer to by the way?
That's a good question. I'm not sure. Perhaps the list of players returned is different on client and server side too ๐ค
the depth of recursion to stop at e.g. when you have tables inside tables inside tables inside tables .... 
oo gotcha, thanks!
That looks right assuming the other mod sets wdypihName on the moddata
You can store that moddata result in a local variable so you don't have to call into java 4 times btw
That sounds.. sensible
yes that could work, I would also check if it's already named by wdypih in your rename code as well, and maybe default to using it if it's found. That way you could allow the user to rename the containers in a way that wdypih could use as well. Its really up to you how compatible you want to make them
What are some really good/essential mods I should be using while playing? Either QOL or add content to keep from getting burned out
#mod_support is the channel you're looking for
will do, thanks!
Does anyone have a tool that will let you watch logs live? I'm using notepad++ which at least tells me when a log has updated and prompt me to refresh, but I'd like to just be able to watch the logs
If you have cygwin installed, can do tail -F Zomboid/console.txt
hmm, I may have installed it at one point, I'll have a look
oh @bronze yoke , I've found that part updates on vehicles keep happening if there is nobody inside on one of 2 conditions. Either A) you've left it running or B) it continues for a short period after you get out. I think it continues to update until the engine cools off but I'm not sure
small bug, when I rename a moveable object, then place it, and pick it up, it resets to its original name, any idea why'd that be?
The Moveable might only exist within the context of being in inventories?
i found that the update ran if you had the mechanics menu open
I imagine you'd need custom code to handle the placing/pickup of the movable to shuffle the moddata over to the tile and back
May have to save the moddata on both the moveable and the world object it is associated with (idk what it is offhand)
hmm, I'm not seeing that at the moment
aaah it can never be simple can it
your update function is on the engine, correct? it would make sense that that continues updating while the engine is still... updating
yes, true, and I'm only listening for engine updates, its possible other parts update when the mechanics window is open, but the engine doesn't
Well I guess this is a bug for another day to fix. I am burnt out for today lol. I really appreciate your help guys!
--client only
local function getNearestPlayers(me)
if me ~= getSpecificPlayer(0) then
return {}
end
local result = {}
local online = getOnlinePlayers()
local objects = getCell():getObjectList()
if online:size() < objects:size() then
for i=0,online:size()-1 do
local player = online:get(i)
if player:getCurrentSquare() and player ~= me then
table.insert(result, player)
end
end
else
for i=0,objects:size()-1 do
local obj = objects:get(i)
if instanceof(obj, 'IsoPlayer') and obj ~= me then
table.insert(result, obj)
end
end
end
return result
end```
Should work. ๐
Cool. Thanks :)
I'll need to adjust it to work server side. I need to find players near to a zombie :)
I'm editing the script someone made for making isometric. The script doesn't made for PZ, so the size is different. * means multiply, what's the 'divide by'?
It's lua
/
thank you!
on second thought, i'm getting updates from the engine being left on
i must've turned it off every time
so if you turn it off the updates on your custom parts stop?
not reliably; i am absolutely certain of my earlier observations, so i'm not really sure what happened there
the test method has changed but i doubt that's relevantโ earlier i was using a print in the function, now i am testing an alternative method so i've removed the update function, and the game is printing errors about that instead
currently my debug output is to make the driver of the vehicle say the debug messages aloud.... but I want to make them come out of the radio. Anyone know how to do that? lol
man, half of the radio methods have like 10-11 unnamed variables. I'll look at this tomorrow
maybe you can refer to the miniscoreboard
it has teleport to player
and that player can give you their locations
and u can use that maybe?
function ConnectToServer:OnConnected()
if not SystemDisabler.getAllowDebugConnections() and getDebug() and not isAdmin() and not isCoopHost() and
not SystemDisabler.getOverrideServerConnectDebugCheck() then
forceDisconnect()
return
end
self.connecting = false
self:setVisible(false)
local joypadData = JoypadState.getMainMenuJoypad()
if not checkSavePlayerExists() then
if MapSpawnSelect.instance:hasChoices() then
MapSpawnSelect.instance:fillList()
MapSpawnSelect.instance:setVisible(true, joypadData)
elseif WorldSelect.instance:hasChoices() then
WorldSelect.instance:fillList()
WorldSelect.instance:setVisible(true, joypadData)
else
MapSpawnSelect.instance:useDefaultSpawnRegion()
MainScreen.instance.charCreationProfession.previousScreen = nil
MainScreen.instance.charCreationProfession:setVisible(true, joypadData)
end
else
GameWindow.doRenderEvent(false)
forceChangeState(LoadingQueueState.new())
end
end
hi guys this is a vanila script about connecting players
is it possible that i inject a function here?
like
if myCustomBanList() then return end```
Looks like getNumActivePlayers() and getSpecificPlayer() are for multiple local players running on one client. Has anyone messed with the split screen mode or know how to set it up? Don't even see it as an option
You could patch that function ```lua
local og = ConnectToServer.OnConnected
function ConnectToServer:OnConnected()
-- do mod stuff here
return og(self)
end
Apparently, you have to have a controller plugged into before starting pz for split screen options to show up
it's drop in, you just press a button on the controller
What's a good way to save my keybindings for mods, because when I disable them to test stuff I lose them.
Can backup the key.ini file.
Can also start pz with a different config dir for when you are doing development stuff
You can have 4 players per udp connection. That must be for 4 players on local split screen joining a remote server
Is there a lua console on a dedicated server? Or do you have to build your own?
I made my own
Client command goes to the server, then it's executed. lua DebugLua = function(player, args) local s, filename = args.param if not s then filename = 'dofile.lua' elseif s:find("%.lua$") then filename = s end if filename then local file = getFileReader(filename, false); local line; local arr = {} while true do line = file:readLine(); if line == nil then file:close(); break; end table.insert(arr, line) end s = table.concat(arr,'\n') end if s then local fn, error = loadstring(s) if fn then fn() else print('SYNTAX ERROR!\n' .. tostring(error)) end end end,
Thanks
{
DisplayCategory = FunTime,
Type = Normal,
DisplayName = Dirty Homemade Pocket Pal,
Icon = PocketPalDirty,
StaticModel = PocketPalDirty,
WorldStaticModel = PocketPalDirty,
Weight = 0.5,
}
item PocketPalUsed
{
DisplayCategory = FunTime,
Type = Normal,
DisplayName = Sticky Homemade Pocket Pal,
Icon = PocketPalUsed,
StaticModel = PocketPalUsed,
WorldStaticModel = PocketPalUsed,
Weight = 0.5,
Wet = TRUE,
WetCooldown = 30000,
ItemWhenDry = PocketPalDirty,
}
Can anyone tell me why when my used pocket pal drys out it disappears and doesn't turn into a PocketPalDirty? what am i doing wrong here?
this pops up in the console after it disappears
it used to work just fine, idk if a recent update made it so it doesn't work correctly anymore
Hey folks..
Is there some way to reload recipes, while running the game in debug mode?
Does reload lua also do recipes?
f11 you can search up the specific lua in the bottom right part
It's not lua though, it's a recipe script
i don;t believe it reloads your .txts, you have to restart for that to work
Not that I've come across, no
Okay, thanks, I'll keep up with the restarting.
Is there some quick/easy reference for the internal name for sounds to use in crafting recipes, or is it just the filename in the sounds folder?
This turned out to be exactly what I needed to do. I figured it out by looking at PDFTZ (which I already run). Thanks for offering best idea you had.
are all mods broken right now because of the new build?
no
I'm trying to implement a category reassignment via ItemTweaker on a number of items which have already been assigned categories in Better Sorting, for example; for some reason, just having an ItemTweaker call to assign a new category to these itemID later in the mod load order doesn't seem to do the trick, as though ItemTweak's going 'This was already given a new category, so I'm skipping it.' It's chiefly to try to update things from 'Junk' that are usable as Crafting, etc. Is there a good way to go about this without the risk of overriding game-relevant item tweaks? (e.g. I don't want to have it drop any mechanical adjustments other mods may have applied, I'm just trying to ensure things get a more up-to-date accurate categorization.)
That shouldn't cause a problem. You can look at the output of the items being tweaked to see what it is actually doing. Are you setting the tweak values prior to OnGameBoot?
I'm just running lines of TweakItem("ItemID","DisplayCategory","NewCat"); after require("ItemTweaker_Copy_CC") if it's a vanilla / base game item, and after a if getActivateDMods():contains(:modID") then if it's from a mod -- there's just a seemingly random subset of items which seem to ignore it for some reason.
Where's the best way to check the output, just console.txt?
Yea, console.txt
Could be something else overwriting your changes?
You can check console.txt to verify your file is loaded after itemtweaker's file
Also, are those calls run when the file is loaded or called later inside a function?
Oh, if some are working and some aren't, I'd bet it is another mod overwriting your changes
I'm setting mine to the very bottom of the load order
If so, try changing your filename from myfile.lua to zz_myfile.lua and make sure it is in client/
load order doesn't help the order lua files are run
The lua file load order is shared/, client/ (unless it is a server), then server/. Within each of those sets, the files are loaded alphabetically
Dang, that's annoying
Try this
Still not sticking even as prefixed with zz in client
Other items in the same lua file inherit their categories correctly
Hmm, I'd search console.txt for the item your are having issues with
LOG : General , 1665328245102> Base.Rubberducky: DisplayCategory, Junk it is the nefarious tyrant, the Rubber Ducky
I'm trying to make it not junk
Hrm, could be a file in server/ is modifying it since it loads after client/ files
or in an event after lua files are loaded
If you have a method to, can search your mod directory for Rubberducky
Is it the only item that has not changed ? Maybe try to modify another attribute like Weight if it works ?
Is there a resource, or a list somewhere that has all the possible container ID's for the procedural distribution list options? (ie. I am modding a firearm pack, and want to spawn them in certain container types)
ProjectZomboid/media/lua/server/Items/ProceduralDistributions.lua has all the vanilla ones
Mods can add their own. You'd have to check their source to see what they modify or add
@undone elbow ```lua
--[[
getNumActivePlayers:
- Singleplayer: number of local players in client (including all split screen players)
- Client: number of local players in client (including all split screen players)
- Server: 1, but getSpecificPlayer() calls always return nil on server
getOnlinePlayers:
- Singleplayer: nil
- Client: lists all players (including split screen players)
- Server: lists all players (including split screen players)
getConnectedPlayers: trash. only seems useful for working with scoreboard?
- Singleplayer: 0
- Client: only updates when a player manually open scoreboard, but lists all players then
- Server: 0
]]
getPlayers = function(predicate)
local result = {}
predicate = predicate or function(player)
return not player:isDead()
-- and player:getCurrentSquare() -- Will filter out players sufficiently far from client that their square isn't loaded
end
if not isClient() and not isServer() then
-- singleplayer
for i = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(i)
if player and predicate(player) then
table.insert(result, player)
end
end
else -- multiplayer
local onlinePlayers = getOnlinePlayers()
for i = 0, onlinePlayers:size() - 1 do
local player = onlinePlayers:get(i)
if player and predicate(player) then
table.insert(result, player)
end
end
end
return result
end
Seems to work well on singleplayer, client, or server
If I use OnKeyPressed, does that go off whenever any player on the server presses the key? Or only when player does it if it's in the Client folder?
only on the client
It might go off if any local split screen player presses a key, haven't tested that
Oh crap
One sec
On multiplayer, this hits all players, right?
for playerIndex = 0, getNumActivePlayers() - 1 do
-- stuff
end```
I have seen that recommended for MP usage
.
getNumActivePlayers() doesn't do what you probably expect in MP
I see. In MP, does it get the current player on the client?
/ all local players
If I am split?
Is it like a fake loop?
It gets the local players, yea
Okay sounds good, that's actually what I need it to be doing, wanted to be sure
Any ideas on this? It seems pretty straightforward but for some reason isn't workin...
local function deactivateDivineProtectionB(player)
if (player:isInvisible()) then
player:setInvisible(false)
end
end
local function dispelGraceB(key)
for playerIndex = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(playerIndex)
deactivateDivineProtectionB(player)
end
end
Events.OnKeyPressed.Add(dispelGraceB)```
Also, for anyone who happens to already know this key-press stuff well, I am extremely interested in doing a follow-up to this mod where I cause all on-screen windows to close using a single button-press... If anyone can help me solve that by pointing me at the right mods or files, โค๏ธ .
#mod_development message
anyone know a fix for this? it used to work before recent updates, now when my item dries it just disappears instead of changing to the thing i want it to be
Hi. Is it possible to control the volume of a sound emitted by โคต๏ธ ?
:getEmitter():playSound(soundFile)
Since it failed to load the asset, I would guess either a bad asset or a bad path, so if the format of assets hasn't changed, I would lean bad path and double check a path hasn't changed
But specifically I don't know
If neither, then maybe new anticheat limitations I don't know about...?
Y'all I think this might be working. Results preliminary, but just to validate, is it the case that some gameplay-oriented (non-map) mods (based on what they mod) need you to restart either the server or the game?
I think keypress modification needed to be in my mod at launch because it was totally failing and I just launched and I'm p sure it worked. Gotta die a few more times to be sure
Any way to catch a gamepad button event? OnKeyStartPressed is ignoring gamepad presses
id take a look at the gamepad UI stuff. you should be able to see how those are triggered, like for example the vehicle scroll wheel
https://steamcommunity.com/sharedfiles/filedetails/?id=2873391925 just released this ๐
Any idea what file that is? I'm looking around desperately for stuff about gamepad triggering UI events... Cannot find the right file.
just search the vanilla files for "gamepad" or "pad" and im sure youll find something
I'm seeing stuff like ISPanelJoypad.onJoypadDown(self, button, joypadData) in some places and self.mainPanel.onJoypadDown in others...
Is it possible each context has its own joypad listeners?
looks like it
ive never actually played with a gamepad so im not sure how different the UI is with them
Apparently a lot going on... but if I just have to find the right context, I will keep trying
I am going to experiment with a function I'm guessing at lol
local function onMainMenuB()
JoypadState.useJoypad()
end
Always annoyed me when I load the game with my controller on I have to press a button to get focus
This is 100% a real function JoypadState.useKeyboardMouse()
useJoypad is a guess
HMmmMMmmMMmmm... what do you think about the name of this? JoypadControllerData:onPressButtonNoFocus(button) @shadow geyser
does anything in game produce something like a smoke effect?
Asset path is usually for the models correct?
I only have icons for these items and they are all in the same folder, and the two other icons I'm using load fine, I can even spawn the one that disappears in admin but when the wetness gets to 0 it just up and vanishes
I'm not seeing one, but is there a mod to can cooked recipes, like can and preserve stews?
jar rather
Asset is just a generic word for a file of your game, so could be anything afaik
@hearty dew Ay, I tried your little trickery for adding a small adjustment to the rules of the reading function to catch gamepad input, and it worked!!! ....Kind of...
local function deactivateDivineProtectionB(player)
if (player:isInvisible()) then
player:setInvisible(false)
end
end
local function dispelGraceGamepadB()
for playerIndex = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(playerIndex)
player:Say("Ayyy!")
if player then
deactivateDivineProtectionB(player)
end
end
end
local onPressButtonB = JoypadControllerData.onPressButtonNoFocus
function JoypadControllerData:onPressButtonNoFocus(button)
dispelGraceGamepadB()
onPressButtonB(button)
end
When I do this, the game says "Ayyy" as expected, but the game throws an exception after that when it tries to run my duplicated version of the file... It gets stuck here:
I believe the error is actually referring to line above green highlight, where "self" does not exist and "joypad" is the "index" of self, so-to-speak
Question is: how can I take over or add to the joypad button detection event without causing it to start throwing weird exceptions where it no longer recognizes itself (har har)?
self is implicitly given to a function when it is called with :
it is defined that way so expects it, are you calling it with : or .
looks above
guessing the game is calling that not u
so self should not be nil
that said, throw some print statements in there and find out, or use the debug to poke thru the variables
Yes, the game calls that thing that needs "self" in the screenshot. So I need to figure out what the game uses to call "function JoypadControllerData:onPressButtonNoFocus(button)"?
onPressButtonB(self, button)
you're not passing self to the original function after your overwrite runs
remember that function JoypadControllerData:onPressButtonNoFocus(button) (with a colon) is the same as writing function JoypadControllerData.onPressButtonNoFocus(self, button)
Okay, great pro-tip, unfortunately, my problem didn't end there ๐ญ
But I am thinking maybe source of all the calls is onJoypadRenderTick
So I am starting there and trying to find a place to insert myself and add an action when it senses a pressed button
if (player:isInvisible()) then
player:setInvisible(false)
end
end
local function dispelGraceGamepadB()
for playerIndex = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(playerIndex)
player:Say("Ayyy!")
if player then
deactivateDivineProtectionB(player)
end
end
end
local onPressButtonB = JoypadControllerData.onPressButton
function JoypadControllerData:onPressButton(button)
dispelGraceGamepadB()
onPressButtonB(self, button)
end```
So I can create and write files using the getFileWriter() call, and I can read files using the getFileReader() method - but is there any way I can delete files after I am done with them?
How does one add extra functionality to an existing tile in the world? I had a crazy idea of hiding inside one of the big garbage cans
Sometimes my shared folder doesn't load in Solo when mod testing... anyone know exactly why?
The lua is not visible
What is the correct name to provide for a sound, when creating a recipe?
It doesn't seem to match exactly what the filename in the media/sounds folder is
is there a reason one might code like this..
local functionName do
local something = somethingElse
function functionName()
doStuff()
end
end
function SomeOtherFunction()
functionName()
end```
afaik do/end in this context just makes a new scope
but it has a name
and it's local
so is it actually an alternative way to define a function
or when i call functionName() is it just calling the inner one..?
why not just
local something = somethingElse
local function functionName()
doStuff()
end
function someOtherFunction()
functionName()
end```
ive got some code i inherited that im afraid to touch cuz i have no idea wtf they're doing with local functionName do wrapping
:p
Lua syntax can be baffling and surreal at times. Why do they need so many ways to define a function? smdh
is it even equivalent tho?
ive only coded in lua for a few months and only for pz
i guess i can putz around on rextester
no idea tbh
it appears to just act as a scope
and the "local" and name are pointless?
from quick testing
Any recommended mods?
lol I just made one that makes you talk shit when you're killing zeds
shrug
(Comes as a trait)
@vague quiver
According to https://projectzomboid.com/modding/zombie/characters/IsoPlayer.html, players have a public field described as public boolean bJoypadMovementActive. I tried accessing this field on my player object and it through weird indexing errors. I'm not sure if it's a cache bug or a bug in the API. Does anyone have a few minutes to run a test for me and see if they can get a true or false response on that field?
I'm glad there is so many lua resources online, because I have no idea how code like this works but it does ๐
function Object:new(o)
o = o or {}
setmetatable(o,self)
self.__index = self
return o
end
What I'm really not clear on, because for some reason every tutorial I look at that does this always passes in nil , is what you would actually pass in to this function otherwise
after some research earlier im guessing the only way to add a command that the rcon has access to is a java mod, yeah?
u dont strictly need to accept an arg there afaik
i have no idea what the index thing does or exactly what a metatable is
lol
i think a metatable is like.. what the thing itself uses to describe itself
both per name and per usage
but
not specifically
at a guess, it's for derived objects
haha, this function is what is typically used to create a traditional "Object", so you can have seperate instances of the same thing, I just don't know what you would pass into it if you wanted to
function DerivedObject:new(o)
o = o or {}
-- do some stuff to it
o = Object.new(self, o)
return o
end
are you saying the o input is only there for creating derivatives?
that makes sense.
it's a guess
it's a better guess than i had, which was "what if you want to provide a premade metatable though?"
which i guess is related, but less purposeful
lol
I'm wondering, if I create an object like this and assign it to something as ModData, then later come back and load said moddata, if I would need to pass the moddata in to recontextualize it as an "object"
you could assign the metadata table to the moddata
since moddata is a table
i know it isn't typed cuz it's lua but im not sure "any random thing u throw in there" will work
at least not for persistence
but to more directly answer, yes
well wait.. no
everything is a table..
lua is weird
u could probably just put the whole thing in
and if u did that then no
but again it would probably not persist just anything
it persists just strings and numbers iirc
it'd temporarily hold it until u relog or restart tho
(client-side)
I doubt the moddata persistence handles function objects, which it would need to to persist objects like this (tables containing function objects)
It could, technically, do it. You can do it in regular lua (not kahlua). It is conceivable it is possible from the java side of kahlua since you could have access to dumping the function objects in a way that can be serialized
So, the answer is idk. Haven't tested it ๐
@hearty dew Thanks. But my goal was to get nearest players in MP on client.
Also I was trying to find the most optimised way to do it (with less calculations).
That's why there is choice what to loop.
you could almost undoubtedly find a pure lua lua serializer
and then persist strings fine
but it wouldn't be just dumping the object in the moddata raw
plus u dont wanna eat the whole moddata object anyway
just use one row
:p
The lua functions to serialize a function don't exist in kahlua. That was an issue I was facing when writing a way to hash a function to fingerprint it a few days ago
dont look for them in kahlua
just make your own

here's a pile of different options
To find nearest players on the server is still an issue, because you still have to deal with getX(), getY or DistTo() to check whether it's near or not. Well, not an issue but it seems not optimised for me.
you could cache player position periodically
throttled
to minimize impact
and update it on OnPlayerMove
like every min or smth
less even
i run a check every 7 seconds on OnPlayerMove that is position dependent and have no real issues
to serialize functions, you'd need lua standard library functions (e.g. string.dump which kahlua doesn't implement). You'd rely on the lua std library to make your own, but the full std lib is missing in kahlua. That's what I'm getting at
yeah, i just mean "it should still be doable in some way"
:p
i realize kahlua is limited
Yea, I haven't worked through that portion just yet. That's next on my list ๐
OnPlayerMove and OnPlayerUpdate are too high-load in terms of optimization...
mm
u could javamod the server to expose players.db access and then use that 
lol
performance-wise the real answer is "Read players.db"
it costs very little to go "is condition false? no? ok." though
so throttling on an update like OnPlayerMove is not a big deal, though if you prefer you could do polling from a method like EveryMinute
or whatever it's called
and poll each player's position
or push it from the client to the server
and store it in a table
or global moddata
and then pull from there when necessary
either way what u wanna do is build ur own database
and then query that
what are you planning to do anyway
who r u talking to
star
the radar mod i run on my server (shows players on map pre-41.73 but also adds new functionality to it post) has a feature for only showing players within N tiles
zero is a decent coder, wonder how they went about that
hmm yeah
Anyone have a write up or explanations on how the coordinate system(s) work in pz? tiles, cells, chunks, regions, etc
I'm looking at the example for creating a traits mod here:
https://github.com/MrBounty/PZ-Mod---Doc/blob/main/How to make a custom trait.md
And the repo for the more traits mod here:
https://github.com/hypnotoadtrance/MoreTraits/blob/master/Contents/mods/More Traits/media/lua/shared/NPCs/MoreTraitsMainCreationMethods.lua
How come more traits mod has the require('NPCs/MainCreationMethods'); line and the trait example doesn't?
The code (presumably) uses some code from NPCs/MainCreationMethods. Assuming that, require ensures that that required file is loaded before running the code below it.
If it were the case that the mod's file loads before NPCs/MainCreationMethods and require were not there, that would cause an issue due to using variables that are not yet initialized during the loading of NPCs/MainCreationMethods.
It so happens that pz loads lua files thusly: lua files in shared/, then lua files in client/ (this is skipped for servers), then lua files in server/. Within each of those 3 sets, the vanilla files are loaded alphabetically based on the path name (if a mod file has the same path as a vanilla file, it loads that instead), then mod files are loaded alphabetically based on the path name.
One option is to rely on that behavior
Another option is to explicitly require the files that you need loaded before your code is run
thanks for the explanation, appreciate it
pretty sure the require('NPCs/MainCreationMethods') isn't actually needed. The reason why is because vanilla files, are all loaded before mod files. so the require statement in this case doesn't do anything. however it might be put there just for readability. anyone now reading it, knows that that file logically needs the maincreationmethods file to have been executed first, even if that line isn't technically needed to enforce that fact.
ah gotcha, was wondering cause i saw some trait mods didnt have it but still worked fine
anyone know what the forage definitions are for fruit, wild herb and packaged food?
im thinking packaged food is JunkFood, no idea what the other two are, but if I had to guess, maybe Fruits and WildHerbs?
also dont know what id firewood would fall under too
what dimensions should poster.png be?
256 x 256
ty
can you access all java classes from lua or only some?
nvm i found the exposed classes in zombie.Lua.LuaManager$Exposer
Is it able to write a mod to simply reduce all kinds of player damage?
Since mod weapons are too strong, finding a way to balance them, but modifying all stats of mod weapons is not practical
Can you die and read? ๐ค
Sure. Try driving, try reading, and hit a poll with crash damage on
10/10 Will do again
Lol you just did that?
no, just joking but I almost killed myself continuously crashing into trees in my McLaren like an hour ago haha
daily basis when you're way too focused and looking on the road but braindead
Apologies. It's like 6:30 here and I haven't slept yet. If I need a bit of help with a mod I'm working on then do I ask here or the mod_support channel?
ah gotcha
so ask here :)
Well I feel super silly and like something is going completely over my head here but. I watched a few videos and one of the guys uses notepad++ and it looks like he has intellisense working. However I have no idea how he is importing the java files into notepad++ so that the lua can access all those functions.
I did find a decent tutorial that requires IntelliJ and I'll do that if I need to. Just feels like I'm missing something here.
My guess is it is a plugin he has or created. Or perhaps he has opened some source files and notepad++ is using words from those files to fill auto-completion. I haven't messed with notepad++ that much, so I'm unsure
@hearty dew I figured it out!
(Joypad button press detection example, feel free to use everyone).
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! THIS **** RIGHT HERE
require ("JoyPadSetup")
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! THIS **** RIGHT HERE
local onPressButtonReplacementB = JoypadControllerData.onPressButton
function JoypadControllerData:onPressButton(button)
for playerIndex = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(playerIndex)
if player then
-- Do Stuff
end
end
onPressButtonReplacementB(self, button)
end
Testing notes: using onPressButton above "works", but causes two signals to be sent every button press. Using onPressButtonNoFocus will only get one signal. Obviously there are methods by which the double-signal from onPressButton could be ignored, but that could cause issues.
Quick question: Best (most resource efficient) way to wait 1-2 real-life minutes regardless of server time before triggering an event?
It's lua. That means you have to build your own everything, including basic systems functions 
Someone posted something that polls on OnTick.. trying to find it. Not super resource efficient, but being lua, you don't have access to OS timers, so not sure there's a much better solution tbh
@thick karma
Anyone know a mod where depression kills, like you shoot yourself or slit yo wrists?
Check in #mod_support
kk
Kahlua has coroutines implemented. Could do something similar where you run coroutines off OnTick. Hmm, wonder if that'd be useful
If necessary I might use OnRenderTick. Doc says to avoid OnTick, gonna respect it. https://pzwiki.net/wiki/Modding:Lua_Events/OnRenderTick
Was hoping not to do math lol also didn't wanna have to find the dang time speed variable I'll need to learn to interpret
@bronze yoke @ancient grail
so you just added a require and it worked?
Yep
It was using local variables from that file
Needed access to them, too
To prevent weird issues on taking over the function
So yeah soon I'll be releasing Meditation! Just gotta get the timer to be game-speed independent
Seems comparitively easy because I sorta know what to do there
Vaguely
Become invisible by sitting. For use going AFK offline without disconnecting from server. Plan to only allow it if a zombie has not recently seen you when you start. Already designed it to break if you take action after it activates.
i don't think that's how require works... i really don't get why this works but i'm glad it does anyway
Well I could be wrong about why it worked, but I tried it as a shot in the dark and the errors went away
i'm trying to make sense of this but i've decided to just accept that some things were not meant to be understood
Maybe you can run it both ways as a test, study the debug, and get more out of it than I did
Basically, I noticed cerain variables called in the function I mod were causing exceptions to be thrown from null errors, so I figured somehow variables were not visible that needed to be, so I tried that.
If you get to the bottom of it, please do share!
And for the same reason you should avoid OnRenderTick :)
I figured RenderTick was muuuuch slower
Wouldn't rendertick be like 60 times a sec or something nnormal?
They both seem to be fired each frame. OnTick just stops firing when the game is paused I think
Oh crap
and in game menus, I'm guessing by the code. Haven't tested that
but while in game, they fire at the same rate, each frame
OnRenderTick is each frame. OnTick is each frame while the game world isn't paused
ow wow this might come in handy . thnk you
OnTick also helpfully gives you a tick counter as an argument. OnRenderTick is less friendly
LOG : General , 1665419532157> ontick 1665419532157 10866
LOG : General , 1665419532164> onrendertick 1665419532164 nil
LOG : General , 1665419532174> ontick 1665419532174 10867
LOG : General , 1665419532182> onrendertick 1665419532182 nil
LOG : General , 1665419532190> ontick 1665419532190 10868
LOG : General , 1665419532197> onrendertick 1665419532197 nil
LOG : General , 1665419532207> ontick 1665419532207 10869
LOG : General , 1665419532214> onrendertick 1665419532214 nil
LOG : General , 1665419532224> ontick 1665419532224 10870
LOG : General , 1665419532232> onrendertick 1665419532232 nil
LOG : General , 1665419532240> ontick 1665419532240 10871
LOG : General , 1665419532247> onrendertick 1665419532247 nil
I see... Thanks for the info
LOG : General , 1665420143429> onrendertick 1665420143429 nil
LOG : General , 1665420143445> onrendertick 1665420143445 nil
LOG : General , 1665420143462> onrendertick 1665420143462 nil
LOG : General , 1665420143479> onrendertick 1665420143479 nil
LOG : General , 1665420143496> onrendertick 1665420143496 nil
LOG : General , 1665420143512> onrendertick 1665420143512 nil
LOG : General , 1665420143529> onrendertick 1665420143529 nil
LOG : General , 1665420143545> onrendertick 1665420143545 nil
LOG : General , 1665420143562> onrendertick 1665420143562 nil
LOG : General , 1665420143579> onrendertick 1665420143579 nil
LOG : General , 1665420143596> onrendertick 1665420143596 nil
and while game is paused
i wish the modding chat becomes a modding category with all the various topics and what not... it would be alot easier for us to categorize stuff and be able to quickly share what we know abt a certain part of modding
I actuslly don't think I will need to use OnTick at all. I don't need it to be that precise. Once a minute in game will be fine
If you need in-game minutes, there is an EveryMinute event (or spelled similarly)
I thought you mean irl minutes
But I want the activation to track time since last zombie spotted me.... Already have the function for that but needs converted to RT
I can trigger the event on in game minutes but I want a condition on event activation that is based on real time
Honestly it likely isn't a big issue doing a bit on each frame. At 60 fps, each frame is 16ms. Doubt you need anywhere near that much time
wait sorry what r u building again? @thick karma
i thought ur done with the walk read mod
@ancient grail
Sorry I can't remember I talked to you about this one my bad for pinging if not
No I don't. I need a boolean variable check on most updates. On some I would need to set a bool
Doesn't get much faster
However if I can avoid it and leave that time available for other modders with more important OnTick stuff, I will
only for zed? or players wont see you too?
Honestly I need to test that but I have no friends who play with me often lol but I imagine the setInvisible function only refers to Zeds seeing you
I do not disappear on my own screen so I assume that isn't how it works
I may also add God Mode to the state so players can't kill you
not sure really its weird on mo
if u set one of em the other one also changes
imean ghost and invi
Or maybe have two versions
i think it makes you invisible to non-admins
unsure exactly, who knows what the difference between invisible and ghost mode is lol
Then maybe I'll switch to setting whether zombies will attack player bool somewhere
but will it make u invi really have u done that part of the script where u can atleast togle invi using a non admin acc?
I am doing it in Solo r.n.
Multi may requure anti cheat disables
Not sure yet what will be needed
well u will have to rework it for mp if u plan the mod to be mp compatible
its alot diffrent
btw theres a mpd that lets u camo using blood . like n TWD
ya might want to check that out
I think the way I access player is already MP compatible according to various sources I've checked... Only thing I'm worried about is anticheat really
i guess but invi is admin power tho
Can i add a helmet item definition with BulletDefense ? Or is this not doing anything, since i can not find any mod with bullet protection for helmets?
Well if you are interested in testing with me I'll hyu when I do and you can see yourself! ๐คช
yes you can.
i spawned it once on a server event using debug console
so no mod needed for that
but yeah if it worked on debug would dfntly work as mod
interesting. birtas and any armor mod i tried and inspected, none of them has even 1 helmet with bullet protection
i guess i have to make my own helmets then ๐
local head = InventoryItemFactory.CreateItem("Base.Hat_CrashHelmetFULL");
local bag = InventoryItemFactory.CreateItem("AZ.Bag_RoadsideDuffel");
head:setName("SOS Ratrace Event Helmet");
head:setCondition(70);
head:setBiteDefense(100);
head:setScratchDefense(100);
head:setBulletDefense(50);
bag:getItemContainer():AddItem("Brit.Hat_Helmet_Headset");
bag:getItemContainer():AddItem(head);
getPlayer():setWornItem("Back", bag);
getPlayer():resetModel();```
this is what i used or maybe something similar not sure cuz its on a snippet file only
thank you, that is a good starting point.
Does anyone have the code for the wet towel? I can't find it
is there any way to determine if a zombie has been reused via modData? i can't find any value i can set so i can find out if this zombie has been reused against previous set modData. since there is no onZombieSpawn lua event i try manipulating the zombie inventory whenever i get a new zombie. onTick -> getCell() -> cell.getZombieList()
go to the steam folder then zomboid media look for script and lua most of the time thats all u ever need to look for references
what r u trying to build?
i'm the author of worse zombie loot condition https://steamcommunity.com/sharedfiles/filedetails/?id=2867084324 it worsens the condition of zombie clothing etc. onZombieHit and onZombieDeath but i try to find a way to worsen the condtion of these items on spawn or some other way. with my current solution i iterate through all zombies in a cell an worsen the conditions. problem is that i need to skip those zombies that already have been affected. problem is there is no way i know of to again worsen the condition of a zombie that has been reused and his inventory was reset
maybe there is an completely easier way on doing this but i just started studying the java code and available lua events
wow cool
maybe you can look at how it spawns in the first place and do something as it spawns or after
You might want to check the technique for replacing or adjusting functions from one of many mods that do this on workshop (e.g. my Mobile Reader) and try augmenting this function:
IsoZombie createZombie(float x, float y, float z, SurvivorDesc desc, int palette, IsoDirections dir)
Not 100% sure where you'll find it in the LUA but you don't necessarily need to see find a way to use it
You could just call its copy from a duplicate and add your own extra stuff, or even rewrite it if necessary
you can't rewrite java functions, i'm afraid
I generally find a corresponding LUA function for all this apparently java-styled doc when I use this resource
It may not exist but I haven't found something yet that didn't exist somewhere in a LUA
Not always class defs onv
Obv
But corresponding functions and events
god fucking damn i wanna use storm api so bad i don't wanna learn lua
but i don't understand how to set up a project with it ๐ญ
It takes 15 minutes to learn Lua.
But it'll take forever to learn PZ API.
Yeah LUA isn't a bad place to start if you're newer to coding. Also it doesn't require compiling so that's a huge plus when you're modding.
Which IDE do most people seem to use for modding?
notepad ๐
most use notepad++
or atleast most of mods i know.... i use vscode and notepad++
Are you guys able to get intellisense working with those? Well at least notepad++ haha.
not even sure what it does.. i think installed it but i dont feel the difference. does it show tips or posible autocomplete? ireally didnt notice
Yeah it does for the most part I think. It can be convenient so you don't have to switch screens to look up a function name or something along those lines.
try out intellij
that's what intellisense is copied from
it just helps you with functions and if it is good like in intellij it will fix your code for you
like if there is a better way to do a lil bit of code it will simplify it for you
Yeah that's what I've been trying to set up today but it keeps freezing. Just giving myself a break mentally before trying again XD
if you want a easy thing to try with intellij just try minecraft
there is a intellij plugin you can download that will set up a pre made empty mod for you
maybe its too cold there?kidding
for mc stuff
Haha
I'll give that a look, thanks!
VS Code ftw
Opens almost as fast as vanilla notepad, but not blinding
Notepad++ opens a little slower in my experience
- Install a mod from Steam Workshop. Record the Workshop ID.
- Open Zomboid install folder in explorer
- Search that folder for a subfolder that uses Workshop ID as its name.
- Examine the directory structure and files contained.
- Repeat steps 1-4.
?
why are you trying to tell me to look at lua mods
i don't wanna make lua mods
storm api is java
Sorry meant to be responding to this
Why are you so resistant to LUA? It's all the same...
why should i have to jump through hoops to access the same methods and functions
I mean is there a way to mod this game using Java?
storm api
That works for PZ?
I see now, I misunderstood you as replying to other people, thinking you didn't know how to set up a project in LUA... I thought Storm wasn't available or something and you were down about it... Now I see. Seems like a cool API.
yeah it's a cool api i just need to figure out how it works
and ye now you can see what i mean
i would rather not jump through extra hoops if i could
i REALLY just wish the devs would give us native java mod support
that would be super cool
Agreed!
Maybe someday but I think there's a good chance it'll be awhile with how much they have on the agenda
it's really not a difficult thing to implement
they also can't really use the excuse of not wanting us to see the code since we can already just decompile the game anyway
For the life of me I'm still having no luck with this -- whether changing filenames to prefix zz, re-checking modules and the lot. Some items just seem to refuse to inherit new information for ItemTweaker and it's driving me bonkers being stumped by it.
When you looked at the console logs, do you see your line with your changes in it?
In other words, is the tweaker api attempting to apply your change and failing? Or is it not even attemping?
Not even attempting, mine don't surface in the console for those items
But I've been successfully applying to several hundred items, many of which are from the same sources as the ones that won't budge; it's baffling.
You might check if you have some mods that are overwriting the API and causing issues. Better sorting does that. I have a mod to remove better sorting's implementation (but that's because it was causing the tweaks to be applied twice, not be not applied). But your situation might be different
If I were you, I'd try printing out the TweakItems nested table that contains the tweaks before and after your api call that seems to not have the intended effect
See what, if anything, changes
It should change. It should change the field that contains the category tweak from the previous value to your new value
Do you need something to print out tables?
In my case I'm trying to accomplish it with Better Sorting's copy of it (applying via ItemTweaker_Copy_CC); I'm not familiar how to print them out, admittedly.
GaistUtils = GaistUtils or {}
GaistUtils.InspectMetatables = GaistUtils.InspectMetatables or true
GaistUtils.InspectDefaultDepth = GaistUtils.InspectDefaultDepth or 3
GaistUtils.InspectTableIndentWidth = GaistUtils.InspectTableIndentWidth or 4
GaistUtils.inspect = function(t, depth)
if not depth then
depth = GaistUtils.InspectDefaultDepth
end
local table_cache = {}
local function inspect_impl(t, depth, indent, prefix)
local indentLead = prefix and "." or " "
prefix = prefix or ""
depth = depth - 1
local tableIndent = indentLead..string.rep(" ", GaistUtils.InspectTableIndentWidth - 1)
local prefixIndent = string.rep(" ", string.len(prefix))
if type(t) == "table" then
if table_cache[t] then
print(indent..prefix..tostring(t).." ** PRUNED. Cycle/duplicate detected **")
return
end
if depth < 0 then
print (indent..prefix..tostring(t).." ** PRUNED. Max depth reached **")
return
end
table_cache[t] = true
print(indent..prefix..tostring(t).." {")
for k, v in pairs(t) do
inspect_impl(v, depth, indent..prefixIndent..tableIndent, "["..tostring(k).."] => ")
end
local metatable = getmetatable(t)
if GaistUtils.InspectMetatables and metatable ~= nil then
inspect_impl(metatable, depth, indent..prefixIndent..tableIndent, "<METATABLE> => ")
end
print(indent..prefixIndent.."}")
elseif type(t) == "userdata" then
local metatable = getmetatable(t)
if not GaistUtils.InspectMetatables or metatable == nil then
print(indent..prefix.."("..type(t)..") "..tostring(t))
return
end
if depth < 0 then
print (indent..prefix.."("..type(t)..") "..tostring(t).." ** PRUNED. Max depth reached **")
return
end
print(indent..prefix.."("..type(t)..") "..tostring(t).." <")
inspect_impl(metatable, depth,
indent..prefixIndent..indentLead..string.rep(" ", string.len("("..type(t)..") ") - 1),
"<METATABLE> => ")
print(indent..prefixIndent..">")
elseif type(t) == "string" then
print(indent..prefix..'"'..t..'"')
else
print(indent..prefix..tostring(t))
end
end
inspect_impl(t, depth, " ")
print()
end
GaistUtils.inspect(TweakItemData)
print("calling TweakItem")
TweakItem("Base.Itemname", blah, blah)
GaistUtils.inspect(TweakItemData)
Would see if the field on the TweakItemData table changed or not
Very kind of you, thank you!
Neither is controller support for a user interface, but they haven't finished that yet either
Unfortunately when you have a stack of 2000 easy jobs to do, you suddenly, paradoxically, have an impossible job to do.
I think a bunch of people want a bunch of things from them and they are a small crew
I'm just glad they enabled LUA modding or some modding at all, because the community of free devs saves this game from being (A) boring (B) a victim of an opinionated and small group of people.
E.g., we cannot read and walk in vanilla because an opinionated small group of people agreed we can't
if* they add java modding
That is bad
it would open a huge community up
I hear you, but, tbh, I think LUA is more accessible to new programmers
I learned Java first and like Java and in fact tutor intro Java online
So I am not a hater
you really shouldn't be a new programmer trying to make mods ngl
I am relatively new to LUA
But LUA allows new programmers to avoid certain complexities that every Java programmer must understand
I actually could not disagree with you more
I think modding is the perfect way for kids to learn to program
It's much easier than designing a standalone app
i actually can't disagree with you more
Some of my youngest students learned to program in order to mod games
nowadays devs make it impossible to learn how to even start making a mod for their games
Well that's just a logical consequence of me establishing that distance. ๐
if you don't have at least some level of exp it is next to impossible to even start
If I could not disagree with you more, it follows that you also are at max disagreement from me, insofar as I'm right
So sort of we just agreed
if you're lucky you might have a small wiki page like pz
why are you trying to use logic in a discord talk bruh
that is so cringe
Most games, you're right. Games with poor modding doc are not the easiest things to mod, but nevertheless modding certain games can be highly educational. Keep in mind kids know how to use YouTube these days, and experienced devs make instructional vids that those kids watch
And they do learn things they're told, though not everything obv
But I don't know any adults who learn everything they're told either
We learn what we can when we're ready and it's important to us
not true at all, i have found with my exp with most games the mod* devs in it gate keep the shit out of the modding scene making it almost impossible to lean how to do anything at all
the only two i have found so far that have been open to helping with issues are mc and pz
Lol more logic on Discord would do the world good
But you're being dramatic. "Impossible" to learn to do "anything at all" is not objectively true language. It's hyperbole. Obviously kids can learn many fundamental skills, e.g., what's a class, what's a function, what's an object, what's an asset, what is the relationship between these ideas, etc.
Yes, there are limitations
Yes, making your own app can teach much more
Infinitely more
But saying that it teaches nothing to mod a game is wrong
If it's true for you, that's just because you have nothing left to learn from doing it
bro what
Keep in mind, kids spend years learning to make a's.
putting stuff in my mouth much???
when did i ever say you don't learn anything from making mods
Here
Your words were literally impossible and anything at all
Lol
Just... Reading what you're saying
Not trying to put words in your mouth
Sorry, almost* impossible, but still wrong.
Actually learning something from modding is easy for open-minded kids
your opinion
The opposite of almost impossible
exactly how i learned but it is because i started with the literal biggest modding com you can start with
I mean, yes, in my opinion a thing many 12-year-olds can do is not almost impossible
can i ask how old you are?
But we are each free to use the phrase "almost impossible" according to our own interpretation
ok so you just admitted everything you have been spouting for the past few messages has been nonsense, ok.
Old enough not to think it's almost impossible for a kid to learn from modding, and to be tired of kids asking how old I am?
ok so you're prob 15 max
good to know
you don't actually have any real world exp
๐
I have helped multiple people acquire Master's Degrees and others acquire well-paying jobs in programming, if you really want to know
But that's beside the point entirely
that's cool
Speaking from authority, age, etc. is not logically defending the accuracy of anything
i own a business that made over 2.5m in profit last year :)
but that''s beside the point entirely
Congratulations, as I said, "Speaking from authority, age, etc. is not logically defending the accuracy of anything."
That's not how science, logic, or facts work
Or causality for that matter
Causality doesn't care how much money you made last year any more than I do...
age can show you the emotional maturity of someone
and just how their are kids that are more mature then some adults
there are some adults who are more immature then some kids
And asking someone's age in the midst of a conversation about facts and psychology can show not only the emotional age of someone, but their intellectual ability, as well.
What is your point?
once again trying to use logic in a discord convo
you wear glasses don't you?
Once again, apparently you're not?
๐
no, i am not
i am waiting for my wife to finish dinner
Congratulations
while coding a small game
if there is nothing else you wanna say ill just leave it here peace gonna go work on this yk how to contact me โฎ๏ธ
that seems to have resolved, but if you're going to argue in the future just take it to DMs please ๐
Discover anything when printing them out?
How does player:getOnlineID() work? Is it unique and immutable?
When I was testing it (with only 2 clients, each with 2 split screen players, so 4 players total), the online id was unique and consistent across the server and the 2 client processes
I didn't test relogging to see if the id remained the same
I think the java server-side had an id->player association stored in a data structure.. I looked at it the other day, but memory is vague now though, I'm not positive now ๐ค
function printOnlinePlayerInfo()
for _,p in pairs(LUtils.getPlayers()) do
print(string.format("isServer=%s name=%s onlineid=%s",
tostring(isServer()),
tostring(p:getDisplayName()),
tostring(p:getOnlineID())))
end
end
LOG : General , 1665463671898> 876,781,845> isServer=false name=testnerd onlineid=0
LOG : General , 1665463671905> 876,781,852> isServer=false name=Player2 onlineid=1
LOG : General , 1665463671913> 876,781,860> isServer=false name=admin onlineid=4
LOG : General , 1665463671922> 876,781,868> isServer=false name=Player2g onlineid=5
LOG : General , 1665463680752> 876,790,703> isServer=true name=testnerd onlineid=0
LOG : General , 1665463680752> 876,790,703> isServer=true name=Player2 onlineid=1
LOG : General , 1665463680752> 876,790,703> isServer=true name=admin onlineid=4
LOG : General , 1665463680753> 876,790,704> isServer=true name=Player2g onlineid=5```
The way the server stores players is in blocks of 4 for each client (because each client can have 4 local split screen players). So making (perhaps a bad) assumption from those numbers, the server assigns 0-3 to one client (for each of its 4 possible players), 4-7 to the second client, etc
Don't think it's safe to really assume that in lua code though, but that makes sense with what I saw when looking through the server-side java code
Nothing that shed light on whatever the heck is going on. I just can't figure it out, it isn't a lua load order, a mod load order, an alphabetical thing or itemID thing. I'm stumped.
Did the field in the TweakItemData table change before and after calling TweakItem()?
If it didn't, I'd dig into what exactly is going wrong when calling the TweakItem() function.
If it did, I'd dig into what exactly is going wrong when the even handler function (ItemTweaker.tweakItems()) is called when the OnGameBoot event is raised.
You can stick some print statements in ItemTweaker_Copy_CC.lua to help debug this btw
to triangulate what the issue is
Trying to narrow down to even just one item to figure it as an example
{
DisplayCategory = Material,
Weight = 0.3,
Type = Normal,
DisplayName = Box of Rubber Bands,
Icon = RubbersBox,
WorldStaticModel = RubberBandsBox_Ground,
}```
From LeGourmetRevolution -> 'TrapItems.txt', module is Base, there is no other external ItemTweaker prompt to affect this item but mine. I req ItemTweaker_Copy_CC and getActivatedMods for 2719327441 which is accurate to Snake's mod, which includes LGR. I flag ```TweakItem("Base.RubberBandsBox","DisplayCategory","Crafting");``` but it winds up Material in-game. In this case I tried to call out Base.RubberBandsBox in the logging util and it threw a stack trace error on me instead.
but it winds up Material in-game.
Let's try to look at each step of what the tweak item api does to find where/what is going wrong.
Can you try printing the contents of TweakItemData before and after the call? What is the field for "Base.RubberBandsBox"'s "DisplayCategory" before and after your call of TweakItem?
The answer to that will inform the next step
Oh for pity's sake, I added a secondary 'or getActivatedMods' specifically for LGR and it seems to have budged -- I was sure that workshop ID was a valid check on that, but it seems in that instance it wants to go all or nothing on subordinate modules for getActivatedMods. Now I'm getting an IGUI_category missing translation style entry when it should be picking up on it, but progress
That's an easy whoops, ItemTweak w/ Better sorting's category defs wants Craft instead of Crafting
This feels very 'did you plug it in?' now
if getActivatedMods():contains("modid") then
-- stuff
end
fyi, you use the mod id (not workshop id) with this api, btw
I'd typically had both but had the mistaken assumption I could include workship ID as a catch-all
Now I need to puzzle out some missing / needed category additions for better better sorting coverage. At this point I've covered something like 1500 items across 50+ mods not previously supported by Better Sorting / patches thereof
Hey! i have a quick question, and i can't find an answer. If the Engine Loudness is 100, what means that in the game? If i drive backwards at max rpm, which distance to be heard is possible?
I also still need to puzzle out a more sane way of trying to dynamically capture and include like-items in recipes that can pop up across different mods -- like the dozen different variations of empty cans that appear to be the same at first glance to a player but have a kaleidoscope of which ones you can crush, recycle into scrap, recycle into aluminum, etc.
Did you resolve this issue? I'm a bit lost on your current situation. Seems like you resolved that and moved on to other things?
That's a bit of a harder problem. I was thinking a bit about that myself. I think a good user-focused solution would be to consolidate them into one item. That entails modifying all the mods' recipes to use that consolidated item and to adjust the loot tables to not include the superfluous items
And an unknown list of other things related to those added items the mods could potentially have added, specially handling of their versions in lua, for example
RubberDucky is one I am trying to fix next, but I puzzled out my problem with a good chunk of the items. I'd been running vanilla items off a getactivatedmod for BetterCC and they hadn't been working, I'm going to see if I can just run the tweak without a getactivated check
The main curveball on this is that in a lot of cases mods/modders have a bunch of variations so that they can have a variety of icons / world models
Okay. If you get the mod id correct, getActivatedMods():contains() should work okay (and in fact, what you do want to do because adding unnecessary items to that api makes loading quite slow)
For example, with the mods I have atm, it takes ItemTweaker.tweakItems() 20 seconds to run through everything and apply the tweaks OnGameBoot
(and because of the way BetterCC implemented their item tweaker api, they cause it to double to 40 seconds. BetterCC registers a duplicate event to OnGameBoot causing it to run twice)
For the sake of experiment I tried doing a test setup where I disabled BetterCC's redundancy on that and just ran everything through a normal single run but didn't find a load time difference with stopwatch comparisons
If you really want a headache there's actually at least two other renamed variations of ItemTweaker besides BetterCC's ItemTweaker_Copy_CC which -also- queue OnGameBoot
Yea, I looked into those too. BetterCC's is a problem because they renamed the file. The others that I have installed, didn't rename the file, so pz only loads one of those
If there are multiple lua files with the same path, pz will only load the one latest in the mod load order
01.ItemTweaker_Core.lua and ItemTweaker_Copy_ogsn.lua also exist among mods as renamed files which load OnGameBoot independently.
I went down a rabbit hole ferreting out rogue copies of itemtweaker
Mm, I don't believe I have those mods, but yea, that's something to watch out for, if you are concerned about the game boot time
At a point I made a dummied-out killswitch mod that just had the variations of itemtweaker's renamed lua commented out as an end of load order override
I solved the issue with my own mod that overwrites those duplicated item tweaker API files
Mm
But that is hardly ideal or something I'd want to sustain, I was curious to see the material difference in redundancy load time
For the record, EliazBetterBags & Backpacks is a pretty popular / commonly installed mod example that also has its own copy of ItemTweaker (01.ItemTweaker_Core.lua)
Fx Clothes Tweaks has that same renamed lua
The OGSN one is found in An Exhilaratingly Organized Literature Mod which is also pretty widely circulated
with like almost 300k subscribers
It's pain for everyone and annoying to me bc I can't just send a pull request to them to fix all those issues with how steam workshop is set up lol
OGSN's may be better or worse because it deviates from the normally just renamed itemtweaker cores in that it appends data instead of replaces it, so that it'll stack with other copies of itemtweaker mucking with items
I tried posting to a discussion thread about the issue in the BetterCC mod, but it probably won't be seen/read
I wound up making my patch compilations because BetterCC wasn't implementing pull requests anymore near as I could tell
Someone did the legwork for like 200 items for LeGourmentRevolution to append to BetterCC's built-in mod support and it sat there for a long time
That's a bad solution with how multiple mods interact in the context of how PZ loads mods and lua. Really, they should make their own API (just change the name to OGSN.TweakItem() and use their own table OGSN.TweakItemData, etc)
function ogsnItemTweaker.tweakItems() is what they use actually / OGSNTweakItem/ OGSNTweakItemData etc.
Ah, then their modifications are isolated from affecting other mods in some ways (the file load order is still an issue, but that is more manageable)
What you're working on sounds useful though. It's something I'd like to use. I had the idea of adjusting some item categories myself, but stopped after one or two items and got distracted with other things :p
Only by virtue of OCD and way too much focus have I been able to go through as much as I have but it has been a gigantic rabbit hole. It started with noting a handful of items that came from newer mods that weren't following the categories at first and then spiraled out to more and more branches of 'Oh, that mod also includes two magazines with recipes' or 'There's weapons not categorized in this mod.' Where I'm brushing into debatable territory is starting to broach new categories in the same spirit as the base BetterCC ones for things that a lot of newer mods have broached that could use them -- which is what wound up butting my head against trying to puzzle out why I can't override a category BetterCC did set on some things, having just re-confirmed that the damn rubber ducky refuses to budge still.
the other big one I am on the fence on is there are a lot of situations with things that are both a tool and a weapon -- which in some cases are just vanilla items that way, but then you have some mods that will make tools into weapons too, and then you've got some bigger newer mods with intentional tool-weapons and there's not reaaaaally a category solution for that, since you can't affix multiple categories to something. So you're left with picking one of the two, or making a new combined category, and then deciding which should go first and so on.
it's all proven to be enormously time consuming, but if it saves other people a headache or makes things feel more cohesive in the end, all the better
Yea, there's a lot of leg work involved, leg work that could be parallelized, like where you have multiple contributors sending pull requests. Unfortunately, it sounds like BetterCC isn't moving along in that direction anymore, or has slowed
I'm just the weird fool who spent the many many hours deciding I did in fact want to apply Media - Audio to 350 True Music tracks like some kind of putz
Pomp's items was another example since it advertises 50 food items but in reality it's actually 264 damned TweakItem entries haha
re: the ducky question, I'd
- verify via logs that only one call to setting the ducky category is occurring (the old ItemTweaker api prints them out. Idk what all the modified versions do, but you could add
prints to them for debugging purposes, if they don't have them) - verify that the
ItemTweakDatatable field is changed when you call the api - if
ItemTweakDatais changed, track down what might be changing it by adding a conditional toTweakIteme.g.
function TweakItem(itemName, itemProperty, propertyValue)
if itemName == "Base.Rubberduck" and itemProperty == "DisplayCategory" and propertyValue == "Junk" end
error("How dare you, sir")
end
if not TweakItemData[itemName] then
TweakItemData[itemName] = {};
end
TweakItemData[itemName][itemProperty] = propertyValue;
end
I think I may have misconstrued how to set up the second parameter set you sent me earlier which is how I wound up getting stack trace errors off it
speaking of which my continual quest to try to fix the stack trace errors of -other- mods feels fruitless
Which are you having trouble with? I've fixed all the ones I've encountered in the mods I use thus far
Well, except one. The author said he isn't going to fix it because it is harmless. -_- I need to get around to fixing that one yet
There's a trio of persisting ones I've tried to alert their respective modders to (for Rabbit Hash, KY, the SecretZ mod and Duck's Shark and Brita's Compatibility Patch) but beyond that I'm encountering them with context menu opening on fuel containers and that's likely a FuelAPI or some other
Oh, I haven't come across those yet (fuelAPI, rabbit hash) or don't have the mod (the rest)
that's off the cuff guessing re: the fuel one, I just noticed it recently popping up and need to go do more thorough testing and checking on the when or why
second parameter?
re:
print("calling TweakItem")
TweakItem("Base.Itemname", blah, blah)
GaistUtils.inspect(TweakItemData)```
Oh, I added a line the top that I initially forgot. Might be that
GaistUtils = GaistUtils or {}
of the other trio
ERROR: General , 1665463056995> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: attempted index of non-table at KahluaUtil.fail line:82.```
They're generally all non-table errors
I forgot to initialize GaistUtils
That needs to be before adding all the other stuff to the GaistUtils table
I will have to mess with it more tomorrow, but I am pretty curious which mods you run in general just for comparison
28dayslater
80kz1000
82oshkoshM911
85merc
86oshkoshP19A
88golfMk2
88jettaMk2
89def110
AAApoc
ATA_Bus
ATA_Jeep
ATA_Petyarbuilt
AliceSPack
AquatsarYachtClub
Arsenal(26)GunFighter
AuthenticAnimations
AwesomeTime
BBVehicles
BB_Throwables
BB_Utils
Barco Abandonado
BarricadedWorld
Basements
BatesMetalicosRevived
BedfordFalls
BetterFlashlights
BetterSortCC
Brita
Brita_2
Chestown
CleanDirt
ClothesBoxRedux
Computer
ComputerClassicsGamePack
ComputerCorporalsGamePack
CraftHelperContinued
CrashedCarsMod
CustomMapBridge
DD_Zombie
DLTS
DRAW_ON_MAP
Diederiks Tile Palooza
DylansTiles
EasyConfigChucked
EerieCountry
ExpandedHelicopterEvents
ExtraMapSymbols
ExtraMapSymbolsUI
FH
FRUsedCars
FRUsedCarsNLF
Factory
FencingKits
FuelAPI
FuelTanksMod
Grapeseed
HandmadeWeapons
ISA
ImprovisedBackpacks
ItemTweakerAPI
LeGourmetRevolution
LongLifeBulbs
LootZetaEnhancedEdition
MapLegendUI
MapSymbolSizeSlider
MilitaryComplex
MiniHealthPanel
MinimalDisplayBars
ModManager
MonkeysLib
MoreBuildsLite
MoreCLR_desc4mood
MoreDescriptionForTraits4166
NRK_NeedLightToRead
Named Literature
NightVisionChucked
OutTheWindow
P4HasBeenRead
PSurvival
PantryPacking
PertsPartyTiles
PlayersOnMap
ProximityInventory
PwSleepingbags
QNW_Ladder
QNW_QNWLibrary
RPropaneTank
RV_Interior
RabbitHashKY
RainWash
RebalancedCalorieBurning
Remastered Kitsune's Crossbow Mod
Riverside Gunstore
SCKCO
SCKCOAccessories
SLEO
SMUI
SYMS
ScrapArmor(new version)
ScrapGuns(new version)
ScrapWeapons(new version)
SearchModeAPI41
SimpleOverhaulTraitsAndOccupations
SimplePlayablePianos4150
SimpleReadWhileWalking41
SkillRecoveryJournal
SkillsMag
SnakeClothingMod
SnakeMansion
SnakeUtilsPack
SpnCloth
SpnHair
SwapIt
TKS
TMC_Trolley
TMC_TrueActions
TableSaw
TallerMecanico
TheStar
TheWorkshop(new version)
Trash and Corpses
TrippingZombies
TrueActionsDancing
TrueActionsDancingVHS
TrueActionsDancingVHS_MAG
TrueActionsPatch4173
TwinkiesVan
VehicleRecycling
Video_Game_Consoles
Visible Generators and Corpses
WDYPIH
WaterGoesBad
Worse Vehicle Condition
YakiHS
YakiMC
YakiMCSkill
YouDriveISleep
agrotsar
amclub
autotsartrailers
blkt_crosshair
coavinsfirearms
coavinssupport2
eris_nightvision_goggles
expandedhotwire
fastkeys41
fuelsideindicator
iMeds
improvedhairmenu
isoContainers
lakeivytownship
lgd_antibodies
lx_autotsartrailers
lx_autotsartrailers_plus
manageContainers
miscpatches
modoptions
moodle_quarters
morefastkeys
nattachments
noirrsling
nostartingbelts
nostartingbelts_addcraftablebelts
pass-out
radialmenuapi
ridiculouslyrareb4173orabove
sapphcooking
sapphcookingbettersorting
tailoringfix41
tkTiles_01
tsarslib
If anyone can help me out I'd appreciate it a lot. Trying to make a mod that simply invokes sendClientCommand() when the player uses (and destroys) a particular item. I looked at recipes but they just convert one set of items to another. Any existing mods I can look at as an example?
What do you mean specifically by use (and destroy) an item?
I want to be allow the player to convert cash money into Server Points. https://steamcommunity.com/sharedfiles/filedetails/?id=2823055977
I had a look at this mod, I just need to call sendClientCommand()
So I need a recipe to consume cash items, and send the command to add Server Points
So you might add a context menu entry when right-clicking the money in the inventory. Then in the callback for that context menu entry, do the sendClientCommand() and remove the item
Yeah that would work, but i'm a real novice at modding. Is there an existing mod that does something similar I could look at for a guide?
Oh, if you want to do it as a recipe, then you just add a function reference to the recipe. In the associated function you'd call sendClientCommand()
Probably easiest development wise to make a recipe
Ok
trying to find an example
recipe Build Spiked Baseball Bat
{
BaseballBat,
Nails=5,
keep [Recipe.GetItemTypes.Hammer],
Result:BaseballBatNails,
Sound:Hammering,
Time:150.0,
Category:Carpentry,
OnCreate:Recipe.OnCreate.SpikedBat,
}
Recipes have events, like this one has OnCreate. When that event happens (which should happen when it is created), the function Recipe.OnCreate.SpikedBat is called
Ok I can have a look at the vanilla code
so you might have in media/scripts/mymodid_recipes.txt: ```json
recipe Buy Server Points
{
CashItemName,
Time:100,
Category:IdkAtm,
OnCreate:MyMod.BuyServerPoints,
}
Then in `media/lua/client/mymodid_buyserverpoints.lua`:
```lua
MyMod = {}
function MyMod.BuyServerPoints(parameters)
-- Maybe some other stuff
sendClientCommand(argumentstofigureout)
end
that's kind of the gist of it
Yeah this gives me enough to make a start - much thanks for the help ๐
There wouldn't happen to be a dyed leather strips mod for tailoring, is there?
I see a texture replacer that makes the patches black leather.
when is a goodtime to use
tostring()
and
String.format()
?
Does anyone know
getPlayer():getPrimaryHandItem():getScriptItem():getSoundRadius()
and
getPlayer():getPrimaryHandItem():getSoundRadius()
difference?
the former will return the sound radius in the script, the latter will return the sound radius of that instance of the item
Anyone know what's necessary to get a non-admin account in a client with -debug enabled to join a dedicated server?
Found an undocumented server command, /dragons ๐ฎ
There definitely be dragons in that java code
no entirely sure but DoLuaChecksum option in server settings may do the trick? This is a total shot in the dark tho