#mod_development

1 messages · Page 161 of 1

spice saddle
#

but i'll go ahead with working with mods, not Workshop

#

i don't even see Contents/ folder in your structure stressed

lone nest
#

Oh, I'm running the mod locally not direct from the workshop

bronze yoke
#

in the mods folder you just create a folder and put your mod.info, media etc into there

lone nest
#

it is, imo, bad to mess with workshop files directly since an update can wipe all the changes.

bronze yoke
#

it's way less annoying than Workshop

spice saddle
bronze yoke
#

Workshop isn't where workshop mods are downloaded to, it's where you put them to upload

#

they're still local mods

lone nest
#

^ looks like albion explained it

spice saddle
#

i knew that's not where mods are downloaded to but i didn't realize that's where i uploaded them, rather where i could tinker with it and then upload to steam workshop once final

bronze yoke
#

it can be done that way but working from mods and then moving it to Workshop when you're ready to upload saves you from the annoying workshop structure until you have to

spice saddle
#

i'm still confused how the folder structure should be when i'm ready to upload but i suppose i'll cross that bridge when i'm done

bronze yoke
#

it's usually Workshop/myMod containing the preview.png, the workshop.txt and the Contents/mods/myMod which is the actual mod folder

lone nest
#

Hm, does anyone know how many ticks are in Events.EveryOneMinute?

I actually don't even remember how long 1 in-game minute is irl time...

bronze yoke
#

usually it's 2.5 seconds, but day length can be changed

#

so it's not a consistent amount of time

#

and rarely a consistent amount of ticks

lone nest
#

Yeah, i'm looking at this function that is running on Events.OnRenderTick

#

from what I can tell, its anywhere between 40-100+ ticks a second., which is a bit absurd.

bronze yoke
#

were you trying to convert it to something that runs less often? i think you mentioned it earlier

lone nest
#

yes

#

something that can be consistently and predictably timed

spice saddle
#

I can finally see it lol

#

Thank you @bronze yoke @lone nest @wanton pier

red tiger
#

Will be nice when I get my vscode extension's linter working for detecting things like invalid data types.

red tiger
lone nest
#

all i see is pain

red tiger
#

What if I put in an invalid type for that item? I should highlight it and notify that it's invalid.

#

It's going to be a fully capable / competent linter for the PZ script format.

#

It'll tell you if you're missing a comma or a curly brace.

#

Names where not needed, vice versa.

#

Case-sensitive property names vs not.

lone nest
#

a part of me wonders if .json files can be used instead for that thing

red tiger
#

Why not YAML?

#

Less to type.

#

I was planning to write a language to compile to ZedScript however YAML works.

#

That's been my current plan.

#

You can write tools ontop of what ZedScript provides, such as inheritance models.

#

I have 50 different shotgun items that all shares 75% of the same properties.. Why not create a BaseShotgun Item with abstract: true?

#

Why. Not. Make. It. Make. Sense.

lone nest
#

I'll admit I am not too familiar with yaml given my experience has mostly dealt with json objects with brackets and braces for everything.

lone nest
#

I guess if you have a chatgpt subscription, you can try some prompt engineering to help you build it.

red tiger
#

It's about as easy as it gets.

#

I mean.. sure?

sour island
#

Made the mod a while back, impressed the VO the guy made for it

trim mist
#

someone tell me why this won't work

frank elbow
#

When you're asking for help, it's good to provide more context; instead of "this won't work", context + an explanation of expected and actual behavior is helpful

red tiger
trim mist
# trim mist someone tell me why this won't work

Use case: attach tags to traits that you create by slapping a good old "||" at the end of the description, and hook into the trait lua to get just the description as normal. And then create a new function for said trait called getTags which returns a table of all tags listed at the end of the description.

trim mist
red tiger
#

I usually do when people talk to me demandingly.

trim mist
#

panic sorry! wasn't trying to be demanding salbhalsjbgalbga

#

It's not an actual error. Just a draft of some code that I haven't run yet

red tiger
#

Ok. Just think about how others hear or read it before pressing the Enter key. 👍

trim mist
#

I'm looking at it really jadedly

lone nest
#

I mean, from the top, it looks like you're trying to call the function before it was created...?

trim mist
#

which is why i said "tell me why this wont work" 😅

frank elbow
#

You've provided the context well, but you're missing the expected & actual behavior still. Is there an error? Does it silently fail? Stuff like that

#

I'm guessing it's an override of a class metatable function

lone nest
#

it might also help if you remember to end getDescription with parenthesis ();

trim mist
#

I was more or less trying to see if this is even possible

lone nest
#

but i could be wrong.

red tiger
#

with TypeScript you get to see syntax errors when compiling. =)

trim mist
frank elbow
#

So have you tested it out ingame ?

#

And have you defined TraitFactory_Trait?

red tiger
#

#ad

trim mist
frank elbow
#

🤦🏾

trim mist
#

but TraitFactory_Trait is here

#

It's vanilla lua

frank elbow
#

That's a type stub for a Java class

trim mist
#

fuck

bronze yoke
#

you can do stuff like this using metatables, but i'm not actually sure how to access nested classes

frank elbow
#

You may be able to override it using __classmetatables, though, assuming it's not used Java-side

#

I'm not sure either, now that I think about it

trim mist
#

For my purposes, all I need is this to be present in the lua

#

but no. Sorry for making y'all think I was demanding help. I'll work on this a little more and be more careful when I type messages in here

bronze yoke
#

i think capsid adds the underscores and that's not actually how they get exposed (since print(TraitFactory_Trait) is no good)

red tiger
#

Why do people use capsid?

bronze yoke
#

intellisense?

red tiger
#

EmyLua?

bronze yoke
#

for java types

#

it generates annotation files for emmylua

frank elbow
#

A quick glance suggests TraitFactory.Trait, but I haven't read it closely enough to be sure about that. If you can access the class as TraitFactory.Trait, then you can patch its metatable by getting __classmetatables[TraitFactory.Trait.class].__index. I don't know whether that's possible & don't have time atm to confirm

red tiger
#

I mean..

#

I could write a generator for EmmyLua..

bronze yoke
#

it's not TraitFactory.Trait

red tiger
#

I've only seen issues when Capsid is mentioned here..

bronze yoke
#

capsid needs a little maintenance

frank elbow
#

The exposing code suggests it creates a table structure for nested items

red tiger
#

I can write an exporter adjacent to PipeWrench typings for the same data.

frank elbow
#

...or I was looking at the wrong method 😄

red tiger
#

If people want I can eliminate Capsid.

bronze yoke
#

i tried _G["TraitFactory.Trait"] and that was no good either

red tiger
#

I'll need the name of a tool from PZ.

#

Anyone know a good name for generated Lua annotations project?

lone nest
#

pz specific for the modding community?

red tiger
#

I need a name of a tool from in-game in PZ.

#

I should call it "BetaBlocker" lol

lone nest
#

Oh, you want to name a project after a tool in PZ.

red tiger
lone nest
#

Well... I'd imagine one of the stationary tool would qualify.

red tiger
#

Repair items too.

#

Those are tools.

#

I've used Sledgehammer, DuctTape, WoodGlue, PipeWrench, Screwdriver so far.

lone nest
#

I'd prefer context-related usage, you're creating a project that is supposed to add context details to what I assume is PZ code.

red tiger
#

Crowbar is also used for an unreleased project.

#

Binoculars?

lone nest
#

regrettably, calculators do not exist in PZ cause math is lost in a zombie apocalypse.

bronze yoke
#

but not _G["TraitFactory$Trait"] strangely

red tiger
lone nest
#

that's the closest thing i can think of to make something prettier

#

at least within PZ.

red tiger
#

_G['TraitFactory$Trait'] !== zombie.characters.traits["TraitFactory$Trait"]

#

_G['TraitFactory$Trait'] === TraitFactory$Trait

lone nest
#

maybe they'll add cattle prod and what not once animals are released.

#

until then...

red tiger
#

I could call it ToiletPaper

bronze yoke
#

the exposer usually puts classes into _G though

#

maybe it doesn't get put there because it doesn't have any statics

red tiger
#

It's the same thing as calling it as a global var.

#

Only diff is that you can call variables this way as global is itself a table.

#

I use it too.

bronze yoke
#

i'm not really sure what you're trying to tell me here

#

i'm using _G["TraitFactory$Trait"] because lua doesn't like $ outside of a string, even if i'm trying to index a table

#

it would be the same as TraitFactory$Trait if that didn't make lua mad

red tiger
#

Thought saying it would help others understand.

bronze yoke
#

oh, i see

frank elbow
#

Desperately need to focus on work rn but I want to read through the exposer to find out 😢

red tiger
#

Going for the name Candle.

#

Bet ya I can get Candle developed to replace Capsid tonight.

#

Setting up the environment right now.

#

#LearningExperience

#

I need to look at the API for Emmylua..

frank elbow
red tiger
#

I only need to know what files that EmmyLua digests.

frank elbow
#

Ah, I missed that you're talking about creating an IntelliJ plugin

red tiger
#

Not an IntelliJ plugin but whatever that Capsid feeds to EmmyLua.

#

I think this is it.

frank elbow
#

Oh, in that case the above is a reference worth looking at—it does the same

red tiger
#

If the files that it creates can be zipped and sent to me then I can begin work on it. =)

thin hornet
#

would be sick to have a tstl plugin that generate the emmylua comments about the classes

frank elbow
#

I don't use capsid myself

red tiger
#

EmmyLua has poor documentation AFAICS

frank elbow
#

I stick with the LuaCATS fork

red tiger
#

Link and link to their generated files?

thin hornet
#

@red tiger i realized that pzpw can also work for lua mods without any ts

red tiger
thin hornet
#

yeah

frank elbow
#

For the stubs I use locally I used pz-zdoc plus a quick-n-dirty Python script to process the output to be a bit better

red tiger
#

Oh so I write typedefs

#

Ok

#

So LuaDoc typedefs

#

God this will be so easy.

frank elbow
#

I think they're a bit distinct from LuaDoc but yeah, nothing too fancy

red tiger
#

Yeah if people are sick and tired of Capsid I can deprecate it.

#

EmmyLua is providing what TypeScript does.

thin hornet
#

well capsid is just unmaintained afaik

red tiger
#

Over 2 years since last commit.

thin hornet
#

damn time fly

#

alright time to write a tutorial

bronze yoke
#

a dream of mine has been to get it to grab parameter names from the reference site

#

but i can't work out any of this gradle plugin stuff so i never worked on it

red tiger
#

I plan to do this for PipeWrench.

#

I could prioritize this task.

#

How much is this in demand?

#

I prioritize what projects I develop based on the needs of the community.

thin hornet
#

pipewrench with more docs?

frank elbow
#

Parameter names would definitely be nice, I've wanted to improve pz-zdoc as well

thin hornet
#

Co had something that was making the code beautifull

red tiger
#

PipeWrench, (Now Candle), and the pz-zdoc?

frank elbow
#

If your annotations are compatible with LuaCATS I'll happily use (and perhaps contribute to) Candle instead 😄

red tiger
#

It'd speed up the process. =)

#

I don't want to run capsid.

frank elbow
#

Sure, I'll zip them up

red tiger
#

Thaaaaanks

#

Huge

frank elbow
#

Note that mine are specific to LuaCATS though; capsid ones won't have some of the stuff mine do

red tiger
thin hornet
hoary widget
#

Just to clarify it's not a coding thing but more id have to make a texture that is big enough for both male and female texture/uvs, I can't just put a line of code in that says one or the other right?

ancient grail
#

Use the brushtool cheat
Then when you right click theres an option to copy and sldo writes the time name

mellow frigate
ancient grail
red tiger
#

Huh..

#

EmmyLua doesn't support generic args for field declarations.

#

All the more the reason to use PipeWrench.

primal remnant
#

I'm struggling with setUsedDelta on an item I'm adding to my inventory.

#

Do I create a local variable that stores an item and modify the setUsedDelta, and then add it?

thin hornet
#

@red tiger Seems there is a problem with using IS objects in pw.
This doesnt work:

const cursor = new ISPlace3DItemCursor(player, [item]);

This works:

const cursor: ISPlace3DItemCursor = _G.ISPlace3DItemCursor.new(player, [item]);
red tiger
#

Document it somewhere for the time being.

thin hornet
#

ah okay

#

is it just the typedef not exporting the actual global object in pw

red tiger
#

Flaws from a sketchy transpiler that I had no time to write.

thin hornet
#
  Exports.ISPlace3DItemCursor = loadstring("return _G['ISPlace3DItemCursor']")()
#

yet it should work

frank elbow
red tiger
#

Already made progress.

wanton pier
#

I think I am blind, but I'm interested in pz typescript. PipeWrench is what I am after?

viral magnet
#

so I'm trying to modify a mod, I have this

#

any ideas it still can't be wore the same time as a backpack?

#
 item RuBag
    {
        WeightReduction    =    50,
        Weight    =    0.5,
        Type    =    Container,
        Capacity    =    10,
        DisplayName    =    RuBag,
        Icon    =    rbao1,
        MetalValue = 15,
    ClothingItem = RuBag,
    CanBeEquipped = FannyPackFront,
    BodyLocation = FannyPackFront,
    ClothingItemExtra = RuBag,
                BloodLocation = Bag,
    ClothingItemExtraOption = FannyPack_WearBack,
    OpenSound            = OpenKitB,
    CloseSound            = CloseKitB,
    PutInSound   =   PutItemInBag,
               WorldStaticModel = GunCase_Ground,
    }
red tiger
#

pzpw

viral magnet
#

im trying to make it take up the fanny pack location

#

but it conflict both fanny pack and backpack

wanton pier
#

That's perfect. Is there a tutorial or just clickaroo on konjima for some links?

frank elbow
red tiger
#

I have my own basic environment but pzpw should be better for people overall.

wanton pier
#

Awesome! Thanks for going out of your way. ❤️

red tiger
#

No problem.

frank elbow
viral magnet
#

Okie

#

I’ll do that

primal remnant
#

Does anyone here have any experience using the setUsedDelta for result items in recipes?

Arsenal mod overwrote the base game Gunpowder to give it a 0.005 useDelta, but when I try to add more than one GunPowder as a result item it simply returns a full one.

I'm kind of stuck in the weeds on the proper way to manipulate an items usedDelta before adding it to a players inventory.

bronze yoke
#

can you show how you're trying?

primal remnant
#

@bronze yoke But of course!

So here's the recipe:
recipe Gather x1 Gun Powder
{
Bullets22/Bullets357/Bullets38/Bullets380/Bullets44/Bullets45/Bullets4570/Bullets45LC/Bullets50MAG/Bullets57/Bullets9mm,
Time:5.0,
OnCreate:GatherGunPowder,
Result:GunPowder,
RemoveResultItem:false,
Category:Omni Ammunition,
NeedToBeLearn:false,
CanBeDoneFromFloor:true,
}
And here's the code I was attempting.

function GatherGunPowder(items,result,player)
    result:setUsedDelta()=0.005

end
#

When I gather a single round, say a "Bullets22" it returns an entire Gunpowder.

bronze yoke
#

result:setUsedDelta(0.005)

#

not =0.005

trim mist
#
local originalGetTraitDescription = zombie.characters.traits["TraitFactory$Trait"].getDescription;
zombie.characters.traits["TraitFactory$Trait"].getDescription = function(self)
    local descAndTags = originalGetTraitDescription(self);
    local indexOfTagsBegin = strFind(descAndTags, "||");
    if indexOfTagsBegin == not nil
    then
        local description = strSub(descAndTags, 0, indexOfTagsBegin);
        return description;
    else
        print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
        return descAndTags;
    end


end

zombie.characters.traits["TraitFactory$Trait"].getTags = function(self)
    local descAndTags = originalGetTraitDescription(self);
    local indexOfTagsBegin = strFind(descAndTags, "||");
    local lastComma = 1;
    local tagTable = {};

    if indexOfTagsBegin == not nil
    then
        local tags = strSub(descAndTags, indexOfTagsBegin);

        for i=1, strlen(tags)
        do
            if tags[i] == '' or tags[i] == ','
            then
                table.insert(tagTable, strSub(tags, lastComma, i));
                lastComma = i;
            end
        end
    else
        print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
        return tagTable;
    end
    return tagTable;
end

Here's what I got

bronze yoke
#

you have to follow this sort of pattern```lua
local metatable = getmetatable(zombie.characters.traits["TraitFactory$Trait"].class).__index
local old_getDesc = metatable.getDesc
metatable.getDesc =

#

(well assigning metatable to a variable is strictly unnecessary but who wants to write all that out every time)

red tiger
#

Capsid seems to export items that aren't exposed. That can confuse the modder..

#

I said I was going to get an initial working copy of Lua definitions. Going to do it..

red tiger
#

My current test file is ~365K lines long.

#

Haha lol

#
--- @public
--- @static
---
--- Method Parameters:
--- - (RoomDef arg0, int arg1): IsoDeadBody
--- - (int arg0, int arg1, int arg2, IsoDirections arg3, int arg4): IsoDeadBody
--- - (IsoGridSquare arg0, IsoDirections arg1, int arg2, int arg3, String arg4): IsoDeadBody
--- - (int arg0, int arg1, int arg2, IsoDirections arg3, int arg4, int arg5): IsoDeadBody
--- - (float arg0, float arg1, float arg2, float arg3, boolean arg4, int arg5, int arg6, String arg7): IsoDeadBody
---
--- @param arg1 RoomDef | int | IsoGridSquare | float
--- @param arg2 int | int | IsoDirections | float
--- @param arg3 int | int | int | float
--- @param arg4 IsoDirections | int | IsoDirections | float
--- @param arg5 int | String | int | boolean
--- @param arg6 int | int
--- @param arg7 int
--- @param arg8 String
function RZSTrapperCamp.createRandomDeadBody(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) end
#

Not too crazy..

primal remnant
#

@bronze yoke I tried the code you mentioned, but it's still showing up as a full item. I don't think result:setUsedDelta(0.005) works the way I think it does.

red tiger
#
--- @public
--- @static
---
--- Additional Methods:
--- @overload fun(arg0: int, arg1: int, arg2: int, arg3: IsoDirections, arg4: int)
--- @overload fun(arg0: IsoGridSquare, arg1: IsoDirections, arg2: int, arg3: int, arg4: String)
--- @overload fun(arg0: int, arg1: int, arg2: int, arg3: IsoDirections, arg4: int, arg5: int)
--- @overload fun(arg0: float, arg1: float, arg2: float, arg3: float, arg4: boolean, arg5: int, arg6: int, arg7: String)
---
--- @param arg0 RoomDef
--- @param arg1 int
--- @return IsoDeadBody
function RZSTrapperCamp.createRandomDeadBody(arg0, arg1) end
#

What a journey that was..

red tiger
#

Okay.. This thing is fuckin evil

#

Will split it up tomorrow and begin looking at debugging but I essentially just wrote an exporter for what Capsid does.

#

@frank elbow @bronze yoke

#

It's past 1 AM and I did what I said I would. I did it in one sitting.

#

Going to grab something and lie down.

mellow frigate
frank elbow
novel swallow
#

Do I remember right in that someone mentioned a mod that can show loot table odds in-game?

neon bronze
#

Loot table odds?

#

Like the probability of items spawned in containers? You can already do that in vanilla with LootZed

novel swallow
#

Oh, that's it "LootZed"!

#

I assumed it was a mod

#

But yeah, that's what I want to do - how do I use it? Is it a -debug option?

#

Ah found it, it's in the Cheats menu when you have -debug on, thanks.

#

Errr, does LootZed work correctly? It seems to think all these kitchen cabinets have the same loot table when they don't...

#

Like it's showing me just the "Bottles" one, even though this is a CannedFood one

#

Oh I see

#

there's a drop down you have to manually change for sub types, nvm

novel swallow
#

Is there an event for something like "OnContainerOpen" that triggers for the client when they open something. More accurately I want to know when they loot a zombie

mellow frigate
#

AFAIK, there is no such thing as a container opening event (there could be something like that, but for vehicles only). There is a container update though. If you are interested in the fact that a container becomes available to a player, it is nearly strictly related to position. (nearly because passage must also not be blocked and not in a restricted area)

novel swallow
#

Basically, I was hoping I could somehow dull a zombie's corpse if you've seen it's inventory. I guess if you got close enough to it that'd work too? But I imagine if you melee killed it, you wouldn't know you've looted it as you were already right next to it.

frank elbow
#

ItemContainers have an isExplored method, but I believe that'll be true if anyone has seen its inventory. Maybe you could override ISInventoryPane.update and use getPlayerLoot to check the container, but I haven't used the latter so idk whether it has the information you need for that

#

What I mean is something like:

local ISInventoryPane_update = ISInventoryPane.update
function ISInventoryPane:update()
  ISInventoryPane_update(self)
  local loot = getPlayerLoot(self.player)
  if not loot then
    return
  end

  -- do something with the return value of getPlayerLoot
end
#

See client/ISUI/ISInventoryPane.lua for examples of getPlayerLoot—unfamiliar with its structure myself, so it may not end up having what you need

novel swallow
#

Thanks, having a look around now

frank elbow
#

It may be wiser to choose a different method to override after a quick glance through myself, but the general idea should be the same. Maybe an event instead, if none fit

#

getPlayerLoot will return an ISInventoryPage or nil

novel swallow
#

so backpack borders has this:

-- Add background and border to new buttons
ISInventoryPage.addContainerButton_pre_backpack_borders = ISInventoryPage.addContainerButton;
function ISInventoryPage:addContainerButton(...)
    local button = self:addContainerButton_pre_backpack_borders(...);
    button:setBorderRGBA(0.6, 0.6, 0.6, 0.5)
    button:setBackgroundRGBA(0.12, 0.12, 0.12, 0.7)
    return button;
end

I wonder if I can do similar and see if the "button" is a zombie's inventory container

sage python
#

how easy is it to make your own true music mod?

novel swallow
red tiger
#

<@&671452400221159444>

#

Phisher scam bot in channel.

lost slate
#

ty

ancient grail
sage python
#

ok

novel swallow
#

Why am I getting Object tried to call nil when I have it wrapped in if button.container ~= nil then 🤔 ?

neon bronze
#

Your button is nil then

#

Actually no iam wrong

novel swallow
#

oh my bad, I copied that after I made sanity changes

#

it was originally just if container ~= nil then

neon bronze
#

Alternatively you can just check with if not button.container then

novel swallow
#

Error:

function: mGuvLevelOverhaulAddContainerButton -- file: mGuv_LevelOverhaul_MarkZombiesAsLooted.lua line # 10 

LOG  : General     , 1684336472787> Object tried to call nil in mGuvLevelOverhaulAddContainerButton
ERROR: General     , 1684336472787> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in mGuvLevelOverhaulAddContainerButton

File:

require "ISUI/ISInventoryPage"

local originalAddContainerButton = ISInventoryPage.addContainerButton;

function mGuvLevelOverhaulAddContainerButton(container, texture, name, tooltip)
    print("A");
    -- is it a zombie? If so what can we do
    if container ~= nil then
        print("AA");
        local name = container:getName(); -- this is line 10
-- etc
neon bronze
#

Container may not have a function called getName()

novel swallow
#

oh is -that- what that error means?

#

That's not clear at all. I thought it was saying container was nil

neon bronze
#

What is container?

novel swallow
#

No idea

#

lol

#

this is me probing based on what I saw elsewhere

#

Looking at the zomboid code it should be a ItemContainer, I don't know why I'm getting nil

#

and then why my nil check fails me

#

Oh whoops, I pulled getName off InventoryContainer not ItemContainer

novel swallow
#

Is there a way to skip current iterations of a loop like continue in other languages? What about break to get out of a loop?

bronze yoke
#

break is available

#

no continue

red tiger
#

So you invert your condition to continue.

novel swallow
#

noooo rip clean code

red tiger
#

This is how you get around this issue.

bronze yoke
#

yeah it's kind of gross

red tiger
#

You could delegate to a function call using return.

#

That is what I do sometimes.

bronze yoke
#

i'm lua's strongest warrior but the lack of continue is gross

red tiger
#

functions can be variables.

#

Use a function with return.

novel swallow
#

I opened one mod's lua to get some ideas and it's like 20 levels of nested ifs, rather than flipping conditions and early returning

#

but looks like it's part because you can't continue properly

red tiger
#

Or just be a real programmer and use TypeScript.

I'll wait.. for Lua people to burn me alive for that statement.

novel swallow
#

I mean I am, but I'm also hand writing lua to learn it at the same time

red tiger
#

Lua is real programming guys.. cmon...

novel swallow
#

so I can read others code, the ts stuff is great but I still need to understand lua lol

red tiger
#

I'm also working on forwarding what PIpeWrench defines with types to Lua through EmmyLua.

#

We help people here.

#

Also too much caffeine today.

lone nest
red tiger
#

Mmmmmmmmmmm

trim mist
red tiger
#

=)

#

I have A LOT to document.

trim mist
red tiger
#

Holding back the trigger on a lot of tutorials.

lone nest
bronze yoke
#

you can just put it on there

fast galleon
red tiger
trim mist
#

no, that was a couple of traits ago haha

#

I'm onto the unholy task of hooking into the getDescription() function of traits and seeing if I can use the description to hold tags related to the trait itself

#

For my purposes I'm trying to limit what anthro species can be chosen based on what traits you have

#

with said tags

#

I'm certain that if anyone made like, a buff model replacer the same technique could be useful

fast galleon
#

because it should be

if indexOfTagsBegin ~= nil then
if indexOfTagsBegin == not nil
    then

is like

if 1 == true
    then
trim mist
#

💀

#

i see. I've used that pattern in several places

#

I'm gonna fix that lmao

lone nest
#

my goodness, I should also make parenthesis required in those if () then blocks.

trim mist
#

Same issue. I find it really odd that I have no locals popping up

#

Do you guys think I'm tackling this the wrong way? Maybe there's an easier way to connect tags with traits?

fast galleon
#

old vs original

neon bronze
#

needs more brackets

novel swallow
#

wait is there really no like... regular way to add to an array? Uh, table? Whatever they call it lol

#

no var[] = x, var.push/insert/add/etc, all I see is... var[#var+1] = x

fast galleon
red tiger
#

Always keep this in mind when looking up Lua tutorials or features.

neon bronze
#

I hope they update the lua in the near future

red tiger
#

I do too..

#

For now I pick on it and have fun making tools to bypass writing actual Lua to do things with PZ.

neon bronze
#

Imagine they had like a modders vote or smth where they would ask modders what they would like to see implemented/exposed to help them mod

red tiger
#

It's why I don't ask. I simply do.

#

One day I'll release my core utilities mod. =)

nimble spoke
novel swallow
#

Can I set custom params with DoParam? If so, how do I read them back out?

bronze yoke
#

yeah, any unrecognised parameter set by doparam or the item script is added as default moddata

#

i'm unsure if default moddata is accessible on the item level but you can grab them from inventoryitems with item:getModData().myParameter

novel swallow
#

ah okay, if I use getModData can I set things with that too?

#

Cos I might as well just stick with that as it's my own item

bronze yoke
#

yeah, moddata is just generic per-object storage

novel swallow
#

Hmm, does that persist between saves?

#

As in, is it serialised

bronze yoke
#

yep

#

that's the primary purpose of it actually

novel swallow
#

Oh I see, hmm. I'm more wishing to change the base of the item

#

I don't know how to describe, like I was modifying the Item {} definition from a items.txt

bronze yoke
#

that's what doparam does

novel swallow
#

Hmm, but it ends up on getModData that gets serialised if it's a custom param 😅 ?

bronze yoke
#

i never considered that actually, that's kind of obnoxious

#

custom parameters are going to be saved for every single instance of the item

novel swallow
#

Yeah, which I don't actually want really.

#

I mean it'll work... But it's wasteful

bronze yoke
#

also default moddata doesn't get applied to existing items, which might be important for your mod

novel swallow
#

Yeah, I heard about that

bronze yoke
#

it might make sense to just store whatever data you wanted to in a table

#

e.g. myParams = {["Base.Apple"] = 5, ["Base.Orange"] = 7}

novel swallow
#

literally rewriting to that now 😅 basically making it a look up via item type, rather than attaching it to the item

drifting ore
#

@bronze yoke Is it okay if I message you with a question about your mods?

bronze yoke
#

sure!

ancient grail
#

Hmmmm sounds useful for random supply box kind of mod

bronze yoke
#

no, i just meant to not use moddata and just use a lookup table instead since it didn't seem to really fit the use case

#

you could do a supply box mod like that but it seems wasteful to use moddata for it

#

and probably wouldn't offer any utility of its own

pseudo jetty
#

can't believe MS included a browser in their XML viewer

lone nest
#

question, is there a mod that displays the square in which a throwable is supposed to land?

#

been messing around and attracting hordes, but the molly doesn't seem to go where I click :(

olive gorge
#

Are there any mods adding quests/tasks to the game?

lone nest
pseudo jetty
#

you don't npcs for tasks

#

it's in Chinese though

abstract pine
#

Is it not possible to mod the erosion system? I'm finding the decompiled Java for it a nightmare to try to make sense of, and it doesn't look like much is possible with lua (short of trying to write a new erosion system from scratch to go on top of the existing one). I wanted to try to uncap erosion so trees and etc don't stop growing once you hit 100% growth, but nothing I look at is giving me a clue how I would go about doing that.

ornate summit
#

Anyone have a tutorial or documentation on how to use lua files on tiles?

quasi kernel
#

This may sound mildly insane but I'm thinking about getting back onto the Ultimate Farming Patch grind to get it working better than ever.

#

So here's my question - how possible would it be to just use a metatable here to store all the data necessary in between mods without requiring individual patchers?

lone nest
quasi kernel
#

To my knowledge, metatables are able to detect edits made within themselves, so if I can turn the global farmingconf table into a meta, I could theoretically get it to hook onto new additions / changes and just cram that all into data.

#

This approach has it's own problems and it's all theoretical thoguh

#

The alternative approach is just making individual "patcher" mods that require a very specific mod load order to function.

#

Though those would also theoretically allow me to make little edits and save to a specific "code" for a custom farming "priority" order.

lone nest
#

the general rule of thumb is complexities grow exponentially per variable; I'm unsure how many variables and tables... then mods you plan to "hook up" together.

#

cause you also have to deal with mod loads ordering

quasi kernel
#

The entire point of UFP is to act as a framework for farming compatibility to turn it more into an unintentionally soulfilcher-type system, but this is the only way I can think of keeping it lightweight and up-to-date.

#

In other words, it forces farming mods to play nice by yoinking their necessary farming data and ordering it in a specific way so they can all be friends.

#

All of this will have to be done-over by the time 42 releases but I have a feeling that could be a bit.

quasi kernel
#

Aaa sorry hehe

#

I'm just off the walls, both in a good and bad way.

#

The last rendition of this mod had ~4K lines of manual data entry for mod support.

#

I'd.. like to get that down a bit.

#

And also let the community introduce mods they want rather easily.

lone nest
#

Hm? That depends on how you plan to restructure the project...

quasi kernel
#

I'm thinking of a "sandwich" style.

quasi kernel
#

You have the Core mod which comes last since it would handle all of the conversions over to a Soul Filcher type system

#

Then you would have individual patchers that save the data in between mods and wipe the slate clean

#

So like

#
- Vanilla
- Vanilla Patcher (Saves all vanilla data.)
- Soul Filcher's
- Soul Filcher's Patcher (Saves all SF data.)
- CORE
#

relatively easy order to maintain.

#

Also, sorry for the ping @nimble spoke, but thank you for existing and making mods for this game.

#

You are literally one of the reasons I started modding.

nimble spoke
#

I appreciate that. I'm glad you're fine and back on the saddle

quasi kernel
#

Yeee!

#

Awesome Time is hands down one of my favorite mods on the workshop.

#

Anywho, I have a horrible amount of work to do!1

#

Can't wait to restructure my ENTIRE MOD!

nimble spoke
#

I assume you hit a roadblock, what was it?

quasi kernel
#

Oh, I just realized that manual data entry isn't worth it like, at all.

#

So automating as much of it as humanly possible to save on the workload and theoretically increase mod update compatibility tenfold would be nice.

#

(And also reduce the file size, which ain't much but hey, it's something.)

#

It only took 11 mods worth of farming data to figure that out!

lone nest
#

blame lua code

quasi kernel
#

If I can get this system up and running, it should take significantly less time to get mods to play nice with the framework, and I wouldn't have to worry about a single update ruining the stats associated with the crops.

#

Really all I can blame is myself, I chose to do the data entry route at the start LOL

#

I didn't think UFP would get anywhere it did.

#

It was originally just a Mo Crops / Soul Filcher's patch

#

Hence the "MoFilchers" name in the files.

nimble spoke
#

Sadly farming mods could have been totally compatible, as that was my goal with the mod, but other modders didn't follow up. Hopefully that will be solved in b42

quasi kernel
#

Yeye

#

I wouldn't have to do any of this if they had just adapted to your system

#

But oh well, I guess people like their mods being standalone..?

nimble spoke
#

Or simply don't care enough about compatibility

quasi kernel
#

Perhaps.

#

Either way though, this can at least be a workaround in the wait for B42.

nimble spoke
#

sure. Players who enjoy farming mods always try to use several of them, you can make their mod lists less janky

red tiger
#

Mmmmmmmmm

quasi kernel
#

The other reason behind this patcher is because it implements a few fixes / features to vanilla too which can't otherwise be used with most other farming mods.

#

Namely a fix I plan on giving to cures which my girlfriend noticed of all people, you tend to use a bit more cure than is actually necessary to get rid of crop disease.

#

(If the crop disease isn't a perfect increment of 5 you could be wasting some cure on every spritz.)

nimble spoke
#

Are there other things in these farming mods that need to be patched or just the growth function / context menu?

quasi kernel
#

Mostly growth function and context, however Le Gourmet does change a lot up.

#

The system allows you to adjust to LG's "Learn to Sow" system if you want it to, so crops aren't left entirely unplantable due to not knowing a recipe from seed packets.

#

(The sow menus required you know how to plant the crop, which is learned from seed packets. This broke compatibility with virtually every other farming mod.)

#

It also allows for "refunding" from LG's crops - and potentially other crops. Stuff like twigs and sheet rope that went into planting it are given back when you harvest, assuming it doesn't reset back to a previous stage.

nimble spoke
#

I'd focus on making the other mods compatible first, so at least it is useful before B42. Trying to include LG may take you too long

quasi kernel
#

Perhaps.

#

I'll focus on that for now, I'll drop in LG support if I can find the time.

#

The only thing I might need to figure out for convenience is how to like..

#

Potentially to get specific parts of a mod to load first, then other parts of the mod to load last.

#

So like, the CORE I could theoretically get up top if I can get only it's necessary global functions and data loaded.

#

Then let all of the patchers add to that.

#

Then when it's done, I just figure out how to get Core to run after everything else is done.

#

Hooking to different functions may be one way.

nimble spoke
#

sounds.... like a nightmare

quasi kernel
#

Yes!

#

All else fails I just make a proper sandwich and just have two core mods. One for initial load and one for wrap-up.

#

Though I'd rather keep it all in one mod if possible because I have a feeling people will be at my throat otherwise.

nimble spoke
#

You don't need the second mod if you find proper events so you can run whatever you want later

quasi kernel
#

Yeye

#

I question if this all is even that good of an idea anymore but oh well, worth a shot at least.

#

Good way to learn and at least grow from my mistakes.

nimble spoke
#

the idea is good, I think you can get it working in time

quasi kernel
#

Thank you.

#

Maybe I can even get it done tonight if I power through.

#

It took me about a week to figure it out the first time, should only be faster the second.

#

..especially with less data entry.

hoary widget
#

do clothing item xmls all have to be 1 word?

fading horizon
#

clearing out my old saves be like

fading horizon
#

i don't think you can have spaces if that's what you mean

#

but theres an example of one of my xmls

hoary widget
#

gothca

hoary widget
fading horizon
#

this is for dev testing saves not real ones though lol

#

also wow

#

if you have a mohawk and you equip a helmet, it flattens your hair

#

i never knew that

hoary widget
#

Thats good to know!

fading horizon
#

on a sidenote, the armor mod ive been working on is almost done

#

haven't been posting here as frequently

hoary widget
#

OOOOOO

#

That helmets visor looks like titanfall! or Mando

fading horizon
#

yeah heres without the nvgs

#

i actually used a mando helmet tutorial to help model it

#

since it is very similar

hoary widget
#

ah..btw are your clothes just clothing or do they like add stats or gui stuff?

fading horizon
#

theres only one piece of clothing there

#

that's the jacket

#

the rest are like accessories

#

shoulder pads, bracers, helmet, tactical belt, backpack

#

the pads and helmet have protection stats

#

NVGs add nightvision functionality

cinder jay
#

no idea how to make mods but if someone wanted to pick the idea up, for a long time in an internet forum ive been a part of the idea that lifting will remove your depression has been around, so making a mod that decreases unhappiness when lifting weights would be cool

drifting ore
#

me omw to fix suicidal ideation from being in the apocalypse through sheer gainz

hoary widget
#

How can I check if I messed something up in scripts for my mod?

hoary widget
fading horizon
#

I don't think you can

#

i'm not 100% but i wouldn't think so

hoary widget
#

gotcha im just trying to figure out hat I messed up cause its frozen at scripts

red tiger
#

Going to pretty up the repo tomorrow.

#

This is a replacement for Capsid.

#

The types are already provided by the repo so there's no need to decompile PZ

#

@thin hornet

#

I'm so thrilled.

#

I met my goal and the results look great.

fast galleon
#

That's super cool @red tiger

red tiger
#

Hopefully this will drastically improve the setup process for modders who would otherwise need to operate Capsid and decompile PZ.

bronze yoke
#

yeah, capsid is kind of a pain to get working and this is a step up in other ways too

#

i hugely recommend people switch to this when they can

red tiger
#

Id like to place Candle in central repositories that people use for EmmyLua

fast galleon
#

wrong link
Is table.isempty(t) included in Candle?

fading horizon
#

just figured out how to make functional NVGs

#

feels cool

fast galleon
drifting ore
#

Any ideas on tools that help us update/upload mod?

#

without open pz

fast galleon
#

You can probably customise the steamcmd scripts used to make this happen.

drifting ore
drifting ore
hoary widget
#

Hey so I have a drop model but when I put the clothing on the ground it just drops the icon

#

item Jacket_samurai_classic
{
Type = Clothing,
DisplayName = Samurai Jacket classic,
ClothingItem = Jacket_samurai_classic,
BodyLocation = Jacket,
BloodLocation = Jacket,
Icon = SteamGuideJacket,
RunSpeedModifier = 0.98,
CombatSpeedModifier = 0.97,
ScratchDefense = 60,
BiteDefense = 30,
Insulation = 0.4,
WindResistance = 0.8,
WaterResistance = 0.6,
Weight = 2,
FabricType = Cotton,
WorldStaticModel = Samurai Jacket_ground,
}

#

Did I mis code something

drifting ore
#

its work right now, thanks for the insight from repo that your share. I can update my mod even on mobile tho.

rotund sail
#

Yo modern phones are strong af

ancient grail
#

Samurai space jacket underscore ground

zinc pilot
#

Is there a reliable way to get an emitter from an IsoObject?

novel swallow
#

Hmm, I am trying to recursively search a container (well 'backpack' as the game seems to call it) by looping through all its contents, and checking if the item can contain items.

#

My check to see if it is a container works, but when I get the items in the container I get nil?

#

I'm testing it with a first aid kid, so little unsure what's going wrong.

mellow frigate
novel swallow
#

Ah thanks, yeah, if you're auto looting you'll be doing very similar to me. Will check it out.

#

(I'm highlighting containers with certain items in - so basically the same without actually grabbing the item)

#

Is it good practice to put all my loose global functions/variables in like a 'Module', like mGuvsStuff = {} mGuvsStuff.SomeGlobal = 'foo', rather than just having SomeGlobal loose

mellow frigate
novel swallow
#

I see it as reducing the chance of causing a collision with another mod so a positive.

#

Though if someone somehow collided with your module name, it'd overwrite it all 😅

mellow frigate
novel swallow
#

True

#

Darn, I just did some digging to see if I could custom set the background for item line entries in your inventory, like how Frozen/Hot stuff does.

#

Super hard coded 😦

mellow frigate
#

there is also a green progression when there is an action on an item. maybe it is easier to use.

subtle bolt
#

Hey guys!

I've developed a mod, but I'm struggling to pinpoint an error the server console for the dedicated server I'm using keeps throwing up at me.

It's claiming an OnEat function I set up (OnEat_Zombex) can't be found, but for the life of me I can't figure out why.

I have it defined in the items.txt correctly and there's no syntax errors I can identify. Just a shot in the dark here but wondering if there's another reason the server console might be unable to find the function that is a little less obvious?

(I only recently learnt this forum existed, so hiiiii! And thank you for taking the time to read)

mellow frigate
subtle bolt
mellow frigate
frank elbow
novel swallow
#

I grabbed an original method, overwrote it, then called the original from inside my overwrite: and the original blows up. If I had to guess, it looks like something happened to self - and I don't know lua enough to know how to fix that 😅

frank elbow
#

Can you show a snippet of the code in question?

novel swallow
#

sure I'll grab the important parts

#
require "ISUI/ISInventoryPage"

local mGuvBaseISInventoryPage = {};
mGuvBaseISInventoryPage.refreshBackpacks = ISInventoryPage.refreshBackpacks;


function mGuvOverwriteLootingUI()
    -- Overwrite original - refreshBackpacks
    function ISInventoryPage:refreshBackpacks(...)
        -- Call original - refreshBackpacks
        mGuvBaseISInventoryPage.refreshBackpacks(...); -- THIS BLOWS UP

        -- Check every backpack button
        for k,containerButton in ipairs(self.backpacks) do
            -- Skip if it doesn't have an inventory
            if containerButton.inventory ~= self.inventory then
                local bestRarity = GetRarestRarityFromItems(containerButton.inventory:getItems());
                -- Only highlight if it wasn't trash
                if bestRarity.Name ~= "Trash" then
                    -- Set the background of the UI icon
                    containerButton:setBackgroundRGBA(bestRarity.Color:getR(), bestRarity.Color:getG(), bestRarity.Color:getB(), 0.7)
                end
            end
        end
    end
end


-- Run last so the backpack borders and sorting mod still work
local loadAfterEverythingElse = function()
    Events.OnLoad.Add(function()
        mGuvOverwriteLootingUI();
    end)
end

Events.OnLoad.Add(loadAfterEverythingElse);
frank elbow
#

Yeah, you're not forwarding the self variable to the call

novel swallow
#

How do I do that?

frank elbow
#

The colon, :, essentially is syntactic sugar for a self parameter. That is, these two are effectively equivalent:

function x:y() end
function x.y(self) end

The self parameter will be implicitly (well, explicitly but sugared) available in the first call. You just need to pass self as the first parameter, since the function expects that

novel swallow
#

I understand scoping/self, just not sure how to fix it in lua. JavaScript lets you use things like apply and bind to set what this is that context

#

oh, I see. So it's sort of automatically sending self as the first param

#

But using the wrong self, as it just grabs the current context

#

not the original

frank elbow
#

Yeah, it'll treat the first parameter as self if you don't pass it

#

x:y() is also equivalent to x.y(x) so it's easy to miss this detail when you're used to calls looking like that

novel swallow
#

yeah

#

wait is my issue just that

frank elbow
#

Yeah

novel swallow
#

mGuvBaseISInventoryPage.refreshBackpacks I did that instead of mGuvBaseISInventoryPage:refreshBackpacks?

frank elbow
#

Oh. No

novel swallow
#

Cos that doesn't look right now I see it as a .

frank elbow
#

Varargs (...) doesn't include self when you declare it with the colon

novel swallow
#

Sorry, still not following. I'm close to understanding but not sure what to do with the information

frank elbow
#

Penny for your 🤔 thoughts, Poltergeist? (asking because of the reaction) If I've said something that sounds strange please do explain

#

What part is unclear?

novel swallow
#

Where/what I need to change betwen : and . - or where I need to drop self in haha

#

I understand the problem but not the syntax

frank elbow
#

In the call to the original function, you should pass self

fast galleon
#
function x:y() end --y function in x table
function x(self, y) end --global x function
novel swallow
#

How can I pass self in if I'm doing it via ...?

#

can you just self, ...?

frank elbow
#

Whoops, thanks

#

Typing on my phone, so at least I can blame that 😄 (fixed)

frank elbow
fast galleon
mellow frigate
novel swallow
#

Though you have just shown me yet another oddity with lua 😅 but I get the need for this kind of control over self with something so dynamic

storm flame
#

Hey! Just joined, wondering if someone can help point me in the right direction for a mod I want to start on. Currently am using FearTheSun, which turns most zombies docile during the day, but I am finding docile zombies are a little too docile. Want to make them a bit more dangerous when fighting many close together.

Is there some script file that controls how zombies act on a moment to moment basis that I should be looking at, or some way to listen for an attack event, grab the position, find all the docile zombies near that and set them to not be docile?

Any help or guidance would be much appreciated, thank you!

bronze yoke
#

ai tends to be heavily hardcoded

#

it depends how fearthesun makes them 'docile' in the first place though

#

if that is something that can easily be flicked off then you can use the OnHitZombie or WeaponSwing events

storm flame
#

Sweet, that seems like it will work then. I will look into that, thanks!

novel swallow
#

If I define a module style thing (thing = {}; thing.x = function() print("foo"); end in say /mods/mymod/test.lua and I want to use it in /mods/mymod/other.lua, do I have to import it or anything?

#

Tried it the most basic why (similar to example provided) and it error'd

#

Oh wait, ignore me.

#

It worked fine. I read the wrong error.

#

Why is the "Errors list" in game so confusing D:

#

I'd be better off just tail -fing console.txt

hoary widget
lone nest
#

pain

red tiger
#

Hey modders. Letting you know that I now have a project targeting the replacement of Capsid. The files come pre-compiled and requires no steps other than placing the files in your EmmyLua environment.

https://github.com/asledgehammer/Candle

GitHub

Contribute to asledgehammer/Candle development by creating an account on GitHub.

#

I'm in the process of cleanup, fixes, and improvements.

#

This is me providing a lot of the same benefits of PipeWrench (TypeScript environment) to the Lua modders.

red tiger
#

(It's a WIP extension)

lone nest
#

hello! I am looking to add sandbox options to my mod, where do I go to get started? (my thanks in advance!)

hoary widget
hoary widget
red tiger
nimble spoke
nimble spoke
lone nest
#

Can someone pin that? I'd imagine more modders will need it in the future.

fast galleon
#

it's pinned on the wiki

hoary widget
red tiger
#

That is the right extension since mine is the only one in existence atm.

uneven fractal
#

can anyone help me create custom presets inside a mod's page in sandbox? I'm so lost

bronze yoke
#

what do you mean? like a sandbox option that is a list of options, or a preset for all the settings on that page?

uneven fractal
#

i want to change recoil force and other values and save them in some established presets in the "weapon presets" option

bronze yoke
#

that just isn't a thing i'm afraid

uneven fractal
#

so you change the recoil and stuff for each weapon

uneven fractal
bronze yoke
#

you could have the weapon presets option just override whatever the user puts in on the lua side but you can't have it change the actual settings

#

per-mod presets are something i'd looked into creating but i wasn't really experienced enough when i tried it, maybe i'll give it another go sometime

uneven fractal
bronze yoke
#

yeah, pretty much - you could have it load from a config file or something but that seems totally overkill

uneven fractal
#

yeah, i was worried it wasn't a thing since no mod has it, damn. Thx anyways

#

Well maybe you can help me with something else, when i create a new option it always goes at the bottom. I dont know what i did before but i did manage to put them at the top or between, but now i can't

bronze yoke
#

i think they just appear in the order they're defined in the sandbox-options.txt

uneven fractal
#

yes, they do but since i can't edit the mod's file i have to do it from mine

#

i created the same options and put mine in between in hope they overwrite the originals but they just duplicate

#

i tried this at first and it worked, but now they just go at the bottom

crystal oar
#

I'm trying to make a recipe that uses the moveable Broken Glass as a ingredient, but it's not working. my module already imports Base, and Base has items with the same ID as the moveables. I tried specifying the movable by saying Moveables.brokenglass_1_0 instead of importing Moveables, but it doesn't work. can anyone help?

bronze yoke
#

i have a mod installed that adds recipes using them that refers to them that way

#

Moveables.brokenglass_1_0/Moveables.brokenglass_1_1/Moveables.brokenglass_1_2/Moveables.brokenglass_1_3,

crystal oar
#

did you just import base or base and moveables?

bronze yoke
#

that mod only imports base

crystal oar
#

okay thanks

fast galleon
# crystal oar

Base and Moveables will be two different items. Often Base is from debug spawns and people who make recipes that give Base instead of Moveables.

mellow frigate
bronze yoke
red tiger
#

Umbrella EmmyLua Project

gilded hawk
#

Does getPlayer have different behavior if you are a client?

bronze yoke
#

getPlayer() always returns the local player 1

gilded hawk
#

So, even if I'm a client, get player will always get my player, right?

bronze yoke
#

yeah

gilded hawk
#

Okay thanks

thin hornet
gilded hawk
#

That is good enough for me

gilded hawk
#

Does anyone know a clean way to force some code to happen on the next tick?

sour island
gilded hawk
#

I tried, this and did not work

local event
  event = function()
    getPlayer():resetModelNextFrame();
    sendVisual(getPlayer());
    Events.OnTick.remove(event)
  end
  Events.OnTick.Add(event)
bronze yoke
#

Remove should be capitalised

sour island
#

I use a table with timestamps and params to run things later

gilded hawk
#

Can you give me an example?

sour island
#

Is this for 1 function or many?

gilded hawk
#

For one function please

golden abyss
#

did it move anywhere?

sour island
# gilded hawk For one function please
local delayedCall = {}
delayedCall.events = {}

function delayedCall.addEvent(ticks, ...)
    local event = {ticks=ticks, args=table.pack(...)}
    table.insert(delayedCall.events, event)
end

function delayedCall.parseCalls()
    for k,event in pairs(delayedCall.events) do
        if event and event.ticks then
            if event.ticks > 0 then
                event.ticks = event.ticks-1
            else
                local args = table.unpack(event.args)
                print("event.ticks: "..event.ticks, args)
                delayedCall.events[k] = nil
            end
        end
    end
end

Events.OnTick.Add(delayedCall.parseCalls)

This snippet is untested, but I've done something similar to this for my zombie AI

gilded hawk
#

Thank you! I'll give it a shot and let you know 🤗

sour island
#

Not really happy with leaving the entries going nil, but ending entries of nil get removed -- so eventually the table should shrink to {}

#

oh typo

#

ticks=1 -> ticks=ticks

#

using ... should mean you can add as many arguments you want

#

they all get packed/unpacked

#

direct references can't be saved tho - so be mindful

gilded hawk
#

Okay thank you, this makes sense

#

I'll look into it in a bit, because another bug just happened

#

And I think it's related to the sendVisual

sour island
#

as with modding

#

you don't happen to be a savant with github actions?

gilded hawk
#

Not really, I really only copy pasted a couple

#

Why? Do you need something specific?

sour island
#

Yeah, I need a way to get my workflow to occur when PRs are merged

#

I was using something that checks the branch's name as hotfix but this is kind of tedious if the person doesnt know

#

So I figured there might be a way to scan the PR's title or body

#

Then I could edit it as needed

gilded hawk
#

Ah, nope, sorry mate,that's very much out of my knowledge of github actions

sour island
#

That's ok

wet axle
gilded hawk
#

Is it common for zomboid to not sync clothings between clients?

frank elbow
sour island
#

It's for community projects

#

I have the action triggered on schedule for fridays at midnight

#

but I also wanted to make a caveat for hotfixes

#

the action uploads the project to workshop

#

rn what I have is that it fires on push if the branch has hotfix in the name

#

seems to fire multiple times because of this tho

frank elbow
#

Strange. I've only used GH Actions for testing & linting so I'm not too sure

sour island
#

Question, can I have 2 workflows? I see that it's named main.yml

#

I was wondering if that pertains to the branch name

frank elbow
#

Yeah, you should be able to include multiple workflows. I don't remember the naming scheme for the files, but I had one for unit tests & one for making sure the example file runs correctly on one project, for example

#

Just checked and it's just called test.yml in that project, so I think that's just used as the workflow name (if not specified with name:)

sour island
#

ah ok

gilded hawk
#

OMFG I FUCKING DID IT

#

TRANSMOG SYNC IN MP

#

All because of ONE line of code

#

sendClothing(player); instead of sendVisual(player);

thin hornet
sour island
#

Figured it out

hidden jungle
#

how do i delete an inventory item?
and is there a way to detect when an item is being consumed or deleted before it happens?

sour island
#

container:Remove(item) if it's on the player
container:removeItemOnServer(item) if it's not and it's on MP

hidden jungle
#

thanks

frank elbow
hidden jungle
#

i saw that as well, i'm gonna check it out later. i've been doing all my modding in notepad++ so far

frank elbow
#

Hey, if it works it works. I didn't even use Intellisense for years but now I'm a sucker for a nice IDE

thin hornet
#

Here's how quick it is to get started

trim mist
#

Can anyone explain this behavior to me?

Changed a metatable entry to point to a new function. Said function runs fine when called in game, but seems to run the old function and not the new. No errors

trim mist
#

wait a minute

#

is there a set metatable function??

#

give me a minute you may have been my rubber duck haha

bronze yoke
#

what are you trying to change the metatable for? the metatables are a lua thing, so if you change a metatable it won't change what happens when that method is called from java

trim mist
#
**local metatable = getmetatable(zombie.characters.traits["TraitFactory$Trait"].class).__index
local originalGetTraitDescription = metatable.getDescription;
metatable.getDescription = function(self)**
    local descAndTags = originalGetTraitDescription(self);
    local indexOfTagsBegin = strFind(descAndTags, "||");
    if indexOfTagsBegin ~= nil
    then
        local description = strSub(descAndTags, 0, indexOfTagsBegin);
        return description;
    else
        print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
        return descAndTags;
    end
end
**metatable.getTags = function(self)**
    local descAndTags = originalGetTraitDescription(self);
    local indexOfTagsBegin = strFind(descAndTags, "||");
    local lastComma = 1;
    local tagTable = {};

    if indexOfTagsBegin ~= nil
    then
        local tags = strSub(descAndTags, indexOfTagsBegin);

        for i=1, strlen(tags)
        do
            if tags[i] == '' or tags[i] == ','
            then
                table.insert(tagTable, strSub(tags, lastComma, i));
                lastComma = i;
            end
        end
    else
        print("Anthro Traits: No tags attached to description of "..tostring(self:getType()))
        return tagTable;
    end
    return tagTable;
end
**setmetatable(zombie.characters.traits["TraitFactory$Trait"].class, metatable)**

Okay, I'm not facing the same issue anymore. Now i'm getting an error saying "Could not set metatable for object"
I've bolded the important lines above, but include the whole bit where i'm modifying it for context

#

or... put asterisks around them in the lua, not bolded them I guess

trim mist
#

🤔 do you guys think this solution is too hacky? I wanted to bundle this into its own mod so other modders could use the tagging idea but. Maybe it's not best-est practice

frank elbow
#

Have you tried __classmetatables[zombie.characters.traits["TraitFactory$Trait"].class].__index? Setting the metatable wouldn't be the solution anyhow; if it worked it'd just set it to the same metatable

#

I'm not intimately familiar with the exposer code so I'm uncertain as to what metatable would be associated with Class objects, but I've used __classmetatables successfully

frank elbow
bronze yoke
#

you could just use a table, i'm not really sure what the benefit to this description method is

trim mist
uneven fractal
#

So I was trying out ChatGPT and asked it how I could create a list of presets containing diferent values for some options of my mod and it throwed this:

Events.OnFillWorldObjectContextMenu.Add(function(player, context, worldobjects)
  local sandboxOptions = SandboxOptions.getOptions()
    local enumOption = {
      name = "MyEnumOption",
      label = "My Enum Option",
      tooltip = "This is an example enum option with presets",
      type = "enum",
      values = {
        { text = "Presets 1", value = { "Advanced_trajectory.fireoffset" = 10 } },
        { text = "Presets 2", value = { "Advanced_trajectory.fireoffset" = 11 } },
      }
    }

    table.insert(targetPage.options, enumOption)
  end

  SandboxOptions.setOptions(sandboxOptions)
end)```
What's the error here?
lone nest
#

Don't rely on chatGPT too much for Lua code, mostly because ChatGPT isn't as well-trained on LUA as other major programming languages.

Also PZ has its own flavor of Lua, which makes it even more difficult to debug.

On a personal note, I always add a semi-color ; to mark the end of a statement... it's clear the gpt generated code has no closure.

uneven fractal
#

oh thx, i know i can't rely too much on it, just wanted to learn a bit by asking questions. Don't want to bother too much here

#

what i dont understand are the missing symbols

#

they all seems to close

#

well, someone told me that what i wanted to do was impossible so it probably doesn't have solution anyways

mellow frigate
pseudo jetty
#

just wondering if there is any way I can determine if a door is metal

#

I could try and hardcode a value for each door, but I want to keep compatibility

mellow frigate
#

you could parse the recipes to find those allowing to create the door and check if metal is used for its creation

thin hornet
#

You could try to use getThumpSound()

---@param door: IsoDoor
function isMetalDoor(door)
    local thumpSound = door:getThumpSound()
    local isMetal = thumpSound == "ZombieThumpMetal" or thumpSound == "ZombieThumpGarageDoor"
    return isMetal
end
pseudo jetty
#

good ideas guys

#

thank you

pseudo jetty
#

Another question, how do I save data, like number of uses on an item for example

lone nest
#
#

Also, you can use Events.OnPostSave.Add(<function>) to save the data whenever the game saves.

#

Believe me, don't write and save shi* more than you need to while the game is running - it will really ruin your in-game performance.

Disclosure: I did that to debug a few things, so I learned the hard way.

thin hornet
#

You can save into global modData or into player modData.
If you want that data to die with the player character i suggest using the player modData. If that data needs to be networked use the globalModData

#

@pseudo jetty @lone nest

--- Quick example
local playerModData = getPlayer():getModData() -- get player mod data
playerModData.itemUseCount = playerModData.itemUseCount or {} -- set the table to save the item usage count
playerModData.itemUseCount[itemFullType] = (playerModData.itemUseCount[itemFullType] or 0) + 1; -- increment that number

---

--- Function to increment a local player item usage count
function addPlayerItemUsesCount(playerNum, itemFullType, amount)
    local player = getSpecificPlayer(playerNum)
    if player then
        local playerModData = player:getModData()
        playerModData.itemUseCount = playerModData.itemUseCount or {}
        playerModData.itemUseCount[itemFullType] = (playerModData.itemUseCount[itemFullType] or 0) + amount;
    end
end

--- Function to get a local player item usage count
function getPlayerItemUsesCount(playerNum, itemFullType)
    local count = 0
    local player = getSpecificPlayer(playerNum)
    if player then
        local playerModData = player:getModData()
        if playerModData.itemUseCount and playerModData.itemUseCount[itemFullType] then
            count = playerModData.itemUseCount[itemFullType]
        end
    end
    return count
end

player dies, the item usage count dies with it.

frank elbow
novel swallow
#

Does anyone have info on Zombie HP and Damage Calculation from firearms? After probing guns, I see they have a lot of stats. Crits are kinda throwing me too, as whatever mod I have that's logging damage, is saying this thing crits from anywhere between like 1.2 to 8+ damage

#

Even though it's a gun that, by default, only does 0.3 - 0.6 damage

#

Probably doesn't help this is Gunfighter/Brita's too, so who knows what that changed

bronze yoke
#

the damage might depend on the hit body part

#

i saw some code about that, seems like the game does track that even though it's not in your control at all

novel swallow
#

hmm, it looks like the super big hits only happen when they're downed

bronze yoke
novel swallow
#

And now I just did loads of damage without a crit, interesting... It must be body parts.

bronze yoke
#

or some weird brita thing

novel swallow
#

yeah going to try the same tests without brita/gun fighter

#

nope, that's vanilla 😅 So there's min/max damage, crit multiplier, crit chance AND then also body part hits it seems

#

as you can miss a crit yet still over kill in a single shot, with 0 aiming skill and the worse weapon

bronze yoke
#

hmmm, doesn't seem like bodypart is actually used for damage calculations

novel swallow
#

No? Weird. I'm seeing some huge numbers on weak guns without critting

thin hornet
#

PZStudio Update 1.1.0
Effortlessly create and maintain Lua mods for Project Zomboid with this intuitive tool.

Require:
NodeJS LTS: https://nodejs.org/en

Commands:
Install Globally: npm install -g pzstudio
New Project: pzstudio new "My New Mod"
Move into project: cd "My New Mod"
Set output dir: pzstudio outdir "C:\Users\Konijima\Zomboid\Workshop"
Build: pzstudio build
Build & Watch: pzstudio watch

Creates a project in a single command, you then focus on developping your mods.
The build commands generate and structure your output mod into your Workshop directory.
No more manually copying and setup when making a mod.

Github: https://github.com/Konijima/project-zomboid-studio

GitHub

Effortlessly create and maintain Lua mods for Project Zomboid with this intuitive tool. Streamline your mod structuring, simplify the creation process, and dynamically monitor and respond to change...

frank elbow
bronze yoke
#

yeah, that's what i saw when i was writing the event schema

frank elbow
#

Oh, I should've just checked that 😄

bronze yoke
#

i'm not sure if i specified that in my documentation, it might just say something useless like 'fires after saving'

frank elbow
#

It says saving & exiting, which could have the interpretation of firing on either but I think the intended interpretation is more likely to be understood

spice saddle
thin hornet
undone elbow
#

I provite an option to mute a sound in my mod. But there is a kind of a bug in multiplayer. How to mute specific sound for the player AND the same sound from other players? And how to not mute the sound from other players, if the player did not mute this sound?

ancient grail
#

anyone knows what sets windchill moddle

#

or how to disable it ratther

bronze yoke
red tiger
#

Good morning.

lone nest
#

When Events.LoadGridSquare.Add(<function>) is called, How often is said function called?

  1. Does it attempt to load ALL known squares the player has explored? (Which worsens the more the player plays)
  2. Or the entire PZ map squares? (Certainly hope not)
bronze yoke
#

it is called for every square in a chunk when the chunk is loaded

#

chunks are only loaded within a certain range around the player

fast galleon
#

depending on the cell size that means you have up to 13 ?, 26? chunks loading at the same time. Chunks are 10 x 10 x 8 as well, though not everything has a square object and will not call this event.

autumn temple
#

@low yarrow this is a more appropriate place for the topic but ya the API takes the speed counter of the vehicle and replaces the model based on how high the speed counter is

#

which makes it hard to notice that it is only switching between 4 static models

hoary widget
#

Hey what decides if a ground model spawns or not? its just in scripts right?

autumn temple
hoary widget
#

For some reason its not working on my mod. I just see the icon

autumn temple
#

which is more helpful on weapon's and ect, to where the model in your hands wouldnt look that good when placed on the ground

hoary widget
#

I know its not the model, I swapped it with the model of another mod to see

lone nest
autumn temple
#

then the games probably not detecting your models and just defaults to the icon

#

I think

lone nest
#

for example, only load the the specified squares given the square input?

autumn temple
#

im having a similar issue too where the game isnt detecting my ground model and idk why

bronze yoke
#

do you mean forcing squares to load or only calling your event on certain squares loading? well the answer to both is no anyway

lone nest
#

Damn, alright, hm. here I was hoping to feed a square parameter and remove the event right away to speed things up

bronze yoke
#

there are some apis that have a single loadgridsquare handler that then call functions you add to them for certain squares but there's no direct way of limiting loadgridsquare calls

lone nest
#

Oh? that might work for me on a single load square

bronze yoke
#

i haven't used any of them so i can't direct you to them unfortunately

#

they should be a decent performance save though

autumn temple
lone nest
hoary widget
#

what did you change in your code?

fast galleon
#

What are the other options?

bronze yoke
#

i was referring to things the community has made, i don't think the game has anything like that

#

b42 is promised to have a loadchunk or something so *eventually*...

autumn temple
#

the model changed, but I tried to change it again and now those changes arent applying

#

I have the ground pooling from the correct model, but any changes I do with the actual model itself doesnt appear ingame.

#

not even the scale change applied

#

it use to be 0.13, i changed it to 0.012

#

and it still shows as 0.13

hoary widget
#

I

#

what

autumn temple
#

I have no clue why that stuff just isnt working

#

restarted my game multiple times and none of the changes I do even work

hoary widget
#

Thats where I'm at right now

#

I can make changes to other stuff but ground is unaffected no matter what I do

autumn temple
#

even though if you are debug mode you shouldnt have to even make a new save to see changes, it happens in real time

hoary widget
#

Yeah! Thats how I was able to test defense changes and model names (when I typed it in wrong)

autumn temple
#

worked fine for other weapon's, but when i try to replicate exactly what I did, it just doesnt work

hoary widget
#

Its not a pathing issue right?

#

Or maybe something that was missed in the script?

autumn temple
#

shouldnt be, this is my model for a rifle that let me change the ground model position

#

and this is the ground for a axe that wont let me

hoary widget
#

Yeah those are the same...

autumn temple
#

ya exactly

hoary widget
#

Mine are like that too..its not the model

#

PZ why do you not work lol

autumn temple
#

these are the exact same too

#

so im stumpted on why it isnt working

hoary widget
#

SameZ!

#
module Base
{
    item Jacket_01-Black
    {
        Type = Clothing,
        DisplayName = KP Jacket (Black),
        ClothingItem = Jacket_01-Black,
        BodyLocation = Jacket,
        BloodLocation = Jacket,
        Icon = Jacket_01-Black_Icon,
        RunSpeedModifier = 0.98,
        CombatSpeedModifier = 0.97,
        ScratchDefense = 60,
        BiteDefense = 30,
        Insulation = 0.4,
        WindResistance = 0.8,
        WaterResistance = 0.6,
        Weight = 2,
        FabricType = Cotton,
        WorldStaticModel = Samurai_Jacket_ground,
    }


}
#

This works

#

but this doesn't

#
module Base
{

 item Jacket_samurai_classic
 {
        Type = Clothing,
        DisplayName = Samurai Jacket classic,
        ClothingItem = Jacket_samurai_classic,
        BodyLocation = Jacket,
        BloodLocation = Jacket,
        Icon = SteamGuideJacket,
        RunSpeedModifier = 0.98,
        CombatSpeedModifier = 0.97,
        ScratchDefense = 60,
        BiteDefense = 30,
        Insulation = 0.4,
        WindResistance = 0.8,
        WaterResistance = 0.6,
        Weight = 2,
        FabricType = Cotton,
        WorldStaticModel = Samurai_Jacket_ground,
    }
}
autumn temple
#

is anyone please able to assist us?

bronze yoke
#

i'm as confused as you are

autumn temple
flat bluff
#

Sorry guys, quick question. What is exactly a 'timed action'? How would you define it?

frank elbow
#

An action that can be inserted into a character's action queue that may either take a certain amount of time (thus, timed) or be indefinite

hoary widget
flat bluff
#

Thanks. So like, opening a can would be a timed action, and it takes defined amount of time (not in seconds afaik). Does anyone know what exactly is the metric for this number? If it is not seconds, what is it(?)

frank elbow
#

I don't know whether there's a metric that it uses; it's based on ingame time which can vary

hoary widget
#

Actually wait whats wrong with the formatting?

autumn temple
#

I tried to move my model into the static folder itself instead of a sub folder in static, and it still doesnt work

bronze yoke
#

the spacing is really inconsistent, but the parser should trim all the spacing out anyway

bronze yoke
#

i'd recommend changing that for readability's sake but it shouldn't be causing your issues

autumn temple
#

idk i remember one time it caused issues for me

frank elbow
bronze yoke
#

it's really odd

flat bluff
bronze yoke
#

the one place i can find the timer for timed actions being used implies that 1 time is 1.25 seconds, but a simple test will show that's clearly not correct

frank elbow
#

I remembered seeing that it used a multiplier in GameTime but I didn't have the time to dig in and get an exact answer

#

And I'm currently not at my home computer to do so either

bronze yoke
#

yeah, that multiplier should be a delta that adds up to 0.8 a second

#

but timed action time is clearly much faster than real time, not slower

fast galleon
#

the read action can scale it to real in-game time

#

if I haven't made any errors it's like this

o.maxTime = minutes * 2 * getGameTime():getMinutesPerDay()

* sorry, that's in-game time that I was targeting

bronze yoke
#

yeah, offhandedly that seems to add up

hoary widget
autumn temple
#

mood

#

sometimes formatting gets you hard

hoary widget
#

I want to die

#

Ive been trying to fix this for 3 days

autumn temple
#

just gotta figure out why mine doesnt work

autumn temple
red tiger
#

You use vscode to do zedscript yet you don't use my extension..

bronze yoke
#

i had no idea the parser actually required it, i thought i'd seen the code behind that, i was just doing it for readability

red tiger
autumn temple
#

just use notepad like a chad

hoary widget
red tiger
autumn temple
#

my model isnt being read at all and i have no clue why

hoary widget
#

just as a double check I mean

autumn temple
#

tried to make the model one of my rifles and it didnt work

bronze yoke
hoary widget
autumn temple
#

I tried with other weapons and it didnt work

hoary widget
#

oh

autumn temple
#

thats the thing

#

that one isnt

#

all my rifles arent bugged

#

but the melee weapon's are

hoary widget
#

Okays thats really weird..

lone nest
#

Can someone please link me documentations on how to create buttons and panels?

#

I see ISPanel, ISButton, etc... but there are no documentation on what events/functions are available

tawdry solar
#

fml

#

NONE

#

of my 2 recent mods work

#

not mods

#

items

#

could it be that some of my files are fbx and others are .x

neon bronze
lone nest
neon bronze
#

But both IsButton and ISPanel have all the necessary calls needed to make a custom ui

#

There is also ISScrollinglistbox to have a scrollable window with items in it

lone nest
delicate widget
neon bronze
lone nest
#

nevermind, i'm an idiot

#

found out the location of the base game ISUI folder

woeful relic
#

ISItemsListViewer (found in AdminPanel Folder) uses ISPanel, ISComboBox, ISTabPanel and ISButton for example.

tawdry solar
#

and the wsm being the normal one you made in bledner

hoary widget
red tiger
#

I need a drink.

tawdry solar
#

i havnt done clothing

tawdry solar
red tiger
#

It's Friday.

tawdry solar
#

oh

#

makes sense

mellow frigate
#

Hi, is there a way to force the reload of a texture ? (when I do getTexture it works on a cache memory while I changed the pic source)

#

this would avoid to restart the game each time I do minor changes

bronze yoke
mellow frigate
bronze yoke
#

it works for me

mellow frigate
#

ok, thanx:)

trim mist
#

So in the vein of our convo the other day I wanted to add trait tags in a different way, so I made this:

#
TraitTags = {}

local function sanitizeTags(tagString)
    --remove all spaces
    local workString = tagString:gsub("%s+", "");
    --remove control characters
    workString = workString:gsub("%c", "");
    --remove hexadecimals
    workString = workString:gsub("%x", "");
    --remove.... zero...?
    workString = workString:gsub("%z", "");
    workString = workString:gsub(",", " ");
    --remove all punctuation and symbols
    workString = workString:gsub("%p", "");
    --replace spaces with commas
    workString = workString:gsub(" ", ",");
    return workString;
end

--Uses alphanumberic symbols and commas only.
function TraitTags:add(traitName, tags)
    local sanitizedTags = sanitizeTags(tags);
    local tagTable = {};
    local prevComma = 0;
    local currChar = '';
    if TraitFactory:getTrait(traitName)
    then
        if string.len(sanitizedTags) > 0
        then
            print("Trait Tags: inserting table entry "..traitName.." to TraitTags.");
            table.insert(TraitTags, traitName);
            print("Trait Tags: adding tags "..sanitizedTags.." to "..traitName" entry.");
            for i = 1, string.len(sanitizedTags) do
                currChar = sanitizedTags:sub(i,i)
                if currChar == ','
                then
                    table.insert(tagTable, sanitizedTags:sub(prevComma + 1, i));
                    prevComma = i;
                elseif i >= string.len(sanitizedTags)
                then
                    table.insert(tagTable, sanitizedTags:sub(prevComma + 1, i));
                end
            end
            table.insert(traitName, tagTable);
        else
            print("Trait Tags: No tags detected for "..traitName..", skipping...");
        end
    else
        print("Trait Tags: Cannot find trait "..traitName..", skipping...");
    end
end

function TraitTags:remove(traitName)
    if TraitTags[traitName]
    then
        table.remove(TraitTags, traitName)
    else
        print("Trait Tags: No entry found for "..traitName..", cannot remove. Skipping...")    
    end
end

function TraitTags:getTagTable(traitName)
    if TraitTags[traitName]
    then
        return TraitTags[traitName]
    else
        print("Trait Tags: No entry found for "..traitName..", cannot get tag table. Skipping...")    
    end
end

function TraitTags:toString()
    local returnString = "";

    for trait, tagTable in ipairs(TraitTags) 
    do
        returnString = returnString + trait + ": "
        for _, tag in ipairs(tagTable)
        do
            returnString = returnString + tag + ", "
        end
        returnString = returnString:sub(1, string.len(returnString) - 2);
        returnString = returnString + "; "
    end

    return returnString;
end

function TraitTags:tagTableToString(traitName)
    local returnString = "";

    if TraitTags[traitName]
    then
        for _, tag in ipairs(TraitTags[traitName])
        do
            returnString = returnString + tag + ", "
        end
        returnString = returnString:sub(1, string.len(returnString) - 2);
        return returnString;
    else
        print("Trait Tags: No entry found for "..traitName..", cannot stringify tag table. Skipping...")    
    end
end

#

I wanna set this up as a dependency for my AnthroTraits mod--how do I do that? I don't see anything about that in the chat history or on the wiki

#

at least, that I can see. I can't test this until I figure that out hahaha

#

Also if any of you sees something that's glaringly wrong your input would be appreciated

frank elbow
#

You can add a require= line to your mod.info to specify mod IDs to require. I'm not sure about the equivalent to specify that on the Steam workshop

#

Ah. "Add/Remove Required Items" on the workshop page for that

#

As for code review, a few things:

  • I would argue against making your module global. You can return it and expect implementers to require it
  • Some of the gsub calls in sanitizeTags can be consolidated; workString = workString:gsub("[%c%x%z]", ""). I wonder, though: why are you removing hexadecimal characters, anyway? That will get rid of 0-9 and a-f
    • Actually, after a second look... if your goal is just to get rid of all characters other than alphanumeric characters and commas, you can use a negated character set instead to replace all of the logic in that function. i.e., tagString:gsub('[^%w,]', '')
  • This is not a review comment, but a clarification: %z is for the null character, '\0'
  • In add, you could negate your conditions and use early returns to decrease the nesting level. That is:
if #sanitizedTags == 0 then
   -- print and return
end

-- continue

(this pattern is possible for all if statements in that function except the one in the loop)

  • You can use string.split for your comma splitting logic in add
  • table.remove in remove can be replaced with TraitTags[traitName] = nil, but no problem keeping it as-is
  • You're using + in toString; I think you meant ... Also, it would be best to add the elements to a table then use table.concat, rather than concatenating repeatedly. This will create unnecessary intermediate strings. Not a big deal, just an easy improvement
  • tagTableToString: see previous note
storm flame
#

Hey, how do I get a zombie to turn towards a specific square, or position?

frank elbow
#

IsoGameCharacter has a faceLocation method which may be what you're looking for, but I don't know how well it interacts with the AI (that is, the AI may make it stop trying to face that location)

tawdry solar
#

i need help

frank elbow
# tawdry solar i need help

Rather than simply declaring that you need help, it's nice to describe what exactly you need help with 😄 We can skip the "what do you need help with?" and get straight to trying to help

tawdry solar
#

but my items wont apear ingame

#

its been like this for a month

#

its actually 2 items

#

but i may know the issue

frank elbow
#

When you say they don't appear ingame, do you mean they just won't spawn, or that they don't show up in the item spawner in debug mode?

tawdry solar
#

i just want to confirm i cna use .fbx and .x