Community Forum

How To Create New Object Class

Forum Overview >> Scripting

Created16.06.2016 10:03

Aden Kuenzi (akuenzi) 16.06.2016 10:17
I am working on a script that spawns rocks behind plows and cultivators (see WIP thread at Initially the rocks spawned were treated as 'bales' by the game engine, and it worked fine for the most part. However, it was recommended to me that I create a new object class for 'rocks' rather than treating them as bales, so as to avoid problems of certain bale equipment wanting to interact with the rocks.

So, I tried to create a new object class, starting with the bale.lua script as my template. I pulled out everything having to do with bale wrapping, exchanged the term "bale" for "rock," and made sure it wasn't a 'static' object class at the top.

The next question was what to do with this new code. I initially tried putting it in a separate lua file, and called it as an 'extrasource' file from the modDesc.xml file of my main rock spawning script. This didn't work. It generated an error that said, "Error: Running LUA method 'update'.
C:/Users/..../RockSpawn.lua:242:attempt to index global 'rock' (a nil value)" The RockSpawn.lua script is my main script, and line 242 is where it attempts to spawn a new rock. Previously it read, local rock = Bale:new(self.isServer, self.isClient). I replaced the 'Bale' in this with 'Rock,' intending it to call the new Rock.lua file I'd created, as mentioned above. But this didn't work.

Next I tried moving the entire contents of my new object class directly into the RockSpawn.lua file itself. Now it seemed to work just fine in game... for single player. I noticed big problems when I tried it in the multiplayer environment, and I suspect it's because I inserted this new object classification into my specialization, which is affixed to plows and cultivators. The host could see all the rock movements just fine, but there was horrible lag/delay at the client level. To get the screen to refresh, I'd have to tab around to other equipment and then come back to see things correctly. Rocks would appear to hover in mid air in places, or appeared to be on the wrong place on the map. You'd try to push them, and they'd still appear behind the vehicle... even though they'd actually been moved. So, even though this 'sort of' worked, it wasn't exactly optimal. There are pictures near the end of my WIP thread if you wish to see examples.

The next thing I tried to do was to set up this new object class as its own mod. This likewise failed similar to the above. The rock class is not recognized at all when my RockSpawn script attempts to call it. The only place it was ever recognized and worked, was when I included it directly in the RockSpawn specialization script itself.

Now I'm doing what I probably should have done before trying all of this. How does one go about properly setting up a new object class? I would put some code here, but the code I have for the new rock class is almost identical to the bale.lua file, except using rock terminology.

Thank you for your assistance.


Aden Kuenzi

Emil Drefers (Unknown) 17.06.2016 07:46

first thing to do is to try using a seperate .lua file for the rock class.
That makes things simpler and more structured.

Let's see ... extra source file should work.
Did you enter some debug prints into your rock.lua to check if it has been loaded and what function get called?

You could also try the source(...) function as used in the vehicle.lua

For your rock.lua you could also inherit from the PhysicsObject class
at least as long as the rock should not be mountable.
Anyhow, you would create a class with all functions the parent has and call the parent (superClass) function when the respective function is called.
function Rock: update(dt)
Rock:superClass().update(self, dt)
-- now do the cutsom code

But, cleaning the Bale.lua should also work ...
Hard to say whats going wrong actually.
Maybe you have implemented a custom updateTick() ?
This would explain why the positions are not update:
see line 69:
-> updateMove() ;)

Hope this infomration can help somehow.

Good luck and cheers,

Aden Kuenzi (akuenzi) 21.06.2016 08:37

Thank you for the suggestion. I tried the source(...) function approach, and that worked great! The script I wrote is now talking with this new object script just fine.

However, I still have the other issue. Client logins to multiplayer games have a delay in seeing movement of the rocks. As mentioned above, this new rock object is patterned after the bale.lua script, so it's currently a mountable object. You suggested looking at line 69 of the mountable object lua file, which is the updateTick() section and reads: if self:updateMove() then self.lastMoveTime = g_currentMission.time;.

The bale.lua file has no section for 'updateTick' (and no section for 'update' either). As such, the new rock object I created didn't have an updateTick section. For my own understanding, does that mean that the updatetick will run automatically in the background for the bale, since the bale is a mountable object and has inherited its properties, and unless there was some 'custom' coding to do, there would otherwise be no need to call 'updateTick' in the bale? Or does the updatetick ONLY run if it's specifically called by the bale.lua file using superClass? I'd assumed it would be the former. Multiplayer works fine for bales, so somehow it is getting its position updated even without a section for updateTick... and I'm assuming it's because of these 'inherited' properties.

One other question for my understanding, please. I see how you set up this 'superClass' bit, and I've observed that a number of times in the lua script files. However, they never stand alone. There's always additional code. You gave an example with the 'update' part. So, this means that for each frame in the game, the parent function would be called from my new rock object script. It would call it... and then immediately thereafter, if I have any additional code, it would do that, too. Incidentally, the mountableObject.lua script doesn't have a section for update. It appears to have been commented out. But if it did, this command would call the parent, and do whatever was in the parent's update section... and then come back to here and do further anything I tell it to do. Do I have that correct, as to how it works?

So... if I don't have any custom code for the updateTick section, and if I've patterned this after the bale... shouldn't it work similar to the bale, even with no additional coding?

Just to explore all angles, I did try this in my rock.lua file, where I added the following code:

function Rock:updateTick(dt)
Rock:superClass().updateTick(self, dt);

I guess my thought was that this would make sure that it 'called' the updateTick bit in the parent object, which had the update stuff in it... and then it would work. But it didn't work, of course. :) So I'm obviously not understanding something important. Is this something you can clear up for me?

If you want to see the code I'm working with for this object, it is here:

Thank you so much!

~ Aden

Emil Drefers (Unknown) 22.06.2016 08:17

before starting to dig deeper and trying to find any other reason.
Here's the first idea:

You have a
function Rock:update()
but it does not call any super/parent function, which is crucial ...
check the update() in PhysicsObject:
It does the position interpolation on the client side.


Aden Kuenzi (akuenzi) 22.06.2016 20:03

Thank you! I think that did the trick. It at least behaves 'normally' now in head-to-head multiplayer. I'll be testing it on a dedicated server shortly. The only change I made to the code was to add this line, just below the function Rock:update() line:


That's the only change I made, and it works. However, in one test, I did try it WITHOUT the superClass call I had in updateTick, and it didn't work in that case. So, it apparently needs both to be in there, even though there is no additional code in the updateTick section of this rock file.

Again, thank you so much! And if you have any further comments as to my questions to help me further understand how this works in the background, I would greatly appreciate your time. Short of coming here and asking, I don't know how someone would otherwise know what something like "superClass" even means. :)



Emil Drefers (Unknown) 23.06.2016 07:04
Hi Aden,

cool, that makes me happy :)

Well, as stated in my last post, you need that call of update() in the superClass to enable the position interpolation on the client side.

Concerning your Rock.lua ...
do the rocks need a fillLevel and a fillType?
If not you could remove that stuff from your code ...

Anyhow, have fun!


Aden Kuenzi (akuenzi) 23.06.2016 09:04

I tested it on a dedicated server tonight, and it works there, too... so I'm hopeful all's well with it.

As for the rocks needing a fillLevel and fillType, they DO need these things. These rocks are of varying sizes as dug up in the fields, and the fillLevels are different as a result. When the rocks are 'sold,' the fillLevel indicates how much money is received for each. And given that it's rock, it's not much money, but some. However, there is a 'gold' fillType for one special rock that is only rarely dug up, and it will get the player a lot of money upon disposal. But I mainly wanted to use fillLevel and fillType in the event these were useful to other modders, such as if someone created a machine to 'crush' the rock and wanted to get a given fillLevel of 'grave' out of it as a result.

The part of the bale.lua file that I did remove from the code was all the stuff on bale wrapping. :)

Again, thank you so much Emil -- this was very helpful, and I sincerely appreciate your willingness to share knowledge with the rest of us.

~ Aden

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