diff options
Diffstat (limited to 'mod/src/cgame')
28 files changed, 0 insertions, 25931 deletions
diff --git a/mod/src/cgame/cg_animation.c b/mod/src/cgame/cg_animation.c deleted file mode 100644 index 5295998e..00000000 --- a/mod/src/cgame/cg_animation.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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" - -/* -=============== -CG_RunLerpFrame - -Sets cg.snap, cg.oldFrame, and cg.backlerp -cg.time should be between oldFrameTime and frameTime after exit -=============== -*/ -void CG_RunLerpFrame( lerpFrame_t *lf ) -{ - int f, numFrames; - animation_t *anim; - - // debugging tool to get no animations - if( cg_animSpeed.integer == 0 ) - { - lf->oldFrame = lf->frame = lf->backlerp = 0; - return; - } - - // if we have passed the current frame, move it to - // oldFrame and calculate a new frame - if( cg.time >= lf->frameTime ) - { - lf->oldFrame = lf->frame; - lf->oldFrameTime = lf->frameTime; - - // get the next frame based on the animation - anim = lf->animation; - if( !anim->frameLerp ) - return; // shouldn't happen - - if( cg.time < lf->animationTime ) - lf->frameTime = lf->animationTime; // initial lerp - else - lf->frameTime = lf->oldFrameTime + anim->frameLerp; - - f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; - numFrames = anim->numFrames; - if( anim->flipflop ) - numFrames *= 2; - - if( f >= numFrames ) - { - f -= numFrames; - if( anim->loopFrames ) - { - f %= anim->loopFrames; - f += anim->numFrames - anim->loopFrames; - } - else - { - f = numFrames - 1; - // the animation is stuck at the end, so it - // can immediately transition to another sequence - lf->frameTime = cg.time; - } - } - - if( anim->reversed ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - f; - else if( anim->flipflop && f >= anim->numFrames ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); - else - lf->frame = anim->firstFrame + f; - - if( cg.time > lf->frameTime ) - { - lf->frameTime = cg.time; - if( cg_debugAnim.integer ) - CG_Printf( "Clamp lf->frameTime\n" ); - } - } - - if( lf->frameTime > cg.time + 200 ) - lf->frameTime = cg.time; - - if( lf->oldFrameTime > cg.time ) - lf->oldFrameTime = cg.time; - - // calculate current lerp value - if( lf->frameTime == lf->oldFrameTime ) - lf->backlerp = 0; - else - lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); -} diff --git a/mod/src/cgame/cg_animmapobj.c b/mod/src/cgame/cg_animmapobj.c deleted file mode 100644 index f0e964bf..00000000 --- a/mod/src/cgame/cg_animmapobj.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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" - - -/* -=============== -CG_DoorAnimation -=============== -*/ -static void CG_DoorAnimation( centity_t *cent, int *old, int *now, float *backLerp ) -{ - CG_RunLerpFrame( ¢->lerpFrame ); - - *old = cent->lerpFrame.oldFrame; - *now = cent->lerpFrame.frame; - *backLerp = cent->lerpFrame.backlerp; -} - - -/* -=============== -CG_ModelDoor -=============== -*/ -void CG_ModelDoor( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *es; - animation_t anim; - lerpFrame_t *lf = ¢->lerpFrame; - - es = ¢->currentState; - - if( !es->modelindex ) - return; - - //create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - AnglesToAxis( cent->lerpAngles, ent.axis ); - - ent.renderfx = RF_NOSHADOW; - - //add the door model - ent.skinNum = 0; - ent.hModel = cgs.gameModels[ es->modelindex ]; - - //scale the door - VectorScale( ent.axis[ 0 ], es->origin2[ 0 ], ent.axis[ 0 ] ); - VectorScale( ent.axis[ 1 ], es->origin2[ 1 ], ent.axis[ 1 ] ); - VectorScale( ent.axis[ 2 ], es->origin2[ 2 ], ent.axis[ 2 ] ); - ent.nonNormalizedAxes = qtrue; - - //setup animation - anim.firstFrame = es->powerups; - anim.numFrames = es->weapon; - anim.reversed = !es->legsAnim; - anim.flipflop = qfalse; - anim.loopFrames = 0; - anim.frameLerp = 1000 / es->torsoAnim; - anim.initialLerp = 1000 / es->torsoAnim; - - //door changed state - if( es->legsAnim != cent->doorState ) - { - lf->animationTime = lf->frameTime + anim.initialLerp; - cent->doorState = es->legsAnim; - } - - lf->animation = &anim; - - //run animation - CG_DoorAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); - - trap_R_AddRefEntityToScene( &ent ); -} - - -/* -=============== -CG_AMOAnimation -=============== -*/ -static void CG_AMOAnimation( centity_t *cent, int *old, int *now, float *backLerp ) -{ - if( !( cent->currentState.eFlags & EF_MOVER_STOP ) ) - { - int delta = cg.time - cent->miscTime; - - //hack to prevent "pausing" mucking up the lerping - if( delta > 900 ) - { - cent->lerpFrame.oldFrameTime += delta; - cent->lerpFrame.frameTime += delta; - } - - CG_RunLerpFrame( ¢->lerpFrame ); - cent->miscTime = cg.time; - } - - *old = cent->lerpFrame.oldFrame; - *now = cent->lerpFrame.frame; - *backLerp = cent->lerpFrame.backlerp; -} - - -/* -================== -CG_animMapObj -================== -*/ -void CG_AnimMapObj( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *es; - float scale; - animation_t anim; - - es = ¢->currentState; - - // if set to invisible, skip - if( !es->modelindex || ( es->eFlags & EF_NODRAW ) ) - return; - - memset( &ent, 0, sizeof( ent ) ); - - VectorCopy( es->angles, cent->lerpAngles ); - AnglesToAxis( cent->lerpAngles, ent.axis ); - - ent.hModel = cgs.gameModels[ es->modelindex ]; - - VectorCopy( cent->lerpOrigin, ent.origin); - VectorCopy( cent->lerpOrigin, ent.oldorigin); - - ent.nonNormalizedAxes = qfalse; - - //scale the model - if( es->angles2[ 0 ] ) - { - scale = es->angles2[ 0 ]; - VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); - VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); - VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); - ent.nonNormalizedAxes = qtrue; - } - - //setup animation - anim.firstFrame = es->powerups; - anim.numFrames = es->weapon; - anim.reversed = qfalse; - anim.flipflop = qfalse; - - // if numFrames is negative the animation is reversed - if( anim.numFrames < 0 ) - { - anim.numFrames = -anim.numFrames; - anim.reversed = qtrue; - } - - anim.loopFrames = es->torsoAnim; - - if( !es->legsAnim ) - { - anim.frameLerp = 1000; - anim.initialLerp = 1000; - } - else - { - anim.frameLerp = 1000 / es->legsAnim; - anim.initialLerp = 1000 / es->legsAnim; - } - - cent->lerpFrame.animation = &anim; - - //run animation - CG_AMOAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); - - // add to refresh list - trap_R_AddRefEntityToScene(&ent); -} diff --git a/mod/src/cgame/cg_attachment.c b/mod/src/cgame/cg_attachment.c deleted file mode 100644 index a256318b..00000000 --- a/mod/src/cgame/cg_attachment.c +++ /dev/null @@ -1,395 +0,0 @@ -// cg_attachment.c -- an abstract attachment 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" - -/* -=============== -CG_AttachmentPoint - -Return the attachment point -=============== -*/ -qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v ) -{ - centity_t *cent; - - if( !a ) - return qfalse; - - // if it all breaks, then use the last point we know was correct - VectorCopy( a->lastValidAttachmentPoint, v ); - - switch( a->type ) - { - case AT_STATIC: - if( !a->staticValid ) - return qfalse; - - VectorCopy( a->origin, v ); - break; - - case AT_TAG: - if( !a->tagValid ) - return qfalse; - - AxisCopy( axisDefault, a->re.axis ); - CG_PositionRotatedEntityOnTag( &a->re, &a->parent, - a->model, a->tagName ); - VectorCopy( a->re.origin, v ); - break; - - case AT_CENT: - if( !a->centValid ) - return qfalse; - - if( a->centNum == cg.predictedPlayerState.clientNum ) - { - // this is smoother if it's the local client - VectorCopy( cg.predictedPlayerState.origin, v ); - } - else - { - cent = &cg_entities[ a->centNum ]; - VectorCopy( cent->lerpOrigin, v ); - } - break; - - case AT_PARTICLE: - if( !a->particleValid ) - return qfalse; - - if( !a->particle->valid ) - { - a->particleValid = qfalse; - return qfalse; - } - else - VectorCopy( a->particle->origin, v ); - break; - - default: - CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" ); - break; - } - - if( a->hasOffset ) - VectorAdd( v, a->offset, v ); - - VectorCopy( v, a->lastValidAttachmentPoint ); - - return qtrue; -} - -/* -=============== -CG_AttachmentDir - -Return the attachment direction -=============== -*/ -qboolean CG_AttachmentDir( attachment_t *a, vec3_t v ) -{ - vec3_t forward; - centity_t *cent; - - if( !a ) - return qfalse; - - switch( a->type ) - { - case AT_STATIC: - return qfalse; - break; - - case AT_TAG: - if( !a->tagValid ) - return qfalse; - - VectorCopy( a->re.axis[ 0 ], v ); - break; - - case AT_CENT: - if( !a->centValid ) - return qfalse; - - cent = &cg_entities[ a->centNum ]; - AngleVectors( cent->lerpAngles, forward, NULL, NULL ); - VectorCopy( forward, v ); - break; - - case AT_PARTICLE: - if( !a->particleValid ) - return qfalse; - - if( !a->particle->valid ) - { - a->particleValid = qfalse; - return qfalse; - } - else - VectorCopy( a->particle->velocity, v ); - break; - - default: - CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" ); - break; - } - - VectorNormalize( v ); - return qtrue; -} - -/* -=============== -CG_AttachmentAxis - -Return the attachment axis -=============== -*/ -qboolean CG_AttachmentAxis( attachment_t *a, vec3_t axis[ 3 ] ) -{ - centity_t *cent; - - if( !a ) - return qfalse; - - switch( a->type ) - { - case AT_STATIC: - return qfalse; - break; - - case AT_TAG: - if( !a->tagValid ) - return qfalse; - - AxisCopy( a->re.axis, axis ); - break; - - case AT_CENT: - if( !a->centValid ) - return qfalse; - - cent = &cg_entities[ a->centNum ]; - AnglesToAxis( cent->lerpAngles, axis ); - break; - - case AT_PARTICLE: - return qfalse; - break; - - default: - CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" ); - break; - } - - return qtrue; -} - -/* -=============== -CG_AttachmentVelocity - -If the attachment can have velocity, return it -=============== -*/ -qboolean CG_AttachmentVelocity( attachment_t *a, vec3_t v ) -{ - if( !a ) - return qfalse; - - if( a->particleValid && a->particle->valid ) - { - VectorCopy( a->particle->velocity, v ); - return qtrue; - } - else if( a->centValid ) - { - centity_t *cent = &cg_entities[ a->centNum ]; - - VectorCopy( cent->currentState.pos.trDelta, v ); - return qtrue; - } - - return qfalse; -} - -/* -=============== -CG_AttachmentCentNum - -If the attachment has a centNum, return it -=============== -*/ -int CG_AttachmentCentNum( attachment_t *a ) -{ - if( !a || !a->centValid ) - return -1; - - return a->centNum; -} - -/* -=============== -CG_Attached - -If the attachment is valid, return qtrue -=============== -*/ -qboolean CG_Attached( attachment_t *a ) -{ - if( !a ) - return qfalse; - - return a->attached; -} - -/* -=============== -CG_AttachToPoint - -Attach to a point in space -=============== -*/ -void CG_AttachToPoint( attachment_t *a ) -{ - if( !a || !a->staticValid ) - return; - - a->type = AT_STATIC; - a->attached = qtrue; -} - -/* -=============== -CG_AttachToCent - -Attach to a centity_t -=============== -*/ -void CG_AttachToCent( attachment_t *a ) -{ - if( !a || !a->centValid ) - return; - - a->type = AT_CENT; - a->attached = qtrue; -} - -/* -=============== -CG_AttachToTag - -Attach to a model tag -=============== -*/ -void CG_AttachToTag( attachment_t *a ) -{ - if( !a || !a->tagValid ) - return; - - a->type = AT_TAG; - a->attached = qtrue; -} - -/* -=============== -CG_AttachToParticle - -Attach to a particle -=============== -*/ -void CG_AttachToParticle( attachment_t *a ) -{ - if( !a || !a->particleValid ) - return; - - a->type = AT_PARTICLE; - a->attached = qtrue; -} - -/* -=============== -CG_SetAttachmentPoint -=============== -*/ -void CG_SetAttachmentPoint( attachment_t *a, vec3_t v ) -{ - if( !a ) - return; - - VectorCopy( v, a->origin ); - a->staticValid = qtrue; -} - -/* -=============== -CG_SetAttachmentCent -=============== -*/ -void CG_SetAttachmentCent( attachment_t *a, centity_t *cent ) -{ - if( !a || !cent ) - return; - - a->centNum = cent->currentState.number; - a->centValid = qtrue; -} - -/* -=============== -CG_SetAttachmentTag -=============== -*/ -void CG_SetAttachmentTag( attachment_t *a, refEntity_t parent, - qhandle_t model, char *tagName ) -{ - if( !a ) - return; - - a->parent = parent; - a->model = model; - strncpy( a->tagName, tagName, MAX_STRING_CHARS ); - a->tagValid = qtrue; -} - -/* -=============== -CG_SetAttachmentParticle -=============== -*/ -void CG_SetAttachmentParticle( attachment_t *a, particle_t *p ) -{ - if( !a ) - return; - - a->particle = p; - a->particleValid = qtrue; -} - -/* -=============== -CG_SetAttachmentOffset -=============== -*/ -void CG_SetAttachmentOffset( attachment_t *a, vec3_t v ) -{ - if( !a ) - return; - - VectorCopy( v, a->offset ); - a->hasOffset = qtrue; -} diff --git a/mod/src/cgame/cg_buildable.c b/mod/src/cgame/cg_buildable.c deleted file mode 100644 index 348bb433..00000000 --- a/mod/src/cgame/cg_buildable.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * 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" - -char *cg_buildableSoundNames[ MAX_BUILDABLE_ANIMATIONS ] = -{ - "construct1.wav", - "construct2.wav", - "idle1.wav", - "idle2.wav", - "idle3.wav", - "attack1.wav", - "attack2.wav", - "spawn1.wav", - "spawn2.wav", - "pain1.wav", - "pain2.wav", - "destroy1.wav", - "destroy2.wav", - "destroyed.wav" -}; - -static sfxHandle_t defaultAlienSounds[ MAX_BUILDABLE_ANIMATIONS ]; -static sfxHandle_t defaultHumanSounds[ MAX_BUILDABLE_ANIMATIONS ]; - -/* -=================== -CG_AlienBuildableExplosion - -Generated a bunch of gibs launching out from a location -=================== -*/ -void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir ) -{ - particleSystem_t *ps; - - trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.alienBuildableExplosion ); - - //particle system - ps = CG_SpawnNewParticleSystem( cgs.media.alienBuildableDestroyedPS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentPoint( &ps->attachment, origin ); - CG_SetParticleSystemNormal( ps, dir ); - CG_AttachToPoint( &ps->attachment ); - } -} - -/* -================= -CG_HumanBuildableExplosion - -Called for human buildables as they are destroyed -================= -*/ -void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ) -{ - particleSystem_t *ps; - - trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.humanBuildableExplosion ); - - //particle system - ps = CG_SpawnNewParticleSystem( cgs.media.humanBuildableDestroyedPS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentPoint( &ps->attachment, origin ); - CG_SetParticleSystemNormal( ps, dir ); - CG_AttachToPoint( &ps->attachment ); - } -} - - -#define CREEP_SIZE 64.0f - -/* -================== -CG_Creep -================== -*/ -static void CG_Creep( centity_t *cent ) -{ - int msec; - float size, frac; - trace_t tr; - vec3_t temp, origin; - int scaleUpTime = BG_FindBuildTimeForBuildable( cent->currentState.modelindex ); - int time; - - time = cent->currentState.time; - - //should the creep be growing or receding? - if( time >= 0 ) - { - msec = cg.time - time; - if( msec >= 0 && msec < scaleUpTime ) - frac = (float)msec / scaleUpTime; - else - frac = 1.0f; - } - else if( time < 0 ) - { - msec = cg.time + time; - if( msec >= 0 && msec < CREEP_SCALEDOWN_TIME ) - frac = 1.0f - ( (float)msec / CREEP_SCALEDOWN_TIME ); - else - frac = 0.0f; - } - - VectorCopy( cent->currentState.origin2, temp ); - VectorScale( temp, -4096, temp ); - VectorAdd( temp, cent->lerpOrigin, temp ); - - CG_Trace( &tr, cent->lerpOrigin, NULL, NULL, temp, cent->currentState.number, MASK_SOLID ); - - VectorCopy( tr.endpos, origin ); - - size = CREEP_SIZE * frac; - - if( size > 0.0f ) - CG_ImpactMark( cgs.media.creepShader, origin, cent->currentState.origin2, - 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, qfalse, size, qtrue ); -} - -/* -====================== -CG_ParseBuildableAnimationFile - -Read a configuration file containing animation counts and rates -models/buildables/hivemind/animation.cfg, etc -====================== -*/ -static qboolean CG_ParseBuildableAnimationFile( const char *filename, buildable_t buildable ) -{ - char *text_p; - int len; - int i; - char *token; - float fps; - char text[ 20000 ]; - fileHandle_t f; - animation_t *animations; - - animations = cg_buildables[ buildable ].animations; - - // load the file - len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if( len <= 0 ) - return qfalse; - - if( len >= sizeof( text ) - 1 ) - { - CG_Printf( "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 information for each frame - for( i = BANIM_NONE + 1; i < MAX_BUILDABLE_ANIMATIONS; i++ ) - { - - token = COM_Parse( &text_p ); - if( !*token ) - break; - - animations[ i ].firstFrame = atoi( token ); - - token = COM_Parse( &text_p ); - if( !*token ) - break; - - animations[ i ].numFrames = atoi( token ); - animations[ i ].reversed = qfalse; - animations[ i ].flipflop = qfalse; - - // if numFrames is negative the animation is reversed - if( animations[ i ].numFrames < 0 ) - { - animations[ i ].numFrames = -animations[ i ].numFrames; - animations[ i ].reversed = qtrue; - } - - token = COM_Parse( &text_p ); - if ( !*token ) - break; - - animations[i].loopFrames = atoi( token ); - - token = COM_Parse( &text_p ); - if( !*token ) - break; - - fps = atof( token ); - if( fps == 0 ) - fps = 1; - - animations[ i ].frameLerp = 1000 / fps; - animations[ i ].initialLerp = 1000 / fps; - } - - if( i != MAX_BUILDABLE_ANIMATIONS ) - { - CG_Printf( "Error parsing animation file: %s\n", filename ); - return qfalse; - } - - return qtrue; -} - -/* -====================== -CG_ParseBuildableSoundFile - -Read a configuration file containing sound properties -sound/buildables/hivemind/sound.cfg, etc -====================== -*/ -static qboolean CG_ParseBuildableSoundFile( const char *filename, buildable_t buildable ) -{ - char *text_p; - int len; - int i; - char *token; - char text[ 20000 ]; - fileHandle_t f; - sound_t *sounds; - - sounds = cg_buildables[ buildable ].sounds; - - // load the file - len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if ( len <= 0 ) - return qfalse; - - if ( len >= sizeof( text ) - 1 ) - { - CG_Printf( "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 information for each frame - for( i = BANIM_NONE + 1; i < MAX_BUILDABLE_ANIMATIONS; i++ ) - { - - token = COM_Parse( &text_p ); - if ( !*token ) - break; - - sounds[ i ].enabled = atoi( token ); - - token = COM_Parse( &text_p ); - if ( !*token ) - break; - - sounds[ i ].looped = atoi( token ); - - } - - if( i != MAX_BUILDABLE_ANIMATIONS ) - { - CG_Printf( "Error parsing sound file: %s\n", filename ); - return qfalse; - } - - return qtrue; -} -/* -=============== -CG_InitBuildables - -Initialises the animation db -=============== -*/ -void CG_InitBuildables( void ) -{ - char filename[ MAX_QPATH ]; - char soundfile[ MAX_QPATH ]; - char *buildableName; - char *modelFile; - int i; - int j; - fileHandle_t f; - - memset( cg_buildables, 0, sizeof( cg_buildables ) ); - - //default sounds - for( j = BANIM_NONE + 1; j < MAX_BUILDABLE_ANIMATIONS; j++ ) - { - strcpy( soundfile, cg_buildableSoundNames[ j - 1 ] ); - - Com_sprintf( filename, sizeof( filename ), "sound/buildables/alien/%s", soundfile ); - defaultAlienSounds[ j ] = trap_S_RegisterSound( filename, qfalse ); - - Com_sprintf( filename, sizeof( filename ), "sound/buildables/human/%s", soundfile ); - defaultHumanSounds[ j ] = trap_S_RegisterSound( filename, qfalse ); - } - - cg.buildablesFraction = 0.0f; - - for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) - { - buildableName = BG_FindNameForBuildable( i ); - - //animation.cfg - Com_sprintf( filename, sizeof( filename ), "models/buildables/%s/animation.cfg", buildableName ); - if ( !CG_ParseBuildableAnimationFile( filename, i ) ) - Com_Printf( S_COLOR_YELLOW "WARNING: failed to load animation file %s\n", filename ); - - //sound.cfg - Com_sprintf( filename, sizeof( filename ), "sound/buildables/%s/sound.cfg", buildableName ); - if ( !CG_ParseBuildableSoundFile( filename, i ) ) - Com_Printf( S_COLOR_YELLOW "WARNING: failed to load sound file %s\n", filename ); - - //models - for( j = 0; j <= 3; j++ ) - { - if( ( modelFile = BG_FindModelsForBuildable( i, j ) ) ) - cg_buildables[ i ].models[ j ] = trap_R_RegisterModel( modelFile ); - } - - //sounds - for( j = BANIM_NONE + 1; j < MAX_BUILDABLE_ANIMATIONS; j++ ) - { - strcpy( soundfile, cg_buildableSoundNames[ j - 1 ] ); - Com_sprintf( filename, sizeof( filename ), "sound/buildables/%s/%s", buildableName, soundfile ); - - if( cg_buildables[ i ].sounds[ j ].enabled ) - { - if( trap_FS_FOpenFile( filename, &f, FS_READ ) > 0 ) - { - //file exists so close it - trap_FS_FCloseFile( f ); - - cg_buildables[ i ].sounds[ j ].sound = trap_S_RegisterSound( filename, qfalse ); - } - else - { - //file doesn't exist - use default - if( BG_FindTeamForBuildable( i ) == BIT_ALIENS ) - cg_buildables[ i ].sounds[ j ].sound = defaultAlienSounds[ j ]; - else - cg_buildables[ i ].sounds[ j ].sound = defaultHumanSounds[ j ]; - } - } - } - - cg.buildablesFraction = (float)i / (float)( BA_NUM_BUILDABLES - 1 ); - trap_UpdateScreen( ); - } - - cgs.media.teslaZapTS = CG_RegisterTrailSystem( "models/buildables/tesla/zap" ); -} - -/* -=============== -CG_SetBuildableLerpFrameAnimation - -may include ANIM_TOGGLEBIT -=============== -*/ -static void CG_SetBuildableLerpFrameAnimation( buildable_t buildable, lerpFrame_t *lf, int newAnimation ) -{ - animation_t *anim; - - lf->animationNumber = newAnimation; - - if( newAnimation < 0 || newAnimation >= MAX_BUILDABLE_ANIMATIONS ) - CG_Error( "Bad animation number: %i", newAnimation ); - - anim = &cg_buildables[ buildable ].animations[ newAnimation ]; - - //this item has just spawned so lf->frameTime will be zero - if( !lf->animation ) - lf->frameTime = cg.time + 1000; //1 sec delay before starting the spawn anim - - lf->animation = anim; - lf->animationTime = lf->frameTime + anim->initialLerp; - - if( cg_debugAnim.integer ) - CG_Printf( "Anim: %i\n", newAnimation ); -} - -/* -=============== -CG_RunBuildableLerpFrame - -Sets cg.snap, cg.oldFrame, and cg.backlerp -cg.time should be between oldFrameTime and frameTime after exit -=============== -*/ -static void CG_RunBuildableLerpFrame( centity_t *cent ) -{ - int f, numFrames; - buildable_t buildable = cent->currentState.modelindex; - lerpFrame_t *lf = ¢->lerpFrame; - animation_t *anim; - buildableAnimNumber_t newAnimation = cent->buildableAnim & ~( ANIM_TOGGLEBIT|ANIM_FORCEBIT ); - - // debugging tool to get no animations - if( cg_animSpeed.integer == 0 ) - { - lf->oldFrame = lf->frame = lf->backlerp = 0; - return; - } - - // see if the animation sequence is switching - if( newAnimation != lf->animationNumber || !lf->animation ) - { - if( cg_debugRandom.integer ) - CG_Printf( "newAnimation: %d lf->animationNumber: %d lf->animation: %d\n", - newAnimation, lf->animationNumber, lf->animation ); - - CG_SetBuildableLerpFrameAnimation( buildable, lf, newAnimation ); - - if( !cg_buildables[ buildable ].sounds[ newAnimation ].looped && - cg_buildables[ buildable ].sounds[ newAnimation ].enabled ) - { - if( cg_debugRandom.integer ) - CG_Printf( "Sound for animation %d for a %s\n", - newAnimation, BG_FindHumanNameForBuildable( buildable ) ); - - trap_S_StartSound( cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, - cg_buildables[ buildable ].sounds[ newAnimation ].sound ); - } - } - - if( cg_buildables[ buildable ].sounds[ lf->animationNumber ].looped && - cg_buildables[ buildable ].sounds[ lf->animationNumber ].enabled ) - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - cg_buildables[ buildable ].sounds[ lf->animationNumber ].sound ); - - // if we have passed the current frame, move it to - // oldFrame and calculate a new frame - if( cg.time >= lf->frameTime ) - { - lf->oldFrame = lf->frame; - lf->oldFrameTime = lf->frameTime; - - // get the next frame based on the animation - anim = lf->animation; - if( !anim->frameLerp ) - return; // shouldn't happen - - if ( cg.time < lf->animationTime ) - lf->frameTime = lf->animationTime; // initial lerp - else - lf->frameTime = lf->oldFrameTime + anim->frameLerp; - - f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; - numFrames = anim->numFrames; - if(anim->flipflop) - numFrames *= 2; - - if( f >= numFrames ) - { - f -= numFrames; - if( anim->loopFrames ) - { - f %= anim->loopFrames; - f += anim->numFrames - anim->loopFrames; - } - else - { - f = numFrames - 1; - // the animation is stuck at the end, so it - // can immediately transition to another sequence - lf->frameTime = cg.time; - cent->buildableAnim = cent->currentState.torsoAnim; - } - } - - if( anim->reversed ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - f; - else if( anim->flipflop && f >= anim->numFrames ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); - else - lf->frame = anim->firstFrame + f; - - if( cg.time > lf->frameTime ) - { - lf->frameTime = cg.time; - if( cg_debugAnim.integer ) - CG_Printf( "Clamp lf->frameTime\n"); - } - } - - if( lf->frameTime > cg.time + 200 ) - lf->frameTime = cg.time; - - if( lf->oldFrameTime > cg.time ) - lf->oldFrameTime = cg.time; - - // calculate current lerp value - if( lf->frameTime == lf->oldFrameTime ) - lf->backlerp = 0; - else - lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); -} - -/* -=============== -CG_BuildableAnimation -=============== -*/ -static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *backLerp ) -{ - entityState_t *es = ¢->currentState; - - //if no animation is set default to idle anim - if( cent->buildableAnim == BANIM_NONE ) - cent->buildableAnim = es->torsoAnim; - - //display the first frame of the construction anim if not yet spawned - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) - { - animation_t *anim = &cg_buildables[ es->modelindex ].animations[ BANIM_CONSTRUCT1 ]; - - //so that when animation starts for real it has sensible numbers - cent->lerpFrame.oldFrameTime = - cent->lerpFrame.frameTime = - cent->lerpFrame.animationTime = - cg.time; - - *old = cent->lerpFrame.oldFrame = anim->firstFrame; - *now = cent->lerpFrame.frame = anim->firstFrame; - *backLerp = cent->lerpFrame.backlerp = 0.0f; - - //ensure that an animation is triggered once the buildable has spawned - cent->oldBuildableAnim = BANIM_NONE; - } - else - { - if( ( cent->oldBuildableAnim ^ es->legsAnim ) & ANIM_TOGGLEBIT ) - { - if( cg_debugAnim.integer ) - CG_Printf( "%d->%d l:%d t:%d %s(%d)\n", - cent->oldBuildableAnim, cent->buildableAnim, - es->legsAnim, es->torsoAnim, - BG_FindHumanNameForBuildable( es->modelindex ), es->number ); - - if( cent->buildableAnim == es->torsoAnim || es->legsAnim & ANIM_FORCEBIT ) - cent->buildableAnim = cent->oldBuildableAnim = es->legsAnim; - else - cent->buildableAnim = cent->oldBuildableAnim = es->torsoAnim; - } - - CG_RunBuildableLerpFrame( cent ); - - *old = cent->lerpFrame.oldFrame; - *now = cent->lerpFrame.frame; - *backLerp = cent->lerpFrame.backlerp; - } -} - -#define TRACE_DEPTH 64.0f - -/* -=============== -CG_PositionAndOrientateBuildable -=============== -*/ -static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t inOrigin, - const vec3_t normal, const int skipNumber, - const vec3_t mins, const vec3_t maxs, - vec3_t outAxis[ 3 ], vec3_t outOrigin ) -{ - vec3_t forward, start, end; - trace_t tr; - - AngleVectors( angles, forward, NULL, NULL ); - VectorCopy( normal, outAxis[ 2 ] ); - ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); - - if( !VectorNormalize( outAxis[ 0 ] ) ) - { - AngleVectors( angles, NULL, NULL, forward ); - ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] ); - VectorNormalize( outAxis[ 0 ] ); - } - - CrossProduct( outAxis[ 0 ], outAxis[ 2 ], outAxis[ 1 ] ); - outAxis[ 1 ][ 0 ] = -outAxis[ 1 ][ 0 ]; - outAxis[ 1 ][ 1 ] = -outAxis[ 1 ][ 1 ]; - outAxis[ 1 ][ 2 ] = -outAxis[ 1 ][ 2 ]; - - VectorMA( inOrigin, -TRACE_DEPTH, normal, end ); - VectorMA( inOrigin, 1.0f, normal, start ); - CG_CapTrace( &tr, start, mins, maxs, end, skipNumber, MASK_SOLID ); - - if( tr.fraction == 1.0f ) - { - //erm we missed completely - try again with a box trace - CG_Trace( &tr, start, mins, maxs, end, skipNumber, MASK_SOLID ); - } - - VectorMA( inOrigin, tr.fraction * -TRACE_DEPTH, normal, outOrigin ); -} - -/* -================== -CG_GhostBuildable -================== -*/ -void CG_GhostBuildable( buildable_t buildable ) -{ - refEntity_t ent; - playerState_t *ps; - vec3_t angles, entity_origin; - vec3_t mins, maxs; - trace_t tr; - float scale; - - ps = &cg.predictedPlayerState; - - memset( &ent, 0, sizeof( ent ) ); - - BG_FindBBoxForBuildable( buildable, mins, maxs ); - - BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, CG_Trace, entity_origin, angles, &tr ); - - CG_PositionAndOrientateBuildable( ps->viewangles, entity_origin, tr.plane.normal, ps->clientNum, - mins, maxs, ent.axis, ent.origin ); - - //offset on the Z axis if required - VectorMA( ent.origin, BG_FindZOffsetForBuildable( buildable ), tr.plane.normal, ent.origin ); - - VectorCopy( ent.origin, ent.lightingOrigin ); - VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all - - ent.hModel = cg_buildables[ buildable ].models[ 0 ]; - - if( ps->stats[ STAT_BUILDABLE ] & SB_VALID_TOGGLEBIT ) - ent.customShader = cgs.media.greenBuildShader; - else - ent.customShader = cgs.media.redBuildShader; - - //rescale the model - scale = BG_FindModelScaleForBuildable( buildable ); - - if( scale != 1.0f ) - { - VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); - VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); - VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); - - ent.nonNormalizedAxes = qtrue; - } - else - ent.nonNormalizedAxes = qfalse; - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - -/* -================== -CG_BuildableParticleEffects -================== -*/ -static void CG_BuildableParticleEffects( centity_t *cent ) -{ - entityState_t *es = ¢->currentState; - buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex ); - int health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT ); - float healthFrac = (float)health / B_HEALTH_SCALE; - - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) - return; - - if( team == BIT_HUMANS ) - { - if( healthFrac < 0.33f && !CG_IsParticleSystemValid( ¢->buildablePS ) ) - { - cent->buildablePS = CG_SpawnNewParticleSystem( cgs.media.humanBuildableDamagedPS ); - - if( CG_IsParticleSystemValid( ¢->buildablePS ) ) - { - CG_SetAttachmentCent( ¢->buildablePS->attachment, cent ); - CG_AttachToCent( ¢->buildablePS->attachment ); - } - } - else if( healthFrac >= 0.33f && CG_IsParticleSystemValid( ¢->buildablePS ) ) - CG_DestroyParticleSystem( ¢->buildablePS ); - } - else if( team == BIT_ALIENS ) - { - if( healthFrac < 0.33f && !CG_IsParticleSystemValid( ¢->buildablePS ) ) - { - cent->buildablePS = CG_SpawnNewParticleSystem( cgs.media.alienBuildableDamagedPS ); - - if( CG_IsParticleSystemValid( ¢->buildablePS ) ) - { - CG_SetAttachmentCent( ¢->buildablePS->attachment, cent ); - CG_SetParticleSystemNormal( cent->buildablePS, es->origin2 ); - CG_AttachToCent( ¢->buildablePS->attachment ); - } - } - else if( healthFrac >= 0.33f && CG_IsParticleSystemValid( ¢->buildablePS ) ) - CG_DestroyParticleSystem( ¢->buildablePS ); - } -} - - -#define HEALTH_BAR_WIDTH 50.0f -#define HEALTH_BAR_HEIGHT 5.0f - -/* -================== -CG_BuildableHealthBar -================== -*/ -static void CG_BuildableHealthBar( centity_t *cent ) -{ - vec3_t origin, origin2, down, right, back, downLength, rightLength; - float rimWidth = HEALTH_BAR_HEIGHT / 15.0f; - float doneWidth, leftWidth, progress; - int health; - qhandle_t shader; - entityState_t *es; - vec3_t mins, maxs; - - es = ¢->currentState; - - health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT ); - progress = (float)health / B_HEALTH_SCALE; - - if( progress < 0.0f ) - progress = 0.0f; - else if( progress > 1.0f ) - progress = 1.0f; - - if( progress < 0.33f ) - shader = cgs.media.redBuildShader; - else - shader = cgs.media.greenBuildShader; - - doneWidth = ( HEALTH_BAR_WIDTH - 2 * rimWidth ) * progress; - leftWidth = ( HEALTH_BAR_WIDTH - 2 * rimWidth ) - doneWidth; - - VectorCopy( cg.refdef.viewaxis[ 2 ], down ); - VectorInverse( down ); - VectorCopy( cg.refdef.viewaxis[ 1 ], right ); - VectorInverse( right ); - VectorSubtract( cg.refdef.vieworg, cent->lerpOrigin, back ); - VectorNormalize( back ); - VectorCopy( cent->lerpOrigin, origin ); - - BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); - VectorMA( origin, 48.0f, es->origin2, origin ); - VectorMA( origin, -HEALTH_BAR_WIDTH / 2.0f, right, origin ); - VectorMA( origin, maxs[ 0 ] + 8.0f, back, origin ); - - VectorCopy( origin, origin2 ); - VectorScale( right, rimWidth + doneWidth, rightLength ); - VectorScale( down, HEALTH_BAR_HEIGHT, downLength ); - CG_DrawPlane( origin2, downLength, rightLength, shader ); - - VectorMA( origin, rimWidth + doneWidth, right, origin2 ); - VectorScale( right, leftWidth, rightLength ); - VectorScale( down, rimWidth, downLength ); - CG_DrawPlane( origin2, downLength, rightLength, shader ); - - VectorMA( origin, rimWidth + doneWidth, right, origin2 ); - VectorMA( origin2, HEALTH_BAR_HEIGHT - rimWidth, down, origin2 ); - VectorScale( right, leftWidth, rightLength ); - VectorScale( down, rimWidth, downLength ); - CG_DrawPlane( origin2, downLength, rightLength, shader ); - - VectorMA( origin, HEALTH_BAR_WIDTH - rimWidth, right, origin2 ); - VectorScale( right, rimWidth, rightLength ); - VectorScale( down, HEALTH_BAR_HEIGHT, downLength ); - CG_DrawPlane( origin2, downLength, rightLength, shader ); - - if( !( es->generic1 & B_POWERED_TOGGLEBIT ) && - BG_FindTeamForBuildable( es->modelindex ) == BIT_HUMANS ) - { - VectorMA( origin, 15.0f, right, origin2 ); - VectorMA( origin2, HEALTH_BAR_HEIGHT + 5.0f, down, origin2 ); - VectorScale( right, HEALTH_BAR_WIDTH / 2.0f - 5.0f, rightLength ); - VectorScale( down, HEALTH_BAR_WIDTH / 2.0f - 5.0f, downLength ); - CG_DrawPlane( origin2, downLength, rightLength, cgs.media.noPowerShader ); - } -} - -#define BUILDABLE_SOUND_PERIOD 500 - -/* -================== -CG_Buildable -================== -*/ -void CG_Buildable( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *es = ¢->currentState; - vec3_t angles; - vec3_t surfNormal, xNormal, mins, maxs; - vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; - float rotAngle; - buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex ); - float scale; - int health; - float healthScale; - - //must be before EF_NODRAW check - if( team == BIT_ALIENS ) - CG_Creep( cent ); - - // if set to invisible, skip - if( es->eFlags & EF_NODRAW ) - { - if( CG_IsParticleSystemValid( ¢->buildablePS ) ) - CG_DestroyParticleSystem( ¢->buildablePS ); - - return; - } - - memset ( &ent, 0, sizeof( ent ) ); - - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); - - VectorCopy( es->origin2, surfNormal ); - - VectorCopy( es->angles, angles ); - BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); - - if( es->pos.trType == TR_STATIONARY ) - CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, es->number, - mins, maxs, ent.axis, ent.origin ); - - //offset on the Z axis if required - VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin ); - - VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all - VectorCopy( ent.origin, ent.lightingOrigin ); - - ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ]; - - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) - { - sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild; - - if( team == BIT_HUMANS ) - { - ent.customShader = cgs.media.humanSpawningShader; - prebuildSound = cgs.media.humanBuildablePrebuild; - } - else if( team == BIT_ALIENS ) - prebuildSound = cgs.media.alienBuildablePrebuild; - - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); - } - - CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); - - //rescale the model - scale = BG_FindModelScaleForBuildable( es->modelindex ); - - if( scale != 1.0f ) - { - VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); - VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); - VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); - - ent.nonNormalizedAxes = qtrue; - } - else - ent.nonNormalizedAxes = qfalse; - - - //add to refresh list - trap_R_AddRefEntityToScene( &ent ); - - CrossProduct( surfNormal, refNormal, xNormal ); - VectorNormalize( xNormal ); - rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) ); - - //turret barrel bit - if( cg_buildables[ es->modelindex ].models[ 1 ] ) - { - refEntity_t turretBarrel; - vec3_t flatAxis[ 3 ]; - - memset( &turretBarrel, 0, sizeof( turretBarrel ) ); - - turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ]; - - CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" ); - VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin ); - AnglesToAxis( es->angles2, flatAxis ); - - RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); - RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); - RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); - - turretBarrel.oldframe = ent.oldframe; - turretBarrel.frame = ent.frame; - turretBarrel.backlerp = ent.backlerp; - - turretBarrel.customShader = ent.customShader; - - if( scale != 1.0f ) - { - VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] ); - VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] ); - VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] ); - - turretBarrel.nonNormalizedAxes = qtrue; - } - else - turretBarrel.nonNormalizedAxes = qfalse; - - trap_R_AddRefEntityToScene( &turretBarrel ); - } - - //turret barrel bit - if( cg_buildables[ es->modelindex ].models[ 2 ] ) - { - refEntity_t turretTop; - vec3_t flatAxis[ 3 ]; - vec3_t swivelAngles; - - memset( &turretTop, 0, sizeof( turretTop ) ); - - VectorCopy( es->angles2, swivelAngles ); - swivelAngles[ PITCH ] = 0.0f; - - turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ]; - - CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" ); - VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin ); - AnglesToAxis( swivelAngles, flatAxis ); - - RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); - RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); - RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); - - turretTop.oldframe = ent.oldframe; - turretTop.frame = ent.frame; - turretTop.backlerp = ent.backlerp; - - turretTop.customShader = ent.customShader; - - if( scale != 1.0f ) - { - VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] ); - VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] ); - VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] ); - - turretTop.nonNormalizedAxes = qtrue; - } - else - turretTop.nonNormalizedAxes = qfalse; - - trap_R_AddRefEntityToScene( &turretTop ); - } - - switch( cg.predictedPlayerState.weapon ) - { - case WP_ABUILD: - case WP_ABUILD2: - case WP_HBUILD: - case WP_HBUILD2: - if( BG_FindTeamForBuildable( es->modelindex ) == - BG_FindTeamForWeapon( cg.predictedPlayerState.weapon ) ) - CG_BuildableHealthBar( cent ); - break; - - default: - break; - } - - //weapon effects for turrets - if( es->eFlags & EF_FIRING ) - { - weaponInfo_t *weapon = &cg_weapons[ es->weapon ]; - - if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME || - BG_FindProjTypeForBuildable( es->modelindex ) == WP_TESLAGEN ) - { - if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] || - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] || - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ) - { - trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ), - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ], - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ], - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ); - } - } - - if( weapon->wim[ WPM_PRIMARY ].firingSound ) - { - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, - weapon->wim[ WPM_PRIMARY ].firingSound ); - } - else if( weapon->readySound ) - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound ); - } - - health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT ); - healthScale = (float)health / B_HEALTH_SCALE; - - if( healthScale < cent->lastBuildableHealthScale && ( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) - { - if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time ) - { - if( team == BIT_HUMANS ) - { - int i = rand( ) % 4; - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] ); - } - else if( team == BIT_ALIENS ) - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage ); - - cent->lastBuildableDamageSoundTime = cg.time; - } - } - - cent->lastBuildableHealthScale = healthScale; - - //smoke etc for damaged buildables - CG_BuildableParticleEffects( cent ); -} diff --git a/mod/src/cgame/cg_consolecmds.c b/mod/src/cgame/cg_consolecmds.c deleted file mode 100644 index c875fa48..00000000 --- a/mod/src/cgame/cg_consolecmds.c +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_consolecmds.c -- text commands typed in at the local console, or -// executed by a key binding - -/* - * 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" - - - -void CG_TargetCommand_f( void ) -{ - int targetNum; - char test[ 4 ]; - - targetNum = CG_CrosshairPlayer( ); - if( !targetNum ) - return; - - trap_Argv( 1, test, 4 ); - trap_SendConsoleCommand( va( "gc %i %i", targetNum, atoi( test ) ) ); -} - - - -/* -================= -CG_SizeUp_f - -Keybinding command -================= -*/ -static void CG_SizeUp_f( void ) -{ - trap_Cvar_Set( "cg_viewsize", va( "%i", (int)( cg_viewsize.integer + 10 ) ) ); -} - - -/* -================= -CG_SizeDown_f - -Keybinding command -================= -*/ -static void CG_SizeDown_f( void ) -{ - trap_Cvar_Set( "cg_viewsize", va( "%i", (int)( cg_viewsize.integer - 10 ) ) ); -} - - -/* -============= -CG_Viewpos_f - -Debugging command to print the current position -============= -*/ -static void CG_Viewpos_f( void ) -{ - CG_Printf( "(%i %i %i) : %i\n", (int)cg.refdef.vieworg[ 0 ], - (int)cg.refdef.vieworg[ 1 ], (int)cg.refdef.vieworg[ 2 ], - (int)cg.refdefViewAngles[ YAW ] ); -} - - -static void CG_ScoresDown_f( void ) -{ - if( cg.scoresRequestTime + 2000 < cg.time ) - { - // the scores are more than two seconds out of data, - // so request new ones - cg.scoresRequestTime = cg.time; - //TA: added \n SendClientCommand doesn't call flush( )? - trap_SendClientCommand( "score\n" ); - - // leave the current scores up if they were already - // displayed, but if this is the first hit, clear them out - if( !cg.showScores ) - { - if( cg_debugRandom.integer ) - CG_Printf( "CG_ScoresDown_f: scores out of date\n" ); - - cg.showScores = qtrue; - cg.numScores = 0; - } - } - else - { - // show the cached contents even if they just pressed if it - // is within two seconds - cg.showScores = qtrue; - } -} - -static void CG_ScoresUp_f( void ) -{ - if( cg.showScores ) - { - cg.showScores = qfalse; - cg.scoreFadeTime = cg.time; - } -} - -static void CG_TellTarget_f( void ) -{ - int clientNum; - char command[ 128 ]; - char message[ 128 ]; - - clientNum = CG_CrosshairPlayer( ); - if( clientNum == -1 ) - return; - - trap_Args( message, 128 ); - Com_sprintf( command, 128, "tell %i %s", clientNum, message ); - trap_SendClientCommand( command ); -} - -static void CG_TellAttacker_f( void ) -{ - int clientNum; - char command[ 128 ]; - char message[ 128 ]; - - clientNum = CG_LastAttacker( ); - if( clientNum == -1 ) - return; - - trap_Args( message, 128 ); - Com_sprintf( command, 128, "tell %i %s", clientNum, message ); - trap_SendClientCommand( command ); -} - -typedef struct -{ - char *cmd; - void (*function)( void ); -} consoleCommand_t; - -static consoleCommand_t commands[ ] = -{ - { "testgun", CG_TestGun_f }, - { "testmodel", CG_TestModel_f }, - { "nextframe", CG_TestModelNextFrame_f }, - { "prevframe", CG_TestModelPrevFrame_f }, - { "nextskin", CG_TestModelNextSkin_f }, - { "prevskin", CG_TestModelPrevSkin_f }, - { "viewpos", CG_Viewpos_f }, - { "+scores", CG_ScoresDown_f }, - { "-scores", CG_ScoresUp_f }, - { "+zoom", CG_ZoomDown_f }, - { "-zoom", CG_ZoomUp_f }, - { "sizeup", CG_SizeUp_f }, - { "sizedown", CG_SizeDown_f }, - { "weapnext", CG_NextWeapon_f }, - { "weapprev", CG_PrevWeapon_f }, - { "weapon", CG_Weapon_f }, - { "tell_target", CG_TellTarget_f }, - { "tell_attacker", CG_TellAttacker_f }, - { "tcmd", CG_TargetCommand_f }, - { "testPS", CG_TestPS_f }, - { "destroyTestPS", CG_DestroyTestPS_f }, - { "testTS", CG_TestTS_f }, - { "destroyTestTS", CG_DestroyTestTS_f }, -}; - - -/* -================= -CG_ConsoleCommand - -The string has been tokenized and can be retrieved with -Cmd_Argc() / Cmd_Argv() -================= -*/ -qboolean CG_ConsoleCommand( void ) -{ - const char *cmd; - const char *arg1; - int i; - - cmd = CG_Argv( 0 ); - - //TA: ugly hacky special case - if( !Q_stricmp( cmd, "ui_menu" ) ) - { - arg1 = CG_Argv( 1 ); - trap_SendConsoleCommand( va( "menu %s\n", arg1 ) ); - return qtrue; - } - - for( i = 0; i < sizeof( commands ) / sizeof( commands[ 0 ] ); i++ ) - { - if( !Q_stricmp( cmd, commands[ i ].cmd ) ) - { - commands[ i ].function( ); - return qtrue; - } - } - - return qfalse; -} - - -/* -================= -CG_InitConsoleCommands - -Let the client system know about all of our commands -so it can perform tab completion -================= -*/ -void CG_InitConsoleCommands( void ) -{ - int i; - - for( i = 0 ; i < sizeof( commands ) / sizeof( commands[ 0 ] ) ; i++ ) - trap_AddCommand( commands[ i ].cmd ); - - // - // the game server will interpret these commands, which will be automatically - // forwarded to the server after they are not recognized locally - // - trap_AddCommand( "kill" ); - trap_AddCommand( "say" ); - trap_AddCommand( "say_team" ); - trap_AddCommand( "tell" ); - trap_AddCommand( "vsay" ); - trap_AddCommand( "vsay_team" ); - trap_AddCommand( "vtell" ); - trap_AddCommand( "vtaunt" ); - trap_AddCommand( "vosay" ); - trap_AddCommand( "vosay_team" ); - trap_AddCommand( "votell" ); - trap_AddCommand( "give" ); - trap_AddCommand( "god" ); - trap_AddCommand( "notarget" ); - trap_AddCommand( "noclip" ); - trap_AddCommand( "team" ); - trap_AddCommand( "follow" ); - trap_AddCommand( "levelshot" ); - trap_AddCommand( "addbot" ); - trap_AddCommand( "setviewpos" ); - trap_AddCommand( "callvote" ); - trap_AddCommand( "vote" ); - trap_AddCommand( "callteamvote" ); - trap_AddCommand( "teamvote" ); - trap_AddCommand( "stats" ); - trap_AddCommand( "teamtask" ); - trap_AddCommand( "class" ); - trap_AddCommand( "build" ); - trap_AddCommand( "buy" ); - trap_AddCommand( "sell" ); - trap_AddCommand( "reload" ); - trap_AddCommand( "itemact" ); - trap_AddCommand( "itemdeact" ); - trap_AddCommand( "itemtoggle" ); - trap_AddCommand( "destroy" ); - trap_AddCommand( "deconstruct" ); - trap_AddCommand( "menu" ); - trap_AddCommand( "ui_menu" ); - trap_AddCommand( "mapRotation" ); - trap_AddCommand( "stopMapRotation" ); - trap_AddCommand( "alienWin" ); - trap_AddCommand( "humanWin" ); -} diff --git a/mod/src/cgame/cg_draw.c b/mod/src/cgame/cg_draw.c deleted file mode 100644 index d7c07036..00000000 --- a/mod/src/cgame/cg_draw.c +++ /dev/null @@ -1,3393 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_draw.c -- draw all of the graphical elements during -// active (after loading) gameplay - -/* - * 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" -#include "../ui/ui_shared.h" - -// used for scoreboard -extern displayContextDef_t cgDC; -menuDef_t *menuScoreboard = NULL; - -int drawTeamOverlayModificationCount = -1; - -int sortedTeamPlayers[ TEAM_MAXOVERLAY ]; -int numSortedTeamPlayers; -char systemChat[ 256 ]; -char teamChat1[ 256 ]; -char teamChat2[ 256 ]; - -//TA UI -int CG_Text_Width( const char *text, float scale, int limit ) -{ - int count,len; - float out; - glyphInfo_t *glyph; - float useScale; -// FIXME: see ui_main.c, same problem -// const unsigned char *s = text; - const char *s = text; - fontInfo_t *font = &cgDC.Assets.textFont; - - if( scale <= cg_smallFont.value ) - font = &cgDC.Assets.smallFont; - else if( scale > cg_bigFont.value ) - font = &cgDC.Assets.bigFont; - - useScale = scale * font->glyphScale; - out = 0; - - if( text ) - { - len = strlen( text ); - if( limit > 0 && len > limit ) - len = limit; - - count = 0; - while( s && *s && count < len ) - { - if( Q_IsColorString( s ) ) - { - s += 2; - continue; - } - else - { - glyph = &font->glyphs[ (int)*s ]; - //TTimo: FIXME: getting nasty warnings without the cast, - //hopefully this doesn't break the VM build - out += glyph->xSkip; - s++; - count++; - } - } - } - - return out * useScale; -} - -int CG_Text_Height( const char *text, float scale, int limit ) -{ - int len, count; - float max; - glyphInfo_t *glyph; - float useScale; -// TTimo: FIXME -// const unsigned char *s = text; - const char *s = text; - fontInfo_t *font = &cgDC.Assets.textFont; - - if( scale <= cg_smallFont.value ) - font = &cgDC.Assets.smallFont; - else if( scale > cg_bigFont.value ) - font = &cgDC.Assets.bigFont; - - useScale = scale * font->glyphScale; - max = 0; - - if( text ) - { - len = strlen( text ); - if( limit > 0 && len > limit ) - len = limit; - - count = 0; - while( s && *s && count < len ) - { - if( Q_IsColorString( s ) ) - { - s += 2; - continue; - } - else - { - glyph = &font->glyphs[ (int)*s ]; - //TTimo: FIXME: getting nasty warnings without the cast, - //hopefully this doesn't break the VM build - if( max < glyph->height ) - max = glyph->height; - - s++; - count++; - } - } - } - - return max * useScale; -} - -void CG_Text_PaintChar( float x, float y, float width, float height, float scale, - float s, float t, float s2, float t2, qhandle_t hShader ) -{ - float w, h; - w = width * scale; - h = height * scale; - CG_AdjustFrom640( &x, &y, &w, &h ); - trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader ); -} - -void CG_Text_Paint( float x, float y, float scale, vec4_t color, const char *text, - float adjust, int limit, int style ) -{ - int len, count; - vec4_t newColor; - glyphInfo_t *glyph; - float useScale; - fontInfo_t *font = &cgDC.Assets.textFont; - - if( scale <= cg_smallFont.value ) - font = &cgDC.Assets.smallFont; - else if( scale > cg_bigFont.value ) - font = &cgDC.Assets.bigFont; - - useScale = scale * font->glyphScale; - if( text ) - { -// TTimo: FIXME -// const unsigned char *s = text; - const char *s = text; - - trap_R_SetColor( color ); - memcpy( &newColor[ 0 ], &color[ 0 ], sizeof( vec4_t ) ); - len = strlen( text ); - - if( limit > 0 && len > limit ) - len = limit; - - count = 0; - while( s && *s && count < len ) - { - glyph = &font->glyphs[ (int)*s ]; - //TTimo: FIXME: getting nasty warnings without the cast, - //hopefully this doesn't break the VM build - - if( Q_IsColorString( s ) ) - { - memcpy( newColor, g_color_table[ ColorIndex( *( s + 1 ) ) ], sizeof( newColor ) ); - newColor[ 3 ] = color[ 3 ]; - trap_R_SetColor( newColor ); - s += 2; - continue; - } - else - { - float yadj = useScale * glyph->top; - if( style == ITEM_TEXTSTYLE_SHADOWED || - style == ITEM_TEXTSTYLE_SHADOWEDMORE ) - { - int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2; - colorBlack[ 3 ] = newColor[ 3 ]; - trap_R_SetColor( colorBlack ); - CG_Text_PaintChar( x + ofs, y - yadj + ofs, - glyph->imageWidth, - glyph->imageHeight, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - - colorBlack[ 3 ] = 1.0; - trap_R_SetColor( newColor ); - } - else if( style == ITEM_TEXTSTYLE_NEON ) - { - vec4_t glow, outer, inner, white; - - glow[ 0 ] = newColor[ 0 ] * 0.5; - glow[ 1 ] = newColor[ 1 ] * 0.5; - glow[ 2 ] = newColor[ 2 ] * 0.5; - glow[ 3 ] = newColor[ 3 ] * 0.2; - - outer[ 0 ] = newColor[ 0 ]; - outer[ 1 ] = newColor[ 1 ]; - outer[ 2 ] = newColor[ 2 ]; - outer[ 3 ] = newColor[ 3 ]; - - inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5; - inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5; - inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5; - inner[ 3 ] = newColor[ 3 ]; - - white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f; - - trap_R_SetColor( glow ); - CG_Text_PaintChar( x - 3, y - yadj - 3, - glyph->imageWidth + 6, - glyph->imageHeight + 6, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - - trap_R_SetColor( outer ); - CG_Text_PaintChar( x - 1, y - yadj - 1, - glyph->imageWidth + 2, - glyph->imageHeight + 2, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - - trap_R_SetColor( inner ); - CG_Text_PaintChar( x - 0.5, y - yadj - 0.5, - glyph->imageWidth + 1, - glyph->imageHeight + 1, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - - trap_R_SetColor( white ); - } - - - CG_Text_PaintChar( x, y - yadj, - glyph->imageWidth, - glyph->imageHeight, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - - x += ( glyph->xSkip * useScale ) + adjust; - s++; - count++; - } - } - - trap_R_SetColor( NULL ); - } -} - -/* -============== -CG_DrawFieldPadded - -Draws large numbers for status bar and powerups -============== -*/ -static void CG_DrawFieldPadded( int x, int y, int width, int cw, int ch, int value ) -{ - char num[ 16 ], *ptr; - int l, orgL; - int frame; - int charWidth, charHeight; - - if( !( charWidth = cw ) ) - charWidth = CHAR_WIDTH; - - if( !( charHeight = ch ) ) - charWidth = CHAR_HEIGHT; - - if( width < 1 ) - return; - - // draw number string - if( width > 4 ) - width = 4; - - switch( width ) - { - case 1: - value = value > 9 ? 9 : value; - value = value < 0 ? 0 : value; - break; - case 2: - value = value > 99 ? 99 : value; - value = value < -9 ? -9 : value; - break; - case 3: - value = value > 999 ? 999 : value; - value = value < -99 ? -99 : value; - break; - case 4: - value = value > 9999 ? 9999 : value; - value = value < -999 ? -999 : value; - break; - } - - Com_sprintf( num, sizeof( num ), "%d", value ); - l = strlen( num ); - - if( l > width ) - l = width; - - orgL = l; - - x += 2; - - ptr = num; - while( *ptr && l ) - { - if( width > orgL ) - { - CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[ 0 ] ); - width--; - x += charWidth; - continue; - } - - if( *ptr == '-' ) - frame = STAT_MINUS; - else - frame = *ptr - '0'; - - CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[ frame ] ); - x += charWidth; - ptr++; - l--; - } -} - -/* -============== -CG_DrawField - -Draws large numbers for status bar and powerups -============== -*/ -static void CG_DrawField( int x, int y, int width, int cw, int ch, int value ) -{ - char num[ 16 ], *ptr; - int l; - int frame; - int charWidth, charHeight; - - if( !( charWidth = cw ) ) - charWidth = CHAR_WIDTH; - - if( !( charHeight = ch ) ) - charWidth = CHAR_HEIGHT; - - if( width < 1 ) - return; - - // draw number string - if( width > 4 ) - width = 4; - - switch( width ) - { - case 1: - value = value > 9 ? 9 : value; - value = value < 0 ? 0 : value; - break; - case 2: - value = value > 99 ? 99 : value; - value = value < -9 ? -9 : value; - break; - case 3: - value = value > 999 ? 999 : value; - value = value < -99 ? -99 : value; - break; - case 4: - value = value > 9999 ? 9999 : value; - value = value < -999 ? -999 : value; - break; - } - - Com_sprintf( num, sizeof( num ), "%d", value ); - l = strlen( num ); - - if( l > width ) - l = width; - - x += 2 + charWidth * ( width - l ); - - ptr = num; - while( *ptr && l ) - { - if( *ptr == '-' ) - frame = STAT_MINUS; - else - frame = *ptr -'0'; - - CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[ frame ] ); - x += charWidth; - ptr++; - l--; - } -} - -static void CG_DrawProgressBar( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special, float progress ) -{ - float rimWidth = rect->h / 20.0f; - float doneWidth, leftWidth; - float tx, ty, tw, th; - char textBuffer[ 8 ]; - - if( rimWidth < 0.6f ) - rimWidth = 0.6f; - - if( special >= 0.0f ) - rimWidth = special; - - if( progress < 0.0f ) - progress = 0.0f; - else if( progress > 1.0f ) - progress = 1.0f; - - doneWidth = ( rect->w - 2 * rimWidth ) * progress; - leftWidth = ( rect->w - 2 * rimWidth ) - doneWidth; - - trap_R_SetColor( color ); - - //draw rim and bar - if( align == ITEM_ALIGN_RIGHT ) - { - CG_DrawPic( rect->x, rect->y, rimWidth, rect->h, cgs.media.whiteShader ); - CG_DrawPic( rect->x + rimWidth, rect->y, - leftWidth, rimWidth, cgs.media.whiteShader ); - CG_DrawPic( rect->x + rimWidth, rect->y + rect->h - rimWidth, - leftWidth, rimWidth, cgs.media.whiteShader ); - CG_DrawPic( rect->x + rimWidth + leftWidth, rect->y, - rimWidth + doneWidth, rect->h, cgs.media.whiteShader ); - } - else - { - CG_DrawPic( rect->x, rect->y, rimWidth + doneWidth, rect->h, cgs.media.whiteShader ); - CG_DrawPic( rimWidth + rect->x + doneWidth, rect->y, - leftWidth, rimWidth, cgs.media.whiteShader ); - CG_DrawPic( rimWidth + rect->x + doneWidth, rect->y + rect->h - rimWidth, - leftWidth, rimWidth, cgs.media.whiteShader ); - CG_DrawPic( rect->x + rect->w - rimWidth, rect->y, rimWidth, rect->h, cgs.media.whiteShader ); - } - - trap_R_SetColor( NULL ); - - //draw text - if( scale > 0.0 ) - { - Com_sprintf( textBuffer, sizeof( textBuffer ), "%d%%", (int)( progress * 100 ) ); - tw = CG_Text_Width( textBuffer, scale, 0 ); - th = scale * 40.0f; - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x + ( rect->w / 10.0f ); - ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - ( rect->w / 10.0f ) - tw; - ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f ); - ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); - break; - - default: - tx = ty = 0.0f; - } - - CG_Text_Paint( tx, ty, scale, color, textBuffer, 0, 0, textStyle ); - } -} - -//=============== TA: was cg_newdraw.c - -void CG_InitTeamChat( void ) -{ - memset( teamChat1, 0, sizeof( teamChat1 ) ); - memset( teamChat2, 0, sizeof( teamChat2 ) ); - memset( systemChat, 0, sizeof( systemChat ) ); -} - -void CG_SetPrintString( int type, const char *p ) -{ - if( type == SYSTEM_PRINT ) - { - strcpy( systemChat, p ); - } - else - { - strcpy( teamChat2, teamChat1 ); - strcpy( teamChat1, p ); - } -} - -/* -=============== -CG_AtHighestClass - -Is the local client at the highest class possible? -=============== -*/ -static qboolean CG_AtHighestClass( void ) -{ - int i; - qboolean superiorClasses = qfalse; - - for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) - { - if( BG_ClassCanEvolveFromTo( - cg.predictedPlayerState.stats[ STAT_PCLASS ], i, - ALIEN_MAX_KILLS, 0 ) >= 0 && - BG_FindStagesForClass( i, cgs.alienStage ) - /*FIXME && G_ClassIsAllowed( i )*/ ) - { - superiorClasses = qtrue; - break; - } - } - - return !superiorClasses; -} - -#define NO_CREDITS_TIME 2000 - -static void CG_DrawPlayerCreditsValue( rectDef_t *rect, vec4_t color, qboolean padding ) -{ - int value; - playerState_t *ps; - centity_t *cent; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - //if the build timer pie is showing don't show this - if( ( cent->currentState.weapon == WP_ABUILD || - cent->currentState.weapon == WP_ABUILD2 ) && ps->stats[ STAT_MISC ] ) - return; - - value = ps->persistant[ PERS_CREDIT ]; - if( value > -1 ) - { - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS && - !CG_AtHighestClass( ) ) - { - if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME ) - { - if( ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) % 2 ) - color[ 3 ] = 0.0f; - } - } - - trap_R_SetColor( color ); - - if( padding ) - CG_DrawFieldPadded( rect->x, rect->y, 4, rect->w / 4, rect->h, value ); - else - CG_DrawField( rect->x, rect->y, 1, rect->w, rect->h, value ); - - trap_R_SetColor( NULL ); - } -} - -static void CG_DrawPlayerBankValue( rectDef_t *rect, vec4_t color, qboolean padding ) -{ - int value; - playerState_t *ps; - - ps = &cg.snap->ps; - - value = ps->persistant[ PERS_BANK ]; - if( value > -1 ) - { - trap_R_SetColor( color ); - - if( padding ) - CG_DrawFieldPadded( rect->x, rect->y, 4, rect->w / 4, rect->h, value ); - else - CG_DrawField( rect->x, rect->y, 1, rect->w, rect->h, value ); - - trap_R_SetColor( NULL ); - } -} - -#define HH_MIN_ALPHA 0.2f -#define HH_MAX_ALPHA 0.8f -#define HH_ALPHA_DIFF (HH_MAX_ALPHA-HH_MIN_ALPHA) - -#define AH_MIN_ALPHA 0.2f -#define AH_MAX_ALPHA 0.8f -#define AH_ALPHA_DIFF (AH_MAX_ALPHA-AH_MIN_ALPHA) - -/* -============== -CG_DrawPlayerStamina1 -============== -*/ -static void CG_DrawPlayerStamina1( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - float stamina = ps->stats[ STAT_STAMINA ]; - float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f; - float progress; - - stamina -= ( 2 * (int)maxStaminaBy3 ); - progress = stamina / maxStaminaBy3; - - if( progress > 1.0f ) - progress = 1.0f; - else if( progress < 0.0f ) - progress = 0.0f; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerStamina2 -============== -*/ -static void CG_DrawPlayerStamina2( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - float stamina = ps->stats[ STAT_STAMINA ]; - float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f; - float progress; - - stamina -= (int)maxStaminaBy3; - progress = stamina / maxStaminaBy3; - - if( progress > 1.0f ) - progress = 1.0f; - else if( progress < 0.0f ) - progress = 0.0f; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerStamina3 -============== -*/ -static void CG_DrawPlayerStamina3( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - float stamina = ps->stats[ STAT_STAMINA ]; - float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f; - float progress; - - progress = stamina / maxStaminaBy3; - - if( progress > 1.0f ) - progress = 1.0f; - else if( progress < 0.0f ) - progress = 0.0f; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerStamina4 -============== -*/ -static void CG_DrawPlayerStamina4( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - float stamina = ps->stats[ STAT_STAMINA ]; - float progress; - - stamina += (float)MAX_STAMINA; - progress = stamina / (float)MAX_STAMINA; - - if( progress > 1.0f ) - progress = 1.0f; - else if( progress < 0.0f ) - progress = 0.0f; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerStaminaBolt -============== -*/ -static void CG_DrawPlayerStaminaBolt( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - float stamina = ps->stats[ STAT_STAMINA ]; - - if( stamina < 0 ) - color[ 3 ] = HH_MIN_ALPHA; - else - color[ 3 ] = HH_MAX_ALPHA; - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerClipsRing -============== -*/ -static void CG_DrawPlayerClipsRing( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - centity_t *cent; - float buildTime = ps->stats[ STAT_MISC ]; - float progress; - float maxDelay; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - - switch( cent->currentState.weapon ) - { - case WP_ABUILD: - case WP_ABUILD2: - case WP_HBUILD: - case WP_HBUILD2: - maxDelay = (float)BG_FindBuildDelayForWeapon( cent->currentState.weapon ); - - if( buildTime > maxDelay ) - buildTime = maxDelay; - - progress = ( maxDelay - buildTime ) / maxDelay; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - break; - - default: - if( ps->weaponstate == WEAPON_RELOADING ) - { - maxDelay = (float)BG_FindReloadTimeForWeapon( cent->currentState.weapon ); - progress = ( maxDelay - (float)ps->weaponTime ) / maxDelay; - - color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF ); - } - break; - } - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerBuildTimerRing -============== -*/ -static void CG_DrawPlayerBuildTimerRing( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - centity_t *cent; - float buildTime = ps->stats[ STAT_MISC ]; - float progress; - float maxDelay; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - - maxDelay = (float)BG_FindBuildDelayForWeapon( cent->currentState.weapon ); - - if( buildTime > maxDelay ) - buildTime = maxDelay; - - progress = ( maxDelay - buildTime ) / maxDelay; - - color[ 3 ] = AH_MIN_ALPHA + ( progress * AH_ALPHA_DIFF ); - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerBoosted -============== -*/ -static void CG_DrawPlayerBoosted( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - qboolean boosted = ps->stats[ STAT_STATE ] & SS_BOOSTED; - - if( boosted ) - color[ 3 ] = AH_MAX_ALPHA; - else - color[ 3 ] = AH_MIN_ALPHA; - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerBoosterBolt -============== -*/ -static void CG_DrawPlayerBoosterBolt( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - qboolean boosted = ps->stats[ STAT_STATE ] & SS_BOOSTED; - vec4_t localColor; - - Vector4Copy( color, localColor ); - - if( boosted ) - { - if( ps->stats[ STAT_BOOSTTIME ] > BOOST_TIME - 3000 ) - { - qboolean flash = ( ps->stats[ STAT_BOOSTTIME ] / 500 ) % 2; - - if( flash ) - localColor[ 3 ] = 1.0f; - } - } - - trap_R_SetColor( localColor ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerPoisonBarbs -============== -*/ -static void CG_DrawPlayerPoisonBarbs( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - int x = rect->x; - int y = rect->y; - int width = rect->w; - int height = rect->h; - qboolean vertical; - int iconsize, numBarbs, i; - - BG_UnpackAmmoArray( ps->weapon, ps->ammo, ps->powerups, &numBarbs, NULL ); - - if( height > width ) - { - vertical = qtrue; - iconsize = width; - } - else if( height <= width ) - { - vertical = qfalse; - iconsize = height; - } - - if( color[ 3 ] != 0.0 ) - trap_R_SetColor( color ); - - for( i = 0; i < numBarbs; i ++ ) - { - if( vertical ) - y += iconsize; - else - x += iconsize; - - CG_DrawPic( x, y, iconsize, iconsize, shader ); - } - - trap_R_SetColor( NULL ); -} - -/* -============== -CG_DrawPlayerWallclimbing -============== -*/ -static void CG_DrawPlayerWallclimbing( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - qboolean ww = ps->stats[ STAT_STATE ] & SS_WALLCLIMBING; - - if( ww ) - color[ 3 ] = AH_MAX_ALPHA; - else - color[ 3 ] = AH_MIN_ALPHA; - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -static void CG_DrawPlayerStamina( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - playerState_t *ps = &cg.snap->ps; - int stamina = ps->stats[ STAT_STAMINA ]; - float progress = ( (float)stamina + (float)MAX_STAMINA ) / ( (float)MAX_STAMINA * 2.0f ); - - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, progress ); -} - -static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) -{ - int value; - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - if( cent->currentState.weapon ) - { - switch( cent->currentState.weapon ) - { - case WP_ABUILD: - case WP_ABUILD2: - //percentage of BP remaining - value = cgs.alienBuildPoints; - break; - - case WP_HBUILD: - case WP_HBUILD2: - //percentage of BP remaining - value = cgs.humanBuildPoints; - break; - - default: - BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, &value, NULL ); - break; - } - - if( value > 999 ) - value = 999; - - if( value > -1 ) - { - trap_R_SetColor( color ); - CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value ); - trap_R_SetColor( NULL ); - } - } -} - - -/* -============== -CG_DrawAlienSense -============== -*/ -static void CG_DrawAlienSense( rectDef_t *rect ) -{ - if( BG_ClassHasAbility( cg.snap->ps.stats[ STAT_PCLASS ], SCA_ALIENSENSE ) ) - CG_AlienSense( rect ); -} - - -/* -============== -CG_DrawHumanScanner -============== -*/ -static void CG_DrawHumanScanner( rectDef_t *rect, qhandle_t shader, vec4_t color ) -{ - if( BG_InventoryContainsUpgrade( UP_HELMET, cg.snap->ps.stats ) ) - CG_Scanner( rect, shader, color ); -} - - -/* -============== -CG_DrawUsableBuildable -============== -*/ -static void CG_DrawUsableBuildable( rectDef_t *rect, qhandle_t shader, vec4_t color ) -{ - vec3_t view, point; - trace_t trace; - entityState_t *es; - - AngleVectors( cg.refdefViewAngles, view, NULL, NULL ); - VectorMA( cg.refdef.vieworg, 64, view, point ); - CG_Trace( &trace, cg.refdef.vieworg, NULL, NULL, - point, cg.predictedPlayerState.clientNum, MASK_SHOT ); - - es = &cg_entities[ trace.entityNum ].currentState; - - if( es->eType == ET_BUILDABLE && BG_FindUsableForBuildable( es->modelindex ) && - cg.predictedPlayerState.stats[ STAT_PTEAM ] == BG_FindTeamForBuildable( es->modelindex ) ) - { - //hack to prevent showing the usable buildable when you aren't carrying an energy weapon - if( ( es->modelindex == BA_H_REACTOR || es->modelindex == BA_H_REPEATER ) && - ( !BG_FindUsesEnergyForWeapon( cg.snap->ps.weapon ) || - BG_FindInfinteAmmoForWeapon( cg.snap->ps.weapon ) ) ) - return; - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); - } -} - - -#define BUILD_DELAY_TIME 2000 - -static void CG_DrawPlayerBuildTimer( rectDef_t *rect, vec4_t color ) -{ - float progress; - int index; - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - if( cent->currentState.weapon ) - { - switch( cent->currentState.weapon ) - { - case WP_ABUILD: - progress = (float)ps->stats[ STAT_MISC ] / (float)ABUILDER_BASE_DELAY; - break; - - case WP_ABUILD2: - progress = (float)ps->stats[ STAT_MISC ] / (float)ABUILDER_ADV_DELAY; - break; - - case WP_HBUILD: - progress = (float)ps->stats[ STAT_MISC ] / (float)HBUILD_DELAY; - break; - - case WP_HBUILD2: - progress = (float)ps->stats[ STAT_MISC ] / (float)HBUILD2_DELAY; - break; - - default: - return; - break; - } - - if( !ps->stats[ STAT_MISC ] ) - return; - - index = (int)( progress * 8.0f ); - - if( index > 7 ) - index = 7; - else if( index < 0 ) - index = 0; - - if( cg.time - cg.lastBuildAttempt <= BUILD_DELAY_TIME ) - { - if( ( ( cg.time - cg.lastBuildAttempt ) / 300 ) % 2 ) - { - color[ 0 ] = 1.0f; - color[ 1 ] = color[ 2 ] = 0.0f; - color[ 3 ] = 1.0f; - } - } - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, - cgs.media.buildWeaponTimerPie[ index ] ); - trap_R_SetColor( NULL ); - } -} - -static void CG_DrawPlayerClipsValue( rectDef_t *rect, vec4_t color ) -{ - int value; - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - if( cent->currentState.weapon ) - { - switch( cent->currentState.weapon ) - { - case WP_ABUILD: - case WP_ABUILD2: - case WP_HBUILD: - case WP_HBUILD2: - break; - - default: - BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, NULL, &value ); - - if( value > -1 ) - { - trap_R_SetColor( color ); - CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value ); - trap_R_SetColor( NULL ); - } - break; - } - } -} - -static void CG_DrawPlayerHealthValue( rectDef_t *rect, vec4_t color ) -{ - playerState_t *ps; - int value; - - ps = &cg.snap->ps; - - value = ps->stats[ STAT_HEALTH ]; - - trap_R_SetColor( color ); - CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value ); - trap_R_SetColor( NULL ); -} - -static void CG_DrawPlayerHealthBar( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - playerState_t *ps; - float total; - - ps = &cg.snap->ps; - - total = ( (float)ps->stats[ STAT_HEALTH ] / (float)ps->stats[ STAT_MAX_HEALTH ] ); - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, total ); -} - -/* -============== -CG_DrawPlayerHealthCross -============== -*/ -static void CG_DrawPlayerHealthCross( rectDef_t *rect, vec4_t color, qhandle_t shader ) -{ - playerState_t *ps = &cg.snap->ps; - int health = ps->stats[ STAT_HEALTH ]; - - if( health < 10 ) - { - color[ 0 ] = 1.0f; - color[ 1 ] = color[ 2 ] = 0.0f; - } - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); -} - -static void CG_DrawProgressLabel( rectDef_t *rect, float text_x, float text_y, vec4_t color, - float scale, int align, const char *s, float fraction ) -{ - vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f }; - float tx, tw = CG_Text_Width( s, scale, 0 ); - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = 0.0f; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->w - tw; - break; - - case ITEM_ALIGN_CENTER: - tx = ( rect->w / 2.0f ) - ( tw / 2.0f ); - break; - - default: - tx = 0.0f; - } - - if( fraction < 1.0f ) - CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, white, - s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); - else - CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, color, - s, 0, 0, ITEM_TEXTSTYLE_NEON ); -} - -static void CG_DrawMediaProgress( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.mediaFraction ); -} - -static void CG_DrawMediaProgressLabel( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align ) -{ - CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Map and Textures", cg.mediaFraction ); -} - -static void CG_DrawBuildablesProgress( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.buildablesFraction ); -} - -static void CG_DrawBuildablesProgressLabel( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align ) -{ - CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Buildable Models", cg.buildablesFraction ); -} - -static void CG_DrawCharModelProgress( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.charModelFraction ); -} - -static void CG_DrawCharModelProgressLabel( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align ) -{ - CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Character Models", cg.charModelFraction ); -} - -static void CG_DrawOverallProgress( rectDef_t *rect, vec4_t color, float scale, - int align, int textStyle, int special ) -{ - float total; - - total = ( cg.charModelFraction + cg.buildablesFraction + cg.mediaFraction ) / 3.0f; - CG_DrawProgressBar( rect, color, scale, align, textStyle, special, total ); -} - -static void CG_DrawLevelShot( rectDef_t *rect ) -{ - const char *s; - const char *info; - qhandle_t levelshot; - qhandle_t detail; - - info = CG_ConfigString( CS_SERVERINFO ); - s = Info_ValueForKey( info, "mapname" ); - levelshot = trap_R_RegisterShaderNoMip( va( "levelshots/%s.tga", s ) ); - - if( !levelshot ) - levelshot = trap_R_RegisterShaderNoMip( "gfx/2d/load_screen" ); - - trap_R_SetColor( NULL ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, levelshot ); - - // blend a detail texture over it - detail = trap_R_RegisterShader( "levelShotDetail" ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, detail ); -} - -static void CG_DrawLoadingString( rectDef_t *rect, float text_x, float text_y, vec4_t color, - float scale, int align, int textStyle, const char *s ) -{ - float tw, th, tx; - int pos, i; - char buffer[ 1024 ]; - char *end; - - if( !s[ 0 ] ) - return; - - strcpy( buffer, s ); - tw = CG_Text_Width( s, scale, 0 ); - th = scale * 40.0f; - - pos = i = 0; - - while( pos < strlen( s ) ) - { - strcpy( buffer, &s[ pos ] ); - tw = CG_Text_Width( buffer, scale, 0 ); - - while( tw > rect->w ) - { - end = strrchr( buffer, ' ' ); - - if( end == NULL ) - break; - - *end = '\0'; - tw = CG_Text_Width( buffer, scale, 0 ); - } - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - tw; - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f ); - break; - - default: - tx = 0.0f; - } - - CG_Text_Paint( tx + text_x, rect->y + text_y + i * ( th + 3 ), scale, color, - buffer, 0, 0, textStyle ); - - pos += strlen( buffer ) + 1; - i++; - } -} - -static void CG_DrawLevelName( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align, int textStyle ) -{ - const char *s; - - s = CG_ConfigString( CS_MESSAGE ); - - CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, s ); -} - -static void CG_DrawMOTD( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align, int textStyle ) -{ - const char *s; - - s = CG_ConfigString( CS_MOTD ); - - CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, s ); -} - -static void CG_DrawHostname( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align, int textStyle ) -{ - char buffer[ 1024 ]; - const char *info; - - info = CG_ConfigString( CS_SERVERINFO ); - - Q_strncpyz( buffer, Info_ValueForKey( info, "sv_hostname" ), 1024 ); - Q_CleanStr( buffer ); - - CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, buffer ); -} - -/* -====================== -CG_UpdateMediaFraction - -====================== -*/ -void CG_UpdateMediaFraction( float newFract ) -{ - cg.mediaFraction = newFract; - - trap_UpdateScreen( ); -} - -/* -==================== -CG_DrawLoadingScreen - -Draw all the status / pacifier stuff during level loading -==================== -*/ -void CG_DrawLoadingScreen( void ) -{ - Menu_Paint( Menus_FindByName( "Loading" ), qtrue ); -} - -float CG_GetValue( int ownerDraw ) -{ - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - switch( ownerDraw ) - { - case CG_PLAYER_AMMO_VALUE: - if( cent->currentState.weapon ) - { - int value; - - BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, - &value, NULL ); - - return value; - } - break; - case CG_PLAYER_CLIPS_VALUE: - if( cent->currentState.weapon ) - { - int value; - - BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, - NULL, &value ); - - return value; - } - break; - case CG_PLAYER_HEALTH: - return ps->stats[ STAT_HEALTH ]; - break; - default: - break; - } - - return -1; -} - -static void CG_DrawAreaSystemChat( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader ) -{ - CG_Text_Paint( rect->x, rect->y + rect->h, scale, color, systemChat, 0, 0, 0 ); -} - -static void CG_DrawAreaTeamChat( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader ) -{ - CG_Text_Paint( rect->x, rect->y + rect->h, scale, color,teamChat1, 0, 0, 0 ); -} - -static void CG_DrawAreaChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) -{ - CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, teamChat2, 0, 0, 0); -} - -const char *CG_GetKillerText( ) -{ - const char *s = ""; - if( cg.killerName[ 0 ] ) - s = va( "Fragged by %s", cg.killerName ); - - return s; -} - - -static void CG_DrawKiller( rectDef_t *rect, float scale, vec4_t color, - qhandle_t shader, int textStyle ) -{ - // fragged by ... line - if( cg.killerName[ 0 ] ) - { - int x = rect->x + rect->w / 2; - CG_Text_Paint( x - CG_Text_Width( CG_GetKillerText( ), scale, 0 ) / 2, - rect->y + rect->h, scale, color, CG_GetKillerText( ), 0, 0, textStyle ); - } -} - - -static void CG_Text_Paint_Limit( float *maxX, float x, float y, float scale, - vec4_t color, const char* text, float adjust, int limit ) -{ - int len, count; - vec4_t newColor; - glyphInfo_t *glyph; - - if( text ) - { -// TTimo: FIXME -// const unsigned char *s = text; // bk001206 - unsigned - const char *s = text; - float max = *maxX; - float useScale; - fontInfo_t *font = &cgDC.Assets.textFont; - - if( scale <= cg_smallFont.value ) - font = &cgDC.Assets.smallFont; - else if( scale > cg_bigFont.value ) - font = &cgDC.Assets.bigFont; - - useScale = scale * font->glyphScale; - trap_R_SetColor( color ); - len = strlen( text ); - - if( limit > 0 && len > limit ) - len = limit; - - count = 0; - - while( s && *s && count < len ) - { - glyph = &font->glyphs[ (int)*s ]; - //TTimo: FIXME: getting nasty warnings without the cast, - //hopefully this doesn't break the VM build - - if( Q_IsColorString( s ) ) - { - memcpy( newColor, g_color_table[ ColorIndex( *(s+1) ) ], sizeof( newColor ) ); - newColor[ 3 ] = color[ 3 ]; - trap_R_SetColor( newColor ); - s += 2; - continue; - } - else - { - float yadj = useScale * glyph->top; - - if( CG_Text_Width( s, useScale, 1 ) + x > max ) - { - *maxX = 0; - break; - } - - CG_Text_PaintChar( x, y - yadj, - glyph->imageWidth, - glyph->imageHeight, - useScale, - glyph->s, - glyph->t, - glyph->s2, - glyph->t2, - glyph->glyph ); - x += ( glyph->xSkip * useScale ) + adjust; - *maxX = x; - count++; - s++; - } - } - - trap_R_SetColor( NULL ); - } -} - -static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader ) -{ - if( cg.spectatorLen ) - { - float maxX; - - if( cg.spectatorWidth == -1 ) - { - cg.spectatorWidth = 0; - cg.spectatorPaintX = rect->x + 1; - cg.spectatorPaintX2 = -1; - } - - if( cg.spectatorOffset > cg.spectatorLen ) - { - cg.spectatorOffset = 0; - cg.spectatorPaintX = rect->x + 1; - cg.spectatorPaintX2 = -1; - } - - if( cg.time > cg.spectatorTime ) - { - cg.spectatorTime = cg.time + 10; - - if( cg.spectatorPaintX <= rect->x + 2 ) - { - if( cg.spectatorOffset < cg.spectatorLen ) - { - //TA: skip colour directives - if( Q_IsColorString( &cg.spectatorList[ cg.spectatorOffset ] ) ) - cg.spectatorOffset += 2; - else - { - cg.spectatorPaintX += CG_Text_Width( &cg.spectatorList[ cg.spectatorOffset ], scale, 1 ) - 1; - cg.spectatorOffset++; - } - } - else - { - cg.spectatorOffset = 0; - - if( cg.spectatorPaintX2 >= 0 ) - cg.spectatorPaintX = cg.spectatorPaintX2; - else - cg.spectatorPaintX = rect->x + rect->w - 2; - - cg.spectatorPaintX2 = -1; - } - } - else - { - cg.spectatorPaintX--; - - if( cg.spectatorPaintX2 >= 0 ) - cg.spectatorPaintX2--; - } - } - - maxX = rect->x + rect->w - 2; - - CG_Text_Paint_Limit( &maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, - &cg.spectatorList[ cg.spectatorOffset ], 0, 0 ); - - if( cg.spectatorPaintX2 >= 0 ) - { - float maxX2 = rect->x + rect->w - 2; - CG_Text_Paint_Limit( &maxX2, cg.spectatorPaintX2, rect->y + rect->h - 3, scale, - color, cg.spectatorList, 0, cg.spectatorOffset ); - } - - if( cg.spectatorOffset && maxX > 0 ) - { - // if we have an offset ( we are skipping the first part of the string ) and we fit the string - if( cg.spectatorPaintX2 == -1 ) - cg.spectatorPaintX2 = rect->x + rect->w - 2; - } - else - cg.spectatorPaintX2 = -1; - } -} - -/* -================== -CG_DrawStageReport -================== -*/ -static void CG_DrawStageReport( rectDef_t *rect, float text_x, float text_y, - vec4_t color, float scale, int align, int textStyle ) -{ - char s[ MAX_TOKEN_CHARS ]; - int tx, w, kills; - - if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR && !cg.intermissionStarted ) - return; - - if( cg.intermissionStarted ) - { - Com_sprintf( s, MAX_TOKEN_CHARS, - "Stage %d" //PH34R MY MAD-LEET CODING SKILLZ - " " - "Stage %d", - cgs.alienStage + 1, cgs.humanStage + 1 ); - } - else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) - { - kills = cgs.alienNextStageThreshold - cgs.alienKills; - - if( cgs.alienNextStageThreshold < 0 ) - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d", cgs.alienStage + 1 ); - else if( kills == 1 ) - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kill for next stage", - cgs.alienStage + 1, kills ); - else - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kills for next stage", - cgs.alienStage + 1, kills ); - } - else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) - { - kills = cgs.humanNextStageThreshold - cgs.humanKills; - - if( cgs.humanNextStageThreshold < 0 ) - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d", cgs.humanStage + 1 ); - else if( kills == 1 ) - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kill for next stage", - cgs.humanStage + 1, kills ); - else - Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kills for next stage", - cgs.humanStage + 1, kills ); - } - - w = CG_Text_Width( s, scale, 0 ); - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - w; - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f ); - break; - - default: - tx = 0.0f; - } - - CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle ); -} - -/* -================== -CG_DrawFPS -================== -*/ -//TA: personally i think this should be longer - it should really be a cvar -#define FPS_FRAMES 20 -#define FPS_STRING "fps" -static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y, - float scale, vec4_t color, int align, int textStyle, - qboolean scalableText ) -{ - char *s; - int tx, w, totalWidth, strLength; - static int previousTimes[ FPS_FRAMES ]; - static int index; - int i, total; - int fps; - static int previous; - int t, frameTime; - - if( !cg_drawFPS.integer ) - return; - - // don't use serverTime, because that will be drifting to - // correct for internet lag changes, timescales, timedemos, etc - t = trap_Milliseconds( ); - frameTime = t - previous; - previous = t; - - previousTimes[ index % FPS_FRAMES ] = frameTime; - index++; - - if( index > FPS_FRAMES ) - { - // average multiple frames together to smooth changes out a bit - total = 0; - - for( i = 0 ; i < FPS_FRAMES ; i++ ) - total += previousTimes[ i ]; - - if( !total ) - total = 1; - - fps = 1000 * FPS_FRAMES / total; - - s = va( "%d", fps ); - w = CG_Text_Width( "0", scale, 0 ); - strLength = CG_DrawStrlen( s ); - totalWidth = CG_Text_Width( FPS_STRING, scale, 0 ) + w * strLength; - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - totalWidth; - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); - break; - - default: - tx = 0.0f; - } - - if( scalableText ) - { - for( i = 0; i < strLength; i++ ) - { - char c[ 2 ]; - - c[ 0 ] = s[ i ]; - c[ 1 ] = '\0'; - - CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle ); - } - } - else - { - trap_R_SetColor( color ); - CG_DrawField( rect->x, rect->y, 3, rect->w / 3, rect->h, fps ); - trap_R_SetColor( NULL ); - } - - if( scalableText ) - CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, FPS_STRING, 0, 0, textStyle ); - } -} - - -/* -================= -CG_DrawTimerMins -================= -*/ -static void CG_DrawTimerMins( rectDef_t *rect, vec4_t color ) -{ - int mins, seconds; - int msec; - - if( !cg_drawTimer.integer ) - return; - - msec = cg.time - cgs.levelStartTime; - - seconds = msec / 1000; - mins = seconds / 60; - seconds -= mins * 60; - - trap_R_SetColor( color ); - CG_DrawField( rect->x, rect->y, 3, rect->w / 3, rect->h, mins ); - trap_R_SetColor( NULL ); -} - - -/* -================= -CG_DrawTimerSecs -================= -*/ -static void CG_DrawTimerSecs( rectDef_t *rect, vec4_t color ) -{ - int mins, seconds; - int msec; - - if( !cg_drawTimer.integer ) - return; - - msec = cg.time - cgs.levelStartTime; - - seconds = msec / 1000; - mins = seconds / 60; - seconds -= mins * 60; - - trap_R_SetColor( color ); - CG_DrawFieldPadded( rect->x, rect->y, 2, rect->w / 2, rect->h, seconds ); - trap_R_SetColor( NULL ); -} - - -/* -================= -CG_DrawTimer -================= -*/ -static void CG_DrawTimer( rectDef_t *rect, float text_x, float text_y, - float scale, vec4_t color, int align, int textStyle ) -{ - char *s; - int i, tx, w, totalWidth, strLength; - int mins, seconds, tens; - int msec; - - if( !cg_drawTimer.integer ) - return; - - msec = cg.time - cgs.levelStartTime; - - seconds = msec / 1000; - mins = seconds / 60; - seconds -= mins * 60; - tens = seconds / 10; - seconds -= tens * 10; - - s = va( "%d:%d%d", mins, tens, seconds ); - w = CG_Text_Width( "0", scale, 0 ); - strLength = CG_DrawStrlen( s ); - totalWidth = w * strLength; - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - totalWidth; - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); - break; - - default: - tx = 0.0f; - } - - for( i = 0; i < strLength; i++ ) - { - char c[ 2 ]; - - c[ 0 ] = s[ i ]; - c[ 1 ] = '\0'; - - CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle ); - } -} - -/* -================== -CG_DrawSnapshot -================== -*/ -static void CG_DrawSnapshot( rectDef_t *rect, float text_x, float text_y, - float scale, vec4_t color, int align, int textStyle ) -{ - char *s; - int w, tx; - - if( !cg_drawSnapshot.integer ) - return; - - s = va( "time:%d snap:%d cmd:%d", cg.snap->serverTime, - cg.latestSnapshotNum, cgs.serverCommandSequence ); - w = CG_Text_Width( s, scale, 0 ); - - switch( align ) - { - case ITEM_ALIGN_LEFT: - tx = rect->x; - break; - - case ITEM_ALIGN_RIGHT: - tx = rect->x + rect->w - w; - break; - - case ITEM_ALIGN_CENTER: - tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f ); - break; - - default: - tx = 0.0f; - } - - CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle ); -} - -/* -=============================================================================== - -LAGOMETER - -=============================================================================== -*/ - -#define LAG_SAMPLES 128 - -typedef struct -{ - int frameSamples[ LAG_SAMPLES ]; - int frameCount; - int snapshotFlags[ LAG_SAMPLES ]; - int snapshotSamples[ LAG_SAMPLES ]; - int snapshotCount; -} lagometer_t; - -lagometer_t lagometer; - -/* -============== -CG_AddLagometerFrameInfo - -Adds the current interpolate / extrapolate bar for this frame -============== -*/ -void CG_AddLagometerFrameInfo( void ) -{ - int offset; - - offset = cg.time - cg.latestSnapshotTime; - lagometer.frameSamples[ lagometer.frameCount & ( LAG_SAMPLES - 1 ) ] = offset; - lagometer.frameCount++; -} - -/* -============== -CG_AddLagometerSnapshotInfo - -Each time a snapshot is received, log its ping time and -the number of snapshots that were dropped before it. - -Pass NULL for a dropped packet. -============== -*/ -void CG_AddLagometerSnapshotInfo( snapshot_t *snap ) -{ - // dropped packet - if( !snap ) - { - lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = -1; - lagometer.snapshotCount++; - return; - } - - // add this snapshot's info - lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->ping; - lagometer.snapshotFlags[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->snapFlags; - lagometer.snapshotCount++; -} - -/* -============== -CG_DrawDisconnect - -Should we draw something differnet for long lag vs no packets? -============== -*/ -static void CG_DrawDisconnect( void ) -{ - float x, y; - int cmdNum; - usercmd_t cmd; - const char *s; - int w; - vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f }; - - // draw the phone jack if we are completely past our buffers - cmdNum = trap_GetCurrentCmdNumber( ) - CMD_BACKUP + 1; - trap_GetUserCmd( cmdNum, &cmd ); - - // special check for map_restart - if( cmd.serverTime <= cg.snap->ps.commandTime || cmd.serverTime > cg.time ) - return; - - // also add text in center of screen - s = "Connection Interrupted"; - w = CG_Text_Width( s, 0.7f, 0 ); - CG_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - - // blink the icon - if( ( cg.time >> 9 ) & 1 ) - return; - - x = 640 - 48; - y = 480 - 48; - - CG_DrawPic( x, y, 48, 48, trap_R_RegisterShader( "gfx/2d/net.tga" ) ); -} - -#define MAX_LAGOMETER_PING 900 -#define MAX_LAGOMETER_RANGE 300 - -#define PING_FRAMES 40 - -/* -============== -CG_DrawLagometer -============== -*/ -static void CG_DrawLagometer( rectDef_t *rect, float text_x, float text_y, - float scale, vec4_t textColor ) -{ - int a, x, y, i; - float v; - float ax, ay, aw, ah, mid, range; - int color; - vec4_t adjustedColor; - float vscale; - vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f }; - - if( cg.snap->ps.pm_type == PM_INTERMISSION ) - return; - - if( !cg_lagometer.integer ) - return; - - if( cg.demoPlayback ) - return; - - Vector4Copy( textColor, adjustedColor ); - adjustedColor[ 3 ] = 0.25f; - - trap_R_SetColor( adjustedColor ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.whiteShader ); - trap_R_SetColor( NULL ); - - // - // draw the graph - // - ax = x = rect->x; - ay = y = rect->y; - aw = rect->w; - ah = rect->h; - - trap_R_SetColor( NULL ); - - CG_AdjustFrom640( &ax, &ay, &aw, &ah ); - - color = -1; - range = ah / 3; - mid = ay + range; - - vscale = range / MAX_LAGOMETER_RANGE; - - // draw the frame interpoalte / extrapolate graph - for( a = 0 ; a < aw ; a++ ) - { - i = ( lagometer.frameCount - 1 - a ) & ( LAG_SAMPLES - 1 ); - v = lagometer.frameSamples[ i ]; - v *= vscale; - - if( v > 0 ) - { - if( color != 1 ) - { - color = 1; - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); - } - - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, mid - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } - else if( v < 0 ) - { - if( color != 2 ) - { - color = 2; - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_BLUE ) ] ); - } - - v = -v; - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, mid, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } - } - - // draw the snapshot latency / drop graph - range = ah / 2; - vscale = range / MAX_LAGOMETER_PING; - - for( a = 0 ; a < aw ; a++ ) - { - i = ( lagometer.snapshotCount - 1 - a ) & ( LAG_SAMPLES - 1 ); - v = lagometer.snapshotSamples[ i ]; - - if( v > 0 ) - { - if( lagometer.snapshotFlags[ i ] & SNAPFLAG_RATE_DELAYED ) - { - if( color != 5 ) - { - color = 5; // YELLOW for rate delay - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); - } - } - else - { - if( color != 3 ) - { - color = 3; - - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_GREEN ) ] ); - } - } - - v = v * vscale; - - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, ay + ah - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } - else if( v < 0 ) - { - if( color != 4 ) - { - color = 4; // RED for dropped snapshots - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_RED ) ] ); - } - - trap_R_DrawStretchPic( ax + aw - a, ay + ah - range, 1, range, 0, 0, 0, 0, cgs.media.whiteShader ); - } - } - - trap_R_SetColor( NULL ); - - if( cg_nopredict.integer || cg_synchronousClients.integer ) - CG_Text_Paint( ax, ay, 0.5, white, "snc", 0, 0, ITEM_TEXTSTYLE_NORMAL ); - else - { - static int previousPings[ PING_FRAMES ]; - static int index; - int i, ping = 0; - char *s; - - previousPings[ index++ ] = cg.snap->ping; - index = index % PING_FRAMES; - - for( i = 0; i < PING_FRAMES; i++ ) - ping += previousPings[ i ]; - - ping /= PING_FRAMES; - - s = va( "%d", ping ); - ax = rect->x + ( rect->w / 2.0f ) - ( CG_Text_Width( s, scale, 0 ) / 2.0f ) + text_x; - ay = rect->y + ( rect->h / 2.0f ) + ( CG_Text_Height( s, scale, 0 ) / 2.0f ) + text_y; - - Vector4Copy( textColor, adjustedColor ); - adjustedColor[ 3 ] = 0.5f; - CG_Text_Paint( ax, ay, scale, adjustedColor, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); - } - - CG_DrawDisconnect( ); -} - -/* -============== -CG_DrawConsole -============== -*/ -static void CG_DrawConsole( rectDef_t *rect, float text_x, float text_y, vec4_t color, - float scale, int align, int textStyle ) -{ - float x, y, w, h; - - //for some reason if these are stored locally occasionally rendering fails - //even though they are both live until the end of the function, hence static - //possible compiler bug?? - static menuDef_t dummyParent; - static itemDef_t textItem; - - //offset the text - x = rect->x; - y = rect->y; - w = rect->w - ( 16 + ( 2 * text_x ) ); //16 to ensure text within frame - h = rect->h; - - textItem.text = cg.consoleText; - - textItem.parent = &dummyParent; - memcpy( textItem.window.foreColor, color, sizeof( vec4_t ) ); - textItem.window.flags = 0; - - switch( align ) - { - case ITEM_ALIGN_LEFT: - textItem.window.rect.x = x; - break; - - case ITEM_ALIGN_RIGHT: - textItem.window.rect.x = x + w; - break; - - case ITEM_ALIGN_CENTER: - textItem.window.rect.x = x + ( w / 2 ); - break; - - default: - textItem.window.rect.x = x; - break; - } - - textItem.window.rect.y = y; - textItem.window.rect.w = w; - textItem.window.rect.h = h; - textItem.window.borderSize = 0; - textItem.textRect.x = 0; - textItem.textRect.y = 0; - textItem.textRect.w = 0; - textItem.textRect.h = 0; - textItem.textalignment = align; - textItem.textalignx = text_x; - textItem.textaligny = text_y; - textItem.textscale = scale; - textItem.textStyle = textStyle; - - //hack to utilise existing autowrap code - Item_Text_AutoWrapped_Paint( &textItem ); -} - -/* -=================== -CG_DrawWeaponIcon -=================== -*/ -void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color ) -{ - int ammo, clips, maxAmmo; - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, &ammo, &clips ); - BG_FindAmmoForWeapon( cent->currentState.weapon, &maxAmmo, NULL ); - - // don't display if dead - if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) - return; - - if( cent->currentState.weapon == 0 ) - return; - - CG_RegisterWeapon( cent->currentState.weapon ); - - if( clips == 0 && !BG_FindInfinteAmmoForWeapon( cent->currentState.weapon ) ) - { - float ammoPercent = (float)ammo / (float)maxAmmo; - - if( ammoPercent < 0.33f ) - { - color[ 0 ] = 1.0f; - color[ 1 ] = color[ 2 ] = 0.0f; - } - } - - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS && CG_AtHighestClass( ) ) - { - if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME ) - { - if( ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) % 2 ) - color[ 3 ] = 0.0f; - } - } - - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].weaponIcon ); - trap_R_SetColor( NULL ); -} - - - -/* -================================================================================ - -CROSSHAIR - -================================================================================ -*/ - - -/* -================= -CG_DrawCrosshair -================= -*/ -static void CG_DrawCrosshair( void ) -{ - float w, h; - qhandle_t hShader; - float x, y; - weaponInfo_t *wi; - - if( !cg_drawCrosshair.integer ) - return; - - if( ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) || - ( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) || - ( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) ) - return; - - if( cg.renderingThirdPerson ) - return; - - wi = &cg_weapons[ cg.snap->ps.weapon ]; - - w = h = wi->crossHairSize; - - x = cg_crosshairX.integer; - y = cg_crosshairY.integer; - CG_AdjustFrom640( &x, &y, &w, &h ); - - hShader = wi->crossHair; - - if( hShader != 0 ) - { - trap_R_DrawStretchPic( x + cg.refdef.x + 0.5 * ( cg.refdef.width - w ), - y + cg.refdef.y + 0.5 * ( cg.refdef.height - h ), - w, h, 0, 0, 1, 1, hShader ); - } -} - - - -/* -================= -CG_ScanForCrosshairEntity -================= -*/ -static void CG_ScanForCrosshairEntity( void ) -{ - trace_t trace; - vec3_t start, end; - int content; - pTeam_t team; - - VectorCopy( cg.refdef.vieworg, start ); - VectorMA( start, 131072, cg.refdef.viewaxis[ 0 ], end ); - - CG_Trace( &trace, start, vec3_origin, vec3_origin, end, - cg.snap->ps.clientNum, CONTENTS_SOLID|CONTENTS_BODY ); - - if( trace.entityNum >= MAX_CLIENTS ) - return; - - // if the player is in fog, don't show it - content = trap_CM_PointContents( trace.endpos, 0 ); - if( content & CONTENTS_FOG ) - return; - - team = cgs.clientinfo[ trace.entityNum ].team; - - if( cg.snap->ps.persistant[ PERS_TEAM ] != TEAM_SPECTATOR ) - { - //only display team names of those on the same team as this player - if( team != cg.snap->ps.stats[ STAT_PTEAM ] ) - return; - } - - // update the fade timer - cg.crosshairClientNum = trace.entityNum; - cg.crosshairClientTime = cg.time; -} - - -/* -===================== -CG_DrawCrosshairNames -===================== -*/ -static void CG_DrawCrosshairNames( rectDef_t *rect, float scale, int textStyle ) -{ - float *color; - char *name; - float w, x; - - if( !cg_drawCrosshair.integer ) - return; - - if( !cg_drawCrosshairNames.integer ) - return; - - if( cg.renderingThirdPerson ) - return; - - // scan the known entities to see if the crosshair is sighted on one - CG_ScanForCrosshairEntity( ); - - // draw the name of the player being looked at - color = CG_FadeColor( cg.crosshairClientTime, 1000 ); - if( !color ) - { - trap_R_SetColor( NULL ); - return; - } - - name = cgs.clientinfo[ cg.crosshairClientNum ].name; - w = CG_Text_Width( name, scale, 0 ); - x = rect->x + rect->w / 2; - CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); - trap_R_SetColor( NULL ); -} - - -/* -=============== -CG_OwnerDraw - -Draw an owner drawn item -=============== -*/ -void CG_OwnerDraw( float x, float y, float w, float h, float text_x, - float text_y, int ownerDraw, int ownerDrawFlags, - int align, float special, float scale, vec4_t color, - qhandle_t shader, int textStyle ) -{ - rectDef_t rect; - - if( cg_drawStatus.integer == 0 ) - return; - - rect.x = x; - rect.y = y; - rect.w = w; - rect.h = h; - - switch( ownerDraw ) - { - case CG_PLAYER_CREDITS_VALUE: - CG_DrawPlayerCreditsValue( &rect, color, qtrue ); - break; - case CG_PLAYER_BANK_VALUE: - CG_DrawPlayerBankValue( &rect, color, qtrue ); - break; - case CG_PLAYER_CREDITS_VALUE_NOPAD: - CG_DrawPlayerCreditsValue( &rect, color, qfalse ); - break; - case CG_PLAYER_BANK_VALUE_NOPAD: - CG_DrawPlayerBankValue( &rect, color, qfalse ); - break; - case CG_PLAYER_STAMINA: - CG_DrawPlayerStamina( &rect, color, scale, align, textStyle, special ); - break; - case CG_PLAYER_STAMINA_1: - CG_DrawPlayerStamina1( &rect, color, shader ); - break; - case CG_PLAYER_STAMINA_2: - CG_DrawPlayerStamina2( &rect, color, shader ); - break; - case CG_PLAYER_STAMINA_3: - CG_DrawPlayerStamina3( &rect, color, shader ); - break; - case CG_PLAYER_STAMINA_4: - CG_DrawPlayerStamina4( &rect, color, shader ); - break; - case CG_PLAYER_STAMINA_BOLT: - CG_DrawPlayerStaminaBolt( &rect, color, shader ); - break; - case CG_PLAYER_AMMO_VALUE: - CG_DrawPlayerAmmoValue( &rect, color ); - break; - case CG_PLAYER_CLIPS_VALUE: - CG_DrawPlayerClipsValue( &rect, color ); - break; - case CG_PLAYER_BUILD_TIMER: - CG_DrawPlayerBuildTimer( &rect, color ); - break; - case CG_PLAYER_HEALTH: - CG_DrawPlayerHealthValue( &rect, color ); - break; - case CG_PLAYER_HEALTH_BAR: - CG_DrawPlayerHealthBar( &rect, color, scale, align, textStyle, special ); - break; - case CG_PLAYER_HEALTH_CROSS: - CG_DrawPlayerHealthCross( &rect, color, shader ); - break; - case CG_PLAYER_CLIPS_RING: - CG_DrawPlayerClipsRing( &rect, color, shader ); - break; - case CG_PLAYER_BUILD_TIMER_RING: - CG_DrawPlayerBuildTimerRing( &rect, color, shader ); - break; - case CG_PLAYER_WALLCLIMBING: - CG_DrawPlayerWallclimbing( &rect, color, shader ); - break; - case CG_PLAYER_BOOSTED: - CG_DrawPlayerBoosted( &rect, color, shader ); - break; - case CG_PLAYER_BOOST_BOLT: - CG_DrawPlayerBoosterBolt( &rect, color, shader ); - break; - case CG_PLAYER_POISON_BARBS: - CG_DrawPlayerPoisonBarbs( &rect, color, shader ); - break; - case CG_PLAYER_ALIEN_SENSE: - CG_DrawAlienSense( &rect ); - break; - case CG_PLAYER_HUMAN_SCANNER: - CG_DrawHumanScanner( &rect, shader, color ); - break; - case CG_PLAYER_USABLE_BUILDABLE: - CG_DrawUsableBuildable( &rect, shader, color ); - break; - case CG_AREA_SYSTEMCHAT: - CG_DrawAreaSystemChat( &rect, scale, color, shader ); - break; - case CG_AREA_TEAMCHAT: - CG_DrawAreaTeamChat( &rect, scale, color, shader ); - break; - case CG_AREA_CHAT: - CG_DrawAreaChat( &rect, scale, color, shader ); - break; - case CG_KILLER: - CG_DrawKiller( &rect, scale, color, shader, textStyle ); - break; - case CG_PLAYER_SELECT: - CG_DrawItemSelect( &rect, color ); - break; - case CG_PLAYER_WEAPONICON: - CG_DrawWeaponIcon( &rect, color ); - break; - case CG_PLAYER_SELECTTEXT: - CG_DrawItemSelectText( &rect, scale, textStyle ); - break; - case CG_SPECTATORS: - CG_DrawTeamSpectators( &rect, scale, color, shader ); - break; - case CG_PLAYER_CROSSHAIRNAMES: - CG_DrawCrosshairNames( &rect, scale, textStyle ); - break; - case CG_STAGE_REPORT_TEXT: - CG_DrawStageReport( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - - //loading screen - case CG_LOAD_LEVELSHOT: - CG_DrawLevelShot( &rect ); - break; - case CG_LOAD_MEDIA: - CG_DrawMediaProgress( &rect, color, scale, align, textStyle, special ); - break; - case CG_LOAD_MEDIA_LABEL: - CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_BUILDABLES: - CG_DrawBuildablesProgress( &rect, color, scale, align, textStyle, special ); - break; - case CG_LOAD_BUILDABLES_LABEL: - CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_CHARMODEL: - CG_DrawCharModelProgress( &rect, color, scale, align, textStyle, special ); - break; - case CG_LOAD_CHARMODEL_LABEL: - CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_OVERALL: - CG_DrawOverallProgress( &rect, color, scale, align, textStyle, special ); - break; - case CG_LOAD_LEVELNAME: - CG_DrawLevelName( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - case CG_LOAD_MOTD: - CG_DrawMOTD( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - case CG_LOAD_HOSTNAME: - CG_DrawHostname( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - - case CG_FPS: - CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qtrue ); - break; - case CG_FPS_FIXED: - CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qfalse ); - break; - case CG_TIMER: - CG_DrawTimer( &rect, text_x, text_y, scale, color, align, textStyle ); - break; - case CG_TIMER_MINS: - CG_DrawTimerMins( &rect, color ); - break; - case CG_TIMER_SECS: - CG_DrawTimerSecs( &rect, color ); - break; - case CG_SNAPSHOT: - CG_DrawSnapshot( &rect, text_x, text_y, scale, color, align, textStyle ); - break; - case CG_LAGOMETER: - CG_DrawLagometer( &rect, text_x, text_y, scale, color ); - break; - - case CG_CONSOLE: - CG_DrawConsole( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - - default: - break; - } -} - -void CG_MouseEvent( int x, int y ) -{ - int n; - - if( ( cg.predictedPlayerState.pm_type == PM_NORMAL || - cg.predictedPlayerState.pm_type == PM_SPECTATOR ) && - cg.showScores == qfalse ) - { - trap_Key_SetCatcher( 0 ); - return; - } - - cgs.cursorX += x; - if( cgs.cursorX < 0 ) - cgs.cursorX = 0; - else if( cgs.cursorX > 640 ) - cgs.cursorX = 640; - - cgs.cursorY += y; - if( cgs.cursorY < 0 ) - cgs.cursorY = 0; - else if( cgs.cursorY > 480 ) - cgs.cursorY = 480; - - n = Display_CursorType( cgs.cursorX, cgs.cursorY ); - cgs.activeCursor = 0; - if( n == CURSOR_ARROW ) - cgs.activeCursor = cgs.media.selectCursor; - else if( n == CURSOR_SIZER ) - cgs.activeCursor = cgs.media.sizeCursor; - - if( cgs.capturedItem ) - Display_MouseMove( cgs.capturedItem, x, y ); - else - Display_MouseMove( NULL, cgs.cursorX, cgs.cursorY ); -} - -/* -================== -CG_HideTeamMenus -================== - -*/ -void CG_HideTeamMenu( ) -{ - Menus_CloseByName( "teamMenu" ); - Menus_CloseByName( "getMenu" ); -} - -/* -================== -CG_ShowTeamMenus -================== - -*/ -void CG_ShowTeamMenu( ) -{ - Menus_OpenByName( "teamMenu" ); -} - -/* -================== -CG_EventHandling -================== - type 0 - no event handling - 1 - team menu - 2 - hud editor - -*/ -void CG_EventHandling( int type ) -{ - cgs.eventHandling = type; - - if( type == CGAME_EVENT_NONE ) - CG_HideTeamMenu( ); -} - - - -void CG_KeyEvent( int key, qboolean down ) -{ - if( !down ) - return; - - if( cg.predictedPlayerState.pm_type == PM_NORMAL || - ( cg.predictedPlayerState.pm_type == PM_SPECTATOR && - cg.showScores == qfalse ) ) - { - CG_EventHandling( CGAME_EVENT_NONE ); - trap_Key_SetCatcher( 0 ); - return; - } - - Display_HandleKey( key, down, cgs.cursorX, cgs.cursorY ); - - if( cgs.capturedItem ) - cgs.capturedItem = NULL; - else - { - if( key == K_MOUSE2 && down ) - cgs.capturedItem = Display_CaptureItem( cgs.cursorX, cgs.cursorY ); - } -} - -int CG_ClientNumFromName( const char *p ) -{ - int i; - - for( i = 0; i < cgs.maxclients; i++ ) - { - if( cgs.clientinfo[ i ].infoValid && - Q_stricmp( cgs.clientinfo[ i ].name, p ) == 0 ) - return i; - } - - return -1; -} - -void CG_RunMenuScript( char **args ) -{ -} - - -void CG_GetTeamColor( vec4_t *color ) -{ - (*color)[ 0 ] = (*color)[ 2 ] = 0.0f; - (*color)[ 1 ] = 0.17f; - (*color)[ 3 ] = 0.25f; -} -//END TA UI - - -/* -================ -CG_DrawLighting - -================ -*/ -static void CG_DrawLighting( void ) -{ - centity_t *cent; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - - //fade to black if stamina is low - if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) && - ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) - { - vec4_t black = { 0, 0, 0, 0 }; - black[ 3 ] = 1.0 - ( (float)( cg.snap->ps.stats[ STAT_STAMINA ] + 1000 ) / 200.0f ); - trap_R_SetColor( black ); - CG_DrawPic( 0, 0, 640, 480, cgs.media.whiteShader ); - trap_R_SetColor( NULL ); - } -} - -/* -=============================================================================== - -CENTER PRINTING - -=============================================================================== -*/ - - -/* -============== -CG_CenterPrint - -Called for important messages that should stay in the center of the screen -for a few moments -============== -*/ -void CG_CenterPrint( const char *str, int y, int charWidth ) -{ - char *s; - - Q_strncpyz( cg.centerPrint, str, sizeof( cg.centerPrint ) ); - - cg.centerPrintTime = cg.time; - cg.centerPrintY = y; - cg.centerPrintCharWidth = charWidth; - - // count the number of lines for centering - cg.centerPrintLines = 1; - s = cg.centerPrint; - while( *s ) - { - if( *s == '\n' ) - cg.centerPrintLines++; - - s++; - } -} - - -/* -=================== -CG_DrawCenterString -=================== -*/ -static void CG_DrawCenterString( void ) -{ - char *start; - int l; - int x, y, w; - int h; - float *color; - - if( !cg.centerPrintTime ) - return; - - color = CG_FadeColor( cg.centerPrintTime, 1000 * cg_centertime.value ); - if( !color ) - return; - - trap_R_SetColor( color ); - - start = cg.centerPrint; - - y = cg.centerPrintY - cg.centerPrintLines * BIGCHAR_HEIGHT / 2; - - while( 1 ) - { - char linebuffer[ 1024 ]; - - for( l = 0; l < 50; l++ ) - { - if( !start[ l ] || start[ l ] == '\n' ) - break; - - linebuffer[ l ] = start[ l ]; - } - - linebuffer[ l ] = 0; - - w = CG_Text_Width( linebuffer, 0.5, 0 ); - h = CG_Text_Height( linebuffer, 0.5, 0 ); - x = ( SCREEN_WIDTH - w ) / 2; - CG_Text_Paint( x, y + h, 0.5, color, linebuffer, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); - y += h + 6; - - while( *start && ( *start != '\n' ) ) - start++; - - if( !*start ) - break; - - start++; - } - - trap_R_SetColor( NULL ); -} - - - - - -//============================================================================== - -//FIXME: both vote notes are hardcoded, change to ownerdrawn? - -/* -================= -CG_DrawVote -================= -*/ -static void CG_DrawVote( void ) -{ - char *s; - int sec; - vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f }; - - if( !cgs.voteTime ) - return; - - // play a talk beep whenever it is modified - if( cgs.voteModified ) - { - cgs.voteModified = qfalse; - trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); - } - - sec = ( VOTE_TIME - ( cg.time - cgs.voteTime ) ) / 1000; - - if( sec < 0 ) - sec = 0; - - s = va( "VOTE(%i): \"%s\" Yes:%i No:%i", sec, cgs.voteString, cgs.voteYes, cgs.voteNo ); - CG_Text_Paint( 8, 340, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); -} - -/* -================= -CG_DrawTeamVote -================= -*/ -static void CG_DrawTeamVote( void ) -{ - char *s; - int sec, cs_offset; - vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f }; - - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS ) - cs_offset = 0; - else if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS ) - cs_offset = 1; - else - return; - - if( !cgs.teamVoteTime[ cs_offset ] ) - return; - - // play a talk beep whenever it is modified - if ( cgs.teamVoteModified[ cs_offset ] ) - { - cgs.teamVoteModified[ cs_offset ] = qfalse; - trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); - } - - sec = ( VOTE_TIME - ( cg.time - cgs.teamVoteTime[ cs_offset ] ) ) / 1000; - - if( sec < 0 ) - sec = 0; - - s = va( "TEAMVOTE(%i): \"%s\" Yes:%i No:%i", sec, cgs.teamVoteString[ cs_offset ], - cgs.teamVoteYes[cs_offset], cgs.teamVoteNo[ cs_offset ] ); - - CG_Text_Paint( 8, 360, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); -} - - -static qboolean CG_DrawScoreboard( void ) -{ - static qboolean firstTime = qtrue; - float fade, *fadeColor; - - if( menuScoreboard ) - menuScoreboard->window.flags &= ~WINDOW_FORCED; - - if( cg_paused.integer ) - { - cg.deferredPlayerLoading = 0; - firstTime = qtrue; - return qfalse; - } - - if( cg.showScores || - cg.predictedPlayerState.pm_type == PM_INTERMISSION ) - { - fade = 1.0; - fadeColor = colorWhite; - } - else - { - cg.deferredPlayerLoading = 0; - cg.killerName[ 0 ] = 0; - firstTime = qtrue; - return qfalse; - } - - - if( menuScoreboard == NULL ) - menuScoreboard = Menus_FindByName( "teamscore_menu" ); - - if( menuScoreboard ) - { - if( firstTime ) - { - CG_SetScoreSelection( menuScoreboard ); - firstTime = qfalse; - } - - Menu_Paint( menuScoreboard, qtrue ); - } - - return qtrue; -} - -/* -================= -CG_DrawIntermission -================= -*/ -static void CG_DrawIntermission( void ) -{ - if( cg_drawStatus.integer ) - Menu_Paint( Menus_FindByName( "default_hud" ), qtrue ); - - cg.scoreFadeTime = cg.time; - cg.scoreBoardShowing = CG_DrawScoreboard( ); -} - -#define FOLLOWING_STRING "following " - -/* -================= -CG_DrawFollow -================= -*/ -static qboolean CG_DrawFollow( void ) -{ - float w; - vec4_t color; - char buffer[ MAX_STRING_CHARS ]; - - if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) - return qfalse; - - color[ 0 ] = 1; - color[ 1 ] = 1; - color[ 2 ] = 1; - color[ 3 ] = 1; - - strcpy( buffer, FOLLOWING_STRING ); - strcat( buffer, cgs.clientinfo[ cg.snap->ps.clientNum ].name ); - - w = CG_Text_Width( buffer, 0.7f, 0 ); - CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - - return qtrue; -} - -/* -================= -CG_DrawQueue -================= -*/ -static qboolean CG_DrawQueue( void ) -{ - float w; - vec4_t color; - char buffer[ MAX_STRING_CHARS ]; - - if( !( cg.snap->ps.pm_flags & PMF_QUEUED ) ) - return qfalse; - - color[ 0 ] = 1; - color[ 1 ] = 1; - color[ 2 ] = 1; - color[ 3 ] = 1; - - Com_sprintf( buffer, MAX_STRING_CHARS, "You are in position %d of the spawn queue.", - cg.snap->ps.persistant[ PERS_QUEUEPOS ] + 1 ); - - w = CG_Text_Width( buffer, 0.7f, 0 ); - CG_Text_Paint( 320 - w / 2, 360, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - - if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) - { - if( cgs.numAlienSpawns == 1 ) - Com_sprintf( buffer, MAX_STRING_CHARS, "There is 1 spawn remaining." ); - else - Com_sprintf( buffer, MAX_STRING_CHARS, "There are %d spawns remaining.", - cgs.numAlienSpawns ); - } - else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) - { - if( cgs.numHumanSpawns == 1 ) - Com_sprintf( buffer, MAX_STRING_CHARS, "There is 1 spawn remaining." ); - else - Com_sprintf( buffer, MAX_STRING_CHARS, "There are %d spawns remaining.", - cgs.numHumanSpawns ); - } - - w = CG_Text_Width( buffer, 0.7f, 0 ); - CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - - return qtrue; -} - -//================================================================================== - -#define SPECTATOR_STRING "SPECTATOR" -/* -================= -CG_Draw2D -================= -*/ -static void CG_Draw2D( void ) -{ - vec4_t color; - float w; - menuDef_t *menu = NULL, *defaultMenu; - - color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 1.0f; - - // if we are taking a levelshot for the menu, don't draw anything - if( cg.levelShot ) - return; - - if( cg_draw2D.integer == 0 ) - return; - - if( cg.snap->ps.pm_type == PM_INTERMISSION ) - { - CG_DrawIntermission( ); - return; - } - - //TA: draw the lighting effects e.g. nvg - CG_DrawLighting( ); - - - defaultMenu = Menus_FindByName( "default_hud" ); - - if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) - { - w = CG_Text_Width( SPECTATOR_STRING, 0.7f, 0 ); - CG_Text_Paint( 320 - w / 2, 440, 0.7f, color, SPECTATOR_STRING, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - } - else - menu = Menus_FindByName( BG_FindHudNameForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ) ); - - if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) && - !( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) && menu && - ( cg.snap->ps.stats[ STAT_HEALTH ] > 0 ) ) - { - if( cg_drawStatus.integer ) - Menu_Paint( menu, qtrue ); - - CG_DrawCrosshair( ); - } - else if( cg_drawStatus.integer ) - Menu_Paint( defaultMenu, qtrue ); - - CG_DrawVote( ); - CG_DrawTeamVote( ); - CG_DrawFollow( ); - CG_DrawQueue( ); - - // don't draw center string if scoreboard is up - cg.scoreBoardShowing = CG_DrawScoreboard( ); - - if( !cg.scoreBoardShowing ) - CG_DrawCenterString( ); -} - -#define PAINBLEND_BORDER_W 0.15f -#define PAINBLEND_BORDER_H 0.07f - -/* -=============== -CG_PainBlend -=============== -*/ -static void CG_PainBlend( void ) -{ - vec4_t color; - int damage; - float damageAsFracOfMax; - qhandle_t shader = cgs.media.viewBloodShader; - float x, y, w, h; - - damage = cg.lastHealth - cg.snap->ps.stats[ STAT_HEALTH ]; - - if( damage < 0 ) - damage = 0; - - damageAsFracOfMax = (float)damage / cg.snap->ps.stats[ STAT_MAX_HEALTH ]; - cg.lastHealth = cg.snap->ps.stats[ STAT_HEALTH ]; - - cg.painBlendValue += damageAsFracOfMax * cg_painBlendScale.value; - - if( cg.painBlendValue > 0.0f ) - { - cg.painBlendValue -= ( cg.frametime / 1000.0f ) * - cg_painBlendDownRate.value; - } - - if( cg.painBlendValue > 1.0f ) - cg.painBlendValue = 1.0f; - else if( cg.painBlendValue <= 0.0f ) - { - cg.painBlendValue = 0.0f; - return; - } - - if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) - VectorSet( color, 0.43f, 0.8f, 0.37f ); - else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) - VectorSet( color, 0.8f, 0.0f, 0.0f ); - - if( cg.painBlendValue > cg.painBlendTarget ) - { - cg.painBlendTarget += ( cg.frametime / 1000.0f ) * - cg_painBlendUpRate.value; - } - else if( cg.painBlendValue < cg.painBlendTarget ) - cg.painBlendTarget = cg.painBlendValue; - - if( cg.painBlendTarget > cg_painBlendMax.value ) - cg.painBlendTarget = cg_painBlendMax.value; - - color[ 3 ] = cg.painBlendTarget; - - trap_R_SetColor( color ); - - //left - x = 0.0f; y = 0.0f; - w = PAINBLEND_BORDER_W * 640.0f; h = 480.0f; - CG_AdjustFrom640( &x, &y, &w, &h ); - trap_R_DrawStretchPic( x, y, w, h, - cg_painBlendZoom.value, cg_painBlendZoom.value, - cg_painBlendZoom.value + PAINBLEND_BORDER_W, 1.0f - cg_painBlendZoom.value, - shader ); - - //right - x = 640.0f - ( PAINBLEND_BORDER_W * 640.0f ); y = 0.0f; - w = PAINBLEND_BORDER_W * 640.0f; h = 480.0f; - CG_AdjustFrom640( &x, &y, &w, &h ); - trap_R_DrawStretchPic( x, y, w, h, - 1.0f - cg_painBlendZoom.value - PAINBLEND_BORDER_W, cg_painBlendZoom.value, - 1.0f - cg_painBlendZoom.value, 1.0f - cg_painBlendZoom.value, - shader ); - - //top - x = PAINBLEND_BORDER_W * 640.0f; y = 0.0f; - w = 640.0f - ( 2 * PAINBLEND_BORDER_W * 640.0f ); h = PAINBLEND_BORDER_H * 480.0f; - CG_AdjustFrom640( &x, &y, &w, &h ); - trap_R_DrawStretchPic( x, y, w, h, - cg_painBlendZoom.value + PAINBLEND_BORDER_W, cg_painBlendZoom.value, - 1.0f - cg_painBlendZoom.value - PAINBLEND_BORDER_W, cg_painBlendZoom.value + PAINBLEND_BORDER_H, - shader ); - - //bottom - x = PAINBLEND_BORDER_W * 640.0f; y = 480.0f - ( PAINBLEND_BORDER_H * 480.0f ); - w = 640.0f - ( 2 * PAINBLEND_BORDER_W * 640.0f ); h = PAINBLEND_BORDER_H * 480.0f; - CG_AdjustFrom640( &x, &y, &w, &h ); - trap_R_DrawStretchPic( x, y, w, h, - cg_painBlendZoom.value + PAINBLEND_BORDER_W, 1.0f - cg_painBlendZoom.value - PAINBLEND_BORDER_H, - 1.0f - cg_painBlendZoom.value - PAINBLEND_BORDER_W, 1.0f - cg_painBlendZoom.value, - shader ); - - trap_R_SetColor( NULL ); -} - -/* -===================== -CG_ResetPainBlend -===================== -*/ -void CG_ResetPainBlend( void ) -{ - cg.painBlendValue = 0.0f; - cg.painBlendTarget = 0.0f; - cg.lastHealth = cg.snap->ps.stats[ STAT_MAX_HEALTH ]; -} - -/* -===================== -CG_DrawActive - -Perform all drawing needed to completely fill the screen -===================== -*/ -void CG_DrawActive( stereoFrame_t stereoView ) -{ - float separation; - vec3_t baseOrg; - - // optionally draw the info screen instead - if( !cg.snap ) - return; - - switch ( stereoView ) - { - case STEREO_CENTER: - separation = 0; - break; - case STEREO_LEFT: - separation = -cg_stereoSeparation.value / 2; - break; - case STEREO_RIGHT: - separation = cg_stereoSeparation.value / 2; - break; - default: - separation = 0; - CG_Error( "CG_DrawActive: Undefined stereoView" ); - } - - // clear around the rendered view if sized down - CG_TileClear( ); - - // offset vieworg appropriately if we're doing stereo separation - VectorCopy( cg.refdef.vieworg, baseOrg ); - - if( separation != 0 ) - VectorMA( cg.refdef.vieworg, -separation, cg.refdef.viewaxis[ 1 ], - cg.refdef.vieworg ); - - // draw 3D view - trap_R_RenderScene( &cg.refdef ); - - // restore original viewpoint if running stereo - if( separation != 0 ) - VectorCopy( baseOrg, cg.refdef.vieworg ); - - // first person blend blobs, done after AnglesToAxis - if( !cg.renderingThirdPerson ) - CG_PainBlend( ); - - // draw status bar and other floating elements - CG_Draw2D( ); -} - - diff --git a/mod/src/cgame/cg_drawtools.c b/mod/src/cgame/cg_drawtools.c deleted file mode 100644 index b1f0d9ab..00000000 --- a/mod/src/cgame/cg_drawtools.c +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc - -/* - * 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" - -/* -=============== -CG_DrawPlane - -Draw a quad in 3 space - basically CG_DrawPic in 3 space -=============== -*/ -void CG_DrawPlane( vec3_t origin, vec3_t down, vec3_t right, qhandle_t shader ) -{ - polyVert_t verts[ 4 ]; - vec3_t temp; - - VectorCopy( origin, verts[ 0 ].xyz ); - verts[ 0 ].st[ 0 ] = 0; - verts[ 0 ].st[ 1 ] = 0; - verts[ 0 ].modulate[ 0 ] = 255; - verts[ 0 ].modulate[ 1 ] = 255; - verts[ 0 ].modulate[ 2 ] = 255; - verts[ 0 ].modulate[ 3 ] = 255; - - VectorAdd( origin, right, temp ); - VectorCopy( temp, verts[ 1 ].xyz ); - verts[ 1 ].st[ 0 ] = 1; - verts[ 1 ].st[ 1 ] = 0; - verts[ 1 ].modulate[ 0 ] = 255; - verts[ 1 ].modulate[ 1 ] = 255; - verts[ 1 ].modulate[ 2 ] = 255; - verts[ 1 ].modulate[ 3 ] = 255; - - VectorAdd( origin, right, temp ); - VectorAdd( temp, down, temp ); - VectorCopy( temp, verts[ 2 ].xyz ); - verts[ 2 ].st[ 0 ] = 1; - verts[ 2 ].st[ 1 ] = 1; - verts[ 2 ].modulate[ 0 ] = 255; - verts[ 2 ].modulate[ 1 ] = 255; - verts[ 2 ].modulate[ 2 ] = 255; - verts[ 2 ].modulate[ 3 ] = 255; - - VectorAdd( origin, down, temp ); - VectorCopy( temp, verts[ 3 ].xyz ); - verts[ 3 ].st[ 0 ] = 0; - verts[ 3 ].st[ 1 ] = 1; - verts[ 3 ].modulate[ 0 ] = 255; - verts[ 3 ].modulate[ 1 ] = 255; - verts[ 3 ].modulate[ 2 ] = 255; - verts[ 3 ].modulate[ 3 ] = 255; - - trap_R_AddPolyToScene( shader, 4, verts ); -} - -/* -================ -CG_AdjustFrom640 - -Adjusted for resolution and screen aspect ratio -================ -*/ -void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) -{ -#if 0 - // adjust for wide screens - if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) { - *x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) ); - } -#endif - // scale for screen sizes - *x *= cgs.screenXScale; - *y *= cgs.screenYScale; - *w *= cgs.screenXScale; - *h *= cgs.screenYScale; -} - -/* -================ -CG_FillRect - -Coordinates are 640*480 virtual values -================= -*/ -void CG_FillRect( float x, float y, float width, float height, const float *color ) -{ - trap_R_SetColor( color ); - - CG_AdjustFrom640( &x, &y, &width, &height ); - trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader ); - - trap_R_SetColor( NULL ); -} - - -/* -================ -CG_DrawSides - -Coords are virtual 640x480 -================ -*/ -void CG_DrawSides( float x, float y, float w, float h, float size ) -{ - CG_AdjustFrom640( &x, &y, &w, &h ); - size *= cgs.screenXScale; - trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader ); - trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader ); -} - -void CG_DrawTopBottom( float x, float y, float w, float h, float size ) -{ - CG_AdjustFrom640( &x, &y, &w, &h ); - size *= cgs.screenYScale; - trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, cgs.media.whiteShader ); - trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, cgs.media.whiteShader ); -} - - -/* -================ -CG_DrawRect - -Coordinates are 640*480 virtual values -================= -*/ -void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) -{ - trap_R_SetColor( color ); - - CG_DrawTopBottom( x, y, width, height, size ); - CG_DrawSides( x, y, width, height, size ); - - trap_R_SetColor( NULL ); -} - - -/* -================ -CG_DrawPic - -Coordinates are 640*480 virtual values -================= -*/ -void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) -{ - CG_AdjustFrom640( &x, &y, &width, &height ); - trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader ); -} - - - -/* -================ -CG_DrawFadePic - -Coordinates are 640*480 virtual values -================= -*/ -void CG_DrawFadePic( float x, float y, float width, float height, vec4_t fcolor, - vec4_t tcolor, float amount, qhandle_t hShader ) -{ - vec4_t finalcolor; - float inverse; - - inverse = 100 - amount; - - CG_AdjustFrom640( &x, &y, &width, &height ); - - finalcolor[ 0 ] = ( ( inverse * fcolor[ 0 ] ) + ( amount * tcolor[ 0 ] ) ) / 100; - finalcolor[ 1 ] = ( ( inverse * fcolor[ 1 ] ) + ( amount * tcolor[ 1 ] ) ) / 100; - finalcolor[ 2 ] = ( ( inverse * fcolor[ 2 ] ) + ( amount * tcolor[ 2 ] ) ) / 100; - finalcolor[ 3 ] = ( ( inverse * fcolor[ 3 ] ) + ( amount * tcolor[ 3 ] ) ) / 100; - - trap_R_SetColor( finalcolor ); - trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader ); - trap_R_SetColor( NULL ); -} - -/* -================= -CG_DrawStrlen - -Returns character count, skiping color escape codes -================= -*/ -int CG_DrawStrlen( const char *str ) -{ - const char *s = str; - int count = 0; - - while( *s ) - { - if( Q_IsColorString( s ) ) - s += 2; - else - { - count++; - s++; - } - } - - return count; -} - -/* -============= -CG_TileClearBox - -This repeats a 64*64 tile graphic to fill the screen around a sized down -refresh window. -============= -*/ -static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) -{ - float s1, t1, s2, t2; - - s1 = x / 64.0; - t1 = y / 64.0; - s2 = ( x + w ) / 64.0; - t2 = ( y + h ) / 64.0; - trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, hShader ); -} - - - -/* -============== -CG_TileClear - -Clear around a sized down screen -============== -*/ -void CG_TileClear( void ) -{ - int top, bottom, left, right; - int w, h; - - w = cgs.glconfig.vidWidth; - h = cgs.glconfig.vidHeight; - - if( cg.refdef.x == 0 && cg.refdef.y == 0 && - cg.refdef.width == w && cg.refdef.height == h ) - return; // full screen rendering - - top = cg.refdef.y; - bottom = top + cg.refdef.height - 1; - left = cg.refdef.x; - right = left + cg.refdef.width - 1; - - // clear above view screen - CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader ); - - // clear below view screen - CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader ); - - // clear left of view screen - CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader ); - - // clear right of view screen - CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader ); -} - - - -/* -================ -CG_FadeColor -================ -*/ -float *CG_FadeColor( int startMsec, int totalMsec ) -{ - static vec4_t color; - int t; - - if( startMsec == 0 ) - return NULL; - - t = cg.time - startMsec; - - if( t >= totalMsec ) - return NULL; - - // fade out - if( totalMsec - t < FADE_TIME ) - color[ 3 ] = ( totalMsec - t ) * 1.0 / FADE_TIME; - else - color[ 3 ] = 1.0; - - color[ 0 ] = color[ 1 ] = color[ 2 ] = 1; - - return color; -} diff --git a/mod/src/cgame/cg_ents.c b/mod/src/cgame/cg_ents.c deleted file mode 100644 index b622d2f3..00000000 --- a/mod/src/cgame/cg_ents.c +++ /dev/null @@ -1,1225 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_ents.c -- present snapshot entities, happens every single frame - -/* - * 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" - -/* -====================== -CG_DrawBoxFace - -Draws a bounding box face -====================== -*/ -static void CG_DrawBoxFace( vec3_t a, vec3_t b, vec3_t c, vec3_t d ) -{ - polyVert_t verts[ 4 ]; - vec4_t color = { 255.0f, 0.0f, 0.0f, 128.0f }; - - VectorCopy( d, verts[ 0 ].xyz ); - verts[ 0 ].st[ 0 ] = 1; - verts[ 0 ].st[ 1 ] = 1; - Vector4Copy( color, verts[ 0 ].modulate ); - - VectorCopy( c, verts[ 1 ].xyz ); - verts[ 1 ].st[ 0 ] = 1; - verts[ 1 ].st[ 1 ] = 0; - Vector4Copy( color, verts[ 1 ].modulate ); - - VectorCopy( b, verts[ 2 ].xyz ); - verts[ 2 ].st[ 0 ] = 0; - verts[ 2 ].st[ 1 ] = 0; - Vector4Copy( color, verts[ 2 ].modulate ); - - VectorCopy( a, verts[ 3 ].xyz ); - verts[ 3 ].st[ 0 ] = 0; - verts[ 3 ].st[ 1 ] = 1; - Vector4Copy( color, verts[ 3 ].modulate ); - - trap_R_AddPolyToScene( cgs.media.outlineShader, 4, verts ); -} - -/* -====================== -CG_DrawBoundingBox - -Draws a bounding box -====================== -*/ -void CG_DrawBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs ) -{ - vec3_t ppp, mpp, mmp, pmp; - vec3_t mmm, pmm, ppm, mpm; - - ppp[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - ppp[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - ppp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - mpp[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mpp[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - mpp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - mmp[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mmp[ 1 ] = origin[ 1 ] + mins[ 1 ]; - mmp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - pmp[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - pmp[ 1 ] = origin[ 1 ] + mins[ 1 ]; - pmp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - ppm[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - ppm[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - ppm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - mpm[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mpm[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - mpm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - mmm[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mmm[ 1 ] = origin[ 1 ] + mins[ 1 ]; - mmm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - pmm[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - pmm[ 1 ] = origin[ 1 ] + mins[ 1 ]; - pmm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - //phew! - - CG_DrawBoxFace( ppp, mpp, mmp, pmp ); - CG_DrawBoxFace( ppp, pmp, pmm, ppm ); - CG_DrawBoxFace( mpp, ppp, ppm, mpm ); - CG_DrawBoxFace( mmp, mpp, mpm, mmm ); - CG_DrawBoxFace( pmp, mmp, mmm, pmm ); - CG_DrawBoxFace( mmm, mpm, ppm, pmm ); -} - - -/* -====================== -CG_PositionEntityOnTag - -Modifies the entities position and axis by the given -tag location -====================== -*/ -void CG_PositionEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ) -{ - int i; - orientation_t lerped; - - // lerp the tag - trap_R_LerpTag( &lerped, parentModel, parent->oldframe, parent->frame, - 1.0 - parent->backlerp, tagName ); - - // FIXME: allow origin offsets along tag? - VectorCopy( parent->origin, entity->origin ); - for( i = 0; i < 3; i++ ) - VectorMA( entity->origin, lerped.origin[ i ], parent->axis[ i ], entity->origin ); - - // had to cast away the const to avoid compiler problems... - MatrixMultiply( lerped.axis, ( (refEntity_t *)parent )->axis, entity->axis ); - entity->backlerp = parent->backlerp; -} - - -/* -====================== -CG_PositionRotatedEntityOnTag - -Modifies the entities position and axis by the given -tag location -====================== -*/ -void CG_PositionRotatedEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ) -{ - int i; - orientation_t lerped; - vec3_t tempAxis[ 3 ]; - -//AxisClear( entity->axis ); - // lerp the tag - trap_R_LerpTag( &lerped, parentModel, parent->oldframe, parent->frame, - 1.0 - parent->backlerp, tagName ); - - // FIXME: allow origin offsets along tag? - VectorCopy( parent->origin, entity->origin ); - for( i = 0; i < 3; i++ ) - VectorMA( entity->origin, lerped.origin[ i ], parent->axis[ i ], entity->origin ); - - // had to cast away the const to avoid compiler problems... - MatrixMultiply( entity->axis, lerped.axis, tempAxis ); - MatrixMultiply( tempAxis, ( (refEntity_t *)parent )->axis, entity->axis ); -} - - - -/* -========================================================================== - -FUNCTIONS CALLED EACH FRAME - -========================================================================== -*/ - -/* -====================== -CG_SetEntitySoundPosition - -Also called by event processing code -====================== -*/ -void CG_SetEntitySoundPosition( centity_t *cent ) -{ - if( cent->currentState.solid == SOLID_BMODEL ) - { - vec3_t origin; - float *v; - - v = cgs.inlineModelMidpoints[ cent->currentState.modelindex ]; - VectorAdd( cent->lerpOrigin, v, origin ); - trap_S_UpdateEntityPosition( cent->currentState.number, origin ); - } - else - trap_S_UpdateEntityPosition( cent->currentState.number, cent->lerpOrigin ); -} - -/* -================== -CG_EntityEffects - -Add continuous entity effects, like local entity emission and lighting -================== -*/ -static void CG_EntityEffects( centity_t *cent ) -{ - // update sound origins - CG_SetEntitySoundPosition( cent ); - - // add loop sound - if( cent->currentState.loopSound ) - { - if( cent->currentState.eType != ET_SPEAKER ) - { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - cgs.gameSounds[ cent->currentState.loopSound ] ); - } - else - { - trap_S_AddRealLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - cgs.gameSounds[ cent->currentState.loopSound ] ); - } - } - - - // constant light glow - if ( cent->currentState.constantLight ) - { - int cl; - int i, r, g, b; - - cl = cent->currentState.constantLight; - r = cl & 255; - g = ( cl >> 8 ) & 255; - b = ( cl >> 16 ) & 255; - i = ( ( cl >> 24 ) & 255 ) * 4; - trap_R_AddLightToScene( cent->lerpOrigin, i, r, g, b ); - } - - if( cg.time > cent->muzzleTSDeathTime && CG_IsTrailSystemValid( ¢->muzzleTS ) ) - CG_DestroyTrailSystem( ¢->muzzleTS ); -} - - -/* -================== -CG_General -================== -*/ -static void CG_General( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // if set to invisible, skip - if( !s1->modelindex ) - return; - - memset( &ent, 0, sizeof( ent ) ); - - // set frame - - ent.frame = s1->frame; - ent.oldframe = ent.frame; - ent.backlerp = 0; - - VectorCopy( cent->lerpOrigin, ent.origin); - VectorCopy( cent->lerpOrigin, ent.oldorigin); - - ent.hModel = cgs.gameModels[ s1->modelindex ]; - - // player model - if( s1->number == cg.snap->ps.clientNum ) - ent.renderfx |= RF_THIRD_PERSON; // only draw from mirrors - - // convert angles to axis - AnglesToAxis( cent->lerpAngles, ent.axis ); - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - -/* -================== -CG_Speaker - -Speaker entities can automatically play sounds -================== -*/ -static void CG_Speaker( centity_t *cent ) -{ - if( ! cent->currentState.clientNum ) - { // FIXME: use something other than clientNum... - return; // not auto triggering - } - - if( cg.time < cent->miscTime ) - return; - - trap_S_StartSound( NULL, cent->currentState.number, CHAN_ITEM, cgs.gameSounds[ cent->currentState.eventParm ] ); - - // ent->s.frame = ent->wait * 10; - // ent->s.clientNum = ent->random * 10; - cent->miscTime = cg.time + cent->currentState.frame * 100 + cent->currentState.clientNum * 100 * crandom( ); -} - - -//============================================================================ - -/* -=============== -CG_LaunchMissile -=============== -*/ -static void CG_LaunchMissile( centity_t *cent ) -{ - entityState_t *es; - const weaponInfo_t *wi; - particleSystem_t *ps; - trailSystem_t *ts; - weapon_t weapon; - weaponMode_t weaponMode; - - es = ¢->currentState; - - weapon = es->weapon; - if( weapon > WP_NUM_WEAPONS ) - weapon = WP_NONE; - - wi = &cg_weapons[ weapon ]; - weaponMode = es->generic1; - - if( wi->wim[ weaponMode ].missileParticleSystem ) - { - ps = CG_SpawnNewParticleSystem( wi->wim[ weaponMode ].missileParticleSystem ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentCent( &ps->attachment, cent ); - CG_AttachToCent( &ps->attachment ); - } - } - - if( wi->wim[ weaponMode ].missileTrailSystem ) - { - ts = CG_SpawnNewTrailSystem( wi->wim[ weaponMode ].missileTrailSystem ); - - if( CG_IsTrailSystemValid( &ts ) ) - { - CG_SetAttachmentCent( &ts->frontAttachment, cent ); - CG_AttachToCent( &ts->frontAttachment ); - } - } -} - -/* -=============== -CG_Missile -=============== -*/ -static void CG_Missile( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *es; - const weaponInfo_t *wi; - weapon_t weapon; - weaponMode_t weaponMode; - const weaponInfoMode_t *wim; - - es = ¢->currentState; - - weapon = es->weapon; - if( weapon > WP_NUM_WEAPONS ) - weapon = WP_NONE; - - wi = &cg_weapons[ weapon ]; - weaponMode = es->generic1; - - wim = &wi->wim[ weaponMode ]; - - // calculate the axis - VectorCopy( es->angles, cent->lerpAngles ); - - // add dynamic light - if( wim->missileDlight ) - { - trap_R_AddLightToScene( cent->lerpOrigin, wim->missileDlight, - wim->missileDlightColor[ 0 ], - wim->missileDlightColor[ 1 ], - wim->missileDlightColor[ 2 ] ); - } - - // add missile sound - if( wim->missileSound ) - { - vec3_t velocity; - - BG_EvaluateTrajectoryDelta( ¢->currentState.pos, cg.time, velocity ); - - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, wim->missileSound ); - } - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - - if( wim->usesSpriteMissle ) - { - ent.reType = RT_SPRITE; - ent.radius = wim->missileSpriteSize; - ent.rotation = 0; - ent.customShader = wim->missileSprite; - ent.shaderRGBA[ 0 ] = 0xFF; - ent.shaderRGBA[ 1 ] = 0xFF; - ent.shaderRGBA[ 2 ] = 0xFF; - ent.shaderRGBA[ 3 ] = 0xFF; - } - else - { - ent.hModel = wim->missileModel; - ent.renderfx = wim->missileRenderfx | RF_NOSHADOW; - - // convert direction of travel into axis - if( VectorNormalize2( es->pos.trDelta, ent.axis[ 0 ] ) == 0 ) - ent.axis[ 0 ][ 2 ] = 1; - - // spin as it moves - if( es->pos.trType != TR_STATIONARY && wim->missileRotates ) - RotateAroundDirection( ent.axis, cg.time / 4 ); - else - RotateAroundDirection( ent.axis, es->time ); - - if( wim->missileAnimates ) - { - int timeSinceStart = cg.time - es->time; - - if( wim->missileAnimLooping ) - { - ent.frame = wim->missileAnimStartFrame + - (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate ) % - wim->missileAnimNumFrames; - } - else - { - ent.frame = wim->missileAnimStartFrame + - (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate ); - - if( ent.frame > ( wim->missileAnimStartFrame + wim->missileAnimNumFrames ) ) - ent.frame = wim->missileAnimStartFrame + wim->missileAnimNumFrames; - } - } - } - - //only refresh if there is something to display - if( wim->missileSprite || wim->missileModel ) - trap_R_AddRefEntityToScene( &ent ); -} - -/* -=============== -CG_Mover -=============== -*/ -static void CG_Mover( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - AnglesToAxis( cent->lerpAngles, ent.axis ); - - ent.renderfx = RF_NOSHADOW; - - // flicker between two skins (FIXME?) - ent.skinNum = ( cg.time >> 6 ) & 1; - - // get the model, either as a bmodel or a modelindex - if( s1->solid == SOLID_BMODEL ) - ent.hModel = cgs.inlineDrawModel[ s1->modelindex ]; - else - ent.hModel = cgs.gameModels[ s1->modelindex ]; - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); - - // add the secondary model - if( s1->modelindex2 ) - { - ent.skinNum = 0; - ent.hModel = cgs.gameModels[ s1->modelindex2 ]; - trap_R_AddRefEntityToScene( &ent ); - } - -} - -/* -=============== -CG_Beam - -Also called as an event -=============== -*/ -void CG_Beam( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( s1->pos.trBase, ent.origin ); - VectorCopy( s1->origin2, ent.oldorigin ); - AxisClear( ent.axis ); - ent.reType = RT_BEAM; - - ent.renderfx = RF_NOSHADOW; - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - - -/* -=============== -CG_Portal -=============== -*/ -static void CG_Portal( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( s1->origin2, ent.oldorigin ); - ByteToDir( s1->eventParm, ent.axis[ 0 ] ); - PerpendicularVector( ent.axis[ 1 ], ent.axis[ 0 ] ); - - // negating this tends to get the directions like they want - // we really should have a camera roll value - VectorSubtract( vec3_origin, ent.axis[ 1 ], ent.axis[ 1 ] ); - - CrossProduct( ent.axis[ 0 ], ent.axis[ 1 ], ent.axis[ 2 ] ); - ent.reType = RT_PORTALSURFACE; - ent.oldframe = s1->powerups; - ent.frame = s1->frame; // rotation speed - ent.skinNum = s1->clientNum / 256.0 * 360; // roll offset - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - -//============================================================================ - -#define SETBOUNDS(v1,v2,r) ((v1)[0]=(-r/2),(v1)[1]=(-r/2),(v1)[2]=(-r/2),\ - (v2)[0]=(r/2),(v2)[1]=(r/2),(v2)[2]=(r/2)) -#define RADIUSSTEP 0.5f - -#define FLARE_OFF 0 -#define FLARE_NOFADE 1 -#define FLARE_TIMEFADE 2 -#define FLARE_REALFADE 3 - -/* -========================= -CG_LightFlare -========================= -*/ -static void CG_LightFlare( centity_t *cent ) -{ - refEntity_t flare; - entityState_t *es; - vec3_t forward, delta; - float len; - trace_t tr; - float maxAngle; - vec3_t mins, maxs, start, end; - float srcRadius, srLocal, ratio = 1.0f; - int entityNum; - - es = ¢->currentState; - - if( cg.renderingThirdPerson ) - entityNum = MAGIC_TRACE_HACK; - else - entityNum = cg.predictedPlayerState.clientNum; - - //don't draw light flares - if( cg_lightFlare.integer == FLARE_OFF ) - return; - - //flare is "off" - if( es->eFlags & EF_NODRAW ) - return; - - CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL, es->angles2, - entityNum, MASK_SHOT ); - - //if there is no los between the view and the flare source - //it definately cannot be seen - if( tr.fraction < 1.0f || tr.allsolid ) - return; - - memset( &flare, 0, sizeof( flare ) ); - - flare.reType = RT_SPRITE; - flare.customShader = cgs.gameShaders[ es->modelindex ]; - flare.shaderRGBA[ 0 ] = 0xFF; - flare.shaderRGBA[ 1 ] = 0xFF; - flare.shaderRGBA[ 2 ] = 0xFF; - flare.shaderRGBA[ 3 ] = 0xFF; - - //flares always drawn before the rest of the scene - flare.renderfx |= RF_DEPTHHACK; - - //bunch of geometry - AngleVectors( es->angles, forward, NULL, NULL ); - VectorCopy( cent->lerpOrigin, flare.origin ); - VectorSubtract( flare.origin, cg.refdef.vieworg, delta ); - len = VectorLength( delta ); - VectorNormalize( delta ); - - //flare is too close to camera to be drawn - if( len < es->generic1 ) - return; - - //don't bother for flares behind the view plane - if( DotProduct( delta, cg.refdef.viewaxis[ 0 ] ) < 0.0 ) - return; - - //only recalculate radius and ratio every three frames - if( !( cg.clientFrame % 2 ) ) - { - //can only see the flare when in front of it - flare.radius = len / es->origin2[ 0 ]; - - if( es->origin2[ 2 ] == 0 ) - srcRadius = srLocal = flare.radius / 2.0f; - else - srcRadius = srLocal = len / es->origin2[ 2 ]; - - maxAngle = es->origin2[ 1 ]; - - if( maxAngle > 0.0f ) - { - float radiusMod = 1.0f - ( 180.0f - RAD2DEG( - acos( DotProduct( delta, forward ) ) ) ) / maxAngle; - - if( es->eFlags & EF_NODRAW ) - flare.radius *= radiusMod; - else if( radiusMod < 0.0f ) - flare.radius = 0.0f; - } - - if( flare.radius < 0.0f ) - flare.radius = 0.0f; - - VectorMA( flare.origin, -flare.radius, delta, end ); - VectorMA( cg.refdef.vieworg, flare.radius, delta, start ); - - if( cg_lightFlare.integer == FLARE_REALFADE ) - { - //draw "correct" albeit inefficient flares - srLocal = cent->lfs.lastSrcRadius; - - //flare radius is likely to be the same as last frame so start with it - do - { - srLocal += RADIUSSTEP; - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - } while( ( tr.fraction == 1.0f && !tr.startsolid ) && ( srLocal < srcRadius ) ); - - srLocal -= RADIUSSTEP; - - //shink the flare until there is a los - do - { - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - srLocal -= RADIUSSTEP; - } while( ( tr.fraction < 1.0f || tr.startsolid ) && ( srLocal > 0.0f ) ); - - ratio = srLocal / srcRadius; - - cent->lfs.lastSrcRadius = srLocal; - } - else if( cg_lightFlare.integer == FLARE_TIMEFADE ) - { - //draw timed flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - if( ( tr.fraction < 1.0f || tr.startsolid ) && cent->lfs.status ) - { - cent->lfs.status = qfalse; - cent->lfs.lastTime = cg.time; - } - else if( ( tr.fraction == 1.0f && !tr.startsolid ) && !cent->lfs.status ) - { - cent->lfs.status = qtrue; - cent->lfs.lastTime = cg.time; - } - - //fade flare up - if( cent->lfs.status ) - { - if( cent->lfs.lastTime + es->time > cg.time ) - ratio = (float)( cg.time - cent->lfs.lastTime ) / es->time; - } - - //fade flare down - if( !cent->lfs.status ) - { - if( cent->lfs.lastTime + es->time > cg.time ) - { - ratio = (float)( cg.time - cent->lfs.lastTime ) / es->time; - ratio = 1.0f - ratio; - } - else - ratio = 0.0f; - } - } - else if( cg_lightFlare.integer == FLARE_NOFADE ) - { - //draw nofade flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - //flare source occluded - if( ( tr.fraction < 1.0f || tr.startsolid ) ) - ratio = 0.0f; - } - } - else - { - ratio = cent->lfs.lastRatio; - flare.radius = cent->lfs.lastRadius; - } - - cent->lfs.lastRatio = ratio; - cent->lfs.lastRadius = flare.radius; - - if( ratio < 1.0f ) - { - flare.radius *= ratio; - flare.shaderRGBA[ 3 ] = (byte)( (float)flare.shaderRGBA[ 3 ] * ratio ); - } - - if( flare.radius <= 0.0f ) - return; - - trap_R_AddRefEntityToScene( &flare ); -} - -/* -========================= -CG_Lev2ZapChain -========================= -*/ -static void CG_Lev2ZapChain( centity_t *cent ) -{ - int i; - entityState_t *es; - centity_t *source, *target; - - es = ¢->currentState; - - for( i = 0; i <= 2; i++ ) - { - switch( i ) - { - case 0: - if( es->time <= 0 ) - continue; - - source = &cg_entities[ es->powerups ]; - target = &cg_entities[ es->time ]; - break; - - case 1: - if( es->time2 <= 0 ) - continue; - - source = &cg_entities[ es->time ]; - target = &cg_entities[ es->time2 ]; - break; - - case 2: - if( es->constantLight <= 0 ) - continue; - - source = &cg_entities[ es->time2 ]; - target = &cg_entities[ es->constantLight ]; - break; - } - - if( !CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - cent->level2ZapTS[ i ] = CG_SpawnNewTrailSystem( cgs.media.level2ZapTS ); - - if( CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - { - CG_SetAttachmentCent( ¢->level2ZapTS[ i ]->frontAttachment, source ); - CG_SetAttachmentCent( ¢->level2ZapTS[ i ]->backAttachment, target ); - CG_AttachToCent( ¢->level2ZapTS[ i ]->frontAttachment ); - CG_AttachToCent( ¢->level2ZapTS[ i ]->backAttachment ); - } - } -} - -/* -========================= -CG_AdjustPositionForMover - -Also called by client movement prediction code -========================= -*/ -void CG_AdjustPositionForMover( const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out ) -{ - centity_t *cent; - vec3_t oldOrigin, origin, deltaOrigin; - vec3_t oldAngles, angles, deltaAngles; - - if( moverNum <= 0 || moverNum >= ENTITYNUM_MAX_NORMAL ) - { - VectorCopy( in, out ); - return; - } - - cent = &cg_entities[ moverNum ]; - - if( cent->currentState.eType != ET_MOVER ) - { - VectorCopy( in, out ); - return; - } - - BG_EvaluateTrajectory( ¢->currentState.pos, fromTime, oldOrigin ); - BG_EvaluateTrajectory( ¢->currentState.apos, fromTime, oldAngles ); - - BG_EvaluateTrajectory( ¢->currentState.pos, toTime, origin ); - BG_EvaluateTrajectory( ¢->currentState.apos, toTime, angles ); - - VectorSubtract( origin, oldOrigin, deltaOrigin ); - VectorSubtract( angles, oldAngles, deltaAngles ); - - VectorAdd( in, deltaOrigin, out ); - - // FIXME: origin change when on a rotating object -} - - -/* -============================= -CG_InterpolateEntityPosition -============================= -*/ -static void CG_InterpolateEntityPosition( centity_t *cent ) -{ - vec3_t current, next; - float f; - - // it would be an internal error to find an entity that interpolates without - // a snapshot ahead of the current one - if( cg.nextSnap == NULL ) - CG_Error( "CG_InterpoateEntityPosition: cg.nextSnap == NULL" ); - - f = cg.frameInterpolation; - - // this will linearize a sine or parabolic curve, but it is important - // to not extrapolate player positions if more recent data is available - BG_EvaluateTrajectory( ¢->currentState.pos, cg.snap->serverTime, current ); - BG_EvaluateTrajectory( ¢->nextState.pos, cg.nextSnap->serverTime, next ); - - cent->lerpOrigin[ 0 ] = current[ 0 ] + f * ( next[ 0 ] - current[ 0 ] ); - cent->lerpOrigin[ 1 ] = current[ 1 ] + f * ( next[ 1 ] - current[ 1 ] ); - cent->lerpOrigin[ 2 ] = current[ 2 ] + f * ( next[ 2 ] - current[ 2 ] ); - - BG_EvaluateTrajectory( ¢->currentState.apos, cg.snap->serverTime, current ); - BG_EvaluateTrajectory( ¢->nextState.apos, cg.nextSnap->serverTime, next ); - - cent->lerpAngles[ 0 ] = LerpAngle( current[ 0 ], next[ 0 ], f ); - cent->lerpAngles[ 1 ] = LerpAngle( current[ 1 ], next[ 1 ], f ); - cent->lerpAngles[ 2 ] = LerpAngle( current[ 2 ], next[ 2 ], f ); - -} - -/* -=============== -CG_CalcEntityLerpPositions - -=============== -*/ -static void CG_CalcEntityLerpPositions( centity_t *cent ) -{ - // if this player does not want to see extrapolated players - if( !cg_smoothClients.integer ) - { - // make sure the clients use TR_INTERPOLATE - if( cent->currentState.number < MAX_CLIENTS ) - { - cent->currentState.pos.trType = TR_INTERPOLATE; - cent->nextState.pos.trType = TR_INTERPOLATE; - } - } - - if( cent->interpolate && cent->currentState.pos.trType == TR_INTERPOLATE ) - { - CG_InterpolateEntityPosition( cent ); - return; - } - - // first see if we can interpolate between two snaps for - // linear extrapolated clients - if( cent->interpolate && cent->currentState.pos.trType == TR_LINEAR_STOP && - cent->currentState.number < MAX_CLIENTS ) - { - CG_InterpolateEntityPosition( cent ); - return; - } - - // just use the current frame and evaluate as best we can - BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); - BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); - - // adjust for riding a mover if it wasn't rolled into the predicted - // player state - if( cent != &cg.predictedPlayerEntity ) - { - CG_AdjustPositionForMover( cent->lerpOrigin, cent->currentState.groundEntityNum, - cg.snap->serverTime, cg.time, cent->lerpOrigin ); - } -} - - -/* -=============== -CG_CEntityPVSEnter - -=============== -*/ -static void CG_CEntityPVSEnter( centity_t *cent ) -{ - entityState_t *es = ¢->currentState; - - if( cg_debugPVS.integer ) - CG_Printf( "Entity %d entered PVS\n", cent->currentState.number ); - - switch( es->eType ) - { - case ET_MISSILE: - CG_LaunchMissile( cent ); - break; - } - - //clear any particle systems from previous uses of this centity_t - cent->muzzlePS = NULL; - cent->muzzlePsTrigger = qfalse; - cent->jetPackPS = NULL; - cent->jetPackState = JPS_OFF; - cent->buildablePS = NULL; - cent->entityPS = NULL; - cent->entityPSMissing = qfalse; - - //make sure that the buildable animations are in a consistent state - //when a buildable enters the PVS - cent->buildableAnim = cent->lerpFrame.animationNumber = BANIM_NONE; - cent->oldBuildableAnim = es->legsAnim; -} - - -/* -=============== -CG_CEntityPVSLeave - -=============== -*/ -static void CG_CEntityPVSLeave( centity_t *cent ) -{ - int i; - entityState_t *es = ¢->currentState; - - if( cg_debugPVS.integer ) - CG_Printf( "Entity %d left PVS\n", cent->currentState.number ); - - switch( es->eType ) - { - case ET_LEV2_ZAP_CHAIN: - for( i = 0; i <= 2; i++ ) - { - if( CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - CG_DestroyTrailSystem( ¢->level2ZapTS[ i ] ); - } - break; - } -} - - -/* -=============== -CG_AddCEntity - -=============== -*/ -static void CG_AddCEntity( centity_t *cent ) -{ - // event-only entities will have been dealt with already - if( cent->currentState.eType >= ET_EVENTS ) - return; - - // calculate the current origin - CG_CalcEntityLerpPositions( cent ); - - // add automatic effects - CG_EntityEffects( cent ); - - switch( cent->currentState.eType ) - { - default: - CG_Error( "Bad entity type: %i\n", cent->currentState.eType ); - break; - - case ET_INVISIBLE: - case ET_PUSH_TRIGGER: - case ET_TELEPORT_TRIGGER: - break; - - case ET_GENERAL: - CG_General( cent ); - break; - - case ET_CORPSE: - CG_Corpse( cent ); - break; - - case ET_PLAYER: - CG_Player( cent ); - break; - - case ET_BUILDABLE: - CG_Buildable( cent ); - break; - - case ET_MISSILE: - CG_Missile( cent ); - break; - - case ET_MOVER: - CG_Mover( cent ); - break; - - case ET_BEAM: - CG_Beam( cent ); - break; - - case ET_PORTAL: - CG_Portal( cent ); - break; - - case ET_SPEAKER: - CG_Speaker( cent ); - break; - - case ET_PARTICLE_SYSTEM: - CG_ParticleSystemEntity( cent ); - break; - - case ET_ANIMMAPOBJ: - CG_AnimMapObj( cent ); - break; - - case ET_MODELDOOR: - CG_ModelDoor( cent ); - break; - - case ET_LIGHTFLARE: - CG_LightFlare( cent ); - break; - - case ET_LEV2_ZAP_CHAIN: - CG_Lev2ZapChain( cent ); - break; - } -} - -/* -=============== -CG_AddPacketEntities - -=============== -*/ -void CG_AddPacketEntities( void ) -{ - int num; - centity_t *cent; - playerState_t *ps; - - // set cg.frameInterpolation - if( cg.nextSnap ) - { - int delta; - - delta = ( cg.nextSnap->serverTime - cg.snap->serverTime ); - - if( delta == 0 ) - cg.frameInterpolation = 0; - else - cg.frameInterpolation = (float)( cg.time - cg.snap->serverTime ) / delta; - } - else - { - cg.frameInterpolation = 0; // actually, it should never be used, because - // no entities should be marked as interpolating - } - - // the auto-rotating items will all have the same axis - cg.autoAngles[ 0 ] = 0; - cg.autoAngles[ 1 ] = ( cg.time & 2047 ) * 360 / 2048.0; - cg.autoAngles[ 2 ] = 0; - - cg.autoAnglesFast[ 0 ] = 0; - cg.autoAnglesFast[ 1 ] = ( cg.time & 1023 ) * 360 / 1024.0f; - cg.autoAnglesFast[ 2 ] = 0; - - AnglesToAxis( cg.autoAngles, cg.autoAxis ); - AnglesToAxis( cg.autoAnglesFast, cg.autoAxisFast ); - - // generate and add the entity from the playerstate - ps = &cg.predictedPlayerState; - BG_PlayerStateToEntityState( ps, &cg.predictedPlayerEntity.currentState, qfalse ); - cg.predictedPlayerEntity.valid = qtrue; - CG_AddCEntity( &cg.predictedPlayerEntity ); - - // lerp the non-predicted value for lightning gun origins - CG_CalcEntityLerpPositions( &cg_entities[ cg.snap->ps.clientNum ] ); - - // scanner - CG_UpdateEntityPositions( ); - - for( num = 0; num < MAX_GENTITIES; num++ ) - cg_entities[ num ].valid = qfalse; - - // add each entity sent over by the server - for( num = 0; num < cg.snap->numEntities; num++ ) - { - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - cent->valid = qtrue; - } - - for( num = 0; num < MAX_GENTITIES; num++ ) - { - cent = &cg_entities[ num ]; - - if( cent->valid && !cent->oldValid ) - CG_CEntityPVSEnter( cent ); - else if( !cent->valid && cent->oldValid ) - CG_CEntityPVSLeave( cent ); - - cent->oldValid = cent->valid; - } - - // add each entity sent over by the server - for( num = 0; num < cg.snap->numEntities; num++ ) - { - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - CG_AddCEntity( cent ); - } - - //make an attempt at drawing bounding boxes of selected entity types - if( cg_drawBBOX.integer ) - { - for( num = 0; num < cg.snap->numEntities; num++ ) - { - float x, zd, zu; - vec3_t mins, maxs; - entityState_t *es; - - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - es = ¢->currentState; - - switch( es->eType ) - { - case ET_BUILDABLE: - case ET_MISSILE: - case ET_CORPSE: - x = ( es->solid & 255 ); - zd = ( ( es->solid >> 8 ) & 255 ); - zu = ( ( es->solid >> 16 ) & 255 ) - 32; - - mins[ 0 ] = mins[ 1 ] = -x; - maxs[ 0 ] = maxs[ 1 ] = x; - mins[ 2 ] = -zd; - maxs[ 2 ] = zu; - - CG_DrawBoundingBox( cent->lerpOrigin, mins, maxs ); - break; - - default: - break; - } - } - } -} - diff --git a/mod/src/cgame/cg_event.c b/mod/src/cgame/cg_event.c deleted file mode 100644 index b89c8e7c..00000000 --- a/mod/src/cgame/cg_event.c +++ /dev/null @@ -1,1011 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_event.c -- handle entity events at snapshot or playerstate transitions - -/* - * 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" - -/* -============= -CG_Obituary -============= -*/ -static void CG_Obituary( entityState_t *ent ) -{ - int mod; - int target, attacker; - char *message; - char *message2; - const char *targetInfo; - const char *attackerInfo; - char targetName[ 32 ]; - char attackerName[ 32 ]; - char className[ 64 ]; - gender_t gender; - clientInfo_t *ci; - - target = ent->otherEntityNum; - attacker = ent->otherEntityNum2; - mod = ent->eventParm; - - if( target < 0 || target >= MAX_CLIENTS ) - CG_Error( "CG_Obituary: target out of range" ); - - ci = &cgs.clientinfo[ target ]; - - if( attacker < 0 || attacker >= MAX_CLIENTS ) - { - attacker = ENTITYNUM_WORLD; - attackerInfo = NULL; - } - else - attackerInfo = CG_ConfigString( CS_PLAYERS + attacker ); - - targetInfo = CG_ConfigString( CS_PLAYERS + target ); - - if( !targetInfo ) - return; - - Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) - 2 ); - strcat( targetName, S_COLOR_WHITE ); - - message2 = ""; - - // check for single client messages - - switch( mod ) - { - case MOD_SUICIDE: - message = "suicides"; - break; - case MOD_FALLING: - message = "fell fowl to gravity"; - break; - case MOD_CRUSH: - message = "was squished"; - break; - case MOD_WATER: - message = "forgot to pack a snorkel"; - break; - case MOD_SLIME: - message = "melted"; - break; - case MOD_LAVA: - message = "does a back flip into the lava"; - break; - case MOD_TARGET_LASER: - message = "saw the light"; - break; - case MOD_TRIGGER_HURT: - message = "was in the wrong place"; - break; - case MOD_HSPAWN: - message = "should have ran further"; - break; - case MOD_ASPAWN: - message = "shouldn't have trod in the acid"; - break; - case MOD_MGTURRET: - message = "was gunned down by a turret"; - break; - case MOD_TESLAGEN: - message = "was zapped by a tesla generator"; - break; - case MOD_ATUBE: - message = "was melted by an acid tube"; - break; - case MOD_OVERMIND: - message = "got too close to the overmind"; - break; - case MOD_REACTOR: - message = "got too close to the reactor"; - break; - case MOD_SLOWBLOB: - message = "should have visited a medical station"; - break; - case MOD_SWARM: - message = "was hunted down by the swarm"; - break; - default: - message = NULL; - break; - } - - if( attacker == target ) - { - gender = ci->gender; - switch( mod ) - { - case MOD_FLAMER_SPLASH: - if( gender == GENDER_FEMALE ) - message = "toasted herself"; - else if( gender == GENDER_NEUTER ) - message = "toasted itself"; - else - message = "toasted himself"; - break; - - case MOD_LCANNON_SPLASH: - if( gender == GENDER_FEMALE ) - message = "irradiated herself"; - else if( gender == GENDER_NEUTER ) - message = "irradiated itself"; - else - message = "irradiated himself"; - break; - - case MOD_GRENADE: - if( gender == GENDER_FEMALE ) - message = "blew herself up"; - else if( gender == GENDER_NEUTER ) - message = "blew itself up"; - else - message = "blew himself up"; - break; - - default: - if( gender == GENDER_FEMALE ) - message = "killed herself"; - else if( gender == GENDER_NEUTER ) - message = "killed itself"; - else - message = "killed himself"; - break; - } - } - - if( message ) - { - CG_Printf( "%s %s.\n", targetName, message ); - return; - } - - // check for double client messages - if( !attackerInfo ) - { - attacker = ENTITYNUM_WORLD; - strcpy( attackerName, "noname" ); - } - else - { - Q_strncpyz( attackerName, Info_ValueForKey( attackerInfo, "n" ), sizeof( attackerName ) - 2); - strcat( attackerName, S_COLOR_WHITE ); - // check for kill messages about the current clientNum - if( target == cg.snap->ps.clientNum ) - Q_strncpyz( cg.killerName, attackerName, sizeof( cg.killerName ) ); - } - - if( attacker != ENTITYNUM_WORLD ) - { - switch( mod ) - { - case MOD_PAINSAW: - message = "was sawn by"; - break; - case MOD_BLASTER: - message = "was blasted by"; - break; - case MOD_MACHINEGUN: - message = "was machinegunned by"; - break; - case MOD_CHAINGUN: - message = "was chaingunned by"; - break; - case MOD_SHOTGUN: - message = "was gunned down by"; - break; - case MOD_PRIFLE: - message = "was pulse rifled by"; - break; - case MOD_MDRIVER: - message = "was mass driven by"; - break; - case MOD_LASGUN: - message = "was lasgunned by"; - break; - case MOD_FLAMER: - message = "was grilled by"; - message2 = "'s flamer"; - break; - case MOD_FLAMER_SPLASH: - message = "was toasted by"; - message2 = "'s flamer"; - break; - case MOD_LCANNON: - message = "felt the full force of"; - message2 = "'s lucifer cannon"; - break; - case MOD_LCANNON_SPLASH: - message = "was caught in the fallout of"; - message2 = "'s lucifer cannon"; - break; - case MOD_GRENADE: - message = "couldn't escape"; - message2 = "'s grenade"; - break; - - case MOD_ABUILDER_CLAW: - message = "should leave"; - message2 = "'s buildings alone"; - break; - case MOD_LEVEL0_BITE: - message = "was bitten by"; - break; - case MOD_LEVEL1_CLAW: - message = "was swiped by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL1 ) ); - message2 = className; - break; - case MOD_LEVEL2_CLAW: - message = "was clawed by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL2 ) ); - message2 = className; - break; - case MOD_LEVEL2_ZAP: - message = "was zapped by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL2 ) ); - message2 = className; - break; - case MOD_LEVEL3_CLAW: - message = "was chomped by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) ); - message2 = className; - break; - case MOD_LEVEL3_POUNCE: - message = "was pounced upon by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) ); - message2 = className; - break; - case MOD_LEVEL3_BOUNCEBALL: - message = "was sniped by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) ); - message2 = className; - break; - case MOD_LEVEL4_CLAW: - message = "was mauled by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) ); - message2 = className; - break; - case MOD_LEVEL4_CHARGE: - message = "should have gotten out of the way of"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) ); - message2 = className; - break; - - case MOD_POISON: - message = "should have used a medkit against"; - message2 = "'s poison"; - break; - case MOD_LEVEL1_PCLOUD: - message = "was gassed by"; - Com_sprintf( className, 64, "'s %s", - BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL1 ) ); - message2 = className; - break; - - - case MOD_TELEFRAG: - message = "tried to invade"; - message2 = "'s personal space"; - break; - default: - message = "was killed by"; - break; - } - - if( message ) - { - CG_Printf( "%s %s %s%s\n", - targetName, message, attackerName, message2 ); - return; - } - } - - // we don't know what it was - CG_Printf( "%s died.\n", targetName ); -} - -//========================================================================== - -/* -================ -CG_PainEvent - -Also called by playerstate transition -================ -*/ -void CG_PainEvent( centity_t *cent, int health ) -{ - char *snd; - - // don't do more than two pain sounds a second - if( cg.time - cent->pe.painTime < 500 ) - return; - - if( health < 25 ) - snd = "*pain25_1.wav"; - else if( health < 50 ) - snd = "*pain50_1.wav"; - else if( health < 75 ) - snd = "*pain75_1.wav"; - else - snd = "*pain100_1.wav"; - - trap_S_StartSound( NULL, cent->currentState.number, CHAN_VOICE, - CG_CustomSound( cent->currentState.number, snd ) ); - - // save pain time for programitic twitch animation - cent->pe.painTime = cg.time; - cent->pe.painDirection ^= 1; -} - -/* -============== -CG_EntityEvent - -An entity has an event value -also called by CG_CheckPlayerstateEvents -============== -*/ -#define DEBUGNAME(x) if(cg_debugEvents.integer){CG_Printf(x"\n");} -void CG_EntityEvent( centity_t *cent, vec3_t position ) -{ - entityState_t *es; - int event; - vec3_t dir; - const char *s; - int clientNum; - clientInfo_t *ci; - int steptime; - - if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) - steptime = 200; - else - steptime = BG_FindSteptimeForClass( cg.snap->ps.stats[ STAT_PCLASS ] ); - - es = ¢->currentState; - event = es->event & ~EV_EVENT_BITS; - - if( cg_debugEvents.integer ) - CG_Printf( "ent:%3i event:%3i ", es->number, event ); - - if( !event ) - { - DEBUGNAME("ZEROEVENT"); - return; - } - - clientNum = es->clientNum; - if( clientNum < 0 || clientNum >= MAX_CLIENTS ) - clientNum = 0; - - ci = &cgs.clientinfo[ clientNum ]; - - switch( event ) - { - // - // movement generated events - // - case EV_FOOTSTEP: - DEBUGNAME( "EV_FOOTSTEP" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - if( ci->footsteps == FOOTSTEP_CUSTOM ) - trap_S_StartSound( NULL, es->number, CHAN_BODY, - ci->customFootsteps[ rand( ) & 3 ] ); - else - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ ci->footsteps ][ rand( ) & 3 ] ); - } - break; - - case EV_FOOTSTEP_METAL: - DEBUGNAME( "EV_FOOTSTEP_METAL" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - if( ci->footsteps == FOOTSTEP_CUSTOM ) - trap_S_StartSound( NULL, es->number, CHAN_BODY, - ci->customMetalFootsteps[ rand( ) & 3 ] ); - else - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ FOOTSTEP_METAL ][ rand( ) & 3 ] ); - } - break; - - case EV_FOOTSTEP_SQUELCH: - DEBUGNAME( "EV_FOOTSTEP_SQUELCH" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ FOOTSTEP_FLESH ][ rand( ) & 3 ] ); - } - break; - - case EV_FOOTSPLASH: - DEBUGNAME( "EV_FOOTSPLASH" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand( ) & 3 ] ); - } - break; - - case EV_FOOTWADE: - DEBUGNAME( "EV_FOOTWADE" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand( ) & 3 ] ); - } - break; - - case EV_SWIM: - DEBUGNAME( "EV_SWIM" ); - if( cg_footsteps.integer && ci->footsteps != FOOTSTEP_NONE ) - { - trap_S_StartSound( NULL, es->number, CHAN_BODY, - cgs.media.footsteps[ FOOTSTEP_SPLASH ][ rand( ) & 3 ] ); - } - break; - - - case EV_FALL_SHORT: - DEBUGNAME( "EV_FALL_SHORT" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.landSound ); - - if( clientNum == cg.predictedPlayerState.clientNum ) - { - // smooth landing z changes - cg.landChange = -8; - cg.landTime = cg.time; - } - break; - - case EV_FALL_MEDIUM: - DEBUGNAME( "EV_FALL_MEDIUM" ); - // use normal pain sound - trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); - - if( clientNum == cg.predictedPlayerState.clientNum ) - { - // smooth landing z changes - cg.landChange = -16; - cg.landTime = cg.time; - } - break; - - case EV_FALL_FAR: - DEBUGNAME( "EV_FALL_FAR" ); - trap_S_StartSound (NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*fall1.wav" ) ); - cent->pe.painTime = cg.time; // don't play a pain sound right after this - - if( clientNum == cg.predictedPlayerState.clientNum ) - { - // smooth landing z changes - cg.landChange = -24; - cg.landTime = cg.time; - } - break; - - case EV_FALLING: - DEBUGNAME( "EV_FALLING" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*falling1.wav" ) ); - break; - - case EV_STEP_4: - case EV_STEP_8: - case EV_STEP_12: - case EV_STEP_16: // smooth out step up transitions - case EV_STEPDN_4: - case EV_STEPDN_8: - case EV_STEPDN_12: - case EV_STEPDN_16: // smooth out step down transitions - DEBUGNAME( "EV_STEP" ); - { - float oldStep; - int delta; - int step; - - if( clientNum != cg.predictedPlayerState.clientNum ) - break; - - // if we are interpolating, we don't need to smooth steps - if( cg.demoPlayback || ( cg.snap->ps.pm_flags & PMF_FOLLOW ) || - cg_nopredict.integer || cg_synchronousClients.integer ) - break; - - // check for stepping up before a previous step is completed - delta = cg.time - cg.stepTime; - - if( delta < steptime ) - oldStep = cg.stepChange * ( steptime - delta ) / steptime; - else - oldStep = 0; - - // add this amount - if( event >= EV_STEPDN_4 ) - { - step = 4 * ( event - EV_STEPDN_4 + 1 ); - cg.stepChange = oldStep - step; - } - else - { - step = 4 * ( event - EV_STEP_4 + 1 ); - cg.stepChange = oldStep + step; - } - - if( cg.stepChange > MAX_STEP_CHANGE ) - cg.stepChange = MAX_STEP_CHANGE; - else if( cg.stepChange < -MAX_STEP_CHANGE ) - cg.stepChange = -MAX_STEP_CHANGE; - - cg.stepTime = cg.time; - break; - } - - case EV_JUMP: - DEBUGNAME( "EV_JUMP" ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*jump1.wav" ) ); - - if( BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_WALLJUMPER ) ) - { - vec3_t surfNormal, refNormal = { 0.0f, 0.0f, 1.0f }; - vec3_t rotAxis; - - if( clientNum != cg.predictedPlayerState.clientNum ) - break; - - //set surfNormal - VectorCopy( cg.predictedPlayerState.grapplePoint, surfNormal ); - - //if we are moving from one surface to another smooth the transition - if( !VectorCompare( surfNormal, cg.lastNormal ) && surfNormal[ 2 ] != 1.0f ) - { - CrossProduct( refNormal, surfNormal, rotAxis ); - VectorNormalize( rotAxis ); - - //add the op - CG_addSmoothOp( rotAxis, 15.0f, 1.0f ); - } - - //copy the current normal to the lastNormal - VectorCopy( surfNormal, cg.lastNormal ); - } - - break; - - case EV_LEV1_GRAB: - DEBUGNAME( "EV_LEV1_GRAB" ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab ); - break; - - case EV_LEV4_CHARGE_PREPARE: - DEBUGNAME( "EV_LEV4_CHARGE_PREPARE" ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare ); - break; - - case EV_LEV4_CHARGE_START: - DEBUGNAME( "EV_LEV4_CHARGE_START" ); - //FIXME: stop cgs.media.alienL4ChargePrepare playing here - trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart ); - break; - - case EV_TAUNT: - DEBUGNAME( "EV_TAUNT" ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) ); - break; - - case EV_WATER_TOUCH: - DEBUGNAME( "EV_WATER_TOUCH" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrInSound ); - break; - - case EV_WATER_LEAVE: - DEBUGNAME( "EV_WATER_LEAVE" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrOutSound ); - break; - - case EV_WATER_UNDER: - DEBUGNAME( "EV_WATER_UNDER" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); - break; - - case EV_WATER_CLEAR: - DEBUGNAME( "EV_WATER_CLEAR" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, CG_CustomSound( es->number, "*gasp.wav" ) ); - break; - - // - // weapon events - // - case EV_NOAMMO: - DEBUGNAME( "EV_NOAMMO" ); - { - } - break; - - case EV_CHANGE_WEAPON: - DEBUGNAME( "EV_CHANGE_WEAPON" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); - break; - - case EV_FIRE_WEAPON: - DEBUGNAME( "EV_FIRE_WEAPON" ); - CG_FireWeapon( cent, WPM_PRIMARY ); - break; - - case EV_FIRE_WEAPON2: - DEBUGNAME( "EV_FIRE_WEAPON2" ); - CG_FireWeapon( cent, WPM_SECONDARY ); - break; - - case EV_FIRE_WEAPON3: - DEBUGNAME( "EV_FIRE_WEAPON3" ); - CG_FireWeapon( cent, WPM_TERTIARY ); - break; - - //================================================================= - - // - // other events - // - case EV_PLAYER_TELEPORT_IN: - DEBUGNAME( "EV_PLAYER_TELEPORT_IN" ); - //deprecated - break; - - case EV_PLAYER_TELEPORT_OUT: - DEBUGNAME( "EV_PLAYER_TELEPORT_OUT" ); - CG_PlayerDisconnect( position ); - break; - - case EV_BUILD_CONSTRUCT: - DEBUGNAME( "EV_BUILD_CONSTRUCT" ); - //do something useful here - break; - - case EV_BUILD_DESTROY: - DEBUGNAME( "EV_BUILD_DESTROY" ); - //do something useful here - break; - - case EV_RPTUSE_SOUND: - DEBUGNAME( "EV_RPTUSE_SOUND" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.repeaterUseSound ); - break; - - case EV_GRENADE_BOUNCE: - DEBUGNAME( "EV_GRENADE_BOUNCE" ); - if( rand( ) & 1 ) - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hgrenb1aSound ); - else - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hgrenb2aSound ); - break; - - // - // missile impacts - // - case EV_MISSILE_HIT: - DEBUGNAME( "EV_MISSILE_HIT" ); - ByteToDir( es->eventParm, dir ); - CG_MissileHitPlayer( es->weapon, es->generic1, position, dir, es->otherEntityNum ); - break; - - case EV_MISSILE_MISS: - DEBUGNAME( "EV_MISSILE_MISS" ); - ByteToDir( es->eventParm, dir ); - CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_DEFAULT ); - break; - - case EV_MISSILE_MISS_METAL: - DEBUGNAME( "EV_MISSILE_MISS_METAL" ); - ByteToDir( es->eventParm, dir ); - CG_MissileHitWall( es->weapon, es->generic1, 0, position, dir, IMPACTSOUND_METAL ); - break; - - case EV_HUMAN_BUILDABLE_EXPLOSION: - DEBUGNAME( "EV_HUMAN_BUILDABLE_EXPLOSION" ); - ByteToDir( es->eventParm, dir ); - CG_HumanBuildableExplosion( position, dir ); - break; - - case EV_ALIEN_BUILDABLE_EXPLOSION: - DEBUGNAME( "EV_ALIEN_BUILDABLE_EXPLOSION" ); - ByteToDir( es->eventParm, dir ); - CG_AlienBuildableExplosion( position, dir ); - break; - - case EV_TESLATRAIL: - DEBUGNAME( "EV_TESLATRAIL" ); - cent->currentState.weapon = WP_TESLAGEN; - { - centity_t *source = &cg_entities[ es->generic1 ]; - centity_t *target = &cg_entities[ es->clientNum ]; - vec3_t sourceOffset = { 0.0f, 0.0f, 28.0f }; - - if( !CG_IsTrailSystemValid( &source->muzzleTS ) ) - { - source->muzzleTS = CG_SpawnNewTrailSystem( cgs.media.teslaZapTS ); - - if( CG_IsTrailSystemValid( &source->muzzleTS ) ) - { - CG_SetAttachmentCent( &source->muzzleTS->frontAttachment, source ); - CG_SetAttachmentCent( &source->muzzleTS->backAttachment, target ); - CG_AttachToCent( &source->muzzleTS->frontAttachment ); - CG_AttachToCent( &source->muzzleTS->backAttachment ); - CG_SetAttachmentOffset( &source->muzzleTS->frontAttachment, sourceOffset ); - - source->muzzleTSDeathTime = cg.time + cg_teslaTrailTime.integer; - } - } - } - break; - - case EV_BULLET_HIT_WALL: - DEBUGNAME( "EV_BULLET_HIT_WALL" ); - ByteToDir( es->eventParm, dir ); - CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD ); - break; - - case EV_BULLET_HIT_FLESH: - DEBUGNAME( "EV_BULLET_HIT_FLESH" ); - CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm ); - break; - - case EV_SHOTGUN: - DEBUGNAME( "EV_SHOTGUN" ); - CG_ShotgunFire( es ); - break; - - case EV_GENERAL_SOUND: - DEBUGNAME( "EV_GENERAL_SOUND" ); - if( cgs.gameSounds[ es->eventParm ] ) - trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.gameSounds[ es->eventParm ] ); - else - { - s = CG_ConfigString( CS_SOUNDS + es->eventParm ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, s ) ); - } - break; - - case EV_GLOBAL_SOUND: // play from the player's head so it never diminishes - DEBUGNAME( "EV_GLOBAL_SOUND" ); - if( cgs.gameSounds[ es->eventParm ] ) - trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.gameSounds[ es->eventParm ] ); - else - { - s = CG_ConfigString( CS_SOUNDS + es->eventParm ); - trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, CG_CustomSound( es->number, s ) ); - } - break; - - case EV_PAIN: - // local player sounds are triggered in CG_CheckLocalSounds, - // so ignore events on the player - DEBUGNAME( "EV_PAIN" ); - if( cent->currentState.number != cg.snap->ps.clientNum ) - CG_PainEvent( cent, es->eventParm ); - break; - - case EV_DEATH1: - case EV_DEATH2: - case EV_DEATH3: - DEBUGNAME( "EV_DEATHx" ); - trap_S_StartSound( NULL, es->number, CHAN_VOICE, - CG_CustomSound( es->number, va( "*death%i.wav", event - EV_DEATH1 + 1 ) ) ); - break; - - case EV_OBITUARY: - DEBUGNAME( "EV_OBITUARY" ); - CG_Obituary( es ); - break; - - case EV_GIB_PLAYER: - DEBUGNAME( "EV_GIB_PLAYER" ); - // no gibbing - break; - - case EV_STOPLOOPINGSOUND: - DEBUGNAME( "EV_STOPLOOPINGSOUND" ); - trap_S_StopLoopingSound( es->number ); - es->loopSound = 0; - break; - - case EV_DEBUG_LINE: - DEBUGNAME( "EV_DEBUG_LINE" ); - CG_Beam( cent ); - break; - - case EV_BUILD_DELAY: - DEBUGNAME( "EV_BUILD_DELAY" ); - if( clientNum == cg.predictedPlayerState.clientNum ) - { - trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); - cg.lastBuildAttempt = cg.time; - } - break; - - case EV_BUILD_REPAIR: - DEBUGNAME( "EV_BUILD_REPAIR" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairSound ); - break; - - case EV_BUILD_REPAIRED: - DEBUGNAME( "EV_BUILD_REPAIRED" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.buildableRepairedSound ); - break; - - case EV_OVERMIND_ATTACK: - DEBUGNAME( "EV_OVERMIND_ATTACK" ); - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS ) - { - trap_S_StartLocalSound( cgs.media.alienOvermindAttack, CHAN_ANNOUNCER ); - CG_CenterPrint( "The Overmind is under attack!", 200, GIANTCHAR_WIDTH * 4 ); - } - break; - - case EV_OVERMIND_DYING: - DEBUGNAME( "EV_OVERMIND_DYING" ); - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS ) - { - trap_S_StartLocalSound( cgs.media.alienOvermindDying, CHAN_ANNOUNCER ); - CG_CenterPrint( "The Overmind is dying!", 200, GIANTCHAR_WIDTH * 4 ); - } - break; - - case EV_DCC_ATTACK: - DEBUGNAME( "EV_DCC_ATTACK" ); - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS ) - { - //trap_S_StartLocalSound( cgs.media.humanDCCAttack, CHAN_ANNOUNCER ); - CG_CenterPrint( "Our base is under attack!", 200, GIANTCHAR_WIDTH * 4 ); - } - break; - - case EV_OVERMIND_SPAWNS: - DEBUGNAME( "EV_OVERMIND_SPAWNS" ); - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS ) - { - trap_S_StartLocalSound( cgs.media.alienOvermindSpawns, CHAN_ANNOUNCER ); - CG_CenterPrint( "The Overmind needs spawns!", 200, GIANTCHAR_WIDTH * 4 ); - } - break; - - case EV_ALIEN_EVOLVE: - DEBUGNAME( "EV_ALIEN_EVOLVE" ); - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienEvolveSound ); - { - particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienEvolvePS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentCent( &ps->attachment, cent ); - CG_AttachToCent( &ps->attachment ); - } - } - - if( es->number == cg.clientNum ) - { - CG_ResetPainBlend( ); - cg.spawnTime = cg.time; - } - break; - - case EV_ALIEN_EVOLVE_FAILED: - DEBUGNAME( "EV_ALIEN_EVOLVE_FAILED" ); - if( clientNum == cg.predictedPlayerState.clientNum ) - { - //FIXME: change to "negative" sound - trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND ); - cg.lastEvolveAttempt = cg.time; - } - break; - - case EV_ALIEN_ACIDTUBE: - DEBUGNAME( "EV_ALIEN_ACIDTUBE" ); - { - particleSystem_t *ps = CG_SpawnNewParticleSystem( cgs.media.alienAcidTubePS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentCent( &ps->attachment, cent ); - ByteToDir( es->eventParm, dir ); - CG_SetParticleSystemNormal( ps, dir ); - CG_AttachToCent( &ps->attachment ); - } - } - break; - - case EV_MEDKIT_USED: - DEBUGNAME( "EV_MEDKIT_USED" ); - trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.medkitUseSound ); - break; - - case EV_PLAYER_RESPAWN: - DEBUGNAME( "EV_PLAYER_RESPAWN" ); - if( es->number == cg.clientNum ) - cg.spawnTime = cg.time; - break; - - default: - DEBUGNAME( "UNKNOWN" ); - CG_Error( "Unknown event: %i", event ); - break; - } -} - - -/* -============== -CG_CheckEvents - -============== -*/ -void CG_CheckEvents( centity_t *cent ) -{ - entity_event_t event; - entity_event_t oldEvent = EV_NONE; - - // check for event-only entities - if( cent->currentState.eType > ET_EVENTS ) - { - event = cent->currentState.eType - ET_EVENTS; - - if( cent->previousEvent ) - return; // already fired - - cent->previousEvent = 1; - - cent->currentState.event = cent->currentState.eType - ET_EVENTS; - - // Move the pointer to the entity that the - // event was originally attached to - if( cent->currentState.eFlags & EF_PLAYER_EVENT ) - { - cent = &cg_entities[ cent->currentState.otherEntityNum ]; - oldEvent = cent->currentState.event; - cent->currentState.event = event; - } - } - else - { - // check for events riding with another entity - if( cent->currentState.event == cent->previousEvent ) - return; - - cent->previousEvent = cent->currentState.event; - if( ( cent->currentState.event & ~EV_EVENT_BITS ) == 0 ) - return; - } - - // calculate the position at exactly the frame time - BG_EvaluateTrajectory( ¢->currentState.pos, cg.snap->serverTime, cent->lerpOrigin ); - CG_SetEntitySoundPosition( cent ); - - CG_EntityEvent( cent, cent->lerpOrigin ); - - // If this was a reattached spilled event, restore the original event - if( oldEvent != EV_NONE ) - cent->currentState.event = oldEvent; -} - diff --git a/mod/src/cgame/cg_local.h b/mod/src/cgame/cg_local.h deleted file mode 100644 index 88df61ba..00000000 --- a/mod/src/cgame/cg_local.h +++ /dev/null @@ -1,2003 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// - -/* - * 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 "../game/q_shared.h" -#include "tr_types.h" -#include "../game/bg_public.h" -#include "cg_public.h" -#include "../ui/ui_shared.h" - -// The entire cgame module is unloaded and reloaded on each level change, -// so there is NO persistant data between levels on the client side. -// If you absolutely need something stored, it can either be kept -// by the server in the server stored userinfos, or stashed in a cvar. - -#define CG_FONT_THRESHOLD 0.1 - -#define POWERUP_BLINKS 5 - -#define POWERUP_BLINK_TIME 1000 -#define FADE_TIME 200 -#define PULSE_TIME 200 -#define DAMAGE_DEFLECT_TIME 100 -#define DAMAGE_RETURN_TIME 400 -#define DAMAGE_TIME 500 -#define LAND_DEFLECT_TIME 150 -#define LAND_RETURN_TIME 300 -#define DUCK_TIME 100 -#define PAIN_TWITCH_TIME 200 -#define WEAPON_SELECT_TIME 1400 -#define ITEM_SCALEUP_TIME 1000 -#define ZOOM_TIME 150 -#define ITEM_BLOB_TIME 200 -#define MUZZLE_FLASH_TIME 20 -#define SINK_TIME 1000 // time for fragments to sink into ground before going away -#define ATTACKER_HEAD_TIME 10000 -#define REWARD_TIME 3000 - -#define PULSE_SCALE 1.5 // amount to scale up the icons when activating - -#define MAX_STEP_CHANGE 32 - -#define MAX_VERTS_ON_POLY 10 -#define MAX_MARK_POLYS 256 - -#define STAT_MINUS 10 // num frame for '-' stats digit - -#define ICON_SIZE 48 -#define CHAR_WIDTH 32 -#define CHAR_HEIGHT 48 -#define TEXT_ICON_SPACE 4 - -#define TEAMCHAT_WIDTH 80 -#define TEAMCHAT_HEIGHT 8 - -// very large characters -#define GIANT_WIDTH 32 -#define GIANT_HEIGHT 48 - -#define NUM_CROSSHAIRS 10 - -#define TEAM_OVERLAY_MAXNAME_WIDTH 12 -#define TEAM_OVERLAY_MAXLOCATION_WIDTH 16 - -#define DEFAULT_MODEL "sarge" -#define DEFAULT_TEAM_MODEL "sarge" -#define DEFAULT_TEAM_HEAD "sarge" - -#define DEFAULT_REDTEAM_NAME "Stroggs" -#define DEFAULT_BLUETEAM_NAME "Pagans" - -typedef enum -{ - FOOTSTEP_NORMAL, - FOOTSTEP_BOOT, - FOOTSTEP_FLESH, - FOOTSTEP_MECH, - FOOTSTEP_ENERGY, - FOOTSTEP_METAL, - FOOTSTEP_SPLASH, - FOOTSTEP_CUSTOM, - FOOTSTEP_NONE, - - FOOTSTEP_TOTAL -} footstep_t; - -typedef enum -{ - IMPACTSOUND_DEFAULT, - IMPACTSOUND_METAL, - IMPACTSOUND_FLESH -} impactSound_t; - -typedef enum -{ - JPS_OFF, - JPS_DESCENDING, - JPS_HOVERING, - JPS_ASCENDING -} jetPackState_t; - -//====================================================================== - -// when changing animation, set animationTime to frameTime + lerping time -// The current lerp will finish out, then it will lerp to the new animation -typedef struct -{ - int oldFrame; - int oldFrameTime; // time when ->oldFrame was exactly on - - int frame; - int frameTime; // time when ->frame will be exactly on - - float backlerp; - - float yawAngle; - qboolean yawing; - float pitchAngle; - qboolean pitching; - - int animationNumber; // may include ANIM_TOGGLEBIT - animation_t *animation; - int animationTime; // time when the first frame of the animation will be exact -} lerpFrame_t; - -//====================================================================== - -//attachment system -typedef enum -{ - AT_STATIC, - AT_TAG, - AT_CENT, - AT_PARTICLE -} attachmentType_t; - -//forward declaration for particle_t -struct particle_s; - -typedef struct attachment_s -{ - attachmentType_t type; - qboolean attached; - - qboolean staticValid; - qboolean tagValid; - qboolean centValid; - qboolean particleValid; - - qboolean hasOffset; - vec3_t offset; - - vec3_t lastValidAttachmentPoint; - - //AT_STATIC - vec3_t origin; - - //AT_TAG - refEntity_t re; //FIXME: should be pointers? - refEntity_t parent; // - qhandle_t model; - char tagName[ MAX_STRING_CHARS ]; - - //AT_CENT - int centNum; - - //AT_PARTICLE - struct particle_s *particle; -} attachment_t; - -//====================================================================== - -//particle system stuff -#define MAX_PS_SHADER_FRAMES 32 -#define MAX_PS_MODELS 8 -#define MAX_EJECTORS_PER_SYSTEM 4 -#define MAX_PARTICLES_PER_EJECTOR 4 - -#define MAX_BASEPARTICLE_SYSTEMS 192 -#define MAX_BASEPARTICLE_EJECTORS MAX_BASEPARTICLE_SYSTEMS*MAX_EJECTORS_PER_SYSTEM -#define MAX_BASEPARTICLES MAX_BASEPARTICLE_EJECTORS*MAX_PARTICLES_PER_EJECTOR - -#define MAX_PARTICLE_SYSTEMS 48 -#define MAX_PARTICLE_EJECTORS MAX_PARTICLE_SYSTEMS*MAX_EJECTORS_PER_SYSTEM -#define MAX_PARTICLES MAX_PARTICLE_EJECTORS*5 - -#define PARTICLES_INFINITE -1 -#define PARTICLES_SAME_AS_INITIAL -2 - -//COMPILE TIME STRUCTURES -typedef enum -{ - PMT_STATIC, - PMT_STATIC_TRANSFORM, - PMT_TAG, - PMT_CENT_ANGLES, - PMT_NORMAL -} pMoveType_t; - -typedef enum -{ - PMD_LINEAR, - PMD_POINT -} pDirType_t; - -typedef struct pMoveValues_u -{ - pDirType_t dirType; - - //PMD_LINEAR - vec3_t dir; - float dirRandAngle; - - //PMD_POINT - vec3_t point; - float pointRandAngle; - - float mag; - float magRandFrac; - - float parentVelFrac; - float parentVelFracRandFrac; -} pMoveValues_t; - -typedef struct pLerpValues_s -{ - int delay; - float delayRandFrac; - - float initial; - float initialRandFrac; - - float final; - float finalRandFrac; - - float randFrac; -} pLerpValues_t; - -//particle template -typedef struct baseParticle_s -{ - vec3_t displacement; - float randDisplacement; - float normalDisplacement; - - pMoveType_t velMoveType; - pMoveValues_t velMoveValues; - - pMoveType_t accMoveType; - pMoveValues_t accMoveValues; - - int lifeTime; - float lifeTimeRandFrac; - - float bounceFrac; - float bounceFracRandFrac; - qboolean bounceCull; - - char bounceMarkName[ MAX_QPATH ]; - qhandle_t bounceMark; - float bounceMarkRadius; - float bounceMarkRadiusRandFrac; - float bounceMarkCount; - float bounceMarkCountRandFrac; - - char bounceSoundName[ MAX_QPATH ]; - qhandle_t bounceSound; - float bounceSoundCount; - float bounceSoundCountRandFrac; - - pLerpValues_t radius; - pLerpValues_t alpha; - pLerpValues_t rotation; - - qboolean dynamicLight; - pLerpValues_t dLightRadius; - byte dLightColor[ 3 ]; - - int colorDelay; - float colorDelayRandFrac; - byte initialColor[ 3 ]; - byte finalColor[ 3 ]; - - char childSystemName[ MAX_QPATH ]; - qhandle_t childSystemHandle; - - char onDeathSystemName[ MAX_QPATH ]; - qhandle_t onDeathSystemHandle; - - char childTrailSystemName[ MAX_QPATH ]; - qhandle_t childTrailSystemHandle; - - //particle invariant stuff - char shaderNames[ MAX_PS_SHADER_FRAMES ][ MAX_QPATH ]; - qhandle_t shaders[ MAX_PS_SHADER_FRAMES ]; - int numFrames; - float framerate; - - char modelNames[ MAX_PS_MODELS ][ MAX_QPATH ]; - qhandle_t models[ MAX_PS_MODELS ]; - int numModels; - animation_t modelAnimation; - - qboolean overdrawProtection; - qboolean realLight; - qboolean cullOnStartSolid; -} baseParticle_t; - - -//ejector template -typedef struct baseParticleEjector_s -{ - baseParticle_t *particles[ MAX_PARTICLES_PER_EJECTOR ]; - int numParticles; - - pLerpValues_t eject; //zero period indicates creation of all particles at once - - int totalParticles; //can be infinite - float totalParticlesRandFrac; -} baseParticleEjector_t; - - -//particle system template -typedef struct baseParticleSystem_s -{ - char name[ MAX_QPATH ]; - baseParticleEjector_t *ejectors[ MAX_EJECTORS_PER_SYSTEM ]; - int numEjectors; - - qboolean thirdPersonOnly; - qboolean registered; //whether or not the assets for this particle have been loaded -} baseParticleSystem_t; - - -//RUN TIME STRUCTURES -typedef struct particleSystem_s -{ - baseParticleSystem_t *class; - - attachment_t attachment; - - qboolean valid; - qboolean lazyRemove; //mark this system for later removal - - //for PMT_NORMAL - qboolean normalValid; - vec3_t normal; -} particleSystem_t; - - -typedef struct particleEjector_s -{ - baseParticleEjector_t *class; - particleSystem_t *parent; - - pLerpValues_t ejectPeriod; - - int count; - int totalParticles; - - int nextEjectionTime; - - qboolean valid; -} particleEjector_t; - - -//used for actual particle evaluation -typedef struct particle_s -{ - baseParticle_t *class; - particleEjector_t *parent; - - int birthTime; - int lifeTime; - - float bounceMarkRadius; - int bounceMarkCount; - int bounceSoundCount; - qboolean atRest; - - vec3_t origin; - vec3_t velocity; - - pMoveType_t accMoveType; - pMoveValues_t accMoveValues; - - int lastEvalTime; - - int nextChildTime; - - pLerpValues_t radius; - pLerpValues_t alpha; - pLerpValues_t rotation; - - pLerpValues_t dLightRadius; - - int colorDelay; - - qhandle_t model; - lerpFrame_t lf; - vec3_t lastAxis[ 3 ]; - - qboolean valid; - int frameWhenInvalidated; - - int sortKey; -} particle_t; - -//====================================================================== - -//trail system stuff -#define MAX_BEAMS_PER_SYSTEM 4 - -#define MAX_BASETRAIL_SYSTEMS 64 -#define MAX_BASETRAIL_BEAMS MAX_BASETRAIL_SYSTEMS*MAX_BEAMS_PER_SYSTEM - -#define MAX_TRAIL_SYSTEMS 32 -#define MAX_TRAIL_BEAMS MAX_TRAIL_SYSTEMS*MAX_BEAMS_PER_SYSTEM -#define MAX_TRAIL_BEAM_NODES 128 - -#define MAX_TRAIL_BEAM_JITTERS 4 - -typedef enum -{ - TBTT_STRETCH, - TBTT_REPEAT -} trailBeamTextureType_t; - -typedef struct baseTrailJitter_s -{ - float magnitude; - int period; -} baseTrailJitter_t; - -//beam template -typedef struct baseTrailBeam_s -{ - int numSegments; - float frontWidth; - float backWidth; - float frontAlpha; - float backAlpha; - byte frontColor[ 3 ]; - byte backColor[ 3 ]; - - // the time it takes for a segment to vanish (single attached only) - int segmentTime; - - // the time it takes for a beam to fade out (double attached only) - int fadeOutTime; - - char shaderName[ MAX_QPATH ]; - qhandle_t shader; - - trailBeamTextureType_t textureType; - - //TBTT_STRETCH - float frontTextureCoord; - float backTextureCoord; - - //TBTT_REPEAT - float repeatLength; - qboolean clampToBack; - - qboolean realLight; - - int numJitters; - baseTrailJitter_t jitters[ MAX_TRAIL_BEAM_JITTERS ]; - qboolean jitterAttachments; -} baseTrailBeam_t; - - -//trail system template -typedef struct baseTrailSystem_s -{ - char name[ MAX_QPATH ]; - baseTrailBeam_t *beams[ MAX_BEAMS_PER_SYSTEM ]; - int numBeams; - - qboolean thirdPersonOnly; - qboolean registered; //whether or not the assets for this trail have been loaded -} baseTrailSystem_t; - -typedef struct trailSystem_s -{ - baseTrailSystem_t *class; - - attachment_t frontAttachment; - attachment_t backAttachment; - - int destroyTime; - qboolean valid; -} trailSystem_t; - -typedef struct trailBeamNode_s -{ - vec3_t refPosition; - vec3_t position; - - int timeLeft; - - float textureCoord; - float halfWidth; - byte alpha; - byte color[ 3 ]; - - vec2_t jitters[ MAX_TRAIL_BEAM_JITTERS ]; - - struct trailBeamNode_s *prev; - struct trailBeamNode_s *next; - - qboolean used; -} trailBeamNode_t; - -typedef struct trailBeam_s -{ - baseTrailBeam_t *class; - trailSystem_t *parent; - - trailBeamNode_t nodePool[ MAX_TRAIL_BEAM_NODES ]; - trailBeamNode_t *nodes; - - int lastEvalTime; - - qboolean valid; - - int nextJitterTimes[ MAX_TRAIL_BEAM_JITTERS ]; -} trailBeam_t; - -//====================================================================== - -// player entities need to track more information -// than any other type of entity. - -// note that not every player entity is a client entity, -// because corpses after respawn are outside the normal -// client numbering range - -//TA: smoothing of view and model for WW transitions -#define MAXSMOOTHS 32 - -typedef struct -{ - float time; - float timeMod; - - vec3_t rotAxis; - float rotAngle; -} smooth_t; - - -typedef struct -{ - lerpFrame_t legs, torso, flag, nonseg; - int painTime; - int painDirection; // flip from 0 to 1 - - // machinegun spinning - float barrelAngle; - int barrelTime; - qboolean barrelSpinning; - - vec3_t lastNormal; - vec3_t lastAxis[ 3 ]; - smooth_t sList[ MAXSMOOTHS ]; -} playerEntity_t; - -typedef struct lightFlareStatus_s -{ - float lastSrcRadius; //caching of likely flare source radius - float lastRadius; //caching of likely flare radius - float lastRatio; //caching of likely flare ratio - int lastTime; //last time flare was visible/occluded - qboolean status; //flare is visble? -} lightFlareStatus_t; - -//================================================= - -// centity_t have a direct corespondence with gentity_t in the game, but -// only the entityState_t is directly communicated to the cgame -typedef struct centity_s -{ - entityState_t currentState; // from cg.frame - entityState_t nextState; // from cg.nextFrame, if available - qboolean interpolate; // true if next is valid to interpolate to - qboolean currentValid; // true if cg.frame holds this entity - - int muzzleFlashTime; // move to playerEntity? - int muzzleFlashTime2; // move to playerEntity? - int muzzleFlashTime3; // move to playerEntity? - int previousEvent; - int teleportFlag; - - int trailTime; // so missile trails can handle dropped initial packets - int dustTrailTime; - int miscTime; - int snapShotTime; // last time this entity was found in a snapshot - - playerEntity_t pe; - - int errorTime; // decay the error from this time - vec3_t errorOrigin; - vec3_t errorAngles; - - qboolean extrapolated; // false if origin / angles is an interpolation - vec3_t rawOrigin; - vec3_t rawAngles; - - vec3_t beamEnd; - - // exact interpolated position of entity on this frame - vec3_t lerpOrigin; - vec3_t lerpAngles; - - lerpFrame_t lerpFrame; - - //TA: - buildableAnimNumber_t buildableAnim; //persistant anim number - buildableAnimNumber_t oldBuildableAnim; //to detect when new anims are set - particleSystem_t *buildablePS; - float lastBuildableHealthScale; - int lastBuildableDamageSoundTime; - - lightFlareStatus_t lfs; - - qboolean doorState; - - particleSystem_t *muzzlePS; - qboolean muzzlePsTrigger; - - particleSystem_t *jetPackPS; - jetPackState_t jetPackState; - - particleSystem_t *entityPS; - qboolean entityPSMissing; - - trailSystem_t *level2ZapTS[ 3 ]; - - trailSystem_t *muzzleTS; //used for the tesla and reactor - int muzzleTSDeathTime; - - qboolean valid; - qboolean oldValid; -} centity_t; - - -//====================================================================== - -typedef struct markPoly_s -{ - struct markPoly_s *prevMark, *nextMark; - int time; - qhandle_t markShader; - qboolean alphaFade; // fade alpha instead of rgb - float color[ 4 ]; - poly_t poly; - polyVert_t verts[ MAX_VERTS_ON_POLY ]; -} markPoly_t; - -//====================================================================== - - -typedef struct -{ - int client; - int score; - int ping; - int time; - int team; - weapon_t weapon; - upgrade_t upgrade; -} score_t; - -// each client has an associated clientInfo_t -// that contains media references necessary to present the -// client model and other color coded effects -// this is regenerated each time a client's configstring changes, -// usually as a result of a userinfo (name, model, etc) change -#define MAX_CUSTOM_SOUNDS 32 -typedef struct -{ - qboolean infoValid; - - char name[ MAX_QPATH ]; - pTeam_t team; - - int botSkill; // 0 = not bot, 1-5 = bot - - vec3_t color1; - vec3_t color2; - - int score; // updated by score servercmds - int location; // location index for team mode - int health; // you only get this info about your teammates - int armor; - int curWeapon; - - int handicap; - int wins, losses; // in tourney mode - - int teamTask; // task in teamplay (offence/defence) - qboolean teamLeader; // true when this is a team leader - - int powerups; // so can display quad/flag status - - int medkitUsageTime; - int invulnerabilityStartTime; - int invulnerabilityStopTime; - - int breathPuffTime; - - // when clientinfo is changed, the loading of models/skins/sounds - // can be deferred until you are dead, to prevent hitches in - // gameplay - char modelName[ MAX_QPATH ]; - char skinName[ MAX_QPATH ]; - char headModelName[ MAX_QPATH ]; - char headSkinName[ MAX_QPATH ]; - char redTeam[ MAX_TEAMNAME ]; - char blueTeam[ MAX_TEAMNAME ]; - - qboolean newAnims; // true if using the new mission pack animations - qboolean fixedlegs; // true if legs yaw is always the same as torso yaw - qboolean fixedtorso; // true if torso never changes yaw - qboolean nonsegmented; // true if model is Q2 style nonsegmented - - vec3_t headOffset; // move head in icon views - footstep_t footsteps; - gender_t gender; // from model - - qhandle_t legsModel; - qhandle_t legsSkin; - - qhandle_t torsoModel; - qhandle_t torsoSkin; - - qhandle_t headModel; - qhandle_t headSkin; - - qhandle_t nonSegModel; //non-segmented model system - qhandle_t nonSegSkin; //non-segmented model system - - qhandle_t modelIcon; - - animation_t animations[ MAX_PLAYER_TOTALANIMATIONS ]; - - sfxHandle_t sounds[ MAX_CUSTOM_SOUNDS ]; - - sfxHandle_t customFootsteps[ 4 ]; - sfxHandle_t customMetalFootsteps[ 4 ]; -} clientInfo_t; - - -typedef struct weaponInfoMode_s -{ - float flashDlight; - vec3_t flashDlightColor; - sfxHandle_t flashSound[ 4 ]; // fast firing weapons randomly choose - qboolean continuousFlash; - - qhandle_t missileModel; - sfxHandle_t missileSound; - float missileDlight; - vec3_t missileDlightColor; - int missileRenderfx; - qboolean usesSpriteMissle; - qhandle_t missileSprite; - int missileSpriteSize; - qhandle_t missileParticleSystem; - qhandle_t missileTrailSystem; - qboolean missileRotates; - qboolean missileAnimates; - int missileAnimStartFrame; - int missileAnimNumFrames; - int missileAnimFrameRate; - int missileAnimLooping; - - sfxHandle_t firingSound; - qboolean loopFireSound; - - qhandle_t muzzleParticleSystem; - - qboolean alwaysImpact; - qhandle_t impactParticleSystem; - qhandle_t impactMark; - qhandle_t impactMarkSize; - sfxHandle_t impactSound[ 4 ]; //random impact sound - sfxHandle_t impactFleshSound[ 4 ]; //random impact sound -} weaponInfoMode_t; - -// each WP_* weapon enum has an associated weaponInfo_t -// that contains media references necessary to present the -// weapon and its effects -typedef struct weaponInfo_s -{ - qboolean registered; - char *humanName; - - qhandle_t handsModel; // the hands don't actually draw, they just position the weapon - qhandle_t weaponModel; - qhandle_t barrelModel; - qhandle_t flashModel; - - vec3_t weaponMidpoint; // so it will rotate centered instead of by tag - - qhandle_t weaponIcon; - qhandle_t ammoIcon; - - qhandle_t crossHair; - int crossHairSize; - - sfxHandle_t readySound; - - qboolean disableIn3rdPerson; - - weaponInfoMode_t wim[ WPM_NUM_WEAPONMODES ]; -} weaponInfo_t; - -typedef struct upgradeInfo_s -{ - qboolean registered; - char *humanName; - - qhandle_t upgradeIcon; -} upgradeInfo_t; - -typedef struct -{ - qboolean looped; - qboolean enabled; - - sfxHandle_t sound; -} sound_t; - -typedef struct -{ - qhandle_t models[ MAX_BUILDABLE_MODELS ]; - animation_t animations[ MAX_BUILDABLE_ANIMATIONS ]; - - //same number of sounds as animations - sound_t sounds[ MAX_BUILDABLE_ANIMATIONS ]; -} buildableInfo_t; - -#define MAX_REWARDSTACK 10 -#define MAX_SOUNDBUFFER 20 - -//====================================================================== - -//TA: -typedef struct -{ - vec3_t alienBuildablePos[ MAX_GENTITIES ]; - int alienBuildableTimes[ MAX_GENTITIES ]; - int numAlienBuildables; - - vec3_t humanBuildablePos[ MAX_GENTITIES ]; - int numHumanBuildables; - - vec3_t alienClientPos[ MAX_CLIENTS ]; - int numAlienClients; - - vec3_t humanClientPos[ MAX_CLIENTS ]; - int numHumanClients; - - int lastUpdateTime; - vec3_t origin; - vec3_t vangles; -} entityPos_t; - -typedef struct -{ - int time; - int length; -} consoleLine_t; - -#define MAX_CONSOLE_TEXT 8192 -#define MAX_CONSOLE_LINES 32 - -// all cg.stepTime, cg.duckTime, cg.landTime, etc are set to cg.time when the action -// occurs, and they will have visible effects for #define STEP_TIME or whatever msec after - -#define MAX_PREDICTED_EVENTS 16 - -typedef struct -{ - int clientFrame; // incremented each frame - - int clientNum; - - qboolean demoPlayback; - qboolean levelShot; // taking a level menu screenshot - int deferredPlayerLoading; - qboolean loading; // don't defer players at initial startup - qboolean intermissionStarted; // don't play voice rewards, because game will end shortly - - // there are only one or two snapshot_t that are relevent at a time - int latestSnapshotNum; // the number of snapshots the client system has received - int latestSnapshotTime; // the time from latestSnapshotNum, so we don't need to read the snapshot yet - - snapshot_t *snap; // cg.snap->serverTime <= cg.time - snapshot_t *nextSnap; // cg.nextSnap->serverTime > cg.time, or NULL - snapshot_t activeSnapshots[ 2 ]; - - float frameInterpolation; // (float)( cg.time - cg.frame->serverTime ) / - // (cg.nextFrame->serverTime - cg.frame->serverTime) - - qboolean thisFrameTeleport; - qboolean nextFrameTeleport; - - int frametime; // cg.time - cg.oldTime - - int time; // this is the time value that the client - // is rendering at. - int oldTime; // time at last frame, used for missile trails and prediction checking - - int physicsTime; // either cg.snap->time or cg.nextSnap->time - - int timelimitWarnings; // 5 min, 1 min, overtime - int fraglimitWarnings; - - qboolean mapRestart; // set on a map restart to set back the weapon - - qboolean renderingThirdPerson; // during deaths, chasecams, etc - - // prediction state - qboolean hyperspace; // true if prediction has hit a trigger_teleport - playerState_t predictedPlayerState; - centity_t predictedPlayerEntity; - qboolean validPPS; // clear until the first call to CG_PredictPlayerState - int predictedErrorTime; - vec3_t predictedError; - - int eventSequence; - int predictableEvents[MAX_PREDICTED_EVENTS]; - - float stepChange; // for stair up smoothing - int stepTime; - - float duckChange; // for duck viewheight smoothing - int duckTime; - - float landChange; // for landing hard - int landTime; - - // input state sent to server - int weaponSelect; - - // auto rotating items - vec3_t autoAngles; - vec3_t autoAxis[ 3 ]; - vec3_t autoAnglesFast; - vec3_t autoAxisFast[ 3 ]; - - // view rendering - refdef_t refdef; - vec3_t refdefViewAngles; // will be converted to refdef.viewaxis - - // zoom key - qboolean zoomed; - int zoomTime; - float zoomSensitivity; - - // information screen text during loading - char infoScreenText[ MAX_STRING_CHARS ]; - - // scoreboard - int scoresRequestTime; - int numScores; - int selectedScore; - int teamScores[ 2 ]; - score_t scores[MAX_CLIENTS]; - qboolean showScores; - qboolean scoreBoardShowing; - int scoreFadeTime; - char killerName[ MAX_NAME_LENGTH ]; - char spectatorList[ MAX_STRING_CHARS ]; // list of names - int spectatorLen; // length of list - float spectatorWidth; // width in device units - int spectatorTime; // next time to offset - int spectatorPaintX; // current paint x - int spectatorPaintX2; // current paint x - int spectatorOffset; // current offset from start - int spectatorPaintLen; // current offset from start - - // centerprinting - int centerPrintTime; - int centerPrintCharWidth; - int centerPrintY; - char centerPrint[ 1024 ]; - int centerPrintLines; - - // low ammo warning state - int lowAmmoWarning; // 1 = low, 2 = empty - - // kill timers for carnage reward - int lastKillTime; - - // crosshair client ID - int crosshairClientNum; - int crosshairClientTime; - - // powerup active flashing - int powerupActive; - int powerupTime; - - // attacking player - int attackerTime; - int voiceTime; - - // reward medals - int rewardStack; - int rewardTime; - int rewardCount[ MAX_REWARDSTACK ]; - qhandle_t rewardShader[ MAX_REWARDSTACK ]; - qhandle_t rewardSound[ MAX_REWARDSTACK ]; - - // sound buffer mainly for announcer sounds - int soundBufferIn; - int soundBufferOut; - int soundTime; - qhandle_t soundBuffer[ MAX_SOUNDBUFFER ]; - - // for voice chat buffer - int voiceChatTime; - int voiceChatBufferIn; - int voiceChatBufferOut; - - // warmup countdown - int warmup; - int warmupCount; - - //========================== - - int itemPickup; - int itemPickupTime; - int itemPickupBlendTime; // the pulse around the crosshair is timed seperately - - int weaponSelectTime; - int weaponAnimation; - int weaponAnimationTime; - - // blend blobs - float damageTime; - float damageX, damageY, damageValue; - - // status bar head - float headYaw; - float headEndPitch; - float headEndYaw; - int headEndTime; - float headStartPitch; - float headStartYaw; - int headStartTime; - - // view movement - float v_dmg_time; - float v_dmg_pitch; - float v_dmg_roll; - - vec3_t kick_angles; // weapon kicks - vec3_t kick_origin; - - // temp working variables for player view - float bobfracsin; - int bobcycle; - float xyspeed; - int nextOrbitTime; - - // development tool - refEntity_t testModelEntity; - refEntity_t testModelBarrelEntity; - char testModelName[MAX_QPATH]; - char testModelBarrelName[MAX_QPATH]; - qboolean testGun; - - int spawnTime; //TA: fovwarp - int weapon1Time; //TA: time when BUTTON_ATTACK went t->f f->t - int weapon2Time; //TA: time when BUTTON_ATTACK2 went t->f f->t - int weapon3Time; //TA: time when BUTTON_USE_HOLDABLE went t->f f->t - qboolean weapon1Firing; - qboolean weapon2Firing; - qboolean weapon3Firing; - - int poisonedTime; - - vec3_t lastNormal; //TA: view smoothage - vec3_t lastVangles; //TA: view smoothage - smooth_t sList[ MAXSMOOTHS ]; //TA: WW smoothing - - int forwardMoveTime; //TA: for struggling - int rightMoveTime; - int upMoveTime; - - float charModelFraction; //TA: loading percentages - float mediaFraction; - float buildablesFraction; - - int lastBuildAttempt; - int lastEvolveAttempt; - - char consoleText[ MAX_CONSOLE_TEXT ]; - consoleLine_t consoleLines[ MAX_CONSOLE_LINES ]; - int numConsoleLines; - qboolean consoleValid; - - particleSystem_t *poisonCloudPS; - - float painBlendValue; - float painBlendTarget; - int lastHealth; -} cg_t; - - -// all of the model, shader, and sound references that are -// loaded at gamestate time are stored in cgMedia_t -// Other media that can be tied to clients, weapons, or items are -// stored in the clientInfo_t, itemInfo_t, weaponInfo_t, and powerupInfo_t -typedef struct -{ - qhandle_t charsetShader; - qhandle_t whiteShader; - qhandle_t outlineShader; - - qhandle_t level2ZapTS; - - qhandle_t balloonShader; - qhandle_t connectionShader; - - qhandle_t selectShader; - qhandle_t viewBloodShader; - qhandle_t tracerShader; - qhandle_t crosshairShader[ WP_NUM_WEAPONS ]; - qhandle_t backTileShader; - - qhandle_t creepShader; - - qhandle_t scannerShader; - qhandle_t scannerBlipShader; - qhandle_t scannerLineShader; - - - qhandle_t numberShaders[ 11 ]; - - qhandle_t shadowMarkShader; - qhandle_t wakeMarkShader; - - // buildable shaders - qhandle_t greenBuildShader; - qhandle_t redBuildShader; - qhandle_t noPowerShader; - qhandle_t humanSpawningShader; - - // disconnect - qhandle_t disconnectPS; - qhandle_t disconnectSound; - - // sounds - sfxHandle_t tracerSound; - sfxHandle_t selectSound; - sfxHandle_t footsteps[ FOOTSTEP_TOTAL ][ 4 ]; - sfxHandle_t talkSound; - sfxHandle_t landSound; - sfxHandle_t fallSound; - - sfxHandle_t hgrenb1aSound; - sfxHandle_t hgrenb2aSound; - - sfxHandle_t voteNow; - sfxHandle_t votePassed; - sfxHandle_t voteFailed; - - sfxHandle_t watrInSound; - sfxHandle_t watrOutSound; - sfxHandle_t watrUnSound; - - sfxHandle_t jetpackDescendSound; - sfxHandle_t jetpackIdleSound; - sfxHandle_t jetpackAscendSound; - - qhandle_t jetPackDescendPS; - qhandle_t jetPackHoverPS; - qhandle_t jetPackAscendPS; - - sfxHandle_t medkitUseSound; - - sfxHandle_t alienStageTransition; - sfxHandle_t humanStageTransition; - - sfxHandle_t alienOvermindAttack; - sfxHandle_t alienOvermindDying; - sfxHandle_t alienOvermindSpawns; - - sfxHandle_t alienBuildableExplosion; - sfxHandle_t alienBuildableDamage; - sfxHandle_t alienBuildablePrebuild; - sfxHandle_t humanBuildableExplosion; - sfxHandle_t humanBuildablePrebuild; - sfxHandle_t humanBuildableDamage[ 4 ]; - - sfxHandle_t alienL1Grab; - sfxHandle_t alienL4ChargePrepare; - sfxHandle_t alienL4ChargeStart; - - qhandle_t cursor; - qhandle_t selectCursor; - qhandle_t sizeCursor; - - //light armour - qhandle_t larmourHeadSkin; - qhandle_t larmourLegsSkin; - qhandle_t larmourTorsoSkin; - - qhandle_t jetpackModel; - qhandle_t jetpackFlashModel; - qhandle_t battpackModel; - - sfxHandle_t repeaterUseSound; - - sfxHandle_t buildableRepairSound; - sfxHandle_t buildableRepairedSound; - - qhandle_t poisonCloudPS; - qhandle_t alienEvolvePS; - qhandle_t alienAcidTubePS; - - sfxHandle_t alienEvolveSound; - - qhandle_t humanBuildableDamagedPS; - qhandle_t humanBuildableDestroyedPS; - qhandle_t alienBuildableDamagedPS; - qhandle_t alienBuildableDestroyedPS; - - qhandle_t alienBleedPS; - qhandle_t humanBleedPS; - - qhandle_t teslaZapTS; - - sfxHandle_t lCannonWarningSound; - - qhandle_t buildWeaponTimerPie[ 8 ]; - qhandle_t upgradeClassIconShader; -} cgMedia_t; - - -// The client game static (cgs) structure hold everything -// loaded or calculated from the gamestate. It will NOT -// be cleared when a tournement restart is done, allowing -// all clients to begin playing instantly -typedef struct -{ - gameState_t gameState; // gamestate from server - glconfig_t glconfig; // rendering configuration - float screenXScale; // derived from glconfig - float screenYScale; - float screenXBias; - - int serverCommandSequence; // reliable command stream counter - int processedSnapshotNum; // the number of snapshots cgame has requested - - qboolean localServer; // detected on startup by checking sv_running - - // parsed from serverinfo - int dmflags; - int teamflags; - int timelimit; - int maxclients; - char mapname[ MAX_QPATH ]; - - int voteTime; - int voteYes; - int voteNo; - qboolean voteModified; // beep whenever changed - char voteString[ MAX_STRING_TOKENS ]; - - int teamVoteTime[ 2 ]; - int teamVoteYes[ 2 ]; - int teamVoteNo[ 2 ]; - qboolean teamVoteModified[ 2 ]; // beep whenever changed - char teamVoteString[ 2 ][ MAX_STRING_TOKENS ]; - - int levelStartTime; - - int scores1, scores2; // from configstrings - - qboolean newHud; - - int alienBuildPoints; - int alienBuildPointsTotal; - int humanBuildPoints; - int humanBuildPointsTotal; - int humanBuildPointsPowered; - - int alienStage; - int humanStage; - int alienKills; - int humanKills; - int alienNextStageThreshold; - int humanNextStageThreshold; - - int numAlienSpawns; - int numHumanSpawns; - - // - // locally derived information from gamestate - // - qhandle_t gameModels[ MAX_MODELS ]; - qhandle_t gameShaders[ MAX_SHADERS ]; - qhandle_t gameParticleSystems[ MAX_GAME_PARTICLE_SYSTEMS ]; - sfxHandle_t gameSounds[ MAX_SOUNDS ]; - - int numInlineModels; - qhandle_t inlineDrawModel[ MAX_MODELS ]; - vec3_t inlineModelMidpoints[ MAX_MODELS ]; - - clientInfo_t clientinfo[ MAX_CLIENTS ]; - - //TA: corpse info - clientInfo_t corpseinfo[ MAX_CLIENTS ]; - - // teamchat width is *3 because of embedded color codes - char teamChatMsgs[ TEAMCHAT_HEIGHT ][ TEAMCHAT_WIDTH * 3 + 1 ]; - int teamChatMsgTimes[ TEAMCHAT_HEIGHT ]; - int teamChatPos; - int teamLastChatPos; - - int cursorX; - int cursorY; - qboolean eventHandling; - qboolean mouseCaptured; - qboolean sizingHud; - void *capturedItem; - qhandle_t activeCursor; - - // media - cgMedia_t media; -} cgs_t; - -//============================================================================== - -extern cgs_t cgs; -extern cg_t cg; -extern centity_t cg_entities[ MAX_GENTITIES ]; - -//TA: weapon limit expanded: -//extern weaponInfo_t cg_weapons[MAX_WEAPONS]; -extern weaponInfo_t cg_weapons[ 32 ]; -//TA: upgrade infos: -extern upgradeInfo_t cg_upgrades[ 32 ]; - -//TA: buildable infos: -extern buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; - -extern markPoly_t cg_markPolys[ MAX_MARK_POLYS ]; - -extern vmCvar_t cg_centertime; -extern vmCvar_t cg_runpitch; -extern vmCvar_t cg_runroll; -extern vmCvar_t cg_bobup; -extern vmCvar_t cg_bobpitch; -extern vmCvar_t cg_bobroll; -extern vmCvar_t cg_swingSpeed; -extern vmCvar_t cg_shadows; -extern vmCvar_t cg_gibs; -extern vmCvar_t cg_drawTimer; -extern vmCvar_t cg_drawFPS; -extern vmCvar_t cg_drawSnapshot; -extern vmCvar_t cg_draw3dIcons; -extern vmCvar_t cg_drawIcons; -extern vmCvar_t cg_drawAmmoWarning; -extern vmCvar_t cg_drawCrosshair; -extern vmCvar_t cg_drawCrosshairNames; -extern vmCvar_t cg_drawRewards; -extern vmCvar_t cg_drawTeamOverlay; -extern vmCvar_t cg_teamOverlayUserinfo; -extern vmCvar_t cg_crosshairX; -extern vmCvar_t cg_crosshairY; -extern vmCvar_t cg_drawStatus; -extern vmCvar_t cg_draw2D; -extern vmCvar_t cg_animSpeed; -extern vmCvar_t cg_debugAnim; -extern vmCvar_t cg_debugPosition; -extern vmCvar_t cg_debugEvents; -extern vmCvar_t cg_teslaTrailTime; -extern vmCvar_t cg_railTrailTime; -extern vmCvar_t cg_errorDecay; -extern vmCvar_t cg_nopredict; -extern vmCvar_t cg_debugMove; -extern vmCvar_t cg_noPlayerAnims; -extern vmCvar_t cg_showmiss; -extern vmCvar_t cg_footsteps; -extern vmCvar_t cg_addMarks; -extern vmCvar_t cg_brassTime; -extern vmCvar_t cg_gun_frame; -extern vmCvar_t cg_gun_x; -extern vmCvar_t cg_gun_y; -extern vmCvar_t cg_gun_z; -extern vmCvar_t cg_drawGun; -extern vmCvar_t cg_viewsize; -extern vmCvar_t cg_tracerChance; -extern vmCvar_t cg_tracerWidth; -extern vmCvar_t cg_tracerLength; -extern vmCvar_t cg_autoswitch; -extern vmCvar_t cg_ignore; -extern vmCvar_t cg_simpleItems; -extern vmCvar_t cg_fov; -extern vmCvar_t cg_zoomFov; -extern vmCvar_t cg_thirdPersonRange; -extern vmCvar_t cg_thirdPersonAngle; -extern vmCvar_t cg_thirdPerson; -extern vmCvar_t cg_stereoSeparation; -extern vmCvar_t cg_lagometer; -extern vmCvar_t cg_drawAttacker; -extern vmCvar_t cg_synchronousClients; -extern vmCvar_t cg_teamChatTime; -extern vmCvar_t cg_teamChatHeight; -extern vmCvar_t cg_stats; -extern vmCvar_t cg_forceModel; -extern vmCvar_t cg_buildScript; -extern vmCvar_t cg_paused; -extern vmCvar_t cg_blood; -extern vmCvar_t cg_predictItems; -extern vmCvar_t cg_deferPlayers; -extern vmCvar_t cg_drawFriend; -extern vmCvar_t cg_teamChatsOnly; -extern vmCvar_t cg_noVoiceChats; -extern vmCvar_t cg_noVoiceText; -extern vmCvar_t cg_scorePlum; -extern vmCvar_t cg_smoothClients; -extern vmCvar_t pmove_fixed; -extern vmCvar_t pmove_msec; -//extern vmCvar_t cg_pmove_fixed; -extern vmCvar_t cg_cameraOrbit; -extern vmCvar_t cg_cameraOrbitDelay; -extern vmCvar_t cg_timescaleFadeEnd; -extern vmCvar_t cg_timescaleFadeSpeed; -extern vmCvar_t cg_timescale; -extern vmCvar_t cg_cameraMode; -extern vmCvar_t cg_smallFont; -extern vmCvar_t cg_bigFont; -extern vmCvar_t cg_noTaunt; -extern vmCvar_t cg_noProjectileTrail; -extern vmCvar_t cg_oldRail; -extern vmCvar_t cg_oldRocket; -extern vmCvar_t cg_oldPlasma; -extern vmCvar_t cg_trueLightning; -extern vmCvar_t cg_creepRes; -extern vmCvar_t cg_drawSurfNormal; -extern vmCvar_t cg_drawBBOX; -extern vmCvar_t cg_debugAlloc; -extern vmCvar_t cg_wwSmoothTime; -extern vmCvar_t cg_wwFollow; -extern vmCvar_t cg_wwToggle; -extern vmCvar_t cg_depthSortParticles; -extern vmCvar_t cg_consoleLatency; -extern vmCvar_t cg_lightFlare; -extern vmCvar_t cg_debugParticles; -extern vmCvar_t cg_debugTrails; -extern vmCvar_t cg_debugPVS; -extern vmCvar_t cg_disableWarningDialogs; -extern vmCvar_t cg_disableScannerPlane; - -extern vmCvar_t cg_painBlendUpRate; -extern vmCvar_t cg_painBlendDownRate; -extern vmCvar_t cg_painBlendMax; -extern vmCvar_t cg_painBlendScale; -extern vmCvar_t cg_painBlendZoom; - -//TA: hack to get class an carriage through to UI module -extern vmCvar_t ui_currentClass; -extern vmCvar_t ui_carriage; -extern vmCvar_t ui_stages; -extern vmCvar_t ui_dialog; -extern vmCvar_t ui_loading; -extern vmCvar_t ui_voteActive; -extern vmCvar_t ui_alienTeamVoteActive; -extern vmCvar_t ui_humanTeamVoteActive; - -extern vmCvar_t cg_debugRandom; - -// -// cg_main.c -// -const char *CG_ConfigString( int index ); -const char *CG_Argv( int arg ); - -void CG_TAUIConsole( const char *text ); -void QDECL CG_Printf( const char *msg, ... ); -void QDECL CG_Error( const char *msg, ... ); - -void CG_StartMusic( void ); - -void CG_UpdateCvars( void ); - -int CG_CrosshairPlayer( void ); -int CG_LastAttacker( void ); -void CG_LoadMenus( const char *menuFile ); -void CG_KeyEvent( int key, qboolean down ); -void CG_MouseEvent( int x, int y ); -void CG_EventHandling( int type ); -void CG_SetScoreSelection( void *menu ); -void CG_BuildSpectatorString( void ); - -qboolean CG_FileExists( char *filename ); -void CG_RemoveConsoleLine( void ); - - -// -// cg_view.c -// -void CG_addSmoothOp( vec3_t rotAxis, float rotAngle, float timeMod ); //TA -void CG_TestModel_f( void ); -void CG_TestGun_f( void ); -void CG_TestModelNextFrame_f( void ); -void CG_TestModelPrevFrame_f( void ); -void CG_TestModelNextSkin_f( void ); -void CG_TestModelPrevSkin_f( void ); -void CG_ZoomDown_f( void ); -void CG_ZoomUp_f( void ); -void CG_AddBufferedSound( sfxHandle_t sfx ); -void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ); - - -// -// cg_drawtools.c -// -void CG_DrawPlane( vec3_t origin, vec3_t down, vec3_t right, qhandle_t shader ); -void CG_AdjustFrom640( float *x, float *y, float *w, float *h ); -void CG_FillRect( float x, float y, float width, float height, const float *color ); -void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ); -void CG_DrawFadePic( float x, float y, float width, float height, vec4_t fcolor, - vec4_t tcolor, float amount, qhandle_t hShader ); - -int CG_DrawStrlen( const char *str ); - -float *CG_FadeColor( int startMsec, int totalMsec ); -void CG_TileClear( void ); -void CG_ColorForHealth( vec4_t hcolor ); -void CG_GetColorForHealth( int health, int armor, vec4_t hcolor ); - -void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ); -void CG_DrawSides(float x, float y, float w, float h, float size); -void CG_DrawTopBottom(float x, float y, float w, float h, float size); - - -// -// cg_draw.c -// -extern int sortedTeamPlayers[ TEAM_MAXOVERLAY ]; -extern int numSortedTeamPlayers; -extern char systemChat[ 256 ]; -extern char teamChat1[ 256 ]; -extern char teamChat2[ 256 ]; - -void CG_AddLagometerFrameInfo( void ); -void CG_AddLagometerSnapshotInfo( snapshot_t *snap ); -void CG_CenterPrint( const char *str, int y, int charWidth ); -void CG_DrawActive( stereoFrame_t stereoView ); -void CG_OwnerDraw( float x, float y, float w, float h, float text_x, float text_y, - int ownerDraw, int ownerDrawFlags, int align, float special, - float scale, vec4_t color, qhandle_t shader, int textStyle); -void CG_Text_Paint( float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style ); -int CG_Text_Width( const char *text, float scale, int limit ); -int CG_Text_Height( const char *text, float scale, int limit ); -float CG_GetValue(int ownerDraw); -void CG_RunMenuScript(char **args); -void CG_SetPrintString( int type, const char *p ); -void CG_InitTeamChat( void ); -void CG_GetTeamColor( vec4_t *color ); -const char *CG_GetKillerText(); -void CG_Text_PaintChar( float x, float y, float width, float height, float scale, - float s, float t, float s2, float t2, qhandle_t hShader ); -void CG_DrawLoadingScreen( void ); -void CG_UpdateMediaFraction( float newFract ); -void CG_ResetPainBlend( void ); - -// -// cg_players.c -// -void CG_Player( centity_t *cent ); -void CG_Corpse( centity_t *cent ); -void CG_ResetPlayerEntity( centity_t *cent ); -void CG_AddRefEntityWithPowerups( refEntity_t *ent, int powerups, int team ); -void CG_NewClientInfo( int clientNum ); -void CG_PrecacheClientInfo( pClass_t class, char *model, char *skin ); -sfxHandle_t CG_CustomSound( int clientNum, const char *soundName ); -void CG_PlayerDisconnect( vec3_t org ); -void CG_Bleed( vec3_t origin, vec3_t normal, int entityNum ); - -// -// cg_buildable.c -// -void CG_GhostBuildable( buildable_t buildable ); -void CG_Buildable( centity_t *cent ); -void CG_InitBuildables( void ); -void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ); -void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir ); - -// -// cg_animation.c -// -void CG_RunLerpFrame( lerpFrame_t *lf ); - -// -// cg_animmapobj.c -// -void CG_AnimMapObj( centity_t *cent ); -void CG_ModelDoor( centity_t *cent ); - -// -// cg_predict.c -// - -#define MAGIC_TRACE_HACK -2 - -void CG_BuildSolidList( void ); -int CG_PointContents( const vec3_t point, int passEntityNum ); -void CG_Trace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, - int skipNumber, int mask ); -void CG_CapTrace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, - int skipNumber, int mask ); -void CG_PredictPlayerState( void ); - - -// -// cg_events.c -// -void CG_CheckEvents( centity_t *cent ); -void CG_EntityEvent( centity_t *cent, vec3_t position ); -void CG_PainEvent( centity_t *cent, int health ); - - -// -// cg_ents.c -// -void CG_DrawBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs ); -void CG_SetEntitySoundPosition( centity_t *cent ); -void CG_AddPacketEntities( void ); -void CG_Beam( centity_t *cent ); -void CG_AdjustPositionForMover( const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out ); - -void CG_PositionEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ); -void CG_PositionRotatedEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ); - - - - -// -// cg_weapons.c -// -void CG_NextWeapon_f( void ); -void CG_PrevWeapon_f( void ); -void CG_Weapon_f( void ); - -void CG_InitUpgrades( ); -void CG_RegisterUpgrade( int upgradeNum ); -void CG_InitWeapons( ); -void CG_RegisterWeapon( int weaponNum ); - -void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode ); -void CG_MissileHitWall( weapon_t weapon, weaponMode_t weaponMode, int clientNum, - vec3_t origin, vec3_t dir, impactSound_t soundType ); -void CG_MissileHitPlayer( weapon_t weapon, weaponMode_t weaponMode, vec3_t origin, vec3_t dir, int entityNum ); -void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ); -void CG_ShotgunFire( entityState_t *es ); - -void CG_AddViewWeapon (playerState_t *ps); -void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent ); -void CG_DrawItemSelect( rectDef_t *rect, vec4_t color ); -void CG_DrawItemSelectText( rectDef_t *rect, float scale, int textStyle ); - - -// -// cg_scanner.c -// -void CG_UpdateEntityPositions( void ); -void CG_Scanner( rectDef_t *rect, qhandle_t shader, vec4_t color ); -void CG_AlienSense( rectDef_t *rect ); - -// -// cg_marks.c -// -void CG_InitMarkPolys( void ); -void CG_AddMarks( void ); -void CG_ImpactMark( qhandle_t markShader, - const vec3_t origin, const vec3_t dir, - float orientation, - float r, float g, float b, float a, - qboolean alphaFade, - float radius, qboolean temporary ); - -// -// cg_snapshot.c -// -void CG_ProcessSnapshots( void ); - -// -// cg_consolecmds.c -// -qboolean CG_ConsoleCommand( void ); -void CG_InitConsoleCommands( void ); - -// -// cg_servercmds.c -// -void CG_ExecuteNewServerCommands( int latestSequence ); -void CG_ParseServerinfo( void ); -void CG_SetConfigValues( void ); -void CG_ShaderStateChanged(void); - -// -// cg_playerstate.c -// -void CG_Respawn( void ); -void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ); -void CG_CheckChangedPredictableEvents( playerState_t *ps ); - -// -// cg_mem.c -// -void CG_InitMemory( void ); -void *CG_Alloc( int size ); -void CG_Free( void *ptr ); -void CG_DefragmentMemory( void ); - -// -// cg_attachment.c -// -qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v ); -qboolean CG_AttachmentDir( attachment_t *a, vec3_t v ); -qboolean CG_AttachmentAxis( attachment_t *a, vec3_t axis[ 3 ] ); -qboolean CG_AttachmentVelocity( attachment_t *a, vec3_t v ); -int CG_AttachmentCentNum( attachment_t *a ); - -qboolean CG_Attached( attachment_t *a ); - -void CG_AttachToPoint( attachment_t *a ); -void CG_AttachToCent( attachment_t *a ); -void CG_AttachToTag( attachment_t *a ); -void CG_AttachToParticle( attachment_t *a ); -void CG_SetAttachmentPoint( attachment_t *a, vec3_t v ); -void CG_SetAttachmentCent( attachment_t *a, centity_t *cent ); -void CG_SetAttachmentTag( attachment_t *a, refEntity_t parent, - qhandle_t model, char *tagName ); -void CG_SetAttachmentParticle( attachment_t *a, particle_t *p ); - -void CG_SetAttachmentOffset( attachment_t *a, vec3_t v ); - -// -// cg_particles.c -// -void CG_LoadParticleSystems( void ); -qhandle_t CG_RegisterParticleSystem( char *name ); - -particleSystem_t *CG_SpawnNewParticleSystem( qhandle_t psHandle ); -void CG_DestroyParticleSystem( particleSystem_t **ps ); - -qboolean CG_IsParticleSystemInfinite( particleSystem_t *ps ); -qboolean CG_IsParticleSystemValid( particleSystem_t **ps ); - -void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal ); - -void CG_AddParticles( void ); - -void CG_ParticleSystemEntity( centity_t *cent ); - -void CG_TestPS_f( void ); -void CG_DestroyTestPS_f( void ); - -// -// cg_trails.c -// -void CG_LoadTrailSystems( void ); -qhandle_t CG_RegisterTrailSystem( char *name ); - -trailSystem_t *CG_SpawnNewTrailSystem( qhandle_t psHandle ); -void CG_DestroyTrailSystem( trailSystem_t **ts ); - -qboolean CG_IsTrailSystemValid( trailSystem_t **ts ); - -void CG_AddTrails( void ); - -void CG_TestTS_f( void ); -void CG_DestroyTestTS_f( void ); - -// -// cg_ptr.c -// -int CG_ReadPTRCode( void ); -void CG_WritePTRCode( int code ); - -// -//=============================================== - -// -// system traps -// These functions are how the cgame communicates with the main game system -// - - -// print message on the local console -void trap_Print( const char *fmt ); - -// abort the game -void trap_Error( const char *fmt ); - -// milliseconds should only be used for performance tuning, never -// for anything game related. Get time from the CG_DrawActiveFrame parameter -int trap_Milliseconds( void ); - -// console variable interaction -void trap_Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ); -void trap_Cvar_Update( vmCvar_t *vmCvar ); -void trap_Cvar_Set( const char *var_name, const char *value ); -void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ); - -// ServerCommand and ConsoleCommand parameter access -int trap_Argc( void ); -void trap_Argv( int n, char *buffer, int bufferLength ); -void trap_Args( char *buffer, int bufferLength ); - -// filesystem access -// returns length of file -int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ); -void trap_FS_Read( void *buffer, int len, fileHandle_t f ); -void trap_FS_Write( const void *buffer, int len, fileHandle_t f ); -void trap_FS_FCloseFile( fileHandle_t f ); -void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t - -// add commands to the local console as if they were typed in -// for map changing, etc. The command is not executed immediately, -// but will be executed in order the next time console commands -// are processed -void trap_SendConsoleCommand( const char *text ); - -// register a command name so the console can perform command completion. -// FIXME: replace this with a normal console command "defineCommand"? -void trap_AddCommand( const char *cmdName ); - -// send a string to the server over the network -void trap_SendClientCommand( const char *s ); - -// force a screen update, only used during gamestate load -void trap_UpdateScreen( void ); - -// model collision -void trap_CM_LoadMap( const char *mapname ); -int trap_CM_NumInlineModels( void ); -clipHandle_t trap_CM_InlineModel( int index ); // 0 = world, 1+ = bmodels -clipHandle_t trap_CM_TempBoxModel( const vec3_t mins, const vec3_t maxs ); -int trap_CM_PointContents( const vec3_t p, clipHandle_t model ); -int trap_CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles ); -void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask ); -void trap_CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask, - const vec3_t origin, const vec3_t angles ); -void trap_CM_CapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask ); -void trap_CM_TransformedCapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask, - const vec3_t origin, const vec3_t angles ); - -// Returns the projection of a polygon onto the solid brushes in the world -int trap_CM_MarkFragments( int numPoints, const vec3_t *points, - const vec3_t projection, - int maxPoints, vec3_t pointBuffer, - int maxFragments, markFragment_t *fragmentBuffer ); - -// normal sounds will have their volume dynamically changed as their entity -// moves and the listener moves -void trap_S_StartSound( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx ); -void trap_S_StopLoopingSound( int entnum ); - -// a local sound is always played full volume -void trap_S_StartLocalSound( sfxHandle_t sfx, int channelNum ); -void trap_S_ClearLoopingSounds( qboolean killall ); -void trap_S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ); -void trap_S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ); -void trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin ); - -// respatialize recalculates the volumes of sound as they should be heard by the -// given entityNum and position -void trap_S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater ); -sfxHandle_t trap_S_RegisterSound( const char *sample, qboolean compressed ); // returns buzz if not found -void trap_S_StartBackgroundTrack( const char *intro, const char *loop ); // empty name stops music -void trap_S_StopBackgroundTrack( void ); - - -void trap_R_LoadWorldMap( const char *mapname ); - -// all media should be registered during level startup to prevent -// hitches during gameplay -qhandle_t trap_R_RegisterModel( const char *name ); // returns rgb axis if not found -qhandle_t trap_R_RegisterSkin( const char *name ); // returns all white if not found -qhandle_t trap_R_RegisterShader( const char *name ); // returns all white if not found -qhandle_t trap_R_RegisterShaderNoMip( const char *name ); // returns all white if not found - -// a scene is built up by calls to R_ClearScene and the various R_Add functions. -// Nothing is drawn until R_RenderScene is called. -void trap_R_ClearScene( void ); -void trap_R_AddRefEntityToScene( const refEntity_t *re ); - -// polys are intended for simple wall marks, not really for doing -// significant construction -void trap_R_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ); -void trap_R_AddPolysToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); -void trap_R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -void trap_R_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -int trap_R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); -void trap_R_RenderScene( const refdef_t *fd ); -void trap_R_SetColor( const float *rgba ); // NULL = 1,1,1,1 -void trap_R_DrawStretchPic( float x, float y, float w, float h, - float s1, float t1, float s2, float t2, qhandle_t hShader ); -void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ); -int trap_R_LerpTag( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame, - float frac, const char *tagName ); -void trap_R_RemapShader( const char *oldShader, const char *newShader, const char *timeOffset ); - -// The glconfig_t will not change during the life of a cgame. -// If it needs to change, the entire cgame will be restarted, because -// all the qhandle_t are then invalid. -void trap_GetGlconfig( glconfig_t *glconfig ); - -// the gamestate should be grabbed at startup, and whenever a -// configstring changes -void trap_GetGameState( gameState_t *gamestate ); - -// cgame will poll each frame to see if a newer snapshot has arrived -// that it is interested in. The time is returned seperately so that -// snapshot latency can be calculated. -void trap_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime ); - -// a snapshot get can fail if the snapshot (or the entties it holds) is so -// old that it has fallen out of the client system queue -qboolean trap_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ); - -// retrieve a text command from the server stream -// the current snapshot will hold the number of the most recent command -// qfalse can be returned if the client system handled the command -// argc() / argv() can be used to examine the parameters of the command -qboolean trap_GetServerCommand( int serverCommandNumber ); - -// returns the most recent command number that can be passed to GetUserCmd -// this will always be at least one higher than the number in the current -// snapshot, and it may be quite a few higher if it is a fast computer on -// a lagged connection -int trap_GetCurrentCmdNumber( void ); - -qboolean trap_GetUserCmd( int cmdNumber, usercmd_t *ucmd ); - -// used for the weapon select and zoom -void trap_SetUserCmdValue( int stateValue, float sensitivityScale ); - -// aids for VM testing -void testPrintInt( char *string, int i ); -void testPrintFloat( char *string, float f ); - -int trap_MemoryRemaining( void ); -void trap_R_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font); -qboolean trap_Key_IsDown( int keynum ); -int trap_Key_GetCatcher( void ); -void trap_Key_SetCatcher( int catcher ); -int trap_Key_GetKey( const char *binding ); - -typedef enum -{ - SYSTEM_PRINT, - CHAT_PRINT, - TEAMCHAT_PRINT -} q3print_t; - - -int trap_CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits ); -e_status trap_CIN_StopCinematic( int handle ); -e_status trap_CIN_RunCinematic( int handle ); -void trap_CIN_DrawCinematic( int handle ); -void trap_CIN_SetExtents( int handle, int x, int y, int w, int h ); - -void trap_SnapVector( float *v ); - -qboolean trap_loadCamera( const char *name ); -void trap_startCamera( int time ); -qboolean trap_getCameraInfo( int time, vec3_t *origin, vec3_t *angles ); - -qboolean trap_GetEntityToken( char *buffer, int bufferSize ); diff --git a/mod/src/cgame/cg_main.c b/mod/src/cgame/cg_main.c deleted file mode 100644 index 81470e0e..00000000 --- a/mod/src/cgame/cg_main.c +++ /dev/null @@ -1,1801 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_main.c -- initialization and primary entry point for cgame - -/* - * 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" - -#include "../ui/ui_shared.h" -// display context for new ui stuff -displayContextDef_t cgDC; - -int forceModelModificationCount = -1; - -void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ); -void CG_Shutdown( void ); - -/* -================ -vmMain - -This is the only way control passes into the module. -This must be the very first function compiled into the .q3vm file -================ -*/ -long vmMain( long command, long arg0, long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6, long arg7, - long arg8, long arg9, long arg10, long arg11 ) -{ - switch( command ) - { - case CG_INIT: - CG_Init( arg0, arg1, arg2 ); - return 0; - - case CG_SHUTDOWN: - CG_Shutdown( ); - return 0; - - case CG_CONSOLE_COMMAND: - return CG_ConsoleCommand( ); - - case CG_DRAW_ACTIVE_FRAME: - CG_DrawActiveFrame( arg0, arg1, arg2 ); - return 0; - - case CG_CROSSHAIR_PLAYER: - return CG_CrosshairPlayer( ); - - case CG_LAST_ATTACKER: - return CG_LastAttacker( ); - - case CG_KEY_EVENT: - CG_KeyEvent( arg0, arg1 ); - return 0; - - case CG_MOUSE_EVENT: - cgDC.cursorx = cgs.cursorX; - cgDC.cursory = cgs.cursorY; - CG_MouseEvent( arg0, arg1 ); - return 0; - - case CG_EVENT_HANDLING: - CG_EventHandling( arg0 ); - return 0; - - default: - CG_Error( "vmMain: unknown command %i", command ); - break; - } - - return -1; -} - - -cg_t cg; -cgs_t cgs; -centity_t cg_entities[ MAX_GENTITIES ]; - -//TA: weapons limit expanded: -//weaponInfo_t cg_weapons[MAX_WEAPONS]; -weaponInfo_t cg_weapons[ 32 ]; -upgradeInfo_t cg_upgrades[ 32 ]; - -buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; - -vmCvar_t cg_teslaTrailTime; -vmCvar_t cg_railTrailTime; -vmCvar_t cg_centertime; -vmCvar_t cg_runpitch; -vmCvar_t cg_runroll; -vmCvar_t cg_bobup; -vmCvar_t cg_bobpitch; -vmCvar_t cg_bobroll; -vmCvar_t cg_swingSpeed; -vmCvar_t cg_shadows; -vmCvar_t cg_gibs; -vmCvar_t cg_drawTimer; -vmCvar_t cg_drawFPS; -vmCvar_t cg_drawSnapshot; -vmCvar_t cg_draw3dIcons; -vmCvar_t cg_drawIcons; -vmCvar_t cg_drawAmmoWarning; -vmCvar_t cg_drawCrosshair; -vmCvar_t cg_drawCrosshairNames; -vmCvar_t cg_drawRewards; -vmCvar_t cg_crosshairX; -vmCvar_t cg_crosshairY; -vmCvar_t cg_draw2D; -vmCvar_t cg_drawStatus; -vmCvar_t cg_animSpeed; -vmCvar_t cg_debugAnim; -vmCvar_t cg_debugPosition; -vmCvar_t cg_debugEvents; -vmCvar_t cg_errorDecay; -vmCvar_t cg_nopredict; -vmCvar_t cg_debugMove; -vmCvar_t cg_noPlayerAnims; -vmCvar_t cg_showmiss; -vmCvar_t cg_footsteps; -vmCvar_t cg_addMarks; -vmCvar_t cg_brassTime; -vmCvar_t cg_viewsize; -vmCvar_t cg_drawGun; -vmCvar_t cg_gun_frame; -vmCvar_t cg_gun_x; -vmCvar_t cg_gun_y; -vmCvar_t cg_gun_z; -vmCvar_t cg_tracerChance; -vmCvar_t cg_tracerWidth; -vmCvar_t cg_tracerLength; -vmCvar_t cg_autoswitch; -vmCvar_t cg_ignore; -vmCvar_t cg_simpleItems; -vmCvar_t cg_fov; -vmCvar_t cg_zoomFov; -vmCvar_t cg_thirdPerson; -vmCvar_t cg_thirdPersonRange; -vmCvar_t cg_thirdPersonAngle; -vmCvar_t cg_stereoSeparation; -vmCvar_t cg_lagometer; -vmCvar_t cg_drawAttacker; -vmCvar_t cg_synchronousClients; -vmCvar_t cg_teamChatTime; -vmCvar_t cg_teamChatHeight; -vmCvar_t cg_stats; -vmCvar_t cg_buildScript; -vmCvar_t cg_forceModel; -vmCvar_t cg_paused; -vmCvar_t cg_blood; -vmCvar_t cg_predictItems; -vmCvar_t cg_deferPlayers; -vmCvar_t cg_drawTeamOverlay; -vmCvar_t cg_teamOverlayUserinfo; -vmCvar_t cg_drawFriend; -vmCvar_t cg_teamChatsOnly; -vmCvar_t cg_noVoiceChats; -vmCvar_t cg_noVoiceText; -vmCvar_t cg_hudFiles; -vmCvar_t cg_scorePlum; -vmCvar_t cg_smoothClients; -vmCvar_t pmove_fixed; -//vmCvar_t cg_pmove_fixed; -vmCvar_t pmove_msec; -vmCvar_t cg_pmove_msec; -vmCvar_t cg_cameraMode; -vmCvar_t cg_cameraOrbit; -vmCvar_t cg_cameraOrbitDelay; -vmCvar_t cg_timescaleFadeEnd; -vmCvar_t cg_timescaleFadeSpeed; -vmCvar_t cg_timescale; -vmCvar_t cg_smallFont; -vmCvar_t cg_bigFont; -vmCvar_t cg_noTaunt; -vmCvar_t cg_noProjectileTrail; -vmCvar_t cg_oldRail; -vmCvar_t cg_oldRocket; -vmCvar_t cg_oldPlasma; -vmCvar_t cg_trueLightning; -vmCvar_t cg_creepRes; -vmCvar_t cg_drawSurfNormal; -vmCvar_t cg_drawBBOX; -vmCvar_t cg_debugAlloc; -vmCvar_t cg_wwSmoothTime; -vmCvar_t cg_wwFollow; -vmCvar_t cg_wwToggle; -vmCvar_t cg_depthSortParticles; -vmCvar_t cg_consoleLatency; -vmCvar_t cg_lightFlare; -vmCvar_t cg_debugParticles; -vmCvar_t cg_debugTrails; -vmCvar_t cg_debugPVS; -vmCvar_t cg_disableWarningDialogs; -vmCvar_t cg_disableScannerPlane; - -vmCvar_t cg_painBlendUpRate; -vmCvar_t cg_painBlendDownRate; -vmCvar_t cg_painBlendMax; -vmCvar_t cg_painBlendScale; -vmCvar_t cg_painBlendZoom; - -//TA: hack to get class and carriage through to UI module -vmCvar_t ui_currentClass; -vmCvar_t ui_carriage; -vmCvar_t ui_stages; -vmCvar_t ui_dialog; -vmCvar_t ui_loading; -vmCvar_t ui_voteActive; -vmCvar_t ui_alienTeamVoteActive; -vmCvar_t ui_humanTeamVoteActive; - -vmCvar_t cg_debugRandom; - - -typedef struct -{ - vmCvar_t *vmCvar; - char *cvarName; - char *defaultString; - int cvarFlags; -} cvarTable_t; - -static cvarTable_t cvarTable[ ] = -{ - { &cg_ignore, "cg_ignore", "0", 0 }, // used for debugging - { &cg_autoswitch, "cg_autoswitch", "1", CVAR_ARCHIVE }, - { &cg_drawGun, "cg_drawGun", "1", CVAR_ARCHIVE }, - { &cg_zoomFov, "cg_zoomfov", "22.5", CVAR_ARCHIVE }, - { &cg_fov, "cg_fov", "90", CVAR_ARCHIVE }, - { &cg_viewsize, "cg_viewsize", "100", CVAR_ARCHIVE }, - { &cg_stereoSeparation, "cg_stereoSeparation", "0.4", CVAR_ARCHIVE }, - { &cg_shadows, "cg_shadows", "1", CVAR_ARCHIVE }, - { &cg_gibs, "cg_gibs", "1", CVAR_ARCHIVE }, - { &cg_draw2D, "cg_draw2D", "1", CVAR_ARCHIVE }, - { &cg_drawStatus, "cg_drawStatus", "1", CVAR_ARCHIVE }, - { &cg_drawTimer, "cg_drawTimer", "1", CVAR_ARCHIVE }, - { &cg_drawFPS, "cg_drawFPS", "1", CVAR_ARCHIVE }, - { &cg_drawSnapshot, "cg_drawSnapshot", "0", CVAR_ARCHIVE }, - { &cg_draw3dIcons, "cg_draw3dIcons", "1", CVAR_ARCHIVE }, - { &cg_drawIcons, "cg_drawIcons", "1", CVAR_ARCHIVE }, - { &cg_drawAmmoWarning, "cg_drawAmmoWarning", "1", CVAR_ARCHIVE }, - { &cg_drawAttacker, "cg_drawAttacker", "1", CVAR_ARCHIVE }, - { &cg_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE }, - { &cg_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE }, - { &cg_drawRewards, "cg_drawRewards", "1", CVAR_ARCHIVE }, - { &cg_crosshairX, "cg_crosshairX", "0", CVAR_ARCHIVE }, - { &cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE }, - { &cg_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE }, - { &cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE }, - { &cg_addMarks, "cg_marks", "1", CVAR_ARCHIVE }, - { &cg_lagometer, "cg_lagometer", "0", CVAR_ARCHIVE }, - { &cg_teslaTrailTime, "cg_teslaTrailTime", "250", CVAR_ARCHIVE }, - { &cg_railTrailTime, "cg_railTrailTime", "400", CVAR_ARCHIVE }, - { &cg_gun_x, "cg_gunX", "0", CVAR_CHEAT }, - { &cg_gun_y, "cg_gunY", "0", CVAR_CHEAT }, - { &cg_gun_z, "cg_gunZ", "0", CVAR_CHEAT }, - { &cg_centertime, "cg_centertime", "3", CVAR_CHEAT }, - { &cg_runpitch, "cg_runpitch", "0.002", CVAR_ARCHIVE}, - { &cg_runroll, "cg_runroll", "0.005", CVAR_ARCHIVE }, - { &cg_bobup , "cg_bobup", "0.005", CVAR_CHEAT }, - { &cg_bobpitch, "cg_bobpitch", "0.002", CVAR_ARCHIVE }, - { &cg_bobroll, "cg_bobroll", "0.002", CVAR_ARCHIVE }, - { &cg_swingSpeed, "cg_swingSpeed", "0.3", CVAR_CHEAT }, - { &cg_animSpeed, "cg_animspeed", "1", CVAR_CHEAT }, - { &cg_debugAnim, "cg_debuganim", "0", CVAR_CHEAT }, - { &cg_debugPosition, "cg_debugposition", "0", CVAR_CHEAT }, - { &cg_debugEvents, "cg_debugevents", "0", CVAR_CHEAT }, - { &cg_errorDecay, "cg_errordecay", "100", 0 }, - { &cg_nopredict, "cg_nopredict", "0", 0 }, - { &cg_debugMove, "cg_debugMove", "0", 0 }, - { &cg_noPlayerAnims, "cg_noplayeranims", "0", CVAR_CHEAT }, - { &cg_showmiss, "cg_showmiss", "0", 0 }, - { &cg_footsteps, "cg_footsteps", "1", CVAR_CHEAT }, - { &cg_tracerChance, "cg_tracerchance", "0.4", CVAR_CHEAT }, - { &cg_tracerWidth, "cg_tracerwidth", "1", CVAR_CHEAT }, - { &cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT }, - { &cg_thirdPersonRange, "cg_thirdPersonRange", "40", CVAR_CHEAT }, - { &cg_thirdPersonAngle, "cg_thirdPersonAngle", "0", CVAR_CHEAT }, - { &cg_thirdPerson, "cg_thirdPerson", "0", CVAR_CHEAT }, - { &cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE }, - { &cg_teamChatHeight, "cg_teamChatHeight", "0", CVAR_ARCHIVE }, - { &cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE }, - { &cg_predictItems, "cg_predictItems", "1", CVAR_ARCHIVE }, - { &cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE }, - { &cg_drawTeamOverlay, "cg_drawTeamOverlay", "0", CVAR_ARCHIVE }, - { &cg_teamOverlayUserinfo, "teamoverlay", "0", CVAR_ROM | CVAR_USERINFO }, - { &cg_stats, "cg_stats", "0", 0 }, - { &cg_drawFriend, "cg_drawFriend", "1", CVAR_ARCHIVE }, - { &cg_teamChatsOnly, "cg_teamChatsOnly", "0", CVAR_ARCHIVE }, - { &cg_noVoiceChats, "cg_noVoiceChats", "0", CVAR_ARCHIVE }, - { &cg_noVoiceText, "cg_noVoiceText", "0", CVAR_ARCHIVE }, - { &cg_creepRes, "cg_creepRes", "16", CVAR_ARCHIVE }, - { &cg_drawSurfNormal, "cg_drawSurfNormal", "0", CVAR_CHEAT }, - { &cg_drawBBOX, "cg_drawBBOX", "0", CVAR_CHEAT }, - { &cg_debugAlloc, "cg_debugAlloc", "0", 0 }, - { &cg_wwSmoothTime, "cg_wwSmoothTime", "300", CVAR_ARCHIVE }, - { &cg_wwFollow, "cg_wwFollow", "1", CVAR_ARCHIVE|CVAR_USERINFO }, - { &cg_wwToggle, "cg_wwToggle", "1", CVAR_ARCHIVE|CVAR_USERINFO }, - { &cg_depthSortParticles, "cg_depthSortParticles", "1", CVAR_ARCHIVE }, - { &cg_consoleLatency, "cg_consoleLatency", "3000", CVAR_ARCHIVE }, - { &cg_lightFlare, "cg_lightFlare", "3", CVAR_ARCHIVE }, - { &cg_debugParticles, "cg_debugParticles", "0", CVAR_CHEAT }, - { &cg_debugTrails, "cg_debugTrails", "0", CVAR_CHEAT }, - { &cg_debugPVS, "cg_debugPVS", "0", CVAR_CHEAT }, - { &cg_disableWarningDialogs, "cg_disableWarningDialogs", "0", CVAR_ARCHIVE }, - { &cg_disableScannerPlane, "cg_disableScannerPlane", "0", CVAR_ARCHIVE }, - { &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE}, - - { &cg_painBlendUpRate, "cg_painBlendUpRate", "10.0", 0 }, - { &cg_painBlendDownRate, "cg_painBlendDownRate", "0.5", 0 }, - { &cg_painBlendMax, "cg_painBlendMax", "0.7", 0 }, - { &cg_painBlendScale, "cg_painBlendScale", "7.0", 0 }, - { &cg_painBlendZoom, "cg_painBlendZoom", "0.18", 0 }, - - { &ui_currentClass, "ui_currentClass", "0", 0 }, - { &ui_carriage, "ui_carriage", "", 0 }, - { &ui_stages, "ui_stages", "0 0", 0 }, - { &ui_dialog, "ui_dialog", "Text not set", 0 }, - { &ui_loading, "ui_loading", "0", 0 }, - { &ui_voteActive, "ui_voteActive", "0", 0 }, - { &ui_humanTeamVoteActive, "ui_humanTeamVoteActive", "0", 0 }, - { &ui_alienTeamVoteActive, "ui_alienTeamVoteActive", "0", 0 }, - - { &cg_debugRandom, "cg_debugRandom", "0", 0 }, - - // the following variables are created in other parts of the system, - // but we also reference them here - - { &cg_buildScript, "com_buildScript", "0", 0 }, // force loading of all possible data amd error on failures - { &cg_paused, "cl_paused", "0", CVAR_ROM }, - { &cg_blood, "com_blood", "1", CVAR_ARCHIVE }, - { &cg_synchronousClients, "g_synchronousClients", "0", 0 }, // communicated by systeminfo - { &cg_cameraOrbit, "cg_cameraOrbit", "0", CVAR_CHEAT}, - { &cg_cameraOrbitDelay, "cg_cameraOrbitDelay", "50", CVAR_ARCHIVE}, - { &cg_timescaleFadeEnd, "cg_timescaleFadeEnd", "1", 0}, - { &cg_timescaleFadeSpeed, "cg_timescaleFadeSpeed", "0", 0}, - { &cg_timescale, "timescale", "1", 0}, - { &cg_scorePlum, "cg_scorePlums", "1", CVAR_USERINFO | CVAR_ARCHIVE}, - { &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE}, - { &cg_cameraMode, "com_cameraMode", "0", CVAR_CHEAT}, - - { &pmove_fixed, "pmove_fixed", "0", 0}, - { &pmove_msec, "pmove_msec", "8", 0}, - { &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE}, - { &cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE}, - { &cg_smallFont, "ui_smallFont", "0.2", CVAR_ARCHIVE}, - { &cg_bigFont, "ui_bigFont", "0.5", CVAR_ARCHIVE}, - { &cg_oldRail, "cg_oldRail", "1", CVAR_ARCHIVE}, - { &cg_oldRocket, "cg_oldRocket", "1", CVAR_ARCHIVE}, - { &cg_oldPlasma, "cg_oldPlasma", "1", CVAR_ARCHIVE}, - { &cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE} -// { &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE } -}; - -static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); - -/* -================= -CG_RegisterCvars -================= -*/ -void CG_RegisterCvars( void ) -{ - int i; - cvarTable_t *cv; - char var[ MAX_TOKEN_CHARS ]; - - for( i = 0, cv = cvarTable; i < cvarTableSize; i++, cv++ ) - { - trap_Cvar_Register( cv->vmCvar, cv->cvarName, - cv->defaultString, cv->cvarFlags ); - } - - //repress standard Q3 console - trap_Cvar_Set( "con_notifytime", "-2" ); - - // see if we are also running the server on this machine - trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) ); - cgs.localServer = atoi( var ); - forceModelModificationCount = cg_forceModel.modificationCount; - - trap_Cvar_Register( NULL, "model", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE ); - trap_Cvar_Register( NULL, "headmodel", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE ); - trap_Cvar_Register( NULL, "team_model", DEFAULT_TEAM_MODEL, CVAR_USERINFO | CVAR_ARCHIVE ); - trap_Cvar_Register( NULL, "team_headmodel", DEFAULT_TEAM_HEAD, CVAR_USERINFO | CVAR_ARCHIVE ); -} - - -/* -=================== -CG_ForceModelChange -=================== -*/ -static void CG_ForceModelChange( void ) -{ - int i; - - for( i = 0; i < MAX_CLIENTS; i++ ) - { - const char *clientInfo; - - clientInfo = CG_ConfigString( CS_PLAYERS + i ); - - if( !clientInfo[ 0 ] ) - continue; - - CG_NewClientInfo( i ); - } -} - - -/* -================= -CG_UpdateCvars -================= -*/ -void CG_UpdateCvars( void ) -{ - int i; - cvarTable_t *cv; - - for( i = 0, cv = cvarTable; i < cvarTableSize; i++, cv++ ) - trap_Cvar_Update( cv->vmCvar ); - - // check for modications here - - // if force model changed - if( forceModelModificationCount != cg_forceModel.modificationCount ) - { - forceModelModificationCount = cg_forceModel.modificationCount; - CG_ForceModelChange( ); - } -} - - -int CG_CrosshairPlayer( void ) -{ - if( cg.time > ( cg.crosshairClientTime + 1000 ) ) - return -1; - - return cg.crosshairClientNum; -} - - -int CG_LastAttacker( void ) -{ - if( !cg.attackerTime ) - return -1; - - return cg.snap->ps.persistant[ PERS_ATTACKER ]; -} - -void CG_RemoveConsoleLine( void ) -{ - int i, offset, totalLength; - - if( cg.numConsoleLines == 0 ) - return; - - offset = cg.consoleLines[ 0 ].length; - totalLength = strlen( cg.consoleText ) - offset; - - //slide up consoleText - for( i = 0; i <= totalLength; i++ ) - cg.consoleText[ i ] = cg.consoleText[ i + offset ]; - - //pop up the first consoleLine - for( i = 0; i < cg.numConsoleLines; i++ ) - cg.consoleLines[ i ] = cg.consoleLines[ i + 1 ]; - - cg.numConsoleLines--; -} - -//TA: team arena UI based console -void CG_TAUIConsole( const char *text ) -{ - if( cg.numConsoleLines == MAX_CONSOLE_LINES ) - CG_RemoveConsoleLine( ); - - if( cg.consoleValid ) - { - strcat( cg.consoleText, text ); - cg.consoleLines[ cg.numConsoleLines ].time = cg.time; - cg.consoleLines[ cg.numConsoleLines ].length = strlen( text ); - cg.numConsoleLines++; - } - -} - -void QDECL CG_Printf( const char *msg, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, msg ); - vsprintf( text, msg, argptr ); - va_end( argptr ); - - CG_TAUIConsole( text ); - - trap_Print( text ); -} - -void QDECL CG_Error( const char *msg, ... ) -{ - va_list argptr; - char text[ 1024 ]; - - va_start( argptr, msg ); - vsprintf( text, msg, argptr ); - va_end( argptr ); - - trap_Error( text ); -} - -void QDECL Com_Error( int level, const char *error, ... ) -{ - va_list argptr; - char text[1024]; - - va_start( argptr, error ); - vsprintf( text, error, argptr ); - va_end( argptr ); - - CG_Error( "%s", text ); -} - -void QDECL Com_Printf( const char *msg, ... ) { - va_list argptr; - char text[1024]; - - va_start (argptr, msg); - vsprintf (text, msg, argptr); - va_end (argptr); - - //TA: team arena UI based console - if( cg.numConsoleLines == MAX_CONSOLE_LINES ) - CG_RemoveConsoleLine( ); - - if( cg.consoleValid ) - { - strcat( cg.consoleText, text ); - cg.consoleLines[ cg.numConsoleLines ].time = cg.time; - cg.consoleLines[ cg.numConsoleLines ].length = strlen( text ); - cg.numConsoleLines++; - } - - CG_Printf ("%s", text); -} - - - -/* -================ -CG_Argv -================ -*/ -const char *CG_Argv( int arg ) -{ - static char buffer[ MAX_STRING_CHARS ]; - - trap_Argv( arg, buffer, sizeof( buffer ) ); - - return buffer; -} - - -//======================================================================== - -/* -================= -CG_FileExists - -Test if a specific file exists or not -================= -*/ -qboolean CG_FileExists( char *filename ) -{ - fileHandle_t f; - - if( trap_FS_FOpenFile( filename, &f, FS_READ ) > 0 ) - { - //file exists so close it - trap_FS_FCloseFile( f ); - - return qtrue; - } - else - return qfalse; -} - -/* -================= -CG_RegisterSounds - -called during a precache command -================= -*/ -static void CG_RegisterSounds( void ) -{ - int i; - char name[ MAX_QPATH ]; - const char *soundName; - - cgs.media.alienStageTransition = trap_S_RegisterSound( "sound/announcements/overmindevolved.wav", qtrue ); - cgs.media.humanStageTransition = trap_S_RegisterSound( "sound/announcements/reinforcement.wav", qtrue ); - - cgs.media.alienOvermindAttack = trap_S_RegisterSound( "sound/announcements/overmindattack.wav", qtrue ); - cgs.media.alienOvermindDying = trap_S_RegisterSound( "sound/announcements/overminddying.wav", qtrue ); - cgs.media.alienOvermindSpawns = trap_S_RegisterSound( "sound/announcements/overmindspawns.wav", qtrue ); - - cgs.media.alienL1Grab = trap_S_RegisterSound( "sound/player/level1/grab.wav", qtrue ); - cgs.media.alienL4ChargePrepare = trap_S_RegisterSound( "sound/player/level4/charge_prepare.wav", qtrue ); - cgs.media.alienL4ChargeStart = trap_S_RegisterSound( "sound/player/level4/charge_start.wav", qtrue ); - - cgs.media.tracerSound = trap_S_RegisterSound( "sound/weapons/machinegun/buletby1.wav", qfalse ); //FIXME - cgs.media.selectSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse ); - - cgs.media.talkSound = trap_S_RegisterSound( "sound/player/talk.wav", qfalse ); //FIXME - cgs.media.landSound = trap_S_RegisterSound( "sound/player/land1.wav", qfalse ); //FIXME - - cgs.media.watrInSound = trap_S_RegisterSound( "sound/player/watr_in.wav", qfalse ); //FIXME - cgs.media.watrOutSound = trap_S_RegisterSound( "sound/player/watr_out.wav", qfalse ); //FIXME - cgs.media.watrUnSound = trap_S_RegisterSound( "sound/player/watr_un.wav", qfalse ); //FIXME - - cgs.media.disconnectSound = trap_S_RegisterSound( "sound/world/telein.wav", qfalse ); //FIXME - - //FIXME - for( i = 0; i < 4; i++ ) - { - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/step%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_NORMAL ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/boot%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_BOOT ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/flesh%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_FLESH ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/mech%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_MECH ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/energy%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_ENERGY ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/splash%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_SPLASH ][ i ] = trap_S_RegisterSound( name, qfalse ); - - Com_sprintf( name, sizeof( name ), "sound/player/footsteps/clank%i.wav", i + 1 ); - cgs.media.footsteps[ FOOTSTEP_METAL ][ i ] = trap_S_RegisterSound( name, qfalse ); - } - - for( i = 1 ; i < MAX_SOUNDS ; i++ ) - { - soundName = CG_ConfigString( CS_SOUNDS + i ); - - if( !soundName[ 0 ] ) - break; - - if( soundName[ 0 ] == '*' ) - continue; // custom sound - - cgs.gameSounds[ i ] = trap_S_RegisterSound( soundName, qfalse ); - } - - cgs.media.jetpackDescendSound = trap_S_RegisterSound( "sound/upgrades/jetpack/low.wav", qfalse ); - cgs.media.jetpackIdleSound = trap_S_RegisterSound( "sound/upgrades/jetpack/idle.wav", qfalse ); - cgs.media.jetpackAscendSound = trap_S_RegisterSound( "sound/upgrades/jetpack/hi.wav", qfalse ); - - cgs.media.medkitUseSound = trap_S_RegisterSound( "sound/upgrades/medkit/medkit.wav", qfalse ); - - cgs.media.alienEvolveSound = trap_S_RegisterSound( "sound/player/alienevolve.wav", qfalse ); - - cgs.media.alienBuildableExplosion = trap_S_RegisterSound( "sound/buildables/alien/explosion.wav", qfalse ); - cgs.media.alienBuildableDamage = trap_S_RegisterSound( "sound/buildables/alien/damage.wav", qfalse ); - cgs.media.alienBuildablePrebuild = trap_S_RegisterSound( "sound/buildables/alien/prebuild.wav", qfalse ); - - cgs.media.humanBuildableExplosion = trap_S_RegisterSound( "sound/buildables/human/explosion.wav", qfalse ); - cgs.media.humanBuildablePrebuild = trap_S_RegisterSound( "sound/buildables/human/prebuild.wav", qfalse ); - - for( i = 0; i < 4; i++ ) - cgs.media.humanBuildableDamage[ i ] = trap_S_RegisterSound( - va( "sound/buildables/human/damage%d.wav", i ), qfalse ); - - cgs.media.hgrenb1aSound = trap_S_RegisterSound( "sound/weapons/grenade/hgrenb1a.wav", qfalse ); //FIXME - cgs.media.hgrenb2aSound = trap_S_RegisterSound( "sound/weapons/grenade/hgrenb2a.wav", qfalse ); //FIXME - - cgs.media.repeaterUseSound = trap_S_RegisterSound( "sound/buildables/repeater/use.wav", qfalse ); - - cgs.media.buildableRepairSound = trap_S_RegisterSound( "sound/buildables/human/repair.wav", qfalse ); - cgs.media.buildableRepairedSound = trap_S_RegisterSound( "sound/buildables/human/repaired.wav", qfalse ); - - cgs.media.lCannonWarningSound = trap_S_RegisterSound( "models/weapons/lcannon/warning.wav", qfalse ); -} - - -//=================================================================================== - - -/* -================= -CG_RegisterGraphics - -This function may execute for a couple of minutes with a slow disk. -================= -*/ -static void CG_RegisterGraphics( void ) -{ - int i; - static char *sb_nums[ 11 ] = - { - "gfx/2d/numbers/zero_32b", - "gfx/2d/numbers/one_32b", - "gfx/2d/numbers/two_32b", - "gfx/2d/numbers/three_32b", - "gfx/2d/numbers/four_32b", - "gfx/2d/numbers/five_32b", - "gfx/2d/numbers/six_32b", - "gfx/2d/numbers/seven_32b", - "gfx/2d/numbers/eight_32b", - "gfx/2d/numbers/nine_32b", - "gfx/2d/numbers/minus_32b", - }; - static char *buildWeaponTimerPieShaders[ 8 ] = - { - "ui/assets/neutral/1_5pie", - "ui/assets/neutral/3_0pie", - "ui/assets/neutral/4_5pie", - "ui/assets/neutral/6_0pie", - "ui/assets/neutral/7_5pie", - "ui/assets/neutral/9_0pie", - "ui/assets/neutral/10_5pie", - "ui/assets/neutral/12_0pie", - }; - - // clear any references to old media - memset( &cg.refdef, 0, sizeof( cg.refdef ) ); - trap_R_ClearScene( ); - - trap_R_LoadWorldMap( cgs.mapname ); - CG_UpdateMediaFraction( 0.66f ); - - for( i = 0; i < 11; i++ ) - cgs.media.numberShaders[ i ] = trap_R_RegisterShader( sb_nums[ i ] ); - - cgs.media.viewBloodShader = trap_R_RegisterShader( "gfx/damage/fullscreen_painblend" ); //FIXME - - cgs.media.connectionShader = trap_R_RegisterShader( "disconnected" ); //FIXME? - - cgs.media.creepShader = trap_R_RegisterShader( "creep" ); - - cgs.media.scannerBlipShader = trap_R_RegisterShader( "gfx/2d/blip" ); - cgs.media.scannerLineShader = trap_R_RegisterShader( "gfx/2d/stalk" ); - - cgs.media.tracerShader = trap_R_RegisterShader( "gfx/misc/tracer" ); //FIXME - cgs.media.selectShader = trap_R_RegisterShader( "gfx/2d/select" ); - - cgs.media.backTileShader = trap_R_RegisterShader( "gfx/2d/backtile" ); //FIXME - - - //TA: building shaders - cgs.media.greenBuildShader = trap_R_RegisterShader("gfx/2d/greenbuild" ); - cgs.media.redBuildShader = trap_R_RegisterShader("gfx/2d/redbuild" ); - cgs.media.noPowerShader = trap_R_RegisterShader("gfx/2d/nopower" ); - cgs.media.humanSpawningShader = trap_R_RegisterShader("models/buildables/telenode/rep_cyl" ); - - for( i = 0; i < 8; i++ ) - cgs.media.buildWeaponTimerPie[ i ] = trap_R_RegisterShader( buildWeaponTimerPieShaders[ i ] ); - - cgs.media.upgradeClassIconShader = trap_R_RegisterShader( "icons/icona_upgrade.tga" ); - - cgs.media.balloonShader = trap_R_RegisterShader( "sprites/balloon3" ); //FIXME? - - cgs.media.disconnectPS = CG_RegisterParticleSystem( "disconnectPS" ); - - CG_UpdateMediaFraction( 0.7f ); - - memset( cg_weapons, 0, sizeof( cg_weapons ) ); - memset( cg_upgrades, 0, sizeof( cg_upgrades ) ); - - cgs.media.shadowMarkShader = trap_R_RegisterShader( "markShadow" ); //FIXME - cgs.media.wakeMarkShader = trap_R_RegisterShader( "wake" ); //FIXME - - cgs.media.poisonCloudPS = CG_RegisterParticleSystem( "poisonCloudPS" ); - cgs.media.alienEvolvePS = CG_RegisterParticleSystem( "alienEvolvePS" ); - cgs.media.alienAcidTubePS = CG_RegisterParticleSystem( "alienAcidTubePS" ); - - cgs.media.jetPackDescendPS = CG_RegisterParticleSystem( "jetPackDescendPS" ); - cgs.media.jetPackHoverPS = CG_RegisterParticleSystem( "jetPackHoverPS" ); - cgs.media.jetPackAscendPS = CG_RegisterParticleSystem( "jetPackAscendPS" ); - - cgs.media.humanBuildableDamagedPS = CG_RegisterParticleSystem( "humanBuildableDamagedPS" ); - cgs.media.alienBuildableDamagedPS = CG_RegisterParticleSystem( "alienBuildableDamagedPS" ); - cgs.media.humanBuildableDestroyedPS = CG_RegisterParticleSystem( "humanBuildableDestroyedPS" ); - cgs.media.alienBuildableDestroyedPS = CG_RegisterParticleSystem( "alienBuildableDestroyedPS" ); - - cgs.media.alienBleedPS = CG_RegisterParticleSystem( "alienBleedPS" ); - cgs.media.humanBleedPS = CG_RegisterParticleSystem( "humanBleedPS" ); - - // register the inline models - cgs.numInlineModels = trap_CM_NumInlineModels( ); - - for( i = 1; i < cgs.numInlineModels; i++ ) - { - char name[ 10 ]; - vec3_t mins, maxs; - int j; - - Com_sprintf( name, sizeof( name ), "*%i", i ); - - cgs.inlineDrawModel[ i ] = trap_R_RegisterModel( name ); - trap_R_ModelBounds( cgs.inlineDrawModel[ i ], mins, maxs ); - - for( j = 0 ; j < 3 ; j++ ) - cgs.inlineModelMidpoints[ i ][ j ] = mins[ j ] + 0.5 * ( maxs[ j ] - mins[ j ] ); - } - - // register all the server specified models - for( i = 1; i < MAX_MODELS; i++ ) - { - const char *modelName; - - modelName = CG_ConfigString( CS_MODELS + i ); - - if( !modelName[ 0 ] ) - break; - - cgs.gameModels[ i ] = trap_R_RegisterModel( modelName ); - } - - CG_UpdateMediaFraction( 0.8f ); - - // register all the server specified shaders - for( i = 1; i < MAX_SHADERS; i++ ) - { - const char *shaderName; - - shaderName = CG_ConfigString( CS_SHADERS + i ); - - if( !shaderName[ 0 ] ) - break; - - cgs.gameShaders[ i ] = trap_R_RegisterShader( shaderName ); - } - - CG_UpdateMediaFraction( 0.9f ); - - // register all the server specified particle systems - for( i = 1; i < MAX_GAME_PARTICLE_SYSTEMS; i++ ) - { - const char *psName; - - psName = CG_ConfigString( CS_PARTICLE_SYSTEMS + i ); - - if( !psName[ 0 ] ) - break; - - cgs.gameParticleSystems[ i ] = CG_RegisterParticleSystem( (char *)psName ); - } -} - - -/* -======================= -CG_BuildSpectatorString - -======================= -*/ -void CG_BuildSpectatorString( void ) -{ - int i; - - cg.spectatorList[ 0 ] = 0; - - for( i = 0; i < MAX_CLIENTS; i++ ) - { - if( cgs.clientinfo[ i ].infoValid && cgs.clientinfo[ i ].team == PTE_NONE ) - Q_strcat( cg.spectatorList, sizeof( cg.spectatorList ), va( "%s " S_COLOR_WHITE, cgs.clientinfo[ i ].name ) ); - } - - i = strlen( cg.spectatorList ); - - if( i != cg.spectatorLen ) - { - cg.spectatorLen = i; - cg.spectatorWidth = -1; - } -} - - - -/* -=================== -CG_RegisterClients - -=================== -*/ -static void CG_RegisterClients( void ) -{ - int i; - - cg.charModelFraction = 0.0f; - - //precache all the models/sounds/etc - for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) - { - CG_PrecacheClientInfo( i, BG_FindModelNameForClass( i ), - BG_FindSkinNameForClass( i ) ); - - cg.charModelFraction = (float)i / (float)PCL_NUM_CLASSES; - trap_UpdateScreen( ); - } - - cgs.media.larmourHeadSkin = trap_R_RegisterSkin( "models/players/human_base/head_light.skin" ); - cgs.media.larmourLegsSkin = trap_R_RegisterSkin( "models/players/human_base/lower_light.skin" ); - cgs.media.larmourTorsoSkin = trap_R_RegisterSkin( "models/players/human_base/upper_light.skin" ); - - cgs.media.jetpackModel = trap_R_RegisterModel( "models/players/human_base/jetpack.md3" ); - cgs.media.jetpackFlashModel = trap_R_RegisterModel( "models/players/human_base/jetpack_flash.md3" ); - cgs.media.battpackModel = trap_R_RegisterModel( "models/players/human_base/battpack.md3" ); - - cg.charModelFraction = 1.0f; - trap_UpdateScreen( ); - - //load all the clientinfos of clients already connected to the server - for( i = 0; i < MAX_CLIENTS; i++ ) - { - const char *clientInfo; - - clientInfo = CG_ConfigString( CS_PLAYERS + i ); - if( !clientInfo[ 0 ] ) - continue; - - CG_NewClientInfo( i ); - } - - CG_BuildSpectatorString( ); -} - -//=========================================================================== - -/* -================= -CG_ConfigString -================= -*/ -const char *CG_ConfigString( int index ) -{ - if( index < 0 || index >= MAX_CONFIGSTRINGS ) - CG_Error( "CG_ConfigString: bad index: %i", index ); - - return cgs.gameState.stringData + cgs.gameState.stringOffsets[ index ]; -} - -//================================================================== - -/* -====================== -CG_StartMusic - -====================== -*/ -void CG_StartMusic( void ) -{ - char *s; - char parm1[ MAX_QPATH ], parm2[ MAX_QPATH ]; - - // start the background music - s = (char *)CG_ConfigString( CS_MUSIC ); - Q_strncpyz( parm1, COM_Parse( &s ), sizeof( parm1 ) ); - Q_strncpyz( parm2, COM_Parse( &s ), sizeof( parm2 ) ); - - trap_S_StartBackgroundTrack( parm1, parm2 ); -} - -// -// ============================== -// new hud stuff ( mission pack ) -// ============================== -// -char *CG_GetMenuBuffer( const char *filename ) -{ - int len; - fileHandle_t f; - static char buf[ MAX_MENUFILE ]; - - len = trap_FS_FOpenFile( filename, &f, FS_READ ); - - if( !f ) - { - trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) ); - return NULL; - } - - if( len >= MAX_MENUFILE ) - { - trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", - filename, len, MAX_MENUFILE ) ); - trap_FS_FCloseFile( f ); - return NULL; - } - - trap_FS_Read( buf, len, f ); - buf[len] = 0; - trap_FS_FCloseFile( f ); - - return buf; -} - -qboolean CG_Asset_Parse( int handle ) -{ - pc_token_t token; - const char *tempStr; - - if( !trap_PC_ReadToken( handle, &token ) ) - return qfalse; - - if( Q_stricmp( token.string, "{" ) != 0 ) - return qfalse; - - while( 1 ) - { - if( !trap_PC_ReadToken( handle, &token ) ) - return qfalse; - - if( Q_stricmp( token.string, "}" ) == 0 ) - return qtrue; - - // font - if( Q_stricmp( token.string, "font" ) == 0 ) - { - int pointSize; - - if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) - return qfalse; - - cgDC.registerFont( tempStr, pointSize, &cgDC.Assets.textFont ); - continue; - } - - // smallFont - if( Q_stricmp( token.string, "smallFont" ) == 0 ) - { - int pointSize; - - if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) - return qfalse; - - cgDC.registerFont( tempStr, pointSize, &cgDC.Assets.smallFont ); - continue; - } - - // font - if( Q_stricmp( token.string, "bigfont" ) == 0 ) - { - int pointSize; - - if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) - return qfalse; - - cgDC.registerFont( tempStr, pointSize, &cgDC.Assets.bigFont ); - continue; - } - - // gradientbar - if( Q_stricmp( token.string, "gradientbar" ) == 0 ) - { - if( !PC_String_Parse( handle, &tempStr ) ) - return qfalse; - - cgDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( tempStr ); - continue; - } - - // enterMenuSound - if( Q_stricmp( token.string, "menuEnterSound" ) == 0 ) - { - if( !PC_String_Parse( handle, &tempStr ) ) - return qfalse; - - cgDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse ); - continue; - } - - // exitMenuSound - if( Q_stricmp( token.string, "menuExitSound" ) == 0 ) - { - if( !PC_String_Parse( handle, &tempStr ) ) - return qfalse; - - cgDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse ); - continue; - } - - // itemFocusSound - if( Q_stricmp( token.string, "itemFocusSound" ) == 0 ) - { - if( !PC_String_Parse( handle, &tempStr ) ) - return qfalse; - - cgDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse ); - continue; - } - - // menuBuzzSound - if( Q_stricmp( token.string, "menuBuzzSound" ) == 0 ) - { - if( !PC_String_Parse( handle, &tempStr ) ) - return qfalse; - - cgDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse ); - continue; - } - - if( Q_stricmp( token.string, "cursor" ) == 0 ) - { - if( !PC_String_Parse( handle, &cgDC.Assets.cursorStr ) ) - return qfalse; - - cgDC.Assets.cursor = trap_R_RegisterShaderNoMip( cgDC.Assets.cursorStr ); - continue; - } - - if( Q_stricmp( token.string, "fadeClamp" ) == 0 ) - { - if( !PC_Float_Parse( handle, &cgDC.Assets.fadeClamp ) ) - return qfalse; - - continue; - } - - if( Q_stricmp( token.string, "fadeCycle" ) == 0 ) - { - if( !PC_Int_Parse( handle, &cgDC.Assets.fadeCycle ) ) - return qfalse; - - continue; - } - - if( Q_stricmp( token.string, "fadeAmount" ) == 0 ) - { - if( !PC_Float_Parse( handle, &cgDC.Assets.fadeAmount ) ) - return qfalse; - - continue; - } - - if( Q_stricmp( token.string, "shadowX" ) == 0 ) - { - if( !PC_Float_Parse( handle, &cgDC.Assets.shadowX ) ) - return qfalse; - - continue; - } - - if( Q_stricmp( token.string, "shadowY" ) == 0 ) - { - if( !PC_Float_Parse( handle, &cgDC.Assets.shadowY ) ) - return qfalse; - - continue; - } - - if( Q_stricmp( token.string, "shadowColor" ) == 0 ) - { - if( !PC_Color_Parse( handle, &cgDC.Assets.shadowColor ) ) - return qfalse; - - cgDC.Assets.shadowFadeClamp = cgDC.Assets.shadowColor[ 3 ]; - continue; - } - } - - return qfalse; // bk001204 - why not? -} - -void CG_ParseMenu( const char *menuFile ) -{ - pc_token_t token; - int handle; - - handle = trap_PC_LoadSource( menuFile ); - - if( !handle ) - handle = trap_PC_LoadSource( "ui/testhud.menu" ); - - if( !handle ) - return; - - while( 1 ) - { - if( !trap_PC_ReadToken( handle, &token ) ) - break; - - //if ( Q_stricmp( token, "{" ) ) { - // Com_Printf( "Missing { in menu file\n" ); - // break; - //} - - //if ( menuCount == MAX_MENUS ) { - // Com_Printf( "Too many menus!\n" ); - // break; - //} - - if( token.string[ 0 ] == '}' ) - break; - - if( Q_stricmp( token.string, "assetGlobalDef" ) == 0 ) - { - if( CG_Asset_Parse( handle ) ) - continue; - else - break; - } - - - if( Q_stricmp( token.string, "menudef" ) == 0 ) - { - // start a new menu - Menu_New( handle ); - } - } - - trap_PC_FreeSource( handle ); -} - -qboolean CG_Load_Menu( char **p ) -{ - char *token; - - token = COM_ParseExt( p, qtrue ); - - if( token[ 0 ] != '{' ) - return qfalse; - - while( 1 ) - { - token = COM_ParseExt( p, qtrue ); - - if( Q_stricmp( token, "}" ) == 0 ) - return qtrue; - - if( !token || token[ 0 ] == 0 ) - return qfalse; - - CG_ParseMenu( token ); - } - return qfalse; -} - - - -void CG_LoadMenus( const char *menuFile ) -{ - char *token; - char *p; - int len, start; - fileHandle_t f; - static char buf[ MAX_MENUDEFFILE ]; - - start = trap_Milliseconds( ); - - len = trap_FS_FOpenFile( menuFile, &f, FS_READ ); - - if( !f ) - { - trap_Error( va( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile ) ); - len = trap_FS_FOpenFile( "ui/hud.txt", &f, FS_READ ); - - if( !f ) - trap_Error( va( S_COLOR_RED "default menu file not found: ui/hud.txt, unable to continue!\n", menuFile ) ); - } - - if( len >= MAX_MENUDEFFILE ) - { - trap_Error( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", - menuFile, len, MAX_MENUDEFFILE ) ); - trap_FS_FCloseFile( f ); - return; - } - - trap_FS_Read( buf, len, f ); - buf[ len ] = 0; - trap_FS_FCloseFile( f ); - - COM_Compress( buf ); - - Menu_Reset( ); - - p = buf; - - while( 1 ) - { - token = COM_ParseExt( &p, qtrue ); - - if( !token || token[ 0 ] == 0 || token[ 0 ] == '}' ) - break; - - if( Q_stricmp( token, "}" ) == 0 ) - break; - - if( Q_stricmp( token, "loadmenu" ) == 0 ) - { - if( CG_Load_Menu( &p ) ) - continue; - else - break; - } - } - - Com_Printf( "UI menu load time = %d milli seconds\n", trap_Milliseconds( ) - start ); -} - - - -static qboolean CG_OwnerDrawHandleKey( int ownerDraw, int flags, float *special, int key ) -{ - return qfalse; -} - - -static int CG_FeederCount( float feederID ) -{ - int i, count = 0; - - if( feederID == FEEDER_ALIENTEAM_LIST ) - { - for( i = 0; i < cg.numScores; i++ ) - { - if( cg.scores[ i ].team == PTE_ALIENS ) - count++; - } - } - else if( feederID == FEEDER_HUMANTEAM_LIST ) - { - for( i = 0; i < cg.numScores; i++ ) - { - if( cg.scores[ i ].team == PTE_HUMANS ) - count++; - } - } - - return count; -} - - -void CG_SetScoreSelection( void *p ) -{ - menuDef_t *menu = (menuDef_t*)p; - playerState_t *ps = &cg.snap->ps; - int i, alien, human; - int feeder; - - alien = human = 0; - - for( i = 0; i < cg.numScores; i++ ) - { - if( cg.scores[ i ].team == PTE_ALIENS ) - alien++; - else if( cg.scores[ i ].team == PTE_HUMANS ) - human++; - - if( ps->clientNum == cg.scores[ i ].client ) - cg.selectedScore = i; - } - - if( menu == NULL ) - // just interested in setting the selected score - return; - - feeder = FEEDER_ALIENTEAM_LIST; - i = alien; - - if( cg.scores[ cg.selectedScore ].team == PTE_HUMANS ) - { - feeder = FEEDER_HUMANTEAM_LIST; - i = human; - } - - Menu_SetFeederSelection(menu, feeder, i, NULL); -} - -// FIXME: might need to cache this info -static clientInfo_t * CG_InfoFromScoreIndex( int index, int team, int *scoreIndex ) -{ - int i, count; - count = 0; - - for( i = 0; i < cg.numScores; i++ ) - { - if( cg.scores[ i ].team == team ) - { - if( count == index ) - { - *scoreIndex = i; - return &cgs.clientinfo[ cg.scores[ i ].client ]; - } - count++; - } - } - - *scoreIndex = index; - return &cgs.clientinfo[ cg.scores[ index ].client ]; -} - -static const char *CG_FeederItemText( float feederID, int index, int column, qhandle_t *handle ) -{ - int scoreIndex = 0; - clientInfo_t *info = NULL; - int team = -1; - score_t *sp = NULL; - qboolean showIcons = qfalse; - - *handle = -1; - - if( feederID == FEEDER_ALIENTEAM_LIST ) - team = PTE_ALIENS; - else if( feederID == FEEDER_HUMANTEAM_LIST ) - team = PTE_HUMANS; - - info = CG_InfoFromScoreIndex( index, team, &scoreIndex ); - sp = &cg.scores[ scoreIndex ]; - - if( ( atoi( CG_ConfigString( CS_CLIENTS_READY ) ) & ( 1 << sp->client ) ) && - cg.intermissionStarted ) - showIcons = qfalse; - else if( cg.snap->ps.pm_type == PM_SPECTATOR || cg.snap->ps.pm_flags & PMF_FOLLOW || - team == cg.snap->ps.stats[ STAT_PTEAM ] || cg.intermissionStarted ) - showIcons = qtrue; - - if( info && info->infoValid ) - { - switch( column ) - { - case 0: - if( showIcons ) - { - if( sp->weapon != WP_NONE ) - *handle = cg_weapons[ sp->weapon ].weaponIcon; - } - break; - - case 1: - if( showIcons ) - { - if( sp->team == PTE_HUMANS && sp->upgrade != UP_NONE ) - *handle = cg_upgrades[ sp->upgrade ].upgradeIcon; - else if( sp->team == PTE_ALIENS ) - { - switch( sp->weapon ) - { - case WP_ABUILD2: - case WP_ALEVEL1_UPG: - case WP_ALEVEL2_UPG: - case WP_ALEVEL3_UPG: - *handle = cgs.media.upgradeClassIconShader; - break; - - default: - break; - } - } - } - break; - - case 2: - if( ( atoi( CG_ConfigString( CS_CLIENTS_READY ) ) & ( 1 << sp->client ) ) && - cg.intermissionStarted ) - return "Ready"; - break; - - case 3: - return info->name; - break; - - case 4: - return va( "%d", info->score ); - break; - - case 5: - return va( "%4d", sp->time ); - break; - - case 6: - if( sp->ping == -1 ) - return "connecting"; - - return va( "%4d", sp->ping ); - break; - } - } - - return ""; -} - -static qhandle_t CG_FeederItemImage( float feederID, int index ) -{ - return 0; -} - -static void CG_FeederSelection( float feederID, int index ) -{ - int i, count; - int team = ( feederID == FEEDER_ALIENTEAM_LIST ) ? PTE_ALIENS : PTE_HUMANS; - count = 0; - - for( i = 0; i < cg.numScores; i++ ) - { - if( cg.scores[ i ].team == team ) - { - if( index == count ) - cg.selectedScore = i; - - count++; - } - } -} - -static float CG_Cvar_Get( const char *cvar ) -{ - char buff[ 128 ]; - - memset( buff, 0, sizeof( buff ) ); - trap_Cvar_VariableStringBuffer( cvar, buff, sizeof( buff ) ); - return atof( buff ); -} - -void CG_Text_PaintWithCursor( float x, float y, float scale, vec4_t color, const char *text, - int cursorPos, char cursor, int limit, int style ) -{ - CG_Text_Paint( x, y, scale, color, text, 0, limit, style ); -} - -static int CG_OwnerDrawWidth( int ownerDraw, float scale ) -{ - switch( ownerDraw ) - { - case CG_KILLER: - return CG_Text_Width( CG_GetKillerText( ), scale, 0 ); - break; - } - - return 0; -} - -static int CG_PlayCinematic( const char *name, float x, float y, float w, float h ) -{ - return trap_CIN_PlayCinematic( name, x, y, w, h, CIN_loop ); -} - -static void CG_StopCinematic( int handle ) -{ - trap_CIN_StopCinematic( handle ); -} - -static void CG_DrawCinematic( int handle, float x, float y, float w, float h ) -{ - trap_CIN_SetExtents( handle, x, y, w, h ); - trap_CIN_DrawCinematic( handle ); -} - -static void CG_RunCinematicFrame( int handle ) -{ - trap_CIN_RunCinematic( handle ); -} - -//TA: hack to prevent warning -static qboolean CG_OwnerDrawVisible( int parameter ) -{ - return qfalse; -} - -/* -================= -CG_LoadHudMenu -================= -*/ -void CG_LoadHudMenu( void ) -{ - char buff[ 1024 ]; - const char *hudSet; - - cgDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip; - cgDC.setColor = &trap_R_SetColor; - cgDC.drawHandlePic = &CG_DrawPic; - cgDC.drawStretchPic = &trap_R_DrawStretchPic; - cgDC.drawText = &CG_Text_Paint; - cgDC.textWidth = &CG_Text_Width; - cgDC.textHeight = &CG_Text_Height; - cgDC.registerModel = &trap_R_RegisterModel; - cgDC.modelBounds = &trap_R_ModelBounds; - cgDC.fillRect = &CG_FillRect; - cgDC.drawRect = &CG_DrawRect; - cgDC.drawSides = &CG_DrawSides; - cgDC.drawTopBottom = &CG_DrawTopBottom; - cgDC.clearScene = &trap_R_ClearScene; - cgDC.addRefEntityToScene = &trap_R_AddRefEntityToScene; - cgDC.renderScene = &trap_R_RenderScene; - cgDC.registerFont = &trap_R_RegisterFont; - cgDC.ownerDrawItem = &CG_OwnerDraw; - cgDC.getValue = &CG_GetValue; - cgDC.ownerDrawVisible = &CG_OwnerDrawVisible; - cgDC.runScript = &CG_RunMenuScript; - cgDC.getTeamColor = &CG_GetTeamColor; - cgDC.setCVar = trap_Cvar_Set; - cgDC.getCVarString = trap_Cvar_VariableStringBuffer; - cgDC.getCVarValue = CG_Cvar_Get; - cgDC.drawTextWithCursor = &CG_Text_PaintWithCursor; - //cgDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode; - //cgDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode; - cgDC.startLocalSound = &trap_S_StartLocalSound; - cgDC.ownerDrawHandleKey = &CG_OwnerDrawHandleKey; - cgDC.feederCount = &CG_FeederCount; - cgDC.feederItemImage = &CG_FeederItemImage; - cgDC.feederItemText = &CG_FeederItemText; - cgDC.feederSelection = &CG_FeederSelection; - //cgDC.setBinding = &trap_Key_SetBinding; - //cgDC.getBindingBuf = &trap_Key_GetBindingBuf; - //cgDC.keynumToStringBuf = &trap_Key_KeynumToStringBuf; - //cgDC.executeText = &trap_Cmd_ExecuteText; - cgDC.Error = &Com_Error; - cgDC.Print = &Com_Printf; - cgDC.ownerDrawWidth = &CG_OwnerDrawWidth; - //cgDC.Pause = &CG_Pause; - cgDC.registerSound = &trap_S_RegisterSound; - cgDC.startBackgroundTrack = &trap_S_StartBackgroundTrack; - cgDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack; - cgDC.playCinematic = &CG_PlayCinematic; - cgDC.stopCinematic = &CG_StopCinematic; - cgDC.drawCinematic = &CG_DrawCinematic; - cgDC.runCinematicFrame = &CG_RunCinematicFrame; - - Init_Display( &cgDC ); - - Menu_Reset( ); - - trap_Cvar_VariableStringBuffer( "cg_hudFiles", buff, sizeof( buff ) ); - hudSet = buff; - - if( hudSet[ 0 ] == '\0' ) - hudSet = "ui/hud.txt"; - - CG_LoadMenus( hudSet ); -} - -void CG_AssetCache( void ) -{ - cgDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR ); - cgDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR ); - cgDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN ); - cgDC.Assets.scrollBarArrowUp = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP ); - cgDC.Assets.scrollBarArrowLeft = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT ); - cgDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT ); - cgDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB ); - cgDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR ); - cgDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB ); -} - -/* -================= -CG_Init - -Called after every level change or subsystem restart -Will perform callbacks to make the loading info screen update. -================= -*/ -void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) -{ - const char *s; - - // clear everything - memset( &cgs, 0, sizeof( cgs ) ); - memset( &cg, 0, sizeof( cg ) ); - memset( cg_entities, 0, sizeof( cg_entities ) ); - - cg.clientNum = clientNum; - - cgs.processedSnapshotNum = serverMessageNum; - cgs.serverCommandSequence = serverCommandSequence; - - // load a few needed things before we do any screen updates - cgs.media.whiteShader = trap_R_RegisterShader( "white" ); - cgs.media.charsetShader = trap_R_RegisterShader( "gfx/2d/bigchars" ); - cgs.media.outlineShader = trap_R_RegisterShader( "outline" ); - - //inform UI to repress cursor whilst loading - trap_Cvar_Set( "ui_loading", "1" ); - - //TA: load overrides - BG_InitClassOverrides( ); - BG_InitBuildableOverrides( ); - - //TA: dyn memory - CG_InitMemory( ); - - CG_RegisterCvars( ); - - CG_InitConsoleCommands( ); - - //TA: moved up for LoadHudMenu - String_Init( ); - - //TA: TA UI - CG_AssetCache( ); - CG_LoadHudMenu( ); // load new hud stuff - - cg.weaponSelect = WP_NONE; - - // old servers - - // get the rendering configuration from the client system - trap_GetGlconfig( &cgs.glconfig ); - cgs.screenXScale = cgs.glconfig.vidWidth / 640.0; - cgs.screenYScale = cgs.glconfig.vidHeight / 480.0; - - // get the gamestate from the client system - trap_GetGameState( &cgs.gameState ); - - // check version - s = CG_ConfigString( CS_GAME_VERSION ); - - if( strcmp( s, GAME_VERSION ) ) - CG_Error( "Client/Server game mismatch: %s/%s", GAME_VERSION, s ); - - s = CG_ConfigString( CS_LEVEL_START_TIME ); - cgs.levelStartTime = atoi( s ); - - CG_ParseServerinfo( ); - - // load the new map - trap_CM_LoadMap( cgs.mapname ); - - cg.loading = qtrue; // force players to load instead of defer - - CG_LoadTrailSystems( ); - CG_UpdateMediaFraction( 0.05f ); - - CG_LoadParticleSystems( ); - CG_UpdateMediaFraction( 0.05f ); - - CG_RegisterSounds( ); - CG_UpdateMediaFraction( 0.60f ); - - CG_RegisterGraphics( ); - CG_UpdateMediaFraction( 0.90f ); - - CG_InitWeapons( ); - CG_UpdateMediaFraction( 0.95f ); - - CG_InitUpgrades( ); - CG_UpdateMediaFraction( 1.0f ); - - //TA: - CG_InitBuildables( ); - - CG_RegisterClients( ); // if low on memory, some clients will be deferred - - cg.loading = qfalse; // future players will be deferred - - CG_InitMarkPolys( ); - - // remove the last loading update - cg.infoScreenText[ 0 ] = 0; - - // Make sure we have update values (scores) - CG_SetConfigValues( ); - - CG_StartMusic( ); - - CG_ShaderStateChanged( ); - - trap_S_ClearLoopingSounds( qtrue ); - - cg.consoleValid = qtrue; - - trap_Cvar_Set( "ui_loading", "0" ); -} - -/* -================= -CG_Shutdown - -Called before every level change or subsystem restart -================= -*/ -void CG_Shutdown( void ) -{ - // some mods may need to do cleanup work here, - // like closing files or archiving session data -} diff --git a/mod/src/cgame/cg_marks.c b/mod/src/cgame/cg_marks.c deleted file mode 100644 index cc8979de..00000000 --- a/mod/src/cgame/cg_marks.c +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_marks.c -- wall marks - -/* - * 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" - -/* -=================================================================== - -MARK POLYS - -=================================================================== -*/ - - -markPoly_t cg_activeMarkPolys; // double linked list -markPoly_t *cg_freeMarkPolys; // single linked list -markPoly_t cg_markPolys[ MAX_MARK_POLYS ]; -static int markTotal; - -/* -=================== -CG_InitMarkPolys - -This is called at startup and for tournement restarts -=================== -*/ -void CG_InitMarkPolys( void ) -{ - int i; - - memset( cg_markPolys, 0, sizeof( cg_markPolys ) ); - - cg_activeMarkPolys.nextMark = &cg_activeMarkPolys; - cg_activeMarkPolys.prevMark = &cg_activeMarkPolys; - cg_freeMarkPolys = cg_markPolys; - - for( i = 0; i < MAX_MARK_POLYS - 1; i++ ) - cg_markPolys[ i ].nextMark = &cg_markPolys[ i + 1 ]; -} - - -/* -================== -CG_FreeMarkPoly -================== -*/ -void CG_FreeMarkPoly( markPoly_t *le ) -{ - if( !le->prevMark ) - CG_Error( "CG_FreeLocalEntity: not active" ); - - // remove from the doubly linked active list - le->prevMark->nextMark = le->nextMark; - le->nextMark->prevMark = le->prevMark; - - // the free list is only singly linked - le->nextMark = cg_freeMarkPolys; - cg_freeMarkPolys = le; -} - -/* -=================== -CG_AllocMark - -Will allways succeed, even if it requires freeing an old active mark -=================== -*/ -markPoly_t *CG_AllocMark( void ) -{ - markPoly_t *le; - int time; - - if( !cg_freeMarkPolys ) - { - // no free entities, so free the one at the end of the chain - // remove the oldest active entity - time = cg_activeMarkPolys.prevMark->time; - - while( cg_activeMarkPolys.prevMark && time == cg_activeMarkPolys.prevMark->time ) - CG_FreeMarkPoly( cg_activeMarkPolys.prevMark ); - } - - le = cg_freeMarkPolys; - cg_freeMarkPolys = cg_freeMarkPolys->nextMark; - - memset( le, 0, sizeof( *le ) ); - - // link into the active list - le->nextMark = cg_activeMarkPolys.nextMark; - le->prevMark = &cg_activeMarkPolys; - cg_activeMarkPolys.nextMark->prevMark = le; - cg_activeMarkPolys.nextMark = le; - return le; -} - - - -/* -================= -CG_ImpactMark - -origin should be a point within a unit of the plane -dir should be the plane normal - -temporary marks will not be stored or randomly oriented, but immediately -passed to the renderer. -================= -*/ -#define MAX_MARK_FRAGMENTS 128 -#define MAX_MARK_POINTS 384 - -void CG_ImpactMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, - float orientation, float red, float green, float blue, float alpha, - qboolean alphaFade, float radius, qboolean temporary ) -{ - vec3_t axis[ 3 ]; - float texCoordScale; - vec3_t originalPoints[ 4 ]; - byte colors[ 4 ]; - int i, j; - int numFragments; - markFragment_t markFragments[ MAX_MARK_FRAGMENTS ], *mf; - vec3_t markPoints[ MAX_MARK_POINTS ]; - vec3_t projection; - - if( !cg_addMarks.integer ) - return; - - if( radius <= 0 ) - CG_Error( "CG_ImpactMark called with <= 0 radius" ); - - //if ( markTotal >= MAX_MARK_POLYS ) { - // return; - //} - - // create the texture axis - VectorNormalize2( dir, axis[ 0 ] ); - PerpendicularVector( axis[ 1 ], axis[ 0 ] ); - RotatePointAroundVector( axis[ 2 ], axis[ 0 ], axis[ 1 ], orientation ); - CrossProduct( axis[ 0 ], axis[ 2 ], axis[ 1 ] ); - - texCoordScale = 0.5 * 1.0 / radius; - - // create the full polygon - for( i = 0; i < 3; i++ ) - { - originalPoints[ 0 ][ i ] = origin[ i ] - radius * axis[ 1 ][ i ] - radius * axis[ 2 ][ i ]; - originalPoints[ 1 ][ i ] = origin[ i ] + radius * axis[ 1 ][ i ] - radius * axis[ 2 ][ i ]; - originalPoints[ 2 ][ i ] = origin[ i ] + radius * axis[ 1 ][ i ] + radius * axis[ 2 ][ i ]; - originalPoints[ 3 ][ i ] = origin[ i ] - radius * axis[ 1 ][ i ] + radius * axis[ 2 ][ i ]; - } - - // get the fragments - VectorScale( dir, -20, projection ); - numFragments = trap_CM_MarkFragments( 4, (void *)originalPoints, - projection, MAX_MARK_POINTS, markPoints[ 0 ], - MAX_MARK_FRAGMENTS, markFragments ); - - colors[ 0 ] = red * 255; - colors[ 1 ] = green * 255; - colors[ 2 ] = blue * 255; - colors[ 3 ] = alpha * 255; - - for( i = 0, mf = markFragments; i < numFragments; i++, mf++ ) - { - polyVert_t *v; - polyVert_t verts[ MAX_VERTS_ON_POLY ]; - markPoly_t *mark; - - // we have an upper limit on the complexity of polygons - // that we store persistantly - if( mf->numPoints > MAX_VERTS_ON_POLY ) - mf->numPoints = MAX_VERTS_ON_POLY; - - for( j = 0, v = verts; j < mf->numPoints; j++, v++ ) - { - vec3_t delta; - - VectorCopy( markPoints[ mf->firstPoint + j ], v->xyz ); - - VectorSubtract( v->xyz, origin, delta ); - v->st[ 0 ] = 0.5 + DotProduct( delta, axis[ 1 ] ) * texCoordScale; - v->st[ 1 ] = 0.5 + DotProduct( delta, axis[ 2 ] ) * texCoordScale; - *(int *)v->modulate = *(int *)colors; - } - - // if it is a temporary (shadow) mark, add it immediately and forget about it - if( temporary ) - { - trap_R_AddPolyToScene( markShader, mf->numPoints, verts ); - continue; - } - - // otherwise save it persistantly - mark = CG_AllocMark( ); - mark->time = cg.time; - mark->alphaFade = alphaFade; - mark->markShader = markShader; - mark->poly.numVerts = mf->numPoints; - mark->color[ 0 ] = red; - mark->color[ 1 ] = green; - mark->color[ 2 ] = blue; - mark->color[ 3 ] = alpha; - memcpy( mark->verts, verts, mf->numPoints * sizeof( verts[ 0 ] ) ); - markTotal++; - } -} - - -/* -=============== -CG_AddMarks -=============== -*/ -#define MARK_TOTAL_TIME 10000 -#define MARK_FADE_TIME 1000 - -void CG_AddMarks( void ) -{ - int j; - markPoly_t *mp, *next; - int t; - int fade; - - if( !cg_addMarks.integer ) - return; - - mp = cg_activeMarkPolys.nextMark; - for ( ; mp != &cg_activeMarkPolys; mp = next ) - { - // grab next now, so if the local entity is freed we - // still have it - next = mp->nextMark; - - // see if it is time to completely remove it - if( cg.time > mp->time + MARK_TOTAL_TIME ) - { - CG_FreeMarkPoly( mp ); - continue; - } - - // fade all marks out with time - t = mp->time + MARK_TOTAL_TIME - cg.time; - if( t < MARK_FADE_TIME ) - { - fade = 255 * t / MARK_FADE_TIME; - if( mp->alphaFade ) - { - for( j = 0; j < mp->poly.numVerts; j++ ) - mp->verts[ j ].modulate[ 3 ] = fade; - } - else - { - for( j = 0; j < mp->poly.numVerts; j++ ) - { - mp->verts[ j ].modulate[ 0 ] = mp->color[ 0 ] * fade; - mp->verts[ j ].modulate[ 1 ] = mp->color[ 1 ] * fade; - mp->verts[ j ].modulate[ 2 ] = mp->color[ 2 ] * fade; - } - } - } - - trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts ); - } -} - diff --git a/mod/src/cgame/cg_mem.c b/mod/src/cgame/cg_mem.c deleted file mode 100644 index 959bd4b0..00000000 --- a/mod/src/cgame/cg_mem.c +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// -// cg_mem.c -// -// Golliwog: All rewritten to allow deallocation -// -// TA: (very) minor changes for client side operation -// thanks to Golliwog of Quake 3 Fortress ( http://www.q3f.com ) -// for this. - - -#include "cg_local.h" - -#define POOLSIZE (256 * 1024) -#define FREEMEMCOOKIE ((int)0xDEADBE3F) // Any unlikely to be used value -#define ROUNDBITS 31 // Round to 32 bytes - -struct freememnode -{ - // Size of ROUNDBITS - int cookie, size; // Size includes node (obviously) - struct freememnode *prev, *next; -}; - -static char memoryPool[ POOLSIZE ]; -static struct freememnode *freehead; -static int freemem; - -void *CG_Alloc( int size ) -{ - // Find a free block and allocate. - // Does two passes, attempts to fill same-sized free slot first. - - struct freememnode *fmn, *prev, *next, *smallest; - int allocsize, smallestsize; - char *endptr; - int *ptr; - - allocsize = ( size + sizeof(int) + ROUNDBITS ) & ~ROUNDBITS; // Round to 32-byte boundary - ptr = NULL; - - smallest = NULL; - smallestsize = POOLSIZE + 1; // Guaranteed not to miss any slots :) - for( fmn = freehead; fmn; fmn = fmn->next ) - { - if( fmn->cookie != FREEMEMCOOKIE ) - CG_Error( "CG_Alloc: Memory corruption detected!\n" ); - - if( fmn->size >= allocsize ) - { - // We've got a block - if( fmn->size == allocsize ) - { - // Same size, just remove - - prev = fmn->prev; - next = fmn->next; - if( prev ) - prev->next = next; // Point previous node to next - if( next ) - next->prev = prev; // Point next node to previous - if( fmn == freehead ) - freehead = next; // Set head pointer to next - ptr = (int *) fmn; - break; // Stop the loop, this is fine - } - else - { - // Keep track of the smallest free slot - if( fmn->size < smallestsize ) - { - smallest = fmn; - smallestsize = fmn->size; - } - } - } - } - - if( !ptr && smallest ) - { - // We found a slot big enough - smallest->size -= allocsize; - endptr = (char *) smallest + smallest->size; - ptr = (int *) endptr; - } - - if( ptr ) - { - freemem -= allocsize; - if( cg_debugAlloc.integer ) - CG_Printf( "CG_Alloc of %i bytes (%i left)\n", allocsize, freemem ); - memset( ptr, 0, allocsize ); - *ptr++ = allocsize; // Store a copy of size for deallocation - return( (void *) ptr ); - } - - CG_Error( "CG_Alloc: failed on allocation of %i bytes\n", size ); - return( NULL ); -} - -void CG_Free( void *ptr ) -{ - // Release allocated memory, add it to the free list. - - struct freememnode *fmn; - char *freeend; - int *freeptr; - - freeptr = ptr; - freeptr--; - - freemem += *freeptr; - if( cg_debugAlloc.integer ) - CG_Printf( "CG_Free of %i bytes (%i left)\n", *freeptr, freemem ); - - for( fmn = freehead; fmn; fmn = fmn->next ) - { - freeend = ((char *) fmn) + fmn->size; - if( freeend == (char *) freeptr ) - { - // Released block can be merged to an existing node - - fmn->size += *freeptr; // Add size of node. - return; - } - } - // No merging, add to head of list - - fmn = (struct freememnode *) freeptr; - fmn->size = *freeptr; // Set this first to avoid corrupting *freeptr - fmn->cookie = FREEMEMCOOKIE; - fmn->prev = NULL; - fmn->next = freehead; - freehead->prev = fmn; - freehead = fmn; -} - -void CG_InitMemory( void ) -{ - // Set up the initial node - - freehead = (struct freememnode *) memoryPool; - freehead->cookie = FREEMEMCOOKIE; - freehead->size = POOLSIZE; - freehead->next = NULL; - freehead->prev = NULL; - freemem = sizeof(memoryPool); -} - -void CG_DefragmentMemory( void ) -{ - // If there's a frenzy of deallocation and we want to - // allocate something big, this is useful. Otherwise... - // not much use. - - struct freememnode *startfmn, *endfmn, *fmn; - - for( startfmn = freehead; startfmn; ) - { - endfmn = (struct freememnode *)(((char *) startfmn) + startfmn->size); - for( fmn = freehead; fmn; ) - { - if( fmn->cookie != FREEMEMCOOKIE ) - CG_Error( "CG_DefragmentMemory: Memory corruption detected!\n" ); - - if( fmn == endfmn ) - { - // We can add fmn onto startfmn. - - if( fmn->prev ) - fmn->prev->next = fmn->next; - if( fmn->next ) - { - if( !(fmn->next->prev = fmn->prev) ) - freehead = fmn->next; // We're removing the head node - } - startfmn->size += fmn->size; - memset( fmn, 0, sizeof(struct freememnode) ); // A redundant call, really. - - startfmn = freehead; - endfmn = fmn = NULL; // Break out of current loop - } - else - fmn = fmn->next; - } - - if( endfmn ) - startfmn = startfmn->next; // endfmn acts as a 'restart' flag here - } -} diff --git a/mod/src/cgame/cg_particles.c b/mod/src/cgame/cg_particles.c deleted file mode 100644 index 64587360..00000000 --- a/mod/src/cgame/cg_particles.c +++ /dev/null @@ -1,2551 +0,0 @@ -// cg_particles.c -- the particle 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 baseParticleSystem_t baseParticleSystems[ MAX_BASEPARTICLE_SYSTEMS ]; -static baseParticleEjector_t baseParticleEjectors[ MAX_BASEPARTICLE_EJECTORS ]; -static baseParticle_t baseParticles[ MAX_BASEPARTICLES ]; -static int numBaseParticleSystems = 0; -static int numBaseParticleEjectors = 0; -static int numBaseParticles = 0; - -static particleSystem_t particleSystems[ MAX_PARTICLE_SYSTEMS ]; -static particleEjector_t particleEjectors[ MAX_PARTICLE_EJECTORS ]; -static particle_t particles[ MAX_PARTICLES ]; -static particle_t *sortedParticles[ MAX_PARTICLES ]; -static particle_t *radixBuffer[ MAX_PARTICLES ]; - -/* -=============== -CG_LerpValues - -Lerp between two values -=============== -*/ -static float CG_LerpValues( float a, float b, float f ) -{ - if( b == PARTICLES_SAME_AS_INITIAL ) - return a; - else - return ( (a) + (f) * ( (b) - (a) ) ); -} - -/* -=============== -CG_RandomiseValue - -Randomise some value by some variance -=============== -*/ -static float CG_RandomiseValue( float value, float variance ) -{ - if( value != 0.0f ) - return value * ( 1.0f + ( random( ) * variance ) ); - else - return random( ) * variance; -} - -/* -=============== -CG_SpreadVector - -Randomly spread a vector by some amount -=============== -*/ -static void CG_SpreadVector( vec3_t v, float spread ) -{ - vec3_t p, r1, r2; - float randomSpread = crandom( ) * spread; - float randomRotation = random( ) * 360.0f; - - PerpendicularVector( p, v ); - - RotatePointAroundVector( r1, p, v, randomSpread ); - RotatePointAroundVector( r2, v, r1, randomRotation ); - - VectorCopy( r2, v ); -} - -/* -=============== -CG_DestroyParticle - -Destroy an individual particle -=============== -*/ -static void CG_DestroyParticle( particle_t *p, vec3_t impactNormal ) -{ - //this particle has an onDeath particle system attached - if( p->class->onDeathSystemName[ 0 ] != '\0' ) - { - particleSystem_t *ps; - - ps = CG_SpawnNewParticleSystem( p->class->onDeathSystemHandle ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - if( impactNormal ) - CG_SetParticleSystemNormal( ps, impactNormal ); - - CG_SetAttachmentPoint( &ps->attachment, p->origin ); - CG_AttachToPoint( &ps->attachment ); - } - } - - p->valid = qfalse; - - //this gives other systems a couple of - //frames to realise the particle is gone - p->frameWhenInvalidated = cg.clientFrame; -} - -/* -=============== -CG_SpawnNewParticle - -Introduce a new particle into the world -=============== -*/ -static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *parent ) -{ - int i, j; - particle_t *p = NULL; - particleEjector_t *pe = parent; - particleSystem_t *ps = parent->parent; - vec3_t attachmentPoint, attachmentVelocity; - vec3_t transform[ 3 ]; - - for( i = 0; i < MAX_PARTICLES; i++ ) - { - p = &particles[ i ]; - - //FIXME: the + 1 may be unnecessary - if( !p->valid && cg.clientFrame > p->frameWhenInvalidated + 1 ) - { - memset( p, 0, sizeof( particle_t ) ); - - //found a free slot - p->class = bp; - p->parent = pe; - - p->birthTime = cg.time; - p->lifeTime = (int)CG_RandomiseValue( (float)bp->lifeTime, bp->lifeTimeRandFrac ); - - p->radius.delay = (int)CG_RandomiseValue( (float)bp->radius.delay, bp->radius.delayRandFrac ); - p->radius.initial = CG_RandomiseValue( bp->radius.initial, bp->radius.initialRandFrac ); - p->radius.final = CG_RandomiseValue( bp->radius.final, bp->radius.finalRandFrac ); - - p->alpha.delay = (int)CG_RandomiseValue( (float)bp->alpha.delay, bp->alpha.delayRandFrac ); - p->alpha.initial = CG_RandomiseValue( bp->alpha.initial, bp->alpha.initialRandFrac ); - p->alpha.final = CG_RandomiseValue( bp->alpha.final, bp->alpha.finalRandFrac ); - - p->rotation.delay = (int)CG_RandomiseValue( (float)bp->rotation.delay, bp->rotation.delayRandFrac ); - p->rotation.initial = CG_RandomiseValue( bp->rotation.initial, bp->rotation.initialRandFrac ); - p->rotation.final = CG_RandomiseValue( bp->rotation.final, bp->rotation.finalRandFrac ); - - p->dLightRadius.delay = - (int)CG_RandomiseValue( (float)bp->dLightRadius.delay, bp->dLightRadius.delayRandFrac ); - p->dLightRadius.initial = - CG_RandomiseValue( bp->dLightRadius.initial, bp->dLightRadius.initialRandFrac ); - p->dLightRadius.final = - CG_RandomiseValue( bp->dLightRadius.final, bp->dLightRadius.finalRandFrac ); - - p->colorDelay = CG_RandomiseValue( bp->colorDelay, bp->colorDelayRandFrac ); - - p->bounceMarkRadius = CG_RandomiseValue( bp->bounceMarkRadius, bp->bounceMarkRadiusRandFrac ); - p->bounceMarkCount = - round( CG_RandomiseValue( (float)bp->bounceMarkCount, bp->bounceMarkCountRandFrac ) ); - p->bounceSoundCount = - round( CG_RandomiseValue( (float)bp->bounceSoundCount, bp->bounceSoundCountRandFrac ) ); - - if( bp->numModels ) - { - p->model = bp->models[ rand( ) % bp->numModels ]; - - if( bp->modelAnimation.frameLerp < 0 ) - { - bp->modelAnimation.frameLerp = p->lifeTime / bp->modelAnimation.numFrames; - bp->modelAnimation.initialLerp = p->lifeTime / bp->modelAnimation.numFrames; - } - } - - if( !CG_AttachmentPoint( &ps->attachment, attachmentPoint ) ) - return NULL; - - VectorCopy( attachmentPoint, p->origin ); - - if( CG_AttachmentAxis( &ps->attachment, transform ) ) - { - vec3_t transDisplacement; - - VectorMatrixMultiply( bp->displacement, transform, transDisplacement ); - VectorAdd( p->origin, transDisplacement, p->origin ); - } - else - VectorAdd( p->origin, bp->displacement, p->origin ); - - for( j = 0; j <= 2; j++ ) - p->origin[ j ] += ( crandom( ) * bp->randDisplacement ); - - switch( bp->velMoveType ) - { - case PMT_STATIC: - if( bp->velMoveValues.dirType == PMD_POINT ) - VectorSubtract( bp->velMoveValues.point, p->origin, p->velocity ); - else if( bp->velMoveValues.dirType == PMD_LINEAR ) - VectorCopy( bp->velMoveValues.dir, p->velocity ); - break; - - case PMT_STATIC_TRANSFORM: - if( !CG_AttachmentAxis( &ps->attachment, transform ) ) - { - CG_Printf( S_COLOR_RED "ERROR: a particle with velocityType " - "static_transform is not attached to something which can " - "provide a transformation\n" ); - return NULL; - } - - if( bp->velMoveValues.dirType == PMD_POINT ) - { - vec3_t transPoint; - - VectorMatrixMultiply( bp->velMoveValues.point, transform, transPoint ); - VectorSubtract( transPoint, p->origin, p->velocity ); - } - else if( bp->velMoveValues.dirType == PMD_LINEAR ) - VectorMatrixMultiply( bp->velMoveValues.dir, transform, p->velocity ); - break; - - case PMT_TAG: - case PMT_CENT_ANGLES: - if( bp->velMoveValues.dirType == PMD_POINT ) - VectorSubtract( attachmentPoint, p->origin, p->velocity ); - else if( bp->velMoveValues.dirType == PMD_LINEAR ) - { - if( !CG_AttachmentDir( &ps->attachment, p->velocity ) ) - return NULL; - } - break; - - case PMT_NORMAL: - if( !ps->normalValid ) - { - CG_Printf( S_COLOR_RED "ERROR: a particle with velocityType " - "normal has no normal\n" ); - return NULL; - } - - VectorCopy( ps->normal, p->velocity ); - - //normal displacement - VectorNormalize( p->velocity ); - VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin ); - break; - } - - VectorNormalize( p->velocity ); - CG_SpreadVector( p->velocity, bp->velMoveValues.dirRandAngle ); - VectorScale( p->velocity, - CG_RandomiseValue( bp->velMoveValues.mag, bp->velMoveValues.magRandFrac ), - p->velocity ); - - if( CG_AttachmentVelocity( &ps->attachment, attachmentVelocity ) ) - { - VectorMA( p->velocity, - CG_RandomiseValue( bp->velMoveValues.parentVelFrac, - bp->velMoveValues.parentVelFracRandFrac ), attachmentVelocity, p->velocity ); - } - - p->lastEvalTime = cg.time; - - p->valid = qtrue; - - //this particle has a child particle system attached - if( bp->childSystemName[ 0 ] != '\0' ) - { - particleSystem_t *ps = CG_SpawnNewParticleSystem( bp->childSystemHandle ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentParticle( &ps->attachment, p ); - CG_AttachToParticle( &ps->attachment ); - } - } - - //this particle has a child trail system attached - if( bp->childTrailSystemName[ 0 ] != '\0' ) - { - trailSystem_t *ts = CG_SpawnNewTrailSystem( bp->childTrailSystemHandle ); - - if( CG_IsTrailSystemValid( &ts ) ) - { - CG_SetAttachmentParticle( &ts->frontAttachment, p ); - CG_AttachToParticle( &ts->frontAttachment ); - } - } - - break; - } - } - - return p; -} - - -/* -=============== -CG_SpawnNewParticles - -Check if there are any ejectors that should be -introducing new particles -=============== -*/ -static void CG_SpawnNewParticles( void ) -{ - int i, j; - particle_t *p; - particleSystem_t *ps; - particleEjector_t *pe; - baseParticleEjector_t *bpe; - float lerpFrac; - int count; - - for( i = 0; i < MAX_PARTICLE_EJECTORS; i++ ) - { - pe = &particleEjectors[ i ]; - ps = pe->parent; - - if( pe->valid ) - { - //a non attached particle system can't make particles - if( !CG_Attached( &ps->attachment ) ) - continue; - - bpe = particleEjectors[ i ].class; - - //if this system is scheduled for removal don't make any new particles - if( !ps->lazyRemove ) - { - while( pe->nextEjectionTime <= cg.time && - ( pe->count > 0 || pe->totalParticles == PARTICLES_INFINITE ) ) - { - for( j = 0; j < bpe->numParticles; j++ ) - CG_SpawnNewParticle( bpe->particles[ j ], pe ); - - if( pe->count > 0 ) - pe->count--; - - //calculate next ejection time - lerpFrac = 1.0 - ( (float)pe->count / (float)pe->totalParticles ); - pe->nextEjectionTime = cg.time + (int)CG_RandomiseValue( - CG_LerpValues( pe->ejectPeriod.initial, - pe->ejectPeriod.final, - lerpFrac ), - pe->ejectPeriod.randFrac ); - } - } - - if( pe->count == 0 || ps->lazyRemove ) - { - count = 0; - - //wait for child particles to die before declaring this pe invalid - for( j = 0; j < MAX_PARTICLES; j++ ) - { - p = &particles[ j ]; - - if( p->valid && p->parent == pe ) - count++; - } - - if( !count ) - pe->valid = qfalse; - } - } - } -} - - -/* -=============== -CG_SpawnNewParticleEjector - -Allocate a new particle ejector -=============== -*/ -static particleEjector_t *CG_SpawnNewParticleEjector( baseParticleEjector_t *bpe, - particleSystem_t *parent ) -{ - int i; - particleEjector_t *pe = NULL; - particleSystem_t *ps = parent; - - for( i = 0; i < MAX_PARTICLE_EJECTORS; i++ ) - { - pe = &particleEjectors[ i ]; - - if( !pe->valid ) - { - memset( pe, 0, sizeof( particleEjector_t ) ); - - //found a free slot - pe->class = bpe; - pe->parent = ps; - - pe->ejectPeriod.initial = bpe->eject.initial; - pe->ejectPeriod.final = bpe->eject.final; - pe->ejectPeriod.randFrac = bpe->eject.randFrac; - - pe->nextEjectionTime = cg.time + - (int)CG_RandomiseValue( (float)bpe->eject.delay, bpe->eject.delayRandFrac ); - pe->count = pe->totalParticles = - (int)round( CG_RandomiseValue( (float)bpe->totalParticles, bpe->totalParticlesRandFrac ) ); - - pe->valid = qtrue; - - if( cg_debugParticles.integer >= 1 ) - CG_Printf( "PE %s created\n", ps->class->name ); - - break; - } - } - - return pe; -} - - -/* -=============== -CG_SpawnNewParticleSystem - -Allocate a new particle system -=============== -*/ -particleSystem_t *CG_SpawnNewParticleSystem( qhandle_t psHandle ) -{ - int i, j; - particleSystem_t *ps = NULL; - baseParticleSystem_t *bps = &baseParticleSystems[ psHandle - 1 ]; - - if( !bps->registered ) - { - CG_Printf( S_COLOR_RED "ERROR: a particle system has not been registered yet\n" ); - return NULL; - } - - for( i = 0; i < MAX_PARTICLE_SYSTEMS; i++ ) - { - ps = &particleSystems[ i ]; - - if( !ps->valid ) - { - memset( ps, 0, sizeof( particleSystem_t ) ); - - //found a free slot - ps->class = bps; - - ps->valid = qtrue; - ps->lazyRemove = qfalse; - - for( j = 0; j < bps->numEjectors; j++ ) - CG_SpawnNewParticleEjector( bps->ejectors[ j ], ps ); - - if( cg_debugParticles.integer >= 1 ) - CG_Printf( "PS %s created\n", bps->name ); - - break; - } - } - - return ps; -} - -/* -=============== -CG_RegisterParticleSystem - -Load the shaders required for a particle system -=============== -*/ -qhandle_t CG_RegisterParticleSystem( char *name ) -{ - int i, j, k, l; - baseParticleSystem_t *bps; - baseParticleEjector_t *bpe; - baseParticle_t *bp; - - for( i = 0; i < MAX_BASEPARTICLE_SYSTEMS; i++ ) - { - bps = &baseParticleSystems[ i ]; - - if( !Q_stricmpn( bps->name, name, MAX_QPATH ) ) - { - //already registered - if( bps->registered ) - return i + 1; - - for( j = 0; j < bps->numEjectors; j++ ) - { - bpe = bps->ejectors[ j ]; - - for( l = 0; l < bpe->numParticles; l++ ) - { - bp = bpe->particles[ l ]; - - for( k = 0; k < bp->numFrames; k++ ) - bp->shaders[ k ] = trap_R_RegisterShader( bp->shaderNames[ k ] ); - - for( k = 0; k < bp->numModels; k++ ) - bp->models[ k ] = trap_R_RegisterModel( bp->modelNames[ k ] ); - - if( bp->bounceMarkName[ 0 ] != '\0' ) - bp->bounceMark = trap_R_RegisterShader( bp->bounceMarkName ); - - if( bp->bounceSoundName[ 0 ] != '\0' ) - bp->bounceSound = trap_S_RegisterSound( bp->bounceSoundName, qfalse ); - - //recursively register any children - if( bp->childSystemName[ 0 ] != '\0' ) - { - //don't care about a handle for children since - //the system deals with it - CG_RegisterParticleSystem( bp->childSystemName ); - } - - if( bp->onDeathSystemName[ 0 ] != '\0' ) - { - //don't care about a handle for children since - //the system deals with it - CG_RegisterParticleSystem( bp->onDeathSystemName ); - } - - if( bp->childTrailSystemName[ 0 ] != '\0' ) - bp->childTrailSystemHandle = CG_RegisterTrailSystem( bp->childTrailSystemName ); - } - } - - if( cg_debugParticles.integer >= 1 ) - CG_Printf( "Registered particle system %s\n", name ); - - bps->registered = qtrue; - - //avoid returning 0 - return i + 1; - } - } - - CG_Printf( S_COLOR_RED "ERROR: failed to register particle system %s\n", name ); - return 0; -} - - -/* -=============== -CG_ParseValueAndVariance - -Parse a value and its random variance -=============== -*/ -static void CG_ParseValueAndVariance( char *token, float *value, float *variance, qboolean allowNegative ) -{ - char valueBuffer[ 16 ]; - char varianceBuffer[ 16 ]; - char *variancePtr = NULL, *varEndPointer = NULL; - float localValue = 0.0f; - float localVariance = 0.0f; - - Q_strncpyz( valueBuffer, token, sizeof( valueBuffer ) ); - Q_strncpyz( varianceBuffer, token, sizeof( varianceBuffer ) ); - - variancePtr = strchr( valueBuffer, '~' ); - - //variance included - if( variancePtr ) - { - variancePtr[ 0 ] = '\0'; - variancePtr++; - - localValue = atof_neg( valueBuffer, allowNegative ); - - varEndPointer = strchr( variancePtr, '%' ); - - if( varEndPointer ) - { - varEndPointer[ 0 ] = '\0'; - localVariance = atof_neg( variancePtr, qfalse ) / 100.0f; - } - else - { - if( localValue != 0.0f ) - localVariance = atof_neg( variancePtr, qfalse ) / localValue; - else - localVariance = atof_neg( variancePtr, qfalse ); - } - } - else - localValue = atof_neg( valueBuffer, allowNegative ); - - if( value != NULL ) - *value = localValue; - - if( variance != NULL ) - *variance = localVariance; -} - -/* -=============== -CG_ParseColor -=============== -*/ -static qboolean CG_ParseColor( 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_ParseParticle - -Parse a particle section -=============== -*/ -static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) -{ - char *token; - float number, randFrac; - int i; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !token ) - break; - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "bounce" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "cull" ) ) - { - bp->bounceCull = qtrue; - - bp->bounceFrac = -1.0f; - bp->bounceFracRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->bounceFrac = number; - bp->bounceFracRandFrac = randFrac; - } - - continue; - } - else if( !Q_stricmp( token, "bounceMark" ) ) - { - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->bounceMarkCount = number; - bp->bounceMarkCountRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->bounceMarkRadius = number; - bp->bounceMarkRadiusRandFrac = randFrac; - - token = COM_ParseExt( text_p, qfalse ); - if( !*token ) - break; - - Q_strncpyz( bp->bounceMarkName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "bounceSound" ) ) - { - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->bounceSoundCount = number; - bp->bounceSoundCountRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - Q_strncpyz( bp->bounceSoundName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "shader" ) ) - { - if( bp->numModels > 0 ) - { - CG_Printf( S_COLOR_RED "ERROR: 'shader' not allowed in " - "conjunction with 'model'\n", token ); - break; - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "sync" ) ) - bp->framerate = 0.0f; - else - bp->framerate = atof_neg( token, qfalse ); - - token = COM_ParseExt( text_p, qfalse ); - if( !*token ) - break; - - while( *token && bp->numFrames < MAX_PS_SHADER_FRAMES ) - { - Q_strncpyz( bp->shaderNames[ bp->numFrames++ ], token, MAX_QPATH ); - token = COM_ParseExt( text_p, qfalse ); - } - - continue; - } - else if( !Q_stricmp( token, "model" ) ) - { - if( bp->numFrames > 0 ) - { - CG_Printf( S_COLOR_RED "ERROR: 'model' not allowed in " - "conjunction with 'shader'\n", token ); - break; - } - - token = COM_ParseExt( text_p, qfalse ); - if( !*token ) - break; - - while( *token && bp->numModels < MAX_PS_MODELS ) - { - Q_strncpyz( bp->modelNames[ bp->numModels++ ], token, MAX_QPATH ); - token = COM_ParseExt( text_p, qfalse ); - } - - continue; - } - else if( !Q_stricmp( token, "modelAnimation" ) ) - { - token = COM_Parse( text_p ); - if( !*token ) - break; - - bp->modelAnimation.firstFrame = atoi_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !*token ) - break; - - bp->modelAnimation.numFrames = atoi( token ); - bp->modelAnimation.reversed = qfalse; - bp->modelAnimation.flipflop = qfalse; - - // if numFrames is negative the animation is reversed - if( bp->modelAnimation.numFrames < 0 ) - { - bp->modelAnimation.numFrames = -bp->modelAnimation.numFrames; - bp->modelAnimation.reversed = qtrue; - } - - token = COM_Parse( text_p ); - if( !*token ) - break; - - bp->modelAnimation.loopFrames = atoi( token ); - - token = COM_Parse( text_p ); - if( !*token ) - break; - - if( !Q_stricmp( token, "sync" ) ) - { - bp->modelAnimation.frameLerp = -1; - bp->modelAnimation.initialLerp = -1; - } - else - { - float fps = atof_neg( token, qfalse ); - - if( fps == 0.0f ) - fps = 1.0f; - - bp->modelAnimation.frameLerp = 1000 / fps; - bp->modelAnimation.initialLerp = 1000 / fps; - } - - continue; - } - /// - else if( !Q_stricmp( token, "velocityType" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "static" ) ) - bp->velMoveType = PMT_STATIC; - else if( !Q_stricmp( token, "static_transform" ) ) - bp->velMoveType = PMT_STATIC_TRANSFORM; - else if( !Q_stricmp( token, "tag" ) ) - bp->velMoveType = PMT_TAG; - else if( !Q_stricmp( token, "cent" ) ) - bp->velMoveType = PMT_CENT_ANGLES; - else if( !Q_stricmp( token, "normal" ) ) - bp->velMoveType = PMT_NORMAL; - - continue; - } - else if( !Q_stricmp( token, "velocityDir" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "linear" ) ) - bp->velMoveValues.dirType = PMD_LINEAR; - else if( !Q_stricmp( token, "point" ) ) - bp->velMoveValues.dirType = PMD_POINT; - - continue; - } - else if( !Q_stricmp( token, "velocityMagnitude" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->velMoveValues.mag = number; - bp->velMoveValues.magRandFrac = randFrac; - - continue; - } - else if( !Q_stricmp( token, "parentVelocityFraction" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->velMoveValues.parentVelFrac = number; - bp->velMoveValues.parentVelFracRandFrac = randFrac; - - continue; - } - else if( !Q_stricmp( token, "velocity" ) ) - { - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->velMoveValues.dir[ i ] = atof_neg( token, qtrue ); - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &randFrac, qfalse ); - - bp->velMoveValues.dirRandAngle = randFrac; - - continue; - } - else if( !Q_stricmp( token, "velocityPoint" ) ) - { - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->velMoveValues.point[ i ] = atof_neg( token, qtrue ); - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &randFrac, qfalse ); - - bp->velMoveValues.pointRandAngle = randFrac; - - continue; - } - /// - else if( !Q_stricmp( token, "accelerationType" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "static" ) ) - bp->accMoveType = PMT_STATIC; - else if( !Q_stricmp( token, "static_transform" ) ) - bp->accMoveType = PMT_STATIC_TRANSFORM; - else if( !Q_stricmp( token, "tag" ) ) - bp->accMoveType = PMT_TAG; - else if( !Q_stricmp( token, "cent" ) ) - bp->accMoveType = PMT_CENT_ANGLES; - else if( !Q_stricmp( token, "normal" ) ) - bp->accMoveType = PMT_NORMAL; - - continue; - } - else if( !Q_stricmp( token, "accelerationDir" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "linear" ) ) - bp->accMoveValues.dirType = PMD_LINEAR; - else if( !Q_stricmp( token, "point" ) ) - bp->accMoveValues.dirType = PMD_POINT; - - continue; - } - else if( !Q_stricmp( token, "accelerationMagnitude" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->accMoveValues.mag = number; - bp->accMoveValues.magRandFrac = randFrac; - - continue; - } - else if( !Q_stricmp( token, "acceleration" ) ) - { - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->accMoveValues.dir[ i ] = atof_neg( token, qtrue ); - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &randFrac, qfalse ); - - bp->accMoveValues.dirRandAngle = randFrac; - - continue; - } - else if( !Q_stricmp( token, "accelerationPoint" ) ) - { - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->accMoveValues.point[ i ] = atof_neg( token, qtrue ); - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &randFrac, qfalse ); - - bp->accMoveValues.pointRandAngle = randFrac; - - continue; - } - /// - else if( !Q_stricmp( token, "displacement" ) ) - { - for( i = 0; i <= 2; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->displacement[ i ] = atof_neg( token, qtrue ); - } - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &randFrac, qfalse ); - - bp->randDisplacement = randFrac; - - continue; - } - else if( !Q_stricmp( token, "normalDisplacement" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bp->normalDisplacement = atof_neg( token, qtrue ); - - continue; - } - else if( !Q_stricmp( token, "overdrawProtection" ) ) - { - bp->overdrawProtection = qtrue; - - continue; - } - else if( !Q_stricmp( token, "realLight" ) ) - { - bp->realLight = qtrue; - - continue; - } - else if( !Q_stricmp( token, "dynamicLight" ) ) - { - bp->dynamicLight = qtrue; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->dLightRadius.delay = (int)number; - bp->dLightRadius.delayRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->dLightRadius.initial = number; - bp->dLightRadius.initialRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - bp->dLightRadius.final = PARTICLES_SAME_AS_INITIAL; - bp->dLightRadius.finalRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->dLightRadius.final = number; - bp->dLightRadius.finalRandFrac = randFrac; - } - - token = COM_Parse( text_p ); - if( !*token ) - break; - - if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseColor( bp->dLightColor, text_p ) ) - break; - - token = COM_Parse( text_p ); - if( Q_stricmp( token, "}" ) ) - { - CG_Printf( S_COLOR_RED "ERROR: missing '}'\n" ); - break; - } - } - - continue; - } - else if( !Q_stricmp( token, "cullOnStartSolid" ) ) - { - bp->cullOnStartSolid = qtrue; - - continue; - } - else if( !Q_stricmp( token, "radius" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->radius.delay = (int)number; - bp->radius.delayRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->radius.initial = number; - bp->radius.initialRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - bp->radius.final = PARTICLES_SAME_AS_INITIAL; - bp->radius.finalRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->radius.final = number; - bp->radius.finalRandFrac = randFrac; - } - - continue; - } - else if( !Q_stricmp( token, "alpha" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->alpha.delay = (int)number; - bp->alpha.delayRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->alpha.initial = number; - bp->alpha.initialRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - bp->alpha.final = PARTICLES_SAME_AS_INITIAL; - bp->alpha.finalRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->alpha.final = number; - bp->alpha.finalRandFrac = randFrac; - } - - continue; - } - else if( !Q_stricmp( token, "color" ) ) - { - token = COM_Parse( text_p ); - if( !*token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->colorDelay = (int)number; - bp->colorDelayRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !*token ) - break; - - if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseColor( bp->initialColor, 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( !*token ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - bp->finalColor[ 0 ] = bp->initialColor[ 0 ]; - bp->finalColor[ 1 ] = bp->initialColor[ 1 ]; - bp->finalColor[ 2 ] = bp->initialColor[ 2 ]; - } - else if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseColor( bp->finalColor, 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, "rotation" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->rotation.delay = (int)number; - bp->rotation.delayRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qtrue ); - - bp->rotation.initial = number; - bp->rotation.initialRandFrac = randFrac; - - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "-" ) ) - { - bp->rotation.final = PARTICLES_SAME_AS_INITIAL; - bp->rotation.finalRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qtrue ); - - bp->rotation.final = number; - bp->rotation.finalRandFrac = randFrac; - } - - continue; - } - else if( !Q_stricmp( token, "lifeTime" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bp->lifeTime = (int)number; - bp->lifeTimeRandFrac = randFrac; - - continue; - } - else if( !Q_stricmp( token, "childSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - Q_strncpyz( bp->childSystemName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "onDeathSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - Q_strncpyz( bp->onDeathSystemName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "childTrailSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - Q_strncpyz( bp->childTrailSystemName, token, MAX_QPATH ); - - continue; - } - else if( !Q_stricmp( token, "}" ) ) - return qtrue; //reached the end of this particle - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in particle\n", token ); - return qfalse; - } - } - - return qfalse; -} - -/* -=============== -CG_InitialiseBaseParticle -=============== -*/ -static void CG_InitialiseBaseParticle( baseParticle_t *bp ) -{ - memset( bp, 0, sizeof( baseParticle_t ) ); - - memset( bp->initialColor, 0xFF, sizeof( bp->initialColor ) ); - memset( bp->finalColor, 0xFF, sizeof( bp->finalColor ) ); -} - -/* -=============== -CG_ParseParticleEjector - -Parse a particle ejector section -=============== -*/ -static qboolean CG_ParseParticleEjector( baseParticleEjector_t *bpe, char **text_p ) -{ - char *token; - float number, randFrac; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !token ) - break; - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "{" ) ) - { - CG_InitialiseBaseParticle( &baseParticles[ numBaseParticles ] ); - - if( !CG_ParseParticle( &baseParticles[ numBaseParticles ], text_p ) ) - { - CG_Printf( S_COLOR_RED "ERROR: failed to parse particle\n" ); - return qfalse; - } - - if( bpe->numParticles == MAX_PARTICLES_PER_EJECTOR ) - { - CG_Printf( S_COLOR_RED "ERROR: ejector has > %d particles\n", MAX_PARTICLES_PER_EJECTOR ); - return qfalse; - } - else if( numBaseParticles == MAX_BASEPARTICLES ) - { - CG_Printf( S_COLOR_RED "ERROR: maximum number of particles (%d) reached\n", MAX_BASEPARTICLES ); - return qfalse; - } - else - { - //start parsing particles again - bpe->particles[ bpe->numParticles ] = &baseParticles[ numBaseParticles ]; - bpe->numParticles++; - numBaseParticles++; - } - continue; - } - else if( !Q_stricmp( token, "delay" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bpe->eject.delay = (int)number; - bpe->eject.delayRandFrac = randFrac; - - continue; - } - else if( !Q_stricmp( token, "period" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - bpe->eject.initial = atoi_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "-" ) ) - bpe->eject.final = PARTICLES_SAME_AS_INITIAL; - else - bpe->eject.final = atoi_neg( token, qfalse ); - - token = COM_Parse( text_p ); - if( !token ) - break; - - CG_ParseValueAndVariance( token, NULL, &bpe->eject.randFrac, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "count" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "infinite" ) ) - { - bpe->totalParticles = PARTICLES_INFINITE; - bpe->totalParticlesRandFrac = 0.0f; - } - else - { - CG_ParseValueAndVariance( token, &number, &randFrac, qfalse ); - - bpe->totalParticles = (int)number; - bpe->totalParticlesRandFrac = randFrac; - } - - continue; - } - else if( !Q_stricmp( token, "particle" ) ) //acceptable text - continue; - else if( !Q_stricmp( token, "}" ) ) - return qtrue; //reached the end of this particle ejector - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in particle ejector\n", token ); - return qfalse; - } - } - - return qfalse; -} - - -/* -=============== -CG_ParseParticleSystem - -Parse a particle system section -=============== -*/ -static qboolean CG_ParseParticleSystem( baseParticleSystem_t *bps, char **text_p, const char *name ) -{ - char *token; - baseParticleEjector_t *bpe; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !token ) - break; - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "{" ) ) - { - if( !CG_ParseParticleEjector( &baseParticleEjectors[ numBaseParticleEjectors ], text_p ) ) - { - CG_Printf( S_COLOR_RED "ERROR: failed to parse particle ejector\n" ); - return qfalse; - } - - bpe = &baseParticleEjectors[ numBaseParticleEjectors ]; - - //check for infinite count + zero period - if( bpe->totalParticles == PARTICLES_INFINITE && - ( bpe->eject.initial == 0.0f || bpe->eject.final == 0.0f ) ) - { - CG_Printf( S_COLOR_RED "ERROR: ejector with 'count infinite' potentially has zero period\n" ); - return qfalse; - } - - if( bps->numEjectors == MAX_EJECTORS_PER_SYSTEM ) - { - CG_Printf( S_COLOR_RED "ERROR: particle system has > %d ejectors\n", MAX_EJECTORS_PER_SYSTEM ); - return qfalse; - } - else if( numBaseParticleEjectors == MAX_BASEPARTICLE_EJECTORS ) - { - CG_Printf( S_COLOR_RED "ERROR: maximum number of particle ejectors (%d) reached\n", - MAX_BASEPARTICLE_EJECTORS ); - return qfalse; - } - else - { - //start parsing ejectors again - bps->ejectors[ bps->numEjectors ] = &baseParticleEjectors[ numBaseParticleEjectors ]; - bps->numEjectors++; - numBaseParticleEjectors++; - } - continue; - } - else if( !Q_stricmp( token, "thirdPersonOnly" ) ) - bps->thirdPersonOnly = qtrue; - else if( !Q_stricmp( token, "ejector" ) ) //acceptable text - continue; - else if( !Q_stricmp( token, "}" ) ) - { - if( cg_debugParticles.integer >= 1 ) - CG_Printf( "Parsed particle system %s\n", name ); - - return qtrue; //reached the end of this particle system - } - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in particle system %s\n", token, bps->name ); - return qfalse; - } - } - - return qfalse; -} - -/* -=============== -CG_ParseParticleFile - -Load the particle systems from a particle file -=============== -*/ -static qboolean CG_ParseParticleFile( const char *fileName ) -{ - char *text_p; - int i; - int len; - char *token; - char text[ 32000 ]; - char psName[ MAX_QPATH ]; - qboolean psNameSet = 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: particle 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( psNameSet ) - { - //check for name space clashes - for( i = 0; i < numBaseParticleSystems; i++ ) - { - if( !Q_stricmp( baseParticleSystems[ i ].name, psName ) ) - { - CG_Printf( S_COLOR_RED "ERROR: a particle system is already named %s\n", psName ); - return qfalse; - } - } - - Q_strncpyz( baseParticleSystems[ numBaseParticleSystems ].name, psName, MAX_QPATH ); - - if( !CG_ParseParticleSystem( &baseParticleSystems[ numBaseParticleSystems ], &text_p, psName ) ) - { - CG_Printf( S_COLOR_RED "ERROR: %s: failed to parse particle system %s\n", fileName, psName ); - return qfalse; - } - - //start parsing particle systems again - psNameSet = qfalse; - - if( numBaseParticleSystems == MAX_BASEPARTICLE_SYSTEMS ) - { - CG_Printf( S_COLOR_RED "ERROR: maximum number of particle systems (%d) reached\n", - MAX_BASEPARTICLE_SYSTEMS ); - return qfalse; - } - else - numBaseParticleSystems++; - - continue; - } - else - { - CG_Printf( S_COLOR_RED "ERROR: unamed particle system\n" ); - return qfalse; - } - } - - if( !psNameSet ) - { - Q_strncpyz( psName, token, sizeof( psName ) ); - psNameSet = qtrue; - } - else - { - CG_Printf( S_COLOR_RED "ERROR: particle system already named\n" ); - return qfalse; - } - } - - return qtrue; -} - - -/* -=============== -CG_LoadParticleSystems - -Load particle systems from .particle files -=============== -*/ -void CG_LoadParticleSystems( void ) -{ - int i, j; - const char *s[ MAX_PARTICLE_FILES ]; - - //clear out the old - numBaseParticleSystems = 0; - numBaseParticleEjectors = 0; - numBaseParticles = 0; - - for( i = 0; i < MAX_BASEPARTICLE_SYSTEMS; i++ ) - { - baseParticleSystem_t *bps = &baseParticleSystems[ i ]; - memset( bps, 0, sizeof( baseParticleSystem_t ) ); - } - - for( i = 0; i < MAX_BASEPARTICLE_EJECTORS; i++ ) - { - baseParticleEjector_t *bpe = &baseParticleEjectors[ i ]; - memset( bpe, 0, sizeof( baseParticleEjector_t ) ); - } - - for( i = 0; i < MAX_BASEPARTICLES; i++ ) - { - baseParticle_t *bp = &baseParticles[ i ]; - memset( bp, 0, sizeof( baseParticle_t ) ); - } - - - //and bring in the new - for( i = 0; i < MAX_PARTICLE_FILES; i++ ) - { - s[ i ] = CG_ConfigString( CS_PARTICLE_FILES + i ); - - if( strlen( s[ i ] ) > 0 ) - { - CG_Printf( "...loading '%s'\n", s[ i ] ); - CG_ParseParticleFile( s[ i ] ); - } - else - break; - } - - //connect any child systems to their psHandle - for( i = 0; i < numBaseParticles; i++ ) - { - baseParticle_t *bp = &baseParticles[ i ]; - - if( bp->childSystemName[ 0 ] ) - { - //particle class has a child, resolve the name - for( j = 0; j < numBaseParticleSystems; j++ ) - { - baseParticleSystem_t *bps = &baseParticleSystems[ j ]; - - if( !Q_stricmp( bps->name, bp->childSystemName ) ) - { - //FIXME: add checks for cycles and infinite children - - bp->childSystemHandle = j + 1; - - break; - } - } - - if( j == numBaseParticleSystems ) - { - //couldn't find named particle system - CG_Printf( S_COLOR_YELLOW "WARNING: failed to find child %s\n", bp->childSystemName ); - bp->childSystemName[ 0 ] = '\0'; - } - } - - if( bp->onDeathSystemName[ 0 ] ) - { - //particle class has a child, resolve the name - for( j = 0; j < numBaseParticleSystems; j++ ) - { - baseParticleSystem_t *bps = &baseParticleSystems[ j ]; - - if( !Q_stricmp( bps->name, bp->onDeathSystemName ) ) - { - //FIXME: add checks for cycles and infinite children - - bp->onDeathSystemHandle = j + 1; - - break; - } - } - - if( j == numBaseParticleSystems ) - { - //couldn't find named particle system - CG_Printf( S_COLOR_YELLOW "WARNING: failed to find onDeath system %s\n", bp->onDeathSystemName ); - bp->onDeathSystemName[ 0 ] = '\0'; - } - } - } -} - -/* -=============== -CG_SetParticleSystemNormal -=============== -*/ -void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal ) -{ - if( ps == NULL || !ps->valid ) - { - CG_Printf( S_COLOR_YELLOW "WARNING: tried to modify a NULL particle system\n" ); - return; - } - - ps->normalValid = qtrue; - VectorCopy( normal, ps->normal ); - VectorNormalize( ps->normal ); -} - - -/* -=============== -CG_DestroyParticleSystem - -Destroy a particle system - -This doesn't actually invalidate anything, it just stops -particle ejectors from producing new particles so the -garbage collector will eventually remove this system. -However is does set the pointer to NULL so the user is -unable to manipulate this particle system any longer. -=============== -*/ -void CG_DestroyParticleSystem( particleSystem_t **ps ) -{ - int i; - particleEjector_t *pe; - - if( *ps == NULL || !(*ps)->valid ) - { - CG_Printf( S_COLOR_YELLOW "WARNING: tried to destroy a NULL particle system\n" ); - return; - } - - if( cg_debugParticles.integer >= 1 ) - CG_Printf( "PS destroyed\n" ); - - for( i = 0; i < MAX_PARTICLE_EJECTORS; i++ ) - { - pe = &particleEjectors[ i ]; - - if( pe->valid && pe->parent == *ps ) - pe->totalParticles = pe->count = 0; - } - - *ps = NULL; -} - -/* -=============== -CG_IsParticleSystemInfinite - -Test a particle system for 'count infinite' ejectors -=============== -*/ -qboolean CG_IsParticleSystemInfinite( particleSystem_t *ps ) -{ - int i; - particleEjector_t *pe; - - if( ps == NULL ) - { - CG_Printf( S_COLOR_YELLOW "WARNING: tried to test a NULL particle system\n" ); - return qfalse; - } - - if( !ps->valid ) - { - CG_Printf( S_COLOR_YELLOW "WARNING: tried to test an invalid particle system\n" ); - return qfalse; - } - - //don't bother checking already invalid systems - if( !ps->valid ) - return qfalse; - - for( i = 0; i < MAX_PARTICLE_EJECTORS; i++ ) - { - pe = &particleEjectors[ i ]; - - if( pe->valid && pe->parent == ps ) - { - if( pe->totalParticles == PARTICLES_INFINITE ) - return qtrue; - } - } - - return qfalse; -} - -/* -=============== -CG_IsParticleSystemValid - -Test a particle system for validity -=============== -*/ -qboolean CG_IsParticleSystemValid( particleSystem_t **ps ) -{ - if( *ps == NULL || ( *ps && !(*ps)->valid ) ) - { - if( *ps && !(*ps)->valid ) - *ps = NULL; - - return qfalse; - } - - return qtrue; -} - -/* -=============== -CG_GarbageCollectParticleSystems - -Destroy inactive particle systems -=============== -*/ -static void CG_GarbageCollectParticleSystems( void ) -{ - int i, j, count; - particleSystem_t *ps; - particleEjector_t *pe; - int centNum; - - for( i = 0; i < MAX_PARTICLE_SYSTEMS; i++ ) - { - ps = &particleSystems[ i ]; - count = 0; - - //don't bother checking already invalid systems - if( !ps->valid ) - continue; - - for( j = 0; j < MAX_PARTICLE_EJECTORS; j++ ) - { - pe = &particleEjectors[ j ]; - - if( pe->valid && pe->parent == ps ) - count++; - } - - if( !count ) - ps->valid = qfalse; - - //check systems where the parent cent has left the PVS - //( local player entity is always valid ) - if( ( centNum = CG_AttachmentCentNum( &ps->attachment ) ) >= 0 && - centNum != cg.snap->ps.clientNum ) - { - if( !cg_entities[ centNum ].valid ) - ps->lazyRemove = qtrue; - } - - if( cg_debugParticles.integer >= 1 && !ps->valid ) - CG_Printf( "PS %s garbage collected\n", ps->class->name ); - } -} - - -/* -=============== -CG_CalculateTimeFrac - -Calculate the fraction of time passed -=============== -*/ -static float CG_CalculateTimeFrac( int birth, int life, int delay ) -{ - float frac; - - frac = ( (float)cg.time - (float)( birth + delay ) ) / (float)( life - delay ); - - if( frac < 0.0f ) - frac = 0.0f; - else if( frac > 1.0f ) - frac = 1.0f; - - return frac; -} - -/* -=============== -CG_EvaluateParticlePhysics - -Compute the physics on a specific particle -=============== -*/ -static void CG_EvaluateParticlePhysics( particle_t *p ) -{ - particleSystem_t *ps = p->parent->parent; - baseParticle_t *bp = p->class; - vec3_t acceleration, newOrigin; - vec3_t mins, maxs; - float deltaTime, bounce, radius, dot; - trace_t trace; - vec3_t transform[ 3 ]; - - if( p->atRest ) - { - VectorClear( p->velocity ); - return; - } - - switch( bp->accMoveType ) - { - case PMT_STATIC: - if( bp->accMoveValues.dirType == PMD_POINT ) - VectorSubtract( bp->accMoveValues.point, p->origin, acceleration ); - else if( bp->accMoveValues.dirType == PMD_LINEAR ) - VectorCopy( bp->accMoveValues.dir, acceleration ); - - break; - - case PMT_STATIC_TRANSFORM: - if( !CG_AttachmentAxis( &ps->attachment, transform ) ) - { - CG_Printf( S_COLOR_RED "ERROR: a particle with accelerationType " - "static_transform is not attached to something which can " - "provide a transformation\n" ); - return; - } - - if( bp->accMoveValues.dirType == PMD_POINT ) - { - vec3_t transPoint; - - VectorMatrixMultiply( bp->accMoveValues.point, transform, transPoint ); - VectorSubtract( transPoint, p->origin, acceleration ); - } - else if( bp->accMoveValues.dirType == PMD_LINEAR ) - VectorMatrixMultiply( bp->accMoveValues.dir, transform, acceleration ); - break; - - case PMT_TAG: - case PMT_CENT_ANGLES: - if( bp->accMoveValues.dirType == PMD_POINT ) - { - vec3_t point; - - if( !CG_AttachmentPoint( &ps->attachment, point ) ) - return; - - VectorSubtract( point, p->origin, acceleration ); - } - else if( bp->accMoveValues.dirType == PMD_LINEAR ) - { - if( !CG_AttachmentDir( &ps->attachment, acceleration ) ) - return; - } - break; - - case PMT_NORMAL: - if( !ps->normalValid ) - return; - - VectorCopy( ps->normal, acceleration ); - - break; - } - -#define MAX_ACC_RADIUS 1000.0f - - if( bp->accMoveValues.dirType == PMD_POINT ) - { - //FIXME: so this fall off is a bit... odd -- it works.. - float r2 = DotProduct( acceleration, acceleration ); // = radius^2 - float scale = ( MAX_ACC_RADIUS - r2 ) / MAX_ACC_RADIUS; - - if( scale > 1.0f ) - scale = 1.0f; - else if( scale < 0.1f ) - scale = 0.1f; - - scale *= CG_RandomiseValue( bp->accMoveValues.mag, bp->accMoveValues.magRandFrac ); - - VectorNormalize( acceleration ); - CG_SpreadVector( acceleration, bp->accMoveValues.dirRandAngle ); - VectorScale( acceleration, scale, acceleration ); - } - else if( bp->accMoveValues.dirType == PMD_LINEAR ) - { - VectorNormalize( acceleration ); - CG_SpreadVector( acceleration, bp->accMoveValues.dirRandAngle ); - VectorScale( acceleration, - CG_RandomiseValue( bp->accMoveValues.mag, bp->accMoveValues.magRandFrac ), - acceleration ); - } - - radius = CG_LerpValues( p->radius.initial, - p->radius.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->radius.delay ) ); - - VectorSet( mins, -radius, -radius, -radius ); - VectorSet( maxs, radius, radius, radius ); - - bounce = CG_RandomiseValue( bp->bounceFrac, bp->bounceFracRandFrac ); - - deltaTime = (float)( cg.time - p->lastEvalTime ) * 0.001; - VectorMA( p->velocity, deltaTime, acceleration, p->velocity ); - VectorMA( p->origin, deltaTime, p->velocity, newOrigin ); - p->lastEvalTime = cg.time; - - CG_Trace( &trace, p->origin, mins, maxs, newOrigin, - CG_AttachmentCentNum( &ps->attachment ), CONTENTS_SOLID ); - - //not hit anything or not a collider - if( trace.fraction == 1.0f || bounce == 0.0f ) - { - VectorCopy( newOrigin, p->origin ); - return; - } - - //remove particles that get into a CONTENTS_NODROP brush - if( ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) || - ( bp->cullOnStartSolid && trace.startsolid ) ) - { - CG_DestroyParticle( p, NULL ); - return; - } - else if( bp->bounceCull ) - { - CG_DestroyParticle( p, trace.plane.normal ); - return; - } - - //reflect the velocity on the trace plane - dot = DotProduct( p->velocity, trace.plane.normal ); - VectorMA( p->velocity, -2.0f * dot, trace.plane.normal, p->velocity ); - - VectorScale( p->velocity, bounce, p->velocity ); - - if( trace.plane.normal[ 2 ] > 0.5f && - ( p->velocity[ 2 ] < 40.0f || - p->velocity[ 2 ] < -cg.frametime * p->velocity[ 2 ] ) ) - p->atRest = qtrue; - - if( bp->bounceMarkName[ 0 ] && p->bounceMarkCount > 0 ) - { - CG_ImpactMark( bp->bounceMark, trace.endpos, trace.plane.normal, - random( ) * 360, 1, 1, 1, 1, qtrue, bp->bounceMarkRadius, qfalse ); - p->bounceMarkCount--; - } - - if( bp->bounceSoundName[ 0 ] && p->bounceSoundCount > 0 ) - { - trap_S_StartSound( trace.endpos, ENTITYNUM_WORLD, CHAN_AUTO, bp->bounceSound ); - p->bounceSoundCount--; - } - - VectorCopy( trace.endpos, p->origin ); -} - - -#define GETKEY(x,y) (((x)>>y)&0xFF) - -/* -=============== -CG_Radix -=============== -*/ -static void CG_Radix( int bits, int size, particle_t **source, particle_t **dest ) -{ - int count[ 256 ]; - int index[ 256 ]; - int i; - - memset( count, 0, sizeof( count ) ); - - for( i = 0; i < size; i++ ) - count[ GETKEY( source[ i ]->sortKey, bits ) ]++; - - index[ 0 ] = 0; - - for( i = 1; i < 256; i++ ) - index[ i ] = index[ i - 1 ] + count[ i - 1 ]; - - for( i = 0; i < size; i++ ) - dest[ index[ GETKEY( source[ i ]->sortKey, bits ) ]++ ] = source[ i ]; -} - -/* -=============== -CG_RadixSort - -Radix sort with 4 byte size buckets -=============== -*/ -static void CG_RadixSort( particle_t **source, particle_t **temp, int size ) -{ - CG_Radix( 0, size, source, temp ); - CG_Radix( 8, size, temp, source ); - CG_Radix( 16, size, source, temp ); - CG_Radix( 24, size, temp, source ); -} - -/* -=============== -CG_CompactAndSortParticles - -Depth sort the particles -=============== -*/ -static void CG_CompactAndSortParticles( void ) -{ - int i, j = 0; - int numParticles; - vec3_t delta; - - for( i = 0; i < MAX_PARTICLES; i++ ) - sortedParticles[ i ] = &particles[ i ]; - - for( i = MAX_PARTICLES - 1; i >= 0; i-- ) - { - if( sortedParticles[ i ]->valid ) - { - //find the first hole - while( sortedParticles[ j ]->valid ) - j++; - - //no more holes - if( j >= i ) - break; - - sortedParticles[ j ] = sortedParticles[ i ]; - } - } - - numParticles = i; - - //set sort keys - for( i = 0; i < numParticles; i++ ) - { - VectorSubtract( sortedParticles[ i ]->origin, cg.refdef.vieworg, delta ); - sortedParticles[ i ]->sortKey = (int)DotProduct( delta, delta ); - } - - CG_RadixSort( sortedParticles, radixBuffer, numParticles ); - - //FIXME: wtf? - //reverse order of particles array - for( i = 0; i < numParticles; i++ ) - radixBuffer[ i ] = sortedParticles[ numParticles - i - 1 ]; - - for( i = 0; i < numParticles; i++ ) - sortedParticles[ i ] = radixBuffer[ i ]; -} - -/* -=============== -CG_RenderParticle - -Actually render a particle -=============== -*/ -static void CG_RenderParticle( particle_t *p ) -{ - refEntity_t re; - float timeFrac, scale; - int index; - baseParticle_t *bp = p->class; - particleSystem_t *ps = p->parent->parent; - baseParticleSystem_t *bps = ps->class; - vec3_t alight, dlight, lightdir; - int i; - vec3_t up = { 0.0f, 0.0f, 1.0f }; - - memset( &re, 0, sizeof( refEntity_t ) ); - - timeFrac = CG_CalculateTimeFrac( p->birthTime, p->lifeTime, 0 ); - - scale = CG_LerpValues( p->radius.initial, - p->radius.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->radius.delay ) ); - - re.shaderTime = p->birthTime / 1000.0f; - - if( bp->numFrames ) //shader based - { - re.reType = RT_SPRITE; - - //apply environmental lighting to the particle - if( bp->realLight ) - { - trap_R_LightForPoint( p->origin, alight, dlight, lightdir ); - for( i = 0; i <= 2; i++ ) - re.shaderRGBA[ i ] = (byte)alight[ i ]; - } - else - { - vec3_t colorRange; - - VectorSubtract( bp->finalColor, - bp->initialColor, colorRange ); - - VectorMA( bp->initialColor, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->colorDelay ), - colorRange, re.shaderRGBA ); - } - - re.shaderRGBA[ 3 ] = (byte)( (float)0xFF * - CG_LerpValues( p->alpha.initial, - p->alpha.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->alpha.delay ) ) ); - - re.radius = scale; - - re.rotation = CG_LerpValues( p->rotation.initial, - p->rotation.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->rotation.delay ) ); - - // if the view would be "inside" the sprite, kill the sprite - // so it doesn't add too much overdraw - if( Distance( p->origin, cg.refdef.vieworg ) < re.radius && bp->overdrawProtection ) - return; - - if( bp->framerate == 0.0f ) - { - //sync animation time to lifeTime of particle - index = (int)( timeFrac * ( bp->numFrames + 1 ) ); - - if( index >= bp->numFrames ) - index = bp->numFrames - 1; - - re.customShader = bp->shaders[ index ]; - } - else - { - //looping animation - index = (int)( bp->framerate * timeFrac * p->lifeTime * 0.001 ) % bp->numFrames; - re.customShader = bp->shaders[ index ]; - } - - } - else if( bp->numModels ) //model based - { - re.reType = RT_MODEL; - - re.hModel = p->model; - - if( p->atRest ) - AxisCopy( p->lastAxis, re.axis ); - else - { - // convert direction of travel into axis - VectorNormalize2( p->velocity, re.axis[ 0 ] ); - - if( re.axis[ 0 ][ 0 ] == 0.0f && re.axis[ 0 ][ 1 ] == 0.0f ) - AxisCopy( axisDefault, re.axis ); - else - { - ProjectPointOnPlane( re.axis[ 2 ], up, re.axis[ 0 ] ); - VectorNormalize( re.axis[ 2 ] ); - CrossProduct( re.axis[ 2 ], re.axis[ 0 ], re.axis[ 1 ] ); - } - - AxisCopy( re.axis, p->lastAxis ); - } - - if( scale != 1.0f ) - { - VectorScale( re.axis[ 0 ], scale, re.axis[ 0 ] ); - VectorScale( re.axis[ 1 ], scale, re.axis[ 1 ] ); - VectorScale( re.axis[ 2 ], scale, re.axis[ 2 ] ); - re.nonNormalizedAxes = qtrue; - } - else - re.nonNormalizedAxes = qfalse; - - p->lf.animation = &bp->modelAnimation; - - //run animation - CG_RunLerpFrame( &p->lf ); - - re.oldframe = p->lf.oldFrame; - re.frame = p->lf.frame; - re.backlerp = p->lf.backlerp; - } - - if( bps->thirdPersonOnly && - CG_AttachmentCentNum( &ps->attachment ) == cg.snap->ps.clientNum && - !cg.renderingThirdPerson ) - re.renderfx |= RF_THIRD_PERSON; - - if( bp->dynamicLight && !( re.renderfx & RF_THIRD_PERSON ) ) - { - trap_R_AddLightToScene( p->origin, - CG_LerpValues( p->dLightRadius.initial, p->dLightRadius.final, - CG_CalculateTimeFrac( p->birthTime, p->lifeTime, p->dLightRadius.delay ) ), - (float)bp->dLightColor[ 0 ] / (float)0xFF, - (float)bp->dLightColor[ 1 ] / (float)0xFF, - (float)bp->dLightColor[ 2 ] / (float)0xFF ); - } - - VectorCopy( p->origin, re.origin ); - - trap_R_AddRefEntityToScene( &re ); -} - -/* -=============== -CG_AddParticles - -Add particles to the scene -=============== -*/ -void CG_AddParticles( void ) -{ - int i; - particle_t *p; - int numPS = 0, numPE = 0, numP = 0; - - //remove expired particle systems - CG_GarbageCollectParticleSystems( ); - - //check each ejector and introduce any new particles - CG_SpawnNewParticles( ); - - //sorting - if( cg_depthSortParticles.integer ) - CG_CompactAndSortParticles( ); - - for( i = 0; i < MAX_PARTICLES; i++ ) - { - p = sortedParticles[ i ]; - - if( p->valid ) - { - if( p->birthTime + p->lifeTime > cg.time ) - { - //particle is active - CG_EvaluateParticlePhysics( p ); - CG_RenderParticle( p ); - } - else - CG_DestroyParticle( p, NULL ); - } - } - - if( cg_debugParticles.integer >= 2 ) - { - for( i = 0; i < MAX_PARTICLE_SYSTEMS; i++ ) - if( particleSystems[ i ].valid ) - numPS++; - - for( i = 0; i < MAX_PARTICLE_EJECTORS; i++ ) - if( particleEjectors[ i ].valid ) - numPE++; - - for( i = 0; i < MAX_PARTICLES; i++ ) - if( particles[ i ].valid ) - numP++; - - CG_Printf( "PS: %d PE: %d P: %d\n", numPS, numPE, numP ); - } -} - -/* -=============== -CG_ParticleSystemEntity - -Particle system entity client code -=============== -*/ -void CG_ParticleSystemEntity( centity_t *cent ) -{ - entityState_t *es; - - es = ¢->currentState; - - if( es->eFlags & EF_NODRAW ) - { - if( CG_IsParticleSystemValid( ¢->entityPS ) && CG_IsParticleSystemInfinite( cent->entityPS ) ) - CG_DestroyParticleSystem( ¢->entityPS ); - - return; - } - - if( !CG_IsParticleSystemValid( ¢->entityPS ) && !cent->entityPSMissing ) - { - cent->entityPS = CG_SpawnNewParticleSystem( cgs.gameParticleSystems[ es->modelindex ] ); - - if( CG_IsParticleSystemValid( ¢->entityPS ) ) - { - CG_SetAttachmentPoint( ¢->entityPS->attachment, cent->lerpOrigin ); - CG_SetAttachmentCent( ¢->entityPS->attachment, cent ); - CG_AttachToPoint( ¢->entityPS->attachment ); - } - else - cent->entityPSMissing = qtrue; - } -} - -static particleSystem_t *testPS; -static qhandle_t testPSHandle; - -/* -=============== -CG_DestroyTestPS_f - -Destroy the test a particle system -=============== -*/ -void CG_DestroyTestPS_f( void ) -{ - if( CG_IsParticleSystemValid( &testPS ) ) - CG_DestroyParticleSystem( &testPS ); -} - -/* -=============== -CG_TestPS_f - -Test a particle system -=============== -*/ -void CG_TestPS_f( void ) -{ - vec3_t origin; - vec3_t up = { 0.0f, 0.0f, 1.0f }; - char psName[ MAX_QPATH ]; - - if( trap_Argc( ) < 2 ) - return; - - Q_strncpyz( psName, CG_Argv( 1 ), MAX_QPATH ); - testPSHandle = CG_RegisterParticleSystem( psName ); - - if( testPSHandle ) - { - CG_DestroyTestPS_f( ); - - testPS = CG_SpawnNewParticleSystem( testPSHandle ); - - VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[ 0 ], origin ); - - if( CG_IsParticleSystemValid( &testPS ) ) - { - CG_SetAttachmentPoint( &testPS->attachment, origin ); - CG_SetParticleSystemNormal( testPS, up ); - CG_AttachToPoint( &testPS->attachment ); - } - } -} diff --git a/mod/src/cgame/cg_players.c b/mod/src/cgame/cg_players.c deleted file mode 100644 index ac1ec181..00000000 --- a/mod/src/cgame/cg_players.c +++ /dev/null @@ -1,2575 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_players.c -- handle the media and animation for player entities - -/* - * 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" - -char *cg_customSoundNames[ MAX_CUSTOM_SOUNDS ] = -{ - "*death1.wav", - "*death2.wav", - "*death3.wav", - "*jump1.wav", - "*pain25_1.wav", - "*pain50_1.wav", - "*pain75_1.wav", - "*pain100_1.wav", - "*falling1.wav", - "*gasp.wav", - "*drown.wav", - "*fall1.wav", - "*taunt.wav" -}; - - -/* -================ -CG_CustomSound - -================ -*/ -sfxHandle_t CG_CustomSound( int clientNum, const char *soundName ) -{ - clientInfo_t *ci; - int i; - - if( soundName[ 0 ] != '*' ) - return trap_S_RegisterSound( soundName, qfalse ); - - if( clientNum < 0 || clientNum >= MAX_CLIENTS ) - clientNum = 0; - - ci = &cgs.clientinfo[ clientNum ]; - - for( i = 0; i < MAX_CUSTOM_SOUNDS && cg_customSoundNames[ i ]; i++ ) - { - if( !strcmp( soundName, cg_customSoundNames[ i ] ) ) - return ci->sounds[ i ]; - } - - CG_Error( "Unknown custom sound: %s", soundName ); - return 0; -} - - - -/* -============================================================================= - -CLIENT INFO - -============================================================================= -*/ - -/* -====================== -CG_ParseAnimationFile - -Read a configuration file containing animation coutns and rates -models/players/visor/animation.cfg, etc -====================== -*/ -static qboolean CG_ParseAnimationFile( const char *filename, clientInfo_t *ci ) -{ - char *text_p, *prev; - int len; - int i; - char *token; - float fps; - int skip; - char text[ 20000 ]; - fileHandle_t f; - animation_t *animations; - - animations = ci->animations; - - // load the file - len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if( len <= 0 ) - return qfalse; - - if( len >= sizeof( text ) - 1 ) - { - CG_Printf( "File %s too long\n", filename ); - trap_FS_FCloseFile( f ); - return qfalse; - } - - trap_FS_Read( text, len, f ); - text[ len ] = 0; - trap_FS_FCloseFile( f ); - - // parse the text - text_p = text; - skip = 0; // quite the compiler warning - - ci->footsteps = FOOTSTEP_NORMAL; - VectorClear( ci->headOffset ); - ci->gender = GENDER_MALE; - ci->fixedlegs = qfalse; - ci->fixedtorso = qfalse; - ci->nonsegmented = qfalse; - - // read optional parameters - while( 1 ) - { - prev = text_p; // so we can unget - token = COM_Parse( &text_p ); - - if( !token ) - break; - - if( !Q_stricmp( token, "footsteps" ) ) - { - token = COM_Parse( &text_p ); - if( !token ) - break; - - if( !Q_stricmp( token, "default" ) || !Q_stricmp( token, "normal" ) ) - ci->footsteps = FOOTSTEP_NORMAL; - else if( !Q_stricmp( token, "boot" ) ) - ci->footsteps = FOOTSTEP_BOOT; - else if( !Q_stricmp( token, "flesh" ) ) - ci->footsteps = FOOTSTEP_FLESH; - else if( !Q_stricmp( token, "mech" ) ) - ci->footsteps = FOOTSTEP_MECH; - else if( !Q_stricmp( token, "energy" ) ) - ci->footsteps = FOOTSTEP_ENERGY; - else if( !Q_stricmp( token, "none" ) ) - ci->footsteps = FOOTSTEP_NONE; - else if( !Q_stricmp( token, "custom" ) ) - ci->footsteps = FOOTSTEP_CUSTOM; - else - CG_Printf( "Bad footsteps parm in %s: %s\n", filename, token ); - - continue; - } - else if( !Q_stricmp( token, "headoffset" ) ) - { - for( i = 0 ; i < 3 ; i++ ) - { - token = COM_Parse( &text_p ); - if( !token ) - break; - - ci->headOffset[ i ] = atof( token ); - } - - continue; - } - else if( !Q_stricmp( token, "sex" ) ) - { - token = COM_Parse( &text_p ); - - if( !token ) - break; - - if( token[ 0 ] == 'f' || token[ 0 ] == 'F' ) - ci->gender = GENDER_FEMALE; - else if( token[ 0 ] == 'n' || token[ 0 ] == 'N' ) - ci->gender = GENDER_NEUTER; - else - ci->gender = GENDER_MALE; - - continue; - } - else if( !Q_stricmp( token, "fixedlegs" ) ) - { - ci->fixedlegs = qtrue; - continue; - } - else if( !Q_stricmp( token, "fixedtorso" ) ) - { - ci->fixedtorso = qtrue; - continue; - } - else if( !Q_stricmp( token, "nonsegmented" ) ) - { - ci->nonsegmented = qtrue; - continue; - } - - // if it is a number, start parsing animations - if( token[ 0 ] >= '0' && token[ 0 ] <= '9' ) - { - text_p = prev; // unget the token - break; - } - - Com_Printf( "unknown token '%s' is %s\n", token, filename ); - } - - if( !ci->nonsegmented ) - { - // read information for each frame - for( i = 0; i < MAX_PLAYER_ANIMATIONS; i++ ) - { - token = COM_Parse( &text_p ); - - if( !*token ) - { - if( i >= TORSO_GETFLAG && i <= TORSO_NEGATIVE ) - { - animations[ i ].firstFrame = animations[ TORSO_GESTURE ].firstFrame; - animations[ i ].frameLerp = animations[ TORSO_GESTURE ].frameLerp; - animations[ i ].initialLerp = animations[ TORSO_GESTURE ].initialLerp; - animations[ i ].loopFrames = animations[ TORSO_GESTURE ].loopFrames; - animations[ i ].numFrames = animations[ TORSO_GESTURE ].numFrames; - animations[ i ].reversed = qfalse; - animations[ i ].flipflop = qfalse; - continue; - } - - break; - } - - animations[ i ].firstFrame = atoi( token ); - - // leg only frames are adjusted to not count the upper body only frames - if( i == LEGS_WALKCR ) - skip = animations[ LEGS_WALKCR ].firstFrame - animations[ TORSO_GESTURE ].firstFrame; - - if( i >= LEGS_WALKCR && i<TORSO_GETFLAG ) - animations[ i ].firstFrame -= skip; - - token = COM_Parse( &text_p ); - if( !*token ) - break; - - animations[ i ].numFrames = atoi( token ); - animations[ i ].reversed = qfalse; - animations[ i ].flipflop = qfalse; - - // if numFrames is negative the animation is reversed - if( animations[ i ].numFrames < 0 ) - { - animations[ i ].numFrames = -animations[ i ].numFrames; - animations[ i ].reversed = qtrue; - } - - token = COM_Parse( &text_p ); - - if( !*token ) - break; - - animations[ i ].loopFrames = atoi( token ); - - token = COM_Parse( &text_p ); - - if( !*token ) - break; - - fps = atof( token ); - if( fps == 0 ) - fps = 1; - - animations[ i ].frameLerp = 1000 / fps; - animations[ i ].initialLerp = 1000 / fps; - } - - if( i != MAX_PLAYER_ANIMATIONS ) - { - CG_Printf( "Error parsing animation file: %s", filename ); - return qfalse; - } - // crouch backward animation - memcpy( &animations[ LEGS_BACKCR ], &animations[ LEGS_WALKCR ], sizeof( animation_t ) ); - animations[ LEGS_BACKCR ].reversed = qtrue; - // walk backward animation - memcpy( &animations[ LEGS_BACKWALK ], &animations[ LEGS_WALK ], sizeof( animation_t ) ); - animations[ LEGS_BACKWALK ].reversed = qtrue; - // flag moving fast - animations[ FLAG_RUN ].firstFrame = 0; - animations[ FLAG_RUN ].numFrames = 16; - animations[ FLAG_RUN ].loopFrames = 16; - animations[ FLAG_RUN ].frameLerp = 1000 / 15; - animations[ FLAG_RUN ].initialLerp = 1000 / 15; - animations[ FLAG_RUN ].reversed = qfalse; - // flag not moving or moving slowly - animations[ FLAG_STAND ].firstFrame = 16; - animations[ FLAG_STAND ].numFrames = 5; - animations[ FLAG_STAND ].loopFrames = 0; - animations[ FLAG_STAND ].frameLerp = 1000 / 20; - animations[ FLAG_STAND ].initialLerp = 1000 / 20; - animations[ FLAG_STAND ].reversed = qfalse; - // flag speeding up - animations[ FLAG_STAND2RUN ].firstFrame = 16; - animations[ FLAG_STAND2RUN ].numFrames = 5; - animations[ FLAG_STAND2RUN ].loopFrames = 1; - animations[ FLAG_STAND2RUN ].frameLerp = 1000 / 15; - animations[ FLAG_STAND2RUN ].initialLerp = 1000 / 15; - animations[ FLAG_STAND2RUN ].reversed = qtrue; - } - else - { - // read information for each frame - for( i = 0; i < MAX_NONSEG_PLAYER_ANIMATIONS; i++ ) - { - token = COM_Parse( &text_p ); - - if( !*token ) - break; - - animations[ i ].firstFrame = atoi( token ); - - token = COM_Parse( &text_p ); - if( !*token ) - break; - - animations[ i ].numFrames = atoi( token ); - animations[ i ].reversed = qfalse; - animations[ i ].flipflop = qfalse; - - // if numFrames is negative the animation is reversed - if( animations[ i ].numFrames < 0 ) - { - animations[ i ].numFrames = -animations[ i ].numFrames; - animations[ i ].reversed = qtrue; - } - - token = COM_Parse( &text_p ); - - if( !*token ) - break; - - animations[ i ].loopFrames = atoi( token ); - - token = COM_Parse( &text_p ); - - if( !*token ) - break; - - fps = atof( token ); - if( fps == 0 ) - fps = 1; - - animations[ i ].frameLerp = 1000 / fps; - animations[ i ].initialLerp = 1000 / fps; - } - - if( i != MAX_NONSEG_PLAYER_ANIMATIONS ) - { - CG_Printf( "Error parsing animation file: %s", filename ); - return qfalse; - } - - // walk backward animation - memcpy( &animations[ NSPA_WALKBACK ], &animations[ NSPA_WALK ], sizeof( animation_t ) ); - animations[ NSPA_WALKBACK ].reversed = qtrue; - } - - return qtrue; -} - -/* -========================== -CG_RegisterClientSkin -========================== -*/ -static qboolean CG_RegisterClientSkin( clientInfo_t *ci, const char *modelName, const char *skinName ) -{ - char filename[ MAX_QPATH ]; - - if( !ci->nonsegmented ) - { - Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower_%s.skin", modelName, skinName ); - ci->legsSkin = trap_R_RegisterSkin( filename ); - if( !ci->legsSkin ) - Com_Printf( "Leg skin load failure: %s\n", filename ); - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper_%s.skin", modelName, skinName ); - ci->torsoSkin = trap_R_RegisterSkin( filename ); - if( !ci->torsoSkin ) - Com_Printf( "Torso skin load failure: %s\n", filename ); - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/head_%s.skin", modelName, skinName ); - ci->headSkin = trap_R_RegisterSkin( filename ); - if( !ci->headSkin ) - Com_Printf( "Head skin load failure: %s\n", filename ); - - if( !ci->legsSkin || !ci->torsoSkin || !ci->headSkin ) - return qfalse; - } - else - { - Com_sprintf( filename, sizeof( filename ), "models/players/%s/nonseg_%s.skin", modelName, skinName ); - ci->nonSegSkin = trap_R_RegisterSkin( filename ); - if( !ci->nonSegSkin ) - Com_Printf( "Non-segmented skin load failure: %s\n", filename ); - - if( !ci->nonSegSkin ) - return qfalse; - } - - return qtrue; -} - -/* -========================== -CG_RegisterClientModelname -========================== -*/ -static qboolean CG_RegisterClientModelname( clientInfo_t *ci, const char *modelName, const char *skinName ) -{ - char filename[ MAX_QPATH * 2 ]; - - //TA: do this first so the nonsegmented property is set - // load the animations - Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg", modelName ); - if( !CG_ParseAnimationFile( filename, ci ) ) - { - Com_Printf( "Failed to load animation file %s\n", filename ); - return qfalse; - } - - // load cmodels before models so filecache works - - if( !ci->nonsegmented ) - { - Com_sprintf( filename, sizeof( filename ), "models/players/%s/lower.md3", modelName ); - ci->legsModel = trap_R_RegisterModel( filename ); - if( !ci->legsModel ) - { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; - } - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/upper.md3", modelName ); - ci->torsoModel = trap_R_RegisterModel( filename ); - if( !ci->torsoModel ) - { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; - } - - Com_sprintf( filename, sizeof( filename ), "models/players/%s/head.md3", modelName ); - ci->headModel = trap_R_RegisterModel( filename ); - if( !ci->headModel ) - { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; - } - } - else - { - Com_sprintf( filename, sizeof( filename ), "models/players/%s/nonseg.md3", modelName ); - ci->nonSegModel = trap_R_RegisterModel( filename ); - if( !ci->nonSegModel ) - { - Com_Printf( "Failed to load model file %s\n", filename ); - return qfalse; - } - } - - // if any skins failed to load, return failure - if( !CG_RegisterClientSkin( ci, modelName, skinName ) ) - { - Com_Printf( "Failed to load skin file: %s : %s\n", modelName, skinName ); - return qfalse; - } - - //FIXME: skins do not load without icon present. do we want icons anyway? -/* Com_sprintf( filename, sizeof( filename ), "models/players/%s/icon_%s.tga", modelName, skinName ); - ci->modelIcon = trap_R_RegisterShaderNoMip( filename ); - if( !ci->modelIcon ) - { - Com_Printf( "Failed to load icon file: %s\n", filename ); - return qfalse; - }*/ - - return qtrue; -} - -/* -==================== -CG_ColorFromString -==================== -*/ -static void CG_ColorFromString( const char *v, vec3_t color ) -{ - int val; - - VectorClear( color ); - - val = atoi( v ); - - if( val < 1 || val > 7 ) - { - VectorSet( color, 1, 1, 1 ); - return; - } - - if( val & 1 ) - color[ 2 ] = 1.0f; - - if( val & 2 ) - color[ 1 ] = 1.0f; - - if( val & 4 ) - color[ 0 ] = 1.0f; -} - - -/* -=================== -CG_LoadClientInfo - -Load it now, taking the disk hits -=================== -*/ -static void CG_LoadClientInfo( clientInfo_t *ci ) -{ - const char *dir, *fallback; - int i; - const char *s; - int clientNum; - - if( !CG_RegisterClientModelname( ci, ci->modelName, ci->skinName ) ) - { - if( cg_buildScript.integer ) - CG_Error( "CG_RegisterClientModelname( %s, %s ) failed", ci->modelName, ci->skinName ); - - // fall back - if( !CG_RegisterClientModelname( ci, DEFAULT_MODEL, "default" ) ) - CG_Error( "DEFAULT_MODEL (%s) failed to register", DEFAULT_MODEL ); - } - - // sounds - dir = ci->modelName; - fallback = DEFAULT_MODEL; - - for( i = 0; i < MAX_CUSTOM_SOUNDS; i++ ) - { - s = cg_customSoundNames[ i ]; - - if( !s ) - break; - - // fanny about a bit with sounds that are missing - if( !CG_FileExists( va( "sound/player/%s/%s", dir, s + 1 ) ) ) - { - //file doesn't exist - - if( i == 11 || i == 8 ) //fall or falling - { - ci->sounds[ i ] = trap_S_RegisterSound( "sound/null.wav", qfalse ); - } - else - { - if( i == 9 ) //gasp - s = cg_customSoundNames[ 7 ]; //pain100_1 - else if( i == 10 ) //drown - s = cg_customSoundNames[ 0 ]; //death1 - - ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse ); - if( !ci->sounds[ i ] ) - ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse ); - } - } - else - { - ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse ); - if( !ci->sounds[ i ] ) - ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse ); - } - } - - if( ci->footsteps == FOOTSTEP_CUSTOM ) - { - for( i = 0; i < 4; i++ ) - { - ci->customFootsteps[ i ] = trap_S_RegisterSound( va( "sound/player/%s/step%d.wav", dir, i + 1 ), qfalse ); - if( !ci->customFootsteps[ i ] ) - ci->customFootsteps[ i ] = trap_S_RegisterSound( va( "sound/player/footsteps/step%d.wav", i + 1 ), qfalse ); - - ci->customMetalFootsteps[ i ] = trap_S_RegisterSound( va( "sound/player/%s/clank%d.wav", dir, i + 1 ), qfalse ); - if( !ci->customMetalFootsteps[ i ] ) - ci->customMetalFootsteps[ i ] = trap_S_RegisterSound( va( "sound/player/footsteps/clank%d.wav", i + 1 ), qfalse ); - } - } - - // reset any existing players and bodies, because they might be in bad - // frames for this new model - clientNum = ci - cgs.clientinfo; - for( i = 0; i < MAX_GENTITIES; i++ ) - { - if( cg_entities[ i ].currentState.clientNum == clientNum && - cg_entities[ i ].currentState.eType == ET_PLAYER ) - CG_ResetPlayerEntity( &cg_entities[ i ] ); - } -} - -/* -====================== -CG_CopyClientInfoModel -====================== -*/ -static void CG_CopyClientInfoModel( clientInfo_t *from, clientInfo_t *to ) -{ - VectorCopy( from->headOffset, to->headOffset ); - to->footsteps = from->footsteps; - to->gender = from->gender; - - to->legsModel = from->legsModel; - to->legsSkin = from->legsSkin; - to->torsoModel = from->torsoModel; - to->torsoSkin = from->torsoSkin; - to->headModel = from->headModel; - to->headSkin = from->headSkin; - to->nonSegModel = from->nonSegModel; - to->nonSegSkin = from->nonSegSkin; - to->nonsegmented = from->nonsegmented; - to->modelIcon = from->modelIcon; - - memcpy( to->animations, from->animations, sizeof( to->animations ) ); - memcpy( to->sounds, from->sounds, sizeof( to->sounds ) ); - memcpy( to->customFootsteps, from->customFootsteps, sizeof( to->customFootsteps ) ); - memcpy( to->customMetalFootsteps, from->customMetalFootsteps, sizeof( to->customMetalFootsteps ) ); -} - - -/* -====================== -CG_GetCorpseNum -====================== -*/ -static int CG_GetCorpseNum( pClass_t class ) -{ - int i; - clientInfo_t *match; - char *modelName; - char *skinName; - - modelName = BG_FindModelNameForClass( class ); - skinName = BG_FindSkinNameForClass( class ); - - for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) - { - match = &cgs.corpseinfo[ i ]; - - if( !match->infoValid ) - continue; - - if( !Q_stricmp( modelName, match->modelName ) - && !Q_stricmp( skinName, match->skinName ) ) - { - // this clientinfo is identical, so use it's handles - return i; - } - } - - //something has gone horribly wrong - return -1; -} - - -/* -====================== -CG_ScanForExistingClientInfo -====================== -*/ -static qboolean CG_ScanForExistingClientInfo( clientInfo_t *ci ) -{ - int i; - clientInfo_t *match; - - for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) - { - match = &cgs.corpseinfo[ i ]; - - if( !match->infoValid ) - continue; - - if( !Q_stricmp( ci->modelName, match->modelName ) && - !Q_stricmp( ci->skinName, match->skinName ) ) - { - // this clientinfo is identical, so use it's handles - CG_CopyClientInfoModel( match, ci ); - - return qtrue; - } - } - - //TA: shouldn't happen - return qfalse; -} - - -/* -====================== -CG_PrecacheClientInfo -====================== -*/ -void CG_PrecacheClientInfo( pClass_t class, char *model, char *skin ) -{ - clientInfo_t *ci; - clientInfo_t newInfo; - - ci = &cgs.corpseinfo[ class ]; - - // the old value - memset( &newInfo, 0, sizeof( newInfo ) ); - - // model - Q_strncpyz( newInfo.modelName, model, sizeof( newInfo.modelName ) ); - Q_strncpyz( newInfo.headModelName, model, sizeof( newInfo.headModelName ) ); - - // modelName didn not include a skin name - if( !skin ) - { - Q_strncpyz( newInfo.skinName, "default", sizeof( newInfo.skinName ) ); - Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) ); - } - else - { - Q_strncpyz( newInfo.skinName, skin, sizeof( newInfo.skinName ) ); - Q_strncpyz( newInfo.headSkinName, skin, sizeof( newInfo.headSkinName ) ); - } - - newInfo.infoValid = qtrue; - - //TA: actually register the models - *ci = newInfo; - CG_LoadClientInfo( ci ); -} - - -/* -====================== -CG_NewClientInfo -====================== -*/ -void CG_NewClientInfo( int clientNum ) -{ - clientInfo_t *ci; - clientInfo_t newInfo; - const char *configstring; - const char *v; - char *slash; - - ci = &cgs.clientinfo[ clientNum ]; - - configstring = CG_ConfigString( clientNum + CS_PLAYERS ); - if( !configstring[ 0 ] ) - { - memset( ci, 0, sizeof( *ci ) ); - return; // player just left - } - - // the old value - memset( &newInfo, 0, sizeof( newInfo ) ); - - // isolate the player's name - v = Info_ValueForKey( configstring, "n" ); - Q_strncpyz( newInfo.name, v, sizeof( newInfo.name ) ); - - // colors - v = Info_ValueForKey( configstring, "c1" ); - CG_ColorFromString( v, newInfo.color1 ); - - v = Info_ValueForKey( configstring, "c2" ); - CG_ColorFromString( v, newInfo.color2 ); - - // bot skill - v = Info_ValueForKey( configstring, "skill" ); - newInfo.botSkill = atoi( v ); - - // handicap - v = Info_ValueForKey( configstring, "hc" ); - newInfo.handicap = atoi( v ); - - // wins - v = Info_ValueForKey( configstring, "w" ); - newInfo.wins = atoi( v ); - - // losses - v = Info_ValueForKey( configstring, "l" ); - newInfo.losses = atoi( v ); - - // team - v = Info_ValueForKey( configstring, "t" ); - newInfo.team = atoi( v ); - - // team task - v = Info_ValueForKey( configstring, "tt" ); - newInfo.teamTask = atoi( v ); - - // team leader - v = Info_ValueForKey( configstring, "tl" ); - newInfo.teamLeader = atoi( v ); - - v = Info_ValueForKey( configstring, "g_redteam" ); - Q_strncpyz( newInfo.redTeam, v, MAX_TEAMNAME ); - - v = Info_ValueForKey( configstring, "g_blueteam" ); - Q_strncpyz( newInfo.blueTeam, v, MAX_TEAMNAME ); - - // model - v = Info_ValueForKey( configstring, "model" ); - Q_strncpyz( newInfo.modelName, v, sizeof( newInfo.modelName ) ); - - slash = strchr( newInfo.modelName, '/' ); - - if( !slash ) - { - // modelName didn not include a skin name - Q_strncpyz( newInfo.skinName, "default", sizeof( newInfo.skinName ) ); - } - else - { - Q_strncpyz( newInfo.skinName, slash + 1, sizeof( newInfo.skinName ) ); - // truncate modelName - *slash = 0; - } - - //CG_Printf( "NCI: %s\n", v ); - - // head model - v = Info_ValueForKey( configstring, "hmodel" ); - Q_strncpyz( newInfo.headModelName, v, sizeof( newInfo.headModelName ) ); - - slash = strchr( newInfo.headModelName, '/' ); - - if( !slash ) - { - // modelName didn not include a skin name - Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) ); - } - else - { - Q_strncpyz( newInfo.headSkinName, slash + 1, sizeof( newInfo.headSkinName ) ); - // truncate modelName - *slash = 0; - } - - // replace whatever was there with the new one - newInfo.infoValid = qtrue; - *ci = newInfo; - - // scan for an existing clientinfo that matches this modelname - // so we can avoid loading checks if possible - if( !CG_ScanForExistingClientInfo( ci ) ) - CG_LoadClientInfo( ci ); -} - - - -/* -============================================================================= - -PLAYER ANIMATION - -============================================================================= -*/ - - -/* -=============== -CG_SetLerpFrameAnimation - -may include ANIM_TOGGLEBIT -=============== -*/ -static void CG_SetLerpFrameAnimation( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation ) -{ - animation_t *anim; - - lf->animationNumber = newAnimation; - newAnimation &= ~ANIM_TOGGLEBIT; - - if( newAnimation < 0 || newAnimation >= MAX_PLAYER_TOTALANIMATIONS ) - CG_Error( "Bad animation number: %i", newAnimation ); - - anim = &ci->animations[ newAnimation ]; - - lf->animation = anim; - lf->animationTime = lf->frameTime + anim->initialLerp; - - if( cg_debugAnim.integer ) - CG_Printf( "Anim: %i\n", newAnimation ); -} - -/* -=============== -CG_RunPlayerLerpFrame - -Sets cg.snap, cg.oldFrame, and cg.backlerp -cg.time should be between oldFrameTime and frameTime after exit -=============== -*/ -static void CG_RunPlayerLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale ) -{ - int f, numFrames; - animation_t *anim; - - // debugging tool to get no animations - if( cg_animSpeed.integer == 0 ) - { - lf->oldFrame = lf->frame = lf->backlerp = 0; - return; - } - - // see if the animation sequence is switching - if( newAnimation != lf->animationNumber || !lf->animation ) - { - CG_SetLerpFrameAnimation( ci, lf, newAnimation ); - } - - // if we have passed the current frame, move it to - // oldFrame and calculate a new frame - if( cg.time >= lf->frameTime ) - { - lf->oldFrame = lf->frame; - lf->oldFrameTime = lf->frameTime; - - // get the next frame based on the animation - anim = lf->animation; - if( !anim->frameLerp ) - return; // shouldn't happen - - if( cg.time < lf->animationTime ) - lf->frameTime = lf->animationTime; // initial lerp - else - lf->frameTime = lf->oldFrameTime + anim->frameLerp; - - f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; - f *= speedScale; // adjust for haste, etc - numFrames = anim->numFrames; - - if( anim->flipflop ) - numFrames *= 2; - - if( f >= numFrames ) - { - f -= numFrames; - if( anim->loopFrames ) - { - f %= anim->loopFrames; - f += anim->numFrames - anim->loopFrames; - } - else - { - f = numFrames - 1; - // the animation is stuck at the end, so it - // can immediately transition to another sequence - lf->frameTime = cg.time; - } - } - - if( anim->reversed ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - f; - else if( anim->flipflop && f>=anim->numFrames ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); - else - lf->frame = anim->firstFrame + f; - - if( cg.time > lf->frameTime ) - { - lf->frameTime = cg.time; - - if( cg_debugAnim.integer ) - CG_Printf( "Clamp lf->frameTime\n" ); - } - } - - if( lf->frameTime > cg.time + 200 ) - lf->frameTime = cg.time; - - if( lf->oldFrameTime > cg.time ) - lf->oldFrameTime = cg.time; - - // calculate current lerp value - if( lf->frameTime == lf->oldFrameTime ) - lf->backlerp = 0; - else - lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); -} - - -/* -=============== -CG_ClearLerpFrame -=============== -*/ -static void CG_ClearLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int animationNumber ) -{ - lf->frameTime = lf->oldFrameTime = cg.time; - CG_SetLerpFrameAnimation( ci, lf, animationNumber ); - lf->oldFrame = lf->frame = lf->animation->firstFrame; -} - - -/* -=============== -CG_PlayerAnimation -=============== -*/ -static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float *legsBackLerp, - int *torsoOld, int *torso, float *torsoBackLerp ) -{ - clientInfo_t *ci; - int clientNum; - float speedScale = 1.0f; - - clientNum = cent->currentState.clientNum; - - if( cg_noPlayerAnims.integer ) - { - *legsOld = *legs = *torsoOld = *torso = 0; - return; - } - - ci = &cgs.clientinfo[ clientNum ]; - - // do the shuffle turn frames locally - if( cent->pe.legs.yawing && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_IDLE ) - CG_RunPlayerLerpFrame( ci, ¢->pe.legs, LEGS_TURN, speedScale ); - else - CG_RunPlayerLerpFrame( ci, ¢->pe.legs, cent->currentState.legsAnim, speedScale ); - - *legsOld = cent->pe.legs.oldFrame; - *legs = cent->pe.legs.frame; - *legsBackLerp = cent->pe.legs.backlerp; - - CG_RunPlayerLerpFrame( ci, ¢->pe.torso, cent->currentState.torsoAnim, speedScale ); - - *torsoOld = cent->pe.torso.oldFrame; - *torso = cent->pe.torso.frame; - *torsoBackLerp = cent->pe.torso.backlerp; -} - - -/* -=============== -CG_PlayerNonSegAnimation -=============== -*/ -static void CG_PlayerNonSegAnimation( centity_t *cent, int *nonSegOld, - int *nonSeg, float *nonSegBackLerp ) -{ - clientInfo_t *ci; - int clientNum; - float speedScale = 1.0f; - - clientNum = cent->currentState.clientNum; - - if( cg_noPlayerAnims.integer ) - { - *nonSegOld = *nonSeg = 0; - return; - } - - ci = &cgs.clientinfo[ clientNum ]; - - // do the shuffle turn frames locally - if( cent->pe.nonseg.yawing && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == NSPA_STAND ) - CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, NSPA_TURN, speedScale ); - else - CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, cent->currentState.legsAnim, speedScale ); - - *nonSegOld = cent->pe.nonseg.oldFrame; - *nonSeg = cent->pe.nonseg.frame; - *nonSegBackLerp = cent->pe.nonseg.backlerp; -} - -/* -============================================================================= - -PLAYER ANGLES - -============================================================================= -*/ - -/* -================== -CG_SwingAngles -================== -*/ -static void CG_SwingAngles( float destination, float swingTolerance, float clampTolerance, - float speed, float *angle, qboolean *swinging ) -{ - float swing; - float move; - float scale; - - if( !*swinging ) - { - // see if a swing should be started - swing = AngleSubtract( *angle, destination ); - - if( swing > swingTolerance || swing < -swingTolerance ) - *swinging = qtrue; - } - - if( !*swinging ) - return; - - // modify the speed depending on the delta - // so it doesn't seem so linear - swing = AngleSubtract( destination, *angle ); - scale = fabs( swing ); - - if( scale < swingTolerance * 0.5 ) - scale = 0.5; - else if( scale < swingTolerance ) - scale = 1.0; - else - scale = 2.0; - - // swing towards the destination angle - if( swing >= 0 ) - { - move = cg.frametime * scale * speed; - - if( move >= swing ) - { - move = swing; - *swinging = qfalse; - } - *angle = AngleMod( *angle + move ); - } - else if( swing < 0 ) - { - move = cg.frametime * scale * -speed; - - if( move <= swing ) - { - move = swing; - *swinging = qfalse; - } - *angle = AngleMod( *angle + move ); - } - - // clamp to no more than tolerance - swing = AngleSubtract( destination, *angle ); - if( swing > clampTolerance ) - *angle = AngleMod( destination - ( clampTolerance - 1 ) ); - else if( swing < -clampTolerance ) - *angle = AngleMod( destination + ( clampTolerance - 1 ) ); -} - -/* -================= -CG_AddPainTwitch -================= -*/ -static void CG_AddPainTwitch( centity_t *cent, vec3_t torsoAngles ) -{ - int t; - float f; - - t = cg.time - cent->pe.painTime; - - if( t >= PAIN_TWITCH_TIME ) - return; - - f = 1.0 - (float)t / PAIN_TWITCH_TIME; - - if( cent->pe.painDirection ) - torsoAngles[ ROLL ] += 20 * f; - else - torsoAngles[ ROLL ] -= 20 * f; -} - - -/* -=============== -CG_PlayerAngles - -Handles seperate torso motion - - legs pivot based on direction of movement - - head always looks exactly at cent->lerpAngles - - if motion < 20 degrees, show in head only - if < 45 degrees, also show in torso -=============== -*/ -static void CG_PlayerAngles( centity_t *cent, vec3_t srcAngles, - vec3_t legs[ 3 ], vec3_t torso[ 3 ], vec3_t head[ 3 ] ) -{ - vec3_t legsAngles, torsoAngles, headAngles; - float dest; - static int movementOffsets[ 8 ] = { 0, 22, 45, -22, 0, 22, -45, -22 }; - vec3_t velocity; - float speed; - int dir, clientNum; - clientInfo_t *ci; - - VectorCopy( srcAngles, headAngles ); - headAngles[ YAW ] = AngleMod( headAngles[ YAW ] ); - VectorClear( legsAngles ); - VectorClear( torsoAngles ); - - // --------- yaw ------------- - - // allow yaw to drift a bit - if( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE || - ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) - { - // if not standing still, always point all in the same direction - cent->pe.torso.yawing = qtrue; // always center - cent->pe.torso.pitching = qtrue; // always center - cent->pe.legs.yawing = qtrue; // always center - } - - // adjust legs for movement dir - if( cent->currentState.eFlags & EF_DEAD ) - { - // don't let dead bodies twitch - dir = 0; - } - else - { - //TA: did use angles2.. now uses time2.. looks a bit funny but time2 isn't used othwise - dir = cent->currentState.time2; - if( dir < 0 || dir > 7 ) - CG_Error( "Bad player movement angle" ); - } - - legsAngles[ YAW ] = headAngles[ YAW ] + movementOffsets[ dir ]; - torsoAngles[ YAW ] = headAngles[ YAW ] + 0.25 * movementOffsets[ dir ]; - - // torso - if( cent->currentState.eFlags & EF_DEAD ) - { - CG_SwingAngles( torsoAngles[ YAW ], 0, 0, cg_swingSpeed.value, - ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - CG_SwingAngles( legsAngles[ YAW ], 0, 0, cg_swingSpeed.value, - ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); - } - else - { - CG_SwingAngles( torsoAngles[ YAW ], 25, 90, cg_swingSpeed.value, - ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - CG_SwingAngles( legsAngles[ YAW ], 40, 90, cg_swingSpeed.value, - ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); - } - - torsoAngles[ YAW ] = cent->pe.torso.yawAngle; - legsAngles[ YAW ] = cent->pe.legs.yawAngle; - - // --------- pitch ------------- - - // only show a fraction of the pitch angle in the torso - if( headAngles[ PITCH ] > 180 ) - dest = ( -360 + headAngles[ PITCH ] ) * 0.75f; - else - dest = headAngles[ PITCH ] * 0.75f; - - CG_SwingAngles( dest, 15, 30, 0.1f, ¢->pe.torso.pitchAngle, ¢->pe.torso.pitching ); - torsoAngles[ PITCH ] = cent->pe.torso.pitchAngle; - - // - clientNum = cent->currentState.clientNum; - - if( clientNum >= 0 && clientNum < MAX_CLIENTS ) - { - ci = &cgs.clientinfo[ clientNum ]; - if( ci->fixedtorso ) - torsoAngles[ PITCH ] = 0.0f; - } - - // --------- roll ------------- - - - // lean towards the direction of travel - VectorCopy( cent->currentState.pos.trDelta, velocity ); - speed = VectorNormalize( velocity ); - - if( speed ) - { - vec3_t axis[ 3 ]; - float side; - - speed *= 0.05f; - - AnglesToAxis( legsAngles, axis ); - side = speed * DotProduct( velocity, axis[ 1 ] ); - legsAngles[ ROLL ] -= side; - - side = speed * DotProduct( velocity, axis[ 0 ] ); - legsAngles[ PITCH ] += side; - } - - // - clientNum = cent->currentState.clientNum; - - if( clientNum >= 0 && clientNum < MAX_CLIENTS ) - { - ci = &cgs.clientinfo[ clientNum ]; - - if( ci->fixedlegs ) - { - legsAngles[ YAW ] = torsoAngles[ YAW ]; - legsAngles[ PITCH ] = 0.0f; - legsAngles[ ROLL ] = 0.0f; - } - } - - // pain twitch - CG_AddPainTwitch( cent, torsoAngles ); - - // pull the angles back out of the hierarchial chain - AnglesSubtract( headAngles, torsoAngles, headAngles ); - AnglesSubtract( torsoAngles, legsAngles, torsoAngles ); - AnglesToAxis( legsAngles, legs ); - AnglesToAxis( torsoAngles, torso ); - AnglesToAxis( headAngles, head ); -} - -#define MODEL_WWSMOOTHTIME 200 - -/* -=============== -CG_PlayerWWSmoothing - -Smooth the angles of transitioning wall walkers -=============== -*/ -static void CG_PlayerWWSmoothing( centity_t *cent, vec3_t in[ 3 ], vec3_t out[ 3 ] ) -{ - entityState_t *es = ¢->currentState; - int i; - vec3_t surfNormal, rotAxis, temp; - vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; - vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; - float stLocal, sFraction, rotAngle; - vec3_t inAxis[ 3 ], lastAxis[ 3 ], outAxis[ 3 ]; - - //set surfNormal - if( !(es->eFlags & EF_WALLCLIMB ) ) - VectorCopy( refNormal, surfNormal ); - else if( !( es->eFlags & EF_WALLCLIMBCEILING ) ) - VectorCopy( es->angles2, surfNormal ); - else - VectorCopy( ceilingNormal, surfNormal ); - - AxisCopy( in, inAxis ); - - if( !VectorCompare( surfNormal, cent->pe.lastNormal ) ) - { - //if we moving from the ceiling to the floor special case - //( x product of colinear vectors is undefined) - if( VectorCompare( ceilingNormal, cent->pe.lastNormal ) && - VectorCompare( refNormal, surfNormal ) ) - { - VectorCopy( in[ 1 ], rotAxis ); - rotAngle = 180.0f; - } - else - { - AxisCopy( cent->pe.lastAxis, lastAxis ); - rotAngle = DotProduct( inAxis[ 0 ], lastAxis[ 0 ] ) + - DotProduct( inAxis[ 1 ], lastAxis[ 1 ] ) + - DotProduct( inAxis[ 2 ], lastAxis[ 2 ] ); - - rotAngle = RAD2DEG( acos( ( rotAngle - 1.0f ) / 2.0f ) ); - - CrossProduct( lastAxis[ 0 ], inAxis[ 0 ], temp ); - VectorCopy( temp, rotAxis ); - CrossProduct( lastAxis[ 1 ], inAxis[ 1 ], temp ); - VectorAdd( rotAxis, temp, rotAxis ); - CrossProduct( lastAxis[ 2 ], inAxis[ 2 ], temp ); - VectorAdd( rotAxis, temp, rotAxis ); - - VectorNormalize( rotAxis ); - } - - //iterate through smooth array - for( i = 0; i < MAXSMOOTHS; i++ ) - { - //found an unused index in the smooth array - if( cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME < cg.time ) - { - //copy to array and stop - VectorCopy( rotAxis, cent->pe.sList[ i ].rotAxis ); - cent->pe.sList[ i ].rotAngle = rotAngle; - cent->pe.sList[ i ].time = cg.time; - break; - } - } - } - - //iterate through ops - for( i = MAXSMOOTHS - 1; i >= 0; i-- ) - { - //if this op has time remaining, perform it - if( cg.time < cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME ) - { - stLocal = 1.0f - ( ( ( cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME ) - cg.time ) / MODEL_WWSMOOTHTIME ); - sFraction = -( cos( stLocal * M_PI ) + 1.0f ) / 2.0f; - - RotatePointAroundVector( outAxis[ 0 ], cent->pe.sList[ i ].rotAxis, - inAxis[ 0 ], sFraction * cent->pe.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 1 ], cent->pe.sList[ i ].rotAxis, - inAxis[ 1 ], sFraction * cent->pe.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 2 ], cent->pe.sList[ i ].rotAxis, - inAxis[ 2 ], sFraction * cent->pe.sList[ i ].rotAngle ); - - AxisCopy( outAxis, inAxis ); - } - } - - //outAxis has been copied to inAxis - AxisCopy( inAxis, out ); -} - -/* -=============== -CG_PlayerNonSegAngles - -Resolve angles for non-segmented models -=============== -*/ -static void CG_PlayerNonSegAngles( centity_t *cent, vec3_t srcAngles, vec3_t nonSegAxis[ 3 ] ) -{ - vec3_t localAngles; - vec3_t velocity; - float speed; - int dir; - entityState_t *es = ¢->currentState; - vec3_t surfNormal; - vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; - - VectorCopy( srcAngles, localAngles ); - localAngles[ YAW ] = AngleMod( localAngles[ YAW ] ); - localAngles[ PITCH ] = 0.0f; - localAngles[ ROLL ] = 0.0f; - - //set surfNormal - if( !( es->eFlags & EF_WALLCLIMBCEILING ) ) - VectorCopy( es->angles2, surfNormal ); - else - VectorCopy( ceilingNormal, surfNormal ); - - //make sure that WW transitions don't cause the swing stuff to go nuts - if( !VectorCompare( surfNormal, cent->pe.lastNormal ) ) - { - //stop CG_SwingAngles having an eppy - cent->pe.nonseg.yawAngle = localAngles[ YAW ]; - cent->pe.nonseg.yawing = qfalse; - } - - // --------- yaw ------------- - - // allow yaw to drift a bit - if( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != NSPA_STAND ) - { - // if not standing still, always point all in the same direction - cent->pe.nonseg.yawing = qtrue; // always center - } - - // adjust legs for movement dir - if( cent->currentState.eFlags & EF_DEAD ) - { - // don't let dead bodies twitch - dir = 0; - } - else - { - //TA: did use angles2.. now uses time2.. looks a bit funny but time2 isn't used othwise - dir = cent->currentState.time2; - if( dir < 0 || dir > 7 ) - CG_Error( "Bad player movement angle" ); - } - - // torso - if( cent->currentState.eFlags & EF_DEAD ) - { - CG_SwingAngles( localAngles[ YAW ], 0, 0, cg_swingSpeed.value, - ¢->pe.nonseg.yawAngle, ¢->pe.nonseg.yawing ); - } - else - { - CG_SwingAngles( localAngles[ YAW ], 40, 90, cg_swingSpeed.value, - ¢->pe.nonseg.yawAngle, ¢->pe.nonseg.yawing ); - } - - localAngles[ YAW ] = cent->pe.nonseg.yawAngle; - - // --------- pitch ------------- - - //NO PITCH! - - - // --------- roll ------------- - - - // lean towards the direction of travel - VectorCopy( cent->currentState.pos.trDelta, velocity ); - speed = VectorNormalize( velocity ); - - if( speed ) - { - vec3_t axis[ 3 ]; - float side; - - //much less than with the regular model system - speed *= 0.01f; - - AnglesToAxis( localAngles, axis ); - side = speed * DotProduct( velocity, axis[ 1 ] ); - localAngles[ ROLL ] -= side; - - side = speed * DotProduct( velocity, axis[ 0 ] ); - localAngles[ PITCH ] += side; - } - - //FIXME: PAIN[123] animations? - // pain twitch - //CG_AddPainTwitch( cent, torsoAngles ); - - AnglesToAxis( localAngles, nonSegAxis ); -} - - -//========================================================================== - -/* -=============== -CG_PlayerUpgrade -=============== -*/ -static void CG_PlayerUpgrades( centity_t *cent, refEntity_t *torso ) -{ - int held, active; - refEntity_t jetpack; - refEntity_t battpack; - refEntity_t flash; - entityState_t *es = ¢->currentState; - - held = es->modelindex; - active = es->modelindex2; - - if( held & ( 1 << UP_JETPACK ) ) - { - memset( &jetpack, 0, sizeof( jetpack ) ); - VectorCopy( torso->lightingOrigin, jetpack.lightingOrigin ); - jetpack.shadowPlane = torso->shadowPlane; - jetpack.renderfx = torso->renderfx; - - jetpack.hModel = cgs.media.jetpackModel; - - //identity matrix - AxisCopy( axisDefault, jetpack.axis ); - - //FIXME: change to tag_back when it exists - CG_PositionRotatedEntityOnTag( &jetpack, torso, torso->hModel, "tag_head" ); - - trap_R_AddRefEntityToScene( &jetpack ); - - if( active & ( 1 << UP_JETPACK ) ) - { - if( es->pos.trDelta[ 2 ] > 10.0f ) - { - if( cent->jetPackState != JPS_ASCENDING ) - { - if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - CG_DestroyParticleSystem( ¢->jetPackPS ); - - cent->jetPackPS = CG_SpawnNewParticleSystem( cgs.media.jetPackAscendPS ); - cent->jetPackState = JPS_ASCENDING; - } - - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.jetpackAscendSound ); - } - else if( es->pos.trDelta[ 2 ] < -10.0f ) - { - if( cent->jetPackState != JPS_DESCENDING ) - { - if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - CG_DestroyParticleSystem( ¢->jetPackPS ); - - cent->jetPackPS = CG_SpawnNewParticleSystem( cgs.media.jetPackDescendPS ); - cent->jetPackState = JPS_DESCENDING; - } - - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.jetpackDescendSound ); - } - else - { - if( cent->jetPackState != JPS_HOVERING ) - { - if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - CG_DestroyParticleSystem( ¢->jetPackPS ); - - cent->jetPackPS = CG_SpawnNewParticleSystem( cgs.media.jetPackHoverPS ); - cent->jetPackState = JPS_HOVERING; - } - - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.jetpackIdleSound ); - } - - memset( &flash, 0, sizeof( flash ) ); - VectorCopy( torso->lightingOrigin, flash.lightingOrigin ); - flash.shadowPlane = torso->shadowPlane; - flash.renderfx = torso->renderfx; - - flash.hModel = cgs.media.jetpackFlashModel; - if( !flash.hModel ) - return; - - AxisCopy( axisDefault, flash.axis ); - - CG_PositionRotatedEntityOnTag( &flash, &jetpack, jetpack.hModel, "tag_flash" ); - trap_R_AddRefEntityToScene( &flash ); - - if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - { - CG_SetAttachmentTag( ¢->jetPackPS->attachment, - jetpack, jetpack.hModel, "tag_flash" ); - CG_SetAttachmentCent( ¢->jetPackPS->attachment, cent ); - CG_AttachToTag( ¢->jetPackPS->attachment ); - } - } - else if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - { - CG_DestroyParticleSystem( ¢->jetPackPS ); - cent->jetPackState = JPS_OFF; - } - } - else if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - { - CG_DestroyParticleSystem( ¢->jetPackPS ); - cent->jetPackState = JPS_OFF; - } - - if( held & ( 1 << UP_BATTPACK ) ) - { - memset( &battpack, 0, sizeof( battpack ) ); - VectorCopy( torso->lightingOrigin, battpack.lightingOrigin ); - battpack.shadowPlane = torso->shadowPlane; - battpack.renderfx = torso->renderfx; - - battpack.hModel = cgs.media.battpackModel; - - //identity matrix - AxisCopy( axisDefault, battpack.axis ); - - //FIXME: change to tag_back when it exists - CG_PositionRotatedEntityOnTag( &battpack, torso, torso->hModel, "tag_head" ); - - trap_R_AddRefEntityToScene( &battpack ); - } - - if( es->eFlags & EF_BLOBLOCKED ) - { - vec3_t temp, origin, up = { 0.0f, 0.0f, 1.0f }; - trace_t tr; - float size; - - VectorCopy( es->pos.trBase, temp ); - temp[ 2 ] -= 4096.0f; - - CG_Trace( &tr, es->pos.trBase, NULL, NULL, temp, es->number, MASK_SOLID ); - VectorCopy( tr.endpos, origin ); - - size = 32.0f; - - if( size > 0.0f ) - CG_ImpactMark( cgs.media.creepShader, origin, up, - 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, qfalse, size, qtrue ); - } -} - - -/* -=============== -CG_PlayerFloatSprite - -Float a sprite over the player's head -=============== -*/ -static void CG_PlayerFloatSprite( centity_t *cent, qhandle_t shader ) -{ - int rf; - refEntity_t ent; - - if( cent->currentState.number == cg.snap->ps.clientNum && !cg.renderingThirdPerson ) - rf = RF_THIRD_PERSON; // only show in mirrors - else - rf = 0; - - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - ent.origin[ 2 ] += 48; - ent.reType = RT_SPRITE; - ent.customShader = shader; - ent.radius = 10; - ent.renderfx = rf; - ent.shaderRGBA[ 0 ] = 255; - ent.shaderRGBA[ 1 ] = 255; - ent.shaderRGBA[ 2 ] = 255; - ent.shaderRGBA[ 3 ] = 255; - trap_R_AddRefEntityToScene( &ent ); -} - - - -/* -=============== -CG_PlayerSprites - -Float sprites over the player's head -=============== -*/ -static void CG_PlayerSprites( centity_t *cent ) -{ - if( cent->currentState.eFlags & EF_CONNECTION ) - { - CG_PlayerFloatSprite( cent, cgs.media.connectionShader ); - return; - } - - if( cent->currentState.eFlags & EF_TALK ) - { - //TA: the masses have decreed this to be wrong -/* CG_PlayerFloatSprite( cent, cgs.media.balloonShader ); - return;*/ - } -} - -/* -=============== -CG_PlayerShadow - -Returns the Z component of the surface being shadowed - - should it return a full plane instead of a Z? -=============== -*/ -#define SHADOW_DISTANCE 128 -static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane, pClass_t class ) -{ - vec3_t end, mins, maxs; - trace_t trace; - float alpha; - entityState_t *es = ¢->currentState; - vec3_t surfNormal = { 0.0f, 0.0f, 1.0f }; - - BG_FindBBoxForClass( class, mins, maxs, NULL, NULL, NULL ); - mins[ 2 ] = 0.0f; - maxs[ 2 ] = 2.0f; - - if( es->eFlags & EF_WALLCLIMB ) - { - if( es->eFlags & EF_WALLCLIMBCEILING ) - VectorSet( surfNormal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( es->angles2, surfNormal ); - } - - *shadowPlane = 0; - - if( cg_shadows.integer == 0 ) - return qfalse; - - // send a trace down from the player to the ground - VectorCopy( cent->lerpOrigin, end ); - VectorMA( cent->lerpOrigin, -SHADOW_DISTANCE, surfNormal, end ); - - trap_CM_BoxTrace( &trace, cent->lerpOrigin, end, mins, maxs, 0, MASK_PLAYERSOLID ); - - // no shadow if too high - if( trace.fraction == 1.0 || trace.startsolid || trace.allsolid ) - return qfalse; - - //TA: FIXME: stencil shadows will be broken for walls. - // Unfortunately there isn't much that can be - // done since Q3 references only the Z coord - // of the shadowPlane - if( surfNormal[ 2 ] < 0.0f ) - *shadowPlane = trace.endpos[ 2 ] - 1.0f; - else - *shadowPlane = trace.endpos[ 2 ] + 1.0f; - - if( cg_shadows.integer != 1 ) // no mark for stencil or projection shadows - return qtrue; - - // fade the shadow out with height - alpha = 1.0 - trace.fraction; - - // add the mark as a temporary, so it goes directly to the renderer - // without taking a spot in the cg_marks array - CG_ImpactMark( cgs.media.shadowMarkShader, trace.endpos, trace.plane.normal, - cent->pe.legs.yawAngle, alpha, alpha, alpha, 1, qfalse, - 24.0f * BG_FindShadowScaleForClass( class ), qtrue ); - - return qtrue; -} - - -/* -=============== -CG_PlayerSplash - -Draw a mark at the water surface -=============== -*/ -static void CG_PlayerSplash( centity_t *cent ) -{ - vec3_t start, end; - trace_t trace; - int contents; - polyVert_t verts[ 4 ]; - - if( !cg_shadows.integer ) - return; - - VectorCopy( cent->lerpOrigin, end ); - end[ 2 ] -= 24; - - // if the feet aren't in liquid, don't make a mark - // this won't handle moving water brushes, but they wouldn't draw right anyway... - contents = trap_CM_PointContents( end, 0 ); - - if( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) ) - return; - - VectorCopy( cent->lerpOrigin, start ); - start[ 2 ] += 32; - - // if the head isn't out of liquid, don't make a mark - contents = trap_CM_PointContents( start, 0 ); - - if( contents & ( CONTENTS_SOLID | CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - return; - - // trace down to find the surface - trap_CM_BoxTrace( &trace, start, end, NULL, NULL, 0, ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ); - - if( trace.fraction == 1.0 ) - return; - - // create a mark polygon - VectorCopy( trace.endpos, verts[ 0 ].xyz ); - verts[ 0 ].xyz[ 0 ] -= 32; - verts[ 0 ].xyz[ 1 ] -= 32; - verts[ 0 ].st[ 0 ] = 0; - verts[ 0 ].st[ 1 ] = 0; - verts[ 0 ].modulate[ 0 ] = 255; - verts[ 0 ].modulate[ 1 ] = 255; - verts[ 0 ].modulate[ 2 ] = 255; - verts[ 0 ].modulate[ 3 ] = 255; - - VectorCopy( trace.endpos, verts[ 1 ].xyz ); - verts[ 1 ].xyz[ 0 ] -= 32; - verts[ 1 ].xyz[ 1 ] += 32; - verts[ 1 ].st[ 0 ] = 0; - verts[ 1 ].st[ 1 ] = 1; - verts[ 1 ].modulate[ 0 ] = 255; - verts[ 1 ].modulate[ 1 ] = 255; - verts[ 1 ].modulate[ 2 ] = 255; - verts[ 1 ].modulate[ 3 ] = 255; - - VectorCopy( trace.endpos, verts[ 2 ].xyz ); - verts[ 2 ].xyz[ 0 ] += 32; - verts[ 2 ].xyz[ 1 ] += 32; - verts[ 2 ].st[ 0 ] = 1; - verts[ 2 ].st[ 1 ] = 1; - verts[ 2 ].modulate[ 0 ] = 255; - verts[ 2 ].modulate[ 1 ] = 255; - verts[ 2 ].modulate[ 2 ] = 255; - verts[ 2 ].modulate[ 3 ] = 255; - - VectorCopy( trace.endpos, verts[ 3 ].xyz ); - verts[ 3 ].xyz[ 0 ] += 32; - verts[ 3 ].xyz[ 1 ] -= 32; - verts[ 3 ].st[ 0 ] = 1; - verts[ 3 ].st[ 1 ] = 0; - verts[ 3 ].modulate[ 0 ] = 255; - verts[ 3 ].modulate[ 1 ] = 255; - verts[ 3 ].modulate[ 2 ] = 255; - verts[ 3 ].modulate[ 3 ] = 255; - - trap_R_AddPolyToScene( cgs.media.wakeMarkShader, 4, verts ); -} - - -/* -================= -CG_LightVerts -================= -*/ -int CG_LightVerts( vec3_t normal, int numVerts, polyVert_t *verts ) -{ - int i, j; - float incoming; - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - - trap_R_LightForPoint( verts[ 0 ].xyz, ambientLight, directedLight, lightDir ); - - for( i = 0; i < numVerts; i++ ) - { - incoming = DotProduct( normal, lightDir ); - - if( incoming <= 0 ) - { - verts[ i ].modulate[ 0 ] = ambientLight[ 0 ]; - verts[ i ].modulate[ 1 ] = ambientLight[ 1 ]; - verts[ i ].modulate[ 2 ] = ambientLight[ 2 ]; - verts[ i ].modulate[ 3 ] = 255; - continue; - } - - j = ( ambientLight[ 0 ] + incoming * directedLight[ 0 ] ); - - if( j > 255 ) - j = 255; - - verts[ i ].modulate[ 0 ] = j; - - j = ( ambientLight[ 1 ] + incoming * directedLight[ 1 ] ); - - if( j > 255 ) - j = 255; - - verts[ i ].modulate[ 1 ] = j; - - j = ( ambientLight[ 2 ] + incoming * directedLight[ 2 ] ); - - if( j > 255 ) - j = 255; - - verts[ i ].modulate[ 2 ] = j; - - verts[ i ].modulate[ 3 ] = 255; - } - return qtrue; -} - - -/* -================= -CG_LightFromDirection -================= -*/ -int CG_LightFromDirection( vec3_t point, vec3_t direction ) -{ - int j; - float incoming; - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - vec3_t result; - - trap_R_LightForPoint( point, ambientLight, directedLight, lightDir ); - - incoming = DotProduct( direction, lightDir ); - - if( incoming <= 0 ) - { - result[ 0 ] = ambientLight[ 0 ]; - result[ 1 ] = ambientLight[ 1 ]; - result[ 2 ] = ambientLight[ 2 ]; - return (int)( (float)( result[ 0 ] + result[ 1 ] + result[ 2 ] ) / 3.0f ); - } - - j = ( ambientLight[ 0 ] + incoming * directedLight[ 0 ] ); - - if( j > 255 ) - j = 255; - - result[ 0 ] = j; - - j = ( ambientLight[ 1 ] + incoming * directedLight[ 1 ] ); - - if( j > 255 ) - j = 255; - - result[ 1 ] = j; - - j = ( ambientLight[ 2 ] + incoming * directedLight[ 2 ] ); - - if( j > 255 ) - j = 255; - - result[ 2 ] = j; - - return (int)((float)( result[ 0 ] + result[ 1 ] + result[ 2 ] ) / 3.0f ); -} - - -/* -================= -CG_AmbientLight -================= -*/ -int CG_AmbientLight( vec3_t point ) -{ - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - vec3_t result; - - trap_R_LightForPoint( point, ambientLight, directedLight, lightDir ); - - result[ 0 ] = ambientLight[ 0 ]; - result[ 1 ] = ambientLight[ 1 ]; - result[ 2 ] = ambientLight[ 2 ]; - return (int)((float)( result[ 0 ] + result[ 1 ] + result[ 2 ] ) / 3.0f ); -} - -#define TRACE_DEPTH 32.0f - -/* -=============== -CG_Player -=============== -*/ -void CG_Player( centity_t *cent ) -{ - clientInfo_t *ci; - - //TA: NOTE: legs is used for nonsegmented models - // this helps reduce code to be changed - refEntity_t legs; - refEntity_t torso; - refEntity_t head; - int clientNum; - int renderfx; - qboolean shadow = qfalse; - float shadowPlane; - entityState_t *es = ¢->currentState; - pClass_t class = ( es->powerups >> 8 ) & 0xFF; - float scale; - vec3_t tempAxis[ 3 ], tempAxis2[ 3 ]; - vec3_t angles; - int held = es->modelindex; - vec3_t surfNormal = { 0.0f, 0.0f, 1.0f }; - - // the client number is stored in clientNum. It can't be derived - // from the entity number, because a single client may have - // multiple corpses on the level using the same clientinfo - clientNum = es->clientNum; - if( clientNum < 0 || clientNum >= MAX_CLIENTS ) - CG_Error( "Bad clientNum on player entity" ); - - ci = &cgs.clientinfo[ clientNum ]; - - // it is possible to see corpses from disconnected players that may - // not have valid clientinfo - if( !ci->infoValid ) - return; - - //don't draw - if( es->eFlags & EF_NODRAW ) - return; - - // get the player model information - renderfx = 0; - if( es->number == cg.snap->ps.clientNum ) - { - if( !cg.renderingThirdPerson ) - renderfx = RF_THIRD_PERSON; // only draw in mirrors - else if( cg_cameraMode.integer ) - return; - } - - if( cg_drawBBOX.integer ) - { - vec3_t mins, maxs; - - BG_FindBBoxForClass( class, mins, maxs, NULL, NULL, NULL ); - CG_DrawBoundingBox( cent->lerpOrigin, mins, maxs ); - } - - memset( &legs, 0, sizeof( legs ) ); - memset( &torso, 0, sizeof( torso ) ); - memset( &head, 0, sizeof( head ) ); - - VectorCopy( cent->lerpAngles, angles ); - AnglesToAxis( cent->lerpAngles, tempAxis ); - - //rotate lerpAngles to floor - if( es->eFlags & EF_WALLCLIMB && - BG_RotateAxis( es->angles2, tempAxis, tempAxis2, qtrue, es->eFlags & EF_WALLCLIMBCEILING ) ) - AxisToAngles( tempAxis2, angles ); - else - VectorCopy( cent->lerpAngles, angles ); - - //normalise the pitch - if( angles[ PITCH ] < -180.0f ) - angles[ PITCH ] += 360.0f; - - // get the rotation information - if( !ci->nonsegmented ) - CG_PlayerAngles( cent, angles, legs.axis, torso.axis, head.axis ); - else - CG_PlayerNonSegAngles( cent, angles, legs.axis ); - - AxisCopy( legs.axis, tempAxis ); - - //rotate the legs axis to back to the wall - if( es->eFlags & EF_WALLCLIMB && - BG_RotateAxis( es->angles2, legs.axis, tempAxis, qfalse, es->eFlags & EF_WALLCLIMBCEILING ) ) - AxisCopy( tempAxis, legs.axis ); - - //smooth out WW transitions so the model doesn't hop around - CG_PlayerWWSmoothing( cent, legs.axis, legs.axis ); - - AxisCopy( tempAxis, cent->pe.lastAxis ); - - // get the animation state (after rotation, to allow feet shuffle) - if( !ci->nonsegmented ) - CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp, - &torso.oldframe, &torso.frame, &torso.backlerp ); - else - CG_PlayerNonSegAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp ); - - // add the talk baloon or disconnect icon - CG_PlayerSprites( cent ); - - // add the shadow - if( ( es->number == cg.snap->ps.clientNum && cg.renderingThirdPerson ) || - es->number != cg.snap->ps.clientNum ) - shadow = CG_PlayerShadow( cent, &shadowPlane, class ); - - // add a water splash if partially in and out of water - CG_PlayerSplash( cent ); - - if( cg_shadows.integer == 3 && shadow ) - renderfx |= RF_SHADOW_PLANE; - - renderfx |= RF_LIGHTING_ORIGIN; // use the same origin for all - - // - // add the legs - // - if( !ci->nonsegmented ) - { - legs.hModel = ci->legsModel; - - if( held & ( 1 << UP_LIGHTARMOUR ) ) - legs.customSkin = cgs.media.larmourLegsSkin; - else - legs.customSkin = ci->legsSkin; - } - else - { - legs.hModel = ci->nonSegModel; - legs.customSkin = ci->nonSegSkin; - } - - VectorCopy( cent->lerpOrigin, legs.origin ); - - VectorCopy( cent->lerpOrigin, legs.lightingOrigin ); - legs.shadowPlane = shadowPlane; - legs.renderfx = renderfx; - VectorCopy( legs.origin, legs.oldorigin ); // don't positionally lerp at all - - //move the origin closer into the wall with a CapTrace - if( es->eFlags & EF_WALLCLIMB && !( es->eFlags & EF_DEAD ) && !( cg.intermissionStarted ) ) - { - vec3_t start, end, mins, maxs; - trace_t tr; - - if( es->eFlags & EF_WALLCLIMBCEILING ) - VectorSet( surfNormal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( es->angles2, surfNormal ); - - BG_FindBBoxForClass( class, mins, maxs, NULL, NULL, NULL ); - - VectorMA( legs.origin, -TRACE_DEPTH, surfNormal, end ); - VectorMA( legs.origin, 1.0f, surfNormal, start ); - CG_CapTrace( &tr, start, mins, maxs, end, es->number, MASK_PLAYERSOLID ); - - //if the trace misses completely then just use legs.origin - //apparently capsule traces are "smaller" than box traces - if( tr.fraction != 1.0f ) - VectorMA( legs.origin, tr.fraction * -TRACE_DEPTH, surfNormal, legs.origin ); - - VectorCopy( legs.origin, legs.lightingOrigin ); - VectorCopy( legs.origin, legs.oldorigin ); // don't positionally lerp at all - } - - //rescale the model - scale = BG_FindModelScaleForClass( class ); - - if( scale != 1.0f ) - { - VectorScale( legs.axis[ 0 ], scale, legs.axis[ 0 ] ); - VectorScale( legs.axis[ 1 ], scale, legs.axis[ 1 ] ); - VectorScale( legs.axis[ 2 ], scale, legs.axis[ 2 ] ); - - legs.nonNormalizedAxes = qtrue; - } - - //offset on the Z axis if required - VectorMA( legs.origin, BG_FindZOffsetForClass( class ), surfNormal, legs.origin ); - VectorCopy( legs.origin, legs.lightingOrigin ); - VectorCopy( legs.origin, legs.oldorigin ); // don't positionally lerp at all - - trap_R_AddRefEntityToScene( &legs ); - - // if the model failed, allow the default nullmodel to be displayed - if( !legs.hModel ) - return; - - if( !ci->nonsegmented ) - { - // - // add the torso - // - torso.hModel = ci->torsoModel; - - if( held & ( 1 << UP_LIGHTARMOUR ) ) - torso.customSkin = cgs.media.larmourTorsoSkin; - else - torso.customSkin = ci->torsoSkin; - - if( !torso.hModel ) - return; - - VectorCopy( cent->lerpOrigin, torso.lightingOrigin ); - - CG_PositionRotatedEntityOnTag( &torso, &legs, ci->legsModel, "tag_torso" ); - - torso.shadowPlane = shadowPlane; - torso.renderfx = renderfx; - - trap_R_AddRefEntityToScene( &torso ); - - // - // add the head - // - head.hModel = ci->headModel; - - if( held & ( 1 << UP_HELMET ) ) - head.customSkin = cgs.media.larmourHeadSkin; - else - head.customSkin = ci->headSkin; - - if( !head.hModel ) - return; - - VectorCopy( cent->lerpOrigin, head.lightingOrigin ); - - CG_PositionRotatedEntityOnTag( &head, &torso, ci->torsoModel, "tag_head" ); - - head.shadowPlane = shadowPlane; - head.renderfx = renderfx; - - trap_R_AddRefEntityToScene( &head ); - } - - // - // add the gun / barrel / flash - // - if( es->weapon != WP_NONE ) - { - if( !ci->nonsegmented ) - CG_AddPlayerWeapon( &torso, NULL, cent ); - else - CG_AddPlayerWeapon( &legs, NULL, cent ); - } - - CG_PlayerUpgrades( cent, &torso ); - - //sanity check that particle systems are stopped when dead - if( es->eFlags & EF_DEAD ) - { - if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) - CG_DestroyParticleSystem( ¢->muzzlePS ); - - if( CG_IsParticleSystemValid( ¢->jetPackPS ) ) - CG_DestroyParticleSystem( ¢->jetPackPS ); - } - - VectorCopy( surfNormal, cent->pe.lastNormal ); -} - -/* -=============== -CG_Corpse -=============== -*/ -void CG_Corpse( centity_t *cent ) -{ - clientInfo_t *ci; - refEntity_t legs; - refEntity_t torso; - refEntity_t head; - entityState_t *es = ¢->currentState; - int corpseNum; - int renderfx; - qboolean shadow = qfalse; - float shadowPlane; - vec3_t origin, liveZ, deadZ; - float scale; - - corpseNum = CG_GetCorpseNum( es->clientNum ); - - if( corpseNum < 0 || corpseNum >= MAX_CLIENTS ) - CG_Error( "Bad corpseNum on corpse entity: %d", corpseNum ); - - ci = &cgs.corpseinfo[ corpseNum ]; - - // it is possible to see corpses from disconnected players that may - // not have valid clientinfo - if( !ci->infoValid ) - return; - - memset( &legs, 0, sizeof( legs ) ); - memset( &torso, 0, sizeof( torso ) ); - memset( &head, 0, sizeof( head ) ); - - VectorCopy( cent->lerpOrigin, origin ); - BG_FindBBoxForClass( es->clientNum, liveZ, NULL, NULL, deadZ, NULL ); - origin[ 2 ] -= ( liveZ[ 2 ] - deadZ[ 2 ] ); - - VectorCopy( es->angles, cent->lerpAngles ); - - // get the rotation information - if( !ci->nonsegmented ) - CG_PlayerAngles( cent, cent->lerpAngles, legs.axis, torso.axis, head.axis ); - else - CG_PlayerNonSegAngles( cent, cent->lerpAngles, legs.axis ); - - //set the correct frame (should always be dead) - if( cg_noPlayerAnims.integer ) - legs.oldframe = legs.frame = torso.oldframe = torso.frame = 0; - else if( !ci->nonsegmented ) - { - memset( ¢->pe.legs, 0, sizeof( lerpFrame_t ) ); - CG_RunPlayerLerpFrame( ci, ¢->pe.legs, es->legsAnim, 1 ); - legs.oldframe = cent->pe.legs.oldFrame; - legs.frame = cent->pe.legs.frame; - legs.backlerp = cent->pe.legs.backlerp; - - memset( ¢->pe.torso, 0, sizeof( lerpFrame_t ) ); - CG_RunPlayerLerpFrame( ci, ¢->pe.torso, es->torsoAnim, 1 ); - torso.oldframe = cent->pe.torso.oldFrame; - torso.frame = cent->pe.torso.frame; - torso.backlerp = cent->pe.torso.backlerp; - } - else - { - memset( ¢->pe.nonseg, 0, sizeof( lerpFrame_t ) ); - CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, es->legsAnim, 1 ); - legs.oldframe = cent->pe.nonseg.oldFrame; - legs.frame = cent->pe.nonseg.frame; - legs.backlerp = cent->pe.nonseg.backlerp; - } - - // add the shadow - shadow = CG_PlayerShadow( cent, &shadowPlane, es->clientNum ); - - // get the player model information - renderfx = 0; - - if( cg_shadows.integer == 3 && shadow ) - renderfx |= RF_SHADOW_PLANE; - - renderfx |= RF_LIGHTING_ORIGIN; // use the same origin for all - - // - // add the legs - // - if( !ci->nonsegmented ) - { - legs.hModel = ci->legsModel; - legs.customSkin = ci->legsSkin; - } - else - { - legs.hModel = ci->nonSegModel; - legs.customSkin = ci->nonSegSkin; - } - - VectorCopy( origin, legs.origin ); - - VectorCopy( origin, legs.lightingOrigin ); - legs.shadowPlane = shadowPlane; - legs.renderfx = renderfx; - legs.origin[ 2 ] += BG_FindZOffsetForClass( es->clientNum ); - VectorCopy( legs.origin, legs.oldorigin ); // don't positionally lerp at all - - //rescale the model - scale = BG_FindModelScaleForClass( es->clientNum ); - - if( scale != 1.0f ) - { - VectorScale( legs.axis[ 0 ], scale, legs.axis[ 0 ] ); - VectorScale( legs.axis[ 1 ], scale, legs.axis[ 1 ] ); - VectorScale( legs.axis[ 2 ], scale, legs.axis[ 2 ] ); - - legs.nonNormalizedAxes = qtrue; - } - - //CG_AddRefEntityWithPowerups( &legs, es->powerups, ci->team ); - trap_R_AddRefEntityToScene( &legs ); - - // if the model failed, allow the default nullmodel to be displayed - if( !legs.hModel ) - return; - - if( !ci->nonsegmented ) - { - // - // add the torso - // - torso.hModel = ci->torsoModel; - if( !torso.hModel ) - return; - - torso.customSkin = ci->torsoSkin; - - VectorCopy( origin, torso.lightingOrigin ); - - CG_PositionRotatedEntityOnTag( &torso, &legs, ci->legsModel, "tag_torso" ); - - torso.shadowPlane = shadowPlane; - torso.renderfx = renderfx; - - //CG_AddRefEntityWithPowerups( &torso, es->powerups, ci->team ); - trap_R_AddRefEntityToScene( &torso ); - - // - // add the head - // - head.hModel = ci->headModel; - if( !head.hModel ) - return; - - head.customSkin = ci->headSkin; - - VectorCopy( origin, head.lightingOrigin ); - - CG_PositionRotatedEntityOnTag( &head, &torso, ci->torsoModel, "tag_head"); - - head.shadowPlane = shadowPlane; - head.renderfx = renderfx; - - //CG_AddRefEntityWithPowerups( &head, es->powerups, ci->team ); - trap_R_AddRefEntityToScene( &head ); - } -} - - -//===================================================================== - -/* -=============== -CG_ResetPlayerEntity - -A player just came into view or teleported, so reset all animation info -=============== -*/ -void CG_ResetPlayerEntity( centity_t *cent ) -{ - cent->errorTime = -99999; // guarantee no error decay added - cent->extrapolated = qfalse; - - CG_ClearLerpFrame( &cgs.clientinfo[ cent->currentState.clientNum ], - ¢->pe.legs, cent->currentState.legsAnim ); - CG_ClearLerpFrame( &cgs.clientinfo[ cent->currentState.clientNum ], - ¢->pe.torso, cent->currentState.torsoAnim ); - CG_ClearLerpFrame( &cgs.clientinfo[ cent->currentState.clientNum ], - ¢->pe.nonseg, cent->currentState.legsAnim ); - - BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); - BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); - - VectorCopy( cent->lerpOrigin, cent->rawOrigin ); - VectorCopy( cent->lerpAngles, cent->rawAngles ); - - memset( ¢->pe.legs, 0, sizeof( cent->pe.legs ) ); - cent->pe.legs.yawAngle = cent->rawAngles[ YAW ]; - cent->pe.legs.yawing = qfalse; - cent->pe.legs.pitchAngle = 0; - cent->pe.legs.pitching = qfalse; - - memset( ¢->pe.torso, 0, sizeof( cent->pe.legs ) ); - cent->pe.torso.yawAngle = cent->rawAngles[ YAW ]; - cent->pe.torso.yawing = qfalse; - cent->pe.torso.pitchAngle = cent->rawAngles[ PITCH ]; - cent->pe.torso.pitching = qfalse; - - memset( ¢->pe.nonseg, 0, sizeof( cent->pe.nonseg ) ); - cent->pe.nonseg.yawAngle = cent->rawAngles[ YAW ]; - cent->pe.nonseg.yawing = qfalse; - cent->pe.nonseg.pitchAngle = cent->rawAngles[ PITCH ]; - cent->pe.nonseg.pitching = qfalse; - - if( cg_debugPosition.integer ) - CG_Printf( "%i ResetPlayerEntity yaw=%i\n", cent->currentState.number, cent->pe.torso.yawAngle ); -} - -/* -================== -CG_PlayerDisconnect - -Player disconnecting -================== -*/ -void CG_PlayerDisconnect( vec3_t org ) -{ - particleSystem_t *ps; - - trap_S_StartSound( org, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.disconnectSound ); - - ps = CG_SpawnNewParticleSystem( cgs.media.disconnectPS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentPoint( &ps->attachment, org ); - CG_AttachToPoint( &ps->attachment ); - } -} - -/* -================= -CG_Bleed - -This is the spurt of blood when a character gets hit -================= -*/ -void CG_Bleed( vec3_t origin, vec3_t normal, int entityNum ) -{ - pTeam_t team = cgs.clientinfo[ entityNum ].team; - qhandle_t bleedPS; - particleSystem_t *ps; - - if( !cg_blood.integer ) - return; - - if( team == PTE_ALIENS ) - bleedPS = cgs.media.alienBleedPS; - else if( team == PTE_HUMANS ) - bleedPS = cgs.media.humanBleedPS; - else - return; - - ps = CG_SpawnNewParticleSystem( bleedPS ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentPoint( &ps->attachment, origin ); - CG_SetAttachmentCent( &ps->attachment, &cg_entities[ entityNum ] ); - CG_AttachToPoint( &ps->attachment ); - - CG_SetParticleSystemNormal( ps, normal ); - } -} diff --git a/mod/src/cgame/cg_playerstate.c b/mod/src/cgame/cg_playerstate.c deleted file mode 100644 index 489b024d..00000000 --- a/mod/src/cgame/cg_playerstate.c +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_playerstate.c -- this file acts on changes in a new playerState_t -// With normal play, this will be done after local prediction, but when -// following another player or playing back a demo, it will be checked -// when the snapshot transitions like all the other entities - -/* - * 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" - -/* -============== -CG_DamageFeedback -============== -*/ -void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) -{ - float left, front, up; - float kick; - int health; - float scale; - vec3_t dir; - vec3_t angles; - float dist; - float yaw, pitch; - - // show the attacking player's head and name in corner - cg.attackerTime = cg.time; - - // the lower on health you are, the greater the view kick will be - health = cg.snap->ps.stats[STAT_HEALTH]; - - if( health < 40 ) - scale = 1; - else - scale = 40.0 / health; - - kick = damage * scale; - - if( kick < 5 ) - kick = 5; - - if( kick > 10 ) - kick = 10; - - // if yaw and pitch are both 255, make the damage always centered (falling, etc) - if( yawByte == 255 && pitchByte == 255 ) - { - cg.damageX = 0; - cg.damageY = 0; - cg.v_dmg_roll = 0; - cg.v_dmg_pitch = -kick; - } - else - { - // positional - pitch = pitchByte / 255.0 * 360; - yaw = yawByte / 255.0 * 360; - - angles[ PITCH ] = pitch; - angles[ YAW ] = yaw; - angles[ ROLL ] = 0; - - AngleVectors( angles, dir, NULL, NULL ); - VectorSubtract( vec3_origin, dir, dir ); - - front = DotProduct( dir, cg.refdef.viewaxis[ 0 ] ); - left = DotProduct( dir, cg.refdef.viewaxis[ 1 ] ); - up = DotProduct( dir, cg.refdef.viewaxis[ 2 ] ); - - dir[ 0 ] = front; - dir[ 1 ] = left; - dir[ 2 ] = 0; - dist = VectorLength( dir ); - - if( dist < 0.1f ) - dist = 0.1f; - - cg.v_dmg_roll = kick * left; - - cg.v_dmg_pitch = -kick * front; - - if( front <= 0.1 ) - front = 0.1f; - - cg.damageX = -left / front; - cg.damageY = up / dist; - } - - // clamp the position - if( cg.damageX > 1.0 ) - cg.damageX = 1.0; - - if( cg.damageX < - 1.0 ) - cg.damageX = -1.0; - - if( cg.damageY > 1.0 ) - cg.damageY = 1.0; - - if( cg.damageY < - 1.0 ) - cg.damageY = -1.0; - - // don't let the screen flashes vary as much - if( kick > 10 ) - kick = 10; - - cg.damageValue = kick; - cg.v_dmg_time = cg.time + DAMAGE_TIME; - cg.damageTime = cg.snap->serverTime; -} - - - - -/* -================ -CG_Respawn - -A respawn happened this snapshot -================ -*/ -void CG_Respawn( void ) -{ - // no error decay on player movement - cg.thisFrameTeleport = qtrue; - - // display weapons available - cg.weaponSelectTime = cg.time; - - // select the weapon the server says we are using - cg.weaponSelect = cg.snap->ps.weapon; - - CG_ResetPainBlend( ); -} - -/* -============== -CG_CheckPlayerstateEvents - -============== -*/ -void CG_CheckPlayerstateEvents( playerState_t *ps, playerState_t *ops ) -{ - int i; - int event; - centity_t *cent; - - if( ps->externalEvent && ps->externalEvent != ops->externalEvent ) - { - cent = &cg_entities[ ps->clientNum ]; - cent->currentState.event = ps->externalEvent; - cent->currentState.eventParm = ps->externalEventParm; - CG_EntityEvent( cent, cent->lerpOrigin ); - } - - cent = &cg.predictedPlayerEntity; // cg_entities[ ps->clientNum ]; - - // go through the predictable events buffer - for( i = ps->eventSequence - MAX_PS_EVENTS; i < ps->eventSequence; i++ ) - { - // if we have a new predictable event - if( i >= ops->eventSequence || - // or the server told us to play another event instead of a predicted event we already issued - // or something the server told us changed our prediction causing a different event - ( i > ops->eventSequence - MAX_PS_EVENTS && ps->events[ i & ( MAX_PS_EVENTS - 1 ) ] != - ops->events[ i & ( MAX_PS_EVENTS - 1 ) ] ) ) - { - event = ps->events[ i & ( MAX_PS_EVENTS - 1 ) ]; - - cent->currentState.event = event; - cent->currentState.eventParm = ps->eventParms[ i & ( MAX_PS_EVENTS - 1 ) ]; - CG_EntityEvent( cent, cent->lerpOrigin ); - cg.predictableEvents[ i & ( MAX_PREDICTED_EVENTS - 1 ) ] = event; - - cg.eventSequence++; - } - } -} - - -/* -================== -CG_CheckChangedPredictableEvents -================== -*/ -void CG_CheckChangedPredictableEvents( playerState_t *ps ) -{ - int i; - int event; - centity_t *cent; - - cent = &cg.predictedPlayerEntity; - - for( i = ps->eventSequence - MAX_PS_EVENTS; i < ps->eventSequence; i++ ) - { - // - if( i >= cg.eventSequence ) - continue; - - // if this event is not further back in than the maximum predictable events we remember - if( i > cg.eventSequence - MAX_PREDICTED_EVENTS ) - { - // if the new playerstate event is different from a previously predicted one - if( ps->events[ i & ( MAX_PS_EVENTS - 1 ) ] != cg.predictableEvents[ i & ( MAX_PREDICTED_EVENTS - 1 ) ] ) - { - event = ps->events[ i & ( MAX_PS_EVENTS - 1 ) ]; - cent->currentState.event = event; - cent->currentState.eventParm = ps->eventParms[ i & ( MAX_PS_EVENTS - 1 ) ]; - CG_EntityEvent( cent, cent->lerpOrigin ); - - cg.predictableEvents[ i & ( MAX_PREDICTED_EVENTS - 1 ) ] = event; - - if( cg_showmiss.integer ) - CG_Printf( "WARNING: changed predicted event\n" ); - } - } - } -} - -/* -================== -CG_CheckLocalSounds -================== -*/ -void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) -{ - int reward; - - // don't play the sounds if the player just changed teams - if( ps->persistant[ PERS_TEAM ] != ops->persistant[ PERS_TEAM ] ) - return; - - // health changes of more than -1 should make pain sounds - if( ps->stats[ STAT_HEALTH ] < ops->stats[ STAT_HEALTH ] - 1 ) - { - if( ps->stats[ STAT_HEALTH ] > 0 ) - CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[ STAT_HEALTH ] ); - } - - - // if we are going into the intermission, don't start any voices - if( cg.intermissionStarted ) - return; - - // reward sounds - reward = qfalse; -} - - -/* -=============== -CG_TransitionPlayerState - -=============== -*/ -void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ) -{ - // check for changing follow mode - if( ps->clientNum != ops->clientNum ) - { - cg.thisFrameTeleport = qtrue; - // make sure we don't get any unwanted transition effects - *ops = *ps; - - CG_ResetPainBlend( ); - } - - // damage events (player is getting wounded) - if( ps->damageEvent != ops->damageEvent && ps->damageCount ) - CG_DamageFeedback( ps->damageYaw, ps->damagePitch, ps->damageCount ); - - // respawning - if( ps->persistant[ PERS_SPAWN_COUNT ] != ops->persistant[ PERS_SPAWN_COUNT ] ) - CG_Respawn( ); - - if( cg.mapRestart ) - { - CG_Respawn( ); - cg.mapRestart = qfalse; - } - - if( cg.snap->ps.pm_type != PM_INTERMISSION && - ps->persistant[ PERS_TEAM ] != TEAM_SPECTATOR ) - CG_CheckLocalSounds( ps, ops ); - - // run events - CG_CheckPlayerstateEvents( ps, ops ); - - // smooth the ducking viewheight change - if( ps->viewheight != ops->viewheight ) - { - cg.duckChange = ps->viewheight - ops->viewheight; - cg.duckTime = cg.time; - } -} - diff --git a/mod/src/cgame/cg_predict.c b/mod/src/cgame/cg_predict.c deleted file mode 100644 index dc6c9dd5..00000000 --- a/mod/src/cgame/cg_predict.c +++ /dev/null @@ -1,615 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_predict.c -- this file generates cg.predictedPlayerState by either -// interpolating between snapshots from the server or locally predicting -// ahead the client's movement. -// It also handles local physics interaction, like fragments bouncing off walls - -/* - * 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 pmove_t cg_pmove; - -static int cg_numSolidEntities; -static centity_t *cg_solidEntities[MAX_ENTITIES_IN_SNAPSHOT]; -static int cg_numTriggerEntities; -static centity_t *cg_triggerEntities[MAX_ENTITIES_IN_SNAPSHOT]; - -/* -==================== -CG_BuildSolidList - -When a new cg.snap has been set, this function builds a sublist -of the entities that are actually solid, to make for more -efficient collision detection -==================== -*/ -void CG_BuildSolidList( void ) -{ - int i; - centity_t *cent; - snapshot_t *snap; - entityState_t *ent; - - cg_numSolidEntities = 0; - cg_numTriggerEntities = 0; - - if( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) - snap = cg.nextSnap; - else - snap = cg.snap; - - for( i = 0; i < snap->numEntities; i++ ) - { - cent = &cg_entities[ snap->entities[ i ].number ]; - ent = ¢->currentState; - - if( ent->eType == ET_ITEM || ent->eType == ET_PUSH_TRIGGER || ent->eType == ET_TELEPORT_TRIGGER ) - { - cg_triggerEntities[ cg_numTriggerEntities ] = cent; - cg_numTriggerEntities++; - continue; - } - - if( cent->nextState.solid && ent->eType != ET_MISSILE ) - { - cg_solidEntities[ cg_numSolidEntities ] = cent; - cg_numSolidEntities++; - continue; - } - } -} - -/* -==================== -CG_ClipMoveToEntities - -==================== -*/ -static void CG_ClipMoveToEntities ( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, - int skipNumber, int mask, trace_t *tr, qboolean capsule ) -{ - int i, j, x, zd, zu; - trace_t trace; - entityState_t *ent; - clipHandle_t cmodel; - vec3_t bmins, bmaxs; - vec3_t origin, angles; - centity_t *cent; - - //SUPAR HACK - //this causes a trace to collide with the local player - if( skipNumber == MAGIC_TRACE_HACK ) - j = cg_numSolidEntities + 1; - else - j = cg_numSolidEntities; - - for( i = 0; i < j; i++ ) - { - if( i < cg_numSolidEntities ) - cent = cg_solidEntities[ i ]; - else - cent = &cg.predictedPlayerEntity; - - ent = ¢->currentState; - - if( ent->number == skipNumber ) - continue; - - if( ent->solid == SOLID_BMODEL ) - { - // special value for bmodel - cmodel = trap_CM_InlineModel( ent->modelindex ); - VectorCopy( cent->lerpAngles, angles ); - BG_EvaluateTrajectory( ¢->currentState.pos, cg.physicsTime, origin ); - } - else - { - // encoded bbox - x = ( ent->solid & 255 ); - zd = ( ( ent->solid >> 8 ) & 255 ); - zu = ( ( ent->solid >> 16 ) & 255 ) - 32; - - bmins[ 0 ] = bmins[ 1 ] = -x; - bmaxs[ 0 ] = bmaxs[ 1 ] = x; - bmins[ 2 ] = -zd; - bmaxs[ 2 ] = zu; - - if( i == cg_numSolidEntities ) - BG_FindBBoxForClass( ( ent->powerups >> 8 ) & 0xFF, bmins, bmaxs, NULL, NULL, NULL ); - - cmodel = trap_CM_TempBoxModel( bmins, bmaxs ); - VectorCopy( vec3_origin, angles ); - VectorCopy( cent->lerpOrigin, origin ); - } - - - if( capsule ) - { - trap_CM_TransformedCapsuleTrace ( &trace, start, end, - mins, maxs, cmodel, mask, origin, angles ); - } - else - { - trap_CM_TransformedBoxTrace ( &trace, start, end, - mins, maxs, cmodel, mask, origin, angles ); - } - - if( trace.allsolid || trace.fraction < tr->fraction ) - { - trace.entityNum = ent->number; - *tr = trace; - } - else if( trace.startsolid ) - tr->startsolid = qtrue; - - if( tr->allsolid ) - return; - } -} - -/* -================ -CG_Trace -================ -*/ -void CG_Trace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, - int skipNumber, int mask ) -{ - trace_t t; - - trap_CM_BoxTrace( &t, start, end, mins, maxs, 0, mask ); - t.entityNum = t.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE; - // check all other solid models - CG_ClipMoveToEntities( start, mins, maxs, end, skipNumber, mask, &t, qfalse ); - - *result = t; -} - -/* -================ -CG_CapTrace -================ -*/ -void CG_CapTrace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, - int skipNumber, int mask ) -{ - trace_t t; - - trap_CM_CapsuleTrace( &t, start, end, mins, maxs, 0, mask ); - t.entityNum = t.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE; - // check all other solid models - CG_ClipMoveToEntities( start, mins, maxs, end, skipNumber, mask, &t, qtrue ); - - *result = t; -} - -/* -================ -CG_PointContents -================ -*/ -int CG_PointContents( const vec3_t point, int passEntityNum ) -{ - int i; - entityState_t *ent; - centity_t *cent; - clipHandle_t cmodel; - int contents; - - contents = trap_CM_PointContents (point, 0); - - for( i = 0; i < cg_numSolidEntities; i++ ) - { - cent = cg_solidEntities[ i ]; - - ent = ¢->currentState; - - if( ent->number == passEntityNum ) - continue; - - if( ent->solid != SOLID_BMODEL ) // special value for bmodel - continue; - - cmodel = trap_CM_InlineModel( ent->modelindex ); - - if( !cmodel ) - continue; - - contents |= trap_CM_TransformedPointContents( point, cmodel, ent->origin, ent->angles ); - } - - return contents; -} - - -/* -======================== -CG_InterpolatePlayerState - -Generates cg.predictedPlayerState by interpolating between -cg.snap->player_state and cg.nextFrame->player_state -======================== -*/ -static void CG_InterpolatePlayerState( qboolean grabAngles ) -{ - float f; - int i; - playerState_t *out; - snapshot_t *prev, *next; - - out = &cg.predictedPlayerState; - prev = cg.snap; - next = cg.nextSnap; - - *out = cg.snap->ps; - - // if we are still allowing local input, short circuit the view angles - if( grabAngles ) - { - usercmd_t cmd; - int cmdNum; - - cmdNum = trap_GetCurrentCmdNumber( ); - trap_GetUserCmd( cmdNum, &cmd ); - - PM_UpdateViewAngles( out, &cmd ); - } - - // if the next frame is a teleport, we can't lerp to it - if( cg.nextFrameTeleport ) - return; - - if( !next || next->serverTime <= prev->serverTime ) - return; - - f = (float)( cg.time - prev->serverTime ) / ( next->serverTime - prev->serverTime ); - - i = next->ps.bobCycle; - if( i < prev->ps.bobCycle ) - i += 256; // handle wraparound - - out->bobCycle = prev->ps.bobCycle + f * ( i - prev->ps.bobCycle ); - - for( i = 0; i < 3; i++ ) - { - out->origin[ i ] = prev->ps.origin[ i ] + f * ( next->ps.origin[ i ] - prev->ps.origin[ i ] ); - - if( !grabAngles ) - out->viewangles[ i ] = LerpAngle( prev->ps.viewangles[ i ], next->ps.viewangles[ i ], f ); - - out->velocity[ i ] = prev->ps.velocity[ i ] + - f * (next->ps.velocity[ i ] - prev->ps.velocity[ i ] ); - } -} - - -/* -========================= -CG_TouchTriggerPrediction - -Predict push triggers and items -========================= -*/ -static void CG_TouchTriggerPrediction( void ) -{ - int i; - trace_t trace; - entityState_t *ent; - clipHandle_t cmodel; - centity_t *cent; - qboolean spectator; - - // dead clients don't activate triggers - if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) - return; - - spectator = ( cg.predictedPlayerState.pm_type == PM_SPECTATOR ); - - if( cg.predictedPlayerState.pm_type != PM_NORMAL && !spectator ) - return; - - for( i = 0; i < cg_numTriggerEntities; i++ ) - { - cent = cg_triggerEntities[ i ]; - ent = ¢->currentState; - - if( ent->solid != SOLID_BMODEL ) - continue; - - cmodel = trap_CM_InlineModel( ent->modelindex ); - if( !cmodel ) - continue; - - trap_CM_BoxTrace( &trace, cg.predictedPlayerState.origin, cg.predictedPlayerState.origin, - cg_pmove.mins, cg_pmove.maxs, cmodel, -1 ); - - if( !trace.startsolid ) - continue; - - if( ent->eType == ET_TELEPORT_TRIGGER ) - cg.hyperspace = qtrue; - } - - // if we didn't touch a jump pad this pmove frame - if( cg.predictedPlayerState.jumppad_frame != cg.predictedPlayerState.pmove_framecount ) - { - cg.predictedPlayerState.jumppad_frame = 0; - cg.predictedPlayerState.jumppad_ent = 0; - } -} - - - -/* -================= -CG_PredictPlayerState - -Generates cg.predictedPlayerState for the current cg.time -cg.predictedPlayerState is guaranteed to be valid after exiting. - -For demo playback, this will be an interpolation between two valid -playerState_t. - -For normal gameplay, it will be the result of predicted usercmd_t on -top of the most recent playerState_t received from the server. - -Each new snapshot will usually have one or more new usercmd over the last, -but we simulate all unacknowledged commands each time, not just the new ones. -This means that on an internet connection, quite a few pmoves may be issued -each frame. - -OPTIMIZE: don't re-simulate unless the newly arrived snapshot playerState_t -differs from the predicted one. Would require saving all intermediate -playerState_t during prediction. - -We detect prediction errors and allow them to be decayed off over several frames -to ease the jerk. -================= -*/ -void CG_PredictPlayerState( void ) -{ - int cmdNum, current, i; - playerState_t oldPlayerState; - qboolean moved; - usercmd_t oldestCmd; - usercmd_t latestCmd; - - cg.hyperspace = qfalse; // will be set if touching a trigger_teleport - - // if this is the first frame we must guarantee - // predictedPlayerState is valid even if there is some - // other error condition - if( !cg.validPPS ) - { - cg.validPPS = qtrue; - cg.predictedPlayerState = cg.snap->ps; - } - - - // demo playback just copies the moves - if( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) ) - { - CG_InterpolatePlayerState( qfalse ); - return; - } - - // non-predicting local movement will grab the latest angles - if( cg_nopredict.integer || cg_synchronousClients.integer ) - { - CG_InterpolatePlayerState( qtrue ); - return; - } - - // prepare for pmove - cg_pmove.ps = &cg.predictedPlayerState; - cg_pmove.trace = CG_Trace; - cg_pmove.pointcontents = CG_PointContents; - cg_pmove.debugLevel = cg_debugMove.integer; - - if( cg_pmove.ps->pm_type == PM_DEAD ) - cg_pmove.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY; - else - cg_pmove.tracemask = MASK_PLAYERSOLID; - - if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) - cg_pmove.tracemask &= ~CONTENTS_BODY; // spectators can fly through bodies - - cg_pmove.noFootsteps = 0; - - // save the state before the pmove so we can detect transitions - oldPlayerState = cg.predictedPlayerState; - - current = trap_GetCurrentCmdNumber( ); - - // if we don't have the commands right after the snapshot, we - // can't accurately predict a current position, so just freeze at - // the last good position we had - cmdNum = current - CMD_BACKUP + 1; - trap_GetUserCmd( cmdNum, &oldestCmd ); - - if( oldestCmd.serverTime > cg.snap->ps.commandTime && - oldestCmd.serverTime < cg.time ) - { // special check for map_restart - if( cg_showmiss.integer ) - CG_Printf( "exceeded PACKET_BACKUP on commands\n" ); - - return; - } - - // get the latest command so we can know which commands are from previous map_restarts - trap_GetUserCmd( current, &latestCmd ); - - // get the most recent information we have, even if - // the server time is beyond our current cg.time, - // because predicted player positions are going to - // be ahead of everything else anyway - if( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) - { - cg.predictedPlayerState = cg.nextSnap->ps; - cg.physicsTime = cg.nextSnap->serverTime; - } - else - { - cg.predictedPlayerState = cg.snap->ps; - cg.physicsTime = cg.snap->serverTime; - } - - if( pmove_msec.integer < 8 ) - trap_Cvar_Set( "pmove_msec", "8" ); - else if( pmove_msec.integer > 33 ) - trap_Cvar_Set( "pmove_msec", "33" ); - - cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer; - cg_pmove.pmove_msec = pmove_msec.integer; - - // run cmds - moved = qfalse; - - for( cmdNum = current - CMD_BACKUP + 1; cmdNum <= current; cmdNum++ ) - { - // get the command - trap_GetUserCmd( cmdNum, &cg_pmove.cmd ); - - if( cg_pmove.pmove_fixed ) - PM_UpdateViewAngles( cg_pmove.ps, &cg_pmove.cmd ); - - // don't do anything if the time is before the snapshot player time - if( cg_pmove.cmd.serverTime <= cg.predictedPlayerState.commandTime ) - continue; - - // don't do anything if the command was from a previous map_restart - if( cg_pmove.cmd.serverTime > latestCmd.serverTime ) - continue; - - // check for a prediction error from last frame - // on a lan, this will often be the exact value - // from the snapshot, but on a wan we will have - // to predict several commands to get to the point - // we want to compare - if( cg.predictedPlayerState.commandTime == oldPlayerState.commandTime ) - { - vec3_t delta; - float len; - - if( cg.thisFrameTeleport ) - { - // a teleport will not cause an error decay - VectorClear( cg.predictedError ); - - if( cg_showmiss.integer ) - CG_Printf( "PredictionTeleport\n" ); - - cg.thisFrameTeleport = qfalse; - } - else - { - vec3_t adjusted; - CG_AdjustPositionForMover( cg.predictedPlayerState.origin, - cg.predictedPlayerState.groundEntityNum, cg.physicsTime, cg.oldTime, adjusted ); - - if( cg_showmiss.integer ) - { - if( !VectorCompare( oldPlayerState.origin, adjusted ) ) - CG_Printf("prediction error\n"); - } - - VectorSubtract( oldPlayerState.origin, adjusted, delta ); - len = VectorLength( delta ); - - if( len > 0.1 ) - { - if( cg_showmiss.integer ) - CG_Printf( "Prediction miss: %f\n", len ); - - if( cg_errorDecay.integer ) - { - int t; - float f; - - t = cg.time - cg.predictedErrorTime; - f = ( cg_errorDecay.value - t ) / cg_errorDecay.value; - - if( f < 0 ) - f = 0; - - if( f > 0 && cg_showmiss.integer ) - CG_Printf( "Double prediction decay: %f\n", f ); - - VectorScale( cg.predictedError, f, cg.predictedError ); - } - else - VectorClear( cg.predictedError ); - - VectorAdd( delta, cg.predictedError, cg.predictedError ); - cg.predictedErrorTime = cg.oldTime; - } - } - } - - // don't predict gauntlet firing, which is only supposed to happen - // when it actually inflicts damage - for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) - cg_pmove.autoWeaponHit[ i ] = qfalse; - - if( cg_pmove.pmove_fixed ) - cg_pmove.cmd.serverTime = ( ( cg_pmove.cmd.serverTime + pmove_msec.integer - 1 ) / - pmove_msec.integer ) * pmove_msec.integer; - - Pmove( &cg_pmove ); - - moved = qtrue; - - // add push trigger movement effects - CG_TouchTriggerPrediction( ); - - // check for predictable events that changed from previous predictions - //CG_CheckChangedPredictableEvents(&cg.predictedPlayerState); - } - - if( cg_showmiss.integer > 1 ) - CG_Printf( "[%i : %i] ", cg_pmove.cmd.serverTime, cg.time ); - - if( !moved ) - { - if( cg_showmiss.integer ) - CG_Printf( "not moved\n" ); - - return; - } - - // adjust for the movement of the groundentity - CG_AdjustPositionForMover( cg.predictedPlayerState.origin, - cg.predictedPlayerState.groundEntityNum, - cg.physicsTime, cg.time, cg.predictedPlayerState.origin ); - - if( cg_showmiss.integer ) - { - if( cg.predictedPlayerState.eventSequence > oldPlayerState.eventSequence + MAX_PS_EVENTS ) - CG_Printf( "WARNING: dropped event\n" ); - } - - // fire events and other transition triggered things - CG_TransitionPlayerState( &cg.predictedPlayerState, &oldPlayerState ); - - if( cg_showmiss.integer ) - { - if( cg.eventSequence > cg.predictedPlayerState.eventSequence ) - { - CG_Printf( "WARNING: double event\n" ); - cg.eventSequence = cg.predictedPlayerState.eventSequence; - } - } -} diff --git a/mod/src/cgame/cg_ptr.c b/mod/src/cgame/cg_ptr.c deleted file mode 100644 index c31e5e40..00000000 --- a/mod/src/cgame/cg_ptr.c +++ /dev/null @@ -1,71 +0,0 @@ -// cg_ptr.c -- post timeout restoration handling - -/* - * 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" - -#define PTRC_FILE "ptrc.cfg" - -/* -=============== -CG_ReadPTRCode - -Read a PTR code from disk -=============== -*/ -int CG_ReadPTRCode( void ) -{ - int len; - char text[ 16 ]; - fileHandle_t f; - - // load the file - len = trap_FS_FOpenFile( PTRC_FILE, &f, FS_READ ); - if( len <= 0 ) - return 0; - - // should never happen - malformed write - if( len >= sizeof( text ) - 1 ) - return 0; - - trap_FS_Read( text, len, f ); - text[ len ] = 0; - trap_FS_FCloseFile( f ); - - return atoi( text ); -} - -/* -=============== -CG_WritePTRCode - -Write a PTR code to disk -=============== -*/ -void CG_WritePTRCode( int code ) -{ - char text[ 16 ]; - fileHandle_t f; - - Com_sprintf( text, 16, "%d", code ); - - // open file - if( trap_FS_FOpenFile( PTRC_FILE, &f, FS_WRITE ) < 0 ) - return; - - // write the code - trap_FS_Write( text, strlen( text ), f ); - - trap_FS_FCloseFile( f ); -} diff --git a/mod/src/cgame/cg_public.h b/mod/src/cgame/cg_public.h deleted file mode 100644 index 39d1a402..00000000 --- a/mod/src/cgame/cg_public.h +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// - -/* - * 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. - */ - -#define CMD_BACKUP 64 -#define CMD_MASK (CMD_BACKUP - 1) -// allow a lot of command backups for very fast systems -// multiple commands may be combined into a single packet, so this -// needs to be larger than PACKET_BACKUP - - -#define MAX_ENTITIES_IN_SNAPSHOT 256 - -// snapshots are a view of the server at a given time - -// Snapshots are generated at regular time intervals by the server, -// but they may not be sent if a client's rate level is exceeded, or -// they may be dropped by the network. -typedef struct -{ - int snapFlags; // SNAPFLAG_RATE_DELAYED, etc - int ping; - - int serverTime; // server time the message is valid for (in msec) - - byte areamask[ MAX_MAP_AREA_BYTES ]; // portalarea visibility bits - - playerState_t ps; // complete information about the current player at this time - - int numEntities; // all of the entities that need to be presented - entityState_t entities[ MAX_ENTITIES_IN_SNAPSHOT ]; // at the time of this snapshot - - int numServerCommands; // text based server commands to execute when this - int serverCommandSequence; // snapshot becomes current -} snapshot_t; - -enum -{ - CGAME_EVENT_NONE, - CGAME_EVENT_TEAMMENU, - CGAME_EVENT_SCOREBOARD, - CGAME_EVENT_EDITHUD -}; - -/* -================================================================== - -functions imported from the main executable - -================================================================== -*/ - -#define CGAME_IMPORT_API_VERSION 4 - -typedef enum -{ - CG_PRINT, - CG_ERROR, - CG_MILLISECONDS, - CG_CVAR_REGISTER, - CG_CVAR_UPDATE, - CG_CVAR_SET, - CG_CVAR_VARIABLESTRINGBUFFER, - CG_ARGC, - CG_ARGV, - CG_ARGS, - CG_FS_FOPENFILE, - CG_FS_READ, - CG_FS_WRITE, - CG_FS_FCLOSEFILE, - CG_SENDCONSOLECOMMAND, - CG_ADDCOMMAND, - CG_SENDCLIENTCOMMAND, - CG_UPDATESCREEN, - CG_CM_LOADMAP, - CG_CM_NUMINLINEMODELS, - CG_CM_INLINEMODEL, - CG_CM_LOADMODEL, - CG_CM_TEMPBOXMODEL, - CG_CM_POINTCONTENTS, - CG_CM_TRANSFORMEDPOINTCONTENTS, - CG_CM_BOXTRACE, - CG_CM_TRANSFORMEDBOXTRACE, - CG_CM_MARKFRAGMENTS, - CG_S_STARTSOUND, - CG_S_STARTLOCALSOUND, - CG_S_CLEARLOOPINGSOUNDS, - CG_S_ADDLOOPINGSOUND, - CG_S_UPDATEENTITYPOSITION, - CG_S_RESPATIALIZE, - CG_S_REGISTERSOUND, - CG_S_STARTBACKGROUNDTRACK, - CG_R_LOADWORLDMAP, - CG_R_REGISTERMODEL, - CG_R_REGISTERSKIN, - CG_R_REGISTERSHADER, - CG_R_CLEARSCENE, - CG_R_ADDREFENTITYTOSCENE, - CG_R_ADDPOLYTOSCENE, - CG_R_ADDLIGHTTOSCENE, - CG_R_RENDERSCENE, - CG_R_SETCOLOR, - CG_R_DRAWSTRETCHPIC, - CG_R_MODELBOUNDS, - CG_R_LERPTAG, - CG_GETGLCONFIG, - CG_GETGAMESTATE, - CG_GETCURRENTSNAPSHOTNUMBER, - CG_GETSNAPSHOT, - CG_GETSERVERCOMMAND, - CG_GETCURRENTCMDNUMBER, - CG_GETUSERCMD, - CG_SETUSERCMDVALUE, - CG_R_REGISTERSHADERNOMIP, - CG_MEMORY_REMAINING, - CG_R_REGISTERFONT, - CG_KEY_ISDOWN, - CG_KEY_GETCATCHER, - CG_KEY_SETCATCHER, - CG_KEY_GETKEY, - CG_PC_ADD_GLOBAL_DEFINE, - CG_PC_LOAD_SOURCE, - CG_PC_FREE_SOURCE, - CG_PC_READ_TOKEN, - CG_PC_SOURCE_FILE_AND_LINE, - CG_S_STOPBACKGROUNDTRACK, - CG_REAL_TIME, - CG_SNAPVECTOR, - CG_REMOVECOMMAND, - CG_R_LIGHTFORPOINT, - CG_CIN_PLAYCINEMATIC, - CG_CIN_STOPCINEMATIC, - CG_CIN_RUNCINEMATIC, - CG_CIN_DRAWCINEMATIC, - CG_CIN_SETEXTENTS, - CG_R_REMAP_SHADER, - CG_S_ADDREALLOOPINGSOUND, - CG_S_STOPLOOPINGSOUND, - - CG_CM_TEMPCAPSULEMODEL, - CG_CM_CAPSULETRACE, - CG_CM_TRANSFORMEDCAPSULETRACE, - CG_R_ADDADDITIVELIGHTTOSCENE, - CG_GET_ENTITY_TOKEN, - CG_R_ADDPOLYSTOSCENE, - CG_R_INPVS, - CG_FS_SEEK, - - CG_MEMSET = 100, - CG_MEMCPY, - CG_STRNCPY, - CG_SIN, - CG_COS, - CG_ATAN2, - CG_SQRT, - CG_FLOOR, - CG_CEIL, - - CG_TESTPRINTINT, - CG_TESTPRINTFLOAT, - CG_ACOS -} cgameImport_t; - - -/* -================================================================== - -functions exported to the main executable - -================================================================== -*/ - -typedef enum -{ - CG_INIT, - // void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) - // called when the level loads or when the renderer is restarted - // all media should be registered at this time - // cgame will display loading status by calling SCR_Update, which - // will call CG_DrawInformation during the loading process - // reliableCommandSequence will be 0 on fresh loads, but higher for - // demos, tourney restarts, or vid_restarts - - CG_SHUTDOWN, - // void (*CG_Shutdown)( void ); - // oportunity to flush and close any open files - - CG_CONSOLE_COMMAND, - // qboolean (*CG_ConsoleCommand)( void ); - // a console command has been issued locally that is not recognized by the - // main game system. - // use Cmd_Argc() / Cmd_Argv() to read the command, return qfalse if the - // command is not known to the game - - CG_DRAW_ACTIVE_FRAME, - // void (*CG_DrawActiveFrame)( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ); - // Generates and draws a game scene and status information at the given time. - // If demoPlayback is set, local movement prediction will not be enabled - - CG_CROSSHAIR_PLAYER, - // int (*CG_CrosshairPlayer)( void ); - - CG_LAST_ATTACKER, - // int (*CG_LastAttacker)( void ); - - CG_KEY_EVENT, - // void (*CG_KeyEvent)( int key, qboolean down ); - - CG_MOUSE_EVENT, - // void (*CG_MouseEvent)( int dx, int dy ); - CG_EVENT_HANDLING - // void (*CG_EventHandling)(int type); -} cgameExport_t; - -//---------------------------------------------- diff --git a/mod/src/cgame/cg_scanner.c b/mod/src/cgame/cg_scanner.c deleted file mode 100644 index 6c2a9997..00000000 --- a/mod/src/cgame/cg_scanner.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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 entityPos_t entityPositions; - -#define HUMAN_SCANNER_UPDATE_PERIOD 700 - -/* -============= -CG_UpdateEntityPositions - -Update this client's perception of entity positions -============= -*/ -void CG_UpdateEntityPositions( void ) -{ - centity_t *cent = NULL; - int i; - - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS ) - { - if( entityPositions.lastUpdateTime + HUMAN_SCANNER_UPDATE_PERIOD > cg.time ) - return; - } - - VectorCopy( cg.refdef.vieworg, entityPositions.origin ); - VectorCopy( cg.refdefViewAngles, entityPositions.vangles ); - entityPositions.lastUpdateTime = cg.time; - - entityPositions.numAlienBuildables = 0; - entityPositions.numHumanBuildables = 0; - entityPositions.numAlienClients = 0; - entityPositions.numHumanClients = 0; - - for( i = 0; i < cg.snap->numEntities; i++ ) - { - cent = &cg_entities[ cg.snap->entities[ i ].number ]; - - if( cent->currentState.eType == ET_BUILDABLE ) - { - //TA: add to list of item positions (for creep) - if( cent->currentState.modelindex2 == BIT_ALIENS ) - { - VectorCopy( cent->lerpOrigin, entityPositions.alienBuildablePos[ - entityPositions.numAlienBuildables ] ); - entityPositions.alienBuildableTimes[ - entityPositions.numAlienBuildables ] = cent->miscTime; - - if( entityPositions.numAlienBuildables < MAX_GENTITIES ) - entityPositions.numAlienBuildables++; - } - else if( cent->currentState.modelindex2 == BIT_HUMANS ) - { - VectorCopy( cent->lerpOrigin, entityPositions.humanBuildablePos[ - entityPositions.numHumanBuildables ] ); - - if( entityPositions.numHumanBuildables < MAX_GENTITIES ) - entityPositions.numHumanBuildables++; - } - } - else if( cent->currentState.eType == ET_PLAYER ) - { - int team = cent->currentState.powerups & 0x00FF; - - if( team == PTE_ALIENS ) - { - VectorCopy( cent->lerpOrigin, entityPositions.alienClientPos[ - entityPositions.numAlienClients ] ); - - if( entityPositions.numAlienClients < MAX_CLIENTS ) - entityPositions.numAlienClients++; - } - else if( team == PTE_HUMANS ) - { - VectorCopy( cent->lerpOrigin, entityPositions.humanClientPos[ - entityPositions.numHumanClients ] ); - - if( entityPositions.numHumanClients < MAX_CLIENTS ) - entityPositions.numHumanClients++; - } - } - } -} - -#define STALKWIDTH 2.0f -#define BLIPX 16.0f -#define BLIPY 8.0f -#define FAR_ALPHA 0.8f -#define NEAR_ALPHA 1.2f - -/* -============= -CG_DrawBlips - -Draw blips and stalks for the human scanner -============= -*/ -static void CG_DrawBlips( rectDef_t *rect, vec3_t origin, vec4_t colour ) -{ - vec3_t drawOrigin; - vec3_t up = { 0, 0, 1 }; - float alphaMod = 1.0f; - float timeFractionSinceRefresh = 1.0f - - ( (float)( cg.time - entityPositions.lastUpdateTime ) / - (float)HUMAN_SCANNER_UPDATE_PERIOD ); - vec4_t localColour; - - Vector4Copy( colour, localColour ); - - RotatePointAroundVector( drawOrigin, up, origin, -entityPositions.vangles[ 1 ] - 90 ); - drawOrigin[ 0 ] /= ( 2 * HELMET_RANGE / rect->w ); - drawOrigin[ 1 ] /= ( 2 * HELMET_RANGE / rect->h ); - drawOrigin[ 2 ] /= ( 2 * HELMET_RANGE / rect->w ); - - alphaMod = FAR_ALPHA + - ( ( drawOrigin[ 1 ] + ( rect->h / 2.0f ) ) / rect->h ) * ( NEAR_ALPHA - FAR_ALPHA ); - - localColour[ 3 ] *= alphaMod; - localColour[ 3 ] *= ( 0.5f + ( timeFractionSinceRefresh * 0.5f ) ); - - if( localColour[ 3 ] > 1.0f ) - localColour[ 3 ] = 1.0f; - else if( localColour[ 3 ] < 0.0f ) - localColour[ 3 ] = 0.0f; - - trap_R_SetColor( localColour ); - - if( drawOrigin[ 2 ] > 0 ) - CG_DrawPic( rect->x + ( rect->w / 2 ) - ( STALKWIDTH / 2 ) - drawOrigin[ 0 ], - rect->y + ( rect->h / 2 ) + drawOrigin[ 1 ] - drawOrigin[ 2 ], - STALKWIDTH, drawOrigin[ 2 ], cgs.media.scannerLineShader ); - else - CG_DrawPic( rect->x + ( rect->w / 2 ) - ( STALKWIDTH / 2 ) - drawOrigin[ 0 ], - rect->y + ( rect->h / 2 ) + drawOrigin[ 1 ], - STALKWIDTH, -drawOrigin[ 2 ], cgs.media.scannerLineShader ); - - CG_DrawPic( rect->x + ( rect->w / 2 ) - ( BLIPX / 2 ) - drawOrigin[ 0 ], - rect->y + ( rect->h / 2 ) - ( BLIPY / 2 ) + drawOrigin[ 1 ] - drawOrigin[ 2 ], - BLIPX, BLIPY, cgs.media.scannerBlipShader ); - trap_R_SetColor( NULL ); -} - -#define BLIPX2 24.0f -#define BLIPY2 24.0f - -/* -============= -CG_DrawDir - -Draw dot marking the direction to an enemy -============= -*/ -static void CG_DrawDir( rectDef_t *rect, vec3_t origin, vec4_t colour ) -{ - vec3_t drawOrigin; - vec3_t noZOrigin; - vec3_t normal, antinormal, normalDiff; - vec3_t view, noZview; - vec3_t up = { 0.0f, 0.0f, 1.0f }; - vec3_t top = { 0.0f, -1.0f, 0.0f }; - float angle; - playerState_t *ps = &cg.snap->ps; - - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) - { - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) - VectorSet( normal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( ps->grapplePoint, normal ); - } - else - VectorSet( normal, 0.0f, 0.0f, 1.0f ); - - AngleVectors( entityPositions.vangles, view, NULL, NULL ); - - ProjectPointOnPlane( noZOrigin, origin, normal ); - ProjectPointOnPlane( noZview, view, normal ); - VectorNormalize( noZOrigin ); - VectorNormalize( noZview ); - - //calculate the angle between the images of the blip and the view - angle = RAD2DEG( acos( DotProduct( noZOrigin, noZview ) ) ); - CrossProduct( noZOrigin, noZview, antinormal ); - VectorNormalize( antinormal ); - - //decide which way to rotate - VectorSubtract( normal, antinormal, normalDiff ); - if( VectorLength( normalDiff ) < 1.0f ) - angle = 360.0f - angle; - - RotatePointAroundVector( drawOrigin, up, top, angle ); - - trap_R_SetColor( colour ); - CG_DrawPic( rect->x + ( rect->w / 2 ) - ( BLIPX2 / 2 ) - drawOrigin[ 0 ] * ( rect->w / 2 ), - rect->y + ( rect->h / 2 ) - ( BLIPY2 / 2 ) + drawOrigin[ 1 ] * ( rect->h / 2 ), - BLIPX2, BLIPY2, cgs.media.scannerBlipShader ); - trap_R_SetColor( NULL ); -} - -/* -============= -CG_AlienSense -============= -*/ -void CG_AlienSense( rectDef_t *rect ) -{ - int i; - vec3_t origin; - vec3_t relOrigin; - vec4_t buildable = { 1.0f, 0.0f, 0.0f, 0.7f }; - vec4_t client = { 0.0f, 0.0f, 1.0f, 0.7f }; - - VectorCopy( entityPositions.origin, origin ); - - //draw human buildables - for( i = 0; i < entityPositions.numHumanBuildables; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) - CG_DrawDir( rect, relOrigin, buildable ); - } - - //draw human clients - for( i = 0; i < entityPositions.numHumanClients; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < ALIENSENSE_RANGE ) - CG_DrawDir( rect, relOrigin, client ); - } -} - -/* -============= -CG_Scanner -============= -*/ -void CG_Scanner( rectDef_t *rect, qhandle_t shader, vec4_t color ) -{ - int i; - vec3_t origin; - vec3_t relOrigin; - vec4_t hIabove; - vec4_t hIbelow; - vec4_t aIabove = { 1.0f, 0.0f, 0.0f, 0.75f }; - vec4_t aIbelow = { 1.0f, 0.0f, 0.0f, 0.5f }; - - Vector4Copy( color, hIabove ); - hIabove[ 3 ] *= 1.5f; - Vector4Copy( color, hIbelow ); - - VectorCopy( entityPositions.origin, origin ); - - //draw human buildables below scanner plane - for( i = 0; i < entityPositions.numHumanBuildables; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] < 0 ) ) - CG_DrawBlips( rect, relOrigin, hIbelow ); - } - - //draw alien buildables below scanner plane - for( i = 0; i < entityPositions.numAlienBuildables; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.alienBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] < 0 ) ) - CG_DrawBlips( rect, relOrigin, aIbelow ); - } - - //draw human clients below scanner plane - for( i = 0; i < entityPositions.numHumanClients; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] < 0 ) ) - CG_DrawBlips( rect, relOrigin, hIbelow ); - } - - //draw alien buildables below scanner plane - for( i = 0; i < entityPositions.numAlienClients; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.alienClientPos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] < 0 ) ) - CG_DrawBlips( rect, relOrigin, aIbelow ); - } - - if( !cg_disableScannerPlane.integer ) - { - trap_R_SetColor( color ); - CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); - trap_R_SetColor( NULL ); - } - - //draw human buildables above scanner plane - for( i = 0; i < entityPositions.numHumanBuildables; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] > 0 ) ) - CG_DrawBlips( rect, relOrigin, hIabove ); - } - - //draw alien buildables above scanner plane - for( i = 0; i < entityPositions.numAlienBuildables; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.alienBuildablePos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] > 0 ) ) - CG_DrawBlips( rect, relOrigin, aIabove ); - } - - //draw human clients above scanner plane - for( i = 0; i < entityPositions.numHumanClients; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] > 0 ) ) - CG_DrawBlips( rect, relOrigin, hIabove ); - } - - //draw alien clients above scanner plane - for( i = 0; i < entityPositions.numAlienClients; i++ ) - { - VectorClear( relOrigin ); - VectorSubtract( entityPositions.alienClientPos[ i ], origin, relOrigin ); - - if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] > 0 ) ) - CG_DrawBlips( rect, relOrigin, aIabove ); - } -} diff --git a/mod/src/cgame/cg_servercmds.c b/mod/src/cgame/cg_servercmds.c deleted file mode 100644 index 71fbaac9..00000000 --- a/mod/src/cgame/cg_servercmds.c +++ /dev/null @@ -1,1130 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_servercmds.c -- reliably sequenced text commands sent by the server -// these are processed at snapshot transition time, so there will definately -// be a valid snapshot this frame - -/* - * 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" - -/* -================= -CG_ParseScores - -================= -*/ -static void CG_ParseScores( void ) -{ - int i; - - cg.numScores = atoi( CG_Argv( 1 ) ); - - if( cg.numScores > MAX_CLIENTS ) - cg.numScores = MAX_CLIENTS; - - cg.teamScores[ 0 ] = atoi( CG_Argv( 2 ) ); - cg.teamScores[ 1 ] = atoi( CG_Argv( 3 ) ); - - memset( cg.scores, 0, sizeof( cg.scores ) ); - - if( cg_debugRandom.integer ) - CG_Printf( "cg.numScores: %d\n", cg.numScores ); - - for( i = 0; i < cg.numScores; i++ ) - { - // - cg.scores[ i ].client = atoi( CG_Argv( i * 6 + 4 ) ); - cg.scores[ i ].score = atoi( CG_Argv( i * 6 + 5 ) ); - cg.scores[ i ].ping = atoi( CG_Argv( i * 6 + 6 ) ); - cg.scores[ i ].time = atoi( CG_Argv( i * 6 + 7 ) ); - cg.scores[ i ].weapon = atoi( CG_Argv( i * 6 + 8 ) ); - cg.scores[ i ].upgrade = atoi( CG_Argv( i * 6 + 9 ) ); - - if( cg.scores[ i ].client < 0 || cg.scores[ i ].client >= MAX_CLIENTS ) - cg.scores[ i ].client = 0; - - cgs.clientinfo[ cg.scores[ i ].client ].score = cg.scores[ i ].score; - cgs.clientinfo[ cg.scores[ i ].client ].powerups = 0; - - cg.scores[ i ].team = cgs.clientinfo[ cg.scores[ i ].client ].team; - } -} - -/* -================= -CG_ParseTeamInfo - -================= -*/ -static void CG_ParseTeamInfo( void ) -{ - int i; - int client; - - numSortedTeamPlayers = atoi( CG_Argv( 1 ) ); - - for( i = 0; i < numSortedTeamPlayers; i++ ) - { - client = atoi( CG_Argv( i * 6 + 2 ) ); - - sortedTeamPlayers[ i ] = client; - - cgs.clientinfo[ client ].location = atoi( CG_Argv( i * 6 + 3 ) ); - cgs.clientinfo[ client ].health = atoi( CG_Argv( i * 6 + 4 ) ); - cgs.clientinfo[ client ].armor = atoi( CG_Argv( i * 6 + 5 ) ); - cgs.clientinfo[ client ].curWeapon = atoi( CG_Argv( i * 6 + 6 ) ); - cgs.clientinfo[ client ].powerups = atoi( CG_Argv( i * 6 + 7 ) ); - } -} - - -/* -================ -CG_ParseServerinfo - -This is called explicitly when the gamestate is first received, -and whenever the server updates any serverinfo flagged cvars -================ -*/ -void CG_ParseServerinfo( void ) -{ - const char *info; - char *mapname; - - info = CG_ConfigString( CS_SERVERINFO ); - cgs.dmflags = atoi( Info_ValueForKey( info, "dmflags" ) ); - cgs.teamflags = atoi( Info_ValueForKey( info, "teamflags" ) ); - cgs.timelimit = atoi( Info_ValueForKey( info, "timelimit" ) ); - cgs.maxclients = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); - mapname = Info_ValueForKey( info, "mapname" ); - Com_sprintf( cgs.mapname, sizeof( cgs.mapname ), "maps/%s.bsp", mapname ); -} - -/* -================== -CG_ParseWarmup -================== -*/ -static void CG_ParseWarmup( void ) -{ - const char *info; - int warmup; - - info = CG_ConfigString( CS_WARMUP ); - - warmup = atoi( info ); - cg.warmupCount = -1; - - if( warmup == 0 && cg.warmup ) - { - } - - cg.warmup = warmup; -} - -/* -================ -CG_SetConfigValues - -Called on load to set the initial values from configure strings -================ -*/ -void CG_SetConfigValues( void ) -{ - cgs.scores1 = atoi( CG_ConfigString( CS_SCORES1 ) ); - cgs.scores2 = atoi( CG_ConfigString( CS_SCORES2 ) ); - - sscanf( CG_ConfigString( CS_BUILDPOINTS ), - "%d %d %d %d %d", &cgs.alienBuildPoints, - &cgs.alienBuildPointsTotal, - &cgs.humanBuildPoints, - &cgs.humanBuildPointsTotal, - &cgs.humanBuildPointsPowered ); - - sscanf( CG_ConfigString( CS_STAGES ), "%d %d %d %d %d %d", &cgs.alienStage, &cgs.humanStage, - &cgs.alienKills, &cgs.humanKills, &cgs.alienNextStageThreshold, &cgs.humanNextStageThreshold ); - sscanf( CG_ConfigString( CS_SPAWNS ), "%d %d", &cgs.numAlienSpawns, &cgs.numHumanSpawns ); - - cgs.levelStartTime = atoi( CG_ConfigString( CS_LEVEL_START_TIME ) ); - cg.warmup = atoi( CG_ConfigString( CS_WARMUP ) ); -} - - -/* -===================== -CG_ShaderStateChanged -===================== -*/ -void CG_ShaderStateChanged( void ) -{ - char originalShader[ MAX_QPATH ]; - char newShader[ MAX_QPATH ]; - char timeOffset[ 16 ]; - const char *o; - char *n, *t; - - o = CG_ConfigString( CS_SHADERSTATE ); - - while( o && *o ) - { - n = strstr( o, "=" ); - - if( n && *n ) - { - strncpy( originalShader, o, n - o ); - originalShader[ n - o ] = 0; - n++; - t = strstr( n, ":" ); - - if( t && *t ) - { - strncpy( newShader, n, t - n ); - newShader[ t - n ] = 0; - } - else - break; - - t++; - o = strstr( t, "@" ); - - if( o ) - { - strncpy( timeOffset, t, o - t ); - timeOffset[ o - t ] = 0; - o++; - trap_R_RemapShader( originalShader, newShader, timeOffset ); - } - } - else - break; - } -} - -/* -================ -CG_AnnounceAlienStageTransistion -================ -*/ -static void CG_AnnounceAlienStageTransistion( stage_t from, stage_t to ) -{ - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] != PTE_ALIENS ) - return; - - trap_S_StartLocalSound( cgs.media.alienStageTransition, CHAN_ANNOUNCER ); - CG_CenterPrint( "We have evolved!", 200, GIANTCHAR_WIDTH * 4 ); -} - -/* -================ -CG_AnnounceHumanStageTransistion -================ -*/ -static void CG_AnnounceHumanStageTransistion( stage_t from, stage_t to ) -{ - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] != PTE_HUMANS ) - return; - - trap_S_StartLocalSound( cgs.media.humanStageTransition, CHAN_ANNOUNCER ); - CG_CenterPrint( "Reinforcements have arrived!", 200, GIANTCHAR_WIDTH * 4 ); -} - -/* -================ -CG_ConfigStringModified - -================ -*/ -static void CG_ConfigStringModified( void ) -{ - const char *str; - int num; - - num = atoi( CG_Argv( 1 ) ); - - // get the gamestate from the client system, which will have the - // new configstring already integrated - trap_GetGameState( &cgs.gameState ); - - // look up the individual string that was modified - str = CG_ConfigString( num ); - - // do something with it if necessary - if( num == CS_MUSIC ) - CG_StartMusic( ); - else if( num == CS_SERVERINFO ) - CG_ParseServerinfo( ); - else if( num == CS_WARMUP ) - CG_ParseWarmup( ); - else if( num == CS_SCORES1 ) - cgs.scores1 = atoi( str ); - else if( num == CS_SCORES2 ) - cgs.scores2 = atoi( str ); - else if( num == CS_BUILDPOINTS ) - sscanf( str, "%d %d %d %d %d", &cgs.alienBuildPoints, - &cgs.alienBuildPointsTotal, - &cgs.humanBuildPoints, - &cgs.humanBuildPointsTotal, - &cgs.humanBuildPointsPowered ); - else if( num == CS_STAGES ) - { - stage_t oldAlienStage = cgs.alienStage; - stage_t oldHumanStage = cgs.humanStage; - - sscanf( str, "%d %d %d %d %d %d", - &cgs.alienStage, &cgs.humanStage, - &cgs.alienKills, &cgs.humanKills, - &cgs.alienNextStageThreshold, &cgs.humanNextStageThreshold ); - - if( cgs.alienStage != oldAlienStage ) - CG_AnnounceAlienStageTransistion( oldAlienStage, cgs.alienStage ); - - if( cgs.humanStage != oldHumanStage ) - CG_AnnounceHumanStageTransistion( oldHumanStage, cgs.humanStage ); - } - else if( num == CS_SPAWNS ) - sscanf( str, "%d %d", &cgs.numAlienSpawns, &cgs.numHumanSpawns ); - else if( num == CS_LEVEL_START_TIME ) - cgs.levelStartTime = atoi( str ); - else if( num == CS_VOTE_TIME ) - { - cgs.voteTime = atoi( str ); - cgs.voteModified = qtrue; - - if( cgs.voteTime ) - trap_Cvar_Set( "ui_voteActive", "1" ); - else - trap_Cvar_Set( "ui_voteActive", "0" ); - } - else if( num == CS_VOTE_YES ) - { - cgs.voteYes = atoi( str ); - cgs.voteModified = qtrue; - } - else if( num == CS_VOTE_NO ) - { - cgs.voteNo = atoi( str ); - cgs.voteModified = qtrue; - } - else if( num == CS_VOTE_STRING ) - Q_strncpyz( cgs.voteString, str, sizeof( cgs.voteString ) ); - else if( num >= CS_TEAMVOTE_TIME && num <= CS_TEAMVOTE_TIME + 1 ) - { - int cs_offset = num - CS_TEAMVOTE_TIME; - - cgs.teamVoteTime[ cs_offset ] = atoi( str ); - cgs.teamVoteModified[ cs_offset ] = qtrue; - - if( cs_offset == 0 ) - { - if( cgs.teamVoteTime[ cs_offset ] ) - trap_Cvar_Set( "ui_humanTeamVoteActive", "1" ); - else - trap_Cvar_Set( "ui_humanTeamVoteActive", "0" ); - } - else if( cs_offset == 1 ) - { - if( cgs.teamVoteTime[ cs_offset ] ) - trap_Cvar_Set( "ui_alienTeamVoteActive", "1" ); - else - trap_Cvar_Set( "ui_alienTeamVoteActive", "0" ); - } - } - else if( num >= CS_TEAMVOTE_YES && num <= CS_TEAMVOTE_YES + 1 ) - { - cgs.teamVoteYes[ num - CS_TEAMVOTE_YES ] = atoi( str ); - cgs.teamVoteModified[ num - CS_TEAMVOTE_YES ] = qtrue; - } - else if( num >= CS_TEAMVOTE_NO && num <= CS_TEAMVOTE_NO + 1 ) - { - cgs.teamVoteNo[ num - CS_TEAMVOTE_NO ] = atoi( str ); - cgs.teamVoteModified[ num - CS_TEAMVOTE_NO ] = qtrue; - } - else if( num >= CS_TEAMVOTE_STRING && num <= CS_TEAMVOTE_STRING + 1 ) - Q_strncpyz( cgs.teamVoteString[ num - CS_TEAMVOTE_STRING ], str, sizeof( cgs.teamVoteString ) ); - else if( num == CS_INTERMISSION ) - cg.intermissionStarted = atoi( str ); - else if( num >= CS_MODELS && num < CS_MODELS+MAX_MODELS ) - cgs.gameModels[ num - CS_MODELS ] = trap_R_RegisterModel( str ); - else if( num >= CS_SHADERS && num < CS_SHADERS+MAX_SHADERS ) - cgs.gameShaders[ num - CS_SHADERS ] = trap_R_RegisterShader( str ); - else if( num >= CS_PARTICLE_SYSTEMS && num < CS_PARTICLE_SYSTEMS+MAX_GAME_PARTICLE_SYSTEMS ) - cgs.gameParticleSystems[ num - CS_PARTICLE_SYSTEMS ] = CG_RegisterParticleSystem( (char *)str ); - else if( num >= CS_SOUNDS && num < CS_SOUNDS+MAX_SOUNDS ) - { - if( str[ 0 ] != '*' ) - { // player specific sounds don't register here - cgs.gameSounds[ num - CS_SOUNDS ] = trap_S_RegisterSound( str, qfalse ); - } - } - else if( num >= CS_PLAYERS && num < CS_PLAYERS+MAX_CLIENTS ) - { - CG_NewClientInfo( num - CS_PLAYERS ); - CG_BuildSpectatorString( ); - } - else if( num == CS_FLAGSTATUS ) - { - } - else if( num == CS_SHADERSTATE ) - { - CG_ShaderStateChanged( ); - } -} - - -/* -======================= -CG_AddToTeamChat - -======================= -*/ -static void CG_AddToTeamChat( const char *str ) -{ - int len; - char *p, *ls; - int lastcolor; - int chatHeight; - - if( cg_teamChatHeight.integer < TEAMCHAT_HEIGHT ) - chatHeight = cg_teamChatHeight.integer; - else - chatHeight = TEAMCHAT_HEIGHT; - - if( chatHeight <= 0 || cg_teamChatTime.integer <= 0 ) - { - // team chat disabled, dump into normal chat - cgs.teamChatPos = cgs.teamLastChatPos = 0; - return; - } - - len = 0; - - p = cgs.teamChatMsgs[cgs.teamChatPos % chatHeight]; - *p = 0; - - lastcolor = '7'; - - ls = NULL; - while( *str ) - { - if( len > TEAMCHAT_WIDTH - 1 ) - { - if( ls ) - { - str -= ( p - ls ); - str++; - p -= ( p - ls ); - } - - *p = 0; - - cgs.teamChatMsgTimes[ cgs.teamChatPos % chatHeight ] = cg.time; - - cgs.teamChatPos++; - p = cgs.teamChatMsgs[ cgs.teamChatPos % chatHeight ]; - *p = 0; - *p++ = Q_COLOR_ESCAPE; - *p++ = lastcolor; - len = 0; - ls = NULL; - } - - if( Q_IsColorString( str ) ) - { - *p++ = *str++; - lastcolor = *str; - *p++ = *str++; - continue; - } - - if( *str == ' ' ) - ls = p; - - *p++ = *str++; - len++; - } - *p = 0; - - cgs.teamChatMsgTimes[ cgs.teamChatPos % chatHeight ] = cg.time; - cgs.teamChatPos++; - - if( cgs.teamChatPos - cgs.teamLastChatPos > chatHeight ) - cgs.teamLastChatPos = cgs.teamChatPos - chatHeight; -} - - - -/* -=============== -CG_MapRestart - -The server has issued a map_restart, so the next snapshot -is completely new and should not be interpolated to. - -A tournement restart will clear everything, but doesn't -require a reload of all the media -=============== -*/ -static void CG_MapRestart( void ) -{ - if( cg_showmiss.integer ) - CG_Printf( "CG_MapRestart\n" ); - - CG_InitMarkPolys( ); - - // make sure the "3 frags left" warnings play again - cg.fraglimitWarnings = 0; - - cg.timelimitWarnings = 0; - - cg.intermissionStarted = qfalse; - - cgs.voteTime = 0; - - cg.mapRestart = qtrue; - - CG_StartMusic( ); - - trap_S_ClearLoopingSounds( qtrue ); - - // we really should clear more parts of cg here and stop sounds - - // play the "fight" sound if this is a restart without warmup - if( cg.warmup == 0 ) - CG_CenterPrint( "FIGHT!", 120, GIANTCHAR_WIDTH * 2 ); - - trap_Cvar_Set( "cg_thirdPerson", "0" ); -} - -/* -================= -CG_RemoveChatEscapeChar -================= -*/ -static void CG_RemoveChatEscapeChar( char *text ) -{ - int i, l; - - l = 0; - for( i = 0; text[ i ]; i++ ) - { - if( text[ i ] == '\x19' ) - continue; - - text[ l++ ] = text[ i ]; - } - - text[ l ] = '\0'; -} - -/* -=============== -CG_SetUIVars - -Set some cvars used by the UI -=============== -*/ -static void CG_SetUIVars( void ) -{ - int i; - char carriageCvar[ MAX_TOKEN_CHARS ]; - - *carriageCvar = 0; - - //determine what the player is carrying - for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) - { - if( BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) && - BG_FindPurchasableForWeapon( i ) ) - strcat( carriageCvar, va( "W%d ", i ) ); - } - for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) - { - if( BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) && - BG_FindPurchasableForUpgrade( i ) ) - strcat( carriageCvar, va( "U%d ", i ) ); - } - strcat( carriageCvar, "$" ); - - trap_Cvar_Set( "ui_carriage", carriageCvar ); - - trap_Cvar_Set( "ui_stages", va( "%d %d", cgs.alienStage, cgs.humanStage ) ); -} - - -/* -============== -CG_Menu -============== -*/ -void CG_Menu( int menu ) -{ - CG_SetUIVars( ); - - switch( menu ) - { - case MN_TEAM: trap_SendConsoleCommand( "menu tremulous_teamselect\n" ); break; - case MN_A_CLASS: trap_SendConsoleCommand( "menu tremulous_alienclass\n" ); break; - case MN_H_SPAWN: trap_SendConsoleCommand( "menu tremulous_humanitem\n" ); break; - case MN_A_BUILD: trap_SendConsoleCommand( "menu tremulous_alienbuild\n" ); break; - case MN_H_BUILD: trap_SendConsoleCommand( "menu tremulous_humanbuild\n" ); break; - case MN_H_ARMOURY: trap_SendConsoleCommand( "menu tremulous_humanarmoury\n" ); break; - - case MN_A_TEAMFULL: - trap_Cvar_Set( "ui_dialog", "The alien team has too many players. Please wait until " - "slots become available or join the human team." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - break; - - case MN_H_TEAMFULL: - trap_Cvar_Set( "ui_dialog", "The human team has too many players. Please wait until " - "slots become available or join the alien team." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - break; - - case MN_H_NOROOM: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the buildable turns " - "translucent green indicating a valid build location." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "There is no room to build here\n" ); - - break; - - case MN_H_NOPOWER: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no power remaining. Free up power by destroying existing " - "buildable objects." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "There is no power remaining\n" ); - - break; - - case MN_H_NOTPOWERED: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "This buildable is not powered. Build a Reactor and/or Repeater in " - "order to power it." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "This buildable is not powered\n" ); - - break; - - case MN_H_NORMAL: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. The surface is too steep or unsuitable " - "to build on. Please choose another site for this structure." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "Cannot build on this surface\n" ); - - break; - - case MN_H_REACTOR: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There can only be one Reactor. Destroy the existing one if you " - "wish to move it." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "There can only be one Reactor\n" ); - - break; - - case MN_H_REPEATER: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no power here. If available, a Repeater may be used to " - "transmit power to this location." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "There is no power here\n" ); - - break; - - case MN_H_NODCC: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no Defense Computer. A Defense Computer is needed to build " - "this." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "There is no Defense Computer\n" ); - - break; - - case MN_H_TNODEWARN: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "WARNING: This Telenode will not be powered. Build near a power " - "structure to prevent seeing this message again." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "This Telenode will not be powered\n" ); - - break; - - case MN_H_RPTWARN: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "WARNING: This Repeater will not be powered as there is no parent " - "Reactor providing power. Build a Reactor." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "This Repeater will not be powered\n" ); - - break; - - case MN_H_RPTWARN2: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "This area already has power. A Repeater is not required here." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "This area already has power\n" ); - - break; - - case MN_H_NOSLOTS: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "You have no room to carry this. Please sell any conflicting " - "upgrades before purchasing this item." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "You have no room to carry this\n" ); - - break; - - case MN_H_NOFUNDS: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "Insufficient funds. You do not have enough credits to perform this " - "action." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "Insufficient funds\n" ); - - break; - - case MN_H_ITEMHELD: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "You already hold this item. It is not possible to carry multiple items " - "of the same type." ); - trap_SendConsoleCommand( "menu tremulous_human_dialog\n" ); - } - else - CG_Printf( "You already hold this item\n" ); - - break; - - - //=============================== - - - case MN_A_NOROOM: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the structure turns " - "translucent green indicating a valid build location." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There is no room to build here\n" ); - - break; - - case MN_A_NOCREEP: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no creep here. You must build near existing Eggs or " - "the Overmind. Alien structures will not support themselves." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There is no creep here\n" ); - - break; - - case MN_A_NOOVMND: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no Overmind. An Overmind must be built to control " - "the structure you tried to place" ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There is no Overmind\n" ); - - break; - - case MN_A_OVERMIND: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There can only be one Overmind. Destroy the existing one if you " - "wish to move it." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There can only be one Overmind\n" ); - - break; - - case MN_A_HOVEL: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There can only be one Hovel. Destroy the existing one if you " - "wish to move it." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There can only be one Hovel\n" ); - - break; - - case MN_A_NOASSERT: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "The Overmind cannot control any more structures. Destroy existing " - "structures to build more." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "The Overmind cannot control any more structures\n" ); - - break; - - case MN_A_SPWNWARN: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "WARNING: This spawn will not be controlled by an Overmind. " - "Build an Overmind to prevent seeing this message again." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "This spawn will not be controlled by an Overmind\n" ); - - break; - - case MN_A_NORMAL: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. This surface is too steep or unsuitable " - "to build on. Please choose another site for this structure." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "Cannot build on this surface\n" ); - - break; - - case MN_A_NOEROOM: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no room to evolve here. Move away from walls or other " - "nearby objects and try again." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There is no room to evolve here\n" ); - - break; - - case MN_A_TOOCLOSE: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "This location is too close to the enemy to evolve. " - "Move away until you are no longer aware of the enemy's " - "presence and try again." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "This location is too close to the enemy to evolve\n" ); - - break; - - case MN_A_NOOVMND_EVOLVE: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "There is no Overmind. An Overmind must be built to allow " - "you to upgrade." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "There is no Overmind\n" ); - - break; - - case MN_A_HOVEL_OCCUPIED: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "This Hovel is occupied by another builder. Please find or build " - "another." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "This Hovel is occupied by another builder\n" ); - - break; - - case MN_A_HOVEL_BLOCKED: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "The exit to this Hovel is currently blocked. Please wait until it " - "becomes clear then try again." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "The exit to this Hovel is currently blocked\n" ); - - break; - - case MN_A_HOVEL_EXIT: - if( !cg_disableWarningDialogs.integer ) - { - trap_Cvar_Set( "ui_dialog", "The exit to this Hovel would always be blocked. Please choose " - "a more suitable location." ); - trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" ); - } - else - CG_Printf( "The exit to this Hovel would always be blocked\n" ); - - break; - - case MN_A_INFEST: - trap_Cvar_Set( "ui_currentClass", va( "%d %d", cg.snap->ps.stats[ STAT_PCLASS ], - cg.snap->ps.persistant[ PERS_CREDIT ] ) ); - trap_SendConsoleCommand( "menu tremulous_alienupgrade\n" ); - break; - - default: - Com_Printf( "cgame: debug: no such menu %d\n", menu ); - } -} - -/* -================= -CG_ServerCommand - -The string has been tokenized and can be retrieved with -Cmd_Argc() / Cmd_Argv() -================= -*/ -static void CG_ServerCommand( void ) -{ - const char *cmd; - char text[ MAX_SAY_TEXT ]; - - cmd = CG_Argv( 0 ); - - if( !cmd[ 0 ] ) - { - // server claimed the command - return; - } - - if( !strcmp( cmd, "cp" ) ) - { - CG_CenterPrint( CG_Argv( 1 ), SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH ); - return; - } - - if( !strcmp( cmd, "cs" ) ) - { - CG_ConfigStringModified( ); - return; - } - - if( !strcmp( cmd, "print" ) ) - { - CG_Printf( "%s", CG_Argv( 1 ) ); - return; - } - - if( !strcmp( cmd, "chat" ) ) - { - if( !cg_teamChatsOnly.integer ) - { - trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); - Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); - CG_RemoveChatEscapeChar( text ); - CG_Printf( "%s\n", text ); - } - - return; - } - - if( !strcmp( cmd, "tchat" ) ) - { - trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND ); - Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT ); - CG_RemoveChatEscapeChar( text ); - CG_AddToTeamChat( text ); - CG_Printf( "%s\n", text ); - return; - } - - if( !strcmp( cmd, "scores" ) ) - { - CG_ParseScores( ); - return; - } - - if( !strcmp( cmd, "tinfo" ) ) - { - CG_ParseTeamInfo( ); - return; - } - - if( !strcmp( cmd, "map_restart" ) ) - { - CG_MapRestart( ); - return; - } - - if( Q_stricmp( cmd, "remapShader" ) == 0 ) - { - if( trap_Argc( ) == 4 ) - trap_R_RemapShader( CG_Argv( 1 ), CG_Argv( 2 ), CG_Argv( 3 ) ); - } - - // clientLevelShot is sent before taking a special screenshot for - // the menu system during development - if( !strcmp( cmd, "clientLevelShot" ) ) - { - cg.levelShot = qtrue; - return; - } - - //enable G_Printfs from the server to appear in the TA console - if( !strcmp( cmd, "gprintf" ) ) - { - if( trap_Argc( ) == 2 ) - CG_TAUIConsole( CG_Argv( 1 ) ); - - return; - } - - //the server has triggered a menu - if( !strcmp( cmd, "servermenu" ) ) - { - if( trap_Argc( ) == 2 && !cg.demoPlayback ) - CG_Menu( atoi( CG_Argv( 1 ) ) ); - - return; - } - - //the server thinks this client should close all menus - if( !strcmp( cmd, "serverclosemenus" ) ) - { - trap_SendConsoleCommand( "closemenus\n" ); - return; - } - - //poison cloud effect needs to be reliable - if( !strcmp( cmd, "poisoncloud" ) ) - { - cg.poisonedTime = cg.time; - - if( CG_IsParticleSystemValid( &cg.poisonCloudPS ) ) - { - cg.poisonCloudPS = CG_SpawnNewParticleSystem( cgs.media.poisonCloudPS ); - CG_SetAttachmentCent( &cg.poisonCloudPS->attachment, &cg.predictedPlayerEntity ); - CG_AttachToCent( &cg.poisonCloudPS->attachment ); - } - - return; - } - - if( !strcmp( cmd, "weaponswitch" ) ) - { - CG_Printf( "client weaponswitch\n" ); - if( trap_Argc( ) == 2 ) - { - cg.weaponSelect = atoi( CG_Argv( 1 ) ); - cg.weaponSelectTime = cg.time; - } - - return; - } - - // server requests a ptrc - if( !strcmp( cmd, "ptrcrequest" ) ) - { - int code = CG_ReadPTRCode( ); - - trap_SendClientCommand( va( "ptrcverify %d", code ) ); - return; - } - - // server issues a ptrc - if( !strcmp( cmd, "ptrcissue" ) ) - { - if( trap_Argc( ) == 2 ) - { - int code = atoi( CG_Argv( 1 ) ); - - CG_WritePTRCode( code ); - } - - return; - } - - // reply to ptrcverify - if( !strcmp( cmd, "ptrcconfirm" ) ) - { - trap_SendConsoleCommand( "menu ptrc_popmenu\n" ); - - return; - } - - CG_Printf( "Unknown client game command: %s\n", cmd ); -} - - -/* -==================== -CG_ExecuteNewServerCommands - -Execute all of the server commands that were received along -with this this snapshot. -==================== -*/ -void CG_ExecuteNewServerCommands( int latestSequence ) -{ - while( cgs.serverCommandSequence < latestSequence ) - { - if( trap_GetServerCommand( ++cgs.serverCommandSequence ) ) - CG_ServerCommand( ); - } -} diff --git a/mod/src/cgame/cg_snapshot.c b/mod/src/cgame/cg_snapshot.c deleted file mode 100644 index 4a5722ae..00000000 --- a/mod/src/cgame/cg_snapshot.c +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_snapshot.c -- things that happen on snapshot transition, -// not necessarily every single rendered frame - -/* - * 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" - -/* -================== -CG_ResetEntity -================== -*/ -static void CG_ResetEntity( centity_t *cent ) -{ - // if the previous snapshot this entity was updated in is at least - // an event window back in time then we can reset the previous event - if( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) - cent->previousEvent = 0; - - cent->trailTime = cg.snap->serverTime; - - VectorCopy( cent->currentState.origin, cent->lerpOrigin ); - VectorCopy( cent->currentState.angles, cent->lerpAngles ); - - if( cent->currentState.eType == ET_PLAYER ) - CG_ResetPlayerEntity( cent ); -} - -/* -=============== -CG_TransitionEntity - -cent->nextState is moved to cent->currentState and events are fired -=============== -*/ -static void CG_TransitionEntity( centity_t *cent ) -{ - cent->currentState = cent->nextState; - cent->currentValid = qtrue; - - // reset if the entity wasn't in the last frame or was teleported - if( !cent->interpolate ) - CG_ResetEntity( cent ); - - // clear the next state. if will be set by the next CG_SetNextSnap - cent->interpolate = qfalse; - - // check for events - CG_CheckEvents( cent ); -} - - -/* -================== -CG_SetInitialSnapshot - -This will only happen on the very first snapshot, or -on tourney restarts. All other times will use -CG_TransitionSnapshot instead. - -FIXME: Also called by map_restart? -================== -*/ -void CG_SetInitialSnapshot( snapshot_t *snap ) -{ - int i; - centity_t *cent; - entityState_t *state; - - cg.snap = snap; - - BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse ); - - // sort out solid entities - CG_BuildSolidList( ); - - CG_ExecuteNewServerCommands( snap->serverCommandSequence ); - - // set our local weapon selection pointer to - // what the server has indicated the current weapon is - CG_Respawn( ); - - for( i = 0; i < cg.snap->numEntities; i++ ) - { - state = &cg.snap->entities[ i ]; - cent = &cg_entities[ state->number ]; - - memcpy( ¢->currentState, state, sizeof( entityState_t ) ); - //cent->currentState = *state; - cent->interpolate = qfalse; - cent->currentValid = qtrue; - - CG_ResetEntity( cent ); - - // check for events - CG_CheckEvents( cent ); - } -} - - -/* -=================== -CG_TransitionSnapshot - -The transition point from snap to nextSnap has passed -=================== -*/ -static void CG_TransitionSnapshot( void ) -{ - centity_t *cent; - snapshot_t *oldFrame; - int i; - - if( !cg.snap ) - CG_Error( "CG_TransitionSnapshot: NULL cg.snap" ); - - if( !cg.nextSnap ) - CG_Error( "CG_TransitionSnapshot: NULL cg.nextSnap" ); - - // execute any server string commands before transitioning entities - CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence ); - - // if we had a map_restart, set everthing with initial - if( !cg.snap ) { } //TA: ? - - // clear the currentValid flag for all entities in the existing snapshot - for( i = 0; i < cg.snap->numEntities; i++ ) - { - cent = &cg_entities[ cg.snap->entities[ i ].number ]; - cent->currentValid = qfalse; - } - - // move nextSnap to snap and do the transitions - oldFrame = cg.snap; - cg.snap = cg.nextSnap; - - BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[ cg.snap->ps.clientNum ].currentState, qfalse ); - cg_entities[ cg.snap->ps.clientNum ].interpolate = qfalse; - - for( i = 0; i < cg.snap->numEntities; i++ ) - { - cent = &cg_entities[ cg.snap->entities[ i ].number ]; - CG_TransitionEntity( cent ); - - // remember time of snapshot this entity was last updated in - cent->snapShotTime = cg.snap->serverTime; - } - - cg.nextSnap = NULL; - - // check for playerstate transition events - if( oldFrame ) - { - playerState_t *ops, *ps; - - ops = &oldFrame->ps; - ps = &cg.snap->ps; - // teleporting checks are irrespective of prediction - if( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) - cg.thisFrameTeleport = qtrue; // will be cleared by prediction code - - // if we are not doing client side movement prediction for any - // reason, then the client events and view changes will be issued now - if( cg.demoPlayback || ( cg.snap->ps.pm_flags & PMF_FOLLOW ) || - cg_nopredict.integer || cg_synchronousClients.integer ) - CG_TransitionPlayerState( ps, ops ); - } -} - - -/* -=================== -CG_SetNextSnap - -A new snapshot has just been read in from the client system. -=================== -*/ -static void CG_SetNextSnap( snapshot_t *snap ) -{ - int num; - entityState_t *es; - centity_t *cent; - - cg.nextSnap = snap; - - BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse ); - cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue; - - // check for extrapolation errors - for( num = 0 ; num < snap->numEntities ; num++ ) - { - es = &snap->entities[ num ]; - cent = &cg_entities[ es->number ]; - - memcpy( ¢->nextState, es, sizeof( entityState_t ) ); - //cent->nextState = *es; - - // if this frame is a teleport, or the entity wasn't in the - // previous frame, don't interpolate - if( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) ) - cent->interpolate = qfalse; - else - cent->interpolate = qtrue; - } - - // if the next frame is a teleport for the playerstate, we - // can't interpolate during demos - if( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) - cg.nextFrameTeleport = qtrue; - else - cg.nextFrameTeleport = qfalse; - - // if changing follow mode, don't interpolate - if( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) - cg.nextFrameTeleport = qtrue; - - // if changing server restarts, don't interpolate - if( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) - cg.nextFrameTeleport = qtrue; - - // sort out solid entities - CG_BuildSolidList( ); -} - - -/* -======================== -CG_ReadNextSnapshot - -This is the only place new snapshots are requested -This may increment cgs.processedSnapshotNum multiple -times if the client system fails to return a -valid snapshot. -======================== -*/ -static snapshot_t *CG_ReadNextSnapshot( void ) -{ - qboolean r; - snapshot_t *dest; - - if( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) - { - CG_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i", - cg.latestSnapshotNum, cgs.processedSnapshotNum ); - } - - while( cgs.processedSnapshotNum < cg.latestSnapshotNum ) - { - // decide which of the two slots to load it into - if( cg.snap == &cg.activeSnapshots[ 0 ] ) - dest = &cg.activeSnapshots[ 1 ]; - else - dest = &cg.activeSnapshots[ 0 ]; - - // try to read the snapshot from the client system - cgs.processedSnapshotNum++; - r = trap_GetSnapshot( cgs.processedSnapshotNum, dest ); - - // FIXME: why would trap_GetSnapshot return a snapshot with the same server time - if( cg.snap && r && dest->serverTime == cg.snap->serverTime ) - { - //continue; - } - - // if it succeeded, return - if( r ) - { - CG_AddLagometerSnapshotInfo( dest ); - return dest; - } - - // a GetSnapshot will return failure if the snapshot - // never arrived, or is so old that its entities - // have been shoved off the end of the circular - // buffer in the client system. - - // record as a dropped packet - CG_AddLagometerSnapshotInfo( NULL ); - - // If there are additional snapshots, continue trying to - // read them. - } - - // nothing left to read - return NULL; -} - - -/* -============ -CG_ProcessSnapshots - -We are trying to set up a renderable view, so determine -what the simulated time is, and try to get snapshots -both before and after that time if available. - -If we don't have a valid cg.snap after exiting this function, -then a 3D game view cannot be rendered. This should only happen -right after the initial connection. After cg.snap has been valid -once, it will never turn invalid. - -Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot -hasn't arrived yet (it becomes an extrapolating situation instead -of an interpolating one) - -============ -*/ -void CG_ProcessSnapshots( void ) -{ - snapshot_t *snap; - int n; - - // see what the latest snapshot the client system has is - trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime ); - - if( n != cg.latestSnapshotNum ) - { - if( n < cg.latestSnapshotNum ) - { - // this should never happen - CG_Error( "CG_ProcessSnapshots: n < cg.latestSnapshotNum" ); - } - - cg.latestSnapshotNum = n; - } - - // If we have yet to receive a snapshot, check for it. - // Once we have gotten the first snapshot, cg.snap will - // always have valid data for the rest of the game - while( !cg.snap ) - { - snap = CG_ReadNextSnapshot( ); - - if( !snap ) - { - // we can't continue until we get a snapshot - return; - } - - // set our weapon selection to what - // the playerstate is currently using - if( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) - CG_SetInitialSnapshot( snap ); - } - - // loop until we either have a valid nextSnap with a serverTime - // greater than cg.time to interpolate towards, or we run - // out of available snapshots - do - { - // if we don't have a nextframe, try and read a new one in - if( !cg.nextSnap ) - { - snap = CG_ReadNextSnapshot( ); - - // if we still don't have a nextframe, we will just have to - // extrapolate - if( !snap ) - break; - - CG_SetNextSnap( snap ); - - // if time went backwards, we have a level restart - if( cg.nextSnap->serverTime < cg.snap->serverTime ) - CG_Error( "CG_ProcessSnapshots: Server time went backwards" ); - } - - // if our time is < nextFrame's, we have a nice interpolating state - if( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) - break; - - // we have passed the transition from nextFrame to frame - CG_TransitionSnapshot( ); - } while( 1 ); - - // assert our valid conditions upon exiting - if( cg.snap == NULL ) - CG_Error( "CG_ProcessSnapshots: cg.snap == NULL" ); - - if( cg.time < cg.snap->serverTime ) - { - // this can happen right after a vid_restart - cg.time = cg.snap->serverTime; - } - - if( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) - CG_Error( "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" ); -} - diff --git a/mod/src/cgame/cg_syscalls.asm b/mod/src/cgame/cg_syscalls.asm deleted file mode 100644 index 9da1dade..00000000 --- a/mod/src/cgame/cg_syscalls.asm +++ /dev/null @@ -1,105 +0,0 @@ -code - -equ trap_Print -1 -equ trap_Error -2 -equ trap_Milliseconds -3 -equ trap_Cvar_Register -4 -equ trap_Cvar_Update -5 -equ trap_Cvar_Set -6 -equ trap_Cvar_VariableStringBuffer -7 -equ trap_Argc -8 -equ trap_Argv -9 -equ trap_Args -10 -equ trap_FS_FOpenFile -11 -equ trap_FS_Read -12 -equ trap_FS_Write -13 -equ trap_FS_FCloseFile -14 -equ trap_SendConsoleCommand -15 -equ trap_AddCommand -16 -equ trap_SendClientCommand -17 -equ trap_UpdateScreen -18 -equ trap_CM_LoadMap -19 -equ trap_CM_NumInlineModels -20 -equ trap_CM_InlineModel -21 -equ trap_CM_LoadModel -22 -equ trap_CM_TempBoxModel -23 -equ trap_CM_PointContents -24 -equ trap_CM_TransformedPointContents -25 -equ trap_CM_BoxTrace -26 -equ trap_CM_TransformedBoxTrace -27 -equ trap_CM_MarkFragments -28 -equ trap_S_StartSound -29 -equ trap_S_StartLocalSound -30 -equ trap_S_ClearLoopingSounds -31 -equ trap_S_AddLoopingSound -32 -equ trap_S_UpdateEntityPosition -33 -equ trap_S_Respatialize -34 -equ trap_S_RegisterSound -35 -equ trap_S_StartBackgroundTrack -36 -equ trap_R_LoadWorldMap -37 -equ trap_R_RegisterModel -38 -equ trap_R_RegisterSkin -39 -equ trap_R_RegisterShader -40 -equ trap_R_ClearScene -41 -equ trap_R_AddRefEntityToScene -42 -equ trap_R_AddPolyToScene -43 -equ trap_R_AddLightToScene -44 -equ trap_R_RenderScene -45 -equ trap_R_SetColor -46 -equ trap_R_DrawStretchPic -47 -equ trap_R_ModelBounds -48 -equ trap_R_LerpTag -49 -equ trap_GetGlconfig -50 -equ trap_GetGameState -51 -equ trap_GetCurrentSnapshotNumber -52 -equ trap_GetSnapshot -53 -equ trap_GetServerCommand -54 -equ trap_GetCurrentCmdNumber -55 -equ trap_GetUserCmd -56 -equ trap_SetUserCmdValue -57 -equ trap_R_RegisterShaderNoMip -58 -equ trap_MemoryRemaining -59 -equ trap_R_RegisterFont -60 -equ trap_Key_IsDown -61 -equ trap_Key_GetCatcher -62 -equ trap_Key_SetCatcher -63 -equ trap_Key_GetKey -64 -equ trap_PC_AddGlobalDefine -65 -equ trap_PC_LoadSource -66 -equ trap_PC_FreeSource -67 -equ trap_PC_ReadToken -68 -equ trap_PC_SourceFileAndLine -69 -equ trap_S_StopBackgroundTrack -70 -equ trap_RealTime -71 -equ trap_SnapVector -72 -equ trap_RemoveCommand -73 -equ trap_R_LightForPoint -74 -equ trap_CIN_PlayCinematic -75 -equ trap_CIN_StopCinematic -76 -equ trap_CIN_RunCinematic -77 -equ trap_CIN_DrawCinematic -78 -equ trap_CIN_SetExtents -79 -equ trap_R_RemapShader -80 -equ trap_S_AddRealLoopingSound -81 -equ trap_S_StopLoopingSound -82 -equ trap_CM_TempCapsuleModel -83 -equ trap_CM_CapsuleTrace -84 -equ trap_CM_TransformedCapsuleTrace -85 -equ trap_R_AddAdditiveLightToScene -86 -equ trap_GetEntityToken -87 -equ trap_R_AddPolysToScene -88 -equ trap_R_inPVS -89 -equ trap_FS_Seek -90 - -equ memset -101 -equ memcpy -102 -equ strncpy -103 -equ sin -104 -equ cos -105 -equ atan2 -106 -equ sqrt -107 -equ floor -108 -equ ceil -109 -equ testPrintInt -110 -equ testPrintFloat -111 - diff --git a/mod/src/cgame/cg_syscalls.c b/mod/src/cgame/cg_syscalls.c deleted file mode 100644 index 3e8c5849..00000000 --- a/mod/src/cgame/cg_syscalls.c +++ /dev/null @@ -1,507 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_syscalls.c -- this file is only included when building a dll -// cg_syscalls.asm is included instead when building a qvm - -/* - * 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 long (QDECL *syscall)( long arg, ... ) = (long (QDECL *)( long, ...))-1; - - -void dllEntry( long (QDECL *syscallptr)( long arg,... ) ) -{ - syscall = syscallptr; -} - - -int PASSFLOAT( float x ) -{ - float floatTemp; - floatTemp = x; - return *(int *)&floatTemp; -} - -void trap_Print( const char *fmt ) -{ - syscall( CG_PRINT, fmt ); -} - -void trap_Error( const char *fmt ) -{ - syscall( CG_ERROR, fmt ); -} - -int trap_Milliseconds( void ) -{ - return syscall( CG_MILLISECONDS ); -} - -void trap_Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) -{ - syscall( CG_CVAR_REGISTER, vmCvar, varName, defaultValue, flags ); -} - -void trap_Cvar_Update( vmCvar_t *vmCvar ) -{ - syscall( CG_CVAR_UPDATE, vmCvar ); -} - -void trap_Cvar_Set( const char *var_name, const char *value ) -{ - syscall( CG_CVAR_SET, var_name, value ); -} - -void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) -{ - syscall( CG_CVAR_VARIABLESTRINGBUFFER, var_name, buffer, bufsize ); -} - -int trap_Argc( void ) -{ - return syscall( CG_ARGC ); -} - -void trap_Argv( int n, char *buffer, int bufferLength ) -{ - syscall( CG_ARGV, n, buffer, bufferLength ); -} - -void trap_Args( char *buffer, int bufferLength ) -{ - syscall( CG_ARGS, buffer, bufferLength ); -} - -int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ) -{ - return syscall( CG_FS_FOPENFILE, qpath, f, mode ); -} - -void trap_FS_Read( void *buffer, int len, fileHandle_t f ) -{ - syscall( CG_FS_READ, buffer, len, f ); -} - -void trap_FS_Write( const void *buffer, int len, fileHandle_t f ) -{ - syscall( CG_FS_WRITE, buffer, len, f ); -} - -void trap_FS_FCloseFile( fileHandle_t f ) -{ - syscall( CG_FS_FCLOSEFILE, f ); -} - -void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ) -{ - syscall( CG_FS_SEEK, f, offset, origin ); -} - -void trap_SendConsoleCommand( const char *text ) -{ - syscall( CG_SENDCONSOLECOMMAND, text ); -} - -void trap_AddCommand( const char *cmdName ) -{ - syscall( CG_ADDCOMMAND, cmdName ); -} - -void trap_RemoveCommand( const char *cmdName ) -{ - syscall( CG_REMOVECOMMAND, cmdName ); -} - -void trap_SendClientCommand( const char *s ) -{ - syscall( CG_SENDCLIENTCOMMAND, s ); -} - -void trap_UpdateScreen( void ) -{ - syscall( CG_UPDATESCREEN ); -} - -void trap_CM_LoadMap( const char *mapname ) -{ - syscall( CG_CM_LOADMAP, mapname ); -} - -int trap_CM_NumInlineModels( void ) -{ - return syscall( CG_CM_NUMINLINEMODELS ); -} - -clipHandle_t trap_CM_InlineModel( int index ) -{ - return syscall( CG_CM_INLINEMODEL, index ); -} - -clipHandle_t trap_CM_TempBoxModel( const vec3_t mins, const vec3_t maxs ) -{ - return syscall( CG_CM_TEMPBOXMODEL, mins, maxs ); -} - -clipHandle_t trap_CM_TempCapsuleModel( const vec3_t mins, const vec3_t maxs ) -{ - return syscall( CG_CM_TEMPCAPSULEMODEL, mins, maxs ); -} - -int trap_CM_PointContents( const vec3_t p, clipHandle_t model ) -{ - return syscall( CG_CM_POINTCONTENTS, p, model ); -} - -int trap_CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, - const vec3_t angles ) -{ - return syscall( CG_CM_TRANSFORMEDPOINTCONTENTS, p, model, origin, angles ); -} - -void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask ) -{ - syscall( CG_CM_BOXTRACE, results, start, end, mins, maxs, model, brushmask ); -} - -void trap_CM_CapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask ) -{ - syscall( CG_CM_CAPSULETRACE, results, start, end, mins, maxs, model, brushmask ); -} - -void trap_CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask, - const vec3_t origin, const vec3_t angles ) -{ - syscall( CG_CM_TRANSFORMEDBOXTRACE, results, start, end, mins, maxs, model, brushmask, origin, angles ); -} - -void trap_CM_TransformedCapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end, - const vec3_t mins, const vec3_t maxs, - clipHandle_t model, int brushmask, - const vec3_t origin, const vec3_t angles ) -{ - syscall( CG_CM_TRANSFORMEDCAPSULETRACE, results, start, end, mins, maxs, model, brushmask, origin, angles ); -} - -int trap_CM_MarkFragments( int numPoints, const vec3_t *points, - const vec3_t projection, - int maxPoints, vec3_t pointBuffer, - int maxFragments, markFragment_t *fragmentBuffer ) -{ - return syscall( CG_CM_MARKFRAGMENTS, numPoints, points, projection, maxPoints, - pointBuffer, maxFragments, fragmentBuffer ); -} - -void trap_S_StartSound( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx ) -{ - syscall( CG_S_STARTSOUND, origin, entityNum, entchannel, sfx ); -} - -void trap_S_StartLocalSound( sfxHandle_t sfx, int channelNum ) -{ - syscall( CG_S_STARTLOCALSOUND, sfx, channelNum ); -} - -void trap_S_ClearLoopingSounds( qboolean killall ) -{ - syscall( CG_S_CLEARLOOPINGSOUNDS, killall ); -} - -void trap_S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) -{ - syscall( CG_S_ADDLOOPINGSOUND, entityNum, origin, velocity, sfx ); -} - -void trap_S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) -{ - syscall( CG_S_ADDREALLOOPINGSOUND, entityNum, origin, velocity, sfx ); -} - -void trap_S_StopLoopingSound( int entityNum ) -{ - syscall( CG_S_STOPLOOPINGSOUND, entityNum ); -} - -void trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin ) -{ - syscall( CG_S_UPDATEENTITYPOSITION, entityNum, origin ); -} - -void trap_S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater ) -{ - syscall( CG_S_RESPATIALIZE, entityNum, origin, axis, inwater ); -} - -sfxHandle_t trap_S_RegisterSound( const char *sample, qboolean compressed ) -{ - return syscall( CG_S_REGISTERSOUND, sample, compressed ); -} - -void trap_S_StartBackgroundTrack( const char *intro, const char *loop ) -{ - syscall( CG_S_STARTBACKGROUNDTRACK, intro, loop ); -} - -void trap_R_LoadWorldMap( const char *mapname ) -{ - syscall( CG_R_LOADWORLDMAP, mapname ); -} - -qhandle_t trap_R_RegisterModel( const char *name ) -{ - return syscall( CG_R_REGISTERMODEL, name ); -} - -qhandle_t trap_R_RegisterSkin( const char *name ) -{ - return syscall( CG_R_REGISTERSKIN, name ); -} - -qhandle_t trap_R_RegisterShader( const char *name ) -{ - return syscall( CG_R_REGISTERSHADER, name ); -} - -qhandle_t trap_R_RegisterShaderNoMip( const char *name ) -{ - return syscall( CG_R_REGISTERSHADERNOMIP, name ); -} - -void trap_R_RegisterFont( const char *fontName, int pointSize, fontInfo_t *font ) -{ - syscall(CG_R_REGISTERFONT, fontName, pointSize, font ); -} - -void trap_R_ClearScene( void ) -{ - syscall( CG_R_CLEARSCENE ); -} - -void trap_R_AddRefEntityToScene( const refEntity_t *re ) -{ - syscall( CG_R_ADDREFENTITYTOSCENE, re ); -} - -void trap_R_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) -{ - syscall( CG_R_ADDPOLYTOSCENE, hShader, numVerts, verts ); -} - -void trap_R_AddPolysToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ) -{ - syscall( CG_R_ADDPOLYSTOSCENE, hShader, numVerts, verts, num ); -} - -int trap_R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ) -{ - return syscall( CG_R_LIGHTFORPOINT, point, ambientLight, directedLight, lightDir ); -} - -void trap_R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) -{ - syscall( CG_R_ADDLIGHTTOSCENE, org, PASSFLOAT(intensity), PASSFLOAT(r), PASSFLOAT(g), PASSFLOAT(b) ); -} - -void trap_R_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) -{ - syscall( CG_R_ADDADDITIVELIGHTTOSCENE, org, PASSFLOAT(intensity), PASSFLOAT(r), PASSFLOAT(g), PASSFLOAT(b) ); -} - -void trap_R_RenderScene( const refdef_t *fd ) -{ - syscall( CG_R_RENDERSCENE, fd ); -} - -void trap_R_SetColor( const float *rgba ) -{ - syscall( CG_R_SETCOLOR, rgba ); -} - -void trap_R_DrawStretchPic( float x, float y, float w, float h, - float s1, float t1, float s2, float t2, qhandle_t hShader ) -{ - syscall( CG_R_DRAWSTRETCHPIC, PASSFLOAT(x), PASSFLOAT(y), PASSFLOAT(w), PASSFLOAT(h), - PASSFLOAT(s1), PASSFLOAT(t1), PASSFLOAT(s2), PASSFLOAT(t2), hShader ); -} - -void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) { - syscall( CG_R_MODELBOUNDS, model, mins, maxs ); -} - -int trap_R_LerpTag( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame, - float frac, const char *tagName ) -{ - return syscall( CG_R_LERPTAG, tag, mod, startFrame, endFrame, PASSFLOAT(frac), tagName ); -} - -void trap_R_RemapShader( const char *oldShader, const char *newShader, const char *timeOffset ) -{ - syscall( CG_R_REMAP_SHADER, oldShader, newShader, timeOffset ); -} - -void trap_GetGlconfig( glconfig_t *glconfig ) -{ - syscall( CG_GETGLCONFIG, glconfig ); -} - -void trap_GetGameState( gameState_t *gamestate ) -{ - syscall( CG_GETGAMESTATE, gamestate ); -} - -void trap_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime ) -{ - syscall( CG_GETCURRENTSNAPSHOTNUMBER, snapshotNumber, serverTime ); -} - -qboolean trap_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) -{ - return syscall( CG_GETSNAPSHOT, snapshotNumber, snapshot ); -} - -qboolean trap_GetServerCommand( int serverCommandNumber ) -{ - return syscall( CG_GETSERVERCOMMAND, serverCommandNumber ); -} - -int trap_GetCurrentCmdNumber( void ) -{ - return syscall( CG_GETCURRENTCMDNUMBER ); -} - -qboolean trap_GetUserCmd( int cmdNumber, usercmd_t *ucmd ) -{ - return syscall( CG_GETUSERCMD, cmdNumber, ucmd ); -} - -void trap_SetUserCmdValue( int stateValue, float sensitivityScale ) -{ - syscall( CG_SETUSERCMDVALUE, stateValue, PASSFLOAT( sensitivityScale ) ); -} - -void testPrintInt( char *string, int i ) -{ - syscall( CG_TESTPRINTINT, string, i ); -} - -void testPrintFloat( char *string, float f ) -{ - syscall( CG_TESTPRINTFLOAT, string, PASSFLOAT(f) ); -} - -int trap_MemoryRemaining( void ) -{ - return syscall( CG_MEMORY_REMAINING ); -} - -qboolean trap_Key_IsDown( int keynum ) -{ - return syscall( CG_KEY_ISDOWN, keynum ); -} - -int trap_Key_GetCatcher( void ) -{ - return syscall( CG_KEY_GETCATCHER ); -} - -void trap_Key_SetCatcher( int catcher ) -{ - syscall( CG_KEY_SETCATCHER, catcher ); -} - -int trap_Key_GetKey( const char *binding ) -{ - return syscall( CG_KEY_GETKEY, binding ); -} - -int trap_PC_AddGlobalDefine( char *define ) -{ - return syscall( CG_PC_ADD_GLOBAL_DEFINE, define ); -} - -int trap_PC_LoadSource( const char *filename ) -{ - return syscall( CG_PC_LOAD_SOURCE, filename ); -} - -int trap_PC_FreeSource( int handle ) -{ - return syscall( CG_PC_FREE_SOURCE, handle ); -} - -int trap_PC_ReadToken( int handle, pc_token_t *pc_token ) -{ - return syscall( CG_PC_READ_TOKEN, handle, pc_token ); -} - -int trap_PC_SourceFileAndLine( int handle, char *filename, int *line ) -{ - return syscall( CG_PC_SOURCE_FILE_AND_LINE, handle, filename, line ); -} - -void trap_S_StopBackgroundTrack( void ) -{ - syscall( CG_S_STOPBACKGROUNDTRACK ); -} - -int trap_RealTime(qtime_t *qtime) -{ - return syscall( CG_REAL_TIME, qtime ); -} - -void trap_SnapVector( float *v ) -{ - syscall( CG_SNAPVECTOR, v ); -} - -// this returns a handle. arg0 is the name in the format "idlogo.roq", set arg1 to NULL, alteredstates to qfalse (do not alter gamestate) -int trap_CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits ) -{ - return syscall(CG_CIN_PLAYCINEMATIC, arg0, xpos, ypos, width, height, bits); -} - -// stops playing the cinematic and ends it. should always return FMV_EOF -// cinematics must be stopped in reverse order of when they are started -e_status trap_CIN_StopCinematic( int handle ) -{ - return syscall(CG_CIN_STOPCINEMATIC, handle); -} - - -// will run a frame of the cinematic but will not draw it. Will return FMV_EOF if the end of the cinematic has been reached. -e_status trap_CIN_RunCinematic( int handle ) -{ - return syscall(CG_CIN_RUNCINEMATIC, handle); -} - - -// draws the current frame -void trap_CIN_DrawCinematic( int handle ) -{ - syscall(CG_CIN_DRAWCINEMATIC, handle); -} - - -// allows you to resize the animation dynamically -void trap_CIN_SetExtents( int handle, int x, int y, int w, int h ) -{ - syscall(CG_CIN_SETEXTENTS, handle, x, y, w, h); -} - 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 ); - } - } -} diff --git a/mod/src/cgame/cg_view.c b/mod/src/cgame/cg_view.c deleted file mode 100644 index 324646c9..00000000 --- a/mod/src/cgame/cg_view.c +++ /dev/null @@ -1,1330 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_view.c -- setup all the parameters (position, angle, etc) -// for a 3D rendering - -/* - * 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" - - -/* -============================================================================= - - MODEL TESTING - -The viewthing and gun positioning tools from Q2 have been integrated and -enhanced into a single model testing facility. - -Model viewing can begin with either "testmodel <modelname>" or "testgun <modelname>". - -The names must be the full pathname after the basedir, like -"models/weapons/v_launch/tris.md3" or "players/male/tris.md3" - -Testmodel will create a fake entity 100 units in front of the current view -position, directly facing the viewer. It will remain immobile, so you can -move around it to view it from different angles. - -Testgun will cause the model to follow the player around and supress the real -view weapon model. The default frame 0 of most guns is completely off screen, -so you will probably have to cycle a couple frames to see it. - -"nextframe", "prevframe", "nextskin", and "prevskin" commands will change the -frame or skin of the testmodel. These are bound to F5, F6, F7, and F8 in -q3default.cfg. - -If a gun is being tested, the "gun_x", "gun_y", and "gun_z" variables will let -you adjust the positioning. - -Note that none of the model testing features update while the game is paused, so -it may be convenient to test with deathmatch set to 1 so that bringing down the -console doesn't pause the game. - -============================================================================= -*/ - -/* -================= -CG_TestModel_f - -Creates an entity in front of the current position, which -can then be moved around -================= -*/ -void CG_TestModel_f( void ) -{ - vec3_t angles; - - memset( &cg.testModelEntity, 0, sizeof( cg.testModelEntity ) ); - memset( &cg.testModelBarrelEntity, 0, sizeof( cg.testModelBarrelEntity ) ); - - if( trap_Argc( ) < 2 ) - return; - - Q_strncpyz( cg.testModelName, CG_Argv( 1 ), MAX_QPATH ); - cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName ); - - Q_strncpyz( cg.testModelBarrelName, CG_Argv( 1 ), MAX_QPATH ); - cg.testModelBarrelName[ strlen( cg.testModelBarrelName ) - 4 ] = '\0'; - Q_strcat( cg.testModelBarrelName, MAX_QPATH, "_barrel.md3" ); - cg.testModelBarrelEntity.hModel = trap_R_RegisterModel( cg.testModelBarrelName ); - - if( trap_Argc( ) == 3 ) - { - cg.testModelEntity.backlerp = atof( CG_Argv( 2 ) ); - cg.testModelEntity.frame = 1; - cg.testModelEntity.oldframe = 0; - } - - if( !cg.testModelEntity.hModel ) - { - CG_Printf( "Can't register model\n" ); - return; - } - - VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[ 0 ], cg.testModelEntity.origin ); - - angles[ PITCH ] = 0; - angles[ YAW ] = 180 + cg.refdefViewAngles[ 1 ]; - angles[ ROLL ] = 0; - - AnglesToAxis( angles, cg.testModelEntity.axis ); - cg.testGun = qfalse; - - if( cg.testModelBarrelEntity.hModel ) - { - angles[ YAW ] = 0; - angles[ PITCH ] = 0; - angles[ ROLL ] = 0; - AnglesToAxis( angles, cg.testModelBarrelEntity.axis ); - } -} - -/* -================= -CG_TestGun_f - -Replaces the current view weapon with the given model -================= -*/ -void CG_TestGun_f( void ) -{ - CG_TestModel_f( ); - cg.testGun = qtrue; - cg.testModelEntity.renderfx = RF_MINLIGHT | RF_DEPTHHACK | RF_FIRST_PERSON; -} - - -void CG_TestModelNextFrame_f( void ) -{ - cg.testModelEntity.frame++; - CG_Printf( "frame %i\n", cg.testModelEntity.frame ); -} - -void CG_TestModelPrevFrame_f( void ) -{ - cg.testModelEntity.frame--; - - if( cg.testModelEntity.frame < 0 ) - cg.testModelEntity.frame = 0; - - CG_Printf( "frame %i\n", cg.testModelEntity.frame ); -} - -void CG_TestModelNextSkin_f( void ) -{ - cg.testModelEntity.skinNum++; - CG_Printf( "skin %i\n", cg.testModelEntity.skinNum ); -} - -void CG_TestModelPrevSkin_f( void ) -{ - cg.testModelEntity.skinNum--; - - if( cg.testModelEntity.skinNum < 0 ) - cg.testModelEntity.skinNum = 0; - - CG_Printf( "skin %i\n", cg.testModelEntity.skinNum ); -} - -static void CG_AddTestModel( void ) -{ - int i; - - // re-register the model, because the level may have changed - cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName ); - cg.testModelBarrelEntity.hModel = trap_R_RegisterModel( cg.testModelBarrelName ); - - if( !cg.testModelEntity.hModel ) - { - CG_Printf( "Can't register model\n" ); - return; - } - - // if testing a gun, set the origin reletive to the view origin - if( cg.testGun ) - { - VectorCopy( cg.refdef.vieworg, cg.testModelEntity.origin ); - VectorCopy( cg.refdef.viewaxis[ 0 ], cg.testModelEntity.axis[ 0 ] ); - VectorCopy( cg.refdef.viewaxis[ 1 ], cg.testModelEntity.axis[ 1 ] ); - VectorCopy( cg.refdef.viewaxis[ 2 ], cg.testModelEntity.axis[ 2 ] ); - - // allow the position to be adjusted - for( i = 0; i < 3; i++ ) - { - cg.testModelEntity.origin[ i ] += cg.refdef.viewaxis[ 0 ][ i ] * cg_gun_x.value; - cg.testModelEntity.origin[ i ] += cg.refdef.viewaxis[ 1 ][ i ] * cg_gun_y.value; - cg.testModelEntity.origin[ i ] += cg.refdef.viewaxis[ 2 ][ i ] * cg_gun_z.value; - } - } - - trap_R_AddRefEntityToScene( &cg.testModelEntity ); - - if( cg.testModelBarrelEntity.hModel ) - { - CG_PositionEntityOnTag( &cg.testModelBarrelEntity, &cg.testModelEntity, - cg.testModelEntity.hModel, "tag_barrel" ); - - trap_R_AddRefEntityToScene( &cg.testModelBarrelEntity ); - } -} - - - -//============================================================================ - - -/* -================= -CG_CalcVrect - -Sets the coordinates of the rendered window -================= -*/ -static void CG_CalcVrect( void ) -{ - int size; - - // the intermission should allways be full screen - if( cg.snap->ps.pm_type == PM_INTERMISSION ) - size = 100; - else - { - // bound normal viewsize - if( cg_viewsize.integer < 30 ) - { - trap_Cvar_Set( "cg_viewsize", "30" ); - size = 30; - } - else if( cg_viewsize.integer > 100 ) - { - trap_Cvar_Set( "cg_viewsize","100" ); - size = 100; - } - else - size = cg_viewsize.integer; - } - - cg.refdef.width = cgs.glconfig.vidWidth * size / 100; - cg.refdef.width &= ~1; - - cg.refdef.height = cgs.glconfig.vidHeight * size / 100; - cg.refdef.height &= ~1; - - cg.refdef.x = ( cgs.glconfig.vidWidth - cg.refdef.width ) / 2; - cg.refdef.y = ( cgs.glconfig.vidHeight - cg.refdef.height ) / 2; -} - -//============================================================================== - - -/* -=============== -CG_OffsetThirdPersonView - -=============== -*/ -#define FOCUS_DISTANCE 512 -static void CG_OffsetThirdPersonView( void ) -{ - vec3_t forward, right, up; - vec3_t view; - vec3_t focusAngles; - trace_t trace; - static vec3_t mins = { -8, -8, -8 }; - static vec3_t maxs = { 8, 8, 8 }; - vec3_t focusPoint; - float focusDist; - float forwardScale, sideScale; - vec3_t surfNormal; - - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING ) - { - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) - VectorSet( surfNormal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( cg.predictedPlayerState.grapplePoint, surfNormal ); - } - else - VectorSet( surfNormal, 0.0f, 0.0f, 1.0f ); - - VectorMA( cg.refdef.vieworg, cg.predictedPlayerState.viewheight, surfNormal, cg.refdef.vieworg ); - - VectorCopy( cg.refdefViewAngles, focusAngles ); - - // if dead, look at killer - if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) - { - focusAngles[ YAW ] = cg.predictedPlayerState.stats[ STAT_VIEWLOCK ]; - cg.refdefViewAngles[ YAW ] = cg.predictedPlayerState.stats[ STAT_VIEWLOCK ]; - } - - //if ( focusAngles[PITCH] > 45 ) { - // focusAngles[PITCH] = 45; // don't go too far overhead - //} - AngleVectors( focusAngles, forward, NULL, NULL ); - - VectorMA( cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint ); - - VectorCopy( cg.refdef.vieworg, view ); - - VectorMA( view, 12, surfNormal, view ); - - //cg.refdefViewAngles[PITCH] *= 0.5; - - AngleVectors( cg.refdefViewAngles, forward, right, up ); - - forwardScale = cos( cg_thirdPersonAngle.value / 180 * M_PI ); - sideScale = sin( cg_thirdPersonAngle.value / 180 * M_PI ); - VectorMA( view, -cg_thirdPersonRange.value * forwardScale, forward, view ); - VectorMA( view, -cg_thirdPersonRange.value * sideScale, right, view ); - - // trace a ray from the origin to the viewpoint to make sure the view isn't - // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything - - if( !cg_cameraMode.integer ) - { - CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); - - if( trace.fraction != 1.0 ) - { - VectorCopy( trace.endpos, view ); - view[ 2 ] += ( 1.0 - trace.fraction ) * 32; - // try another trace to this position, because a tunnel may have the ceiling - // close enogh that this is poking out - - CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); - VectorCopy( trace.endpos, view ); - } - } - - VectorCopy( view, cg.refdef.vieworg ); - - // select pitch to look at focus point from vieword - VectorSubtract( focusPoint, cg.refdef.vieworg, focusPoint ); - focusDist = sqrt( focusPoint[ 0 ] * focusPoint[ 0 ] + focusPoint[ 1 ] * focusPoint[ 1 ] ); - if ( focusDist < 1 ) { - focusDist = 1; // should never happen - } - cg.refdefViewAngles[ PITCH ] = -180 / M_PI * atan2( focusPoint[ 2 ], focusDist ); - cg.refdefViewAngles[ YAW ] -= cg_thirdPersonAngle.value; -} - - -// this causes a compiler bug on mac MrC compiler -static void CG_StepOffset( void ) -{ - float steptime; - int timeDelta; - vec3_t normal; - playerState_t *ps = &cg.predictedPlayerState; - - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) - { - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) - VectorSet( normal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( ps->grapplePoint, normal ); - } - else - VectorSet( normal, 0.0f, 0.0f, 1.0f ); - - steptime = BG_FindSteptimeForClass( ps->stats[ STAT_PCLASS ] ); - - // smooth out stair climbing - timeDelta = cg.time - cg.stepTime; - if( timeDelta < steptime ) - { - float stepChange = cg.stepChange - * (steptime - timeDelta) / steptime; - - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) - VectorMA( cg.refdef.vieworg, -stepChange, normal, cg.refdef.vieworg ); - else - cg.refdef.vieworg[ 2 ] -= stepChange; - } -} - -#define PCLOUD_ROLL_AMPLITUDE 25.0f -#define PCLOUD_ROLL_FREQUENCY 0.4f -#define PCLOUD_ZOOM_AMPLITUDE 15 -#define PCLOUD_ZOOM_FREQUENCY 0.7f - - -/* -=============== -CG_OffsetFirstPersonView - -=============== -*/ -static void CG_OffsetFirstPersonView( void ) -{ - float *origin; - float *angles; - float bob; - float ratio; - float delta; - float speed; - float f; - vec3_t predictedVelocity; - int timeDelta; - float bob2; - vec3_t normal, baseOrigin; - playerState_t *ps = &cg.predictedPlayerState; - - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) - { - if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) - VectorSet( normal, 0.0f, 0.0f, -1.0f ); - else - VectorCopy( ps->grapplePoint, normal ); - } - else - VectorSet( normal, 0.0f, 0.0f, 1.0f ); - - - if( cg.snap->ps.pm_type == PM_INTERMISSION ) - return; - - origin = cg.refdef.vieworg; - angles = cg.refdefViewAngles; - - VectorCopy( origin, baseOrigin ); - - // if dead, fix the angle and don't add any kick - if( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ) - { - angles[ ROLL ] = 40; - angles[ PITCH ] = -15; - angles[ YAW ] = cg.snap->ps.stats[ STAT_VIEWLOCK ]; - origin[ 2 ] += cg.predictedPlayerState.viewheight; - return; - } - - // add angles based on weapon kick - VectorAdd( angles, cg.kick_angles, angles ); - - // add angles based on damage kick - if( cg.damageTime ) - { - ratio = cg.time - cg.damageTime; - if( ratio < DAMAGE_DEFLECT_TIME ) - { - ratio /= DAMAGE_DEFLECT_TIME; - angles[ PITCH ] += ratio * cg.v_dmg_pitch; - angles[ ROLL ] += ratio * cg.v_dmg_roll; - } - else - { - ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME; - if( ratio > 0 ) - { - angles[ PITCH ] += ratio * cg.v_dmg_pitch; - angles[ ROLL ] += ratio * cg.v_dmg_roll; - } - } - } - - // add pitch based on fall kick -#if 0 - ratio = ( cg.time - cg.landTime) / FALL_TIME; - if (ratio < 0) - ratio = 0; - angles[PITCH] += ratio * cg.fall_value; -#endif - - // add angles based on velocity - VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity ); - - delta = DotProduct( predictedVelocity, cg.refdef.viewaxis[ 0 ] ); - angles[ PITCH ] += delta * cg_runpitch.value; - - delta = DotProduct( predictedVelocity, cg.refdef.viewaxis[ 1 ] ); - angles[ ROLL ] -= delta * cg_runroll.value; - - // add angles based on bob - //TA: bob amount is class dependant - - if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) - bob2 = 0.0f; - else - bob2 = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ); - - -#define LEVEL4_FEEDBACK 10.0f - - //give a charging player some feedback - if( ps->weapon == WP_ALEVEL4 ) - { - if( ps->stats[ STAT_MISC ] > 0 ) - { - float fraction = (float)ps->stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME; - - if( fraction > 1.0f ) - fraction = 1.0f; - - bob2 *= ( 1.0f + fraction * LEVEL4_FEEDBACK ); - } - } - - if( bob2 != 0.0f ) - { - // make sure the bob is visible even at low speeds - speed = cg.xyspeed > 200 ? cg.xyspeed : 200; - - delta = cg.bobfracsin * ( bob2 ) * speed; - if( cg.predictedPlayerState.pm_flags & PMF_DUCKED ) - delta *= 3; // crouching - - angles[ PITCH ] += delta; - delta = cg.bobfracsin * ( bob2 ) * speed; - if( cg.predictedPlayerState.pm_flags & PMF_DUCKED ) - delta *= 3; // crouching accentuates roll - - if( cg.bobcycle & 1 ) - delta = -delta; - - angles[ ROLL ] += delta; - } - -#define LEVEL3_FEEDBACK 20.0f - - //provide some feedback for pouncing - if( cg.predictedPlayerState.weapon == WP_ALEVEL3 || - cg.predictedPlayerState.weapon == WP_ALEVEL3_UPG ) - { - if( cg.predictedPlayerState.stats[ STAT_MISC ] > 0 ) - { - float fraction1, fraction2; - vec3_t forward; - - AngleVectors( angles, forward, NULL, NULL ); - VectorNormalize( forward ); - - fraction1 = (float)( cg.time - cg.weapon2Time ) / (float)LEVEL3_POUNCE_CHARGE_TIME; - - if( fraction1 > 1.0f ) - fraction1 = 1.0f; - - fraction2 = -sin( fraction1 * M_PI / 2 ); - - VectorMA( origin, LEVEL3_FEEDBACK * fraction2, forward, origin ); - } - } - -#define STRUGGLE_DIST 5.0f -#define STRUGGLE_TIME 250 - - //allow the player to struggle a little whilst grabbed - if( cg.predictedPlayerState.pm_type == PM_GRABBED ) - { - vec3_t forward, right, up; - usercmd_t cmd; - int cmdNum; - float fFraction, rFraction, uFraction; - float fFraction2, rFraction2, uFraction2; - - cmdNum = trap_GetCurrentCmdNumber(); - trap_GetUserCmd( cmdNum, &cmd ); - - AngleVectors( angles, forward, right, up ); - - fFraction = (float)( cg.time - cg.forwardMoveTime ) / STRUGGLE_TIME; - rFraction = (float)( cg.time - cg.rightMoveTime ) / STRUGGLE_TIME; - uFraction = (float)( cg.time - cg.upMoveTime ) / STRUGGLE_TIME; - - if( fFraction > 1.0f ) - fFraction = 1.0f; - if( rFraction > 1.0f ) - rFraction = 1.0f; - if( uFraction > 1.0f ) - uFraction = 1.0f; - - fFraction2 = -sin( fFraction * M_PI / 2 ); - rFraction2 = -sin( rFraction * M_PI / 2 ); - uFraction2 = -sin( uFraction * M_PI / 2 ); - - if( cmd.forwardmove > 0 ) - VectorMA( origin, STRUGGLE_DIST * fFraction, forward, origin ); - else if( cmd.forwardmove < 0 ) - VectorMA( origin, -STRUGGLE_DIST * fFraction, forward, origin ); - else - cg.forwardMoveTime = cg.time; - - if( cmd.rightmove > 0 ) - VectorMA( origin, STRUGGLE_DIST * rFraction, right, origin ); - else if( cmd.rightmove < 0 ) - VectorMA( origin, -STRUGGLE_DIST * rFraction, right, origin ); - else - cg.rightMoveTime = cg.time; - - if( cmd.upmove > 0 ) - VectorMA( origin, STRUGGLE_DIST * uFraction, up, origin ); - else if( cmd.upmove < 0 ) - VectorMA( origin, -STRUGGLE_DIST * uFraction, up, origin ); - else - cg.upMoveTime = cg.time; - } - - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_POISONCLOUDED && - !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) - { - float fraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 2 * PCLOUD_ROLL_FREQUENCY ); - float pitchFraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 5 * PCLOUD_ROLL_FREQUENCY ); - - fraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME ); - pitchFraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME ); - - angles[ ROLL ] += fraction * PCLOUD_ROLL_AMPLITUDE; - angles[ YAW ] += fraction * PCLOUD_ROLL_AMPLITUDE; - angles[ PITCH ] += pitchFraction * PCLOUD_ROLL_AMPLITUDE / 2.0f; - } - - //TA: this *feels* more realisitic for humans - if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS ) - { - angles[PITCH] += cg.bobfracsin * bob2 * 0.5; - - //TA: heavy breathing effects //FIXME: sound - if( cg.predictedPlayerState.stats[ STAT_STAMINA ] < 0 ) - { - float deltaBreath = (float)( - cg.predictedPlayerState.stats[ STAT_STAMINA ] < 0 ? - -cg.predictedPlayerState.stats[ STAT_STAMINA ] : - cg.predictedPlayerState.stats[ STAT_STAMINA ] ) / 200.0; - float deltaAngle = cos( (float)cg.time/150.0 ) * deltaBreath; - - deltaAngle += ( deltaAngle < 0 ? -deltaAngle : deltaAngle ) * 0.5; - - angles[ PITCH ] -= deltaAngle; - } - } - -//=================================== - - // add view height - //TA: when wall climbing the viewheight is not straight up - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING ) - VectorMA( origin, ps->viewheight, normal, origin ); - else - origin[ 2 ] += cg.predictedPlayerState.viewheight; - - // smooth out duck height changes - timeDelta = cg.time - cg.duckTime; - if( timeDelta < DUCK_TIME) - { - cg.refdef.vieworg[ 2 ] -= cg.duckChange - * ( DUCK_TIME - timeDelta ) / DUCK_TIME; - } - - // add bob height - bob = cg.bobfracsin * cg.xyspeed * bob2; - - if( bob > 6 ) - bob = 6; - - //TA: likewise for bob - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING ) - VectorMA( origin, bob, normal, origin ); - else - origin[ 2 ] += bob; - - - // add fall height - delta = cg.time - cg.landTime; - - if( delta < LAND_DEFLECT_TIME ) - { - f = delta / LAND_DEFLECT_TIME; - cg.refdef.vieworg[ 2 ] += cg.landChange * f; - } - else if( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) - { - delta -= LAND_DEFLECT_TIME; - f = 1.0 - ( delta / LAND_RETURN_TIME ); - cg.refdef.vieworg[ 2 ] += cg.landChange * f; - } - - // add step offset - CG_StepOffset( ); - - // add kick offset - - VectorAdd (origin, cg.kick_origin, origin); -} - -//====================================================================== - -void CG_ZoomDown_f( void ) -{ - if( cg.zoomed ) - return; - - cg.zoomed = qtrue; - cg.zoomTime = cg.time; -} - -void CG_ZoomUp_f( void ) -{ - if( !cg.zoomed ) - return; - - cg.zoomed = qfalse; - cg.zoomTime = cg.time; -} - - -/* -==================== -CG_CalcFov - -Fixed fov at intermissions, otherwise account for fov variable and zooms. -==================== -*/ -#define WAVE_AMPLITUDE 1 -#define WAVE_FREQUENCY 0.4 - -#define FOVWARPTIME 400.0 - -static int CG_CalcFov( void ) -{ - float x; - float phase; - float v; - int contents; - float fov_x, fov_y; - float zoomFov; - float f; - int inwater; - int attribFov; - - if( cg.predictedPlayerState.pm_type == PM_INTERMISSION || - ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) ) - { - // if in intermission, use a fixed value - fov_x = 90; - } - else - { - //TA: don't lock the fov globally - we need to be able to change it - attribFov = BG_FindFovForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ); - fov_x = attribFov; - - if ( fov_x < 1 ) - fov_x = 1; - else if ( fov_x > 160 ) - fov_x = 160; - - if( cg.spawnTime > ( cg.time - FOVWARPTIME ) && - BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_FOVWARPS ) ) - { - float temp, temp2; - - temp = (float)( cg.time - cg.spawnTime ) / FOVWARPTIME; - temp2 = ( 180 - fov_x ) * temp; - - //Com_Printf( "%f %f\n", temp*100, temp2*100 ); - - fov_x = 180 - temp2; - } - - // account for zooms - zoomFov = BG_FindZoomFovForWeapon( cg.predictedPlayerState.weapon ); - if ( zoomFov < 1 ) - zoomFov = 1; - else if ( zoomFov > attribFov ) - zoomFov = attribFov; - - //TA: only do all the zoom stuff if the client CAN zoom - if( BG_WeaponCanZoom( cg.predictedPlayerState.weapon ) ) - { - if ( cg.zoomed ) - { - f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME; - - if ( f > 1.0 ) - fov_x = zoomFov; - else - fov_x = fov_x + f * ( zoomFov - fov_x ); - } - else - { - f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME; - - if ( f > 1.0 ) - fov_x = fov_x; - else - fov_x = zoomFov + f * ( fov_x - zoomFov ); - } - } - } - - x = cg.refdef.width / tan( fov_x / 360 * M_PI ); - fov_y = atan2( cg.refdef.height, x ); - fov_y = fov_y * 360 / M_PI; - - // warp if underwater - contents = CG_PointContents( cg.refdef.vieworg, -1 ); - - if( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - { - phase = cg.time / 1000.0 * WAVE_FREQUENCY * M_PI * 2; - v = WAVE_AMPLITUDE * sin( phase ); - fov_x += v; - fov_y -= v; - inwater = qtrue; - } - else - inwater = qfalse; - - if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_POISONCLOUDED && - cg.predictedPlayerState.stats[ STAT_HEALTH ] > 0 && - !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) - { - phase = cg.time / 1000.0 * PCLOUD_ZOOM_FREQUENCY * M_PI * 2; - v = PCLOUD_ZOOM_AMPLITUDE * sin( phase ); - v *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME ); - fov_x += v; - fov_y += v; - } - - - // set it - cg.refdef.fov_x = fov_x; - cg.refdef.fov_y = fov_y; - - if( !cg.zoomed ) - cg.zoomSensitivity = 1; - else - cg.zoomSensitivity = cg.refdef.fov_y / 75.0; - - return inwater; -} - - - -#define NORMAL_HEIGHT 64.0f -#define NORMAL_WIDTH 6.0f - -/* -=============== -CG_DrawSurfNormal - -Draws a vector against -the surface player is looking at -=============== -*/ -static void CG_DrawSurfNormal( void ) -{ - trace_t tr; - vec3_t end, temp; - polyVert_t normal[ 4 ]; - vec4_t color = { 0.0f, 255.0f, 0.0f, 128.0f }; - - VectorMA( cg.refdef.vieworg, 8192, cg.refdef.viewaxis[ 0 ], end ); - - CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL, end, cg.predictedPlayerState.clientNum, MASK_SOLID ); - - VectorCopy( tr.endpos, normal[ 0 ].xyz ); - normal[ 0 ].st[ 0 ] = 0; - normal[ 0 ].st[ 1 ] = 0; - Vector4Copy( color, normal[ 0 ].modulate ); - - VectorMA( tr.endpos, NORMAL_WIDTH, cg.refdef.viewaxis[ 1 ], temp ); - VectorCopy( temp, normal[ 1 ].xyz); - normal[ 1 ].st[ 0 ] = 0; - normal[ 1 ].st[ 1 ] = 1; - Vector4Copy( color, normal[ 1 ].modulate ); - - VectorMA( tr.endpos, NORMAL_HEIGHT, tr.plane.normal, temp ); - VectorMA( temp, NORMAL_WIDTH, cg.refdef.viewaxis[ 1 ], temp ); - VectorCopy( temp, normal[ 2 ].xyz ); - normal[ 2 ].st[ 0 ] = 1; - normal[ 2 ].st[ 1 ] = 1; - Vector4Copy( color, normal[ 2 ].modulate ); - - VectorMA( tr.endpos, NORMAL_HEIGHT, tr.plane.normal, temp ); - VectorCopy( temp, normal[ 3 ].xyz ); - normal[ 3 ].st[ 0 ] = 1; - normal[ 3 ].st[ 1 ] = 0; - Vector4Copy( color, normal[ 3 ].modulate ); - - trap_R_AddPolyToScene( cgs.media.outlineShader, 4, normal ); -} - -/* -=============== -CG_addSmoothOp -=============== -*/ -void CG_addSmoothOp( vec3_t rotAxis, float rotAngle, float timeMod ) -{ - int i; - - //iterate through smooth array - for( i = 0; i < MAXSMOOTHS; i++ ) - { - //found an unused index in the smooth array - if( cg.sList[ i ].time + cg_wwSmoothTime.integer < cg.time ) - { - //copy to array and stop - VectorCopy( rotAxis, cg.sList[ i ].rotAxis ); - cg.sList[ i ].rotAngle = rotAngle; - cg.sList[ i ].time = cg.time; - cg.sList[ i ].timeMod = timeMod; - return; - } - } - - //no free indices in the smooth array -} - -/* -=============== -CG_smoothWWTransitions -=============== -*/ -static void CG_smoothWWTransitions( playerState_t *ps, const vec3_t in, vec3_t out ) -{ - vec3_t surfNormal, rotAxis, temp; - vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; - vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f }; - int i; - float stLocal, sFraction, rotAngle; - float smoothTime, timeMod; - qboolean performed = qfalse; - vec3_t inAxis[ 3 ], lastAxis[ 3 ], outAxis[ 3 ]; - - if( cg.snap->ps.pm_flags & PMF_FOLLOW ) - { - VectorCopy( in, out ); - return; - } - - //set surfNormal - if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) - VectorCopy( ps->grapplePoint, surfNormal ); - else - VectorCopy( ceilingNormal, surfNormal ); - - AnglesToAxis( in, inAxis ); - - //if we are moving from one surface to another smooth the transition - if( !VectorCompare( surfNormal, cg.lastNormal ) ) - { - //if we moving from the ceiling to the floor special case - //( x product of colinear vectors is undefined) - if( VectorCompare( ceilingNormal, cg.lastNormal ) && - VectorCompare( refNormal, surfNormal ) ) - { - AngleVectors( in, temp, NULL, NULL ); - ProjectPointOnPlane( rotAxis, temp, refNormal ); - VectorNormalize( rotAxis ); - rotAngle = 180.0f; - timeMod = 1.5f; - } - else - { - AnglesToAxis( cg.lastVangles, lastAxis ); - rotAngle = DotProduct( inAxis[ 0 ], lastAxis[ 0 ] ) + - DotProduct( inAxis[ 1 ], lastAxis[ 1 ] ) + - DotProduct( inAxis[ 2 ], lastAxis[ 2 ] ); - - rotAngle = RAD2DEG( acos( ( rotAngle - 1.0f ) / 2.0f ) ); - - CrossProduct( lastAxis[ 0 ], inAxis[ 0 ], temp ); - VectorCopy( temp, rotAxis ); - CrossProduct( lastAxis[ 1 ], inAxis[ 1 ], temp ); - VectorAdd( rotAxis, temp, rotAxis ); - CrossProduct( lastAxis[ 2 ], inAxis[ 2 ], temp ); - VectorAdd( rotAxis, temp, rotAxis ); - - VectorNormalize( rotAxis ); - - timeMod = 1.0f; - } - - //add the op - CG_addSmoothOp( rotAxis, rotAngle, timeMod ); - } - - //iterate through ops - for( i = MAXSMOOTHS - 1; i >= 0; i-- ) - { - smoothTime = (int)( cg_wwSmoothTime.integer * cg.sList[ i ].timeMod ); - - //if this op has time remaining, perform it - if( cg.time < cg.sList[ i ].time + smoothTime ) - { - stLocal = 1.0f - ( ( ( cg.sList[ i ].time + smoothTime ) - cg.time ) / smoothTime ); - sFraction = -( cos( stLocal * M_PI ) + 1.0f ) / 2.0f; - - RotatePointAroundVector( outAxis[ 0 ], cg.sList[ i ].rotAxis, - inAxis[ 0 ], sFraction * cg.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 1 ], cg.sList[ i ].rotAxis, - inAxis[ 1 ], sFraction * cg.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 2 ], cg.sList[ i ].rotAxis, - inAxis[ 2 ], sFraction * cg.sList[ i ].rotAngle ); - - AxisCopy( outAxis, inAxis ); - performed = qtrue; - } - } - - //if we performed any ops then return the smoothed angles - //otherwise simply return the in angles - if( performed ) - AxisToAngles( outAxis, out ); - else - VectorCopy( in, out ); - - //copy the current normal to the lastNormal - VectorCopy( in, cg.lastVangles ); - VectorCopy( surfNormal, cg.lastNormal ); -} - -/* -=============== -CG_smoothWJTransitions -=============== -*/ -static void CG_smoothWJTransitions( playerState_t *ps, const vec3_t in, vec3_t out ) -{ - int i; - float stLocal, sFraction; - qboolean performed = qfalse; - vec3_t inAxis[ 3 ], outAxis[ 3 ]; - - if( cg.snap->ps.pm_flags & PMF_FOLLOW ) - { - VectorCopy( in, out ); - return; - } - - AnglesToAxis( in, inAxis ); - - //iterate through ops - for( i = MAXSMOOTHS - 1; i >= 0; i-- ) - { - //if this op has time remaining, perform it - if( cg.time < cg.sList[ i ].time + cg_wwSmoothTime.integer ) - { - stLocal = ( ( cg.sList[ i ].time + cg_wwSmoothTime.integer ) - cg.time ) / cg_wwSmoothTime.integer; - sFraction = 1.0f - ( ( cos( stLocal * M_PI * 2.0f ) + 1.0f ) / 2.0f ); - - RotatePointAroundVector( outAxis[ 0 ], cg.sList[ i ].rotAxis, - inAxis[ 0 ], sFraction * cg.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 1 ], cg.sList[ i ].rotAxis, - inAxis[ 1 ], sFraction * cg.sList[ i ].rotAngle ); - RotatePointAroundVector( outAxis[ 2 ], cg.sList[ i ].rotAxis, - inAxis[ 2 ], sFraction * cg.sList[ i ].rotAngle ); - - AxisCopy( outAxis, inAxis ); - performed = qtrue; - } - } - - //if we performed any ops then return the smoothed angles - //otherwise simply return the in angles - if( performed ) - AxisToAngles( outAxis, out ); - else - VectorCopy( in, out ); -} - - -/* -=============== -CG_CalcViewValues - -Sets cg.refdef view values -=============== -*/ -static int CG_CalcViewValues( void ) -{ - playerState_t *ps; - - memset( &cg.refdef, 0, sizeof( cg.refdef ) ); - - // calculate size of 3D view - CG_CalcVrect( ); - - ps = &cg.predictedPlayerState; - - // intermission view - if( ps->pm_type == PM_INTERMISSION ) - { - VectorCopy( ps->origin, cg.refdef.vieworg ); - VectorCopy( ps->viewangles, cg.refdefViewAngles ); - AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); - - return CG_CalcFov( ); - } - - cg.bobcycle = ( ps->bobCycle & 128 ) >> 7; - cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) ); - cg.xyspeed = sqrt( ps->velocity[ 0 ] * ps->velocity[ 0 ] + - ps->velocity[ 1 ] * ps->velocity[ 1 ] ); - - VectorCopy( ps->origin, cg.refdef.vieworg ); - - if( BG_ClassHasAbility( ps->stats[ STAT_PCLASS ], SCA_WALLCLIMBER ) ) - CG_smoothWWTransitions( ps, ps->viewangles, cg.refdefViewAngles ); - else if( BG_ClassHasAbility( ps->stats[ STAT_PCLASS ], SCA_WALLJUMPER ) ) - CG_smoothWJTransitions( ps, ps->viewangles, cg.refdefViewAngles ); - else - VectorCopy( ps->viewangles, cg.refdefViewAngles ); - - //clumsy logic, but it needs to be this way round because the CS propogation - //delay screws things up otherwise - if( !BG_ClassHasAbility( ps->stats[ STAT_PCLASS ], SCA_WALLJUMPER ) ) - { - if( !( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING ) ) - VectorSet( cg.lastNormal, 0.0f, 0.0f, 1.0f ); - } - - // add error decay - if( cg_errorDecay.value > 0 ) - { - int t; - float f; - - t = cg.time - cg.predictedErrorTime; - f = ( cg_errorDecay.value - t ) / cg_errorDecay.value; - - if( f > 0 && f < 1 ) - VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg ); - else - cg.predictedErrorTime = 0; - } - - //shut off the poison cloud effect if it's still on the go - if( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ) - { - if( CG_IsParticleSystemValid( &cg.poisonCloudPS ) ) - CG_DestroyParticleSystem( &cg.poisonCloudPS ); - } - - if( cg.renderingThirdPerson ) - { - // back away from character - CG_OffsetThirdPersonView( ); - } - else - { - // offset for local bobbing and kicks - CG_OffsetFirstPersonView( ); - } - - // position eye reletive to origin - AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); - - if( cg.hyperspace ) - cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE; - - //draw the surface normal looking at - if( cg_drawSurfNormal.integer ) - CG_DrawSurfNormal( ); - - // field of view - return CG_CalcFov( ); -} - -/* -===================== -CG_AddBufferedSound -===================== -*/ -void CG_AddBufferedSound( sfxHandle_t sfx ) -{ - if( !sfx ) - return; - - cg.soundBuffer[ cg.soundBufferIn ] = sfx; - cg.soundBufferIn = ( cg.soundBufferIn + 1 ) % MAX_SOUNDBUFFER; - - if( cg.soundBufferIn == cg.soundBufferOut ) - cg.soundBufferOut++; -} - -/* -===================== -CG_PlayBufferedSounds -===================== -*/ -static void CG_PlayBufferedSounds( void ) -{ - if( cg.soundTime < cg.time ) - { - if( cg.soundBufferOut != cg.soundBufferIn && cg.soundBuffer[ cg.soundBufferOut ] ) - { - trap_S_StartLocalSound( cg.soundBuffer[ cg.soundBufferOut ], CHAN_ANNOUNCER ); - cg.soundBuffer[ cg.soundBufferOut ] = 0; - cg.soundBufferOut = ( cg.soundBufferOut + 1 ) % MAX_SOUNDBUFFER; - cg.soundTime = cg.time + 750; - } - } -} - -//========================================================================= - -/* -================= -CG_DrawActiveFrame - -Generates and draws a game scene and status information at the given time. -================= -*/ -void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) -{ - int inwater; - - cg.time = serverTime; - cg.demoPlayback = demoPlayback; - - // update cvars - CG_UpdateCvars( ); - - // if we are only updating the screen as a loading - // pacifier, don't even try to read snapshots - if( cg.infoScreenText[ 0 ] != 0 ) - { - CG_DrawLoadingScreen( ); - return; - } - - // any looped sounds will be respecified as entities - // are added to the render list - trap_S_ClearLoopingSounds( qfalse ); - - // clear all the render lists - trap_R_ClearScene( ); - - // set up cg.snap and possibly cg.nextSnap - CG_ProcessSnapshots( ); - - // if we haven't received any snapshots yet, all - // we can draw is the information screen - if( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) - { - CG_DrawLoadingScreen( ); - return; - } - - // let the client system know what our weapon and zoom settings are - trap_SetUserCmdValue( cg.weaponSelect, cg.zoomSensitivity ); - - // this counter will be bumped for every valid scene we generate - cg.clientFrame++; - - // update cg.predictedPlayerState - CG_PredictPlayerState( ); - - // decide on third person view - cg.renderingThirdPerson = cg_thirdPerson.integer || ( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ); - - // build cg.refdef - inwater = CG_CalcViewValues( ); - - // build the render lists - if( !cg.hyperspace ) - { - CG_AddPacketEntities( ); // after calcViewValues, so predicted player state is correct - CG_AddMarks( ); - } - - CG_AddViewWeapon( &cg.predictedPlayerState ); - - //after CG_AddViewWeapon - if( !cg.hyperspace ) - { - CG_AddParticles( ); - CG_AddTrails( ); - } - - // add buffered sounds - CG_PlayBufferedSounds( ); - - // finish up the rest of the refdef - if( cg.testModelEntity.hModel ) - CG_AddTestModel( ); - - cg.refdef.time = cg.time; - memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); - - //remove expired console lines - if( cg.consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 ) - CG_RemoveConsoleLine( ); - - // update audio positions - trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater ); - - // make sure the lagometerSample and frame timing isn't done twice when in stereo - if( stereoView != STEREO_RIGHT ) - { - cg.frametime = cg.time - cg.oldTime; - - if( cg.frametime < 0 ) - cg.frametime = 0; - - cg.oldTime = cg.time; - CG_AddLagometerFrameInfo( ); - } - - if( cg_timescale.value != cg_timescaleFadeEnd.value ) - { - if( cg_timescale.value < cg_timescaleFadeEnd.value ) - { - cg_timescale.value += cg_timescaleFadeSpeed.value * ( (float)cg.frametime ) / 1000; - if( cg_timescale.value > cg_timescaleFadeEnd.value ) - cg_timescale.value = cg_timescaleFadeEnd.value; - } - else - { - cg_timescale.value -= cg_timescaleFadeSpeed.value * ( (float)cg.frametime ) / 1000; - if( cg_timescale.value < cg_timescaleFadeEnd.value ) - cg_timescale.value = cg_timescaleFadeEnd.value; - } - - if( cg_timescaleFadeSpeed.value ) - trap_Cvar_Set( "timescale", va( "%f", cg_timescale.value ) ); - } - - // actually issue the rendering calls - CG_DrawActive( stereoView ); - - if( cg_stats.integer ) - CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame ); -} - diff --git a/mod/src/cgame/cg_weapons.c b/mod/src/cgame/cg_weapons.c deleted file mode 100644 index 7297c518..00000000 --- a/mod/src/cgame/cg_weapons.c +++ /dev/null @@ -1,1810 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_weapons.c -- events and effects dealing with weapons - -/* - * 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" - -/* -================= -CG_RegisterUpgrade - -The server says this item is used on this level -================= -*/ -void CG_RegisterUpgrade( int upgradeNum ) -{ - upgradeInfo_t *upgradeInfo; - char *icon; - - upgradeInfo = &cg_upgrades[ upgradeNum ]; - - if( upgradeNum == 0 ) - return; - - if( upgradeInfo->registered ) - return; - - memset( upgradeInfo, 0, sizeof( *upgradeInfo ) ); - upgradeInfo->registered = qtrue; - - if( !BG_FindNameForUpgrade( upgradeNum ) ) - CG_Error( "Couldn't find upgrade %i", upgradeNum ); - - upgradeInfo->humanName = BG_FindHumanNameForUpgrade( upgradeNum ); - - //la la la la la, i'm not listening! - if( upgradeNum == UP_GRENADE ) - upgradeInfo->upgradeIcon = cg_weapons[ WP_GRENADE ].weaponIcon; - else if( ( icon = BG_FindIconForUpgrade( upgradeNum ) ) ) - upgradeInfo->upgradeIcon = trap_R_RegisterShader( icon ); -} - -/* -=============== -CG_InitUpgrades - -Precaches upgrades -=============== -*/ -void CG_InitUpgrades( void ) -{ - int i; - - memset( cg_upgrades, 0, sizeof( cg_upgrades ) ); - - for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) - CG_RegisterUpgrade( i ); -} - - -/* -=============== -CG_ParseWeaponModeSection - -Parse a weapon mode section -=============== -*/ -static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p ) -{ - char *token; - int i; - - // read optional parameters - while( 1 ) - { - token = COM_Parse( text_p ); - - if( !token ) - break; - - if( !Q_stricmp( token, "" ) ) - return qfalse; - - if( !Q_stricmp( token, "missileModel" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileModel = trap_R_RegisterModel( token ); - - if( !wim->missileModel ) - CG_Printf( S_COLOR_RED "ERROR: missile model not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "missileSprite" ) ) - { - int size = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - size = atoi( token ); - - if( size < 0 ) - size = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileSprite = trap_R_RegisterShader( token ); - wim->missileSpriteSize = size; - wim->usesSpriteMissle = qtrue; - - if( !wim->missileSprite ) - CG_Printf( S_COLOR_RED "ERROR: missile sprite not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "missileRotates" ) ) - { - wim->missileRotates = qtrue; - - continue; - } - else if( !Q_stricmp( token, "missileAnimates" ) ) - { - wim->missileAnimates = qtrue; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileAnimStartFrame = atoi( token ); - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileAnimNumFrames = atoi( token ); - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileAnimFrameRate = atoi( token ); - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileAnimLooping = atoi( token ); - - continue; - } - else if( !Q_stricmp( token, "missileParticleSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileParticleSystem = CG_RegisterParticleSystem( token ); - - if( !wim->missileParticleSystem ) - CG_Printf( S_COLOR_RED "ERROR: missile particle system not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "missileTrailSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileTrailSystem = CG_RegisterTrailSystem( token ); - - if( !wim->missileTrailSystem ) - CG_Printf( S_COLOR_RED "ERROR: missile trail system not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "muzzleParticleSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->muzzleParticleSystem = CG_RegisterParticleSystem( token ); - - if( !wim->muzzleParticleSystem ) - CG_Printf( S_COLOR_RED "ERROR: muzzle particle system not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "impactParticleSystem" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->impactParticleSystem = CG_RegisterParticleSystem( token ); - - if( !wim->impactParticleSystem ) - CG_Printf( S_COLOR_RED "ERROR: impact particle system not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "impactMark" ) ) - { - int size = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - size = atoi( token ); - - if( size < 0 ) - size = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->impactMark = trap_R_RegisterShader( token ); - wim->impactMarkSize = size; - - if( !wim->impactMark ) - CG_Printf( S_COLOR_RED "ERROR: impact mark shader not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "impactSound" ) ) - { - int index = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - index = atoi( token ); - - if( index < 0 ) - index = 0; - else if( index > 3 ) - index = 3; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->impactSound[ index ] = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "impactFleshSound" ) ) - { - int index = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - index = atoi( token ); - - if( index < 0 ) - index = 0; - else if( index > 3 ) - index = 3; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->impactFleshSound[ index ] = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "alwaysImpact" ) ) - { - wim->alwaysImpact = qtrue; - - continue; - } - else if( !Q_stricmp( token, "flashDLightColor" ) ) - { - for( i = 0 ; i < 3 ; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->flashDlightColor[ i ] = atof( token ); - } - - continue; - } - else if( !Q_stricmp( token, "continuousFlash" ) ) - { - wim->continuousFlash = qtrue; - - continue; - } - else if( !Q_stricmp( token, "missileDlightColor" ) ) - { - for( i = 0 ; i < 3 ; i++ ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileDlightColor[ i ] = atof( token ); - } - - continue; - } - else if( !Q_stricmp( token, "missileDlight" ) ) - { - int size = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - size = atoi( token ); - - if( size < 0 ) - size = 0; - - wim->missileDlight = size; - - continue; - } - else if( !Q_stricmp( token, "firingSound" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->firingSound = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "missileSound" ) ) - { - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->missileSound = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "flashSound" ) ) - { - int index = 0; - - token = COM_Parse( text_p ); - if( !token ) - break; - - index = atoi( token ); - - if( index < 0 ) - index = 0; - else if( index > 3 ) - index = 3; - - token = COM_Parse( text_p ); - if( !token ) - break; - - wim->flashSound[ index ] = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "}" ) ) - return qtrue; //reached the end of this weapon section - else - { - CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in weapon section\n", token ); - return qfalse; - } - } - - return qfalse; -} - - -/* -====================== -CG_ParseWeaponFile - -Parses a configuration file describing a weapon -====================== -*/ -static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi ) -{ - char *text_p; - int len; - char *token; - char text[ 20000 ]; - fileHandle_t f; - weaponMode_t weaponMode = WPM_NONE; - - // load the file - len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if( len <= 0 ) - return qfalse; - - if( len >= sizeof( text ) - 1 ) - { - CG_Printf( "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( !token ) - break; - - if( !Q_stricmp( token, "" ) ) - break; - - if( !Q_stricmp( token, "{" ) ) - { - if( weaponMode == WPM_NONE ) - { - CG_Printf( S_COLOR_RED "ERROR: weapon mode section started without a declaration\n" ); - return qfalse; - } - else if( !CG_ParseWeaponModeSection( &wi->wim[ weaponMode ], &text_p ) ) - { - CG_Printf( S_COLOR_RED "ERROR: failed to parse weapon mode section\n" ); - return qfalse; - } - - //start parsing ejectors again - weaponMode = WPM_NONE; - - continue; - } - else if( !Q_stricmp( token, "primary" ) ) - { - weaponMode = WPM_PRIMARY; - continue; - } - else if( !Q_stricmp( token, "secondary" ) ) - { - weaponMode = WPM_SECONDARY; - continue; - } - else if( !Q_stricmp( token, "tertiary" ) ) - { - weaponMode = WPM_TERTIARY; - continue; - } - else if( !Q_stricmp( token, "weaponModel" ) ) - { - char path[ MAX_QPATH ]; - - token = COM_Parse( &text_p ); - if( !token ) - break; - - wi->weaponModel = trap_R_RegisterModel( token ); - - if( !wi->weaponModel ) - CG_Printf( S_COLOR_RED "ERROR: weapon model not found %s\n", token ); - - strcpy( path, token ); - COM_StripExtension( path, path ); - strcat( path, "_flash.md3" ); - wi->flashModel = trap_R_RegisterModel( path ); - - strcpy( path, token ); - COM_StripExtension( path, path ); - strcat( path, "_barrel.md3" ); - wi->barrelModel = trap_R_RegisterModel( path ); - - strcpy( path, token ); - COM_StripExtension( path, path ); - strcat( path, "_hand.md3" ); - wi->handsModel = trap_R_RegisterModel( path ); - - if( !wi->handsModel ) - wi->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" ); - - continue; - } - else if( !Q_stricmp( token, "idleSound" ) ) - { - token = COM_Parse( &text_p ); - if( !token ) - break; - - wi->readySound = trap_S_RegisterSound( token, qfalse ); - - continue; - } - else if( !Q_stricmp( token, "icon" ) ) - { - token = COM_Parse( &text_p ); - if( !token ) - break; - - wi->weaponIcon = wi->ammoIcon = trap_R_RegisterShader( token ); - - if( !wi->weaponIcon ) - CG_Printf( S_COLOR_RED "ERROR: weapon icon not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "crosshair" ) ) - { - int size = 0; - - token = COM_Parse( &text_p ); - if( !token ) - break; - - size = atoi( token ); - - if( size < 0 ) - size = 0; - - token = COM_Parse( &text_p ); - if( !token ) - break; - - wi->crossHair = trap_R_RegisterShader( token ); - wi->crossHairSize = size; - - if( !wi->crossHair ) - CG_Printf( S_COLOR_RED "ERROR: weapon crosshair not found %s\n", token ); - - continue; - } - else if( !Q_stricmp( token, "disableIn3rdPerson" ) ) - { - wi->disableIn3rdPerson = qtrue; - - continue; - } - - Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token ); - return qfalse; - } - - return qtrue; -} - -/* -================= -CG_RegisterWeapon -================= -*/ -void CG_RegisterWeapon( int weaponNum ) -{ - weaponInfo_t *weaponInfo; - char path[ MAX_QPATH ]; - vec3_t mins, maxs; - int i; - - weaponInfo = &cg_weapons[ weaponNum ]; - - if( weaponNum == 0 ) - return; - - if( weaponInfo->registered ) - return; - - memset( weaponInfo, 0, sizeof( *weaponInfo ) ); - weaponInfo->registered = qtrue; - - if( !BG_FindNameForWeapon( weaponNum ) ) - CG_Error( "Couldn't find weapon %i", weaponNum ); - - Com_sprintf( path, MAX_QPATH, "models/weapons/%s/weapon.cfg", BG_FindNameForWeapon( weaponNum ) ); - - weaponInfo->humanName = BG_FindHumanNameForWeapon( weaponNum ); - - if( !CG_ParseWeaponFile( path, weaponInfo ) ) - Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path ); - - // calc midpoint for rotation - trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs ); - for( i = 0 ; i < 3 ; i++ ) - weaponInfo->weaponMidpoint[ i ] = mins[ i ] + 0.5 * ( maxs[ i ] - mins[ i ] ); - - //FIXME: - for( i = WPM_NONE + 1; i < WPM_NUM_WEAPONMODES; i++ ) - weaponInfo->wim[ i ].loopFireSound = qfalse; -} - -/* -=============== -CG_InitWeapons - -Precaches weapons -=============== -*/ -void CG_InitWeapons( void ) -{ - int i; - - memset( cg_weapons, 0, sizeof( cg_weapons ) ); - - for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) - CG_RegisterWeapon( i ); - - cgs.media.level2ZapTS = CG_RegisterTrailSystem( "models/weapons/lev2zap/lightning" ); -} - - -/* -======================================================================================== - -VIEW WEAPON - -======================================================================================== -*/ - -/* -================= -CG_MapTorsoToWeaponFrame - -================= -*/ -static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame ) -{ - - // change weapon - if( frame >= ci->animations[ TORSO_DROP ].firstFrame && - frame < ci->animations[ TORSO_DROP ].firstFrame + 9 ) - return frame - ci->animations[ TORSO_DROP ].firstFrame + 6; - - // stand attack - if( frame >= ci->animations[ TORSO_ATTACK ].firstFrame && - frame < ci->animations[ TORSO_ATTACK ].firstFrame + 6 ) - return 1 + frame - ci->animations[ TORSO_ATTACK ].firstFrame; - - // stand attack 2 - if( frame >= ci->animations[ TORSO_ATTACK2 ].firstFrame && - frame < ci->animations[ TORSO_ATTACK2 ].firstFrame + 6 ) - return 1 + frame - ci->animations[ TORSO_ATTACK2 ].firstFrame; - - return 0; -} - - -/* -============== -CG_CalculateWeaponPosition -============== -*/ -static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) -{ - float scale; - int delta; - float fracsin; - float bob; - - VectorCopy( cg.refdef.vieworg, origin ); - VectorCopy( cg.refdefViewAngles, angles ); - - // on odd legs, invert some angles - if( cg.bobcycle & 1 ) - scale = -cg.xyspeed; - else - scale = cg.xyspeed; - - // gun angles from bobbing - //TA: bob amount is class dependant - bob = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ); - - if( bob != 0 ) - { - angles[ ROLL ] += scale * cg.bobfracsin * 0.005; - angles[ YAW ] += scale * cg.bobfracsin * 0.01; - angles[ PITCH ] += cg.xyspeed * cg.bobfracsin * 0.005; - } - - // drop the weapon when landing - if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ) ) - { - delta = cg.time - cg.landTime; - if( delta < LAND_DEFLECT_TIME ) - origin[ 2 ] += cg.landChange*0.25 * delta / LAND_DEFLECT_TIME; - else if( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) - origin[ 2 ] += cg.landChange*0.25 * - ( LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta ) / LAND_RETURN_TIME; - - // idle drift - scale = cg.xyspeed + 40; - fracsin = sin( cg.time * 0.001 ); - angles[ ROLL ] += scale * fracsin * 0.01; - angles[ YAW ] += scale * fracsin * 0.01; - angles[ PITCH ] += scale * fracsin * 0.01; - } -} - - -/* -====================== -CG_MachinegunSpinAngle -====================== -*/ -#define SPIN_SPEED 0.9 -#define COAST_TIME 1000 -static float CG_MachinegunSpinAngle( centity_t *cent ) -{ - int delta; - float angle; - float speed; - - delta = cg.time - cent->pe.barrelTime; - if( cent->pe.barrelSpinning ) - angle = cent->pe.barrelAngle + delta * SPIN_SPEED; - else - { - if( delta > COAST_TIME ) - delta = COAST_TIME; - - speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME ); - angle = cent->pe.barrelAngle + delta * speed; - } - - if( cent->pe.barrelSpinning == !( cent->currentState.eFlags & EF_FIRING ) ) - { - cent->pe.barrelTime = cg.time; - cent->pe.barrelAngle = AngleMod( angle ); - cent->pe.barrelSpinning = !!( cent->currentState.eFlags & EF_FIRING ); - //TA: um? - } - - return angle; -} - - -/* -============= -CG_AddPlayerWeapon - -Used for both the view weapon (ps is valid) and the world modelother character models (ps is NULL) -The main player will have this called for BOTH cases, so effects like light and -sound should only be done on the world model case. -============= -*/ -void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent ) -{ - refEntity_t gun; - refEntity_t barrel; - refEntity_t flash; - vec3_t angles; - weapon_t weaponNum; - weaponMode_t weaponMode; - weaponInfo_t *weapon; - qboolean noGunModel; - qboolean firing; - - weaponNum = cent->currentState.weapon; - weaponMode = cent->currentState.generic1; - - if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) - weaponMode = WPM_PRIMARY; - - if( ( ( cent->currentState.eFlags & EF_FIRING ) && weaponMode == WPM_PRIMARY ) || - ( ( cent->currentState.eFlags & EF_FIRING2 ) && weaponMode == WPM_SECONDARY ) || - ( ( cent->currentState.eFlags & EF_FIRING3 ) && weaponMode == WPM_TERTIARY ) ) - firing = qtrue; - else - firing = qfalse; - - CG_RegisterWeapon( weaponNum ); - weapon = &cg_weapons[ weaponNum ]; - - // add the weapon - memset( &gun, 0, sizeof( gun ) ); - VectorCopy( parent->lightingOrigin, gun.lightingOrigin ); - gun.shadowPlane = parent->shadowPlane; - gun.renderfx = parent->renderfx; - - // set custom shading for railgun refire rate - if( ps ) - { - gun.shaderRGBA[ 0 ] = 255; - gun.shaderRGBA[ 1 ] = 255; - gun.shaderRGBA[ 2 ] = 255; - gun.shaderRGBA[ 3 ] = 255; - - //set weapon[1/2]Time when respective buttons change state - if( cg.weapon1Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING ) ) - { - cg.weapon1Time = cg.time; - cg.weapon1Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING ); - } - - if( cg.weapon2Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING2 ) ) - { - cg.weapon2Time = cg.time; - cg.weapon2Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING2 ); - } - - if( cg.weapon3Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING3 ) ) - { - cg.weapon3Time = cg.time; - cg.weapon3Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING3 ); - } - } - - gun.hModel = weapon->weaponModel; - - noGunModel = ( ( !ps || cg.renderingThirdPerson ) && weapon->disableIn3rdPerson ) || !gun.hModel; - - if( !ps ) - { - // add weapon ready sound - if( firing && weapon->wim[ weaponMode ].firingSound ) - { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - weapon->wim[ weaponMode ].firingSound ); - } - else if( weapon->readySound ) - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound ); - } - - if( !noGunModel ) - { - CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" ); - - trap_R_AddRefEntityToScene( &gun ); - - // add the spinning barrel - if( weapon->barrelModel ) - { - memset( &barrel, 0, sizeof( barrel ) ); - VectorCopy( parent->lightingOrigin, barrel.lightingOrigin ); - barrel.shadowPlane = parent->shadowPlane; - barrel.renderfx = parent->renderfx; - - barrel.hModel = weapon->barrelModel; - angles[ YAW ] = 0; - angles[ PITCH ] = 0; - angles[ ROLL ] = CG_MachinegunSpinAngle( cent ); - AnglesToAxis( angles, barrel.axis ); - - CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" ); - - trap_R_AddRefEntityToScene( &barrel ); - } - } - - if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) - { - if( ps || cg.renderingThirdPerson || - cent->currentState.number != cg.predictedPlayerState.clientNum ) - { - if( noGunModel ) - CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); - else - CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" ); - } - - //if the PS is infinite disable it when not firing - if( !firing && CG_IsParticleSystemInfinite( cent->muzzlePS ) ) - CG_DestroyParticleSystem( ¢->muzzlePS ); - } - - // add the flash - if( !weapon->wim[ weaponMode ].continuousFlash || !firing ) - { - // impulse flash - if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ) - return; - } - - memset( &flash, 0, sizeof( flash ) ); - VectorCopy( parent->lightingOrigin, flash.lightingOrigin ); - flash.shadowPlane = parent->shadowPlane; - flash.renderfx = parent->renderfx; - - flash.hModel = weapon->flashModel; - if( flash.hModel ) - { - angles[ YAW ] = 0; - angles[ PITCH ] = 0; - angles[ ROLL ] = crandom( ) * 10; - AnglesToAxis( angles, flash.axis ); - - if( noGunModel ) - CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_weapon" ); - else - CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash" ); - - trap_R_AddRefEntityToScene( &flash ); - } - - if( ps || cg.renderingThirdPerson || - cent->currentState.number != cg.predictedPlayerState.clientNum ) - { - if( weapon->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger ) - { - cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->wim[ weaponMode ].muzzleParticleSystem ); - - if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) - { - if( noGunModel ) - CG_SetAttachmentTag( ¢->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" ); - else - CG_SetAttachmentTag( ¢->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" ); - - CG_SetAttachmentCent( ¢->muzzlePS->attachment, cent ); - CG_AttachToTag( ¢->muzzlePS->attachment ); - } - - cent->muzzlePsTrigger = qfalse; - } - - // make a dlight for the flash - if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] || - weapon->wim[ weaponMode ].flashDlightColor[ 1 ] || - weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ) - { - trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ), - weapon->wim[ weaponMode ].flashDlightColor[ 0 ], - weapon->wim[ weaponMode ].flashDlightColor[ 1 ], - weapon->wim[ weaponMode ].flashDlightColor[ 2 ] ); - } - } -} - -/* -============== -CG_AddViewWeapon - -Add the weapon, and flash for the player's view -============== -*/ -void CG_AddViewWeapon( playerState_t *ps ) -{ - refEntity_t hand; - centity_t *cent; - clientInfo_t *ci; - float fovOffset; - vec3_t angles; - weaponInfo_t *wi; - weapon_t weapon = ps->weapon; - weaponMode_t weaponMode = ps->generic1; - - if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) - weaponMode = WPM_PRIMARY; - - CG_RegisterWeapon( weapon ); - wi = &cg_weapons[ weapon ]; - cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum]; - - if( ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) || - ( ps->stats[ STAT_STATE ] & SS_INFESTING ) || - ( ps->stats[ STAT_STATE ] & SS_HOVELING ) ) - return; - - //TA: no weapon carried - can't draw it - if( weapon == WP_NONE ) - return; - - if( ps->pm_type == PM_INTERMISSION ) - return; - - //TA: draw a prospective buildable infront of the player - if( ( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) > BA_NONE ) - CG_GhostBuildable( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ); - - if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 ) - { - if( ps->stats[ STAT_MISC ] > ( LCANNON_TOTAL_CHARGE - ( LCANNON_TOTAL_CHARGE / 3 ) ) ) - trap_S_AddLoopingSound( ps->clientNum, ps->origin, vec3_origin, cgs.media.lCannonWarningSound ); - } - - // no gun if in third person view - if( cg.renderingThirdPerson ) - return; - - // allow the gun to be completely removed - if( !cg_drawGun.integer ) - { - vec3_t origin; - - VectorCopy( cg.refdef.vieworg, origin ); - VectorMA( origin, -8, cg.refdef.viewaxis[ 2 ], origin ); - - if( cent->muzzlePS ) - CG_SetAttachmentPoint( ¢->muzzlePS->attachment, origin ); - - //check for particle systems - if( wi->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger ) - { - cent->muzzlePS = CG_SpawnNewParticleSystem( wi->wim[ weaponMode ].muzzleParticleSystem ); - - if( CG_IsParticleSystemValid( ¢->muzzlePS ) ) - { - CG_SetAttachmentPoint( ¢->muzzlePS->attachment, origin ); - CG_SetAttachmentCent( ¢->muzzlePS->attachment, cent ); - CG_AttachToPoint( ¢->muzzlePS->attachment ); - } - cent->muzzlePsTrigger = qfalse; - } - - return; - } - - // don't draw if testing a gun model - if( cg.testGun ) - return; - - // drop gun lower at higher fov - //if ( cg_fov.integer > 90 ) { - //TA: the client side variable isn't used ( shouldn't iD have done this anyway? ) - if( cg.refdef.fov_y > 90 ) - fovOffset = -0.4 * ( cg.refdef.fov_y - 90 ); - else - fovOffset = 0; - - memset( &hand, 0, sizeof( hand ) ); - - // set up gun position - CG_CalculateWeaponPosition( hand.origin, angles ); - - VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[ 0 ], hand.origin ); - VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[ 1 ], hand.origin ); - VectorMA( hand.origin, ( cg_gun_z.value + fovOffset ), cg.refdef.viewaxis[ 2 ], hand.origin ); - - if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 ) - { - float fraction = (float)ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE; - - VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 0 ], hand.origin ); - VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 1 ], hand.origin ); - } - - AnglesToAxis( angles, hand.axis ); - - // map torso animations to weapon animations - if( cg_gun_frame.integer ) - { - // development tool - hand.frame = hand.oldframe = cg_gun_frame.integer; - hand.backlerp = 0; - } - else - { - // get clientinfo for animation map - ci = &cgs.clientinfo[ cent->currentState.clientNum ]; - hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame ); - hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame ); - hand.backlerp = cent->pe.torso.backlerp; - } - - hand.hModel = wi->handsModel; - hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT; - - // add everything onto the hand - CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity ); -} - -/* -============================================================================== - -WEAPON SELECTION - -============================================================================== -*/ - -/* -=============== -CG_WeaponSelectable -=============== -*/ -static qboolean CG_WeaponSelectable( weapon_t weapon ) -{ - //int ammo, clips; - // - //BG_UnpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips ); - // - //TA: this is a pain in the ass - //if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( i ) ) - // return qfalse; - - if( !BG_InventoryContainsWeapon( weapon, cg.snap->ps.stats ) ) - return qfalse; - - return qtrue; -} - - -/* -=============== -CG_UpgradeSelectable -=============== -*/ -static qboolean CG_UpgradeSelectable( upgrade_t upgrade ) -{ - if( !BG_InventoryContainsUpgrade( upgrade, cg.snap->ps.stats ) ) - return qfalse; - - return qtrue; -} - - -#define ICON_BORDER 4 - -/* -=================== -CG_DrawItemSelect -=================== -*/ -void CG_DrawItemSelect( rectDef_t *rect, vec4_t color ) -{ - int i; - int x = rect->x; - int y = rect->y; - int width = rect->w; - int height = rect->h; - int iconsize; - int items[ 64 ]; - int numItems = 0, selectedItem = 0; - int length; - int selectWindow; - qboolean vertical; - centity_t *cent; - playerState_t *ps; - - cent = &cg_entities[ cg.snap->ps.clientNum ]; - ps = &cg.snap->ps; - - // don't display if dead - if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 ) - return; - - if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) ) - { - // first make sure that whatever it selected is actually selectable - if( cg.weaponSelect <= 32 && !CG_WeaponSelectable( cg.weaponSelect ) ) - CG_NextWeapon_f( ); - else if( cg.weaponSelect > 32 && !CG_UpgradeSelectable( cg.weaponSelect ) ) - CG_NextWeapon_f( ); - } - - // showing weapon select clears pickup item display, but not the blend blob - cg.itemPickupTime = 0; - - if( height > width ) - { - vertical = qtrue; - iconsize = width; - length = height / width; - } - else if( height <= width ) - { - vertical = qfalse; - iconsize = height; - length = width / height; - } - - selectWindow = length / 2; - - for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) - { - if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) - continue; - - if( i == cg.weaponSelect ) - selectedItem = numItems; - - CG_RegisterWeapon( i ); - items[ numItems ] = i; - numItems++; - } - - for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) - { - if( !BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) ) - continue; - - if( i == cg.weaponSelect - 32 ) - selectedItem = numItems; - - CG_RegisterUpgrade( i ); - items[ numItems ] = i + 32; - numItems++; - } - - for( i = 0; i < length; i++ ) - { - int displacement = i - selectWindow; - int item = displacement + selectedItem; - - if( ( item >= 0 ) && ( item < numItems ) ) - { - trap_R_SetColor( color ); - - if( items[ item ] <= 32 ) - CG_DrawPic( x, y, iconsize, iconsize, cg_weapons[ items[ item ] ].weaponIcon ); - else if( items[ item ] > 32 ) - CG_DrawPic( x, y, iconsize, iconsize, cg_upgrades[ items[ item ] - 32 ].upgradeIcon ); - - trap_R_SetColor( NULL ); - -/* if( displacement == 0 ) - CG_DrawPic( x, y, iconsize, iconsize, cgs.media.selectShader );*/ - } - - if( vertical ) - y += iconsize; - else - x += iconsize; - } -} - - -/* -=================== -CG_DrawItemSelectText -=================== -*/ -void CG_DrawItemSelectText( rectDef_t *rect, float scale, int textStyle ) -{ - int x, w; - char *name; - float *color; - - color = CG_FadeColor( cg.weaponSelectTime, WEAPON_SELECT_TIME ); - if( !color ) - return; - - trap_R_SetColor( color ); - - // draw the selected name - if( cg.weaponSelect <= 32 ) - { - if( cg_weapons[ cg.weaponSelect ].registered && - BG_InventoryContainsWeapon( cg.weaponSelect, cg.snap->ps.stats ) ) - { - if( ( name = cg_weapons[ cg.weaponSelect ].humanName ) ) - { - w = CG_Text_Width( name, scale, 0 ); - x = rect->x + rect->w / 2; - CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); - } - } - } - else if( cg.weaponSelect > 32 ) - { - if( cg_upgrades[ cg.weaponSelect - 32 ].registered && - BG_InventoryContainsUpgrade( cg.weaponSelect - 32, cg.snap->ps.stats ) ) - { - if( ( name = cg_upgrades[ cg.weaponSelect - 32 ].humanName ) ) - { - w = CG_Text_Width( name, scale, 0 ); - x = rect->x + rect->w / 2; - CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); - } - } - } - - trap_R_SetColor( NULL ); -} - - -/* -=============== -CG_NextWeapon_f -=============== -*/ -void CG_NextWeapon_f( void ) -{ - int i; - int original; - - if( !cg.snap ) - return; - - if( cg.snap->ps.pm_flags & PMF_FOLLOW ) - { - trap_SendClientCommand( "followprev\n" ); - return; - } - - cg.weaponSelectTime = cg.time; - original = cg.weaponSelect; - - for( i = 0; i < 64; i++ ) - { - cg.weaponSelect++; - if( cg.weaponSelect == 64 ) - cg.weaponSelect = 0; - - if( cg.weaponSelect <= 32 ) - { - if( CG_WeaponSelectable( cg.weaponSelect ) ) - break; - } - else if( cg.weaponSelect > 32 ) - { - if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) - break; - } - } - - if( i == 64 ) - cg.weaponSelect = original; -} - -/* -=============== -CG_PrevWeapon_f -=============== -*/ -void CG_PrevWeapon_f( void ) -{ - int i; - int original; - - if( !cg.snap ) - return; - - if( cg.snap->ps.pm_flags & PMF_FOLLOW ) - { - trap_SendClientCommand( "follownext\n" ); - return; - } - - cg.weaponSelectTime = cg.time; - original = cg.weaponSelect; - - for( i = 0; i < 64; i++ ) - { - cg.weaponSelect--; - if( cg.weaponSelect == -1 ) - cg.weaponSelect = 63; - - if( cg.weaponSelect <= 32 ) - { - if( CG_WeaponSelectable( cg.weaponSelect ) ) - break; - } - else if( cg.weaponSelect > 32 ) - { - if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) ) - break; - } - } - - if( i == 64 ) - cg.weaponSelect = original; -} - -/* -=============== -CG_Weapon_f -=============== -*/ -void CG_Weapon_f( void ) -{ - int num; - - if( !cg.snap ) - return; - - if( cg.snap->ps.pm_flags & PMF_FOLLOW ) - return; - - num = atoi( CG_Argv( 1 ) ); - - if( num < 1 || num > 31 ) - return; - - cg.weaponSelectTime = cg.time; - - if( !BG_InventoryContainsWeapon( num, cg.snap->ps.stats ) ) - return; // don't have the weapon - - cg.weaponSelect = num; -} - - -/* -=================================================================================================== - -WEAPON EVENTS - -=================================================================================================== -*/ - -/* -================ -CG_FireWeapon - -Caused by an EV_FIRE_WEAPON event -================ -*/ -void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode ) -{ - entityState_t *es; - int c; - weaponInfo_t *wi; - weapon_t weaponNum; - - es = ¢->currentState; - - weaponNum = es->weapon; - - if( weaponNum == WP_NONE ) - return; - - if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) - weaponMode = WPM_PRIMARY; - - if( weaponNum >= WP_NUM_WEAPONS ) - { - CG_Error( "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" ); - return; - } - - wi = &cg_weapons[ weaponNum ]; - - // mark the entity as muzzle flashing, so when it is added it will - // append the flash to the weapon model - cent->muzzleFlashTime = cg.time; - - if( wi->wim[ weaponMode ].muzzleParticleSystem ) - { - if( !CG_IsParticleSystemValid( ¢->muzzlePS ) || - !CG_IsParticleSystemInfinite( cent->muzzlePS ) ) - cent->muzzlePsTrigger = qtrue; - } - - // play a sound - for( c = 0; c < 4; c++ ) - { - if( !wi->wim[ weaponMode ].flashSound[ c ] ) - break; - } - - if( c > 0 ) - { - c = rand( ) % c; - if( wi->wim[ weaponMode ].flashSound[ c ] ) - trap_S_StartSound( NULL, es->number, CHAN_WEAPON, wi->wim[ weaponMode ].flashSound[ c ] ); - } -} - - -/* -================= -CG_MissileHitWall - -Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing -================= -*/ -void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientNum, - vec3_t origin, vec3_t dir, impactSound_t soundType ) -{ - qhandle_t mark = 0; - qhandle_t ps = 0; - int c; - float radius = 1.0f; - weaponInfo_t *weapon = &cg_weapons[ weaponNum ]; - - if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) - weaponMode = WPM_PRIMARY; - - mark = weapon->wim[ weaponMode ].impactMark; - radius = weapon->wim[ weaponMode ].impactMarkSize; - ps = weapon->wim[ weaponMode ].impactParticleSystem; - - if( soundType == IMPACTSOUND_FLESH ) - { - //flesh sound - for( c = 0; c < 4; c++ ) - { - if( !weapon->wim[ weaponMode ].impactFleshSound[ c ] ) - break; - } - - if( c > 0 ) - { - c = rand( ) % c; - if( weapon->wim[ weaponMode ].impactFleshSound[ c ] ) - trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->wim[ weaponMode ].impactFleshSound[ c ] ); - } - } - else - { - //normal sound - for( c = 0; c < 4; c++ ) - { - if( !weapon->wim[ weaponMode ].impactSound[ c ] ) - break; - } - - if( c > 0 ) - { - c = rand( ) % c; - if( weapon->wim[ weaponMode ].impactSound[ c ] ) - trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->wim[ weaponMode ].impactSound[ c ] ); - } - } - - //create impact particle system - if( ps ) - { - particleSystem_t *partSystem = CG_SpawnNewParticleSystem( ps ); - - if( CG_IsParticleSystemValid( &partSystem ) ) - { - CG_SetAttachmentPoint( &partSystem->attachment, origin ); - CG_SetParticleSystemNormal( partSystem, dir ); - CG_AttachToPoint( &partSystem->attachment ); - } - } - - // - // impact mark - // - if( radius > 0.0f ) - CG_ImpactMark( mark, origin, dir, random( ) * 360, 1, 1, 1, 1, qfalse, radius, qfalse ); -} - - -/* -================= -CG_MissileHitPlayer -================= -*/ -void CG_MissileHitPlayer( weapon_t weaponNum, weaponMode_t weaponMode, - vec3_t origin, vec3_t dir, int entityNum ) -{ - vec3_t normal; - weaponInfo_t *weapon = &cg_weapons[ weaponNum ]; - - VectorCopy( dir, normal ); - VectorInverse( normal ); - - CG_Bleed( origin, normal, entityNum ); - - if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES ) - weaponMode = WPM_PRIMARY; - - if( weapon->wim[ weaponMode ].alwaysImpact ) - CG_MissileHitWall( weaponNum, weaponMode, 0, origin, dir, IMPACTSOUND_FLESH ); -} - - -/* -============================================================================ - -BULLETS - -============================================================================ -*/ - - -/* -=============== -CG_Tracer -=============== -*/ -void CG_Tracer( vec3_t source, vec3_t dest ) -{ - vec3_t forward, right; - polyVert_t verts[ 4 ]; - vec3_t line; - float len, begin, end; - vec3_t start, finish; - vec3_t midpoint; - - // tracer - VectorSubtract( dest, source, forward ); - len = VectorNormalize( forward ); - - // start at least a little ways from the muzzle - if( len < 100 ) - return; - - begin = 50 + random( ) * ( len - 60 ); - end = begin + cg_tracerLength.value; - if( end > len ) - end = len; - - VectorMA( source, begin, forward, start ); - VectorMA( source, end, forward, finish ); - - line[ 0 ] = DotProduct( forward, cg.refdef.viewaxis[ 1 ] ); - line[ 1 ] = DotProduct( forward, cg.refdef.viewaxis[ 2 ] ); - - VectorScale( cg.refdef.viewaxis[ 1 ], line[ 1 ], right ); - VectorMA( right, -line[ 0 ], cg.refdef.viewaxis[ 2 ], right ); - VectorNormalize( right ); - - VectorMA( finish, cg_tracerWidth.value, right, verts[ 0 ].xyz ); - verts[ 0 ].st[ 0 ] = 0; - verts[ 0 ].st[ 1 ] = 1; - verts[ 0 ].modulate[ 0 ] = 255; - verts[ 0 ].modulate[ 1 ] = 255; - verts[ 0 ].modulate[ 2 ] = 255; - verts[ 0 ].modulate[ 3 ] = 255; - - VectorMA( finish, -cg_tracerWidth.value, right, verts[ 1 ].xyz ); - verts[ 1 ].st[ 0 ] = 1; - verts[ 1 ].st[ 1 ] = 0; - verts[ 1 ].modulate[ 0 ] = 255; - verts[ 1 ].modulate[ 1 ] = 255; - verts[ 1 ].modulate[ 2 ] = 255; - verts[ 1 ].modulate[ 3 ] = 255; - - VectorMA( start, -cg_tracerWidth.value, right, verts[ 2 ].xyz ); - verts[ 2 ].st[ 0 ] = 1; - verts[ 2 ].st[ 1 ] = 1; - verts[ 2 ].modulate[ 0 ] = 255; - verts[ 2 ].modulate[ 1 ] = 255; - verts[ 2 ].modulate[ 2 ] = 255; - verts[ 2 ].modulate[ 3 ] = 255; - - VectorMA( start, cg_tracerWidth.value, right, verts[ 3 ].xyz ); - verts[ 3 ].st[ 0 ] = 0; - verts[ 3 ].st[ 1 ] = 0; - verts[ 3 ].modulate[ 0 ] = 255; - verts[ 3 ].modulate[ 1 ] = 255; - verts[ 3 ].modulate[ 2 ] = 255; - verts[ 3 ].modulate[ 3 ] = 255; - - trap_R_AddPolyToScene( cgs.media.tracerShader, 4, verts ); - - midpoint[ 0 ] = ( start[ 0 ] + finish[ 0 ] ) * 0.5; - midpoint[ 1 ] = ( start[ 1 ] + finish[ 1 ] ) * 0.5; - midpoint[ 2 ] = ( start[ 2 ] + finish[ 2 ] ) * 0.5; - - // add the tracer sound - trap_S_StartSound( midpoint, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.tracerSound ); -} - - -/* -====================== -CG_CalcMuzzlePoint -====================== -*/ -static qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle ) -{ - vec3_t forward; - centity_t *cent; - int anim; - - if( entityNum == cg.snap->ps.clientNum ) - { - VectorCopy( cg.snap->ps.origin, muzzle ); - muzzle[ 2 ] += cg.snap->ps.viewheight; - AngleVectors( cg.snap->ps.viewangles, forward, NULL, NULL ); - VectorMA( muzzle, 14, forward, muzzle ); - return qtrue; - } - - cent = &cg_entities[entityNum]; - - if( !cent->currentValid ) - return qfalse; - - VectorCopy( cent->currentState.pos.trBase, muzzle ); - - AngleVectors( cent->currentState.apos.trBase, forward, NULL, NULL ); - anim = cent->currentState.legsAnim & ~ANIM_TOGGLEBIT; - - if( anim == LEGS_WALKCR || anim == LEGS_IDLECR ) - muzzle[ 2 ] += CROUCH_VIEWHEIGHT; - else - muzzle[ 2 ] += DEFAULT_VIEWHEIGHT; - - VectorMA( muzzle, 14, forward, muzzle ); - - return qtrue; - -} - - -/* -====================== -CG_Bullet - -Renders bullet effects. -====================== -*/ -void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ) -{ - vec3_t start; - - // if the shooter is currently valid, calc a source point and possibly - // do trail effects - if( sourceEntityNum >= 0 && cg_tracerChance.value > 0 ) - { - if( CG_CalcMuzzlePoint( sourceEntityNum, start ) ) - { - // draw a tracer - if( random( ) < cg_tracerChance.value ) - CG_Tracer( start, end ); - } - } - - // impact splash and mark - if( flesh ) - CG_Bleed( end, normal, fleshEntityNum ); - else - CG_MissileHitWall( WP_MACHINEGUN, WPM_PRIMARY, 0, end, normal, IMPACTSOUND_DEFAULT ); -} - -/* -============================================================================ - -SHOTGUN TRACING - -============================================================================ -*/ - -/* -================ -CG_ShotgunPattern - -Perform the same traces the server did to locate the -hit splashes -================ -*/ -static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum ) -{ - int i; - float r, u; - vec3_t end; - vec3_t forward, right, up; - trace_t tr; - - // derive the right and up vectors from the forward vector, because - // the client won't have any other information - VectorNormalize2( origin2, forward ); - PerpendicularVector( right, forward ); - CrossProduct( forward, right, up ); - - // generate the "random" spread pattern - for( i = 0; i < SHOTGUN_PELLETS; i++ ) - { - r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; - u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16; - VectorMA( origin, 8192 * 16, forward, end ); - VectorMA( end, r, right, end ); - VectorMA( end, u, up, end ); - - CG_Trace( &tr, origin, NULL, NULL, end, otherEntNum, MASK_SHOT ); - - if( !( tr.surfaceFlags & SURF_NOIMPACT ) ) - { - if( cg_entities[ tr.entityNum ].currentState.eType == ET_PLAYER ) - CG_MissileHitPlayer( WP_SHOTGUN, WPM_PRIMARY, tr.endpos, tr.plane.normal, tr.entityNum ); - else if( tr.surfaceFlags & SURF_METALSTEPS ) - CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL ); - else - CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT ); - } - } -} - -/* -============== -CG_ShotgunFire -============== -*/ -void CG_ShotgunFire( entityState_t *es ) -{ - vec3_t v; - - VectorSubtract( es->origin2, es->pos.trBase, v ); - VectorNormalize( v ); - VectorScale( v, 32, v ); - VectorAdd( es->pos.trBase, v, v ); - - CG_ShotgunPattern( es->pos.trBase, es->origin2, es->eventParm, es->otherEntityNum ); -} - diff --git a/mod/src/cgame/tr_types.h b/mod/src/cgame/tr_types.h deleted file mode 100644 index 26240a2f..00000000 --- a/mod/src/cgame/tr_types.h +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// - -/* - * 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. - */ - -#ifndef __TR_TYPES_H -#define __TR_TYPES_H - - -#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces -#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing - -// renderfx flags -#define RF_MINLIGHT 1 // allways have some light (viewmodel, some items) -#define RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites) -#define RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob) -#define RF_DEPTHHACK 8 // for view weapon Z crunching -#define RF_NOSHADOW 64 // don't add stencil shadows - -#define RF_LIGHTING_ORIGIN 128 // use refEntity->lightingOrigin instead of refEntity->origin - // for lighting. This allows entities to sink into the floor - // with their origin going solid, and allows all parts of a - // player to get the same lighting -#define RF_SHADOW_PLANE 256 // use refEntity->shadowPlane -#define RF_WRAP_FRAMES 512 // mod the model frames by the maxframes to allow continuous - // animation without needing to know the frame count - -// refdef flags -#define RDF_NOWORLDMODEL 1 // used for player configuration screen -#define RDF_HYPERSPACE 4 // teleportation effect - -typedef struct -{ - vec3_t xyz; - float st[ 2 ]; - byte modulate[ 4 ]; -} polyVert_t; - -typedef struct poly_s -{ - qhandle_t hShader; - int numVerts; - polyVert_t *verts; -} poly_t; - -typedef enum -{ - RT_MODEL, - RT_POLY, - RT_SPRITE, - RT_BEAM, - RT_RAIL_CORE, - RT_RAIL_RINGS, - RT_LIGHTNING, - RT_PORTALSURFACE, // doesn't draw anything, just info for portals - - RT_MAX_REF_ENTITY_TYPE -} refEntityType_t; - -typedef struct -{ - refEntityType_t reType; - int renderfx; - - qhandle_t hModel; // opaque type outside refresh - - // most recent data - vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN) - float shadowPlane; // projection shadows go here, stencils go slightly lower - - vec3_t axis[ 3 ]; // rotation vectors - qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale - float origin[ 3 ]; // also used as MODEL_BEAM's "from" - int frame; // also used as MODEL_BEAM's diameter - - // previous data for frame interpolation - float oldorigin[ 3 ]; // also used as MODEL_BEAM's "to" - int oldframe; - float backlerp; // 0.0 = current, 1.0 = old - - // texturing - int skinNum; // inline skin index - qhandle_t customSkin; // NULL for default skin - qhandle_t customShader; // use one image for the entire thing - - // misc - byte shaderRGBA[ 4 ]; // colors used by rgbgen entity shaders - float shaderTexCoord[ 2 ];// texture coordinates used by tcMod entity modifiers - float shaderTime; // subtracted from refdef time to control effect start times - - // extra sprite information - float radius; - float rotation; -} refEntity_t; - - -#define MAX_RENDER_STRINGS 8 -#define MAX_RENDER_STRING_LENGTH 32 - -typedef struct -{ - int x, y, width, height; - float fov_x, fov_y; - vec3_t vieworg; - vec3_t viewaxis[ 3 ]; // transformation matrix - - // time in milliseconds for shader effects and other time dependent rendering issues - int time; - - int rdflags; // RDF_NOWORLDMODEL, etc - - // 1 bits will prevent the associated area from rendering at all - byte areamask[ MAX_MAP_AREA_BYTES ]; - - // text messages for deform text shaders - char text[ MAX_RENDER_STRINGS ][ MAX_RENDER_STRING_LENGTH ]; -} refdef_t; - - -typedef enum -{ - STEREO_CENTER, - STEREO_LEFT, - STEREO_RIGHT -} stereoFrame_t; - - -/* -** glconfig_t -** -** Contains variables specific to the OpenGL configuration -** being run right now. These are constant once the OpenGL -** subsystem is initialized. -*/ -typedef enum -{ - TC_NONE, - TC_S3TC -} textureCompression_t; - -typedef enum -{ - GLDRV_ICD, // driver is integrated with window system - // WARNING: there are tests that check for - // > GLDRV_ICD for minidriverness, so this - // should always be the lowest value in this - // enum set - GLDRV_STANDALONE, // driver is a non-3Dfx standalone driver - GLDRV_VOODOO // driver is a 3Dfx standalone driver -} glDriverType_t; - -typedef enum -{ - GLHW_GENERIC, // where everthing works the way it should - GLHW_3DFX_2D3D, // Voodoo Banshee or Voodoo3, relevant since if this is - // the hardware type then there can NOT exist a secondary - // display adapter - GLHW_RIVA128, // where you can't interpolate alpha - GLHW_RAGEPRO, // where you can't modulate alpha on alpha textures - GLHW_PERMEDIA2 // where you don't have src*dst -} glHardwareType_t; - -typedef struct -{ - char renderer_string[ MAX_STRING_CHARS ]; - char vendor_string[ MAX_STRING_CHARS ]; - char version_string[ MAX_STRING_CHARS ]; - char extensions_string[ BIG_INFO_STRING ]; - - int maxTextureSize; // queried from GL - int maxActiveTextures; // multitexture ability - - int colorBits, depthBits, stencilBits; - - glDriverType_t driverType; - glHardwareType_t hardwareType; - - qboolean deviceSupportsGamma; - textureCompression_t textureCompression; - qboolean textureEnvAddAvailable; - - int vidWidth, vidHeight; - - // aspect is the screen's physical width / height, which may be different - // than scrWidth / scrHeight if the pixels are non-square - // normal screens should be 4/3, but wide aspect monitors may be 16/9 - float windowAspect; - - int displayFrequency; - - // synonymous with "does rendering consume the entire screen?", therefore - // a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that - // used CDS. - qboolean isFullscreen; - qboolean stereoEnabled; - qboolean smpActive; // dual processor -} glconfig_t; - - -#if !defined _WIN32 - -#define _3DFX_DRIVER_NAME "libMesaVoodooGL.so" -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=524 -#define OPENGL_DRIVER_NAME "libGL.so.1" - -#else - -#define _3DFX_DRIVER_NAME "3dfxvgl" -#define OPENGL_DRIVER_NAME "opengl32" - -#endif // !defined _WIN32 - - -#endif // __TR_TYPES_H |