316 lines
7 KiB
C++
316 lines
7 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $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 );
|
|
}
|