#mod_development
1 messages · Page 29 of 1
You can already do that with doors
Put a rubbish bin behind a door and you can't open it, is that what you mean?
I can't access another player's inventory via client-side code, can I? I'll need to make a server request and get the server to ask the client, right?
You can run your server and games in nosteam mode and test it fast
So you can also use -debug and update the code or use the debug console to check stuff fast
But I have no idea if it's clientside when in multiplayer
Yeah I'm doing that at the moment, just wondering if anyone knew off the top of their head
Ahh okay 😄
I almost had to try that before, but things went a different route
I'm pretty sure each client doesn't know what the other ones have in their inventory
how can i get my own player/character obj?
imagine necromorphs in pz
Oh for fuck sake hahahaha
lua arrays start at 1
You have no idea how long that's taken me to debug
So, I was trying to get if an item is a medical item or not, and I did this
item:getScriptItem().Medical
In the java files, Medical is a boolean, but for some reason It's not accessible from the lua 😦
Does anyone know a way around this?
Do you mean the item's category, or are you saying there is a flag called medical that some items have?
Try this:
item:getScriptItem():getStringItemType()
If this item medical, then this return "Medical"
Sadly, it does not work with items like the Antibiotics, Because Base.Antibiotics is StringItemType = Food
I had to find a weak workaround by doing this
function MxAcceptItemFunction.MedicalOnly(container, item)
-- print(tostring(item:getScriptItem().Medical)) -- Apparently this does not work :-/
return item:getStringItemType() == "Medical" or item:getDisplayCategory() == "FirstAid"
end
This item have any medical word in script?
The antibiotics has the Medical = TRUE flag, and the display category to FirstAid
item Antibiotics
{
DisplayCategory = FirstAid,
Weight = 0.1,
Type = Food,
DisplayName = Antibiotics,
Icon = Antibiotics,
ReduceInfectionPower = 50,
CustomContextMenu = Take,
CantBeFrozen = TRUE,
Tooltip = Tooltip_Antibiotics,
Medical = TRUE,
WorldStaticModel = Antibiotics,
}
I'm not sure if I understood the question tho
Then you can't get medical from code :/
Only by some hack 😄
Well, it's not amazing, but thank you anyway
You can try get Medical value of Item Script Object by this:
-- For find index of variable
local v1 = item:getScriptItem()
local num = getNumClassFields(v1)
for i=0, num-1 do
print(getClassField(v1, i), " --", i)**
end
-- For get value
local field = getClassField(v1, YOURINDEX)
local medical = field:get(v1)
print(medical)
Truly interesting, I will try it ASAP
Also @tame mulch, do you know if createNewScriptItem works at all?
I was using it for my transmogV2 (https://github.com/mxswat/pz-Transmogv2) mod, but apparently it just does not work, which is truly sad since I handicaps my ability to generate script items at run time
I am not sure that this is possible
Okay, so can I assume that the media\lua\server\Items\ScriptItemInterface.lua file with createNewScriptItem and cloneItemType are there as legacy/obsolte code, right?
Maybe 🤷♂️
I not found usage this file in game or this func in any mod
I know that @calm depot Was using it in this mod: https://steamcommunity.com/sharedfiles/filedetails/?id=2759865696
But I wasn't able to get in touch with him since last month, and to me it seemes like createNewScriptItem is not working
Interesting mod 🙂
Yes, it really is.
I based my new transmog mod on his code, https://github.com/mxswat/pz-Transmogv2/blob/master/Contents/mods/Transmogv2/media/lua/shared/~Transmogv2.shared.lua
As you can see on line 92 (65 in the diff), I used to have createNewScriptItem https://github.com/mxswat/pz-Transmogv2/commit/3fa4ac408bd90afeac279a79aa4c6b6c9da0b5dc
But, since createNewScriptItem is not really working, I had to fall back in limiting this mod to
- generate items,
- reboot game
- and then you get the transmog item
If createNewScriptItem worked, I could skip the reboot game (and server) part
What exactly you want do by this mod?
This mode does the following;
- It generate a new file
TransmogItems.txt - Then it loops through all the
Type = Clothingthat the game has, for each item it does two things:
-
- generates a new Clothing item that has no stats or weight, this new item is what I call cosmetic item.
-
- it generates a recipe to convert the original item, into a cosmetic item
The result is in the screenshot, it basically allows for transmog in zomboid (but this time with MP sync compared to my old mod: https://steamcommunity.com/sharedfiles/filedetails/?id=2768901065&searchtext=transmog)
As you can see the player is wearing a cosmetic beret, but is also wearing a military helmet, the cosmetic beret was generated from the vanilla beret at runtime.
Let me know if I explained myself poorly
yeah the game works backwards from the clothingtem file i think for some reason
yep, thats why you can't use vanilla clothingItems for your own items unless you intend to replace them
I think the games does that just to troll us 👀
Does anybody know of mods that show off sending items from one player to another? I've tried a few different ways including appropriating the trading code and haven't had much luck as of yet
Is it possible to move the crafting context menu option under a submenu in the context menu? 🤔
I believe it should be able to if you overwrite this vanilla function in ISInventoryPaneContextMenu.lua
Line 2730: ISInventoryPaneContextMenu.addDynamicalContextMenu = function(selectedItem, context, recipeList, player, containerList)
Save off the vanilla function, use the original context to make a submenu, and then send that new submenu context down into the vanilla call instead of the one you started with.
Sounds like a good idea, thank you
i can reference a base function and override it like so:
local ISCraftingUI_populateRecipesList = ISCraftingUI.populateRecipesList
function ISCraftingUI:populateRecipesList()
-- my logic
-- ....
-- og call
ISCraftingUI_populateRecipesList(self)
end
but what can i do if i have 2x ISCraftingUI.populateRecipesList ? like the vanilla lua function and a mod function with absolutely the same name.
How can i specify which function i want, from which origin?
i don't think you can, it will grab the vanilla function if your mod loads before the other mod, and the other mod's one if that loads first
can i not say something like local x = require "blabla/mod"
and then reference the function?
i think that would work!
yeah but how 😄
it wouldn't help you get the vanilla one though
this is what will happen...if your mod loads first, you grab the original...if your mod loads second, you grab the overwritten function....if the other mod replaced the function the same way you did (correctly) then all 3 versions will run (yours, the other mods, then finally the original)
i was assuming that the other mod doesn't replace it correctly, or this probably wouldn't be a question
but yeah, if the other mod does the same thing with calling the original, all three will run
yes it is not correctly replacing the function. therefore i want to reference both vanilla and the mod function and use it in my mod
well if its not replacing it correctly then theres going to be conflicts, incompatibilities and broken bits regardless
if its not correct (referencing and calling the original) then its probably completely replaced it (and duplicated its code), so firing both is no longer practical. You'll have to pick one or the other
it will basically come down to load order at that point...load first, grab the original.. load second: grab the overwrite
if you really want both reference, load first, grab the original...then grab the overwrite later (on event triggered delay or similar)
so i can not load last and choose?
not likely. if you load last, the other mod has probably replaced the function...the original maybe stored in a local variable (if they bothered to save it at all)...but its unlikely you'll beable to access it (unless they shoved it into another variable inside ISCraftingUI)
if they stored it in a local variable, then you cant access it....if they didnt store it at all then its basically gone. best option is to load first if you really want to pick and choose
thanks that helped. ok so i have to copy both codes and mix and match them.
in order to beat the chaos, i have to make more chaos 😄
Where are item icons stored?
in texturepacks (UI, UI2)
thanks!
I know how to add translations -- but how exactly do I translate an item's name?
Q: Is it possible to use moveables(furniture/tiles) in crafting recipes yet? is there fancy way of doing it, or is it not impossible? thanks
nvm found the ItemName.txt file
You can load a file before the other mod's file runs, capture the function before it is modified, and also load a file after the other mod's file runs, and do whatever you want with their implementation
-- OtherModId_OverwriteISCraftingUI.lua
function ISCraftingUI:populateRecipesList()
-- my logic
-- I hate the original ISCraftingUI.populateRecipesList implementation, so not gunna call it! muhaha!
end```
```lua
-- !!_MyModId_preOtherModId_CaptureOriginal.lua
MyModIdNamespace = MyModIdNamespace or {}
MyModIdNamespace.ISCraftingUI_populateRecipesList = ISCraftingUI.populateRecipesList
-- zz_MyModId_postOtherModId_OverwriteISCraftingUI.lua
function ISCraftingUI:populateRecipesList()
-- my logic
-- ....
-- og call
MyModIdNamespace.ISCraftingUI_populateRecipesList(self)
end```
There may be an issue whereby a third mod modified the same function after !!_MyModId_preOtherModId_CaptureOriginal.lua but before OtherModId_OverwriteISCraftingUI.lua is loaded, so you may want to adjust the filename so it loads to as close as possible to before OtherModId_OverwriteISCraftingUI.lua
PZ loads lua files in alphabetical order, so you have that to manipulate the load order
any good guides for modding/importing custom models like clothing, helmets, backpacks, etc
It was a model problem after all, heh.
Anyways... It's fixed now. I also added a crafting recipe and fancy sound effects while I was at it.
Thank you for taking the time of your day to try and help me out.
oh weird what was causing it
I think I botched the UV map or something like that
I just took a spiffo head from the game files and modified it a bit
now it works
nice
Not gonna dwell on it, I'll just thank the computer gods that it somehow works.
anyone know how to make custom poses?
What is the best way to make a sound heard across the map (for both players & zeds)? There seems to be a cap on sound/radius?
PlayWorldSound(java.lang.String string, boolean boolean1, IsoGridSquare square, float float1, float float2, float float3, boolean boolean2)
I'm working on a guide about anims :)
is there an early draft i can read?
Not for the moment, I'm just in the introduction
Is this code part still valid ?
buildUtil.getWoodHealth(self)
Re: player:getXp(), I have a couple of questions:
-
Can I reduce the player's XP? Trying to call setXPToLevel(perk,level) works when increasing the level, but does not reduce it if the level is higher.
-
The AddXPNoMultiplier(perk,amount) method seems to imply it will apply the provided XP without adjustment due to the multiplier. But the amount actually applied doesn't seem to be the amount provided. e.g. If I say AddXPNoMultiplier(farming,100), starting from zero, I don't necessarily end up at 100 xp.
For example, I gave 100 xp to "Fitness", starting from Zero. I ended up with 100 xp. Using exactly the same method call, I then gave 100 xp to "Lightfoot", starting from Zero. I ended up with 32.5xp.
What else could be affecting the XP actually given?
is there any sneaky way in Lua to get access to a local variable?
In what context?
Everything in lua/server/VehicleCommands.lua is stored in a local variable, but I'd like to use them
If this was java, I'd use reflection or something to get into a private variable anyway, just wondering if there is something similar in lua or if I have to just straight up overwrite the whole file in order to fix it
Oh, that's rude. The least they could have done was return Commands at the end of the file so that you could require Vehicle/VehicleCommands to use it 😅
I can't think of a way to get at that. If you could load a file prior to that, maybe you could do something tricky with setfenv. But idk if you can even load a mod lua file prior to vanilla lua files
If I have a matching file with a matching name in my mod it will just override it, right? Not great for intercompatibility, I know, but I'm not particularly worried about that atm
That's definitely the case between mods. I believe it also works that way to override vanilla lua files, yes
time to hackerman this sh*t then
looks like they do the local commands thing in a bunch of places. Not a bad design choice, but nasty for modding imo
Mm. If they'd just add at the end of the files the linelua return Commands
In your mods, you could dolua local VehicleCommands = require("Vehicle/VehiclesCommands") VehicleCommands.doCommand(blah)
I want to override the commands, more than use them, tbh
That's an option that doesn't pollute the global table and also enables mods to access those function
You would be able to override them as well
local VehicleCommands = require("Vehicle/VehiclesCommands")
local og = VehiclesCommands.doCommand
VehiclesCommands.doCommand = function(...)
-- ...
og(...)
end```
I think overriding the entire file is probably the easiest option with how it is atm though
well, I tried overriding the file, still get the attempted index of non-table error, but if I go to the lua file in debug mode it shows my changes. Weird
You can check console.txt to see which files are loaded in which order
it seems to recognize that I'm overriding it and loads my version instead without ever trying to load the vanilla one
And you changed the local Commands = ... to Commands = ...?
Mm, make sure the new VehiclesCommands.lua file loads before the file that uses them. (require will do that for you)
does the require have to be at the top?
no, it's just a regular function
maybe I need to require("server/Vehicle/VehicleCommands") or something, local VehicleCommands = require("Vehicle/VehicleCommands") results in nil
server/ shouldn't be there
also its Vehicles, that might be it too
Do you return Commands at the end of the file?
ya
Mm, check for them typos 😅
vehicle:getId() vs vehicle:getID() is what got me yesterday. They're both valid functions that do different things, lmao
got it. Had to put if isClient() then return end at the top of the file to keep it from trying to load clientside
Does anyone know of a mod that adds an extra option to the context menu of an item?
I want to learn how to do this and would like to see how it's done.
the refurbish mod adds a refubish option to the context menu of pretty much any item, probably a good one to look at
Thanks, I'll look into it 🙂
Is there a way to do: if i'm holding a certain item, my transfer speed increases in lua?
Bummer, there doesn't seem to be any event or other way to tell when a vehicle has hit a zombie
or even when a vehicle has taken damage in general, aside from when it hits anything that isn't a zombie/player
I don't suppose there is any way to listen for a particular packet?
there is, but only from a weapon
doesn't seem to be. Bit of an oversight on the devs' part to leave vehicles like this, but from what I understand they've only recently been reworked
How do item tagging works for recipes?
I added the canopener tag to the kitchen knife and overided the item. It shows the knife in the recipe droplist but it doesnt recognize that I have the knife on me
When a player opens a world container, I need to create a modData property to an item in that container. How to sync it with server?
Haha, me again. How can I assign an icon to a custom clothing item? Seems to be a question mark no matter what I do.
If there is a function associated with that circumstance, you can make your own event by decorating that function
ProjectZomboid/media/lua/client/ISUI/ISInventoryPaneContextMenu.lua is a good place to look at too
It adds vanilla context menu entries on items. Most mods do it similarly
that's what I did yeah, easier
everything I can find is java-side
function MSGTweaks_RecipeCodes.OnCreate.ConvertToMetalLow(items, result, player)
MSGTweaks_RecipeCodes.ConvertToMetal(items, player, false)
end
function MSGTweaks_RecipeCodes.OnCreate.ConvertToMetalHigh(items, result, player)
MSGTweaks_RecipeCodes.ConvertToMetal(items, player, true)
end
function MSGTweaks_RecipeCodes.OnGiveXP.ConvertingToMetalLow(recipe, ingredients, result, player)
player:getXp():AddXP(Perks.MetalWelding, 20)
end
function MSGTweaks_RecipeCodes.OnGiveXP.ConvertingToMetalHigh(recipe, ingredients, result, player)
player:getXp():AddXP(Perks.MetalWelding, 40)
end```
Why do these reward `5`, and `10` experience?
xp math is weird, xp is quartered by default
+75% on the character creation screen means 25%+75%
so someone who starts with one point gets the xp you actually put in, for some reason
You can make your own (simple or complicated) event system, e.g.: ```lua
local MyEventSystem; MyEventSystem = {
data = {},
Add = function(type, fn)
if not MyEventSystem.data[type] then
MyEventSystem.data[type] = {}
end
MyEventSystem.data[type][fn] = true
end,
Trigger = function(type)
for fn in pairs(MyEventSystem.data[type]) do
fn()
end
end,
}
MyEventSystem.Add("custom_event", function()
print('hi')
end)
MyEventSystem.Trigger("custom_event")```
nvm I figured it out
Are there any mods out that let you paint or write on boxes for organization?
Which is better to use: vehiclePart:getModData() or vehiclePart:getInventoryItem():getModData() ?
Someone early had said mod data doesn't persist on inventory items, but does on vehicle parts. So presumably the former is better if you intend for the data to persist, but I haven't tested personally
I used part:getModData() and it persisted, for what its worth
But what if I uninstalled the part? How to get the modData if it's already an item?
Is there a way to just... copy a bag with it's contents?
I've just tested in singleplayer. Mod data persists on inventory item. Uninstalled, installed, reloaded the save.
I doubt its possible but are we able to override java classes as well?
Thanks, I appreciate it! Sadly, I don't think I'll be able to do what I want. I need to be able to override BodyDamage.JustTookPill, but I can't find any statement that calls it in the java code or the lua code.
I figure I can't override java methods, either way, but I was hoping that maybe it was exported to lua
Hmm, actually, I might be able to do it. There's a line In LuaManager and, if it's what I think it is, then it might be possible.
this.setExposed(BodyDamage.class);
Or maybe I don't need to override it at all, depending on how the context menu items work. If it allows me to include a pointer to a function, I should be fine.
I guess not. oof 
Do you want add a option to that context or replace?
Add option. Basically, I want to make it so that I can take half or all of the Vitamins since the default amount is so minuscule that it becomes tedious having to press "Take Pills" over and over and over.
Probably this can help you
Events.OnFillWorldObjectContextMenu.Add(OnFillWorldObjectContextMenu)
local function OnFillWorldObjectContextMenu(player, context, worldObjects, test)
local contextMenuList = context:getMenuOptionNames();
if contextMenuList["OptionaNameHere"] then
local testOption = context:addOption("Test", "Blabla", animal, nil)
end
end
end
Events.OnFillWorldObjectContextMenu.Add(OnFillWorldObjectContextMenu)
Thanks, looking at it now
In the following line, is this where I would check for the item name?
if contextMenuList["OptionaNameHere"] then
the more I look at the code the more I kinda cringe. Why does InventoryItem have a getSuspensionCompression method, for example? Serious refactoring is needed, lmao
that returns all options of a specific context, but better try with this
ISInventoryMenuElements = ISInventoryMenuElements or {};
ISInventoryMenuElements.YourContextMod = function()
local self = ISMenuElement.new()
self.inventoryMenu = ISContextManager.getInstance().getInventoryMenu()
self.createMenu = function(item)
local source = getPlayer();
if item:getName() == "blablalba" then
self.inventoryMenu.context:addOption("Test", item, self.equipContainer, source);
end
end
return self
end
is it possible to change the fire rate of a weapon?
Well this is weird, there are lots of variables in the vehicles that do nothing. For example the gearRatios in the vehicle scripts aren't used. Also, the EnginePower you see in the mechanics menu does nothing, you can set it to whatever you like but it changes nothing, your engine power is actually the engineForce in the vehicle script. I don't think that value can be changed easily either
I want to be able to change the vehicle's handling and strength, but its not going to be easy. Best I can think of is to make the vehicle lighter and the tires stickier to give the impression its more powerful, but then collisions get really weird
Wish the vehicle code wasn't a mess
does anyone know what get() function i can print to get the server time?
i want this, but in zomboid
https://www.youtube.com/watch?v=Q8BwSvYbmDQ&t=28s
Just wondering if anybody has made or is working on a "mountable weapon" mod (like a tripod). That would preferably work in tandem with Brita's Weapons. Would be great to mount a minigun, or even just a m16 with a 60 round mag to a stationary position like covering a gate. If not I'm def tempted to make it myself.
best mod for adding 2 weapons on back/backpack without the need to install 3 mods to achieve this?
Hi guys, i'm trying to add a stats to the player when they make a recipe. I want the player to use the lighter to do those tricks, so right now I wrote a recipe that does require only the lighter, the result of the recipe is the lighter itself but I made a "oncreate" function that take it away. I would like to ass a -5 stress to the recipe using the function, but i'm not that good. Anyone can help?
function Removestress (items, result, player)
player:getInventory():Remove("7ippoclassic");
end
this is the simple function i'm using now
as I said I would like to add a -5 stress to it
i am afk so i cant help look for that script part but i suggest looking at vanila lua files
i think it should be like
function Removestress (items, result, player)
local currentStress = player:getStress()
player:setStress(currentStress - 5)
end```
not sure though
I've checked on the recipecode.lua I can't figure it out
Thx I'll give it a try
sure
if it doesn't work, try changing player to its object first
like this:
function Removestress (items, result, player)
local playerObj = getSpecificPlayer(player)
local currentStress = playerObj:getStress()
playerObj:setStress(currentStress - 5)
end```
the lua file has to be in the "client" folder or in the "server" folder?
Client
There should be a getStats() call, like
playerObj:getStats():getStress()
Thanks! Can you tell me what the source parameter is for?
If they don’t do a PvP overhaul someone should make a mod to better the combat with firearms and melee.
Example: being able to have a hot key while you’re holding a weapon to duck for cover next to the wall you’re standing by/sandbags etc.
I know someone has modded prone into the game but they should chunk it in with this idea. Being able to shoot while prone and while crouching would be nice.
Also.. the stun lock mechanic is the dumbest thing I’ve seen.. just have your movement speed reduced instead of not being able to fight back at all, increase the blood loss as well. I hate having to empty 12 bullets into my victim to finish the job.
Also do something with the head tracking so I don’t have to stand on a persons face to do crit damage while smacking my baseball bat on the cement above my victim
Is there a way to make a container accept only one kind of an item?
@hollow current You can add an AcceptItemFunction property to containers
Set up a function like in media/lua/server/Items/AcceptItemFunction.lua
Then use that function name as the value for the property
Thanks!
To modify a subscribed mod from a dedicated server, is it enough to just upload the modified files of the mod to replace them with the old ones or is it necessary to go through a complete copy of the mod to upload on the workshop on steam?
Also someone fix vehicle PvP you can just shoot through vehicles like they don’t exist and that doesn’t make sense..
is there a way to check what kind of water container the player is using? (Sink/Toilet/etc)
you can modify the stress from the recipe itself i think
or item
youcan also add
removeresultitem:true,
so that whatver result will get deleted and u wont have to delete it from the oncreate
I saw it before, never made it work
and it's not working now either
RemoveResultItem:True, ok seems that the capital letters are import. it is working, for the stress I know I can do it for the item, but does it works on recepies?
ye sorry bout that im on mobile when i typed it
Q: Is it possible to use moveables(furniture/tiles) in crafting recipes yet? is there fancy way of doing it, or is it not impossible? thanks
it can be done but ihavent explored this yet
you can try refering to the vanila cigarettes
including its category
no problem, it was already correct, just googled it for better result
alright tyvm, ill keep digging, if anyone knows a way, feel free to dm me💪
the cigarettes have the stats, but it is also an item, not a recipe
StressChange = -5, this is on the cigarettes
yep u could change the item ur doing
what exactly is the item ur doing
if your modifykng the vanilla u can use itemtweaker
local zones = ScriptManager.instance:getAllZones()
that's line 14
function: 0_UdderlyVehicleRespawn_Core.lua -- file: 0_UdderlyVehicleRespawn_Core.lua line # 14 | MOD: Udderly Vehicle Respawn
ERROR: General , 1664556193217> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in 0_UdderlyVehicleRespawn_Core.lua at KahluaUtil.fail line:82.```
getScriptManager()?
tried that first
swapped over to ScriptManager.instance when that said this already
gonna try calling it with . instead of : real quick
i use both
getAllZones() isn't on the .65 one
why
why would that be gone
:|
ugh
i've been trying to figure out how to get zones for a cell
for ages
dont use the old docs
i actually thought those were newer but incomplete
thats from like 7 years ago
since they didnt specify a version and were on the official site
they're ancient

so
my other approach to getting zones is well within the newer docs and doesn't work
local zones = getWorld():getMetaGrid():getCellData(cellX * 300, cellY * 300)["vehicleZones"]
print("[UdderlyVehicleRespawn] Found "..zones:size().." zones in cell "..cellX..", "..cellY..".")
local vehicleZones = {}
for i=0, zones:size()-1 do
local zone = zones:get(i)
if instanceof(zone, "VehicleZone") then
table.insert(vehicleZones, zone)
end
end
return vehicleZones
apparently it just returns nothing every time, if i recall, but it's been a week or so since i ran that iteration
reverts all changes and tests
i thought writing a vehicle respawn mod would be hard but i never imagined it'd be hard because there's no way to get zones
:P
there's tons of functions, they are just all broken
Is there any sort of list where I can find all possible animations?
local zones = getWorld():getMetaGrid():getCellData(cellX * 300, cellY * 300)["vehicleZones"]
STACK TRACE
-----------------------------------------
function: GetZonesForCellAt -- file: 0_UdderlyVehicleRespawn_Core.lua line # 173 | MOD: Udderly Vehicle Respawn
function: RespawnVehiclesClient -- file: 0_UdderlyVehicleRespawn_Core.lua line # 250 | MOD: Udderly Vehicle Respawn
ERROR: General , 1664558909993> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: attempted index: vehicleZones of non-table: null at KahluaThread.tableget line:1689.
ERROR: General , 1664558909993> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: attempted index: vehicleZones of non-table: null```
that is line 173
I am not sure what the issue is, but I'd start with trying to print each section of that line separately
from what i can gleam it's not finding the meta cell
maybe you don't need to multiply the co-ordinates? as a complete guess
i'm honestly not clear on how cells work, as soon as my code needs to work with them i just go and find a different way to do it lol
but i see 'getCellDataAbs()' which could mean absolute co-ordinates, which would imply that the normal one isn't in normal co-ordinates?
fair i'll try that
i know how cells work but it's hard to know what the args are for what
also i don't know why i was keying into it like a damn table
musta been burned out when i wrote this
Is there a mod that lets me pick up doors from other building, and place them in a door frame I built?
yup i had big stupid when i wrote that a week or so ago
don't write code when you're tired
or distracted, or burned out
it's just bad
xD
field not accessible it seems, im guessing, by the null
will try the reflection stuff
ugh
LOG : General , 1664563046487> UDDTST: Found 0 zones for cell 36x33.
LOG : General , 1664563127937> UDDTST: Total zone count: 30
LOG : General , 1664563127937> UDDTST: Found 0 zones for cell 36x33.
ok so
there's zones just not vehicle zones
is there something wrong with doing this:
vehicleZones = {}
for i=0, zones:size()-1 do
local zone = zones:get(i)
if instanceof(zone, "VehicleZone") then
table.insert(vehicleZones, zone)
end
end```
so they're all vehicle zones
yet instanceof ain't workin
guessin "VehicleZone" doesn't cut it
they return as "zombie.iso.IsoMetaGrid$VehicleZone"
if i print them as string..
guess ill try "zombie.iso.IsoMetaGrid.VehicleZone"
I can only get sounds to be heard upto 10 tiles from players away no matter what the volume/range is. Zeds do hear the sound, and at a long distance. Any ideas?
I.E.:PlayWorldSound("PZ_ChopTree1", true, getPlayer():getCurrentSquare(), 6000, 6000, 6000, true) ;
Using PlayWorldSoundServer doesnt seem to produce any sound.
If you mean character animations then you can open the game in debug mode press the debug button and click "Dev" and then "Animation Viewer" and you can see them all and view them in action too.
If you add a vehicle mod with more vehicles to an excisting game. Will the new vehicles spawn? or do you have to restart
will spawn only in areas of the map that have not yet been explored by the player
@pearl prism Thank you
AH HA! So your the reason i cant use sandbox options with loot
Good find. That damn thing has given me such a headache. It loads sandbox settings after distribution anytime after the initial setting - right? What file is this in?
looks like OnLoadMapZones fires off about 100 lines later
i submitted a suggestion asking if sandboxoptions can be loaded before OnPreDistributionMerge or OnInitWorld because im having to relay on a lua config for my mod.
I have seen a lot of other mods using one of those three events when messing with loot i suspect it would really be a saving grace for when mod options stops working
Yep I had to deal with the same problem - can you tell me what file this is in? I would like to understand it better.
zombie/iso/IsoWorld.java
As far as I can tell it is not supported to enter loot table information via the sandbox because of this issue - that suggestion is a good one.
well the funny thing is, on new game creation and new server creation the first instance of the world has access to those variables
Awesome I will take a look at that. It looks like you found the root cause of my problem. The issue I was having was that sandbox works the first time to teh first setting just fine, after that, the load order is bad and it won't update until after distribution.
Yep thats right. same thing.
so if you are only testing your mod by starting it up and shutting it down you never catch it breaking on the restart/reload
Yep that is exactly the same behavior I had. Works perfect the first time, load order breaks it every time after, only if sandbox is involved.
@willow estuary ^ Tagging you because Xyberviri found where the sandbox loot table bug is that prevents us from using sandbox for loot tables reliably.
@calm acorn I had been battling this for awhile before I honed in on it being a load order issue but I never jumped into the java to find it. Good find!
any easy way to remove an item from the loot table / distribution table?
Thanks!
How do I know what is the anime name to use in the script? Because apparently the name appearing in the anim viewer isn't the right one to use
If you mean like a single function call, no, not to my knowledge. However, you can iterate over the tables and remove the entries with those items
so just using table.remove on the distribution table? what is the table that holds all the base vanilla items? or do i have to itterate over several tables?
There are multiple tables for different loot placements. There is one for items that spawn in containers, one for items that appear on zombies (clothes, etc), one for attachments on zombies (gun on back, scissors/crowbar in back, etc). One for vehicles. Depending on what exactly you're trying to do, you may need to look at more than one
They all contain base vanilla items
is there a wiki page listing all the different tables?
just the names, not the contents
Idk about a wiki, but here are at least a few of them
ProjectZomboid/media/lua/shared/NPCs/ZombiesZoneDefinition.lua```
That one is for items/clothes on zombies
thanks a lot. appreciate all those detailed answers.
There might be a way to delete an item that'd be easier if you simply want the item removed from the game. If so, hopefully someone familiar with it chimes in
actually yeah my problem is twofold. i want to remove some items completely form the game, like some mods add a lot of stuff. but we only want a handful. but then some vanilla base items should be sold in our own shop system, but not be found in containers around the world.
i tought i beat both use cases just modifying the distribution
In that situation, it sound worthwhile to write a function that iterates those tables and removes references to items you specify
eggon's "all doors are yours", or something like that
Thanks
So I lied earlier, engine power DOES matter, but only in reverse
anyone know if there is somewhere I can report an issue like that?
Bugs go here. Please save us the time to translate all the posts in different languages and post them in English instead.
do they get mad if you imply you've decompiled the code to find the issue?
nope
actually now that I say that, I should probably see about decompiling a newer version so I'm not misled
Does anyone know what the int value is for in this method?
IsoGridSquare():getLightLevel(int int1);
public float getLightLevel(final int n) {
return (this.lighting[n].lightInfo().r + this.lighting[n].lightInfo().g + this.lighting[n].lightInfo().b) / 3.0f;
}```
this.lighting = new IsoGridSquare.ILighting[4];```
How it is initialized in the ctor
So it's the color index of the rgb. Now to figure out where to get said index from lol
void cacheLightInfo() {
final int playerIndex = IsoCamera.frameState.playerIndex;
this.lightInfo[playerIndex] = this.lighting[playerIndex].lightInfo();
}
private int renderFloorInternal(final Shader shader) {
final int playerIndex = IsoCamera.frameState.playerIndex;
final ColorInfo colorInfo = this.lightInfo[playerIndex];
final IsoGridSquare camCharacterSquare = IsoCamera.frameState.CamCharacterSquare;
final boolean bCouldSee = this.lighting[playerIndex].bCouldSee();
final float darkMulti = this.lighting[playerIndex].darkMulti();```

Is anyone aware of a way to play a sound that can be heard by players beyond 10 tiles away? You can set the distanceMax in the script of an item, but I am looking for a way to set distanceMax dynamically. Seemingly range only applies to zed hearing range which can be changed dynamically,
How to get all nearest players with specific player on the server?
try this
getSoundManager():PlayWorldSound("ZombieSurprisedPlayer", getPlayer():getSquare(), 0, 10, 10.0, false);
addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), getPlayer():getZ(), 350, 50); ```
i havent really figured out much of it but i think the 350 is the radius
and idk how to increase the radius but zombies wont react to it but yeah play around it and if you figured it out pls let me know too 🙂 thnx
Uh oh. I am not sure. If you have an example of the format you need maybe you can try reformatting the names to that - or you can try playing some animations and then closing the game and searching for them in console.txt - maybe it could output something when it plays them? I am not sure - there may be a better list somewhere. I will look around a bit.
Its a bit confusing considering there was major changes to sound modding at some point, but I found this considering addSound:
Try here "...steamapps\common\ProjectZomboid\media\AnimSets\player"
That is for player, one folder back in AnimSets looks like it has all animations in there
getOnlinePlayers() vs getConnectedPlayers() ? What is better?
Question: Is there a way I can remove the heat requirement from a specific item in regards to using heat as a requirement for a recipe? I'd like to just have it so that the oil only needs to be hot here, and not the breading.
Any help would be appreciated.
Is that from a mod? Or vanilla?
never seen that in vanilla
pretty sure thats what he is creating right now
id love to help but i have no exp with cooking mods atm
Yeah I don't think it is vanilla either, I don't know if I have ever seen (Hot) as a requirement - is that a vanilla thing or from another mod? It seems like it would just be a requirement in the recipe.txt but I am not sure if that is a modded requirement or one that is available in vanilla.
but you can GetModData() i think im not realy sure how to use that tho
xyberviri just gave it to me earlier as part of a code
I think you can call GetModData() on just about anything and and use it to store variables. So like
playerModStuff = player:GetModData()
playerModStuff.something = "1"
playerSomething = playerModStuff.something
I think it works kind of like that
The window element doesn't have health data like a door or a wall? I can't find any information
Anyone know what defines "low quality?" I'm guessing the weapon's condition is low, but just want to make sure.
-- meat cleaver & some others low weapons (Hand Axes..) in the back AttachedWeaponDefinitions.meatCleaverBackLowQuality = { chance = 5, weaponLocation = {"MeatCleaver in Back"}, bloodLocations = {"Back"}, addHoles = true, daySurvived = 0, weapons = { "Base.MeatCleaver", "Base.HandAxe", }, }
-- Better weapons in the back AttachedWeaponDefinitions.meatCleaverBack = { chance = 1, weaponLocation = {"MeatCleaver in Back"}, bloodLocations = {"Back"}, addHoles = true, daySurvived = 20, weapons = { "Base.Machete", "Base.HandAxe", }, }
addSound(playerObj, square:getX(), square:getY(), square:getZ(), radius, volume)
i think in that file it just refers to how good the weapon is
but it calls zed tho. what if we want radius for players only
How to update mod data of all items in washer after it finished its work?
If you're referring to my post, that file (AttachedWeaponDefinitions.lua) is for weapon distribution on zombies.
yeah, the 'higher quality' weapons are the better weapons that only spawn later
By higher quality, do you mean better condition?
no, the file's comments often say 'low quality' or 'high quality', what they're referring to is the type of weapon
in your example, the second definition has a machete
I have a client side lua script that I wish to add to my local dedicated server. When I upload this script to my server's directory it does not work and I cannot see the script when pressing f11 while in the server. My server side lua script works but where do the client side scripts go?
Did you put your mod files here?
C:\Users\{USER}\Zomboid\Workshop
And set same folder hierarchy than ModTemplate example folder.
(Maybe it is not the same with a local dedicated server...)
This is where I am getting lost. For the server lua scripts that work they are in a separate directory: pzserver/media/lua/server. I tried to put the client scripts in pzserver/media/lua/client but they do not work. If I want the mods to work on my local server, am I suppose to upload the scripts to my local user directory; the same directory you referenced?
I'm not sure what I was saying. It's the folder to use with local mod in a solo game.
And I only have a dedicated server based on linux
The good news is that I got the script to work by adding it to the local mod directory like you said, I just don't know how exactly it is working. I am not sure if it is working because I have the mod in the servertest.ini. 🤷♂️
dedicated servers use that directory too
You can add own mods on a dedicated server without going through the steam workshop?
yeah, just place them in that directory
maybe just if you set a non-steam dedicated server no?
if I try to overwrite a mod, I can just upload it to this folder and add it to the mod list without going through the steam workshop?
yeah that's all you need to do
honestly i've never used it for anything but local testing, so i don't know
see if there is already mods like that on workshop and see how they are made
From what I understand, you can access the file system from the zomboid lua, but its sandboxed a bit. Do you have access to the scripts folder?
item:setDirtyness() doesn't really work. I do item:setDirtyness(50) but it drops to previous value in washer even in singleplayer. Does anybody know how to fix that?
you might need to trigger OnClothingUpdated after setting the dirtiness
triggerEvent("OnClothingUpdated", player)
Is there any way to check the map status (Visited, Known) on the Lua side?
I found those Setter methods (setVisistedIn~, setKnownIn~) in "zombie.worldMap.WorldMapVisited", but there didn't seem to be a Getter method. And "isCellVisible" or "hasFlags" methods that may be useful are not public.
Any ideas?
well thats good news, I may be able to salvage my mod concept after all
I want to flesh out the engine mechanics, but its going to require me to be able to make vehicle scripts on the fly
hopefully new scripts can be loaded at runtime too
Yall r nerds
For someone who has 0 experience with lua, how hard would it be to create a simple food mod with craft recipes?
easy
i dont think its to hard, it allways depends on whether or not there is a tutorial for it. for a food item there should be one i think its a tutorial from Blackbeard on youtube. might wanna check it out 😉
Ty
How to attach a model to character body part? (it's not an equipped item)
some 1 who make mod's for project zomboid make zombie child
Hi! I have two questions:
-
Is it possible to check whether a specific mod is active?
-
Given a string, is it possible to find out whether this string denotes a body location?
Do you mean how to attach a weapon to one of the weapon slots via code? Or just attaching any 3d model to any part of the character model?
attaching any 3d model to any part of the character model
the only strategy I know about is by doing this via "fake" clothing items but not sure whether this is applicable in your specific case
- Yes. By special function or by global variables of that mod.
- Yes I guess
for no. 2), do you know the relevant code/commands for this? I checked the java doc but didn't found anything which might accomplish that....
but anyway, I think your trick no. 1) might also work fine for my case
- e.g.
if getModInfoByID("rasBodyMod") then
great! probably the most clean way of doing this.... thanks!
Not sure if it's cleanest. I've just found an answer in the game code)
sec
BodyLocations may be added by modders.
this is exactly the pojnt. i am currently working on better compatibility for my body mod with the clothing redux mod (the problems you mentioned in the discussion section). the redux mod adds a new body location and in order to treat it properly, I need to find out whether this mod is active or even better, whether the name it gives to the new body location does indeed refer to a body location....
but using this getModInfoByID is definitely one option I can work with
Thanks so much!
if BodyLocations.getGroup("Human"):getLocation("Belt") then
"Belt" is your string 🙂
didn't try this option yet! thanks. if this works, this will be a quite safe way of doing this!!
I've tested it before post)
many thanks!
if getActivatedMods():contains("CraftHelper41") then
is a better way to do it, since the contains function explicitly returns a true false value. the getModinfoByID probably will technically work, but this way is more explicit
whats the difference with getCell():getGridSquare(x, y, z) and getPlayer():getSquare() and getPlayer():getCell()
cells are a 300x300(?) area
had to make sure 🙂 thnx
function BatteryJumpstarter_JumpstarterTimedAction:perform() -- Trigger when the action is complete
local chance = ZombRand(1,100) --Generate a random number between 1 and 100
local ui = getPlayerMechanicsUI(self.character:getPlayerNum());
self.item:Use()
if chance <= 75 then
ui:startFlashGreen()
self.part:getInventoryItem():setUsedDelta(0.05)
else
ui:startFlashRed()
end
ISBaseTimedAction.perform(self);
end```
This script is supposed to change the usedDelta of a battery that is currently installed in a vehicle. Visually, it does change it, but it actually doesn't change. When starting the vehicle or uninstalling the part, it resets back to what it was originally. Any idea what may cause this?
p.s.: This is a MP issue. Script works fine in SP
is it a client script?
the script is in client folder, if that's what you mean
yeah it's only changing it on the client
so, should I copy and paste the same files and put in server folder?
i'm not sure, i think timed actions are client only
you'll need to use sendClientCommand() and have a function on the server that changes the battery usedDelta
Any specific tutorial on how to set a function up that can be used with sendClientCommand?
local function OnClientCommand(module, command, player, args)
if module == 'BatteryJumpstarter' and command == 'functionThatChangesTheBattery' then
functionThatChangesTheBattery()
end
end
Events.OnClientCommand.Add(OnClientCommand)```
if you have multiple you usually want to keep the commands in a table and index them based on the command argument but i think you only need one command
and then on the client you just go sendClientCommand('BatteryJumpstarter', 'functionThatChangesTheBattery', {})
Well, the item being used with the battery gets charged from a generator, which increases its usedDelta and decreases the getFuel of the generator, so I assume I will have to set up client commands for those too, right?
yes, although the generator might already have a command for it or a function for syncing data, so id check for that first
i'm unusure, you should test that, but if that's the case then you just want to go
local Commands = {}
function Commands.Function()
end
function Commands.AnotherFunction()
end
local function OnClientCommand(module, command, player, args)
if module == 'BatteryJumpstarter' then
Commands[command]()
end
end
Events.OnClientCommand.Add(OnClientCommand)```
if you start needing arguments it gets a bit more complicated but i don't think you will
I'll try messing with that, thanks so much, both of you!
I assume, since I am adding a client command anyways, it's better to change self.part:getInventoryItem():setUsedDelta(0.05) to the client command, making it work for both sp and mp?
anyone knows how acces the whitelist via modding? like to make functions that readd the whitelist of a person droped from the list when he died but after a cooldown
i think so!
One more thing. I am not sure why I am getting an error at the last end here
function Commands.increaseUsedDelta(part)
part:getInventoryItem():setUsedDelta(0.05)
end
--function Commands.AnotherFunction()
--end
local function OnClientCommand(module, command, player, part)
if module == 'BatteryJumpstarter' then
Commands[command]()
end
end
Events.OnClientCommand.Add(OnClientCommand)```
nvm i think i may know why
Am I passing the part argument correctly? It doesn't look like I am
function BatteryJumpstarter_JumpstarterTimedAction:perform() -- Trigger when the action is complete
local chance = ZombRand(1,100) --Generate a random number between 1 and 100
local ui = getPlayerMechanicsUI(self.character:getPlayerNum());
self.item:Use()
if chance <= 75 then
ui:startFlashGreen()
sendClientCommand('BatteryJumpstarter', 'increaseUsedDelta', {self.part})
else
ui:startFlashRed()
end
ISBaseTimedAction.perform(self);
end```
```lua
local Commands = {}
function Commands.increaseUsedDelta(part)
print(part)
part:getInventoryItem():setUsedDelta(0.05)
end
local function OnClientCommand(module, command, player, part)
if module == 'BatteryJumpstarter' then
Commands[command]()
end
end
Events.OnClientCommand.Add(OnClientCommand)```
Hey @nimble spoke could you confirm that Anomalous Rain isn't supported in MP currently?
oh, arguments are passed as a table
so in this case, you'd want to use Commandscommand
hmm no luck, returns part as nil
The red weather effect doesn't show so players don't know when it is dangerous to go outside. I will make changes and update, right now I suggest disabling it
oh, i wasn't thinking, you probably can't send the part as an object over
i wrote something for night that worked with vehicles, let me check what i did there
i think we sent the vehicle's getId() as the argument and then used getVehicleById() on the server
you could send the part's id too but i think you're always changing the battery so it's not necessary
sth like this?
---timed action function
function name:perform()
local vehicleId = self.part:getVehicle():getID()
sendClientCommand('BatteryJumpstarter', 'increaseUsedDelta', {self.vehicleId})
end
--clientCommand
function Commands.increaseUsedDelta(vehicleId)
local vehicle = vehicleId:getVehicleById()
local part = vehicle:getPart() ---What's the function to get the Battery Part?
part:getInventoryItem():setUsedDelta(0.05)
end```?
Thank you!
getPartById('Battery')
and i think it's 'getId()' not 'getID()' (they return different values)
Ah thanks! I will try that out
seems like most errors are fixed and the clientCommand is being sent, except that vehicleId is being passed as nil for some reason
--Timed Action
function BatteryJumpstarter_JumpstarterTimedAction:perform() -- Trigger when the action is complete
local chance = ZombRand(1,100) --Generate a random number between 1 and 100
local ui = getPlayerMechanicsUI(self.character:getPlayerNum());
self.item:Use()
if chance <= 75 then
ui:startFlashGreen()
local vehicleId = self.part:getVehicle():getId()
sendClientCommand('BatteryJumpstarter', 'increaseUsedDelta', {self.vehicleId})
--self.part:getInventoryItem():setUsedDelta(0.05)
else
ui:startFlashRed()
end
ISBaseTimedAction.perform(self);
end
--Client Command
local Commands = {}
function Commands.increaseUsedDelta(vehicleId)
local vehicle = vehicleId:getVehicleById()
local part = vehicle:getPartById('Battery')
part:getInventoryItem():setUsedDelta(0.05)
end
--function Commands.AnotherFunction()
--end
local function OnClientCommand(module, command, player, vehicleId)
if module == 'BatteryJumpstarter' then
Commands[command](vehicleId[1])
end
end
Events.OnClientCommand.Add(OnClientCommand)```
Rest of locals seem to be defined fine
that's really odd! i can't see a meaningful difference between some of my tested code and yours
oki prolly found the issue
one min
alright ye I was being dumb and passing self.vehicleId instead of vehicleId
Although now the error is being thrown at local part = vehicle:getPartById('Battery') 🤦♂️
what's the error?
function: OnClientCommand -- file: ClientCommands.lua line # 15 | MOD: Battery Jumpstarter
LOG : General , 1664637020755> Object tried to call nil in increaseUsedDelta
LOG : General , 1664637020781> creating new sourcewindow:
ERROR: General , 1664637031683> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in increaseUsedDelta at KahluaUtil.fail line:82.
ERROR: General , 1664637031683> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: Object tried to call nil in increaseUsedDelta
at se.krka.kahlua.vm.KahluaUtil.fail(KahluaUtil.java:82)
at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:973)
at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:163)
at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1980)
at se.krka.kahlua.vm.KahluaThread.pcallvoid(KahluaThread.java:1812)
at se.krka.kahlua.integration.LuaCaller.pcallvoid(LuaCaller.java:66)
at se.krka.kahlua.integration.LuaCaller.protectedCallVoid(LuaCaller.java:139)
at zombie.Lua.Event.trigger(Event.java:64)
at zombie.Lua.LuaEventManager.triggerEvent(LuaEventManager.java:214)
at zombie.spnetwork.SinglePlayerServer.receiveClientCommand(SinglePlayerServer.java:229)
at zombie.spnetwork.SinglePlayerServer.mainLoopDealWithNetData(SinglePlayerServer.java:183)
at zombie.spnetwork.SinglePlayerServer.update(SinglePlayerServer.java:171)
at zombie.GameWindow.logic(GameWindow.java:238)
at zombie.core.profiling.AbstractPerformanceProfileProbe.invokeAndMeasure(AbstractPerformanceProfileProbe.java:71)
at zombie.GameWindow.frameStep(GameWindow.java:764)
at zombie.GameWindow.run_ez(GameWindow.java:680)
at zombie.GameWindow.mainThread(GameWindow.java:494)
at java.base/java.lang.Thread.run(Unknown Source)```
tried changing it to lua function Commands.increaseUsedDelta(vehicleId) local vehicle = vehicleId:getVehicleById() print(vehicle) --local part = vehicle:getPartById('Battery') --part:getInventoryItem():setUsedDelta(0.05) end
apparently the error is with the local vehicle
The function I am using is correct, no?
oh! it should be getVehicleById(vehicleId)
🤦♂️
of course
Alright, that does fix everything finally
I'll just follow the same steps for the other functions
I really appreciate the help and time. Thank you so much!
of course ^u^ i'm glad it's working for you now
Hey guys, could someone point me in the right direction of retrieving an up-to-date list of all available Lua functions/methods within the current game's version?
Javadoc Project Zomboid Modding API package index
Thanks, I believe this is the main thing to be looking at? https://zomboid-javadoc.com/41.65/zombie/Lua/LuaManager.GlobalObject.html
Javadoc Project Zomboid Modding API declaration: package: zombie.Lua, class: LuaManager, class: GlobalObject
that's the one of most interest yes
function Commands.rechargeJumpstarter(item)
local currentDelta = item:getUsedDelta()
item:setUsedDelta(currentDelta+0.2)
end
local function OnClientCommand(module, command, player, args)
if module == 'BatteryJumpstarter' then
Commands[command](args[1])
end
end
Events.OnClientCommand.Add(OnClientCommand)```
```lua
function BatteryJumpstarter_GeneratorTimedAction:perform() -- Trigger when the action is complete
sendClientCommand('BatteryJumpstarter', 'rechargeJumpstarter', {self.item})
self.sound = self.character:playSound("beep")
local fuel = self.generator:getFuel()
self.generator:setFuel(math.floor(fuel+0.5)-1)
ISBaseTimedAction.perform(self);
end```
Any idea why this doesn't change the UsedDelta of the item?
it looks like item is being passed correctly. The command returns print(item) and print(item:getUsedDelta()) correctly
but setUsedDelta doesn't seem to be doing anything
have you tested that doing it clientside doesn't work in multiplayer? i think the client is still authoritative over items
hmm no I haven't, i'll give it a go
otherwise, it's the same problem as the vehicle where you can't pass the object itself (you're essentially creating a clone of its data and sending it to the server, not referencing the same object)
is there some kind of an "Id" to pass instead for inventory items?
no :( from what i've heard referencing specific instances of items is very difficult, if not impossible?
Well that'd suck. Let's hope it works clientside in mp
Well, that's rather weird. The function that was set up earlier to mess with the car battery, works in SP but not MP
Not the same issue, but now it doesn't even change the battery charge, not visually or technically
hmm... perhaps vehicles behave differently on the server
Would anyone be able to confirm if that's the case?
vehicle:transmitPartUsedDelta(part)
I don't think the client command is being executed at all, not even a print function works. Would it have anything to do with file names maybe?
are you using dedicated or co-op?
i think calling this after setting the delta might fix it
if you're using the in-game console to check for the prints, that can be unreliable
if it's the server console/log they're not showing up in that is different
lemme check if it shows in the server console
ye shows in server console. function is definitely being executed
the client still runs server code so some prints from there will show up, but OnClientCommand never fires on the client so you wouldn't see those in-game
oo i see
giving this a go
By the way, is there some kind of a definitive guide that covers everything/such common issues?
not that i know of, but i'm not familiar with a lot of the community resources
most if not all guides I have come across are either outdated, not completed, or just not very well put together
i've considered writing my own documentation but i bet it'd just end up outdated and incomplete too
I bet it won't be that hard to maintain if it was done by a number of modders, rather than each one individually working on his own
That works by the way, thanks!
oh good ^u^
One more question, I am not sure if its a server issue or a mod issue, but the server sound effect seem to work fine in SP (even though it throws a warning at me that the sound effect was not found, yet it is played anywyas), but not MP. Somehow, different sound effects are not being played in MP server too, like failure to start the engine or exiting/entering the vehicle
unfortunately i don't have any experience with that
Ah np then, I'll try messing around more with it. Anyways, really appreciate it once again, thanks!
And oh, the other issue, attempting to change inventory item used delta via client command, it seems like its not needed
it indeed works with normal client functions in MP
at least sometimes things can be simple LOL
hahaha yea thankfully
anyone know anything ab changing weapon firerates
is there a way to print all banned account ?
think this has something to do with animation . someone once told me
How to detect that main menu is opened while playing?
I'm trying to fix a mod and I have a question.
The mod adds a callback to Events.OnDeviceText.
I've checked the function signature and it's correct, but here it is, anyway:
function RadioWavs.OnDeviceText(_interactCodes, _x, _y, _z, _line, _source)
You can double check the signature here: https://pzwiki.net/wiki/Modding:Lua_Events/OnDeviceText
The problem is, the first parameter being sent to the function is always nil.
Anyone know what's going on and how to fix it?
a new parameter was added
function RadioWavs.OnDeviceText(_guid, _interactCodes, _x, _y, _z, _line, _source)
Thanks, gonna try it out
the wiki is outdated on that one, i was going to update it but you have to like, contribute it to github or something...?
It fixed the error, but the mod still doesn't work. 😦
I've seen people use a line-by-line debugger in game, do you know how to bring it up? I figure you have to start the game with -debug, but I don't know where to go from there. EDIT: it's F11 key, but it doesn't display any mod files.
is it possible to "consume" an event? As in prevent any other event listeners after yours from seeing the event? Is it possible to make sure your listener fires first?
Anyone know how to make sounds heard by players over 10 squares away?
you can open files from the explorer. the UI isn't that great, it opens automatically when there is an error though
I think you might be able to manually manipulate the callback inside the event manager, but I haven't tried by it before. I don't know if you can make the events consume the event
Is it possible that when you open an object it has X chances of giving you certain objects?
For example a <Bag of unknown seeds>. and when you right-click on the object, you get an Open bag action.
yeha you can create a recipe, and the Oncreate would have the logic for the randomization
Do you have any idea where I could get an example of such randomization?
doesn't expanded helicopter events have something like that?
with the boxes?
hydrocraft has a recipe doing exactly this. its even for the "packet of unknown seeds" item to open it.
I feel stupid, knowing that I put that example of that particular mod
How viable would it be to control the order of an option you added to a context menu?
I.e. make it the first/second/last option?
Should be able to control to some degree whether it is first or last by performing your manipulation of the context object before or after calling the original implementation that fills out the context menu options
Going to depend on order of lua files that are loaded, which you can control too somewhat bc they are loaded alphabetically
I am sorry, but I am kind of confused about how to implement that in my code, would there be some kind of an example?
Uh is it possible I can break the default recipes by adding my own?
I just logged into my Multiplayer server with my new mod, and I can't seem to open a tin of soup lol
make sure the name of the file you have that is adding recipes, isn't name the same as the files vanilla uses, it might be replacing the file that adds the open tin of soup recipe
I presume you are overriding a function to add to an existing content menu, right? In your implementation, you call the original function, I'm assuming. If so, you can call that original function before or after adding your own context menu entry. If you have some code, I can explain further
@shadow geyser Oh I think it is because I used a mod structure to start my mod, and it was called scripts/recipes.txt by default, so I kept it like that lol
I just renamed it so let's see, I guess thats the issue
ISRenameEverything = {};
require "ISInventoryPaneContextMenu"
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
canBeRenamed = item;
end
if canBeRenamed then
context:addOption(getText("ContextMenu_renameButton"), canBeRenamed, ISRenameEverything.onRenameItem, player);
end
end
This what I am using to add a context option
I have a very weird situation, I restart my game after turning off my mod - but it's still there when I reload and continue my save, even though it's disabled in mod loader
Oh, you're not adding onto an existing menu
In what way do you need to control the order then? I misunderstood
The option is being added to the top of the context menu, can the option be instead moved to the bottom?
there are events for before the context menu is populated, and after
Which context menu, ISInvPaneContextMenu?
Oh, right. I forgot it has that event..
ye, the one that appears when you right click an item in your inventory
are we adding stuff to the context menu without using the events?
So using that event, you can't control it too well. What you could do instead possibly is override the ISInvPaneContextMenu functions to add the context option earlier than the event allows. I'd have to look at the code to see how to do that
triggerEvent("OnPreFillInventoryObjectContextMenu", player, context, items);
Can you use that event to insert at top? (if that's what you are looking to do) @hollow current
ye, at least to the best of my knowledge if understand the code correctly lol
I wasn't aware that was possible, but I did context menu stuff before I really knew what was going on
saves have their own mod list. the main menu mod list only controls what mods are loaded during the creation of a save, and in the main menu
if you want to remove a mod from a save, you need to go to the save in the load option from the main menu, then at the bottom there should be a mods option, there you can remove mods
I will try to look at the code to see how viable is that
my keybind isnt set to default and i cant remember the default but to check the mods you have to open a panel from kne of the f keys
Actually I am trying to add it at the bottom
what's the event name for that?
onpostfillinventory etc
triggerEvent("OnFillInventoryObjectContextMenu", player, context, items);
👆
OnFillInventoryObjectContextMenu adds it to the end, but if you have other mods loading afterwards, then they will add their stuff to the end as well
I will try that, thanks guys!
I assume that goes to the top of the code?
oh never mind I think i figured it out
nono, just use that string as the event name
I copied it from the code that triggers the event in the vanilla source code
bc lazy
If some other mods are adding entries after yours, you can try renaming your lua file that adds the event handler to zz_myfilename.lua to influence the lua load order (which will affect the order the events are registered)
ISRenameEverything = {};
require "ISInventoryPaneContextMenu"
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
canBeRenamed = item;
end
if canBeRenamed then
context:addOption(getText("ContextMenu_renameButton"), canBeRenamed, ISRenameEverything.onRenameItem, player);
end
end
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
Events.OnFillInventoryObjectContextMenu.Add(ISRenameEverything.createMenu);```
That's full code
I think it should it
how do i create a custom table with data and be able to store itpermanently unless j delete the data and how do i delete them
basically i need it to hold specific steamids
store them in the global moddata
Any idea what could be messing with you not being able to barricade/unbarricade? I have a mod causing the issue. The timed action of barricading/unbarricading happens but nothing actually changes. Items don't get consumed, and it doesn't barricade not does it unbarricade. Not sure what's causing that issue
Fixed
What was the issue?
How can I check if the game is in debugmode?
never used it before, but probably getDebug()
What is the easiest way to show some sort of message to the player after completing an action?
Okay thank you
Like, let's say I cut up a car hood and get 2 small metal sheets, and 1 metal sheet - how would I say something like
** You gained XSmall Metal Sheets andY Large Metal Sheets
over the player's head?
I see getDebug() (as mentioned above) and isDebugEnabled() used in the code to check
oh yeah, getDebug() is actually a member of core, not globalobject
so use isDebugEnabled()
I had named my client commands file the same as the vanilla file, so it was overriding it and causing issue with all client command actions
easiest way is just to use the isoplayer:Say(message)
It's like the 3rd time I forget and do the same thing. Thankfully was able to debug it quicker. The first time took me almost half the day to find out why half of the items in game were missing lol
in general, you should avoid generic file names, as even if you don't override vanilla you still might override another mod
Mm, I generally follow the pattern of
mymodid_filename.lua```
Or if I need the file to load early or late (to muck with other mods):```
!!_mymodid_filename.lua
zz_mymodid_filename.lua```
i tend to use modname.lua, or modname/file.lua if i have enough files to justify that
how do you send a command that deletes the whole file or atleast all the entry once its read?
what are you trying to achieve with this?
do getRandomSquareInZone and GetRandomUnseenSquareInZone require the square(s) to be loaded to be picked?
cuz both are returning nil squares for me for zones that are potentially not loaded presently
True
I also started to use modid_filename as Tyrir mentioned. I guess it'd majorly avoid conflicts with other mods if they happen to use the same generic names
I would think so. the same thing happens when you try to use getgridsquare with coordinates that are unloaded
ugh
im trying to get a square in a zone though, so i dont have coordinates
guess i can get X/Y/Width/Height and pick a random spot
then load it
Javadoc Project Zomboid Modding API declaration: package: zombie, class: LoadGridsquarePerformanceWorkaround
My mod isn't giving the player items after completing the recipe, it works in SP
function MSGTweaks_RecipeCodes.ConvertToMetal(items, player, high)
local itemValueType = MSGTweaks_RecipeCodes.GetMetalValueType(items)
local skillPoints = math.floor(player:getPerkLevel(Perks.MetalWelding) + (player:getPerkLevel(Perks.Mechanics) * 0.25))
local metalPoints = 1
if (itemValueType == 2) then
metalPoints = metalPoints + 1
end
if (high) then
metalPoints = metalPoints * 2
end
if (skillPoints >= 7) then
metalPoints = metalPoints + 1
end
local smallMetalSheet = 0
local largeMetalSheet = 0
for i = 1, math.max(1, metalPoints) do
local size = ZombRand(0, skillPoints)
if size >= 5 then
largeMetalSheet = largeMetalSheet + 1
else
smallMetalSheet = smallMetalSheet + 1
end
end
if (smallMetalSheet > 0) then
player:sendObjectChange('addItemOfType', { type = 'Base.SmallSheetMetal', count = smallMetalSheet })
end
if (largeMetalSheet > 0) then
player:sendObjectChange('addItemOfType', { type = 'Base.SheetMetal', count = largeMetalSheet })
end
--log("Item Value Type: " ..tostring(itemValueType).. " points: "..tostring(metalPoints)..", " ..tostring(skillPoints))
end
function MSGTweaks_RecipeCodes.OnCreate.ConvertToMetalLow(items, result, player)
MSGTweaks_RecipeCodes.ConvertToMetal(items, player, false)
end
function MSGTweaks_RecipeCodes.OnCreate.ConvertToMetalHigh(items, result, player)
MSGTweaks_RecipeCodes.ConvertToMetal(items, player, true)
end
guaranteed to give 1 metal, but it isn't giving anything
works in my Singleplayer
I don't know what the issue is, but my guess is the player:sendObjectChange calls may be on the wrong client/server side
I'd debug it by manually calling those functions to figure out how/where it should be called to get the desired effect
Hey guys sorry quick question, if I want to edit a vanilla tile with TileZed how should I go about doing that?
Unless i'm reading this wrong: https://theindiestone.com/forums/index.php?/topic/21951-the-one-stop-tilezed-mapping-shop/
that guide is more for creating a new map than editing just a simple tile.
1Here you will find a (hopefully) comprehensive guide to map modding using TileZed, from scratch, to uploading to Steam Workshop. Step 1) Installation and setup Spoiler - Download the latest version of TileZed here https://theindiestone.com/forums/index.php?/topic/50425-latest-tilezed-worlded-and...
basically I need store username and steamids of players that dies
it is compiled on a serverfile
then when it hits friday all of the stored name is read and deleted from the file.
basically this is a mod for a hardcoreserver that babs the player until friday
local rawtimestring = tostring(Calendar.getInstance():getTime())
print(rawtimestring)
if string.find(rawtimestring, "Fri") then
print("Unbannning IDs")
print("get all ids from table")
print("remove id from table")
end
function BanDeath()
local addbanid = getSteamIDFromUsername(getPlayer():getUsername())
print(addbanid)
SendCommandToServer(string.format("/banid " .. addbanid))
print("add id to a table")
print("write it on a file")
end
Events.OnPlayerDeath.Add(BanDeath)
and this is what i have so far
and a few reference scripts on saving and loading from files
but this is the first time in modding that involves saving and loading from file
and i havent tried doing the k, v or any other functions that get the contents one by one
so im really lost i just kept on looking at the references and hoping to be able to make em fit
i think it might be possible to to use sandboxvar instead to hold the ids?
im guessing u will have better luck asking that here #mapping
you can reference my Udderly Cell File Lister for how to write out to files
it's not hard
ahhh i have multiple references of writing and reading but dont have one that does both well i do but t only writes 1 string and thats it not something that has delimiters
So, I finally nailed this transmog problem
https://steamcommunity.com/sharedfiles/filedetails/?id=2870193357
It does work in MP now
oh wow! well done
Thank you I tooks many weeks to make it work properly, but I can finally say that this old version (https://steamcommunity.com/sharedfiles/filedetails/?id=2768901065) can finally be replaced for MP servers
every time i saw you talking about it in here i was thinking 'there is no way this will ever work' LOL
🤣 I thought the same so many damn times man
congratulations man!
im getting nuts with this readfile thing. i should give it a rest i guess and try again tom
i got it i think
but this is a client side reference tho
function BanDeath.flushEntries()
local rawtimestring = tostring(Calendar.getInstance():getTime())
print(rawtimestring)
if string.find(rawtimestring, "Fri") then
print("Unbannning IDs")
SendCommandToServer(string.format("/unbanid " .. addbanid))
print("remove id from table")
end
function BanDeath()
local addbanid = getSteamIDFromUsername(getPlayer():getUsername())
print(addbanid)
BanDeath.writeSaveFile();
SendCommandToServer(string.format("/banid " .. addbanid))
end
Events.OnPlayerDeath.Add(BanDeath)
--WIP way to delete the entries
function BanDeath.readSavedDeathFile()
local retVal = {};
local saveFile = getFileReader(BanDeath.savefile, true);
local BanList = 0
local line = saveFile:readLine();
while line ~= nil do
if luautils.stringStarts(line, "BanList=") then
BanList = tonumber(string.split(line, "=")[2])
elseif BanList == ENTRY_BanList then
local s = luautils.split(line, ":");
retVal[s[1]] = s[2];
end
line = saveFile:readLine();
end
saveFile:close();
return retVal;
end
function BanDeath.writeSaveFile(options)
local account = getFileWriter(BanDeath.savefile, true, false); -- overwrite
account:write("BanList="..tostring(ENTRY_BanList).."\n")
for key,val in pairs(options) do
account:write(key..":"..val.."\n");
end
account:close();
end
Really great mod. Thank you @gilded hawk
If I have a UI panel listening to an event, should I manually unsubscribe from that even when I close the ui?
I'm looking at the way the trade panel works as an example, and it doesn't appear that IS are doing it, so I'm assuming it's all good
I'm looking to change some stats on guns via lua instead of overwriting them via the script files. I'm using ItemTweaker for it, but it seems to only be editing fresh items, not pre-spawned ones. How can I make sure the existing items get affected too?
Digging into the code, ItemTweaker doesn't do anything special, and I thought it was good for existing items too - Durability overhaul by Drey uses the same method though self-rolled, and it edits existing items just fine as far as I can tell.
https://steamcommunity.com/sharedfiles/filedetails/?id=2843189389
if anyone has suggestions, please ping me - I might miss it otherwise
I'm pretty sure once an item is spawned in, it's stats are stored somewhere. Items don't look up their stats once they've been created, they just are. Evidence for this is that you can alter the weight/damage/whatever via the 'Edit Item' option in debug/admin mode and that specific instance of that item will have the altered stats, but others of it's kind will not. I imagine Item Tweaker alters the 'template' that new items copy when created by the factory, but does not loop through every item in existence and retroactively change them, and if it did that would probably cause a lot of issues. @mystic meteor
wont hurt if u try this maybe..?
overwrite them
look at them
then revert to original plus tweaker
Maybe a function registered to the OnEquipPrimary event that checks if the weapon being equipped is one of the guns you want to tweak and, if so, update the desired stats to match the new tweaked template? It'd do the job of getting the guns being used to have your new stats and doesn't need to go find all the guns in existence.
you can just use player:getInventory():AddItem(item). yeah its a bit strange even though the oncreates are on the server side, you dont need to use sendObjectChange.
the globalmoddata just seems like a more appropriate data storage than using files
easiest way, would be to have a table storing the modifications somewhere, then using a OnEquipPrimary function, to modify the stats whenever the player equips it. this ensures that the weapon will have the correct stats whenever the player tries to use it. Then if you want you can also run the changes on equipped items, whenever you modify the stats in general, which will then ensure that cornercase is covered.
i dont know how to use that yet
Hey guys, i have a suggestion for a useful mod; how about multitool in PZ? A rare complex tool, that can act like a knife, can opener, screwdriver and mb something more. It should be really rare, bc it makes things way more easy imo.
-- for testing
function BanDeath.KillMe()
getPlayer():setGodMod(false);
getPlayer():getBodyDamage():setOverallBodyHealth(0)
print(getPlayer():getUsername() .. " Commited Suicide")
end
--writes ban data
function BanDeath.DoBan()
--BanDeath.writeSaveFile();
local banlist = ModData.getOrCreate("banned");
local banDataName = getPlayer():getUsername();
local banDataId = getSteamIDFromUsername(getPlayer():getUsername());
table.insert(banlist, banDataName, banDataId)
-- for k,v in banlist do
SendCommandToServer(string.format("/banid " .. banDataId))
print"BanDeath:writes " .. banDataName .. banDataId )
end
-- triggers every friday IRL
function BanDeath.CheckBan()
local rawtimestring = tostring(Calendar.getInstance():getTime())
print(rawtimestring)
if string.find(rawtimestring, "Fri") then
BanDeath.UnBan()
end
end
--read ban data
function BanDeath.UnBan()
local banlist = ModData.getOrCreate("banned");
local banDataName = getPlayer():getUsername();
local banDataId = getSteamIDFromUsername(getPlayer():getUsername());
table.insert(banlist, banDataName, banDataId)
for k,v in banlist do
SendCommandToServer(string.format("/unbanid " .. banDataId))
print"BanDeath:reads " .. banDataName .. banDataId )
BanDeath.FlushBan()
end
function BanDeath.FlushBan()
--deletes ban data
banlist = {}
end
Events.OnPlayerDeath.Add(BanDeath.DoBan)
Events.OnGameBoot.Add(BanDeath.CheckBan)
Events.OnLoginState.Add(BanDeath.CheckBan)
Events.EveryDays.Add(BanDeath.CheckBan)
i havent tested i really hope i nailed it!
thanking xyberviri and Robot ex140 for the help
It seems it isn't server-side even though it is inside of the server folder, which is very weird
At least according to this error, it's client-side
you could run a function on player load-in to adjust all items on their person and run another for when they look in a container to adjust all items in the container as necessary
the server folder runs on the client too
Yeah, I assumed because it is in a server folder, the server is executing it
and yet somehow some things work in shared but not client, etc.
because of loading order
so it really can throw people
I got it working now, but damn was that weird to debug
It worked in SP with
player:sendObjectChange('addItemOfType', { type = 'Base.SheetMetal', count = largeMetalSheet })```
but obviously SP runs that code server side
and not the case for MP
--- Add Items to the Character Inventory
function addItemsToPlayer(player, itemName, itemCount)
log("Adding Item: ".. itemName .." x"..tostring(itemCount))
player:getInventory():AddItems(itemName, itemCount)
--for count = 1, amount do
-- player:getInventory():AddItem(item)
--end
end
function MSGTweaks_RecipeCodes.ConvertToMetal(items, player, high)
if isServer() then
log("Called Server Side -> ConvertToMetal")
end
local itemValueType = MSGTweaks_RecipeCodes.GetMetalValueType(items)
local skillPoints = math.floor(player:getPerkLevel(Perks.MetalWelding) + (player:getPerkLevel(Perks.Mechanics) * 0.25))
local metalPoints = 1
if (itemValueType == 2) then
metalPoints = metalPoints + 1
end
if (high) then
metalPoints = metalPoints * 2
end
if (skillPoints >= 7) then
metalPoints = metalPoints + 1
end
local smallMetalSheet = 0
local largeMetalSheet = 0
for i = 1, math.max(1, metalPoints) do
local size = ZombRand(0, skillPoints)
if size >= 5 then
largeMetalSheet = largeMetalSheet + 1
else
smallMetalSheet = smallMetalSheet + 1
end
end
if (smallMetalSheet > 0) then
addItemsToPlayer(player, "SmallSheetMetal", smallMetalSheet)
end
if (largeMetalSheet > 0) then
addItemsToPlayer(player, "SheetMetal", largeMetalSheet)
--player:sendObjectChange('addItemOfType', { type = 'Base.SheetMetal', count = largeMetalSheet })
end
--log("Item Value Type: " ..tostring(itemValueType).. " points: "..tostring(metalPoints)..", " ..tostring(skillPoints))
end
Yeah but I thought it was serverside, so I used serverside code - you know because of their weird client/server/shared strut
ah
it's a wrapper
with random
yeah
u can run that on the client - that's how recipecode works
the only thing stopping users from cheating is the lua checksum/etc.
for the time being items are controlled by the client, so you don't need to worry about doing it on the server
a few things have to run on the server, like vehicle spawn-in
and vehicle mechanics is also server side
yeah most vehicle things
if numParts > 0 then
player:sendObjectChange('addItemOfType', { type = 'Base.EngineParts', count = numParts })
end```
this is the default code for taking engine parts
so I referenced that for my recipe, assuming it was serverside too lol
Oh well it works now, so thankfully no more issues 🤞
Just hopefully not too many people sub'd to my mod before I fixed it lol
me, clueless: 'there's no way this mod wouldn't work in mp! i don't need to test it!'
Well it worked perfectly in SP, so I was like OK add to Steam and test on my friends MP, and then yeah - received 0 items
for that kind of testing i release unlisted and test it with that
I had no reason to think adding the item would suddenly break on an MP haha, but next time I will test no matter what lol
Oh that's a good idea
it will make it less noticed if u keep it unlisted for long tho
I have 45 subscribers already, to a broken mod (now fixed)
yeah if i've had a mod unlisted for ages for testing i just reupload it for the actual release
cut is level 8 metal working
i guess u mean cut with a torch'
Yeah lol
cut with torch (weld, because easier) is lv. 4 metalwelding
and cut with saw is lv. 8
🤷♂️
wish there were Recipe.GetItemTypes entries for car parts so that all car mods that add custom parts would already be set up in them
i use a mod that adds a similar feature to car parts for breakdown
on my serv
Yeah that would be nice, I wish some of the item data in this game was easier to parse
function MSGTweaks_RecipeCodes.GetItemTypes.EyeProtection(scriptItems)
addExistingItemType(scriptItems, "Glasses_SafetyGoggles")
addExistingItemType(scriptItems, "Glasses_SkiGoggles")
addExistingItemType(scriptItems, "Glasses_SwimmingGoggles")
scriptItems:addAll(getScriptManager():getItemsTag("WeldingMask"))
end
--[MSGTweaks_RecipeCodes.GetItemTypes.ConvertsToMetal]
function MSGTweaks_RecipeCodes.GetItemTypes.ConvertsToMetalLow(scriptItems)
--- Trunk Lid
addExistingItemType(scriptItems, "TrunkDoor1") -- Standard
addExistingItemType(scriptItems, "TrunkDoor2") -- Heavy
addExistingItemType(scriptItems, "TrunkDoor3") -- Sports
--- Car Doors
addExistingItemType(scriptItems, "FrontCarDoor1") -- Standard
addExistingItemType(scriptItems, "FrontCarDoor2") -- Heavy
addExistingItemType(scriptItems, "FrontCarDoor3") -- Sports
addExistingItemType(scriptItems, "RearCarDoor1") -- Standard
addExistingItemType(scriptItems, "RearCarDoor2") -- Heavy
addExistingItemType(scriptItems, "RearCarDoor3") -- Sports
end
function MSGTweaks_RecipeCodes.GetItemTypes.ConvertsToMetalHigh(scriptItems)
--- Van Style Doors
addExistingItemType(scriptItems, "RearCarDoorDouble1") -- Standard
addExistingItemType(scriptItems, "RearCarDoorDouble2") -- Heavy
addExistingItemType(scriptItems, "RearCarDoorDouble3") -- Sports
--- Hood
addExistingItemType(scriptItems, "EngineDoor1") -- Standard
addExistingItemType(scriptItems, "EngineDoor2") -- Heavy
addExistingItemType(scriptItems, "EngineDoor3") -- Sports
end
for my mod, sports/standard are treated equally, but heavy duty gives more metal - so I did this weird check:
function MSGTweaks_RecipeCodes.GetMetalValueType(items)
for i=0,items:size() - 1 do
local item = items:get(i):getType()
--log(" + " .. tostring(item))
if string.match(tostring(item), "Door") and tonumber(string.sub(tostring(item), -1)) ~= nil then
return tonumber(string.sub(tostring(item), -1))
end
end
return 1
end```
if it returns 2 then it's a heavy duty vehicle part lol
since it's only two types u could have just made it be "IsHeavyDutyPart" and return true or false
<_<
is there really no field for this?
Yeah, I just made it integer based because I was going to seperate them into categories, but I wanted to keep it more simple after talking
I couldn't find it, they're all just called Car Hood
and such
Is there a double door for sports btw, or is that a placeholder lol
can't think of a sports car that would have double rear doors lol
I shoved it in anyway
afaik only heavy has the double doors in use
I think you're right yeah
Also I deleted my original mod and lost my DALLE image sad
Really nice to make interesting mod preview images
How do i get a player name?
Thank you 
Damn, that's a good idea using AI
can use it to make tiles and textures too :p
but instead i wasted all my starter credits making a cow programming at a computer
oh well :)
What's the code for teleporting a player?
I'm having an issue with CanBeEquipped I made a new item, but I can't equip it for some reason 😦
item Bag_TransmogBag
{
DisplayCategory = Bag,
Type = Container,
DisplayName = Transmog Outfits Bag,
ClothingItem = Belt,
CanBeEquipped = TransmogBag,
WeightReduction = 100,
Weight = 0,
Capacity = 0,
Icon = Duffelbag,
OpenSound = OpenBag,
CloseSound = CloseBag,
PutInSound = PutItemInBag,
RunSpeedModifier = 0.95,
CanHaveHoles = false,
ReplaceInSecondHand = Bag_DuffelBag_LHand holdingbagleft,
ReplaceInPrimaryHand = Bag_DuffelBag_RHand holdingbagright,
WorldStaticModel = DuffelBag_Ground,
SoundParameter = EquippedBaggageContainer DuffleBag,
}
local group = BodyLocations.getGroup("Human")
group:getOrCreateLocation("TransmogBag")
Why can't I equip it 😦
You get 15 every month, or you can buy some for $15 - I got early access so thankfully I had a lot of points for free
so did i, i literally used 49 of them making this
the first bunch were exploratory to understand the platform
but some 40 were def all this..
used my last credit to attempt to generate a fuel tank sprite but didn't know it was the last one
result was not good enough
it rolls the dice for the item multiple times
each entry in the items table has <rolls> chances to spawn.
you can also increase this for just one item by entering it in the list multiple times
though that can result in multiple spawning
where rolls cannot afaik
rolls can spawn mutliple times last i checked
ya
And 100 for each item?
Anyone know of an event that triggers the first time someone opens a container? - I am not looking for OnFillContainer - that triggers the first time someone sees the container.
huh. I just got a timeout, I think for mentioning five people in one message. Bah.
Anyway, thanks for the feedback for this question! Having to hook additional events is about what I expected (Itemtweaker hooks OnGameBoot). OnEquipPrimary is probably a solid bet, though I'm gonna look into the events for opening containers and players spawning too.
huh. Where's the list of all the events? I thought they were in the lua files somewhere, but apparently I'm wrong.
I believe the wiki is up to date
Good enough start, thanks.
found it, it's in the java. zombie/Lua/LuaEventManger.java
How can I check if the mod is running on a server instead of a client? 🤔
isServer()
Thanks mate
more specifically:
Oh, my dude, I'll kiss you
Is there a way to make a delayed call? 🤔
Like calling a function after X second? 🤔
I've been making really good progress on my vaccine mod, I do need to save the state of the players immunity level, is there any way for mods to save data when the game is closed, so it can be retrieved after loading the same save?
you could add a function to OnTick that counts up a variable every time it's called, and when it reaches a certain number it calls another function and removes itself from the event
well, depending on how long you want the timer to work, you could use a flag and a EveryTenMinute call. if you want it to be a delay in real time, I think there is some way to get the real time clock and use that instead to make sure it happens so and so many seconds/minutes later
IsoPlayer moddata should be preserved. you can store it there.
I need to make a delayed call, so that the main mod I have can check if the optional mod is preset, and if it is present then it has to do a different thing
can't you just do a isactivated call?
IsoPlayer moddata, what function would I need to call to add data there?
can't you just use getActivatedMods():contains()?
The issue is the optional mod requires the main mod so it will be loaded after main one, and by the time the main one as been loaded the code would have run
no it should be fine
player:getModData() returns a table you can use
the getActivatedMods():contains() checks which modid's are active for that save, so it doesn't need to be loaded already
amazing @bronze yoke - That's exactly what I need.
i don't think this is an issue, but if it is can't you just use a require or OnGameBoot?
Would OnGameBoot work on server too? 🤔
the require would be kind of weird actually don't do that
i think so!
Alright, I'll give it a look, thanks mate
Is there any onHour, onDay, events, or should I just use the OnTick event. I only want my function to trigger either each hour or each day since OnTick would be overkill.
Is there anywhere I can go or any function I can call to get a list of all Events available to mods for the game?
awesome, thanks so much
So you know how zombies have a small chance to resurrect if left to rot?
Is it possible to have the zombie act differently when it does? For example, have it become a sprinter?
if i want to replace a function of a vanilla lua file Fishing/BuildingObjects/FishingNet.lua do i have to recreate the same folder structure or can i simply put it in lua/server/patches/FishingNetPatch.lua and import the function and replace it?
kind of depends. if the file is using some local tables, you need to replace the file entirely. if not, and you only want to replace some function, you can just replace the function. there are some other cornercases too though. like for example, if the function you are replacing is being put into a event handler, you need to manually remove the old one and add in the new one. replacing the function doesn't work
UI also is like that
Is anyone currently working on a mod that changes the behavior of zombies to "swim"?
Can I suggest a mod here?
I think having like aristocratic outfits from colonial times and also having muskets and powder weaponry would be pretty cool
does anyone have a good modpact for single player?
Steam Workshop: Project Zomboid. Image made by twitter.com/Im_DaFox
make the path/name of the mod u want to load later come after the one it needs
easy way out is to prefix the mod that must come first with something like 0_, and prefix the one that must come later with something like Z_
mind the path does matter, so folders and such change things alphabetically
if you can't choose the name of the stuff in one of the mods
then u can do something like
ModName = ModName or {}
on both
and store stuff in there to call in the one that runs later
cause it to execute via an event to ensure it runs after everything loads if u dont wanna mess with names
On coop-host, does the server and client lua code run in the same environment? Or separated (separated variables, etc)?
honestly the best solution would just be to do the following rather than any funny business with filenames if you want the optional mod to load before something in the main mod.
if getActivatedMods():contains("submod") then
require "submod files"
end
Just use getActivatedMods():contains() as suggested. It doesn't check whether a mod is loaded already. It checks whether it has been activated
yeah if i had known about those features when i wrote my stuff i might have gone about things that way
but u dont always have a choice when patching others' mods
so it's important to know the other things you can do
Mm, if you need funny business to load before or after another mod loads its lua files, pz loads the lua files in alphabetical order, so you can rename your files accordingly
Can then override functions, muck with metatables, all kinds of goodness
Need mod suggestions just got the game
Alternate Inventory Rendering. Otherwise you want #mod_support, this channel is for dev work.
@weak sierra So I'm looking through my options, and I haven't been able to find the event you suggested, for when an inventory container is opened. What would that event be?
if you are still looking for an event for opening containers, there isn't one
you didn't suggest an event, but you did imply there was an event for that that.
on player load-in
oh
yeah
eggon does it for trunks
poke around this, might only be trunks that can do it idk
i think it hooks the UI
for container switching in the right pane
yeah, I'm digging through both the java and lua to find where it'd be. I'll update here if I find a good one. At the moment my best thought is actually to use neither and instead hijack the code for OnPreFillInventoryObjectContextMenu
that way whenever they right click on an item it would check that item
thats actually a great idea
the stats only matter when the player is looking at them, so the context menu one would work
Nah, but this is meant for hot-adds - and telling them "right click to update your guns" is at least a good option
but you should still use the OnequipPrimary or the secondary one as well
why not just hook the function that populates the inventory and throttle your code?
then they dont have to do anything
How would I go about hooking it? That is the best choice, but I don't want to overwrite game files and at the moment I only know how to hook events.
local original = Whatever.TheOriginal.Is
function Whatever.TheOriginal:Is()
--do stuff
original(self)
end
(I'm also running into the situation that I'm not seeing a great way to blindly edit arbitrary values the same way that can be done on prototypes)
but that's likely just me not understanding the interactions between Lua and Java
look at the code for the admin/debug item editor screen
shud tell u how to go about that
Hm. Good thought.
it'd be nice if I could just DoParam on existing items, but that doesn't seem to work...
and gotcha re: hooking. So it's easy to override with a copy of the original
the setters should probably be these ones here. https://zomboid-javadoc.com/41.65/zombie/inventory/types/HandWeapon.html
Javadoc Project Zomboid Modding API declaration: package: zombie.inventory.types, class: HandWeapon
yeah, that's the realm I was poking. had some trouble being sure I was working on the right stuff.
It was erroring in that for loop because something was nil
actually an issue with this MIGHT be for users of Alternate Inventory Rendering, I'd need to make sure that it works for them too
I just want to say, I really think that just having 2 functions, one in the OnPrimaryEquip event, and one on the OnPreFillContextMenu is a much cleaner solution. OnPrimaryEquip will make sure the stats are correct in any case when the player is trying to use it. and OnPreFillContextMenu will cover all instances when a player is trying to examine a item, so the stats are correct in the tooltip and such.
Yeah. It's probably the cleanest, I'm just really hoping to get ones that don't require equips. I also just realized that I need to flag an item as fixed, so that it doesn't screw up things after an attachment has been added.
hooking into a function is nice, but can be easily overwritten by other mods. ofc if everyone did things properly, and also used hooks it would be fine, but many people do not write mods well, and will just overwrite it
yeah.
that's another great argument for using events, frankly
if only there was an event for items switching between containers...
even if there was, I don't think you would need it. the other 2 events already cover any player facing points where the stats would need to be correct
well, prefill is only for right clicks. The hover menu would be a better event, but I'm not sure if that's got an event - or at least, not what that event is
like, it doesn't matter if the stats are technically "wrong" while being moved from one container to another, as long as when you are trying to use the weapon it is correct
yeah
oh i see thats a good point
and, worst case, I'll fall back to equipping
or hell, slap a custom right-click option for "refresh stats" on it
have it fire off with a screwdriver in inventory, remove all the modifications, update stats, re-add attachments
so make sure your function that hooks comes later
in the load order

you can, but then you need to fix it every time another mod comes around
much easier to avoid hooking when you can
yeah, it's not a great solution since it's relatively fragile
I wonder how viable it is to add custom events from the lua...
in this specific case for the hover, I think you may need to use a hook, as there isn't an appropriate event
take a peek at ISInventoryPane:update() and ISInventoryPane:updateTooltip()
thanks
you might be able to hook onto those. although I think they might get executed every tick, so there might be a better function to hook onto somewhere nearby
Probably, yeah. I want this performant. And the more I think about it, the more I think a custom right click option when you have some required tools in hand would be the better option.
it's manual, but it gives a performant way to update live saves that also doesn't run into issues with attachments
well, id try the hook, and check if there is any performance issue. you are only checking the item, and you can just a flag short circuit any repeat calls.
how would I store that though?
that's not ur problem that's the server owner or end user
they have to know how to set up their mods
or they can come ask about it
yeah, people will definitely still come complaining to you about it
that's a pretty limited way to look at it, server owners and end users are stupid and you want to avoid things thy can break
i hook all over my mods and i have never had one complaint
then you are very lucky
maybe
probably also not hooking things that are liable to be overwritten
it'd have to be popular spots to overwrite
eyah
tbh if a mod overwrites things it's written poorly
if i see that i usually tell them to change their approach
whereas "the code that populates the inventory" is a pretty hot zone
you can store it in the moddata. it technically won't be there permanently as it is wiped on restarts, but you don't need it to persist that long
moddata on InventoryItems and vehicles is not persisted, but other moddata is, to be clear
hm. A viable solution then. Still, I have to worry about items with attachments, since the game is just updating their base stats separately
can you give me a reference for moddata and how to use it?
can programmatically remove the attachments, update stats, then reattach them
or just count up the stat changes and add them to ur application
yeah, that's my thought. Part of why I think it being a manual fix is a good idea.
i've considered making a mod to do the thing ur talking about for a bit
but it's low priority for me
Let me know if you do. I'd hoped ItemTweaker was the solution I needed but it turns out it only works on prototypes.
for this its fairly simple since you only need it to work client side.
local moddata = item:getModData()
moddata["yourmod"] = {}
Sick, that's hella simple
then you can just manipulate moddata as a normal lua table
item:getModData()["thing"] = stuff
the worst part of my digging around is that there's so many events for inventory manipulation and none of them do what I want
actually yeah, make sure you are putting yourstuff into your own index in the moddata, incase some other mod is also doing stuff with the moddata
Yeah, the usual code cleanliness, even if it's just variable prefixes
im cranky cuz i've been working on vehicle respawn mod all day
if u think inventory manipulation is a headache

I hear that. I've got like.... six different java AND lua files open right now, and that's only after closing ones I didn't think were helpful. And the java is in Eclipse because it got hefty enough that I needed cross-file references
I can only thank my past self for getting good at file manip for figuring out where keywords are to have made this slightly less of a pain
checking - ISUpgradeWeapon = ISBaseTimedAction:derive("ISUpgradeWeapon"); is this creating a new timed action here? And then they override the needed functions?
I'm used to inheriting, so I assume this is the logical reverse of that
Nevermind, it seems that's setting up the code for removing items, and then the actual context menu information is elsewhere
oh, gross! The upgrades are all hard-coded for each one!
Is there a "simple" way to make zombies walk on water?
Right... getting some good research done on this, at the very least I know how to access the part data that I need, even if certain things are going to need to be a hard-coded if-tree in the lua, I could probably implement a custom version of ItemTweaker that worked on generated objects too.
well, you could make the water tiles just normal tiles that can be walked over, but then everything would be able to go over them, players and cars