I saw these cameras in Duke Nukem back in 1997 - see the real thing in this article!
I want to obtain
"real" surveillance cameras, so I'm switching between the default view (camera)
and my new view, surv_camera.
Function init_surveillance() is called in main; its
purpose is to create a view that has the same size and position like the
original "camera" view surv_camera {} function init_surveillance() { surv_camera.size_x = screen_size.x;
surv_camera.size_y = screen_size.y;
surv_camera.pos_x = 0; surv_camera.pos_y = 0; } Every surveillance camera (fish.mdl in my example) has
this action attached to it: action surveillance_camera { if (my.skill1 + my.skill2 +
my.skill3 + my.skill4 + my.skill5 + my.skill6 == 0) {beep; beep; return;} while (1) {
my.skill10 = abs(ang(player.pan) - ang(my.pan));
if ((vec_dist(player.x, my.x) < 100) && (my.skill10 > 150) && (my.skill10 <
210))
{
camera.visible = off;
surv_camera.x = my.skill1;
surv_camera.y = my.skill2;
surv_camera.z = my.skill3;
surv_camera.pan = my.skill4;
surv_camera.tilt = my.skill5;
surv_camera.roll = my.skill6;
surv_camera.visible = on;
my.skill11 = 0;
}
else {
if (my.skill11 == 0)
{
surv_camera.visible = off;
camera.visible = on;
my.skill11 += 1;
} } wait
(1); } } If we forget to fill in at least one of these
skill1...skill6 values, we hear two beeps and then the camera model is removed.
We store the distance angle between fish.mdl (camera trigger) and the player in
skill10. If the player is closer than 100 quants and the angle stored in skill10
is between 150 and 210 degrees, the player is facing the camera trigger and the
corresponding surveillance camera is enabled. If one of the surveillance cameras is enabled, the camera
is hidden and surv_camera is made visible. Surv_camera's coordinates are read
from skill1..6 (x, y, z, pan, tilt, roll) so you should get these values in Wed.
If you want to deactivate the surveillance camera, simply rotate the player or
move back. If you want to improve this camera code you could add a
panel that looks like a TV frame when you are in surveillance mode, play some
sounds, etc. 
Bow and arrow
This time I am going to take you through all the steps that are needed to create the code for a bow and arrows; please note that this example can be used to create (almost) any type of weapon and its bullets.
First of all we define
an entity that will be used for the bow:
entity bow_entity { type = <bow.mdl>; layer = 10; view = camera; x = 30; y = 8; z = -10; }
We are using the same
model (bow.mdl) for the bow that is being placed in the level in Wed. The bow
rotates if it hasn't been picked up yet; when the player impacts with the bow,
the bow will be removed and bow_entity is made visible. Bow_entity.frame = 2
will show the 2nd frame which contains the bow and the arrow.
action bow { my.enable_impact = me; my.event = get_bow; while (my != null) // or while
(my) {
my.pan += 3 * time;
wait (1); } } function get_bow() { wait (1); ent_remove (me); bow_entity.frame = 2; bow_entity.visible = on; } We are calling function init_bowarrow() in main: function init_bowarrow() { while
(1) {
if ((mouse_left == 1 || key_ctrl == 1) && bow_entity.frame < 7)
{
bow_entity.frame += 2 * time;
}
else
{
if (bow_entity.frame >= 7 && arrow_fired == 0)
{
while (mouse_left == 1 || key_ctrl == 1) {wait (1);}
vec_set (temp, player.pos);
temp.z += 20;
ent_create (arrow_mdl, temp, move_arrow);
arrow_fired = 1; // a single arrow
}
else // the player isn't shooting
{
arrow_fired = 0; // enable firing
bow_entity.frame = 2;
} } wait (1); } } If we press the LMB or the Ctrl key, we animate bow_entity
by changing its frame parameter. If bow_entity.frame >= 7, we wait until the LMB
or the Ctrl key are released (we do this because we want to disable autofire)
and then we create an arrow 20 quants above player's origin. I chose this value
because it looked real with my player + bow + arrow combination; you will have
to try other values if you are using other models. If the player isn't shooting
anymore, we enable firing and we set bow_entity's frame to 2 again.
The function associated to the arrow is: function move_arrow() { wait (1); my.enable_entity = on; my.enable_block = on; my.event = hurt_you; my.passable = on; my.pan = camera.pan; my.tilt = camera.tilt; my.skill12 = 50; // skill12, 13, 14
act like a var my.skill13 = 0; my.skill14 = 0; my.skill12 *= time; while (my.skill12 != 0) // moves
until it hits something { if (vec_dist
(my.x, player.x) < 100) {my.passable = on;} //
don't collide with the player else {my.passable
= off;}
ent_move (my.skill12, nullvector); wait
(1); } } The arrow is sensitive to entities and level blocks; if it
hits a block it will stuck in it and if it hits an entity it will disappear. I'm
using skill12, 13, 14 as if they were a single var named skill12; I need to make
sure that the first skill is divided by 3 (so I can start with skill3, 6, 9, 12,
15, etc). If the distance between the player and the arrow is smaller than 100
quants, the arrow is passable in order to prevent the arrow from hitting its
creator. The last function is: function hurt_you() { wait (1); if (event_type == event_entity) { my.skill12 =
0; // stop moving you._HEALTH
-= 80; // damage = 80; ent_remove
(me); } if (event_type == event_block) { my.skill12 =
0; // stop the arrow my.passable
= on; // it shouldn't stand in our way } } If the rocket hits an entity, it will cause 80 hit points
damage. If the entity is a tree sprite, it won't matter but if it is an enemy
(robot2 in my example) you will see him running away after the first hit.
Here's a small tip: I have used the same model for the
bow_entity and for the bow that is placed in Wed although it had an arrow and a
hand attached to it all the time. Of course you wouldn't want to see the bow,
the arrow and the hand attached to it waiting to be picked up. The models need
to have the same number of triangles every frame, so I have decided to hide the
hand and the arrow inside the bow (much smaller, of course, but they're there).
I'm using the first bow.mdl frame before picking up the bow and frames 2..7 for
the animated bow + arrow + hand. What about those
screams you were talking about? I was just joking, but
you can easily add them with a ent_playsound instruction placed in robot2's
template code.