summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_local.h26
-rw-r--r--src/cgame/cg_main.c4
-rw-r--r--src/cgame/cg_players.c107
-rw-r--r--src/cgame/cg_predict.c1
-rw-r--r--src/cgame/cg_servercmds.c153
5 files changed, 225 insertions, 66 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 62b32ea4..b2d8aabe 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -383,6 +383,17 @@ typedef struct
int animationTime; // time when the first frame of the animation will be exact
} lerpFrame_t;
+//TA: smoothing of view and model for WW transitions
+#define MAXSMOOTHS 32
+
+typedef struct
+{
+ float time;
+
+ vec3_t rotAxis;
+ float rotAngle;
+} smooth_t;
+
typedef struct
{
@@ -396,6 +407,8 @@ typedef struct
qboolean barrelSpinning;
vec3_t lastNormal;
+ vec3_t lastAxis[ 3 ];
+ smooth_t sList[ MAXSMOOTHS ];
} playerEntity_t;
typedef struct lightFlareStatus_s
@@ -750,17 +763,6 @@ typedef struct
sound_t sounds[ MAX_BUILDABLE_ANIMATIONS ];
} buildableInfo_t;
-//TA: smoothing of view for WW transitions
-#define MAXSMOOTHS 32
-
-typedef struct
-{
- float time;
-
- vec3_t rotAxis;
- float rotAngle;
-} smooth_t;
-
#define MAX_REWARDSTACK 10
#define MAX_SOUNDBUFFER 20
@@ -1356,6 +1358,7 @@ extern vmCvar_t cg_alienZapTime;
extern vmCvar_t cg_railTrailTime;
extern vmCvar_t cg_errorDecay;
extern vmCvar_t cg_nopredict;
+extern vmCvar_t cg_debugMove;
extern vmCvar_t cg_noPlayerAnims;
extern vmCvar_t cg_showmiss;
extern vmCvar_t cg_footsteps;
@@ -1425,6 +1428,7 @@ extern vmCvar_t cg_consoleLatency;
extern vmCvar_t cg_lightFlare;
extern vmCvar_t cg_debugParticles;
extern vmCvar_t cg_debugPVS;
+extern vmCvar_t cg_disableBuildWarnings;
//TA: hack to get class an carriage through to UI module
extern vmCvar_t ui_currentClass;
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index cd6a9333..1312cc23 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -126,6 +126,7 @@ vmCvar_t cg_debugPosition;
vmCvar_t cg_debugEvents;
vmCvar_t cg_errorDecay;
vmCvar_t cg_nopredict;
+vmCvar_t cg_debugMove;
vmCvar_t cg_noPlayerAnims;
vmCvar_t cg_showmiss;
vmCvar_t cg_footsteps;
@@ -199,6 +200,7 @@ vmCvar_t cg_consoleLatency;
vmCvar_t cg_lightFlare;
vmCvar_t cg_debugParticles;
vmCvar_t cg_debugPVS;
+vmCvar_t cg_disableBuildWarnings;
//TA: hack to get class and carriage through to UI module
vmCvar_t ui_currentClass;
@@ -267,6 +269,7 @@ static cvarTable_t cvarTable[ ] =
{ &cg_debugEvents, "cg_debugevents", "0", CVAR_CHEAT },
{ &cg_errorDecay, "cg_errordecay", "100", 0 },
{ &cg_nopredict, "cg_nopredict", "0", 0 },
+ { &cg_debugMove, "cg_debugMove", "0", 0 },
{ &cg_noPlayerAnims, "cg_noplayeranims", "0", CVAR_CHEAT },
{ &cg_showmiss, "cg_showmiss", "0", 0 },
{ &cg_footsteps, "cg_footsteps", "1", CVAR_CHEAT },
@@ -299,6 +302,7 @@ static cvarTable_t cvarTable[ ] =
{ &cg_lightFlare, "cg_lightFlare", "3", CVAR_ARCHIVE },
{ &cg_debugParticles, "cg_debugParticles", "0", CVAR_CHEAT },
{ &cg_debugPVS, "cg_debugPVS", "0", CVAR_CHEAT },
+ { &cg_disableBuildWarnings, "cg_disableBuildWarnings", "0", CVAR_ARCHIVE },
{ &ui_currentClass, "ui_currentClass", "0", 0 },
{ &ui_carriage, "ui_carriage", "", 0 },
diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c
index 0759927e..648b2d04 100644
--- a/src/cgame/cg_players.c
+++ b/src/cgame/cg_players.c
@@ -1303,6 +1303,100 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t srcAngles,
AnglesToAxis( headAngles, head );
}
+#define MODEL_WWSMOOTHTIME 200
+
+/*
+===============
+CG_PlayerWWSmoothing
+
+Smooth the angles of transitioning wall walkers
+===============
+*/
+static void CG_PlayerWWSmoothing( centity_t *cent, vec3_t in[ 3 ], vec3_t out[ 3 ] )
+{
+ entityState_t *es = &cent->currentState;
+ int i;
+ vec3_t surfNormal, rotAxis, temp;
+ vec3_t refNormal = { 0.0f, 0.0f, 1.0f };
+ vec3_t ceilingNormal = { 0.0f, 0.0f, -1.0f };
+ float stLocal, sFraction, rotAngle;
+ vec3_t inAxis[ 3 ], lastAxis[ 3 ], outAxis[ 3 ];
+
+ //set surfNormal
+ if( !( es->eFlags & EF_WALLCLIMBCEILING ) )
+ VectorCopy( es->angles2, surfNormal );
+ else
+ VectorCopy( ceilingNormal, surfNormal );
+
+ AxisCopy( in, inAxis );
+
+ if( !VectorCompare( surfNormal, cent->pe.lastNormal ) )
+ {
+ //if we moving from the ceiling to the floor special case
+ //( x product of colinear vectors is undefined)
+ if( VectorCompare( ceilingNormal, cent->pe.lastNormal ) &&
+ VectorCompare( refNormal, surfNormal ) )
+ {
+ VectorCopy( in, rotAxis );
+ rotAngle = 180.0f;
+ }
+ else
+ {
+ AxisCopy( cent->pe.lastAxis, lastAxis );
+ rotAngle = DotProduct( inAxis[ 0 ], lastAxis[ 0 ] ) +
+ DotProduct( inAxis[ 1 ], lastAxis[ 1 ] ) +
+ DotProduct( inAxis[ 2 ], lastAxis[ 2 ] );
+
+ rotAngle = RAD2DEG( acos( ( rotAngle - 1.0f ) / 2.0f ) );
+
+ CrossProduct( lastAxis[ 0 ], inAxis[ 0 ], temp );
+ VectorCopy( temp, rotAxis );
+ CrossProduct( lastAxis[ 1 ], inAxis[ 1 ], temp );
+ VectorAdd( rotAxis, temp, rotAxis );
+ CrossProduct( lastAxis[ 2 ], inAxis[ 2 ], temp );
+ VectorAdd( rotAxis, temp, rotAxis );
+
+ VectorNormalize( rotAxis );
+ }
+
+ //iterate through smooth array
+ for( i = 0; i < MAXSMOOTHS; i++ )
+ {
+ //found an unused index in the smooth array
+ if( cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME < cg.time )
+ {
+ //copy to array and stop
+ VectorCopy( rotAxis, cent->pe.sList[ i ].rotAxis );
+ cent->pe.sList[ i ].rotAngle = rotAngle;
+ cent->pe.sList[ i ].time = cg.time;
+ break;
+ }
+ }
+ }
+
+ //iterate through ops
+ for( i = MAXSMOOTHS - 1; i >= 0; i-- )
+ {
+ //if this op has time remaining, perform it
+ if( cg.time < cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME )
+ {
+ stLocal = 1.0f - ( ( ( cent->pe.sList[ i ].time + MODEL_WWSMOOTHTIME ) - cg.time ) / MODEL_WWSMOOTHTIME );
+ sFraction = -( cos( stLocal * M_PI ) + 1.0f ) / 2.0f;
+
+ RotatePointAroundVector( outAxis[ 0 ], cent->pe.sList[ i ].rotAxis,
+ inAxis[ 0 ], sFraction * cent->pe.sList[ i ].rotAngle );
+ RotatePointAroundVector( outAxis[ 1 ], cent->pe.sList[ i ].rotAxis,
+ inAxis[ 1 ], sFraction * cent->pe.sList[ i ].rotAngle );
+ RotatePointAroundVector( outAxis[ 2 ], cent->pe.sList[ i ].rotAxis,
+ inAxis[ 2 ], sFraction * cent->pe.sList[ i ].rotAngle );
+
+ AxisCopy( outAxis, inAxis );
+ }
+ }
+
+ //outAxis has been copied to inAxis
+ AxisCopy( inAxis, out );
+}
/*
===============
@@ -1315,7 +1409,6 @@ static void CG_PlayerNonSegAngles( centity_t *cent, vec3_t srcAngles, vec3_t non
{
vec3_t localAngles;
float dest;
- static int movementOffsets[ 8 ] = { 0, 22, 45, -22, 0, 22, -45, -22 };
vec3_t velocity;
float speed;
int dir, clientNum;
@@ -1338,8 +1431,7 @@ static void CG_PlayerNonSegAngles( centity_t *cent, vec3_t srcAngles, vec3_t non
//make sure that WW transitions don't cause the swing stuff to go nuts
if( !VectorCompare( surfNormal, cent->pe.lastNormal ) )
{
- VectorCopy( surfNormal, cent->pe.lastNormal );
-
+ //stop CG_SwingAngles having an eppy
cent->pe.nonseg.yawAngle = localAngles[ YAW ];
cent->pe.nonseg.yawing = qfalse;
}
@@ -1948,11 +2040,18 @@ void CG_Player( centity_t *cent )
else
CG_PlayerNonSegAngles( cent, angles, legs.axis );
+ AxisCopy( legs.axis, tempAxis );
+
//rotate the legs axis to back to the wall
if( es->eFlags & EF_WALLCLIMB &&
BG_rotateAxis( es->angles2, legs.axis, tempAxis, qfalse, es->eFlags & EF_WALLCLIMBCEILING ) )
AxisCopy( tempAxis, legs.axis );
+ //smooth out WW transitions so the model doesn't hop around
+ CG_PlayerWWSmoothing( cent, legs.axis, legs.axis );
+
+ AxisCopy( tempAxis, cent->pe.lastAxis );
+
// get the animation state (after rotation, to allow feet shuffle)
if( !ci->nonsegmented )
CG_PlayerAnimation( cent, &legs.oldframe, &legs.frame, &legs.backlerp,
@@ -2107,6 +2206,8 @@ void CG_Player( centity_t *cent )
if( CG_IsParticleSystemValid( &cent->jetPackPS ) )
CG_DestroyParticleSystem( &cent->jetPackPS );
}
+
+ VectorCopy( surfNormal, cent->pe.lastNormal );
}
/*
diff --git a/src/cgame/cg_predict.c b/src/cgame/cg_predict.c
index a68d58f6..548efb86 100644
--- a/src/cgame/cg_predict.c
+++ b/src/cgame/cg_predict.c
@@ -419,6 +419,7 @@ void CG_PredictPlayerState( void )
cg_pmove.ps = &cg.predictedPlayerState;
cg_pmove.trace = CG_Trace;
cg_pmove.pointcontents = CG_PointContents;
+ cg_pmove.debugLevel = cg_debugMove.integer;
if( cg_pmove.ps->pm_type == PM_DEAD )
cg_pmove.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c
index 72d20f6c..187c6395 100644
--- a/src/cgame/cg_servercmds.c
+++ b/src/cgame/cg_servercmds.c
@@ -576,51 +576,81 @@ void CG_Menu( int menu )
case MN_H_ARMOURY: trap_SendConsoleCommand( "menu tremulous_humanarmoury\n" ); break;
case MN_H_NOROOM:
- trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the buildable turns "
- "translucent green indicating a valid build location." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the buildable turns "
+ "translucent green indicating a valid build location." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_NOPOWER:
- trap_Cvar_Set( "ui_dialog", "There is no power remaining. Free up power by destroying existing "
- "buildable objects." );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no power remaining. Free up power by destroying existing "
+ "buildable objects." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
+ break;
+
+ case MN_H_NOTPOWERED:
+ trap_Cvar_Set( "ui_dialog", "This buildable is not powered. Build a reactor and/or repeater in "
+ "order to power it." );
trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
break;
case MN_H_NORMAL:
- trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. The surface is too steep or unsuitable "
- "to build on. Please choose another site for this structure." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. The surface is too steep or unsuitable "
+ "to build on. Please choose another site for this structure." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_REACTOR:
- trap_Cvar_Set( "ui_dialog", "There can only be one reactor. Destroy the existing one if you "
- "wish to move it." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There can only be one reactor. Destroy the existing one if you "
+ "wish to move it." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_REPEATER:
- trap_Cvar_Set( "ui_dialog", "There is no power here. If available, a Repeater may be used to "
- "transmit power to this location." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no power here. If available, a Repeater may be used to "
+ "transmit power to this location." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_NODCC:
- trap_Cvar_Set( "ui_dialog", "There is no Defense Computer. A Defense Computer is needed to build "
- "this." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no Defense Computer. A Defense Computer is needed to build "
+ "this." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_RPLWARN:
- trap_Cvar_Set( "ui_dialog", "WARNING: This replicator will not be powered. Build a reactor to "
- "prevent seeing this message again." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "WARNING: This replicator will not be powered. Build a reactor to "
+ "prevent seeing this message again." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_RPTWARN:
- trap_Cvar_Set( "ui_dialog", "WARNING: This repeater will not be powered as there is no parent "
- "reactor providing power. Build a reactor." );
- trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "WARNING: This repeater will not be powered as there is no parent "
+ "reactor providing power. Build a reactor." );
+ trap_SendConsoleCommand( "menu tremulous_human_dialog\n" );
+ }
break;
case MN_H_NOSLOTS:
@@ -646,56 +676,75 @@ void CG_Menu( int menu )
case MN_A_NOROOM:
- trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the structure turns "
- "translucent green indicating a valid build location." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no room to build here. Move until the structure turns "
+ "translucent green indicating a valid build location." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_NOCREEP:
- trap_Cvar_Set( "ui_dialog", "There is no creep here. You must build near existing Eggs or "
- "the Overmind. Alien structures will not support themselves." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no creep here. You must build near existing Eggs or "
+ "the Overmind. Alien structures will not support themselves." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_NOOVMND:
- trap_Cvar_Set( "ui_dialog", "There is no Overmind. An Overmind must be built to control "
- "the structure you tried to place" );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no Overmind. An Overmind must be built to control "
+ "the structure you tried to place" );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_NOEROOM:
- trap_Cvar_Set( "ui_dialog", "There is no room to evolve here. Move away from walls or other "
- "nearby objects and try again." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There is no room to evolve here. Move away from walls or other "
+ "nearby objects and try again." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_OVERMIND:
- trap_Cvar_Set( "ui_dialog", "There can only be one Overmind. Destroy the existing one if you "
- "wish to move it." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "There can only be one Overmind. Destroy the existing one if you "
+ "wish to move it." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_NOASSERT:
- trap_Cvar_Set( "ui_dialog", "The Overmind cannot control anymore structures. Destroy existing "
- "structures to build more." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "The Overmind cannot control anymore structures. Destroy existing "
+ "structures to build more." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_SPWNWARN:
- trap_Cvar_Set( "ui_dialog", "WARNING: This spawn will not be controlled by an Overmind. "
- "Build an Overmind to prevent seeing this message again." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "WARNING: This spawn will not be controlled by an Overmind. "
+ "Build an Overmind to prevent seeing this message again." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_NORMAL:
- trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. This surface is too steep or unsuitable "
- "to build on. Please choose another site for this structure." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
- break;
-
- case MN_A_NOFUNDS:
- trap_Cvar_Set( "ui_dialog", "You do not possess sufficient organs to perform this action." );
- trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ if( !cg_disableBuildWarnings.integer )
+ {
+ trap_Cvar_Set( "ui_dialog", "Cannot build on this surface. This surface is too steep or unsuitable "
+ "to build on. Please choose another site for this structure." );
+ trap_SendConsoleCommand( "menu tremulous_alien_dialog\n" );
+ }
break;
case MN_A_HOVEL_OCCUPIED: