mirror of
https://github.com/UberGames/RPG-X2.git
synced 2024-11-25 13:51:03 +00:00
198 lines
5.5 KiB
C
198 lines
5.5 KiB
C
|
// Copyright (C) 2000 Raven Software
|
||
|
//
|
||
|
// g_roff.c -- The main code behind setting up
|
||
|
// and managing 'ROFF' code in EF
|
||
|
|
||
|
#include "g_local.h"
|
||
|
#include "g_roff.h"
|
||
|
// The list of precached ROFFs
|
||
|
roff_list_t roffs[MAX_ROFFS];
|
||
|
int num_roffs = 0;
|
||
|
#define ROFF_DIR "maps/roffs"
|
||
|
|
||
|
//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.
|
||
|
//
|
||
|
// TiM: Modded it so it conforms to ANSI C parameters
|
||
|
//-------------------------------------------------------
|
||
|
|
||
|
int G_LoadRoff( const char *fileName )
|
||
|
{
|
||
|
char file[MAX_QPATH];
|
||
|
byte data[2*1024*1024];
|
||
|
int len, i, roff_id = 0;
|
||
|
fileHandle_t f;
|
||
|
roff_hdr_t *header;
|
||
|
move_rotate_t *mem;
|
||
|
move_rotate_t *roff_data;
|
||
|
|
||
|
// Before even bothering with all of this, make sure we have a place to store it.
|
||
|
if ( num_roffs >= MAX_ROFFS )
|
||
|
{
|
||
|
G_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", ROFF_DIR, fileName );
|
||
|
|
||
|
// See if I'm already precached
|
||
|
for ( i = 0; i < num_roffs; i++ )
|
||
|
{
|
||
|
if ( Q_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 = trap_FS_FOpenFile( fileName, &f, FS_READ );
|
||
|
|
||
|
if ( len <= 0 )
|
||
|
{
|
||
|
G_Printf( S_COLOR_RED "Could not open .ROF file '%s'\n", fileName );
|
||
|
return roff_id;
|
||
|
}
|
||
|
|
||
|
trap_FS_Read( &data, len, f );
|
||
|
data[len+1] = '\0';
|
||
|
|
||
|
// Now let's check the header info...
|
||
|
header = (roff_hdr_t *)((byte *)data);
|
||
|
|
||
|
// ..and make sure it's reasonably valid
|
||
|
if ( strncmp( header->sHeader, "ROFF", 4 ) !=0 || header->lVersion != ROFF_VERSION || header->fCount <= 0 )
|
||
|
{
|
||
|
G_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
|
||
|
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
|
||
|
roff_data = ( move_rotate_t *)&header[1];
|
||
|
|
||
|
// Copy all of the goods into our ROFF cache
|
||
|
for ( 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
trap_FS_FCloseFile( f );
|
||
|
|
||
|
return roff_id;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// G_Roff
|
||
|
//
|
||
|
// Handles applying the roff data to the specified ent
|
||
|
//-------------------------------------------------------
|
||
|
|
||
|
void G_Roff( gentity_t *ent )
|
||
|
{
|
||
|
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
|
||
|
|
||
|
// 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 );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Lock me to a 10hz update rate
|
||
|
ent->next_roff_time = level.time + 100;
|
||
|
}
|
||
|
|
||
|
/*QUAKED func_roff_mover (0 .5 .8) ? START_ON LOOP
|
||
|
Loads all of the movement data from an external ROFF file and applies
|
||
|
it to this entity, creating much more fluid motion.
|
||
|
|
||
|
"model2" .md3 model to also draw
|
||
|
"angle" determines the opening direction
|
||
|
"target" once the animation ends, these targetted entities will be triggered
|
||
|
"wait" from activation, how many seconds to wait before moving
|
||
|
"endwait" from the end of the animation, how many seconds to wait b4 firing its targets
|
||
|
"color" constantLight color
|
||
|
"light" constantLight radius
|
||
|
"noise" looping sound file that plays as it animates.
|
||
|
*/
|
||
|
void SP_func_roff_mover ( gentity_t *ent )
|
||
|
{
|
||
|
ent->think = G_Roff;
|
||
|
|
||
|
}
|