#mod_development

1 messages ยท Page 43 of 1

thick karma
#

And then you add your mod to a server config and then you launch the server

#

and then this is how you die.

tawdry solar
#

how do i put it in mods folder

#

i took it out

#

bc i deleted all my mods

#

from files

bronze yoke
#

it'll load the mods folder in your workshop folder structure

thick karma
#

You can load it from Workshop

#

It's fine

tawdry solar
#

i dont have mod IN the folders

thick karma
#

Just put the zip I sent you in Zomboid/Workshop

tawdry solar
#

oh ight

thick karma
#

With all your files in the right subdirectories

#

it'll appear in the game again after that

tawdry solar
#

here??

thick karma
#

And you can test it

#

Exactly

#

nO

#

Wait

#

Shit

#

Zomboid / Workshop is not the same as ProjectZomboid / Workshop

bronze yoke
#

does zomboid even load the mods in ProjectZomboid/mods either?

#

i remember tripping up on that when i very first started

blissful salmon
#

I'm looking for some guideance to get my simple model to work. Currently I have an fbx (ClubV1.fbx) in the models_X folder. I created an item (copy of the nightstick) and tried to use my fbx. But it's not showing something in the hand... What steps do I have to do?

    item ClubV1
    {
        DisplayCategory = Weapon,
        MaxRange    =    1.2,
        WeaponSprite    =    ClubV1,
        MinAngle    =    0.72,
        Type    =    Weapon,
        MinimumSwingTime    =    2,
        KnockBackOnNoDeath    =    FALSE,
        SwingAmountBeforeImpact    =    0.02,
        Categories    =    SmallBlunt,
        ConditionLowerChanceOneIn    =    20,
        Weight    =    1.5,
        SplatNumber    =    1,
        PushBackMod    =    0.3,
        SubCategory    =    Swinging,
        ConditionMax    =    15,
        MaxHitCount    =    2,
        DoorDamage    =    1,
        SwingAnim    =    Bat,
        DisplayName    =    Club V1,
        MinRange    =    0.61,
        SwingTime    =    2,
        KnockdownMod    =    0,
        SplatBloodOnNoDeath    =    FALSE,
        Icon    =    RawBat,
        RunAnim    =    Run_Weapon2,
        IdleAnim    =    Idle_Weapon2,
        BreakSound  =   NightstickBreak,
        DoorHitSound = NightstickHit,
        HitSound = NightstickHit,
        HitFloorSound = NightstickHit,
        SwingSound = NightstickSwing,
        TreeDamage  =   0,
        CriticalChance    =    25,
        CritDmgMultiplier = 2,
        MinDamage    =    0.6,
        MaxDamage    =    1.1,
        BaseSpeed = 1,
        WeaponLength = 0.45,
        AttachmentType = Nightstick,
    }

I renamed the fbx file for the folder (ClubV1.fbx).

tawdry solar
bronze yoke
#

yeah!

tawdry solar
#

tysm

thick karma
#

Yeah mods in either Workshop or mods (the old place you were testing) will show up as loadable in game

tawdry solar
#

this a good poster?

#

i used yours for the size

fast galleon
#

Stella kratao maxairi

bronze yoke
#

yeah it has to be 256x256

#

there's also a file size restriction but you're unlikely to run into that

tawdry solar
#

ight

blissful salmon
#

@hearty dew Because your my current Java/Lua lowlevel god. Do you know if there's a potential solution for this? The java code has 3 overloads and I would like to call the one with IsoObject (but object is nil).

tardy wren
bronze yoke
#

LOL is that a problem in rimworld??

tawdry solar
#

im gonna buy rw soon

#

looks fun

hearty dew
# blissful salmon <@479489390121582612> Because your my current Java/Lua lowlevel god. Do you know...
l.inspect(IsoObject)
----------  table  ----------
table 0x1899911670 {
    [class] => (userdata) class zombie.iso.IsoObject <
               .          <METATABLE> => table 0x789091424 {
               .                         .   [__index] => table 0x682936769  ** PRUNED. Max depth reached **
               .                         }
               >
    [factoryFromFileInput] => function 0x119961287
    [FindExternalWaterSource] => function 0x319974980
    [FindWaterSourceOnSquare] => function 0x1463048914
    [getNew] => function 0x1413892139
    [factoryGetClassID] => function 0x1617071146
    [getLastRendered] => function 0x1619177004
    [setLastRendered] => function 0x362125860
    [getFactoryVehicle] => function 0x1937018797
    [getLastRenderedRendered] => function 0x117657141
    [setLastRenderedRendered] => function 0x1912955703
    [setDefaultCondition] => function 0x1274581993
    [factoryFromFileInput_OLD] => function 0x480666844
    [factoryClassFromFileInput] => function 0x21619611
    [OBF_Highlighted] => (userdata) 1
    [OBF_HighlightRenderOnce] => (userdata) 2
    [OBF_Blink] => (userdata) 4
    [MAX_WALL_SPLATS] => (userdata) 32 <
                         .          <METATABLE> => table 0x431509976 {
                         .                         .   [__index] => table 0x1658513944  ** PRUNED. Max depth reached **
                         .                         }
                         >
    [rmod] => (userdata) 0.0 <
              .          <METATABLE> => table 0x1477190750 {
              .                         .   [__index] => table 0x1466209133  ** PRUNED. Max depth reached **
              .                         }
              >
    [gmod] => (userdata) 0.0 <
              .          <METATABLE> => table 0x1477190750  ** PRUNED. Cycle/duplicate detected **
              >
    [bmod] => (userdata) 0.0 <
              .          <METATABLE> => table 0x1477190750  ** PRUNED. Cycle/duplicate detected **
              >
    [LowLightingQualityHack] => false
    [new] => function 0x2018221529
}

Try calling the new static method on IsoObject (You'll need to check what the parameter types are in java).

local dummyIsoObject = IsoObject.new(...)
tawdry solar
#

ty for yalls help

thick karma
#

Everyone can easily read the name

tawdry solar
#

i need a few sc shts

#

gonna do that

#

then upload it

#

or work my bugs

hearty dew
#

@blissful salmon Before you do that, actually, what is the parameter used for? Maybe passing it an IsoPlayer or IsoZombie would be appropriate (IsoObject is a superclass for them, iirc)

tawdry solar
#

how do i edit where it spawns

blissful salmon
tardy wren
tawdry solar
#

couldnt be arsed

#

its all the same

#

gonna change icons

#

well then

blissful salmon
hearty dew
#

So you're trying to pass null to the java method? If so, I misunderstood your initial question

blissful salmon
hearty dew
#

Trying to call playSoundImpl with null as the 2nd arg?

blissful salmon
#

yes.. but it has 3 overloads (IsoObject, IsoGridSquare, third is irelevant)

tawdry solar
#

is that a good pic for the workshop

blissful salmon
hearty dew
#

I think that might not be possible in kahlua. I assumed kahlua just looksup the java.lang.reflect.Methods for the method name and matches the argument types.. Let me see how this is implemented in kahlua. Hopefully it has some way to do this

blissful salmon
hearty dew
#

For each invoker ,it does prepcareCall and then checks if the args are valid in that last link

#

Here is where it adds multiple java invokers. It just adds additional ones if one with the same method name already exists

blissful salmon
hearty dew
#

What you pass on the lua side is retrieved in prepareCall (looks like by callFrame.get())

blissful salmon
hearty dew
#

What's the exception text you get when you try to pass nil?

blissful salmon
#

Give me a second. I provoke the error.

hearty dew
#

and stack frame too, actually

blissful salmon
#

I'me confused right now. I call the following:

local player = getPlayer()
    if key == Keyboard.KEY_NUMPAD8 then
    local square = player:getSquare()
    local soundEmitter = getWorld():getFreeEmitter(player:getX(), player:getY(), 0)
    --getWorld():takeOwnershipOfEmitter(soundEmitter)
    local soundId = soundEmitter:playSoundImpl("ZombieDemonScream", nil)
    soundEmitter:setVolume(soundId, 0.55)
    end

but now it plays the sound. Don't know why this works now and which method it does choose...
To be clear I call this test with the Event: Events.OnKeyPressed

hearty dew
#
l.inspectJava(getWorld():getFreeEmitter(getPlayer():getX(), getPlayer():getY(), 0), "playSoundImpl")
==========  fmod.fmod.FMODSoundEmitter@f470030  ==========
----------  grep: playSoundImpl  ----------
----------  Instance Methods  ----------
Return Type Method Name  Parameters
long        playSoundImpl(String, boolean, IsoObject)
long        playSoundImpl(String, IsoGridSquare)
long        playSoundImpl(String, IsoObject)

#

I suspect it selects one of those last two overrides

blissful salmon
hearty dew
#

    public long playSoundImpl(String string, IsoGridSquare isoGridSquare) {
        this.x = (float)isoGridSquare.x + 0.5f;
        this.y = (float)isoGridSquare.y + 0.5f;
        this.z = (float)isoGridSquare.z + 0.5f;
        return this.playSoundImpl(string, (IsoObject)null);
    }

Yea, I see what you mean. If it were this override, it would throw a null pointer exception.

blissful salmon
#

exactly... but I don't know why it works now...

hearty dew
#

    public long playSoundImpl(String string, IsoObject isoObject) {
        GameSound gameSound = GameSounds.getSound((String)string);
        if (gameSound == null) {
            return 0L;
        }
        GameSoundClip gameSoundClip = gameSound.getRandomClip();
        return this.playClip(gameSoundClip, isoObject);
    }

This one calls playClip, which is public. Maybe you could call playClip directly to not rely on kahlua not selecting the other override that would cause an exception ๐Ÿ˜…

#

GameSound and GameSoundClip are exposed, so that should be doable

blissful salmon
#

Maybe I made an error when I tested it before. But I'd rather use the square if I can't say for sure what is called...

blissful salmon
hearty dew
blissful salmon
#

I'll test...

hearty dew
#

Is this playing the audio clip with stereo directionality for you?

blissful salmon
#

But I first have to see how I got the GameSound

blissful salmon
#

The emitter plays it from the coordiantes given...

hearty dew
blissful salmon
hearty dew
#

I don't even have stereo, so I didn't know there was directionality in the audio ๐Ÿ˜…

blissful salmon
#

Think this works. I'll do further testings in multiplayer when I have time ๐Ÿ™‚ But this all seems promising...

safe silo
#

I want the player to say a message. How do I get the local player? AFAIK I can do Player:say("Hello World") but not sure how to get the object

blissful salmon
#

Does anybody can (or is at least willing) to help me with this? A friend made this simple club for me. But I'm just a coder and don't get what exactly to do here.

hearty dew
blissful salmon
safe silo
hearty dew
narrow crown
#

is there a general list of weapon stats, preferably with brita's weapons?

hearty dew
#

pzwiki has stats for vanilla weapons

blissful salmon
fierce cipher
#

Im brand new to modding pz

tawdry solar
#

ight

fierce cipher
#

All Ive done is look at code and try to pick out patterns

#

Ive tweaked stats at most

tawdry solar
#

i have not messed with that stuff

#

idk

#

@bronze yoke was looking at most popular 6 months and i found this aha

fierce cipher
#

Yea Ive wanted to make a portable wood stove mod for a while

bronze yoke
#

hell yeah

thick karma
#

@weak sierra Updated Dawn of the Zed... you can hide the dag'on cursor now. And doing so is optional (in Mod Settings). Thanks again, @bronze yoke

Note that you will have to redo your Mod Options if you had UI default off. This is a result of redoing my Mod Options set-up in a hopefully better way that required keys to change. It is not a bug.

tawdry solar
#

how do i make short blade mods

#

i wanna make a glass shard

fierce cipher
#

How do you make new items in game?

drifting ore
#

taco

#

I know you're involved in something right now

#

but I have a request

shell tartan
#

whats the mod that gives all car animations

#

nvm got it

dusk sonnet
#

In the following table snippet, what is the correct syntax to reference the procList fields and properties?

bookstore = {
        shelves = {
            procedural = true,
            procList = {
                {name="BookstoreBooks", min=6, max=99, weightChance=100},
                {name="BookstoreMisc", min=0, max=99, weightChance=20}

bookstore.shelves.procList[1].name?
bookstore[shelves][procList][1].name?
Something else?

hearty dew
#
bookstore.shelves.procList[1].name

bookstore["shelves"]["procList"][1]["name"]

Either of those work, but it assumes there is at least 1 value in procList. If there isn't, the value returned by doing [1] will be nil, causing the following .name or ["name"] to cause an error

#

If you can't guarantee procList has at least one element in it, you'll want to do something different to avoid the error. What are you trying to do to those procList elements? Add one, delete one, find one and modify it's contents?

dusk sonnet
#

I'm actually trying to parse Distributions.lua in a C# program. I can enumerate a table down to procList, and at that point I'm trying to get any/all fields and properties within

#

But honestly this is kind of a headache

hearty dew
#

Probably easiest to encode to json or similar and then decode in c#

dusk sonnet
#

That's a good suggestion, and one that I've come across once or twice so far in my Googling

hearty dew
dusk sonnet
#

Did you just have that lying around or did you use a tool to convert it?

hearty dew
dusk sonnet
#

Thanks. I'm working with a library that allows me to work with Lua, but I might check that out if I get stumped. Just figured out how to execute a function to get the length of the procList table

shell tartan
#

so, previously modded this game fine, but now in me and my friend's personal server, it just won't mod at all

#

i've enabled it both in the menu and the game's server settings but nada

#

when i press esc and click 'mods' in the bottom right, the section is blank

#

i also can't access map mod priority order

shell tartan
#

ah wrong place mb

astral dune
#

finally learning what the heck __index and metatables are today. Thank you roblox forums

hearty dew
astral dune
#

this guy described things in a way a 12 year old could understand, which is good because thats about as much mental capacity as I have left at the end of a work day

hearty dew
#

actually, the 5.4 lua manual is good at describing metatables. The 5.1 isn't :p

#

The 5.1 manual just gives you code lol

astral dune
#

what version is pz anyway?

hearty dew
#

5.1, but __index is the same between 5.1 and 5.4 as far as I know

#

5.1*

#

*: kahlua's 5.1

astral dune
#

right, an incomplete 5.1 from what I'm told

hearty dew
#

Mm, has some missing apis and some bugs here and there

ancient grail
#

Goodday yal

hearty dew
#

So if there is an api to wait for a function to complete and you can provide it args and also specify an optional timeout, what would be a good interface?

function awaitTask(func, args, timeout)
-- where args = {arg1, arg2, ...}
function awaitTask(timeout, func, ...)
function awaitTask(func, ...)
-- where args go after func, and the optional timeout is the first param?

Something else?

astral dune
#

I like passing an args table because then you don't need to get the order of the inputs correct tbh

#

if you put in a timeout, it should probably be its own argument, at the end where it can easily be omitted

#

so the first one

hearty dew
#

Oh, you'd still need to worry about the order here. The above would be used like:```lua
function myFunc(arg1, arg2)
return arg1 + arg2
end

```lua
function myTask()
  local result = awaitTask(myFunc, {5, 10})
end
astral dune
#

actually I guess you would still need the order of the inputs correct, because the function isn't going to know what order to unpack them

#

ya

hearty dew
#

yea

astral dune
#

still the first one though, with the caveat that timeout should just be given some default value if not supplied

#

curious though, does ... pass by reference like an args table does?

hearty dew
#

each of the params are passed individually as far as I know (numbers would be passed by value, for example, and table by reference)

#

same as normal

astral dune
#

I wonder if that's better or worse

thick karma
#

No chance another else can get MoodleUI's setVisible(false) to hide the Moodle UI is there? I could not figure it out earlier, and my workaround is giving me a headache too, lol, enough so that it would be ideal to avoid the workaround entirely...

#

I tried so many ways... MoodlesUI.getInstance():setVisible(false), MoodlesUI.getInstance()[0]:setVisible(false), MoodlesUI.getInstance():setVisible(false), UIManager.getMoodleUI(0.0):setVisible (and 1.0), all kinds of stuff failed me ๐Ÿ˜ฆ

hearty dew
astral dune
#

garbage collection, performance

#

generally I like to pass as much by reference as possible, as long as the data can get closured in some way to prevent any weird behaviour

hearty dew
#

Oh, not sure. I double it's an issue with a couple hundred function calls. Might be something to measure once you get into 10k function calls

astral dune
#

I have a different brain teaser for you, if you're interested

hearty dew
#

Well, passing some things (e.g. int) by value is often faster than passing by reference

#

or can be depending on a number of variables (relationship in memory)

astral dune
#

I'll take the eye emote as a maybe'

hearty dew
#

Let's hear it lol

astral dune
#

let me see if I can get it as plain as possible

#

the mod I'm working on is to flesh out the engine and engine mechanics

#

as such, I've appended a list of parts to the engine as moddata. This includes everything from sparkplugs, connecting rods, lifters, etc etc

#

damage to the engine, as well as the engine's stats, and various new effects from things like low oil or poor cam timings have been implemented

hearty dew
thick karma
#

maybe it was MoodlesUI

#

It was MoodlesUI

#

Sorry @hearty dew

hearty dew
#

gotcha

thick karma
#

I tried a lot of things for about an hour awhile ago, couldn't find the right thing. I know it's exposed. I figure I'm using it wrong but no idea how it wants to be used.

hearty dew
#

Hmm, not sure. There is a render method on it. I imagine you could patch that to not render

astral dune
# astral dune damage to the engine, as well as the engine's stats, and various new effects fro...

However, there is one last thing missing: I want the parts to only be visible and accessible, if it makes sense. Player's shouldn't be able to check the condition of the piston, for example, without removing the cylinder head. The piston shouldn't be removable without at least pulling off the oil pan and maybe crankshaft. Modeling these relationships in an extendable and logical way has been eluding me

hearty dew
hearty dew
astral dune
#

The vehicle has actual Part objects, but my parts are merely small tables in the moddata. The intention is to generate InventoryItems as needed when those parts are removed, but not actually utilize the vanilla parts system

hearty dew
astral dune
#

currently the only Part in the engine is the engine itself, which does nothing aside from take damage, in vanilla

thick karma
astral dune
#

I initially thought of having Attachment points on each part, and using keys relate them to the parts that are attached there... but thats clunky and wasteful, there has to be a good way to do this

thick karma
#

UIManager.setVisibleAllUI(false) will hide it @hearty dew ... Doesn't help me to know that, but you are, you know, you.

hearty dew
astral dune
#

I've added an "Engine Mechanics" window, almost a carbon copy of the Vehicle Mechanics window, but for the engine alone. Same as the Vehicle Mechanics window, all the parts show up in a list on the right. I plan on greying out any part that is currently not "visible", so that the player would need to pull parts out to get access to it

hearty dew
#

Hmm, tricky part for me is understanding the nature of all the types of relationships there are between the parts to then come up with a good model

astral dune
#

Similar to the vanilla mechanic forcing you to take a tire off before you can remove the brakes, but with an added visibility element

hearty dew
#

Is this something you could model as a graph?

#

nodes with directed edges

astral dune
#

I thought of modeling it as a tree, with the leaves being the external visible parts, but that's not going to work

hearty dew
#

Something like this where a node (part) is only visible when all nodes with edges pointing to it are visible

astral dune
#

some parts can be accessed in different ways from different directions. Again leaning on the piston example, you can SEE it from above OR below by removing different parts. Also, it can only be removed from below, so I have to decide if I want visibility and accessibility to be different or just say "if you can't get a tool on it, you can't 'see' it"

hearty dew
astral dune
#

you're probably right, just trying to mull over how that would actually work

hearty dew
#

visibility and accessibility
ah, that complicates it heh

astral dune
#

Spark plugs are a good example of that. Immediately accessible, but only "visible" if you pull them out, or take the head off

hearty dew
#

Might have two graphs based on the same set of vertices, one for visibility and one for accessibility

astral dune
#

engines are similar enough that these graphs could potentially be generalized into functions rather than imprinted on the parts themselves, but I'm not sure

hearty dew
#

Did they have rotary car engines in 1993? ๐Ÿ˜…

astral dune
#

I believe the wankel existed, ya... its in my engine type enum, just in case, lol

#

seems like I will have to separate accessibility and visibility, something like this:

           | Accessible | Not Accessible
Visible     |  "Exposed" | "Visible"
Not Visible | "Obscured" | "Hidden"
hearty dew
#

Thinking something like this.. So if you want to check whether the cover gasket can be removed, you'd check all outgoing edges to see whether they have been removed (the head cover, in this example)

#

and do that recursively

hearty dew
# hearty dew

Ignore the cylinder head -> gasket arrow. That doesn't really make sense

astral dune
#

Seems simple, so my brain is rejecting it

hearty dew
#

heh

#

That's my job. Try to simply things ๐Ÿ˜…

astral dune
#

I think it will work, just have to be smart about it

young edge
#

@candid light If you remember the spawntweaks thing I talked about eons ago, it's nearing a workable state. If you're fine downloading most of the common/less common vehicle mods (soft requirement), I can send you the link for testing ๐Ÿค”
It also has support for your zones mod, too.

hearty dew
#

engineBlock = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
headGasket = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
cylinderHead = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
cylinderHeadCover = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
cylinderHeadCoverGasket = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
exhaustManifold = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
exhaustManifoldGasket = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
intakeManifold = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}
intakeManifoldGasket = {
    isInstalled = true,
    partsBlockingVisibility = {},
    partsBlockingAccessibility = {},
}

table.insert(engineBlock.partsBlockingAccessibility, cylinderHead)
table.insert(headGasket.partsBlockingAccessibility, cylinderHead)
table.insert(cylinderHead.partsBlockingAccessibility, exhaustManifold)
table.insert(cylinderHead.partsBlockingAccessibility, intakeManifold)
table.insert(cylinderHead.partsBlockingAccessibility, cylinderHeadCover)
table.insert(cylinderHeadCoverGasket.partsBlockingAccessibility, cylinderHead)
table.insert(exhaustManifoldGasket.partsBlockingAccessibility, exhaustManifold)
table.insert(intakeManifoldGasket.partsBlockingAccessibility, intakeManifold)

function isAccessible(part)
    for _, p in ipairs(part.partsBlockingAccessibility) do
        if p.isInstalled then
            return false
        end
    end
    return true
end
#
table 0x713881734 {
    [isInstalled] => true
    [partsBlockingVisibility] => table 0x1641781397 {
                                 }
    [partsBlockingAccessibility] => table 0x2107390646 {
                                    .   [1] => table 0x1511959155 {
                                    .          .   [isInstalled] => true
                                    .          .   [partsBlockingVisibility] => table 0x387658110 {
                                    .          .                                }
                                    .          .   [partsBlockingAccessibility] => table 0x716770360 {
                                    .          .                                   .   [1] => table 0x921487955 {
                                    .          .                                   .          .   [isInstalled] => true
                                    .          .                                   .          .   [partsBlockingVisibility] => table 0x428782543 {
                                    .          .                                   .          .                                }
                                    .          .                                   .          .   [partsBlockingAccessibility] => table 0x1464918337 {
                                    .          .                                   .          .                                   }
                                    .          .                                   .          }
                                    .          .                                   .   [2] => table 0x896204639 {
                                    .          .                                   .          .   [isInstalled] => true
                                    .          .                                   .          .   [partsBlockingVisibility] => table 0x1703151091 {
                                    .          .                                   .          .                                }
                                    .          .                                   .          .   [partsBlockingAccessibility] => table 0x167297607 {
                                    .          .                                   .          .                                   }
                                    .          .                                   .          }
                                    .          .                                   .   [3] => table 0x1500668112 {
                                    .          .                                   .          .   [isInstalled] => true
                                    .          .                                   .          .   [partsBlockingVisibility] => table 0x989920422 {
                                    .          .                                   .          .                                }
                                    .          .                                   .          .   [partsBlockingAccessibility] => table 0x2121194920 {
                                    .          .                                   .          .                                   }
                                    .          .                                   .          }
                                    .          .                                   }
                                    .          }
                                    }
}
hearty dew
young edge
hearty dew
astral dune
# hearty dew Something like that might work

I was thinking maybe something like this

AccessGraph = {
    [Part.FanBelt] = {},
    [Part.Piston] = {{Part.OilPan, Part.CylinderHead},{Part.OilPan, Part.CrankShaft}},
    [Part.CrankShaft] = {Part.MainBearing},
    [Part.MainBearing] = {Part.OilPan},
    [Part.CylinderHead] = {Part.ExhaustManifold, Part.IntakeManifold, Part.CylinderHeadCover},
    [Part.CylinderHeadCover] = {},
    [Part.Radiator] = {},
    [Part.WaterPump] = {},
    [Part.HeadGasket] = {Part.CylinderHead},
    [Part.SparkPlug] = {},
    [Part.IntakeManifold] = {},
    [Part.ExhaustManifold] = {},
    [Part.Alternator] = {},
    [Part.FanBelt] = {},
    [Part.AlternatorBelt] = {},
    [Part.SuperBelt] = {},
    [Part.SerpentineBelt] = {},
    [Part.Starter] = {},
    [Part.CamShaft]= {},
    [Part.Lifters] = {},
    [Part.PushRods] = {},
    [Part.Valves] = {},
    [Part.Distributor] = {},
    [Part.Carburetor] = {},
    [Part.FuelInjectors] = {},
    [Part.AirFilter] = {},
    [Part.OilFilter] = {},
    [Part.OilPan] = {},
    [Part.TimingBelt] = {},
    [Part.TimingChain] = {}
}```
then I could treat it like template, have different access graphs for different engine types
young edge
#

First production car with one was in 1967 FeelsNeatMan

astral dune
#

just looking for resources on the last engine I owned in the 90s, the LM1, to get an idea of how a GM 350 engine would have been put together

hearty dew
astral dune
#

I'm thinking leaving the templates outside of the moddata, and storing the installed parts only in the moddata

hearty dew
hearty dew
astral dune
#

they are my fancy enums that looks Something like

Parts = {
Sparkplug = "Sparkplug",
Fanbelt = "Fanbelt",
...
}
young edge
#

Tyr, how do bullbars (or other items, really) apply a protective effect on whatever part they're covering? Thonk

#

Kinda looking at the M998, saw front and rear health but no real modifiers on the entries around the bullbar

hearty dew
#

I haven't the slightest idea. I think Anonymous looked at that some time ago. Or someone did. I recall a convo about it

astral dune
#

from what I've seen, most mods store the condition of all the parts on the vehicle, and check every tick whether they've changed and revert the changes if applicable

#

that being said, there is a "Front end condition", I can't currently remember how it factors in though

young edge
#

that seems like a PITA.
But yeah, seems to be correct, the M998armor.lua does seem to store part conditions ๐Ÿค”

astral dune
#

I've come up with some better ways to mitigate damage from zombies, crashes and wear and tear

#

but I haven't yet figured out how to deal with weapon damage

young edge
#

I am listening with both of my ears and all of the hair on my body reeee

astral dune
#

lol

young edge
#

because the way zombies interact with vehicles in terms of damage (and them slowing down to a crawl) has caused me mental agony

astral dune
#

unfortunately we are locked clean out of the physics engine, so its very difficult to impossible to mitigate the slowdown, but the damage is easy to deal with

young edge
#

I noticed that vehicles have physical mass, does that affect anything at all?

astral dune
#

yes, mass and engine power control how quickly you accelerate, and also how well you stick to the road

#

one thing to try is to maybe increase the weight and power equal amounts when you hit a zombie, might make running them over easier, I haven't tried it yet

#

detecting when you've hit a zombie at speed is easy, I'll give you the secret: any impact with a zombie (and potentially player) that is hard enough to cause damage also leaves some blood on the car. Its very computationally inexpensive to check the blood levels

young edge
#

but if you do that around the corner, handling would be impacted, correct?
Sounds "simple" enough. Sadly I lack the know-how to do these things, the spawntweaks I've made with the help of a buddy is about as far as it goes for me Pain_Peko

astral dune
#

it very hard to tell how handling is effected by anything. The game does limit your steering power the faster you go, but I'm pretty sure wheel friction, suspension damping, compression etc all play a part in how a vehicle actually handles, but that's all done in the physics engine, which can't even be decompiled afaik

heady crystal
#

Override:true doesn't seem to work on recipes for me. Is it broken or am I missing something?

young edge
#

Fair enough. I do hope you're able to release your mod sooner rather than later. It kind of sucks when other vehicles are trivialized by KI5 vehicles solely due to them having a bullbar Pain_Peko Meanwhile other vehicles which have a visual one on their model still fall apart pepeLaugh
Not to mention trucks. reeee

astral dune
#

I'm considering making my vehicle damage detection an api so others can use it as well, but I'm probably not going to release anything until build 42, since there is a vehicle revamp coming then, and also there is an intentional bug in the java code right now that makes it very hard to change engine power

young edge
#

There's a vehicle revamp coming? Thonk

#

and here I thought I paid attention to the devblogs

astral dune
#

dev said it to me personally in this very channel

#

lol

#

I don't think its been mentioned in the blogs

young edge
#

a

bronze yoke
#

it's likely that vehicle armour could be added then anyway

heady crystal
#

Do I hear proper two wheeled vehicles

young edge
#

did they go into any detail as to the nature of it or just a "might wanna hold off there for a bit, bud"

astral dune
#

they did make it sound like they were putting in means of adding armor as well as detecting damage, which makes a lot of my current work obsolete

heady crystal
#

Outstanding

#

That'd allow me to make crazy mods

#

They better make this in December or January so I can flip off new mods on industrial scale

bronze yoke
#

i would be shocked if b42 was out that soon

young edge
#

Well.. Still would mean that modders would have to update their vehicles, assumedly.
unless they make it a system of "armored doors" instead of normal doors, etc. etc.

astral dune
heady crystal
#

They probably won't make it incompatible

#

You can't just break mods and call it a day

bronze yoke
#

they totally can

heady crystal
#

Yeah but have they ever

bronze yoke
#

most b40 mods don't work at all

young edge
#

Not like they'd break them, they just wouldn't make use of the new systems, methinks

heady crystal
bronze yoke
#

from the sheer scale of b42 i would expect a lot to break

astral dune
#

ya, absolutely

bronze yoke
#

although i wouldn't worry much about things they haven't mentioned specific plans of reworking

young edge
#

p sure they'd give modders time to update their mods ahead of time anyway

#

unstable branch and such

bronze yoke
#

i don't expect my vehicle armour mod to work in b42, but i'm optimistic that they'll make it obsolete entirely

young edge
#

that's the hope pepeLaugh

heady crystal
#

I hope they add bicycles

#

and basements

young edge
#

devs making the modder's work obsolete is a desirable outcome

#

basements have been confirmed iirc?

bronze yoke
#

i'm pretty happy with how the models are turning out, but i'm not an artist, tis would do much better

astral dune
#

I hope so for me as well. For now I just play with my java modded to what I think build 42 might look like for vehicles, but its unlikely that I'm right

heady crystal
#

As long as they one up me by a significant margin, I am completely ok with them integrating "my" mod concepts

bronze yoke
#

well like

astral dune
#

them revamping the whole coordinate system just to add basements is wild

bronze yoke
#

if they somehow did it worse than me i would just make my mod improve it

heady crystal
young edge
bronze yoke
young edge
#

seems like B42 is gonna be the feature playground build

fast galleon
#

can I set up a fake controller for testing

bronze yoke
#

i'm most excited for that skill revamp honestly

#

hopefully that'll solve the sometimes strange balance

young edge
#

Optimization is the highest factor for me atm

bronze yoke
#

also i'm unreasonably excited for that light propagation stuff, it doesn't have a big gameplay effect i just think it's super cool

young edge
#

Some of my friends' potatoes wanna throw themselves off a cliff.
And even my PC is still working harder than it should

Same here lel

bronze yoke
#

i'm a big fan of playing with pitch black nights so more variance in light levels always sounds good to me

young edge
#

I'd consider it if light levels made more sense. Flashlights would become a bit nicer to use too

astral dune
#

full tilt down the highway is like 10fps for me, optimization is definitely very welcome

young edge
#

amen

bronze yoke
#

plus when i was new to the game i thought zombies were attracted to light and was super careful with curtains and stuff and i want to return to that life

astral dune
#

and I have a rtx 3080

young edge
#

this game just hammers the CPU

heady crystal
#

Turning off the flashlight and seeing absolutely nothing thinking I was so smart

astral dune
#

they do see flashlights

bronze yoke
#

they don't

heady crystal
#

โ˜๏ธ

young edge
#

someone's life has been a lie, just not sure whose

bronze yoke
#

turning on lights at night does attract zombies, but it doesn't matter if you have curtains or even a solid wall

heady crystal
#

lmao

bronze yoke
#

and it's only house lights that does that

heady crystal
#

Probably due to sound too

bronze yoke
#

yeah it's just a sound

young edge
#

furiously clicks the light

astral dune
#

could have sworn I saw it in the code, the flashlight has to be pointed directly at them though

#

and they have to be turned towards you too

bronze yoke
#

well i'd be happy to be proven wrong

young edge
#

inb4 anon was just dreaming about PZ

astral dune
#

I could be imagining things. A quick search shows very few mentions online of it

young edge
astral dune
#

that they're attracted to light switch noises is dumb though

heady crystal
#

My friend actually did this to us once and I was so mad lmao

astral dune
#

Still need the blinds

bronze yoke
#

well hopefully with light propagation they'll get rid of that

young edge
bronze yoke
#

๐Ÿค” i could probably make zombies attracted to the flashlight

young edge
#

give them pinpoint hearing and they'll instil the fear of god into you

bronze yoke
#

although with my experience with pitch black nights it's not too necessary

#

if you can see them, they've seen you

astral dune
#

one of my runs was ended by me very carefuly fortifying a house, putting up blinds etc, only for a zombie to break in next door and trigger the alarm

bronze yoke
#

LOL

young edge
#

that's cursed

heady crystal
#

Oh my god

#

I never even thought of that

#

Holy shit I've been so lucky so far lmao

astral dune
#

thats what gives this game its charm imo, lol

bronze yoke
#

yeah i never even considered the possibility

young edge
#

everyone gonna double and triple check their neighbors for the next few days pepeLaugh

weary matrix
#

Hi there, just to let you know the domain zomboid-javadoc.com is going to expire on the 23rd of december. If you're using the website please consider making a donation on my ko-fi (see my discord profile).

hearty dew
#

Anyone happen to know a good way to get the number of clients connected to a server (server-side in lua)?

#

Not seeing any useful apis on the GlobalObject.

#

Can probably do it by inferring which players are splitscreen based on how the server assigns online IDs, but hopefully there is something less brittle to change

tardy wren
#

Maybe in zombie.network.server.getPlayers()?

#

seems to be the list of players

steep copper
#

Hi, i try to make a mod but none of these two scripts are loaded in the game. I'm unable to start a game with it, and i don't understand why. I think there's an error somewhere but i don't know where.

pigments.txt : https://pastebin.com/Nzm6UHHB
paintbuckets.txt : https://pastebin.com/9mXxaRD7

Can you help me with it ?

#

there is nothing special in the console

tardy wren
steep copper
#

Arf, that's right, i try them again

tardy wren
#

How Do I actually upload my mod to the workshop?

ruby urchin
#

then in the game menu, select "workshop" and then by common sense you will know what to do

tardy wren
#

thanks

ruby urchin
#

I'm really confused, why database is management from client side(? It isn't a vulnerability?

sour island
placid delta
ancient grail
sour island
#

Hey it's a Nolan sighting

placid delta
# ancient grail works with mp?

no because this is a quest system for superb survivors and i dont plan to make that mp compatible, would require serious overhaul to do so

tardy wren
#

I suppose this is MP for people without friends

steep copper
#

Hi, do you know how the Heat value work for items ? Actually, Heat:-0.22 in recipe is Hot, but i don't really understand what it really means. Any maths behind this ?

ancient grail
#

Juat went and used game logic without understanding it ๐Ÿ˜‚

steep copper
#

lol okay ! myb we need to ask to a dev

sour island
#

Anyone know where/what to look for to add onto or modify the 'toggle held light' action?

#

Can't really find any files using 'torch' 'light' 'flashlight'

#

there's a timed action for lightswitches

#

media/lua/client/ISUI/ISLightSourceRadialMenu.lua heh

#

Didn't even know you could activate the radial menu for lights

#

so I didn't bother checking

#

getCore():getKey("Equip/Turn On/Off Light Source") helped me find the standard 1 press

blissful salmon
#

I still struggling with adding a weapons using my fbx as model. I also ask my question in the #modeling channel so far but till now didn't get an answer. If someone could give me a hand to add a simple model to the game I would really appreciate it (I absolutely have no clue about this stuff). I described my current situation in the post: #mod_development message

devout rock
#

I am having trouble with making a UI panel interactable in the world map screen. Unlike the vanilla ISWorldMapSymbols element, if I create a new ISPanel,ISPanelJoypad or ISCollapsableWindow on the World Map, then I can't click on it, and in the case of the ISCollapsableWindow I also can't close, move or resize it. Therefore, any additional elements within the panel (buttons, checkboxes, etc.) can't be interacted with, the game just behaves as if I was clicking on the map itself and dragging it around instead of my new UI element.

Is there a way I can fix this? I'm trying to look through code for ISWorldMapSymbols in search for something that makess the map screen treat an element as "solid", but so far I've not found anything that would work in my case.

devout galleon
#

can someone help me with some crafting recipe stuff?

Basically i want my crafting recipe to have 2 different items as output

tardy wren
#

You'll going to need to make an event for it I believe

bronze yoke
#

you need an OnCreate function

tardy wren
#
    {
        CannedTomato,

        Result:farming.Tomato=5,
        Time:30.0,
        OnCreate:Recipe.OnCreate.OpenCannedFood,
        Category:Cooking,
        OnGiveXP:Recipe.OnGiveXP.None,
    }
#

Like here. Recipe.OnCreate.OpenCannedFood spawns an empty jar in your inventory

devout galleon
#

so the thing i am testing with is a couch

#
    {
        Plank=4,
        keep Saw/GardenSaw,
        keep Hammer/BallPeenHammer/HammerStone,

        Result:Moveables.furniture_storage_01_52,
        Time:240.0,
        SkillRequired:Woodwork=7,
        Category:MathoulDrawers,
        AnimNode: BuildLow,
        Prop1: Hammer,
        Sound: Hammering,
        OnGiveXP:Recipe.OnGiveXP.Woodwork11,
}

so i would have to create an on create function like

    result:Moveables.furniture_seating_indoor_03_16;
    result:Moveables.furniture_seating_indoor_03_17;
end```

?
#

sry kinda new to that and just learning to make some small things for a server

tardy wren
#

This is the OnCreate for the canned food

#

Wait, no

tardy wren
#

This is the one that gives you a jar

devout galleon
#

oh so i will need player:getInventory():AddItem("Base.EmptyJar");

#

just with the proper item

#

thank you

tardy wren
#

yes

elfin stump
#

I have been trying to use this but I cannot get it to work. I may be misunderstanding how to utilize it. Could you possibly give an example on how to write a lua table to json using this?

devout galleon
#

So basically what i am trying to craft is this 2 seated couch

For some reason

    player:getInventory():AddItem("Moveables.furniture_seating_indoor_03_17");
end ```

Does not spawn the item in however if i change it to "Base.EmptyJar" it gives me a jar

The Result of this recipe works tho but the only issue is i kinda need both halfs to be created and thats what i struggle with rn
```    recipe Test
    {
        Plank=4,
        Nails=2,
        Woodglue=2,
        Drawer=1,
        keep Saw/GardenSaw,
        keep Hammer/BallPeenHammer/HammerStone,

        Result:Moveables.furniture_seating_indoor_03_16,
        Time:240.0,
        SkillRequired:Woodwork=7,
        Category:TestCouch,
        AnimNode: BuildLow,
        Prop1: Hammer,
        Sound: Hammering,
        OnCreate:Recipe.OnCreate.CustomRecipe,
        OnGiveXP:Recipe.OnGiveXP.Woodwork11,
    }```
#

ignore the ingredients lol its just a copy paste from a drawer that i created before

#

it works perfectly fine with single tile items however once its 2 tiles it gets wonky

tardy wren
#

As in Base. or whatever mod it's from

#

Also there may be checks in place to not overfill player inventory?

devout galleon
#

it says Moveables.

#

that might be a thing that the inventory is full

weak sierra
#
UdderlyVehicleRespawn.GetViaReflection(zone, "public IsoDirections dir")```
#
--Reflection Wrapper

UdderlyVehicleRespawn.ReflectionCache = {}

function UdderlyVehicleRespawn.GetField(obj, fieldString)
    local cachedValue = UdderlyVehicleRespawn.ReflectionCache[fieldString]
    if cachedValue == nil then
        local num = getNumClassFields(obj)
        local idx = nil
        local zones = nil
        for i=0, num-1 do
            local field = getClassField(obj, i)
            if tostring(field) == fieldString then
                UdderlyVehicleRespawn.ReflectionCache[fieldString] = field
            end
        end
    end
    return UdderlyVehicleRespawn.ReflectionCache[fieldString]
end

function UdderlyVehicleRespawn.GetViaReflection(obj, fieldString)
    return getClassFieldVal(obj, UdderlyVehicleRespawn.GetField(obj, fieldString))
end

--End Reflection Wrapper```
#

Q: anyone know why i can't retrieve the field "public IsoDirections dir" from vehiclezone via reflection?

#

repost of what i asked last night which got buried instantly :P

devout galleon
tardy wren
#

It... Might not be an item

#

But something else?

weak sierra
#

u have to add an OnCreate function

#

and make it give u the second one

#

getPlayer():getInventory():addItem("whatever") or etc

tardy wren
#

That's what he did

weak sierra
#

oh.

tardy wren
#

But the item isn't added when it's yhe furniture piece

#

A normal jar does

weak sierra
#

ive never messed with that kind of item, so im not sure if there's any special magic around them

tardy wren
#

Which makes me think the moveable furniture isn't an item

weak sierra
#

yeah it's some kind of magic thing

#

i believe

#

but it should still be possible shouldn't it

tardy wren
#

At least it should throw an error or something

devout galleon
#

yeah but not even an error

#

its kinda weird

#

main reason i want to go the crafting menu way and not the RMB menu like carpentry is that if you have too many items its just massive and annoying bloat

#

i could bypass it by making 2 recipes but i would prefer it to be a single craft else there is bloat in the crafting window ๐Ÿ˜‚

tardy wren
#

I suppose, try adding the module to the item? How it's defined in the lua files?

devout galleon
#

this is kinda all i can find when i search for that tile

#

tho i am only searching in the media folder

tardy wren
#

No, media should have them all?

#

I don't know tbh

#

It should work

#

Maybe without the Moveables?

bronze yoke
#

moveables are really weird

devout galleon
#

yeah

#

some tables if you pick them up their item becomes "Moveables.moveable"

#

and there is like

#

500 moveables.moveable

bronze yoke
#

maybe moveables are just one item with different properties...?

weak sierra
#

Yet listed multiple times, magic nonsense

devout galleon
#

cant even find this lol

fast galleon
#

Did you make the tiles sheet?

devout galleon
#

its base pz

bronze yoke
#

in-game item list doesn't have couches either, i'm guessing multiple part moveables are just a generic item with properties and not unique items

#

yeah, it's all moddata looks like

devout galleon
#

i dont understand why they are even 2 items to begin with...

#

yes some couches are multiple pieces but that couch isnt lol

fast galleon
#

another thing, are you in debug / do they fit into your inventory

devout galleon
#

i am in debug yes

#

they 100% fit in my inventory

#

combined weight is 30

bronze yoke
#

ReadFromWorldSprite(string) seems relevant

fast galleon
#

I was doing something similar but I added scripts for the moveables, to spawn with debugger easier

devout galleon
#

hmm

#

main reason for all this is that its for a RP server and stuff like More builds is just massive clutter and not really something you want on a MP server since it uses wood to create metal objects aka you can craft, disassemble and get metal

fast galleon
#

itemTest5
{
Type = Moveable,
WorldObjectSprite = test_4,
DisplayName = Moveable,
}

#

try to create the objects from console and print result

devout galleon
#

nvm there is an error

#

it doesnt consider the moveable to be spawnable by additem

bronze yoke
#

not sure it is moddata actually, can't find anywhere in the lua or java that this moddata is actually set

#

might just be for modders or something

devout galleon
devout galleon
#

will see if i find anything

fast galleon
#

print(InventoryItemFactory.CreateItem("Moveables.furniture_seating_indoor_03_16"))

bronze yoke
#

getPlayer():getInventory():AddItem('Moveables.Moveable'):ReadFromWorldSprite('furniture_seating_indoor_03_16') spawned the first half

#

seems perfect except i have no idea how to get 2/2 yet

fast galleon
#

doesn't work for sprite 17?

bronze yoke
#

that does work, didn't know that was how moveables worked ๐Ÿ˜…

#

@devout galleon

getPlayer():getInventory():AddItem('Moveables.Moveable'):ReadFromWorldSprite('furniture_seating_indoor_03_16')
getPlayer():getInventory():AddItem('Moveables.Moveable'):ReadFromWorldSprite('furniture_seating_indoor_03_17')
#

your oncreate function would look something like this

function Recipe.OnCreate.CustomRecipe(items, result, player)
    player:getInventory():AddItem('Moveables.Moveable'):ReadFromWorldSprite('furniture_seating_indoor_03_17')
end
fast galleon
#

I don't know how heavy it is but might be better to put those on the floor.

bronze yoke
#

yeah it's 15 ๐Ÿ˜จ

devout galleon
#

oh lemme see

#

oh my god yes it works thank you sooooooooooooooooooo much!

#

how would i make it that the result is placed on the floor?

#

might be useful since i plan to allow beds to be crafted too and i doubt someone can carry those kingsize beds haha

#

is it possible to define the crafting icon in the recipe?

#

so it does not draw from the result?

bronze yoke
#

getSquare() instead of getInventory() i think

devout galleon
#

i see will try it

#

noticed tho if you craft something that goes over your 50kilo limit it drops it on the floor automatically

jade chasm
#

anyone know where I can find the 3D models for the ammo boxes? I can't find 556 and 308 in the gamefiles

jade chasm
#

^ok apparently they are only one model and texture. very cool

hearty dew
sour island
#

There is one for coop - I didn't realize what you actually wanted

#
for playerIndex=0, getNumActivePlayers()-1 do
#

This one may have to be ran from client side and have information sent over

hearty dew
sour island
#

I am surprised that getOnlinePlayers wouldn't return the IsoPlayers for everyone though?

#
      @LuaMethod(
         name = "getOnlinePlayers",
         global = true
      )
      public static ArrayList getOnlinePlayers() {
         if (GameServer.bServer) {
            return GameServer.getPlayers();
         } else {
            return GameClient.bClient ? GameClient.instance.getPlayers() : null;
         }
      }
#
   public static ArrayList getPlayers(ArrayList var0) {
      var0.clear();

      for(int var1 = 0; var1 < udpEngine.connections.size(); ++var1) {
         UdpConnection var2 = (UdpConnection)udpEngine.connections.get(var1);

         for(int var3 = 0; var3 < 4; ++var3) {
            IsoPlayer var4 = var2.players[var3];
            if (var4 != null && var4.OnlineID != -1) {
               var0.add(var4);
            }
         }
      }

      return var0;
   }
#

I think getOnlinePlayers is meant to return all players regardless of coop

hearty dew
# sour island There is one for coop - I didn't realize what you actually wanted

I don't want coop. You can have one client on a dedicated server that has multiple players. getNumPlayers doesn't work server-side:

    Notes:
    getNumActivePlayers:
    - Singleplayer: number of local players in client (including all split screen players)
    - Client: number of local players in client (including all split screen players)
    - Server: 1, but getSpecificPlayer() calls always return nil on server
    ```
hearty dew
sour island
#

Ah I get what you mean now

hearty dew
#

I'm trying to get the number of clients not players

sour island
#

must have misread

hearty dew
#

The way the server assigns online ids to players is done in such a way that I should be able to infer which players are from the same client (it seems to assign them in blocks of 4 for each clients to allow for run a 4 online ids for the players on the udp connection for that one client). It's a rather brittle solution though since it is coupled to implementation details, will break if pz devs change it

sour island
#

what about ```java
public static UdpConnection getConnectionFromPlayer(IsoPlayer var0) {
Long var1 = (Long)PlayerToAddressMap.get(var0);
return var1 == null ? null : udpEngine.getActiveConnection(var1);
}

#

I would assume each client is one connection? You could parse through and not record duplicates

hearty dew
#

yea, each client is one connection

#

That's on GameServer, which isn't exposed, I believe? Let me double check

sour island
#

I'm scanning through uses of udpEngine.connections.size to see if there's anything

hearty dew
sour island
#

Well sending server commands only goes through 1 connection

#

You could have a ping-pong of server to client to server

#

But honestly, checking the online IDs seems like less of a headache

#

I get you want to look out for maintainability but sometimes that 80% 20% rule kicks in

hearty dew
hearty dew
#

I'll just go with inferring based on the online IDs for now. Nothing else seems to stand out as a better option at this point. Thanks

sour island
#

np

#

Honestly surprised there isn't already a 'getConnections' feature

#

looking through the java - they use getconnections internally and for loop Isoplayers each time - when it could be it's own function

hearty dew
#

I presume the devs decided not to expose the connections, as it's be rather powerful to be able to send packets directly. GameClient, GameServer, UdpConnection, all not exposed

#

Would be quite handy though

sour island
#

Yeah, my point was they've done this

#

that's from 1 file

hearty dew
#

Ah

#
GameServer.udpEngine.connections.size();

is used all over GameServer.

I imagine the first dev did it that way, and the pattern emerged

sour island
#

I mistook each use as also parsing through the 1-4 isoPlayers

bronze yoke
#

weird that gameclient isn't exposed but the lua global object has a getter for it

hearty dew
#

I recall reading some brief remark from a pz dev (on forum maybe? idk) that suggested that there was a lot more exposed to lua previously (java.lang.reflect.Method, java.lang.reflect.Field, etc) that they have since removed. That getGameClient api might be a left over they missed

#

Oh, wait, there's a field to get the UdpEngine on the GameClient. If I can get the number of connections via fields alone, that could work :o

#

On client-side:

#

on server-side:

#

๐Ÿ˜ญ

sour island
#

If a class is exposed would all the subclasses be as well?

#

MediaData is exposed but MediaData.MediaLineData is not

#

java.lang.RuntimeException: attempted index: getTextGuid of non-table: zombie.radio.media.MediaData$MediaLineData@1421bc76

#

I'm assuming that's why I'm getting this

hearty dew
sour island
#

I was hoping I could get around a really old issue, so I'm trying to take a crack at it

hearty dew
#

If the guid is readable from a field, you could get it that way

sour island
#

I tried also if mediaLineData.getTextGuid as a means to make it compatible when it can be used - but that also sends the same error

hearty dew
#

How can I get an instance of a MediaData to check?

sour island
#
function SRJ.getListenedToMedia(player)

    local knownMediaLines = {}

    local ZR = getZomboidRadio():getRecordedMedia()
    local categories = ZR:getCategories()
    for i=1,categories:size() do
        local category = categories:get(i-1)
        local mediaType = RecordedMedia.getMediaTypeForCategory(category)
        local list = ZR:getAllMediaForType(mediaType)
        for j=1,list:size() do
            ---@type MediaData
            local mediaData = list:get(j-1)
            print("Watched - mediaData: ".." ("..mediaData:getId()..")  "..mediaData:getLineCount())

            for jj=1, mediaData:getLineCount() do
                ---@type MediaData.MediaLineData
                local mediaLineData = mediaData:getLine(jj-1)
                if mediaLineData then
                    --TODO: Bother Nasko about adding: this.setExposed(MediaData.MediaLineData.class); in LuaManager.java
                    local lineGuid = mediaLineData:getTextGuid()
                    if lineGuid then
                        print(" ---getTextGuid: "..tostring(lineGuid))
                        if player:isKnownMediaLine(lineGuid) then
                            print("Watched - "..tostring(lineGuid))
                            table.insert(knownMediaLines, lineGuid)
                        end
                    end
                end
            end
        end
    end

    return knownMediaLines
end
#

It's a bit buried

#

I'm trying to fetch and apply known media lines

#

IsoPlayer's knownMediaLines is unfortunately not gettable

#

although you can add/remove from it

hearty dew
#

That's what you're trying to get at?

sour island
#

Yeah

#

Specifically the mediaLineData, and it's getTextGuid's return

hearty dew
#

Can only get the text, color, and codes fields (in non-debug clients)

sour island
#

ah that's right, I forgot debug mode lets you do some checks for that

#

text is what I'd need

odd notch
#

is there a method to finding if an item has a custom name or not? isCustomName doesn't seem to detect any change

hearty dew
#

yea, debug mode you could write fields and invoke methods

#

in non-debug, can only read fields

sour island
#

reading would be fine

#

I've read fields before but then I was trying to set it

#

didn't know reading works in non-debug

#

do you have the field stuff handy?

#

nvm found my old stuff

hearty dew
#

Oh, wait, the text field has a guid in it. Is that not the guid you are after?

#

Would need to parse it a bit

sour island
#

the text field is what I need exactly

#

the knownmedialines in IsoPlayer seems to just be a collection (hasmap if I recall) of those guids

#

this is what I was doing a while back for setting a field

#
local function setZombieSpeed(zombie, speedVal)
    --TODO: Figure out how to get this to work outside of debug

    for i = 0, getNumClassFields(zombie) - 1 do
        ---@type Field
        local javaField = getClassField(zombie, i)
        if javaField then
            if luautils.stringEnds(tostring(javaField), '.' .. "speedType") then
                print("-EHE:SWH: javaField: "..tostring(javaField))
                if not javaField.setInt then
                    print("-EHE:SWH: setZombieSpeed: ERROR: javaField.setInt not found.")
                    return
                else
                    javaField:setInt(zombie,speedVal)
                end
            end
        end
    end

end
#

do you still need to parse through each field?

hearty dew
#

yea, have to iterate over them to find the right one

sour island
#

alright

#

not too bad with so few

hearty dew
#
print(l.debugGetFieldValue(l.debugGetFieldValue(getMediaData(),"lines"):get(0),"text"))
sour island
#

nice

#

that solves a big issue with Skill Recovery Journal

hearty dew
#

function getMediaData()
    local player = getPlayer()
    local knownMediaLines = {}

    local ZR = getZomboidRadio():getRecordedMedia()
    local categories = ZR:getCategories()
    local category = categories:get(0)
    local mediaType = RecordedMedia.getMediaTypeForCategory(category)
    local list = ZR:getAllMediaForType(mediaType)
    return list:get(0)
end


--[[
    Usage example:
    
    ChuckUtils.debugGetFieldValue(getPlayer(), "MaxSpeed")
]]
ChuckUtils.debugGetFieldValue = function(object, fieldName)
    for i = 0, getNumClassFields(object) - 1 do
        local field = getClassField(object, i)
        if string.find(tostring(field), "%."..fieldName) then
            local result = getClassFieldVal(object, field)
            print(string.format("Field value result:\n%s\n%s", tostring(field), tostring(result)))
            return result
        end
    end
    return (ChuckUtils.getFieldValue(object, fieldName))
end

local getFieldValueCache = {}

--[[
    Usage example:
    
    local value = ChuckUtils.getFieldValue(getPlayer(), "public float zombie.characters.IsoPlayer.MaxSpeed")
    ----
    local value, cachedField
    value, cachedField = ChuckUtils.getFieldValue(object, "private int zombie.iso.Foo.otherthing", cachedField)
]]
ChuckUtils.getFieldValue = function(object, fieldName, field)
    if field then
        return getClassFieldVal(object, field), field
    end

    local className
    if getmetatable(object) then
        className = tostring(object:getClass())
    else
        className = tostring(object)
        className = className:match("([^@]+)@") -- zombie.network.GameClient@c6e80100
        if not className then
            error(string.format("ChuckUtils.getFieldValue: ERROR: Unexpected format for %s", tostring(object)))
        end
    end

    getFieldValueCache[fieldName] = getFieldValueCache[fieldName] or {}
    local cachedField = getFieldValueCache[fieldName][className]
    if cachedField then
        return getClassFieldVal(object, cachedField), cachedField
    end

    local numFields = getNumClassFields(object)
    for fieldIndex = 0, numFields - 1 do
        local field = getClassField(object, fieldIndex)
        if fieldName == tostring(field) then
            getFieldValueCache[fieldName][className] = field
            return getClassFieldVal(object, field), field
        end
    end

    local errorOutput = {"\n"}
    table.insert(errorOutput, className.." has the following fields:")
    for fieldIndex = 0, numFields - 1 do
        table.insert(errorOutput, tostring(getClassField(object, fieldIndex)))
    end
    table.insert(errorOutput, "\n")
    print(table.concat(errorOutput, "\n"))
    error("ChuckUtils.getFieldValue: ERROR: Unknown fieldName: "..tostring(fieldName))
end
#

debugGetFieldValue is easier to use in the console. getFieldValue caches the field object to avoid the cost of looking it up via reflection multiple times

sour island
#

that was fast

#

thanks!

hearty dew
#

Might be buggy. Haven't used this version with the cache yet aside from testing it a bit. Let me know if there are any issues with it

#

If you give it a wrong name, it will print out all the proper strings that can be used for the fieldName

hearty dew
sour island
#

People can rewatch VHS tapes of TV shows to stack XP

#

might still be an issue tbh

#

now that I think about it

#

welp

#

having the lines in the journal prevents using the TV shows after reading but I need to figure out how to see if they watched before

#

Btw, couldn't I just do local lineGuid = getClassFieldVal(mediaLineData,"text") ?

hearty dew
#

In debug, because Field is exposed, you can :getName() (I believe) to just do "text". That's the way I had written it at first, but then it wouldn't work in non-debug.

You could write it to parse out the last bit after the final . from the full name of the field though

#

(sort of like how debugGetFieldValue does)

#

Instead of```lua
string.find(tostring(field), "%."..fieldName)

could do something like
```lua
string.find(tostring(field), "%."..fieldName.."$")
blissful salmon
#

Whats the difference between getConnectedPlayers() and getOnlinePlayers()?

#

I'm wondering because both return an array with players...

weak sierra
#

and in most other gun mods

#

might be why

hearty dew
# blissful salmon Whats the difference between getConnectedPlayers() and getOnlinePlayers()?
    Notes:
    getNumActivePlayers:
    - Singleplayer: number of local players in client (including all split screen players)
    - Client: number of local players in client (including all split screen players)
    - Server: 1, but getSpecificPlayer() calls always return nil on server
    
    getOnlinePlayers:
    - Singleplayer: nil
    - Client: lists all players (including split screen players)
    - Server: lists all players (including split screen players)
    
    getConnectedPlayers: trash. only seems useful for working with scoreboard?
    - Singleplayer: 0
    - Client: only updates when a player manually open scoreboard, but lists all players then
    - Server: 0
#

getConnectedPlayers seems to be for messing with the scoreboard

#

and returns 0 or returns stale data most of the time

blissful salmon
#

ok... so what do I use when I want to loop through all current player on the server? getOnlinePlayers()? I thought I read something above that this doesn't work serverside...

hearty dew
#

yea, getOnlinePlayers() if the code is running server-side

#
SoulUtils = SoulUtils or {}

--[[
    Gets all players matching a predicate. The default predicate is all players that aren't dead.
    
    Usage example:
    local all_living_players = SoulUtils.getPlayers()
    local all_players_named_bob = SoulUtils.getPlayers(function(p) return p:getDisplayName() == "bob" end)

    Notes:
    getNumActivePlayers:
    - Singleplayer: number of local players in client (including all split screen players)
    - Client: number of local players in client (including all split screen players)
    - Server: 1, but getSpecificPlayer() calls always return nil on server
    
    getOnlinePlayers:
    - Singleplayer: nil
    - Client: lists all players (including split screen players)
    - Server: lists all players (including split screen players)
    
    getConnectedPlayers: trash. only seems useful for working with scoreboard?
    - Singleplayer: 0
    - Client: only updates when a player manually open scoreboard, but lists all players then
    - Server: 0
]]
SoulUtils.getPlayers = function(predicate)
    local result = {}
    predicate = predicate or function(player)
        return not player:isDead()
            -- and player:getCurrentSquare() -- Will filter out players sufficiently far from client that their square isn't loaded
    end
    if not isClient() and not isServer() then
        -- singleplayer
        for i = 0, getNumActivePlayers() - 1 do
            local player = getSpecificPlayer(i)
            if player and (predicate == true or predicate(player)) then
                table.insert(result, player)
            end
        end
    else -- multiplayer
        local onlinePlayers = getOnlinePlayers()
        for i = 0, onlinePlayers:size() - 1 do
            local player = onlinePlayers:get(i)
            if player and (predicate == true or predicate(player)) then
                table.insert(result, player)
            end
        end
    end
    
    return result
end
for _, player in ipairs(SoulUtils.getPlayers(true)) do
  print(player:getDisplayName())
end
#

It will take care of server-side/client-side specifics

blissful salmon
#

but this uses getOnlinePlayers() on server... so it works?

hearty dew
#
    getOnlinePlayers:
    - Singleplayer: nil
    - Client: lists all players (including split screen players)
    - Server: lists all players (including split screen players)

getOnlinePlayers works on client and server. In singleplayer it returns nil

blissful salmon
#

ok... this is no problem...

#

Is there an easy way to go through all active zombies in the world on server side? My question above was already for a not so clean solution (iterate the player get the cell get the zombielist). But if there is a better way I open to it...

hearty dew
#

I see another mod using getCell():getZombieList(). I really don't know. What's a cell vs a world map is something I'm still not clear on yet

#
    public static IsoCell getCell() {
        return IsoWorld.instance.getCell();
    }
sour island
#

iirc getCell returns the active cell

hearty dew
#

I presume there is 1 cell per world? Not sure

sour island
#

and cells are 300x300 pieces

hearty dew
#

300x300 tiles?

sour island
#

you can load parts of multiple cells in "chunks"

#

300 tiles x 300 tiles I think

hearty dew
#

and grid squares are blocks of tiles (10x10, or around there, I think it was variable?)

hearty dew
sour island
#

I think the 10x10 might be the chunks?

#

Not too sure

sour island
#

going through the players is probably the only logical way to go about it

#

you could try identifying duplicate cells in the case of multiple players if you were worried about that

#

or even check the duplicate on the zombies

#

What is your eventual goal?

blissful salmon
#

so the cell is at a fixed place? not wandering with a player I suppose? If there are multiple players in different parts in the world there should be multiple active cells or did I get this wrong?

#

I want to go through all active zombies and check if it's time to do a scream...

sour island
#

The chunk 'wanders'

#

Cells are fixed

blissful salmon
#

But if I standing on the edge of a cell do I get the zombies of the cell right next to me?

weak sierra
#

it is not variable

hearty dew
#

Ooh, that makes sense. That explains these variables:

IsoChunkMap.ChunkWidthInTiles -> 190
IsoChunkMap.ChunkGridWidth -> 19
weak sierra
#

clarification: i don't know what it does in memory, but on disk chunks are fixed

#

the same files for the same cells

#

the same number of files

sour island
#

The 'Cell' is handled per client - not sure what coop does - maybe it handles up to 4

blissful salmon
weak sierra
#

i only deal in dedicated mp

sour island
#

From what I understand chunks are not fixed on the map

weak sierra
#

i can copy a chunk file out of a save

#

and put it in another save

#

and it will be the same area

#

the filenames never change

#

each cell has the same number

#

961 files per cell

sour island
#

maybe it's broken down to make the scope easier to read?

weak sierra
#

unless i've critically messed up my cell file lister

sour island
#

makes me think what the point of cells are

weak sierra
#

but it's been working thsi whole time

#

so

weak sierra
#

afaik

#

there's metadata stored at the cell level

#

then the actual data for the tiles is at the chunk level

sour island
#

ah, like lots and stuff

weak sierra
#

the items are stored at the cell level too i think

#

but i could be wrong about that

sour island
#

would make more sense tbh

#

would be a pain in the ass to parse through 10x10s

weak sierra
#

if u transplant chunks from one save to another without the cell files

#

u lose all ur items

#

retain tiles

#

chunks are only tiles

#

zombie data is in zpop files

#

and vehicles are in vehicles.db

sour island
#

so the map is broken down into both cells/chunks

weak sierra
#

outside of the map files entirely

#

one of my first mods was in this topic to let me reset cells selectively

sour island
#

but I've seen something that handles the player's scope of whats loading also referred to as a chunk

weak sierra
#

recommend skimming its code

#

would probably tell u a lot

#

or maybe just redundantly what i already told u

#

idk

weak sierra
#

we call that the reality bubble in my experience

#

lol

#

it's 150 around the player

#

so half a cell in any direction

sour island
#

that sounds familiar

weak sierra
#

if someone's out there callin it a chunk too

#

that's confusing af

sour island
#

I could have also just misread like I usually do

#

I for sure never saw reality bubble tho lol

weak sierra
#

i mean im speaking of what players call it

#

and modders

#

i have no idea if the code somewhere refers to it as something else

blissful salmon
#

I'm even more confused... I checked the javacode for getCell():
public IsoCell getCell() { return IsoWorld.instance.CurrentCell; }
So I'm not sure if I can use this on serverside. Because on server side the Worlds CurrentCell can't be the same on every player.

weak sierra
#

that's just a static instance

blissful salmon
#

So my idea don't work i think.

weak sierra
#

oh

#

it isnt it seems

#

huh

#

well on the server u can use that

#

i have done it

#

but i have no idea what the current cell is in that circumstance

#

lol

#

i was calling things that should be static but aren't

#

so it didn't matter

blissful salmon
#

hmm... I have to inspect further... But sometimes I try to understand what I'm coding ๐Ÿ˜„

sour island
#

I think the server has it's own 'client' instance - but I don't think it would help in this case

#

Your code would have to be ran on clientside for getCell() to work

weak sierra
#

the server is a headless client, yeah

blissful salmon
#

My idea was to do the check every 10 minutes instead of zombieUpdate. just because of performance...

weak sierra
#

kinda curious how that works

#

it'd be cool to hijack that to move the "player" around to force load stuff

#

if it's that complete anyway

blissful salmon
#

but now it seems that the onZombieUpdate is the more safe approach...

weak sierra
#

can always throttle

#

idk what ur doing but

sour island
#

you can do a bypass

#

similar to how ontick houses onhour etc

#

but I dump shit in updates all the time to no impact lol

#

also, @hearty dew ๐Ÿ‘

#

I still need to sit down and figure out how to prevent gaining XP from the known media :\

#

In the case of people watching the VHSs before reading

#

With this, if they read prior, the TV shows shouldn't do anything

hearty dew
sour island
#

What exactly are you trying to achieve again? I don't recall seeing it mentioned

blissful salmon
#

Atm I use the onZombieUpdate to apply settings from the moddata some zombies have. I made a list of all zombies I already checked so I can jump out as soon as possible from onZombieUpdate. when the settings are applied (in my testcase zombies that where resurrected player) I want to do a scream which is hearable by every player. At the moment I did it in the 10minutes function on server to trigger. So far it worked in my solo test... But now I try to make it multiplayer...

last flax
#

Hi, I don't know if this is the channel to ask, but does anyone know how to design textures for vehicles? I have the model but I don't have the knowledge in design

sour island
#

So basically you want to make player deaths generate a scream?

#

or just zombies that scream every ten minutes

hearty dew
blissful salmon
sour island
#

Like all zombies?

bronze yoke
#

can anyone confirm if player usernames are/aren't unique? it just uses your steam username right, couldn't two players have the same one?

sour island
#

SteamID is unique

blissful salmon
sour island
#

alright

#

you could leave it in zombieUpdate, and use timestamp checks'

hearty dew
#

So if I understand your requirements.. When a player dies, it emits a scream. And also, all zombies that were previously players should screen at the same time on all clients. The time at which the ex-player zombies scream is still up in the air but it seems to be periodic with perhaps some randomness?

steep copper
#

Hi, is there a way to add "pour on ground" option on right click on a new drainable ?

blissful salmon
#

I'm trying to get kind of an all in one solution. I also think about to adding it to modData and the check on the clients... But then I have no event and have to check every tick or zombieUpdate.

#

Currently I'm using this on server

zombie:addWorldSoundUnlessInvisible(150, 100, false)

and this on client:

Events.OnWorldSound.Add(OnWorldSound)
hearty dew
#
Events.OnPlayerDeath

There is that for player deaths. Its parameter is the player object.

blissful salmon
#

But im not sure if this is a good option.

sour island
#

you might not need modData tbh

#

iirc, the game has a variable for former player zombies

#
public boolean isReanimatedPlayer() {
      return this.bReanimatedPlayer;
   }
#

If you wanted them to do it insync

blissful salmon
sour island
#

so the zombies should be screaming periodically and independently

sour island
#

Idk if zombies store modData

blissful salmon
#

The first scream is not the problem but I struggle with syncing the others.

#

they do...

#

I think modData is on IsoObject...

sour island
#

modData should be universal, but there's some cases where it isn't

#

you probably don't need modData

blissful salmon
#

Hmm... I wish for some more events ๐Ÿ˜„

sour island
#

I wonder what would happen if you stored the zombies in a list

#

and they became unloaded

astral dune
#

memory leak I suppose, lol

blissful salmon
#

But I can try to check the modData on every zombie in cell on client cell each 10 ingame minutes...

blissful salmon
sour island
#

Idk if the references are kept between loads

#

you could have the zombieUpdate check for the reanimated boolean, then add itself as a key to a table with a timestamp as the value

#

then during update it checks for the value against the time and generates a scream + assigns new time stamp

#

then you wouldn't be parsing through the list

#

although if the references don't get saved idk if that would cause an issue

#

+unloaded zombies

blissful salmon
# sour island Idk if the references are kept between loads

We are nearly on line together ๐Ÿ™‚ But the reanimatedPlayer flag is just for my first step. I want to be able to add stuff to random zombies. Which will be kept when I restart the server. And save as much resources as possible... If the list doesn't work. I can in worst case rely on the modData. Maybe this is not to bad if I can jump out of onZombieUpdate early. The list was an idea for performance.

sour island
#

Let me check something

#

I don't think zombies retain modData

#

I've messed with Zombies to make custom AI

#

they're very particular to any changes done on the fly

#

you'll have to reapply changes everytime

#

The way I set my AI was to create an object they wear in a unique slot

astral dune
#

I recall hearing something similar from someone. The changes they applied DID persist, but moved to a different zombie, lol

blissful salmon
#

For me the zombies kept the data... At least if I didn't messed up my tests...

sour island
#

Could have been changed since I last saw

astral dune
#

it easy to forget they're changing stuff all the time

sour island
#

@hearty dew In order to securely tell how much XP was earned via media lines I have to modify the vanilla event handling the lines as raw text anyway

#

which I wanted to avoid

#

all the field stuff was for nothing lol

blissful salmon
astral dune
#

it'll be interesting to find out

hearty dew
astral dune
#

ya, I imagine the dev's didn't figure anyone would be able to tell zeds apart

blissful salmon
#

So I'm lost?

sour island
#

not necessarily

#

atleast for screaming

blissful salmon
#

As IT engineer I'm a master of dirty/bad and ugly solutions (saw a lot of them)... Maybe I can give the zombie an item with a custom stat that has a number of my mod settings and get the settings from a saved file. But I cry if I had to do it in such ways...

weak sierra
#

hehehe

sour island
#

my AI code looks for outfits and uses the weapon attachment (the embedded weapons) code

astral dune
#

modding this game is all about sacrificing your pride as a programmer and doing dirty hacks

sour island
#

basically it has an invisible weapon jammed in the zombie

hearty dew
#

If you're okay with some randomness, I'd just do the screams based on probability. Calculate that on the server, and broadcast a server command for the zombie to scream. I think that'd work and be relatively simple

sour island
#
---@param zombie IsoZombie | IsoGameCharacter | IsoObject
---@param apply boolean
function eHelicopter_zombieAI.onUpdate(zombie, apply)
    if not zombie or zombie:isDead() then
        return
    end

    local AIs = eHelicopter_zombieAI.checkForAI(zombie)
    if AIs then
        for AI_ID,_ in pairs(AIs) do
            local specialAI = eHelicopter_zombieAI["onUpdate_"..AI_ID]
            if specialAI then
                if zombie:getModData()["initApply"] ~= true then
                    --[DEBUG]] print("EHE:SWH:SZ:initApply not true, setting `apply` to true")
                    apply = true
                    zombie:getModData()["initApply"] = true
                end
                specialAI(zombie, apply or false)
            end
        end
    end
end
Events.OnZombieUpdate.Add(eHelicopter_zombieAI.onUpdate)
#

in this case I rely on the modData not being saved

#

that's why I confirmed it isn't saved

#

and this hasn't broken since

#
local group = AttachedLocations.getGroup("Human")
group:getOrCreateLocation("Special Zombie AI"):setAttachmentName("special_zombie_AI")


AttachedWeaponDefinitions.gottaGoFast = {
    chance = 100, weaponLocation = {"Special Zombie AI"}, outfit = {"AlienTourist"},
    bloodLocations = nil, addHoles = false, daySurvived = 0, weapons = { "ZombieAI.gottaGoFast" } }
AttachedWeaponDefinitions.attachedWeaponCustomOutfit.AlienTourist = { chance = 100, maxitem = 1, weapons = {AttachedWeaponDefinitions.gottaGoFast} }
#
module ZombieAI
{
    imports
    {
        Base
    }

    item gottaGoFast
    {
        Type = Normal,
    }

    item nemesis
    {
        Type = Normal,
    }

    item licking
    {
        Type = Normal,
    }

    item fodder
    {
        Type = Normal,
    }

}
blissful salmon
#

Is there a way in discord to bookmark stuff for myself?

sour island
#

you could copy the message link

blissful salmon
#

thats the current way ๐Ÿ™‚

sour island
#

also, turns out I can't safely/reliably figure out how much XP was gained from TV shows

#

asfaik it's sort of random

#

and most of the radiointeraction code is local

blissful salmon
astral dune
#

the xp is gained by specific lines in the show, not the show itself, right?

sour island
#

nah

#

from what it looks like it has a cooldown

#

that's doubly local

#

like, the object is localized, and in that localized init - it has local vars

#

seems like it tries to add an amount everytime and stops per cooldown of 30

blissful salmon
#

I tested a mod which gave the possibility to give an XP multiplier to each perk and also an option to make the XP gain "flat"...

astral dune
#

huh. It always seemed that the XP increases happened exactly during a new line appearing above the tv, but could have been confirmation bias

sour island
#
    function self.OnTick()
        for playerNum=1,4 do
            local tbl = cooldowns[playerNum]
            if tbl then
                for code,value in pairs(tbl) do
                    if value > 0 then
                        tbl[code] = value - (1*getGameTime():getMultiplier());
                    end
                end
            end
        end
    end
#

this is under the radioInteractions object

#
                    local code = string.sub(_v, 1, 3);
                    local op = string.sub(_v, 4, 4);
                    local amount = code~="RCP" and tonumber(string.sub(_v, 5, _v:len())) or nil;
                    if amount ~= nil and code~="RCP" then
                        amount = op=="-" and amount*-1 or amount;

                        if Interactions[code] ~= nil then
                            if not cooldowns[playerNum] or not cooldowns[playerNum][code] or cooldowns[playerNum][code]<=0 then
                                Interactions[code](player, amount, op=="=");
                                cooldowns[playerNum] = cooldowns[playerNum] or {}
                                cooldowns[playerNum][code] = 30;
                            end
                        end
                    end
#

the amount seems to be tied to the line

#

like you say, but there's also a cooldown

#

hmm

blissful salmon
#

ok... maybe than it's just random for the stuff like electricity gain when dismantle stuff or whatever...

astral dune
#

its possible they put a cooldown in so you can't gain all the XP from a show the first time you watch it, and have to go looking for the VHSes. I'm pretty certain I've gotten XP from a tape of a show I had already seen. I was gonna go look for more copies of the vhs to see if it was just tied to the particular tape, but this makes more sense

sour island
#

I'll have to figure out something

#

it's the one caveat to the recovery journal

astral dune
#

does the recovery journal still get eaten if someone has the consume book mod? Got a good laugh when one of my roommates realized his skillbook had disappeared

weak sierra
#

ive been considering adding that option to my skillbook mod and using it on my server

sour island
#

the reading is done by a looped crafting action

weak sierra
#

had a chat about it

#

then saw konijima made a mod for it

#

doesnt do all the other stuff mine does tho.

sour island
#

Why would people want books consumed?

weak sierra
#

balance

#

difficulty

#

make u raid book stores more

#

trade in books

#

etc

#

speaking of which the named lit mod not having tweakable stats might make me remove it

blissful salmon
weak sierra
#

imba af atm with fast reading

astral dune
#

ye, I like it as a concept, makes the books more consistent with the magazines as well'

weak sierra
#

i love the RP value but oof

sour island
#

My other mod Named Literature makes rereading books in general return a diminishing return

weak sierra
#

yeah

#

but if u read at the speed of a second

#

it diminishes but never hits zero

#

and u can spam it

sour island
#

the return would be abysmal under normal circumstances

weak sierra
#

yeah

#

i dont doubt it's fine in most cases

#

but in my case it's a problem xD

#

i like your mod for the RP value of different book names and such

#

but the mechanics it introduces don't work for it balance-wise cuz of that

sour island
#

you would want it to lock to 0 forever?

weak sierra
#

i mean ideally it'd have a configurable "amount of time to get to full value for re-read" setting

#

xD

#

maybe also an option to change the actual amount it gives at most

sour island
#

it's like 6 mo in game time to 'forget' a time read

#

I can add sandbox options

astral dune
#

is your named literature mod the one that adds Dragonlance books? I spend a good while trying to collect the whole series in game

sour island
#

I didn't realize it was an issue lol

weak sierra
#

i reported it at some point i think but u get a lot of crap in there

#

i still get errors from ur mod interacting with things xD

sour island
astral dune
#

lol

weak sierra
#
LOG  : General     , 1666980049026> 570,332,378> -------------------------------------------------------------
attempted index: StackableTypes of non-table: null

LOG  : General     , 1666980049026> 570,332,378> -----------------------------------------
STACK TRACE
-----------------------------------------
function: modifyLitScript -- file: namedLit - ScriptModify.lua line # 3 | MOD: Named Literature

ERROR: General     , 1666980049026> 570,332,378> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: attempted index: StackableTypes of non-table: null at KahluaThread.tableget line:1689.
ERROR: General     , 1666980049026> 570,332,378> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: attempted index: StackableTypes of non-table: null
    at se.krka.kahlua.vm.KahluaThread.tableget(KahluaThread.java:1689)
    at se.krka.kahlua.vm.KahluaThread.luaMainloop(KahluaThread.java:492)
    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.network.GameServer.doMinimumInit(GameServer.java:1431)
    at zombie.network.GameServer.main(GameServer.java:684)
LOG  : General     , 1666980049027> 570,332,379> -----------------------------------------
STACK TRACE
-----------------------------------------
function: modifyLitScript -- file: namedLit - ScriptModify.lua line # 3 | MOD: Named Literature

LOG  : General     , 1666980049027> 570,332,379> Named Literature: ver:0.7.6-REFACTOR-HOTFIX-AUG-12```
sour island
#

Oh that

weak sierra
#

well, it doesn't implicate anything else

#

but

#

i assume it's an interaction since it isn't sorted out by now

sour island
#

that's an issue of client/server

weak sierra
#

i figure u can't see it

#

this happens on server startup

sour island
#

doesn't/shouldn't break anything

weak sierra
#

client uninvolved

#

it doesn't seem to no

#

just unfortunate

#

random errors

sour island
#

yeah the issue is the server is trying to grab something that only clients have

weak sierra
#

if isServer() and not isClient() return end

sour island
#

yeah I probably did it in the git repo and never updated

weak sierra
#

dont get me wrong, sounding like a ball of complaints, i love a lot of your stuff :)

sour island
#

might be

#

I'm still waiting for inventoryItems to be able to have independent models

#

right now it's loaded specifically off the script ๐Ÿ˜ฆ

weak sierra
#

u planning to make them all have appearances?

astral dune
#

I'm not looking forward to diving into the inventoryitem world for my mod

weak sierra
#

that'd be cool

weak sierra
#

i assume u've put it in the modder suggestion thread?

sour island
#

I just ping nasko a bunch of stuff once and a while

#

Helps to have the filenames/lines, specific reason why, etc

weak sierra
#

does he take kindly to that? i heard someone say they think nasko hates them once for badgering him

#

xD

#

i want vehicles.db access

#

and a syntax checker for scripts

#

those are my two requests

thick karma
sour island
#

I didn't assume he likes me more than others

weak sierra
#

seriously

#

xD

#

idk if ur gonna burn out but it's impressive

gilded hawk
#

Don't stop modding dude ๐Ÿ‘Œ

weak sierra
#

i gave them a bunch of new requirements/requests and they're all in place in 24 hours

#

hehe

gilded hawk
weak sierra
#

LOL

#

i burn out but now im just on fire and keep going :)

sour island
#

the modify scriptfile is in shared for some reason

#

wish I commented why

#

but the stacktypes are in client

bronze yoke
#

i'm definitely going to burn out soon but i'm not quite there yet so i gotta get what i've already done out

sour island
bronze yoke
#

i'll probably do that soon, that should be a lot less frustrating than some of the weird stuff i've been doing recently

sour island
#

going to add sandbox options for the diminishing factors + rebund time @weak sierra

gilded hawk
jade chasm
#

hey anyone know how to scale an attachement? I want to use the recoil pad with a weapon but the pad is too large for the rifle butt. i've tried scale and scaling in the item doc below offset and rotate but it is not working

sour island
#

good thing I totally planned this out and these exsist

gilded hawk
sour island
#

Forgot I did a fancy schmancy formula - will have to work on it later

sour island
#

Actually, just going to add another sandbox option "can read passed max".

astral dune
hearty dew
astral dune
#

I don't think its exposed very well, I've messed with it a little to add things to the vanilla vehicles but I don't think it can be used for stuff other than items, vehicles, etc

hearty dew
#

With the writeModFile and readModFile apis, it will read to/from the mod file btw

astral dune
#

ya, I just poached the JSON api you linked, but that should work pretty good i think. After our discussion yesterday I have a pretty good idea of how I'm going to implement my data structures, but I don't want them taking up a bunch of space in my lua. This will probably do the trick, although I guess I'd have to figure out a way to sync them

hearty dew
#

It does a pretty good job. I use it to serialize item types selected by the user

#

I'd probably just stick any data structures that aren't going to be modified into its own lua file though, rather than a json file to be parsed at boot up. If the data structures are going to be changed and that change has to persist, then serializing/deserializing to json makes good sense imo

astral dune
#

having a mechanism to load them opens up the ability for end users to add their own fairly easily, which is a nice benefit, While also letting me keep my code clean. Having to sync additions and changes to clients is a stark downside, so I'm still undecided.

hearty dew
#

Ah, so you're thinking of a system where another mod can come along and add the missing gaskets, washers, etc to the graphs of engine parts

astral dune
#

if they want to, sure. For example one file would be a SmallBlockChevy.json or maybe more specific like 79_GMC_LM1.json, and contain the graphs we talk about containing the relationships between the parts. Someone could then later add their own engine blueprints as they like, or change mine to include other parts or whatever

#

I feel its a pretty elegant solution to how to model different types of engine configurations while still using a small set of standard "parts"

drifting stump
#

what are you trying to accomplish?

#

ah config files

#

theres a much simpler way of pulling it off

astral dune
#

pretty much ya, more similar to the template and vehicle scripts tbh

drifting stump
#

let me grab the system i made for a mod

#
local listings

Events.OnInitGlobalModData.Add(function(isNewGame)
    local fileReader = getFileReader("ServerPointsListings.ini", true)
    local lines = {}
    local line = fileReader:readLine()
    while line do
        table.insert(lines, line)
        line = fileReader:readLine()
    end
  fileReader:close()
    listings = loadstring(table.concat(lines))() or {["Missing Configuration"] = {}}
end)
#

this was used for a server side config file

astral dune
#

ya thats pretty straightforward. I need a way to serialize and parse some tables though, which is why I thought to lean on the JSON api so I don't have to reinvent any wheels

drifting stump
#

so you also need to save a table?

astral dune
#

several tables of tables, ya, haha. I've paid particular attention not to have any circular references or functions in them so they can be properly serialized

drifting stump
#

i guess then the json lib could be used

#

though keep in mind globalmoddata can be used for persistent data

astral dune
#

data could change between reloads, no point storing it in the save file tbh

bronze yoke
#

trying to debug an issue with one of my mods, one file's server commands listener seems to have stopped receiving responses 5 hours into a user's session and after countless restarts it refuses to work at all, does anyone know what that could possibly mean? another file in my mod uses *exactly the same code* and has not broken like this

ancient grail
weak sierra
#

the part where u used the same code on two mods

#

and one breaks somehow

#

that has happened to me

#

for me it was some tiny detail in the commands for one and not the other iirc

#

ive never heard of something like that just pissing off after 5 hours tho

bronze yoke
#

it's been narrowed down to an equally mysterious 'the part of code that requests the data from the server just stopped getting run for some reason'

#

so it wasn't directly the server commands... thank god

weak sierra
#

huh

bronze yoke
#

also not only was it 5 hours into a session, but the mod had worked perfectly for a week before that

weak sierra
#

that sounds like "something in this user's save"

#

or their set of mods

bronze yoke
#

unfortunately it's a public multiplayer server so i'm reluctant to tell them to wipe

weak sierra
#

are u sure it's ur mod at this point?

bronze yoke
#

i am not confident it is my mod

weak sierra
#

mayhap it is not

bronze yoke
#

but it's pretty hard for other mods to interfere with it, it's all local (i grew out of that habit, but it was someone else's mod that i was commissioned to update)

hearty dew
#

'the part of code that requests the data from the server just stopped getting run for some reason'
How was this determined?

bronze yoke
#

put a print before it, never showed up

#

i've just discovered that they added a new mod right before the problems happened, so... yeah

hearty dew
#

Did they provide a full console.txt?

bronze yoke
#

yep, several

hearty dew
#

That's tricky.. Would it be possible to instrument the code in such a way that the user's logs could print more information of your design that would help narrowing down the issue further?