summaryrefslogtreecommitdiff
path: root/mod/src/cgame/cg_trails.c
diff options
context:
space:
mode:
Diffstat (limited to 'mod/src/cgame/cg_trails.c')
-rw-r--r--mod/src/cgame/cg_trails.c1489
1 files changed, 0 insertions, 1489 deletions
diff --git a/mod/src/cgame/cg_trails.c b/mod/src/cgame/cg_trails.c
deleted file mode 100644
index 3ef19f00..00000000
--- a/mod/src/cgame/cg_trails.c
+++ /dev/null
@@ -1,1489 +0,0 @@
-// cg_trails.c -- the trail system
-
-/*
- * Portions Copyright (C) 2000-2001 Tim Angus
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the OSML - Open Source Modification License v1.0 as
- * described in the file COPYING which is distributed with this source
- * code.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include "cg_local.h"
-
-static baseTrailSystem_t baseTrailSystems[ MAX_BASETRAIL_SYSTEMS ];
-static baseTrailBeam_t baseTrailBeams[ MAX_BASETRAIL_BEAMS ];
-static int numBaseTrailSystems = 0;
-static int numBaseTrailBeams = 0;
-
-static trailSystem_t trailSystems[ MAX_TRAIL_SYSTEMS ];
-static trailBeam_t trailBeams[ MAX_TRAIL_BEAMS ];
-
-/*
-===============
-CG_CalculateBeamNodeProperties
-
-Fills in trailBeamNode_t.textureCoord
-===============
-*/
-static void CG_CalculateBeamNodeProperties( trailBeam_t *tb )
-{
- trailBeamNode_t *i = NULL;
- trailSystem_t *ts;
- baseTrailBeam_t *btb;
- float nodeDistances[ MAX_TRAIL_BEAM_NODES ];
- float totalDistance = 0.0f, position = 0.0f;
- int j, numNodes = 0;
- float TCRange, widthRange, alphaRange;
- vec3_t colorRange;
- float fadeAlpha = 1.0f;
-
- if( !tb || !tb->nodes )
- return;
-
- ts = tb->parent;
- btb = tb->class;
-
- if( ts->destroyTime > 0 && btb->fadeOutTime )
- {
- fadeAlpha -= ( cg.time - ts->destroyTime ) / btb->fadeOutTime;
-
- if( fadeAlpha < 0.0f )
- fadeAlpha = 0.0f;
- }
-
- TCRange = tb->class->backTextureCoord -
- tb->class->frontTextureCoord;
- widthRange = tb->class->backWidth -
- tb->class->frontWidth;
- alphaRange = tb->class->backAlpha -
- tb->class->frontAlpha;
- VectorSubtract( tb->class->backColor,
- tb->class->frontColor, colorRange );
-
- for( i = tb->nodes; i && i->next; i = i->next )
- {
- nodeDistances[ numNodes++ ] =
- Distance( i->position, i->next->position );
- }
-
- for( j = 0; j < numNodes; j++ )
- totalDistance += nodeDistances[ j ];
-
- for( j = 0, i = tb->nodes; i; i = i->next, j++ )
- {
- if( tb->class->textureType == TBTT_STRETCH )
- {
- i->textureCoord = tb->class->frontTextureCoord +
- ( ( position / totalDistance ) * TCRange );
- }
- else if( tb->class->textureType == TBTT_REPEAT )
- {
- if( tb->class->clampToBack )
- i->textureCoord = ( totalDistance - position ) /
- tb->class->repeatLength;
- else
- i->textureCoord = position / tb->class->repeatLength;
- }
-
- i->halfWidth = ( tb->class->frontWidth +
- ( ( position / totalDistance ) * widthRange ) ) / 2.0f;
- i->alpha = (byte)( (float)0xFF * ( tb->class->frontAlpha +
- ( ( position / totalDistance ) * alphaRange ) ) * fadeAlpha );
- VectorMA( tb->class->frontColor, ( position / totalDistance ),
- colorRange, i->color );
-
- position += nodeDistances[ j ];
- }
-}
-
-/*
-===============
-CG_LightVertex
-
-Lights a particular vertex
-===============
-*/
-static void CG_LightVertex( vec3_t point, byte alpha, byte *rgba )
-{
- int i;
- vec3_t alight, dlight, lightdir;
-
- trap_R_LightForPoint( point, alight, dlight, lightdir );
- for( i = 0; i <= 2; i++ )
- rgba[ i ] = (int)alight[ i ];
-
- rgba[ 3 ] = alpha;
-}
-
-/*
-===============
-CG_RenderBeam
-
-Renders a beam
-===============
-*/
-static void CG_RenderBeam( trailBeam_t *tb )
-{
- trailBeamNode_t *i = NULL;
- trailBeamNode_t *prev = NULL;
- trailBeamNode_t *next = NULL;
- vec3_t up;
- polyVert_t verts[ ( MAX_TRAIL_BEAM_NODES - 1 ) * 4 ];
- int numVerts = 0;
- baseTrailBeam_t *btb;
- trailSystem_t *ts;
- baseTrailSystem_t *bts;
-
- if( !tb || !tb->nodes )
- return;
-
- btb = tb->class;
- ts = tb->parent;
- bts = ts->class;
-
- if( bts->thirdPersonOnly &&
- ( CG_AttachmentCentNum( &ts->frontAttachment ) == cg.snap->ps.clientNum ||
- CG_AttachmentCentNum( &ts->backAttachment ) == cg.snap->ps.clientNum ) &&
- !cg.renderingThirdPerson )
- return;
-
- CG_CalculateBeamNodeProperties( tb );
-
- i = tb->nodes;
-
- do
- {
- prev = i->prev;
- next = i->next;
-
- if( prev && next )
- {
- //this node has two neighbours
- GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up );
- }
- else if( !prev && next )
- {
- //this is the front
- GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up );
- }
- else if( prev && !next )
- {
- //this is the back
- GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up );
- }
- else
- break;
-
- if( prev )
- {
- VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz );
- verts[ numVerts ].st[ 0 ] = i->textureCoord;
- verts[ numVerts ].st[ 1 ] = 1.0f;
-
- if( btb->realLight )
- CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate );
- else
- {
- VectorCopy( i->color, verts[ numVerts ].modulate );
- verts[ numVerts ].modulate[ 3 ] = i->alpha;
- }
-
- numVerts++;
-
- VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz );
- verts[ numVerts ].st[ 0 ] = i->textureCoord;
- verts[ numVerts ].st[ 1 ] = 0.0f;
-
- if( btb->realLight )
- CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate );
- else
- {
- VectorCopy( i->color, verts[ numVerts ].modulate );
- verts[ numVerts ].modulate[ 3 ] = i->alpha;
- }
-
- numVerts++;
- }
-
- if( next )
- {
- VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz );
- verts[ numVerts ].st[ 0 ] = i->textureCoord;
- verts[ numVerts ].st[ 1 ] = 0.0f;
-
- if( btb->realLight )
- CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate );
- else
- {
- VectorCopy( i->color, verts[ numVerts ].modulate );
- verts[ numVerts ].modulate[ 3 ] = i->alpha;
- }
-
- numVerts++;
-
- VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz );
- verts[ numVerts ].st[ 0 ] = i->textureCoord;
- verts[ numVerts ].st[ 1 ] = 1.0f;
-
- if( btb->realLight )
- CG_LightVertex( verts[ numVerts ].xyz, i->alpha, verts[ numVerts ].modulate );
- else
- {
- VectorCopy( i->color, verts[ numVerts ].modulate );
- verts[ numVerts ].modulate[ 3 ] = i->alpha;
- }
-
- numVerts++;
- }
-
- i = i->next;
- } while( i );
-
- trap_R_AddPolysToScene( tb->class->shader, 4, &verts[ 0 ], numVerts / 4 );
-}
-
-/*
-===============
-CG_AllocateBeamNode
-
-Allocates a trailBeamNode_t from a trailBeam_t's nodePool
-===============
-*/
-static trailBeamNode_t *CG_AllocateBeamNode( trailBeam_t *tb )
-{
- baseTrailBeam_t *btb = tb->class;
- int i;
- trailBeamNode_t *tbn;
-
- for( i = 0; i < MAX_TRAIL_BEAM_NODES; i++ )
- {
- tbn = &tb->nodePool[ i ];
- if( !tbn->used )
- {
- tbn->timeLeft = btb->segmentTime;
- tbn->prev = NULL;
- tbn->next = NULL;
- tbn->used = qtrue;
- return tbn;
- }
- }
-
- // no space left
- return NULL;
-}
-
-/*
-===============
-CG_DestroyBeamNode
-
-Removes a node from a beam
-Returns the new head
-===============
-*/
-static trailBeamNode_t *CG_DestroyBeamNode( trailBeamNode_t *tbn )
-{
- trailBeamNode_t *newHead = NULL;
-
- if( tbn->prev )
- {
- if( tbn->next )
- {
- // node is in the middle
- tbn->prev->next = tbn->next;
- tbn->next->prev = tbn->prev;
- }
- else // node is at the back
- tbn->prev->next = NULL;
-
- // find the new head (shouldn't have changed)
- newHead = tbn->prev;
-
- while( newHead->prev )
- newHead = newHead->prev;
- }
- else if( tbn->next )
- {
- //node is at the front
- tbn->next->prev = NULL;
- newHead = tbn->next;
- }
-
- tbn->prev = NULL;
- tbn->next = NULL;
- tbn->used = qfalse;
-
- return newHead;
-}
-
-/*
-===============
-CG_FindLastBeamNode
-
-Returns the last beam node in a beam
-===============
-*/
-static trailBeamNode_t *CG_FindLastBeamNode( trailBeam_t *tb )
-{
- trailBeamNode_t *i = tb->nodes;
-
- while( i && i->next )
- i = i->next;
-
- return i;
-}
-
-/*
-===============
-CG_CountBeamNodes
-
-Returns the number of nodes in a beam
-===============
-*/
-static int CG_CountBeamNodes( trailBeam_t *tb )
-{
- trailBeamNode_t *i = tb->nodes;
- int numNodes = 0;
-
- while( i )
- {
- numNodes++;
- i = i->next;
- }
-
- return numNodes;
-}
-
-/*
-===============
-CG_PrependBeamNode
-
-Prepend a new beam node to the front of a beam
-Returns the new node
-===============
-*/
-static trailBeamNode_t *CG_PrependBeamNode( trailBeam_t *tb )
-{
- trailBeamNode_t *i;
-
- if( tb->nodes )
- {
- // prepend another node
- i = CG_AllocateBeamNode( tb );
-
- if( i )
- {
- i->next = tb->nodes;
- tb->nodes->prev = i;
- tb->nodes = i;
- }
- }
- else //add first node
- {
- i = CG_AllocateBeamNode( tb );
-
- if( i )
- tb->nodes = i;
- }
-
- return i;
-}
-
-/*
-===============
-CG_AppendBeamNode
-
-Append a new beam node to the back of a beam
-Returns the new node
-===============
-*/
-static trailBeamNode_t *CG_AppendBeamNode( trailBeam_t *tb )
-{
- trailBeamNode_t *last, *i;
-
- if( tb->nodes )
- {
- // append another node
- last = CG_FindLastBeamNode( tb );
- i = CG_AllocateBeamNode( tb );
-
- if( i )
- {
- last->next = i;
- i->prev = last;
- i->next = NULL;
- }
- }
- else //add first node
- {
- i = CG_AllocateBeamNode( tb );
-
- if( i )
- tb->nodes = i;
- }
-
- return i;
-}
-
-/*
-===============
-CG_ApplyJitters
-===============
-*/
-static void CG_ApplyJitters( trailBeam_t *tb )
-{
- trailBeamNode_t *i = NULL;
- int j;
- baseTrailBeam_t *btb;
- trailSystem_t *ts;
- trailBeamNode_t *start;
- trailBeamNode_t *end;
-
- if( !tb || !tb->nodes )
- return;
-
- btb = tb->class;
- ts = tb->parent;
-
- for( j = 0; j < btb->numJitters; j++ )
- {
- if( tb->nextJitterTimes[ j ] <= cg.time )
- {
- for( i = tb->nodes; i; i = i->next )
- {
- i->jitters[ j ][ 0 ] = ( crandom( ) * btb->jitters[ j ].magnitude );
- i->jitters[ j ][ 1 ] = ( crandom( ) * btb->jitters[ j ].magnitude );
- }
-
- tb->nextJitterTimes[ j ] = cg.time + btb->jitters[ j ].period;
- }
- }
-
- start = tb->nodes;
- end = CG_FindLastBeamNode( tb );
-
- if( !btb->jitterAttachments )
- {
- if( CG_Attached( &ts->frontAttachment ) && start->next )
- start = start->next;
-
- if( CG_Attached( &ts->backAttachment ) && end->prev )
- end = end->prev;
- }
-
- for( i = start; i; i = i->next )
- {
- vec3_t forward, right, up;
- trailBeamNode_t *prev;
- trailBeamNode_t *next;
- float upJitter = 0.0f, rightJitter = 0.0f;
-
- prev = i->prev;
- next = i->next;
-
- if( prev && next )
- {
- //this node has two neighbours
- GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up );
- VectorSubtract( next->position, prev->position, forward );
- }
- else if( !prev && next )
- {
- //this is the front
- GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up );
- VectorSubtract( next->position, i->position, forward );
- }
- else if( prev && !next )
- {
- //this is the back
- GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up );
- VectorSubtract( i->position, prev->position, forward );
- }
-
- VectorNormalize( forward );
- CrossProduct( forward, up, right );
- VectorNormalize( right );
-
- for( j = 0; j < btb->numJitters; j++ )
- {
- upJitter += i->jitters[ j ][ 0 ];
- rightJitter += i->jitters[ j ][ 1 ];
- }
-
- VectorMA( i->position, upJitter, up, i->position );
- VectorMA( i->position, rightJitter, right, i->position );
-
- if( i == end )
- break;
- }
-}
-
-/*
-===============
-CG_UpdateBeam
-
-Updates a beam
-===============
-*/
-static void CG_UpdateBeam( trailBeam_t *tb )
-{
- baseTrailBeam_t *btb;
- trailSystem_t *ts;
- trailBeamNode_t *i;
- int deltaTime;
- int nodesToAdd;
- int j;
- int numNodes;
-
- if( !tb )
- return;
-
- btb = tb->class;
- ts = tb->parent;
-
- deltaTime = cg.time - tb->lastEvalTime;
- tb->lastEvalTime = cg.time;
-
- // first make sure this beam has enough nodes
- if( ts->destroyTime <= 0 )
- {
- nodesToAdd = btb->numSegments - CG_CountBeamNodes( tb ) + 1;
-
- while( nodesToAdd-- )
- {
- i = CG_AppendBeamNode( tb );
-
- if( !tb->nodes->next && CG_Attached( &ts->frontAttachment ) )
- {
- // this is the first node to be added
- if( !CG_AttachmentPoint( &ts->frontAttachment, i->refPosition ) )
- CG_DestroyTrailSystem( &ts );
- }
- else
- VectorCopy( i->prev->refPosition, i->refPosition );
- }
- }
-
- numNodes = CG_CountBeamNodes( tb );
-
- for( i = tb->nodes; i; i = i->next )
- VectorCopy( i->refPosition, i->position );
-
- if( CG_Attached( &ts->frontAttachment ) && CG_Attached( &ts->backAttachment ) )
- {
- // beam between two attachments
- vec3_t dir, front, back;
-
- if( ts->destroyTime > 0 && ( cg.time - ts->destroyTime ) >= btb->fadeOutTime )
- {
- tb->valid = qfalse;
- return;
- }
-
- if( !CG_AttachmentPoint( &ts->frontAttachment, front ) )
- CG_DestroyTrailSystem( &ts );
-
- if( !CG_AttachmentPoint( &ts->backAttachment, back ) )
- CG_DestroyTrailSystem( &ts );
-
- VectorSubtract( back, front, dir );
-
- for( j = 0, i = tb->nodes; i; i = i->next, j++ )
- {
- float scale = (float)j / (float)( numNodes - 1 );
-
- VectorMA( front, scale, dir, i->position );
- }
- }
- else if( CG_Attached( &ts->frontAttachment ) )
- {
- // beam from one attachment
-
- // cull the trail tail
- i = CG_FindLastBeamNode( tb );
-
- if( i && i->timeLeft >= 0 )
- {
- i->timeLeft -= deltaTime;
-
- if( i->timeLeft < 0 )
- {
- tb->nodes = CG_DestroyBeamNode( i );
-
- if( !tb->nodes )
- {
- tb->valid = qfalse;
- return;
- }
-
- // if the ts has been destroyed, stop creating new nodes
- if( ts->destroyTime <= 0 )
- CG_PrependBeamNode( tb );
- }
- else if( i->timeLeft >= 0 && i->prev )
- {
- vec3_t dir;
- float length;
-
- VectorSubtract( i->refPosition, i->prev->refPosition, dir );
- length = VectorNormalize( dir ) *
- ( (float)i->timeLeft / (float)tb->class->segmentTime );
-
- VectorMA( i->prev->refPosition, length, dir, i->position );
- }
- }
-
- if( tb->nodes )
- {
- if( !CG_AttachmentPoint( &ts->frontAttachment, tb->nodes->refPosition ) )
- CG_DestroyTrailSystem( &ts );
-
- VectorCopy( tb->nodes->refPosition, tb->nodes->position );
- }
- }
-
- CG_ApplyJitters( tb );
-}
-
-/*
-===============
-CG_ParseTrailBeamColor
-===============
-*/
-static qboolean CG_ParseTrailBeamColor( byte *c, char **text_p )
-{
- char *token;
- int i;
-
- for( i = 0; i <= 2; i++ )
- {
- token = COM_Parse( text_p );
-
- if( !Q_stricmp( token, "" ) )
- return qfalse;
-
- c[ i ] = (int)( (float)0xFF * atof_neg( token, qfalse ) );
- }
-
- return qtrue;
-}
-
-/*
-===============
-CG_ParseTrailBeam
-
-Parse a trail beam
-===============
-*/
-static qboolean CG_ParseTrailBeam( baseTrailBeam_t *btb, char **text_p )
-{
- char *token;
-
- // read optional parameters
- while( 1 )
- {
- token = COM_Parse( text_p );
-
- if( !Q_stricmp( token, "" ) )
- return qfalse;
-
- if( !Q_stricmp( token, "segments" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->numSegments = atoi_neg( token, qfalse );
-
- if( btb->numSegments >= MAX_TRAIL_BEAM_NODES )
- {
- btb->numSegments = MAX_TRAIL_BEAM_NODES - 1;
- CG_Printf( S_COLOR_YELLOW "WARNING: too many segments in trail beam\n" );
- }
- continue;
- }
- else if( !Q_stricmp( token, "width" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->frontWidth = atof_neg( token, qfalse );
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "-" ) )
- btb->backWidth = btb->frontWidth;
- else
- btb->backWidth = atof_neg( token, qfalse );
- continue;
- }
- else if( !Q_stricmp( token, "alpha" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->frontAlpha = atof_neg( token, qfalse );
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "-" ) )
- btb->backAlpha = btb->frontAlpha;
- else
- btb->backAlpha = atof_neg( token, qfalse );
- continue;
- }
- else if( !Q_stricmp( token, "color" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "{" ) )
- {
- if( !CG_ParseTrailBeamColor( btb->frontColor, text_p ) )
- break;
-
- token = COM_Parse( text_p );
- if( Q_stricmp( token, "}" ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: missing '}'\n" );
- break;
- }
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "-" ) )
- {
- btb->backColor[ 0 ] = btb->frontColor[ 0 ];
- btb->backColor[ 1 ] = btb->frontColor[ 1 ];
- btb->backColor[ 2 ] = btb->frontColor[ 2 ];
- }
- else if( !Q_stricmp( token, "{" ) )
- {
- if( !CG_ParseTrailBeamColor( btb->backColor, text_p ) )
- break;
-
- token = COM_Parse( text_p );
- if( Q_stricmp( token, "}" ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: missing '}'\n" );
- break;
- }
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: missing '{'\n" );
- break;
- }
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: missing '{'\n" );
- break;
- }
-
- continue;
- }
- else if( !Q_stricmp( token, "segmentTime" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->segmentTime = atoi_neg( token, qfalse );
- continue;
- }
- else if( !Q_stricmp( token, "fadeOutTime" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->fadeOutTime = atoi_neg( token, qfalse );
- continue;
- }
- else if( !Q_stricmp( token, "shader" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- Q_strncpyz( btb->shaderName, token, MAX_QPATH );
-
- continue;
- }
- else if( !Q_stricmp( token, "textureType" ) )
- {
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "stretch" ) )
- {
- btb->textureType = TBTT_STRETCH;
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->frontTextureCoord = atof_neg( token, qfalse );
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->backTextureCoord = atof_neg( token, qfalse );
- }
- else if( !Q_stricmp( token, "repeat" ) )
- {
- btb->textureType = TBTT_REPEAT;
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "front" ) )
- btb->clampToBack = qfalse;
- else if( !Q_stricmp( token, "back" ) )
- btb->clampToBack = qtrue;
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unknown textureType clamp \"%s\"\n", token );
- break;
- }
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->repeatLength = atof_neg( token, qfalse );
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unknown textureType \"%s\"\n", token );
- break;
- }
-
- continue;
- }
- else if( !Q_stricmp( token, "realLight" ) )
- {
- btb->realLight = qtrue;
-
- continue;
- }
- else if( !Q_stricmp( token, "jitter" ) )
- {
- if( btb->numJitters == MAX_TRAIL_BEAM_JITTERS )
- {
- CG_Printf( S_COLOR_RED "ERROR: too many jitters\n", token );
- break;
- }
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->jitters[ btb->numJitters ].magnitude = atof_neg( token, qfalse );
-
- token = COM_Parse( text_p );
- if( !Q_stricmp( token, "" ) )
- break;
-
- btb->jitters[ btb->numJitters ].period = atoi_neg( token, qfalse );
-
- btb->numJitters++;
-
- continue;
- }
- else if( !Q_stricmp( token, "jitterAttachments" ) )
- {
- btb->jitterAttachments = qtrue;
-
- continue;
- }
- else if( !Q_stricmp( token, "}" ) )
- return qtrue; //reached the end of this trail beam
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in trail beam\n", token );
- return qfalse;
- }
- }
-
- return qfalse;
-}
-
-/*
-===============
-CG_InitialiseBaseTrailBeam
-===============
-*/
-static void CG_InitialiseBaseTrailBeam( baseTrailBeam_t *btb )
-{
- memset( btb, 0, sizeof( baseTrailBeam_t ) );
-
- btb->numSegments = 1;
- btb->frontWidth = btb->backWidth = 1.0f;
- btb->frontAlpha = btb->backAlpha = 1.0f;
- memset( btb->frontColor, 0xFF, sizeof( btb->frontColor ) );
- memset( btb->backColor, 0xFF, sizeof( btb->backColor ) );
-
- btb->segmentTime = 100;
-
- btb->textureType = TBTT_STRETCH;
- btb->frontTextureCoord = 0.0f;
- btb->backTextureCoord = 1.0f;
-}
-
-/*
-===============
-CG_ParseTrailSystem
-
-Parse a trail system section
-===============
-*/
-static qboolean CG_ParseTrailSystem( baseTrailSystem_t *bts, char **text_p, const char *name )
-{
- char *token;
-
- // read optional parameters
- while( 1 )
- {
- token = COM_Parse( text_p );
-
- if( !Q_stricmp( token, "" ) )
- return qfalse;
-
- if( !Q_stricmp( token, "{" ) )
- {
- CG_InitialiseBaseTrailBeam( &baseTrailBeams[ numBaseTrailBeams ] );
-
- if( !CG_ParseTrailBeam( &baseTrailBeams[ numBaseTrailBeams ], text_p ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: failed to parse trail beam\n" );
- return qfalse;
- }
-
- if( bts->numBeams == MAX_BEAMS_PER_SYSTEM )
- {
- CG_Printf( S_COLOR_RED "ERROR: trail system has > %d beams\n", MAX_BEAMS_PER_SYSTEM );
- return qfalse;
- }
- else if( numBaseTrailBeams == MAX_BASETRAIL_BEAMS )
- {
- CG_Printf( S_COLOR_RED "ERROR: maximum number of trail beams (%d) reached\n",
- MAX_BASETRAIL_BEAMS );
- return qfalse;
- }
- else
- {
- //start parsing beams again
- bts->beams[ bts->numBeams ] = &baseTrailBeams[ numBaseTrailBeams ];
- bts->numBeams++;
- numBaseTrailBeams++;
- }
- continue;
- }
- else if( !Q_stricmp( token, "thirdPersonOnly" ) )
- bts->thirdPersonOnly = qtrue;
- else if( !Q_stricmp( token, "beam" ) ) //acceptable text
- continue;
- else if( !Q_stricmp( token, "}" ) )
- {
- if( cg_debugTrails.integer >= 1 )
- CG_Printf( "Parsed trail system %s\n", name );
-
- return qtrue; //reached the end of this trail system
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in trail system %s\n", token, bts->name );
- return qfalse;
- }
- }
-
- return qfalse;
-}
-
-/*
-===============
-CG_ParseTrailFile
-
-Load the trail systems from a trail file
-===============
-*/
-static qboolean CG_ParseTrailFile( const char *fileName )
-{
- char *text_p;
- int i;
- int len;
- char *token;
- char text[ 32000 ];
- char tsName[ MAX_QPATH ];
- qboolean tsNameSet = qfalse;
- fileHandle_t f;
-
- // load the file
- len = trap_FS_FOpenFile( fileName, &f, FS_READ );
- if( len <= 0 )
- return qfalse;
-
- if( len >= sizeof( text ) - 1 )
- {
- CG_Printf( S_COLOR_RED "ERROR: trail file %s too long\n", fileName );
- return qfalse;
- }
-
- trap_FS_Read( text, len, f );
- text[ len ] = 0;
- trap_FS_FCloseFile( f );
-
- // parse the text
- text_p = text;
-
- // read optional parameters
- while( 1 )
- {
- token = COM_Parse( &text_p );
-
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "{" ) )
- {
- if( tsNameSet )
- {
- //check for name space clashes
- for( i = 0; i < numBaseTrailSystems; i++ )
- {
- if( !Q_stricmp( baseTrailSystems[ i ].name, tsName ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: a trail system is already named %s\n", tsName );
- return qfalse;
- }
- }
-
- Q_strncpyz( baseTrailSystems[ numBaseTrailSystems ].name, tsName, MAX_QPATH );
-
- if( !CG_ParseTrailSystem( &baseTrailSystems[ numBaseTrailSystems ], &text_p, tsName ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: %s: failed to parse trail system %s\n", fileName, tsName );
- return qfalse;
- }
-
- //start parsing trail systems again
- tsNameSet = qfalse;
-
- if( numBaseTrailSystems == MAX_BASETRAIL_SYSTEMS )
- {
- CG_Printf( S_COLOR_RED "ERROR: maximum number of trail systems (%d) reached\n",
- MAX_BASETRAIL_SYSTEMS );
- return qfalse;
- }
- else
- numBaseTrailSystems++;
-
- continue;
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unamed trail system\n" );
- return qfalse;
- }
- }
-
- if( !tsNameSet )
- {
- Q_strncpyz( tsName, token, sizeof( tsName ) );
- tsNameSet = qtrue;
- }
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: trail system already named\n" );
- return qfalse;
- }
- }
-
- return qtrue;
-}
-
-/*
-===============
-CG_LoadTrailSystems
-
-Load trail system templates
-===============
-*/
-void CG_LoadTrailSystems( void )
-{
- int i;
- /*const char *s[ MAX_TRAIL_FILES ];*/
-
- //clear out the old
- numBaseTrailSystems = 0;
- numBaseTrailBeams = 0;
-
- for( i = 0; i < MAX_BASETRAIL_SYSTEMS; i++ )
- {
- baseTrailSystem_t *bts = &baseTrailSystems[ i ];
- memset( bts, 0, sizeof( baseTrailSystem_t ) );
- }
-
- for( i = 0; i < MAX_BASETRAIL_BEAMS; i++ )
- {
- baseTrailBeam_t *btb = &baseTrailBeams[ i ];
- memset( btb, 0, sizeof( baseTrailBeam_t ) );
- }
-
- //and bring in the new
-/* for( i = 0; i < MAX_TRAIL_FILES; i++ )
- {
- s[ i ] = CG_ConfigString( CS_TRAIL_FILES + i );
-
- if( strlen( s[ i ] ) > 0 )
- {
- CG_Printf( "...loading '%s'\n", s[ i ] );
- CG_ParseTrailFile( s[ i ] );
- }
- else
- break;
- }*/
- CG_Printf( "trail.trail: %d\n", CG_ParseTrailFile( "scripts/trail.trail" ) );
-}
-
-/*
-===============
-CG_RegisterTrailSystem
-
-Load the media that a trail system needs
-===============
-*/
-qhandle_t CG_RegisterTrailSystem( char *name )
-{
- int i, j;
- baseTrailSystem_t *bts;
- baseTrailBeam_t *btb;
-
- for( i = 0; i < MAX_BASETRAIL_SYSTEMS; i++ )
- {
- bts = &baseTrailSystems[ i ];
-
- if( !Q_stricmp( bts->name, name ) )
- {
- //already registered
- if( bts->registered )
- return i + 1;
-
- for( j = 0; j < bts->numBeams; j++ )
- {
- btb = bts->beams[ j ];
-
- btb->shader = trap_R_RegisterShader( btb->shaderName );
- }
-
- if( cg_debugTrails.integer >= 1 )
- CG_Printf( "Registered trail system %s\n", name );
-
- bts->registered = qtrue;
-
- //avoid returning 0
- return i + 1;
- }
- }
-
- CG_Printf( S_COLOR_RED "ERROR: failed to register trail system %s\n", name );
- return 0;
-}
-
-
-/*
-===============
-CG_SpawnNewTrailBeam
-
-Allocate a new trail beam
-===============
-*/
-static trailBeam_t *CG_SpawnNewTrailBeam( baseTrailBeam_t *btb,
- trailSystem_t *parent )
-{
- int i;
- trailBeam_t *tb = NULL;
- trailSystem_t *ts = parent;
-
- for( i = 0; i < MAX_TRAIL_BEAMS; i++ )
- {
- tb = &trailBeams[ i ];
-
- if( !tb->valid )
- {
- memset( tb, 0, sizeof( trailBeam_t ) );
-
- //found a free slot
- tb->class = btb;
- tb->parent = ts;
-
- tb->valid = qtrue;
-
- if( cg_debugTrails.integer >= 1 )
- CG_Printf( "TB %s created\n", ts->class->name );
-
- break;
- }
- }
-
- return tb;
-}
-
-
-/*
-===============
-CG_SpawnNewTrailSystem
-
-Spawns a new trail system
-===============
-*/
-trailSystem_t *CG_SpawnNewTrailSystem( qhandle_t psHandle )
-{
- int i, j;
- trailSystem_t *ts = NULL;
- baseTrailSystem_t *bts = &baseTrailSystems[ psHandle - 1 ];
-
- if( !bts->registered )
- {
- CG_Printf( S_COLOR_RED "ERROR: a trail system has not been registered yet\n" );
- return NULL;
- }
-
- for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ )
- {
- ts = &trailSystems[ i ];
-
- if( !ts->valid )
- {
- memset( ts, 0, sizeof( trailSystem_t ) );
-
- //found a free slot
- ts->class = bts;
-
- ts->valid = qtrue;
- ts->destroyTime = -1;
-
- for( j = 0; j < bts->numBeams; j++ )
- CG_SpawnNewTrailBeam( bts->beams[ j ], ts );
-
- if( cg_debugTrails.integer >= 1 )
- CG_Printf( "TS %s created\n", bts->name );
-
- break;
- }
- }
-
- return ts;
-}
-
-/*
-===============
-CG_DestroyTrailSystem
-
-Destroy a trail system
-===============
-*/
-void CG_DestroyTrailSystem( trailSystem_t **ts )
-{
- (*ts)->destroyTime = cg.time;
-
- if( CG_Attached( &(*ts)->frontAttachment ) &&
- !CG_Attached( &(*ts)->backAttachment ) )
- {
- vec3_t v;
-
- // attach the trail head to a static point
- CG_AttachmentPoint( &(*ts)->frontAttachment, v );
- CG_SetAttachmentPoint( &(*ts)->frontAttachment, v );
- CG_AttachToPoint( &(*ts)->frontAttachment );
-
- (*ts)->frontAttachment.centValid = qfalse; // a bit naughty
- }
-
- ts = NULL;
-}
-
-/*
-===============
-CG_IsTrailSystemValid
-
-Test a trail system for validity
-===============
-*/
-qboolean CG_IsTrailSystemValid( trailSystem_t **ts )
-{
- if( *ts == NULL || ( *ts && !(*ts)->valid ) )
- {
- if( *ts && !(*ts)->valid )
- *ts = NULL;
-
- return qfalse;
- }
-
- return qtrue;
-}
-
-/*
-===============
-CG_GarbageCollectTrailSystems
-
-Destroy inactive trail systems
-===============
-*/
-static void CG_GarbageCollectTrailSystems( void )
-{
- int i, j, count;
- trailSystem_t *ts;
- trailBeam_t *tb;
- int centNum;
-
- for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ )
- {
- ts = &trailSystems[ i ];
- count = 0;
-
- //don't bother checking already invalid systems
- if( !ts->valid )
- continue;
-
- for( j = 0; j < MAX_TRAIL_BEAMS; j++ )
- {
- tb = &trailBeams[ j ];
-
- if( tb->valid && tb->parent == ts )
- count++;
- }
-
- if( !count )
- ts->valid = qfalse;
-
- //check systems where the parent cent has left the PVS
- //( local player entity is always valid )
- if( ( centNum = CG_AttachmentCentNum( &ts->frontAttachment ) ) >= 0 &&
- centNum != cg.snap->ps.clientNum )
- {
- trailSystem_t *tempTS = ts;
-
- if( !cg_entities[ centNum ].valid )
- CG_DestroyTrailSystem( &tempTS );
- }
-
- if( ( centNum = CG_AttachmentCentNum( &ts->backAttachment ) ) >= 0 &&
- centNum != cg.snap->ps.clientNum )
- {
- trailSystem_t *tempTS = ts;
-
- if( !cg_entities[ centNum ].valid )
- CG_DestroyTrailSystem( &tempTS );
- }
-
- if( cg_debugTrails.integer >= 1 && !ts->valid )
- CG_Printf( "TS %s garbage collected\n", ts->class->name );
- }
-}
-
-/*
-===============
-CG_AddTrails
-
-Add trails to the scene
-===============
-*/
-void CG_AddTrails( void )
-{
- int i;
- trailBeam_t *tb;
- int numTS = 0, numTB = 0;
-
- //remove expired trail systems
- CG_GarbageCollectTrailSystems( );
-
- for( i = 0; i < MAX_TRAIL_BEAMS; i++ )
- {
- tb = &trailBeams[ i ];
-
- if( tb->valid )
- {
- CG_UpdateBeam( tb );
- CG_RenderBeam( tb );
- }
- }
-
- if( cg_debugTrails.integer >= 2 )
- {
- for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ )
- if( trailSystems[ i ].valid )
- numTS++;
-
- for( i = 0; i < MAX_TRAIL_BEAMS; i++ )
- if( trailBeams[ i ].valid )
- numTB++;
-
- CG_Printf( "TS: %d TB: %d\n", numTS, numTB );
- }
-}
-
-static trailSystem_t *testTS;
-static qhandle_t testTSHandle;
-
-/*
-===============
-CG_DestroyTestTS_f
-
-Destroy the test a trail system
-===============
-*/
-void CG_DestroyTestTS_f( void )
-{
- if( CG_IsTrailSystemValid( &testTS ) )
- CG_DestroyTrailSystem( &testTS );
-}
-
-/*
-===============
-CG_TestTS_f
-
-Test a trail system
-===============
-*/
-void CG_TestTS_f( void )
-{
- char tsName[ MAX_QPATH ];
-
- if( trap_Argc( ) < 2 )
- return;
-
- Q_strncpyz( tsName, CG_Argv( 1 ), MAX_QPATH );
- testTSHandle = CG_RegisterTrailSystem( tsName );
-
- if( testTSHandle )
- {
- CG_DestroyTestTS_f( );
-
- testTS = CG_SpawnNewTrailSystem( testTSHandle );
-
- if( CG_IsTrailSystemValid( &testTS ) )
- {
- CG_SetAttachmentCent( &testTS->frontAttachment, &cg_entities[ 0 ] );
- CG_AttachToCent( &testTS->frontAttachment );
- }
- }
-}