rpgxef/code/game/g_roff.c
Walter Julius Hennecke a39565b783 Integrated RPG-X2 rpgxEF edition into the rpgxEF repo
... 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)
2012-08-04 12:54:37 +02:00

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;
}