// Template file v4.202 //////////////////////////////////////////////////////////////////////// // File: movement.wdl // WDL prefabs for entity movement //////////////////////////////////////////////////////////////////////// // Mod Date: 6/5/00 // Added code to handleP2 new animation // playerP2 can now stand, walk, run, DUCKP2, JUMPP2, 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 __FALLP2 (FLAG1) and _FALLTIMEP2 (SKILL31) // If __FALLP2 is ON, playerP2 takes damage from FALLP2s // _FALLTIMEP2 contains the amount of time spent FALLP2ing (calculated in move_gravityP2) // // Mod Date: 7/18/00 // Changed slope gravityP2 (added var 'slopefacP2') // // Mod Date: 7/19/00 // Added code to adjust my_heightP2 while DUCKINGP2 and CRAWLINGP2 // - Add var 'DUCKP2_heightP2' // - modified var 'eye_height_DUCKP2' to equal 'eye_height_upP2' // // Mod Date: 7/28/00 // Added __DUCKP2 flag as flag #8 (replaces __SOUND flag) // playerP2 can only DUCKP2 if the __DUCKP2 flag is set to ON // // Mod Date: 8/28/00 DCP // Removed Actions 'playerP2_heli' and 'playerP2_fly' (experimental code) // Added MODEs _MODE_PLANEP2 & _MODE_CHOPPERP2 // Expanded VAR 'camera_distP2' & 'temp_cdistP2' into vectors (X,Y,Z fields) // Modified 'move_view_3rdP2' FUNCTION to take advantage of 'camera_distP2' vector // Replaced min with max (to eliminate 'creep') in 'gravityP2' functions // // Mod Date: 8/31/00 DCP // Added movement_scaleP2 and actor_scaleP2 to scale movement and models (to make world appear larger or smaller) // Modified "swim_gravityP2" to scale distP2 and absdistP2 by movement_scaleP2 before MOVE // Modified "wade_gravityP2" to scale distP2 and absdistP2 by movement_scaleP2 before MOVE // Modified "move_gravityP2" to scale distP2 and absdistP2 by movement_scaleP2 before MOVE // Modified function "anim_initP2" to use actor_scaleP2 to scale the entity that calls it. // Modified 'walk_or_runP2' by 'movement_scaleP2' in function "actor_animP2" // // Mod Date: 9/2/00 DCP // Modified 'move_view_3rdP2' to set camera_distP2.Z to playerP2.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_scaleP2 = 1.00; // used to scale the movement VAR actor_scaleP2 = 1.00; // used to scale the size of actors // NOTE: in most cases it is a good idea to make actor_scaleP2 == movement_scaleP2 VAR gnd_fricP2 = 0.5; // ground frictionP2 VAR air_fricP2 = 0.03; // air frictionP2 VAR water_fricP2 = 0.75; // water frictionP2 VAR ang_fricP2 = 0.6; // angular frictionP2 VAR gravityP2 = 6; // gravityP2 FORCEP2 VAR elasticity = 0.1; // of the floor var strengthP2[3] = 5,4,75; // default ahead, side, JUMPP2 strengthP2 (25) var astrengthP2[3] = 7,5,2; // default pan, tilt, roll strengthP2 var slopefacP2 = 2; // gravityP2 on SLOPESP2, determines the max angle to climb VAR eye_height_upP2 = 0.8; // eye position factor for WALKINGP2, DRIVINGP2 VAR eye_height_downP2 = 0.7; // for SWIMMINGP2 VAR eye_height_DUCKP2 = 0.8; //0.3; // for DUCKINGP2 (7/19/00: same as eye_height_upP2 since DUCKINGP2 is controlled by my_heightP2) VAR walk_rateP2 = 3; // for head wave, 360 / step width VAR wave_rateP2 = 25; // same for SWIMMINGP2, 360 / wave time VAR walk_amplP2 = 4; // WALKINGP2 head wave amplitude VAR wave_amplP2 = 2; // SWIMMINGP2 head wave amplitude VAR anim_ATTACKP2_ticksP2 = 16;// time for one ATTACKP2 animation cycle VAR anim_stand_ticksP2 = 16; // time for one standing anim cycle VAR anim_jump_ticks = 6; // time for one JUMPP2 animation cycle VAR anim_DUCKP2_ticksP2 = 8; // time for one DUCKP2 animation cycle VAR anim_walk_distP2 = 1; // distP2 per model width per walk cycle VAR anim_run_distP2 = 1.5; // distP2 per model width per run cycle VAR anim_crawl_distP2 = 0.8; // distP2 per model width per crawl cycle VAR anim_wade_distP2 = 0.8; // distP2 per model width per crawl cycle VAR anim_swim_distP2 = 1; // distP2 per model width per swim cycle VAR person_3rdP2 = 0; // 0: 1st person mode; 0.5: 3rd person mode //VAR camera_distP2 = 90; // camera distance to entity in 3rd person view VAR camera_distP2[3] = 90,0,0; // camera distance to entity in 3rd person view VAR mouseviewP2 = 1; // mouse factor, set 0 to disable mouse VAR client_moving = 0; // multiplayerP2 mode VAR JUMP_heightP2 = 50; // maximum JUMPP2 height above ground var FALL_timeP2 = 6; // max FALLP2 time before HEALTHP2 is reduced VAR DUCKP2_heightP2 = 25; // distance to adjust my_heightP2 while DUCKINGP2 VAR walk_or_runP2 = 12; // max quants per tick to switch from walk to run animation VAR POWERP2_maxP2 = 1; // maximum engine POWERP2 for aircraft // strings for defining the animation frames STRING anim_stand_strP2,"stand"; STRING anim_walk_strP2,"walk"; STRING anim_run_strP2,"run"; STRING anim_DUCKP2_strP2,"DUCKP2"; STRING anim_swim_strP2,"swim"; STRING anim_dive_strP2,"dive"; STRING anim_JUMP_str,"JUMPP2"; STRING anim_crawl_strP2,"crawl"; STRING anim_wade_strP2,"wade"; // string synonyms for defining the animation frames (and their default values) STRING anim_default_death_strP2,"death"; STRING anim_default_ATTACKP2_strP2,"ATTACKP2"; SYNONYM anim_ATTACKP2_strP2 { TYPE STRING; DEFAULT anim_default_ATTACKP2_strP2;} SYNONYM anim_death_strP2 { TYPE STRING; DEFAULT anim_default_death_strP2;} /////////////////////////////////////////////////////////////////////// // Entity skill & flag definitions // some definitions here are also needed for ACTORS.WDL and WAR.WDL DEFINE _WALKFRAMESP2,SKILL1; // non-zero for old style animation DEFINE _RUNFRAMESP2,SKILL2; DEFINE _ATTACKFRAMESP2,SKILL3; DEFINE _DIEFRAMESP2,SKILL4; DEFINE _FORCEP2,SKILL5; // determines SPEEDP2 DEFINE _ENTFORCEP2,SKILL5; DEFINE _BANKINGP2,SKILL6; // BANKINGP2 - for playerP2 only DEFINE _PENDOLINOP2,SKILL6; // BANKINGP2 - for playerP2 only DEFINE _HITMODEP2,SKILL6; // for actors DEFINE _MOVEMODEP2,SKILL7; DEFINE _FIREMODEP2,SKILL8; // for actors DEFINE __FALLP2,FLAG1; // take damage from FALLP2s DEFINE __WHEELSP2,FLAG2; // block turns without moving DEFINE __SLOPESP2,FLAG3; // adapt the tilt and roll angle to SLOPESP2 DEFINE __JUMPP2,FLAG4; // be able to JUMPP2 DEFINE __BOBP2,FLAG5; // head wave DEFINE __STRAFEP2,FLAG6; // be able to move sidewards DEFINE __TRIGGER,FLAG7; // be able to TRIGGER doors automatically DEFINE __DUCKP2, FLAG8; // be able to DUCKP2 DEFINE __SOUND,FLAG8; // internal flag /////////////////////////////////////////////////////////////////////// DEFINE _HEALTHP2,SKILL9; DEFINE _ARMORP2,SKILL10; DEFINE _SPEEDP2,SKILL11; // SPEEDP2 DEFINE _SPEEDP2_X,SKILL11; DEFINE _SPEEDP2_Y,SKILL12; DEFINE _POWERP2,SKILL12; // engine POWERP2 for aircraft models DEFINE _SPEEDP2_Z,SKILL13; DEFINE _ASPEEDP2,SKILL14; // angular SPEEDP2 DEFINE _ASPEEDP2_PAN,SKILL14; DEFINE _ASPEEDP2_TILT,SKILL15; DEFINE _ASPEEDP2_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 playerP2 entities DEFINE _FORCEP2_X,SKILL17; DEFINE _FORCEP2_Y,SKILL18; DEFINE _FORCEP2_Z,SKILL19; DEFINE _AFORCEP2_PAN,SKILL20; DEFINE _AFORCEP2_TILT,SKILL21; DEFINE _AFORCEP2_ROLL,SKILL22; DEFINE _WALKSOUND,SKILL23; // WALKINGP2 SOUND DEFINE _SIGNALP2,SKILL24; // communication for actions or client->server DEFINE _COUNTERP2,SKILL25; // internal COUNTERP2 DEFINE _STATEP2,SKILL26; // the STATEP2 it is in (walk, ATTACKP2, escape etc.) DEFINE _WALKDISTP2,SKILL27; // distance per walk cycle DEFINE _RUNDISTP2,SKILL28; // distance per run cycle DEFINE _ANIMDISTP2,SKILL28; // time for standing, JUMPINGP2, and DUCKINGP2 animations DEFINE _TYPE,SKILL30; // the type of the entity - door, key, etc. DEFINE _FALLTIMEP2,SKILL31; // amount of time spent FALLP2ing // Skills up to 32 are reserved for future template actions // Skills 33-40 can be used freely /////////////////////////////////////////////////////////////////////// // Mod Date: 7/4/00 DCP // Changed SPEEDP2 -> camera_SPEEDP2 // aSPEEDP2-> camera_aSPEEDP2 VAR camera_SPEEDP2[3] = 0,0,0; // cartesian SPEEDP2, entity coordinates VAR camera_aSPEEDP2[3]; // angular SPEEDP2 VAR FORCEP2[3]; // cartesian FORCEP2, entity coordinates VAR absFORCEP2[3]; // cartesian FORCEP2, world coordinates VAR aFORCEP2[3]; // angular FORCEP2 VAR abSPEEDP2[3] = 0,0,0; // cartesian SPEEDP2, world coordinates var distP2[3]; var absdistP2[3]; // distances used for MOVE VAR pP2[3]; VAR frictionP2; VAR limitP2[3]; VAR covered_distP2; VAR anim_distP2; var head_angleP2[3] = 0,0,0; // separated from other values VAR headwaveP2 = 0; VAR walkwaveP2 = 0; VAR my_distP2; // distance for actor anim VAR player_distP2; // distance for head BOBP2bing VAR scan_sectorP2; VAR my_heightP2; VAR my_floornormalP2[3]; VAR my_floorSPEEDP2[3]; VAR temp_cdistP2[3] = 120,0,0; // current camera distance in 3rd pP2 view //-VAR debugskill; VAR current_fog_index = 0; // the current fog color index????????????????????????????????? SYNONYM playerP2 { TYPE ENTITY; } SYNONYM temp_entP2 { TYPE ENTITY; } SYNONYM carryP2 { TYPE ACTION; } SYNONYM anim_strP2 { TYPE STRING; } DEFINE _MODE_WALKINGP2,1; DEFINE _MODE_DRIVINGP2,2; DEFINE _MODE_SWIMMINGP2,3; DEFINE _MODE_DIVINGP2,4; DEFINE _MODE_WADINGP2,5; DEFINE _MODE_HELICOPTERP2,6; // very primitive HELICOPTERP2 mode DEFINE _MODE_ROCKETEERP2,7; DEFINE _MODE_DUCKINGP2,8; // DUCKINGP2 DEFINE _MODE_JUMPINGP2,9; // JUMPINGP2 DEFINE _MODE_CRAWLINGP2,10; // CRAWLINGP2 DEFINE _MODE_STILLP2,15; DEFINE _MODE_PLANEP2,16; DEFINE _MODE_CHOPPERP2,17; // modes 20 and above are handleP2d by a different wdl DEFINE _MODE_ATTACKP2,20; DEFINE _SOUND_WALKER,1;//?????????????????????????????????????????????????? DEFINE _SOUND_ROBOT,2;//?????????????????????????????????????????????????? DEFINE _TYPE_playerP2,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_ARMORP2,22; DEFINE _TYPE_HEALTHP2,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: playerP2 drive action // // Mod Date: 8/31/00 DCP // Scale the playerP2 by vec_scale ACTION player_driveP2 { MY._MOVEMODEP2 = _MODE_DRIVINGP2; MY._FORCEP2 = 1.5; MY._BANKINGP2 = 0.5; MY.__SLOPESP2 = ON; MY.__TRIGGER = ON; player_moveP2(); } // Desc: playerP2 walk action // // Mod Date: 8/31/00 DCP // Scale the playerP2 by vec_scale ACTION player_walkP2 { MY._MOVEMODEP2 = _MODE_WALKINGP2; MY._FORCEP2 = 0.75; MY._BANKINGP2 = -0.1; MY.__JUMPP2 = ON; MY.__DUCKP2 = ON; MY.__STRAFEP2 = ON; MY.__BOBP2 = ON; MY.__TRIGGER = ON; player_moveP2(); } // Desc: playerP2 swim action // ACTION player_swimP2 { MY._MOVEMODEP2 = _MODE_SWIMMINGP2; MY._FORCEP2 = 0.75; MY._BANKINGP2 = 0; MY.__JUMPP2 = ON; MY.__DUCKP2 = ON; MY.__STRAFEP2 = OFF; MY.__BOBP2 = ON; player_moveP2(); } /////////////////////////////////////////////////////////////////////// // Desc: Shakes the playerP2, used for hits and death function player_shakeP2() { 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: playerP2 tips over, can be used for death function player_tipP2() { MY._MOVEMODEP2 = 0; // suspend normal movement action eye_height_upP2.Z = eye_height_upP2; // store original eye height WHILE (MY.ROLL < 80) { MY.ROLL += 8 * TIME; MY.TILT += 2 * TIME; IF (eye_height_upP2 > 0.15) { eye_height_upP2 -= 0.1 * TIME; } IF (client_moving==0) { move_view(); } WAIT 1; } MY.ROLL = 80; MY.TILT = 20; eye_height_upP2 = eye_height_upP2.Z; // restore original eye height } //////////////////////////////////////////////////////////////////////// // Desc: main playerP2 movement action // called from 'player_walkP2', 'player_driveP2', & 'player_swimP2' // // Mod Date: 5/10/00 @ 973 Doug Poston // Added code to handleP2 SWIMMINGP2 // Mod Date: 5/11/00 @ 097 Doug Poston // Added code to handleP2 DUCKINGP2 and CRAWLINGP2 // Mod Date: 5/16/00 Doug Poston // Modified underwater fog code // Modified playerP2 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 SWIMMINGP2 to check if // the playerP2 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 WADINGP2 (fixed in v4.193) ACTION player_moveP2 { IF (MY.CLIENT == 0) { playerP2 = ME; } // created on the server? MY._TYPE = _TYPE_playerP2; MY.ENABLE_SCAN = ON; // so that enemies can detect me IF ((MY.TRIGGER_RANGE == 0) && (MY.__TRIGGER == ON)) { MY.TRIGGER_RANGE = 32; } IF (MY._FORCEP2 == 0) { MY._FORCEP2 = 1.5; } IF (MY._MOVEMODEP2 == 0) { MY._MOVEMODEP2 = _MODE_WALKINGP2; } IF (MY._WALKFRAMESP2 == 0) { MY._WALKFRAMESP2 = DEFAULT_WALK; } IF (MY._RUNFRAMESP2 == 0) { MY._RUNFRAMESP2 = DEFAULT_RUN; } IF (MY._WALKSOUND == 0) { MY._WALKSOUND = _SOUND_WALKER; } anim_initP2(); // init old style animation perform_handleP2(); // react on pressing the handleP2 key // while we are in a valid MOVEMODEP2 WHILE ((MY._MOVEMODEP2 > 0)&&(MY._MOVEMODEP2 <= _MODE_STILLP2)) { // if we are not in 'STILLP2' mode IF (MY._MOVEMODEP2 != _MODE_STILLP2) { // Get the angular and translation FORCEP2s (set aFORCEP2 & FORCEP2 values) _player_FORCEP2(); // find ground below (set my_heightP2, my_floornormalP2, & my_floorSPEEDP2) scan_floorP2(); // if they are on or in a passable block... IF ( ((my_heightP2 < 5) && (ON_PASSABLE != 0)) || (IN_PASSABLE != 0) ) { // if not already SWIMMINGP2 or WADINGP2... IF ((MY._MOVEMODEP2 != _MODE_SWIMMINGP2) && (MY._MOVEMODEP2 != _MODE_WADINGP2)) { PLAY_SOUND splash,50; MY._MOVEMODEP2 = _MODE_SWIMMINGP2; } // if SWIMMINGP2... IF (MY._MOVEMODEP2 == _MODE_SWIMMINGP2) // SWIMMINGP2 on/in a passable block { IF (ON_PASSABLE == ON) // && (IN_PASSABLE != ON)) -> Not need with version 4.193+ { // check for WADINGP2 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 WADINGP2 MY._MOVEMODEP2 = _MODE_WADINGP2; MY.TILT = 0; // stop tilting my_heightP2 = RESULT + MY.MIN_Z; // calculate WADINGP2 height } // check for edge (for 'JUMPINGP2' out of water) // +++This code can be added here+++ } }// END SWIMMINGP2 on/in a passable block // if WADINGP2... IF (MY._MOVEMODEP2 == _MODE_WADINGP2) // WADINGP2 on/in a passable block { // check for SWIMMINGP2 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 SWIMMINGP2 MY._MOVEMODEP2 = _MODE_SWIMMINGP2; } ELSE // use SOLID surface for height (can't walk on water) { my_heightP2 = RESULT + MY.MIN_Z; // calculate WADINGP2 height } } // END WADINGP2 on/in a passable block } // END if they are on or in a passable block... ELSE // not in or on a passable block { // if WADINGP2 or SWIMMINGP2 while *not* on/in a passable block... IF ((MY._MOVEMODEP2 == _MODE_SWIMMINGP2) || (MY._MOVEMODEP2 == _MODE_WADINGP2)) { // get out of the water (go to walk mode) MY._MOVEMODEP2 = _MODE_WALKINGP2; 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.__SLOPESP2 == ON) { // Adapt the playerP2 angle to the floor slope MY_ANGLE.TILT = 0; MY_ANGLE.ROLL = 0; IF ((my_heightP2 < 10) && ((my_floornormalP2.X != 0) || (my_floornormalP2.Y != 0) )) { // on a slope? // rotate the floor normal relative to the playerP2 MY_ANGLE.PAN = -MY.PAN; VECROTATE my_floornormalP2,MY_ANGLE; // calculate the destination tilt and roll angles MY_ANGLE.TILT = -ASIN(my_floornormalP2.X); MY_ANGLE.ROLL = -ASIN(my_floornormalP2.Y); } // change the playerP2 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 FORCEP2 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 SPEEDP2, and change his angles // -old method- ACCEL MY._ASPEEDP2,aFORCEP2,ang_fricP2; temp = min(TIME*ang_fricP2,1); MY._ASPEEDP2_PAN += (TIME * aFORCEP2.pan) - (temp * MY._ASPEEDP2_PAN); MY._ASPEEDP2_TILT += (TIME * aFORCEP2.tilt) - (temp * MY._ASPEEDP2_TILT); MY._ASPEEDP2_ROLL += (TIME * aFORCEP2.roll) - (temp * MY._ASPEEDP2_ROLL); temp = MY._ASPEEDP2_PAN * MY._SPEEDP2_X * 0.05; IF (MY.__WHEELSP2) { // Turn only if moving ahead //jcl 07-03-00 patch to fix movement MY.PAN += temp * TIME; } ELSE { MY.PAN += MY._ASPEEDP2_PAN * TIME; } MY.ROLL += (temp * MY._BANKINGP2 + MY._ASPEEDP2_ROLL) * TIME; // the head angle is only set on the playerP2 in a single playerP2 system. if (ME == playerP2) { head_angleP2.TILT += MY._ASPEEDP2_TILT * TIME; //jcl 07-03-00 end of patcht // limitP2 the TILT value head_angleP2.TILT = ANG(head_angleP2.TILT); IF (head_angleP2.TILT > 80) { head_angleP2.TILT = 80; } IF (head_angleP2.TILT < -80) { head_angleP2.TILT = -80; } } // disable strafing IF (MY.__STRAFEP2 == OFF) { FORCEP2.Y = 0; // no STRAFEP2 } // if SWIMMINGP2... IF (MY._MOVEMODEP2 == _MODE_SWIMMINGP2) { // move in water swim_gravityP2(); } ELSE // not SWIMMINGP2 { // if WADINGP2... IF (MY._MOVEMODEP2 == _MODE_WADINGP2) { wade_gravityP2(); } ELSE // not SWIMMINGP2 or WADINGP2 (not in water) { // DUCKINGP2 or CRAWLINGP2... IF ((MY._MOVEMODEP2 == _MODE_DUCKINGP2) || (MY._MOVEMODEP2 == _MODE_CRAWLINGP2)) { IF (FORCEP2.Z >= 0) { MY._MOVEMODEP2 = _MODE_WALKINGP2; } ELSE // STILLP2 DUCKINGP2 { // reduce height by DUCKINGP2 value my_heightP2 += DUCKP2_heightP2; } } ELSE // not DUCKINGP2 or CRAWLINGP2 { // if we have a DUCKINGP2 FORCEP2 and are not already DUCKINGP2 or CRAWLINGP2... IF ((FORCEP2.Z < 0) && (MY.__DUCKP2 == ON)) // dcp 7/28/00 added __DUCKP2 { // ...switch to DUCKINGP2 mode MY._MOVEMODEP2 = _MODE_DUCKINGP2; MY._ANIMDISTP2 = 0; FORCEP2.Z = 0; } } // Decide whether the actor can JUMPP2 or not. He can't if he is in the air IF ((JUMP_heightP2 <= 0) || (MY.__JUMPP2 == OFF) || (my_heightP2 > 4) || (FORCEP2.Z <= 0)) { FORCEP2.Z = 0; } // move on land move_gravityP2(); } // END (not in water) }// END not SWIMMINGP2 } // END not in 'STILLP2' mode // animate the actor actor_animP2(); // If I'm the only playerP2, draw the camera and weapon with ME IF (client_moving == 0) { move_view(); } carryP2(); // action synonym used to carryP2 items with the playerP2 (eg. a gun or sword) // Wait one tick, then repeat WAIT 1; } // END WHILE ((MY._MOVEMODEP2 > 0)&&(MY._MOVEMODEP2 <= _MODE_STILLP2)) } // 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 SPEEDP2 and aSPEEDP2 to camera_SPEEDP2 and camera_aSPEEDP2 // Movement is now time corrected ACTION camera_moveP2//??????????????????????????????????????????????????????????? { _camera = 1; WHILE (_camera == 1) { _playerP2_intentions(); // set FORCEP2 and aFORCEP2 value from user input // -old method- ACCEL aSPEEDP2,aFORCEP2,0.9; camera_aSPEEDP2.pan += (TIME * aFORCEP2.pan) - (0.9 * camera_aSPEEDP2.pan); camera_aSPEEDP2.tilt += (TIME * aFORCEP2.tilt) - (0.9 * camera_aSPEEDP2.tilt); camera_aSPEEDP2.roll += (TIME * aFORCEP2.roll) - (0.9 * camera_aSPEEDP2.roll); CAMERA.PAN += camera_aSPEEDP2.PAN * TIME; CAMERA.TILT += camera_aSPEEDP2.TILT * TIME; CAMERA.ROLL += camera_aSPEEDP2.ROLL * TIME; // Calculate camera's new SPEEDP2 // -old method- ACCEL SPEEDP2,FORCEP2,0.9; camera_SPEEDP2.x += (TIME * FORCEP2.x) - (0.9 * camera_SPEEDP2.x); camera_SPEEDP2.y += (TIME * FORCEP2.y) - (0.9 * camera_SPEEDP2.y); camera_SPEEDP2.z += (TIME * FORCEP2.z) - (0.9 * camera_SPEEDP2.z); // calculate relative distance distP2.x = camera_SPEEDP2.x * TIME; distP2.y = camera_SPEEDP2.y * TIME; distP2.z = camera_SPEEDP2.z * TIME; move_view CAMERA,distP2,NULLSKILL; WAIT 1; } } ///////////////////////////////////////////////////////////////////// // Core part of move action, common for actors and playerP2s function move_airborne() { MY._POWERP2 += 0.1*FORCEP2.Z; IF (MY._POWERP2 < 0) { MY._POWERP2 = 0; } IF (MY._POWERP2 > POWERP2_maxP2) { MY._POWERP2 = POWERP2_maxP2; } absFORCEP2.X = 0; absFORCEP2.Y = 0; absFORCEP2.Z = 0; frictionP2 = air_fricP2; FORCEP2.X = 0; FORCEP2.Y = 0; FORCEP2.Z = 0; } function anim_airborne() { // standing animation IF (MY._POWERP2 > 0) // engine running { MY._ANIMDISTP2 += TIME * MY._POWERP2; // wrap animation time to a value between zero and anim_stand_ticksP2 IF (MY._ANIMDISTP2 > anim_stand_ticksP2) { MY._ANIMDISTP2 -= anim_stand_ticksP2; } // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP2 / anim_stand_ticksP2; // set the frame from the percentage SET_CYCLE ME,anim_stand_strP2,temp; RETURN; } RETURN; } //////////////////////////////////////////////////////////////////////// // Desc: gravityP2 / buoyancy effect on the playerP2 in water (IN_PASSABLE) // this action should be called when the playerP2 is SWIMMINGP2 (_MODE_SWIMMINGP2) // // Created: 05/9/00 @ 863 by Doug Poston // // Mod Date: 5/10/00 @ 913 by Doug Poston // Added code to TILT the playerP2 (allowing them to dive and rise in water) // Mod Date: 5/18/00 by Doug Poston // Added code to drop playerP2 to the surface of the water // Mod Data: 5/24/00 Doug Poston // Using an 'offset sonar' (7 units) to check if the playerP2 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 _FALLTIMEP2 (no FALLP2ing damage is you land in water) // Mod Date: 6/27/00 Doug Poston // Replaced ACCEL // Mod Date: 6/28/00 Doug Poston // Modified gravityP2 check to handleP2 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 FORCEP2s are now completely TIME dependent // Mod Date: 7/22/00 JCL // Modified because of changes in scan_floorP2 // Mod Date: 8/31/00 DCP // Scale distP2 and absdistP2 by movement_scaleP2 before MOVE function swim_gravityP2() { frictionP2 = water_fricP2; // set frictionP2 to water frictionP2 MY._FALLTIMEP2 = 0; // no FALLP2ing damage in water // TILT the playerP2 if DIVINGP2 IF (FORCEP2.Z > 0) { MY.TILT += 3 * TIME; } IF (FORCEP2.Z < 0) { MY.TILT -= 3 * TIME; } MY.TILT = ANG (MY.TILT); // make sure angle stays between -180 and +180 /* NO absFORCEP2 needed in this swim_gravityP2 // reset absolute FORCEP2s absFORCEP2.X = 0; absFORCEP2.Y = 0; absFORCEP2.Z = 0; */ // SWIMMINGP2 - rhythmic acceleration FORCEP2.X *= 0.5 + (0.25*walkwaveP2); FORCEP2.Y *= 0.5; FORCEP2.Z = 0; // up and down handleP2d by entity's tilt in water // accelerate the entity relative SPEEDP2 by the FORCEP2 // -old method- ACCEL MY._SPEEDP2_X,FORCEP2,frictionP2; /* temp = min(TIME*frictionP2,1); MY._SPEEDP2_X += (TIME * FORCEP2.x) - (temp * MY._SPEEDP2_X); // vx = ax*dt - min(f*dt,1) * vx MY._SPEEDP2_Y += (TIME * FORCEP2.y) - (temp * MY._SPEEDP2_Y); // vy = ay*dt - min(f*dt,1) * vy MY._SPEEDP2_Z += (TIME * FORCEP2.z) - (temp * MY._SPEEDP2_Z); // vz = az*dt - min(f*dt,1) * vz */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP2),0); MY._SPEEDP2_X = (TIME * FORCEP2.x) + (temp * MY._SPEEDP2_X); // vx = ax*dt - min(f*dt,1) * vx MY._SPEEDP2_Y = (TIME * FORCEP2.y) + (temp * MY._SPEEDP2_Y); // vy = ay*dt - min(f*dt,1) * vy MY._SPEEDP2_Z = (TIME * FORCEP2.z) + (temp * MY._SPEEDP2_Z); // vz = az*dt - min(f*dt,1) * vz // calculate relative distances distP2.x = MY._SPEEDP2_X * TIME; // dx = vx * dt distP2.y = MY._SPEEDP2_Y * TIME; // dy = vy * dt distP2.z = MY._SPEEDP2_Z * TIME; // dz = vz * dt // use a 16 unit 'offset buffer' to test if we are STILLP2 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_floorP2 changed IF ((ON_PASSABLE == ON) && (my_heightP2 > MY.MIN_Z)) //&& (IN_PASSABLE ==0)) -> check not need in v4.193+ { // reset absolute distance absdistP2.x = 0; absdistP2.y = 0; absdistP2.z = 0; // if MY center is greater than the surface level... IF (((my_heightP2 - MY.MIN_Z) > 5))//??16))) // 5 = "float value" { // pull down to the surface of the water temp = (my_heightP2 - MY.MIN_Z) - 5; // difference between surface IF (temp > gravityP2) { temp = gravityP2; } absdistP2.Z -= temp; } // restrict DRIVINGP2 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 SPEEDP2 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP2,movement_scaleP2); // scale distance by movement_scaleP2 vec_scale(absdistP2,movement_scaleP2); // scale absolute distance by movement_scaleP2 MOVE ME,distP2,absdistP2; } ELSE // underwater { // NOTE: this is where we would add buoyancy (using absFORCEP2) // right now we are assuming zero buoyancy // NOTE: this is where we could add the effect of currents (using absFORCEP2) // Now move ME by the relative and the absolute SPEEDP2 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP2,movement_scaleP2); // scale distance by movement_scaleP2 MOVE ME,distP2,NULLSKILL; } // Store the distance covered, for animation my_distP2 = RESULT; // Store the distance for playerP2 1st person head BOBP2bing // (only for single playerP2 system) IF (ME == playerP2) { player_distP2 += MY._SPEEDP2_X;//SQRT(SPEEDP2.X*SPEEDP2.X + SPEEDP2.Y*SPEEDP2.Y); } } // Desc: WADINGP2 movement action // this action should be called when the playerP2 is WADINGP2 (_MODE_WADINGP2) // // Mod Date: 5/18/00 by Doug Poston // Created // Mod Date: 5/25/00 by Doug Poston // Adjusted ground elasticity (so it doesn't FORCEP2 playerP2 to swim) // Mod Date: 5/25/00 by Doug Poston // Adjust playerP2 FORCEP2 by water depth (slower the deeper the playerP2 is WADINGP2) // Mod Date: 5/29/00 Doug Poston // Change 'offset sonar' from 7 to 16 units // Mod Date: 6/19/00 Doug Poston // Reset _FALLTIMEP2 (no FALLP2ing 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 SPEEDP2 and distance are TIME dependent // Mod Date: 8/31/00 DCP // Scaled distP2 and absdistP2 by movement_scaleP2 before MOVE command function wade_gravityP2() { // basic frictionP2 frictionP2 = gnd_fricP2; MY._FALLTIMEP2 = 0; // reset FALLTIMEP2 (no FALLP2ing damage in water) //adjust playerP2 FORCEP2 depending on depth of water // MY.Z += 16; // SONAR MY,4000; // MY.Z -= 16; //jcl 07-22-00 scan_floorP2 changed temp = 1.0 - (my_heightP2 / min(-1,MY.MIN_Z)); // MY.min_z can be 0!! IF (temp < 0.1) // minimum SPEEDP2 { temp = 0.1; } FORCEP2.X *= temp; FORCEP2.Y *= temp; FORCEP2.Z *= temp; // reset absFORCEP2 absFORCEP2.X = 0; absFORCEP2.Y = 0; absFORCEP2.Z = 0; /* Old Method // If on a slope, apply gravityP2 to draw him downwards: IF (my_floornormalP2.Z < 0.85) { // FORCEP2 is less in water than on land absFORCEP2.X = my_floornormalP2.X * gravityP2 * 0.25; absFORCEP2.Y = my_floornormalP2.Y * gravityP2 * 0.25; // If slope too steep, really push him back temp = 0.66 - my_floornormalP2.Z; IF (temp > 0) { absFORCEP2.X *= 1.5; absFORCEP2.Y *= 1.5; } } */ // If on a slope, apply gravityP2 to draw him downwards: IF (my_floornormalP2.Z < 0.9) { // reduce ahead FORCEP2 because playerP2 FORCEP2 it is now deflected upwards FORCEP2.x *= my_floornormalP2.z; FORCEP2.y *= my_floornormalP2.z; // gravityP2 draws him down the slope (but only at 1/4 of above water) absFORCEP2.X = my_floornormalP2.x * gravityP2 * slopefacP2 * 0.25; absFORCEP2.Y = my_floornormalP2.y * gravityP2 * slopefacP2 * 0.25; } // -old method- ACCEL SPEEDP2,FORCEP2,frictionP2; /* temp = min(TIME*frictionP2,1); MY._SPEEDP2_X += (TIME * FORCEP2.x) - (temp * MY._SPEEDP2_X); // vx = ax*dt - min(f*dt, 1) * vx MY._SPEEDP2_Y += (TIME * FORCEP2.y) - (temp * MY._SPEEDP2_Y); // vy = ay*dt - min(f*dt, 1) * vy MY._SPEEDP2_Z += (TIME * absFORCEP2.z) - (temp * MY._SPEEDP2_Z); */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP2),0); MY._SPEEDP2_X = (TIME * FORCEP2.x) + (temp * MY._SPEEDP2_X); // vx = ax*dt + max(1-f*dt,0) * vx MY._SPEEDP2_Y = (TIME * FORCEP2.y) + (temp * MY._SPEEDP2_Y); // vy = ay*dt + max(1-f*dt,0) * vy MY._SPEEDP2_Z = (TIME * absFORCEP2.z) + (temp * MY._SPEEDP2_Z); // calculate relative distances distP2.x = MY._SPEEDP2_X * TIME; // dx = vx * dt distP2.y = MY._SPEEDP2_Y * TIME; // dy = vy * dt distP2.z = 0; // dz = 0 // calculate absolute distances absdistP2.x = absFORCEP2.x * TIME * TIME; // dx = ax * dt^2 absdistP2.y = absFORCEP2.y * TIME * TIME; // dy = ay * dt^2 absdistP2.z = 0; // NO JUMPINGP2 WHILE WADINGP2 // Add the SPEEDP2 given by the ground elasticity IF (my_heightP2 < -5) { temp = my_heightP2; IF (temp < -10) { temp = -10; } absdistP2.Z -= (temp - 5); } // Pull back down to the underwater surface // NOTE: this is taken care of by the playerP2 switching to SWIMMINGP2, then back to WADINGP2 // Now move ME by the relative and the absolute SPEEDP2 YOU = NULL; // YOU entity is considered passable by MOVE vec_scale(distP2,movement_scaleP2); // scale distance by movement_scaleP2 vec_scale(absdistP2,movement_scaleP2); // scale absolute distance by movement_scaleP2 MOVE ME,distP2,absdistP2; // Store the distance covered, for animation my_distP2 = RESULT; // Store the distance for playerP2 1st person head BOBP2bing // (only for single playerP2 system) IF (ME == playerP2) { player_distP2 = my_distP2; } } // Desc: calculate the damage taken by a FALLP2 // // Param: FALL_timeP2 and MY must be set before calling // // Note: override this function if you want to use a different formula function FALLP2_damage() { // calculate damage depending on _FALLTIMEP2 RETURN (10 + INT((MY._FALLTIMEP2 - FALL_timeP2) * 1.75)); } // Desc: on ground movement action // use when playerP2 is not SWIMMINGP2 or WADINGP2 // // Mod Date: 5/10/00 @ 942 by Doug Poston // Added code to switch to JUMPINGP2 mode when needed // Mod Date: 5/25/00 by Doug Poston // Split MOVE into two, so my_distP2 is now a function of playerP2 // movement only (ie. not effected by elevators or platforms) // Mod Date: 6/19/00 by Doug Poston // Added FALLP2ing damage. // _FALLTIMEP2 keeps track of the time spent FALLP2ing // if __FALLP2 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 SPEEDP2 and distance are TIME dependent // Mod Date: 7/18/00 DCP // Removed time dependence on FORCEP2s // Changed slope gravityP2 // Mod Date: 7/19/00 DCP // Changed JUMPINGP2 code so playerP2 always JUMPP2s to the same height // Mod Date: 8/10/00 JCL // Changed 'airborne' FORCEP2 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 FALLP2 damge formula with call to 'FALLP2_damage' // Mod Date: 8/31/00 DCP // Scale distP2 and absdistP2 by movement_scaleP2 before MOVE command function move_gravityP2() { // Filter the FORCEP2s and frictionP2s dependent on the STATEP2 of the actor, // and then apply them, and move him // First, decide whether the actor is standing on the floor or not IF (my_heightP2 < 5) { // Calculate FALLP2ing damage IF ((MY.__FALLP2 == ON) && (MY._FALLTIMEP2 > FALL_timeP2)) { MY._HEALTHP2 -= FALLP2_damage(); // take damage depending on FALL_timeP2 } MY._FALLTIMEP2 = 0; // reset FALLTIMEP2 frictionP2 = gnd_fricP2; IF (MY._MOVEMODEP2 == _MODE_DRIVINGP2) { // DRIVINGP2 - less frictionP2, less FORCEP2 frictionP2 *= 0.3; FORCEP2.X *= 0.3; } // reset absolute FORCEP2s absFORCEP2.X = 0; absFORCEP2.Y = 0; absFORCEP2.Z = 0; // If on a slope, apply gravityP2 to draw him downwards: IF (my_floornormalP2.Z < 0.9) { // reduce ahead FORCEP2 because playerP2 FORCEP2 it is now deflected upwards FORCEP2.x *= my_floornormalP2.z; FORCEP2.y *= my_floornormalP2.z; // gravityP2 draws him down the slope absFORCEP2.X = my_floornormalP2.x * gravityP2 * slopefacP2; absFORCEP2.Y = my_floornormalP2.y * gravityP2 * slopefacP2; } /* Old method IF (my_floornormalP2.Z < 0.85) { absFORCEP2.X = my_floornormalP2.X * gravityP2 * 2; absFORCEP2.Y = my_floornormalP2.Y * gravityP2 * 2; // If slope too steep, really push him back temp = 0.66 - my_floornormalP2.Z; IF (temp > 0) { absFORCEP2.X *= 3; absFORCEP2.Y *= 3; } } */ } ELSE // (my_heightP2 >= 5) { // airborne - reduce all relative FORCEP2s // to prevent him from JUMPINGP2 or further moving in the air frictionP2 = air_fricP2; //jcl 10-08-00 FORCEP2.X *= 0.2; // don't set the FORCEP2 completely to zero, otherwise FORCEP2.Y *= 0.2; // playerP2 could be stuck on top of a non-wmb entity FORCEP2.Z = 0; absFORCEP2.X = 0; absFORCEP2.Y = 0; // Add the world gravityP2 FORCEP2 absFORCEP2.Z = -gravityP2; // only FALLP2ing if moving downward IF (MY._SPEEDP2_Z <= 0) { MY._FALLTIMEP2 += TIME; // add FALLP2ing time } } // accelerate the entity relative SPEEDP2 by the FORCEP2 // -old method- ACCEL SPEEDP2,FORCEP2,frictionP2; /* temp = min(TIME*frictionP2,1); //_SPEEDP2_X,Y stores the relative XY SPEEDP2 MY._SPEEDP2_X += (TIME * FORCEP2.x) - (temp * MY._SPEEDP2_X); MY._SPEEDP2_Y += (TIME * FORCEP2.y) - (temp * MY._SPEEDP2_Y); //_SPEEDP2_Z stores the absolute Z SPEEDP2, accelerated by gravityP2 MY._SPEEDP2_Z += (TIME * absFORCEP2.z) - (temp * MY._SPEEDP2_Z); */ // replaced min with max (to eliminate 'creep') temp = max((1-TIME*frictionP2),0); MY._SPEEDP2_X = (TIME * FORCEP2.x) + (temp * MY._SPEEDP2_X); // vx = ax*dt + max(1-f*dt,0) * vx MY._SPEEDP2_Y = (TIME * FORCEP2.y) + (temp * MY._SPEEDP2_Y); // vy = ay*dt + max(1-f*dt,0) * vy MY._SPEEDP2_Z = (TIME * absFORCEP2.z) + (temp * MY._SPEEDP2_Z); // calculate relative distances to move distP2.x = MY._SPEEDP2_X * TIME; // dx = vx * dt distP2.y = MY._SPEEDP2_Y * TIME; // dy = vy * dt distP2.z = 0; // dz = 0 (only gravityP2 and JUMPINGP2) // calculate absolute distance to move absdistP2.x = absFORCEP2.x * TIME * TIME; // dx = ax*dt^2 absdistP2.y = absFORCEP2.y * TIME * TIME; // dy = ay*dt^2 absdistP2.z = MY._SPEEDP2_Z * TIME; // dz = vz*dt //jcl 07-22-00 // Add the SPEEDP2 given by the ground elasticity and the JUMPINGP2 FORCEP2 IF (my_heightP2 < 5) { // bring to ground level - only if slope not too steep //jcl 10-08-00 if (my_floornormalP2.Z > slopefacP2/4) { absdistP2.z = -max(my_heightP2,-10); } // if we have a JUMPINGP2 FORCEP2... if (FORCEP2.Z > 0) { // predict the initial SPEEDP2 required to reach the JUMPP2 height // v = a*t; s = a/2*t*t; -> v = sqrt(2*a*s) MY._SPEEDP2_Z = sqrt((JUMP_heightP2-my_heightP2)*2*gravityP2); absdistP2.z = MY._SPEEDP2_Z * TIME; // ...switch to JUMPINGP2 mode MY._MOVEMODEP2 = _MODE_JUMPINGP2; MY._ANIMDISTP2 = 0; } // If the actor is standing on a moving platform, add it's horizontal displacement absdistP2.X += my_floorSPEEDP2.X; absdistP2.Y += my_floorSPEEDP2.Y; } // Restrict the vertical distance to the maximum JUMPINGP2 height IF ((MY.__JUMPP2 == ON) && (absdistP2.z > 0) && (absdistP2.z + my_heightP2 > JUMP_heightP2)) { absdistP2.z = max(JUMP_heightP2 - my_heightP2,0); } // Now move ME by the relative and the absolute SPEEDP2 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,SPEEDP2,abSPEEDP2; vec_scale(distP2,movement_scaleP2); // scale distance by movement_scaleP2 MOVE ME,distP2,NULLVECTOR; // Store the distance covered, for animation my_distP2 = RESULT; vec_scale(absdistP2,movement_scaleP2); // scale absolute distance by movement_scaleP2 MOVE ME,NULLVECTOR,absdistP2; // Store the distance for playerP2 1st person head BOBP2bing // (only for single playerP2 system) IF (ME == playerP2) { player_distP2 += SQRT(distP2.X*distP2.X + distP2.Y*distP2.Y); } //jcl 07-03-00 end of patch } // Desc: set up for animation // scale entity by actor_scaleP2 // 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 playerP2 by vec_scale function anim_initP2() { vec_scale(MY.SCALE_X,actor_scaleP2); temp = FRC(MY._WALKFRAMESP2) * 1000; IF (temp != 0) { // old style animation MY._WALKFRAMESP2 = INT(MY._WALKFRAMESP2); IF (MY._WALKFRAMESP2 == 0) { MY._WALKFRAMESP2 = 13; } MY._WALKDISTP2 = MY._WALKFRAMESP2 / temp; temp = FRC(MY._RUNFRAMESP2) * 1000; MY._RUNFRAMESP2 = INT(MY._RUNFRAMESP2); IF (MY._RUNFRAMESP2 == 0) { MY._RUNFRAMESP2 = 5; } MY._RUNDISTP2 = MY._RUNFRAMESP2 / temp; } } // Desc: play some kinds of foot SOUND // // Mod Date: 6/9/00 Doug Poston // changed to function function _play_walkSOUND() { IF ((ME == playerP2) && (person_3rdP2 == 0)) { RETURN; } // don't play entity SOUNDs for 1st person playerP2 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 WALKINGP2 actor, depending on distP2 // covered (my_distP2) // // Mod Date: 5/9/00 @ 812 Doug Poston // Added SWIMMINGP2 animation // Mod Date: 5/10/00 @ 970 Doug Poston // Added JUMPINGP2 animation // Mod Date: 5/11/00 @ 795 by Doug Poston // Added DUCKINGP2 and CRAWLINGP2 animations // Mod Date: 5/23/00 Doug Poston // Added code to check for backwards motion (using FORCEP2.X) // Mod Date: 6/23/00 Doug Poston // Added code for ATTACKP2 animations // Mod Date: 6/27/00 Doug Poston // Modified ATTACKP2 animation code to only work for playerP2 animation // Mod Date: 8/31/00 DCP // Modified walk_or_runP2 var by movement_scaleP2 function actor_animP2() { // decide whether it's a frame number (old) or frame name (new) animation IF (FRC(MY._WALKFRAMESP2) > 0) { goto old_style_anim; } // START NEW STYLE ANIMATIONS (frame names) // Check to see if playerP2 is ATTACKP2ing IF (( ME == playerP2) && (MY._FIREMODEP2 != 0)) { // if you have more than one ATTACKP2ing animation, here's where you would test for it... // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP2 / anim_ATTACKP2_ticksP2; // set the frame from the percentage SET_FRAME ME,anim_ATTACKP2_strP2,temp; // increment _ANIMDISTP2 by elapsed time MY._ANIMDISTP2 += TIME; // check to see if we finished the ATTACKP2 animation IF (MY._ANIMDISTP2 > anim_ATTACKP2_ticksP2) { MY._ANIMDISTP2 = 0; // reset animation distance MY._FIREMODEP2 = 0; // reset FIREMODEP2 } RETURN; } ELSE // not firing { ///////////////////////////////////////////////////////////////////// // Animations that can take place standing STILLP2 (JUMPINGP2, DUCKINGP2, etc.) ///////////////////////////////////////////////////////////////////// // the JUMPINGP2 animation IF (MY._MOVEMODEP2 == _MODE_JUMPINGP2) { // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP2 / anim_jump_ticks; // set the frame from the percentage SET_FRAME ME,anim_JUMP_str,temp; // increment _ANIMDISTP2 by elapsed time MY._ANIMDISTP2 += TIME; // check to see if we finished JUMPP2 animation IF (MY._ANIMDISTP2 > anim_jump_ticks) { MY._ANIMDISTP2 = 0; MY._MOVEMODEP2 = _MODE_WALKINGP2; } RETURN; } // the DUCKINGP2 animation IF (MY._MOVEMODEP2 == _MODE_DUCKINGP2) { // you can only DUCKP2 at WALKINGP2 SPEEDP2s or below. IF (my_distP2 >= walk_or_runP2*TIME*movement_scaleP2) // to fast to DUCKP2? { MY._MOVEMODEP2 = _MODE_WALKINGP2; // catch the WALKINGP2 mode below this one } ELSE { // DUCKINGP2 // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP2 / anim_DUCKP2_ticksP2; // set the frame from the percentage SET_FRAME ME,anim_DUCKP2_strP2,temp; // increment _ANIMDISTP2 by elapsed time MY._ANIMDISTP2 += TIME; // check to see if we finished DUCKINGP2 IF (MY._ANIMDISTP2 > anim_DUCKP2_ticksP2) { MY._ANIMDISTP2 = 0; MY._MOVEMODEP2 = _MODE_CRAWLINGP2; } RETURN; } } // the CRAWLINGP2 animation IF (MY._MOVEMODEP2 == _MODE_CRAWLINGP2) { // you can only crawl at WALKINGP2 SPEEDP2s or below. IF (my_distP2 >= walk_or_runP2*TIME*movement_scaleP2) // to fast to crawl? { MY._MOVEMODEP2 = _MODE_WALKINGP2; // catch the WALKINGP2 mode below this one } ELSE { // CRAWLINGP2 // set the distance covered, in percent of the model width covered_distP2 = MY._WALKDISTP2 + my_distP2 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP2 > anim_crawl_distP2) { covered_distP2 -= anim_crawl_distP2; } IF (FORCEP2.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP2 / anim_crawl_distP2; SET_CYCLE ME,anim_crawl_strP2,temp; MY._WALKDISTP2 = covered_distP2; // save for next 'frame' of animation RETURN; } } // the SWIMMINGP2 animation IF (MY._MOVEMODEP2 == _MODE_SWIMMINGP2) { // set the distance covered, in percent of the model width covered_distP2 = MY._WALKDISTP2 + my_distP2 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP2 > anim_swim_distP2) { covered_distP2 -= anim_swim_distP2; } IF (FORCEP2.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP2 / anim_swim_distP2; SET_CYCLE ME,anim_swim_strP2,temp; MY._WALKDISTP2 = covered_distP2; // save for next 'frame' of animation RETURN; } // the WADINGP2 animation IF (MY._MOVEMODEP2 == _MODE_WADINGP2) { // set the distance covered, in percent of the model width covered_distP2 = MY._WALKDISTP2 + my_distP2 / (MY.MAX_X-MY.MIN_X); // calculate the real cycle distance from the model size WHILE (covered_distP2 > anim_wade_distP2) { covered_distP2 -= anim_wade_distP2; } IF (FORCEP2.X < 0) // moving backwards? { temp = 100 - temp; } temp = 100 * covered_distP2 / anim_wade_distP2; SET_CYCLE ME,anim_wade_strP2,temp; MY._WALKDISTP2 = covered_distP2; // save for next 'frame' of animation RETURN; } // the standing STILLP2 animation // NOTE: the must be *before* _MODE_WALKINGP2 but after any other mode // that can animate while the playerP2 is not moving (SWIMMINGP2, // DUCKINGP2, JUMPINGP2, etc.) IF ((my_distP2 < 0.01) || (MY._MOVEMODEP2 == _MODE_STILLP2)) { MY._ANIMDISTP2 += TIME; // wrap animation time to a value between zero and anim_stand_ticksP2 IF (MY._ANIMDISTP2 > anim_stand_ticksP2) { MY._ANIMDISTP2 -= anim_stand_ticksP2; } // calculate a percentage out of the animation time temp = 100 * MY._ANIMDISTP2 / anim_stand_ticksP2; // set the frame from the percentage SET_CYCLE ME,anim_stand_strP2,temp; RETURN; } // WALKINGP2 animation IF (MY._MOVEMODEP2 == _MODE_WALKINGP2) { // set the distance covered, in percent of the model width covered_distP2 = MY._WALKDISTP2 + my_distP2 / (MY.MAX_X-MY.MIN_X); // decide whether to play the walk or run animation IF (my_distP2 < walk_or_runP2*TIME*movement_scaleP2) // WALKINGP2 { anim_distP2 = anim_walk_distP2; anim_strP2 = anim_walk_strP2; } ELSE { // running anim_distP2 = anim_run_distP2; anim_strP2 = anim_run_strP2; } // calculate the real cycle distance from the model size IF (covered_distP2 > anim_distP2) { covered_distP2 -= anim_distP2; } temp = 100 * covered_distP2 / anim_distP2; IF (FORCEP2.X < 0) // moving backwards? { temp = 100 - temp; } SET_CYCLE ME,anim_strP2,temp; if (covered_distP2 < MY._WALKDISTP2) { _play_walkSOUND(); // SOUND for right foot } if ((covered_distP2 > anim_distP2*0.5) && (MY._WALKDISTP2 < anim_distP2*0.5)) { _play_walkSOUND(); // SOUND for left foot } MY._WALKDISTP2 = covered_distP2; RETURN; } RETURN; // END OF NEW STYLE ANIMATIONS (frame names) } IF ((MY._MOVEMODEP2 == _MODE_STILLP2) || (my_distP2 < 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._MOVEMODEP2 == _MODE_WALKINGP2) { // decide whether to play the walk or run animation IF ((MY._RUNFRAMESP2 <= 0) || (my_distP2 < walk_or_runP2*TIME*movement_scaleP2)) // WALKINGP2 { IF (MY.FRAME < 2) { MY.FRAME = 2; } MY.FRAME += MY._WALKDISTP2*my_distP2; // this is one of the expert exceptions where you can use WHILE without WAIT! WHILE (MY.FRAME >= 2 + MY._WALKFRAMESP2) { // SOUND for right foot IF (MY.__SOUND == ON) { _play_walkSOUND(); MY.__SOUND = OFF; } // cycle the animation MY.FRAME -= MY._WALKFRAMESP2; } IF (MY.FRAME > 1 + MY._WALKFRAMESP2*0.5) { // SOUND for left foot IF (MY.__SOUND == OFF) { _play_walkSOUND(); MY.__SOUND = ON; } } IF (MY.FRAME > 1 + MY._WALKFRAMESP2) { MY.NEXT_FRAME = 2; // inbetween to the first WALKINGP2 frame } ELSE { MY.NEXT_FRAME = 0; // inbetween to the real next frame } RETURN; } ELSE { // Running IF (MY.FRAME < 2 + MY._WALKFRAMESP2) { MY.FRAME = 2 + MY._WALKFRAMESP2; } MY.FRAME += MY._RUNDISTP2*my_distP2; WHILE (MY.FRAME >= 2 + MY._WALKFRAMESP2 + MY._RUNFRAMESP2) { IF (MY.__SOUND == ON) { _play_walkSOUND(); MY.__SOUND = OFF; } MY.FRAME -= MY._RUNFRAMESP2; } IF (MY.FRAME > 1 + MY._WALKFRAMESP2 + MY._RUNFRAMESP2*0.5) { IF (MY.__SOUND == OFF) { _play_walkSOUND(); MY.__SOUND = ON; } } IF (MY.FRAME > 1 + MY._WALKFRAMESP2 + MY._RUNFRAMESP2) { MY.NEXT_FRAME = 2 + MY._WALKFRAMESP2; } 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 DUCKINGP2 and CRAWLINGP2 // 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 SWIMMINGP2 at any height function move_view_1stP2() { IF (_camera == 0) // If the camera does not move itself { IF (my_heightP2 < 5 || (playerP2._MOVEMODEP2 == _MODE_SWIMMINGP2) ) { // use headwaveP2 = SIN(player_distP2*walk_rateP2); IF ((playerP2._MOVEMODEP2 == 0) // moving on client? || (playerP2._MOVEMODEP2 == _MODE_WALKINGP2)) { // Play the right and left foot SOUND IF (((headwaveP2 > 0) && (walkwaveP2 <= 0)) || ((headwaveP2 <= 0) && (walkwaveP2 > 0))) { PLAY_SOUND thud,30; } // head BOBP2bing walkwaveP2 = headwaveP2; headwaveP2 = walk_amplP2*(ABS(headwaveP2)-0.5); } IF (playerP2._MOVEMODEP2 == _MODE_SWIMMINGP2) { IF ((headwaveP2 > 0) && (walkwaveP2 <= 0)) { PLAY_SOUND splash,30; } // in-water wave movement walkwaveP2 = headwaveP2; headwaveP2 = wave_amplP2*SIN(TOTAL_TICKS*wave_rateP2); head_angleP2.TILT += 0.1*wave_amplP2*SIN(TOTAL_TICKS*wave_rateP2 - 60); } } CAMERA.DIAMETER = 0; // make the camera passable CAMERA.GENIUS = playerP2; // don't display parts of ME CAMERA.X = playerP2.X; CAMERA.Y = playerP2.Y; CAMERA.Z = playerP2.Z + playerP2.MIN_Z; IF (playerP2.__BOBP2 == ON) { CAMERA.Z += headwaveP2; } IF (playerP2._MOVEMODEP2 == _MODE_SWIMMINGP2) { // adjust eye height for SWIMMINGP2 CAMERA.Z += (playerP2.MAX_Z-playerP2.MIN_Z)*eye_height_downP2; } ELSE { IF ((playerP2._MOVEMODEP2 == _MODE_DUCKINGP2) || (playerP2._MOVEMODEP2 == _MODE_CRAWLINGP2)) { // adjust eye height for DUCKINGP2 and CRAWLINGP2 CAMERA.Z += (playerP2.MAX_Z-playerP2.MIN_Z)*eye_height_DUCKP2; } ELSE { // adjust eye height for 'normal' modes CAMERA.Z += (playerP2.MAX_Z-playerP2.MIN_Z)*eye_height_upP2; } } CAMERA.PAN = playerP2.PAN; CAMERA.TILT = playerP2.TILT + head_angleP2.TILT; CAMERA.ROLL = playerP2.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_3rdP2 = 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_3rdP2() { if ((_camera == 0) && (playerP2 != NULL)) { CAMERA.DIAMETER = 0; // make the camera passable CAMERA.genius = playerP2; CAMERA.pan += 0.2 * ang(playerP2.pan-CAMERA.pan); // tilt the camera differently if we are using a vehicle if ( (playerP2._MOVEMODEP2 == _MODE_PLANEP2) ||(playerP2._MOVEMODEP2 == _MODE_CHOPPERP2)) { CAMERA.tilt += 0.2 * ang(playerP2.tilt-CAMERA.tilt); } else { // WALKINGP2, SWIMMINGP2 etc. CAMERA.tilt = head_angleP2.tilt-5; if((person_3rdP2 < 1) && (camera_distP2.Z == 0)) // switching to 3rd person { camera_distP2.Z = - playerP2.MAX_Z; } } vec_set(temp,temp_cdistP2); // temp = temp_cdistP2 VECROTATE temp,playerP2.PAN; CAMERA.X += 0.3*(playerP2.X - temp.X - CAMERA.X); CAMERA.Y += 0.3*(playerP2.Y - temp.Y - CAMERA.Y); CAMERA.Z += 0.3*(playerP2.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_cdistP2.X *= 0.7; // place it closer to the playerP2 temp_cdistP2.Y *= 0.7; temp_cdistP2.Z *= 0.7; } else { temp_cdistP2.X += 0.2*(playerP2.MAX_X + camera_distP2.X - temp_cdistP2.X); temp_cdistP2.Y += 0.2*(playerP2.MAX_Y + camera_distP2.Y - temp_cdistP2.Y); temp_cdistP2.Z += 0.2*(playerP2.MAX_Z + camera_distP2.Z - temp_cdistP2.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_3rdP2 = 1; } } function move_view() { IF (playerP2 == NULL) { playerP2 = ME; } // this action needs the playerP2 synonym IF (playerP2 == NULL) { RETURN; } // STILLP2 no playerP2 -> can't work IF (person_3rdP2 > 0) { // This skill should be local move_view_3rdP2(); } ELSE { move_view_1stP2(); } } // Desc: create a shadow below the entity ACTION drop_shadowP2 { IF (VIDEO_DEPTH >= 16) { CREATE SHADOWSPRITE,MY.POS,move_shadowP2; } ELSE { CREATE SHADOWFLAT,MY.POS,move_shadowP2; } } // Desc: function used to move shadow // // Mod Date: 05/29/00 // Added check for SWIMMINGP2 or WADINGP2 (no shadow) // Mod Date: 7/30/00 JCL // Made shadow darker + adapted to floor slope function move_shadowP2() { 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._MOVEMODEP2 == _MODE_SWIMMINGP2) || (YOU._MOVEMODEP2 == _MODE_WADINGP2)) { MY.invisible = ON; } else { MY.invisible = OFF; temp_entP2 = YOU; SONAR temp_entP2,500; // get height above the floor YOU = temp_entP2; // 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 playerP2 // // Set aFORCEP2 & FORCEP2 values using playerP2 input (keyboard/mouse/joystick) // Make sure these values are within limitP2 // // Mod Date: 6/9/00 Doug Poston // changed from ACTION to function function _playerP2_intentions() { // Set the angular FORCEP2s according to the playerP2 intentions aFORCEP2.PAN = -astrengthP2.PAN*(KEY_D-KEY_A);//+JOY_FORCE.X aFORCEP2.TILT = astrengthP2.TILT*(KEY_G-KEY_B); IF (MOUSE_MODE == 0) { // Mouse switched off? aFORCEP2.PAN += -astrengthP2.PAN*MOUSE_FORCE.X*mouseviewP2; aFORCEP2.TILT += astrengthP2.TILT*MOUSE_FORCE.Y*mouseviewP2; } aFORCEP2.ROLL = 0; // Set ROLL FORCEP2 if ALT was pressed IF (KEY_ALT != 0) { aFORCEP2.ROLL = aFORCEP2.PAN; aFORCEP2.PAN = 0; } // Double the forces in case the playerP2 pressed F IF (KEY_F != 0) { aFORCEP2.PAN += aFORCEP2.PAN; aFORCEP2.TILT += aFORCEP2.TILT; aFORCEP2.ROLL += aFORCEP2.ROLL; } // limitP2 the FORCEP2s in case the playerP2 // pressed buttons, mouse and joystick simultaneously limitP2.PAN = 2*astrengthP2.PAN; limitP2.TILT = 2*astrengthP2.TILT; limitP2.ROLL = 2*astrengthP2.ROLL; IF (aFORCEP2.PAN > limitP2.PAN) { aFORCEP2.PAN = limitP2.PAN; } IF (aFORCEP2.PAN < -limitP2.PAN) { aFORCEP2.PAN = -limitP2.PAN; } IF (aFORCEP2.TILT > limitP2.TILT) { aFORCEP2.TILT = limitP2.TILT; } IF (aFORCEP2.TILT < -limitP2.TILT) { aFORCEP2.TILT = -limitP2.TILT; } IF (aFORCEP2.ROLL > limitP2.ROLL) { aFORCEP2.ROLL = limitP2.ROLL; } IF (aFORCEP2.ROLL < -limitP2.ROLL) { aFORCEP2.ROLL = -limitP2.ROLL; } // Set the cartesian FORCEP2s according to the playerP2 intentions FORCEP2.X = strengthP2.X*(KEY_W-KEY_S);//+JOY_FORCE.Y FORCEP2.Y = strengthP2.Y*(KEY_1-KEY_2); FORCEP2.Z = strengthP2.Z*(KEY_C-KEY_V); IF (MOUSE_MODE == 0) { // Mouse switched off? FORCEP2.X += strengthP2.X*MOUSE_RIGHT*mouseviewP2; } // Double the FORCEP2s in case the playerP2 pressed F IF (KEY_F != 0) { FORCEP2.X += FORCEP2.X; FORCEP2.Y += FORCEP2.Y; FORCEP2.Z += FORCEP2.Z; } // limitP2 the FORCEP2s in case the playerP2 tried to cheat by // operating buttons, mouse and joystick simultaneously limitP2.X = 2*strengthP2.X; limitP2.Y = 2*strengthP2.Y; limitP2.Z = 2*strengthP2.Z; IF (FORCEP2.X > limitP2.X) { FORCEP2.X = limitP2.X; } IF (FORCEP2.X < -limitP2.X) { FORCEP2.X = -limitP2.X; } IF (FORCEP2.Y > limitP2.Y) { FORCEP2.Y = limitP2.Y; } IF (FORCEP2.Y < -limitP2.Y) { FORCEP2.Y = -limitP2.Y; } IF (FORCEP2.Z > limitP2.Z) { FORCEP2.Z = limitP2.Z; } IF (FORCEP2.Z < -limitP2.Z) { FORCEP2.Z = -limitP2.Z; } } // Desc: set FORCEP2 and aFORCEP2 values // these values come from _playerP2_intentions (single playerP2) // or from the client (multiplayerP2) // // Calls: _playerP2_intentions // // Mod Date: 6/9/00 Doug Poston // changed to function function _player_FORCEP2() { // If the camera does not move itself if (_camera == 0) { // multiplayerP2 mode if (client_moving) { // get FORCEP2s from server FORCEP2.X = MY._FORCEP2_X; FORCEP2.Y = MY._FORCEP2_Y; FORCEP2.Z = MY._FORCEP2_Z; aFORCEP2.PAN = MY._AFORCEP2_PAN; aFORCEP2.TILT = MY._AFORCEP2_TILT; aFORCEP2.ROLL = MY._AFORCEP2_ROLL; } else { // get FORCEP2s from user input _playerP2_intentions(); } aFORCEP2.PAN *= MY._FORCEP2; aFORCEP2.TILT *= MY._FORCEP2; aFORCEP2.ROLL *= MY._FORCEP2; FORCEP2.X *= MY._FORCEP2; FORCEP2.Y *= MY._FORCEP2; FORCEP2.Z *= MY._FORCEP2; } else { // playerP2 controls camera - set actor FORCEP2s to zero aFORCEP2.PAN = 0; aFORCEP2.TILT = 0; aFORCEP2.ROLL = 0; FORCEP2.X = 0; FORCEP2.Y = 0; FORCEP2.Z = 0; } } // Desc: used in multiplayerP2 (client/server) games // set client_moving var to 1 // take user input use that to adjust the 'playerP2' FORCEP2s // SEND playerP2 FORCEP2s to the server // move the camera // // Call: _playerP2_intentions // move_view function client_move()//??????????????????????????????????????????????????????? { client_moving = 1; WHILE (1) { _playerP2_intentions();// user key/mouse input sets FORCEP2 and aFORCEP2 values // playerP2 created on the client? if (playerP2) { playerP2._FORCEP2_X = FORCEP2.X; playerP2._FORCEP2_Y = FORCEP2.Y; playerP2._FORCEP2_Z = FORCEP2.Z; playerP2._AFORCEP2_PAN = aFORCEP2.PAN; playerP2._AFORCEP2_TILT = aFORCEP2.TILT; playerP2._AFORCEP2_ROLL = aFORCEP2.ROLL; // send playerP2 FORCEP2s to server SEND playerP2._FORCEP2_X; SEND playerP2._FORCEP2_Y; SEND playerP2._FORCEP2_Z; SEND playerP2._AFORCEP2_PAN; SEND playerP2._AFORCEP2_TILT; SEND playerP2._AFORCEP2_ROLL; // move the camera move_view(); } WAIT 1; } } ///////////////////////////////////////////////////////////////////// function toggle_personP2() { IF (person_3rdP2 > 0) { person_3rdP2 = 0; } ELSE { person_3rdP2 = 0.5; } } ///////////////////////////////////////////////////////////////////// // Auxiliary actions // values set in scan_floorP2 var on_passable_;//?????????????????????????????????????????????????????? var in_passable_; var in_solid_; // Desc: scan for a surface below the ME entity // set my_floornormalP2 vector to the normal of the surface // set my_heightP2 to the distance between ME.MIN_Z and the surface // set floorSPEEDP2 to the X & Y SPEEDP2 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_floorP2() { 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_floornormalP2.X = NORMAL.X; // set my_floornormalP2 to the normal of the surface my_floornormalP2.Y = NORMAL.Y; my_floornormalP2.Z = NORMAL.Z; my_heightP2 = RESULT; // set my_heightP2 to the distance between entity's MIN_Z and surface my_floorSPEEDP2.X = 0; // reset floorSPEEDP2 to zero my_floorSPEEDP2.Y = 0; // if the playerP2 is standing on a platform, move him with it IF (YOU != NULL) { IF (YOUR._TYPE == _TYPE_ELEVATOR) { my_floorSPEEDP2.X = YOUR._SPEEDP2_X; my_floorSPEEDP2.Y = YOUR._SPEEDP2_Y; // Z SPEEDP2 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: pP2 (distance) // Output: MY_POS function set_pos_aheadP2() { temp.X = COS(CAMERA.PAN); temp.Y = SIN(CAMERA.PAN); temp.Z = pP2*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 + pP2*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_xyzP2() { VECROTATE MY_POS,CAMERA.PAN; IF (person_3rdP2 != 0) { MY_POS.X += playerP2.X; MY_POS.Y += playerP2.Y; MY_POS.Z += playerP2.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; }//???????????????????????????????????????????????????? ////////////////////////////////////////////////////////////////////////??????????????????????????????????? // handleP2 action. Set to SPACE by default. // Will operate doors or items within 200 quants. VAR indicator = 0; DEFINE _handleP2,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 handleP2 { IF (playerP2 != NULL) { MY_POS.X = playerP2.X; MY_POS.Y = playerP2.Y; MY_POS.Z = playerP2.Z; MY_ANGLE.PAN = playerP2.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_handleP2(); } // Desc: scan a wide cone of 200 quants range function scan_handleP2() { temp.PAN = 120; temp.TILT = 180; temp.Z = 200; indicator = _handleP2; SCAN MY_POS,MY_ANGLE,temp; } // Desc: This action can be run by a playerP2 entity on the server // It checks for receiving a handleP2 SIGNALP2, then performs a scan function perform_handleP2() { WHILE (1) { IF (MY._SIGNALP2 == _handleP2) { // client has pressed handleP2 key MY.HIDDEN = ON; MY._SIGNALP2 = 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_handleP2(); } WAIT 1; } } function send_handleP2() { IF (playerP2 != NULL) { playerP2._SIGNALP2 = _handleP2; // send command to perform a scan SEND playerP2._SIGNALP2; } } ///////////////////////////////////////////////////////////////////// ON_5 toggle_personP2; ON_4 send_handleP2; /////////////////////////////////////////////////////////////////////