Scripting Reference?

User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Scripting Reference?

Post by brack »

Hello, I'm starting to get back into FS modding and I'm trying to find a scripting reference that can explain what the available built in functions do.

I've seen the GDN site (https://gdn.giants-software.com/documen ... ipting.php) however this seems like it is designed more for people who purchased the engine, not just the game. Also a google search returned http://www.ls-mods.de/scriptDocumentation.php but this doesn't seem to go anywhere anymore.

If there is a Farming Simulator specific scripting reference (or even tutorial with similar information) that anyone knows about I'd love to hear of it. I'm just trying to make a simple mod that displays some text on the screen, and I figured with a solid programming background and decent documentation it wouldn't be difficult but I'm running into barriers learning the API.

EDIT: One useful reference I found is a list of many functions, classes, tables and variables here: http://wiki.universalprocesskit.de/inde ... tionsliste
Once you know how to print tables this list becomes quite handy.
Last edited by brack on Tue Dec 13, 2016 12:41 pm, edited 2 times in total.
User avatar
Aranea
Posts: 289
Joined: Thu Oct 06, 2016 9:51 pm
Location: meine Höhle

Re: Scripting Reference?

Post by Aranea »

Hello brack,
the GDN is your best reference for FS17 scripts to your question, the basics and further stuff you need to figue out yourself by testing around, or looking into other people's scripts - trying to understand the stuff thats going on there.

i was there too, a few years back. and i have no clue of programming or stuff like that but seems like i got myself on the way to script for FS15 and now 17 (mostly) by my own.
MfG
die Spinne :hi:
FS modder & scripter
quality modding and support since 2012
viewtopic.php?f=884&t=115656
User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Re: Scripting Reference?

Post by brack »

Maybe I should just be more direct with my question then.

I'm trying to get the prices for each fruit from each sell point. I found the "getEffectiveFillTypePrice" function within Triggers > TipTrigger which I think is what I need, but I'm having some trouble implementing this. I don't know how to loop through each sell point to get the value.

Any help would be much appreciated.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

I would agree that GDN is probably the best script reference you are going to find. Of course the problem is that Giant's does not document everything and in fact keep some things hidden, specifically they do not document g_currentMission -- which is a treasure trove of information -- but they also tend to NOT provide documentation for economic information, such as prices.

I am not sure how good you are with LUA, but i would recommend spending some time with it and getting to know how to use LUA to debug/introspect LUA, specifically displaying the values of tables and how the table metadata works for "inheriting" functions.

That said, GDN does provide some functions, specifically in the script section, under Utils, there is DebugUtil. Probably the most useful function is printTableRecursively. This is a very useful function for printing out tables(like g_currentMission) to inspect them. In fact, if you want to understand LUA better, making your own function of this nature is a good exercise. (LOL, I actually did write my own before finding this function, and today I still use my own function because it provides more information than the one given by Giants.)

GDN also documents another set of debug functions in the engine section, under General. Probably the most useful function (besides print) is printCallStack, although if you are doing graphic things the drawDebug... functions can also be useful. PrintCallStack can be used to help document the series of functions called to get to where you inserted your code. This is not always useful, but because you cannot introspect actual LUA function code, this can sometimes help you to intuit what a series of functions actually does..

But to get on to your specific question, if you look at the g_currentMission table it will have a sub-table called tipTriggers. Here is some LUA code to print the prices to the console

Code: Select all

	print(">>");
	local PADDING = string.rep(".", 16); 
	for tipTrigger in pairs(g_currentMission.tipTriggers) do
		if tipTrigger.isSellingPoint then
			print(string.format(">> %s (%s)", g_i18n:getText(tipTrigger.stationName), tipTrigger.stationName));
			for fillType in pairs(tipTrigger.fillTypePrices) do
				print(string.format(">>   %16.16s base price:$%9.6f/L  delta price:$%9.6f/L  price scale:%9.6f  effective price:$%9.6f/L", 
					FillUtil.fillTypeIntToName[fillType] .. PADDING, 
					tipTrigger.fillTypePrices[fillType], 
					tipTrigger.fillTypePriceRandomDelta[fillType], 
					tipTrigger.priceMultipliers[fillType], 
					tipTrigger:getEffectiveFillTypePrice(fillType)));
			end
			print(">>");
		end
	end
The above will print to the console (which is also output to the log.txt file) something like this:

Code: Select all

>>
>> Maplefield Mill (station_railroadMillGCV)
>>   wheat........... base price:$ 0.741400/L  delta price:$ 0.139568/L  price scale: 1.000000  effective price:$ 0.880968/L
>>   barley.......... base price:$ 0.688600/L  delta price:$-0.107506/L  price scale: 1.000000  effective price:$ 0.581094/L
>>   rape............ base price:$ 1.326600/L  delta price:$ 0.028787/L  price scale: 1.000000  effective price:$ 1.355387/L
>>   sunflower....... base price:$ 1.480600/L  delta price:$-0.316661/L  price scale: 1.000000  effective price:$ 1.163939/L
>>   soybean......... base price:$ 1.711600/L  delta price:$ 0.032635/L  price scale: 1.000000  effective price:$ 1.744235/L
>>   maize........... base price:$ 0.836000/L  delta price:$-0.014752/L  price scale: 1.000000  effective price:$ 0.821248/L
>>   potato.......... base price:$ 0.378400/L  delta price:$ 0.072306/L  price scale: 1.000000  effective price:$ 0.450706/L
>>   sugarBeet....... base price:$ 0.268400/L  delta price:$-0.010569/L  price scale: 1.000000  effective price:$ 0.257831/L
>>
>> Mary's Farm (station_farmer2GCV)
>>   wheat........... base price:$ 0.674000/L  delta price:$-0.130493/L  price scale: 1.000000  effective price:$ 0.543507/L
>>   barley.......... base price:$ 0.626000/L  delta price:$ 0.093695/L  price scale: 1.000000  effective price:$ 0.719695/L
>>   rape............ base price:$ 1.206000/L  delta price:$ 0.046395/L  price scale: 1.000000  effective price:$ 1.252395/L
>>   sunflower....... base price:$ 1.346000/L  delta price:$ 0.236189/L  price scale: 1.000000  effective price:$ 1.582189/L
>>   soybean......... base price:$ 1.556000/L  delta price:$-0.533160/L  price scale: 1.000000  effective price:$ 1.022840/L
>>   maize........... base price:$ 0.760000/L  delta price:$ 0.065744/L  price scale: 1.000000  effective price:$ 0.825744/L
>>   potato.......... base price:$ 0.344000/L  delta price:$ 0.006943/L  price scale: 1.000000  effective price:$ 0.350943/L
>>   sugarBeet....... base price:$ 0.244000/L  delta price:$-0.008835/L  price scale: 1.000000  effective price:$ 0.235165/L
>>
>> Mary's Farm (station_farmer2GCV)
>>   manure.......... base price:$ 0.085800/L  delta price:$-0.011846/L  price scale: 1.000000  effective price:$ 0.073954/L
>>
>> Spinnery (station_spinnery)
>>   wool............ base price:$ 7.600000/L  delta price:$-0.016558/L  price scale: 1.000000  effective price:$ 7.583442/L
>>
>> Goldcrest Pacific Grain (station_grainElevatorGCV)
>>   wheat........... base price:$ 0.674000/L  delta price:$ 0.164151/L  price scale: 1.000000  effective price:$ 0.838151/L
>>   barley.......... base price:$ 0.626000/L  delta price:$-0.121470/L  price scale: 1.000000  effective price:$ 0.504530/L

.
.
.
.
Note that prices in the game engine are usually stored in currency/liter even though they are shown in the user interface as currency/1000 liters. Also time is usually stored internally as milliseconds, so 3,600,000 milliseconds / hour.

One last tip, if you are looking to do something specific with the information, you may want to render in on the screen, this is documented in the engine section under Text Rendering. That said, it can be difficult to know how to use the "engine" functions because they do not provide LUA source code, this is likely because the engine is actually written in C. I cannot provide insight into these functions, but a good way to gain knowledge of how they work is to find LUA code that uses them in the "script" section OR find another mod that does text rendering and open it up and look at the LUA code in that mod. Finding good examples is hard, but previous mods are probably your best bet.
User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Re: Scripting Reference?

Post by brack »

Wow. This is all very useful information for someone getting started. Thank you for taking the time to write it up. As far as my personal experience, I have programming experience in PHP, Java, C++, C# etc... however I am somewhat new to LUA syntax.

Some of the addons I had looked through referenced a g_currentMission but because of how it was named I was thinking it was related to the in-game missions. The fact that some of the addons were written in German didn't help me either.

You said GIANTS didn't document g_currentMission, but is there a list of these tables somewhere, or is g_currentMission basically all of the stored data?
EDIT: Yes: http://wiki.universalprocesskit.de/inde ... tionsliste

Also your explanation of printTableRecursively makes perfect sense. I still don't exactly understand what printCallStack is for, however I can play with it a bit to see.

Again, thanks a lot for this. Definitely enough to keep my feet wet for a bit, and some new roads to explore. This code block is pretty much perfect both for learning and my actual mod's progress. Thanks again.
Last edited by brack on Tue Dec 13, 2016 12:45 pm, edited 2 times in total.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

I noticed that you did not mention Javascript in your personal experience, so likely you do not have much exposure to prototype based programming.

Actually, I find LUA quite elegant, LUA is very simple in some ways, but provides quite a powerful set of features. LUA is not a traditional OOP language like Java, C++ or C# -- and this can be a benefit to us modders, but can also make our job harder. Since LUA is not a traditional OOP, it does not provide many mechanisms for encapsulation, this means LUA tends to expose it's parts, specifically the table structures that make up most of LUA's organization. On the making our job harder side, LUA does not have traditional Class structures like Java or C#. Most class structures are implementation dependent and it is up to the developer (in this case Giants) on how they actually implement things like constructors, destructors, inheritance, etc.

Here is a really good online book -- Programming in LUA -- I would recommend reading at least Part 1 and Part 2. I actually think Part 2 is more important to understand, but Part 1 is laying the groundwork to understand Part 2. Just a note, this book is somewhat dated focusing on LUA 5.0, but do not worry about that, the Giants engine uses LUA 5.1 which is also somewhat dated.

As a bit of incentive, if you look at Chapter 14, you will see code that can help you discover global variables (such a g_currentMission) in a LUA environment. That said, without understanding metatables (Chapter 13) you likely will still have a hard time finding all of the global variables. Jumping straight into Chapter 13 may be confusing though (particularly if you do not have experince with Javascript or another prototype based programming language), so you might want to read through the previous chapters first.

Being able to find and examine global variables can be a very powerful tool if you wish to pursue farming simulator modding. In fact, in the previous example I provide for printing prices, there were a number of global variables, g_currentMission, g_i18n, and even FillUtil is a global variable. Yes, FillUtil looks like a class and from an implementation standpoint it could be said that FillUtil is a class, but FillUtil is actually a LUA table under the covers. Since FillUtil is a table you can use printTableRecursively to examine it. You will find an undocumented sub-table called fillTypeIntToName which was used in the example to lookup up the fill type name.

BTW, I did not discover the fillTypeIntToName through introspection of global variables, I found it through inspection of other mods. This is the most powerful way to learn things, look at previous examples or mods. But, once you find something, it is nice to have additional tools too look even deeper.

Once again, onto your question:
You said GIANTS didn't document g_currentMission, but is there a list of these tables somewhere, or is g_currentMission basically all of the stored data?
Yes, there is a list of tables somewhere -- in the LUA global environment space. Probably not the answer you wanted. I would say make note of any table starting with "g_" as you are looking throught mods, this seems to be a naming convention followed by Giants for global tables. Also, as you get familiar with LUA, you may be able to write a function that searches the global environment for particular information.

Second answer, g_currentMission is an important table, I don't think it will ever be documented because it is a bit of a dumping ground for the current map/tutorial you are playing. For example, one of the things you will find in g_currentMission is a structure storing gold nugget informtion for the gold crest valley map, I suspect it would NOT be there for sosnovka map. Another example, g_currentMission is also used in the tutorials, but I suspect it would be a very abbreviated version by comparison to playing an actual map like gold crest valley. Finally, even multiplayer affects things that are available in g_currentMission, once again gold nuggets are not available in multiplayer gold crest valley.

I would recommend printing out g_currentMission to get a feel for it, but the first time you see g_currentMission, it will likely be simliar to the first time you looked at the GDN documentation, there will be a lot of information and you may not know where to start.

I have already said this, but previous examples are the best place to start, most of my initial knowledge coming from mods that I cracked open and reading the LUA code inside them. Then, when you start getting a feel for how Giants has organized it's code, you will more easily find the right places to look in both the GDN documentation and inside the LUA global environment.

Lastly, I will say this, you do NOT have to know LUA to do modding in farming simulator. The engine for farming simulator is VERY data driven through XML files and even more XML files -- I3D files are XML files created through the Giants Editor (GE). I have focused on LUA because you seem to want to understand and possibly change the way the script works, instead of configuring a new item that works within the framework Giants has provided. That said, do not ignore these other things, quite often data is hidden in these XML (and I3D) files. Understanding the XML can help you understand the LUA script and vice versa. You may want to go through all the video tutorials provided on the GDN site even if you are not that interested in making a new map or a new piece of equipment, understanding these things will help you understand the scripting.
User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Re: Scripting Reference?

Post by brack »

Well after getting me jump-started I've managed to hobble together my first mod. I still need to grab a couple more icons and add some polish, but here's what I've done with what you showed me. https://i.imgur.com/19m9kan.png

Currently the mod just shows the current and top price seen for each fruit type. The next version will hopefully have options to only display fruits that are currently the best price, or within a configurable margin. Also working on displaying the current text in red or green based on whether it is increasing or decreasing and hiding the current column entirely if desired.

Thanks again for all the information. This post should be a useful tutorial for anyone else in my position as well I hope.
Last edited by brack on Tue Dec 13, 2016 12:46 pm, edited 3 times in total.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

The mod is looking good.

Couple of additional things to think about when testing your new mod,

1) Multiplayer, client vs server. When making a mod that is using shared information, such as prices, you need to think about how and when the information is transmitted (serialized) between client and server. You may have thought about this, but if not lets look at the method you are using to get prices: getEffectiveFillTypePrice

Code: Select all

511	function TipTrigger:getEffectiveFillTypePrice(fillType)
512	    if self.isServer then
513	        return ((self.fillTypePrices[fillType] + self.fillTypePriceRandomDelta[fillType]) * self.priceMultipliers[fillType])
514	    else
515	        return self.fillTypePrices[fillType]
516	    end
517	end
The interesting line is 512, if self.isServer, the question becomes, why does it return different values on the server vs NOT on the server?

The answer comes down to what information is transmitted between client and server, in some cases information is not transmitted, things that are NOT transmitted are fillTypePriceRandomDelta and priceMultiplier. What ends up happening is the server calculates the new price using the fillTypePriceRandomDelta and priceMultipler and then transmits the calculated price to the client, the client then stores ONLY the price. So if you are not on the server, be careful displaying hidden fields which may not have data, or may have invalid data.

How to discover what information is transmitted? Information is transmitted through serialization which seems to be implemented through readStream and writeStream. If you examine the writeStream method, you see that it basically only writes two pieces of information (for each acceptedFillType) to the Network stream, specifically it serializes the results of getEffectiveFillTypePrice and getCurrentPricingTrend.

So this means if you stick to these two pieces of information, you mod will likely be multiplayer compatible. (Since this seems to be the case, you are likely OK, but I wanted to mention this because you might decide to enhance or expand your mod in the future.) That said, testing should always be done to make sure.

Note, you could show more information than those fields in multiplayer, but you would have likely have to write additional code to send that information over the net. Since farming simulator is pretty focused on supporting multiplayer, you will find just about every script object has readStream and writeStream. That said, information that is loaded from XML configuration files is inherently shared because farming simulator uses checksums to make sure every client and server running uses the same XML configurations, an example of this is the isSellPoint boolean value on an instance of a TipTrigger, this is configured in the XML, so does not have to be serialized over the network. This is why mods WITHOUT LUA script are likely to be multiplayer compatible by default.

2) Secondly, be careful of using hidden or undocumented values. This of course relates to the multiplayer differences I highlighted in point 1, but can also relate to some fields, like g_currentMission.tipTriggers. Because they are undocumented, we are "guessing" at how they are used. For example, it should be obvious there are more tipTriggers than sell points due to the fact the example code checks to see if the trigger is a sell point.

I would recommend taking a bit of a deeper look (or maybe you already have) at the "other" tipTriggers. Likely you can guess, because it is somewhat intuitive, other tipTriggers include Farm Silos, the Train Elevator/Silos, etc., where you do not actually sell things but you can "tip" items (fillTypes). But one object you may not think of right away is the HeatingPlantPlaceable. HeatingPLantPlaceable is the LUA "class" associated with the Heizmat Heating Plant that can be purchased to sell wood chips.

Whereas most of the tip/sell points are statically defined in the map's XML/I3D file, this is one case where a new tip/sell point can be dynamically created on the map. This does raise certain questions:
  • will this create a new entry in g_currentMissions.tipTriggers?
  • if it does, is it a sell point?
  • how would this affect your mod?
I will leave you to answer these questions if you are so interested.

This actually brings me full circle to where I was when I started responding to this thread, I was interested in how pricing worked for the Heizmat Heating Plant, because a lot of people think the price of heating plant wood chips is tied to selling wood chips at the sawmill and I was trying to resolve it for thread on reddit. Basically the answer I came to is that the heating plant has a hidden price which does fluctuate like other prices, but is not visible.

I actually consider the fact that Giants does not display the price for the heating plant a bug, or at least something that could be enhanced, possibly through a mod? Since your mod is trying to show the best price and sell point, you may wish to take this into consideration. One thing I did find out though, heating plants cannot use g_i18n.getText to get a localized name for the plant like most map defined sell points. (or at least not in the same way g_i18n.getText is used in the example)
User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Re: Scripting Reference?

Post by brack »

That is some good information regarding multiplayer, thanks. I hadn't really considered multiplayer compatibility as I play single almost exclusively, however I would like to support it in the future. I also hadn't looked very far into the heating plant sell prices.

Now that I've gotten a little further I do have two large questions that I was hoping someone could answer:

1) Are the primary functions documented anywhere? I can guess that loadMap happens during the loading screen when starting a game and that mouseEvent and keyEvent happen during mouse clicks and keyboard presses, however I'm confused on the difference between update and draw. They seem similar and I assume one happens each frame. I also haven't seen deleteMap used yet in any mods I've looked at.

2) Is there any way to detect when the user saves the game so that I can save my mod's data to XML at that point? Currently I'm writing to XML in update() and I'm guessing that is more resource intensive than it needs to be.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

I have just started looking into modding for fs17 myself, and I didn't even play fs15.

I got interested in fs17 modding about a month ago when Giants released the first version of the crop destruction mod. It worked for certain things, but I wanted to change it, so I dug into the GDN documentation while inspecting the code for the mod and created my own version. During this exercise, I found a lot of stuff was not documented, so I created my first mod which added a bunch of console commands to help me debug and inspect the LUA code. I also did not like the "easy" money from gold nuggets and field missions, so I created a single player mod to disable nuggets and decrease mission payout -- I might release this mod as it is pretty close to finished. I am also looking at creating a derivative of the crop destruction mod - but that is a work in progress and I might lose interest.

I am also a bit of a min/maxer when playing games, so I dug into the code to get information about prices and costs as there was a lot of incorrect assumptions out there. This is why I had some knowledge about the more direct second question you asked:
I'm trying to get the prices for each fruit from each sell point. I found the "getEffectiveFillTypePrice" function within Triggers > TipTrigger which I think is what I need, but I'm having some trouble implementing this. I don't know how to loop through each sell point to get the value.
When you asked this question, I had just been looking into this myself to answer some questions about pricing, so I was able to answer the question fairly easily. Also, I had just been spending time trying to "crack" the GDN documentation, so I thought I would explain the way I was able to gain more insight into GDN scripting.
1) Are the primary functions documented anywhere? I can guess that loadMap happens during the loading screen when starting a game and that mouseEvent and keyEvent happen during mouse clicks and keyboard presses, however I'm confused on the difference between update and draw. They seem similar and I assume one happens each frame. I also haven't seen deleteMap used yet in any mods I've looked at.
I have not found any documentation on the ModEventListener methods, just usage from other mods. I will say Giants seems to follow a convention of using "load" type methods to initialize/construct objects and "delete" type methods to cleanup/destroy objects. As for keyEvent and mouseEvent, I have not used these methods at all -- and one of the mods I examined (follow me) did not seem to use keyEvent for input -- so these events might not be as intuitive as they sound. As for draw and update, they seem to overlap a bit, and I do not have a definitive answer for which to use and when.

That said, I have looked into Specializations (Crop Destruction uses a specialization) and they have similiar methods, load, delete, update, updateTick, and draw -- I "googled" and found this thread in the GDN scripting forums about load, update and updateTick.
2) Is there any way to detect when the user saves the game so that I can save my mod's data to XML at that point? Currently I'm writing to XML in update() and I'm guessing that is more resource intensive than it needs to be
.
I do not know how to detect the save event in a mod. I would actually like to know.

I would be careful with update as it does fire every frame, I have had problems even putting "prints" in update/updateTick events because it can drag down the application if you are not careful. (i.e printing to the log every frame will basically hang your game.)

I suspect you are trying to save the "max" prices for your mod. Being able to save these prices when a user saves the game does seem to be the best solution. I would say look for other mods that do the same thing, but I cannot think a mod that would require quite the same interaction with saving the game -- Most of the mods that save data seem to do it based upon user interaction or as a configuration file, both of which can be done without knowing when the user actually saves the game.

if you do end up finding out how to do this, please post it back here.. Or maybe someone else here knows.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

Since I wanted to know, I decided to look into am "onSave" solution a little more...

There is a method in g_currentMission (instance of FSMIssionBase "class") that the GUI uses to save the game, the method is named saveSavegame. If you were brave (notice I didn't say smart... lol), you could hook into this method to detect when a user presses the save button -- but I would NOT recommend it.

With some consideration -- specifically about multiplayer -- I came to the conclusion that basing something on "saving" the game would likely make your mod incompatible with multiplayer. i.e. When saving a multiplayer game, the save file is on the server -- not your local computer. The game is also saved automatically and possibly at the discretion of another player(admin), so likely you would not even be notified of the save.

This may raise some questions for your mod if you are trying to be multiplayer compatible. For instance, you probably want to disable saving information on the server, or if you do save information on the server -- how do you get the information back to the client? Secondly, since the save is on the server, the client will not be notified, so the client may never save... and even if the client is notified, and you wish to save locally -- there probably is not a local save directory -- you would likely have to prompt the user for a file name and location.

You may also wish to take this into consideration when loading information -- I am pretty sure you will get a loadMap event when starting multiplayer -- but using the current save directory may not be valid in this case....

This may be why an "onSave" event does not exist -- or at least is not documented.
User avatar
brack
Posts: 221
Joined: Tue Oct 18, 2011 4:14 am
Location: RI, USA

Re: Scripting Reference?

Post by brack »

Thanks for looking into the save event. It would be nice if GIANTS provided an onSave event and a folder that both the server and client-only versions could use.

I'll do a little more investigation on my own, but it sounds like I may need to come up with a different way to save price data. I may look into saving the data on a time interval.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

There is a way to detect multiplayer, there is a field in "g_currentMission.missionDynamicInfo" table, cannot remember the field name -- something like is multiplayer or multiplayer enabled. You could probably find it by using printTableRecursively. You might just want to disable all loading and saving in multiplayer.
User avatar
Decker_MMIV
Posts: 287
Joined: Wed Aug 22, 2012 1:02 am

Re: Scripting Reference?

Post by Decker_MMIV »

JupAxe wrote:As for draw and update, they seem to overlap a bit
These are my collected experiences/observations, from since the FS2011 days when I started modding for Farming Simulator.

draw should only contain code that actually 'draws' something on the screen. Don't place input-detection nor world-/object-transformation in this method.
It will be called for every 'render-frame', when the LUA-object is in some kind of "active" state.

update will usually contain the input-detection, i.e. InputBinding.hasEvent() and such, and game-world state-changes that can be or needs to be checked/updated very often, to create a smooth gameplay-experience for the player. Don't place any lengthy or complex computations in this method.
Could potentially be called either 'more often' or 'less frequently' than draw. I have no clue about the actual internals of GIANTS game-engine.

updateTick, which unfortunately does not seem to be available/called for addModEventListener(..) registered LUA-objects/mods, is called less times than update. Game-world state-changes which are not required to be "synchronized with the rendered-frames", should be placed in this method. Also I think this method is related to how often the game-engine sends/receives network-packets in a multiplayer game.
To simulate 'updateTick' when only the update method is called, I usually accumulate the delta-time value (milliseconds) which is supplied in the call, into a object-specific variable, and when the sum is greater than a specific threshold, perhaps every 1000 milliseconds, I just manually call updateTick.

keyEvent and mouseEvent are called every time a state-change of the corresponding input-device is detected by the game-engine. Normally these two methods - which needs to be there but not require any body-code in them - are used when more specific/special handling of keyboard- and mouse-events are needed, which can't be implemented via InputBinding methods. Like getting the x/y of the mouse-cursor or if a modifier-key (SHIFT, CTRL, ALT) is pressed or not.
JupAxe wrote:how to detect the save event in a mod.
To my knowledge, GIANTS have not officially documented any 'onSave' callback handler for addModEventListener(..) registered LUA-objects/mods. - Only those that derive from or require Vehicle.LUA have a "documented" save feature getSaveAttributesAndNodes which is used to supply what to store in the savegame#\vehicles.xml file.

So the modding-community have found their own work-arounds and hacks, which usually "break" when the next new version of the game is released every 2nd year, thereby causing the community-scripters to figure out how to do it "the new way". ... I have not had a need for it yet, so not been looking for a solution.

Maybe some of my FS15 mods could give inspiration for searching/exploring what FS17 has to offer? - I did try to make a FS15 'ModsSettings' mod, in a futile attempt to make it "easier" for mod-scripters to have their mod's settings be easily available via some "API" methods. However I never did finish it. Try take a look at it from line 430 and down, to see if that could give you some hints of what to search for in FS17.
JupAxe wrote:There is a way to detect multiplayer
Normally it should be enough for script-code to know if it is being executed on "the server" or on "a client". So when you notice all those ".isClient" or ":getIsServer()" in the code, then that is why.
However there is also a need to know if it is a listen-server (GUI and host-server) or a dedicated-server (server only, no GUI). With some effort in FS2013 and studying lots of other scripters' mods, I discovered they used if g_dedicatedServerInfo ~= nil then to know that their script were executing on the dedicated-server, as ".isServer / :getIsServer()" would return true either way.
JupAxe
Posts: 19
Joined: Thu Nov 24, 2016 10:04 am

Re: Scripting Reference?

Post by JupAxe »

Maybe some of my FS15 mods could give inspiration for searching/exploring what FS17 has to offer? - I did try to make a FS15 'ModsSettings' mod, in a futile attempt to make it "easier" for mod-scripters to have their mod's settings be easily available via some "API" methods. However I never did finish it. Try take a look at it from line 430 and down, to see if that could give you some hints of what to search for in FS17.
Actually, if you look specifically at lines 441 to 456 this is what I meant by "you could hook into this method"

This once again comes down to the fact that a LUA "class" like FSBaseMIssion is actually a table with functions ("methods"). You save the original function and put your own function in it's place. Within your own function, you call the original function you saved. Of course you have to be careful to preserve parameters and return values which can be slightly tricky when you don't have documentation. The example above is pretty straightforward because it just returns at the end, but of course you can do more complex things as well.

In the mod that I created to decrease payout of missions, I used a similar technique where I hooked into some "methods" in the FieldJobManager and then changed the values it returned to decrease payout.

You can also use this technique to insert hooks to debug/introspect/inspect code, like inserting a printCallStack to get information how a function is called, or use printTableRecursively on function parameters and return values to discover more information about a function.

That said, I think the warning from Decker should be heeded:
So the modding-community have found their own work-arounds and hacks, which usually "break" when the next new version of the game is released every 2nd year, thereby causing the community-scripters to figure out how to do it "the new way"
Lastly, Thank you to Decker for chiming in, he is obviously much more experienced in modding farming simulator than me -- I even referenced his very popular mod follow me previously in this thread -- as it was one of the early mods that included significant scripting and therefore could be examined for helpful information. My experience is more my coding background of 35+ years with a number of different languages, including injection of testing frameworks and profiling programs, and this is why I approached this whole discussion more from the side of understanding LUA than from knowing farming simulator.
Post Reply