ef2-sdk/dlls/game/mover.cpp
2003-11-05 00:00:00 +00:00

281 lines
5.9 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /EF2/Code/DLLs/game/mover.cpp $
// $Revision:: 11 $
// $Author:: Singlis $
// $Date:: 9/26/03 2:36p $
//
// 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.
//
//
// 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 "_pch_cpp.h"
#include "entity.h"
#include "trigger.h"
#include "mover.h"
CLASS_DECLARATION( Listener, Mover, "mover" )
{
{ &EV_MoveDone, &Mover::MoveDone },
{ NULL, NULL }
};
Mover::Mover()
{
// Should always use other constructor
assert( 0 );
}
Mover::Mover( Entity *ent )
{
self = ent;
self->edict->s.pos.trType = TR_LERP;
endevent = NULL;
finaldest = ent->origin;
}
Mover::~Mover()
{
}
void Mover::MoveDone( Event *ev )
{
Event * event;
Vector move;
Vector amove;
// zero out the movement
if ( moveflags & MOVE_ANGLES )
{
self->avelocity = vec_zero;
amove = angledest - self->localangles;
}
else
{
amove = vec_zero;
}
if ( moveflags & MOVE_ORIGIN )
{
self->velocity = vec_zero;
move = finaldest - self->GetLocalOrigin();
}
else
{
move = vec_zero;
}
if ( !G_PushMove( self, 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 )
{
self->setOrigin( finaldest );
}
if ( moveflags & MOVE_ANGLES )
{
self->localangles = angledest;
if ( ( self->localangles.x >= 360.0f ) || ( self->localangles.x < 0.0f ) )
{
self->localangles.x -= (float)( ( (int)self->localangles.x / 360 ) * 360 );
}
if ( ( self->localangles.y >= 360.0f ) || ( self->localangles.y < 0.0f ) )
{
self->localangles.y -= (float)( ( (int)self->localangles.y / 360 ) * 360 );
}
if ( ( self->localangles.z >= 360.0f ) || ( self->localangles.z < 0.0f ) )
{
self->localangles.z -= (float)( ( (int)self->localangles.z / 360 ) * 360 );
}
}
event = endevent;
endevent = NULL;
self->ProcessEvent( event );
}
/*
=============
MoveTo
calculate self.velocity and self.nextthink to reach dest from
self.origin traveling at speed
===============
*/
void Mover::MoveTo( const Vector &tdest, const Vector &angdest, float tspeed, Event &event )
{
Vector vdestdelta;
Vector angdestdelta;
float len;
float traveltime;
assert( tspeed >= 0.0f );
if ( !tspeed )
{
error( "MoveTo", "No speed is defined!" );
}
if ( tspeed < 0.0f )
{
error( "MoveTo", "Speed is negative!" );
}
// Cancel previous moves
CancelEventsOfType( EV_MoveDone );
moveflags = 0;
if ( endevent )
{
delete endevent;
}
endevent = new Event( event );
finaldest = tdest;
angledest = angdest;
if ( finaldest != self->GetLocalOrigin() )
{
moveflags |= MOVE_ORIGIN;
}
if ( angledest != self->localangles )
{
moveflags |= MOVE_ANGLES;
}
if ( !moveflags )
{
// stop the object from moving
self->velocity = vec_zero;
self->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 - self->GetLocalOrigin();
angdestdelta = angdest - self->localangles;
if ( tdest == self->GetLocalOrigin() )
{
// 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
// E3 HACK
// 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 )
{
self->velocity = vdestdelta * ( 1.0f / traveltime );
}
if ( moveflags & MOVE_ANGLES )
{
self->avelocity = angdestdelta * ( 1.0f / traveltime );
}
PostEvent( EV_MoveDone, traveltime );
}
/*
=============
LinearInterpolate
===============
*/
void Mover::LinearInterpolate( const Vector &tdest, const Vector &angdest, float time, Event &event )
{
Vector vdestdelta;
Vector angdestdelta;
float t;
if ( endevent )
{
delete endevent;
}
endevent = new Event( event );
finaldest = tdest;
angledest = angdest;
// Cancel previous moves
CancelEventsOfType( EV_MoveDone );
// Quantize to FRAMETIME
//E3 HACK
// time *= ( 1 / FRAMETIME );
// time = ( float )( (int)time ) * FRAMETIME;
if ( time < FRAMETIME )
{
time = FRAMETIME;
}
moveflags = 0;
t = 1.0f / time;
// scale the destdelta vector by the time spent traveling to get velocity
if ( finaldest != self->GetLocalOrigin() )
{
vdestdelta = tdest - self->GetLocalOrigin();
self->velocity = vdestdelta * t;
moveflags |= MOVE_ORIGIN;
}
if ( angledest != self->localangles )
{
angdestdelta = angdest - self->localangles;
self->avelocity = angdestdelta * t;
moveflags |= MOVE_ANGLES;
}
PostEvent( EV_MoveDone, time );
}
void Mover::SetEndEvent( const int endEvent )
{
if ( endevent )
{
delete endevent;
}
endevent = new Event( endEvent );
}