psychopsi@Posted: Fri Feb 11, 2005 7:02 pm :
I was noticing there isn't any tutorial on func_mover's so i decided to write one :D .

func_mover's can be brushes or models and must be controlled through scripts.

Open up your doom_events.script and take a look at the func_movers section. Here we have just about everything we need to make our levels alive. Now if you don't know anything about scripting, most of these functions are pretty easy to use, so you'll be a pro in no time.

SETTING UP YOUR MOVER

In our basic room i've created a func_mover. I choose models/mapobjects/lab/cscope/cscopearm.lwo as my model. Now that I've got it where i want to have it start we'll start scripting.
Image

Open your text editor and create a new script file with the same name as your map. We're going to make a function called SetUpMovers which will be run in the main function of your map. You don't have to do it this way but it feels cleaner (to me anyway) like this.

Code:
void SetUpMovers ()
{

}

void main ()
{
     SetUpMovers();
}

Our mover will need a name right now so in the map editor change the name to something easy like 'arm' for our purposes. In our doom_events.script we see our setup function: speed, time, decelTime, and accelTime. Speed will set the (duh) speed of our mover. This is useful in some applications but for our we'll use time. Time is the time in seconds for the mover to complete one move. It will take this long for the mover to move to each position EVERY time until you change it.

In our SetUpMovers function we'll add the following lines

Code:
     $arm.time(1);
     $arm.decelTime(.25);
     $arm.accelTime(.25);

What this means is the arm will take 1 second to complete each move and a quarter of a second each decelerating and accelerating. In this function we can add any and all the movers we're going to use.
Let's make it do something!

ROTATION

You'll want to make a new function that is the actual movement of our arm. I named this Arm_move. In your doom_events.script you'll notice all kinds of ways to rotate your mover. For the most part using the functions 'rotate' and 'rotateTo' aren't very useful and requires more testing to get the desired results. We'll use the rotateUpTo and rotateDownTo functions.

Both require an axis and an angle. I want my arm to stand up and wave. First we'll have to get it standing up so we'll need to rotate is 90 degrees on the x axis. You'll have to add
Code:
     $arm.rotateUpTo(X_AXIS, 90);

to your Arm_move function. So lets try it! But wait! How will the player interact? You'll need a trigger to start the arm to move. I used a func_static as a platguistand targeted to a trigger_relay with the key 'call' set as 'Arm_move'. We have to do it this way because a func_static will not 'call' a function. A trigger_relay will.
What we have looks like this:
Image

You may notice a curious thing if you rotated your model in the editor using the angle or the rotation buttons on the menu. The arm did a 360 while it rotated up!! Because the editor has either an angle or rotation set on our mover, the game will bring the rotation back to zero before it completes this action... usually taking the long way. To counter this sometimes ugly move, you can rotate the model to the desired angle at the start up of the level by putting the move in the main function(you'll have to delete the key with your rotation or angle).
since we'd see it rotate anyway in our small room I'm just going to leave it.

USING MULTIPLE MOVES

Okay so now we want our hand to wave to all of us. Since we've got it to stand up we'll need to tell it to wave. This means we want to to repeat the wave and not the upward rotation.

Between each movement we'll need to tell the game to waitFor the action to complete.
Code:
     sys.waitFor($arm);

will tell the system to wait for the arm to stand. our script should now look like this.
Code:
void SetUpMovers ()
{
     $arm.time(1);
     $arm.decelTime(.25);
     $arm.accelTime(.25);
}
void Arm_move ()
{
     $arm.rotateUpTo(X_AXIS, 90);
     sys.waitFor($arm);

}

void main ()
{
     SetUpMovers();
}


we're going to add a new function now called Arm_wave. This will need to be BEFORE the Arm_move function because it will be called there. Our script will look like this:
Code:
void SetUpMovers ()
{
     $arm.time(1);
     $arm.decelTime(.25);
     $arm.accelTime(.25);
}
void Arm_wave ()
{
     while(1)
     {
      $arm.rotateDownTo(Z_AXIS, -30);
      sys.waitFor($arm);
      $arm.rotateUpTo(Z_AXIS, 30);
      sys.waitFor($arm);
     }
}
void Arm_move ()
{
     $arm.rotateUpTo(X_AXIS, 90);
     sys.waitFor($arm);
     thread Arm_wave();

}

void main ()
{
     SetUpMovers();
}


The 'while (1)' makes our function loop and 'thread Arm_wave();' tells the system to run Arm_wave as a thread, or "in the background". Notice after every move I tell the system to wait. This is also a good place to trigger other thing like lights and sounds.

Okay the hand is pretty lame so lets make a corpse dance around the room or something

MOVEMENT

We'll create another mover here out of a brush. Use the texture common/nodraw so we wont see it. I named this mover corpse_anchor. I'm sure you've read the corpse through glass tut as it's a helpful one. you'll need to bind your ragdoll to the mover as well as have the key 'bindConstraint name1' set to something like 'ballAndSocket waist Hips'.

we'll need to setup our corpse's time and such so add the following to your SetUpMovers function.
Code:
     $corpse_anchor.time(.5);
     $corpse_anchor.decelTime(.1);
     $corpse_anchor.accelTime(.1);


Lets make it dance! Add a func_static with a name like 'point1' or anything you like with the texture common/nodraw. The ragdoll will be moved to this point. Our new function will look like this:
Code:
void corpse_dance();
{
     $corpse_anchor.moveTo($point1);
     sys.waitFor($corpse_anchor);

}

Now lets make it move again.
We'll add the lines:

Code:
     $corpse_anchor.move(LEFT, 20);
     sys.waitFor($corpse_anchor);

This just makes the mover go 20 units left, for the purpose of seeing how the move command works.

In our doom_events movers section we have 'bob' and 'sway'. These functions are similar. With 'bob' you will need speed, phase, and distance; with 'sway' you'll need speed, phase, and angle. We'll make him bob so you can add the line:
Code:
     $corpse_anchor.bob(10, 0, '0 0 5');


the speed is 10, the phase will be 0 (can anyone fill me in of the meaning of phase?) and the distance is '0 0 5' which means 5 in the z-axis. The distance and the angle on either bob or sway must be a vector meaning 'x y z' values. our zombie will now move twice then act like he's floating. Also notice that once a mover is given a 'bob' or 'sway' command that it will continue to do so in a loop.

MISC

-Rotate models through scripting and NOT in the editor when dealing with models that need a different oreintation.
-Sway is good for swinging lights or objects.
-You can trigger entities after moves complete.
-For info on func_movers following NURBS visit http://www.doom3world.org/phpbb2/viewtopic.php?t=5123
-Experiment!!



psychopsi@Posted: Wed Feb 16, 2005 4:29 am :
An important function i forgot to add is moveToPos. it's simple enough to use, ex:
Code:
     $your_movers_name.moveToPos('0 0 0');

just replace the zeros with coordinates and it will move straight there with the current time or speed (thru solid geometry as well, so be careful).



mfh1900@Posted: Wed Jul 12, 2006 1:06 pm :
Why yours tut isn't on tutorial listing? It's very good. I like manipulating monvers. If u first see scripts u think - it's impossible to make that mover, it's so hard. But if u look at this better u think - it's so easy to make that movers. :D



voldemort@Posted: Wed Jul 12, 2006 1:46 pm :
dont forget if its a simple movement from point a to point b using a curve ""spline"" is easier and quicker to set up .. Since you allready have to plot out the cordinates in editor why not just add a curve point at each position

thera are actually a ton of other tutorials on movers but they typically are tied in to other topics or use titles like spline or curves etc

Look for camera or cinematic tutorials and there is even one here that shows you how to reproduce the trains in doom3

good tutorial though especiially since scripting does give you more control over movements