Community Forum

Update(dt)

Forum Overview >> Scripting

CategoryScripting
Created06.02.2019 13:18


Ruben Cobos (Unknown) 06.02.2019 13:18
I'm trying to get my farm silo to rotate about the y axis at a given rate.

Single calls to rotateAboutLocalAxis work just fine, but when I try to get it to rotate continuously using the update function nothing happens.

Is this not correct?:

function update(dt)
rotateAboutLocalAxis(4288, math.rad(0.08)*dt, 0.0, 1.0, 0.0);
end;

Bilbo Beutlin (BBeutlin) 06.02.2019 16:03
1. Make sure your update() function is called at all. Probably you'll need to register it.

2. Why not simply using a "Rotator" object?

Heady Planet-ls (Headshot XXL) 06.02.2019 19:18
I made the experience that update(dt) in mod placeables is not called. only a few times in the beginning

my solution would be to call the update() instance of a ModEventListener.
MyModClassName: update(dt)
MyPlaceableInstance: update(dt);
end;
addModEventListener (MyModClassName); "


Ruben Cobos (Unknown) 07.02.2019 05:05
Ok I will try those methods. Thanks

Derek Squire (dezza069) 16.02.2019 11:37
Have also found that update(dt) in a custom placeable mod is only called twice in the beginning of the load.

Wondering if anyone else has the experience in a custom placeable script of not being able to access "self" in "function MyModClassName:update(dt)", if the class is registered using "addModEventListener(MyModClassName);" - although if "addModEventListener(self);" is used from within another function (eg MyModClassName:finalizePlacement()) "self" can be used?

Have I misinterpreted something? (very likely!!) Are there reasons "self" is not available?

Is it okay to use "addModEventListener(self);" to register the class? Just seems like a really bad hack...

Thanks in advance.

Bilbo Beutlin (BBeutlin) 16.02.2019 17:41
For exact definition and usage of class, instance, metatables, self-construct, etc. see common lua tutorials.

The FS lua system function 'addModEventListener()' adds a certain mod to the lua dispatcher which then calls the standard functions by event.
I'm not sure - didn't try yet ;) - but I think it's not intended to register a class to the dispatcher.
Like in earlier FS the usual way is to register your single mod (functions). Example:
-------------------
myMod = {}
-- perhaps followed by global variables like
myMod.var1 = ...
-- and run-once procedures like eg.
myMod.doThisStuff()
-- then the functions like
myMod:function1()
myMod:function2()
-- where at least the expected basic functions like update(), draw(), etc. should be defined
-- finally "myMod" becomes registered to the dispatcher by
addModEventListener(myMod)
-------------------

At least this the way I'd recommand for placeables and general scripts.
The methods for specializations are a little different.

Derek Squire (dezza069) 17.02.2019 00:54
Thanks Bilbo.

I get that, thanks. The structure of the mod is almost exactly as you've laid out.

From my experimenting, if there's no "addModEventListener(myMod)" or the like, such as an appendedFunction for main threads .update(dt), the placeable subclassed myMod.update gets fired only twice, then just stops regularly firing.

Eg:
function myMod:update(dt)
print("myMod:update NO DEBUG "..string.format("myMod.isActive %s", myMod.isActive)..string.format(", self.isActive %s", self.isActive)..string.format(", self.counter %s", self.counter));
self.counter = self.counter + 1;
end;


Log entries:
No addModEventListener(myMod);:
2019-02-16 15:38 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 0
2019-02-16 15:38 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 1
(that's it, two entries)


With addModEventListener(myMod); (also if set via the "loader.lua" script, for example)
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 0
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive nil, self.counter nil
2019-02-16 15:42 Error: Running LUA method 'update'.
2019-02-16 15:42 C:/Users/User/Documents/My Games/FarmingSimulator2019/mods/myMod/scripts/myMod.lua:674: attempt to perform arithmetic on field 'counter' (a nil value)
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 1
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive nil, self.counter nil
2019-02-16 15:42 Error: Running LUA method 'update'.
2019-02-16 15:42 C:/Users/User/Documents/My Games/FarmingSimulator2019/mods/myMod/scripts/myMod.lua:674: attempt to perform arithmetic on field 'counter' (a nil value)
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive nil, self.counter nil
2019-02-16 15:42 Error: Running LUA method 'update'.
2019-02-16 15:42 C:/Users/User/Documents/My Games/FarmingSimulator2019/mods/myMod/scripts/myMod.lua:674: attempt to perform arithmetic on field 'counter' (a nil value)
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive nil, self.counter nil
2019-02-16 15:42 Error: Running LUA method 'update'.
2019-02-16 15:42 C:/Users/User/Documents/My Games/FarmingSimulator2019/mods/myMod/scripts/myMod.lua:674: attempt to perform arithmetic on field 'counter' (a nil value)
2019-02-16 15:42 myMod:update NO DEBUG myMod.isActive nil, self.isActive nil, self.counter nil
2019-02-16 15:42 Error: Running LUA method 'update'.


With addModEventListener(self); (located as last line in myMod:finalizePlacement())
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 0
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 1
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 2
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 3
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 4
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 5
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 6
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 7
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 8
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 9
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 10
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 11
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 12
2019-02-16 15:47 myMod:update NO DEBUG myMod.isActive nil, self.isActive false, self.counter 13
(....etc)

Thanks, any suggestions are welcomed!! :)

Bilbo Beutlin (BBeutlin) 18.02.2019 01:47
You must be careful if your mod runs in multiple instances (in opposite to a global mod valid for all similiar objects).

For multi-instance usually the 'new()' function is used in the style
function myMod:new(isServer, isClient, mt)
In this function an instance proprietary 'metatable' is introduced which you can access later with the 'self' construct.
Here are usually also the first 'self.xyz' variables initialized.
For reference see the LUADOC -> Placeables.

Without initialized metatable the 'self' construct can have random content or even be 'nil'.

The variables you used in your example and got 'nil' were not initialized earlier, are unknown.

Curious that your function 'update()' is called at all if it wasn't registered by 'addModEventListener()'.

Derek Squire (dezza069) 18.02.2019 02:48
Hi Bilbo,

Thanks for your efforts and info.

The variables used in the example were initialised in a myMod:new(isServer, isClient, customMt), I just didn't put everything in my example (see below). Probably should have, sorry about that.

You'll also note that the "myMod.isActive = nil" will always be so as it's not a global or referenced. The other "self" variables return the correct values, as they should - except if "addModEventListener(myMod)" is used and then there's 2 firings with the correct results, each followed by another immediately after which fires wrong. After this is just fails and repeats the error.

The first two firings, as you said, are curious because I believe they're the two which fire even if there's no registration - which, I also find weird myMod:update(dt) is called twice without being officially registered...

The results from "addModEventListener(self)" are more what I would expect if using "addModEventListener(myMod)", and I doubt self should really be used in the "addModEventListener" call.

... I'm wondering if someone typed a "." instead of a ":" in the behind the scenes code, because as far as I understand if you refer to a function with myMod.functionName() there is no "self" passed, yet if you use myMod:functionName() it is.

Anyways, thanks heaps for your thoughts and suggestions, it's been good looking back through my code and checking things.

Kind regards



contents of myMod:new(… stuff ....) includes:
----
local self = Placeable:new(isServer, isClient, customMt or myMod_mt);
registerObjectClassName(self, "myMod");
if( self ) then
if( self:getDebugLvl() ) then
print("myMod:new success - self created");
end;
end;

self.isEnabled = false;
self.isActive = false;
self.isPlayerInRange = false;
self.counter = 0;
self.debug = false;

……. stuff …….

return self;
------


Gtx | Andy (GtX_Andy) 18.02.2019 12:34
Hey Derek,

When using the 'update(dt)' function as part of the 'Object' class you need to activate the 'LOOP' when you require it.
This is a great feature for network objects as it does not waste resources or performance calling the update(dt) function when it is not required.

For example.

function MyMod:startRotation(state)
if state ~= self.isRotating then
self.isRotating = state

self:raiseActive()
end
end

function MyMod:update(dt)
if self.isRotating == true then
local rotatation = 1 * dt * self.rotationSpeed
rotate(self.node, 0, rotatation, 0)

self:raiseActive()
end
end


So as you can see above 'self:raiseActive()' is called with 'MyMod:startRotation(state)' so that the LOOP will start. If 'self.isRotating == true' then 'self:raiseActive()' will be again called and the LOOP will again continue. This way it only operates as needed.

p.s It is not a good idea to use 'modEventListeners' as part of the Object Class.
So you are also aware for future, you no longer need to add functions to the listener you are not using. So if you do not need 'draw()' do not added it ;-)

Without knowing your end goal or seeing the script this is about all I can contribute but it should help I think :-)

Cheers, GtX

Derek Squire (dezza069) 19.02.2019 02:38
Thank you Andy,


This is my first FS19 mod after modding a map and writing one script for myself for FS17, I'd not seen "raiseActive()" in the latest documentation relating to placeables, or obviously paid attention to it when looking through the other docs relating to silos and had no idea it existed...

Explains the two firings of :upate(dt) I couldn't work out.

After making a few slight adjustments to my code to form that loop - BINGO!!! YAY!!!!!!

It all works without the dodgy "addModEventListener(self)" I'd hacked in. Rather pleased now, really wasn't happy with that "hack" as it didn't feel right. So excited.... :) :) :)



Thank you.


Note: Log in to post. Create a new account here.