251 lines
4.8 KiB
C++
251 lines
4.8 KiB
C++
// 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 "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 );
|
|
}
|