#mod_development

1 messages ยท Page 18 of 1

quaint mirage
#

If it could be lower it'd be ideal

#

So outside the [] or inside?

#

[Recipe.GetItemTypes.Petrol]=1,

calm depot
#

that's correct

#

you could try using a float, I forget if it requires integral values or not

#

probably not though

quaint mirage
#

Ill be messing with that as lighters dont use that much fuel, least not enough to fill a quarter of a car lol

#

Very handy tips mate, learning a lot from asking in here and reading some of the code in media/

calm depot
#

yeah, the units of drainables is a bit arbitrary at the moment and doesn't make sense, especially when you compare it to weight

#

but, build 42 is going to fix all that

quaint mirage
#

Amazing maybe then i can pass in 0.1 units of gas per refil or something

calm depot
#

containers will be able to hold mixes of fluids

#

so I'm expecting we'll actually have proper units of volume you can tell a container to lose

#

it does also mean that you'll have to deal with someone who filled a can with 10% petrol and 90% water

quaint mirage
#

Looking forward to that, proper ml, l, pints etc

heady kiln
#

so i did some rotating, deleting of polygons, and squishing and shifting of the handle, and now i have a sawed off stock, but the textures have vanished and its just grey now

#

in game i mean, it was always grey in blender

calm depot
#

you might have broken the UV map

#

go into the UV part of blender and see how it's laid out

quaint mirage
heady kiln
#

i see a square

calm depot
#

yeah, that's just a blank area where you can put an image

#

just make a new one that's all white and start selecting geometry

#

it'll show you where on the image a particular polygon is textured from

heady kiln
#

doing a select all in edit mode brings up what i assume is the 2d net

calm depot
#

you can also just google "Blender UV tutorial"

#

welp, that's all out of bounds ๐Ÿ™‚

quaint mirage
#

Got another question, can you reload mods while in debug mode SP, ima assume not but just wondering

#

I usally back in and out

heady kiln
#

ok its now in the square

calm depot
#

you can get it to "reload" a Lua file, however, don't consider this a reload, consider it as simply executing the same code again

quaint mirage
#

Ok cool no prob, ill keep reloading it fully back to menu and new save

calm depot
#

so, depending on how you structured your code, it can be anything from absolutely fine, to not at all

#

unless you really understand how the re-execution of your code is going to affect the lua state, don't do it, just go back to the main menu

quaint mirage
#

Yep not a clue xD back to menu it is

heady kiln
#

indian youtube tutorial man taught me how to texture paint

#

i really hope this works

#

i put in way too much effort in the painting

#

yay, it doesnt fucking work

#

zomboid didnt load the fucking UV map

tame mulch
heady kiln
#

as far as i know, one

tame mulch
#

material only one?

heady kiln
#

uh, the youtube tutorial i followed said select smart UV project? and then i used texture paint on the model

#

ima be honest i know nothing about blender im just fumbling my way through this

#

where should i check for "material only"

tame mulch
#

Hmmm. Try another tutorial, I think it will help

#

Also you saved UV map?

#

*Object after change UV

heady kiln
#

i've saved the project as a .blend file? im guessing thats not the right thing

tame mulch
#

need fbx

heady kiln
#

oh, i did export it as a .fbx, and put it into my mod

#

thats what produced the broken texture mess

#

that i posted

#

also i know its 10x the size but its hard to work on a tiny model

tame mulch
#

Hmmmm. Can you send me mod in PM? I will try help

heady kiln
#

ok, 1 sec

#

sent it

drowsy citrus
#

I'm trying to start working with a simple script mod. I think I did lua scripting once like 10 years ago with gmod so I'm a little out of my element here. I'm trying to make a mod that sets all vehicles in the world to have a rust value of "1" for those months/years later playthroughs. Where do I start/what file am I looking to modify?

tame mulch
heady kiln
#

thanks for the help Aiteron, i have credited you in the mod description on its workshop page

blissful copper
heady kiln
#

the problem was i had no idea what i was doing, and the textures of the gun were broken or missing

blissful copper
#

the files or the xml and that stuff?

#

i'm also learning, so i'm interested lol

heady kiln
#

the model did not have textures, so it seems like it was trying to apply the default shotgun texture to the changed model

#

its on the workshop now under the name One-Handed Sawed-Off Double Barrel Shotgun, so you can download it and see for yourself how aiteron fixed it, i cant take any credit for getting the textures working

blissful copper
#

oh haha

#

very nice

drowsy citrus
gilded hawk
tame mulch
gloomy geyser
#
local playerObj = getSpecificPlayer(_player)
local playerInv = playerObj:getInventory()
local Item = playerInv:FindAll("Coffee2")

Item:delete()
calm depot
#

Yep, you didn't read what I said

#

Not only did I say that you call it on the item container, I said the function is called Remove

#

So you have somehow managed to completely ignore me and just invent what you think the code should be

#

Never mind the fact that FindAll returns an array

gloomy geyser
#

And because, actually, I'm trying to do this as a test. Because my current error is with TimedAction, which is giving some error and I suspect it was because of the item, which in the action has "self.item:delete()" in the "local function MyAction:perform()" function, so I thought which could be giving an incorrect value. I don't know how to solve this problem :/

drowsy citrus
quasi kernel
#

Now begins the ISTimedAction magic

#

@calm depot may I summon thee

calm depot
#

No, I'm smoking cigars and drunk as a skunk.

quasi kernel
#

Fair enough, I will commit summoning rituals at a future time then

calm depot
#

(you can try, but don't expect much from me)

quasi kernel
gilded hawk
#

Does anyone know where can I get free(or low cost) low poly-ish 3d models of military webbing and pouches? ๐Ÿค”
I would like to make a simple mod that adds simple gear to the game without too much bloat and dependencies

quasi kernel
#

Personally I'm asking similar for a portable hand crank

#

Tho I might just have to model it myself

#

How do I add an option to an item's context menu?

#

I want to have a "Charge Battery" option to the Hand Crank, but I'm unsure if recipes will work properly for it or not (?)

#

Actually it might nvm

gloomy geyser
#

I need to find the name of the item in my inventory, but FindAll("item"):getName() doesn't work, is there a specific get for that?

quasi kernel
#

Wouldn't FindAll be a table/array?

gloomy geyser
quasi kernel
#

Oh huh

#

:getType() is to get the name btw

gloomy geyser
#

Ohh lets see

quasi kernel
#

If you want the name specifcally with it's module as well then do :getFullType()

#

IF you only need name, IE "Battery", it's just :getType()

#

If you need the module its inheriting from, IE "Base.Battery", it's :getFullType()

gloomy geyser
#

๐Ÿค”

#

getType and getFullType are not working, it gives an error when I try to put it in FindAll(): > get <

quasi kernel
#

Hm

gloomy geyser
#

and now? :(

quasi kernel
#

I have no clue that was the best idea I had

#

Im still new to modding

gloomy geyser
#

I'm going to test things here

drifting ore
#

Has someone made a mod with all the TWD clothing

shadow geyser
# quasi kernel Actually it might nvm

you said nvm so I figure the recipe stuff was fine, but in case in future you want to add your own options, I find the easiest way is using OnFillInventoryObjectContextMenu event. here is an example.

InFridgeMenu.doMenu = function(player, context, items)
    for i,v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
                item = v.items[1];
        end
    if item:getType() == "HCCooler" or item:getType() == "HCIcechest" then
            local container = item:getItemContainer();
        if container:getType() == "fridge" then
        context:addOption("Take Coldpack out of "..item:getName(), item, InFridgeMenu.toggleCooler, player);
        else
            if getSpecificPlayer(player):getInventory():contains("Base.Coldpack") then
            context:addOption("Put Coldpack into "..item:getName(), item,  InFridgeMenu.toggleCooler, player);
        end
        end
    end
    end
end

Events.OnFillInventoryObjectContextMenu.Add(InFridgeMenu.doMenu);

gloomy geyser
#

Ahh cool, my doubt is now another ๐Ÿ˜…

#

How do I make the player equip an item in hand?

ancient grail
#

pls hellp. how do i improve my code.

 if not player:getNearVehicle() == nil then
 local car = player:getVehicle();
 else
 local car = player:getNearVehicle();
 end
 car:repair(); 
 car:getPartById("Battery"):getInventoryItem():setUsedDelta(100);
 car:getPartById("GasTank"):setContainerContentAmount(100);  
 for i = 0, car:getPartCount() -1 do local part = car:getPartByIndex(i)
 if part:getCondition() > 0 then part:setCondition(100);  
 end 
 end 
 end ```
#

@nimble valley
hi
did it work? the generator thing?

quasi kernel
quasi kernel
#

Also, robot, how would I make it hook to my custom Timed Event?

#

Is there an event for knowing when an InventoryObjectContext is activated or will I have to find another way?

proud pivot
#

is there any big modpacks that i should try out?

mellow oyster
#

How do i add new animations to zombies (Don't want to replace already existing ones, i want to add new ones)

heady crystal
#

Is it possible to create a sound emitter in a specific square?

quasi kernel
#

Found this in testtimed.lua in luaexamples

#

getSoundManager():PlayWorldSound("explode", square, 0, 20, 1.0, false);

#

Seems you can provide a specific square rather easily

heady crystal
#

Thank you!

quasi kernel
#

Yeye!

gilded hawk
#
local module = "Base"
local name = "MxDebug"
local displayname = "MxDebugName"
local type = "Clothing"
local inventoryIcon = 'WatermelonSmashed'
local item = createNewScriptItem(module, name, displayname, type, inventoryIcon);

item:DoParam("DisplayCategory = Clothing")
item:DoParam("Type = Clothing")
item:DoParam("DisplayName = Bikini")
item:DoParam("ClothingItem = Bikini_TINT")
item:DoParam("BodyLocation = Underwear")
item:DoParam("Icon = Bikini_White")
item:DoParam("Weight = 0.2")
item:DoParam("WorldStaticModel = Bikini_Ground")

print(tostring(item))
print(tostring(item:isHidden()))
print(tostring(item:getObsolete()))

Events.OnGameStart.Add(function ()
    getPlayer():getInventory():AddItem("Base.MxDebug");
end);

Please anyone from TIS Im getting this long error everytime I hove the mouse over the item I created, can some of you help me with this? I attached the error log as a file. I tried to ask other modders but no one was able to help me and I have been stuck on this for a week now

shadow geyser
quasi kernel
#

Is there a has tag function?

#

wait thats a dumb question there probably is

#

I know how to add a timed event, I just dont know how to hook it into my system

#
context:addOption("Take Coldpack out of "..item:getName(), item, InFridgeMenu.toggleCooler, player);
#

Would I just replace InFrigeMenu.toggleCooler with something like BetterBatteries.doChargeAction() and have that inititate the timedactionqueue?

#

function BetterBatteries.doChargeMenu(player, context, items)
    for i,v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
            item = v.items[1];
        end
        if item:hasTag("HandCrank") then
            context:addOption("Charge Battery with "..item:getName(), item, BetterBatteries.doChargeAction, player);
        end
    end
end
#
function BetterBatteries.doChargeAction()
    ISTimedActionQueue.add(ISChargeBattery:new(player, item, 70 + (item:getUsedDelta() * 40)));
end
shadow geyser
#

yep exactly that

quasi kernel
#

Sweet

#

Look at me go, learning things!1

#

Thank you!

shadow geyser
#

np

quasi kernel
#

Wait, would my doChargeAction be supplied with any parameters?

shadow geyser
#

oh yeah no

#

you need to pass item into the doChargeAction

quasi kernel
#

So just.. BetterBatteries.doChargeAction(player, item)

shadow geyser
#

since item is local in just the context of the doChargeMenu

#

yeah

quasi kernel
#

Ok perfect

#

How would I go about determining if the character has max exertion so I can prevent them from starting an action / quit the action early?

#

I have self.character:getMoodles() and I found the moodle class which lets me use "getMoodleLevel"

#

But I dont know how to supply a MoodleType for getMoodleLevel

#

Nor do I know if intensity is like "4" for max exertion or something like "0"

#

Found a way

#

It pops up now, but I had to remove the () and the args supplied to doChargeMenu

#

@shadow geyser Any ideas?

drifting ore
#

wheel FrontRight
{
front = true,
offset = -1 -0.26 1.63,
radius = 0.15f,
width = 0.2f,
ayo im tryna tweak something, which of these settings is basically the wheel going up and down, x/y?

#

is offset xyz?

shadow geyser
#

its basically because you need to pass the function, but its a big weird to pass also some arguments for it

#

bit*

quasi kernel
#

I think I figured it out (?)

#

Everything following the function seems to be params fed into said function

#

Up to 10 params

#

Not sure why they didnt do ... for virtually endless params but whatever lol

shadow geyser
#

yeah thats right

#

was trying to find a good example for it, but youve figured it out yourself

quasi kernel
#

Seems to be erroring regardless, probably some of the data im feeding it

shadow geyser
quasi kernel
#

yeye I did player and item

#

function BetterBatteries.doChargeAction(player, item)

shadow geyser
#

try the following

context:addOption("Charge Battery with "..item:getName(), player, BetterBatteries.doChargeAction, item);

idk why. its weird, but its what I see everywhere. the var before the function is the first param, then the ones after follow it

#

its super wierd, and I don't know why its done like that. but it is

quasi kernel
#

oh huh

#

yeah it seems to be that way

#

really weird

shadow geyser
#

you can see in line 90 in ISContextMenu

option.onSelect(option.target, option.param1, option.param2, option.param3, option.param4, option.param5, option.param6, option.param7, option.param8, option.param9, option.param10);

then the addOption is also formatted that way.

function ISContextMenu:addOption(name, target, onSelect, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)
#

super weird and I don't see the logic about it. but thats just how it is

quasi kernel
#

I think target might be seperated entirely from params (?)

#

Unsure hto

heady crystal
#

Ok so getSoundManager():PlayWorldSound() works but it sucks. I can't hear the sound unless I am very close to it regardless of the parameters apparently

quasi kernel
#

Aw heck, I'm sorry.

heady crystal
#

I wanted to be able to hear it from far away

quasi kernel
#

Hm..

#

Robot is smart, they might be able to help more than I hehe

heady crystal
#

I couldn't find what the parameters mean exactly, I assume it's name, square, minRange, maxRange, Volume, loop ? But I tried setting it to 0 min and 5000 max and it didn't work, 500 min 1500 max didn't either and so on

quasi kernel
#

I can look into the params if you'd like

#

This may be the way, just with wonky params or something

heady crystal
#

Do you know what's the difference between PlayWorldSound and PlayWorldSoundImpl ?

quasi kernel
#

There's so many functions oh my god

heady crystal
#

Yeah lol

#

And a lot of them just don't work

quasi kernel
#

PlayWorldSound, PlayWorldSoundImpl, PlayWorldSoundWav, PlayWorldSoundWavImpl

heady crystal
#

Oh boy

quasi kernel
#

There does appear to be an optional 7th argument in some of the duplicate functions

heady crystal
quasi kernel
#

..and some of the Impl have up to 9 args

#

none of which are labelled

#

aside from "var 1, var2, var3" etc..

#

Literal nightmare fuel

heady crystal
#

I get errors when trying to use Impl for some reason

quasi kernel
#

Impl seems to want generally more args compared to just regular

#

9 vs 7

#

Oh I see now

#

Impl wants the uhh

#

Coordinates

#

Not the grid square

#

PlayWorldSound uses Impl anyways

#

So just stick with it for now

heady crystal
#

Straight up copying an example with Impl doesn't work for some reason

quasi kernel
#

oh huh

#

Gonna be honest with you, I'm lost lol

heady crystal
#

Yeah me too why does stuff never just work tired

quasi kernel
#

It really be like that tho

#

Love the game too much to stop trying though

heady crystal
#

Me too but it's starting to get old

quasi kernel
#

I feel that

cyan basalt
#

i definitely got a bit burnt out as well

#

i wish we had documented java code with variable names

heady crystal
#

I don't want to have to play this on the player

quasi kernel
#

Wasn't it 42 or something when they were opening more stuff up?

#

I dont recall

cyan basalt
#

more accessibility from lua you mean?

quasi kernel
#

Yea I think

cyan basalt
#

not sure but that would be nice

heady crystal
#

There we go

#

Here we go with hardcoded stuff again ๐Ÿ‘

quasi kernel
#

Fingers crossed someone answered them

heady crystal
#

They did

#

Didn't find a solution

quasi kernel
#

oh my god

cyan basalt
#

lol my first thought there is to just play the same sound at multiple points if it can only spread that far

#

but play it at the same time

quasi kernel
#

I bet chuck knows something

#

Hey @sour island, if you're on, any idea of how to get a sound to play in world space further than like 15 tiles? Braven is having trouble with :PlayWorldSound()

#

I feel like he'd know something because of his snazzy heli mod, you can usually hear the heli from far off.

#

Though now that I think about it, that could've been using an interesting solution that just popped into my head.

#

@heady crystal, this is stupid, and obv wait until chuck responds, but I had an idea.

#

If you could somehow get the direction of the sound source, you could assign a tile about 15 units away in the direction of said sound source, and adjust the volume based on distance.

#

Hacky, yes, but it'd work assuming I understand how the system works

#

I'd recommend waiting on Chuck though, I imagine he knows something cleaner unless he used that method.

heady crystal
#

That'd be incredibly complicated since a loud enough sound would be audible in a 360 degree radius for quite the distance

#

I'd have to play sound in so many places lol

quasi kernel
#

hmm

heady crystal
#

Well I guess if there's no other way I'll have it play on the player directly and if they're outside range I suddenly cut it off

#

That's so stupid tho

autumn sparrow
#

I am new to modding Project Zomboid so this is a stupid question, but how do I pass a variable from one function to another, or is this not possible?

heady crystal
#

Use arguments and parameters. Just an example:

function A()
  local test = "Hey!"
  B(test)
end

function B(someVariable)
  print(someVariable)
end

Function B has a parameter. When it is executed, it prints whatever it received. LUA is not fully type safe so when you declare a variable it can be anything really. So I can send anything to function B. In this example, A is sending a string variable named test to B. So the variable passes from one function to the other.

#

I suck at explaining, I hope that's understandable.

autumn sparrow
#

Thank you for trying to explain. I'm going to try this out. I'm trying to read someone else's mod to learn and I'm not sure how they're able to pass the variable.

heady crystal
#

You can also have variables declared on the instance of your script that are "global" in the scope of that instance like

local test = "Hey!"

function A()
  print(test)
end

function B()
  print(test)
end

Both will result in "Hey!" as they print test, which can be accessed from anywhere within the code so long as whatever is accessing it is below the declaration.

#

You can also call a function from another script

#

I don't know much about LUA tho, this is mostly based on what I know of programming in general.
I'd watch a few LUA tutorials if I were you, to get the hang of it. It can be a very annoying language to try to learn on your own.

#

LUA isn't beginner friendly

autumn sparrow
#

Thanks. I've been at this for days lol I read up on it and I've started to get some things to work, but some things are annoying me.

cyan basalt
#

and when you add a listener to an event the event will pass vars to the functions as well

halcyon dagger
#

hey qq, trying to read the server stats with getServerStatistics() but I can't enable the server stats with setServerStatisticEnable(true). Any ideas? ๐Ÿค”

heady crystal
#

Does this game seriously not have a distance from player to square method? Come on

autumn sparrow
quasi kernel
#

@shadow geyser Does the OnFillInventoryObjectContextMenu and the function it connects to have to be client side for the timed action to work?

shadow geyser
#

yeah

#

the server doesn't do anything for OnFilInventoryObjectContextMenu, and all the timed actions in vanilla are also in client side, so server shouldn't need any of it

halcyon dagger
quasi kernel
#

I'm pretty sure this is set up correctly.

#
function BetterBatteries.doChargeAction(item, player)
    print(tostring(ISChargeBattery))
    ISTimedActionQueue.add(ISChargeBattery:new(player, item));
end
#

It's not detecting ISChargeBattery as a valid thing though.

#
require "TimedActions/ISBaseTimedAction"

ISChargeBattery = ISBaseTimedAction:derive("ISChargeBattery");

function ISChargeBattery:isValid()
    return (self.character:isPrimaryHandItem(self.handCrank) or self.character:isSecondaryHandItem(self.handCrank)) and self.handCrank:getUsedDelta() < 1 and self.character:getMoodles():getMoodleLevel(MoodleType.Endurance) < 4
end

function ISChargeBattery:waitToStart()
    return false
end

function ISChargeBattery:update()
    self.character:setMetabolicTarget(Metabolics.HeavyDomestic);
end

function ISChargeBattery:start()
    self:setActionAnim("Craft")
    -- Don't call setOverrideHandModels() with self.petrol, the right-hand mask
    -- will bork the animation.
    self:setOverrideHandModels(self.handCrank:getStaticModel(), nil)
    self.sound = self.character:playSound("GeneratorRepair")
end

function ISChargeBattery:stop()
    self.character:stopOrTriggerSound(self.sound)
    ISBaseTimedAction.stop(self);
end

function ISChargeBattery:perform()
    self.character:stopOrTriggerSound(self.sound)

    while self.handCrank and self.handCrank:getUsedDelta() < 1 and self.character and self.character:getMoodles():getMoodleLevel(MoodleType.Endurance) < 4 do
        self.handCrank:setUsedDelta(self.handCrank:getUsedDelta() + 0.01)
        self.character:getStats():setEndurance(self.character:getStats():getEndurance() - 0.0002)
    end

    if self.character:getMoodles():getMoodleLevel(MoodleType.Endurance) >= 4 then
        self.character:Say("I'm too tired to keep doing this..")
    end
    
    -- needed to remove from queue / start next.
    ISBaseTimedAction.perform(self);
end

function ISChargeBattery:new(character, handCrank, time)
    local o = {}
    setmetatable(o, self)
    self.__index = self
    o.character = getSpecificPlayer(character);
    o.handCrank = handCrank;
    o.stopOnWalk = false;
    o.stopOnRun = true;

    print("Doing some cool stuff! Yeaaaah!")

    o.maxTime = time;
    --if o.character:isTimedActionInstant() then o.maxTime = 1; end
    return o;
end
#

pleh I need to get funny uhhh

#

thing set up

#

Yo the man is here!!

sour island
#

@heady crystal sounds can be scripted much like items. You can set min and max distance. I use world emitters for EHE.

quasi kernel
#

Thank you Chuck

heady crystal
#

Wait a second

#

You're right

#

I was so focused on it not working that I never stopped to think that maybe the sound itself was limiting it

#

Which is still a dumb concept, I'll die on this hill

#

But let's see if it works lol

#

I can't make it compatible with true music this way I imagine tho, I'll have to stick with having it play on the player I guess

quasi kernel
#

ISChargeBattery isn't being recognized as a thing despite the fact it's in a similar directory, derives from ISBaseTimedAction, and is a global

shadow geyser
#

UI stuff is funky. if the UI is created calling the ISChargeBattery before the ISChargeBattery is declared in its file, I think it will stay nil, because of the funky UI behavior. so even if you change the ISChargeBattery so something valid later, it broke because it wasn't valid beforehand

cosmic quiver
#

anyone know a good mod that increases item transfer speed

quasi kernel
shadow geyser
#

yep, the one where you are adding the context menu

quasi kernel
#

Ohh ok

final ridge
#

anyone online in here to help me with a clothing item script, dm me pls โค๏ธ

quasi kernel
#

Still nada @shadow geyser

shadow geyser
#

you have the wrong number of parameters

#

I think lua resolves it differently depending on the number of parameters you give

#

but im not sure, but atleast that should be fixed

#

your new is defined as following

function ISChargeBattery:new(character, handCrank, time)

but you are only giving the following

ISTimedActionQueue.add(ISChargeBattery:new(player, item));
#

need to pass the hand crank as well

quasi kernel
#

isn't item the handcrank?

#

I think I forgot time lol

shadow geyser
#

ah time is missing

#

its almost 4am rn for me. shouldn't be awake rn XD

quasi kernel
#

Still got the same error

#

Also heck, if you gotta go sleep then go sleep lol

#

Dont let me keep you upp

shadow geyser
#

can you show the entire file for the UI part please

quasi kernel
#

yeah

#

lemme do it on pastebin or something

shadow geyser
#

thats youre ISChargeBattery file. Also i don't think the require "ISChargeBattery" is doing anything. it should be in the file making the context menu

mellow oyster
#

How do i add new animations to zombies (Don't want to replace already existing ones, i want to add new ones)

quasi kernel
#

oh im dumb mb

#
BetterBatteries = {}

function BetterBatteries.doChargeAction(item, player)
    print(tostring(ISChargeBattery))
    ISTimedActionQueue.add(ISChargeBattery:new(player, item, 100));
end

function BetterBatteries.doChargeMenu(player, context, items)
    for i,v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
            item = v.items[1];
        end

        if item:hasTag("HandCrank") and not item:getModData().batteryRemoved then
            context:addOption("Charge Battery with "..item:getName(), item, BetterBatteries.doChargeAction, player);
        end
    end
end

Events.OnFillInventoryObjectContextMenu.Add(BetterBatteries.doChargeMenu);
shadow geyser
#

also might as well put that file into the TimedActions folder, just for organization purposes

quasi kernel
shadow geyser
quasi kernel
#

Still nada, mfw

shadow geyser
#

same error?

quasi kernel
#

Does it hurt that ISChargeBattery is in it's own folder for directory purposes?

shadow geyser
#

should be fine as long as you give the path properly in the require statement

quasi kernel
#

I changed it to TimedActions/ISChargeBattery

shadow geyser
#

so if it is inside TimedActions, it would be require "TimedActions/ISChargeBattery"

quasi kernel
#

Aaaand it still borked

#

I'm open to just trying this tomorrow if you wanna sleep btw lol

shadow geyser
#

yeah. Ill try to think about it tomorrow with some more sleep in me

quasi kernel
#

Oki!

#

Rest well my friend, thank you for your help once again.

jagged ingot
#

Hey. Am currently looking for mods that people write extended mods requiring them. I'm looking to write typings for those mods. Please let me know if you think of one that is popular and that'll help me out a lot. Thanks.

gilded hawk
jagged ingot
#

@gilded hawk I'll look it up! Thanks!

#

The idea is to write typings to help people who might be interested in writing Typescript mods.

jagged ingot
mellow oyster
hollow violet
#

my mods wont load

cyan basalt
cyan basalt
#

do you guys know if there's something I have to do to get player:setX() to do something? I can't see a visible change and it doesn't update the value

#

does it have to be serverside or something?

#

i would have thought in singleplayer it would still work in a client script though

jagged ingot
#

Either way the client sends the next coordinates until instructed otherwise.

#

All setX() does is set the variable for the server to track where it thinks the player is at.

#

(IIRC)

#

So either send the teleport packet or send the client via Lua command API to set there.

cyan basalt
#

ahhhh I see that actually makes so much sense thank you

cyan basalt
jagged ingot
#

I just double-checked and the teleport commands only sends packets to instruct the client the new coordinates.

cyan basalt
#

ahhh I see

#

so if I set the coords client side and then called the server to set them serverside would that suffice?

#

rather than sending the teleport packet?

jagged ingot
#

The client is the authority for player's position coordinates.

cyan basalt
#

ah I see

#

so what would I need to do then? sorry I think I'm confused lol

jagged ingot
#

Send the info to the client and then set the coordinates there. I believe that should work.

cyan basalt
#

okay so a onServerCommand or whatever it is and then player.setX/Y in there?

jagged ingot
#

Yeah.

cyan basalt
#

weirdddd okay

#

if the client is the authority i would have though I could just set it clientside. guess I still have a lot to learn lol

jagged ingot
#
sendServerCommand(isoPlayerObject, 'my_module_id', 'teleport_player', {x, y, z});
cyan basalt
#

is that using the built in teleport method?

#

and that would be from the client itself?

jagged ingot
#

Nope. It's me sending over coordinates to the client.

#

That would be going to the client.

#

so OnServerCommand listens for sendServerCommand. This is the same for client commands.

cyan basalt
#

Ohhhh gotcha okay

#

Wait so if the client manages worldpos why couldnโ€™t I just set it in client?

jagged ingot
#

All that is basically sending data Client <-> Server.

cyan basalt
#

How does receiving from the server change that?

jagged ingot
#

If you have it on the client-side, then simply set it there.

#

I assumed you were operating on the server-side.

cyan basalt
#

I was just messing in sp

jagged ingot
#

Ahhhh.

cyan basalt
#

And I have a key press that updates the x pos by the previous + 10

jagged ingot
#

I completely misunderstood your issue.

#

I work so much on server stuff.

cyan basalt
#

All good! I didnโ€™t explain very well haha

#

I mean thatโ€™s good to know for the future still

#

But yeah updating the coords doesnโ€™t change anything on client

jagged ingot
#

Hmmm

#

Are you writing this in Lua?

cyan basalt
#
function addLift(key:number){
    if (!(key === Keyboard.KEY_Q)){
        return;
    }
    let player = getPlayer();
    player.setX(player.getX() + 10);

}

onKeyPressed.addListener(addLift);```
#

pipewrench ๐Ÿ˜

jagged ingot
#
player.setPosition(x, y, z);
#

Try that.

#

It sets a few fields in IsoPlayer, which might be what allows the player to be teleported properly.

cyan basalt
#

Iโ€™ll see thanks!

jagged ingot
#

Are you trying to make the player go up in the air? (Looking at the function's name)

#

If so, that'd be the Z axis.

cyan basalt
#

I was at first but then that wasnโ€™t working so I tried X

jagged ingot
#

Z will be that axis.

#

X,Y are lon and lat basically but in world coords.

#

You'd be teleporting a player above the highest floor IIRC. (0-7)

cyan basalt
#

Ah I see

#

But yeah x wasnโ€™t working either

random finch
#

Is there a way to set access level other than these 2 methods? If your client is not admin, then they will not work.
playerObj:setAccessLevel("admin");
and this:
local command = string.format("/setaccesslevel %s admin", tostring(playerObj:getUsername())); SendCommandToServer(command);

frail dagger
#

I'm making my first mod. I'm trying to make a temporary effect based on which item a zombie was killed with.
Anyone know which event to use and how to get that information?
I found onZombieDead event, but i don't know how to get the info i need regarding the weapon used to kill it, or the player who killed it.

shadow geyser
frail dagger
#

I found isAlive(), but I'm also trying to figure out lua syntax, so it's taking a bit longer than I'd like

shadow geyser
frail dagger
#

Question:
Am I using this isAlive() correctly?
I'm not getting any errors in my debug, but it's not reading the if else

local function onHit(zombie, player, bodyPartType, weapon)
    if zombie:isAlive()
        player:Say("Hyaa")
    else
        player:Say("Got'em")
end

Events.OnHitZombie.Add(onHit)
smoky meadow
#

guys help how to disable a script using LUA.

cosmic condor
smoky meadow
#

but disable it so it can't be called.

cosmic condor
#

manifest your intentions or give an example of what are you trying to do

smoky meadow
cosmic condor
#

so you are going to create a mod that patch this specific mod, right?

cosmic condor
#

you have to make this mod as a requirement to ensure load order

#

then create a script file with the same name, but remove all items scripts in that file

#

never do this myself but I assume it should work lol

cosmic condor
#

but there can be many ways to make this thing work, my solution might not be the best

smoky meadow
cosmic condor
#

who gonna sue you? ๐Ÿ˜…

smoky meadow
lunar robin
#

Any updates on this, pal?

cosmic condor
smoky meadow
#

no rather i will ask him.

frail dagger
# frail dagger Question: Am I using this isAlive() correctly? I'm not getting any errors in m...

I've been able to correct my syntax issues by looking at some other mods.

local function onHit(zombie, player, bodyPartType, weapon)
    if zombie:isAlive() then player:Say("Hyaa");
    else player:Say("Got'em")
    end
end

Events.OnHitZombie.Add(onHit)

However, now I know isAlive() isn't what I'm looking for because it always returns true since the zombie never dies before OnHitZombie is invoked.
Anyone know how I can get if the zombie died from the attack?

shadow geyser
#

try checking the health. of the zombie maybe?

frail dagger
#

I don't think the health updates before the call is invoked, but i can give it a shot

shadow geyser
#

or you could do something more fancy. have a table on which you store the zombie you attacked. So you end up using 2 events. The OnHitZombie one, to get the weapon, then store it in the table. then use the OnZombieDie. from there, you check what that zombie was hit with from your table to do what you want.

#

would just need to figure out some sort of identifier for the zombie. I'm not sure if they are hashed, but might be worth looking into

frail dagger
shadow geyser
#

you can have as many lines of code using the local tracker = require "zombietracker" and the table will be the same shared table

frail dagger
#

Interesting.. I'll need to look up how tables work. Then I'll need to figure out how to update the table to make sure I'm only getting the zombie I need, since i'm trying to make it for MP

#

Thanks for the idea

shadow geyser
#

yeah would be interesting to make it work in MP. Im not sure where the onzombiedead and onzombiehit are called in MP, if client or server. I would think on client side but im not sure

frail dagger
#

I would definitely have thought that the devs would at least have a function to get the character that killed another. Aren't there mods that have that though? Like some of the log outputs can tell admins who killed who or what.. So I'm curious why that's not a public function ๐Ÿค”

I've seen getAttackedBy(), but it's null when OnZombieDead event is called

smoky acorn
#

I'm making gun attachment but when i upgrade my gun with it ,the attachment model don't appear, anyone knows it?

quaint mirage
smoky meadow
#

guys how to play sound using LUA code.

frail dagger
# shadow geyser yeah would be interesting to make it work in MP. Im not sure where the onzombied...

So... it turns out, getAttackedBy() does indeed work when getting the character who killed the zombie on OnZombieDead.
The first time I tried it, I must've been using the wrong syntax or something.

local function onDead(zombie)
    local player = zombie:getAttackedBy()
    player:Say("Got'em")
end

Events.OnZombieDead.Add(onDead)

This was all that was required. I thought something was fishy if we couldn't access something like that lol

smoky acorn
random finch
smoky meadow
# smoky acorn it didn't work

did you add this on your script?

model (your attachment)
{
mesh = Weapons/parts/(your attachment model),
texture = Weapons/parts/(your attachment texture),
}

#

this is not a WorldItem Model but a Static one

smoky acorn
quaint mirage
#

Hey don't suppose someone could give me advice how i can get reference to the First petrol container with some used delta left, this is my first attempt but i cant seem to access it

#
CraftAndRefillLighters = {}

function CraftAndRefillLighters.doFillGasAction(item, player)

end

function CraftAndRefillLighters.doCreateMenu(player, context, items)
    local petrolContainerToUse;

    for i,v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
            item = v.items[1];
        end

        if item:getType() == "WinePetrol" then
            petrolContainerToUse = item;
        end
    end

    -- Find lighter items to add Refil context menu to
    for i,v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
            item = v.items[1];
        end
        if item:getType() == "Lighter" then
            if item:getUsedDelta() < 1 then
                context:addOption("Refill Lighter", item, CraftAndRefillLighters.doFillGasAction, player);
                if petrolContainerToUse then
                    context:addOption("Refill Lighter with " + petrolContainerToUse:getName() , item, CraftAndRefillLighters.doFillGasAction, player);
                end
            end
        end
    end
end

function CraftAndRefillLighters.DepleteGas(items, result, player)
    result:setUsedDelta(0);
end

Events.OnFillInventoryObjectContextMenu.Add(CraftAndRefillLighters.doCreateMenu);
#

Is there another way i can get hold of it more efficiently than this ? ๐Ÿ˜›

#

You can see adding to the menu works, but when i want to reference an item im trying to find im having issues

#
if petrolContainerToUse then
    context:addOption("Refill Lighter with " + petrolContainerToUse:getName() , item, CraftAndRefillLighters.doFillGasAction, player);
end
quasi kernel
#

Wait did you get the action working @quaint mirage?

#

I've been encountering an error that prevents it from executing

#

Also @shadow geyser I'll be back later, I have Sunday chores to deal with

quaint mirage
#

Ur code helped me add a custom menu item based on whats in my inv but havent done any logic on the event yet

quasi kernel
#

Ah I see

quaint mirage
#

I want to pair it with needing any type of Petrol container, it doesnt seem to either set the local variabble or create the item with concatenated item name

#

Fill Lighter with Bottle Of Gasoline is what i want

quasi kernel
#

I think I see your problem

#

You're indexing a specific type of gas container instead of using the gas container tag

#

You're using "WinePetrol" which if I'm assuming correctly is a wine bottle full of... petrol.

#

It won't identify regular bottles or gas cans.

quaint mirage
#

Yep that was for testing i tried hasTag("Petrol")

quasi kernel
#

Ah I see

quaint mirage
#

In lua you concat with .. is that right? ๐Ÿ˜„

quasi kernel
#

Correct

quaint mirage
#

Ill look more into probably something minor, banging my head againt the wall on it

quasi kernel
#

Just make sure you use tostring() because otherwise it can get angry

#

(unless it's already a string then it won't cause problems)

ancient grail
quaint mirage
#

@quasi kernel only ever finds the item i right click on by looks of it, is there another way to search inventory only at same time

quasi kernel
#

Yeah I think so

#
getSpecificPlayer(player):getInventory()
#

Then you can loop through the inv for an item that matches your criteria

quaint mirage
#

Thanks

quasi kernel
#

(thank you robot I shamelessly ripped that code lol)

quaint mirage
#

Does this need ipairs like the other loops at all?

quasi kernel
#

I believe so, though it may also be a :get and :size type

#

Experiment a bit

quaint mirage
#

Thanks again

quasi kernel
#

Np!

quasi kernel
#

@shadow geyser ready when you are

#

Actually, @thin hornet, may I call upon your wisdom once more?

#

I searched through discord to see if anyone had any knowledge on TimedActions and you seem to know a thing or two

shadow geyser
quasi kernel
#

I could always send a zip

#

Unless that's too strange aa

shadow geyser
#

sure. idk if you can send in this channel, if not just dm it to me

quasi kernel
#

Ill send it via DMs, gimme a second

quaint mirage
# quasi kernel ``` getSpecificPlayer(player):getInventory() ```

I finally got it working thanks to this

CraftAndRefillLighters = {}


-- When the Refill lighter action is clicked
function CraftAndRefillLighters.doFillGasAction(item, player)
    -- Todo
end

-- Create the context menu for a specific item, when lighter we want to allow refils from gas cans, so both need to be within the inventory.
function CraftAndRefillLighters.doCreateMenu(player, context, items)
    -- Find lighter items to add Refil context menu to
    for i, v in ipairs(items) do
        local item = v;
        if not instanceof(v, "InventoryItem") then
            item = v.items[1];
        end

        if item:getType() == "Lighter" then
            if item:getUsedDelta() < 1 then
                local petrolItem = nil;
                local playerInv = getSpecificPlayer(player):getInventory();
                for x = 0, playerInv:getItems():size() - 1 do
                    local vItem = playerInv:getItems():get(x);
                    print(tostring(vItem:getName()));

                    if (vItem:hasTag("Petrol") or vItem:getType() == "PetrolCan") and vItem:getUsedDelta() > 0 then
                        context:addOption("Refill Lighter with " .. vItem:getName(), item, CraftAndRefillLighters.doFillGasAction, player);
                    end
                end
            end
        end
    end
end


-- As soon as a player crafts a lighter, set usedDelta to 0
function CraftAndRefillLighters.DepleteGas(items, result, player)
    result:setUsedDelta(0);
end

Events.OnFillInventoryObjectContextMenu.Add(CraftAndRefillLighters.doCreateMenu);
quasi kernel
#

Ohh I see how, you didn't make a custom timed action

quaint mirage
#

Not yet, thats the next bit xD

zenith smelt
#

Anyone know what does getPlayer() give me when I use it in script in the server folder?

#

Or is there a way to check if a player is local?

#

in the OnPlayerUpdate event

#

is isLocalPlayer reliable to have scripts only run on the player that the current client controls?

quaint mirage
#

Think i need to figure out timed actions too, i followed a guide but cant seem to get them working, just errors out here

#

in media/lua/TimedActions

require "TimedActions/ISBaseTimedAction"

LighterRefillAction = ISBaseTimedAction:derive("LighterRefillAction");

function LighterRefillAction:isValid() -- Check if the action can be done
    return true;
end

function LighterRefillAction:update() -- Trigger every game update when the action is perform
    print("Action is update");
end

function LighterRefillAction:waitToStart() -- Wait until return false
    return false;
end

function LighterRefillAction:start() -- Trigger when the action start
    print("Action start");
end

function LighterRefillAction:stop() -- Trigger if the action is cancel
    print("Action stop");
    ISBaseTimedAction.stop(self);
end

function LighterRefillAction:perform() -- Trigger when the action is complete
    print("Action perform");
    ISBaseTimedAction.perform(self);
end

function LighterRefillAction:new(character) -- What to call in you code
    local o = ISBaseTimedAction.new(self, character);

    o.character = character;
    if o.character:isTimedActionInstant() then
        o.maxTime = 1;
    else
        o.maxTime = 30;
    end
    return o;
end
#
-- When the Refill lighter action is clicked
function CraftAndRefillLighters.doFillGasAction(item, player)
    ISTimedActionQueue.add(LighterRefillAction:new(player));
end

#

I found this?

halcyon dagger
tame mulch
tame mulch
halcyon dagger
#

kk just thought someone might know ๐Ÿ™‚

quaint mirage
quasi kernel
#

How does one get the player's current strength?

#

I'm looking in the :getStats() docs but there doesn't appear to be a :getStrength() method

#

There's a :getFitness() but that's not what I need

tame mulch
quasi kernel
#

Tysm

quaint mirage
#

So when i pass player in it's 0, do i need to run through getSpecificPlayer first?

#
OG  : General     , 1661703756456> Bottle of Gasoline
LOG  : General     , 1661703756456> Gas Can
LOG  : General     , 1661703756457> Gas Can
LOG  : General     , 1661703756457> Lighter
LOG  : General     , 1661703756457> Lighter
LOG  : General     , 1661703757383> Do the gas action, try prining the player...
LOG  : General     , 1661703757383> 0
LOG  : General     , 1661703757383> -----------------------------------------
STACK TRACE
-----------------------------------------
function: new -- file: LighterRefillAction.lua line # 39 | MOD: Craft and Refill Lighters
function: doFillGasAction -- file: lighter.lua line # 10 | MOD: Craft and Refill Lighters
function: onMouseUp -- file: ISContextMenu.lua line # 90 | Vanilla

LOG  : General     , 1661703757383> Object tried to call nil in new
ERROR: General     , 1661703757384> ExceptionLogger.logException> Exception thrown java.lang.RuntimeException: Object tried to call nil in new at KahluaUtil.fail line:82.
ERROR: General     , 1661703757384> DebugLogStream.printException> Stack trace:
java.lang.RuntimeException: Object tried to call nil in new
quasi kernel
#

Believe so

quaint mirage
#
-- When the Refill lighter action is clicked
function CraftAndRefillLighters.doFillGasAction(item, player)
    print("Do the gas action, try prining the player...");
    print(tostring(getSpecificPlayer(player)));

    ISTimedActionQueue.add(LighterRefillAction:new(getSpecificPlayer(player)));
end

ok giving it a spin

#

Think i'm in business now thanks @tame mulch and @quasi kernel

quasi kernel
#

Should a hand crank increase fitness or strength?

weak sierra
#

why does it chuck errors at me for running transmitModData after getting and changing some mod data via indexing into it?

#

the error doesn't really specify a problem just the line

#
            if hb_ItemProvidesSlot(pack,slotDef.type) then -- does our backpack provide this attachment?
                item:getModData().hbSlot = ""..tostring(slotDef.type)
                table.insert(itemsToMove,item)
                item:transmitModData()
            end```
#

it just goes "yeah the line where u transmit the mod data, that's an error"

weak sierra
#

if u mean for a flashlight

#

they don't have much resistance ive used em

quasi kernel
#

Fair point

quasi kernel
#

I don't 100% know how much effort would have to go into fully charging a battery

quaint mirage
#

Ok one more question and i think it might be the last for now ๐Ÿ˜„

-- When the Refill lighter action is clicked
function CraftAndRefillLighters.doFillGasAction(ligher, player, fuelSource)
    ISTimedActionQueue.add(LighterRefillAction:new(getSpecificPlayer(player), ligher, fuelSource));
end

and

context:addOption("Refill Lighter with " .. vItem:getName(), item, CraftAndRefillLighters.doFillGasAction(item, player, vItem), player);

If i manually pass parameters like this the context menu doesn't close, is there a way for me to stop this or provide the data to the timed action in another way?

quasi kernel
#

Don't pass params like that

#

addOption functions starngely

#

The "item" you pass first is the first param

#

Everything after CraftAndRefill are params 2-10

quaint mirage
#

Yeah i get what its doing the params passed anon but i wondered how i can pass extra stuff

quasi kernel
#

So treat the arg before CraftAndRefill as param 1

#
context:addOption("Refill Lighter with " .. vItem:getName(), item, CraftAndRefillLighters.doFillGasAction, player, vItem);
quaint mirage
#

So currently it renders like this, which is ideal because later i want to have it show how many units are left

#

Maybe i can find a way to group them later kind of like the Attach to belt stuff

quasi kernel
#

hm

#

mayb

#

I do have a question of my own though, is it at all possible to adjust the maxTime dynamically?

quaint mirage
#

I static coded one in but looks like you can

quasi kernel
#

I need to do so since my action will take an indeterminate amount of time, as it changes based on strength, fitness, current exertion, and current battery charge.

quaint mirage
#

I wondered if i can pass the event down to tell the UI to close, not much else errors there

quasi kernel
#

@shadow geyser any ideas?

#

Just gotta get this one thing done and I can make the other hand crank texture, soup it up real nice, then make battery packs

#

Then the thing is basically done

quaint mirage
quasi kernel
#

yeye

quaint mirage
# quasi kernel I need to do so since my action will take an indeterminate amount of time, as it...

Would it work to take this from the base and override it in your timed action?

function ISBaseTimedAction:adjustMaxTime(maxTime)
    if maxTime ~= -1 then
        -- add a slight maxtime if the character is unhappy
        maxTime = maxTime + ((self.character:getMoodles():getMoodleLevel(MoodleType.Unhappy)) * 10)

        -- add more time if the character have his hands wounded
        if not self.ignoreHandsWounds then
            for i=BodyPartType.ToIndex(BodyPartType.Hand_L), BodyPartType.ToIndex(BodyPartType.ForeArm_R) do
                local part = self.character:getBodyDamage():getBodyPart(BodyPartType.FromIndex(i));
                maxTime = maxTime + part:getPain();
            end
        end

        -- Apply a multiplier based on body temperature.
        maxTime = maxTime * self.character:getTimedActionTimeModifier();
    end
    return maxTime;
end
quasi kernel
#

oo I didnt even know that was a thing

random finch
random finch
quasi kernel
#

Is there a maximum to how much pain a limb can experience?

#

If so, I'd like to balance my multiplier based off of that, so my charge speed is slower the more pain my hand is in

gloomy geyser
#

How do I do an if to check if I have one of the items in my inventory from a table?

halcyon dagger
#

can you get player info of offline players? ๐Ÿค”

gloomy geyser
#

Nop

#

I want to check items

#

In an if, to know whether or not this item is in the player's inventory

#

Well, I think doing:

if playerInv:contains("item1") or playerInv:contains("item2") or playerInv:contains("item3") then end

I don't think it's that efficient :(

#

So, I wanted to check in an IF somehow if there is this item in the player's inventory, like this:

local items = {
"Item1",
"Item2",
"Item3"
}

if playerInv:contains(Items) then end
#

but this method doesn't work :( so is there a correct way to do this?

random finch
gloomy geyser
#

wow, thanks. i will test here

quasi kernel
#

Wouldn't something like ["hat1"] = true and hats[items:get(i):getType()] be more efficient due to dictionary indexing?

#

(Not that I'm saying this doesn't work, dictionaries are just muy epic)

random finch
#

Ive never really used them I guess

quasi kernel
#

Valid

random finch
#

How would that work>

quasi kernel
#

Basically, how an dictionary works is it uses "keys" and "definitions"

#

Think of an actual dictionary.

#

You look up a word, you get it's definition

#

So if you do hats["hat1"] and the definition in the dictionary of hats1 is true, you'd get true

#

So for example

#
local hats = {
  ["hat1"] = true;
end

print(tostring(hats["hat1"])) -- true
print(tostring(hats["hat2"])) -- nil
#

I hope that makes a bit of sense

#

This is just an optimization suggestion, alternatively you could make use of zomboid's tag system, but that's a whole other thing.

random finch
#

It does make sense.

quasi kernel
#

Yeye!

random finch
#

Appreciate that, I may have use for it yet

quasi kernel
#

Hehe np

shadow geyser
quasi kernel
#

I need to adjust maxTime dynamically so my action won't get cut off after like 5 seconds of charging

#

I want the player to keep charging

shadow geyser
#

why don't you just set it -1 . I think -1 stops it from doing anything

quasi kernel
#

that's a thing?

#

huh

shadow geyser
#

then the action will just last however long you tell it to last in the beginning

quasi kernel
#

Yeah but that's the problem

#

I'm gonna need some stupid equation just to calculate the time it'd take, and it wouldn't even be reliable

drifting ore
#

anybody here take commissions?

shadow geyser
#

well, you need to do that anyways if you want the progress bar to be meaningful

quasi kernel
#

@jagged ingot

#

Is there not a setProgressBar method or something I can use?

#

Because then I can just make the progress bar correspond to my battery charge.

#

The entire problem is that it changes endurance as it like

#

Charges

#

And the endurance modifies how much is charged

#

ntm the player can walk and do the action at the same time which can also drain endurance depending on the load

#

found it

gloomy geyser
quasi kernel
#

self.action:setTime(math.max(self.object:getWaterAmount(), 100))

red rapids
#

hello can someone help me i have a few questions about modifying a mod

#

the mod noir does not support some authentic z backpacks and to add the backpack what do i need to do i am looking at the structure of one back and it looks something like this

shadow geyser
# quasi kernel found it

oh I see. well then im not sure how you would get a proper progress bar, you might have better luck making repeated Timed actions, andyou would recalculate it every time. so you would have one action for each unit charged

red rapids
#

can i copy the whole script and just change the name for the one of the backpack i want or does it not work like this

shadow geyser
# quasi kernel ntm the player can walk and do the action at the same time which can also drain ...
function ISAddPollenAction:perform()

    local inv = self.character:getInventory()
    local count = inv:getItemCount("Hydrocraft.HCPollen")

    local args = { x = self.beehive.x, y = self.beehive.y, z = self.beehive.z}
    inv:Remove("HCPollen");
    sendClientCommand(self.character, 'Beehive', 'addPollen', args)
    -- needed to remove from queue / start next.
    ISBaseTimedAction.perform(self);
    count = count - 1

    -- add 2 week_unit to check if new action is needed because beehive.pollenAmount wont update immediately
    if ((self.beehive.pollenAmount + 2*Beehive.week_unit) <= self.beehive.honeyMax and count > 0) then
        -- queue up another pollen action if the beehive has the space for it.
        ISTimedActionQueue.add(ISAddPollenAction:new(self.character, self.beehive, 100))
    end

end

just do it like this to make the repeated actions. obvs you would be recalculating the time for the action as well

quasi kernel
#

oo i see

quasi kernel
#

How do I get it to respect game time?

#

In other words, faster game speed make it go nyoom

quasi kernel
#

There's gotta be a way to get elapsed time to calculate speed right-

#

I don't believe os.clock() would be reliable since it's not dependant on game speed

#

I need a time variable that is dependant on game speed.

calm depot
#

so uh, you're trying to make the action work even when the player is running/sprinting around instead of walking?

quasi kernel
#

I'm not too worried about that anymore

#

I only wanted it to be walking lol

#

Robot found a solution that satisfies me

calm depot
#

OK, cool, because that would be a lot of additional complexity for not much real gain

quasi kernel
#

Now I'm just worried about adjusting :update() to game speed

#

Because it's per tick, but ticks don't update based on game speed

calm depot
#

anyway, as for making the operation take the correct amount of time; the code for refuelling from a gas pump does this

quasi kernel
#

And nor does os.clock (I don't even know if Kahlua respects os.clock)

calm depot
#

yeah, don't use os.clock - look at how they do the time calculation for refuelling, that's all you need

quasi kernel
#

"ISAddFuel"?

#

I think that's for gens-

#

Probably something else

#

Ah, ISTakeFuel

#

Seems to be using :getJobDelta()

calm depot
#

well yeah, because that delta value essentially represents the increment between the last call to update() and the current call to update

#

AKA, the delta ๐Ÿ˜›

quasi kernel
#

so like

#

job 1 vs job 2

#

would be delta 1

#

I think?

calm depot
#

I believe the value depends on how quickly the game is running, and also how frequently the game is able to invoke your update function

#

print the value of getJobDelta to the console and you'll see

#

(and print it from your update function)

quasi kernel
#

It seems to be more like a "job completion" delta more than anything

polar gyro
#

Can anyone tell me how to add custom occupations in current cities? I mean they do spawn as unemployed, but I want to add custom ones to them with default "city spawns".

#

I tried to find mod analogue but can't somehow

calm depot
#

what do you see when you print the value out?

quasi kernel
#

a 0-1 value

#

Nothing more, nothing less.

#

Likely representing the progressbar completion.

calm depot
#

show me a few lines of output

quasi kernel
#

It just progressively increases until it strikes 1, then resets because a new job is called.

calm depot
#

ah OK, yes. that should be dependent on what you configure in your start() using self.action:setTime()

quasi kernel
#

Well, until it strikes one or the action ends prematurely.

#

Isn't set time just the action duration?

#

I dunno if what I have is even compatible with getJobDelta because of how it's set up

#
function ISChargeBattery:update()
    print(self:getJobDelta())
    local strength = self.character:getPerkLevel(Perks.Strength)
    local currEnduranceLevel = self.character:getMoodles():getMoodleLevel(MoodleType.Endurance)
    if self.handCrank and self.handCrank:getUsedDelta() < 1 and self.character and currEnduranceLevel < 4 then
        local unhappiness = (1 - self.character:getMoodles():getMoodleLevel(MoodleType.Unhappy)/4)
        self.handCrank:setUsedDelta(self.handCrank:getUsedDelta() - ((self.handCrank:getUseDelta() * ((0.002 * (math.pow(strength, 2)) + 0.17 * strength + 0.1)) * (1 - (currEnduranceLevel/4) * (1/(unhappiness+1))))) * getGameSpeed())
        self.character:getStats():setEndurance(self.character:getStats():getEndurance() - 0.00005 * getGameSpeed())
    end
end
#

It gets the strength, current endurance level, current unhappiness level, and goes.

calm depot
#

at the start of the action, you should calculate the total amount of time it will take to completely fill the battery and pass that to setTime

quasi kernel
#

Don't mind game speed, that was an old solution.

calm depot
#

then, in your update function, getJobDelta() is essentially the fraction of completion

quasi kernel
#

That's the problem, how do I do that? The time can vary greatly and will increase/decrease because of endurance and the like.

#

I'd have to do some over the top formula, and there's still a risk it could end before it's supposed to be finished because the character could be walking with a heavy load, further reducing endurance more than expected

#

And preventing the player from walking would just be awkward with something like this

calm depot
#

so, the way I would suggest doing it is like this:
at the start, compute a modifier value based on current exertion and remember what their exertion was.
If at any time during a call to update() you find that their tiredness has changed, requeue your action so that start() will be called and you can end the current one

#

this will result in the user seeing a fresh progress bar, but this makes more sense because the amount of time it's going to take has changed anyway

quasi kernel
#

hm

#

What even is "time" anyways? Is it ticks? Elapsed in-game time? Elapsed computer time..?

#

I'd need to base it around whatever it is correctly

calm depot
#

it corresponds to the in-game clock

quasi kernel
#

Ok, so 60 is an in-game minute.

calm depot
#

the only thing you should be doing is computing the value you want to pass to setTime()

#

you don't need to care about game speed or anything like that because getJobDelta() is the representation of how much time has elapsed relative to how long you said it should take to complete

quasi kernel
#

I see

#

Welp, time to figure out a formula

calm depot
#

just make it work without considering endurance first

quasi kernel
#

So only considering unhappiness and strength?

calm depot
#

no, don't consider any of that crap

quasi kernel
#

Ok

calm depot
#

because you're talking about applying a penalty as a factor of... three stats?

#

endurance, unhappiness and strength?

quasi kernel
#

Ye

#

Or a buff depending on strength

#

Increased strength would make it go by faster

calm depot
#

OK, so, once it works without considering any of them, applying the modifiers should be fairly straightforward math. start with strength first

quasi kernel
#

So let's say the base time is 600 seconds, or 10 minutes to charge a single battery.

#

That sounds like a long time but in-game time passes fast

#

And this is a dinky little charger anyways

calm depot
#

sure, and at strength level 0, your multiplier is 1 (i.e. unchanged)

quasi kernel
#

Oh, I'd figure it'd give a negative multiplier and we'd change based off of 5

#

So 5 would be our mulitplier of 1 since that's generally "default"

calm depot
#

what? no, don't do that

#

just decide what the multiplier for strength level 1 is, and level 10

quasi kernel
#

10 should be 2, 0 should be like, I guess 1 or something lower.

#

(Yes strength 0 is possible)

calm depot
#

no, don't express it like this

#

strength 0 is obvious, it's no change

#

say, strength 1 gives you a 10% speedup and strength 10 gives you a 90% speedup

#

well, you tell me, what is the min %age speedup and max that you want?

quasi kernel
#

At 10 I know I want it to go twice as fast, so 100%

calm depot
#

that would be 50%

quasi kernel
#

?

calm depot
#

going twice as fast is either divide by 2, or multiply by 0.5

quasi kernel
#

Oh I see

#

mb

#

I was considering in terms of speed not time

calm depot
#

the code will be easier to make sense of by using multiplication rather than division

#

once you decide what the speedup for level 1 and level 10 is, we can derive a formula - obviously you could also manually choose a value for every level, but now you've got to write code for every damn strength level

quasi kernel
#

So it'd just be like, .1 * strength?

#

No wait

#

That's speed

calm depot
#

as an example, let's say you choose that it's 5% up to 50%, you simply do baseTime * (1 - (0.05 * strengthLevel))

quasi kernel
#

Oh, so it's just (1 - (.1 * strengthLevel))..?

#

Sorry, I've never been good at making formulas.

calm depot
#

huh? I gave you the formula right there

#

or are you now saying you want it to range from 10% to 50% speedup?

quasi kernel
#

Hold on im trying to wrap my head around this, I've been okay with the logic side of programming but math has never been my strong suit, hence why I never entered the field.

#

Just kinda do it as a hobby.

calm depot
#

so do I ๐Ÿ˜›

#

well, the math part anyway

quasi kernel
#

I can make really basic formulas but it takes me a second to read them and make sense of them, so apologies

calm depot
#

then perform a substitution: at strength level 1, it would look like baseTime * (1 - (0.05 * 1))

quasi kernel
#

So basetime is 600, (1 - (0.05 * 10)) is 1 - (.5) which is .5 in the end result, so it'd be 600 * .5 which is 300

#

That'd be with strength 10

calm depot
#

which then becomes baseTime * (1 - 0.05) and finally baseTime * 0.95

quasi kernel
#

Oo that makes sense now!

#

Okay

#

Thank you for your patience

#

I'm a little slow sometimes

#

Alright, that formula makes sense to me now.

weak sierra
#

so

#

InventoryItem has getModData, and you can put mod data in there

#

but it does not have transmitModData

quasi kernel
#

wait what

weak sierra
#

so.. what do you do to ensure mod data gets propagated

quasi kernel
#

Does it get automatically transmitted or something?

weak sierra
#

idk im gonna have to dig in the source if nobody knows

quasi kernel
#

Okay okay, hold on, unhappiness should be the next one.

cyan basalt
#

I thought it just gets set since itโ€™s a lua table

calm depot
#

@weak sierra correct, because it's not a world object

quasi kernel
#

Unhappiness is a range of 0 to 4.

cyan basalt
#

Or do you mean like transmitted to the server or something

quasi kernel
#

4 being worse case scenario, 0 means perfectly content with life.

weak sierra
#

server yes

#

so there's a mod i use

#

and it saves some stuff and works fine in SP

#

but on MP the items it relates to despawn when u relog

#

and i noticed no transmit lines, so i added some

#

maybe this particular one isn't needed

#

but

#

now i want to understand how ur supposed to ensure transmission of moddata for inventory items

quasi kernel
#

Let's say maximum depression is 200%, or 2

weak sierra
#

ok so the java for getModData just literally gives a table if it exists, if not it gives a new one

quasi kernel
#

(Sorry evelyn am rambling)

#

No depression would just be 100%, or 1, no change.

weak sierra
#

looks like InventoryItem:save does the thing

calm depot
#

that's when the game is getting saved, unsurprisingly

weak sierra
#

if i can call that that'd be fine

#

but

#

seems odd

#

so, here's the specific case:

#

"Save Backpack Attachments" mod

#

forces items attached to backpacks (with one of several mods)

#

into the pack, disregarding weight limits

#

saves info about them in the pack's moddata

#

and/or in the items' moddata

#

and in the player moddata

#

relog -> the attached items are deleted from the bag somehow

calm depot
#

AFAIK, inventory item mod data was never designed to be shared across players; the worldItem of the inventory Item can though, since it's a class that derives from IsoObject

weak sierra
#

which now that im talking through it seems more like the inventory update isn't being saved

#

and is only clientside somehow?

#
function SavePackAttachments(pack,player)
    local items = {}
    -- loop through all attached items, and find ones provided by the backpack
    local hotbar = getPlayerHotbar(player:getPlayerNum());
    if hotbar ~= nil then
        --SA_ClearOldPacks(pack)
        local itemsToMove = {}
        for i,item in pairs(hotbar.attachedItems) do
            local slot = hotbar.availableSlot[i]
            local slotDef = slot.def
            if hb_ItemProvidesSlot(pack,slotDef.type) then -- does our backpack provide this attachment?
                item:getModData().hbSlot = ""..tostring(slotDef.type)
                table.insert(itemsToMove,item)
            end
        end
        if #itemsToMove > 0 then
            for mi,mitem in pairs(itemsToMove) do
                -- put them in the bag and set mod data.
                hotbar:removeItem(mitem, false)
                if mitem.isEquipped and mitem:isEquipped() then
                    player:removeWornItem(mitem)
                end
                pack:getItemContainer():AddItem(mitem)
                --player:getInventory():Remove(mitem)
                
            end
        end
    end
end```
#

here's the function that manages the indiviual items to be saved/moved

#

so it's storing what slot they go in in the moddata

#

but the items are disappearing on relog, so it's not just missing moddata

#
pack:getItemContainer():AddItem(mitem)```
#

is this insufficient?

#

i haven't messed with inventory code much yet

calm depot
#

are there item scripts for these things or are they getting generated on the fly?

weak sierra
#

they're existing items in the game

#

anything that happens to be attached to the apck

#

could be a wrench, a spiffo plushie

#

whatever

calm depot
#

it sounds suspiciously to me like the code is creating the item definitions on the fly rather than having them defined in media/scripts

weak sierra
#

it's base game items even

#

idk what u mean

#

it gets item references from the hotbar

#

and operates on those

#

u can see it above

calm depot
#

there are two ways to define an item: the default is media/scripts, the "custom" way is to write lua code that defines it. In either case, they get added to the world dictionary of the game's save

weak sierra
#

yes i know

#

but these are not items from this mod

#

at all

#

they are items from any mod and the base game

#

as i said

#

my examples included a wrench

#

it doesn't matter what the item is

#

so it can't matter how it's defined

calm depot
#

yeah, but it sounds to me like they're actually different items which are generated on the fly. this will fail in multiplayer because the server has no idea about them. so when you rejoin the server, your world dictionary will be re-downloaded

weak sierra
#

but fwiw i don't think any dynamically generated items are going on

calm depot
#

since those on-the-fly items don't exist in the world dictionary, they get deleted

weak sierra
#

this is.. not helping

#

there are no on-the-fly items

calm depot
#

OK, then they shouldn't be getting deleted

weak sierra
#

..yes

#

i know

#

lol

calm depot
#

actually, do this, use Edit Item on any item that is getting deleted, what is its fully qualified name?

#

it'll be something like Base.BlahBlah

weak sierra
#

it happens with literally any item

#

it doesn't matter what the item is

calm depot
#

OK, so reproduce the bug, and before you sign off, examine the fully qualified name of the item

weak sierra
#

u feel super sure about this huh

#

fine, ill rule it out

calm depot
#

no, I want to rule it out

undone elbow
#

Doesn't work. ๐Ÿ˜•

calm depot
#

it's far more sensible to verify it's not the most common cause of items disappearing before diving deeper

weak sierra
#

ive read all the code for the mod

#

it's not making new items at all

#

it just uses the existing items

#

and moves them around

#

adding/removing them from inventories

#

never makes a new one

calm depot
#

well, you've read all the code, sure. Yet here you are

weak sierra
#

it's only two files

#

not exactly a marathon

calm depot
#

link to the mod?

halcyon dagger
#

has anyone ever tried to pass an param of type ByteArray?

weak sierra
#

one file does all the heavy lifting, the other displays little yellow dots by the icons in teh inventory

#

lua files that is

#

taking some time to test, have to remove the patch mod from my local test dedicated, reboot it, join

#

so u can't edit items while they're in a bag on the ground

#

hm

#

maybe using SAC i can access them while they're in the bag but within my inventory

calm depot
#

hm, I'm slightly suspicious as to how it's presenting the items client-side. I've seen mods that present additional items client side based on traits and the additional items vanish as soon as you attempt to move them because the server disagrees about their existence - one way to verify this is to instead dump the item out onto the ground and see if it does remain

weak sierra
#

ok yeah i looked at it thru SAC

#

same ID

#

as i said it just removes it from the attachment and adds it into the bag

#

the item is just an item

#

with some metadata

#

yeah u can take the items out

#

sometimes the markers glitchily stay on them

#

but

#

let's see

#

yup the two plushies i tried with appeared on the ground fine

calm depot
#

yeah, it's some anticheat they added a while back

weak sierra
#

they still have the yellow marker

#

so presumably they still have the moddata too

calm depot
#

server doesn't think the items are really "there"

weak sierra
#

i have several anti-cheats disabled for various reasons

#

any idea which one that is

calm depot
#

no, I never looked into it, try turning them all off and see if the problem goes away, though I have the suspicion that it won't

#

I don't think this particular "item accounting" was ever exposed as a server var

weak sierra
#

what do u think is breaking anyway?

#

do u think the server doesn't "know" that the items are in the bag?

#

so they're phantoms on the client?

#

but if that's the case they would have disappeared no?

#

when dragging to floor

#

cuz that triggers a command on the server i think

calm depot
#

it does, but it's different

weak sierra
#

to place the world object

calm depot
#

if you have a mod that creates client-side items, you can always make them not get deleted by first dragging them to the ground

weak sierra
#

hm

#

so a test could be putting them back in the bag

#

and then relogging

calm depot
#

but, whenever you pull them straight to your inventory, server nukes them

weak sierra
#

ill also test that

#

i did experience that at one point i vaguely recall in the past

#

but that was fixed at some point

#

without an update to the mod

#

i think something else was breaking that previously

calm depot
#

I still get it when I play on servers with the scavenger skill mod

weak sierra
#

nod

#

yeah im familiar with that

#

generates extra items based on skill

#

and does it on client end cuz written with SP in mind

#

or without MP in mind

#

whichever u wanna think of it as

#

the shitty thing is that to test this i have to reboot a server every time to give myself the ability to log in and out lmao

#

makes each test cycle slow

#

which is why i sought help instead of just troubleshooting it endlessly

calm depot
#

what do you mean by restart the server every time to login and out?

weak sierra
#

if i change stuff

#

obviously not if i dont have to change stuff

#

:p

#

to change code or settings, etc

calm depot
#

if you're changing the server code, yeah, you have to restart the server

quasi kernel
#

baseTime * (1 - (0.125 * unhappiness)) I think?

#

It took me way too long to finish that I got distracted

weak sierra
#

and i have to publish it

calm depot
#

if you're changing the client code, you don't if you disable the lua checksum option

weak sierra
#

yaeh

#

hm

calm depot
#

you don't have to publish it, you can make the server run mods in your Zomboid/Workshop folder

#

that's how I test all my own mods, I don't first publish them

weak sierra
#

i run it from a separate folder cuz im on linux and run the client in wine

#

i could copy it

#

ig

#

or symlink

#

im not sure if any of this runs on the server end, it has code in the server folder so it should be performing this stuff on the server end

#

if that's how that works

calm depot
#

there's a linux build of the client, though

#

no?

weak sierra
#

yeah it sucks tho

#

works fine for vanilla

#

but

#

weird lag issues

#

with some mods

calm depot
#

why? most of the game is java

weak sierra
#

and some textures/etc. missing probably due to path interpretation stuff

calm depot
#

there's just a few native libs that are JNI'd

#

interesting, you should try it on a case-insensitive mount point

weak sierra
#

never considered that tbh

#

but that's a thing for anothr day

#

well, after dragging them to the ground and putting them back in

#

they dont disappear but the moddata is discarded

#

so they dont re-attach themselves either

#

im guessing those are not related issues though

quasi kernel
#

Okay so for Endurance..
0 would be 1, or 100%
4 would be 0, or 0%

weak sierra
#

but the IDs were fine

quasi kernel
#

(Dont mind me)

weak sierra
#

so what does that mean

#
DEBUG: Multiplayer , 1661721780910> 1,698,334,344> ItemTransactionManager.receiveOnServer> set accepted [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721781127> 1,698,334,560> ItemTransactionManager.receiveOnServer> remove processed [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721817421> 1,698,370,854> ItemTransactionManager.receiveOnServer> set accepted [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721819494> 1,698,372,927> ItemTransactionManager.receiveOnServer> remove processed [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721897872> 1,698,451,305> ItemTransactionManager.receiveOnServer> set accepted [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721898077> 1,698,451,510> ItemTransactionManager.receiveOnServer> remove processed [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661721901470> 1,698,454,903> ItemTransactionManager.receiveOnServer> set accepted [ 308852067 : 315655877 => -1 ]
DEBUG: Multiplayer , 1661721901556> 1,698,454,989> ItemTransactionManager.receiveOnServer> remove processed [ 308852067 : 315655877 => -1 ]
DEBUG: Multiplayer , 1661721903304> 1,698,456,737> ItemTransactionManager.receiveOnServer> set accepted [ 418050617 : 315655877 => -1 ]
DEBUG: Multiplayer , 1661721903390> 1,698,456,823> ItemTransactionManager.receiveOnServer> remove processed [ 418050617 : 315655877 => -1 ]
LOG  : General     , 1661721933945> 1,698,487,378> watering plants
DEBUG: Multiplayer , 1661722104009> 1,698,657,442> ItemTransactionManager.receiveOnServer> set accepted [ 308852067 : -1 => 315655877 ]
DEBUG: Multiplayer , 1661722104489> 1,698,657,922> ItemTransactionManager.receiveOnServer> remove processed [ 308852067 : -1 => 315655877 ]
DEBUG: Multiplayer , 1661722104489> 1,698,657,922> ItemTransactionManager.receiveOnServer> set accepted [ 418050617 : -1 => 315655877 ]
DEBUG: Multiplayer , 1661722105014> 1,698,658,447> ItemTransactionManager.receiveOnServer> remove processed [ 418050617 : -1 => 315655877 ]```
#

guessing that's it being well aware of the movement of items

#

lets try without putting it on the floor and seeee

#
DEBUG: Multiplayer , 1661722621110> 1,699,174,543> ItemTransactionManager.receiveOnServer> set accepted [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661722623190> 1,699,176,624> ItemTransactionManager.receiveOnServer> remove processed [ 315655877 : -1 => -1 ]
LOG  : General     , 1661722685581> 1,699,239,014> watering plants
DEBUG: Multiplayer , 1661722787409> 1,699,340,842> ItemTransactionManager.receiveOnServer> set accepted [ 315655877 : -1 => -1 ]
DEBUG: Multiplayer , 1661722787626> 1,699,341,060> ItemTransactionManager.receiveOnServer> remove processed [ 315655877 : -1 => -1 ]```
calm depot
#

I would be curious to know what happens if you move the server code to shared instead

#

probably a different kind of breakage, but at least server and client would be "doing the same thing"

weak sierra
#

would that duplicate the actions?

#

:p

calm depot
#

dunno, try it

weak sierra
#

ill have to move the whole mod into my fix copy then for now

#

and copy it to both spots..

#

will take a few mins

#

or

#

edit both workshop copies

#

i should see if this happens in SP, too

#

i just assume it doesnt but who knows

calm depot
#

unlikely, the client and server folders become meaningless in SP

#

all code from all 3 folders is executing in one lua state

weak sierra
#

gonna rule that out before i continue

#

as a sanity check

#

make sure it isnt a fundamental issue with the mod rather than a syncrhonization one

calm depot
#

you mean you didn't check if it was also broken in SP?

weak sierra
#

nope

#

i assumed it was not

calm depot
#

I doubt it would be broken in SP

weak sierra
#

due to the behavior only occuring on logout

#

and login

#

but

#

who knows

#

maybe quit-reload save

#

let's find out

quasi kernel
#

Hey oli, would I check to see if things changed in update?

gloomy geyser
#

Does anyone know how I get a zomboid sound? A sound effect you already have in zomboid?

calm depot
#

well, since their fatigue could certainly change, yes

#

if you really want to be consistent, you could also check unhappiness but I'd consider it a bit of overkill

quasi kernel
#

imo unhappiness isn't that unrealistic to check

#

Esp with smoker without cigarettes existing

calm depot
#

it's not at all unrealistic, just more work for little gain

quasi kernel
#

What would be overkill is checking strength LOL

calm depot
#

letting them get away with crossing over a boundary for unhappiness isn't that big of a deal

quasi kernel
#

hmm

#

Yeah I guess that's true

#

:setTime() doesn't seem to be valid

calm depot
#

huh?

quasi kernel
#

Gonna look over some vanilla code

#

oh gotta do self.action for setTime

weak sierra
#

the items do not disappear in SP but the moddata is still lost after a reload

deft jacinth
#

What vehicle are you supposed to be using for the ISO gasoline tank?

calm depot
#

what?

weak sierra
calm depot
#

there is no IsoGasolineTank

weak sierra
#

it's from a mod.

calm depot
#

ah

weak sierra
#

containers i think

#

thing has no wheels, barely moves when full

#

heh

#

alright, now gonna test making that stuff be in shared instead of server

#

well nothing weird happened on the first part, relogging..

#

ok well that seems to have fixed that, unless i've lost my mind, which after enough tests that can happen

#

moddata still lost but that's a smaller problem

calm depot
#

figures

weak sierra
#

so back to the original problem i suppose

#

the moddata is not saved

#

stuff is stored on the player and on the items

#

provided the player moddata is being synchronized OK

#

could move the other stuff into a table within that moddata

#

but then it'd be annoying to render the icons, have to mess with that too