Elevators, multi-floor

From The DarkMod Wiki
Revision as of 18:41, 22 April 2008 by Fidcal (talk | contribs)
Jump to navigationJump to search

Two stage elevator using sliding door entity

A quick and simple way to make a two-floor elevator is just to use the sliding door entity. This is now superseded by a custom Dark Mod elevator entity but for interest, see for details.

Multi stage elevator using custom Dark Mod entities

written by Fidcal

Three stage elevator using a script

Originally written by Dram on http://forums.thedarkmod.com/topic/3865 Ok, assumed knowledge is:

These are covered in the how to make a platform move tutorial, so do that one first and everything here will be simpler to understand.

This elevator basically is like the ones in thief, in that you press a button to go up or down rather then a button to select which floor to go to.

Start

Ok, to start, make 3 floors, each with a panel that has buttons, and the elevator itself. The bottom floor needs one button, the middle floor needs two, and the top needs one. Make all the buttons into func_darkmod_button. For the bottom floor button we have these attributes:

image14ea.jpg

Those attributes are for the bottom button. For the other buttons the only difference is what script function it calls vie the "state_change_callback" attribute. The following pic shows the name of each script function in relation to the buttons. Remember that these script function names can be changed to whatever you wish.

Names of script functions relative to buttons

Also make sure your elevator is at the bottom level. For this purpose anyway. Once you understand how the scripts work you'll be able to change where it starts yourself. Now change the elevator into a func_mover, if you have'nt already.

These are the settings on the elevator in this tute:

image39cc.jpg

To explain the settings:

  • name elevator - Name of the entity. Can be whatever you want, just remember the name.
  • accel_time 0.4 - Time it takes to accelerate to full speed. ).4 seconds for this one to tune in with the sound.
  • decel_time 0.4 - As above except for deceleration.
  • move_speed 30 - The speed at which the elevator travels in Doom units/second. Make sure you calculate how long it takes to get to each floor otherwise pressing the button when it has'nt completed it's movement will restart it and cause problems. Basically calculate it for the delay that will be mentioned later on.
  • dmg 1000 - Does 1000 damage to anything that obstructs it - DON'T STAND UNDER IT MWAHAHAHA.
  • snd_move test_elevator_loop - The sound to make while moving. Put your own sound here. The sound has to be a looping sound otherwise it'll play only once.
  • snd_accel test_elevator_stop - The sound to make when accelerating. Does not need to loop.
  • snd_decel test_elevator_stop - As above but for deceleration.

The Script

Now to make the script for it. Remember that you can have many script functions in one map script, just they all have to be unique.

Paste the following code into your map script:

float elevator_moving = 0;
float elevator_state = 0; // 0 is bottom, 1 is middle, 2 is top

void main()
{
}

// The Elevator

void elevator_bottom(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (elevator_moving == 0)
     {
        if (elevator_state == 1)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 248 );
          sys.wait(9);
          elevator_state = 0;
          elevator_moving = 0;
        }
        else if (elevator_state == 2)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 472 );
          sys.wait(19);
          elevator_state = 0;
          elevator_moving = 0;
        }
        else if (elevator_state == 0)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 248 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
     }
  }
}

void elevator_middle_a(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (elevator_moving == 0)
     {
        if (elevator_state == 1)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 248 );
          sys.wait(9);
          elevator_state = 0;
          elevator_moving = 0;
        }
        else if (elevator_state == 2)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 224 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
        else if (elevator_state == 0)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 248 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
     }
  }
}

void elevator_middle_b(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (elevator_moving == 0)
     {
        if (elevator_state == 1)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 224 );
          sys.wait(9);
          elevator_state = 2;
          elevator_moving = 0;
        }
        else if (elevator_state == 2)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 224 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
        else if (elevator_state == 0)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 248 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
     }
  }
}

void elevator_top(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (elevator_moving == 0)
     {
        if (elevator_state == 1)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 224 );
          sys.wait(9);
          elevator_state = 2;
          elevator_moving = 0;
        }
        else if (elevator_state == 2)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 224 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
        else if (elevator_state == 0)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 472 );
          sys.wait(19);
          elevator_state = 2;
          elevator_moving = 0;
        }
     }
  }
}

Notice that there are four functions - elevator_top, elevator_middle_a, elevator_middle_b, and elevator_bottom.

These are the functions called on by the state_change_callback mentioned earlier.

Now to look at the code in a bit more detail. Things in bold are comments to help you understand wtf it is.

The Code

float elevator_moving = 0; // this variable is at 0 if the elevator is NOT moving
float elevator_state = 0;  // 0 is bottom, 1 is middle, 2 is top 
                           //this variable is used to show which floor the elevator is currently on
void main() as mentioned in the platform tute, this has to be in a map script, but does'nt need to do anything
{
}

The Elevator

Bottom Floor Button.

When the elevator is on this floor and you press this button, the elevator goes up one floor

void elevator_bottom(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted) 
{
  if(bOpen)  // do the following if the button is open (pressed)
  {
    door.Close(1);  // close the button (push it back out). This makes it act like a button
    if (elevator_moving == 0)  // if the elevator is NOT moving"
    {
       if (elevator_state == 1) // if the variable is on 1 then the elevator is on the middle floor (0 is bottom floor)
       {
          elevator_moving = 1;  // set this variable to 1 so that the code knows that the elevator is moving and not to restart the sequence
          sys.wait(2);          // 2 second delay before movement to give the user time to get on the elevator
          $elevator.move ( DOWN, 248 ); // where it says elevator in $elevator.move is the name of your elevator entity.

So if yours is called func_mover_1 then put that in there instead of elevator. As for the movement, this was described in the platform tute, but to summarise, the DOWN is the direction to move, and the 248 is the distance to move in Doom Units. The platform tute explains how to find this distance etc.

          sys.wait(9); 

this delay is here because for this particular elevator it takes 9 seconds to move from the middle floor to the bottom floor. Set this to how long your one takes to reach the bottom floor.

          elevator_state = 0;  // after the elevator reaches the bottom floor set this variable to reflect that
          elevator_moving = 0; // our elevator has stopped moving, so set this variable to reflect that
       }
       else if (elevator_state == 2)  // if the variable is on 2 then the elevator is on the top floor

I think you can figure the rest out for yourself from here. It's all the same pretty much except the variables change for each floor and the distance to move does too

       {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 472 ); // distance to move from top floor to bottom floor
          sys.wait(19);                 // the time it takes for the elevator to reach the bottom floor from the top floor
          elevator_state = 0;
          elevator_moving = 0;
       }
       else if (elevator_state == 0)    // if the variable is on 0 then the elevator is on the bottom floor"
       {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 248 ); 

we're at the bottom floor so make the elevator go up one floor instead of further down. The distance here is from bottom floor to middle floor

          sys.wait(9);                  // time it takes to get from bottom to middle floor
          elevator_state = 1;
          elevator_moving = 0;
       }
     }
   }
 }

The rest of these functions are like the above one, except they're relevant to each floor

Middle Floor Button

The bottom one in this case. When the elevator is on this floor and you press this button, the elevator goes down one floor

void elevator_middle_a(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
  if(bOpen)
  {
     door.Close(1);
     if (elevator_moving == 0)
     {
        if (elevator_state == 1)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 248 );
          sys.wait(9);
          elevator_state = 0;
          elevator_moving = 0;
        }
        else if (elevator_state == 2)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( DOWN, 224 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
        else if (elevator_state == 0)
        {
          elevator_moving = 1;
          sys.wait(2);
          $elevator.move ( UP, 248 );
          sys.wait(9);
          elevator_state = 1;
          elevator_moving = 0;
        }
      }
    }
  }

Middle Floor Button. The top one in this case.

When the elevator is on this floor and you press this button, the elevator goes up one floor. Note that the code is very similar to the other button on this floor, except that this one makes the elevator go up rather then down, hence the need for two buttons on the middle floor

void elevator_middle_b(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
 if(bOpen)
 {
   door.Close(1);
   if (elevator_moving == 0)
   {
     if (elevator_state == 1)
     {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( UP, 224 );
       sys.wait(9);
       elevator_state = 2;
       elevator_moving = 0;
     }
     else if (elevator_state == 2)
     {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( DOWN, 224 );
       sys.wait(9);
       elevator_state = 1;
       elevator_moving = 0;
     }
     else if (elevator_state == 0)
     {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( UP, 248 );
       sys.wait(9);
       elevator_state = 1;
       elevator_moving = 0;
     }
   }
 }
}

Top Floor Button

When the elevator is on this floor and you press this button, the elevator goes down one floor

void elevator_top(entity door, boolean bOpen, boolean bLocked, boolean bInterrupted)
{
 if(bOpen)
  {
  door.Close(1);
  if (elevator_moving == 0)
  {
    if (elevator_state == 1)
    {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( UP, 224 );
       sys.wait(9);
       elevator_state = 2;
       elevator_moving = 0;
    }
    else if (elevator_state == 2)
    {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( DOWN, 224 );
       sys.wait(9);
       elevator_state = 1;
       elevator_moving = 0;
    }
    else if (elevator_state == 0)
    {
       elevator_moving = 1;
       sys.wait(2);
       $elevator.move ( UP, 472 );
       sys.wait(19);
       elevator_state = 2;
       elevator_moving = 0;
    }
  }
 }
}

If you've done the platform tute then you'll understand that code a bit better, so you should be able to tell what to change and where.

That covers elevators. If you understand this code now then you'll see where you need to add what sop that you can have an elevator that goes to multiple floors, not just three. Basically you'd need to add more functions. 2 functions per floor except the top and bottom floor, which have one.