mirror of
https://github.com/UberGames/rpgxEF.git
synced 2024-11-14 00:40:34 +00:00
a39565b783
... not quite content with where the project files lie but it is ok for now. ... compiling works fine so far (only tested mingw32 right now)
198 lines
No EOL
5.5 KiB
C
198 lines
No EOL
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;
|
|
|
|
} |