// Template file v4.202 //////////////////////////////////////////////////////////////////////// // File: movement.wdl // WDL prefabs for entity movement //////////////////////////////////////////////////////////////////////// // Mod Date: 6/5/00 // Added code to handle new animation // playerP1 can now stand, walk, run, DUCKP1, JUMPP1, crawl, swim, and wade // // Mod Date: 6/8/00 // Converted code to 4.187 format (removed SETs and CALLs) // // Mod Date: 6/19/00 // Added __FALLP1 (FLAG1) and _FALLTIMEP1 (SKILL31) // If __FALLP1 is ON, playerP1 takes damage from FALLP1s // _FALLTIMEP1 contains the amount of time spent FALLP1ing (calculated in move_gravityP1) // // Mod Date: 7/18/00 // Changed slope gravityP1 (added var 'slopefacP1') // // Mod Date: 7/19/00 // Added code to adjust my_heightP1 while DUCKINGP1 and CRAWLINGP1 // - Add var 'DUCKP1_heightP1' // - modified var 'eye_height_DUCKP1' to equal 'eye_height_upP1' // // Mod Date: 7/28/00 // Added __DUCKP1 flag as flag #8 (replaces __SOUND flag) // playerP1 can only DUCKP1 if the __DUCKP1 flag is set to ON // // Mod Date: 8/28/00 DCP // Removed Actions 'playerP1_heli' and 'playerP1_fly' (experimental code) // Added MODEs _MODE_PLANEP1 & _MODE_CHOPPERP1 // Expanded VAR 'camera_distP1' & 'temp_cdistP1' into vectors (X,Y,Z fields) // Modified 'move_view_3rdP1' FUNCTION to take advantage of 'camera_distP1' vector // Replaced min with max (to eliminate 'creep') in 'gravityP1' functions // // Mod Date: 8/31/00 DCP // Added movement_scaleP1 and actor_scaleP1 to scale movement and models (to make world appear larger or smaller) // Modified "swim_gravityP1" to scale distP1 and absdistP1 by movement_scaleP1 before MOVE // Modified "wade_gravityP1" to scale distP1 and absdistP1 by movement_scaleP1 before MOVE // Modified "move_gravityP1" to scale distP1 and absdistP1 by movement_scaleP1 before MOVE // Modified function "anim_initP1" to use actor_scaleP1 to scale the entity that calls it. // Modified 'walk_or_runP1' by 'movement_scaleP1' in function "actor_animP1" // // Mod Date: 9/2/00 DCP // Modified 'move_view_3rdP1' to set camera_distP1.Z to playerP1.MAX_Z if zero //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// // 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,; SOUND robo_thud,; SOUND splash,; DEFINE shadowsprite,; DEFINE shadowflat,; 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 VAR movement_scaleP1 = 1.00; // used to scale the movement VAR actor_scaleP1 = 1.00; // used to scale the size of actors // NOTE: in most cases it is a good idea to make actor_scaleP1 == movement_scaleP1 VAR gnd_fricP1 = 0.5; // ground frictionP1 VAR air_fricP1 = 0.03; // air frictionP1 VAR water_fricP1 = 0.75; // water frictionP1 VAR ang_fricP1 = 0.6; // angular frictionP1 VAR gravityP1 = 6; // gravityP1 FORCEP1 VAR elasticity = 0.1; // of the floor var strengthP1[3] = 5,4,75; // default ahead, side, JUMPP1 strengthP1 (25) var astrengthP1[3] = 7,5,2; // default pan, tilt, roll strengthP1 var slopefacP1 = 2; // gravityP1 on SLOPESP1, determines the max angle to climb VAR eye_height_upP1 = 0.8; // eye position factor for WALKINGP1, DRIVINGP1 VAR eye_height_downP1 = 0.7; // for SWIMMINGP1 VAR eye_height_DUCKP1 = 0.8; //0.3; // for DUCKINGP1 (7/19/00: same as eye_height_upP1 since DUCKINGP1 is controlled by my_heightP1) VAR walk_rateP1 = 3; // for head wave, 360 / step width VAR wave_rateP1 = 25; // same for SWIMMINGP1, 360 / wave time VAR walk_amplP1 = 4; // WALKINGP1 head wave amplitude VAR wave_amplP1 = 2; // SWIMMINGP1 head wave amplitude VAR anim_ATTACKP1_ticksP1 = 16;// time for one ATTACKP1 animation cycle VAR anim_stand_ticksP1 = 16; // time for one standing anim cycle VAR anim_jump_ticks = 6; // time for one JUMPP1 animation cycle VAR anim_DUCKP1_ticksP1 = 8; // time for one DUCKP1 animation cycle VAR anim_walk_distP1 = 1; // distP1 per model width per walk cycle VAR anim_run_distP1 = 1.5; // distP1 per model width per run cycle VAR anim_crawl_distP1 = 0.8; // distP1 per model width per crawl cycle VAR anim_wade_distP1 = 0.8; // distP1 per model width per crawl cycle VAR anim_swim_distP1 = 1; // distP1 per model width per swim cycle VAR person_3rdP1 = 0; // 0: 1st person mode; 0.5: 3rd person mode //VAR camera_distP1 = 90; // camera distance to entity in 3rd person view VAR camera_distP1[3] = 90,0,0; // camera distance to entity in 3rd person view VAR mouseviewP1 = 1; // mouse factor, set 0 to disable mouse VAR client_moving = 0; // multiplayerP1 mode VAR JUMP_heightP1 = 50; // maximum JUMPP1 height above ground var FALL_timeP1 = 6; // max FALLP1 time before HEALTHP1 is reduced VAR DUCKP1_heightP1 = 25; // distance to adjust my_heightP1 while DUCKINGP1 VAR walk_or_runP1 = 12; // max quants per tick to switch from walk to run animation VAR POWERP1_maxP1 = 1; // maximum engine POWERP1 for aircraft // strings for defining the animation frames STRING anim_stand_strP1,"stand"; STRING anim_walk_strP1,"walk"; STRING anim_run_strP1,"run"; STRING anim_DUCKP1_strP1,"DUCKP1"; STRING anim_swim_strP1,"swim"; STRING anim_dive_strP1,"dive"; STRING anim_JUMP_str,"JUMPP1"; STRING anim_crawl_strP1,"crawl"; STRING anim_wade_strP1,"wade"; // string synonyms for defining the animation frames (and their default values) STRING anim_default_death_strP1,"death"; STRING anim_default_ATTACKP1_strP1,"ATTACKP1"; SYNONYM anim_ATTACKP1_strP1 { TYPE STRING; DEFAULT anim_default_ATTACKP1_strP1;} SYNONYM anim_death_strP1 { TYPE STRING; DEFAULT anim_default_death_strP1;} /////////////////////////////////////////////////////////////////////// // Entity skill & flag definitions // some definitions here are also needed for ACTORS.WDL and WAR.WDL DEFINE _WALKFRAMESP1,SKILL1; // non-zero for old style animation DEFINE _RUNFRAMESP1,SKILL2; DEFINE _ATTACKFRAMESP1,SKILL3; DEFINE _DIEFRAMESP1,SKILL4; DEFINE _FORCEP1,SKILL5; // determines SPEEDP1 DEFINE _ENTFORCEP1,SKILL5; DEFINE _BANKINGP1,SKILL6; // BANKINGP1 - for playerP1 only DEFINE _PENDOLINOP1,SKILL6; // BANKINGP1 - for playerP1 only DEFINE _HITMODEP1,SKILL6; // for actors DEFINE _MOVEMODEP1,SKILL7; DEFINE _FIREMODEP1,SKILL8; // for actors DEFINE __FALLP1,FLAG1; // take damage from FALLP1s DEFINE __WHEELSP1,FLAG2; // block turns without moving DEFINE __SLOPESP1,FLAG3; // adapt the tilt and roll angle to SLOPESP1 DEFINE __JUMPP1,FLAG4; // be able to JUMPP1 DEFINE __BOBP1,FLAG5; // head wave DEFINE __STRAFEP1,FLAG6; // be able to move sidewards DEFINE __TRIGGER,FLAG7; // be able to TRIGGER doors automatically DEFINE __DUCKP1, FLAG8; // be able to DUCKP1 DEFINE __SOUND,FLAG8; // internal flag /////////////////////////////////////////////////////////////////////// DEFINE _HEALTHP1,SKILL9; DEFINE _ARMORP1,SKILL10; DEFINE _SPEEDP1,SKILL11; // SPEEDP1 DEFINE _SPEEDP1_X,SKILL11; DEFINE _SPEEDP1_Y,SKILL12; DEFINE _POWERP1,SKILL12; // engine POWERP1 for aircraft models DEFINE _SPEEDP1_Z,SKILL13; DEFINE _ASPEEDP1,SKILL14; // angular SPEEDP1 DEFINE _ASPEEDP1_PAN,SKILL14; DEFINE _ASPEEDP1_TILT,SKILL15; DEFINE _ASPEEDP1_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 playerP1 entities DEFINE _FORCEP1_X,SKILL17; DEFINE _FORCEP1_Y,SKILL18; DEFINE _FORCEP1_Z,SKILL19; DEFINE _AFORCEP1_PAN,SKILL20; DEFINE _AFORCEP1_TILT,SKILL21; DEFINE _AFORCEP1_ROLL,SKILL22; DEFINE _WALKSOUND,SKILL23; // WALKINGP1 SOUND DEFINE _SIGNALP1,SKILL24; // communication for actions or client->server DEFINE _COUNTERP1,SKILL25; // internal COUNTERP1 DEFINE _STATEP1,SKILL26; // the STATEP1 it is in (walk, ATTACKP1, escape etc.) DEFINE _WALKDISTP1,SKILL27; // distance per walk cycle DEFINE _RUNDISTP1,SKILL28; // distance per run cycle DEFINE _ANIMDISTP1,SKILL28; // time for standing, JUMPINGP1, and DUCKINGP1 animations DEFINE _TYPE,SKILL30; // the type of the entity - door, key, etc. DEFINE _FALLTIMEP1,SKILL31; // amount of time spent FALLP1ing // Skills up to 32 are reserved for future template actions // Skills 33-40 can be used freely /////////////////////////////////////////////////////////////////////// // Mod Date: 7/4/00 DCP // Changed SPEEDP1 -> camera_SPEEDP1 // aSPEEDP1-> camera_aSPEEDP1 VAR camera_SPEEDP1[3] = 0,0,0; // cartesian SPEEDP1, entity coordinates VAR camera_aSPEEDP1[3]; // angular SPEEDP1 VAR FORCEP1[3]; // cartesian FORCEP1, entity coordinates VAR absFORCEP1[3]; // cartesian FORCEP1, world coordinates VAR aFORCEP1[3]; // angular FORCEP1 VAR abSPEEDP1[3] = 0,0,0; // cartesian SPEEDP1, world coordinates var distP1[3]; var absdistP1[3]; // distances used for MOVE VAR pP1[3]; VAR frictionP1; VAR limitP1[3]; VAR covered_distP1; VAR anim_distP1; var head_angleP1[3] = 0,0,0; // separated from other values VAR headwaveP1 = 0; VAR walkwaveP1 = 0; VAR my_distP1; // distance for actor anim VAR player_distP1; // distance for head BOBP1bing VAR scan_sectorP1; VAR my_heightP1; VAR my_floornormalP1[3]; VAR my_floorSPEEDP1[3]; VAR temp_cdistP1[3] = 120,0,0; // current camera distance in 3rd pP1 view //-VAR debugskill; VAR current_fog_index = 0; // the current fog color index????????????????????????????????? SYNONYM playerP1 { TYPE ENTITY; } SYNONYM temp_entP1 { TYPE ENTITY; } SYNONYM carryP1 { TYPE ACTION; } SYNONYM anim_strP1 { TYPE STRING; } DEFINE _MODE_WALKINGP1,1; DEFINE _MODE_DRIVINGP1,2; DEFINE _MODE_SWIMMINGP1,3; DEFINE _MODE_DIVINGP1,4; DEFINE _MODE_WADINGP1,5; DEFINE _MODE_HELICOPTERP1,6; // very primitive HELICOPTERP1 mode DEFINE _MODE_ROCKETEERP1,7; DEFINE _MODE_DUCKINGP1,8; // DUCKINGP1 DEFINE _MODE_JUMPINGP1,9; // JUMPINGP1 DEFINE _MODE_CRAWLINGP1,10; // CRAWLINGP1 DEFINE _MODE_STILLP1,15; DEFINE _MODE_PLANEP1,16; DEFINE _MODE_CHOPPERP1,17; // modes 20 and above are handled by a different wdl DEFINE _MODE_ATTACKP1,20; DEFINE _SOUND_WALKER,1;//?????????????????????????????????????????????????? DEFINE _SOUND_ROBOT,2;//?????????????????????????????????????????????????? DEFINE _TYPE_playerP1,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_ARMORP1,22; DEFINE _TYPE_HEALTHP1,23; DEFINE _FOG_UNDERWATER,2; // fog color 2 is used for underwater fog /////////////////////////////////////////////////////////////////////// //-DEFINE RETURN,END; // I prefer RETURN to END SOUND beep_SOUND,; //SYNONYM debugsyn { TYPE ENTITY; } /////////////////////////////////////////////////////////////////////// // Desc: playerP1 drive action // // Mod Date: 8/31/00 DCP // Scale the playerP1 by vec_scale ACTION player_driveP1 { MY._MOVEMODEP1 = _MODE_DRIVINGP1; MY._FORCEP1 = 1.5; MY._BANKINGP1 = 0.5; MY.__SLOPESP1 = ON; MY.__TRIGGER = ON; player_moveP1(); } // Desc: playerP1 walk action // // Mod Date: 8/31/00 DCP // Scale the playerP1 by vec_scale ACTION player_walkP1 { MY._MOVEMODEP1 = _MODE_WALKINGP1; MY._FORCEP1 = 0.75; MY._BANKINGP1 = -0.1; MY.__JUMPP1 = ON; MY.__DUCKP1 = ON; MY.__STRAFEP1 = ON; MY.__BOBP1 = ON; MY.__TRIGGER = ON; player_moveP1(); } // Desc: playerP1 swim action // ACTION player_swimP1 { MY._MOVEMODEP1 = _MODE_SWIMMINGP1; MY._FORCEP1 = 0.75; MY._BANKINGP1 = 0; MY.__JUMPP1 = ON; MY.__DUCKP1 = ON; MY.__STRAFEP1 = OFF; MY.__BOBP1 = ON; player_moveP1(); } /////////////////////////////////////////////////////////////////////// // Desc: Shakes the playerP1, used for hits and death function player_shakeP1() { 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; } } // Desc: playerP1 tips over, can be used for death function player_tipP1() { MY._MOVEMODEP1 = 0; // suspend normal movement action eye_height_upP1.Z = eye_height_upP1; // store original eye height WHILE (MY.ROLL < 80) { MY.ROLL += 8 * TIME; MY.TILT += 2 * TIME; IF (eye_height_upP1 > 0.15) { eye_height_upP1 -= 0.1 * TIME; } IF (client_moving==0) { move_view(); } WAIT 1; } MY.ROLL = 80; MY.TILT = 20; eye_height_upP1 = eye_height_upP1.Z; // restore original eye height } //////////////////////////////////////////////////////////////////////// // Desc: main playerP1 movement action // called from 'player_walkP1', 'player_driveP1', & 'player_swimP1' // // Mod Date: 5/10/00 @ 973 Doug Poston // Added code to handle SWIMMINGP1 // Mod Date: 5/11/00 @ 097 Doug Poston // Added code to handle DUCKINGP1 and CRAWLINGP1 // Mod Date: 5/16/00 Doug Poston // Modified underwater fog code // Modified playerP1 MIN_Z (when getting in & out of water) // Fixed so you can no longer crawl over water // Mod Date: 5/16/00 Doug Poston // Returned fog control back to the camera views // Mod Date: 5/18/00 Doug Poston // Removed MIN_Z modifications (too easy to get stuck in objects) // Mod Date: 5/25/00 Doug Poston // Using an 'offset sonar' (7 units) while SWIMMINGP1 to check if // the playerP1 is ON_PASSABLE // Mod Date: 5/29/00 Doug Poston // Change 'offset sonar' from 7 to 16 units // Mod Date: 6/5/00 Doug Poston // Removed Sets // Mod Date: 6/27/00 Doug Poston // Replaced ACCEL // Mod Date: 6/29/00 Doug Poston // Remove IN_PASSABLE check for WADINGP1 (fixed in v4.193) ACTION player_moveP1 { IF (MY.CLIENT == 0) { playerP1 = ME; } // created on the server? MY._TYPE = _TYPE_playerP1; MY.ENABLE_SCAN = ON; // so that enemies can detect me IF ((MY.TRIGGER_RANGE == 0) && (MY.__TRIGGER == ON)) { MY.TRIGGER_RANGE = 32; } IF (MY._FORCEP1 == 0) { MY._FORCEP1 = 1.5; } IF (MY._MOVEMODEP1 == 0) { MY._MOVEMODEP1 = _MODE_WALKINGP1; } IF (MY._WALKFRAMESP1 == 0) { MY._WALKFRAMESP1 = DEFAULT_WALK; } IF (MY._RUNFRAMESP1 == 0) { MY._RUNFRAMESP1 = DEFAULT_RUN; } IF (MY._WALKSOUND == 0) { MY._WALKSOUND = _SOUND_WALKER; } anim_initP1(); // init old style animation perform_handleP1(); // react on pressing the handle key // while we are in a valid MOVEMODEP1 WHILE ((MY._MOVEMODEP1 > 0)&&(MY._MOVEMODEP1 <= _MODE_STILLP1)) { // if we are not in 'STILLP1' mode IF (MY._MOVEMODEP1 != _MODE_STILLP1) { // Get the angular and translation FORCEP1s (set aFORCEP1 & FORCEP1 values) _player_FORCEP1(); // find ground below (set my_heightP1, my_floornormalP1, & my_floorSPEEDP1) scan_floorP1(); // if they are on or in a passable block... IF ( ((my_heightP1 < 5) && (ON_PASSABLE != 0)) || (IN_PASSABLE != 0) ) { // if not already SWIMMINGP1 or WADINGP1... IF ((MY._MOVEMODEP1 != _MODE_SWIMMINGP1) && (MY._MOVEMODEP1 != _MODE_WADINGP1)) { PLAY_SOUND splash,50; MY._MOVEMODEP1 = _MODE_SWIMMINGP1; } // if SWIMMINGP1... IF (MY._MOVEMODEP1 == _MODE_SWIMMINGP1) // SWIMMINGP1 on/in a passable block { IF (ON_PASSABLE == ON) // && (IN_PASSABLE != ON)) -> Not need with version 4.193+ { // check for WADINGP1 temp.X = MY.X; temp.Y = MY.Y; temp.Z = MY.Z + MY.MIN_Z; // can my feet touch? SHOOT MY.POS,temp; // NOTE: SHOOT ignores passable blocks IF (RESULT > 0) { // switch to WADINGP1 MY._MOVEMODEP1 = _MODE_WADINGP1; MY.TILT = 0; // stop tilting my_heightP1 = RESULT + MY.MIN_Z; // calculate WADINGP1 height } // check for edge (for 'JUMPINGP1' out of water) // +++This code can be added here+++ } }// END SWIMMINGP1 on/in a passable block // if WADINGP1... IF (MY._MOVEMODEP1 == _MODE_WADINGP1) // WADINGP1 on/in a passable block { // check for SWIMMINGP1 temp.X = MY.X; temp.Y = MY.Y; temp.Z = MY.Z + MY.MIN_Z; // can my feet touch? SHOOT MY.POS,temp; // NOTE: ignore passable blocks IF (RESULT == 0) { // switch to SWIMMINGP1 MY._MOVEMODEP1 = _MODE_SWIMMINGP1; } ELSE // use SOLID surface for height (can't walk on water) { my_heightP1 = RESULT + MY.MIN_Z; // calculate WADINGP1 height } } // END WADINGP1 on/in a passable block } // END if they are on or in a passable block... ELSE // not in or on a passable block { // if WADINGP1 or SWIMMINGP1 while *not* on/in a passable block... IF ((MY._MOVEMODEP1 == _MODE_SWIMMINGP1) || (MY._MOVEMODEP1 == _MODE_WADINGP1)) { // get out of the water (go to walk mode) MY._MOVEMODEP1 = _MODE_WALKINGP1; MY.TILT = 0; // stop tilting } } // END not in or above water // if he is on a slope, change his angles, and maybe let him slide down IF (MY.__SLOPESP1 == ON) { // Adapt the playerP1 angle to the floor slope MY_ANGLE.TILT = 0; MY_ANGLE.ROLL = 0; IF ((my_heightP1 < 10) && ((my_floornormalP1.X != 0) || (my_floornormalP1.Y != 0) )) { // on a slope? // rotate the floor normal relative to the playerP1 MY_ANGLE.PAN = -MY.PAN; VECROTATE my_floornormalP1,MY_ANGLE; // calculate the destination tilt and roll angles MY_ANGLE.TILT = -ASIN(my_floornormalP1.X); MY_ANGLE.ROLL = -ASIN(my_floornormalP1.Y); } // change the playerP1 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 FORCEP1 to set the angle back //jcl 07-08-00 fix loopings on < 3 fps systems MY.ROLL -= 0.2*ANG(MY.ROLL); } // Now accelerate the angular SPEEDP1, and change his angles // -old method- ACCEL MY._ASPEEDP1,aFORCEP1,ang_fricP1; temp = min(TIME*ang_fricP1,1); MY._ASPEEDP1_PAN += (TIME * aFORCEP1.pan) - (temp * MY._ASPEEDP1_PAN); MY._ASPEEDP1_TILT += (TIME * aFORCEP1.tilt) - (temp * MY._ASPEEDP1_TILT); MY._ASPEEDP1_ROLL += (TIME * aFORCEP1.roll) - (temp * MY._ASPEEDP1_ROLL); temp = MY._ASPEEDP1_PAN * MY._SPEEDP1_X * 0.05; IF (MY.__WHEELSP1) { // Turn only if moving ahead //jcl 07-03-00 patch to fix movement MY.PAN += temp * TIME; } ELSE { MY.PAN += MY._ASPEEDP1_PAN * TIME; } MY.ROLL += (temp * MY._BANKINGP1 + MY._ASPEEDP1_ROLL) * TIME; // the head angle is only set on the playerP1 in a single playerP1 system. if (ME == playerP1) { head_angleP1.TILT += MY._ASPEEDP1_TILT * TIME; //jcl 07-03-00 end of patcht // limitP1 the TILT value head_angleP1.TILT = ANG(head_angleP1.TILT); IF (head_angleP1.TILT > 80) { head_angleP1.TILT = 80; } IF (head_angleP1.TILT < -80) { head_angleP1.TILT = -80; } } // disable strafing IF (MY.__STRAFEP1 == OFF) { FORCEP1.Y = 0; // no STRAFEP1 } // if SWIMMINGP1... IF (MY._MOVEMODEP1 == _MODE_SWIMMINGP1) { // move in water swim_gravityP1(); } ELSE // not SWIMMINGP1 { // if WADINGP1... IF (MY._MOVEMODEP1 == _MODE_WADINGP1) { wade_gravityP1(); } ELSE // not SWIMMINGP1 or WADINGP1 (not in water) { // DUCKINGP1 or CRAWLINGP1... IF ((MY._MOVEMODEP1 == _MODE_DUCKINGP1) || (MY._MOVEMODEP1 == _MODE_CRAWLINGP1)) { IF (FORCEP1.Z >= 0) { MY._MOVEMODEP1 = _MODE_WALKINGP1; } ELSE // STILLP1 DUCKINGP1 { // reduce height by DUCKINGP1 value my_heightP1 += DUCKP1_heightP1; } } ELSE // not DUCKINGP1 or CRAWLINGP1 { // if we have a DUCKINGP1 FORCEP1 and are not already DUCKINGP1 or CRAWLINGP1... IF ((FORCEP1.Z < 0) && (MY.__DUCKP1 == ON)) // dcp 7/28/00 added __DUCKP1 { // ...switch to DUCKINGP1 mode MY._MOVEMODEP1 = _MODE_DUCKINGP1; MY._ANIMDISTP1 = 0; FORCEP1.Z = 0; } } // Decide whether the actor can JUMPP1 or not. He can't if he is in the air IF ((JUMP_heightP1 <= 0) || (MY.__JUMPP1 == OFF) || (my_heightP1 > 4) || (FORCEP1.Z <= 0)) { FORCEP1.Z = 0; } // move on land move_gravityP1(); } // END (not in water) }// END not SWIMMINGP1 } // END not in 'STILLP1' mode // animate the actor actor_animP1(); // If I'm the only playerP1, draw the camera and weapon with ME IF (client_moving == 0) { move_view(); } carryP1(); // action synonym used to carryP1 items with the playerP1 (eg. a gun or sword) // Wait one tick, then repeat WAIT 1; } // END WHILE ((MY._MOVEMODEP1 > 0)&&(MY._MOVEMODEP1 <= _MODE_STILLP1)) } // Desc: This is the main movement action for the camera // // Mod Date: 6/27/00 Doug Poston // Replaced ACCEL (x2) // Mod Date: 7/3/00 Doug Poston // Added time correction to CAMERA.PAN,.TILT, & .ROLL // Mode Date: 7/4/00 Doug Poston // Switched generic SPEEDP1 and aSPEEDP1 to camera_SPEEDP1 and camera_aSPEEDP1 // Movement is now time corrected ACTION camera_moveP1//??????????????????????????????????????????????????????????? { _camera = 1; WHILE (_camera == 1) { _playerP1_intentions(); // set FORCEP1 and aFORCEP1 value from user input // -old method- ACCEL aSPEEDP1,aFORCEP1,0.9; camera_aSPEEDP1.pan += (TIME * aFORCEP1.pan) - (0.9 * camera_aSPEEDP1.pan); camera_aSPEEDP1.tilt += (TIME * aFORCEP1.tilt) - (0.9 * camera_aSPEEDP1.tilt); camera_aSPEEDP1.roll += (TIME * aFORCEP1.roll) - (0.9 * camera_aSPEEDP1.roll); CAMERA.PAN += camera_aSPEEDP1.PAN * TIME; CAMERA.TILT += camera_aSPEEDP1.TILT * TIME; CAMERA.ROLL += camera_aSPEEDP1.ROLL * TIME; // Calculate camera's new SPEEDP1 // -old method- ACCEL SPEEDP1,FORCEP1,0.9; camera_SPEEDP1.x += (TIME * FORCEP1.x) - (0.9 * camera_SPEEDP1.x); camera_SPEEDP1.y += (TIME * FORCEP1.y) - (0.9 * camera_SPEEDP1.y); camera_SPEEDP1.z += (TIME * FORCEP1.z) - (0.9 * camera_SPEEDP1.z); // calculate relative distance distP1.x = camera_SPEEDP1.x * TIME; distP1.y = camera_SPEEDP1.y * TIME; distP1.z = camera_SPEEDP1.z * TIME; move_view CAMERA,distP1,NULLSKILL; WAIT 1; } } ///////////////////////////////////////////////////////////////////// // Core part of move action, common for actors and playerP1s function move_airborne() { MY._POWERP1 += 0.1*FORCEP1.Z; IF (MY._POWERP1 < 0) { MY._POWERP1 = 0; } IF (MY._POWERP1 > POWERP1_maxP1) { MY._POWERP1 = POWERP1_maxP1; } absFORCEP1.X = 0; absFORCEP1.Y = 0; absFORCEP1.Z = 0; frictionP1 = air_fricP1; FORCEP1.X = 0; FORCEP1.Y = 0; FORCEP1.Z = 0; } function anim_airborne() { // standing animation IF (MY._POWERP1 > 0) // engine running { MY._ANIMDISTP1 += TIME * MY._POWERP1; // wrap animation time to a value between zero and anim_stand_ticksP1 IF (MY._ANIMDISTP1 > anim_stand_ticksP1) { MY._ANIMDISTP1 -= anim_stand_ticksP1; } // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP1 / anim_stand_ticksP1; // set the frame from the percentage SET_CYCLE ME,anim_stand_strP1,temp; RETURN; } RETURN; } //////////////////////////////////////////////////////////////////////// // Desc: gravityP1 / buoyancy effect on the playerP1 in water (IN_PASSABLE) // this action should be called when the playerP1 is SWIMMINGP1 (_MODE_SWIMMINGP1) // // Created: 05/9/00 @ 863 by Doug Poston // // Mod Date: 5/10/00 @ 913 by Doug Poston // Added code to TILT the playerP1 (allowing them to dive and rise in water) // Mod Date: 5/18/00 by Doug Poston // Added code to drop playerP1 to the surface of the water // Mod Data: 5/24/00 Doug Poston // Using an 'offset sonar' (7 units) to check if the playerP1 is ON_PASSABLE // Mod Date: 5/29/00 Doug Poston // Change 'offset sonar' from 7 to 16 units // Mod Date: 6/19/00 Doug Poston // Reset _FALLTIMEP1 (no FALLP1ing damage is you land in water) // Mod Date: 6/27/00 Doug Poston // Replaced ACCEL // Mod Date: 6/28/00 Doug Poston // Modified gravityP1 check to handle ON_PASSABLE while IN_PASSABLE // Mod Date: 6/29/00 Doug Poston // Remove IN_PASSABLE check while ON_PASSABLE (6/28/00 mod) (fixed in v4.193) // Mod Date: 7/3/00 Doug Poston // Fixed code so FORCEP1s are now completely TIME dependent // Mod Date: 7/22/00 JCL // Modified because of changes in scan_floorP1 // Mod Date: 8/31/00 DCP // Scale distP1 and absdistP1 by movement_scaleP1 before MOVE function swim_gravityP1() { frictionP1 = water_fricP1; // set frictionP1 to water frictionP1 MY._FALLTIMEP1 = 0; // no FALLP1ing damage in water // TILT the playerP1 if DIVINGP1 IF (FORCEP1.Z > 0) { MY.TILT += 3 * TIME; } IF (FORCEP1.Z < 0) { MY.TILT -= 3 * TIME; } MY.TILT = ANG (MY.TILT); // make sure angle stays between -180 and +180 /* NO absFORCEP1 needed in this swim_gravityP1 // reset absolute FORCEP1s absFORCEP1.X = 0; absFORCEP1.Y = 0; absFORCEP1.Z = 0; */ // SWIMMINGP1 - rhythmic acceleration FORCEP1.X *= 0.5 + (0.25*walkwaveP1); FORCEP1.Y *= 0.5; FORCEP1.Z = 0; // up and down handled by entity's tilt in water // accelerate the entity relative SPEEDP1 by the FORCEP1 // -old method- ACCEL MY._SPEEDP1_X,FORCEP1,frictionP1; /* temp = min(TIME*frictionP1,1); MY._SPEEDP1_X += (TIME * FORCEP1.x) - (temp * MY._SPEEDP1_X); // vx = ax*dt - min(f*dt,1) * vx MY._SPEEDP1_Y += (TIME * FORCEP1.y) - (temp * MY._SPEEDP1_Y); // vy = ay*dt - min(f*dt,1) * vy MY._SPEEDP1_Z += (TIME * FORCEP1.z) - (temp * MY._SPEEDP1_Z); // vz = az*dt - min(f*dt,1) * vz */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP1),0); MY._SPEEDP1_X = (TIME * FORCEP1.x) + (temp * MY._SPEEDP1_X); // vx = ax*dt - min(f*dt,1) * vx MY._SPEEDP1_Y = (TIME * FORCEP1.y) + (temp * MY._SPEEDP1_Y); // vy = ay*dt - min(f*dt,1) * vy MY._SPEEDP1_Z = (TIME * FORCEP1.z) + (temp * MY._SPEEDP1_Z); // vz = az*dt - min(f*dt,1) * vz // calculate relative distances distP1.x = MY._SPEEDP1_X * TIME; // dx = vx * dt distP1.y = MY._SPEEDP1_Y * TIME; // dy = vy * dt distP1.z = MY._SPEEDP1_Z * TIME; // dz = vz * dt // use a 16 unit 'offset buffer' to test if we are STILLP1 above the water // (SONAR) // MY.Z += 16; // SONAR MY,4000; // MY.Z -= 16; // on the surface (and not in another surface)... //jcl 07-22-00 scan_floorP1 changed IF ((ON_PASSABLE == ON) && (my_heightP1 > MY.MIN_Z)) //&& (IN_PASSABLE ==0)) -> check not need in v4.193+ { // reset absolute distance absdistP1.x = 0; absdistP1.y = 0; absdistP1.z = 0; // if MY center is greater than the surface level... IF (((my_heightP1 - MY.MIN_Z) > 5))//??16))) // 5 = "float value" { // pull down to the surface of the water temp = (my_heightP1 - MY.MIN_Z) - 5; // difference between surface IF (temp > gravityP1) { temp = gravityP1; } absdistP1.Z -= temp; } // restrict DRIVINGP1 and climbing motion on surface... IF (MY.TILT > 5) { MY.TILT = 5; // shallow climb } IF (MY.TILT < -45) { MY.TILT = -45; // shallow dive only from surface } // Now move ME by the relative and the absolute SPEEDP1 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP1,movement_scaleP1); // scale distance by movement_scaleP1 vec_scale(absdistP1,movement_scaleP1); // scale absolute distance by movement_scaleP1 MOVE ME,distP1,absdistP1; } ELSE // underwater { // NOTE: this is where we would add buoyancy (using absFORCEP1) // right now we are assuming zero buoyancy // NOTE: this is where we could add the effect of currents (using absFORCEP1) // Now move ME by the relative and the absolute SPEEDP1 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP1,movement_scaleP1); // scale distance by movement_scaleP1 MOVE ME,distP1,NULLSKILL; } // Store the distance covered, for animation my_distP1 = RESULT; // Store the distance for playerP1 1st person head BOBP1bing // (only for single playerP1 system) IF (ME == playerP1) { player_distP1 += MY._SPEEDP1_X;//SQRT(SPEEDP1.X*SPEEDP1.X + SPEEDP1.Y*SPEEDP1.Y); } } // Desc: WADINGP1 movement action // this action should be called when the playerP1 is WADINGP1 (_MODE_WADINGP1) // // Mod Date: 5/18/00 by Doug Poston // Created // Mod Date: 5/25/00 by Doug Poston // Adjusted ground elasticity (so it doesn't FORCEP1 playerP1 to swim) // Mod Date: 5/25/00 by Doug Poston // Adjust playerP1 FORCEP1 by water depth (slower the deeper the playerP1 is WADINGP1) // Mod Date: 5/29/00 Doug Poston // Change 'offset sonar' from 7 to 16 units // Mod Date: 6/19/00 Doug Poston // Reset _FALLTIMEP1 (no FALLP1ing damage is you land in water) // Mod Date: 6/27/00 Doug Poston // Replaced ACCEL (x2) // Mod Date: 7/3/00 Doug Poston // Fixed code so SPEEDP1 and distance are TIME dependent // Mod Date: 8/31/00 DCP // Scaled distP1 and absdistP1 by movement_scaleP1 before MOVE command function wade_gravityP1() { // basic frictionP1 frictionP1 = gnd_fricP1; MY._FALLTIMEP1 = 0; // reset FALLTIMEP1 (no FALLP1ing damage in water) //adjust playerP1 FORCEP1 depending on depth of water // MY.Z += 16; // SONAR MY,4000; // MY.Z -= 16; //jcl 07-22-00 scan_floorP1 changed temp = 1.0 - (my_heightP1 / min(-1,MY.MIN_Z)); // MY.min_z can be 0!! IF (temp < 0.1) // minimum SPEEDP1 { temp = 0.1; } FORCEP1.X *= temp; FORCEP1.Y *= temp; FORCEP1.Z *= temp; // reset absFORCEP1 absFORCEP1.X = 0; absFORCEP1.Y = 0; absFORCEP1.Z = 0; /* Old Method // If on a slope, apply gravityP1 to draw him downwards: IF (my_floornormalP1.Z < 0.85) { // FORCEP1 is less in water than on land absFORCEP1.X = my_floornormalP1.X * gravityP1 * 0.25; absFORCEP1.Y = my_floornormalP1.Y * gravityP1 * 0.25; // If slope too steep, really push him back temp = 0.66 - my_floornormalP1.Z; IF (temp > 0) { absFORCEP1.X *= 1.5; absFORCEP1.Y *= 1.5; } } */ // If on a slope, apply gravityP1 to draw him downwards: IF (my_floornormalP1.Z < 0.9) { // reduce ahead FORCEP1 because playerP1 FORCEP1 it is now deflected upwards FORCEP1.x *= my_floornormalP1.z; FORCEP1.y *= my_floornormalP1.z; // gravityP1 draws him down the slope (but only at 1/4 of above water) absFORCEP1.X = my_floornormalP1.x * gravityP1 * slopefacP1 * 0.25; absFORCEP1.Y = my_floornormalP1.y * gravityP1 * slopefacP1 * 0.25; } // -old method- ACCEL SPEEDP1,FORCEP1,frictionP1; /* temp = min(TIME*frictionP1,1); MY._SPEEDP1_X += (TIME * FORCEP1.x) - (temp * MY._SPEEDP1_X); // vx = ax*dt - min(f*dt, 1) * vx MY._SPEEDP1_Y += (TIME * FORCEP1.y) - (temp * MY._SPEEDP1_Y); // vy = ay*dt - min(f*dt, 1) * vy MY._SPEEDP1_Z += (TIME * absFORCEP1.z) - (temp * MY._SPEEDP1_Z); */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP1),0); MY._SPEEDP1_X = (TIME * FORCEP1.x) + (temp * MY._SPEEDP1_X); // vx = ax*dt + max(1-f*dt,0) * vx MY._SPEEDP1_Y = (TIME * FORCEP1.y) + (temp * MY._SPEEDP1_Y); // vy = ay*dt + max(1-f*dt,0) * vy MY._SPEEDP1_Z = (TIME * absFORCEP1.z) + (temp * MY._SPEEDP1_Z); // calculate relative distances distP1.x = MY._SPEEDP1_X * TIME; // dx = vx * dt distP1.y = MY._SPEEDP1_Y * TIME; // dy = vy * dt distP1.z = 0; // dz = 0 // calculate absolute distances absdistP1.x = absFORCEP1.x * TIME * TIME; // dx = ax * dt^2 absdistP1.y = absFORCEP1.y * TIME * TIME; // dy = ay * dt^2 absdistP1.z = 0; // NO JUMPINGP1 WHILE WADINGP1 // Add the SPEEDP1 given by the ground elasticity IF (my_heightP1 < -5) { temp = my_heightP1; IF (temp < -10) { temp = -10; } absdistP1.Z -= (temp - 5); } // Pull back down to the underwater surface // NOTE: this is taken care of by the playerP1 switching to SWIMMINGP1, then back to WADINGP1 // Now move ME by the relative and the absolute SPEEDP1 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP1,movement_scaleP1); // scale distance by movement_scaleP1 vec_scale(absdistP1,movement_scaleP1); // scale absolute distance by movement_scaleP1 MOVE ME,distP1,absdistP1; // Store the distance covered, for animation my_distP1 = RESULT; // Store the distance for playerP1 1st person head BOBP1bing // (only for single playerP1 system) IF (ME == playerP1) { player_distP1 = my_distP1; } } // Desc: calculate the damage taken by a FALLP1 // // Param: FALL_timeP1 and MY must be set before calling // // Note: override this function if you want to use a different formula function FALLP1_damage() { // calculate damage depending on _FALLTIMEP1 RETURN (10 + INT((MY._FALLTIMEP1 - FALL_timeP1) * 1.75)); } // Desc: on ground movement action // use when playerP1 is not SWIMMINGP1 or WADINGP1 // // Mod Date: 5/10/00 @ 942 by Doug Poston // Added code to switch to JUMPINGP1 mode when needed // Mod Date: 5/25/00 by Doug Poston // Split MOVE into two, so my_distP1 is now a function of playerP1 // movement only (ie. not effected by elevators or platforms) // Mod Date: 6/19/00 by Doug Poston // Added FALLP1ing damage. // _FALLTIMEP1 keeps track of the time spent FALLP1ing // if __FALLP1 is set, damage is taken when landing // Mod Date: 6/27/00 Doug Poston // Replace ACCEL (x2) // Mod Date: 7/3/00 JCL // quick patch to fix movement for Adeptus // Mod Date: 7/3/00 DCP // Modified code so SPEEDP1 and distance are TIME dependent // Mod Date: 7/18/00 DCP // Removed time dependence on FORCEP1s // Changed slope gravityP1 // Mod Date: 7/19/00 DCP // Changed JUMPINGP1 code so playerP1 always JUMPP1s to the same height // Mod Date: 8/10/00 JCL // Changed 'airborne' FORCEP1 values to prevent entities from 'sticking' // Mod Date: 8/10/00 JCL // "bring to ground level - only if slope not too steep" // Mod Date: 8/10/00 DCP // Replace FALLP1 damge formula with call to 'FALLP1_damage' // Mod Date: 8/31/00 DCP // Scale distP1 and absdistP1 by movement_scaleP1 before MOVE command function move_gravityP1() { // Filter the FORCEP1s and frictionP1s dependent on the STATEP1 of the actor, // and then apply them, and move him // First, decide whether the actor is standing on the floor or not IF (my_heightP1 < 5) { // Calculate FALLP1ing damage IF ((MY.__FALLP1 == ON) && (MY._FALLTIMEP1 > FALL_timeP1)) { MY._HEALTHP1 -= FALLP1_damage(); // take damage depending on FALL_timeP1 } MY._FALLTIMEP1 = 0; // reset FALLTIMEP1 frictionP1 = gnd_fricP1; IF (MY._MOVEMODEP1 == _MODE_DRIVINGP1) { // DRIVINGP1 - less frictionP1, less FORCEP1 frictionP1 *= 0.3; FORCEP1.X *= 0.3; } // reset absolute FORCEP1s absFORCEP1.X = 0; absFORCEP1.Y = 0; absFORCEP1.Z = 0; // If on a slope, apply gravityP1 to draw him downwards: IF (my_floornormalP1.Z < 0.9) { // reduce ahead FORCEP1 because playerP1 FORCEP1 it is now deflected upwards FORCEP1.x *= my_floornormalP1.z; FORCEP1.y *= my_floornormalP1.z; // gravityP1 draws him down the slope absFORCEP1.X = my_floornormalP1.x * gravityP1 * slopefacP1; absFORCEP1.Y = my_floornormalP1.y * gravityP1 * slopefacP1; } /* Old method IF (my_floornormalP1.Z < 0.85) { absFORCEP1.X = my_floornormalP1.X * gravityP1 * 2; absFORCEP1.Y = my_floornormalP1.Y * gravityP1 * 2; // If slope too steep, really push him back temp = 0.66 - my_floornormalP1.Z; IF (temp > 0) { absFORCEP1.X *= 3; absFORCEP1.Y *= 3; } } */ } ELSE // (my_heightP1 >= 5) { // airborne - reduce all relative FORCEP1s // to prevent him from JUMPINGP1 or further moving in the air frictionP1 = air_fricP1; //jcl 10-08-00 FORCEP1.X *= 0.2; // don't set the FORCEP1 completely to zero, otherwise FORCEP1.Y *= 0.2; // playerP1 could be stuck on top of a non-wmb entity FORCEP1.Z = 0; absFORCEP1.X = 0; absFORCEP1.Y = 0; // Add the world gravityP1 FORCEP1 absFORCEP1.Z = -gravityP1; // only FALLP1ing if moving downward IF (MY._SPEEDP1_Z <= 0) { MY._FALLTIMEP1 += TIME; // add FALLP1ing time } } // accelerate the entity relative SPEEDP1 by the FORCEP1 // -old method- ACCEL SPEEDP1,FORCEP1,frictionP1; /* temp = min(TIME*frictionP1,1); //_SPEEDP1_X,Y stores the relative XY SPEEDP1 MY._SPEEDP1_X += (TIME * FORCEP1.x) - (temp * MY._SPEEDP1_X); MY._SPEEDP1_Y += (TIME * FORCEP1.y) - (temp * MY._SPEEDP1_Y); //_SPEEDP1_Z stores the absolute Z SPEEDP1, accelerated by gravityP1 MY._SPEEDP1_Z += (TIME * absFORCEP1.z) - (temp * MY._SPEEDP1_Z); */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP1),0); MY._SPEEDP1_X = (TIME * FORCEP1.x) + (temp * MY._SPEEDP1_X); // vx = ax*dt + max(1-f*dt,0) * vx MY._SPEEDP1_Y = (TIME * FORCEP1.y) + (temp * MY._SPEEDP1_Y); // vy = ay*dt + max(1-f*dt,0) * vy MY._SPEEDP1_Z = (TIME * absFORCEP1.z) + (temp * MY._SPEEDP1_Z); // calculate relative distances to move distP1.x = MY._SPEEDP1_X * TIME; // dx = vx * dt distP1.y = MY._SPEEDP1_Y * TIME; // dy = vy * dt distP1.z = 0; // dz = 0 (only gravityP1 and JUMPINGP1) // calculate absolute distance to move absdistP1.x = absFORCEP1.x * TIME * TIME; // dx = ax*dt^2 absdistP1.y = absFORCEP1.y * TIME * TIME; // dy = ay*dt^2 absdistP1.z = MY._SPEEDP1_Z * TIME; // dz = vz*dt //jcl 07-22-00 // Add the SPEEDP1 given by the ground elasticity and the JUMPINGP1 FORCEP1 IF (my_heightP1 < 5) { // bring to ground level - only if slope not too steep //jcl 10-08-00 if (my_floornormalP1.Z > slopefacP1/4) { absdistP1.z = -max(my_heightP1,-10); } // if we have a JUMPINGP1 FORCEP1... if (FORCEP1.Z > 0) { // predict the initial SPEEDP1 required to reach the JUMPP1 height // v = a*t; s = a/2*t*t; -> v = sqrt(2*a*s) MY._SPEEDP1_Z = sqrt((JUMP_heightP1-my_heightP1)*2*gravityP1); absdistP1.z = MY._SPEEDP1_Z * TIME; // ...switch to JUMPINGP1 mode MY._MOVEMODEP1 = _MODE_JUMPINGP1; MY._ANIMDISTP1 = 0; } // If the actor is standing on a moving platform, add it's horizontal displacement absdistP1.X += my_floorSPEEDP1.X; absdistP1.Y += my_floorSPEEDP1.Y; } // Restrict the vertical distance to the maximum JUMPINGP1 height IF ((MY.__JUMPP1 == ON) && (absdistP1.z > 0) && (absdistP1.z + my_heightP1 > JUMP_heightP1)) { absdistP1.z = max(JUMP_heightP1 - my_heightP1,0); } // Now move ME by the relative and the absolute SPEEDP1 YOU = NULL; // YOU entity is considered passable by MOVE // NOTE: split move into two sections, so that movement from platforms does not effect move distance // (this is for animation reasons. ie. so model does not 'walk' on elevators) // MOVE ME,SPEEDP1,abSPEEDP1; vec_scale(distP1,movement_scaleP1); // scale distance by movement_scaleP1 MOVE ME,distP1,NULLVECTOR; // Store the distance covered, for animation my_distP1 = RESULT; vec_scale(absdistP1,movement_scaleP1); // scale absolute distance by movement_scaleP1 MOVE ME,NULLVECTOR,absdistP1; // Store the distance for playerP1 1st person head BOBP1bing // (only for single playerP1 system) IF (ME == playerP1) { player_distP1 += SQRT(distP1.X*distP1.X + distP1.Y*distP1.Y); } //jcl 07-03-00 end of patch } // Desc: set up for animation // scale entity by actor_scaleP1 // if using the "old style animation" // - split the integer and fractional parts of the animation // frame numbers, and store distance factors // // Mod Date: 8/31/00 DCP // Scale the playerP1 by vec_scale function anim_initP1() { vec_scale(MY.SCALE_X,actor_scaleP1); temp = FRC(MY._WALKFRAMESP1) * 1000; IF (temp != 0) { // old style animation MY._WALKFRAMESP1 = INT(MY._WALKFRAMESP1); IF (MY._WALKFRAMESP1 == 0) { MY._WALKFRAMESP1 = 13; } MY._WALKDISTP1 = MY._WALKFRAMESP1 / temp; temp = FRC(MY._RUNFRAMESP1) * 1000; MY._RUNFRAMESP1 = INT(MY._RUNFRAMESP1); IF (MY._RUNFRAMESP1 == 0) { MY._RUNFRAMESP1 = 5; } MY._RUNDISTP1 = MY._RUNFRAMESP1 / temp; } } // Desc: play some kinds of foot SOUND // // Mod Date: 6/9/00 Doug Poston // changed to function function _play_walkSOUND() { IF ((ME == playerP1) && (person_3rdP1 == 0)) { RETURN; } // don't play entity SOUNDs for 1st person playerP1 IF (MY._WALKSOUND == _SOUND_WALKER) { PLAY_ENTSOUND ME,thud,60; } IF (MY._WALKSOUND == _SOUND_ROBOT) { PLAY_ENTSOUND ME,robo_thud,60; } } //////////////////////////////////////////////////////////////////// // Desc: Main action to animate a WALKINGP1 actor, depending on distP1 // covered (my_distP1) // // Mod Date: 5/9/00 @ 812 Doug Poston // Added SWIMMINGP1 animation // Mod Date: 5/10/00 @ 970 Doug Poston // Added JUMPINGP1 animation // Mod Date: 5/11/00 @ 795 by Doug Poston // Added DUCKINGP1 and CRAWLINGP1 animations // Mod Date: 5/23/00 Doug Poston // Added code to check for backwards motion (using FORCEP1.X) // Mod Date: 6/23/00 Doug Poston // Added code for ATTACKP1 animations // Mod Date: 6/27/00 Doug Poston // Modified ATTACKP1 animation code to only work for playerP1 animation // Mod Date: 8/31/00 DCP // Modified walk_or_runP1 var by movement_scaleP1 function actor_animP1() { // decide whether it's a frame number (old) or frame name (new) animation IF (FRC(MY._WALKFRAMESP1) > 0) { goto old_style_anim; } // START NEW STYLE ANIMATIONS (frame names) // Check to see if playerP1 is ATTACKP1ing IF (( ME == playerP1) && (MY._FIREMODEP1 != 0)) { // if you have more than one ATTACKP1ing animation, here's where you would test for it... // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP1 / anim_ATTACKP1_ticksP1; // set the frame from the percentage SET_FRAME ME,anim_ATTACKP1_strP1,temp; // increment _ANIMDISTP1 by elapsed time MY._ANIMDISTP1 += TIME; // check to see if we finished the ATTACKP1 animation IF (MY._ANIMDISTP1 > anim_ATTACKP1_ticksP1) { MY._ANIMDISTP1 = 0; // reset animation distance MY._FIREMODEP1 = 0; // reset FIREMODEP1 } RETURN; } ELSE // not firing { ///////////////////////////////////////////////////////////////////// // Animations that can take place standing STILLP1 (JUMPINGP1, DUCKINGP1, etc.) ///////////////////////////////////////////////////////////////////// // the JUMPINGP1 animation IF (MY._MOVEMODEP1 == _MODE_JUMPINGP1) { // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP1 / anim_jump_ticks; // set the frame from the percentage SET_FRAME ME,anim_JUMP_str,temp; // increment _ANIMDISTP1 by elapsed time MY._ANIMDISTP1 += TIME; // check to see if we finished JUMPP1 animation IF (MY._ANIMDISTP1 > anim_jump_ticks) { MY._ANIMDISTP1 = 0; MY._MOVEMODEP1 = _MODE_WALKINGP1; } RETURN; } // the DUCKINGP1 animation IF (MY._MOVEMODEP1 == _MODE_DUCKINGP1) { // you can only DUCKP1 at WALKINGP1 SPEEDP1s or below. IF (my_distP1 >= walk_or_runP1*TIME*movement_scaleP1) // to fast to DUCKP1? { MY._MOVEMODEP1 = _MODE_WALKINGP1; // catch the WALKINGP1 mode below this one } ELSE { // DUCKINGP1 // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP1 / anim_DUCKP1_ticksP1; // set the frame from the percentage SET_FRAME ME,anim_DUCKP1_strP1,temp; // increment _ANIMDISTP1 by elapsed time MY._ANIMDISTP1 += TIME; // check to see if we finished DUCKINGP1 IF (MY._ANIMDISTP1 > anim_DUCKP1_ticksP1) { MY._ANIMDISTP1 = 0; MY._MOVEMODEP1 = _MODE_CRAWLINGP1; } RETURN; } } // the CRAWLINGP1 animation IF (MY._MOVEMODEP1 == _MODE_CRAWLINGP1) { // you can only crawl at WALKINGP1 SPEEDP1s or below. IF (my_distP1 >= walk_or_runP1*TIME*movement_scaleP1) // to fast to crawl? { MY._MOVEMODEP1 = _MODE_WALKINGP1; // catch the WALKINGP1 mode below this one } ELSE { // CRAWLINGP1 // set the distance covered, in percent of the model width covered_distP1 = MY._WALKDISTP1 + my_distP1 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP1 > anim_crawl_distP1) { covered_distP1 -= anim_crawl_distP1; } IF (FORCEP1.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP1 / anim_crawl_distP1; SET_CYCLE ME,anim_crawl_strP1,temp; MY._WALKDISTP1 = covered_distP1; // save for next 'frame' of animation RETURN; } } // the SWIMMINGP1 animation IF (MY._MOVEMODEP1 == _MODE_SWIMMINGP1) { // set the distance covered, in percent of the model width covered_distP1 = MY._WALKDISTP1 + my_distP1 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP1 > anim_swim_distP1) { covered_distP1 -= anim_swim_distP1; } IF (FORCEP1.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP1 / anim_swim_distP1; SET_CYCLE ME,anim_swim_strP1,temp; MY._WALKDISTP1 = covered_distP1; // save for next 'frame' of animation RETURN; } // the WADINGP1 animation IF (MY._MOVEMODEP1 == _MODE_WADINGP1) { // set the distance covered, in percent of the model width covered_distP1 = MY._WALKDISTP1 + my_distP1 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP1 > anim_wade_distP1) { covered_distP1 -= anim_wade_distP1; } IF (FORCEP1.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP1 / anim_wade_distP1; SET_CYCLE ME,anim_wade_strP1,temp; MY._WALKDISTP1 = covered_distP1; // save for next 'frame' of animation RETURN; } // the standing STILLP1 animation // NOTE: the must be *before* _MODE_WALKINGP1 but after any other mode // that can animate while the playerP1 is not moving (SWIMMINGP1, // DUCKINGP1, JUMPINGP1, etc.) IF ((my_distP1 < 0.01) || (MY._MOVEMODEP1 == _MODE_STILLP1)) { MY._ANIMDISTP1 += TIME; // wrap animation time to a value between zero and anim_stand_ticksP1 IF (MY._ANIMDISTP1 > anim_stand_ticksP1) { MY._ANIMDISTP1 -= anim_stand_ticksP1; } // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP1 / anim_stand_ticksP1; // set the frame from the percentage SET_CYCLE ME,anim_stand_strP1,temp; RETURN; } // WALKINGP1 animation IF (MY._MOVEMODEP1 == _MODE_WALKINGP1) { // set the distance covered, in percent of the model width covered_distP1 = MY._WALKDISTP1 + my_distP1 / (MY.MAX_X-MY.MIN_X); // decide whether to play the walk or run animation IF (my_distP1 < walk_or_runP1*TIME*movement_scaleP1) // WALKINGP1 { anim_distP1 = anim_walk_distP1; anim_strP1 = anim_walk_strP1; } ELSE { // running anim_distP1 = anim_run_distP1; anim_strP1 = anim_run_strP1; } // calculate the real cycle distance from the model size IF (covered_distP1 > anim_distP1) { covered_distP1 -= anim_distP1; } temp = 100 * covered_distP1 / anim_distP1; IF (FORCEP1.X < 0) // moving backwards? { temp = 100 - temp; } SET_CYCLE ME,anim_strP1,temp; if (covered_distP1 < MY._WALKDISTP1) { _play_walkSOUND(); // SOUND for right foot } if ((covered_distP1 > anim_distP1*0.5) && (MY._WALKDISTP1 < anim_distP1*0.5)) { _play_walkSOUND(); // SOUND for left foot } MY._WALKDISTP1 = covered_distP1; RETURN; } RETURN; // END OF NEW STYLE ANIMATIONS (frame names) } IF ((MY._MOVEMODEP1 == _MODE_STILLP1) || (my_distP1 < 0.01)) { // if the entity has a standing animation, instead of just one frame, // place it here. Otherwise... MY.FRAME = 1; // standing RETURN; } old_style_anim: IF (MY._MOVEMODEP1 == _MODE_WALKINGP1) { // decide whether to play the walk or run animation IF ((MY._RUNFRAMESP1 <= 0) || (my_distP1 < walk_or_runP1*TIME*movement_scaleP1)) // WALKINGP1 { IF (MY.FRAME < 2) { MY.FRAME = 2; } MY.FRAME += MY._WALKDISTP1*my_distP1; // this is one of the expert exceptions where you can use WHILE without WAIT! WHILE (MY.FRAME >= 2 + MY._WALKFRAMESP1) { // SOUND for right foot IF (MY.__SOUND == ON) { _play_walkSOUND(); MY.__SOUND = OFF; } // cycle the animation MY.FRAME -= MY._WALKFRAMESP1; } IF (MY.FRAME > 1 + MY._WALKFRAMESP1*0.5) { // SOUND for left foot IF (MY.__SOUND == OFF) { _play_walkSOUND(); MY.__SOUND = ON; } } IF (MY.FRAME > 1 + MY._WALKFRAMESP1) { MY.NEXT_FRAME = 2; // inbetween to the first WALKINGP1 frame } ELSE { MY.NEXT_FRAME = 0; // inbetween to the real next frame } RETURN; } ELSE { // Running IF (MY.FRAME < 2 + MY._WALKFRAMESP1) { MY.FRAME = 2 + MY._WALKFRAMESP1; } MY.FRAME += MY._RUNDISTP1*my_distP1; WHILE (MY.FRAME >= 2 + MY._WALKFRAMESP1 + MY._RUNFRAMESP1) { IF (MY.__SOUND == ON) { _play_walkSOUND(); MY.__SOUND = OFF; } MY.FRAME -= MY._RUNFRAMESP1; } IF (MY.FRAME > 1 + MY._WALKFRAMESP1 + MY._RUNFRAMESP1*0.5) { IF (MY.__SOUND == OFF) { _play_walkSOUND(); MY.__SOUND = ON; } } IF (MY.FRAME > 1 + MY._WALKFRAMESP1 + MY._RUNFRAMESP1) { MY.NEXT_FRAME = 2 + MY._WALKFRAMESP1; } ELSE { MY.NEXT_FRAME = 0; } RETURN; } } } /////////////////////////////////////////////////////////////////////// // First person camera view // This should be a client-only action!! // // Mod Date: 5/10/00 @ 954 Doug Poston // Added code to create 'under water' fog // Mod Date: 5/15/00 @ 947 Doug Poston // Added eye_height adjustment for DUCKINGP1 and CRAWLINGP1 // Mod Date: 5/22/00 Doug Poston // Added TOUCH for underwater fog // Mod Date: 6/5/00 Doug Poston // Replaced TOUCH with ent_content() function // Mod Date: 6/26/00 Doug Poston // Modifed IF to accept SWIMMINGP1 at any height function move_view_1stP1() { IF (_camera == 0) // If the camera does not move itself { IF (my_heightP1 < 5 || (playerP1._MOVEMODEP1 == _MODE_SWIMMINGP1) ) { // use headwaveP1 = SIN(player_distP1*walk_rateP1); IF ((playerP1._MOVEMODEP1 == 0) // moving on client? || (playerP1._MOVEMODEP1 == _MODE_WALKINGP1)) { // Play the right and left foot SOUND IF (((headwaveP1 > 0) && (walkwaveP1 <= 0)) || ((headwaveP1 <= 0) && (walkwaveP1 > 0))) { PLAY_SOUND thud,30; } // head BOBP1bing walkwaveP1 = headwaveP1; headwaveP1 = walk_amplP1*(ABS(headwaveP1)-0.5); } IF (playerP1._MOVEMODEP1 == _MODE_SWIMMINGP1) { IF ((headwaveP1 > 0) && (walkwaveP1 <= 0)) { PLAY_SOUND splash,30; } // in-water wave movement walkwaveP1 = headwaveP1; headwaveP1 = wave_amplP1*SIN(TOTAL_TICKS*wave_rateP1); head_angleP1.TILT += 0.1*wave_amplP1*SIN(TOTAL_TICKS*wave_rateP1 - 60); } } CAMERA.DIAMETER = 0; // make the camera passable CAMERA.GENIUS = playerP1; // don't display parts of ME CAMERA.X = playerP1.X; CAMERA.Y = playerP1.Y; CAMERA.Z = playerP1.Z + playerP1.MIN_Z; IF (playerP1.__BOBP1 == ON) { CAMERA.Z += headwaveP1; } IF (playerP1._MOVEMODEP1 == _MODE_SWIMMINGP1) { // adjust eye height for SWIMMINGP1 CAMERA.Z += (playerP1.MAX_Z-playerP1.MIN_Z)*eye_height_downP1; } ELSE { IF ((playerP1._MOVEMODEP1 == _MODE_DUCKINGP1) || (playerP1._MOVEMODEP1 == _MODE_CRAWLINGP1)) { // adjust eye height for DUCKINGP1 and CRAWLINGP1 CAMERA.Z += (playerP1.MAX_Z-playerP1.MIN_Z)*eye_height_DUCKP1; } ELSE { // adjust eye height for 'normal' modes CAMERA.Z += (playerP1.MAX_Z-playerP1.MIN_Z)*eye_height_upP1; } } CAMERA.PAN = playerP1.PAN; CAMERA.TILT = playerP1.TILT + head_angleP1.TILT; CAMERA.ROLL = playerP1.ROLL; // check to see if camera is located in a passable block //jcl 07-22-00 old fog is saved if (ent_content(NULL,CAMERA.x) == CONTENT_PASSABLE) { if (FOG_COLOR != _FOG_UNDERWATER) { current_fog_index = FOG_COLOR; // save old fog FOG_COLOR = _FOG_UNDERWATER; // set fog color to underwater fog } } else { if (FOG_COLOR == _FOG_UNDERWATER) { // else restore current_fog_index FOG_COLOR = current_fog_index; } } person_3rdP1 = 0; } } // Third person camera view // // Mod Data: 5/10/00 DCP // Added code to create 'under water' fog // Mod Date: 5/22/00 Doug Poston // Added TOUCH for underwater fog // Mod Date: 6/5/00 DCP // Replaced TOUCH with ent_content() function // Mod Date: 8/28/00 DCP // Replaced 4.205 function with modified 'Fly Level' function function move_view_3rdP1() { if ((_camera == 0) && (playerP1 != NULL)) { CAMERA.DIAMETER = 0; // make the camera passable CAMERA.genius = playerP1; CAMERA.pan += 0.2 * ang(playerP1.pan-CAMERA.pan); // tilt the camera differently if we are using a vehicle if ( (playerP1._MOVEMODEP1 == _MODE_PLANEP1) ||(playerP1._MOVEMODEP1 == _MODE_CHOPPERP1)) { CAMERA.tilt += 0.2 * ang(playerP1.tilt-CAMERA.tilt); } else { // WALKINGP1, SWIMMINGP1 etc. CAMERA.tilt = head_angleP1.tilt-5; if((person_3rdP1 < 1) && (camera_distP1.Z == 0)) // switching to 3rd person { camera_distP1.Z = - playerP1.MAX_Z; } } vec_set(temp,temp_cdistP1); // temp = temp_cdistP1 VECROTATE temp,playerP1.PAN; CAMERA.X += 0.3*(playerP1.X - temp.X - CAMERA.X); CAMERA.Y += 0.3*(playerP1.Y - temp.Y - CAMERA.Y); CAMERA.Z += 0.3*(playerP1.Z - temp.Z - CAMERA.Z); // test if camera is IN_PASSABLE or IN_SOLID temp = ent_content(NULL,CAMERA.x); // if camera moved into a wall... if (temp == CONTENT_SOLID) { temp_cdistP1.X *= 0.7; // place it closer to the playerP1 temp_cdistP1.Y *= 0.7; temp_cdistP1.Z *= 0.7; } else { temp_cdistP1.X += 0.2*(playerP1.MAX_X + camera_distP1.X - temp_cdistP1.X); temp_cdistP1.Y += 0.2*(playerP1.MAX_Y + camera_distP1.Y - temp_cdistP1.Y); temp_cdistP1.Z += 0.2*(playerP1.MAX_Z + camera_distP1.Z - temp_cdistP1.Z); } // check to see if camera is located in a passable block if (temp == CONTENT_PASSABLE) { if (FOG_COLOR != _FOG_UNDERWATER) { current_fog_index = FOG_COLOR; // save old fog FOG_COLOR = _FOG_UNDERWATER; // set fog color to underwater fog } } else { if (FOG_COLOR == _FOG_UNDERWATER) { // else restore current_fog_index FOG_COLOR = current_fog_index; } } person_3rdP1 = 1; } } function move_view() { IF (playerP1 == NULL) { playerP1 = ME; } // this action needs the playerP1 synonym IF (playerP1 == NULL) { RETURN; } // STILLP1 no playerP1 -> can't work IF (person_3rdP1 > 0) { // This skill should be local move_view_3rdP1(); } ELSE { move_view_1stP1(); } } // Desc: create a shadow below the entity ACTION drop_shadowP1 { IF (VIDEO_DEPTH >= 16) { CREATE SHADOWSPRITE,MY.POS,move_shadowP1; } ELSE { CREATE SHADOWFLAT,MY.POS,move_shadowP1; } } // Desc: function used to move shadow // // Mod Date: 05/29/00 // Added check for SWIMMINGP1 or WADINGP1 (no shadow) // Mod Date: 7/30/00 JCL // Made shadow darker + adapted to floor slope function move_shadowP1() { MY.flare = ON; MY.transparent = ON; //inverse alpha MY.passable = ON; MY.oriented = ON; MY.ambient = -100; // shadow should be totally black MY.unlit = ON; //(plus UNLIT flag in version 4.20) // scale the shadow so that it matches its master's (YOU) size MY.scale_x = (YOU.max_x - YOU.min_x)/(MY.max_x - MY.min_x); MY.scale_y = MY.scale_x * 0.8; MY.scale_z = 1.0; while (YOU != NULL) { if ((YOU.invisible == ON) || (YOU._MOVEMODEP1 == _MODE_SWIMMINGP1) || (YOU._MOVEMODEP1 == _MODE_WADINGP1)) { MY.invisible = ON; } else { MY.invisible = OFF; temp_entP1 = YOU; SONAR temp_entP1,500; // get height above the floor YOU = temp_entP1; // YOU (the entity itself) is changed by SONAR // place shadow 2 quants above the floor MY.z = YOU.z + YOUR.min_z + 2 - RESULT; MY.x = YOU.x; MY.y = YOU.y; MY.pan = YOU.pan; // adapt shadow orientation to floor slope if ((NORMAL.x != 0) || (NORMAL.y != 0)) { // we're on a slope // rotate the floor normal relative to the shadow vec_set(temp,nullvector); // set temp tilt and roll to 0 temp.pan = -MY.PAN; VECROTATE NORMAL,temp; // calculate the destination tilt and roll angles MY.tilt = 90-asin(NORMAL.x); MY.roll = -asin(NORMAL.y); } else { MY.tilt = 90; // set it flat onto the floor MY.roll = 0; } } wait(1); } // end while(YOU != NULL) REMOVE ME; } // Desc: Get key input from the playerP1 // // Set aFORCEP1 & FORCEP1 values using playerP1 input (keyboard/mouse/joystick) // Make sure these values are within limitP1 // // Mod Date: 6/9/00 Doug Poston // changed from ACTION to function function _playerP1_intentions() { // Set the angular FORCEP1s according to the playerP1 intentions aFORCEP1.PAN = -astrengthP1.PAN*(KEY_FORCE.X);//+JOY_FORCE.X aFORCEP1.TILT = astrengthP1.TILT*(KEY_PGUP-KEY_PGDN); IF (MOUSE_MODE == 0) { // Mouse switched off? aFORCEP1.PAN += -astrengthP1.PAN*MOUSE_FORCE.X*mouseviewP1; aFORCEP1.TILT += astrengthP1.TILT*MOUSE_FORCE.Y*mouseviewP1; } aFORCEP1.ROLL = 0; // Set ROLL FORCEP1 if ALT was pressed IF (KEY_ALT != 0) { aFORCEP1.ROLL = aFORCEP1.PAN; aFORCEP1.PAN = 0; } // Double the forces in case the playerP1 pressed P IF (KEY_P != 0) { aFORCEP1.PAN += aFORCEP1.PAN; aFORCEP1.TILT += aFORCEP1.TILT; aFORCEP1.ROLL += aFORCEP1.ROLL; } // limitP1 the FORCEP1s in case the playerP1 // pressed buttons, mouse and joystick simultaneously limitP1.PAN = 2*astrengthP1.PAN; limitP1.TILT = 2*astrengthP1.TILT; limitP1.ROLL = 2*astrengthP1.ROLL; IF (aFORCEP1.PAN > limitP1.PAN) { aFORCEP1.PAN = limitP1.PAN; } IF (aFORCEP1.PAN < -limitP1.PAN) { aFORCEP1.PAN = -limitP1.PAN; } IF (aFORCEP1.TILT > limitP1.TILT) { aFORCEP1.TILT = limitP1.TILT; } IF (aFORCEP1.TILT < -limitP1.TILT) { aFORCEP1.TILT = -limitP1.TILT; } IF (aFORCEP1.ROLL > limitP1.ROLL) { aFORCEP1.ROLL = limitP1.ROLL; } IF (aFORCEP1.ROLL < -limitP1.ROLL) { aFORCEP1.ROLL = -limitP1.ROLL; } // Set the cartesian FORCEP1s according to the playerP1 intentions FORCEP1.X = strengthP1.X*(KEY_FORCE.Y);//+JOY_FORCE.Y FORCEP1.Y = strengthP1.Y*(KEY_COMMA-KEY_PERIOD); FORCEP1.Z = strengthP1.Z*(KEY_HOME-KEY_END); IF (MOUSE_MODE == 0) { // Mouse switched off? FORCEP1.X += strengthP1.X*MOUSE_RIGHT*mouseviewP1; } // Double the FORCEP1s in case the playerP1 pressed P IF (KEY_P != 0) { FORCEP1.X += FORCEP1.X; FORCEP1.Y += FORCEP1.Y; FORCEP1.Z += FORCEP1.Z; } // limitP1 the FORCEP1s in case the playerP1 tried to cheat by // operating buttons, mouse and joystick simultaneously limitP1.X = 2*strengthP1.X; limitP1.Y = 2*strengthP1.Y; limitP1.Z = 2*strengthP1.Z; IF (FORCEP1.X > limitP1.X) { FORCEP1.X = limitP1.X; } IF (FORCEP1.X < -limitP1.X) { FORCEP1.X = -limitP1.X; } IF (FORCEP1.Y > limitP1.Y) { FORCEP1.Y = limitP1.Y; } IF (FORCEP1.Y < -limitP1.Y) { FORCEP1.Y = -limitP1.Y; } IF (FORCEP1.Z > limitP1.Z) { FORCEP1.Z = limitP1.Z; } IF (FORCEP1.Z < -limitP1.Z) { FORCEP1.Z = -limitP1.Z; } } // Desc: set FORCEP1 and aFORCEP1 values // these values come from _playerP1_intentions (single playerP1) // or from the client (multiplayerP1) // // Calls: _playerP1_intentions // // Mod Date: 6/9/00 Doug Poston // changed to function function _player_FORCEP1() { // If the camera does not move itself if (_camera == 0) { // multiplayerP1 mode if (client_moving) { // get FORCEP1s from server FORCEP1.X = MY._FORCEP1_X; FORCEP1.Y = MY._FORCEP1_Y; FORCEP1.Z = MY._FORCEP1_Z; aFORCEP1.PAN = MY._AFORCEP1_PAN; aFORCEP1.TILT = MY._AFORCEP1_TILT; aFORCEP1.ROLL = MY._AFORCEP1_ROLL; } else { // get FORCEP1s from user input _playerP1_intentions(); } aFORCEP1.PAN *= MY._FORCEP1; aFORCEP1.TILT *= MY._FORCEP1; aFORCEP1.ROLL *= MY._FORCEP1; FORCEP1.X *= MY._FORCEP1; FORCEP1.Y *= MY._FORCEP1; FORCEP1.Z *= MY._FORCEP1; } else { // playerP1 controls camera - set actor FORCEP1s to zero aFORCEP1.PAN = 0; aFORCEP1.TILT = 0; aFORCEP1.ROLL = 0; FORCEP1.X = 0; FORCEP1.Y = 0; FORCEP1.Z = 0; } } // Desc: used in multiplayerP1 (client/server) games // set client_moving var to 1 // take user input use that to adjust the 'playerP1' FORCEP1s // SEND playerP1 FORCEP1s to the server // move the camera // // Call: _playerP1_intentions // move_view function client_move()//??????????????????????????????????????????????????????? { client_moving = 1; WHILE (1) { _playerP1_intentions();// user key/mouse input sets FORCEP1 and aFORCEP1 values // playerP1 created on the client? if (playerP1) { playerP1._FORCEP1_X = FORCEP1.X; playerP1._FORCEP1_Y = FORCEP1.Y; playerP1._FORCEP1_Z = FORCEP1.Z; playerP1._AFORCEP1_PAN = aFORCEP1.PAN; playerP1._AFORCEP1_TILT = aFORCEP1.TILT; playerP1._AFORCEP1_ROLL = aFORCEP1.ROLL; // send playerP1 FORCEP1s to server SEND playerP1._FORCEP1_X; SEND playerP1._FORCEP1_Y; SEND playerP1._FORCEP1_Z; SEND playerP1._AFORCEP1_PAN; SEND playerP1._AFORCEP1_TILT; SEND playerP1._AFORCEP1_ROLL; // move the camera move_view(); } WAIT 1; } } ///////////////////////////////////////////////////////////////////// function toggle_personP1() { IF (person_3rdP1 > 0) { person_3rdP1 = 0; } ELSE { person_3rdP1 = 0.5; } } ///////////////////////////////////////////////////////////////////// // Auxiliary actions // values set in scan_floorP1 var on_passable_;//?????????????????????????????????????????????????????? var in_passable_; var in_solid_; // Desc: scan for a surface below the ME entity // set my_floornormalP1 vector to the normal of the surface // set my_heightP1 to the distance between ME.MIN_Z and the surface // set floorSPEEDP1 to the X & Y SPEEDP1 of any platform ME is on. // set on_passable_, in_passable_, and in_solid_ to the 'offset SONAR' // values. // // Mod Date: 7/22/00 JCL // sets on_passable_, in_passable_, and in_solid_ values using the // "MY.Z += 16 SONAR" method. // function scan_floorP1() { SONAR ME,4000; // if the first sonar shows we are in_passable... if (IN_PASSABLE == ON) { // the entity can be completely or partially under water MY.z += 16; // displace me upwards by the hull size - now my hull is outside the water SONAR MY,4000; // detect ground again - this time a water surface will be found MY.z -= 16; // back to old position } // save SONAR values for later use on_passable_ = on_passable; in_passable_ = in_passable; in_solid_ = in_solid; my_floornormalP1.X = NORMAL.X; // set my_floornormalP1 to the normal of the surface my_floornormalP1.Y = NORMAL.Y; my_floornormalP1.Z = NORMAL.Z; my_heightP1 = RESULT; // set my_heightP1 to the distance between entity's MIN_Z and surface my_floorSPEEDP1.X = 0; // reset floorSPEEDP1 to zero my_floorSPEEDP1.Y = 0; // if the playerP1 is standing on a platform, move him with it IF (YOU != NULL) { IF (YOUR._TYPE == _TYPE_ELEVATOR) { my_floorSPEEDP1.X = YOUR._SPEEDP1_X; my_floorSPEEDP1.Y = YOUR._SPEEDP1_Y; // Z SPEEDP1 is not necessary - this is done by the height adaption } } // test the floor texture // temp.X = MY.X; // temp.Y = MY.Y; // temp.Z = MY.Z - 500; // LOOK NULL,MY.X,temp; } ///////////////////////////////////////////////////////////// // Desc: Calculate a position directly ahead of the camera // Input: pP1 (distance) // Output: MY_POS function set_pos_aheadP1() { temp.X = COS(CAMERA.PAN); temp.Y = SIN(CAMERA.PAN); temp.Z = pP1*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 + pP1*SIN(CAMERA.TILT); } ///////////////////////////////////////////////////////////// // Desc: Calculate a 3d position relative to the camera angles // Input: MY_POS // Output: MY_POS // Mod Date: 6/9/00 Doug Poston // changed to function function _set_pos_ahead_xyzP1() { VECROTATE MY_POS,CAMERA.PAN; IF (person_3rdP1 != 0) { MY_POS.X += playerP1.X; MY_POS.Y += playerP1.Y; MY_POS.Z += playerP1.Z; } ELSE { MY_POS.X += CAMERA.X; MY_POS.Y += CAMERA.Y; MY_POS.Z += CAMERA.Z; } } //////////////////////////////////////////////////////////////////////// // Desc: event action to indicate any event by resetting the event flag // // Mod Date: 6/9/00 Doug Poston // changed to function function _setback()//?????????????????????????????????????????????????????????????? { IF (EVENT_TYPE == EVENT_BLOCK) { MY.ENABLE_BLOCK = OFF; } IF (EVENT_TYPE == EVENT_ENTITY) { MY.ENABLE_ENTITY = OFF; } IF (EVENT_TYPE == EVENT_STUCK) { MY.ENABLE_STUCK = OFF; } IF (EVENT_TYPE == EVENT_PUSH) { MY.ENABLE_PUSH = OFF; } IF (EVENT_TYPE == EVENT_IMPACT) { MY.ENABLE_IMPACT = OFF; } IF (EVENT_TYPE == EVENT_DETECT) { MY.ENABLE_DETECT = OFF; } IF (EVENT_TYPE == EVENT_SCAN) { MY.ENABLE_SCAN = OFF; } IF (EVENT_TYPE == EVENT_SHOOT) { MY.ENABLE_SHOOT = OFF; } IF (EVENT_TYPE == EVENT_TRIGGER) { MY.ENABLE_TRIGGER = OFF; } IF (EVENT_TYPE == EVENT_TOUCH) { MY.ENABLE_TOUCH = OFF; } IF (EVENT_TYPE == EVENT_RELEASE) { MY.ENABLE_RELEASE = OFF; } IF (EVENT_TYPE == EVENT_CLICK) { MY.ENABLE_CLICK = OFF; } } // Mod Date: 6/9/00 Doug Poston // changed to function function _beep() { BEEP; }//???????????????????????????????????????????????????? ////////////////////////////////////////////////////////////////////////??????????????????????????????????? // Handle action. Set to SPACE by default. // Will operate doors or items within 200 quants. VAR indicator = 0; DEFINE _handleP1,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 handleP1 { IF (playerP1 != NULL) { MY_POS.X = playerP1.X; MY_POS.Y = playerP1.Y; MY_POS.Z = playerP1.Z; MY_ANGLE.PAN = playerP1.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; scan_handleP1(); } // Desc: scan a wide cone of 200 quants range function scan_handleP1() { temp.PAN = 120; temp.TILT = 180; temp.Z = 200; indicator = _handleP1; SCAN MY_POS,MY_ANGLE,temp; } // Desc: This action can be run by a playerP1 entity on the server // It checks for receiving a handle SIGNALP1, then performs a scan function perform_handleP1() { WHILE (1) { IF (MY._SIGNALP1 == _handleP1) { // client has pressed handle key MY.HIDDEN = ON; MY._SIGNALP1 = 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; scan_handleP1(); } WAIT 1; } } function send_handleP1() { IF (playerP1 != NULL) { playerP1._SIGNALP1 = _handleP1; // send command to perform a scan SEND playerP1._SIGNALP1; } } ///////////////////////////////////////////////////////////////////// ON_6 toggle_personP1; ON_8 send_handleP1; /////////////////////////////////////////////////////////////////////