Questions from the forum

Top  Previous  Next

Q: I want to make a bullet destroy itself when it hits a wall. It sounds easy but I didn't manage to make it work.

A: Use the code below.

 

SOUND* bullet_wav = "bullet.wav";

 

function remove_bullets() // this function runs when the bullet collides with the wall

{

       wait (1); // wait a frame to be sure (don't trigger engine warnings)

       my.event = NULL; // don't trigger bullet events (for this bullet) anymore

       ent_playsound(my, bullet_wav, 2000);

       set (my, INVISIBLE); // hide the bullet

       wait (-1); // give the sound enough time to be played

       ent_remove (my); // and then remove the bullet

}

 

function move_bullets()

{

       VECTOR bullet_speed[3]; // stores the speed of the bullet

       // the bullet is sensitive to impacts with entities and level blocks

       my.emask = ENABLE_IMPACT | ENABLE_ENTITY | ENABLE_BLOCK;

       my.event = remove_bullets; // when it collides with something, its event function (remove_bullets) will run

       my.pan = you.pan; // the bullet has the same pan and tilt angles with its creator

       my.tilt = you.tilt;

       bullet_speed.x = 50 * time_step; // adjust the speed of the bullet here

       bullet_speed.y = 0; // the bullet doesn't move sideways

       bullet_speed.z = 0; // or up / down on the z axis

       while (my) // this loop will run for as long as the bullet exists (it isn't "NULL")

       {

               // move the bullet ignoring its creator (the bullet generator)

               c_move (my, bullet_speed, nullvector, IGNORE_PASSABLE | IGNORE_YOU);

               wait (1);

       }

}

 

action bullet_generator()

{

       VECTOR bullet_pos[3];

       while (1)

       {

               // generate bullets from the 108th vertex of the weapon (get the vertex number from Med)

               vec_for_vertex(bullet_pos, my, 108);

               ent_create("bullet.mdl", bullet_pos, move_bullets);

               wait (-2); // fire a bullet every 2 seconds

       }

}

 

Q: I have made a platform (wmb) and the script to drive it, but the player falls through it. Is there any code which I can add to the lift script so that the player will stay on the lift and move with it?

A: Your player code needs changes as well; here's an example of player and lift code that works fine:

 

ENTITY* lift1;

 

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

{

       player = my; // I'm the player

       while (!lift1) {wait (1);} // wait until the lift entity is loaded

       var movement_speed = 20; // movement speed

       var distance_to_ground;

       VECTOR temp;

       set (my, INVISIBLE); // 1st person player

       while (1)

       {

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

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1

               camera.pan = my.pan;

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

               vec_set (temp.x, my.x); // trace 10,000 quants below the player

               temp.z -= 10000;

               distance_to_ground = c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | SCAN_TEXTURE);

               // replace "elevator1" with the name of the texture that is used by your lift

               if (str_cmpi(tex_name, "elevator1")) // the player is using the lift?

               {

                       my.z = lift1.z + 100; // play with 100

               }

               else // the player isn't using the lift? Then keep its feet on the ground

               {

                       temp.z = -distance_to_ground + 20; // play with 20

               }

               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);

               wait (1);

       }

}

 

action my_lift() // attach this action to your lift

{

       lift1 = my;

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

       var init_z;        

       var max_height = 200; // the lift can move upwards for up to 200 quants

       init_z = my.z; // store the initial height of the lift

       while (1)

       {

               while (my.z < init_z + max_height)

               {

                       my.z += 5 * time_step;

                       wait (1);

               }

               wait (-3); // wait 3 seconds at the top

               while (my.z > init_z)

               {

                       my.z -= 5 * time_step;

                       wait (1);

               }

               wait (-5); // wait 5 seconds at the bottom

       }

}

 

 

Q: How can I make player's pan angle change depending on the position of the mouse?

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);

       }

}

 

action players_code()

{

       VECTOR temp, temp2;

       player = my; // I'm the player

       while (1)

       {

               temp.x = mouse_pos.x;

               temp.y = mouse_pos.y;

               temp.z = 2000;

               // create a position 2000 quants below the camera (not a critical value)

               vec_for_screen(temp, camera);

               vec_set(temp2, temp.x);

               vec_sub(temp2, my.x);

               vec_to_angle(my.pan, temp2); // player's pan points towards the mouse pointer here

               my.tilt = 0; // don't change player's tilt angle, though

               // put your own player movement code here

               wait (1);

       }        

}

 

aum87_faq1

 

 

Q: I have been trying to make a background picture that doesn't move. The camera is fixed; how can I use a picture that is 512 x 256 pixels so that it's behind everything all the times, stretched from 0,0 to 1024,768.

A: Place the picture behind all the entities from your level, just like you'd place a regular sprite, and then play with its position and scale until it fills the entire screen.

 

action background_picture()

{        

       // the background picture is passable and doesn't get blurred

       set (my, PASSABLE | NOFILTER);

       my.pan = 0.1; // don't allow the sprite to rotate with the camera

       my.scale_x = 2; // play with this value, it sets the scale on the x axis

       my.scale_y = 3.5; // play with this value, it sets the scale on the y axis

}

 

 

Q: I'd like to have my entities stop their animations if they aren't visible on the screen.

A: Use this example.

 

action my_cow()

{        

var anim_percentage = 0;

set(my, POLYGON);                

while(1)

{

               // the cow is visible on the screen? Then play its animation!

               if (!(my.eflags & CLIPPED))

               {

                       ent_animate(my, "eatgrass", anim_percentage, NULL);                                

                       anim_percentage += 2 * time_step;

                       anim_percentage %= 100;

               }

               else // the cow isn't visible on the screen here, so do something else if needed

               {

                       // beep();

               }

     wait (1);

       }        

}

 

 

Q: I am trying to create a weapon that fires bullets when I click the left mouse button, but doesn't allow the player to fire a new bullet until the "shoot" animation is 100% completed.

A: Use the code below.

 

var gun_firing = 0;

 

ENTITY* weapon1;

 

SOUND* fire_wav = "fire.wav";

 

function attach_weapon1()

{

       weapon1 = my; // I'm the gun

       set(my, PASSABLE);

       while (1)

       {

               vec_set (my.x, vector (20, -10, 35)); // set the proper gun offset in relation to the player

               vec_rotate (my.x, you.pan);

               vec_add (my.x, you.x);

               my.pan = you.pan;

               my.tilt = camera.tilt;

               wait (1);

       }

}

 

action players_code() // simple player and 1st person camera code

{

       player = my; // I'm the player

       ent_create ("gun1.mdl", nullvector, attach_weapon1);

       while (1)

       {

               // move the player using the "W", "S", "A" and "D" keys; "10" = movement speed, "6" = strafing speed

               c_move (my, vector(10 * (key_w - key_s) * time_step, 6 * (key_a - key_d) * time_step, 0), nullvector, GLIDE);

               vec_set (camera.x, player.x); // use player's x and y for the camera as well

               camera.z += 30; // place the camera 30 quants above the player on the z axis (approximate eye level)

               camera.pan -= 5 * mouse_force.x * time_step; // rotate the camera around by moving the mouse

               camera.tilt += 3 * mouse_force.y * time_step; // on its x and y axis

               player.pan = camera.pan; // the camera and the player have the same pan angle

               wait (1);

       }

}

function remove_bullets() // this function runs when the bullet collides with something

{

       wait (1); // wait a frame to be sure (don't trigger engine warnings)

       ent_remove (my); // and then remove the bullet

}

 

function move_bullets()

{

       VECTOR bullet_speed[3]; // stores the speed of the bullet

       // the bullet is sensitive to impacts with entities and level blocks

       my.emask = ENABLE_IMPACT | ENABLE_ENTITY | ENABLE_BLOCK;

       my.event = remove_bullets; // when it collides with something, its event function (remove_bullets) will run

       my.pan = weapon1.pan;

       my.tilt = weapon1.tilt;

       bullet_speed.x = 150 * time_step; // adjust the speed of the bullet here

       bullet_speed.y = 0; // the bullet doesn't move sideways

       bullet_speed.z = 0; // or up / down on the z axis

       while (my) // this loop will run for as long as the bullet exists (it isn't "NULL")

       {

               // move the bullet ignoring its creator (weapon1)

               c_move (my, bullet_speed, nullvector, IGNORE_PASSABLE | IGNORE_YOU);

               wait (1);

       }

}

 

function fire_bullets()

{

       if (gun_firing)

               return; // don't allow the player to fire until the previous "shot" animation has finished

       snd_play(fire_wav, 100, 0);

       gun_firing = 1;

       VECTOR bullet_pos[3];

       var anim_factor = 0;

       // generate bullets from the 952th vertex of the weapon (get the vertex number from Med)

       vec_for_vertex(bullet_pos, weapon1, 952);

       while (anim_factor < 70) // the gun fires the bullet at 70% of its animation - play with 70

       {

               ent_animate(weapon1, "shot", anim_factor, NULL);                                

               anim_factor += 7 * time_step;

               wait (1);

       }

       ent_create("bullet.mdl", bullet_pos, move_bullets);

       while (anim_factor < 100) // continue with the rest of the "shot" animation

       {

               ent_animate(weapon1, "shot", anim_factor, NULL);                                

               anim_factor += 6 * time_step;

               wait (1);

       }

       gun_firing = 0; // allow the gun to fire again

}

 

function bullets_startup()

{

       on_mouse_left = fire_bullets;

}

 

 

Q: In the A5 templates there was a function called msg_show( ) that shows a message when it is called like this: msg_show("I AM AWESOME"); I was wondering if someone could create a new version that uses bitmapped fonts.

A: There you go:

 

STRING* message_str = "#100"; // the message can have up to 100 characters

 

FONT* cool_font = "antique.tga";

 

SOUND* message_wav = "message.wav";

 

function msg_show(STRING* message, duration);

 

TEXT* message_txt =

{

       pos_x = 200;

       pos_y = 20;

       string(message_str);

       font(cool_font);

       flags = SHOW;

}

 

function msg_show(STRING* message, duration)

{

       str_cpy((message_txt.pstring)[0], message);

       message_txt.flags |= SHOW; // display the message

       snd_play(message_wav, 70, 0);

       wait (-duration); // for the specified number of seconds

       message_txt.flags &= ~SHOW; // and then hide the message

}

 

function messages_startup()

{

       wait (-7);

       msg_show("I AM AWESOME", 3);

       wait (-5);

       msg_show("or at least cool", 2);

       wait (-4);

       msg_show("or maybe just a regular guy", 4);

       wait (-6);

       msg_show("OK, OK, I'm a bit dumb...", 5);

}

 

aum87_faq2

 

 

Q: I need help with creating a countdown timer that will work while the player is running, and if the timer <= 0 the player is not able to run any more. Also, the timer must recharge so that the player can run again.

A: Use this example.

 

var countdown_timer = 10;

 

SOUND* gottime_wav = "gottime.wav";

 

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

{

       var movement_speed = 20; // movement speed

       VECTOR temp;

       set (my, INVISIBLE); // 1st person player

       player = my; // I'm the player

       while (1)

       {

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

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1

               camera.pan = my.pan;

               camera.tilt = player.tilt; //5 * mouse_force.y * time_step;

               vec_set (temp.x, my.x); // trace 10,000 quants below the player

               temp.z -= 10000;

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

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

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

               if (countdown_timer > 0) // the countdown time didn't reach zero?

               {

                       temp.x *= 2; // increase the forward movement speed with 100%

                       temp.y *= 1.5; // increase the sideway movement speed with 50%

               }

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

               wait (1);

       }

}

 

action get_time() // attach this action to the time powerups that can be picked up by the player

{

       set (my, PASSABLE);

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

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

       snd_play(gottime_wav, 100, 0);

       set (my, INVISIBLE);

       countdown_timer += 10;

       wait (-2);

       ent_remove(my);

}

 

function countdown_startup()

{

       while (1)

       {

               countdown_timer -= time_step / 16;

               countdown_timer = maxv(countdown_timer, 0); // don't allow the timer to go below zero

               wait (1);

       }

}

 

PANEL* time_pan =

{

       layer = 15;

       digits(20, 20, 4 ,* , 1, countdown_timer);

       flags = SHOW;

}

 

 

Q: Does anyone know how I can make props that only animate when they get destroyed?

A: Use the following snippet; the crates / barrels only get destroyed and explode after being shot 3 times.

 

var gun_firing = 0;

 

ENTITY* weapon1;

 

SOUND* fire_wav = "fire.wav";

 

function attach_weapon1()

{

       weapon1 = my; // I'm the gun

       set(my, PASSABLE);

       while (1)

       {

               vec_set (my.x, vector (20, -10, 35)); // set the proper gun offset in relation to the player

               vec_rotate (my.x, you.pan);

               vec_add (my.x, you.x);

               my.pan = you.pan;

               my.tilt = camera.tilt;

               wait (1);

       }

}

 

action players_code() // simple player and 1st person camera code

{

       player = my; // I'm the player

       ent_create ("gun1.mdl", nullvector, attach_weapon1);

       while (1)

       {

               // move the player using the "W", "S", "A" and "D" keys; "10" = movement speed, "6" = strafing speed

               c_move (my, vector(10 * (key_w - key_s) * time_step, 6 * (key_a - key_d) * time_step, 0), nullvector, GLIDE);

               vec_set (camera.x, player.x); // use player's x and y for the camera as well

               camera.z += 30; // place the camera 30 quants above the player on the z axis (approximate eye level)

               camera.pan -= 5 * mouse_force.x * time_step; // rotate the camera around by moving the mouse

               camera.tilt += 3 * mouse_force.y * time_step; // on its x and y axis

               player.pan = camera.pan; // the camera and the player have the same pan angle

               wait (1);

       }

}

function remove_bullets() // this function runs when the bullet collides with something

{

       wait (1); // wait a frame to be sure (don't trigger engine warnings)

       ent_remove (my); // and then remove the bullet

}

 

function move_bullets()

{

       my.skill99 = 1357; // uniquely identify a bullet

       VECTOR bullet_speed[3]; // stores the speed of the bullet

       // the bullet is sensitive to impacts with entities and level blocks

       my.emask = ENABLE_IMPACT | ENABLE_ENTITY | ENABLE_BLOCK;

       my.event = remove_bullets; // when it collides with something, its event function (remove_bullets) will run

       my.pan = weapon1.pan;

       my.tilt = weapon1.tilt;

       bullet_speed.x = 150 * time_step; // adjust the speed of the bullet here

       bullet_speed.y = 0; // the bullet doesn't move sideways

       bullet_speed.z = 0; // or up / down on the z axis

       while (my) // this loop will run for as long as the bullet exists (it isn't "NULL")

       {

               // move the bullet ignoring its creator (weapon1)

               c_move (my, bullet_speed, nullvector, IGNORE_PASSABLE | IGNORE_YOU);

               wait (1);

       }

}

 

function fire_bullets()

{

       if (gun_firing)

               return; // don't allow the player to fire until the previous "shot" animation has finished

       snd_play(fire_wav, 100, 0);

       gun_firing = 1;

       VECTOR bullet_pos[3];

       var anim_factor = 0;

       // generate bullets from the 952th vertex of the weapon (get the vertex number from Med)

       vec_for_vertex(bullet_pos, weapon1, 952);

       while (anim_factor < 70) // the gun fires the bullet at 70% of its animation - play with 70

       {

               ent_animate(weapon1, "shot", anim_factor, NULL);                                

               anim_factor += 7 * time_step;

               wait (1);

       }

       ent_create("bullet.mdl", bullet_pos, move_bullets);

       while (anim_factor < 100) // continue with the rest of the "shot" animation

       {

               ent_animate(weapon1, "shot", anim_factor, NULL);                                

               anim_factor += 6 * time_step;

               wait (1);

       }

       gun_firing = 0; // allow the gun to fire again

}

 

function bullets_startup()

{

       on_mouse_left = fire_bullets;

}

 

// destroyable crate / barrel code from here on

 

function explo_sprite()

{

       set(my, BRIGHT);

       my.alpha = 100;

       my.scale_x = 3; // this value gives the scale of the explosion sprite

       my.scale_y = my.scale_x;

       my.frame = 1;

       while (my.frame < 5)

       {

               my.frame += 0.5 * time_step;

               wait (1);

       }

       while (my.alpha > 0)

       {

               my.alpha -= 3 * time_step;

               wait (1);

       }

       ent_remove (my);

}

 

function destroy_crate()

{

       // don't do anything if the crate wasn't destroyed by one of player's bullets

       // we have set skill99 to 1357 for each bullet inside function move_bullets() - above

       if (you.skill99 != 1357)        

               return;

       my.skill1 -= 1;

}

 

action my_crate()

{

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       my.event = destroy_crate;

       my.skill1 = 3; // allow the

       while (my.skill1 > 1) {wait (1);}

       // the crate was shot 3 times here

       ent_create("explo+5.pcx", my.x, explo_sprite);

       my.alpha = 100;

       set (my, TRANSLUCENT);

       while (my.alpha > 0)

       {

               my.alpha -= 7 * time_step;

               wait (1);

       }

       ent_remove (my); // and then remove the crate

}

 

 

Q: Does anyone has an idea in implementing an entity passing through a tunnel and exiting on another tunnel? It's like a portal in Quake 3; when the player enters the portal, it'll exit somewhere else in the map.

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

 

ENTITY* beamer1;

ENTITY* beamer2;

 

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

{

       var movement_speed = 20; // movement speed

       VECTOR temp;

       set (my, INVISIBLE); // 1st person player

       player = my; // I'm the player

       while (1)

       {

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

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1

               camera.pan = my.pan;

               camera.tilt = player.tilt; //5 * mouse_force.y * time_step;

               vec_set (temp.x, my.x); // trace 10,000 quants below the player

               temp.z -= 10000;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) - 2; // play with 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);

               wait (1);

       }

}

 

function beam_me1()

{

       my.event = NULL; // don't trigger several events

       wait (1);

       set (beamer2, PASSABLE); // don't allow beamer2 to teleport the player back to beamer1

       vec_set(player.x, beamer2.x);

       my.event = beam_me1;

}

 

action portal1() // attach this action to the first portal

{

       beamer1 = my;

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

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       while (1)

       {

               if (vec_dist(player.x, my.x) < 10) // the player was just beamed here?

               {

                       set (my, PASSABLE);

                       my.event = NULL; // then don't allow this beamer to teleport it back

                       // wait until the player has moved away from this beamer

                       while (vec_dist (my.x, player.x) < 100) {wait (1);}

               }        

               else

               {

                       reset (my, PASSABLE);

                       my.event = beam_me1;

               }

               wait (1);

       }

}

 

function beam_me2()

{

       my.event = NULL; // don't trigger several events

       wait (1);

       set (beamer1, PASSABLE); // don't allow beamer1 to teleport the player back to beamer2

       vec_set(player.x, beamer1.x);

       my.event = beam_me2;

}

 

action portal2() // attach this action to the second portal

{

       beamer2 = my;

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

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       while (1)

       {

               if (vec_dist(player.x, my.x) < 10) // the player was just beamed here?

               {

                       set (my, PASSABLE);

                       my.event = NULL; // then don't allow this beamer to teleport it back

                       // wait until the player has moved away from this beamer

                       while (vec_dist (my.x, player.x) < 100) {wait (1);}

               }        

               else

               {

                       reset (my, PASSABLE);

                       my.event = beam_me2;

               }

               wait (1);

       }

}