#mod_development
1 messages Β· Page 233 of 1
Good morning.
"Morning"
protected float getAlphaUpdateRateMul() {
float var1 = super.getAlphaUpdateRateMul();
if (IsoCamera.CamCharacter.Traits.ShortSighted.isSet()) {
var1 /= 2.0F;
}
if (IsoCamera.CamCharacter.Traits.EagleEyed.isSet()) {
var1 *= 1.5F;
}
return var1;
}
protected can't be patched?
sad...
No hint on a first iteration of the b42 beta on today's thurdroid. Sad π¦
Did some full-on cooking this morning for Breakfast and made prep rice for dinner. =)
Time to do some awesome modding. :D
I just realized that 41 only publicly released at the end of 2021. It's actually been a few years now.
Wow.
<@&671452400221159444>
Cheers
The content in the blog post is really good.
If I want to kill a player if it uses an item, is there a way other than setting damage ?
Like player:setDead() or alike ?
and that would put the player in a state that he becomes a zombie (as if he died from zombies bites)
One thing tho that maybe needs some explaining is that no matter how much I adjust the spawnrate of an item it seems to always spawn in the same amounts
So i got a question, guns of 93 doesnt have compatibility in The Workshop mod, so you cant dissasemble those guns, but if you add a tag to the guns they can be used in the recipes from TW. is it possible to check for items that have the subcategory firearm and doparam a new tag to them? or is there some other easier way to achieve my goal? looking into it now, but figured maybe someone had a quick answer fo rme
player:Kill(anything)
The variable can be anything, even nil, but you need to pass it or you'll throw error
And yes that function has a capital first letter for no good reason and sounds like you're killing someone else π
If you want them to become a zombie, infect them first
ok so player:Kill() will work as intended ?
I was exploring also
player:setHealth(0)
yes Kill works as intended
Yes but you do need the param
Cannot just call Kill() even though the param can be nil. It's Javaside and Java is strict about getting the number of fields it expects
I often write it as Kill(me)
Even though I don't define me
local function zReWeaponAdjuster()
local items = getAllItems();
for i = 0, items:size() - 1, 1 do
local tags = "";
local item = items:get(i);
if item:getTypeString() == "Weapon" then
if item:isRanged() then -- isAimedFirearm() i'm not sure
tags = "Your;Tags;Here";
end
zReWeaponAdjuster2(item:getFullName(),"Tags",tags);
end
end
end
local function zReWeaponAdjuster2(Name, Property, Value)
local Item = ScriptManager.instance:getItem(Name)
if Item then
Item:DoParam(Property.." = "..Value)
end
end
all firearms weapon be with tag
Thatβs funny
ah yes, that helps me alot, thanks!
Could the parameter be attributive? Like crediting something for the kill?
It's possible. I never use it that way so dunno
The param is an IsoGameCharacter
So that seems a likely purpose
Also no idea what the point of identifying the killer would be
I guess scoring in PvP somehow maybe
wdym by that ?
If I call in a function player:Say("Blabla") and I want the "Blabla" to be stored in a translate file, how I should do that ?
I tried player:Say("UI_blablatext") and added in my lua/shared/Translate/EN/UI_EN.txt :
UI_blablatext = "This is my texte",
}```
but it doesn't work
player:Say(getText("UI_blablatext"))
ok thanks π
also, how can I have Γ© or Γ or other accentuated characters ? because I also make a FR folder with FR files, but when I use Γ© it's bugged, even if in the vanilla files it's also accentuated characters that are used
this ?
yup
Your accents might still be broken and you might need to replace them but once the file has the right encoding it should be good
ok thanks
However uploading directly in github seems to break it sometimes, not sure about github desktop if it breaks it too
If I were to make a game which involved damage and killing, Iβd use some way to tell the game what exactly killed the player or npc. So a parameter would be used in those brackets. Triggering that through a command line would throw an error if I didnβt have a default value set
Iβm speculating, thatβs all
eh
i can put here custom folder, which will not be read?
Most likely yes
nice
for a mod I used the granolabar models and textures and modified the texture to have a custom item. I would like we see the object in hands when the character is using it. It could just copy the character animation when we search in our backpack, but with the object in primary hand. Would it be a simple task to mod that or not ? (just to know if I can investigate or if I drop π )
https://steamcommunity.com/sharedfiles/filedetails/?id=3053141858
this is can help
I don't understand what you are trying to do here
see the object in hand ? Or have an animation when you have the object in hand ?
Thx
Ideally both, at least see in hand when player have it equiped (and I'll use the luautils equiping requirement to force equip on use).
easy to do
It's 2 different items : an "autotest" and a serynge
You have to make a model to have it show in hands and when using the item you can trigger an animation
I have the model with a .fbx file, and a .png texture
I also defined the _Ground mesh
when the new version comes out will the mods be all down or will they work with the new version
I am currently having troubles with modding my multiplayer server so honestly idk
im new to this modding thing so im trying my best here.
Chevalier evolution VLC π
Is it possible to have the player confirm an action after they got a warning ? (Example : player use a serynge, they get a warning : are you sure ? then they have to either click a box to confirm, or do the action a second time. I guess with the player modData I could do that right ?
Yes there is actually a confirmation dialog that can be provided a function to run when user says yes. Idr exactly the code I used last but there is a simple example in Wookiee Gamepad Support in the part of the code that adds a confirmation popup to exiting a server
Sounds like something that you could make as a generic action that executes an action based on a button click.
Oh silly me. If there's already something then yeah use that.
I'm not home or I'd just post the code
Might be ISModalDialog can be used for that iirc
Gaha sorry
I can't wait to sink my teeth into the ISUI documentation.
Idr exactly the code to implement for that purpose but it's p straightforward
I'm looking forward to it, in particular because I'm pretty certain there's a bug in one of the vanilla Lua files related to its handling of callback parameters
But I haven't been able to find it again after noticing it the first time, and I didn't make a note of it π© so hopefully taking a look will give a reason to track that down
The bug being that I believe there's somewhere that passes something like param3, param3 rather than the third and the fourth. Only a bug with respect to mods using it (probably) & presumably something less common or it would've been called out
tyvm π gonna dig ISModalDialog then
Ah okay. Thanks for making me aware of the issue.
Of course, maybe I'll beat you to finding wherever it's hiding π
I'm pushing code to the live web branch for Mallet. It should be available in ~ 2 minutes. Did some fixes and improvements to the UI.
So I would need to call for ISModalDialog:new(x, y, width, height, text, yesno, target, onclick, player, param1, param2) right ?
Yep
@frank elbow I want to take luaparse and generate my Rosetta objects like how you render Lua typings.
This should be a huge speed-boost for production of documentation.
Yo I just got home I'll show you one working way to do it.
I'm unsure I understand; you mean to go from Lua source to Rosetta JSON?
tyvm π
Ah, so people can input a file and have a starting point?
From Lua source to the Rosetta API.
Yeah.
oh, that reminds me
That'd be neat
at least one ISUI class uses multiple inheritance - since derive() doesn't support that they just merge the table with a pairs loop, which means nothing we have picked that up
i think it was ISPanelJoypad, i wouldn't be surprised if more of the joypad ones did it too
Alright. If this affects how we render Lua typings then we'll need an issue to sort this out.
That'd make sense. Does Rosetta have support for specifying multiple base types? Or would that just look like defining the return as an A, B string?
I only have an extends field ATM.
We can modify the schema if this is something that can occur.
LuaCats supports it with the comma, so presumably just having a comma in the field would do it. May be ideal to allow an array in the schema, yeah
For returns we have a string field for type.
It arbitrates in the web tool to make it friendlier / easier to manage.
i'm deep in the c++ mines but i'll take a quick look to see if any other classes did it
You can do this in Mallet but it requires the Custom type option.
it makes the intellisense for the class in question nearly useless since almost all of its interface is inherited from the pairs'd class
and afaik the joypad classes are preferred over the non-joypad ones so we should make sure they work okay
Alright. I'll keep this in mind.
here it is```lua
ISCollapsableWindowJoypad = ISPanelJoypad:derive("ISCollapsableWindowJoypad")
-- HACK
for k,v in pairs(ISCollapsableWindow) do
ISCollapsableWindowJoypad[k] = v
end
I do remember seeing that π€¦πΎ forgot all about it
Ultimately as long as the typings can render for both or all derives then we should be good.
I'm probably not going to continue with the static analysis I had going since it wasn't ideal, but if we can specify it in Rosetta LLS at least can handle it. Can't speak to the older annotation system (with the name that escapes me)
emmylua 
That's the one π I'll see whether it handles that, I think it does
not sure if i've mentioned it to you but we target lls exclusively now
Oh thank goodness
emmylua fell behind lls a long time ago, the reason it was previously the 'primary' target was because it supported intellij
but the first 2022 build of intellij rewrote some core part of the api that means emmylua doesn't support indexing anymore, and it has never been updated to the newer system
so it's becoming increasingly outdated and impractical, no sense in targeting it
Hooray for things with better alternatives becoming obsolete. I hope there's at least a way to set up the language server with IntelliJ, for those who do prefer it
But as a loyal VS Code user that is music to my ears either way
yeah, i'm not happy about it but i finally jumped ship a few months ago
there's a couple alternative lua plugins for intellij including an lls port but none of them seemed like they were in an impressive state
That's a shame, I hope the IntelliJ plugins catch up
for those who choose to stick to older versions of intellij, the annotations are mostly cross compatible anyway
LLS has been diverging a bit more here and there lately, with stuff like exact types
But idt we'd need that for Umbrella anyhow
Yeah..
emylua documentation is horrendous too.
So like we could actually be a good source for documentation by knowing what we can do with lls.
I remain peeved that there are some things in EmmyLua that are exclusively documented in changelogs
I was okay abandoning EmmyLua before anyone else.
I'm a vscode guy and will push people to go there.
(Wrote extensions for PZ modding development in it)
local Example = {}
Example.completeProcess = function(target, response, param1, param2)
if response.internal == "YES" then
-- do yes stuff
else
-- do no stuff
end
end
Example.showConfirmationModal = function()
local width = 400
local height = 120 -- Matches vanilla game exit confirmation
local x = (getCore():getScreenWidth() / 2) - (width / 2)
local y = (getCore():getScreenHeight() / 2) - (height / 2)
local text = "Are you sure?" -- Or whatever translation using getText("UI_translation_variable")
local yesOrNo = true
local selectionProcessingFunction = Example.completeProcess
local player = getPlayer() -- Depends on situation; ideally call this from somewhere that provides a player object.
local param1 = anythingYouNeedToPassToOnClickFunction
local param2 = anythingElseYouNeedToPassToOnClickFunction
local confirmation = ISModalDialog:new(x, y, width, height, text, yesOrNo, target, selectionProcessingFunction, player, param1, param2)
-- Enforces size/position you chose.
-- :new may choose its own width and position otherwise.
confirmation.x = x
confirmation.y = y
confirmation.width = width
confirmation.height = height
confirmation:setAlwaysOnTop(true)
confirmation:bringToTop()
end
return Example
Something like this
Idk I may have a typo or an oversight
But it's close to that.
i remain fiercely loyal to jetbrains ides but it went too far even for me
I ran into a bug with custom types however Mallet is incredibly stable.
The code for it is developed in preparation for Java documentation.
I'm going to document Java API for PZ too.
Where was the link to the collaboration repo you'd mentioned the other day? You said it was in the intro blurb but I didn't interpret anything there as that (unless I misunderstood)
In the interest of not duplicating work you're doing
(In reality I have a custom version of the modal-creation process that uses the width of the text I choose to set the width and x-position of my modal, but I wanted to keep example simple.) @violet shell
What I mean is a place to organize who's documenting what in the vanilla code
I have a repo for patches. Hold
Working on this issue lol
Thanks a lot
If you get any errors you can't solve, ping me.
So, where I put that code and how I call for it ?
Ah, the Mallet repo will hold the community docs?
Maybe. I'm making a new repo actually for the patches.
One can make their own patch.
I will make mine.
Well, depends on what you're confirming. If you're using a syringe, I would probably call it from the use function for using said syringe.
@violet shell
My plan is to passively write documentation on my own patch and allow for people to use it.
And ideally that function will have access to player
So you could edit what I wrote to pass player to the function showConfirmationModal
Accepting contributions, I hope? There's a considerable amount to document & I see no reason not to encourage community effort
@frank elbow My patch will be here. https://github.com/asledgehammer/RosettaPatch
Yes.
I plan on adding a field at the class level for documentation authors.
my second pass on events is close to complete
(and has come to encompass a little more than events)
The thing is that since this will be a lot of work I'd like to open up the option for people to donate or contribute money to the project.
I'd like to keep this FOSS and available for anyone to do.
This will also open up the ability to translate documentation to other languages.
Rosetta is solving the biggest problem plaguing PZ's modding community: Documentation.
@violet shell So basically you decorate that syringe use function and you instead call the modal dialog and only call the original function if they say yes.
I'm sorry I don't get it. I have to call the Example.showConfirmationModal () ?
Right... and adjust its parameters to pass anything you'll want or need to pass it.
You say you want to do this when you use a syringe... is that from a mod?
Idr if syringe use is vanilla. I cannot find any mention of syringes in vanilla.
it's in my mod
it's a mod that adds a trait you can take that gives you 2 autotests and 1 experimental injection. All those are biocoded so only you can use it safely.
if you try to use an autotest not coded with your biocode, then it's wasted, if you try to use the serum that isn't yours, you have a bigger chance to die, so I want that the player confirm their choice
Okay well what is the function that activates use of the injection and makes the things happen when you use the item in your mod?
i don't think the recipe framework will support this very well
This one? Inject_Biocoded_Cure
I mean if the function is being called we can run it through a confirmation...
yes, and if the biocode match is false, it calls WrongInjection
you can't really catch 'about to craft something'
which is not finished
Oh so you're saying items will disappear regardless of the outcome of the modal
Biocoded_Cure_Exp,
Sound:BreakAmpule,
Time:120.0,
Category:Health,
CanBeDoneFromFloor:False,
NeedToBeLearn:False,
OnCreate:Inject_Biocoded_Cure,
Tooltip = Tooltip_Inject_CureExp,
}```
yeah, you can't really make a recipe trigger something *before* you craft it, only after
No, I'll reinject the item in player inventory if it says NO
That's a fair enough workaround most likely.
oh, yeah, then just putting it in your oncreate is probably fine
Just replace used items and remove the ones you'll get
I'll make the recipe "Keep" the item, and make the item disappear in the function that uses it
to remove an item it's player:getInventory():Remove(item) ? right?
or player:getInventory():DoRemoveItem(item) ?
local zReBLBP = win.character:getInventory():getFirstTypeRecurse("BobbyPin")
local zReBLHBP = win.character:getInventory():getFirstTypeRecurse("HandmadeBobbyPin")
if zReBLBP then
zReBLBP:getContainer():DoRemoveItem(zReBLBP)
elseif zReBLHBP then
zReBLHBP:getContainer():DoRemoveItem(zReBLHBP)
else
ok, and how I check their hands, inventory & bags/containers ?
I have to check both inventory & container ?
so it would be like that :
player:getInventory():getContainer():DoRemoveItem(items:get(0));```?
You can manually check for those.
local locationList = {"Back", "FannyPackFront", "FannyPackBack"}
for _,location in pairs(locationList) do
local bag = player:getWornItem(location)
if bag and instanceof(bag, "InventoryContainer") then
local container = bag:getInventory()
-- code for removing the items (example: container:Remove(item))
end
end
-- check bags equipped in hands
local itemA = player:getPrimaryHandItem()
local itemB = player:getSecondaryHandItem()
local itemList = {itemA, itemB}
for _,item in pairs(itemList) do
if item and instanceof(item, "InventoryContainer") then
local container = item:getInventory()
-- code for removing items
end
end```
Only disadavantage of this approach is that it may it not work for all bags/backpacks in case players use mods which allow to carry more bags than the vanilla game does. To make it compatible with those type of mods, you could iterate through all clothing items the player wears, check whether they are a container (use ``instanceOf(clothingItem, "InventoryContainer")``) and then delete the items.
Something like this:
local Example = {}
Example.fixInventory = function(player, confirmed)
-- To be done.
end
Example.completeProcess = function(player, response, items, result)
-- response.player will be playerIndex due to how vanilla ISModalDialog works.
if response.internal == "YES" then
Inject_Biocoded_Cure(items, result, player)
Example.fixInventory(player, true)
else
Example.fixInventory(player, false)
end
end
showInjectionConfirmation = function(items, result, player)
local width = 400
local height = 120 -- Matches vanilla game exit confirmation
local x = (getCore():getScreenWidth() / 2) - (width / 2)
local y = (getCore():getScreenHeight() / 2) - (height / 2)
local text = "Are you sure?" -- Or whatever translation using getText("UI_translation_variable")
local yesOrNo = true
local selectionProcessingFunction = Example.completeProcess
local confirmation = ISModalDialog:new(x, y, width, height, text, yesOrNo, player, selectionProcessingFunction, player:getPlayerNum(), items, result)
confirmation.x = x
confirmation.y = y
confirmation.width = width
confirmation.height = height
confirmation:setAlwaysOnTop(true)
confirmation:bringToTop()
end
return Example
And change recipe to call showInjectionConfirmation instead.
Might honestly just want to throw that in a global module for use with recipes.
But regardless this should in theory do the thing
Again I'm not really testing, so, you know, can't guarantee it's perfect code, and lmk if you can't solve any surprise errors.
But it's close to what you would need.
ok, I just don't understand the return Example at the end (I'm sorry, I'm mostly a selflearner/dabbler)
It's just a helpful compatibility-oriented practice to return your original locals functions / variables in an accessible module at end-of-file for other modders who may someday want or need to patch what you've done.
If that stuff were all in lua/client/Example.lua (which to be clear would NOT be a good name for a file in practice lol), you could do
local Example = require("Example")
to import that table from its file.
And then e.g. people could decorate the function that happens when people confirm the injection.
ok
so I should put all the example bloc in a separate file, and call it with require() ?
showInjectionConfirmation = function(items, result, player) and
function showInjectionConfirmation(items, result, player) are the same right ? @thick karma
@frank elbow I fixed known bugs I've seen for Mallet. =)
bro, i need your help
i cant overwrite client commands...
Vanilla:
if isClient() then return end
local ClientCommands = {}
local Commands = {}
Commands.object = {}
Commands.object.shovelGround = function(player, args)
--some stuff here, nevermind.
end
i need just overwrite this func, like do nothing
if isClient() then return end
local zReMS_SERVER_IJECTOR = {}
-- ClientCommands.lua (server/)
zReMS_SERVER_IJECTOR.old_Commands = {}
zReMS_SERVER_IJECTOR.old_Commands.object = {}
zReMS_SERVER_IJECTOR.old_Commands.object.shovelGround = Commands.object.shovelGround
Commands.object.shovelGround = function (...)
-- do nothing
end
return zReMS_SERVER_IJECTOR
but this is not work
if the file you're targeting is in server/ you can hook Events.OnClientCommand.Add to snipe the event handler
how? oo
Yeah, those are the same. And yes, after you rename Example to something fitting for your mod, putting it in its own file and importing it to use it is standard practice. Maybe Example in your case could become InjectionRequests or something.
ok thanks
Of course in this case if those functions will only ever be called by the associated global, there may never be a purpose to importing Example anywhere else. You can just leave the recipe's global trigger function in the same file as the Example module stuff, and that function will have access to that stuff.
But you may prefer to have a GlobalRecipeFunctions file or something in a parent folder of your mod, i.e. something like lua/client/AsilarMod/GlobalRecipeFunctions.lua and then import Example stuff for availability there
It's a little bit of a stylistic judgment call based on how complex you expect certain files to get, in my opinion.
local old_add = Events.OnClientCommand.Add
Events.OnClientCommand.Add = function(handler)
-- need some way to ensure you are actually hooking the right one
-- since vanilla files always load in the same order you could just use a counter, call old_add until the xth one
-- might also be able to check which file the function comes from directly using some of the debugger functions? might only work in debug
old_add(function(module, command, player, args)
-- do nothing if it's the module and command that triggers the function you want to delete
if module == "Module" and command == "Command" then
return
end
handler(module, command, player, args)
end)
-- reset it after replacing the handler so you don't yeet some random mod functions
Events.OnClientCommand.Add = old_add
end
getFilenameOfClosure(handler) if it's not debug only
don't understood about it?!
you can stop that function from running by using this to stop the event handler if the command that triggers it is fired
but it is difficult to determine that you are hooking the right event handler
unless it is non-local
I'm here right now, I changed a little your code, because I don't want the confirmation window to popup if the player uses their own serynge
I have an issue there : both files require the other one
because I call function Injection_confirmed (items, result, player) in both files
or should I place it in your second lua file, and call it InjectionRequests.Confirmed ?
If the same function IS required to be imported to multiple other files, it is usually best to pull it out and put it in a 3rd file. However, that global function does not need to be imported.
Also you're missing a closing " on your getText call
fixed it π
That's why all the colors are wonky in your post.
Also you have return Example sitting in the middle of your file
Definitely can't do that
@thick karma is this a way to avoid the issue ?
Returning the local module needs to happen at the end.
yeah, I was not sure what to do with the return. I'll put it at the end of InjectionRequests.lua file
Also ```lua
InjectionsRequests.completeProcess = function(player, response, items, result)
-- response.player will be playerIndex due to how vanilla ISModalDialog works.
if response.internal == "YES" then
Injection_confirmed(items, result, player);
InjectionsRequests.fixInventory(player, true)
else
InjectionsRequests.fixInventory(player, false)
end
end
Example -> InjectionsRequests
I also wouldn't leave showInjectionConfirmation as a global if you're no longer calling it from recipe file.
Pretty much the only reason to make functions global is to make them callable from those recipes.
something like this```lua
-- this code MUST be placed in shared so that it runs before vanilla server code
local old_add = Events.OnClientCommand.Add
Events.OnClientCommand.Add = function(handler)
local originFile = string.match(getFilenameOfClosure(handler), "media/lua/(.+)%.lua$")
-- not sure what file you are trying to hook, put its full path after lua/ here
if originFile != "server/ClientCommands.lua" then
old_add(handler)
return
end
old_add(function(module, command, player, args)
-- do nothing if it's the module and command that triggers the function you want to delete
if module == "Module" and command == "Command" then
return
end
handler(module, command, player, args)
end)
-- reset it after replacing the handler so you don't yeet some random mod functions
Events.OnClientCommand.Add = old_add
end
Unless perhaps it's an easy-access function for debugging by hosts.
Even then you could use a triggered event to avoid that.
@thick karma Shouldn't this local selectionProcessingFunction = InjectionsRequests.completeProcess have arguments passed ?
like local selectionProcessingFunction = InjectionsRequests.completeProcess(player, items, ...)
Something like this.
Absolutely not. That variable points to the function's definition (the things it does). Using parentheses would cause it to take the function's result (the things it returns when it's done).
Very important distinction to understand.
ISModalDialog will call the actual function to produce a result here:
This is why the processing function takes player, response, items, result.
InjectionsRequests.Confirmed(items, result, player); -> InjectionsRequests.confirmed(items, result, player)
(honestly I'd lose all the unnecessary ending ;)
(I don't like unnecessary coding punctuation personally)
originFile ~= ?
Where is InjectionsRequests.lua, first of all? InjectionsRequests appears to be a structure in this file, so importing it via require doesn't really make any sense to me at a glance...
!= - it's java?
Yeah, the injection block will be transfered into its own lua file afterwards, it's just to have only 1 file to transfer for now
nah, not working...
In the example I sent back to you I made several changes I would recommend; abstractly, I would group the global functions in your file together and group the subfunctions of InjectionsRequests together, and I would make every function that does not need to be called by the recipe code (such as showInjectionConfirmation) a subfunction of InjectionsRequests
@violet shell
I would just post the correct 2 files you plan to use. It's hard to know whether you're understanding fully the way you've written it. But the require line at least would be wrong. Assuming InjectionsRequests.lua exists, you would want:
local InjectionsRequests = require("InjectionsRequests")
No .lua
Your example still currently indicates you're trying to return from the middle of a file, which is not allowed.
(Unless it's a conditional return.)
(And bear in mind that conditionally returning from middle of a file stops rest of the file from ever loading.)
@thick karma
i want hook "server/ClientCommands.lua"
yes this is on the right track. Not sure if there are any typos I'm overlooking, but the general format is right.
Also do you call CurePlayer from recipe or not?
Ahhh no
CurePlayer needs to move
I move Cureplayer to InjectionsRequests too ?
been writing too much c++ π
Also just FYI I would recommend you make all functions lowerCamelCase naming convention, personally. @violet shell
It's how Java does it and Lua has no standards, so unless we look to Java for standards, we just get chaos.
(PZ is Java-based so it is not a random choice for a source of standards here.)
ok π
also, I don't understand function InjectionsRequests.completeProcess(player, response, items, result) -- response.player will be playerIndex due to how vanilla ISModalDialog works. if response.internal == "YES" then InjectionsRequests.fixInventory(player, items, true) InjectionsRequests.Confirmed else InjectionsRequests.fixInventory(player, items, false) end end
Modules like InjectionsRequests get capitalized though
And Lua filenames tend to be capitalized throughout vanilla and in most mods.
Particularly the InjectionsRequests.fixInventory(player, items, true) I though you cannot pass arguments with those functions
Eh? Sure you can.
local old_add = Events.OnClientCommand.Add
Events.OnClientCommand.Add = function(handler)
local originFile = string.match(getFilenameOfClosure(handler), "lua/server/ClientCommands.lua")
-- not sure what file you are trying to hook, put its full path after lua/ here
if originFile ~= "server/ClientCommands.lua" then
old_add(handler)
return
end
old_add(function(module, command, player, args)
-- do nothing if it's the module and command that triggers the function you want to delete
if module == "object" and command == "shovelGround" then
return
end
handler(module, command, player, args)
end)
-- reset it after replacing the handler so you don't yeet some random mod functions
Events.OnClientCommand.Add = old_add
end
in shared, not work...
I think you must have made another error and mistaken the cause... Those functions can definitely receive arguments.
or i should path file where call sendClientCommand(self.character, 'object', 'shovelGround', args)?
that may be easier

local zReMS_INJECTOR = {}
-- ISShovelGround.lua (client/BuildingObjects/TimedActions/)
zReMS_INJECTOR.old_ISShovelGround = {}
zReMS_INJECTOR.old_ISShovelGround.perform = ISShovelGround.perform
function ISShovelGround:perform(...)
self.emptyBag:setJobDelta(0.0)
if self.sound ~= 0 and self.character:getEmitter():isPlaying(self.sound) then
self.character:getEmitter():stopSound(self.sound);
end
local sq = self.sandTile:getSquare()
local args = { x = sq:getX(), y = sq:getY(), z = sq:getZ() }
-- zRe sendClientCommand(self.character, 'object', 'shovelGround', args)
-- FIXME: server should manage the player's inventory
if self.emptyBag:hasTag("HoldDirt") then
local isPrimary = self.character:isPrimaryHandItem(self.emptyBag)
local isSecondary = self.character:isSecondaryHandItem(self.emptyBag)
self.character:removeFromHands(self.emptyBag);
self.character:getInventory():Remove(self.emptyBag);
local item = self.character:getInventory():AddItem(self.newBag);
if item ~= nil then
item:setUsedDelta(item:getUseDelta())
if isPrimary then
self.character:setPrimaryHandItem(item)
end
if isSecondary then
self.character:setSecondaryHandItem(item)
end
end
elseif self.emptyBag:getUsedDelta() + self.emptyBag:getUseDelta() <= 1 then
self.emptyBag:setUsedDelta(self.emptyBag:getUsedDelta() + self.emptyBag:getUseDelta())
end
if ZombRand(5) == 0 then
self.character:getInventory():AddItem("Base.Worm");
end
-- refresh backpacks to hide equipped filled dirt bags
getPlayerInventory(self.character:getPlayerNum()):refreshBackpacks();
getPlayerLoot(self.character:getPlayerNum()):refreshBackpacks();
-- needed to remove from queue / start next.
ISBaseTimedAction.perform(self);
end
return zReMS_INJECTOR
Ok, new try to normalize the names and so, as you told me.
@thick karma fixed a little issue in function InjectionsRequests.confirmed(items, result, player) body = player:getBodyDamage() if body:isInfected() then if randomChance <= 4 then player:die() elseif randomChance <= 54 then InjectionsRequests.CurePlayer elseif body:setInfectionLevel(0) end else body:setInfected(true) body:setInfectionMortalityDuration(body:pickMortalityDuration()) body:setInfectionTime(player:getHoursSurvived()) end end
typo in the string pattern, "media/lua/(.+%.lua)$" works
I would minorly refactor the third file like so:
I didn't look for other errors but that is the formatting I would use.
the old pattern captured without the .lua but expected it for the comparison
-- this code MUST be placed in shared so that it runs before vanilla server code
local old_add = Events.OnClientCommand.Add
Events.OnClientCommand.Add = function(handler)
local originFile = string.match(getFilenameOfClosure(handler), "media/lua/(.+%.lua)$")
if originFile ~= "server/ClientCommands.lua" then
old_add(handler)
return
end
old_add(function(module, command, player, args)
-- do nothing if it's the module and command that triggers the function you want to delete
if module == "object" and command == "shovelGround" then
return
end
handler(module, command, player, args)
end)
-- reset it after replacing the handler so you don't yeet some random mod functions
Events.OnClientCommand.Add = old_add
end
```full working code to cancel the function
I gotta hop off for a bit but I will try to reply later if you get stuck and ping me. You are definitely on the right track. Just follow console errors carefully if they exist and they'll tell you what last things need fixed.
If you can't figure them out, share the stack trace in your console logs and I'll try to check on my phone if I can.
KING!
ok thanks, last question : is it ok to have local stuff in the {} that is already local ?
Remember console.txt for clientside errors (which yours will likely be) is in %UserProfile%/Zomboid @violet shell
like : ```local BiocodedCureKitTrait = {}
function BiocodedCureKitTrait.initModData(player)
if player:HasTrait("BiocodedCureKitTrait") then
local pMod = player:getModData()
local playerName = player:getDescriptor():getForename() .. " " .. player:getDescriptor():getSurname()
local playerUsername = player:getUsername()
local randomNumber = ZombRand(9999)+1
pMod.autotest = {}
pMod.biocodedCureExp = {}
...```
No. Once the table is local, everything in it is also local.
Wait what?
ok so I should clean up the local then
yeah
Those SHOULD be local
Otherwise you'd be declaring a global variable named pMod (I'm not saying you should, I'm saying that if you leave off the word local, the variables will be global automatically, unless they're the descendent of a local object such as a table).
I delcare it later
What you should not do is this:
local BiocodedCureKitTrait = {}
local function BiocodedCureKitTrait.initModData(player)
. . .
pMod.autotest = {}
I need my pMod to be global, is it ok to have it declared in a local {} ?
Yes.
fine π
But not in the brackets like you're accidentally literally implying
ok last thing to do : try to write the fixInventory function π
You would not write this:
local BiocodedCureKitTrait = {
pMod = {}
}
This pMod would be a local subtable of the local table BiocodedCureKitTrait
I would not personally recommend it but it's okay. If you want it to be global you just do this in the example I sent you back:
local BiocodedCureKitTrait = {}
function BiocodedCureKitTrait.addTrait()
TraitFactory.addTrait("BiocodedCureKitTrait", getText("UI_trait_BiocodedCureKitTrait"), 2, getText("UI_trait_BiocodedCureKitTraitdesc"), false, false)
end
function BiocodedCureKitTrait.initModData(player)
if player:HasTrait("BiocodedCureKitTrait") then
pMod = player:getModData() -- by deleting "local" I made it global here.
However, for splitscreen compat, you'll want to grab whichever player mod data is currently relevant to the player using the syringe.
So you really don't want to just save 1 mod data table for that 1 player imo.
Storing it would save almost no time.
Thanks, I gonna dig with this, can I call you back if I struggle (which will probably happen at some point...) ?
Practically speaking it would save a pointless amount of time.
I need pMod to be global because I store data in it that I use to check compatibility between item and player (player ownership of some sort)
I would recommend leaving pMod local and using local pMod = player:getModData() in any function that needs to access a player's mod data when you're in that function so you know you're using the right player object.
Grabbing that data from player object does not take long at all and if you're only doing it once when the player manually activates a task, it is a complete nonissue for performance.
the data is stored in player ModData even if I don't declare it global ?
Correct.
damn !
player:getModData() is a table that you can summon all over your files and it will give you access to the correct table.
And if you store it in a local variable, that is just for convenience -- the local variable still points to the exact same table
It's just that you can only use that variable to do so until end-of-scope (so end of function, usually, or end of loop as the case may be).
ok, so I should transfer all my pMod to local. Is it the same for items modData ?
so I should also transfer all my iMod to local too right ?
Oh yeah leave that local too.
But I think you may need to transmit item mod data to sync it. @bronze yoke can probably confirm, but you may want to do (Nope, I'm wrong.)iMod:transmitModData() before adding it to your inventory.
no, item mod data doesn't need syncing and doesn't even have a transmit method
yeah
I see.
local pMod.autotest = {}``` is it correct ?
No local on the 2nd one
It's the same case as the one I mentioned earlier where the module is already local
pMod is sort of like a module -- structurally, it's the same thing, just a Lua table. Practically speaking, we use modules a bit differently sometimes, but they're still just tables.
ok that's what I was worried about
and function InjectionsRequests.confirmed(items, result, player) local body = player:getBodyDamage() if body:isInfected() then if randomChance <= 4 then player:die() elseif randomChance <= 54 then InjectionsRequests.CurePlayer elseif body:setInfectionLevel(0) end else body:setInfected(true) body:setInfectionMortalityDuration(body:pickMortalityDuration()) body:setInfectionTime(player:getHoursSurvived()) end end
It's better to have "body" local right ?
Definitely.
I would never make a variable with a name as common as the word body global, as a rule of thumb.
If I am making something global, I do my best to give it a name no one else has used or will be likely to use.
Gotta get out of here but I wish you luck from there and I'll try to respond to further questions later if nobody beats me to it.
Tons of people here can tell you exactly what I'm telling you though so feel free to keep floating questions and just hang in there until someone sees it.
Thank you so much, it's helping me a lot !
and I understand far better some other code I was struggling to read
Btw just in case you're unaware, I have 20+ published mods and welcome anyone interested (including you) to review their code to understand how I solved this or that problem and refactor anything you need from those mods. Just make sure you change any global module names used in my older mods, all MOD ids, and all full filenames (meaning lua/client[or shared or server]/Full/Path/And/Filename.lua needs to be unique).
Can someone help me replicate this in a mod? I've been stuck on it for days
I've got the case spawning in the world just fine, but can't get the case itself to spawn the loot I want
Can someone help me ?
ERROR: General , 1714081981030> ExceptionLogger.logException> Exception thrown java.lang.NumberFormatException: For input string: "Tooltip_Inject_CureExp" at FloatingDecimal.readJavaFormatString.
ERROR: General , 1714081981031> DebugLogStream.printException> Stack trace:
java.lang.NumberFormatException: For input string: "Tooltip_Inject_CureExp"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.base/jdk.internal.math.FloatingDecimal.parseFloat(Unknown Source)
at java.base/java.lang.Float.parseFloat(Unknown Source)
at java.base/java.lang.Float.<init>(Unknown Source)
at zombie.scripting.objects.Recipe.DoSource(Recipe.java:429)
at zombie.scripting.objects.Recipe.Load(Recipe.java:409)
at zombie.scripting.objects.ScriptModule.CreateFromToken(ScriptModule.java:285)
at zombie.scripting.objects.ScriptModule.ParseScript(ScriptModule.java:459)
at zombie.scripting.objects.ScriptModule.Load(ScriptModule.java:60)
at zombie.scripting.ScriptManager.CreateFromToken(ScriptManager.java:174)
at zombie.scripting.ScriptManager.ParseScript(ScriptManager.java:75)
at zombie.scripting.ScriptManager.LoadFile(ScriptManager.java:147)
at zombie.scripting.ScriptManager.Load(ScriptManager.java:758)
at zombie.GameWindow.initShared(GameWindow.java:148)
at zombie.GameWindow.init(GameWindow.java:1197)
at zombie.GameWindow.mainThreadInit(GameWindow.java:576)
at zombie.GameWindow.mainThread(GameWindow.java:489)
at java.base/java.lang.Thread.run(Unknown Source)```
did you read it ?

Yes, but I don't understand what's the problem. Syntax in my string ?
What's the line with the issue ?
From what I read, that sounds like a wrongly used function but you'd have to show the line with the string
Ok, now I have a problem in lua file π
you cannot have an elseif with ~= ?
I don't understand, in another mod I made earlier, I used the exact same syntax and it works fine.
so i tried this, and even tried with isAimedFirearm. and tested a few diferent ways and stuff, i couldnt get it to work, not sure why. but the items werent getting the tag applied
@violet shell You aren't calling the functions. I overlooked how you wrote that earlier. You simply wrote their names, which leads the compiler to expect that you are going to assign them some new value, i.e., you're about to say something to the effect "A = B". The compiler communicates this to you by saying, '=' expected near elseif
Specifically it's observing that before elseif (right before it, i.e., near it), it expects = after InjectionsRequests.confirmationWindow
You should have written InjectionsRequests.confirmationWindow()*
(* okay not quite...)
In fact you also need the params in the parentheses. I'm pretty sure the confirmation window had params.
Last you sent it to me, its params were items, result, player
So you really should have written InjectionsRequests.confirmationWindow(items, result, player)
And tbh, you shouldn't even write this branch this way.
(lol π )
You should write it this way @violet shell:
if iMod.biocodedCureExp.playerUsername ~= player:getUsername() or
iMod.biocodedCureExp.playerName ~= playerName or
iMod.biocodedCureExp.randomNumber ~= pMod.biocodedCureExp.randomNumber then
InjectionsRequests.confirmationWindow(items, result, player)
else
InjectionsRequests.confirmed(items, result, player)
end
Those would be the appropriate function calls.
Was this caused by the Lua-style comments?
I would expect that to be the reason for this error.
But maybe those comments are allowed and I've never known. Also possible.
In general, I would not expect Lua-style comment format to be allowed in a script.
And maybe -- is being interpreted as some effort to subtract something and that's how it ends up resulting in a number format exception.
If removing -- lines (in translation files) fixes this, it was probably something like that.
Ok, but those lines are copy/paste from vanilla files π
I removed them btw
Ok, took all your advice, gonna test it again π
ERROR: General , 1714085624443> DebugLogStream.printException> Stack trace:
java.lang.NumberFormatException: For input string: "Tooltip_Inject_CureExp"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.base/jdk.internal.math.FloatingDecimal.parseFloat(Unknown Source)
at java.base/java.lang.Float.parseFloat(Unknown Source)
at java.base/java.lang.Float.<init>(Unknown Source)
at zombie.scripting.objects.Recipe.DoSource(Recipe.java:429)
at zombie.scripting.objects.Recipe.Load(Recipe.java:409)
at zombie.scripting.objects.ScriptModule.CreateFromToken(ScriptModule.java:285)
at zombie.scripting.objects.ScriptModule.ParseScript(ScriptModule.java:459)
at zombie.scripting.objects.ScriptModule.Load(ScriptModule.java:60)
at zombie.scripting.ScriptManager.CreateFromToken(ScriptManager.java:174)
at zombie.scripting.ScriptManager.ParseScript(ScriptManager.java:75)
at zombie.scripting.ScriptManager.LoadFile(ScriptManager.java:147)
at zombie.scripting.ScriptManager.Load(ScriptManager.java:758)
at zombie.GameWindow.initShared(GameWindow.java:148)
at zombie.GameWindow.init(GameWindow.java:1197)
at zombie.GameWindow.mainThreadInit(GameWindow.java:576)
at zombie.GameWindow.mainThread(GameWindow.java:489)
at java.base/java.lang.Thread.run(Unknown Source)```
Still get the issue with ToolTip @thick karma
Missing a trailing comma
I wonder if that's one of those weird situations where you need the closing comma?
Tooltip = Tooltip_Inject_CureExp β Tooltip = Tooltip_Inject_CureExp,
Now who is ninjaing.
Damn ninja.
π
I was honestly guessing but if you're sure nice.
Should be that, scripts require the trailing comma on all values
So does this mean -- comments are fine in those files?
Should be, they're accepted in string files & I'd expect the same for those
I added the coma, and still have an issue π
Different code paths so I'm not 100% certain there
Is it the same issue?
nope, but almost same trace
What's the new one?
wait
ERROR: General , 1714086028226> ExceptionLogger.logException> Exception thrown java.lang.NumberFormatException: For input string: "Tooltip_Inject_CureExp" at FloatingDecimal.readJavaFormatString.
ERROR: General , 1714086028226> DebugLogStream.printException> Stack trace:
java.lang.NumberFormatException: For input string: "Tooltip_Inject_CureExp"
at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.base/jdk.internal.math.FloatingDecimal.parseFloat(Unknown Source)
at java.base/java.lang.Float.parseFloat(Unknown Source)
at java.base/java.lang.Float.<init>(Unknown Source)
at zombie.scripting.objects.Recipe.DoSource(Recipe.java:429)
at zombie.scripting.objects.Recipe.Load(Recipe.java:409)
at zombie.scripting.objects.ScriptModule.CreateFromToken(ScriptModule.java:285)
at zombie.scripting.objects.ScriptModule.ParseScript(ScriptModule.java:459)
at zombie.scripting.objects.ScriptModule.Load(ScriptModule.java:60)
at zombie.scripting.ScriptManager.CreateFromToken(ScriptManager.java:174)
at zombie.scripting.ScriptManager.ParseScript(ScriptManager.java:75)
at zombie.scripting.ScriptManager.LoadFile(ScriptManager.java:147)
at zombie.scripting.ScriptManager.Load(ScriptManager.java:758)
at zombie.GameWindow.initShared(GameWindow.java:148)
at zombie.GameWindow.init(GameWindow.java:1197)
at zombie.GameWindow.mainThreadInit(GameWindow.java:576)
at zombie.GameWindow.mainThread(GameWindow.java:489)
at java.base/java.lang.Thread.run(Unknown Source)
Hmmmm seems the same.
It may be because you have some colons where you should have =
I'd have to double-check (I don't use scripts all that often) but I think only some of those should be :
recipe HockeyMaskSmashBottle
{
WineEmpty/WineEmpty2/WhiskeyEmpty,
Result:SmashedBottle,
Time:20,
OnCanPerform:Recipe.OnCanPerform.HockeyMaskSmashBottle,
Tooltip:Tooltip_Recipe_HockeyMaskSmashBottle,
}
so it should be Tooltip : Tooltip_blabla ?
Oh whoops I said that backwards
ok thanks π
Yeah, confirmed, items use =, recipes use :
damn, that's so weird π
You presumably copied tooltip from one to the other.
pretty sure I did π
another issue : when I launch, everything is ok, no more error nor any stack trace, but the game don't load
after the loading I never get the "click to start"
Does the game hang?
Like "not responding"
If not, I'd double-check to make sure there's no error. If so, seems like a potential infinite loop
yup, hosted server to start with, and when it works fine on hosted server I move to dedicated one
in coop-console I got that :
LOG : Lua , 1714086218786> 1?197?927?759> Loading: C:/Users/Gusty/Zomboid/Workshop/Asilar_BiocodedCureKit/Contents/mods/Asilar_BiocodedCureKit/media/lua/server/Asilar_Biocoded_Cure_Kit.lua
LOG : Lua , 1714086218787> 1?197?927?760> Loading: C:/Users/Gusty/Zomboid/Workshop/Asilar_BiocodedCureKit/Contents/mods/Asilar_BiocodedCureKit/media/lua/server/InjectionsRequests.lua
LOG : General , 1714086218789> 1?197?927?761> luaChecksum: eae2a1aec2db491d3e37eb3e32bc4153
ERROR: General , 1714086219038> 1?197?928?011> LuaManager.getFunctionObject> no such function "onCreateAutotest"
ERROR: General , 1714086219039> 1?197?928?012> RecipeManager.LoadedAfterLua> no such function LuaCreate = "onCreateAutotest" in recipe "Use_an_Autotest"
just post the whole file I mean
Some things that strike me as weird that happen near the disconnect are this:
LOG : Network , 1714083436868> 0> [26-04-24 00:17:16.868] > ConnectionManager: [RakNet] "disconnection-notification" connection: guid=126100832844820618 ip=90197630470637574 steam-id=76561198192785714 access="" username="peanits" connection-type="Disconnected"
LOG : Network , 1714083436869> 0> [26-04-24 00:17:16.869] > ConnectionManager: [disconnect] "21" connection: guid=126100832844820618 ip=90197630470637574 steam-id=76561198192785714 access="" username="peanits" connection-type="Disconnected"
ERROR: General , 1714083438917> 0> java.nio.file.NoSuchFileException: /lua/EasyConfigChuckedServerConfigs/servertest_config
ERROR: General , 1714083438917> 0> at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.deleteFile(Unknown Source)
ERROR: General , 1714083438918> 0> at jdk.zipfs/jdk.nio.zipfs.ZipPath.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at java.base/java.nio.file.Files.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.deleteDirectory(ZipLogs.java:305)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.addDirToZipLua(ZipLogs.java:264)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.addZipFile(ZipLogs.java:80)
ERROR: General , 1714083438918> 0> at zombie.network.CoopMaster.readServer(CoopMaster.java:243)
ERROR: General , 1714083438918> 0> at java.base/java.lang.Thread.run(Unknown Source)
as well as these references to two hidden mods:
LOG : Network , 1714083054248> 0> [26-04-24 00:10:54.248] > ZNet: workshop item 2048847068 is not installed
LOG : Network , 1714083054259> 0> [26-04-24 00:10:54.259] > ZNet: workshop item 2579085757 is not installed
This also looks less than ideal at a glance and the timing makes me wonder about it:
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: CRakNet -> CZombienet: OnClosedConnection
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: OnClosedConnection: m_connectionState=6
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: OnClosedConnection: reason=DisconnectionNotification port=16262
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: CZombienet -> CZombienet: CloseConnection
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: CloseConnection: DisconnectionNotification (1208)
LOG : Network , 1714083436867> 0> [26-04-24 00:17:16.867] > ZNet: CZombienet -> CZombienet: CancelAuth
LOG : Network , 1714083436868> 0> [26-04-24 00:17:16.868] > ZNet: CancelAuth
LOG : Network , 1714083436868> 0> [26-04-24 00:17:16.868] > ZNet: CZombienet -> CZombienet : UpdateConnectionState
LOG : Network , 1714083436868> 0> [26-04-24 00:17:16.868] > ConnectionManager: [RakNet] "disconnection-notification" connection: guid=126100832844820618 ip=90197630470637574 steam-id=76561198192785714 access="" username="peanits" connection-type="Disconnected"
LOG : Network , 1714083436869> 0> [26-04-24 00:17:16.869] > ConnectionManager: [disconnect] "21" connection: guid=126100832844820618 ip=90197630470637574 steam-id=76561198192785714 access="" username="peanits" connection-type="Disconnected"
ERROR: General , 1714083438917> 0> java.nio.file.NoSuchFileException: /lua/EasyConfigChuckedServerConfigs/servertest_config
ERROR: General , 1714083438917> 0> at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.deleteFile(Unknown Source)
ERROR: General , 1714083438918> 0> at jdk.zipfs/jdk.nio.zipfs.ZipPath.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at java.base/java.nio.file.Files.delete(Unknown Source)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.deleteDirectory(ZipLogs.java:305)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.addDirToZipLua(ZipLogs.java:264)
ERROR: General , 1714083438918> 0> at zombie.core.logger.ZipLogs.addZipFile(ZipLogs.java:80)
ERROR: General , 1714083438918> 0> at zombie.network.CoopMaster.readServer(CoopMaster.java:243)
ERROR: General , 1714083438918> 0> at java.base/java.lang.Thread.run(Unknown Source)
I have to Alt-F4 to quit the game
maybe it's the source of the last errors ?
but I still cannot enter the game.
must be a infinite loop somewhere ?
it's probably linked to Events.OnNewGame.Add(BiocodedCureKitTrait.initModData)
sure
WARN : Script , 1714087112332> 1?198?821?305> ModelScript.check> no such model "???.Autotest_KnoxInf" for Asilar_Autotest_Knox_Infection.Autotest_Knox_Infection
WARN : Script , 1714087112332> 1?198?821?305> ModelScript.check> no such model "???.Item_LabSyringe" for Asilar_Biocoded_Cure_Kit.biocodedCureExp
No clue why my memory decided to hold on to this exchange from two years ago, but ZipFileSystem + EasyConfigChuckedServerConfigs reminds me of #mod_development message
May want to ask Chuck how that was ultimately sorted, unless removing the unavailable mod IDs fixed it
If you haven't yet resolved it, looks like Chuck said up there that deleting the offending folder fixes it
deleting the offending folder ? @frank elbow
Reverted to my vanilla code from the other mod that works, and in SP player spawns with the items as intended, but there are stuff that doesn't work (cannot open crafting UI).
In Hosted MP, it doesn't work I have to test again.
I still get this : WARN : Script , 1714090063474> 0> ModelScript.checkTexture> no such texture "Autotest_KnoxInf" for Asilar_Autotest_Knox_Infection.Autotest_KnoxInf
WARN : Script , 1714090063475> 0> ModelScript.checkTexture> no such texture "Item_LabSyringe" for Asilar_Biocoded_Cure_Kit.Item_LabSyringe
Odd. But fyi I just finished work and tested and I don't think that's their problem. I'm leaning infinite loop because it blackscreens without errors and the server actually isn't crashing. @frank elbow @violet shell Taking a look now.
I wonder what happens between loading map chunks and pressing start in general... Anyone know off the top what events fire there, or what files load there?
Actually after Loading World to be more specific...
I started to add some print() almost everywhere in the trait creation lua file. gonna run 1 time to check what's happening
LOG : General , 1714093719777> 0> Enter BiocodedCureKitTraitOnNewGame
LOG : General , 1714093719777> 0> Enter if loop
LOG : General , 1714093719778> 0> Rudolph Ramey
LOG : General , 1714093719778> 0> Asilar
LOG : General , 1714093719778> 0> 8358
LOG : General , 1714093719778> 0> Enter for loop for 1 times
LOG : General , 1714093719779> 0> Enter for loop for 2 times
LOG : General , 1714093719779> 0> Start Create biocodedCureExp
LOG : General , 1714093719779> 0> pMod.autotest.randomNumber = 8358
LOG : General , 1714093719780> 0> pMod.biocodedCureExp.randomNumber = 8358
LOG : General , 1714093719785> 0> LuaNet: Loading...
LOG : General , 1714093719785> 0> LuaNet: Registering client listener...
LOG : General , 1714093719786> 0> LuaNet: Initialization [DONE], triggering events for 'LuaNet.onInitAdd'.
LOG : General , 1714093719852> 0> Saving GlobalModData
Very confusing issue I must say.
It's not the Trait creation that loops, because we go through the whole process without any problem
Yeah I see that.
Very odd. I am gonna take a break from staring at it and try to look a little later. Kind of a lot of points of failure here and hard to say which is the issue for me without an error message to go by. I'm thinking it may be a script issue of some kind but idk at all tbh.
is it possible that the missing StaticModels Omar was talking about is messing it up ?
I was AFK when he said that
what if I delete the static as for my previous mod
I don't know about that and didn't even see that comment
But Omar is a G who has contributed very useful technical solutions to the mod scene so I would take his guesses as highly educated.
I do not know scripts as well as some so I can't just glance at them and be sure they're all formed right, tbh... And when I want to run a function from an item historically, I often attach the function using OnFillInventoryContextMenu event rather than using recipe functions. This is somewhat fuzzy territory for me.
In Solo play, with a reverted ugly code
also in the bugs : I cannot open the crafting UI
i can't do it
I may have found one of the issues : my crafting recipe didn't have a result
I am pretty confident that the error is some disconnect between how recipes work and how you've connected the functions to them... If the Lua code itself were malfunctioning severely, I'd expect Lua stack traces or something.
And I forgot a coma in imports{Base,}
I just don't know for sure.
But my money is on issues in the scripts as the main reason game won't get to Start Game button.
subsidiary question : where are the traits icons ? I can't find the vanilla ones
ok, now Crafting UI is working
@thick karma It WORKS !!!! DAMN IT WORKS !!
what am I doing wrong? can I not call a distribution table to an item?
i just want to replicate gun case function
I got the cases, they spawn, but no matter what I do they are always empty
Anyone have some knowledge about StaticModels around ?
Are your cases considered containers?
Uhh, maybe? I think they might be bags
How are you defining them?
Let me pull it up
Hey everyone. I'm doing outfits for custom zombies at the moment, and I'm wondering whether it's possible to force a zombie to wear a specific colour of item. So for instance, I want one to wear a motorcycle helmet, but specifically the red one, with no chance of spawning with the other colours. Is that possible?
They have military zombies with military helmets and construction worker zombies with hard hats, so I would imagine it is. There should be some Lua code in the media/lua directory for zombie outfits in your game installation directory that you could probably retrofit to what you want to do.
So I have it definited in items like this
And it does exist in game
Then I have it defined in procedural generations like this
And it does spawn in those locations
But after that I can't get it to spawn the items
This is as far as I ever got
I tried a bunch of other shit with local function applyLootBoxLoot() but couldn't get it to work
But the military helmet and hard hat are their own unique items :/ I've looked through the lua files and I couldn't find anything related to what I'm looking for π₯²
I'm not familiar with loot distributions, but i would assume that is your issue, something not being connected there.
Probably not the right way to do things, but you might be able to use OnContainerUpdate in order to force spawn some items in it semi-randomly? https://github.com/demiurgeQuantified/PZEventDoc/blob/develop/docs/Events.md
(Client) OnContainerUpdate: Fires when a container is added or removed from the world.
Parameters: object - The container that was added or removed.
I know that KATJA's armor pack... I forget the exact name... has variations on colors of the exact same piece of equipment. Maybe that mod would be able to give you some insight?
Pale Jack, you know stuff about StaticModel ? I'm struggling to finish my mod
I think I have messed with them before, but I don't recall exactly... sorry my mind is like a sieve. π
I really messed up KATTAJ1's name... lol
i'm not entirely sure what this does
It's an event that fires anytime a container spawns. So you could register a function and then add it to trigger when that event fires. One second and I can give you a pseudo code example.
local function OnContainerUpdate(container)
-- Test if container is one of your gun cases
-- Add items to container
end
Events.OnContainerUpdate.Add(OnContainerUpdate)
Stupid Discord messed up my indentation. π₯²
hmmmmmmmmmmmmmmmmmmmmmmm
if not zed then return false end
local item = "Base.YourOutfit"
local inv = zed:getInventory()
local equip = inv:AddItem(item);
local texture = 2
equip:getVisual():setTextureChoice(texture); --based on the number of textures you added
zed:setWornItem(equip:getBodyLocation(), equip);
Textures are defined on the xml
Hero. ππ»
and where would I put this? In a .lua file?
Yes
Well... no. You don't put your distribution list in there. Sorry. It's a little more complicated than that. Do you know how to develop in Lua?
Not at all 
Everything I do I do via reverse-engineering other mods or vanilla code
i've never coded in my life
@bronze yoke seemed to know how it works but i must've misunderstood where to put the code
I see. Give me a second.
They gave me this thing
And I've tried implementing it 101 different ways but couldn't get it to work
#mod_development message I also tried this
@manic magnet My issue is :
I renamed GranolaBar.fbx into myItem.fbx, and made a myItem.png changing colors and drawings on the GranolaBar.png (texture).
Then I made a model : model myItem3D { mesh = WorldItems/myItem, scale = 0.4, } item myItem { ... WorldStaticModel = myItem3D, }
And it works nicely
Well. That creates a new distribution table... correct. I don't know how to associate your distribution table with a spawned in container though. Have you tried looking at the lua for containers in the PZ installation folder? Specifically inside media/lua.
Yup, I found this behaviourhttps://cdn.discordapp.com/attachments/232196827577974784/1233172448590041149/image.png?ex=662c20d6&is=662acf56&hm=7aa4753190e520e777fb5c4c505bf9a3100e2cafe1494aa9627772576e412324&
What file is this located in?
So you figured out your issue?
@manic magnet But when I try to add StaticModel, here what I did :
I converted GranolaBar.fbx to GranolaBar.x (using online converted), renamed it in myItem.X and adding it into models_X directory
Then added code :model myStaticItem { mesh = myItem, } item myItem { ... StaticModel = myStaticItem, WorldStaticModel = myItem3D, } But the item is not in the hand when player use it or when I equip it in primary hand
\common\ProjectZomboid\media\lua\server\Items\Distributions.lua
Are you putting your distribution table in the same directory tree inside your mod? π€
It might be the way the model was converted to .x?
mmm yeah, it's next to the ProceduralDistributions Lua that handles the case itself spawning in the game
if I take the example of Book.fbx and Book.x it's not a simple conversion ?
I am pretty sure that there are actually different versions of the .x format, one being text, for example... and a couple of different binary ones? I can't remember exactly. It's been a minute since I have messed with them.
Anyway, I am not certain which versions PZ does and does not support.
ok thanks
That's my best guess... sorry I couldn't be more helpful.
this distribution nonsense will be the death of me
I converted Book.fbx to .x with the same online converter, and compared with Book.X
seems it's the same format, but in the converted file, I don't have template ColorRGB {} for example nor template Material {} nor template TextureFilename {}
I see. But can you rename the new Book.x made with the online converter to match your new item and see of that shows in game still?
Good idea
I think there is a piece missing to add your distribution list to your container...
yeah i think so
https://pzwiki.net/wiki/Procedural_distributions this is the only documentation I can find on the matter... no clue what you could be doing wrong though. The use case they present isn't much like what you are trying to do...
Yeah this is for Procedural Generations which is what I used to get the case itself working to begin with
the problem is getting items to spawn in the bag
oh my god i did it
i don't know what the fuck fixed it
PistolCaseMakarov = {
rolls = 1,
items = {
"Base.9x18mmClip", 200,
"Makarov", 200,
"Base.Bullets9x18mmBox", 200,
},
junk = {
rolls = 1,
items = {
}
}
},
}
table.insert(Distributions, 1, distributionTable);
--for mod compat:
SuburbsDistributions = distributionTable;```
converted book is not shown when I read it π¦
So, how I can have a good conversion from fbx to X ?
@thick karma I converted back all the files of functions in your syntax, but I get an error I don't understand
Less Than for operand not defined
__lt is table syntax (not the proper name but idk names) for less than, __gt is greater than etc
yes, I finally found the error π Changing names of stuff is always painful π
So whatever you're doing at InjectionsRequests.lua:54 or at Asilar_Biocoded_Cure_Kit.lua:14
good job!
I hope it's the last one π
Yeah ! That's good now π Finally, I can go to bed π Thanks all for your help, and see you tomorrow for more questions π
Would you mind elaborating a little bit? Is this an lua function that has to be performed serverside?
You can trigger it via client
Or debug
Anywhere actually
You could try and use OnZombieUpdate() or from contextmenu or something
Sorry I have a mental deficiency, could you please explain like I'm five years old?
I dont think i can do that.. hmmm....
Whats your purpose for choosing specific texture? When do you want select texture
I want zombie to spawn with rainbow pants
Okay no, hold on, let me elaborate a bit more than that
Just loading in to grab a screenshot so you can see what I mean...
Oh you can just look at how vanilla spawns them
OR maybe use the addhorde or something like that
Thats you spawn zed
So there's a bunch of dead zombies here. I've referred to both AuthenticZ and ClothesBox for the clothing. The pants, which are from ClothesBox, are spawning in all different kinds of colours, but I want the specific rainbow pants on the south-most zombie to be a 100% guaranteed spawn, instead of having the variation of like 20 different styles. I could easily just make a unique pair of pants that only uses that texture, but is there a more efficient way using code or GUIDs or something to guarantee that?
this is untested i just wrote this now
local yourItem = 'Base.Hat_JokeKnife'
local yourOutfit = 'HazardSuit'
function ZContext(pl, context, worldobjects)
if not pl then return end
local zed = nil
if clickedSquare then zed = clickedSquare:getZombie() end
--zed:getInventory():contains(yourItem)
--zed:getWornItems():getItems()
if zed then
context:addOption("set texture", worldobjects, function()
if zed:getInventory():contains(yourItem) then
yourItem:getVisual():setTextureChoice(2);
end
end)
context:addOption("set texture2", worldobjects, function()
for i=0, zed:getWornItems():size()-1 do
local item = zed:getWornItems():get(i):getItem();
if item and item:getFullType() == yourItem then
item:getVisual():setTextureChoice(2);
end
end
end)
context:addOption("give item then set texture", worldobjects, function()
local inv = zed:getInventory()
local equip = inv:AddItem(yourItem);
zed:setWornItem(equip:getBodyLocation(), equip);
equip:getVisual():setTextureChoice(2);
end)
context:addOption("spawn with your outfit", worldobjects, function()
local sq = clickedSquare
addZombiesInOutfit(sq:getX(), sq:getY(), sq:getZ(), 1, yourOutfit, nil, true, true, false, true, 2)
end)
end
end
Events.OnFillWorldObjectContextMenu.Remove(ZContext)
Events.OnFillWorldObjectContextMenu.Add(ZContext)
my syntax might all be messed up so just refer to the vanilla lua to correct it
those are different methods and hopefully one of em works
you can also iterate worldobjects
and search for movingobjects
something like this
for i=1,square:getMovingObjects():size() do
local obj = square:getMovingObjects():get(i - 1)
if obj and instanceof(obj, "IsoZombie") then
ahhhh ok
so forget what i wrote so you want the game to spawn em then just define another clothing outfit
that contains only 1 texture
which will guarantee that it will spawn
you need an xml here
'\media\clothing'
an entry of that xml here
fileGuidTable.xml
your item.txt on the scripts folder
the model aswell
then the texture goes to the textures folder
thats basically how you create a outfit i think
to make em spawn you need a lua on the shared folder
require 'NPCs/ZombiesZoneDefinition'
Events.OnPostDistributionMerge.Add(function()
table.insert(ZombiesZoneDefinition.Army, {name = "yourOutfit", 5});
end)
something like that
Very glad you solved it because I passed out lol
yoh i made an entire profession init lua thats far to shorter than any other mods you see
this is vanilla
this is mine
see the page lol
this is how i did that
check out how i did the mutual exclusive
function DNZ_Init.doMutualExclusive(entry)
local result = ''
for _, v in pairs(entry) do
for i = 1, #v do
for j = i + 1, #v do
local k = v[i]
local l = v[j]
if TraitFactory.getTrait(k) ~= nil and TraitFactory.getTrait(l) ~= nil then
if isDebugEnabled() then
local toPair = tostring(k..' | '.. l)
result = result .. toPair .. '\n'
end
TraitFactory.setMutualExclusive(k, l)
end
end
end
end
if isDebugEnabled() then
Clipboard.setClipboard(result)
print(result)
end
end
looks familliar?
thats from your BS table thing
ive been using that valuable pievce of code ever since
i owe all my table skills from that
@thick karma
Ayyyy nice work, glad you made that work. Interesting mod.
Was so happy when i saw no errors and checked the stats
And they were all there
Thnx so much
Hi, simple question. I've added some icons for a couple of items but they're not shown in the item list when using debug. Is there any way to fix this or am I stuck looking at the void instead of the item's icon? New icons replacing base game ones also don't show, but instead what the game uses in vanilla
yeah, the debug item list just doesn't load icons correctly
i think someone wrote a patch for it if it bothers you, but it doesn't mean you're doing anything wrong
Congrats!
alright thanks
i figured its just the list being silly, not anything bad but it does make it harder to test my stuff
i wasn't able to find the patch, i guess it wasn't made by who i thought it was and it wasn't easily findable on the workshop
but basically the debug item list uses a function that only searches the base game directory for icons, so it doesn't reflect mods at all
Hi π I'm still looking for help for 2 last things : convert the fbx model of GranolaBar into x file, and I'm still hardly stuck on my mod "Readwithfriends" to simulate fast forwarding time when you read in MP, simulating stats drain like Fast forward in SP. π If anyone have some spare time, I'll be grateful π
why would you convert any file from fbx to x ?
my statsapi reimplements stat calculations in lua, that might be a helpful reference
@bright fog because the X file doesn't exist for that item, and I used the fbx file to make my custom item,and I would like to have the item visible in hands π
you don't have to use x files, the game will render fbx too
Why use x file ???
it didn't work when I tried
You don't need a .x file to see the item in hands
I tried with fbx and it didn't work
I must have failed somewhere then
Don't even use .x, for the sake of yourself and everyone, don't put your model files in .x
I'm interested π
The item needs to be attached to a bone
the source code is available here https://github.com/demiurgeQuantified/StatsAPI
How I do that ?
Within blender you need to add the bone and parent the model to the bone
i won't lie, because of the scope of the project the code is somewhat dense so i didn't suggest it to you before
I've never done it myself but a ton of people already did it
i was actually working on something that needed to simulate a stat drain myself so i may add a library for that if it's useful
Check out modded items that can be held in hands (vanilla files are in x and don't even bother getting those and their bones, if it's the same as animations it requires you reading the bible in fragmotion, literally)
(also I'm not joking about reading the bible in fragmotion, that's the only way to get access to the software)
You're right, code seems dense, I don't know if I have the skills to use it properly lol π
Can you point me to a mod that actually does this ? I checked Visible Walkies but it has x files too π
no idea
@sonic needle you have more detail on that ?
@bright fog @thick karma I have another critical issue for my server that is going to start in a feuw hours. I'm using a mod that plays alert sounds 10 and 5 minutes before a server start, but I get an error I don't understand. Can I submit the file and error log to you ?
Don't bother, I made a typo error in the sandbox options I setup π
I was workin but glad you solved it.
I still have issues with having staticmodel visible π¦
@verbal yew I cracked the code on that btw thx for your help also good work on the random zombies thing I'm using it on my server now
loooool
NOOOOO
I just swapped it innnn
Do you know what's wrong
rly nope... i'm trying find problem but...
Flew too close to the sun...
like first zombies updated, but not new, but should, because script start every 7 sec
Hmmm
That's weird
Well I'd really appreciate the performance boost
Because I suspect the old one was incinerating my server performance
did you verify your script starts every 7 seconds with prints ?
yep yep
If your static model isn't showing, might want to check Meditation mod. I think I have static models in that mod that work.
does it actually run through your function
i mean, my crawler zombies can exist and swap on new zombies
but sandbox setting look like broke after...
after after
xD
If only you had waited for my Zomboid Forge framework haha 
joking of course, you shouldn't wait to do your own stuff
But like my framework is the perfect code to add random zombies, and I even planned it as a mod using my framework lol
tyvm
in 42 be new event
onzombiespawn
and normal randomizer setting to walk type
hmmm... maybe change zombie speed
like
setWalkType
how to look into one zombie in debug? like list of params?
Community debug tools
Give a fuck ton of tools and go use it now if you don't use it
?
It's some books, so you use the vanilla stuff π
WARN : Script , 1714147613165> 0> ModelScript.check> no such model "???.Item_biocodedCureExp" for Asilar_Biocoded_Cure_Kit.BiocodedCure_Result
WARN : Script , 1714147613166> 0> ModelScript.checkMesh> no such mesh "Biocoded_CureExp" for Asilar_Biocoded_Cure_Kit.Biocoded_CureExp
what are the ??? before the model name ?
nevermind, it's an item than never spawns because it's only a result of a recipe that I remove on result π
I haven't quite figured that error out to be honest, but I think it's saying it cannot figure out the intended module of the model.
Hmmm I see. I've always wondered about the conditions for triggering those errors.
I see them sometimes in mod support but never triggered them myself so didn't know how to.
And yes, I'm p sure I used a vanilla static model, so my code probably can't tell you about declaring the model correctly, only referencing it.
so I noticed that despite making the probability quite a bit higher I haven't noticed an increase in items spawned
any way I can fix that?
You been clearing map data to make sure containers are being repopulated?
I just made new saves essentially after I changed the probability and replaced the mod folder in mods
Hmmm I mean the numbers tend to affect probs for me historically so I think somehow the update is getting ignored
Is it possible that you have two versions of your mod on your pc, perhaps one version you're subscribed to on the workshop and one in your local working folders inside Zomboid?
@vestal gyro This could cause Zomboid to load the wrong version of your mod and create the illusion that changes are doing nothing...
could be
but I also uploaded the one with higher probability to the workshop afterwards anyways
I'll revisit it today or tomorrow and make sure
thanks tho that could be it
@bright fogdamn, i figure out my problem
What was the issue ?
i change zombie and drop in moddata stuff, for not change this zombie in future
im run away, back again, all zombies just walk, because they has moddata, but sandbox setting for they drop on default
hmhmhhmhmh
Like I told you, moddata isn't the way to go
yeah...
And you need to reference zombies with the pID like I showed you
Do you do that ?
Do you use the pID ?
The true ID ?
nope, idk how to do this stuff
i see your func in math
but rly dont know how to work with that
where you recreate true ID
You link an IsoZombie with info that it was updated right ?
should be
Well that's your issue
Because an IsoZombie is dynamic and switches for a same entity when that entity gets loaded and unloaded
So an entity zombie will constantly swap moddata
(unless I understand wrongly how mod data is linked to a zombie)
No there's no way it doesn't swap, or else true ID would be useless
OU!
@thick karma are you familiar with mod data for zombies ?
but it's true
local zs = getCell():getZombieList()
local sz = zs:size()
print("This now: " .. now)
for i = 0, sz - 1 do
local z = zs:get(i)
if not z:getModData().zReRANDOMZOMBIES and not (client and z:isRemoteZombie()) then
zRe_updateZombie(z)
end
end
this is IsoZombie should be
But as i say, when im walk away on high distance and back again - this is zombies not trigger anymore, but has defaul speed setting
it's mean they save moddata
but yep, after reloaded into game - empty moddata
And I told you, don't fucking use mod data
Use something non persistent
Tbf I never use mod data on zombies
I use the global mod data
To save info about zombies
No it's not
It's been a while I've worked on my framework and getting back on it but I don't
I don't do it
I don't do that
for zombies, which i'm walked faraway
wait...
not about moddata
local function zRe_updateSpeed(zombie, targetSpeed)
getSandboxOptions():set("ZombieLore.Speed", targetSpeed)
zombie:makeInactive(true)
zombie:makeInactive(false)
getSandboxOptions():set("ZombieLore.Speed", SPEED_FAST_SHAMBLER)
zombie:getModData().zReRANDOMZOMBIES = true
print("Updated Speed")
end
i'm changed for isoZombie too
it's should be like isoZombie
it's problem, yep?
AHHSAHAHS
You're just talking about moddata!
I'm telling you that the speed is reset, but the date mod remains.
When you want to access info about a zombie entity, and I'm not talking about an IsoZombie, but an actual zombie entity which stays the same when you reload an area (save or walking area and coming back), you can't use IsoZombie, the tag you usually get
WAIT
getSandboxOptions():set("ZombieLore.Speed", targetSpeed) - i change this stuff for IsoZombie
but should like for zombieID
yep?
Yes you need to change for IsoZombie
zombie moddata is not reset when the zombie is recycled
What you are doing is right
this means that when a zombie unloads, a random future zombie will inherit its moddata
because of this there's no real reason to use moddata on zombies
it's not just not persistent but causes false positives later on
π
Yeah so use mod data linked to a trueID of a zombie with the function I sent you yesterday or whenever
I'M NOT ABOUT MOD DATA AT THIS TIME!!!
Or your zombies will just be shuffled around and some will be marked as updated even tho they aren't updated
Maybe (probably) I missed something, but is this a thing that makes sense?
zombie:makeInactive(true)
zombie:makeInactive(false)
yes
Why would you... what would be... why?
That's to update the speed of zombies
yup
guys guys guys
Gross (sorry I'll shut up)
You mark zombies as updated with mod data, this is wrong because an entity will be marked as updated and perhaps it got updated but once you reload that area, that same entity will get a random IsoZombie class applied to it and thus not HIS mod data. So you mark zombies as updated, and others not yet but you end up shuffling these around so zombies get the wrong marks of being updated

main problem - i swap speed for zombies - but i take this zombies like IsoZombies, here:
local zs = getCell():getZombieList()
local sz = zs:size()
print("This now: " .. now)
for i = 0, sz - 1 do
local z = zs:get(i)
--if not z:getModData().zReRANDOMZOMBIES then
zRe_updateZombie(z)
--end
end
i transfer z in all functions, it's like isoZombies, yep?
I'M NOT ABOUT MODDATA AT THIS TIME
STOP IT XD
Yes it is
In next function i change speed for this z with sandbox options.
This is options put info in z modData, right?
I'm not talking about my flag
i mean
zombies in default contain info, somewhere... in ModData?! Nope? (not my flag, something like Health, Walk_Type etc)
You mean like accessing the zombie stats ?
no, vanilla does not use zombie moddata at all
otherwise it would encounter this same issue
I think he meant that rhetorically... I think he's wondering how to persistently store data on a zombie
I told you about that, in my way of doing that I check the stats of the zombies are the right one via the fields
._.
well vanilla just uses fields that are saved/loaded when the zombie is recycled/created, nothing you would be able to access
So checking the fields as Jvla suggested is the only way?
there isn't a simple solution for modders to persistently associate data with zombies
Download this from our dear Albion here
https://steamcommunity.com/sharedfiles/filedetails/?id=3001901955&searchtext=accessible+fields
then you access a zombie speed with
IsoZombie.speed
That way you can check if you need to update it
I'll take zombies. I change his speed to running. (FAK MOD DATE AT THIS EXAMPLE!). I'm going far away. I'm coming back. The speed dropped to walking. Why?
the trueID method we use with Chuck actually works great
it works but it isn't simple and wasn't discovered without great effort
Because the zombie's data went to another zombie apparently.
If I'm understanding Jvla and albion.
I mean, yeah, but it still works very well and is basically the only way we know of rn to have persistent data on a specific zombie
i hope future builds add an explicit unique zombie id, and reset moddata so that it can at least be safe to use
MAY MOTHER EARTH BLESS YOU!
you kept yelling at us for talking about moddata but moddata was literally the problem π
I think you gotta slooooow down the reading, padawan. π
This is what I'm trying to find out.
So I need to work with the zombie as with his ID?
It doesn't actually
They throw information at me about my flag from the mod date and other crap about the mod date.
@thick karma @verbal yew I have an issue with Recipe names translation
No you don't lmao, this is only used to follow if the zombie got updated or not
Oh so the mod data gets recycled to a new zed, but not the run speed data?
yup
it doesn't
Oh what a cluster
I just verified it bcs I haven't worked on my mod in a while
they're walking when you return because:
a) the zombie unloaded and reloaded, which resets their speed
b) their speed did not get set again by your code, because the moddata stopped it from running
But it doesn't yeah
me too π
yep yep. I already understood that. Thank you
What's your recipe file look like?
From my testing swapping the IsoZombie doesn't reset their speed
I just tested it again and I find my zombie with its speed again
are you sure? the whole reason chuck had to work out the pid stuff was because they *didn't* save their speed
Tho I need to verify the speed doesn't get updated anymore
it's not something i'm personally knowledgeable about but it surprises me to hear
they drop it on current sandbox setting
That's a possible reason why I find my zombies with the speed it's supposed to have yes
I'll test that better
recipe Inject_Biocoded_Cure {
keep biocodedCureExp,
Result:BiocodedCure_Result,
Sound:BreakAmpule,
Time:120.0,
Category:Health,
CanBeDoneFromFloor:False,
NeedToBeLearn:False,
OnCreate:injectBiocodedCure,
RemoveResultItem:true,
Tooltip:Tooltip_Inject_Biocoded_Cure,
}
recipe Inject_Biocoded_Cure
{
without space after _Cure
Also recipe Inject Biocoded Cure
okay, i think im understood all problem, it's mean i should contain somewhere zID with my param and if i get this zID again - restore speed and another suff for this zID
Damn, the _ is the problem ?
@violet shell
This:
recipe Craft Jukebox
{
Tsarcraft.TCBoombox,
Tsarcraft.TCVinylplayer,
ElectronicsScrap=10,
SheetMetal=1,
Screws=4,
ElectricWire=1,
keep [Recipe.GetItemTypes.Screwdriver],
noBrokenItems:true,
Result:Moveables.recreational_01_1,
NeedToBeLearn:true,
Time:1200.0,
Category:Electrical,
AnimNode:Disassemble,
Prop1:Screwdriver,
Sound:Dismantle
}
Corresponds to this:
Ok, spaces are converted in the recipes translation files as underscores ?
Correctamundo
there's nothing wrong with having an inline opening bracket
No you were right, speed doesn't stay persistent
And neither is it linked to an IsoZombie
lol albion is always right
So every zombies have their speed reset
e.g. working recipe from my mod``` recipe Make Tap Filter {
keep Base.Scissors,
Base.WaterBottleEmpty/Base.PopBottleEmpty,
Base.Sandbag=1,
Base.Gravelbag=1,
Base.RippedSheets/Base.CottonBalls,
Result:TapFilter,
Category:Survivalist,
Time:30.0,
}
Except about Steam star system.

Goddamn system is trash and irredeemable
Our goddess Albion only speaks the truth
i'm not use _ in translate files, work fine
Oh really?
So it's optional there?
Wow, never would have seen that coming.
oh that's interesting, i see i used underscores too
Thanks for enlightening us. @verbal yew
I need to permanently update zombie stats
Unless I find a way to tag a zombie respawning
I could do that actually
Keep a list of every IsoZombies in a cell around the player
And whenever I have a zombie update, check if the zombie is in the list, if not that means it was newly loaded in
So requires an update of stats
yep, that's like Random Zombies by belette work
Actually that could do it but how do I check that a zombie is no longer in the list, perhaps ontick verify every zombies in a cell
hmm
sounds expensive
ever think about how many mods would be like three lines if they just had OnCreateZombie
I need to have my zombie updating function run before I append the list. I can have a timer OnTick to only update the list like every 10 seconds
Yeah lmao
fucking hell
Actually
Actually wait
Could you link a new Event to the creation of a new zombie ?
Like myself ?
Without even java modding ?
A java decoration ?
@thick karma do you think that could be doable ?
not without java modding
Yeah bcs the creation of zombie is probably not accessible
I would expect zombies to be created Javaside often
Although createZombie is exposed.
i don't know if they're ever created by lua
They are not created by lua, that's for sure