home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Gamer 5.14
/
2000-11_-_Disc_5.14.iso
/
Goodies
/
3DGameStudio
/
Mission
/
movement.wdl
< prev
next >
Wrap
Text File
|
2000-02-08
|
29KB
|
987 lines
///////////////////////////////////////////////////////////////////////////////////
// WDL prefabs for entity movement
///////////////////////////////////////////////////////////////////////////////////
// Some definitions
// Change them by re-defining them in your main wdl script
// BEFORE the include, and adding DEFINE MOVE_DEFS;
IFNDEF MOVE_DEFS;
SOUND thud,<tap.wav>;
SOUND robo_thud,<gate.wav>;
SOUND splash,<splash.wav>;
DEFINE shadowsprite,<shadow.pcx>;
DEFINE shadowflat,<shadflat.pcx>;
DEFINE DEFAULT_WALK,13.040;
DEFINE DEFAULT_RUN,5.060;
ENDIF;
///////////////////////////////////////////////////////////////////////////////////
// Some global skill definitions
// Duplicate them in your wdl script AFTER the include
// to give them new values
SKILL gnd_fric { VAL 0.5; } // ground friction
SKILL air_fric { VAL 0.03; } // air friction
SKILL ang_fric { VAL 0.6; } // angular friction
SKILL gravity { VAL 6; } // gravity force
SKILL elasticity { VAL 0.1; } // of the floor
SKILL strength { X 5; Y 4; Z 25; } // default ahead, side, jump strength
SKILL astrength { PAN 7; TILT 5; ROLL 2; } // default pan, tilt, roll strength
SKILL eye_height_up { VAL 0.8; } // eye position factor for walking, driving
SKILL eye_height_down { VAL 0.2; } // for swimming
SKILL walk_rate { VAL 3; } // for head wave, 360 / step width
SKILL wave_rate { VAL 25; }// same for swimming, 360 / wave time
SKILL walk_ampl { VAL 4; } // walking head wave amplitude
SKILL wave_ampl { VAL 2; } // swimming head wave amplitude
SKILL person_3rd { VAl 0; } // 0: 1st person mode; 0.5: 3rd person mode
SKILL camera_dist { VAl 120; } // camera distance to entity in 3rd person view
SKILL mouseview { VAL 1; } // mouse factor, set 0 to disable mouse
SKILL client_moving { VAL 0; } // multiplayer mode
SKILL jump_height { VAL 100; } // maximum jump height above ground
SKILL walk_or_run { VAL 12; } // max quants per tick to switch from walk to run animation
///////////////////////////////////////////////////////////////////////
// Entity skill & flag definitions
// some definitions here are also needed for ACTORS.WDL and WAR.WDL
DEFINE _WALKFRAMES,SKILL1;
DEFINE _RUNFRAMES,SKILL2;
DEFINE _ATTACKFRAMES,SKILL3;
DEFINE _DIEFRAMES,SKILL4;
DEFINE _FORCE,SKILL5; // determines speed
DEFINE _ENTFORCE,SKILL5;
DEFINE _BANKING,SKILL6; // banking - for player only
DEFINE _PENDOLINO,SKILL6; // banking - for player only
DEFINE _HITMODE,SKILL6; // for actors
DEFINE _MOVEMODE,SKILL7;
DEFINE _FIREMODE,SKILL8; // for actors
DEFINE __WHEELS,FLAG2; // block turns without moving
DEFINE __SLOPES,FLAG3; // adapt the tilt and roll angle to slopes
DEFINE __JUMP,FLAG4; // be able to jump
DEFINE __BOB,FLAG5; // head wave
DEFINE __STRAFE,FLAG6; // be able to move sidewards
DEFINE __TRIGGER,FLAG7; // be able to trigger doors automatically
DEFINE __SOUND,FLAG8;
///////////////////////////////////////////////////////////////////////
DEFINE _HEALTH,SKILL9;
DEFINE _ARMOR,SKILL10;
DEFINE _SPEED,SKILL11; // speed
DEFINE _SPEED_X,SKILL11;
DEFINE _SPEED_Y,SKILL12;
DEFINE _SPEED_Z,SKILL13;
DEFINE _ASPEED,SKILL14; // angular speed
DEFINE _ASPEED_PAN,SKILL14;
DEFINE _ASPEED_TILT,SKILL15;
DEFINE _ASPEED_ROLL,SKILL16;
// for actor entities, and for doors and platforms
DEFINE _TARGET_X,SKILL17;
DEFINE _TARGET_Y,SKILL18;
DEFINE _TARGET_Z,SKILL19;
DEFINE _TARGET_PAN,SKILL20;
DEFINE _TARGET_TILT,SKILL21;
DEFINE _TARGET_ROLL,SKILL22;
// for player entities
DEFINE _FORCE_X,SKILL17;
DEFINE _FORCE_Y,SKILL18;
DEFINE _FORCE_Z,SKILL19;
DEFINE _AFORCE_PAN,SKILL20;
DEFINE _AFORCE_TILT,SKILL21;
DEFINE _AFORCE_ROLL,SKILL22;
DEFINE _WALKSOUND,SKILL23; // walking sound
DEFINE _SIGNAL,SKILL24; // communication for actions or client->server
DEFINE _COUNTER,SKILL25; // internal counter
DEFINE _STATE,SKILL26; // the state it is in (walk, attack, escape etc.)
DEFINE _WALKDIST,SKILL27; // distance per walk cycle
DEFINE _RUNDIST,SKILL28; // distance per run cycle
DEFINE _TYPE,SKILL30; // the type of the entity
// Skills up to 32 are reserved for future template actions
// Skills 33-40 can be used freely
///////////////////////////////////////////////////////////////////////
SKILL force {} // cartesian force, entity coordinates
SKILL absforce {} // cartesian force, world coordinates
SKILL aforce {} // angular force
SKILL speed { X 0; Y 0; Z 0; } // cartesian speed, entity coordinates
SKILL abspeed { X 0; Y 0; Z 0; } // cartesian speed, world coordinates
SKILL aspeed {} // angular speed
SKILL p {}
SKILL friction {}
SKILL limit {}
SKILL head_angle { PAN 0; TILT 0; ROLL 0; } // separated from other values
SKILL headwave { VAL 0; }
SKILL walkwave { VAL 0; }
SKILL my_dist {} // intended covered distance
SKILL quants {} // real covered distance
SKILL scan_sector {}
SKILL my_height {}
SKILL my_floornormal {}
SKILL my_floorspeed {}
SKILL temp_cdist { VAl 120; } // current camera distance in 3rd p view
SKILL debugskill {}
SYNONYM player { TYPE ENTITY; }
SYNONYM temp_ent { TYPE ENTITY; }
SYNONYM carry { TYPE action; }
DEFINE _MODE_WALKING,1;
DEFINE _MODE_DRIVING,2;
DEFINE _MODE_SWIMMING,3;
DEFINE _MODE_DIVING,4;
DEFINE _MODE_WADING,5;
DEFINE _MODE_FLYING,6;
DEFINE _MODE_STILL,10;
// modes above 10 are handled by a different wdl
DEFINE _MODE_ATTACK,20;
DEFINE _SOUND_WALKER,1;
DEFINE _SOUND_ROBOT,2;
DEFINE _TYPE_PLAYER,1;
DEFINE _TYPE_ACTOR,2;
DEFINE _TYPE_FOE,3;
DEFINE _TYPE_DOOR,10;
DEFINE _TYPE_GATE,11;
DEFINE _TYPE_ELEVATOR,12;
DEFINE _TYPE_GUN,20;
DEFINE _TYPE_AMMO,21;
DEFINE _TYPE_ARMOR,22;
DEFINE _TYPE_HEALTH,23;
///////////////////////////////////////////////////////////////////////
DEFINE RETURN,END; // compatibility to old versions
SOUND beep_sound,<beep.wav>;
//SYNONYM debugsyn { TYPE ENTITY; }
///////////////////////////////////////////////////////////////////////
// Some actions, which use player_move
ACTION player_drive {
MY._MOVEMODE = _MODE_DRIVING;
MY._FORCE = 1.5;
MY._BANKING = 0.5;
SET MY.__SLOPES,ON;
CALL player_move;
}
ACTION player_walk {
MY._MOVEMODE = _MODE_WALKING;
MY._FORCE = 0.75;
MY._BANKING = -0.1;
SET MY.__JUMP,ON;
SET MY.__STRAFE,ON;
SET MY.__BOB,ON;
SET MY.__TRIGGER,ON;
CALL player_move;
}
ACTION player_swim {
MY._MOVEMODE = _MODE_SWIMMING;
MY._FORCE = 0.75;
MY._BANKING = 0;
SET MY.__JUMP,ON;
SET MY.__STRAFE,OFF;
SET MY.__BOB,ON;
CALL player_move;
}
///////////////////////////////////////////////////////////////////////
// Shakes the player, used for hits and death
ACTION player_shake
{
IF (RANDOM(1) > 0.5)
{
MY.ROLL += 8;
MY.TILT += 8;
WAITT 2;
MY.TILT -= 5;
WAITT 2;
MY.ROLL -= 8;
MY.TILT -= 3;
} ELSE {
MY.ROLL -= 8;
MY.TILT += 8;
WAITT 2;
MY.TILT -= 5;
WAITT 2;
MY.ROLL += 8;
MY.TILT -= 3;
}
}
// player tips over, used for death
ACTION player_tip
{
MY._MOVEMODE = 0; // suspend normal movement action
eye_height_up.Z = eye_height_up; // store original eye height
WHILE (MY.ROLL < 80)
{
MY.ROLL += 8 * TIME;
MY.TILT += 2 * TIME;
IF (eye_height_up > 0.15) {
eye_height_up -= 0.1 * TIME; }
IF (client_moving==0) { CALL move_view; }
WAIT 1;
}
MY.ROLL = 80;
MY.TILT = 20;
eye_height_up = eye_height_up.Z; // restore original eye height
}
///////////////////////////////////////////////////////////////////////
// main player movement action
ACTION player_move {
IFDEF ACKNEX_VERSION414;
IF (MY.CLIENT == 0) { SET player,ME; } // created on the server?
IFELSE;
SET player,ME; // to be accessible by a synonym
ENDIF;
MY._TYPE = _TYPE_PLAYER;
SET MY.ENABLE_SCAN,ON; // so that enemies can detect me
IF (MY._FORCE == 0) { MY._FORCE = 1.5; }
IF (MY._MOVEMODE == 0) { MY._MOVEMODE = _MODE_WALKING; }
IF (MY._WALKFRAMES == 0) { MY._WALKFRAMES = DEFAULT_WALK; }
IF (MY._RUNFRAMES == 0) { MY._RUNFRAMES = DEFAULT_RUN; }
IF (MY._WALKSOUND == 0) { MY._WALKSOUND = _SOUND_WALKER; }
CALL anim_init;
CALL perform_handle; // react on pressing the handle key
WHILE ((MY._MOVEMODE > 0)&&(MY._MOVEMODE <= _MODE_STILL))
{
IF (MY._MOVEMODE == _MODE_STILL) { // do nothing at all
WAIT 1;
CONTINUE;
}
// Get the angular and translation forces
CALL _player_force;
// find ground below
CALL scan_floor;
// if he is above water, switch to swimming
IF (ON_PASSABLE) {
// my_height += (MY.MAX_Z-MY.MIN_Z)*0.5; // dive into it
// if he walked before, play a splash
IF (MY._MOVEMODE == _MODE_WALKING) {
PLAY_SOUND splash,50;
MY._MOVEMODE = _MODE_SWIMMING;
}
} ELSE {
IF (MY._MOVEMODE == _MODE_SWIMMING) {
MY._MOVEMODE = _MODE_WALKING;
}
}
// if he is on a slope, change his angles, and maybe let him slide down
IF (MY.__SLOPES == ON) {
// Adapt the player angle to the floor slope
MY_ANGLE.TILT = 0;
MY_ANGLE.ROLL = 0;
IF (my_height < 10 && (my_floornormal.X != 0 || my_floornormal.Y != 0 ))
{ // on a slope?
// rotate the floor normal relative to the player
MY_ANGLE.PAN = -MY.PAN;
VECROTATE my_floornormal,MY_ANGLE;
// calculate the destination tilt and roll angles
MY_ANGLE.TILT = -ASIN(my_floornormal.X);
MY_ANGLE.ROLL = -ASIN(my_floornormal.Y);
}
// change the player angles towards the destination angles
MY.TILT += 0.2 * ANG(MY_ANGLE.TILT-MY.TILT);
MY.ROLL += 0.2 * ANG(MY_ANGLE.ROLL-MY.ROLL);
} ELSE {
// If the ROLL angle was not equal to zero,
// apply a ROLL force to set the angle back
aforce.ROLL = -0.2*ANG(MY.ROLL);
}
// Now accelerate the angular speed, and change his angles
ACCEL MY._ASPEED,aforce,ang_fric;
temp = MY._ASPEED_PAN * MY._SPEED_X * 0.05;
IF (MY.__WHEELS) { // Turn only if moving ahead
MY.PAN += temp;
} ELSE {
MY.PAN += MY._ASPEED_PAN;
}
MY.ROLL += temp * MY._BANKING + MY._ASPEED_ROLL;
head_angle.TILT += MY._ASPEED_TILT;
// Limit the TILT value
head_angle.TILT = ANG(head_angle.TILT);
IF (head_angle.TILT > 80) { head_angle.TILT = 80; }
IF (head_angle.TILT < -80) { head_angle.TILT = -80; }
// Decide whether the actor can jump or not. He can't if he is in the air
IF ((jump_height <= 0)
|| (MY.__JUMP == OFF)
|| (my_height > 4)
|| (force.Z <= 0))
{
force.Z = 0;
}
// disable strafing
IF (MY.__STRAFE == OFF) {
force.Y = 0; // no strafe
}
// now move him
CALL move_gravity;
// select the right walking frame (swimming anim not yet implemented)
CALL actor_anim;
// If I'm the only player, draw the camera and weapon with ME
IF (client_moving == 0) { CALL move_view; }
CALL carry;
// Wait one tick, then repeat
WAIT 1;
}
}
// this is the main movement action for the camera
ACTION camera_move {
_camera = 1;
WHILE (_camera == 1)
{
CALL _player_intentions;
ACCEL aspeed,aforce,0.9;
CAMERA.PAN += aspeed.PAN;
CAMERA.TILT += aspeed.TILT;
CAMERA.ROLL += aspeed.ROLL;
ACCEL speed,force,0.9;
MOVE_VIEW CAMERA,speed,NULLSKILL;
WAIT 1;
}
}
/////////////////////////////////////////////////////////////////////
// Core part of move action, common for actors and players
ACTION move_gravity
{
// Filter the forces and frictions dependent on the state of the actor,
// and then apply them, and move him
// First, decide whether the actor is standing on the floor or not
IF (my_height < 5) {
friction = gnd_fric;
IF (MY._MOVEMODE == _MODE_DRIVING) {
// Driving - less friction, less force
friction *= 0.3;
force.X *= 0.3;
}
IF (MY._MOVEMODE == _MODE_SWIMMING) {
// Swimming - rhythmic acceleration
force.X *= 0.5 + 0.25*walkwave;
force.Y *= 0.5;
}
absforce.X = 0;
absforce.Y = 0;
absforce.Z = 0;
// If on a slope, apply gravity to draw him downwards:
IF (my_floornormal.Z < 0.85) {
absforce.X = my_floornormal.X * gravity * 2;
absforce.Y = my_floornormal.Y * gravity * 2;
// If slope too steep, really push him back
temp = 0.66 - my_floornormal.Z;
IF (temp > 0) {
absforce.X *= 3;
absforce.Y *= 3;
}
}
} ELSE {
// airborne - set all relative forces to 0
// to prevent him from jumping or further moving in the air
friction = air_fric;
force.X = 0;
force.Y = 0;
force.Z = 0;
absforce.X = 0;
absforce.Y = 0;
absforce.Z = -gravity;
}
// accelerate the entity relative speed by the force
speed.X = MY._SPEED_X;
speed.Y = MY._SPEED_Y;
ACCEL speed,force,friction;
speed.Z = 0; // jumping force controls absolute speed only
MY._SPEED_X = speed.X;
MY._SPEED_Y = speed.Y;
// Add the world gravity force
abspeed.X = 0;
abspeed.Y = 0;
abspeed.Z = MY._SPEED_Z;
ACCEL abspeed,absforce,friction;
// Add the speed given by the ground elasticity and the jumping force
IF (my_height < 5) {
temp = my_height;
IF (temp < -10) { temp = -10; }
abspeed.Z = force.Z-temp;
}
// Restrict the speed to the maximum jumping height
IF ((abspeed.Z > 0) && (abspeed.Z + my_height > jump_height)) {
abspeed.Z = jump_height - my_height;
if (abspeed.Z < 0) { abspeed.Z = 0; }
}
MY._SPEED_Z = abspeed.Z;
// If the actor is standing on a moving platform, add it's horizontal speed
IF (my_height < 5) {
abspeed.X = my_floorspeed.X;
abspeed.Y = my_floorspeed.Y;
}
// Now move ME by the relative and the absolute speed
SET YOU,NULL; // YOU entity is considered passable by MOVE
MOVE ME,speed,abspeed;
// Store the distance to cover, for head bobbing
// my_dist = SQRT(MY_SPEED.X*MY_SPEED.X + MY_SPEED.Y*MY_SPEED.Y);
my_dist = SQRT(speed.X*speed.X + speed.Y*speed.Y);
}
// split the integer and fractional parts of the animation frame numbers
ACTION anim_init {
temp = FRC(MY._WALKFRAMES) * 1000;
IF (temp == 0) { temp = 40; }
MY._WALKFRAMES = INT(MY._WALKFRAMES);
IF (MY._WALKFRAMES == 0) { MY._WALKFRAMES = 13; }
MY._WALKDIST = MY._WALKFRAMES / temp;
temp = FRC(MY._RUNFRAMES) * 1000;
IF (temp == 0) { temp = 60; }
MY._RUNFRAMES = INT(MY._RUNFRAMES);
IF (MY._RUNFRAMES == 0) { MY._RUNFRAMES = 5; }
MY._RUNDIST = MY._RUNFRAMES / temp;
}
// play some kinds of foot sound
ACTION _play_walksound {
IF ((ME == player) && (person_3rd == 0)) { RETURN; } // don't play entity sounds for 1st peron player
IF (MY._WALKSOUND == _SOUND_WALKER) { PLAY_ENTSOUND ME,thud,60; }
IF (MY._WALKSOUND == _SOUND_ROBOT) { PLAY_ENTSOUND ME,robo_thud,60; }
}
////////////////////////////////////////////////////////////////////
// Main action to animate a walking actor, depending on dist covered
ACTION actor_anim
{
IF ((MY._MOVEMODE == _MODE_STILL) || (my_dist < 0.01))
{
// if the entity has a standing animation, instead of just one frame,
// place it here. Otherwise...
MY.FRAME = 1; // standing
RETURN;
}
IF (MY._MOVEMODE == _MODE_WALKING)
{
// decide whether to play the walk or run animation
IF (my_dist < walk_or_run*TIME) // Walking
{
IF (MY.FRAME < 2) { MY.FRAME = 2; }
MY.FRAME += MY._WALKDIST*my_dist;
// this is one of the expert exceptions where you can use WHILE without WAIT!
WHILE (MY.FRAME >= 2 + MY._WALKFRAMES) {
// sound for right foot
IF (MY.__SOUND == ON) { CALL _play_walksound; SET MY.__SOUND,OFF; }
// cycle the animation
MY.FRAME -= MY._WALKFRAMES;
}
IF (MY.FRAME > 1 + MY._WALKFRAMES*0.5) {
// sound for left foot
IF (MY.__SOUND == OFF) { CALL _play_walksound; SET MY.__SOUND,ON; }
}
IFDEF ACKNEX_VERSION412;
IF (MY.FRAME > 1 + MY._WALKFRAMES) {
MY.NEXT_FRAME = 2; // inbetween to the first walking frame
} ELSE {
MY.NEXT_FRAME = 0; // inbetween to the real next frame
}
ENDIF;
RETURN;
}
ELSE { // Running
IF (MY.FRAME < 2 + MY._WALKFRAMES) { MY.FRAME = 2 + MY._WALKFRAMES; }
MY.FRAME += MY._RUNDIST*my_dist;
WHILE (MY.FRAME >= 2 + MY._WALKFRAMES + MY._RUNFRAMES) {
IF (MY.__SOUND == ON) { CALL _play_walksound; SET MY.__SOUND,OFF; }
MY.FRAME -= MY._RUNFRAMES;
}
IF (MY.FRAME > 1 + MY._WALKFRAMES + MY._RUNFRAMES*0.5) {
IF (MY.__SOUND == OFF) { CALL _play_walksound; SET MY.__SOUND,ON; }
}
IFDEF ACKNEX_VERSION412;
IF (MY.FRAME > 1 + MY._WALKFRAMES + MY._RUNFRAMES) {
MY.NEXT_FRAME = 2 + MY._WALKFRAMES;
} ELSE {
MY.NEXT_FRAME = 0;
}
ENDIF;
RETURN;
}
}
// place here the swimming animation if any
// IF (MY._MOVEMODE == _MODE_SWIMMING) {
// RETURN;
// }
// or place here further animations ...
}
///////////////////////////////////////////////////////////////////////
// First person camera view
// This should be a client-only action!!
SKILL position_old {}
ACTION move_view_1st
{
IF (_camera == 0) { // If the camera does not move itself
IF (my_height < 5) {
// quants += SQRT((player.X-position_old.X)*(player.X-position_old.X)
// + (player.Y-position_old.Y)*(player.Y-position_old.Y));
quants += my_dist;
position_old.X = player.X;
position_old.Y = player.Y;
headwave = SIN(quants*walk_rate);
IF ((player._MOVEMODE == 0) // moving on client?
|| (player._MOVEMODE == _MODE_WALKING)) {
// Play the right and left foot sound
IF (((headwave > 0) && (walkwave <= 0))
|| ((headwave <= 0) && (walkwave > 0))) {
PLAY_SOUND thud,30; }
// head bobbing
walkwave = headwave;
headwave = walk_ampl*(ABS(headwave)-0.5);
}
IF (player._MOVEMODE == _MODE_SWIMMING) {
IF ((headwave > 0) && (walkwave <= 0)) {
PLAY_SOUND splash,30;
}
// in-water wave movement
walkwave = headwave;
headwave = wave_ampl*SIN(TOTAL_TICKS*wave_rate);
head_angle.TILT += 0.1*wave_ampl*SIN(TOTAL_TICKS*wave_rate - 60);
}
}
CAMERA.DIAMETER = 0; // make the camera passable
SET CAMERA.GENIUS,player; // don't display parts of ME
CAMERA.X = player.X;
CAMERA.Y = player.Y;
CAMERA.Z = player.Z + player.MIN_Z;
IF (player.__BOB == ON) { CAMERA.Z += headwave; }
IF (player._MOVEMODE == _MODE_SWIMMING) {
CAMERA.Z += (player.MAX_Z-player.MIN_Z)*eye_height_down; // Add eye height
} ELSE {
CAMERA.Z += (player.MAX_Z-player.MIN_Z)*eye_height_up;
}
CAMERA.PAN = player.PAN;
CAMERA.TILT = player.TILT + head_angle.TILT;
CAMERA.ROLL = player.ROLL;
person_3rd = 0;
}
}
// Third person camera view
ACTION move_view_3rd
{
IF (_camera == 0) { // If the camera does not move itself
CAMERA.DIAMETER = 0; // make the camera passable
SET CAMERA.GENIUS,player;
CAMERA.PAN += 0.2 * ANG(player.PAN-CAMERA.PAN);
CAMERA.TILT = head_angle.TILT-5;
MY_SPEED.X = 0.3*(player.X - temp_cdist * COS(player.PAN) - CAMERA.X);
MY_SPEED.Y = 0.3*(player.Y - temp_cdist * SIN(player.PAN) - CAMERA.Y);
MY_SPEED.Z = 0.5*(player.Z + player.MAX_Z - CAMERA.Z);
IF (person_3rd < 1) { // not yet fully set?
CAMERA.X += 3*MY_SPEED.X; // displace the camera directly
CAMERA.Y += 3*MY_SPEED.Y; // otherwise it's stuck in the player
CAMERA.Z += 2*MY_SPEED.Z;
// CAMERA.DIAMETER = 8; // now make the camera impassable
} ELSE {
MOVE_VIEW CAMERA,NULLSKILL,MY_SPEED;
}
IF (IN_SOLID) { // if camera moved into a wall,
temp_cdist *= 0.7; // place it closer to the player
} ELSE {
temp_cdist += 0.2*(camera_dist - temp_cdist);
}
person_3rd = 1;
}
/* IFDEF FACE_THE_PLAYER;
ELSE {
temp.X = player.X - camera.X;
temp.Y = player.Y - camera.Y;
temp.Z = 0;
VEC2ANGLE temp,temp;
camera.pan = temp.pan;
}
ENDIF; */
}
ACTION move_view
{
IF (player == NULL) { RETURN; } // this action needs the player synonym
// don't move the view if the entity was client created
IF (person_3rd > 0) { // This skill should be local
CALL move_view_3rd;
} ELSE {
CALL move_view_1st;
}
}
// create a shadow below the entity
ACTION drop_shadow
{
IF (VIDEO_DEPTH >= 16) {
CREATE SHADOWSPRITE,MY.POS,move_shadow;
} ELSE {
CREATE SHADOWFLAT,MY.POS,move_shadow;
}
}
ACTION move_shadow
{
SET MY.TRANSPARENT,ON;
SET MY.PASSABLE,ON;
SET MY.ORIENTED,ON;
MY.AMBIENT = 0;
MY.SCALE_X = (YOUR.MAX_X - YOUR.MIN_X)/(MY.MAX_X - MY.MIN_X);
MY.SCALE_Y = MY.SCALE_X * 0.7;
MY.SCALE_Z = 1.0;
MY.TILT = 90; // set it flat onto the floor
WHILE ((YOU != NULL)&&(YOUR._MOVEMODE > 0))
{
IF (YOUR.INVISIBLE == ON) {
SET MY.INVISIBLE,ON;
} ELSE {
SET MY.INVISIBLE,OFF;
SET temp_ent,YOU;
SONAR temp_ent,500; // get height above the floor
my_height = RESULT;
SET YOU,temp_ent; // YOU (the entity itself) is changed by SONAR
MY.PAN = YOUR.PAN;
MY.X = YOUR.X;
MY.Y = YOUR.Y;
MY.Z = YOUR.Z + YOUR.MIN_Z + 2 - my_height;
// To improve: Adapt shadow orientation to floor slope
}
WAIT 1;
}
REMOVE ME;
}
// Get key input from the player
ACTION _player_intentions {
// Set the angular forces according to the player intentions
aforce.PAN = -astrength.PAN*(KEY_FORCE.X+JOY_FORCE.X);
aforce.TILT = astrength.TILT*(KEY_PGUP-KEY_PGDN);
IF (MOUSE_MODE == 0) { // Mouse switched off?
aforce.PAN += -astrength.PAN*MOUSE_FORCE.X*mouseview;
aforce.TILT += astrength.TILT*MOUSE_FORCE.Y*mouseview;
}
aforce.ROLL = 0;
// Set ROLL force if ALT was pressed
IF (KEY_ALT != 0) {
aforce.ROLL = aforce.PAN;
aforce.PAN = 0;
}
// Double the forces in case the player pressed SHIFT
IF (KEY_SHIFT != 0) {
aforce.PAN += aforce.PAN;
aforce.TILT += aforce.TILT;
aforce.ROLL += aforce.ROLL;
}
// Limit the forces in case the player
// pressed buttons, mouse and joystick simultaneously
limit.PAN = 2*astrength.PAN;
limit.TILT = 2*astrength.TILT;
limit.ROLL = 2*astrength.ROLL;
IF (aforce.PAN > limit.PAN) { aforce.PAN = limit.PAN; }
IF (aforce.PAN < -limit.PAN) { aforce.PAN = -limit.PAN; }
IF (aforce.TILT > limit.TILT) { aforce.TILT = limit.TILT; }
IF (aforce.TILT < -limit.TILT) { aforce.TILT = -limit.TILT; }
IF (aforce.ROLL > limit.ROLL) { aforce.ROLL = limit.ROLL; }
IF (aforce.ROLL < -limit.ROLL) { aforce.ROLL = -limit.ROLL; }
// Set the cartesian forces according to the player intentions
force.X = strength.X*(KEY_FORCE.Y+JOY_FORCE.Y);
force.Y = strength.Y*(KEY_COMMA-KEY_PERIOD);
force.Z = strength.Z*(KEY_HOME-KEY_END);
IF (MOUSE_MODE == 0) { // Mouse switched off?
force.X += strength.X*MOUSE_RIGHT*mouseview;
}
// Double the forces in case the player pressed SHIFT
IF (KEY_SHIFT != 0) {
force.X += force.X;
force.Y += force.Y;
force.Z += force.Z;
}
// Limit the forces in case the player tried to cheat by
// operating buttons, mouse and joystick simultaneously
limit.X = 2*strength.X;
limit.Y = 2*strength.Y;
limit.Z = 2*strength.Z;
IF (force.X > limit.X) { force.X = limit.X; }
IF (force.X < -limit.X) { force.X = -limit.X; }
IF (force.Y > limit.Y) { force.Y = limit.Y; }
IF (force.Y < -limit.Y) { force.Y = -limit.Y; }
IF (force.Z > limit.Z) { force.Z = limit.Z; }
IF (force.Z < -limit.Z) { force.Z = -limit.Z; }
}
ACTION _player_force {
IF (_camera == 0) { // If the camera does not move itself
IFDEF ACKNEX_VERSION414;
if (client_moving) {
force.X = MY._FORCE_X;
force.Y = MY._FORCE_Y;
force.Z = MY._FORCE_Z;
aforce.PAN = MY._AFORCE_PAN;
aforce.TILT = MY._AFORCE_TILT;
aforce.ROLL = MY._AFORCE_ROLL;
} ELSE {
CALL _player_intentions;
}
IFELSE;
CALL _player_intentions;
ENDIF;
aforce.PAN *= MY._FORCE;
aforce.TILT *= MY._FORCE;
aforce.ROLL *= MY._FORCE;
force.X *= MY._FORCE;
force.Y *= MY._FORCE;
force.Z *= MY._FORCE;
} ELSE { // player controls camera - set actor forces to zero
aforce.PAN = 0;
aforce.TILT = 0;
aforce.ROLL = 0;
force.X = 0;
force.Y = 0;
force.Z = 0;
}
}
ACTION client_move
{
IFDEF ACKNEX_VERSION414;
client_moving = 1;
WHILE (1) {
CALL _player_intentions;
if (player) { // player created on the client?
player._FORCE_X = force.X;
player._FORCE_Y = force.Y;
player._FORCE_Z = force.Z;
player._AFORCE_PAN = aforce.PAN;
player._AFORCE_TILT = aforce.TILT;
player._AFORCE_ROLL = aforce.ROLL;
// send forces to server
SEND player._FORCE_X;
SEND player._FORCE_Y;
SEND player._FORCE_Z;
SEND player._AFORCE_PAN;
SEND player._AFORCE_TILT;
SEND player._AFORCE_ROLL;
// move the camera
CALL move_view;
}
WAIT 1;
}
ENDIF;
RETURN;
}
/////////////////////////////////////////////////////////////////////
ACTION toggle_person {
IF (person_3rd > 0) {
person_3rd = 0;
} ELSE {
person_3rd = 0.5;
}
}
/////////////////////////////////////////////////////////////////////
// Auxiliary actions
ACTION scan_floor
{
SONAR ME,4000;
my_floornormal.X = NORMAL.X;
my_floornormal.Y = NORMAL.Y;
my_floornormal.Z = NORMAL.Z;
my_height = RESULT;
my_floorspeed.X = 0;
my_floorspeed.Y = 0;
// if the player is standing on a platform, move him with it
IF (YOU != NULL) {
IF (YOUR._TYPE == _TYPE_ELEVATOR) {
_shot_no += 1; //$$$
my_floorspeed.X = YOUR._SPEED_X;
my_floorspeed.Y = YOUR._SPEED_Y;
// Z speed is not necessary - this is done by the height adaption
}
}
}
// Calculate a position directly ahead of the camera
// Input: p (distance)
// Output: MY_POS
ACTION set_pos_ahead
{
temp.X = COS(CAMERA.PAN);
temp.Y = SIN(CAMERA.PAN);
temp.Z = p*COS(CAMERA.TILT);
MY_POS.X = CAMERA.X + temp.Z*temp.X;
MY_POS.Y = CAMERA.Y + temp.Z*temp.Y;
MY_POS.Z = CAMERA.Z + p*SIN(CAMERA.TILT);
}
////////////////////////////////////////////////////////////////////////
// event action to indicate any event by resetting the event flag
ACTION _setback {
IF (EVENT_TYPE == EVENT_BLOCK) { SET MY.ENABLE_BLOCK,OFF; }
IF (EVENT_TYPE == EVENT_ENTITY) { SET MY.ENABLE_ENTITY,OFF; }
IF (EVENT_TYPE == EVENT_STUCK) { SET MY.ENABLE_STUCK,OFF; }
IF (EVENT_TYPE == EVENT_PUSH) { SET MY.ENABLE_PUSH,OFF; }
IF (EVENT_TYPE == EVENT_IMPACT) { SET MY.ENABLE_IMPACT,OFF; }
IF (EVENT_TYPE == EVENT_DETECT) { SET MY.ENABLE_DETECT,OFF; }
IF (EVENT_TYPE == EVENT_SCAN) { SET MY.ENABLE_SCAN,OFF; }
IF (EVENT_TYPE == EVENT_SHOOT) { SET MY.ENABLE_SHOOT,OFF; }
IF (EVENT_TYPE == EVENT_TRIGGER) { SET MY.ENABLE_TRIGGER,OFF; }
IF (EVENT_TYPE == EVENT_TOUCH) { SET MY.ENABLE_TOUCH,OFF; }
IF (EVENT_TYPE == EVENT_RELEASE) { SET MY.ENABLE_RELEASE,OFF; }
IF (EVENT_TYPE == EVENT_CLICK) { SET MY.ENABLE_CLICK,OFF; }
}
ACTION _beep { BEEP; }
////////////////////////////////////////////////////////////////////////
// Handle action. Set to SPACE by default.
// Will operate doors or items within 200 quants.
SKILL indicator { VAL 0; }
DEFINE _HANDLE,1; // SCAN via space key
DEFINE _EXPLODE,2; // SCAN by an explosion
DEFINE _GUNFIRE,3; // SHOOT fired by a gun
DEFINE _WATCH,4; // looking for an enemy
DEFINE _DETECTED,5; // detected by an enemy
DEFINE _SHOOT1,6; // shoot key pressed (not used yet)
ACTION handle
{
IF (player != NULL) {
MY_POS.X = player.X;
MY_POS.Y = player.Y;
MY_POS.Z = player.Z;
MY_ANGLE.PAN = player.PAN;
} ELSE {
MY_POS.X = CAMERA.X;
MY_POS.Y = CAMERA.Y;
MY_POS.Z = CAMERA.Z;
MY_ANGLE.PAN = CAMERA.PAN;
}
MY_ANGLE.TILT = CAMERA.TILT;
CALL scan_handle;
}
// scan a wide cone of 200 quants range
ACTION scan_handle
{
temp.PAN = 120;
temp.TILT = 180;
temp.Z = 200;
indicator = _HANDLE;
SCAN MY_POS,MY_ANGLE,temp;
}
// This action can be run by a player entity on the server
// It checks for receiving a handle signal, then performs a scan
ACTION perform_handle
{
IFDEF ACKNEX_VERSION414;
WHILE (1) {
IF (MY._SIGNAL == _HANDLE) { // client has pressed handle key
SET MY.HIDDEN,ON;
MY._SIGNAL = 0; // reset it
MY_POS.X = MY.X;
MY_POS.Y = MY.Y;
MY_POS.Z = MY.Z;
MY_ANGLE.PAN = MY.PAN;
MY_ANGLE.TILT = MY.TILT;
CALL scan_handle;
}
WAIT 1;
}
ENDIF;
RETURN;
}
ACTION send_handle
{
IFDEF ACKNEX_VERSION414;
IF (player != NULL) {
player._SIGNAL = _HANDLE; // send command to perform a scan
SEND player._SIGNAL;
}
IFELSE;
BRANCH handle;
ENDIF;
}
/////////////////////////////////////////////////////////////////////
ON_F7 toggle_person;
ON_SPACE send_handle;
/////////////////////////////////////////////////////////////////////