Questions from the forum

Top  Previous  Next

Q: How can I create an object that uses c_scan to damage the player when it is nearby?

A: Use the following snippet as a base for your code.

 

var players_health = 100;

 

SOUND* damage_wav = "damage.wav";

 

action my_player() // attach this action to your player model

{        

       var movement_speed = 20;

       VECTOR temp;

       set (my, INVISIBLE);

       player = my;

       while (players_health > 0)

       {                        

               my.pan -= 7 * mouse_force.x * time_step;

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE) - 2;

               temp.x = movement_speed * (key_w - key_s) * time_step;

               temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50;

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               wait (1);

       }

       camera.roll -= 30; // slant the camera, the player is dead here

}

 

// attach this action to an entity that is supposed to kill the player

action player_destroyer()

{

       while (!player) {wait (1);}

       VECTOR temp[3];

       while (1)

       {

               my.pan += 24 * time_step; // rotating damaging stuff looks scarier ;)

               // the player will be damaged if it comes closer than 200 quants to this entity

               c_scan(my.x, my.pan, vector(360, 90, 200), IGNORE_ME | SCAN_ENTS); // play with 200

               if (you == player) // detected the player?

            {

                       players_health -= 2 * time_step; // reduce player's health here, play with 5

                       if (total_frames % 50 == 1)

                               snd_play(damage_wav, 100, 0);

               }

               wait (1);

       }

}

 

 

Q: How do I create a totally transparent panel with visible buttons?

A: Create a panel that doesn't use a bmap. Here's an example:

 

BMAP* pictureon_pcx = "pictureon.pcx";

BMAP* pictureoff_pcx = "pictureoff.pcx";

 

BMAP* pointer_tga = "pointer.tga";

 

function mouse_startup()

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

function your_function_here()

{

       beep();        

}

 

PANEL* invisible_pan =

{

       layer = 15;

       button(40, 10, pictureon_pcx, pictureoff_pcx, pictureon_pcx, your_function_here, NULL, NULL);

       flags = SHOW;

}

 

 

Q: How do I create a menu that opens up when I click one of my RTS units?

A: Here's an example that creates a pop-up menu with two options - unit clockwise and counterclockwise rotation.

 

BMAP* pointer_tga = "pointer.tga";

 

BMAP* rotate1_jpg = "rotate1.jpg";

BMAP* rotate2_jpg = "rotate2.jpg";

BMAP* cckrotate1_jpg = "cckrotate1.jpg";

BMAP* cckrotate2_jpg = "cckrotate2.jpg";

 

var unit_angle;

 

VECTOR* unit_pos[3];

 

ENTITY* active_unit;

 

function rotate_clockwise();

function rotate_counterclockwise();

 

function mouse_startup()

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

PANEL* unit_pan =

{

       bmap = "rtsmenu.png";

       button = 0, 0, rotate1_jpg, rotate2_jpg, rotate1_jpg, rotate_clockwise, NULL, NULL;

       button = 128, 0, cckrotate1_jpg, cckrotate2_jpg, cckrotate1_jpg, rotate_counterclockwise, NULL, NULL;

}

 

function rotate_clockwise()

{

       unit_angle = active_unit.pan;

       while (active_unit.pan < (unit_angle + 360))

       {

               active_unit.pan += 5 * time_step;

               wait (1);

       }

}

 

function rotate_counterclockwise()

{

       unit_angle = active_unit.pan;

       while (active_unit.pan > (unit_angle - 360))

       {

               active_unit.pan -= 5 * time_step;

               wait (1);

       }

}

 

function display_menu()

{

       active_unit = my;

       vec_set(unit_pos, my.x);

       vec_to_screen(unit_pos, camera);

       unit_pan.pos_x = unit_pos.x;

       unit_pan.pos_y = unit_pos.y;

       unit_pan.flags |= VISIBLE;

}

 

action rts_unit()

{

  my.emask |= ENABLE_CLICK;

  my.event = display_menu;

  while (1)

  {

         wait (1);

         // do your RTS movement, AI, etc here        

  }

}

 

 

Q: How do I make an entity "wake up" (play a lively animation) when the mouse pointer if over it?

A: There you go:

 

BMAP* pointer_tga = "pointer.tga";

 

function mouse_startup()

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

function animate_me()

{

       if (event_type == EVENT_RELEASE)

       {

               my.skill99 = 1;

       }

       if (event_type == EVENT_TOUCH)

       {

               my.skill99 = 0;

       }

}

 

action my_npc()

{

       var anim_speed;

  my.emask |= ENABLE_TOUCH | ENABLE_RELEASE;

  my.event = animate_me;

  my.skill99 = 1; // the entity is animate using its "stand" animation by default

  while (1)

  {

         if (my.skill99 == 1) // playing the "stand" animation?

         {

                       anim_speed += 2 * time_step;

                       ent_animate(my, "stand", anim_speed, ANM_CYCLE);

               }

               else

         {

                       anim_speed += 3 * time_step;

                       ent_animate(my, "walk", anim_speed, ANM_CYCLE);

               }

               wait (1);

       

}

 

 

Q: I'd like to have a camera that rotates around the player, showing its surroundings, while a key is being pressed. The camera should return to a 3rd person perspective after I release the key.

A: Here's a code snippet that does what you want.

 

action my_player()

{

       var movement_speed = 10; // movement speed

       var anim_percentage;

       var camangle;

       VECTOR temp;

       VECTOR temp2;

       player = my; // I'm the player

       while (1)

       {

               if((!key_w) && (!key_s) && (!key_a) && (!key_d)) // the player isn't moving at all?

               {

                       ent_animate(my, "stand", anim_percentage, ANM_CYCLE); // and play the "stand" animation

               }

               else // the player is moving?

               {

                       camangle = 0; // reset the camera rotation angle

                       ent_animate(my, "walk", anim_percentage, ANM_CYCLE); // and play the "walk" animation

               }

               anim_percentage += 5 * time_step; // 5 = animation speed

               if (key_r) // the "R" key has been pressed? Then let's rotate the player!

               {

                       camera.x = player.x - 250 * cos(camangle);

                       camera.y = player.y - 250 * sin(camangle);

                       camangle += 0.5 * time_step;

                       vec_set(temp2.x, my.x);

                       vec_sub(temp2.x, camera.x);

                       vec_to_angle(camera.pan, temp2);

               }

               else // the "R" key isn't pressed?

               {

                       camera.x = player.x - 250 * cos(player.pan);

                       camera.y = player.y - 250 * sin(player.pan);

                       camera.pan = player.pan;

               }

               camera.z = player.z + 150; // place the camera above the player, play with this value

               camera.tilt = -25;

               temp.x = movement_speed * (key_w - key_s) * time_step;

               temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;

               temp.z = 0;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               wait (1);

       }

}

 

 

Q: How do I load a different level, depending on the hallway that the player chooses?

A: Place entities that trigger level loading instructions in the center of the hallways, and then use a code snippet like this:

 

STRING* level1_wmb = "level1.wmb";

STRING* level2_wmb = "level2.wmb";

STRING* level3_wmb = "level3.wmb";

 

action player_code() // attach this action to your player model

{        

       var movement_speed = 20;

       VECTOR temp;

       set (my, INVISIBLE);

       player = my;

       while (1)

       {                        

               my.pan -= 7 * mouse_force.x * time_step;

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE) - 2;

               temp.x = movement_speed * (key_w - key_s) * time_step;

               temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50;

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               wait (1);

       }

}

 

action hallway_entity1()

{

       while (!player) {wait (1);}

       // wait until the player comes closer than 150 quants to the entity

       while (vec_dist (player.x, my.x) > 150) {wait (1);}

       level_load (level1_wmb);

}

 

action hallway_entity2()

{

       while (!player) {wait (1);}

       // wait until the player comes closer than 150 quants to the entity

       while (vec_dist (player.x, my.x) > 150) {wait (1);}

       level_load (level2_wmb);

}

 

action hallway_entity3()

{

       while (!player) {wait (1);}

       // wait until the player comes closer than 150 quants to the entity

       while (vec_dist (player.x, my.x) > 150) {wait (1);}

       level_load (level3_wmb);

}

 

 

Q: How do I put a rotating siren on top of my police car? It should rotate and move with the car at all times, of course.

A: Create a separate model for the siren and attach it the action below.

 

STRING* siren_mdl = "siren.mdl";

 

function attach_siren()

{

       while (1)

       {

               // place the siren 0 quants in front of the car, 0 quants sideways and 50 quants above the car model's origin

               // tweak these values according to your needs

               vec_set (my.x, vector(0, 0, 50));

               vec_rotate (my.x, you.pan);

               vec_add (my.x, you.x);

               my.pan += 25 * time_step; // rotate the siren model

               wait (1);

       }               

}

 

action my_car() // simple car action, rotates the car in a circle

{

       ent_create (siren_mdl, my.x, attach_siren);

       while (1) // use your own car code here

       {

               c_move (my, vector (10 * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);

               my.pan += 2 * time_step; // make this car rotate in a circle at all times

               wait (1);

       }

}

 

 

Q: How do I complete a small puzzle for kids by simply running into its pieces?

A: Here's an example that uses 4 puzzle pieces.

 

BMAP* puzzle1_pcx = "puzzle1.pcx";

BMAP* puzzle2_pcx = "puzzle2.pcx";

BMAP* puzzle3_pcx = "puzzle3.pcx";

BMAP* puzzle4_pcx = "puzzle4.pcx";

 

PANEL* puzzle1_pan =

{

       bmap = puzzle1_pcx;

       pos_x = 0;

       pos_y = 0;

}

 

PANEL* puzzle2_pan =

{

       bmap = puzzle2_pcx;

       pos_x = 200;

       pos_y = 0;

}

 

PANEL* puzzle3_pan =

{

       bmap = puzzle3_pcx;

       pos_x = 0;

       pos_y = 200;

}

 

PANEL* puzzle4_pan =

{

       bmap = puzzle4_pcx;

       pos_x = 200;

       pos_y = 200;

}

 

action players_code() // attach this action to your player model

{        

       var movement_speed = 20;

       VECTOR temp;

       set (my, INVISIBLE);

       player = my;

       while (1)

       {                        

               my.pan -= 7 * mouse_force.x * time_step;

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE) - 2;

               temp.x = movement_speed * (key_w - key_s) * time_step;

               temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50;

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               wait (1);

       }

}

 

action puzzle1() // attach this to your first puzzle piece image (use the same sprite, a model, etc)

{

       set(my, PASSABLE);

       while (!player) {wait (1);} // wait until the player is loaded

       while (vec_dist (player.x, my.x) > 70) {wait (1);}

       set(puzzle1_pan, SHOW);

       ent_remove(my);

}

 

action puzzle2() // attach this to your second puzzle piece

{

       set(my, PASSABLE);

       while (!player) {wait (1);} // wait until the player is loaded

       while (vec_dist (player.x, my.x) > 70) {wait (1);}

       set(puzzle2_pan, SHOW);

       ent_remove(my);

}

 

action puzzle3() // attach this to your third puzzle piece

{

       set(my, PASSABLE);

       while (!player) {wait (1);} // wait until the player is loaded

       while (vec_dist (player.x, my.x) > 70) {wait (1);}

       set(puzzle3_pan, SHOW);

       ent_remove(my);

}

 

action puzzle4() // attach this to your fourth puzzle piece

{

       set(my, PASSABLE);

       while (!player) {wait (1);} // wait until the player is loaded

       while (vec_dist (player.x, my.x) > 70) {wait (1);}

       set(puzzle4_pan, SHOW);

       ent_remove(my);

}

 

 

Q: How do you create a 3D arrow that points down at a particular NPC who is moving on a path?

A: Use this snippet as a base for your code:

 

ENTITY* dummy1;

 

STRING* arrow_mdl = "arrow.mdl";

 

function npc_arrow()

{

       my.tilt -= 90; // if you want to convert an horizontal arrow into a vertical one, pointing downwards

       my.z = you.z + 130; // play with 130, it sets the vertical distance between the arrow and the npc origin

       set(my, PASSABLE);

       while (1)

       {

               // find the best combination by playing with 3 (amplitude) and 15 (speed)

               my.x = you.x;

               my.y = you.y;

               my.z += 3 * sin(total_ticks * 15) * time_step;

               wait (1);

       }

}

 

action my_npc()

{

       ent_create(arrow_mdl, nullvector, npc_arrow);

       var walk_percentage;

       var distance = 0;

       var previous_pan;

       var following_pan;

       var min_speed = 1;

       var max_speed = 3;

       var walking_speed;

       VECTOR last_pos[3];

       VECTOR direction[3];

       // create a dummy entity that will move on the path

       dummy1 = ent_create(NULL, nullvector, NULL);

       // make sure to name your path this way

       path_set(dummy1, "path_001");

       while(1)

       {

               previous_pan = my.pan;

               // place the dummy entity on the path

               path_spline(dummy1, my.x, distance);

               distance += walking_speed * time_step;

               // let the npc look ahead

               vec_diff(direction, my.x, last_pos);

               vec_to_angle(my.pan, direction);

               vec_set(last_pos, my.x);

               wait(1);

               following_pan = my.pan;

               // sudden direction change during the last frame? Then lower the speed of the npc!

               if (abs(following_pan - previous_pan) > 1)

               {

                       walking_speed -= 4 * time_step;

               }

               else

               {

                       walking_speed += 2 * time_step;

               }               

               // don't allow the walking speed to exceed the specified min / max limits

               walking_speed = clamp(walking_speed, min_speed, max_speed);

               ent_animate(my, "walk", walk_percentage, ANM_CYCLE); // play the "walk" animation

               walk_percentage += 3 * time_step; // "3" controls the animation speed

       }

}