Hello
I was wondering if someone could help me out. I have this door I made and would like for it to open when the train hits a trigger. I am using 3ds max. How would I script this? Do I create an animation? Thanks.
leftDoor = sco.getElementForName("DoorLeft"); rightDoor = sco.getElementForName("DoorRight");
import com.nolimitscoaster.*;
import nlvm.math3d.*;
public class DoorScript extends Script implements TrackTriggerListener
{
private SceneObject sco;
private SceneObjectElement leftDoor;
private SceneObjectElement rightDoor;
private static final int STATE_IDLE = 0;
private static final int STATE_OPENING = 1;
private static final int STATE_OPENING_REVERSED = 2;
private static final int STATE_CLOSING = 3;
// rotate up to 90 degrees
private static final float MAX_ANGLE = (float)(Math.PI / 2.0);
private static final float SPEED = 1.6f;
// rotate around Y-Axis
private static final Vector3f AXIS = new Vector3f(0,1,0);
private int state;
private float rot;
private TrackTrigger beforeDoorTrigger;
private TrackTrigger behindDoorTrigger;
private StaticSound doorSound;
private static final String scriptName = "DoorScript";
// must be constant string expression and marked as final so that the compiler will no complain with a warning when used for
// StaticSound.loadFromFile
private final static String doorSoundFile = "doorsound.ogg";
public bool onInit()
{
sco = sim.getSceneObjectForEntityId(getParentEntityId());
if (sco == null)
{
System.err.println(scriptName + ": the script is not part of a scene object");
return false;
}
leftDoor = sco.getElementForName("left");
if (leftDoor == null)
{
System.err.println(scriptName + ": element not found: left");
return false;
}
rightDoor = sco.getElementForName("right");
if (rightDoor == null)
{
System.err.println(scriptName + ": element not found: right");
return false;
}
doorSound = StaticSound.loadFromFile(doorSoundFile, 0);
if (doorSound == null)
{
System.err.println(scriptName + ": could not load sound '" + doorSoundFile + "'");
return false;
}
Vector3f pos = new Vector3f();
sco.getTranslation(pos);
doorSound.setPosition(pos);
// Setting to 'Local' will enable environmental (reverb) effects if this sound's position should be e.g. in a tunnel
doorSound.setEnvironmentMode(StaticSound.E_ENVMODE_LOCAL);
// These parameters affect the distance attenuation
doorSound.setDistanceParameters(2.0f, 0.8f);
final float range = 10;
// create triggers...
TrackPos trackPos = sim.findNearestCoasterTrack(pos, range);
if (trackPos == null)
{
System.err.println(scriptName + ": no coaster found within a range of "+ range + " meters");
return false;
}
else
{
Coaster coaster = trackPos.getCoaster();
System.out.println(scriptName + ": Coaster found: " + coaster);
System.out.println("Coaster Style is: " + coaster.getCoasterStyleId());
// create a trigger 5 meters in front of the track pos
beforeDoorTrigger = TrackTrigger.createTrackTriggerAtOffset(trackPos, -5.0);
// create a trigger 5 meters after the track pos
behindDoorTrigger = TrackTrigger.createTrackTriggerAtOffset(trackPos, +5.0);
// tell the triggers that they should call our onTrainEntering/onTrainLeaving methods
// We have to implement the TrackTriggerListener interface
beforeDoorTrigger.addTrackTriggerListener(this);
behindDoorTrigger.addTrackTriggerListener(this);
}
state = STATE_IDLE;
rot = 0;
return true;
}
public void onNextFrame(float fTickTime)
{
switch (state)
{
case STATE_IDLE:
// do nothing
break;
case STATE_OPENING:
{
rot += fTickTime * SPEED;
if (rot >= MAX_ANGLE)
{
rot = MAX_ANGLE;
state = STATE_IDLE;
}
//leftDoor.setRotation(rot, AXIS);
leftDoor.setTranslation(new Vector3f(-rot, 0, 0));
//rightDoor.setRotation(-rot, AXIS);
rightDoor.setTranslation(new Vector3f(rot, 0, 0));
}
break;
case STATE_OPENING_REVERSED:
{
rot -= fTickTime * SPEED;
if (rot <= -MAX_ANGLE)
{
rot = -MAX_ANGLE;
state = STATE_IDLE;
}
//leftDoor.setRotation(rot, AXIS);
leftDoor.setTranslation(new Vector3f(-rot, 0, 0));
//rightDoor.setRotation(-rot, AXIS);
rightDoor.setTranslation(new Vector3f(rot, 0, 0));
}
break;
case STATE_CLOSING:
{
if (rot > 0)
{
rot -= fTickTime * SPEED;
if (rot <= 0)
{
rot = 0;
state = STATE_IDLE;
}
}
else if (rot < 0)
{
rot += fTickTime * SPEED;
if (rot >= 0)
{
rot = 0;
state = STATE_IDLE;
}
}
//leftDoor.setRotation(rot, AXIS);
leftDoor.setTranslation(new Vector3f(-rot, 0, 0));
//rightDoor.setRotation(-rot, AXIS);
rightDoor.setTranslation(new Vector3f(rot, 0, 0));
}
break;
}
}
/**
* This method is part of the TrackTriggerListener Interface implementation
*
* It will be called if the interface is registered for a trigger using the
* addTrackTriggerListener method.
*/
public void onTrainEntering(TrackTrigger trigger, Train train)
{
if (trigger == beforeDoorTrigger)
{
if (train.getSpeed() > 0)
{
state = STATE_OPENING;
doorSound.play();
//printTrainPositionAndRotation(train);
}
}
else if (trigger == behindDoorTrigger)
{
if (train.getSpeed() < 0)
{
state = STATE_OPENING_REVERSED;
doorSound.play();
}
}
}
/**
* This method is part of the TrackTriggerListener Interface implementation
*
* It will be called if the interface is registered for a trigger using the
* addTrackTriggerListener method.
*/
public void onTrainLeaving(TrackTrigger trigger, Train train)
{
if (trigger == beforeDoorTrigger)
{
if (train.getSpeed() < 0)
{
state = STATE_CLOSING;
doorSound.play();
}
}
else if (trigger == behindDoorTrigger)
{
if (train.getSpeed() > 0)
{
state = STATE_CLOSING;
doorSound.play();
}
}
}
// This method demonstrates how to get the position and rotation of the first bogey
private void printTrainPositionAndRotation(Train train)
{
if (train.getBogieCount() > 0)
{
Vector3f pos = new Vector3f();
Vector3f front = new Vector3f();
train.getBogieOrientationAndPosition(0, front, null, null, pos);
System.out.println(scriptName + ": First bogey is at " + pos);
double azimuthRad = Math.atan2(front.x, -front.z);
double elevationRad = Math.atan2(front.y, Math.sqrt(front.x* front.x + front.z* front.z));
System.out.println(scriptName + ": Yaw is " + Math.toDegrees(azimuthRad) + " degrees");
System.out.println(scriptName + ": Pitch is " + Math.toDegrees(elevationRad) + " degrees");
}
}
}
Return to NoLimits Coaster 2 Scripting