Changed line endings to UNIX.
This commit is contained in:
1 parent
7acbb8c956
commit
fc0f4ac57c
52 files changed
+53864
-53864
No files matched your search
+227
-227
@@ -1,227 +1,227 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#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 ) || cent->animPlaying )
|
||||
{
|
||||
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;
|
||||
|
||||
if( !anim.loopFrames )
|
||||
{
|
||||
// add one frame to allow the animation to play the last frame
|
||||
// add another to get it to stop playing at the first frame
|
||||
anim.numFrames += 2;
|
||||
|
||||
if( !cent->animInit )
|
||||
{
|
||||
cent->animInit = qtrue;
|
||||
cent->animPlaying = !( cent->currentState.eFlags & EF_MOVER_STOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cent->animLastState !=
|
||||
!( cent->currentState.eFlags & EF_MOVER_STOP ) )
|
||||
{
|
||||
cent->animPlaying = qtrue;
|
||||
cent->lerpFrame.animationTime = cg.time;
|
||||
cent->lerpFrame.frameTime = cg.time;
|
||||
}
|
||||
}
|
||||
cent->animLastState = !( cent->currentState.eFlags & EF_MOVER_STOP );
|
||||
}
|
||||
|
||||
//run animation
|
||||
CG_AMOAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );
|
||||
|
||||
// add to refresh list
|
||||
trap_R_AddRefEntityToScene(&ent);
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#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 ) || cent->animPlaying )
|
||||
{
|
||||
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;
|
||||
|
||||
if( !anim.loopFrames )
|
||||
{
|
||||
// add one frame to allow the animation to play the last frame
|
||||
// add another to get it to stop playing at the first frame
|
||||
anim.numFrames += 2;
|
||||
|
||||
if( !cent->animInit )
|
||||
{
|
||||
cent->animInit = qtrue;
|
||||
cent->animPlaying = !( cent->currentState.eFlags & EF_MOVER_STOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cent->animLastState !=
|
||||
!( cent->currentState.eFlags & EF_MOVER_STOP ) )
|
||||
{
|
||||
cent->animPlaying = qtrue;
|
||||
cent->lerpFrame.animationTime = cg.time;
|
||||
cent->lerpFrame.frameTime = cg.time;
|
||||
}
|
||||
}
|
||||
cent->animLastState = !( cent->currentState.eFlags & EF_MOVER_STOP );
|
||||
}
|
||||
|
||||
//run animation
|
||||
CG_AMOAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );
|
||||
|
||||
// add to refresh list
|
||||
trap_R_AddRefEntityToScene(&ent);
|
||||
}
|
||||
+404
-404
@@ -1,404 +1,404 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_attachment.c -- an abstract attachment system
|
||||
|
||||
#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;
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_attachment.c -- an abstract attachment system
|
||||
|
||||
#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;
|
||||
}
|
||||
+1423
-1423
File diff suppressed because it is too large.
Load diff
+325
-325
@@ -1,325 +1,325 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_consolecmds.c -- text commands typed in at the local console, or
|
||||
// executed by a key binding
|
||||
|
||||
|
||||
#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 ] );
|
||||
}
|
||||
|
||||
qboolean CG_RequestScores( 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" );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
else
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
extern menuDef_t *menuScoreboard;
|
||||
|
||||
static void CG_scrollScoresDown_f( void )
|
||||
{
|
||||
if( menuScoreboard && cg.scoreBoardShowing )
|
||||
{
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_ALIENTEAM_LIST, qtrue );
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_HUMANTEAM_LIST, qtrue );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void CG_scrollScoresUp_f( void )
|
||||
{
|
||||
if( menuScoreboard && cg.scoreBoardShowing )
|
||||
{
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_ALIENTEAM_LIST, qfalse );
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_HUMANTEAM_LIST, qfalse );
|
||||
}
|
||||
}
|
||||
|
||||
static void CG_ScoresDown_f( void )
|
||||
{
|
||||
if( !cg.showScores )
|
||||
{
|
||||
Menu_SetFeederSelection( menuScoreboard, FEEDER_ALIENTEAM_LIST, 0, NULL );
|
||||
Menu_SetFeederSelection( menuScoreboard, FEEDER_HUMANTEAM_LIST, 0, NULL );
|
||||
}
|
||||
|
||||
if( CG_RequestScores( ) )
|
||||
{
|
||||
// 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 },
|
||||
{ "scoresUp", CG_scrollScoresUp_f },
|
||||
{ "scoresDown", CG_scrollScoresDown_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( "advanceMapRotation" );
|
||||
trap_AddCommand( "alienWin" );
|
||||
trap_AddCommand( "humanWin" );
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_consolecmds.c -- text commands typed in at the local console, or
|
||||
// executed by a key binding
|
||||
|
||||
|
||||
#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 ] );
|
||||
}
|
||||
|
||||
qboolean CG_RequestScores( 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" );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
else
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
extern menuDef_t *menuScoreboard;
|
||||
|
||||
static void CG_scrollScoresDown_f( void )
|
||||
{
|
||||
if( menuScoreboard && cg.scoreBoardShowing )
|
||||
{
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_ALIENTEAM_LIST, qtrue );
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_HUMANTEAM_LIST, qtrue );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void CG_scrollScoresUp_f( void )
|
||||
{
|
||||
if( menuScoreboard && cg.scoreBoardShowing )
|
||||
{
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_ALIENTEAM_LIST, qfalse );
|
||||
Menu_ScrollFeeder( menuScoreboard, FEEDER_HUMANTEAM_LIST, qfalse );
|
||||
}
|
||||
}
|
||||
|
||||
static void CG_ScoresDown_f( void )
|
||||
{
|
||||
if( !cg.showScores )
|
||||
{
|
||||
Menu_SetFeederSelection( menuScoreboard, FEEDER_ALIENTEAM_LIST, 0, NULL );
|
||||
Menu_SetFeederSelection( menuScoreboard, FEEDER_HUMANTEAM_LIST, 0, NULL );
|
||||
}
|
||||
|
||||
if( CG_RequestScores( ) )
|
||||
{
|
||||
// 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 },
|
||||
{ "scoresUp", CG_scrollScoresUp_f },
|
||||
{ "scoresDown", CG_scrollScoresDown_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( "advanceMapRotation" );
|
||||
trap_AddCommand( "alienWin" );
|
||||
trap_AddCommand( "humanWin" );
|
||||
}
|
||||
+3524
-3524
File diff suppressed because it is too large.
Load diff
+378
-378
@@ -1,378 +1,378 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_WorldToScreen
|
||||
================
|
||||
*/
|
||||
qboolean CG_WorldToScreen( vec3_t point, float *x, float *y )
|
||||
{
|
||||
vec3_t trans;
|
||||
float xc, yc;
|
||||
float px, py;
|
||||
float z;
|
||||
|
||||
px = tan( cg.refdef.fov_x * M_PI / 360.0 );
|
||||
py = tan( cg.refdef.fov_y * M_PI / 360.0 );
|
||||
|
||||
VectorSubtract( point, cg.refdef.vieworg, trans );
|
||||
|
||||
xc = 640.0f / 2.0f;
|
||||
yc = 480.0f / 2.0f;
|
||||
|
||||
z = DotProduct( trans, cg.refdef.viewaxis[ 0 ] );
|
||||
if( z <= 0.001f )
|
||||
return qfalse;
|
||||
|
||||
if( x )
|
||||
*x = xc - DotProduct( trans, cg.refdef.viewaxis[ 1 ] ) * xc / ( z * px );
|
||||
|
||||
if( y )
|
||||
*y = yc - DotProduct( trans, cg.refdef.viewaxis[ 2 ] ) * yc / ( z * py );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_KeyBinding
|
||||
================
|
||||
*/
|
||||
char *CG_KeyBinding( const char *bind )
|
||||
{
|
||||
static char key[ 32 ];
|
||||
char bindbuff[ MAX_CVAR_VALUE_STRING ];
|
||||
int i;
|
||||
|
||||
key[ 0 ] = '\0';
|
||||
// NOTE: change K_LAST_KEY to MAX_KEYS for full key support (eventually)
|
||||
for( i = 0; i < K_LAST_KEY; i++ )
|
||||
{
|
||||
trap_Key_GetBindingBuf( i, bindbuff, sizeof( bindbuff ) );
|
||||
if( !Q_stricmp( bindbuff, bind ) )
|
||||
{
|
||||
trap_Key_KeynumToStringBuf( i, key, sizeof( key ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !key[ 0 ] )
|
||||
{
|
||||
Q_strncpyz( key, "\\", sizeof( key ) );
|
||||
Q_strcat( key, sizeof( key ), bind );
|
||||
}
|
||||
return key;
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_WorldToScreen
|
||||
================
|
||||
*/
|
||||
qboolean CG_WorldToScreen( vec3_t point, float *x, float *y )
|
||||
{
|
||||
vec3_t trans;
|
||||
float xc, yc;
|
||||
float px, py;
|
||||
float z;
|
||||
|
||||
px = tan( cg.refdef.fov_x * M_PI / 360.0 );
|
||||
py = tan( cg.refdef.fov_y * M_PI / 360.0 );
|
||||
|
||||
VectorSubtract( point, cg.refdef.vieworg, trans );
|
||||
|
||||
xc = 640.0f / 2.0f;
|
||||
yc = 480.0f / 2.0f;
|
||||
|
||||
z = DotProduct( trans, cg.refdef.viewaxis[ 0 ] );
|
||||
if( z <= 0.001f )
|
||||
return qfalse;
|
||||
|
||||
if( x )
|
||||
*x = xc - DotProduct( trans, cg.refdef.viewaxis[ 1 ] ) * xc / ( z * px );
|
||||
|
||||
if( y )
|
||||
*y = yc - DotProduct( trans, cg.refdef.viewaxis[ 2 ] ) * yc / ( z * py );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_KeyBinding
|
||||
================
|
||||
*/
|
||||
char *CG_KeyBinding( const char *bind )
|
||||
{
|
||||
static char key[ 32 ];
|
||||
char bindbuff[ MAX_CVAR_VALUE_STRING ];
|
||||
int i;
|
||||
|
||||
key[ 0 ] = '\0';
|
||||
// NOTE: change K_LAST_KEY to MAX_KEYS for full key support (eventually)
|
||||
for( i = 0; i < K_LAST_KEY; i++ )
|
||||
{
|
||||
trap_Key_GetBindingBuf( i, bindbuff, sizeof( bindbuff ) );
|
||||
if( !Q_stricmp( bindbuff, bind ) )
|
||||
{
|
||||
trap_Key_KeynumToStringBuf( i, key, sizeof( key ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !key[ 0 ] )
|
||||
{
|
||||
Q_strncpyz( key, "\\", sizeof( key ) );
|
||||
Q_strcat( key, sizeof( key ), bind );
|
||||
}
|
||||
return key;
|
||||
}
|
||||
+1256
-1256
File diff suppressed because it is too large.
Load diff
+1034
-1034
File diff suppressed because it is too large.
Load diff
+2071
-2071
File diff suppressed because it is too large.
Load diff
+1840
-1840
File diff suppressed because it is too large.
Load diff
+289
-289
@@ -1,289 +1,289 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_marks.c -- wall marks
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_marks.c -- wall marks
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
|
||||
+202
-202
@@ -1,202 +1,202 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
+2567
-2567
File diff suppressed because it is too large.
Load diff
+2565
-2565
File diff suppressed because it is too large.
Load diff
+317
-317
@@ -1,317 +1,317 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
+878
-878
File diff suppressed because it is too large.
Load diff
+81
-81
@@ -1,81 +1,81 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_ptr.c -- post timeout restoration handling
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_ptr.c -- post timeout restoration handling
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
+252
-252
@@ -1,252 +1,252 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
#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_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_FS_GETFILELIST,
|
||||
CG_LITERAL_ARGS,
|
||||
CG_CM_BISPHERETRACE,
|
||||
CG_CM_TRANSFORMEDBISPHERETRACE,
|
||||
CG_GETDEMOSTATE,
|
||||
CG_GETDEMOPOS,
|
||||
CG_GETDEMONAME,
|
||||
|
||||
CG_KEY_KEYNUMTOSTRINGBUF,
|
||||
CG_KEY_GETBINDINGBUF,
|
||||
CG_KEY_SETBINDING,
|
||||
|
||||
CG_PARSE_ADD_GLOBAL_DEFINE,
|
||||
CG_PARSE_LOAD_SOURCE,
|
||||
CG_PARSE_FREE_SOURCE,
|
||||
CG_PARSE_READ_TOKEN,
|
||||
CG_PARSE_SOURCE_FILE_AND_LINE,
|
||||
|
||||
CG_MEMSET = 200,
|
||||
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);
|
||||
|
||||
CG_CONSOLE_TEXT
|
||||
// void (*CG_ConsoleText)( void );
|
||||
// pass text that has been printed to the console to cgame
|
||||
// use Cmd_Argc() / Cmd_Argv() to read it
|
||||
} cgameExport_t;
|
||||
|
||||
//----------------------------------------------
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
#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_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_FS_GETFILELIST,
|
||||
CG_LITERAL_ARGS,
|
||||
CG_CM_BISPHERETRACE,
|
||||
CG_CM_TRANSFORMEDBISPHERETRACE,
|
||||
CG_GETDEMOSTATE,
|
||||
CG_GETDEMOPOS,
|
||||
CG_GETDEMONAME,
|
||||
|
||||
CG_KEY_KEYNUMTOSTRINGBUF,
|
||||
CG_KEY_GETBINDINGBUF,
|
||||
CG_KEY_SETBINDING,
|
||||
|
||||
CG_PARSE_ADD_GLOBAL_DEFINE,
|
||||
CG_PARSE_LOAD_SOURCE,
|
||||
CG_PARSE_FREE_SOURCE,
|
||||
CG_PARSE_READ_TOKEN,
|
||||
CG_PARSE_SOURCE_FILE_AND_LINE,
|
||||
|
||||
CG_MEMSET = 200,
|
||||
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);
|
||||
|
||||
CG_CONSOLE_TEXT
|
||||
// void (*CG_ConsoleText)( void );
|
||||
// pass text that has been printed to the console to cgame
|
||||
// use Cmd_Argc() / Cmd_Argv() to read it
|
||||
} cgameExport_t;
|
||||
|
||||
//----------------------------------------------
|
||||
+365
-365
@@ -1,365 +1,365 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
+1016
-1016
File diff suppressed because it is too large.
Load diff
+411
-411
@@ -1,411 +1,411 @@
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_snapshot.c -- things that happen on snapshot transition,
|
||||
// not necessarily every single rendered frame
|
||||
|
||||
|
||||
#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" );
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
Copyright (C) 2000-2006 Tim Angus
|
||||
|
||||
This file is part of Tremulous.
|
||||
|
||||
Tremulous is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
Tremulous 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Tremulous; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// cg_snapshot.c -- things that happen on snapshot transition,
|
||||
// not necessarily every single rendered frame
|
||||
|
||||
|
||||
#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" );
|
||||
}
|
||||
|
||||
+116
-116
@@ -1,116 +1,116 @@
|
||||
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_S_StopBackgroundTrack -65
|
||||
equ trap_RealTime -66
|
||||
equ trap_SnapVector -67
|
||||
equ trap_RemoveCommand -68
|
||||
equ trap_R_LightForPoint -69
|
||||
equ trap_CIN_PlayCinematic -70
|
||||
equ trap_CIN_StopCinematic -71
|
||||
equ trap_CIN_RunCinematic -72
|
||||
equ trap_CIN_DrawCinematic -73
|
||||
equ trap_CIN_SetExtents -74
|
||||
equ trap_R_RemapShader -75
|
||||
equ trap_S_AddRealLoopingSound -76
|
||||
equ trap_S_StopLoopingSound -77
|
||||
equ trap_CM_TempCapsuleModel -78
|
||||
equ trap_CM_CapsuleTrace -79
|
||||
equ trap_CM_TransformedCapsuleTrace -80
|
||||
equ trap_R_AddAdditiveLightToScene -81
|
||||
equ trap_GetEntityToken -82
|
||||
equ trap_R_AddPolysToScene -83
|
||||
equ trap_R_inPVS -84
|
||||
equ trap_FS_Seek -85
|
||||
equ trap_FS_GetFileList -86
|
||||
equ trap_LiteralArgs -87
|
||||
equ trap_CM_BiSphereTrace -88
|
||||
equ trap_CM_TransformedBiSphereTrace -89
|
||||
equ trap_GetDemoState -90
|
||||
equ trap_GetDemoPos -91
|
||||
equ trap_GetDemoName -92
|
||||
equ trap_Key_KeynumToStringBuf -93
|
||||
equ trap_Key_GetBindingBuf -94
|
||||
equ trap_Key_SetBinding -95
|
||||
|
||||
equ trap_Parse_AddGlobalDefine -96
|
||||
equ trap_Parse_LoadSource -97
|
||||
equ trap_Parse_FreeSource -98
|
||||
equ trap_Parse_ReadToken -99
|
||||
equ trap_Parse_SourceFileAndLine -100
|
||||
|
||||
equ memset -201
|
||||
equ memcpy -202
|
||||
equ strncpy -203
|
||||
equ sin -204
|
||||
equ cos -205
|
||||
equ atan2 -206
|
||||
equ sqrt -207
|
||||
equ floor -208
|
||||
equ ceil -209
|
||||
equ testPrintInt -210
|
||||
equ testPrintFloat -211
|
||||
|
||||
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_S_StopBackgroundTrack -65
|
||||
equ trap_RealTime -66
|
||||
equ trap_SnapVector -67
|
||||
equ trap_RemoveCommand -68
|
||||
equ trap_R_LightForPoint -69
|
||||
equ trap_CIN_PlayCinematic -70
|
||||
equ trap_CIN_StopCinematic -71
|
||||
equ trap_CIN_RunCinematic -72
|
||||
equ trap_CIN_DrawCinematic -73
|
||||
equ trap_CIN_SetExtents -74
|
||||
equ trap_R_RemapShader -75
|
||||
equ trap_S_AddRealLoopingSound -76
|
||||
equ trap_S_StopLoopingSound -77
|
||||
equ trap_CM_TempCapsuleModel -78
|
||||
equ trap_CM_CapsuleTrace -79
|
||||
equ trap_CM_TransformedCapsuleTrace -80
|
||||
equ trap_R_AddAdditiveLightToScene -81
|
||||
equ trap_GetEntityToken -82
|
||||
equ trap_R_AddPolysToScene -83
|
||||
equ trap_R_inPVS -84
|
||||
equ trap_FS_Seek -85
|
||||
equ trap_FS_GetFileList -86
|
||||
equ trap_LiteralArgs -87
|
||||
equ trap_CM_BiSphereTrace -88
|
||||
equ trap_CM_TransformedBiSphereTrace -89
|
||||
equ trap_GetDemoState -90
|
||||
equ trap_GetDemoPos -91
|
||||
equ trap_GetDemoName -92
|
||||
equ trap_Key_KeynumToStringBuf -93
|
||||
equ trap_Key_GetBindingBuf -94
|
||||
equ trap_Key_SetBinding -95
|
||||
|
||||
equ trap_Parse_AddGlobalDefine -96
|
||||
equ trap_Parse_LoadSource -97
|
||||
equ trap_Parse_FreeSource -98
|
||||
equ trap_Parse_ReadToken -99
|
||||
equ trap_Parse_SourceFileAndLine -100
|
||||
|
||||
equ memset -201
|
||||
equ memcpy -202
|
||||
equ strncpy -203
|
||||
equ sin -204
|
||||
equ cos -205
|
||||
equ atan2 -206
|
||||
equ sqrt -207
|
||||
equ floor -208
|
||||
equ ceil -209
|
||||
equ testPrintInt -210
|
||||
equ testPrintFloat -211
|
||||
|
||||
+570
-570
File diff suppressed because it is too large.
Load diff
+1500
-1500
File diff suppressed because it is too large.
Load diff
+1340
-1340
File diff suppressed because it is too large.
Load diff
+1845
-1845
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user