home *** CD-ROM | disk | FTP | other *** search
/ PC Gamer 5.14 / 2000-11_-_Disc_5.14.iso / Goodies / 3DGameStudio / Mission / movement.wdl < prev    next >
Text File  |  2000-02-08  |  29KB  |  987 lines

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. // WDL prefabs for entity movement
  3. ///////////////////////////////////////////////////////////////////////////////////
  4. // Some definitions
  5. // Change them by re-defining them in your main wdl script
  6. // BEFORE the include, and adding DEFINE MOVE_DEFS;
  7. IFNDEF MOVE_DEFS;
  8.  SOUND  thud,<tap.wav>;
  9.  SOUND  robo_thud,<gate.wav>;
  10.  SOUND  splash,<splash.wav>;
  11.  DEFINE shadowsprite,<shadow.pcx>;
  12.  DEFINE shadowflat,<shadflat.pcx>;
  13.  DEFINE DEFAULT_WALK,13.040;
  14.  DEFINE DEFAULT_RUN,5.060;
  15. ENDIF;
  16.  
  17. ///////////////////////////////////////////////////////////////////////////////////
  18. // Some global skill definitions
  19. // Duplicate them in your wdl script AFTER the include
  20. // to give them new values
  21. SKILL gnd_fric { VAL 0.5; }    // ground friction
  22. SKILL air_fric { VAL 0.03; }    // air friction
  23. SKILL ang_fric { VAL 0.6; }    // angular friction
  24. SKILL gravity  { VAL 6; }        // gravity force
  25. SKILL elasticity { VAL 0.1; }    // of the floor
  26. SKILL strength  { X 5; Y 4; Z 25; }    // default ahead, side, jump strength
  27. SKILL astrength { PAN 7; TILT 5; ROLL 2; }    // default pan, tilt, roll strength
  28.  
  29. SKILL eye_height_up { VAL 0.8; }    // eye position factor for walking, driving
  30. SKILL eye_height_down { VAL 0.2; }    // for swimming
  31.  
  32. SKILL walk_rate { VAL 3; }    // for head wave, 360 / step width
  33. SKILL wave_rate { VAL 25; }// same for swimming, 360 / wave time
  34. SKILL walk_ampl { VAL 4; }    // walking head wave amplitude
  35. SKILL wave_ampl { VAL 2; }    // swimming head wave amplitude
  36.  
  37. SKILL person_3rd    { VAl 0; }    // 0: 1st person mode; 0.5: 3rd person mode
  38. SKILL camera_dist    { VAl 120; }  // camera distance to entity in 3rd person view
  39. SKILL mouseview { VAL 1; }          // mouse factor, set 0 to disable mouse
  40. SKILL client_moving { VAL 0; }  // multiplayer mode
  41.  
  42. SKILL jump_height { VAL 100; }    // maximum jump height above ground
  43. SKILL walk_or_run { VAL 12; }        // max quants per tick to switch from walk to run animation
  44.  
  45. ///////////////////////////////////////////////////////////////////////
  46. // Entity skill & flag definitions
  47. // some definitions here are also needed for ACTORS.WDL and WAR.WDL
  48. DEFINE _WALKFRAMES,SKILL1;
  49. DEFINE _RUNFRAMES,SKILL2;
  50. DEFINE _ATTACKFRAMES,SKILL3;
  51. DEFINE _DIEFRAMES,SKILL4;
  52.  
  53. DEFINE _FORCE,SKILL5;        // determines speed
  54. DEFINE _ENTFORCE,SKILL5;
  55. DEFINE _BANKING,SKILL6;        // banking - for player only
  56. DEFINE _PENDOLINO,SKILL6;    // banking - for player only
  57. DEFINE _HITMODE,SKILL6;        // for actors
  58. DEFINE _MOVEMODE,SKILL7;
  59. DEFINE _FIREMODE,SKILL8;    // for actors
  60.  
  61. DEFINE __WHEELS,FLAG2;    // block turns without moving
  62. DEFINE __SLOPES,FLAG3;    // adapt the tilt and roll angle to slopes
  63. DEFINE __JUMP,FLAG4;        // be able to jump
  64. DEFINE __BOB,FLAG5;       // head wave
  65. DEFINE __STRAFE,FLAG6;    // be able to move sidewards
  66. DEFINE __TRIGGER,FLAG7;    // be able to trigger doors automatically
  67.  
  68. DEFINE __SOUND,FLAG8;
  69.  
  70. ///////////////////////////////////////////////////////////////////////
  71. DEFINE _HEALTH,SKILL9;
  72. DEFINE _ARMOR,SKILL10;
  73.  
  74. DEFINE _SPEED,SKILL11;        // speed
  75. DEFINE _SPEED_X,SKILL11;
  76. DEFINE _SPEED_Y,SKILL12;
  77. DEFINE _SPEED_Z,SKILL13;
  78. DEFINE _ASPEED,SKILL14;        // angular speed
  79. DEFINE _ASPEED_PAN,SKILL14;
  80. DEFINE _ASPEED_TILT,SKILL15;
  81. DEFINE _ASPEED_ROLL,SKILL16;
  82.  
  83. // for actor entities, and for doors and platforms
  84. DEFINE _TARGET_X,SKILL17;
  85. DEFINE _TARGET_Y,SKILL18;
  86. DEFINE _TARGET_Z,SKILL19;
  87. DEFINE _TARGET_PAN,SKILL20;
  88. DEFINE _TARGET_TILT,SKILL21;
  89. DEFINE _TARGET_ROLL,SKILL22;
  90.  
  91. // for player entities
  92. DEFINE _FORCE_X,SKILL17;
  93. DEFINE _FORCE_Y,SKILL18;
  94. DEFINE _FORCE_Z,SKILL19;
  95. DEFINE _AFORCE_PAN,SKILL20;
  96. DEFINE _AFORCE_TILT,SKILL21;
  97. DEFINE _AFORCE_ROLL,SKILL22;
  98.  
  99. DEFINE _WALKSOUND,SKILL23;    // walking sound
  100. DEFINE _SIGNAL,SKILL24;        // communication for actions or client->server
  101. DEFINE _COUNTER,SKILL25;    // internal counter
  102. DEFINE _STATE,SKILL26;        // the state it is in (walk, attack, escape etc.)
  103.  
  104. DEFINE _WALKDIST,SKILL27;    // distance per walk cycle
  105. DEFINE _RUNDIST,SKILL28;    // distance per run cycle
  106. DEFINE _TYPE,SKILL30;        // the type of the entity
  107.  
  108. // Skills up to 32 are reserved for future template actions
  109. // Skills 33-40 can be used freely
  110.  
  111. ///////////////////////////////////////////////////////////////////////
  112. SKILL force    {}        // cartesian force, entity coordinates
  113. SKILL absforce    {}    // cartesian force, world coordinates
  114. SKILL aforce    {}    // angular force
  115. SKILL speed    { X 0; Y 0; Z 0; }    // cartesian speed, entity coordinates
  116. SKILL abspeed  { X 0; Y 0; Z 0; }    // cartesian speed, world coordinates
  117. SKILL aspeed    {}    // angular speed
  118. SKILL p    {}
  119. SKILL friction {}
  120. SKILL limit  {}
  121.  
  122. SKILL head_angle    { PAN 0; TILT 0; ROLL 0; }    // separated from other values
  123. SKILL headwave    { VAL 0; }
  124. SKILL walkwave    { VAL 0; }
  125. SKILL my_dist     {}        // intended covered distance
  126. SKILL quants    {}        // real covered distance
  127. SKILL scan_sector    {}
  128. SKILL my_height    {}
  129. SKILL my_floornormal    {}
  130. SKILL my_floorspeed {}
  131. SKILL temp_cdist    { VAl 120; }  // current camera distance in 3rd p view
  132. SKILL debugskill {}
  133.  
  134. SYNONYM player { TYPE ENTITY; }
  135. SYNONYM temp_ent { TYPE ENTITY; }
  136. SYNONYM carry { TYPE action; }
  137.  
  138. DEFINE _MODE_WALKING,1;
  139. DEFINE _MODE_DRIVING,2;
  140. DEFINE _MODE_SWIMMING,3;
  141. DEFINE _MODE_DIVING,4;
  142. DEFINE _MODE_WADING,5;
  143. DEFINE _MODE_FLYING,6;
  144. DEFINE _MODE_STILL,10;
  145. // modes above 10 are handled by a different wdl
  146. DEFINE _MODE_ATTACK,20;
  147.  
  148. DEFINE _SOUND_WALKER,1;
  149. DEFINE _SOUND_ROBOT,2;
  150.  
  151. DEFINE _TYPE_PLAYER,1;
  152. DEFINE _TYPE_ACTOR,2;
  153. DEFINE _TYPE_FOE,3;
  154. DEFINE _TYPE_DOOR,10;
  155. DEFINE _TYPE_GATE,11;
  156. DEFINE _TYPE_ELEVATOR,12;
  157. DEFINE _TYPE_GUN,20;
  158. DEFINE _TYPE_AMMO,21;
  159. DEFINE _TYPE_ARMOR,22;
  160. DEFINE _TYPE_HEALTH,23;
  161.  
  162. ///////////////////////////////////////////////////////////////////////
  163. DEFINE RETURN,END;    // compatibility to old versions
  164.  
  165. SOUND beep_sound,<beep.wav>;
  166. //SYNONYM debugsyn { TYPE ENTITY; }
  167.  
  168. ///////////////////////////////////////////////////////////////////////
  169. // Some actions, which use player_move
  170. ACTION player_drive {
  171.     MY._MOVEMODE = _MODE_DRIVING;
  172.     MY._FORCE = 1.5;
  173.     MY._BANKING = 0.5;
  174.     SET MY.__SLOPES,ON;
  175.     CALL player_move;
  176. }
  177.  
  178. ACTION player_walk {
  179.     MY._MOVEMODE = _MODE_WALKING;
  180.     MY._FORCE = 0.75;
  181.     MY._BANKING = -0.1;
  182.     SET MY.__JUMP,ON;
  183.     SET MY.__STRAFE,ON;
  184.     SET MY.__BOB,ON;
  185.     SET MY.__TRIGGER,ON;
  186.     CALL player_move;
  187. }
  188.  
  189. ACTION player_swim {
  190.     MY._MOVEMODE = _MODE_SWIMMING;
  191.     MY._FORCE = 0.75;
  192.     MY._BANKING = 0;
  193.     SET MY.__JUMP,ON;
  194.     SET MY.__STRAFE,OFF;
  195.     SET MY.__BOB,ON;
  196.     CALL player_move;
  197. }
  198.  
  199. ///////////////////////////////////////////////////////////////////////
  200. // Shakes the player, used for hits and death
  201. ACTION player_shake
  202. {
  203.     IF (RANDOM(1) > 0.5)
  204.     {
  205.         MY.ROLL += 8;
  206.         MY.TILT += 8;
  207.         WAITT 2;
  208.         MY.TILT -= 5;
  209.         WAITT 2;
  210.         MY.ROLL -= 8;
  211.         MY.TILT -= 3;
  212.     } ELSE {
  213.         MY.ROLL -= 8;
  214.         MY.TILT += 8;
  215.         WAITT 2;
  216.         MY.TILT -= 5;
  217.         WAITT 2;
  218.         MY.ROLL += 8;
  219.         MY.TILT -= 3;
  220.     }
  221. }
  222.  
  223. // player tips over, used for death
  224. ACTION player_tip
  225. {
  226.     MY._MOVEMODE = 0;    // suspend normal movement action
  227.     eye_height_up.Z = eye_height_up;    // store original eye height
  228.     WHILE (MY.ROLL < 80)
  229.     {
  230.         MY.ROLL += 8 * TIME;
  231.         MY.TILT += 2 * TIME;
  232.         IF (eye_height_up > 0.15) {
  233.             eye_height_up -= 0.1 * TIME; }
  234.  
  235.         IF (client_moving==0) { CALL move_view; }
  236.         WAIT 1;
  237.     }
  238.  
  239.     MY.ROLL = 80;
  240.     MY.TILT = 20;
  241.     eye_height_up = eye_height_up.Z;    // restore original eye height
  242. }
  243.  
  244. ///////////////////////////////////////////////////////////////////////
  245. // main player movement action
  246. ACTION player_move {
  247. IFDEF ACKNEX_VERSION414;
  248.     IF (MY.CLIENT == 0) { SET player,ME; } // created on the server?
  249. IFELSE;
  250.     SET player,ME; // to be accessible by a synonym
  251. ENDIF;
  252.  
  253.     MY._TYPE = _TYPE_PLAYER;
  254.     SET MY.ENABLE_SCAN,ON;    // so that enemies can detect me
  255.  
  256.     IF (MY._FORCE == 0) {  MY._FORCE = 1.5; }
  257.     IF (MY._MOVEMODE == 0) { MY._MOVEMODE = _MODE_WALKING; }
  258.     IF (MY._WALKFRAMES == 0) { MY._WALKFRAMES = DEFAULT_WALK; }
  259.     IF (MY._RUNFRAMES == 0) { MY._RUNFRAMES = DEFAULT_RUN; }
  260.     IF (MY._WALKSOUND == 0) { MY._WALKSOUND = _SOUND_WALKER; }
  261.  
  262.     CALL anim_init;
  263.     CALL perform_handle;    // react on pressing the handle key
  264.  
  265.     WHILE ((MY._MOVEMODE > 0)&&(MY._MOVEMODE <= _MODE_STILL))
  266.     {
  267.         IF (MY._MOVEMODE == _MODE_STILL) {    // do nothing at all
  268.             WAIT 1;
  269.             CONTINUE;
  270.         }
  271.  
  272. // Get the angular and translation forces
  273.         CALL    _player_force;
  274. // find ground below
  275.         CALL  scan_floor;
  276.  
  277. // if he is above water, switch to swimming
  278.         IF (ON_PASSABLE) {
  279. //            my_height += (MY.MAX_Z-MY.MIN_Z)*0.5;    // dive into it
  280.  
  281. // if he walked before, play a splash
  282.             IF (MY._MOVEMODE == _MODE_WALKING) {
  283.                 PLAY_SOUND splash,50;
  284.                 MY._MOVEMODE = _MODE_SWIMMING;
  285.             }
  286.         } ELSE {
  287.             IF (MY._MOVEMODE == _MODE_SWIMMING) {
  288.                 MY._MOVEMODE = _MODE_WALKING;
  289.             }
  290.         }
  291.  
  292. // if he is on a slope, change his angles, and maybe let him slide down
  293.         IF (MY.__SLOPES == ON) {
  294. // Adapt the player angle to the floor slope
  295.             MY_ANGLE.TILT = 0;
  296.             MY_ANGLE.ROLL = 0;
  297.             IF (my_height < 10 && (my_floornormal.X != 0 || my_floornormal.Y != 0 ))
  298.             {    // on a slope?
  299. // rotate the floor normal relative to the player
  300.                 MY_ANGLE.PAN = -MY.PAN;
  301.                 VECROTATE my_floornormal,MY_ANGLE;
  302. // calculate the destination tilt and roll angles
  303.                 MY_ANGLE.TILT = -ASIN(my_floornormal.X);
  304.                 MY_ANGLE.ROLL = -ASIN(my_floornormal.Y);
  305.             }
  306. // change the player angles towards the destination angles
  307.             MY.TILT += 0.2 * ANG(MY_ANGLE.TILT-MY.TILT);
  308.             MY.ROLL += 0.2 * ANG(MY_ANGLE.ROLL-MY.ROLL);
  309.         } ELSE {
  310. // If the ROLL angle was not equal to zero,
  311. // apply a ROLL force to set the angle back
  312.             aforce.ROLL = -0.2*ANG(MY.ROLL);
  313.         }
  314.  
  315. // Now accelerate the angular speed, and change his angles
  316.         ACCEL    MY._ASPEED,aforce,ang_fric;
  317.  
  318.         temp = MY._ASPEED_PAN * MY._SPEED_X * 0.05;
  319.         IF (MY.__WHEELS) {    // Turn only if moving ahead
  320.             MY.PAN += temp;
  321.         } ELSE {
  322.             MY.PAN += MY._ASPEED_PAN;
  323.         }
  324.         MY.ROLL += temp * MY._BANKING + MY._ASPEED_ROLL;
  325.         head_angle.TILT += MY._ASPEED_TILT;
  326.  
  327. // Limit the TILT value
  328.         head_angle.TILT = ANG(head_angle.TILT);
  329.         IF (head_angle.TILT > 80) { head_angle.TILT = 80; }
  330.         IF (head_angle.TILT < -80) { head_angle.TILT = -80; }
  331.  
  332. // Decide whether the actor can jump or not. He can't if he is in the air
  333.         IF ((jump_height <= 0)
  334.             || (MY.__JUMP == OFF)
  335.             || (my_height > 4)
  336.             || (force.Z <= 0))
  337.         {
  338.             force.Z = 0;
  339.         }
  340.  
  341. // disable strafing
  342.         IF (MY.__STRAFE == OFF) {
  343.             force.Y = 0;    // no strafe
  344.         }
  345.  
  346. // now move him
  347.         CALL  move_gravity;
  348.  
  349. // select the right walking frame (swimming anim not yet implemented)
  350.         CALL actor_anim;
  351.  
  352. // If I'm the only player, draw the camera and weapon with ME
  353.         IF (client_moving == 0) { CALL move_view; }
  354.         CALL carry;
  355.  
  356. // Wait one tick, then repeat
  357.         WAIT    1;
  358.     }
  359. }
  360.  
  361. // this is the main movement action for the camera
  362. ACTION camera_move {
  363.     _camera = 1;
  364.     WHILE (_camera == 1)
  365.     {
  366.         CALL  _player_intentions;
  367.  
  368.         ACCEL    aspeed,aforce,0.9;
  369.         CAMERA.PAN += aspeed.PAN;
  370.         CAMERA.TILT += aspeed.TILT;
  371.         CAMERA.ROLL += aspeed.ROLL;
  372.  
  373.         ACCEL    speed,force,0.9;
  374.         MOVE_VIEW CAMERA,speed,NULLSKILL;
  375.         WAIT    1;
  376.     }
  377. }
  378.  
  379. /////////////////////////////////////////////////////////////////////
  380. // Core part of move action, common for actors and players
  381. ACTION move_gravity
  382. {
  383. // Filter the forces and frictions dependent on the state of the actor,
  384. // and then apply them, and move him
  385.  
  386. // First, decide whether the actor is standing on the floor or not
  387.     IF (my_height < 5) {
  388.         friction = gnd_fric;
  389.         IF (MY._MOVEMODE == _MODE_DRIVING) {
  390. // Driving - less friction, less force
  391.             friction *= 0.3;
  392.             force.X *= 0.3;
  393.         }
  394.         IF (MY._MOVEMODE == _MODE_SWIMMING) {
  395. // Swimming - rhythmic acceleration
  396.             force.X *= 0.5 + 0.25*walkwave;
  397.             force.Y *= 0.5;
  398.         }
  399.  
  400.         absforce.X = 0;
  401.         absforce.Y = 0;
  402.         absforce.Z = 0;
  403. // If on a slope, apply gravity to draw him downwards:
  404.         IF (my_floornormal.Z < 0.85) {
  405.             absforce.X = my_floornormal.X * gravity * 2;
  406.             absforce.Y = my_floornormal.Y * gravity * 2;
  407. // If slope too steep, really push him back
  408.             temp = 0.66 - my_floornormal.Z;
  409.             IF (temp > 0) {
  410.                 absforce.X *= 3;
  411.                 absforce.Y *= 3;
  412.             }
  413.         }
  414.     } ELSE {
  415. // airborne - set all relative forces to 0
  416. // to prevent him from jumping or further moving in the air
  417.         friction = air_fric;
  418.         force.X = 0;
  419.         force.Y = 0;
  420.         force.Z = 0;
  421.         absforce.X = 0;
  422.         absforce.Y = 0;
  423.         absforce.Z = -gravity;
  424.     }
  425.  
  426. // accelerate the entity relative speed by the force
  427.     speed.X = MY._SPEED_X;
  428.     speed.Y = MY._SPEED_Y;
  429.     ACCEL    speed,force,friction;
  430.     speed.Z = 0;    // jumping force controls absolute speed only
  431.     MY._SPEED_X = speed.X;
  432.     MY._SPEED_Y = speed.Y;
  433.  
  434. // Add the world gravity force
  435.     abspeed.X = 0;
  436.     abspeed.Y = 0;
  437.     abspeed.Z = MY._SPEED_Z;
  438.     ACCEL    abspeed,absforce,friction;
  439.  
  440. // Add the speed given by the ground elasticity and the jumping force
  441.     IF (my_height < 5) {
  442.         temp = my_height;
  443.         IF (temp < -10)  { temp = -10; }
  444.         abspeed.Z = force.Z-temp;
  445.     }
  446.  
  447. // Restrict the speed to the maximum jumping height
  448.     IF ((abspeed.Z > 0) && (abspeed.Z + my_height > jump_height)) {
  449.         abspeed.Z = jump_height - my_height;
  450.         if (abspeed.Z < 0) { abspeed.Z = 0; }
  451.     }
  452.     MY._SPEED_Z = abspeed.Z;
  453.  
  454. // If the actor is standing on a moving platform, add it's horizontal speed
  455.     IF (my_height < 5) {
  456.         abspeed.X = my_floorspeed.X;
  457.         abspeed.Y = my_floorspeed.Y;
  458.     }
  459.  
  460. // Now move ME by the relative and the absolute speed
  461.     SET YOU,NULL;    // YOU entity is considered passable by MOVE
  462.     MOVE ME,speed,abspeed;
  463.  
  464. // Store the distance to cover, for head bobbing
  465. //    my_dist = SQRT(MY_SPEED.X*MY_SPEED.X + MY_SPEED.Y*MY_SPEED.Y);
  466.     my_dist = SQRT(speed.X*speed.X + speed.Y*speed.Y);
  467. }
  468.  
  469. // split the integer and fractional parts of the animation frame numbers
  470. ACTION anim_init {
  471.     temp = FRC(MY._WALKFRAMES) * 1000;
  472.     IF (temp == 0) { temp = 40; }
  473.     MY._WALKFRAMES = INT(MY._WALKFRAMES);
  474.     IF (MY._WALKFRAMES == 0) { MY._WALKFRAMES = 13; }
  475.     MY._WALKDIST = MY._WALKFRAMES / temp;
  476.  
  477.     temp = FRC(MY._RUNFRAMES) * 1000;
  478.     IF (temp == 0) { temp = 60; }
  479.     MY._RUNFRAMES = INT(MY._RUNFRAMES);
  480.     IF (MY._RUNFRAMES == 0) { MY._RUNFRAMES = 5; }
  481.     MY._RUNDIST = MY._RUNFRAMES / temp;
  482. }
  483.  
  484. // play some kinds of foot sound
  485. ACTION _play_walksound {
  486.     IF ((ME == player) && (person_3rd == 0)) { RETURN; }    // don't play entity sounds for 1st peron player
  487.     IF (MY._WALKSOUND == _SOUND_WALKER) { PLAY_ENTSOUND ME,thud,60; }
  488.     IF (MY._WALKSOUND == _SOUND_ROBOT) { PLAY_ENTSOUND ME,robo_thud,60; }
  489. }
  490.  
  491. ////////////////////////////////////////////////////////////////////
  492. // Main action to animate a walking actor, depending on dist covered
  493. ACTION actor_anim
  494. {
  495.     IF ((MY._MOVEMODE == _MODE_STILL) || (my_dist < 0.01))
  496.     {
  497. // if the entity has a standing animation, instead of just one frame,
  498. // place it here. Otherwise...
  499.         MY.FRAME = 1;    // standing
  500.         RETURN;
  501.     }
  502.  
  503.     IF (MY._MOVEMODE == _MODE_WALKING)
  504.     {
  505. // decide whether to play the walk or run animation
  506.         IF (my_dist < walk_or_run*TIME)    // Walking
  507.         {
  508.             IF (MY.FRAME < 2) { MY.FRAME = 2; }
  509.  
  510.             MY.FRAME += MY._WALKDIST*my_dist;
  511.  
  512. // this is one of the expert exceptions where you can use WHILE without WAIT!
  513.             WHILE (MY.FRAME >= 2 + MY._WALKFRAMES) {
  514. // sound for right foot
  515.                 IF (MY.__SOUND == ON) { CALL _play_walksound; SET MY.__SOUND,OFF; }
  516. // cycle the animation
  517.                 MY.FRAME -= MY._WALKFRAMES;
  518.             }
  519.  
  520.             IF (MY.FRAME > 1 + MY._WALKFRAMES*0.5) {
  521. // sound for left foot
  522.                 IF (MY.__SOUND == OFF) { CALL _play_walksound; SET MY.__SOUND,ON; }
  523.             }
  524.  
  525. IFDEF ACKNEX_VERSION412;
  526.             IF (MY.FRAME > 1 + MY._WALKFRAMES) {
  527.                 MY.NEXT_FRAME = 2;    // inbetween to the first walking frame
  528.             } ELSE {
  529.                 MY.NEXT_FRAME = 0;    // inbetween to the real next frame
  530.             }
  531. ENDIF;
  532.  
  533.             RETURN;
  534.         }
  535.         ELSE {    // Running
  536.             IF (MY.FRAME < 2 + MY._WALKFRAMES) { MY.FRAME = 2 + MY._WALKFRAMES; }
  537.  
  538.             MY.FRAME += MY._RUNDIST*my_dist;
  539.  
  540.             WHILE (MY.FRAME >= 2 + MY._WALKFRAMES + MY._RUNFRAMES) {
  541.                 IF (MY.__SOUND == ON) { CALL _play_walksound; SET MY.__SOUND,OFF; }
  542.                 MY.FRAME -= MY._RUNFRAMES;
  543.             }
  544.  
  545.             IF (MY.FRAME > 1 + MY._WALKFRAMES + MY._RUNFRAMES*0.5) {
  546.                 IF (MY.__SOUND == OFF) { CALL _play_walksound; SET MY.__SOUND,ON; }
  547.             }
  548.  
  549. IFDEF ACKNEX_VERSION412;
  550.             IF (MY.FRAME > 1 + MY._WALKFRAMES + MY._RUNFRAMES) {
  551.                 MY.NEXT_FRAME = 2 + MY._WALKFRAMES;
  552.             } ELSE {
  553.                 MY.NEXT_FRAME = 0;
  554.             }
  555. ENDIF;
  556.  
  557.             RETURN;
  558.         }
  559.     }
  560.  
  561. // place here the swimming animation if any
  562. //    IF (MY._MOVEMODE == _MODE_SWIMMING) {
  563. //     RETURN;
  564. //    }
  565.  
  566. // or place here further animations ...
  567. }
  568.  
  569. ///////////////////////////////////////////////////////////////////////
  570. // First person camera view
  571. // This should be a client-only action!!
  572. SKILL position_old {}
  573.  
  574. ACTION move_view_1st
  575. {
  576.     IF (_camera == 0) {        // If the camera does not move itself
  577.         IF (my_height < 5) {
  578. //            quants += SQRT((player.X-position_old.X)*(player.X-position_old.X)
  579. //                        + (player.Y-position_old.Y)*(player.Y-position_old.Y));
  580.             quants += my_dist;
  581.             position_old.X = player.X;
  582.             position_old.Y = player.Y;
  583.             headwave = SIN(quants*walk_rate);
  584.             IF ((player._MOVEMODE == 0)    // moving on client?
  585.                 || (player._MOVEMODE == _MODE_WALKING)) {
  586. // Play the right and left foot sound
  587.                 IF (((headwave > 0) && (walkwave <= 0))
  588.                     || ((headwave <= 0) && (walkwave > 0))) {
  589.                     PLAY_SOUND thud,30; }
  590. // head bobbing
  591.                 walkwave = headwave;
  592.                 headwave = walk_ampl*(ABS(headwave)-0.5);
  593.             }
  594.             IF (player._MOVEMODE == _MODE_SWIMMING) {
  595.                 IF ((headwave > 0) && (walkwave <= 0)) {
  596.                     PLAY_SOUND splash,30;
  597.                 }
  598. // in-water wave movement
  599.                 walkwave = headwave;
  600.                 headwave = wave_ampl*SIN(TOTAL_TICKS*wave_rate);
  601.                 head_angle.TILT += 0.1*wave_ampl*SIN(TOTAL_TICKS*wave_rate - 60);
  602.             }
  603.         }
  604.  
  605.         CAMERA.DIAMETER = 0;        // make the camera passable
  606.         SET CAMERA.GENIUS,player;    // don't display parts of ME
  607.         CAMERA.X = player.X;
  608.         CAMERA.Y = player.Y;
  609.         CAMERA.Z = player.Z + player.MIN_Z;
  610.         IF (player.__BOB == ON) { CAMERA.Z += headwave;    }
  611.  
  612.         IF (player._MOVEMODE == _MODE_SWIMMING) {
  613.             CAMERA.Z += (player.MAX_Z-player.MIN_Z)*eye_height_down; // Add eye height
  614.         } ELSE {
  615.             CAMERA.Z += (player.MAX_Z-player.MIN_Z)*eye_height_up;
  616.         }
  617.  
  618.         CAMERA.PAN = player.PAN;
  619.         CAMERA.TILT = player.TILT + head_angle.TILT;
  620.         CAMERA.ROLL = player.ROLL;
  621.  
  622.         person_3rd = 0;
  623.     }
  624. }
  625.  
  626. // Third person camera view
  627. ACTION move_view_3rd
  628. {
  629.     IF (_camera == 0) {        // If the camera does not move itself
  630.         CAMERA.DIAMETER = 0;        // make the camera passable
  631.         SET CAMERA.GENIUS,player;
  632.         CAMERA.PAN += 0.2 * ANG(player.PAN-CAMERA.PAN);
  633.         CAMERA.TILT = head_angle.TILT-5;
  634.       MY_SPEED.X = 0.3*(player.X - temp_cdist * COS(player.PAN) - CAMERA.X);
  635.       MY_SPEED.Y = 0.3*(player.Y - temp_cdist * SIN(player.PAN) - CAMERA.Y);
  636.       MY_SPEED.Z = 0.5*(player.Z + player.MAX_Z - CAMERA.Z);
  637.         IF (person_3rd < 1) {            // not yet fully set?
  638.             CAMERA.X += 3*MY_SPEED.X;    // displace the camera directly
  639.             CAMERA.Y += 3*MY_SPEED.Y;    // otherwise it's stuck in the player
  640.             CAMERA.Z += 2*MY_SPEED.Z;
  641. //          CAMERA.DIAMETER = 8;        // now make the camera impassable
  642.         } ELSE {
  643.             MOVE_VIEW CAMERA,NULLSKILL,MY_SPEED;
  644.         }
  645.         IF (IN_SOLID) {             // if camera moved into a wall,
  646.             temp_cdist *= 0.7;    // place it closer to the player
  647.         } ELSE {
  648.             temp_cdist += 0.2*(camera_dist - temp_cdist);
  649.         }
  650.         person_3rd = 1;
  651.     }
  652. /* IFDEF FACE_THE_PLAYER;
  653.    ELSE {
  654.        temp.X = player.X - camera.X;
  655.        temp.Y = player.Y - camera.Y;
  656.        temp.Z = 0;
  657.         VEC2ANGLE temp,temp;
  658.         camera.pan = temp.pan;
  659.     }
  660. ENDIF; */
  661. }
  662.  
  663. ACTION move_view
  664. {
  665.     IF (player == NULL) { RETURN; }    // this action needs the player synonym
  666. // don't move the view if the entity was client created
  667.     IF (person_3rd > 0) {    // This skill should be local
  668.         CALL move_view_3rd;
  669.     } ELSE {
  670.         CALL move_view_1st;
  671.     }
  672. }
  673.  
  674. // create a shadow below the entity
  675. ACTION drop_shadow
  676. {
  677.     IF (VIDEO_DEPTH >= 16) {
  678.         CREATE SHADOWSPRITE,MY.POS,move_shadow;
  679.     } ELSE {
  680.         CREATE SHADOWFLAT,MY.POS,move_shadow;
  681.     }
  682. }
  683.  
  684. ACTION move_shadow
  685. {
  686.     SET MY.TRANSPARENT,ON;
  687.     SET MY.PASSABLE,ON;
  688.     SET MY.ORIENTED,ON;
  689.     MY.AMBIENT = 0;
  690.     MY.SCALE_X = (YOUR.MAX_X - YOUR.MIN_X)/(MY.MAX_X - MY.MIN_X);
  691.     MY.SCALE_Y = MY.SCALE_X * 0.7;
  692.     MY.SCALE_Z = 1.0;
  693.     MY.TILT = 90;    // set it flat onto the floor
  694.     WHILE ((YOU != NULL)&&(YOUR._MOVEMODE > 0))
  695.     {
  696.         IF (YOUR.INVISIBLE == ON) {
  697.             SET MY.INVISIBLE,ON;
  698.         } ELSE {
  699.             SET MY.INVISIBLE,OFF;
  700.             SET temp_ent,YOU;
  701.             SONAR    temp_ent,500;    // get height above the floor
  702.             my_height = RESULT;
  703.             SET YOU,temp_ent;        // YOU (the entity itself) is changed by SONAR
  704.             MY.PAN = YOUR.PAN;
  705.             MY.X = YOUR.X;
  706.             MY.Y = YOUR.Y;
  707.             MY.Z = YOUR.Z + YOUR.MIN_Z + 2 - my_height;
  708. // To improve: Adapt shadow orientation to floor slope
  709.         }
  710.         WAIT 1;
  711.     }
  712.     REMOVE ME;
  713. }
  714.  
  715.  
  716. // Get key input from the player
  717. ACTION _player_intentions {
  718. // Set the angular forces according to the player intentions
  719.     aforce.PAN = -astrength.PAN*(KEY_FORCE.X+JOY_FORCE.X);
  720.     aforce.TILT = astrength.TILT*(KEY_PGUP-KEY_PGDN);
  721.     IF (MOUSE_MODE == 0) {    // Mouse switched off?
  722.          aforce.PAN += -astrength.PAN*MOUSE_FORCE.X*mouseview;
  723.          aforce.TILT += astrength.TILT*MOUSE_FORCE.Y*mouseview;
  724.     }
  725.     aforce.ROLL = 0;
  726. // Set ROLL force if ALT was pressed
  727.     IF (KEY_ALT != 0) {
  728.         aforce.ROLL = aforce.PAN;
  729.         aforce.PAN = 0;
  730.     }
  731. // Double the forces in case the player pressed SHIFT
  732.     IF (KEY_SHIFT != 0) {
  733.         aforce.PAN += aforce.PAN;
  734.         aforce.TILT += aforce.TILT;
  735.         aforce.ROLL += aforce.ROLL;
  736.     }
  737. // Limit the forces in case the player
  738. // pressed buttons, mouse and joystick simultaneously
  739.     limit.PAN = 2*astrength.PAN;
  740.     limit.TILT = 2*astrength.TILT;
  741.     limit.ROLL = 2*astrength.ROLL;
  742.  
  743.     IF (aforce.PAN > limit.PAN) {  aforce.PAN = limit.PAN; }
  744.     IF (aforce.PAN < -limit.PAN) {  aforce.PAN = -limit.PAN; }
  745.     IF (aforce.TILT > limit.TILT) {  aforce.TILT = limit.TILT; }
  746.     IF (aforce.TILT < -limit.TILT) {  aforce.TILT = -limit.TILT; }
  747.     IF (aforce.ROLL > limit.ROLL) {  aforce.ROLL = limit.ROLL; }
  748.     IF (aforce.ROLL < -limit.ROLL) {  aforce.ROLL = -limit.ROLL; }
  749.  
  750. // Set the cartesian forces according to the player intentions
  751.     force.X = strength.X*(KEY_FORCE.Y+JOY_FORCE.Y);
  752.     force.Y = strength.Y*(KEY_COMMA-KEY_PERIOD);
  753.     force.Z = strength.Z*(KEY_HOME-KEY_END);
  754.     IF (MOUSE_MODE == 0) {    // Mouse switched off?
  755.         force.X += strength.X*MOUSE_RIGHT*mouseview;
  756.     }
  757.  
  758. // Double the forces in case the player pressed SHIFT
  759.     IF (KEY_SHIFT != 0) {
  760.         force.X += force.X;
  761.         force.Y += force.Y;
  762.         force.Z += force.Z;
  763.     }
  764.  
  765. // Limit the forces in case the player tried to cheat by
  766. // operating buttons, mouse and joystick simultaneously
  767.     limit.X = 2*strength.X;
  768.     limit.Y = 2*strength.Y;
  769.     limit.Z = 2*strength.Z;
  770.  
  771.     IF (force.X > limit.X) {  force.X = limit.X; }
  772.     IF (force.X < -limit.X) { force.X = -limit.X; }
  773.     IF (force.Y > limit.Y) {  force.Y = limit.Y; }
  774.     IF (force.Y < -limit.Y) { force.Y = -limit.Y; }
  775.     IF (force.Z > limit.Z) {  force.Z = limit.Z; }
  776.     IF (force.Z < -limit.Z) { force.Z = -limit.Z; }
  777. }
  778.  
  779. ACTION _player_force {
  780.     IF (_camera == 0) {    // If the camera does not move itself
  781. IFDEF ACKNEX_VERSION414;
  782.         if (client_moving) {
  783.             force.X = MY._FORCE_X;
  784.             force.Y = MY._FORCE_Y;
  785.             force.Z = MY._FORCE_Z;
  786.             aforce.PAN = MY._AFORCE_PAN;
  787.             aforce.TILT = MY._AFORCE_TILT;
  788.             aforce.ROLL = MY._AFORCE_ROLL;
  789.         } ELSE {
  790.             CALL _player_intentions;
  791.         }
  792. IFELSE;
  793.         CALL _player_intentions;
  794. ENDIF;
  795.         aforce.PAN *= MY._FORCE;
  796.         aforce.TILT *= MY._FORCE;
  797.         aforce.ROLL *= MY._FORCE;
  798.         force.X *= MY._FORCE;
  799.         force.Y *= MY._FORCE;
  800.         force.Z *= MY._FORCE;
  801.     } ELSE { // player controls camera - set actor forces to zero
  802.         aforce.PAN = 0;
  803.         aforce.TILT = 0;
  804.         aforce.ROLL = 0;
  805.         force.X = 0;
  806.         force.Y = 0;
  807.         force.Z = 0;
  808.     }
  809. }
  810.  
  811.  
  812. ACTION client_move
  813. {
  814. IFDEF ACKNEX_VERSION414;
  815.     client_moving = 1;
  816.     WHILE (1) {
  817.         CALL _player_intentions;
  818.         if (player) {    // player created on the client?
  819.             player._FORCE_X = force.X;
  820.             player._FORCE_Y = force.Y;
  821.             player._FORCE_Z = force.Z;
  822.             player._AFORCE_PAN = aforce.PAN;
  823.             player._AFORCE_TILT = aforce.TILT;
  824.             player._AFORCE_ROLL = aforce.ROLL;
  825. // send forces to server
  826.             SEND player._FORCE_X;
  827.             SEND player._FORCE_Y;
  828.             SEND player._FORCE_Z;
  829.             SEND player._AFORCE_PAN;
  830.             SEND player._AFORCE_TILT;
  831.             SEND player._AFORCE_ROLL;
  832. // move the camera
  833.             CALL move_view;
  834.         }
  835.         WAIT 1;
  836.     }
  837. ENDIF;
  838.     RETURN;
  839. }
  840.  
  841. /////////////////////////////////////////////////////////////////////
  842. ACTION toggle_person {
  843.     IF (person_3rd > 0) {
  844.         person_3rd = 0;
  845.     } ELSE {
  846.         person_3rd = 0.5;
  847.     }
  848. }
  849.  
  850. /////////////////////////////////////////////////////////////////////
  851. // Auxiliary actions
  852.  
  853. ACTION scan_floor
  854. {
  855.     SONAR    ME,4000;
  856.     my_floornormal.X = NORMAL.X;
  857.     my_floornormal.Y = NORMAL.Y;
  858.     my_floornormal.Z = NORMAL.Z;
  859.     my_height = RESULT;
  860.  
  861.     my_floorspeed.X = 0;
  862.     my_floorspeed.Y = 0;
  863. // if the player is standing on a platform, move him with it
  864.     IF (YOU != NULL) {
  865.         IF (YOUR._TYPE == _TYPE_ELEVATOR) {
  866.         _shot_no += 1;        //$$$
  867.             my_floorspeed.X = YOUR._SPEED_X;
  868.             my_floorspeed.Y = YOUR._SPEED_Y;
  869. // Z speed is not necessary - this is done by the height adaption
  870.         }
  871.     }
  872. }
  873.  
  874. // Calculate a position directly ahead of the camera
  875. // Input:  p (distance)
  876. // Output: MY_POS
  877. ACTION set_pos_ahead
  878. {
  879.     temp.X = COS(CAMERA.PAN);
  880.     temp.Y = SIN(CAMERA.PAN);
  881.     temp.Z = p*COS(CAMERA.TILT);
  882.     MY_POS.X = CAMERA.X + temp.Z*temp.X;
  883.     MY_POS.Y = CAMERA.Y + temp.Z*temp.Y;
  884.     MY_POS.Z = CAMERA.Z + p*SIN(CAMERA.TILT);
  885. }
  886.  
  887. ////////////////////////////////////////////////////////////////////////
  888. // event action to indicate any event by resetting the event flag
  889. ACTION _setback {
  890.     IF (EVENT_TYPE == EVENT_BLOCK) { SET MY.ENABLE_BLOCK,OFF; }
  891.     IF (EVENT_TYPE == EVENT_ENTITY) { SET MY.ENABLE_ENTITY,OFF; }
  892.     IF (EVENT_TYPE == EVENT_STUCK) { SET MY.ENABLE_STUCK,OFF; }
  893.  
  894.     IF (EVENT_TYPE == EVENT_PUSH) { SET MY.ENABLE_PUSH,OFF; }
  895.     IF (EVENT_TYPE == EVENT_IMPACT) { SET MY.ENABLE_IMPACT,OFF; }
  896.  
  897.     IF (EVENT_TYPE == EVENT_DETECT) { SET MY.ENABLE_DETECT,OFF; }
  898.     IF (EVENT_TYPE == EVENT_SCAN) { SET MY.ENABLE_SCAN,OFF; }
  899.     IF (EVENT_TYPE == EVENT_SHOOT) { SET MY.ENABLE_SHOOT,OFF; }
  900.     IF (EVENT_TYPE == EVENT_TRIGGER) { SET MY.ENABLE_TRIGGER,OFF; }
  901.  
  902.     IF (EVENT_TYPE == EVENT_TOUCH) { SET MY.ENABLE_TOUCH,OFF; }
  903.     IF (EVENT_TYPE == EVENT_RELEASE) { SET MY.ENABLE_RELEASE,OFF; }
  904.     IF (EVENT_TYPE == EVENT_CLICK) { SET MY.ENABLE_CLICK,OFF; }
  905. }
  906.  
  907. ACTION _beep { BEEP; }
  908.  
  909. ////////////////////////////////////////////////////////////////////////
  910. // Handle action. Set to SPACE by default.
  911. // Will operate doors or items within 200 quants.
  912. SKILL indicator { VAL 0; }
  913.  
  914. DEFINE _HANDLE,1;        // SCAN via space key
  915. DEFINE _EXPLODE,2;    // SCAN by an explosion
  916. DEFINE _GUNFIRE,3;    // SHOOT fired by a gun
  917. DEFINE _WATCH,4;        // looking for an enemy
  918. DEFINE _DETECTED,5;    // detected by an enemy
  919. DEFINE _SHOOT1,6;        // shoot key pressed (not used yet)
  920.  
  921. ACTION handle
  922. {
  923.     IF (player != NULL) {
  924.         MY_POS.X = player.X;
  925.         MY_POS.Y = player.Y;
  926.         MY_POS.Z = player.Z;
  927.         MY_ANGLE.PAN = player.PAN;
  928.     } ELSE {
  929.         MY_POS.X = CAMERA.X;
  930.         MY_POS.Y = CAMERA.Y;
  931.         MY_POS.Z = CAMERA.Z;
  932.         MY_ANGLE.PAN = CAMERA.PAN;
  933.     }
  934.     MY_ANGLE.TILT = CAMERA.TILT;
  935.     CALL scan_handle;
  936. }
  937.  
  938. // scan a wide cone of 200 quants range
  939. ACTION scan_handle
  940. {
  941.     temp.PAN = 120;
  942.     temp.TILT = 180;
  943.     temp.Z = 200;
  944.     indicator = _HANDLE;
  945.     SCAN    MY_POS,MY_ANGLE,temp;
  946. }
  947.  
  948.  
  949. // This action can be run by a player entity on the server
  950. // It checks for receiving a handle signal, then performs a scan
  951. ACTION perform_handle
  952. {
  953. IFDEF ACKNEX_VERSION414;
  954.     WHILE (1) {
  955.         IF (MY._SIGNAL == _HANDLE) {    // client has pressed handle key
  956.             SET MY.HIDDEN,ON;
  957.             MY._SIGNAL = 0;                // reset it
  958.             MY_POS.X = MY.X;
  959.             MY_POS.Y = MY.Y;
  960.             MY_POS.Z = MY.Z;
  961.             MY_ANGLE.PAN = MY.PAN;
  962.             MY_ANGLE.TILT = MY.TILT;
  963.             CALL scan_handle;
  964.         }
  965.         WAIT 1;
  966.     }
  967. ENDIF;
  968.     RETURN;
  969. }
  970.  
  971. ACTION send_handle
  972. {
  973. IFDEF ACKNEX_VERSION414;
  974.     IF (player != NULL) {
  975.         player._SIGNAL = _HANDLE;    // send command to perform a scan
  976.         SEND player._SIGNAL;
  977.     }
  978. IFELSE;
  979.     BRANCH handle;
  980. ENDIF;
  981. }
  982. /////////////////////////////////////////////////////////////////////
  983. ON_F7 toggle_person;
  984.  
  985. ON_SPACE send_handle;
  986.  
  987. /////////////////////////////////////////////////////////////////////