Platform That Moves When Button Is Pressed

From The DarkMod Wiki
Jump to: navigation, search

written by Dram

Ok, here's the first tute of many. With pictures!

This tute assumes that you already have set up a brush or whatever that will be your mover and another brush that will be your button.

Platform that moves when button is pressed

This button once pressed can be pressed as many times as you want but will only set it off once during the transition of the platform's movement. In other words, pressing the button while the platform is moving does not restart the sequence nor reverse it; you can only get the platform to move if it's finished moving.

The platform also has TWO movement parts. First down and then right. You'll see.

This tute will have two parts:

  • setting up the platform
  • making a script to match

Setting Up the Platform

Ok, first set the brush that will be your button to a func_darkmod_button (I have it as a func_darkmod_sliding_door in this, but I'm guessing that for the future it should be a button):

Image

Now we set parameters to it. I will explain the parameters I have set it to and why:

  • translate 0 -2 0 - This makes the button move -2 units in the y direction. The axis' here are x y z respectively, so you can have it move in several directions.
  • rotate 0 0 0 - This makes the button not rotate. AFAIK Spar said this must be set otherwise it will turn in the default of 90 to the x axis.
  • state_change_callback platform_state - This is the script function that should be called when this button is pressed. You can name that function whatever you like, but for this tute I've named it platform_state.
  • translate_speed 15 - This is the speed at which the button should move in doom units/sec. You can set this to however fast or slow you want.
  • interruptable 0 - This is a value that should be set to the button otherwise if you frob the button and frob it again it will stop in it's movement. This means that you could frob it and refrob it and it could stop halfway in it's movement - very ugly and annoying, so we set this value and it will keep going until it getsd to either open state or closed state (in or out for buttons).

Now that we've set up our button, time for the platform:

Select the brush that will be your platform and select func_mover from the list

Image

Now for the parameters:

  • accel_time 1 - This sets how long it takes for the mover to get to full speed. I have it to 1 second so that it looks believable that it speeds up in a little while rather then straight away.
  • decel_time 1 - As above but for decelleration.
  • move_time 3 - This is how long it takes for the mover to make a complete move (so if it's told to go 300 units down then it will take 3 seconds to do so in this example). You can do this or you can do it through the speed it moves at during it's move - move_speed but you'll have to make sure you know how long it moves for. You'll see why.

Making a Script to match

Ok, now we can save the map and make a script. It's easiest to just copy another map's script and edit it, but you can simply create one by making a .txt document and renaming it to .script - same formatt really.

Now open up your script in Notepad or Wordpad (I use MS Visual C++ to open it as it has colour coding, making it easier to work with, but you don't need this) and add the following code into it:

float door_state = 0;
float door_done = 1;

void main()
{
}

void platform_state(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (door_state == 0)
     {
       if (door_done == 1)
       {
         door_done = 0;
         sys.wait(2);
         $func_mover_1.move ( 270, 384 );
         sys.wait(3);
         $func_mover_1.move ( 0, 64 );
         sys.wait(3);
         door_state++;
         door_done = 1;
       }
     }
     else
     {
       if (door_done == 1)
       {
         door_done = 0;
         sys.wait(2);
         $func_mover_1.move ( 180, 64 );
         sys.wait(3);
         $func_mover_1.move ( 90, 384 );
         sys.wait(3);
         door_state = 0;
         door_done = 1;
       }
     }
  }
}

Ok, now to explain WTF everything does:

  • float door_state = 0; - This is a variable and is set to 0 by default. If you put float door_state; then it won't have the number as default, and I think the default will be 0.
  • float door_done = 1; - This is another variable.

Now on to the main code, you'll se the importance of these variables further on:

void main()
{
}

I'm not completely sure what this function is used for and when, but you have to put it in anyway afaik. For our case we have it do nothing.

void platform_state(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{

Remember how I said to put whatever name you want for the script function called? Well this is it. As you can see the name of mine is platform_state.

Ok, now to go through the rest of the code:

if(bOpen)  // the bOpen here is when our button is pushed in, or "open"
{
   door.Close(1); // this makes the button go back out ala T1/2, or "close"

When our button is first pressed the following happens:

if (door_state == 0)  // if the platform is NOT moving do the following:
{

When the platform is at our starting position door_state is 0. If this variable is at anything else BUT 0 it will skip this part of the code and go down the the ELSE you seefurther down. Basically - "Is the door state 0 (start)? yes, good, make it move." then when it's moved, "Is the door state 0 (start)? no, ok, go down to what happens if it's NOT at the start"

if (door_done == 1) 
{ 

When the platform is in motion this is set to 0 so that pressing the button again and again won't reverse or restart the sequence. The reason for this is that basically pressing the button again and again would constantly restart this sequence, meaning it would end up waaay away from where you want it

door_done = 0; // this sets the variable door_done to 0, which for this case indicates that the platform is in motion
sys.wait(2);   // this is a delay. 2 seconds for our case to give the player time to get onto the platform. 
               // You don't need this at all, but for a platform the player is meant to get on this is needed.

as you see below, there is $func_mover_1.move, this is basically addressing a specific mover. This is super-important, so make sure that instead of $func_mover_1 you have the name of your platform. eg: your platform's NAME is func_mover_195, then you address it directly via $func_mover_195 - that is, the dollar ($) sign.

 $func_mover_1.move ( 270, 384 ); // the movement of the platform. Will explain this later on
 sys.wait(3);                     // remember how I set the move_time of the platform to 3 seconds? this is why. 
                                  // This delay basically is to let the mover make it's first movement before the second movement
 $func_mover_1.move ( 0, 64 );    // second movement
 sys.wait(3);                     // again a delay so that the platform has time to move
 door_state++;                    // this adds 1 to the door_state variable. so if it's already at 1 it'll go to 2 and so on. 
                                  // you can also have it just set the value straight, ie: door_state = 1, 
                                  // but I've chosen to do it this way to get you familiar with more functions

 door_done = 1;                   // after both movements are done we set this variable to 1 again, 
                                  // this means that we can press the button to move the platform again
 }
}
else                              
{

As explained before, this is when the door is NOT at the start. Basically when the door_state variable is anything BUT 0. The rest is just the reverse of before. So when you press the button at first it moves to a certain spot, then when pressed again it moves back.

   if (door_done == 1)
   {
    door_done = 0;
    sys.wait(2);
    $func_mover_1.move ( 180, 64 );
    sys.wait(3);
    $func_mover_1.move ( 90, 384 );
    sys.wait(3);
    door_state = 0;
    door_done = 1;
   }
  }
 }
}

The Platform's Movement

As we saw above, the mover is told at first to move like this:

$func_mover_1.move ( 270, 384 );

Let's go into more depth about this.

Ok, so basically there are two values to a MOVE function - direction, and amount. In perspective that's move ( DIRECTION, AMOUNT );

So telling our mover to $func_mover_1.move ( 270, 384 ); means that we're telling it to go in the azimuth of 270 (if you have a look in the editor there is a direction definition thingy inthe entity view)

Image

270 in the editor is down the screen if you look from top view, or "XY TOP". So basically we're telling our mover to move 384 doom units down the screen from top view. If you want it to move left then you'd set it to 180, right 0 or 360 and up 90 etc. For moving UP and DOWN (actual up and down, not up or down the screen) you put UP or DOWN instead of 270 or whatever.

so with our mover:

$func_mover_1.move ( 270, 384 );   // makes it move in azimuth 270 and moves 384 Doom units in that direction

Now if we wanted to make it move in several directions at once in our script, we'd do it like this:

$func_mover_1.move ( 270, 384 );
$func_mover_1.move ( 180, 384 );
$func_mover_1.move ( UP, 384 );

This will make it move 384 in the directions: 270, 180, UP. Nice and simple. So to relate this to our code:

$func_mover_1.move ( 270, 384 );
sys.wait(3);
$func_mover_1.move ( 0, 64 );
sys.wait(3);

if we want it to do both movements at once we'd do:

$func_mover_1.move ( 270, 384 );
$func_mover_1.move ( 0, 64 );
sys.wait(3);

Remember that we still need that delay at the bottom so that it has time to finish it's movement.

Handy Trick to measure Distance in Edtior

You can either count the grid spaces between the platform edge and where it should end up or you can do it the following way:

Look at your platform's edge and draw a brush from it's edge to where you want that edge to end up. For our case we'll check the distance in azimuth 270.

Image

Ok, now that we have the brush there leave it selected and hold down Q on your keyboard. As you can see it shows the stats of the brush on screen (it's length and width etc). Now just read what it says as the width and now you know how many doom units the distance is. Easy.

Image

Congratulations, you've just made your first platform.

Caution

An Important thing to note: YOU MUST NOT HAVE THE SCRIPT AIM TO MOVE THE MOVER INTO THE VOID OF THE MAP, basically out of the map. This is because the mover will then be NON SOLID. This is also the case if you put the mover as starting in the void.