//----------------------------------------------------------------------------- // // $Logfile:: /Quake 2 Engine/Sin/code/game/mover.cpp $ // $Revision:: 18 $ // $Author:: Jimdose $ // $Date:: 10/24/98 8:30p $ // // Copyright (C) 1997 by Ritual Entertainment, Inc. // All rights reserved. // // This source is may not be distributed and/or modified without // expressly written permission by Ritual Entertainment, Inc. // // $Log:: /Quake 2 Engine/Sin/code/game/mover.cpp $ // // 18 10/24/98 8:30p Jimdose // fixed door revolving bug // // 17 9/03/98 9:08p Jimdose // Added checks for negative speeds in MoveTo // // 16 8/29/98 9:44p Jimdose // Made SV_ commands begin with G_ // // 15 5/03/98 4:36p Jimdose // Changed Vector class // // 14 4/06/98 6:42p Jimdose // the minimum movetime is now FRAMETIME so that we don't get into any infinite // loops with scripts // // 13 4/05/98 1:58a Jimdose // Mover now only modifies avelocity if there's angular movement and velocity // if there's translational movement. This allows us to move and have // continual rotation // // 12 3/24/98 5:00p Jimdose // Made MoveDone post a new EV_MoveDone instead of postponing the old one // (which had already been executed, oops!) // // 11 3/23/98 1:31p Jimdose // Revamped event and command system // // 10 3/11/98 2:24p Jimdose // Now quantize movetimes to nearest multiple of FRAMETIME // // 9 3/02/98 8:49p Jimdose // Changed the classid parameter of CLASS_DECLARATION to a quoted string so // that you could have a NULL classid. // // 8 2/21/98 1:12p Jimdose // Fixed bug where EVENT_MOVEDONE was allowing the event to pass to the // superclass // // 7 2/18/98 8:01p Jimdose // Pending EVENT_MOVEDONEs are cancelled when starting a new move. // // 6 2/16/98 2:12p Jimdose // Made MoveDone do a PushMove instead of a setOrigin so that blocking works // correctly at the end of moves // // 5 2/03/98 10:45a Jimdose // Updated to work with Quake 2 engine // Made changeover from hackthinker to events // // 3 10/27/97 3:29p Jimdose // Removed dependency on quakedef.h // // 2 9/26/97 5:23p Jimdose // Added standard Ritual headers // // DESCRIPTION: // Base class for any object that needs to move to specific locations over a // period of time. This class is kept separate from most entities to keep // class size down for objects that don't need such behavior. // #include "g_local.h" #include "entity.h" #include "trigger.h" #include "mover.h" #define MOVE_ANGLES 1 #define MOVE_ORIGIN 2 CLASS_DECLARATION( Trigger, Mover, "mover" ); ResponseDef Mover::Responses[] = { { &EV_MoveDone, ( Response )Mover::MoveDone }, { NULL, NULL } }; EXPORT_FROM_DLL void Mover::MoveDone ( Event *ev ) { Vector move; Vector amove; // zero out the movement if ( moveflags & MOVE_ANGLES ) { avelocity = vec_zero; amove = angledest - angles; } else { amove = vec_zero; } if ( moveflags & MOVE_ORIGIN ) { velocity = vec_zero; move = finaldest - origin; } else { move = vec_zero; } if ( !G_PushMove( this, move, amove ) ) { // Delay finish till we can move into the final position PostEvent( EV_MoveDone, FRAMETIME ); return; } // // After moving, set origin to exact final destination // if ( moveflags & MOVE_ORIGIN ) { setOrigin( finaldest ); } if ( moveflags & MOVE_ANGLES ) { angles = angledest; if ( ( angles.x >= 360 ) || ( angles.x < 0 ) ) { angles.x -= ( (int)angles.x / 360 ) * 360; } if ( ( angles.y >= 360 ) || ( angles.y < 0 ) ) { angles.y -= ( (int)angles.y / 360 ) * 360; } if ( ( angles.z >= 360 ) || ( angles.z < 0 ) ) { angles.z -= ( (int)angles.z / 360 ) * 360; } } ProcessEvent( endevent ); } /* ============= MoveTo calculate self.velocity and self.nextthink to reach dest from self.origin traveling at speed =============== */ EXPORT_FROM_DLL void Mover::MoveTo ( Vector tdest, Vector angdest, float tspeed, Event &event ) { Vector vdestdelta; Vector angdestdelta; float len; float traveltime; assert( tspeed >= 0 ); if ( !tspeed ) { error( "MoveTo", "No speed is defined!" ); } if ( tspeed < 0 ) { error( "MoveTo", "Speed is negative!" ); } // Cancel previous moves CancelEventsOfType( EV_MoveDone ); moveflags = 0; endevent = event; finaldest = tdest; angledest = angdest; if ( finaldest != origin ) { moveflags |= MOVE_ORIGIN; } if ( angledest != angles ) { moveflags |= MOVE_ANGLES; } if ( !moveflags ) { // stop the object from moving velocity = vec_zero; avelocity = vec_zero; // post the event so we don't wait forever PostEvent( EV_MoveDone, FRAMETIME ); return; } // set destdelta to the vector needed to move vdestdelta = tdest - origin; angdestdelta = angdest - angles; if ( tdest == origin ) { // calculate length of vector based on angles len = angdestdelta.length(); } else { // calculate length of vector based on distance len = vdestdelta.length(); } // divide by speed to get time to reach dest traveltime = len / tspeed; // Quantize to FRAMETIME traveltime *= ( 1 / FRAMETIME ); traveltime = ( float )( (int)traveltime ) * FRAMETIME; if ( traveltime < FRAMETIME ) { traveltime = FRAMETIME; vdestdelta = vec_zero; angdestdelta = vec_zero; } // scale the destdelta vector by the time spent traveling to get velocity if ( moveflags & MOVE_ORIGIN ) { velocity = vdestdelta * ( 1 / traveltime ); } if ( moveflags & MOVE_ANGLES ) { avelocity = angdestdelta * ( 1 / traveltime ); } PostEvent( EV_MoveDone, traveltime ); } /* ============= LinearInterpolate =============== */ EXPORT_FROM_DLL void Mover::LinearInterpolate ( Vector tdest, Vector angdest, float time, Event &event ) { Vector vdestdelta; Vector angdestdelta; float t; endevent = event; finaldest = tdest; angledest = angdest; // Cancel previous moves CancelEventsOfType( EV_MoveDone ); // Quantize to FRAMETIME time *= ( 1 / FRAMETIME ); time = ( float )( (int)time ) * FRAMETIME; if ( time < FRAMETIME ) { time = FRAMETIME; } moveflags = 0; t = 1 / time; // scale the destdelta vector by the time spent traveling to get velocity if ( finaldest != origin ) { vdestdelta = tdest - origin; velocity = vdestdelta * t; moveflags |= MOVE_ORIGIN; } if ( angledest != angles ) { angdestdelta = angdest - angles; avelocity = angdestdelta * t; moveflags |= MOVE_ANGLES; } PostEvent( EV_MoveDone, time ); }