stvoy-sp-sdk/game/g_roff.cpp

253 lines
7.3 KiB
C++
Raw Normal View History

2002-11-22 00:00:00 +00:00
#include "g_local.h"
#include "g_roff.h"
// The list of precached ROFFs
roff_list_t roffs[MAX_ROFFS];
int num_roffs = 0;
extern void Q3_TaskIDComplete( gentity_t *ent, taskID_t taskType );
//-------------------------------------------------------
// G_LoadRoff
//
// Does the fun work of loading and caching a roff file
// If the file is already cached, it just returns an
// ID to the cached file.
//-------------------------------------------------------
int G_LoadRoff( const char *fileName )
{
char file[MAX_QPATH];
byte *data;
int len, i, roff_id = 0;
// Before even bothering with all of this, make sure we have a place to store it.
if ( num_roffs >= MAX_ROFFS )
{
Com_Printf( S_COLOR_RED"MAX_ROFFS count exceeded. Skipping load of .ROF '%s'\n", fileName );
return roff_id;
}
// The actual path
sprintf( file, "%s/%s.rof", Q3_SCRIPT_DIR, fileName );
// See if I'm already precached
for ( i = 0; i < num_roffs; i++ )
{
if ( stricmp( file, roffs[i].fileName ) == 0 )
{
// Good, just return me...avoid zero index
return i + 1;
}
}
#ifdef _DEBUG
Com_Printf( S_COLOR_GREEN"Caching ROF: '%s'\n", file );
#endif
// Read the file in one fell swoop
len = gi.FS_ReadFile( file, (void**) &data);
if ( len <= 0 )
{
Com_Printf( S_COLOR_RED"Could not open .ROF file '%s'\n", fileName );
return roff_id;
}
// Now let's check the header info...
roff_hdr_t *header = (roff_hdr_t *)data;
// ..and make sure it's reasonably valid
if ( strncmp( header->sHeader, "ROFF", 4 ) !=0 || header->lVersion != ROFF_VERSION || header->fCount <= 0 )
{
Com_Printf( S_COLOR_RED"Bad header data in .ROF file '%s'\n", fileName );
}
else
{
// Cool, the file seems to be valid
int count = (int)header->fCount;
// Ask the game to give us some memory to store this pooch
move_rotate_t *mem = roffs[num_roffs].data = (move_rotate_t *) G_Alloc( count * sizeof( move_rotate_t ) );
if ( mem )
{
// The allocation worked, so stash this stuff off so we can reference the data later if needed
roffs[num_roffs].fileName = G_NewString( file );
roffs[num_roffs].frames = count;
// Step past the header to get to the goods
move_rotate_t *roff_data = ( move_rotate_t *)&header[1];
// Copy all of the goods into our ROFF cache
for ( int i = 0; i < count; i++, roff_data++, mem++ )
{
// Copy just the delta position and orientation which can be applied to anything at a later point
VectorCopy( roff_data->origin_delta, mem->origin_delta );
VectorCopy( roff_data->rotate_delta, mem->rotate_delta );
}
// Done loading this roff, so save off an id to it..increment first to avoid zero index
roff_id = ++num_roffs;
}
}
gi.FS_FreeFile( data );
return roff_id;
}
//-------------------------------------------------------
// G_Roff
//
// Handles applying the roff data to the specified ent
//-------------------------------------------------------
void G_Roff( gentity_t *ent )
{
if ( !ent->next_roff_time || ent->next_roff_time > level.time )
{
// either I don't think or it's just not time to have me think yet
return;
}
int roff_id = G_LoadRoff( ent->roff );
if ( !roff_id )
{
// Couldn't cache this rof
return;
}
// The ID is one higher than the array index
move_rotate_t *roff = &roffs[roff_id - 1].data[ent->roff_ctr];
int frames = roffs[roff_id - 1].frames;
#ifdef _DEBUG
Com_Printf( S_COLOR_GREEN"ROFF dat: o:<%.2f %.2f %.2f> a:<%.2f %.2f %.2f>\n",
roff->origin_delta[0], roff->origin_delta[1], roff->origin_delta[2],
roff->rotate_delta[0], roff->rotate_delta[1], roff->rotate_delta[2] );
#endif
if ( ent->client )
{
// Set up the angle interpolation
//-------------------------------------
VectorAdd( ent->s.apos.trBase, roff->rotate_delta, ent->s.apos.trBase );
ent->s.apos.trTime = level.time;
ent->s.apos.trType = TR_INTERPOLATE;
// Store what the next apos->trBase should be
VectorCopy( ent->s.apos.trBase, ent->client->ps.viewangles );
VectorCopy( ent->s.apos.trBase, ent->currentAngles );
VectorCopy( ent->s.apos.trBase, ent->s.angles );
if ( ent->NPC )
{
//ent->NPC->desiredPitch = ent->s.apos.trBase[PITCH];
ent->NPC->desiredYaw = ent->s.apos.trBase[YAW];
}
// Set up the origin interpolation
//-------------------------------------
VectorAdd( ent->s.pos.trBase, roff->origin_delta, ent->s.pos.trBase );
ent->s.pos.trTime = level.time;
ent->s.pos.trType = TR_INTERPOLATE;
// Store what the next apos->trBase should be
VectorCopy( ent->s.pos.trBase, ent->client->ps.origin );
VectorCopy( ent->s.pos.trBase, ent->currentOrigin );
//VectorCopy( ent->s.pos.trBase, ent->s.origin );
}
else
{
// Set up the angle interpolation
//-------------------------------------
VectorScale( roff->rotate_delta, ROFF_SAMPLE_RATE, ent->s.apos.trDelta );
VectorCopy( ent->pos2, ent->s.apos.trBase );
ent->s.apos.trTime = level.time;
ent->s.apos.trType = TR_LINEAR;
// Store what the next apos->trBase should be
VectorAdd( ent->pos2, roff->rotate_delta, ent->pos2 );
// Set up the origin interpolation
//-------------------------------------
VectorScale( roff->origin_delta, ROFF_SAMPLE_RATE, ent->s.pos.trDelta );
VectorCopy( ent->pos1, ent->s.pos.trBase );
ent->s.pos.trTime = level.time;
ent->s.pos.trType = TR_LINEAR;
// Store what the next apos->trBase should be
VectorAdd( ent->pos1, roff->origin_delta, ent->pos1 );
}
// See if the ROFF playback is done
//-------------------------------------
if ( ++ent->roff_ctr >= frames )
{
// We are done, so let me think no more, then tell the task that we're done.
ent->next_roff_time = 0;
// Stop any rotation or movement.
VectorClear( ent->s.pos.trDelta );
VectorClear( ent->s.apos.trDelta );
Q3_TaskIDComplete( ent, TID_MOVE_NAV );
return;
}
// Lock me to a 10hz update rate
ent->next_roff_time = level.time + 100;
}
//-------------------------------------------------------
// G_SaveCachedRoffs
//
// Really fun savegame stuff
//-------------------------------------------------------
void G_SaveCachedRoffs()
{
int i, len;
// Write out the number of cached ROFFs
gi.AppendToSaveGame( 'ROFF', (void *)&num_roffs, sizeof(num_roffs) );
// Now dump out the cached ROFF file names in order so they can be loaded on the other end
for ( i = 0; i < num_roffs; i++ )
{
// Dump out the string length to make things a bit easier on the other end...heh heh.
len = strlen( roffs[i].fileName ) + 1;
gi.AppendToSaveGame( 'SLEN', (void *)&len, sizeof(len) );
gi.AppendToSaveGame( 'RSTR', (void *)(*roffs[i].fileName), len );
}
}
//-------------------------------------------------------
// G_LoadCachedRoffs
//
// Really fun loadgame stuff
//-------------------------------------------------------
void G_LoadCachedRoffs()
{
int i, count, len;
char buffer[MAX_QPATH];
// Get the count of goodies we need to revive
gi.ReadFromSaveGame( 'ROFF', (void *)&count, sizeof(count) );
// Now bring 'em back to life
for ( i = 0; i < count; i++ )
{
gi.ReadFromSaveGame( 'SLEN', (void *)&len, sizeof(len) );
gi.ReadFromSaveGame( 'RSTR', (void *)(buffer), len );
G_LoadRoff( buffer );
}
}