#mod_development
1 messages · Page 42 of 1
is there already a vehicle there? is it water? if it's water it should be a boat, etc..
if there's already a vehicle there it should pick a new spot
at present i am thinking of restructuring this and taking the vehicle-to-spawn out of the equation and doing that at spawntime, picking from boat or vehicle depending on if the zone is water
(to avoid having to reject zones due to this)
the clients pick the first random spot to take load off the server, but i think the server will end up placing subsequent random spots into the queue
this could potentially lead to a loop of checking and rejecting in a row if enough chunks are loaded
anyone have any thoughts on how to do that any cleaner?
is there an elegant way to get player from online id on the server? getPlayerByOnlineId seems to be client-only
EDIT: no idea what i was going on about here, getPlayerByOnlineId exists on the server too
what is an online id
lol
usually we go by steam id or username
depending on whether account or broader to the player
well there's no getplayerbysteamid either, and i was worried about whether usernames were unique
loop thru em and check yeah
:P
or
loop through them periodically and build a table
keyed to steam id or whatever
and specifically i wanted this to work with splitscreen, they'd probably share a username/steam id
i dont even know how people access splitscreen
coop button i guess
ive never touched it 😂
--[[
Gets all players matching a predicate. The default predicate is all players that aren't dead.
Usage example:
local all_living_players = albionUtils.getPlayers()
local all_players_named_bob = albionUtils.getPlayers(function(p) return p:getDisplayName() == "bob" end)
Notes:
getNumActivePlayers:
- Singleplayer: number of local players in client (including all split screen players)
- Client: number of local players in client (including all split screen players)
- Server: 1, but getSpecificPlayer() calls always return nil on server
getOnlinePlayers:
- Singleplayer: nil
- Client: lists all players (including split screen players)
- Server: lists all players (including split screen players)
getConnectedPlayers: trash. only seems useful for working with scoreboard?
- Singleplayer: 0
- Client: only updates when a player manually open scoreboard, but lists all players then
- Server: 0
]]
albionUtils.getPlayers = function(predicate)
local result = {}
predicate = predicate or function(player)
return not player:isDead()
-- and player:getCurrentSquare() -- Will filter out players sufficiently far from client that their square isn't loaded
end
if not isClient() and not isServer() then
-- singleplayer
for i = 0, getNumActivePlayers() - 1 do
local player = getSpecificPlayer(i)
if player and (predicate == true or predicate(player)) then
table.insert(result, player)
end
end
else -- multiplayer
local onlinePlayers = getOnlinePlayers()
for i = 0, onlinePlayers:size() - 1 do
local player = onlinePlayers:get(i)
if player and (predicate == true or predicate(player)) then
table.insert(result, player)
end
end
end
return result
end
local onlineID = 10
local players = albionUtils.getPlayers(function(p)
return onlineID == p:getOnlineID()
end)
if players[1] then ...
Note that'll only work in multiplayer I think bc getOnlineID() doesn't work in single player
LOG : General , 1666902398797> isServer=false name=SonjaMaples onlineid=0
LOG : General , 1666902398803> isServer=false name=RafaelaBonilla onlineid=1
Oh, I guess there is an online ID returned by getOnlineID() in single player, so that should work on either
online IDs aren't persistent afaik, btw
between game loads
tyrir goes all out sometimes
:)
now write the overhaul of the vehicle respawn code for me pls lmfao
i've had no ADHD meds for over a month this is killing me
ima go take some old ones i think, better than nothing
<_<
I know your pain 😦
I'm still waiting for mine
Does mod options allow to use use sliders? Like the ones in the screenshots?
So for the "They Knew" mod, does the zomboxivir Ampule completely cure it when your bitten?
yes, but there are other mods which act as a suppressant instead
they share a similar name
Nah, just the checkbox (boolean) and dropdown (table) atm
Okay, I guess I will use mcm then 🤔
.
What's mcm?
A nice less known alternative to mod options https://steamcommunity.com/sharedfiles/filedetails/?id=2815552312&searchtext=Mod+Configuration+Menu
So, I made a mod that everytime you get a random crit, you hear the TF2 Crit sound
local function onHit(attacker, target, weapon, damage)
local isDoneByThePlayer = (target:getObjectName() == "Zombie" and attacker:getObjectName() == "Player")
local isCrit = attacker:isCriticalHit();
if not isDoneByThePlayer or not isCrit then
return
end
print('TF2CritSound!')
getSoundManager():PlaySound("TF2CritSound", false, 5):setVolume(1);
end
Events.OnWeaponHitCharacter.Add(onHit);
But with this code the sound plays in both speakers and has no location, how can I make that the sound is played from the location of the zombie I just hit?
If target is an IsoGameCharacter, might try the playSound() method on it. If memory serves, it will pass the IsoGameCharacter x/y coords to the sound emitter (which I'm assuming will handle stereo sounds, but I have no idea)
How zombie toughness work? It increasethe zombie health or it reduces the damage, and if so, by how much it reduces on each toughness option?
@gilded hawk E.g. if target is a zombie. I think I was unclear how I said that
if (SandboxOptions.instance.Lore.Toughness.getValue() == 1) {
this.setHealth(3.5f + Rand.Next((float)0.0f, (float)0.3f));
}
if (SandboxOptions.instance.Lore.Toughness.getValue() == 2) {
this.setHealth(1.8f + Rand.Next((float)0.0f, (float)0.3f));
}
if (SandboxOptions.instance.Lore.Toughness.getValue() == 3) {
this.setHealth(0.5f + Rand.Next((float)0.0f, (float)0.3f));
}
if (SandboxOptions.instance.Lore.Toughness.getValue() == 4) {
this.setHealth(Rand.Next((float)0.5f, (float)3.5f) + Rand.Next((float)0.0f, (float)0.3f));
}
Just health it looks like
Thought there was a strength option (or something?) for damage
It's clear dont worry 
Yea, it's strength that affects offense. For example, here it affects how many zombies are needed to do drag downs
What type of time interval events can I use?
I know of Events.OnGameTick and Events.EveryOneMinute but is there others?
pzwiki has a list of them. idk how up to date it is though
The usual ones are OnTick, OnTickEvenPaused, EveryOneMinute, EveryTenMinutes, EveryHour, EveryDay... That's all that come to mind
There are a few other tick events, one specifically for rendering, one for climate
OnTick wouldn't it take a huge performance hit?
I'm looking to check when a generator is turned off it should also turn off my item attached to it. Currently just checking if the tile the item is on has square:haveElectricity() == false, turn it off.
I'm sure there are better ways to do this though, but I assume if it checked each tick might be extreme
t={}; for i,j in pairs(Events) do table.insert(t,i) end; table.sort(t); print(table.concat(t,"\n"))```
You do want to be mindful of performance if you are doing something on every frame, yea
Aight one minute it is then
Hmm, is there no event for when the generator goes on/off?
I don't know actually
not event, but something to hook into, a function call for example
@hearty dew I just tried it, and I think it requires me to disable anticheat type 12.
hmm, wouldnt be sure where to look tbf
It's odd, play sound does not seem to work 🤔
It seems like it still plays the sound from the character
how do i get the square if I have the x, y, z?
I don't see anything with a quick search
This seems to work tho
local function onHit(attacker, target, weapon, damage)
local isDoneByThePlayer = (target:getObjectName() == "Zombie" and attacker:getObjectName() == "Player")
local isCrit = attacker:isCriticalHit();
if not isDoneByThePlayer or not isCrit then
return
end
print('TF2CritSound!')
getSoundManager():PlayWorldSoundImpl("TF2CritSound", false, target:getX(), target:getY(), 0, 0, 20, 1, false);
end
Events.OnWeaponHitCharacter.Add(onHit);
Hmm.. Do any other sounds in the game have directional sound? I don't play with stereo so I never noticed
getSquare(x, y, z)
Odd timing, I just found a solution, but I'm not sure about the params
Idk offhand. Does the object you are using have a getSquare() method or similar?
Like what 0, 0, 20, 1, false do? 🤔 I took this from media\lua\client\Tutorial\Steps.lua
if getSquare(v.x, v.y, v.z):haveElectricity() == false then
Like so?
Have you look at the elevators mod code? it does what you are looking for w/ the electricity check
It worked! @hearty dew I just got done testing with 2 different clients on a local server. They ate me and ignored the yogi!
I got it on video as proof of the fact that right after I died I got kicked on a type 5 violation! And also of my success! 🤪
will check ty ❤️
if you're sure that in that coords the square have :haveElectricity() function, probably yes, but anyway I recommend something like
local square = getSquare(x, y, z)
if square then
--TODO
end
--or
if square and square:haveElectricity() then
--TODO
end
I wonder what type 5 is and why it didn't trigger until I died...
Boh, this thing does not seem to work, I tried getSoundManager():PlayWorldSound("TF2CritSound", target:getSquare(), 0, 10, 1, true) but sound still seems to not work as stereo
Are any sounds in the game directional/stereo? I don't play with stereo so I never noticed if that's a thing
Most of them are, helicopter, zombies, gunshots
Are those random events directional (wolf howl, gunshot/scream in distance)? Those go through the AmbientStreamManager if I recall correctly
Quick mod question guys. I'm having a bug where mods are like, missing segments of a model
Example image, STALKER overcoat is missing the legs
I was asking cause I'm trying to increase the melee damage when using a item I am making. For that I'm using onhitingcharacter event that give me the hit damage. But after several logs and then digging the source code, I found out that this damage the event give me it's not the final damage that is reduced from zombie health, several other operations occurs like multipliers from weapon skil for example and a final 0.15 multiplier for melee weapon, if I get this correct. So is that another method that I can call to inflict this extra damage that take account all those multipliers too?
I was just taking this hit damage setting zombie health minus the extra damage, but that's happening to be too high than I thought, because it's seems the final damage pass through all those multipliers
Maybe it's the image file mask's alpha layer, or the text-like file's "Mask ID" #modeling message.
It appears to be, my confusion is that it seems to be happening on base models of the STALKER mod as intended
Like the armband doesn't end up in the right spot or whatever
What u mean dawg?
Like running STALKER outfits, the oxygen tank and stuff are clipped by everything and have sections missing
So I imagine it isn't the mod itself doing that, although it could
Like something is interfering
Do you mean you downloaded the mod and it was doing that?
Yea
I feel like I see it happen with Shark's stuff too
So I wonder if its a settings issue somewhere
Maybe you have a mod that overwrites mask image files that are referenced by mods.
Yeah I just thought it was by item, not something overwritten
Does it happen with base game non-mod things too?
No, it doesn't seem to happen with base items
hey guys how do I enable upgrades on my firearm mod? I have the modelweaponparts in the item file but there is no upgrade option
took a look at the mod myself - doesn't look like a masking issue to me, if i compare my game to the screenshot the clothing models are literally just smaller in the screenshot
:/
Either the weapon upgrade also needs to list the weapon in its list of weapons it can attach to, or you need to code the choice to attach it into something like the context menu, or maybe a recipe if that would work.
do you know if there is a code template to add a weapon to the upgrade list?
maybe
local something1 = InventoryItemFactory.CreateItem(item_full_type) --makes a copy of the item so that you can get what weapons it can attach to. that's all the item copy is needed for here and it should disappear by itself soon.
local something2 = something1:getMountOn(); --gets the list of weapons it can attach to
local something3 = ScriptManager.instance:getItem(item_full_type) --gets the script item, which is the item template the game uses to create items from which you can edit
Then some more code to turn the list of weapons into a string and then add to the string and then apply the string back to the script item.
Do you know Lua or a coding language?
not really lol. I also don't know enough about the actual game structure itself to do much yet. kind of just putting together mods that are based on my interests in modelling and balancing items. I appreciate the help here!
would I throw this into the lua/items folder then yeah? or can I just throw this into the item file?
I am just adding an AK47 to the game as a standalone gun so I should be able to skip the list string part right?
This might work for that.
local function something()
local attachment_full_type_array = {"base.hey", "base.hail", "base.hello"}
for i,attachment_full_type in pairs(attachment_full_type_array) do
local something1 = InventoryItemFactory.CreateItem(attachment_full_type)
local something2 = something1:getMountOn();
local something3 = ScriptManager.instance:getItem(attachment_full_type)
local something4 = "MountOn ="
for j = 1,something2:size() do
something4 = something4 .. " " .. mountOn:get(j-1) .. ";"
end
newString = newString .. " someMod.AK47;"
something3:DoParam(newString)
end
end
Events.OnGameBoot.Add(something)
Except you have to list each attachment in attachment_full_type_array instead of things like hello. This should go in a lua file. media\lua\client should be fine.
Also, farewell.
i was wondering if anyone knew which mods these are related to?
the OS- ones are from more occupations
how do one create a horizontal scrolling panel?
i tried using double ISPanel for scroll frame + content but it didn't work plus rendering content outside of frame's width
first row is the scroll panel while the other is using vanilla grid
do i need to write new ui components using stencil rect?
Anyone knows what´s the proper encoding of the translation txt files for russian?
$ file ProjectZomboid/media/lua/shared/Translate/RU/*
ProjectZomboid/media/lua/shared/Translate/RU/Challenge_RU.txt: ISO-8859 text, with very long lines (446), with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/ContextMenu_RU.txt: ISO-8859 text, with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/DynamicRadio_RU.txt: ISO-8859 text, with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/EvolvedRecipeName_RU.txt: ISO-8859 text, with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/Farming_RU.txt: ISO-8859 text, with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/GameSound_RU.txt: ISO-8859 text, with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/IG_UI_RU.txt: ISO-8859 text, with very long lines (487), with CRLF line terminators
ProjectZomboid/media/lua/shared/Translate/RU/ItemName_RU.txt: ISO-8859 text, with CRLF line terminators
The vanilla russian translation files are ISO-8859 it seems
$ cat ProjectZomboid/media/lua/shared/Translate/RU/language.txt
VERSION = 1,
text = Russian,
charset = Cp1251,
CP 1251 is also known as Windows Cyrillic.
Appears to be https://en.wikipedia.org/wiki/Windows-1251.
Not sure why file detected it as ISO-8859. Might be some overlap between those character encodings or some mistake in file
I don't know how to change the encoding, tried a lot of encodings, but I get some gibberish every time
Not sure if it is VSCode
I have a mod idea but its beyond my ability to mod..
To be able to build containers with distrib
So that items spawns
Watch daddy dirks youtube tutorial. Thats where i learned
@thick karma
is it ok to pm you with question about controller support?
could you make a guide with best practices for controleers
I am adding some context options and cursor.
-- client-side
local function clientSideFunc(task)
-- ...
task.yield()
-- ...
task.wait(500)
return 2
end
local function fn(task, player)
local result = task.awaitFunction(clientSideFunc)
print(result) -- => 2
local remoteResult = task.awaitRemoteCommand("MyModule", "myCommand", 5, player)
print(remoteResult) -- => 100
-- etc
end
local task = createTask(fn).start(currentPlayer)
-- Do some other things ...
-- server-side
function MyModule.myCommand(task, arg, player)
for _, p in pairs(getNearbyPlayers(player)) do
task.awaitRemoteCommand("MyModule", "otherCommand", "arg", p)
end
print(arg) -- => 5
return 100
end
@thick karma @astral dune Would something like that make sense / be useful? If so, any ideas to improve it?
I can't really think of contexts in pz modding where awaitFunction would be useful?
Maybe useful as a generic utility when an action being done affects another player until the action is complete.
I certainly wouldn't mind an awaitFunction used to decorate Medical Check to hold the stupid patient in place while administering medical care... 😒
The await could also act as a timeout in the case of something happening to the person doing the action (e.g. actor getting Thanos snapped) without needing the actor to notify the awaiting player that whatever they were awaiting was disrupted for whatever reason.
So something like Await("MyModule", "DoThisUntil", "untilArgs", "ThisIsCalled", timeout)
I'm looking for a way to play a directional sound only hearable by the local player and not the others. Does anybody has an idea? I'm currently playing around with the SoundEmitter stuff. But no luck so far.
Try UI sound
You just have to create left and right panned audio tho
I think theres a way to play UI audio
does the UI have a sample of a directional sound where I can peak in the code?
Idk man. Its just an idea of where u might find leads hopefuly it helps
ok, thx... I check if I can find something.
It does look useful! The await function automatically passing the task it's inside of?
Yeah of course.
applyMedication = function ()
player:getBodyDamage():seColdStrength(player:getBodyDamage():getColdStrength() - 20);
player:Say("I feel bit better")
end
anyone have idea why it doesn't work
player:getBodyDamage():seColdStrength(player:getBodyDamage():getColdStrength() - 20); this part gets error in debug
If I could have an await function running in an entirely separate thread, wouldn't execution generally be a little faster than in the current meta where I interrupt the main flow of events OnTick for some logic checks and possibly for triggering more complex procedures?
"seColdStrength"
np
after i fix it my character does not get lowered cold sickness nor says "i feel bit better"
yet the script happens
Hi. I'm trying to increase some melee damage on zombie. Right now using the OnWeaponHitCharacter(player, target, weapon, damage) envent to get the damage and reduce some extra damage from target health via target:setHealth(target:getHealth() - damage/2). But what happens is, for example:
Just debuging to see what happens, the given damage by the event is 1.7. But when I log the target health before and after the attack the health reduces only 0.250 for example (I think this is because this damage it's not the final damage that is reduced from the zombie health, several multiplier occurs after the event)
Is there a way I can get this final damage, the one that is actually reduced from zombie health? Or right now, this event is the only way?
finally was able to remove items on the ground
local inv = getPlayer():getInventory()
local sq = getPlayer():getSquare()
for i=0, sq:getObjects():size()-1 do
if instanceof(sq:getObjects():get(i), "IsoWorldInventoryObject") then
local item = sq:getObjects():get(i)
sq:transmitRemoveItemFromSquare(item);
item:removeFromWorld()
item:removeFromSquare()
end
end
ISInventoryPage.renderDirty = true;
ISInventoryPage.dirtyUI();
inv:setDrawDirty(true);
but its not yet a perfect script it throws error and sometimes it doesnt delete all
can someone ppls help improve the snippet
do you want to instant kill?
local zombie = square:getZombie()
if zombie then
zombie:Kill(playerObj)
No. Just increase the damage by 50% for example.
ah iwouldnt know,,.. havent tried it
And because this damage the event give me looks like it's not the final one, if I use the way I said, the increase will be much higher than the 50% I want....
I think it throws an error because "sq:getObjects():size()-1" is the size of the list before you altered it by removing items. So 'i' increments against a list that is no longer the same size, eventually calling for an item out of the bounds of the item list.
Maybe try "local item = sq:getObjects():get(0)" so you are always getting whatever is at the top of the list "sq:getObjects():size()-1" times.
what you said is hard to digest for me... lol ill try
Ive also seen that for iterating a shrinking list, you can start from the top, as in i=sq:getObjects():size()-1 and till i>0
Say you have a list {A, B, C}
Size will tell you there are 3 items in there
So your for loop will run 3 times with i = 0 then 1 and then 2.
But you are removing items from the list each time.
So the first run would be list.Get(0) which is 'A'.
But after you remove 'A' from the list, the list is now {B, C} while the for loop will still run two more times with i continuing on to 1 and 2.
So the next loop will be list.Get(1) which is 'C' instead of the 'B' you expect.
And the third iteration of the for loop will ask for the third element of a list that only has { B } so it'll error out.
This is for looping through Lua tables. I think you're accessing Java ArrayList functions that have been made visible to Lua
E.g., I use this:
-- Util
function showMeContents(someTable)
for key, value in pairs(someTable) do print(key) end
end
To see the keys of those mysterious table objects that have fields that aren't documented in any obvious public way to my knowledge
ill try thnx
for key, value in pairs(getPlayer():getSquare():getObjects()) do print(key) end
right?
i think its cuz of the table im trying to get the items from
getPlayer():getSquare():getObjects()
isnt really a container
You wouldn't use pairs on getPlayer():getSquare():getObjects() afaik, because you're accessing Java methods and receiving Java objects when you make calls to getPlayer() and its methods
You want the items on a specific square?
Your goal is just to loop through all the items in a single square, right?
Actually, wait, your goal is to remove all of the items in a single square? @ancient grail
Can you clarify?
yes
but the thing im looping from is the getObjects which also containes non worldinventoryitems
if instanceof(sq:getObjects():get(i), "IsoWorldInventoryObject")
so i had to do this
If theres an array for only worldinventoryobject on the tile the player is stepping on then thats the solution
Hello this is the mod Keep that Radio ON! Lite I would like to patch it so when you don't hold your talkie walkie, it would shut down the microphone so you can only listen to people talking in the talkie and only be able to talk on the talkie if you are holding it in your hands
Do you have an idea about what to do?
Have you tried getPlayer():getSquare():removeAllWorldObjects()?
Also, @ anyone who can answer this, how does split screen work for keyboard users in Zomboid? If someone is playing on keyboard, how does the game know which player pressed the key during keyboard events? I'm wondering if I fire a function on a key event that loops through until getNumActivePlayers, will it apply to all the local players whenever someone using a keyboard presses a key? (Not the desired effect... would prefer function to affect only the player who pressed the key.
The joypad stuff lets me get the calling player directly from self... That's super convenient. Stuff like OnPlayerMove also guarantees that I have the right player. But OnTick and OnKeyStartPressed and such seem dangerous
(for split screen)
Never mind, just saw Indie Stone confirm that lack of support for KBM splitscreen is a fundamental Windows issue afaik... so thankfully I can ignore that I hope.
I will when i get back to it. Thnx!
I've seen a lot of overwriting functionshere lately and remembered somebody was using the triggerevent command before / after certain function, instead of hooking/decorating. Can't remember where it was unfortunately.
Was thinking of updating some of my old code.
What are you trying to update?
I know snake's modpack breaks my inventory transfer hook for example. I haven't checked what he does, but I thought I'd go back and update my hooks. I am going to rename the file for sure, not sure what else I'll do.
I see. I am sure there are a variety of conflicts that can arise from attempting to hook / overwrite the same functions in different ways. When I overwrite, I am trying to make sure that I only reference globals that I have declared in my own class or locals of the overwrite function, and that seems to prevent my double-overwrite of JoypadControllerData.onPressButtonNoFocus from causing any problems (just an example of something I am currently double-overwriting without generating any errors / exceptions).
Anyone know what causes a Type 5 or Type 12 error? Or are these still a total mystery, and we just disable the ones that seem necessary for our mods to work???
It seems to trigger intermittently during my respawn or immediately after respawning...
Does anyone have a clue on which command to use to disable microphone and enable microphone from a talkie?
I'm familiarizing myself with Lua coming from C#. Looking at Distributions.lua specifically:
items = {
"BandageDirty", 1,
"BeerCanEmpty", 2,
}
How does this get parsed? From my current understanding, 1 isn't automatically associated with "BandageDirty", it's just a standalone value in the table.
@ancient grail do you have an idea about that please?
no sorry no i havent dont anything with mic related mod
crap :c
Indeed. They are just two standalone values so you'd need to trust the list is was made and added to in the expected format.
Such as parsing it with
local itemName = items[i];
local lootChance = items[i+1];
end```
Alright, that's what I thought, but wanted to make sure I wasn't missing some underlying functionality. Thanks!
At a glance, this sounds more difficult than just examining this file alone. The key code that was modded to make the walkie talkie work while unequipped appears to be this:
--if self.deviceData and self.deviceType=="InventoryItem" then -- conveniently turn off radio when unequiped to prevent accidental loss of power.
-- self.deviceData:setIsTurnedOn(false);
--end !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!REMOVED to allow radio to remain turned on while not equipped in hand!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Yes the command that is activated when you unequip the talkie is put in comment
Unfortunately, as you can see, the code just decides whether to turn the radio on or off
It doesn't seem that there are separate states for "canHear" and "canTalk"
It's just on or off
we could replace self.deviceData:setIsTurnedOn(false); with the command to turn off microphone
then how the game can store the value of the microphone?
So the game may have some internal ability to set the mic on or off independently of the receiver, or it may not, but either way it does not seem to be in that file
D:
The game could simply use the same variable
why is it always so complicated for VOIP 
try item:setActivated()
e.g. ```
if isOn
activateMic()
activateSound()
end
That would be one variable responsible for both
That said, there likely are unique functions
or that
For activating the reception vs. speaking.
So you would have to go into the file that determines how the walkie talkie hears or talks and see when exactly those commands get sent, and how
I do not know where that is
I am speaking abstractly
wouldn't this turn off the walkie entirely?
Well I did not read every single line, but I searched that file for "equip", and only that one example showed up
So there is no obvious place where the equipped state of the walkie is being checked like that
Hmm
At least I would like to turn off the microphone when you unequip the talkie, if we have to turn back on the mic when getting it again in hands it's okay
and we have the line for unequip
Hold on
Here we go
This is the breadcrumb so-to-speak @kind fossil :
function ISRadioWindow:createChildren()
ISCollapsableWindow.createChildren(self);
local th = self:titleBarHeight();
--self:addModule(RWMSignal:new (0, 0, self.width, 0 ), "Signal", false);
self:addModule(RWMGeneral:new (0, 0, self.width, 0), getText("IGUI_RadioGeneral"), true);
self:addModule(RWMPower:new (0, 0, self.width, 0), getText("IGUI_RadioPower"), true);
self:addModule(RWMGridPower:new (0, 0, self.width, 0), getText("IGUI_RadioPower"), true);
self:addModule(RWMSignal:new (0, 0, self.width, 0), getText("IGUI_RadioSignal"), true);
self:addModule(RWMVolume:new (0, 0, self.width, 0), getText("IGUI_RadioVolume"), true);
self:addModule(RWMMicrophone:new (0, 0, self.width, 0), getText("IGUI_RadioMicrophone"), true);
self:addModule(RWMMedia:new (0, 0, self.width, 0 ), getText("IGUI_RadioMedia"), true);
self:addModule(RWMChannel:new (0, 0, self.width, 0 ), getText("IGUI_RadioChannel"), true);
self:addModule(RWMChannelTV:new (0, 0, self.width, 0 ), getText("IGUI_RadioChannel"), true);
end```
It adds these children
One of which is RWMMicrophone
That keyword does not appear anywhere else in the file, so I'm guessing it's its own class in its own file somewhere else.
Okay, @kind fossil , looks like that RWMMicrophone has a mute state:
function RWMMicrophone:new (x, y, width, height)
local o = RWMPanel:new(x, y, width, height);
setmetatable(o, self)
self.__index = self
o.x = x;
o.y = y;
o.background = true;
o.backgroundColor = {r=0, g=0, b=0, a=0.0};
o.borderColor = {r=0.4, g=0.4, b=0.4, a=1};
o.width = width;
o.height = height;
o.anchorLeft = true;
o.anchorRight = false;
o.anchorTop = true;
o.anchorBottom = false;
o.fontheight = getTextManager():MeasureStringY(UIFont.Small, "AbdfghijklpqtyZ")+2;
o.muteState = false;
return o
end
This suggests that if you can access the RWMMicrophone object, you can just go:
mic.muteState = true
when the player puts away the walkie.
And that MAY work
IF that variable gets checked before the walkie listens to you
Yeah I assume that is getting checked... I dunno I'll look around
No
Looks like that's a no go
Because here
if self.deviceData then
self.muteState = self.deviceData:getMicIsMuted();
if self.muteState then
self.muteButton:setTitle(getText("IGUI_RadioUnmuteMic"));
else
self.muteButton:setTitle(getText("IGUI_RadioMuteMic"));
end
end
end```
It uses that variable internally and overwrites it with then result of getting the mic state from the device data
so we can't alter the variable?
We can, sure, pointlessly
fck
But it's calling this with the deviceData
Javadoc Project Zomboid Modding API declaration: package: zombie.radio.devices, class: DeviceData
so the mod can't be possible?
Hope is not lost, just gotta keep thinking @kind fossil
So when you grab the deviceData object off the microphone as it does in setMuteButtonText() above when it says self.deviceData, you get that Java class back... sort of. You get access to it functions, at least. getMicIsMuted is a Java-side function that is clearly exposed to the Lua (or the Lua couldn't be calling it here)
deviceData will contain a function: setMicIsMuted(boolean boolean1)
I'm like 99% sure that's the function you would need to call.
damn maybe we can find something
so, it would basically be microphone.deviceData:setMicIsMuted(true) when you pocket it, or false when you retrieve it.
How exactly to acquire microphone properly depends on where and how you hook it
At a glance, self.deviceData appears to be available in that first class you posted.
So perhaps, instead of the commented-out part here...
--if self.deviceData and self.deviceType=="InventoryItem" then
-- self.deviceData:setIsTurnedOn(false); -- Turns it off.
--end
try...
if self.deviceData and self.deviceType=="InventoryItem" then
self.deviceData:setMicIsMuted(true); -- Mutes it.
end
Then wherever you find setIsTurnedOn when you pull it out, change it to setMicIsMuted(false) instead.
You following?
I'm sharing screenshots to the team but yeah i get it
Cool, let me know if you can't figure it out from there, I feel like those are the keys
not a dev myself but studied IT for 2 years so I understand what it means
i think so
i'll try in solo
Good luck!
thank you so much
I'm not sure where setIsTurnedOn(true) actually happens, but honestly you might not even need to mod that, because I would imagine / hope that turning it on twice in a row is designed to be safe.
So if you just design it to stay on in your pocket, I'm guessing that's good
You could add a condition based on a Mod Option to either turn it off or just turn off the mic at the same entry point above @kind fossil
Can I cast nil to a IsoObject in lua? I want to call e method which takes 3 diffrent objects as the second parameter and I want to call the one with IsoObject and it should be null in java.
if you change line 3 to for i=sq:getObjects():size()-1, 0, -1 do this should work fine
Is there any JS/React dev in here?
I'm looking for help with a small zomboid modding related PWA
Anyone know how I can get my hands on the enum Item.Type?
I need to compare against it(See if an item is of type food)
i know i just did this but i forgot where u_u let me see if i can find it
oki
None(0),
Weapon(1),
Food(2),
Literature(3),
Drainable(4),
Clothing(5),
Key(6),
KeyRing(7),
Moveable(8),
AlarmClock(9),
AlarmClockClothing(10);
I circumvented the problem by getting a square at the coordinates I have. To pass nil as an IsoObject (if possible) would still be the better solution. The code I'm using now is:
local soundEmitter = getWorld():getFreeEmitter(soundX, soundY, 0)
proxySoundSquare = getSquare(soundX, soundY, 0) -- Hack because I would like to pass the IsoObject nil parameter to playSoundImpl()
local soundId = soundEmitter:playSoundImpl("ZombieDemonScream", proxySoundSquare)
soundEmitter:setVolume(soundId, 0.90)
Passing the square overwrite the exact coordinates I pass when getting the FreeEmitter.
couldn't find it, maybe i misremembered, but i did something similar, see if just ItemType.Clothing (or whatever) is exposed, and if not try ItemType:valueOf('Clothing')
could you not just do instanceof(item, 'Food')?
instanceof or instanceOf?
instanceof
as part of an if statement i mean
I don't know if that worked
All my items are a food, but they failed the check
Wait no
I can't
I'm operating on Items, not InventoryItems
ok, his file starts with z and completely overwrites the function.
oh! i think you can just go if item:getTypeString() == 'Food' then
this worked thanks!
getPlayer():getSquare():removeAllWorldObjects()
ISInventoryPage.renderDirty = true;
Cool!
I'm not quite following it atm, but I'll take a good look when I get home
Is there a flag for running in debug mode?
isDebugEnabled()
I see... How about for server admins trying to bugfix their online lists?
what do you mean?
Yes
Ah, okay. I'll leave some debug mode logging then
Since I'm doing an autopatcher, wanna give people some way to check what gets caught
hi, i try to create a mod on project zomboid, i wanna make possible to cook an existing item (here bucket of paint) and when it's cooked, its transformed in a new item (color pigments)
I don't really know how to do this
ReplaceOnCooked property in an item
Yep u just have to put
if isDebugEnabled() then
print("somestuff")
end
Does anyone know if daysFresh equal to 1000000000 means that item doesn't have the property set at all and is therefore not perishable?
Idk sorry... you could print it in-game and see if it's going down for a particular item
If it's going down I would imagine it eventually spoils?
Can I do that in admin tools or something?
If you launch with -debug you could open your debug console, use your player object to get your inventory, use your inventory to grab an item, and print its daysFresh. That is an item property right?
I don't see it on the Java side so it might be a lua property that you'll have to go digging for.
Probably somewhere in an item's data.
huh? it is on the java side
Item calss
Really? I tried searching the https://zomboid-javadoc.com/41.65/zombie/util/list/PZArrayList.html and saw nothing
Javadoc Project Zomboid Modding API declaration: package: zombie.util.list, class: PZArrayList
Ahaaaaa
@bronze yoke It's DaysFresh
not InventoryItem. Item
Doh
yeah if you're looking generally for something, if you type all lowercase it won't try to be case sensitive
as in write lua commands in-game?
Both Lua and Java commands to a degree can be launched from the console
e.g., you can type, getSpecificPlayer(0):Say("Ayyyy")
tmk calling a Lua function that forwards straight into a Java function
So essentially you're calling the IsoPlayer (Java class's) Say method, which it inherits from other classes it extends.
oh god
You could also write, yourUncle = "Nobody", and then bobIsYourUncle = function() yourUncle = "Bob" end, and then bobIsYourUncle(), and verify that Bob is in fact your uncle now with print(yourUncle)
That's all Lua
the console basically just follows the same rules as .lua files
Great
Exactly. It counts as its own little scope
I barely know Lua
It remembers variables, functions, etc while you're in-game
LOG : General , 1666974611430> 564,894,782> [UdderlyVehicleRespawn] Running command "RemoveAndSpawnRandomVehicleSomewhere" for player "UdderlyEvelyn".
LOG : General , 1666974611430> 564,894,782> [UdderlyVehicleRespawn] Removing vehicle "Base.VAZ07" as 6999.47998046875, 7554.5 for player "UdderlyEvelyn" to spawn replacement.
LOG : General , 1666974611431> 564,894,783> UDDTST: Zone Specs: 5x3 at 10971, 9447 to 10976, 9450, center: 10973, 9448.
LOG : General , 1666974611431> 564,894,783> -----------------------------------------
STACK TRACECallframe at: getOrCreateGridSquare
function: SpawnVehicle -- file: UdderlyVehicleRespawn_Server.lua line # 54 | MOD: Udderly Vehicle Respawn Testing
function: SpawnRandomVehicleSomewhere -- file: UdderlyVehicleRespawn_Server.lua line # 93 | MOD: Udderly Vehicle Respawn Testing
function: RemoveAndSpawnRandomVehicleSomewhere -- file: UdderlyVehicleRespawn_Server.lua line # 120 | MOD: Udderly Vehicle Respawn Testing
function: Add -- file: UdderlyVehicleRespawn_Server.lua line # 83 | MOD: Udderly Vehicle Respawn TestingERROR: General , 1666974611432> 564,894,784> ExceptionLogger.logException> Exception thrown java.lang.IllegalArgumentException at NativeMethodAccessorImpl.invoke0 (Native Method).
function UdderlyVehicleRespawn.SpawnVehicle(vehicleToSpawn, spawnX, spawnY, spawnFacing, playerUsername)
local squareToSpawnAt = getCell():getOrCreateGridSquare(spawnX, spawnY, 0)
if squareToSpawnAt:getChunk() ~= nil then --It's loaded, try to spawn it now.
if UdderlyVehicleRespawn.TestSquare(squareToSpawnAt) then --If it's not occupied, spawn vehicle.
vehicleToSpawn = vehicleToSpawn or UdderlyVehicleRespawn.GetRandomVehicleScriptForSquare(squareToSpawnAt)
print("[UdderlyVehicleRespawn] Spawning \""..vehicleToSpawn.."\" at "..spawnX..", "..spawnY.." for player \""..playerUsername.."\".")
addVehicleDebug(vehicleToSpawn, spawnFacing, nil, squareToSpawnAt)
else --It's occupied, try another recursively.
local centerOfRandomZone = UdderlyVehicleRespawn.GetCenterOfZoneSomewhere()
UdderlyVehicleRespawn.SpawnVehicle(nil, centerOfRandomZone.x, centerOfRandomZone.y, centerOfRandomZone.facing, playerUsername)
end
else --It's not loaded, throw it in the backlog.
print("[UdderlyVehicleRespawn] Could not spawn vehicle at "..spawnX..", "..spawnY.." for player \""..playerUsername.."\" because the selected square had no chunk, adding to backlog for later.")
UdderlyVehicleRespawn.AddVehicleSpawnToBacklog(vehicleToSpawn, spawnX, spawnY, playerUsername)
end
end```
54 is the second line
oh no it's my boss

it's literally failing to get a grid square
ive never seen this fail
it can be unloaded and thus have nil chunk
but i've NEVER seen it just throw illegal argument exception
the only arguments are x, y, z
i dont see how it can be illegal with args of 10973, 9448, 0
esp when this same function operates fine when called from a different source
a nearly identical one
UdderlyVehicleRespawn.CommandHandlers["SpawnRandomVehicleSomewhere"] = function(player, args)
local centerOfZoneToSpawnIn = UdderlyVehicleRespawn.GetCenterOfZoneSomewhere()
UdderlyVehicleRespawn.SpawnVehicle(centerOfZoneToSpawnIn.x, centerOfZoneToSpawnIn.y, centerOfZoneToSpawnIn.facing, player:getUsername())
end
UdderlyVehicleRespawn.CommandHandlers["SpawnVehicleSomewhere"] = function(player, args)
local vehicleToSpawn = args["vehicleToSpawn"]
local centerOfZoneToSpawnIn = UdderlyVehicleRespawn.GetCenterOfZoneSomewhere()
UdderlyVehicleRespawn.SpawnVehicle(vehicleToSpawn, centerOfZoneToSpawnIn.x, centerOfZoneToSpawnIn.y, centerOfZoneToSpawnIn.facing, player:getUsername())
end```
only difference is it adds a specific vehicle script
i require help
please :|
spent hours last night
FYI, you could also grab a single Lua table object and dump its keys (to see what can be accessed inside of it) with a function like this:
BS = {}
BS.reveal = function(someTable)
for key, value in pairs(someTable) do print(key) end
end
I needed this to get at the details of your joypad's focus object (JoypadState.players[self.player+1].focus) and the contents of a table named items that I was retrieving from somewhere mysterious to me.
you're not passing the arguments you think you are
the earlier one is passing x into vehicleToSpawn
function UdderlyVehicleRespawn.SpawnVehicle(vehicleToSpawn, spawnX, spawnY, spawnFacing, playerUsername)
yeah
oh
thank you so much
hugs
i spent 4 hours last night
of course ^u^
boutta cry that u figured it out so easy 😂
Eve, go to bed now
Good eye @bronze yoke
no i gotta go have a daytime
no, sleep
SLEEP
@weak sierra Omg so many nights recently trying to make these mods less of an embarrassment to my effort
yeah i've been getting like 5 hours recently, sleep sucks
Sleep is stupid fuck sleep
same, ~3yo daughter + modding + just bad sleep out of the box
i want them magic future pills that replace sleep
You should make a mod so we need less sleep! @weak sierra
if u find the hook to mod IRL u let me the fuck know
wat is problem
Yes, I have never heard of this "problem". What is this?
I know that some items define ReplaceOnRotten
problem is when "this is fine" dog
But some don't
/russianaccent
check nil
I wanna check if the item has?
so instead of the get function, I just try to access it directly?
something.x = nil is same as something {}
if (item.ReplaceOnRotten) then youAreGood() end @tardy wren
yes
local x = something.x
Ah... I've been using the getFunctions
if x == nil then --[[do stuff]] end
and it failed on me because Item isn't a Food
wait r u talking about fields
Is it currently not possible or just way to hard to add Custom Events like Annotated Houses?
uh
yeah for fields
get functions hould just return nil
usually
if not there
but u can use reflection to access field directly
if public
(reflection in here is limited)
methods can be nil
if u access them without calling them
they are variables that hold code basically
u can manipulate them same way aso ther variables
everything in lua is a table
exception being kahlua has userdata objects for java objects
which are.. kinda
half-tables
kahlua is the java<->lua implementation
@tardy wren Are we talking about a Java object with a Java method or a Lua table with a Lua function?
Java Java
diakon is new and learning by thrusting self into modding
for context
he is helping with my server's modding, very appreciated
even small things taken off my plate 
Eve u have a fricking pickup as your plate
my plate is a semi truck
What class? @tardy wren zombie.scripting.objects.Item?
local item = scriptManager:FindItem(recipe:getResult():getFullType())
if item:getTypeString() == "Food" then
--if isDebugEnabled() then
--getDaysFresh seems to return 1000000000 for unspoilable items. Same for getDaysTotallyRotten
print("Jarred Food Adjusted: ",item)
--end
end
end
For nuw just printing stuff
yeah, for whatever reason, there's no replaceOnRotten field
there is ReplaceOnCooked
if item:getReplaceOnRotten() then probably works though
it doesn't
either u are using it wrong
or
they did something weird
sometimes things dont work like they should
I imagine because I'm calling on an Item
Whereas getReplaceOnRotten is a function in Food
public String getReplaceOnRotten() {
return this.replaceOnRotten;
}```
this is the java
it's uh
simple
and no it's on item
there's no superclass
they just redundantly reuse it
like Thing on rimworld (he comes from rimworld modding)
okay maybe I screwed up in copying the text over again
29 print("Jarred Food Adjusted: ",item:getReplaceOnRotten())
STACK TRACE
-----------------------------------------
function: JarredFoodAdjuster.lua -- file: JarredFoodAdjuster.lua line # 29 | MOD: Jarred Food Spoilage Adjuster
ERROR: General , 1666975740502> 254 499 348> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in JarredFoodAdjuster.lua at KahluaUtil.fail line:82.
ERROR: General , 1666975740502> 254 499 348> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: Object tried to call nil in JarredFoodAdjuster.lua
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.pcall(KahluaThread.java:1782)
at se.krka.kahlua.integration.LuaCaller.pcall(LuaCaller.java:76)
at se.krka.kahlua.integration.LuaCaller.protectedCall(LuaCaller.java:117)
at zombie.Lua.LuaManager.RunLuaInternal(LuaManager.java:559)
at zombie.Lua.LuaManager.RunLua(LuaManager.java:505)
at zombie.Lua.LuaManager.RunLua(LuaManager.java:491)
at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:334)
at zombie.Lua.LuaManager.LoadDirBase(LuaManager.java:261)
at zombie.network.GameServer.doMinimumInit(GameServer.java:1405)
at zombie.network.GameServer.main(GameServer.java:684)
LOG : General , 1666975740506> 254 499 352> -----------------------------------------
STACK TRACE
-----------------------------------------
--if isDebugEnabled() then
--getDaysFresh seems to return 1000000000 for unspoilable items. Same for getDaysTotallyRotten
print("Jarred Food Adjusted: ",item:getReplaceOnRotten())
--end
end
``` Gonna try this?
They are all Foods
yeah, the problem is diakon is operating on Items, and getReplaceOnRotten() is from Food, which extends InventoryItem
I'm trying to figure out how to get a Food from that r.n. and failing @bronze yoke
There's no way to go from Item to Food
I can get the Item from Food
but not the opposite
you could create an instance of the item and check for it there
What about getDaysFresh()?
You're getting an Item with FindItem.... did that call not work?
Ohhh
I see.
I thought you wanted days until rotten for some reason
Rugged Recipes has "fermenting" as its preparation, and I need to go down that tree
thank you albion, saved me many hours of blindly not seeing that mistake potentially
lol

Q: anyone know why i can't retrieve the field "public IsoDirections dir" from vehiclezone via reflection?
UdderlyVehicleRespawn.GetViaReflection(zone, "public IsoDirections dir")```
--Reflection Wrapper
UdderlyVehicleRespawn.ReflectionCache = {}
function UdderlyVehicleRespawn.GetField(obj, fieldString)
local cachedValue = UdderlyVehicleRespawn.ReflectionCache[fieldString]
if cachedValue == nil then
local num = getNumClassFields(obj)
local idx = nil
local zones = nil
for i=0, num-1 do
local field = getClassField(obj, i)
if tostring(field) == fieldString then
UdderlyVehicleRespawn.ReflectionCache[fieldString] = field
end
end
end
return UdderlyVehicleRespawn.ReflectionCache[fieldString]
end
function UdderlyVehicleRespawn.GetViaReflection(obj, fieldString)
return getClassFieldVal(obj, UdderlyVehicleRespawn.GetField(obj, fieldString))
end
--End Reflection Wrapper```
everyone has their own reflection wrapper to make it comfy lol
zone is filtered down to vehicle zones only
btw if anyone is unfamiliar with routine caching of things, take a look at how i use a table there to reduce repeated checks to a very fast keyed lookup
can make your mods much faster in some cases
yeah if it's run-once it doesn't matter
depends on the case
tho if it adds significantly to loadtime u cud communicate the precalculated server data to the client in some cases
rather than recalculate it
again depends
Jar of Pickles (Rotten) is usually a good bet
and it might be the same item
just with a different name display calculated
no, it's a separate item
ur sure?
item JarredPicklesUnready
{
DisplayCategory = Food,
Type = Food,
DisplayName = Jar of Brining Pickles,
Weight = 2,
Icon = JarOfPickles,
DaysFresh = 0,
DaysTotallyRotten = 7,
StaticModel = CanClosed,
WorldStaticModel = JarFoodLeeks_Ground,
ReplaceOnRotten = RuggedRecipes.JarredPicklesReady,
}
Pretty sure
that's unready
yes
that's what is crafter
ok so this one rots into the ready
yes
which means u wanna ignore this one
and edit the ready version
or u just lengthen the fermentation time
yes
yeh
But I need to get the ready version
so.. read from ReplaceOnRotten
i assume opening the jars returns jars?
yes
yes
i would still suggest reverting to a simple "put in item ids for those u wish to up the stat on"
because that's two passes on the recipes
Except taht for the compat with rugged recipes, I'm almost done with this
sunk cost fallacy
u spent another whole day when u cudda retooled last night
but
:p
It returns nil for all of them
Item or InventoryItem
Item
I can't get InventoryItem from Item
ur doing dot syntax
yes
that's what falls me
there is a getter for the replaceoncooked in Item
which returns a list of strings
if InventoryItemFactory is exposed, you could use InventoryItemFactory:CreateItem() and then use the getter
nope
But would that modify all the items?
And not the specific instance of the item I created?
you can then use :DoParam() on the script to change the script, you just need the instance to actually get the value
oh there's actually an InstanceItem() on Item
it takes a string though, idk what that's expecting
just read through it, var1 is optional
idk what it does but every use of it first checks if there even is one
I don't know what good those will do you but you can inspect if you want
Thanks
oh i think it might be to do with items that have multiple colour variations
ah, okay
Looks like you can instantiate a Food() with an Item() but I don't know about doing that from Lua
the string sets which variation to instantiate somehow
we just found a way
Looks like the first 3 inputs needed for an InventoryItem are
this.module = var1;
this.name = var2;
this.type = var3;
it might not be the best idea to post these full decompilations, as it does sort of break the tos
uhhh
STACK TRACE
-----------------------------------------
Callframe at: InstanceItem
function: JarredFoodAdjuster.lua -- file: JarredFoodAdjuster.lua line # 29 | MOD: Jarred Food Spoilage Adjuster
paź 28, 2022 7:17:48 PM zombie.Lua.LuaManager RunLuaInternal
SEVERE: java.lang.RuntimeException
paź 28, 2022 7:17:48 PM zombie.Lua.LuaManager RunLuaInternal
SEVERE: java.lang.RuntimeException:
paź 28, 2022 7:17:48 PM zombie.Lua.LuaManager RunLuaInternal
SEVERE: at InstanceItem
at JarredFoodAdjuster.lua:29```
I don't think I can do this
i've never seen an error like that 😟
there might still be a way to do it, but yeah, it's strange that there isn't one, it might be an oversight
Eve mentioned going backwards
finding what items/recipes give me a jar
But yes, that is two loops
one through items, one through recipes
My anger grows
i guess the java is strict about how many arguments you give it
Sha,e it doesn't define a default
Okay, I can actually get the item from this
This is what I needed
LOG : General , 1666977912895> 256 669 409> Jarred Food Adjusted: Item{Module: KnoxCooking, Name:PineSyrupFerment, Type:Food} KnoxCooking.PineSyrupReady
print("Jarred Food Adjusted: ",item,inventoryItem:getReplaceOnRotten())
albion you deserve a Zombiexivir
let's gooo
yay
now... Do I futureproof by going recursive on this?
or into a loop like a sane person
As in someone makes several stages of fermentation
nah
wait, should I worry about cleaning up my trash?
what do you mean?
as long as they're locals, the memory will be freed when the code leaves its scope
Ah
I wrote them local in the... uhh...
Global?
tldr, when my file ceases to execute, it will clean up?
print("HEREBEITEMS")
local scriptManager = ScriptManager.instance
local recipes = scriptManager:getAllRecipes()
for i=0, recipes:size() - 1 do
local recipe = recipes:get(i)
local recipeSource = recipe:getSource()
local foundAJar = false
local foundALid = false
for j=0, recipeSource:size()-1 do
if recipe:getCategory() ~= "Cooking" then
break
end
local recipeItem = recipeSource:get(j):getItems()
if recipeItem:contains("Base.EmptyJar") then
foundAJar = true
end
if recipeItem:contains("Base.JarLid") then
foundALid = true
end
if foundAJar and foundALid then
break
end
end
if foundAJar and foundALid then
local item = scriptManager:FindItem(recipe:getResult():getFullType())
if item:getTypeString() == "Food" then
--if isDebugEnabled() then
--getDaysFresh seems to return 1000000000 for unspoilable items. Same for getDaysTotallyRotten
local rottenReplace = item:InstanceItem(nil):getReplaceOnRotten() --I need to do this to get ReplaceOnRotten, ugh
if rottenReplace ~= nil then
item = scriptManager:FindItem(rottenReplace)
end
print("Jarred Food Adjusted: ",item)
--end
end
end
end```
Like that's my code so far
scriptManager and recipes won't, but there's a little workaround for that
put them in a function?
if your code is only meant to run once you can just start it with do and end it with end and that makes it its own scope
ah, nice
Jarred Food Adjusted: Item{Module: Base, Name:CannedTomato, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedCarrots, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedPotato, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedEggplant, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedLeek, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedRedRadish, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedBellPepper, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedCabbage, Type:Food}
Jarred Food Adjusted: Item{Module: Base, Name:CannedBroccoli, Type:Food}
Jarred Food Adjusted: Item{Module: SapphCooking, Name:CannedEggs, Type:Food}
Jarred Food Adjusted: Item{Module: KnoxCooking, Name:PineSyrupReady, Type:Food}
Jarred Food Adjusted: Item{Module: KnoxCooking, Name:AcornFlourLeached, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:ReadyBerryWine, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:ReadyKvass, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:FermentedKentuckyKimchi, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:CannedCucumber, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:JarredPicklesReady, Type:Food}
Jarred Food Adjusted: Item{Module: RuggedRecipes, Name:JarredSauerkrautReady, Type:Food}
I got my items
Now to multiply their values properly
Here's the third hard part
Nice find @bronze yoke... So that returned the Food because it was that kind of InventoryItem? That was a tricky find.
yes
Nice one
😇
It creates an instance of the item... Which I can scrape for its values I need
Then got back to Item
I was looking for a way to create the InventoryItem from the item but I just couldn't find any
okay, now for something simple
I followed that much. My surprise was that it gave you a Food because it only tells us on the Doc that it gives us an InventoryItem, and while Food extends InventoryItem, that is to my knowledge the only hint in existence that might have implied you'll get back Food from that function when the InventoryItem is specifically Food.
How can I round to the nearest whole number?
math.floor() rounds down, math.ceil() rounds up
a way to do this is to do math.floor(num + 0.5)
that's so hacky I love it
Would Lua let you add a function to math? @bronze yoke
math.round = function(num)
return math.floor(num + 0.5)
end
``` @tardy wren
i don't see why it wouldn't, but it's probably not good practice
Booooooo 😉
I am now curious what happens if my mod pushes the days fresh above 1000000000
I mean definitely you would be told not to do so in a lot of classes, but ultimately if it works, it works. And in general Lua doesn't seem to get mad when we overwrite other existing built-in libraries, right? I could name a variable math, right?
I don't need to
Plus, doesn't math just deserve a round?
Haha I know but if he is going to use it often it'll look a lot cleaner.
to be fair, math.ceil is just math.floor(num+1)... 🤔
LOL really?
well i don't know the code, but functionally
I thought you meant they wrote it that way
so putting a round in there is basically the same thing as having both of those functions in the first place
@gilded hawk was trying to figure out the same thing, I believe
you think math.floor works by casting to int?
yeah, but if i were to do this it'd be a local function
Mx figured out that being hit by a car is more enjoyable than figuring out 3d audio 💯
Just in case some other asshole like me wants to do something to math.round 🙂
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmin = luaL_checknumber(L, 1);
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_checknumber(L, i);
if (d < dmin)
dmin = d;
}
lua_pushnumber(L, dmin);
return 1;
}
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmax = luaL_checknumber(L, 1);
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_checknumber(L, i);
if (d > dmax)
dmax = d;
}
lua_pushnumber(L, dmax);
return 1;
}
they don't work that way :(
But I'm making a PWA to easily edit and preview the workshop.txt which is quite cool since today I'm stuck at home alone 
oh that'd be super useful
That would be nice a.f. @gilded hawk
PWA?
So tired of duping description=
I made something like that for PD2 some time ago
https://mxswat.github.io/pd2-localization-helper/
Payday 2 Localization helper helps you visualize your custom localization strings
Noper. Because there's no parallelism. The only option available in lua in pz is cooperative multitasking (one routine says to another "okay, now you go", then that routine saying "okay, I'm done, now your turn", etc)
Got it, so it's essentially more sugar.
Well, that's okay, I'm addicted to sugar...
Wait.
What? U got hit by car?
Is it okay?
No, but I'm considering to get it by one next time I try to make 3d audio in pz 
Yay, my mod seems to work
Ok stay safe
Need to pass -Ddebug=true to the server's java process (not at the end of the command line args)
Congrats man
Mind sharing the link?
Woah awsome mod
Maybe that's how it is implemented in java. In lua, there is no distinction between integers and floating point numbers
Too much 3d audio for u man
the math library isn't written in lua
Bruh I'm entering the game for the first time ever to test it lmao
but no, it doesn't work that way anyway
I didn't even hook up the sanbox options yet
Mm, figured it would be written in java in kahlua, if not C using jni
Oh hey I'm a sledgehammer now
it's in c
ow where did my sledgehammer go? owell
@tardy wren re: how to enable debug mode server-side
Thansk. I just asked if it's possible, not how to do it
:)
Alright... @bronze yoke ? Haha I need a whiz on this one... You found the last miracle solution I needed for the halo notes, maybe you'll solve this one. I need access to zombie.input.Mouse, which afaik is exposed to the Lua here:
If it's exposed to the Lua, I feel like the Lua must act on that object SOMEWHERE (or why bother?) but I just cannot for the life of me find a single reference to it.
Might check if it has a getInstance static method or static field
if so, you could do Mouse.instance or Mouse.getInstance()
if you have my inspect function, you can use that to see what's available, Burryaga.inspect(Mouse)
Hmmm so maybe it just exists even though nothing calls it you're thinking?
I'd have to check the java code, but that's possible
What's your inspect function do? I don't think I've seen that one.
hold on i'm playing toontown lol
Hey no stress, lol, if I modded in a hurry I'd have burst into flames years ago
LOL true
I'll jump into the game and try from debug
just prints out what the object is that you pass it
---------- table ----------
table 0x148767608 {
[class] => (userdata) class zombie.input.Mouse <
. <METATABLE> => table 0x789091424 {
. . [__index] => table 0x682936769 ** PRUNED. Max depth reached **
. }
>
[getX] => function 0x1615348194
[getY] => function 0x410340176
[isButtonDownUICheck] => function 0x1932879786
[isButtonDown] => function 0x2101433036
[renderCursorTexture] => function 0x1596218327
[getXA] => function 0x1832494248
[getYA] => function 0x904496786
[setCursorVisible] => function 0x1120495057
[isCursorVisible] => function 0x1070490812
[initCustomCursor] => function 0x535993097
[isRightPressed] => function 0x1716933491
[isLeftPressed] => function 0x1865962885
[loadCursor] => function 0x597632858
[getWheelState] => function 0x675203827
[UIBlockButtonDown] => function 0x2082982220
[isLeftDown] => function 0x1369325360
[isLeftReleased] => function 0x190937006
[isLeftUp] => function 0x1440111971
[isMiddleDown] => function 0x393843516
[isMiddlePressed] => function 0x926832988
[isMiddleReleased] => function 0x929207314
[isMiddleUp] => function 0x1354296024
[isRightDown] => function 0x184771456
[isRightReleased] => function 0x1320304389
[isRightUp] => function 0x1834213573
[setXY] => function 0x2057976221
[update] => function 0x1780832811
[poll] => function 0x892340861
[bLeftDown] => true
[bLeftWasDown] => false
[bRightDown] => false
[bRightWasDown] => false
[bMiddleDown] => false
[bMiddleWasDown] => false
[m_buttonDownStates] => (userdata) [Z@471791d6
[lastActivity] => (userdata) 1666983399932 <
. <METATABLE> => table 0x1826238072 {
. . [__index] => table 0x745457098 ** PRUNED. Max depth reached **
. }
>
[wheelDelta] => (userdata) 0 <
. <METATABLE> => table 0x431509976 {
. . [__index] => table 0x1658513944 ** PRUNED. Max depth reached **
. }
>
[UICaptured] => (userdata) [Z@5f4eb1d5
[new] => function 0x97812323
}
setCursorVisible 👀
only one way to find out!
I've already found this, I just don't know how to access the gd Mouse
haha
Mouse.instance was a no go @hearty dew

All the static methods/fields would be in that table printed above
so no instance, no
Is there a place to read the command console output log? I just dumped _G
it probably just goes into console.txt, right?
honestly idk I assumed that was for errors, checking now @bronze yoke
Ugh look how it taunts me
I wonder...
OMFG
Daaamn
It's ignoring me 😭
i can't find any references at all in vanilla lua
Mouse.setCursorVisible(false) just ignores me 😭
it exists and just says no 😭
No errors.
probably because it's not grabbing any specific instance
Fair but usually wouldn't that throw some kind of error? I thought Java doesn't like accessing instance methods statically...
Maybe it's in a pcall
Or whatever
And just failing and ignoring it
the java seems to use it that way too...
Damn you're right
Just searched it
ooooooof
Tyriiiiiiiiir lmfao
Ah shit I have been betrayed by Java again
Mouse.setCursorVisible(false), damn you! Mouse.setCursorVisible(false)!
If it's a function on Mouse, it is a static method (generally)
instance methods would be on the metatable (__classmetatables has references to those if you can't get an instance otherwise)
i've got some bad news for you
So confusing that print(Mouse.setCursorVisible) prints function
It knows the function exists but cannot use it
the reason this isn't working is because setCursorVisible is set to true every frame
Where?
player update
java
That might be okay
What does that mean? If you're calling it, it's being used. Probably just not fully understanding the implications of using it
Hold on, I think albion made this add up
I think that I AM calling it and it IS working
But what albion said is defeating the purpose
hello, do people here use capsid? I only get this error when using jdk 8
> Process 'command 'C:\Program Files\Eclipse Adoptium\jdk-8.0.345.1-hotspot\bin\java.exe'' finished with non-zero exit value 1
sorry, it's not player update doing it, it's logic() in GameWindow
player update was something else
oh i did it
YOU'VE DONE IT AGAIN YOU BLOODY GENIUS
this hides the cursor
I just figured it out similarly lmfao @bronze yoke
I can't use Sandbox settings to customize it
I cannot screenshot it because my cursor is gone and my controller stole focus lmao
hehe i'm glad we worked that one out
But I added my event to player update
because you told me it happened on player update
And it worked too
Omfg you're a genius
This is like the icing Dawn of the Zed
every player update while you're aiming it sets cursor visible to false, so my guess is that the only way to hide the cursor is to hide it every frame
I needed this so much you don't even know
Albion really is a jenuous
hehe ^u^
Omfg albion you hero
put it on an event that happens after sandbox loads but before items are spawned, i think OnInitGlobalModData is a valid option
So I put all my code into a function, and I add that function into said event?
I knew if it was possible y'all would get me there. Thanks for your input as well, @hearty dew , it helped a lot
yeah!
still having touble
ALBIOOOOOOOOON
AHHHHHH
It's so amazing
DIE CURSOR!
AHHHH PROPER UI HIDING HAS ARRIVED
hehe i'm glad you're happy with it
Now I just need to resist the extreme urge to push this update right now without testing it 😭
tbh i don't test nearly enough
huh so i took a look at the tutorial and figured it out 🙂
shoutout to that time when i updated my literacy mod and accidentally made books completely unreadable; nobody even complained about it, i just happened to notice a week later
BRO WHAT
send that mod
ty
i have an insanely huge update for this mod finished but i've been putting off writing the strings for it for like two months LOL
regarding reading, I want books that give multiplier to more levels but I don't know how to balance it.
Haha congrats!
lol oof yeah I am afraid of doing that myself
well as long as you do the most basic testing that won't happen to you lol
i thought you did it on purpose for a sec then i read it back
oops yeah i did sort of imply that
yeah sorta, you can get a lot faster than that but the xp is pretty hard to get after a certain point
yeah it's working perfectly right now
and of course it's super customisable so if you don't like the balance you can just change it lol
oh sick
@gilded hawk I posted the way I found so far.... I just didn't found a solution to pass an nil IsoObject. But this works for me so far...
#mod_development message
I post the whole solution of my zombie sound stuff when I finished this part of mod.
for a workshop id do i make a folder like this
Interesting
ill watch the vid to find out
No.
huh?
ty
Check a workshop folder for another working mod and copy how it does its workshop info file, but leave out the id line entirely.
Then, when you upload your mod for the first time, Steam will edit that file and automatically assign you an id
i dont understand
what
Open that
ok
So far I calculate the direction of a zombie who is sreaming and make a near proxy square to play the sound.
Unzip the folder I just send you, and look at workshop.txt in the folder
Change title, description, tags
i got smth similar to it
the file structure looks like Zomboid/Workshop/ModName/Contents/mods/ModName/mod.info
yes
you've probably just been working in the mods folder right?
Check the directory structure in my zip
You need to move your mods folder into the directory structure that my zip uses
the what ?
The setup of folders
You need Mod Name > Contents > mods > everything you already have
huh
the base i used
You'll see the pattern if you flip through the zip I sent
Just delete all my files.
Hold on
apart from the workshop txt right
oh sick ty
Edit your descriptions and notice where I set your name and mod id and such
Overwrite poster.png and preview.png or people will think you're making a mod about reading while you move
tysm
If you make them in Gimp and flatten them and export with default settings as .png, you should be good
But make sure you flatten
alr
I didn't once, image wound up slightly misformatted, and nobody could install my mod
Even though it was exactly the same resolution in 2D
that was ridiculous
So... make sure you flatten
2 description lines?
can i delete this
Yes
I was only pointing out that if you want to say things in, say, 2 or 3 paragraphs, you need more description= tags
ty
Yes
what abt id
just put no description there
Just upload your mod to Steam after you get your pictures sorted
Will it use Steam's??!?!
put it either later when uploading and it populates
when you got to upload there's a button put description
i need to test it a bit how can i use it ingame?
or just format on steam and ignore the file
Ohhhh
I see what you're saying
You're saying it's unnecessary to have the description in the workshop.txt
because game lets you write it
how do i??
Yeah, I could just keep a separate text file and copy-paste my description into the box when I upload
there's 3 options
a) workshop.txt
b) before upload there's a button
c) steam
Wait you haven't tested it and you're trying to put it on Steam?
b autopopulates the file
i just changed smth
before that
i just need to see it ingame
to see it in game you turn the mod on in MODS in the main screen.... idk if I understand your question
