#mod_development
1 messages · Page 177 of 1
Okay, so technically this isn't a direct modding question, per se, but...
I'll start with what, in a perfect world, I would like to do, and then maybe we can see what can be done, if anything, to achieve that.
What I'd like to do: Use a telnet client (Specifically, Mudlet, though I can use a different one if necessary) to intercept the messages written to 'server-console.txt', so that I can use Regex triggers to initiate/automate certain admin commands and track data independently, among other things.
I have done similar with 7 Days to Die, on a server where I served as the in-house modder for almost two years, so I'm not completely inept. I just can't seem to figure out how to do it with PZ, or to even confirm if it is possible in the first place.
I'm using Bisect Hosting, and they have a terminal/console on their site that essentially has the output I want, so, on some level, I know it is possible. I'm just struggling to figure out how to get that information through my telnet client.
So, yeah. I think it may be a bit more feasible to write a separate script that reads the server-console.txt and runs alongside zomboid. Not sure if you can do that
Hmm, perhaps. I've been banging my head against this for like 14 hours straight now, so that's probably a 'tomorrow' project 😛
I don't know if there's a way to change where zomboid outputs its console. There may be some linux OS stuff, but I am unaware of those
now I'm wondering if I'm just going about this all wrong, and if it might just be easier to set up custom server commands through the chat box itself...
I have a crazy project idea, live server map on a website?
I assume the question mark is asking if it's possible/feasible (?)
If so, it is possible & its feasibility depends on how comfortable you are creating a website + a mod to send updates (or a program running on the same machine as the server, but a mod would be more straightforward)
Easily done in python and a $2 vps - can provide guidance if needed
Flask / SimpleHTTPServer etc
Just poll on a set interval and parse map data/information to the python script and you could have your idea done and spun up in maybe a week if you’re starting fresh on Linux, python and Lua
Wesbite isn't a problem at all, just getting the raw data (username, x,y coordinates) for me might be difficult since i have no idea how I can get the data
mod for a server would be neat since its super easy to setup
Then that would be fairly trivial
but an external program has more flexibility
External should be resilient against updates if you’re only posting user data and map data
That way would require reading the game data, which is entirely possible but idr how often the coordinates update. It's in binary
If you read from the database sure, but not directly from the user data since that changes with updates (although I suppose if you only read up to the bit you need you'd probably be fine)
I run several websites on React, and making one for pz exclusively now so thats not a problem
But like its possible to save all of the data into a file?
using just lua
Yes
declaration: package: zombie.Lua, class: LuaManager, class: GlobalObject
See also: getFileWriter
I guess making a post request using lua could also work but i have no idea if its possible
Rip
Well.. could work with GET too
wanky af but you can pass parameters to GET request
Only thing you can control is the url params
declaration: package: zombie.Lua, class: LuaManager, class: GlobalObject
This is likely obvious, but there are security considerations to think about, considering people will be able to look at the mod source
Security in this case just meaning ensuring users can't spoof their location or the locations of others
don't use modfilewriter
What do you recommend instead?
the modfilewriter only has a use maybe for development tools, any completed mod should use the regular filewriter
alright
Does it write to the mod directory? I couldn't remember
the modfilewriter writes to the mod directory, which means in multiplayer the checksum fails
ohh..
is there any guide to code zombie outfits?
or should I just reverse engineer some mod out there
use player:getPlayerNum() instead of player
also set all your variables local please, I'm still hurt with people using globals for no reason in the "Item incident"
in general everything should always be local, there's very rarely any reason to go global
Is there a way to get the translated recipe name similar to getText("Recipe_Clean_Bandage")? Doing that gives "missing translation", but it is a valid translation string in Recipes_EN.txt. The way I see it in the game is getting the recipe from the ScriptManager and just getting the name from there, but hoping there's a more direct way.
idk if anyone has any more useful resources, but here's some on the wiki https://pzwiki.net/wiki/Modding#Mapping_tutorials also if you search your steam library you should see "project zomboid modding tools" which i think is for making maps
Alright ty
I’ve mapped on L4D2 before, and it can’t get any more difficult than that
So it’s worth a shot lol
anyone else got any resources for getting started in map making?
Thank you!
what is difference beetween ItemContainer:DoAddItem(InventoryItem) and ItemContainer:AddItems(InventoryItem, 1) . And DoAddItemBlind what is it?
you can specify how many, using AddItems. not sure about blind.
DoAddItem and DoAddItemBlind are the same thing in my decompiled Java and run self.AddItem(item). likely something kept for legacy reasons
strange naming. Why they use "do" instead "add" these are all verbs
Thanks
there's more! addItem and AddItem and AddItemBlind. I'm in shoke
Not sure. The "Do" prefix could mean immediately, as opposed to a request that is carried out in a few frames, or something.
Or it could act as a "TryAddItem" type of function, where it performs various checks first, under the hood.
like dhert said, I'm pretty sure all 6 functions do the same thing.
most weird naming is because of non-english devs
I am interested in understanding what m_Scalar and m_Scalar2 parameters do in AnimSets xml files and when they can be used. I fear the manual RE is gonna be too much for me poor soul so any cue is welcome.
I am also non-English 🙂
are there any mods some of the more experienced people in this channel recommend to look at the code to learn from? i tried poking my nose into the docs and my brain was just rejecting whatever i was reading
Anyone familiar with ProceduralDistributions?
I'm working on a mod that adds new items to school lockers. The items don't seem to be affected by the loot rarity.
Setting my world's loot to Insanely Rare, then searching the West Point school lockers, I find ~50 of the new items
(now that I think about it, maybe modded items need to be classified as 'Other', so that the world's loot rarity sandbox settings work).
Because the world's loot rarity sandbox settings dont work, I decided to adjust the ProceduralDistribution numbers!
adjusting the ProceduralDistribution, I change the value from 1.0 to 0.00000000001.
Checking the lockers with Debug - LootZed, the modded items, indeed, have a E-10% chance to spawn (0.00000000001%), great!
I search the school again, and I still find ~50 of the new items. wtf?
I even changed the ProceduralDistribution value to 0.0% chance to spawn. Checking LootZed, yes. 0% chance to spawn.
...but the school lockers were filled with the new items. What is going on??
yeah, i've never heard an explanation why that makes sense to me but values low enough for it to start displaying with scientific notation don't seem to work properly
yeah, i'd prefer to not use floats/doubles this small...
But playing zomboid on insanely rare loot settings, a pencil or piece of paper goes from 50% to 0.5%.
so assuming my item needs to be much more rare than a pencil, I feel like I have no choice but to drop into scientific notation. hmmm,
if you want spawn chances even lower than is supported, you need to use custom spawning/deletion logic using the onfillcontainer event (which is fired on the server only when a container is populated by the loot generator)
I might be able to sidestep the issue entirely, if I can assign an 'item type' to the modded items?
Looking at the loot rarity sandbox settings, there is non-canned food, ammo, medical, survival essentials, mechanics, literature, other.
maybe the problem, is that these items are none of the above... as a result, they are never set to Insanely Rare. ?
i would assume other is automatically assigned
i know i've never manually assigned one
not sure this is the place to find that, did you try #1019737819981283459 ? plenty of people looking for new friends there i think
Working on a first aid overhaul, it adds a new profession called Paramedic where all medical actions are 2x faster. Speed :)
craz
can i attach a Lua function to an items variable value, in a similar way to how you can have a recipe give XP? like if i make an Icecream as a food item, and the player has a trait that interacts with that, like 'Sweet Tooth' or something, id want the UnhappyChange of the item to be different. Or is there a different approach on how to go about it?
no, the workaround most people use for that is to hook the eating action and perform the checks then
you'd also have to hook the tooltip if you want it to show the trait affected value
it may be something that should have an api made because it's so common
wdym by hook? like having a check if a player did an action per frame/update?
no, you take the vanilla function and add your own code around it
eating is fully lua so you can just edit the functions
local old_foo = foo
function foo()
print("bar")
old_foo()
end
```this redefines a function named foo to fire modded code before/after it without having to overwrite the file or the function entirely
old_foo stores the original version of the function, so when you redefine foo you just need to call old_foo before or after (or in the middle) of your code for it to run the vanilla code
it's a powerful way of editing any lua behaviour, and sometimes java behaviour
so its kind of like in java using inheritance in a way? like a Super call to the original objects constructor
yeah sort of
you can also just redefine a function outright, but saving the original into a variable and then calling it allows for multiple mods to edit the same function (since they'd just stack on top of each other based on load order)
ill have to take a look at how the game does the eating code then to see how to implement my stuff. would i be able to edit base foods in the same way if i redefine the section? so like a base Chocolate Bar for the same sweet tooth perk
yeah, the way i've seen someone do it is basically
(pseudocode, no idea what the correct syntax would be for this exact application)```lua
local old_perform = ISEatFoodAction.perform
function ISEatFoodAction:perform(...) -- perform in a timed action is the one that handles successfully completing it, so i assume eating is done in there
local original_hunger = self.item:getHungerChange()
if self.item:getFullType() == "Base.ChocolateBar" then
self.item:setHungerChange(original_hunger * 2)
end
old_perform(self, ...)
self.item:setHungerChange(original_hunger) -- change it back so it doesn't actually change the stats of the item
end
so basically your editting the item temporarily? would i have to worry about an approach like that for a server?
shouldn't matter as long as you change it back
ok ok, good to know, is the javadoc the best resource to see all the different Lua functions? or has someone written it in different words somewhere else?
the javadoc only has the interface to the java portion of the game, if you want to see the lua stuff most people just go through the code themselves
if you're using a decent ide you can add the game's lua folder as a library to your project to get intellisense for that stuff
oh man when i finally got umbrella working, it was magical
i do use Intellij, is there a guide to set that up?
i'm not sure but i can quickly show you since i use it too
file -> project structure
global libraries
plus sign at the top left to add a library, pick Lua Zip Library and then navigate to your game's lua folder (usually in Steam/steamapps/common/ProjectZomboid/media/lua/)
i think it adds it to your current project automatically but from now on all you have to do to add it to new projects is to go back to this screen, right click the library and add to modules
woot its working thanks!, is there a way to figure out what functions do what? or is that a guess based on name thing
pretty much :( if you use umbrella you can get intellisense for java stuff as well, and i think it makes the intellisense for lua a bit better
there's a project in progress that will allow modders to contribute documentation for both sides, but it's not ready yet
Ah is that the umbrella discussion going on in this channel?
yeah, it's typings for the java and some limited typings for the lua https://github.com/asledgehammer/Umbrella
the lua stuff is a little limited but the java intellisense is fantastic
there's instructions on how to clone the repo properly there, then you just need to add it as a library like you did with the lua folder
ok, ill do that, thanks!
hopefully i won't have to ask as much questions with all this setup now lmao. i know a good bit of java but its just a question of equating everything in my brain and my brain being stubborn
30 seconds into coding and my brain is already feeling confused about the no curly brackets and semi colons .-.
that could easily be a medic feature
it is a medic feature
paramedic only
the first aid centric occupations are getting some unique bonus to incentivize taking them for something that you cant replicate simply by levelling first aid
does anyone know how the TraitFactory method works to add a trait? i get the first field being the name of the trait, but examples i see have a getText(the name that appears in client i believe?), an integer, another getText(teh description in client i believe?), and a boolean. im not sure how the getText functions work as they don't seem to have a filepath?, then theres the integer and boolean that idk what they do
getText() grabs the translations string matching the ID
you can supply a raw string temporarily if you're just testing stuff out (as in get rid of getText())
ok that makes sense, what do the integer and boolean do? i would have thought the integer would be like "placement in the perk menu" but there seems to be a few of them in this mod im referencing for it that has the same number, and the boolean always seems to be false
oh wait
wait
is it the points it adds
if thats the case then that makes sense, but i still dont know about the boolean
some of the traits in the MainCreationMethods.lua seem to have both a false and a true even
👍 thanks!
since those last two bools have just been made clear to me, it reminds me of this wiki link that also didn't know what they were for. https://github.com/MrBounty/PZ-Mod---Doc/blob/main/How to make a custom trait.md
Also, I'm surprised the wiki points to an external github repo. I was going to edit it but obviously I can't.
oof - you can supply a PR technically if it's on github
Yeah that's just more work. :/
mood
I've reached out to pzwiki_editing to see how they want to handle it. There's also a section labled Occupations, Traits and Skills that's completely empty. I might just copy the github info into a new wiki page and link it in this section. I just hate having duplicate information with no real gain.
hey so i want a timed action to require a specific item, adding a new treatment to the first aid system got me wanting to blow my brains out because i can't figure out how to tell the game what item to look for.
the specifics of first aid are probably not relevant to figuring out how to make a time action require gunpowder to show up when prompted so how to i make a timed action look for a specific item
What exactly problem with TA?
Or what exactly you want to do?
i want to add cauterizing wounds with gunpowder
seal them shut and remove infection but add a bad burn
cant get a new option to appear in first aid menu tho
this moodleframework just hates me, I am setting up the thresholds like the framework tells me to, but it keeps making Bad4 use its default value of 0.1 instead of 8, which breaks the whole thing
ive been messing with it for three days, ive had multiple friends look at it, none of us can figure out whats wrong
Anybody know how to make fireworks into pz? I know nothing bout coding...
if you know nothing, its best you look at a tutorial for Lua, because afaik, the only things that don't require it, or java, is crafting recipes and adding new items
https://pzwiki.net/wiki/Modding here is a link to the wiki for it that might help if you haven't already perused it
I haven't worked with the moodle framework at all so I probably can't help. However I'm curious how you're reloading the lua files when you want to test again? Are you backing out of the loaded game entirely and reloading from the main screen? Or are you reloading in the debug screen? If you're only reloading in the debug screen be aware that reloading just loads an additional copy of the lua and doesn't overwrite the first. You might be getting the result you want and then your original code is overwriting it. I don't actually know if there's a order to which copy of the file executes first.
ive been restarting my game
Quick question, could your API be used to limit the amount of boredom sending text in chat while in Multiplayer gives you?
wot
okay my theory is completely out the window then. Sorry 😦
You can just spam a letter after another until all your boredom has dissappeared
Kinda broken
The idea is that there would be a limit to how much boredom can be reduced by sending text, not just reduce the amount of boredom points per message.
reloading lua gave me issues earlier so ive just been restarting my game for the past few changes
the code should just be like this. because values is (0.1, 0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9)
I set it up so on a scale from 0 to 10.0, the negitive moodles should appear, level 1 at 2.0, level 2 at 4.0, level 3 at 6.0 and level 4 at 8.0
but negitive level 4 decides to use the default value of 0.1, so it appears on loading a new game, and disappears when level 1 gets hit at 2.0
so for some reason my negitive level 1-3 is working. but negitive level 4 is not
are you able to get the negative level 4 value if you set the value directly to 0 with the :setValue instead of using testStat?
im not the most familiar with lua, but the way your describing it makes me think that maybe the or statement when you declare testStat is picking the wrong value?
idk
this is the TestStat made with the help from Albion
Okay I'm starting to see what's going on here. Still looking over it.
Does TestStat get initialized with a value or is it just zero?
^, maybe testStat is returning null/nil/whatever lua calls it
I did this and it still gave me bad4 at 0.1
i didn't know this was a source of boredom, so i looked into it... the boredom i've reimplemented is dead code and the api does not actually cover boredom right now 😅
the api is mostly a reimplementation of the java Stats update, and it looks like boredom was moved to BodyDamage at some point, so the small bit left that i reimplemented doesn't actually do anything
(and needs to be removed since you get double idle boredom in its current state)
the BodyDamage stats are slowly being assimilated (i have a panic reimplementation done for the next minor version), i can do boredom next if that's something you're interested in
I mean, it's something I think should be patched up
Just sending many messages in chat to get rid of boredom makes all items that are meant to be used for it kinda pointless
So I propose a limit to it, instead of just removing the feature
Maybe a cooldown as well
i honestly didn't know that was a thing, the api will be able to sort that out once boredom comes under its scope (for real this time)
does the game have a default moodles threshold? maybe its not using the thresholds you determined if thats the case? otherwise i think someone else should help ya cause idk what else it could be off the dome
i'm looking at boredom and it looks like it'll be more complex to reimplement than panic was, but probably not impossible
I checked the workshop page for the moodle framework and it specifies values range from 0 to 1. However @autumn temple said they "set it up so on a scale from 0 to 10.0". Duckling, you confirmed this works the way you expect it to for every value but bad4?
0.0 <= myNewMoodleValue <=1.0
I have tried to edit all the numbers to make my TestStat go from 0.0 to 1.0, and edited the thresholds accordingly. and it still gives the same issues as it does from 0 to 10.0
yes, the framework has default thresholds, which is the problem im having which is bad4 is using the default threshold but bad1, bad2, bad3 are not.
the default threshold for bad4 being 0.1
if you shift it from 1 to 11.0 instead, does it do the error at 1.1? maybe it could be that bad4's threshold is being overwritten somewhere else.
hm, let me try that
making it start at 1 then going to 11 just makes the issue happen at 1.1
hmm
on the modData.TestStat + 0.1, if you change the 0.1 to another value, will it still do it on the 0.1?
like a 0.05
hm ya it gave it to me before it even hit 0.1
ignore the error, i kept it there purposely so I know when the moodles change
which ya it applies right at 0.01
sorry for this question. I write C#. lua is gibberish to me. trying to concat a varaible and a string. googling this provides unclear examples.
player:Say(ZedCount .. "Zombies nearby")
--edit: or maybe
player:Say(ZedCount, "Zombies nearby")
--edit: or maybe
player:Say(string.formatted , ZedCount, "Zombies nearby")
I actually have a hopefully quick question myself. I'm currently leveraging InstanceItem to pull all existing values from items into a copied version of said item. For example I can get a bag's capacity, weight reduction, etc. with this code. But I can't get the runSpeedModifier from an item I KNOW has one.
local item = getScriptManager():getItem("Bag_FoodCanned")
local instance_item = item:InstanceItem(item:getFullName())
local instance_capacity = instance_item:getCapacity() --works, comes from InventoryContainer
local instance_weight_reduction = instance_item:getWeightReduction() --works, comes from InventoryContainer
local instance_metal_value = instance_item:getMetalValue() --works, comes from InventoryItem
local instance_RSM1 = instance_item:getRunSpeedModifier() --DOESN'T work, comes from InventoryItem.Clothing
local instance_RSM2 = instance_item.Clothing:getRunSpeedModifier() --DOESN'T work
Does anyone have any clue why my getRunSpeedModifier() lines are throwing errors?
at a glance that looks like it should work
I just tried it and it makes the game unhappy. I'm looking into it
might be a hacky solution, but can you do an if statement where if its the value it keeps being weird at, just... update the value again maybe?
ya there is a 2nd way to do it that is just a bunch of if, elseif statements but i dont know if that will let me disable the good moodles
which the mod I am testing for I only want negitive moodles
bags aren't Clothing
it actually doesn't have a runspeedmodifier - they don't work anyway so you wouldn't know, but that field is being ignored since its type (InventoryContainer) doesn't have any handling for it
if you've ever noticed that bags don't get dirty properly this is also why, bags aren't clothing even though they pretend to be
okmyownquestionrealquick, when i make a trait, do i need to specify a filename/filepath, or similar? or does the game look in a specific folder for a file that contains the name of the perk added?
i can't tell how some of these other trait mods do it
the trait name is usually a getText() call that references a translation string in lua/shared/Translate/EN/UI_EN.txt
oh sorry i ment like the UI image for it mb
like when you create a character/look at your characters traits how each of the traits have an icon
oh yes, it looks for media/ui/Traits/trait_TRAITNAME.png
18x18.png, according to https://github.com/MrBounty/PZ-Mod---Doc/blob/main/How to make a custom trait.md
yeah, oddly enough
strange its not divisible like 8
it's so strange i had to go check even though i'd already made one 😅
afaik images are commonly a power of 2, for compression reasons. but 18x18 doesnt really need to be compressed, right? 😛
module Base
{
item Bag_FoodCanned
{
DisplayCategory = Bag,
Type = Container,
DisplayName = Duffel Bag,
ClothingItem = Bag_FoodCanned,
CanBeEquipped = Back,
WeightReduction = 65,
Weight = 1,
Capacity = 18,
Icon = Duffelbag,
OpenSound = OpenBag,
CloseSound = CloseBag,
PutInSound = PutItemInBag,
RunSpeedModifier = 0.95, ------------------------------------------------<<<<<<
CanHaveHoles = false,
ReplaceInSecondHand = Bag_DuffelBag_LHandTINT holdingbagleft,
ReplaceInPrimaryHand = Bag_DuffelBag_RHandTINT holdingbagright,
WorldStaticModel = DuffelBag_Ground,
}
This is from the official game file ProjectZomboid/media/scripts/newBags.txt. I'm guessing this value is there for future proofing then, in case they do add a runspeedmodifier to more types of items? This is literally the first item in the file.
it might if I want my mod to fit in a QR code 🙃
yeah, if you track the variable from doparam to instanceitem you'll see it only gets applied to the instance if it's Clothing or AlarmClockClothing (watches)
oh... huh
i'm correct that it does not get added to the instance
private float calcRunSpeedModByBag(InventoryContainer inventoryContainer) {
float float1 = inventoryContainer.getScriptItem().runSpeedModifier - 1.0F;
good thing that got me to double check
it just grabs it from the script
Ahh I'm slowly learning how to read (what I believe) are the java docs. I could definitely benefit from some java experience. I wasn't sure how getCapacity() and getMetalValue() were both working despite me not specifying where they were coming from. I'm assuming the methods have been inherited from up the line. getCapacity() works because the item is of class InventoryContainer. getMetalValue() works because the InventoryContainer extends InventoryItem (which has a declared method named getMetalValue())
that's right!
My OOP is POOP
ye i also had aha moments when it came to how OOP works with java, it took me a year to be like "oh so THATS INHERITENCE"
back to this question. I'm only playing around in the command console (in game) which could be more limited than actual lua files. I tried concating an integer and a string (without even saying anything in game) and that blew up. However that should definitely be possible in lua.
the dog or car examples are apt, but idk maybe because its not the most applicable i had a hard time with it at first
Like, I get the concept of inheritance but only when it's pointed out to me. 😂
I just have very limited exposure to OOP so it's just something I need to spend more time doing
i had a similar experience
i think the latest example of me using it was in my 2d lightcasting project i had an abstract Light class, and a Pointlight class that extends from Light
and the light class had the boring getters and setters
to concat a string and a non-string, use tostring(variable):
player:Say(tostring(ZedCount) .. "Zombies nearby")```
idk how big this will show up in discord tho, but i think this salad bowl icon ain't toooo bad?
oh hell thats TOINY
tried that in command console and it also failed
why did mine fail... that's exactly what I was doing 😦
It will fail if its nil
and other things
you are correct, in most cases it will work if its an integer. doing tostring() will guarantee you get a string though.
did you have a player reference?
getPlayer():Say(tostring(ZedCount) .....) ```
OHHH I had declared zedCount as local.. I forget that when you do that in the command console it's just lost to the void after you hit enter
yeah, every line is its own environment
bigger salad bowl

well I'm sharing this anyway because I'm proud of how fast I was able to write it. I had it written (but forgot to reload lua when I was testing it) before the question was answered. 😦
thank you @ albion, Collide, dhert 😉
three kinds of people...
Liar
das a lot of zombies
shoot. maybe I need chunk, not cell?
"nearby"
well, nearby just a string.
local Zeds = getCell():getZombieList()
local ZedCount = Zeds:size()
cell should be correct
the IsoCell is the entire loaded area
IsoChunks are 10x10 square areas
Sorry I was just trying to make a joke about your search size.
lol
was going to add a gif of Dr. Evil doing airquotes but I took too long, posted the wrong one, and decided to die with my shame instead of fixing it.
LOL
getting a car stuck horizontally in a hallway fits with my 16x zombie pop
woot another icon i drew that i don't immediately go "oof" at
I like them! I hate the ones I draw.
danke
i think a part of the reason i like em more than usual is i don't use solid black as the outline color
if i need an outline i was using a slightly darker version of the color the thing is
i've come to peace with my programmer art
i don't do baaad art in general, im just kind of perfectionist in a way? and i don't have a drawing pad
like i drew these two with a mouse, but my pixel art is kinda rough
abused the hell out of the splatter brush on gimp
the tools are there for tooling /shrug
i'm a strong believer that any modded content should fit perfectly in vanilla, so i am perfectionist to a degree, but i have to accept that art just isn't my focus and it's not worth it
fair fair
also agree
I also agree. My next project will be adding a new wall tile and I'm most stressed about making it look like it fits with vanilla.
for my bigger projects i'll find someone to commission, otherwise it doesn't really matter if my trait icon is an off-looking recolour of a vanilla one
if i realllly need to i have an artist friend i could bug, but i dun wanna be that guy
This was the trait icon for my last mod called House Fire Survivor. It took me an hour and this was my 5th attempt
looks good!
^ ye
I think so too. It was the only one I didn't hate. The rest were bad. 🙃
it helps us that the trait icons are so small cause then it hides imperfections
thank god for our obnoxiously small ui
@bronze yoke my picture above, debug-zombie population shows 8854, but "nearby" is 3304, meaning 5550 are 'simulated'. is there any way to include simulated zeds in the size of getCell():getZombieList():size()?
(unless getCell is different than IsoCell, then in that case, would i type... IsoCell():getCell() ?
i've been trying to combine vanilla icons to make some actions for my context radial. so far the results have been good enough imo. zoomed in a bit for visibility
doesn't seem possible from my examination (and getCell just returns the IsoCell)
I like them all but the burning zombie is incredible
that UI is oddly implemented in java, and the place it gets that count from doesn't seem accessible
I'm 100% joking, but you could instead do "At least 3304 zombies nearby"
It's not wrong. It's just not right.
if you got the amount of nonsim zombies, and the total amount of zombies
couldn't you just
take the total - nonsim
and boom?
we don't know how to get the total amount
total requires me to be running in debug mode
ah
whats the context of this btw? if its for the player to know the amount, you could write a little more code to keep track of seen/heard zombies rather than just all the ones nearby?
How so?
i think Stats keeps track of this already
Maybe it's possible. I just don't know how 😮
If there's a java field but no exposed getter you can use https://github.com/Project-Zomboid-Community-Modding/pz-community-modding/issues/55
Not a plug-n-play snippet
can you tostring a field when it isn't exposed?
uhh...
in this case the field was exposed, just without a getter
Not sure about unexposed fields
This is something I employ in a mod
i wouldn't've expected tostring to play nice with an object that isn't exposed
you can also set fields in debug mode - for extra fun
where can I find the getter?
I'm just looking here https://projectzomboid.com/modding/zombie/iso/IsoCell.html#getZombieList()
which is one of the only results on Google when searching "Project Zomboid getZombieList"
I know that it has a public method size(), it isn't listed on that website.
not sure if getZombieList has other variables, or methods.
it's an arraylist, so its methods are going to be listed on java's site - you can get there just by clicking arraylist
getter refers to a method/function to get a field
getZombieList is a getter for zombie list
The context of the discussion seemed to imply there was a field that had information you wanted - but I think I misread
I see, so ArrayList size(), and all the other methods are listed on the docs oracle site, nice.
any idea why it don't like my line 13?
the file that its erroring is in my lua/client
the line its self is if its too small: "Events.OnGameBoot().Add(addTatersTraits);"
the local function on top of that function call is:
"local function addTatersTraits()
local Vegetarian = TraitFactory.addTrait("Vegetarian", "Vegetarian", -4, "Penalizes eating meat", false, false)
local Carnivore = TraitFactory.addTrait("Carnivore", "Carnivore", -6, "Penalizes not eating meat", false, false)
local Cannibal = TraitFactory.addTrait("Cannibal", "Cannibal", -6, "Allows to eat human flesh", false, false)
local SweetTooth = TraitFactory.addTrait("SweetTooth", "Sweet Tooth", 1, "Bonus to eating sugary items", false, false)
end"
Events.OnGameBoot.Add(addTatersTraits)
the () tries to call Events.OnGameBoot as a function, but it isn't one
whats a way of printing to the ingame console? i realize at some point im going to have to resort to my tried and true "random print statement to see when my code borks" methodology andi wanna be ready
i tried print("oi") and that didn't seeeeem to do anything
that's correct
thats correct in that print is the way to do it or thats correct in that it doesn't do anything?
print is the way to do it
ok
hmm,
local old_perform = ISEatFoodAction.perform
function ISEatFoodAction:perform(...)
local original_hunger = self.item:getHungerChange()
print("aoi")
if self.item:getFullType() == "Base.Chocolate" then
print("boi")
if player:HasTrait("SweetTooth") then
print("oi")
end
end
old_perform(self, ...)
end
when i ate a chocolate bar, none of the prints went off in the command consoles output log
also, is there a way to do categories of items, like sweets in general in one if statement, or do i gotta do it for all sweets
depends if the game keeps track of what items are sweets
also i might be dumb, the lua file i created with the function in it wasn't even in the modfolder 😓
@hasty horizon check this out
ye? i have that don't i
its for discord lua formatting
o
---i see
so i did the
function ISEatFoodAction:perform(...)
print("aoi")
if self.item:getFullType() == "Base.Chocolate" then
print("boi")
if player:HasTrait("SweetTooth") then
print("oi")
end
end
old_perform(self, ...)
end
and line 13 is that player:HasTrait, if im reading that stacktrace right its saying that the function call returns null? SweetTooth should be correct since i was able to use setMutualExclusive on it in another file. this was how i created it:
local SweetTooth = TraitFactory.addTrait("SweetTooth", "Sweet Tooth", 1, "Bonus to eating sugary items", false, false)
just to check,
if not player:HasTrait("SweetTooth") then
print("oi, you don't even have it")
return
end
confirmed that i do have the perk.
the console didn't bring up the print
im trying it with Sweet Tooth rather than SweetTooth to see if that changes anything
nah that didn't work either
but this is line 13 ???
if player:HasTrait("SweetTooth") then
Yes
if not player then
print("oi, you don't even have player")
return
end
I tried that. It still errored on the code before that, and did not print out either. Unless it stops reading the file once it errors
also, you asked 10 hours ago,
are there any mods some of the more experienced people in this channel recommend to look at the code to learn from?
edit: not that i'm 'experienced', but check out dynamic traits by peppercat, i used it as a coding reference for my first mod, very useful to browse around the lua scripts
https://steamcommunity.com/sharedfiles/filedetails/?id=2459400130
yeah it will stop, can you move the debugs up, before the error
You don't have any player object in scope here. Try to do:
if self.character:HasTrait("SweetTooth") then
I'll try both when I'm available tomorrow, I gotta keep a sleep schedule rip.
I'll also take a look at the mod
Maybe i'm getting closer?
--this works, but it only returns ~half of the zeds in the cell, as can be seen in the Zombie Population debug tool
getPlayer():Say(getCell():getZombieList():size() .. " zeds nearby")
--possibly something here? returns 0
getPlayer():Say(getWorld():getSpawnedZombieZone():size() .. " zeds nearby")
--possibly something here? causes error
getPlayer():Say(getWorld():MetaCell():zombieCount() .. " zeds nearby")
--possibly something here? causes error
getPlayer():Say(zombie.popman.ZombiePopulationManager():radarCount() .. " zeds nearby")
--possibly something here? causes error
getPlayer():Say(getPlayer():getGameCharacterAIBrain():getCloseZombieCount() .. " zeds nearby")
hey guys, how do i open console in the left down corner again? bc i accidentally closed it
I would actually love to know this too. Last time I closed it I had to completely restart my game. I spent 20 minutes digging through options trying to find it... 😦
Wow. I found it on accident... @neon hedge press the tilde key. On most standard (english) keyboards it's above the tab key.
huh. yeah there it is. good to know! Thank you!
Hello, is there a reason for 'keyBinding' to be in shared ? My half brain would have put it in client side only. Am I missing something ?
Doesn't make a whole lot of sense to me either. The only thing I can think of is that shared is the first folder to execute #mod_development message. Still, there's no reason that I can think of to register key presses before client is loaded as well.
TchernoLib now includes an interface to set keybinds, compatible solo & multi & with other keybinds interfaces like ModOptions. simple & fast. https://steamcommunity.com/workshop/filedetails/discussion/2986578314/3812909188452909116/
I'm having some trouble getting my one mod to successfully fetch a file from another mod despite requiring it. This fails to print DoD_TestHelpers.foo. I have the following code/files:
--Contents\mods\DuffelsOfDirtItemBuilder\media\lua\client\DoD_BagExtractor.lua
local DoD_TestHelpers = require("DuffelsOfDirt/DoD_TestHelpers")
print(DoD_TestHelpers.foo)
--EOF ------------------------------------------------------------
--Contents\mods\DuffelsOfDirt\media\lua\client\DoD_TestHelpers.lua
local DoD_TestHelpers = {}
DoD_TestHelpers.foo = "barbarbarbarbar"
return DoD_TestHelpers
--EOF ------------------------------------------------------------
This previously worked when the two files were in the same directory but now that I've moved DoD_BagExtractor.lua out, it throws a fit. DuffelsOfDirt is a requirement for DuffelsOfDirtItemBuilder. The mod folder is named DuffelsOfDirt. The modinfo file lists the mod ID as DuffelsOfDirt. I'm not really sure what else the string could possibly need to be. Does anyone have any thoughts or advice?
Update: Capitalization error. Update Update: It was not, in fact, a capitalization error 😢
require("DoD_TestHelpers")
That also fails
sorry then for the noise
I'm trying it again. It hasn't failed yet.
I... what? It works now. I must have typed something in wrong. I just spent an hour and a half using the right solution and somehow getting the wrong answer. Thank you @mellow frigate!
happens to me a lot
Why does it not require DuffelsOfDirt though? I'm also requiring a few other files like so
local TestFramework = require("TestFramework/TestFramework")
local TestUtils = require("TestFramework/TestUtils")
And these require TestFramework to be explicitly declared.
Oh. I answered my own question. These are in a folder.... client/TestFramework/TestFramework.lua.
🤦
don't blame yourself. https://en.wikipedia.org/wiki/Rubber_duck_debugging
In software engineering, rubber duck debugging (or rubberducking) is a method of debugging code by articulating a problem in spoken or written natural language. The name is a reference to a story in the book The Pragmatic Programmer in which a programmer would carry around a rubber duck and debug their code by forcing themselves to explain it, l...
Hello guys, I'm a developer newly into Lua and zomboid modding. I want to make a mod that allows players to place and create a heat source in the world in multiplayer.
Can I get a basic example of how to handle the mod data if it's not too complex? Basically I want to make sure the heat source is there for all the players even if they logged in after it was place.
It doesn't have to be actual working code, just need a rough idea of the good practice.
Thanks! 
You are starting modding in hard mode: you should use Global Object. Those are complex objects. But it is still (a lot) better than redoing it yourself.
I also suggest you use this interface from TchernoLib mod. But I am partial as I'm the author (and only user afayk) https://steamcommunity.com/workshop/filedetails/discussion/2986578314/3812906855246163752/
Just had a quick look, and that's a really good library you made! Seems like it's gonna tackle the issues I ran into last time I tried messing with zomboid modding. Much appreciated, mate!
i
know but i want an modder friend
Hi! What is InventoryItem:getRegistry_id() ? What is registry in general?
Hello, if I make a weapon and put "NeedToBeLearn:true" Can I put this recipe into a magazine that is already in the game, if so how?
@hasty horizon ok so from looking more into my problem yestarday. it appears that all the bad thresholds are being overwritten not just bad4. but the good thresholds are not being overwritten at all.
I'm sure plenty of you are PZ car specialist in there 😄 How do I get access to the window associated to a passenger seat ? I was hopping to get the equivalent of BaseVehicle.getPassengerDoor for the window but I do not find it. Also I need to distinguish a door with a window from a door without a window.
inv:AddItems("LabItems.LabSyringeReusable", 1);
ZombRand can be added into this code?
like inv:AddItems("LabItems.LabSyringeReusable", ZombRand(0, 1));
local windowPart = VehicleUtils.getChildWindow(door) -- got it
guys? ^^'
yes
ok so moodleframework is giving me anyother problem, to where the moodle is updating every tick, and violently shaking. instead of updating/shaking when the moodle gets changed. how would I go about preventing or slowing down when the moodle updates?
I'm about halfway through the ISWorldObjectContextMenu (though it doesn't look it in practice) and assigning icons to actions in the radial: all the water/fuel interactions, toggling items on, etc., are working. There are some things I'm just not going to be able to assign an icon without further overriding the base game though...
This looks nice
On M/KB I'm indifferent, but this would be huge if I'm playing on a Steam Deck or controller
it shakes when you update the moodle with a different value. Do not update the value to avoid the shaking.
Ok thanks
can i reload lua from inside debug game, or do i need to quit to main menu and press blue button on bottom right?
you can reload files from the f11 menu, but keep in mind that it doesn't 'undo' the original execution of the file (so if you changed something outside of the file's environment like overwriting a function, it won't undo that)
generally i just reload the save to avoid issues
lua reloads if you load a save with different mods, so i just disable my mods on the main menu and reload the save
works perfectly, thanks!
i've been alt+f4ing each time i delete a colon or something, this will help 😛
i forget, do you make your character before or after click to start?
before
great so OnGameStart is when you click to start right?
roughly
but definately after character creation?
yeah
thanks
How does a character get dirty?
I wish I could like. Roll them through mud or sth
running through trees isn't really getting me anywhere lol
it seems mostly random
there's random chance of gaining dirt while moving, running, sprinting, while hot, while standing in a puddle, and while in trees
you can see the logic in IsoGameCharacter.updateDirt, which is called during its per-tick update
sigh
i've added dirt via the visual parts cheat on the health menu
find it kind of odd the avatar's back is squeaky clean but whatever lol
self.character worked 👍
local sweets = {
["Base.PopBottle"] = TRUE,
["Base.Pop" ] = TRUE,
["Base.Pop2" ] = TRUE,
["Base.Pop3" ] = TRUE,
["Base.JuiceBox" ] = TRUE,
["Base.Cereal"] = TRUE,
["Base.Biscuit" ] = TRUE,
["Base.CakeBlackForest"] = TRUE,
["Base.LicoriceBlack"] = TRUE,
["Base.CakeSlice"] = TRUE,
["Base.Candycane"] = TRUE,
["Base.CandyPackage"] = TRUE,
}
function ISEatFoodAction:perform(...)
if self.character:HasTrait("SweetTooth") then
local func = sweets[self.item:getFullType()]
if (func) then
---some code here
end
end
end
so the game doesn't keep track of what is and what isn't a sweet, i was going to do a switch statement but from my googling, Lua does not have those. am i correct in this being functionally the same? each food item is going to have the same thing done to them
oh hey! I'm doing something quite similar in my mod. I decided on tagging each item at the beginning of the game
you can probably remove CandyPackage.
same as Badonn, you should add a tag on the script items instead
how do i go about adding the tag and checking for it?
oop
inventoryItem:hasTag('Sweet')--read the tag on InventoryItem instance```
scriptItem:DoParam('Tag=Sweet')--write the tag on Item instance (e.g. OnGameStart)```
Hi Tchernobill! 
How ya doin?
AnthroTraitsUtilities.AddItemTagToItemsFromFile = function(path, tag)
...
AnthroTraitsMain.ATOnInitWorld = function()
...
local OriginalEatPerform = ISEatFoodAction.perform;
ISEatFoodAction.perform = function(self)
-- code to run before the original
OriginalEatPerform(self);
-- code to run after the original
ATM.DoVoreModifier(self.character, self.item, self.percentage)
end
...
AnthroTraitsMain.DoVoreModifier = function(character, foodEaten, foodPercentEaten)
...
AnthroTraitsMain.ApplyFoodTypeMod = function(modifier, character, foodEaten, percentEaten)
I'm getting some rest after improving the parkour mods. And I'm happy cause they get a lot of success 😄
Taking a look at my repo and the listed functions should help you out!
I listed them in order of implementation
and here's an example file. I listed it in the root of my mod folder
so for this it would be something like:
local function addTag()
Base.PopBottle:DoParam('Tag=Sweet')
end
Events.OnGameBoot.Add(addTag)
to apply the tag, then just an if statement with the :hasTag?
at the minimum, yeah. @mellow frigate would using DoParam('tag=sweet') append the tag or overwrite them?
append
pog. good to know
Base.PopBottle does not exist afayk. lua local scriptItem = getScriptManager():getItem('Base.PopBottle') if scriptItem then scriptItem:DoParam('Tag=Sweet') end
is it because the bottle can be refilled or something?
and remember that after each change on the script item, you should create a new instance of the item to test it.
I do not understand your question
you said Base.PopBottle does not exist?
I did. in lua there is no object called Base.PopBottle.
There is an item instance (of the java type Item) whose parameter "FullType" is "Base.PopBottle".
i c, so could i make a table, then do a for loop for the amount of items in that table, using the value at each position? idk how to write it in lua rn but in java something like:
String[] sweets = "chips", "chips2", "chips3";
scriptItem script; //assuming scriptItem can be used as the object for this example
for (int a = 0; a < sweets.length; a++) {
if (sweets[a] != null) {
script = getScriptmanager():getItem(sweets[a]); //however you would grab that equiv in java
script:DoParam('Tag=Sweet');
}
}
or could i just leave scriptItem as scriptItem = getScriptManager() then later do scriptItem:getItem?
yes for the idea
But you are writing (mixed) Java code, and in your mod you will probably use lua instead
ik i wrote it in a different language, i just know more java and i thought it would get my idea acrossed better
i was going to write the equivalence of it in lua
local trait = TraitFactory:getTrait(item) is giving me trouble, item is a string that has had leading and trailing spaces removed, but the debugger says i am passing two arguments to it
and it def doesn't like the code, throws an error when i boot it up
have you printed out the item string to make sure its actually sending what you think its sending?
i was, let me do that again
looking for Nutritionist seems like that should find the trait right?
but instead i get ```java.lang.RuntimeException:
at se.krka.kahlua.integration.expose.MethodArguments.assertValid(MethodArguments.java:123)
at se.krka.kahlua.integration.expose.LuaJavaInvoker.call(LuaJavaInvoker.java:186)
at se.krka.kahlua.vm.KahluaThread.callJava(KahluaThread.java:182)
at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:1007)
at se.krka.kahlua.vm.KahluaThread.call(KahluaThread.java:163)
at se.krka.kahlua.vm.KahluaThread.pcall(KahluaThread.java:1980)
at se.krka.kahlua.vm.KahluaThread.pcallvoid(KahluaThread.java:1812)
at se.krka.kahlua.integration.LuaCaller.pcallvoid(LuaCaller.java:66)
at se.krka.kahlua.integration.LuaCaller.protectedCallVoid(LuaCaller.java:139)
at zombie.Lua.Event.trigger(Event.java:64)
at zombie.Lua.LuaEventManager.triggerEvent(LuaEventManager.java:65)
at zombie.gameStates.IngameState.enter(IngameState.java:737)
at zombie.gameStates.GameStateMachine.update(GameStateMachine.java:145)
at zombie.GameWindow.logic(GameWindow.java:298)
at zombie.core.profiling.AbstractPerformanceProfileProbe.invokeAndMeasure(AbstractPerformanceProfileProbe.java:71)
at zombie.GameWindow.frameStep(GameWindow.java:765)
at zombie.GameWindow.run_ez(GameWindow.java:681)
at zombie.GameWindow.mainThread(GameWindow.java:495)
at java.base/java.lang.Thread.run(Unknown Source)
LOG : General , 1688600999284> 0> -----------------------------------------
STACK TRACE
Callframe at: getTrait
function: DoctrineOnGameStart -- file: DoctrineForcer.lua line # 10 | MOD: Doctrine```
thanks
now player:getTraits():add(trait) is tripping me up, and again on nutritionist
Only notable oddity is that add does not take a trait object. It wants the name.
ah so i should pass item not trait
thanks for the help so far, i feel like we are making good progress on this
so it seems to not like traits with spaces in the name, Trait not found! Thick Blood Trait not found! Axe Man
local sweets = {
["Base.PopBottle"] = TRUE,
["Base.Pop" ] = TRUE,
["Base.Pop2" ] = TRUE,
["Base.Pop3" ] = TRUE,
["Base.JuiceBox" ] = TRUE,
["Base.Cereal"] = TRUE,
["Base.Biscuit" ] = TRUE,
["Base.CakeBlackForest"] = TRUE,
["Base.CakeStrawberryShortcake"] = TRUE,
}
local function addTags()
local scriptItem = getScriptManger()
local func
for i=0, #sweets, 1 do
func = sweets[i]
if func then
scriptItem:getItem(sweets[i]):DoParam('Tag=sweet')
end
end
end
does this function work the way i want it to? (apply the tag sweet to the item), i ran it in the game and the function is my most iffy part of it, with the other part being:
require('NPCs/MainCreationMethods')
local old_perform = ISEatFoodAction.perform
function ISEatFoodAction:perform(...)
if self.character:HasTrait("SweetTooth") then
if inventoryItem:hasTag('sweet') then
print('oi')
end
end
old_perform(self, ...)
end
heck thats taller than i meant, uh ill shorten that table
in game, it didn't seem to do anything, it didn't error however.
The format of the sweets table is incorrect for how you are looping
tables are key/value maps, the keys in your table are the item names, but your loop uses indexes
also i seem to be wrong about it not erroring, i just didn't update my mod folder
Reformat sweets like this:
local sweets = {
"Base.PopBottle",
"Base.Pop",
"Base.Pop2" ,
"Base.Pop3" ,
"Base.JuiceBox" ,
"Base.Cereal",
"Base.Biscuit" ,
"Base.CakeBlackForest",
"Base.CakeStrawberryShortcake",
}
Also, start your loop at 1, not 0
Lua be like that
would i then have to change anything about the function addTags or the eat function besides the loop at 1?
I think it should be good with just those changes.
aye aye captain, ill report back once i do those changes
any idea why my code doesn't like traits with spaces in the name? ```function DoctrineModDataLoaded()
local list = SandboxVars.Doctrine.DisabledPerks
if list then
for item in string.gmatch(list, "[^;]+") do
item = item:match("^%s*(.-)%s*$") -- Trim leading and trailing spaces
print("looking for ", item)
local trait = TraitFactory.getTrait(item)
if trait then
print("Disabling ", item)
trait:setRemoveInMP(true)
else
print("Trait not found! ", item)
end
end
end
end
Events.OnInitGlobalModData.Add(DoctrineModDataLoaded)```
it finds nutritionist fine, but for example axe man makes it sad
i think in the code, axe man they format as one word?
yeah looking in the lua/NPCs/MainCreationMethods.lua they use Axeman as the trait
Axe man is the visual trait name for UI's
i wonder if it's going to be fussy about the case
Wrote a test write quick
every single trait contains no whitesapce
EXCEPT
Out of Shape
😭
going back to this, the inventoryItem:hasTag('sweet') errors, is inventoryItem something i would have had to define myself and i misunderstood something?
this is the lua script they use to make all the traits if thats quicker
just skim through
(the expand wont show all the lines rip)
@crystal oar
out of shape is out of the shape of the other traits
and Very Underweight
you can just test for out of shape/very underweight seperately, then do a generic case for the rest?
@mellow frigate can I DM you a question about Moodle Framework?
I suck at reading regex, but I think the code is already handling everything fine. Looks like ; is the delimeter and only leading/trailing whitespace is getting removed.
theres sites online that let you test regex on them if that helps
How does one get an instance of another class?
Specifically trying to get an instance of InventoryContainer.class in zombie.inventory.ItemContainer so I can use getItemsFromCategory(String str)
java or lua?
Lua
so i haven't used OOP in lua myself yet, but heres a wiki page that goes over Inheritance, which i think would be what your looking for https://www.lua.org/pil/16.2.html unless im misunderstanding
I think you want ItemContainer, not InventoryContainer
ItemContainer is a inventory itself.
InventoryContainer is an InventoryItem with an associated ItemContainer, like a backpack
That would be what I want lol, reading is hard
As for getting an instance of an inventory, what inventory are you looking to search?
i.e.
The player's inventory
A backpack
A nearby fridge
I'm more looking for a list/table/array of all clothing items, such as
local clothingArray = getItemsFromCategory("Clothing")
hey guys, where can i find vitamins model name? couldnt find it anywhere
Ah, that function is not for that. Its for searching an existing inventory by category.
Is there a function that would return all items categorized as "Clothing"?
If not how would I go about even sifting through the items to find those categorized as such?
There is a global getAllItems() which will return a list of every Item in the game.
I'd say search through that once on load and and save the results for later.
Doc page for Item
https://zomboid-javadoc.com/41.78/zombie/scripting/objects/Item.html
Javadoc Project Zomboid Modding API declaration: package: zombie.scripting.objects, class: Item
when code is in the... root of the lua file, they are ran when the game starts, or i guess, when you Reset Lua
(if that makes sense).
I want to use sandbox options, but that happens after the lua reset, so my code never gets to see my sandbox bools, etc.
I think I need to move my code out of the root, and into a function -- a function that's called when an Event happens, such as 'start game', or whatever that event is.
i'll look up all the info myself, but is this thought process correct?
item PillsVitamins
{
DisplayCategory = FirstAid,
FatigueChange = -2,
Weight = 0.2,
UseDelta = 0.1,
Type = Drainable,
UseWhileEquipped = FALSE,
DisplayName = Vitamins,
Icon = Vitamins,
Tooltip = Tooltip_Vitamins,
StaticModel = PillBottle,
WorldStaticModel = Vitamins_Ground,
Medical = TRUE,
}
and
model Vitamins_Ground
{
mesh = WorldItems/Vitamins,
scale = 0.4,
}
off topic, but when i do this line of code when i overwrite the ISEatFoodAction
print(self.item:getTags())
it seems to return that there is no tags the item has. is this the correct way of going about getting the tags? and is self.item:hasTag also correct? or do get and has have to be capitalized?
Yep, sounds right to me.
@hasty horizon
When do you call addTags()?
i add it in with Events.OnGameBoot
I'm not familiar with how items tagging works. So I can't offer much else...
and the lua file that the addTags is in is the first file in the Server folder, while the ISEatFoodAction overwrite is 3rd
@hasty horizon
The format for tags is actually:
Tags = BluePen;Pen;Pencil;RedPen;Write
From the Crayons item ^
is that for making an item with multiple tags, or adding tags to existing items? because im doing the later
local function addTags()
local scriptItem = getScriptManger()
local func
for i=0, #sweets, 1 do
func = sweets[i]
if func then
local item = scriptItem:getItem(sweets[i])
local existingTags = item:getTags()
local newTagString = "Tags = sweets"
for i = 0, existingTags:size() - 1 do
local tag = existingTags:get(i)
newTagString = newTagString .. ";" .. tag
end
item:DoParam(newTagString)
end
end
end
This might work?
Notloc already answered your question by suggesting getAllItems(), but I figured I'd share a snippet of my code since I've been doing literally this for the past few weeks anyway. This will build a list of all clothing items for you.
function getAllClothing()
local all_items = getScriptManager():getAllItems()
local clothing_list = {}
print("getting all clothing:")
print(all_items:size())
for i = all_items:size() - 1, 0, -1 do
local item = all_items:get(i)
local item_type = tostring(item:getType())
if item_type == "Clothing" then
table.insert(clothing_list, item)
end
end
for _,clothing in pairs(clothing_list) do
local clothing_name = tostring(clothing:getName())
print("clothing name is: " .. clothing_name)
end
return clothing_list
end
hmm, no it still prints out [] when i do print(self.item:getTags()) in the ISEatFoodAction
function Tests.updateTags()
local item = ScriptManager.instance:getItem("Base.Axe")
local existingTags = item:getTags()
local newTagString = "Tags = sweets"
for i = 0, existingTags:size() - 1 do
local tag = existingTags:get(i)
newTagString = newTagString .. ";" .. tag
end
item:DoParam(newTagString)
TestUtils.assert(item:getTags():contains("sweets"))
local invItem = InventoryItemFactory.CreateItem("Base.Axe")
TestUtils.assert(invItem:hasTag("sweets"))
TestUtils.assert(invItem:hasTag("CutPlant"))
TestUtils.assert(invItem:hasTag("ChopTree"))
print(invItem:getTags():toString())
end
This test is passing in my test framework
so when im looping through the items in my list to add the sweet tag to, i would pass that string into this function to use for the item variables getItem?
or is your function just a proof of concept
The most recent code I posted is just to prove that the method works and retains the items original tags.
these are my two lua files ive been working with
@hasty horizon
sweet vs sweets
Your code is failing when I test it, one sec
Ah!
getScriptManger -> getScriptManager
yeah when i hopped in and ate 1/4th a chocolate bar it printed out [] twice that time
man, my typos are killing me
I highly recommend an IDE with Lua Language Server setup.
i thought i did have it set up, i followed what Albion had here like, yesterday or the day before?
im using Intellij with the games lua library attached
and umbrella
Hmm, I use VS Code with Umbrella, the getScriptManager typo was underlined yellow for me
You're hot reloading?
i exitted out fully, then replaced the mod
Zero chance print('oi') prints []
ik, but it seems to be. ill see if putting a print statement in another spot prints it out or if my game is cursed
my mod might be made on an ancient indian burial ground for all i know
well i have this now:
function ISEatFoodAction:perform(...)
print("boop")
if self.character:HasTrait("SweetTooth") then
print("doop")
if self.item:hasTag("sweets") then
print("oi")
end
end
old_perform(self, ...)
end
and it printed out [], then boop, then doop
so idk whats happening
what item you eating?
chocolate
right below crisps4 in my list
i realized the Eat.lua i had was named Tatos instead of Taters, so i switched it to taters, and now the [] is gone, but it doesn't recognize that the lollipop has a sweets tag .-. (changing the name changed the order of files in the folder)
Huge help from both you and @wet sandal !
Turns out InventoryItem objects name is formatted differently than an Item objects 🙂
One has it in snake_case with the type or module it comes from as a prefix, and the other just has the in game display name as it's name, which is painful.
Now I just need to iterate through the clothingList and figure out a way to determine how 'comfy' each piece of clothing is, but that is a problem for another day
My best guess for that though is going to more or less just be "what material is it made from? (cloth/denim/leather/none)" and/or "where is it equipped (head/torso/feet/etc)"
I know invItem:getFullType() will give you Module.Name format.
If thats still something you need to work around.
Yea, heuristically assigning comfiness is a good start.
It will be hard to match hand crafted quality, but you support mod items this way.
I fixed that part, an InventoryItem objects getName() returns the display name, but an Item object returns it in Module.Base form by the look of it
It definitely will be, adjusting the comfiness for one item will adjust it for the whole category instead of per-item if I were to hard code it
For what Im doing at least, I think generically:
- light clothes (tank tops/tshirts/shorts/underwear) being comfy
- heavier clothing (anything leather) being pretty uncomfy
- bags & footwear being very uncomfortable
will probably suit my needs, at least for now
sure
so i tried:
local item = ScriptManager.instance:getItem("Base.Chocolate")
local existingTags = item:getTags()
local newTagString = "Tags = sweets"
for i = 0, existingTags:size() - 1 do
local tag = existingTags:get(i)
newTagString = newTagString .. ";" .. tag
end
item:DoParam(newTagSTring)
end
just ditching the list currently to try to get at least ONE item to work. unless im misunderstanding something, i got spirits in my code.
local item = ScriptManager.instance:getItem("Base.Chocolate")
item:getTags():add("MyTag")
no need to use doparam or complicate things like this
Hi
I'm still a bit puzzled about this
The Pick Axe has a chance to kill zombies in a single hit, making it useful for close-quarters combat.
There doesn't seem to be anything special surrounding the Pick Axe's critical attack, is the "killing zombies in a single hit" just a result of it having a very high (or just high enough) Critical Multiplier or there is something else going on?
so i put that in
function addTags()
local item = ScriptManager.instance:getItem("Base.Chocolate")
item:getTags():add("sweets")
end
Events.OnGameBoot.Add(addTags);
and heres my hook
function ISEatFoodAction:perform(...)
print("boop")
if self.character:HasTrait("SweetTooth") then
print("doop")
if self.item:hasTag("sweets") then
print("oi")
end
end
old_perform(self, ...)
end
when i get in game and eat some chocolate, it doesn't seem to get to the "oi" print statement. is self.item:hasTag not the correct way to do this?
{
MaxRange = 1.6,
WeaponSprite = PickAxe,
MinAngle = 0.65,
Type = Weapon,
MinimumSwingTime = 3.0,
KnockBackOnNoDeath = TRUE,
SwingAmountBeforeImpact = 0.002,
Categories = Axe,
ConditionLowerChanceOneIn = 20,
Weight = 3,
SplatNumber = 3,
PushBackMod = 0.3,
SubCategory = Swinging,
ConditionMax = 13,
MaxHitCount = 2,
DoorDamage = 35,
IdleAnim = Idle_Weapon2,
SwingAnim = Bat,
DisplayName = PickAxe,
MinRange = 0.61,
SwingTime = 3.0,
HitAngleMod = -30,
SplatSize = 5,
KnockdownMod = 2,
SplatBloodOnNoDeath = TRUE,
Icon = PickAxe,
RunAnim = Run_Weapon2,
TwoHandWeapon = TRUE,
BreakSound = BreakWoodItem,
TreeDamage = 35,
MetalValue = 120,
CriticalChance = 25,
CritDmgMultiplier = 9,
MinDamage = 1,
MaxDamage = 2.2,
BaseSpeed = 0.8,
DamageCategory = Slash,
DamageMakeHole = TRUE,
AttachmentType = BigBlade,
Tags = DigPlow,
}```
that should be correct, can you add a print to addTags to verify that it's running?
hmm i looked in the console for my print of "beep boop bop", i can't find it. i didn't forget to replace the mod after i made the changes, and i did a fresh reboot of zomboid
i have done it :)
To speed things up, you can work on the installed version of the mod.
Entering the main menu is sufficient to fully reload lua.
wait, big chance i might be dumb
im testing in a single player world
my script is in server-
ok
it even runs on the clients in multiplayer
if your script messes with timed actions, it should be moved to client though - timed actions are client and that one actually is client/singleplayer only, so it'll cause errors on the server
ok good to know
only if the activated mods in your save file do not match the mods on your main menu
would there be a particular reason why this addTags wouldn't be printing?
oh!!! it's in server right?
ye
the server folder is dumb, move it to shared
i forgot about this, the server folder doesn't load until you enter a game
which is after ongameboot fires
My mods match and it reloads fully for me.
debugMode feature?
maybe only in debug yeah
i was thinking it did that but when i tested it it didn't, but that was a while ago and i don't remember if i was specifically testing if it did that in debug or if it did that normally
I do specifically mean, entering, not leaving, the main menu.
strange, my traits.lua file adds the traits when i make the character, unless thats what it means by "ongameboot"?
and the traits.lua is in server
oh, maybe? that's not what i was looking for
ongameboot is upon first reaching the main menu
it also fires after lua resets
woo it fired the Oi finally
moving it to shared did work
but it strangely didn't print out to console either way, the addTag
do you mean the in-game console or console.txt? the in-game console doesn't appear by the time that code runs
how do i get to the console.txt?
it's in your Zomboid folder
of course ^_^
now to do the batch adding the tags i had before now
anyone have a simple guide on how to use the DoParam function?
-- get the item object
local item = ScriptManager.instance:getItem("Module.ItemName")
-- set an item parameter exactly like you would in an item script
item:DoParam("Parameter = Value")
Can you change multiple parameters in the single function?
local function addTags()
local item
for i=1, #sweets, 1 do
item = ScriptManager.instance:getItem(sweets[i])
item:getTags():add("sweets")
end
end
the item:getTags():add() seems to be throwing me errors here. i looked at the console.txt after adding a print(sweets[i]) and it gets to crisps in my list before it goes and says "attempted index: getTags of non-table: null"
LOG : General , 1688616075451> Base.PopBottle
LOG : General , 1688616075451> Base.Pop
LOG : General , 1688616075451> Base.Pop2
LOG : General , 1688616075452> Base.Pop3
LOG : General , 1688616075452> Base.JuiceBox
LOG : General , 1688616075452> Base.Cereal
LOG : General , 1688616075452> Base.Biscuit
LOG : General , 1688616075452> Base.CakeBlackForest
LOG : General , 1688616075452> Base.LicoriceBlack
LOG : General , 1688616075452> Base.CakeSlice
LOG : General , 1688616075452> Base.Candycane
LOG : General , 1688616075452> Base.CakeCarrot
LOG : General , 1688616075452> Base.CakeCheesecake
LOG : General , 1688616075452> -------------------------------------------------------------
attempted index: getTags of non-table: null
did i mess up some syntax or not understand how lua loops?
it didn't find an item for one of them
sorry, Albion and you are rightlua local function addTags() local item for i=1, #sweets, 1 do item = ScriptManager.instance:getItem(sweets[i-1])--java container not lua: starts at 0 item:getTags():add("sweets") end end
? isn't sweets a table
Yea it is
local sweets = {
"Base.PopBottle",
"Base.Pop",
"Base.Pop2",
"Base.Pop3",
"Base.JuiceBox",
"Base.Cereal",
"Base.Biscuit",
"Base.CakeBlackForest",
"Base.LicoriceBlack",
"Base.CakeSlice",
"Base.Candycane",
"Base.CakeCarrot",
"Base.CakeCheesecake",
"Base.Crisps",
"Base.Crisps2",
"Base.Crisps3",
"Base.Crisps4",
"Base.Chocolate",
"Base.Painauchocolat",
"Base.CakeChocolate",
"Base.ChocolateChips",
"Base.CookiesChocolate",
"Base.DoughnutChocolate",
"Base.CinnamonRoll",
"Base.CookieChocolateChip",
"Base.Cupcake",
"Base.DoughnutPlain",
"Base.DoughnutFrosted",
"Base.MuffinFruit",
"Base.Icecream",
"Base.ConeIcecream",
"Base.Icing",
"Base.DoughnutJelly",
"Base.Lollipop",
"Base.Marshmallows",
"Base.MintCandy",
"Base.Modjeska",
"Base.CookiesOatmeal",
"Base.Peppermint",
"Base.CookieJelly",
"Base.LicoriceRed",
"Base.CakeRedVelvet",
"Base.CookiesShortbread",
"Base.Smore",
"Base.CakeStrawberryShortcake",
}
i recommend having a nil check in there just because items might get removed by TIS and you don't want that to break your mod, but in this case there's probably just a typo in one of your item names
nil check would be smart, but i had copy pasted the ID's from the wiki is the strange thing
if it's case sensitive, CakeCheesecake should be CakeCheeseCake
local function addTags()
local item
for i=1, #sweets, 1 do
item = ScriptManager.instance:getItem(sweets[i])
if item then
item:getTags():add("sweets")
else
print ('Unknown Item '..sweets[i])
end
end
end
i've never run into a case difference so i don't know if it is
This is the incorrectt name
Base.CakeCheesecake
Its the only one
oh
Albion fastest gun in the west
🤠
it did turn out to be case sensitive
for the cake
i guess thats an edit for the wiki tho, they had that as the item id
now to tag up anything i think'll be relevant for features i plan to add
the features i plan to add you might ask?
idk. i didn't think i'd get this far.
what is the way to get the happiness/unhappiness an item gives? i tried doing self.item:getUnhappinessChange() but the console gave me an error
also related: how can i see the functions available to use on items like this, so i know what i can/can't get?
okay, so, this is relating to an issue I'm having in a paid commission:
ZombRand(0,1) always seems to return 0. Is this because ZombRand is exclusive? I just want it to create a decimal
the upper limit is exclusive, use zombrandfloat
huh! the more you know.
i think umbrella doesn't know the fields of a lua class so it doesn't recognise self.item, i think if you added a line like```lua
---@type Food
self.item = self.item
since lua isn't a typed language and tis don't use any annotations we don't really have an easy way of detecting these for the typing generator
i put that in, and it still doesn't seem to want to kick in it seems
also when i was first learning java, i was annoyed by having to declare a type, but now with lua its the opposite for reasons like that it seems lmao
when you've used a language that doesn't have it you understand why you have it
are there any other ways to get the intellisense to kick in? when i put in the : the list that shows up is random stuff in the file like the https from the emmylua generated header, the else keyword, ect
with a pencil icon leading each entry
it seemed to work for me
maybe my umbrella isn't properly installed or something?
Food is red and italic, that means it can't find the type
hmm
you should get this
so i have the games lua file, and umbrella as libraries, and i use the emmylua plugin, am i missing anything?
the folders don't have >s, are they empty?
oh, did you download a zip from github? i'm not actually sure if that handles submodules correctly
ye i downloaded it from github, its what showed up on google for me, did you download it a different way?
also wait what, the download i got from github, the candle, events and lua folders are empty 💀
i guess thats what you meant but not handling submodules
so the way umbrella works is that it's just a collection of other projects that have their own github repos, and submodules let us do that and easily update them and stuff
i wrote events, jab wrote candle, and omar wrote lua
could you three just make a joint github account then and just every time you commit to your own project, also commit to the umbrella?
this is the way we use it
i don't know too much about github, my own account i just use as a way to truck code between my desktop and laptop, when i click on code and go under Clone, do i just copy/paste the https link into the terminal or something in intellij?
i have git bash installed, and i am on windows
perfect
Open git bash where you want to put the Umbrella folder
run this command to get the files
git clone https://github.com/asledgehammer/Umbrella.git
ok i got it opened there, ill do that
I assume you don't have ssh setup?
If you do, use this instead:
git clone git@github.com:asledgehammer/Umbrella.git
well the first one was sent before i saw the second, but the search bar says i do have ssh
so now i do the step 6?
there we go! danke
maybe we should investigate ways to make this a bit less manual
maybe a script of some kind to automate it?
i wonder if we could get a github action to make a release after every push
A release would be easier for people.
i should probably make an effort to understand git/github more, i only really use push/pull myself
and commit
git goes insanely deep, but honestly, I only use a handul of commands on an average day:
git status
git add *
git commit -m "message"
git reset
git checkout branch-name
git checkout -b new-branch-name
this is hella embarassing but if there's any chance it's helpful at all I recorded this introduction to git for my friends a few years ago. https://www.youtube.com/watch?v=ERNVd-pBEMs It sounds like you already have the basics covered but maybe this could help a lurker or two or might cover something you didn't already know.
well the deepest i've gone is the widgets that intellij adds when you share the project on github lmao
ill take a look at it at some point, thanks!
intellij's git integration has covered everything i've needed to do
Just be warned this was more of an inside joke than anything else. I don't usually sound like an asshat.
its like my cs teacher said, fully featured IDEs can be a bit of a crutch lmao
Return to monke (notepad)
if it's not a crutch why use it
They can be. That was my philosophy when I was younger and wrote only in notepad++. But as I've gotten older I've learned that as long as you're paying attention to what you're doing the crutch just helps you learn how to walk.
sorta offtopic but kinda on topic of crutches, i try very hard to not use chatGPT, the only times i've used it is "i got a coding question that my google skills can't seem to find an answer to, and i don't want ot be crucified on stack overflow"
ive had some very rude answers on SO
if i do get code from gpt, i rewrite it and get myself to understand it first
i just google, and if google doesn't have the answer it's impossible
I haven't tried chatGPT for code yet. I need to get around to it just to see what it spits out. Also I'm exclusively a lurker on SO for that reason. A few weeks ago I stumbled across two opposing answers to a simple question and one of them ended up creating a seperate post complaining about it... I'm here to fix my bugs, not deal with politics.
like one project i had to dip into linear algebra and the wiki, the coding train video i got the idea from, and a commonly accepted java solution for it all had different formula
stack overflow is pretty famous for that
I recently saw a job posting that was asking for a stack overflow account link. I just noped out of that app.
LOL
I've never posted on stack, too scary
my account can't ask anymore questions on the main site because either my questions get ignored, removed, or don't get answers that solve the problem im having (this one is probably my bad when i explain, but still)
zomboid modding is my escape from this project though: https://github.com/Potat-OS1/lightsGPU. i was redoing my intro to java final, and feature crept to hell. i wanted a lighting system but my code was getting messy so i kept making different projects to try to keep my head on straight, to later on maybe add it as a library or something and this is the one attempt where the FPS isn't sub 10 on my desktop
it uses ray casting to get the hard shadow, then uses a few shaders to soften it
im procrastinating doing beam lights and cone lights
also the performance is still kinda bad? idk if im just not allocating resources correctly but on a 3060 and 12 core cpu it runs at 30~ fps at 900x900 res 💀
That reminds me of how I play PZ on the road... My laptop isn't good enough to play at a decent framerate fullscreen so I play windowed mode. 💀
r i p
In Louisville I make the window even smaller...
when i lived in a dormroom for a while i didn't bring my main monitor, and i thought my old pc was getting slow
my monitor i brought was 30hrtz, the main monitor i used before that was 60hrtz
when i would play MC i would get nausiated from quickly breaking/placing blocks because of how the refreshrate lined up with my fps
I get a little motion sickness playing Rocket League when my framerate dips to like 40... so I completely understand.
certain games its just a lil too rough playing sub 60
which is weird cause growing up id be like "oh heck ya 10 frames"
but now my pc can run this at 80-100~ frames
i remember when 30 was the target...
i need to get back to that mc world eventually, still haven't finished that base. that pic wasn't even recent it was back in december or something
I definitely remember playing some Baldur's Gate games that operated around 30 or below. Fond memories.
I was starting to write an AHK script that would automine a chunk at a time. I was getting into optical character recognition etc but I dropped it pretty quickly. Maybe I'll go back to that one day.
I quit because the OCR wasn't reliable enough to consistently tell me what block I was looking at
for MC?
nowadays you could do some wild stuff with redstone that idk if a script like that would be prudent
you can make tunnel bores and just chug along with that, or world eaters
yeah it was more of a challenge to see if I could do it in autohotkey
fair fair
wanted something for my portfolio
maybe it would have a better time recognizing it if you had a torch in your offhand?
and used something like optifine to create light when you hold a torch
I was reading from the debug screen so the text was always fully lit
ah
but the OCR couldn't 100% tell me that an 8 was an 8 and not a B
maybe if you saved a section of the screen as an image, then filled anything that wasnt the color of the letters to black, so it would have a clearer image?
like use a threshold or whatever the operation is called
maybe. But that's not tonight's problem. 🙃 tonights problem is filling all these duffel bags with dirt
man discord gotta up its emoji game, brown square was the best i could come up with
I actually have a PZ modding question to get this channel back on topic. I have the following code which breaks claiming __concat not defined for operands: item type is and Container
local item_type = item:getType()
print("item type is " .. item_type)
but it works when I do
print("item type is " .. tostring(item_type))
Why do I have to explicitly convert a string to a string for concat to succeed?
I've been just... avoiding this... for weeks but I'm curious why it behaves this way.
is item an InventoryItem or an Item?
I believe it's just an Item.
yep that one
that's not a string
I'm now seeing that but I can't determine what it IS.
it's an Item.Type
like an Enum?
you can use getTypeString if you need the string
Item.Type is just an enum of the possible types
I know I'm in over my head when I have to google "what is an enum"
but ye ive used enums in the past to basically have more complicated primitive types, which i thiiiink is how you can use them? you can have methods inside em
cause enum comparison is less costly than string comparison
(at least what i was told)
Once again I did a silly because I had assumed Item:getType would be the same type as InventoryItem:getType
But if IS were to refactor that they would probably break 95% of mods now. Or maybe that makes perfect sense to someone more experienced than me.
so your saying that despite not playing league of legends, i cannot escape the spaghetti
fun fact: printing several thousand lines of data to the console is likely to crash the game 👌
prints are basically the slowest thing you can possibly do
thankfully I'm only using them to debug and expose the data I'm working with. I am, unfortunately, crippled by being a very visual learner. I pulled all the prints out and the code executed pretty quickly.
yeah, as long as prints don't end up released it's fine
this code specifically is to build the item list and will never be deployed as a mod. It turned out to produce 4000 lines so I'm glad I wrote tools to do it rather than doing it by hand.
merging them all into one single print is surprisingly much much faster than printing multiple times
Ohh sorry no my data isn't being printed. I was just printing along the way to debug. I'm using the filewriter to literally build the item file.
anyway my item builders have finally reached a point where I can start testing that everything works. Thanks, everyone, for always having an answer and being willing to share it! Good night all!
you ever wish you could just smack someone through the first aid menu? im adding that ability :)
@mellow frigate thanks again, I figured out my problem, I accidentally had an extra line that would set the value, so both lines kept trying to overwrite eachother, causing a endless loop of updates
Hey guys, anyone got any experience using the LineDrawer class? I'm trying to add some visual representations for a rectangle but having some difficulty calling addrect or drawrect?
here's kinda the function I'm trying to create, any help would be appreciated, also, I'm new here so henlo 😄 👋
function drawZoneBorder()
local x1, y1 = 10899, 10143 -- Top-left corner
local x2, y2 = 10943, 10112 -- Bottom-right corner
LineDrawer.addRect(x1, y1, x2, y2, 255, 0, 0, 255) -- Red rectangle
end
this is extremely cool btw!
you need to convert from iso (world) to screen (display) ```lua
local x1Iso = 10899 --West
local y1Iso = 10143 --South
local x2Iso = 10943 --East
local y2Iso = 10112 --North
local player = getPlayer() --maybe use another player source if you have it at hand
local playerNum = player:getPlayerNum() --there are cases player will be nil and this will crash
local isoZ = getPlayer():getZ()
local x1 = isoToScreenX(playerNum, x1Iso, y1Iso, isoZ);
local y1 = isoToScreenY(playerNum, x1Iso, y1Iso, isoZ);
local x2 = isoToScreenX(playerNum, x2Iso, y2Iso, isoZ);
local y2 = isoToScreenY(playerNum, x2Iso, y2Iso, isoZ);
thanks Tchernobill! this workaround smort ❤️
Hey everyone. Im a game asset artist and not much of a coder. Recent obsession has been zomboid and I wanted to contribute what i can to this game has taken over my spare time.
My specialty is unconventional out there rigging and animation but im decent at character creation
I wanted to make up some abomination style special infected with some unique animations. Kind of thinking left 4 dead special infected in regards to unique animations and different models and skeletons.
Trying to keep my post short. Is this possible? I have seen some asset swapping of zombies but animations look the same. Would I need to use a base zomboid character skeleton?
Second any one like the idea and willing to help insert these into the game? As mentioned. Not a coder. I can supply all the models and animations. Just need some one who knows what they are doing.
can somebody give me a hand on spawning outfits on zombies?
both vanilla and mod items
I am crazy in need off animations for AFightMechanism mod. It has been sleeping for.. too long.. because I am not able to add animations. Are you interested ? https://steamcommunity.com/sharedfiles/filedetails/?id=2811855174
Looking at making a comparability patch for AuthenticZ and some of the backpacks in Britas. Any recommended guides to help me get started?
albion just wanted ask you about this really quick
about said same (paid) mod i've been asking about here and there
player:getBodyDamage():setFoodSicknessLevel(DirtinessSickness.getNewFoodSicknessValue(player));
This gets overwritten every frame. Not sure why. I'd really rather not poison players with this mod lmao
that's the only way i've made people sick successfully before
yo man, I'm pretty big noob but I'd suggest using the getter first for the player sickness level
local sickness = player:getBodyDamage():getFoodSicknessLevel();
you can then reference that in the setter
player:getBodyDamage():setFoodSicknessLevel(sickness + 0.1)
If u wanna be spicy you can use a temporary on-tick function to iterate the sickness level up an even smaller value on each tick but that may not be relevant at all in your case @trim mist hope this is helpful
i'm not sure i understand what's going on, could you elaborate?
oop sorry
This is a cool idea, but i'm not sure if it's relevant
in a OnEveryHours event, I give players with certain conditions sickness, using the above code. I print the food sickness level regardless per hour
when i assign it, it takes and prints correctly. Next time it runs it says 0
In my mind that means it's being overwritten like other sickness functions do
if it's every hour, if it's not a *huge* amount of food sickness it's just going to fall back down
i set it to .9
food sickness is 0-100
it's always something dumb eh
how can I alternate between two or more pieces of cloth on an outfit?
<!--Metalworker-->
<m_MaleOutfits>
<m_Name>MG_Metalworker</m_Name>
<m_Guid>945a39c9-8c11-4eea-aece-7a4ef60dfc5d</m_Guid>
<m_Top>false</m_Top>
<m_Pants>false</m_Pants>
<m_AllowPantsHue>false</m_AllowPantsHue>
<m_AllowTopTint>false</m_AllowTopTint>
<m_AllowTShirtDecal>false</m_AllowTShirtDecal>
<m_AllowPantsHue>false</m_AllowPantsHue>
<m_items> <!-- Metalwelder Gloves Grey -->
<itemGUID>5e59171e-14b1-4a90-b050-2800da20f337</itemGUID>
</m_items>
<m_items> <!-- Metalwelder Gloves Orange-->
<itemGUID>8f058f89-cbae-418e-8a7a-02ee98edd2ff</itemGUID>
</m_items>
I tried using <probability>0.15</probability> but it didn't work
🥳 🥳
Let me check it out. Idea of combo attacks would be very cool
i'm trying to create a really simple mod that adds a screwdriver as a valid can opener but it does not seem to load and I can't figure out why.
This is my mod structure:
~/Zomboid/mods/CanOpenerMod λ find . . ./poster2.png ./poster.png ./icon.png ./mod.info ./media ./media/lua ./media/lua/server ./media/lua/server/ExtraCanOpeners.lua ./poster3.png
ExtraCanOpeners.lua code:
Events.OnGameBoot.Add(function() Recipe.GetItemTypes.CanOpener = function(self, scriptItems) scriptItems:addAll(getScriptManager():getItemsTag("CanOpener")) addExistingItemType(scriptItems, "Screwdriver") end end)
It doesn't even show in the lua debugger as a script, but it is selected in the mod menu.
Anyone have a clue or direction?
the console.log does say that it loads it
addExistingItemType is a local function, you can't call it from another file
oh, also, files in the server folder should not use OnGameBoot
on the client, the server folder only loads when you start loading into a game, which is after ongameboot
so code on that event will never run
good to know, got it working with some troubleshooting!
how many ticks are in an in game day
I've done it... now I must rest.
It's not pretty but it works
will modding senpai notice me now
nice, would be cool if you can import too
like, an item script?
I'm assuming once you close and open the generator all your previous data is lost?
it would be nice if you could open the generated file so that all your previously set values are shown inside the generator again
human readable numbers would be nice too
so that you can make adjustments, or add more or remove
i'm not sure exactly what formula gets the actual spawnchance from the number you put in, but lootzed must know it
I haven't yet cracked what's rare or more -- it seems in all containers the chance is much lower and usually a float -- where as on the procedural list the chance is an integer that ranges from 1 - 6 ish
Yeah -- I can work on adding a save function so you can save your file or open other files -- I think importing from a lua file would be a headache. For example, I'm not sure of a good way for it to read the current distributions table in a way that you can edit it since this adds table inserts.
you could write the data in any format you'd like
you can regex them back out, but i'd say just use a json
Alright gonna make some improvements ; thanks for your suggestions! really!
I'm gonna add the ability to save and load and the ability to import items from a script
awesome 🙂
is ZombRand inclusive?
edit: or maybe that depends on if it returns an int or a double? i'll look around on the wiki
sounds good
can i tell lua, that my local is an int or float? or does it 'become' one of those two things, when assigned to something?
it becomes one of those when it's passed to java
lua just considers all numbers of type 'number'
(internally of course they're still represented by java types but that's not really important)
Is there a better way to write this, or is this fine?
local waterMax = ZombRand(0,51)
waterDispenser:setAmount(ZombRand(0, waterMax));
local waterTainted = ZombRand(0,2)
if waterTainted == 0 then
waterDispenser:setTainted(true);
else
waterDispenser:setTainted(false);
end
(maybe 3 zombRand is not performant)
what's the purpose of rolling twice for the setAmount? is waterMax going to be used somewhere else too?
oops, yeah, no reason.
from what jab told me, ZombRand uses a needlessly high quality random number generator so it can be a little slow
stylistically i prefer ZombRand(51) when the lower limit is zero but i'm sure other people would prefer it the other way for consistency or clarity or something
If you really wanted to minimize ZombRand calls I suppose you could call it once as waterMax = ZombRand(101) and if >50, set tainted and amount = waterMax-51 … ?
ah, for sure.
yeah modulus could work, but that requires my neurons to fire for a second when i see that operator.
i was also checking to see if lua could use the ternary operator
waterTainted = 0 ? setTainted(true) : setTainted(false)
and it looks like you can, maybe like this: "condition and true or false"
but i'm new to lua, and not the greatest programmer, i'll just be verbose and write it all out plainly. with comments 😛
that's right!
readable code is always the best code
for sure. like you said, its gonna be turned into javascript anyways lol
exactly here u can just use waterDispenser:setTainted(ZombRand(0,2) == 0)
waterDispenser:setTainted(ZombRand(0,2) == 0)
okay, so if ZombRand returns 0, the expression 0==0 is true, water will be tainted. else not tainted.
makes sense. i wouldnt have thought to replace a bool with a conditional statement that returns bools.
as i said, not the best engineer over here. thanks tho

he meant what when u exporting .lua file then u can import this file back to ur program
or import any other distribution .lua file
people do distributions in all sorts of different ways
That probably wouldn't work if it's expecting a certain format
u can support most popular ways
if someone doing it by strange way - it's none of your business

I could probably support opening a lua file that you've generated but
Not reading other distribution tables
yea, at least u have to support reading .lua files that was generated by ur program
@abstract raptor that looks handy!
it would be ideal to read the same lua file, but this works too
I'm working on getting it to parse a lua file as we speak
3 hours ago you said "I've done it... now I must rest."
I take it you're done resting lol...
nothing is ever done 
@abstract raptor in case you are not familiar with regex, you could possibly check out https://regexr.com/ if you're going that direction
grouping in particular
better to use this one (exactly for lua): https://gitspartv.github.io/lua-patterns/
not all lua regular expressions can be represented by same way in other regular languages
isn't it written in python though
I'm following this tutorial to patch a mod,
https://github.com/FWolfe/Zomboid-Modding-Guide/blob/master/api/README.md
and I made my own function to replace the existing function.
I need to get a reference, though.
How can I get a reference to a function in another lua file? and functions are typically local, so I can't find it by name, hmmm...
if it's local you can't
huh?
the tool they want to use regex for?
idk
i would be shocked if it was lua
archive have no files with python*.dll so I think smth else but python
guh i knew adding items from lua was gonna be a headache lol
i thought i saw python source files in one of her videos, might be mixing something up
at least it's not breaking everything
yeah I can't get it to parse this lua file
I feel like if you didn't save your just sol lol, I added saving so that's a thing.
are clothing items that you can wear in more than one way, like hoodies (up/down), represented as multiple items or something? i'm trying to modify the item properties to make an 'enchanted' item but it doesn't seem to work properly on things like hoodies because it's not registering on both the hood up and hood down
like so
just released the new version
and when i wear it either way, it reverts back to just "hoodie" whereas the "gloves of dexterity" are working fine
I think this is a decent start
I also rearranged the window and made it scrollable
oh noooo ... import from script only adds the first item 
fixed it
it's kinda hilarious when you import a vanilla item script, the print just shows you every single item
just use regular expressions to capture text between table.insert( and ) and after split it and etc
u can save data into json file and recovery info from there when program will be open again
Bleh. I will probably add it later.
so weird error. it works, but it throws that error to the console. line 22 is the self.item:setUnhappyChange(original_happiness) line. eating multiple sweets shows it does revert to its previous value, and i tried a couple different sweets and they seemed to have their tag added
so basically: code doing what its supposed to, but threw error anyways
doesn't bring up the debug menu, but does have the red box int he corner
i have an idea. try this. i would be surprised if this doesn't fix it.
if self.character:HasTrait("SweetTooth") then
self.item:setUnhappyChange(original_happiness * 1.0)
end
i replaced 21-23 with that, (which you were correct line 22 is third from bottom) and this time it actually brought up the debug menu when it errored, though its not giving the full stack trace
well, the error was java.lang.illegalargumentexception, meaning 'original_happiness' was an inappropriate argument to be sending into the setUnhappyChange function.
(but the game didn't mind line 14 and 16... which is why I recommended the * 1.0)
i figured it was when i got the error, but its strange how it was working despite being angry
is setUnhappyChange a default PZ function, or something you made?
default
lua functions can't have illegal arguments
maybe just modify the unhappiness directly, instead of using the base setUnhappyChange function?
heres how PepperCat does it in the DynamicTraits mod
function DTdecreaseUnhappyness(player, unhappyness)
local currentUnhappyness = player:getBodyDamage():getUnhappynessLevel();
player:getBodyDamage():setUnhappynessLevel(currentUnhappyness - unhappyness);
if player:getBodyDamage():getUnhappynessLevel() < 0 then
player:getBodyDamage():setUnhappynessLevel(0);
end
end
these seem to use regular PZ methods
https://zomboid-javadoc.com/41.65/zombie/characters/BodyDamage/BodyDamage.html
so i decided to print out the type, and it returned Nil. so what im going to assume is: because i declared what original_happiness is inside an if statement, Lua doesn't remember the variable when the if statement ends?
so ill try declaring it outside of it
and see if i still get the error
is the bottom if supposed to be an else? or... if not has trait?
right
but yeah, it looks liek the var was out of scope
the bottom was supposed to be resetting the value back to normal after usage. var did seem to be out of scope cause its working now
u can put local original_happiness before if statement and remove local on 12 line
function ISEatFoodAction:perform(...)
local original_happiness
if self.character:HasTrait("SweetTooth") then
---@type Food
self.item = self.item
original_happiness = self.item:getUnhappyChange()
if self.item:hasTag("sweets") then
self.item:setUnhappyChange(original_happiness * 1.2)
else
self.item:setUnhappyChange(original_happiness * .8)
end
end
old_perform(self, ...)
if self.character:HasTrait("SweetTooth") then
self.item:setUnhappyChange(original_happiness)
end
end
its strange tho how it was reverting to its original value even though the variable was out of scope though
me and my pet hammer
taking your hammer on a walk to the local harbor freight
is there any functional difference between using self.character:whateverfunction and using getPlayer()? i was looking at the more simple traits mod and they tend to use local player = getPlayer(); then whenever they need something like if they have a trait, if their running, ect they use it on the player variable
if there isn't, i don't seem to know what type to use to get umbrella to give me the same functions as getPlayer()