The Official Scripting Ask Thread
I cannot get this scenic railway train to attach to the hidden wireframe.

I keep getting this error. "attach_object.nlvm: No train 1 found within range of 3.0 meters" The 3ds train is is right in the middle of the hidden wireframe train but still gets the error.
Hello ! I was reading the NL2 Script manual and i found the method " onTrainLeaving ( TrackTrigger trigger, Train train)" Does it mean that the word trigger should be replaced with the name of your trigger and the word train replaced by the number of the train you want to detect ?
No, NL2 will provide you with the information which trigger has been left by which train with these two:
This whole method is a so called "callback" method. And each time a trigger to which you have so to say "subscribed" can send you "hey mr. a train just left a trigger". You can then access more information or actions by using these two so called parameters like for example query the train's speed.
To break the meanings down a little bit more:
-"TrackTrigger" designates that the first parameter will be a TrackTrigger object. You can look up in the class reference what you can do with these track trigger objects.
-"trigger" is just a name (you can think of it as a label put on a box in which you can find a track trigger) suggested in the manual for acessing it in the code that will follow in this method. It's perfeclty valid to choose your own name to acess it in the following code but I would not recommend to do so.
The same with the second parameter:
-"Train" designates that the second parameter will be a Train object. When you look it up in the class reference you will probably notice that you can at a first glance do more interesting things with it like query it's speed or position.
-"train" is also just a label as before.
An example as it would be used in the code.
public void onTrainLeaving(TrackTrigger trigger, Train train) {
train.getSpeed();
train.getCarCount();
train.getBogieCount();
train.getHarnessState();
}
And to hopefully make clear what I meant with the labeling, that would also work (but is not recommended):
public void onTrainLeaving(TrackTrigger theTriggerThatCalledThisMethod, Train theTrainThatLeftTheTrigger) {
theTrainThatLeftTheTrigger.getSpeed();
theTrainThatLeftTheTrigger.getCarCount();
theTrainThatLeftTheTrigger.getBogieCount();
theTrainThatLeftTheTrigger.getHarnessState();
}
And you might wondering for what the trigger parameter might be used for (since you cannot even query interesting looking information or do interesting actions at this point). Typically that is just used when you "subscribe" to more than one trigger in your script, to desinguish between them. This would require that you "remember" the triggers to which you have "subscribed" in your script and then compare these in this method like for example:
public void onTrainLeaving(TrackTrigger trigger, Train train) {
if (trigger == theTriggerNextToTheStation) {
//do something
} else if (trigger == theTriggerNextToTheLift) {
//do something different
}
}
The same could be also be done to identify a certain train number.
I think dealing with triggers and callbacks is a little bit more advanced topic since the mechanism might seem a little bit inconvenient at first maybe, but that's actually a very elegant programming technique.
If you have further questions don't hesitate to ask. But also notice that there is a working example script that comes with NL2 in the scene object demos that also automatically creates track triggers at the object position, "subscribes" to these triggers (registering the Script as a trigger listener) and executing these steps in these methods.
Thank you so much Bestdani, your explanation was very good :)
I'm trying to add an object to Special Track (Tilt) but i got an error : Error: Class not found: AttachToSpecialTrackByName
Who can help me ?
That means that nl2 can't find the required Script class, in this case the file "AttachToSpecialTrackByName.nlvm" is probably not present in your object / scripts folder or it is corrupt for some reason.
Hello,
i have a problem with a simple script. I have a water wheel that should rotate around the Z-axis, its axle is the Z-axis itself. I have copied the example file from NoLimits help and used it in a test park with a wheel that has its axle in Z-direction. That works, i have change
sco.setRotation(0, 0, totalTime);
But in my other park the wheel is rotated by 90° in Y, so its axle shows now in x.diretion. But now it is not rotating. If i change
sco.setRotation(totalTime, 0, 0);
wheel flips around X-axis, nut is not rotated by 90° around Y.
What is to do if your rotating object has another orientation (rotate Y) as 0°. I think, there is no problem, when it is rotating around Y...
Also there is one error message, that i do not understand:
if i write
sco.setRotation(0, 0, totalTime/2);
in my test park, wheel rotates with half speed (one rotation in ca. 12.6 seconds = 2PI), but when i write
sco.setRotation(0, 0, 0.5totalTime);
i get an erroe message: "Unknown Methof: setRotation(int, int, double);"
But totalTime is a float or double, it is the time in seconds. I have added code that resets totalTime after it becomes >10, every 10 seconds rotations jumps, but rotation itself is smooth (so a time of e.g. 2.134 seconds results in correct angle of wheel for that time). But i cannot use formulas with float constants.
Best regards
U can set the rotation in the SCO editor, maybe that helps.
For the rotation, u can use the emergencylight script and modify it.
Hello,
i have written this lines:
angle = (float)1.570796; // PI/2 = 90°
sco.setRotation(0, angle, totalTime/2);
This is a "dirty" solution. Angle is a private float variable, if i insert the value of PI/2 directly, i get an error message. I rotate the wheel around Z with animation and i rotate around Y to position wheel, this give a correct view in play mode. I have luck because rotation around Z is made obviously before around Y... But in edit mode the wheel is positioned 90° wrong because it will not be rotated by 90° in editor but only in script file. I do not know if it will also work if you have angles other than multiple of 90°.
There must be solutions, how does the ferris wheel work? It rotates by a horizontal axle and can be positioned like all other scenery objects including rotating around Y by any angle. Are there switches to set that an object animates first by script and then is rotated, scaled and translated as in editor adjusted?
Best regards
For the rotation, there are several solutions:
The cleanest would be just rotating a specific element of the scene object instead of setting the whole object, without having looked at at it, i'm pretty sure that this is what the ferris wheel does. Doing it this way, the element and all sub elements would always rotate around the object's local axis.
If the "dirty" solution works for you for now it's fine, if you really want to rotate the sco around a specific axis with a specific rotation order you can achieve this by multiplying the required rotation matrices in the desired order manually in the script. The cleanest solution when you do it that way would be probably done by reading the preset editor rotation at the script startup.
By the way, for just constantly rotating elements one can also use a special material rotation effect instead of scripting or keyframe animations. Keyframe animations can also be controlled by the script, this would allow some interaction if it's needed, this would take away completely the responsibility for managing rotations.
For the not understood problems with doubles. The short answer is just manually down cast it to float as before every time and it will work. For the multiplications when you write setRotation(0, 0, 0.5f * totalTime); instead of setRotation(0, 0, 0.5 * totalTime); it will be automatically kept a float if angle is a float already.
There are strict rules for Java and for NLVM which are probably exactly the same, how expressions get automatically casted to other types. In your case with the double totalTime expression 0.5 * totalTime will be a double since 0.5 is a double.
But totalTime / 2 will be a float since 2 is an integer which will be casted to float before the division when I remember the exact rules correctly.
And 0.5f * totalTime will stay a float since both 0.5f and totalTime are floats.
Since doubles never get downcasted to floats automatically, NLVM will also not do this when you enter setRotation(float, float, double) to use the only existing setRotation(float, float, float) method. But integers will be casted, so setRotation(int, int, float) for example will be casted to match the existing method. There are also exact rules when this happens.
When you wonder why it is this way: It has to do with the inaccuracies when working with floating point values, while you do not lose information when the engine automatically casts from float to double or from int to double you will the other way around, therefore this never happens automatically.
Hello,
i thought, that the script will be done first for the object and then the rotating and scaling for the position, last the translation as in the editor adjusted. But this is obviously not the case. The best solution is as described, so i can add the animated element like any other scenery object and rotate, scale and translate it into the park. My waterwheel is made of two parts: the fixed, not animated part like waterpipes, supports etc. and the animated wheel itself. Both parts are added separately to the park. But i do not know the order of calculations from scripts and editing parameters, so there is a lot of try and error to see what is going on.
Now it works, but looks strange in edit mode because wheel axle is turned by 90°. All other solutions need editing in script files or so before adding to park and rotating by editor positioning window is not possible.
I have also recognized, that function need float, not double. I am programming in C, there variables are casted "up" and "down" according needed format (not all cases). So you can mix float and double without getting syntax errors, you get only a warning for loosing accuracy, when implicitly casting double to float. For the fixed angle i had used a float variable, i didn't know the syntax "2.0f" for a float constant. Matrix multiply is needed for flat rides with more complicated movements, also the ferris wheel: the single cabins are rotating the other way as the wheel, so that they are always upright, other rides like break dancer etc. have a lot of matrix multiplications.
Perhaps i will try more scripts when i make more objects, most objects are not animated like buildings, requisites, a wooden station for wooden coasters made by single segments, so stations of different lengths are possible etc.
Best regards
Hi.
2 simple question:
NoLimits.getVersion() - Why is the version: 33883401 and not 2559?
getVersion () - Returns the application version encoded as 4 values static int (a.b.c.d).
Secound question:
How to get the total track lenght of a coaster via nlvm (not hardcoded written down from the statistics window)
This might be really simple, and might just be a dumb question, but.... old Arrow coaster chains usually go extreamly slow untill the car catches it, then speeds up to a resonably fast speed.... still pretty dang slow, but still... Figure i need scripting for this, so thougt id ask..... Help?
^
if i remember correctly, you just need to set the acceleration to a low number like: 0.1 or 0.01.
Yes, when you tires, the friction isnt stong enough to carry the train up the track. But Chains dosnt have friction or have infinite friction.
So the chain instead accelerate in a slow way.

Important is, that the Station is around 10 meters behind a block segment.
Its like 90% accurate and the best result without scripting.
Does anyone know of a step-by-step tutorial on how to script? Because I’ve searched all over and CANNOT find a good scripting tutorial for myself. So if anyone knows of anything useful, could you tell me or help me out? Thanks!
There isn't any complete as far as I know, probably since it would be an enormous effort to do it well and related to this: There are already many great tutorials, books and courses about programming in general.
With basic knowledge from one of these it's easy to start writing own NL2 scripts using the information provided in the nl2 manual.
Since the NLVM language is very close to Java you might want to learn with tutorials for this. But since the concepts of all common programming languages are the same it should be possible to switch from any language to NLVM with just little effort.
^^^ Thanks! That helped a lot, thanks!
Thanks! I’ll try that!
Does anyone know where I could find a script for water spray effects similar to manta?
u can use the triggered fog and changing the particles to make it like the effect u want, use triggers along the track to make it more realistic.
I have a highly customizable water splash effect script online Steam Workshop or Dropbox (Probably I will update this soon, so rather subscribe in steam to not miss it).
How do you make custom chain lift sounds?
You couple the sound playback, its gain and maybe its pitch to the Section.getLiftCurrentSpeed() value.
A simple example script (I did not test it, it may contains bugs or typos):
/*
* Save this file as LiftSound.nlvm and use it as a coaster script
* You have to modify some parameters below to match it for usage in your park
*/
import com.nolimitscoaster.Coaster;
import com.nolimitscoaster.Script;
import com.nolimitscoaster.Section;
import com.nolimitscoaster.StaticSound;
import nlvm.math3d.Vector3f;
public class LiftSound extends Script {
private StaticSound sound;
private Section liftSection;
public bool onInit() {
Coaster coaster = sim.getCoasterForEntityId(getParentEntityId());
liftSection = coaster.getSection("your lift section name");
sound = StaticSound.loadFromFile("your sound file.wav", 0);
sound.setPosition(new Vector3f(0, 0, 0)); //replace 0 values with position of the sound
sound.setDistanceParameters(1, 1); //set as desired (referenceDistance, rolloffFactor)
return true;
}
public void onNextFrame(float tick) {
float liftSpeed = liftSection.getLiftCurrentSpeed();
if(liftSpeed > 0){
sound.playLoop();
sound.setGain( 0.3f * liftSpeed);
sound.setPitch( 0.8f + 0.3f * liftSpeed);
}else {
sound.stopFaded(0.3f);
}
}
}
im trying to make a simple track trigger, that says something when the train triggers it using the:
System.println(" ")
(TrackTrigger trigger, Train train)
I know im probably missing something

i may have posted in the wrong thread earlier. i am a noob at scripting, i have the camera script by jet pulse and am trying to figure out how to make it work. i have discord to use since sometimes thats easier for me to learn etc. i guess there are some specifics im missing on it. any help would be appreciated. simplifying this stuff works sometimes. lol