summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_draw.c37
-rw-r--r--src/cgame/cg_ents.c153
-rw-r--r--src/cgame/cg_event.c10
-rw-r--r--src/cgame/cg_local.h10
-rw-r--r--src/cgame/cg_main.c25
-rw-r--r--src/cgame/cg_view.c89
-rw-r--r--src/cgame/cg_weapons.c19
-rw-r--r--src/game/bg_misc.c56
-rw-r--r--src/game/bg_pmove.c28
-rw-r--r--src/game/bg_public.h27
-rw-r--r--src/game/g_active.c59
-rw-r--r--src/game/g_cmds.c24
-rw-r--r--src/game/g_local.h4
-rw-r--r--src/game/g_misc.c18
-rw-r--r--src/game/g_weapon.c112
15 files changed, 358 insertions, 313 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 6befbcd0..7674df5c 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -1451,8 +1451,12 @@ static void CG_DrawConsole( rectDef_t *rect, float text_x, float text_y, vec4_t
float scale, int align, int textStyle )
{
float x, y, w, h;
- menuDef_t dummyParent;
- itemDef_t textItem;
+
+ //for some reason if these are stored locally occasionally rendering fails
+ //even though they are both live until the end of the function, hence static
+ //possible compiler bug??
+ static menuDef_t dummyParent;
+ static itemDef_t textItem;
//offset the text
x = rect->x;
@@ -1780,14 +1784,8 @@ static void CG_DrawLighting( void )
cent = &cg_entities[cg.snap->ps.clientNum];
- if( cg.snap->ps.stats[ STAT_PCLASS ] == PCL_H_BASE )
- {
- if( BG_activated( UP_NVG, cg.snap->ps.stats ) )
- CG_DrawPic( 0, 0, 640, 480, cgs.media.humanNV );
- }
-
//fade to black if stamina is low
- if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) &&
+ if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) &&
( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) )
{
vec4_t black = { 0, 0, 0, 0 };
@@ -2393,8 +2391,9 @@ CG_Draw2D
*/
static void CG_Draw2D( void )
{
- vec4_t color;
- float w;
+ vec4_t color;
+ float w;
+ menuDef_t *menu, *defaultMenu;
color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 1.0f;
@@ -2414,23 +2413,23 @@ static void CG_Draw2D( void )
//TA: draw the lighting effects e.g. nvg
CG_DrawLighting( );
+ menu = Menus_FindByName( BG_FindHudNameForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ) );
+ defaultMenu = Menus_FindByName( "default_hud" );
+
if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
{
w = CG_Text_Width( SPECTATOR_STRING, 0.7f, 0 );
CG_Text_Paint( 320 - w / 2, 440, 0.7f, color, SPECTATOR_STRING, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
}
- else if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) &&
- !( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) )
+
+ if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) &&
+ !( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) && menu )
{
// don't draw any status if dead or the scoreboard is being explicitly shown
if( !cg.showScores && cg.snap->ps.stats[ STAT_HEALTH ] > 0 )
{
if( cg_drawStatus.integer )
- {
- Menu_Paint(
- Menus_FindByName(
- BG_FindHudNameForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ) ), qtrue );
- }
+ Menu_Paint( menu, qtrue );
CG_DrawAmmoWarning( );
CG_DrawCrosshair( );
@@ -2442,6 +2441,8 @@ static void CG_Draw2D( void )
CG_AlienSense( );
}
}
+ else if( cg_drawStatus.integer )
+ Menu_Paint( defaultMenu, qtrue );
CG_DrawVote( );
CG_DrawTeamVote( );
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c
index 8578ab08..f0e10574 100644
--- a/src/cgame/cg_ents.c
+++ b/src/cgame/cg_ents.c
@@ -132,7 +132,7 @@ static void CG_EntityEffects( centity_t *cent ) {
// constant light glow
- if ( cent->currentState.constantLight && cent->currentState.eType != ET_TORCH )
+ if ( cent->currentState.constantLight )
{
int cl;
int i, r, g, b;
@@ -484,154 +484,6 @@ static void CG_Portal( centity_t *cent ) {
//============================================================================
-#define MAX_MARK_FRAGMENTS 128
-#define MAX_MARK_POINTS 384
-#define TORCH_R 0.2f
-#define TORCH_G 0.25f
-#define TORCH_B 0.3f
-
-/*
-===============
-CG_TorchLight
-===============
-*/
-static void CG_TorchLight( centity_t *cent )
-{
- int i, j, lum, numFragments;
- polyVert_t verts[ 4 ];
- float size, texCoordScale, veclength;
- trace_t tr;
- vec2_t tex[ 4 ];
- vec3_t temp, origin, normal, projection, angles;
- vec3_t to, from, forward, length;
- vec3_t markPoints[ MAX_MARK_POINTS ];
- vec3_t square[ 4 ];
- vec4_t axis[ 3 ], color;
- vec3_t mins = { -15, -15, -15 };
- vec3_t maxs = { 15, 15, 15 };
- markFragment_t markFragments[ MAX_MARK_FRAGMENTS ], *mf;
-
- if( cent->currentState.clientNum == cg.predictedPlayerState.clientNum )
- {
- VectorCopy( cg.predictedPlayerState.origin, from );
- VectorCopy( cg.refdefViewAngles, angles );
- }
- else
- {
- VectorCopy( cent->lerpOrigin, from );
- VectorCopy( cent->lerpAngles, angles );
- }
-
- from[2] += cg.predictedPlayerState.viewheight;
-
- AngleVectors( angles, forward, NULL, NULL );
- VectorMA( from, 4096, forward, to );
-
- CG_Trace( &tr, from, mins, maxs, to, -1, MASK_SOLID );
-
- VectorSubtract( tr.endpos, from, length );
- veclength = VectorLength( length );
-
- size = veclength / 2.0f;
- if( size > 255 ) size = 255;
- if( size < 0 ) size = 0;
-
- VectorCopy( tr.endpos, origin );
- VectorCopy( tr.plane.normal, normal );
-
- //slightly above surface
- VectorMA( origin, 1, normal, origin );
-
-#if 1
- trap_R_AddLightToScene( origin, size * 2, 1, 1, 1 );
- trap_R_AddAdditiveLightToScene( origin, size * 2, ( ( 512 - size ) / 512 ) * TORCH_R,
- ( ( 512 - size ) / 512 ) * TORCH_G,
- ( ( 512 - size ) / 512 ) * TORCH_B );
-#else
- texCoordScale = 0.5f / size;
-
- //decide where the corners of the poly go
- VectorNormalize2( normal, axis[0] );
- PerpendicularVector( axis[1], axis[0] );
- CrossProduct( axis[0], axis[1], axis[2] );
-
- for ( i = 0 ; i < 3 ; i++ )
- {
- square[0][i] = origin[i] - size * axis[1][i] - size * axis[2][i];
- square[1][i] = origin[i] - size * axis[1][i] + size * axis[2][i];
- square[2][i] = origin[i] + size * axis[1][i] + size * axis[2][i];
- square[3][i] = origin[i] + size * axis[1][i] - size * axis[2][i];
- }
-
- //set texture coordinates
- Vector2Set( tex[ 0 ], 0, 0 );
- Vector2Set( tex[ 1 ], 0, 1 );
- Vector2Set( tex[ 2 ], 1, 1 );
- Vector2Set( tex[ 3 ], 1, 0 );
-
- VectorScale( normal, -32, projection );
- numFragments = trap_CM_MarkFragments( 4, (void *)square,
- projection, MAX_MARK_POINTS, markPoints[0],
- MAX_MARK_FRAGMENTS, markFragments );
-
- color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255;
-
- VectorCopy( origin, temp );
- VectorMA( temp, 48, normal, temp );
- lum = CG_AmbientLight( temp );
-
- lum += (int)( ( size / 255.0f ) * 24 );
-
- if( lum > 255 )
- lum = 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 );
- VectorMA( v->xyz, 0.1f, normal, 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 *)color;
- }
-
- if( lum < 64 )
- {
- if( lum < 10 )
- trap_R_AddPolyToScene( cgs.media.humanTorch8, mf->numPoints, verts );
- else if( lum >= 10 && lum < 16 )
- trap_R_AddPolyToScene( cgs.media.humanTorch7, mf->numPoints, verts );
- else if( lum >= 16 && lum < 22 )
- trap_R_AddPolyToScene( cgs.media.humanTorch6, mf->numPoints, verts );
- else if( lum >= 22 && lum < 28 )
- trap_R_AddPolyToScene( cgs.media.humanTorch5, mf->numPoints, verts );
- else if( lum >= 28 && lum < 34 )
- trap_R_AddPolyToScene( cgs.media.humanTorch4, mf->numPoints, verts );
- else if( lum >= 34 && lum < 40 )
- trap_R_AddPolyToScene( cgs.media.humanTorch3, mf->numPoints, verts );
- else if( lum >= 40 && lum < 46 )
- trap_R_AddPolyToScene( cgs.media.humanTorch2, mf->numPoints, verts );
- else if( lum >= 46 )
- trap_R_AddPolyToScene( cgs.media.humanTorch1, mf->numPoints, verts );
- }
- }
-#endif
-}
-
/*
=========================
CG_LightFlare
@@ -846,9 +698,6 @@ static void CG_AddCEntity( centity_t *cent ) {
case ET_MISSILE:
CG_Missile( cent );
break;
- case ET_TORCH:
- CG_TorchLight( cent );
- break;
case ET_MOVER:
CG_Mover( cent );
break;
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index 27d8ada8..2637528b 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -1159,6 +1159,16 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
cg.firstPoisonedTime = cg.time;
break;
+ case EV_KNOCKOVER:
+ DEBUGNAME("EV_KNOCKOVER");
+ cg.firstKnockedTime = cg.time;
+ break;
+
+ case EV_GETUP:
+ DEBUGNAME("EV_GETUP");
+ cg.firstGetUpTime = cg.time;
+ break;
+
case EV_PLAYER_RESPAWN:
DEBUGNAME("EV_PLAYER_RESPAWN");
if( es->number == cg.clientNum )
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 2bd676a2..a1ae20bc 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -725,8 +725,12 @@ typedef struct {
int rightMoveTime;
int upMoveTime;
- int poisonedTime; //TA: poison cloud
- int firstPoisonedTime; //TA: poison cloud
+ int poisonedTime; //TA: poison cloud
+ int firstPoisonedTime; //TA: poison cloud
+ int lastRumbleTime; //TA: knocked over time
+ vec3_t rumbleVector; //TA: vertical displacement whilst rumbling
+ int firstKnockedTime; //TA: knocked over time
+ int firstGetUpTime; //TA: getting up time
float charModelFraction; //TA: loading percentages
float mediaFraction;
@@ -739,6 +743,8 @@ typedef struct {
char consoleText[ MAX_CONSOLE_TEXT ];
consoleLine_t consoleLines[ MAX_CONSOLE_LINES ];
int numConsoleLines;
+ qboolean consoleValid;
+
} cg_t;
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index a5ffec50..29984b33 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -445,10 +445,13 @@ void QDECL CG_Printf( const char *msg, ... ) {
if( cg.numConsoleLines == MAX_CONSOLE_LINES )
CG_RemoveConsoleLine( );
- strcat( cg.consoleText, text );
- cg.consoleLines[ cg.numConsoleLines ].time = cg.time;
- cg.consoleLines[ cg.numConsoleLines ].length = strlen( text );
- cg.numConsoleLines++;
+ if( cg.consoleValid )
+ {
+ strcat( cg.consoleText, text );
+ cg.consoleLines[ cg.numConsoleLines ].time = cg.time;
+ cg.consoleLines[ cg.numConsoleLines ].length = strlen( text );
+ cg.numConsoleLines++;
+ }
trap_Print( text );
}
@@ -486,6 +489,18 @@ void QDECL Com_Printf( const char *msg, ... ) {
vsprintf (text, msg, argptr);
va_end (argptr);
+ //TA: team arena UI based console
+ if( cg.numConsoleLines == MAX_CONSOLE_LINES )
+ CG_RemoveConsoleLine( );
+
+ if( cg.consoleValid )
+ {
+ strcat( cg.consoleText, text );
+ cg.consoleLines[ cg.numConsoleLines ].time = cg.time;
+ cg.consoleLines[ cg.numConsoleLines ].length = strlen( text );
+ cg.numConsoleLines++;
+ }
+
CG_Printf ("%s", text);
}
@@ -1744,6 +1759,8 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) {
CG_ShaderStateChanged();
trap_S_ClearLoopingSounds( qtrue );
+
+ cg.consoleValid = qtrue;
}
/*
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index ce49d68a..6c5d2ad3 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -356,7 +356,7 @@ static void CG_OffsetFirstPersonView( void ) {
vec3_t predictedVelocity;
int timeDelta;
float bob2;
- vec3_t normal;
+ vec3_t normal, baseOrigin;
playerState_t *ps = &cg.predictedPlayerState;
if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
@@ -377,6 +377,8 @@ static void CG_OffsetFirstPersonView( void ) {
origin = cg.refdef.vieworg;
angles = cg.refdefViewAngles;
+ VectorCopy( origin, baseOrigin );
+
// if dead, fix the angle and don't add any kick
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
angles[ROLL] = 40;
@@ -553,6 +555,89 @@ static void CG_OffsetFirstPersonView( void ) {
}
}
+#define KNOCK_ROLL 70.0f
+#define KNOCK_SHAKE_HEIGHT 10
+#define KNOCK_RUMBLE_TIME 60
+
+ if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_KNOCKEDOVER )
+ {
+ int deltaTime;
+ float deltaSecs;
+ trace_t tr;
+ vec3_t mins, maxs;
+ float rollFraction;
+
+ BG_FindBBoxForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ], NULL, NULL, NULL, mins, maxs );
+
+ //bit closer to the ground
+ mins[ 2 ] = -1.0f;
+
+ deltaTime = cg.time - ( cg.firstKnockedTime + (int)( (float)KOVER_TIME / 5.0f ) );
+
+ if( deltaTime < 0 )
+ {
+ if( cg.time > cg.lastRumbleTime )
+ {
+ cg.rumbleVector[ 0 ] = rand( ) % KNOCK_SHAKE_HEIGHT;
+ cg.rumbleVector[ 1 ] = rand( ) % KNOCK_SHAKE_HEIGHT;
+ cg.rumbleVector[ 2 ] = rand( ) % KNOCK_SHAKE_HEIGHT;
+
+ cg.lastRumbleTime = cg.time + KNOCK_RUMBLE_TIME;
+ }
+
+ VectorAdd( origin, cg.rumbleVector, origin );
+ }
+ else
+ {
+ deltaSecs = deltaTime * 0.001; // milliseconds to seconds
+ origin[ 2 ] -= 0.5 * DEFAULT_GRAVITY * deltaSecs * deltaSecs; // FIXME: local gravity...
+
+ CG_Trace( &tr, baseOrigin, mins, maxs, origin, cg.predictedPlayerState.clientNum, MASK_SOLID );
+ VectorCopy( tr.endpos, origin );
+
+ rollFraction = (float)deltaTime / ( (float)KOVER_TIME / 6.0f );
+
+ if( rollFraction > 1.0f )
+ rollFraction = 1.0f;
+
+ angles[ ROLL ] -= rollFraction * KNOCK_ROLL;
+ VectorSet( cg.rumbleVector, 0.0f, 0.0f, 0.0f );
+ }
+ }
+
+ if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_GETTINGUP )
+ {
+ int deltaTime;
+ trace_t tr;
+ vec3_t mins, maxs, ground, pushUp;
+ float rollFraction;
+
+ BG_FindBBoxForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ], NULL, NULL, NULL, mins, maxs );
+
+ //bit closer to the ground
+ mins[ 2 ] = -1.0f;
+
+ VectorCopy( baseOrigin, ground );
+ ground[ 2 ] -= 64.0f;
+
+ CG_Trace( &tr, baseOrigin, mins, maxs, ground, cg.predictedPlayerState.clientNum, MASK_SOLID );
+ VectorSubtract( baseOrigin, tr.endpos, pushUp );
+
+ deltaTime = cg.time - cg.firstGetUpTime;
+
+ rollFraction = (float)deltaTime / (float)GETUP_TIME;
+
+ if( rollFraction > 1.0f )
+ rollFraction = 1.0f;
+
+ rollFraction = 1.0f - rollFraction;
+
+ VectorScale( pushUp, rollFraction, pushUp );
+ VectorSubtract( origin, pushUp, origin );
+
+ angles[ ROLL ] -= rollFraction * KNOCK_ROLL;
+ }
+
//TA: this *feels* more realisitic for humans
if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
@@ -1237,7 +1322,7 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
/*CG_PowerupTimerSounds();*/
//remove expired console lines
- if( cg.consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time )
+ if( cg.consoleLines[ 0 ].time + cg_consoleLatency.integer < cg.time && cg_consoleLatency.integer > 0 )
CG_RemoveConsoleLine( );
// update audio positions
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index a2e1bf3e..8f83e288 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -782,6 +782,11 @@ void CG_RegisterWeapon( int weaponNum )
weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/grenade1.md3" );
break;
+ case WP_GROUND_POUND:
+ MAKERGB( weaponInfo->flashDlightColor, 0, 0, 0 );
+ weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
+ break;
+
case WP_ABUILD:
case WP_ABUILD2:
case WP_HBUILD:
@@ -1437,6 +1442,17 @@ void CG_AddViewWeapon( playerState_t *ps ) {
VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[1], hand.origin );
}
+ if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_KNOCKEDOVER )
+ {
+ vec3_t weaponRumble;
+
+ VectorCopy( cg.rumbleVector, weaponRumble );
+ VectorInverse( weaponRumble );
+ VectorScale( weaponRumble, 0.1f, weaponRumble );
+
+ VectorAdd( hand.origin, weaponRumble, hand.origin );
+ }
+
AnglesToAxis( angles, hand.axis );
// map torso animations to weapon animations
@@ -1456,8 +1472,7 @@ void CG_AddViewWeapon( playerState_t *ps ) {
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
// add everything onto the hand
- CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity );
-}
+ CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity );}
/*
==============================================================================
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 43f01c44..eaffd383 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -1556,7 +1556,7 @@ classAttributes_t bg_classList[ ] =
100, //int health;
5, //int regenRate;
SCA_CANJUMP|SCA_NOWEAPONDRIFT|SCA_FOVWARPS, //int abilities;
- WP_VENOM, //weapon_t startWeapon
+ WP_GROUND_POUND, //weapon_t startWeapon
0.0f, //float buildDist;
130, //int fov;
0.0f, //float bob;
@@ -1730,7 +1730,7 @@ char *BG_FindHudNameForClass( int pclass )
return bg_classList[ i ].hudName;
}
- //note: must return a valid modelName!
+ //note: must return a valid hudName!
return bg_classList[ 0 ].hudName;
}
@@ -2541,6 +2541,28 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
+ WP_GROUND_POUND, //int weaponNum;
+ 100, //int price;
+ ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_WEAPON, //int slots;
+ "groundpound", //char *weaponName;
+ "Ground Pound", //char *weaponHumanName;
+ { "models/weapons2/gauntlet/gauntlet.md3", 0, 0, 0 },
+ "icons/iconw_gauntlet",
+ 0, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qtrue, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ 750, //int repeatRate;
+ 0, //int reloadTime;
+ qtrue, //qboolean hasAltMode;
+ qtrue, //qboolean hasThirdMode;
+ qfalse, //qboolean purchasable;
+ 0, //int buildDelay;
+ WUT_ALIENS //WUTeam_t team;
+ },
+ {
WP_LOCKBLOB_LAUNCHER, //int weaponNum;
100, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
@@ -2979,32 +3001,6 @@ WUTeam_t BG_FindTeamForWeapon( int weapon )
upgradeAttributes_t bg_upgrades[ ] =
{
{
- UP_TORCH, //int upgradeNum;
- 100, //int price;
- ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
- SLOT_NONE, //int slots;
- "torch", //char *upgradeName;
- "Torch", //char *upgradeHumanName;
- "icons/iconw_machinegun",
- WP_NONE, //weapon_t weaponAmmo;
- 0, //int ammo;
- 0, //int clips;
- WUT_HUMANS //WUTeam_t team;
- },
- {
- UP_NVG, //int upgradeNum;
- 100, //int price;
- ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
- SLOT_HEAD, //int slots;
- "nvg", //char *upgradeName;
- "NVG", //char *upgradeHumanName;
- "icons/iconw_plasma",
- WP_NONE, //weapon_t weaponAmmo;
- 0, //int ammo;
- 0, //int clips;
- WUT_HUMANS //WUTeam_t team;
- },
- {
UP_CHESTARMOUR, //int upgradeNum;
100, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
@@ -3551,7 +3547,9 @@ char *eventnames[] = {
"EV_TAUNT_PATROL",
"EV_MENU", //TA: menu event
- "EV_POISONCLOUD" //TA: client poisoned
+ "EV_POISONCLOUD", //TA: client poisoned
+ "EV_KNOCKOVER" //TA: client knocked over
+ "EV_GETUP" //TA: client getting up
};
/*
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 0539294e..f3158199 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -329,7 +329,7 @@ static float PM_CmdScale( usercmd_t *cmd ) {
modifier *= (float)( pm->ps->stats[ STAT_STAMINA ] + 1000 ) / 500.0f;
}
- if( pm->ps->pm_type == PM_GRABBED )
+ if( pm->ps->pm_type == PM_GRABBED || pm->ps->pm_type == PM_KNOCKED )
modifier = 0.0f;
if( !BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_CANJUMP ) )
@@ -463,7 +463,7 @@ static qboolean PM_CheckJump( void )
}
//can't jump whilst grabbed
- if( pm->ps->pm_type == PM_GRABBED )
+ if( pm->ps->pm_type == PM_GRABBED && pm->ps->pm_type == PM_KNOCKED )
{
pm->cmd.upmove = 0;
return qfalse;
@@ -2152,6 +2152,9 @@ static void PM_Weapon( void )
if( pm->ps->stats[ STAT_STATE ] & SS_HOVELING )
return;
+ if( pm->ps->stats[ STAT_STATE ] & SS_KNOCKEDOVER )
+ return;
+
// check for dead player
if ( pm->ps->stats[STAT_HEALTH] <= 0 )
{
@@ -2561,6 +2564,25 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd )
ps->delta_angles[ i ] -= ANGLE2SHORT( fabs( diff ) * 0.05f );
}
}
+
+ //fiz the view to the lock point
+ if( ps->pm_type == PM_KNOCKED )
+ {
+ for( i = 0; i < 3; i++ )
+ {
+ float diff = AngleSubtract( ps->viewangles[ i ], ps->grapplePoint[ i ] );
+
+ while( diff > 180.0f )
+ diff -= 360.0f;
+ while( diff < -180.0f )
+ diff += 360.0f;
+
+ if( diff < 0 )
+ ps->delta_angles[ i ] += ANGLE2SHORT( fabs( diff ) );
+ else if( diff > 0 )
+ ps->delta_angles[ i ] -= ANGLE2SHORT( fabs( diff ) );
+ }
+ }
}
@@ -2714,7 +2736,7 @@ void PmoveSingle (pmove_t *pmove)
// update the viewangles
PM_UpdateViewAngles( pm->ps, &pm->cmd );
- if ( pm->ps->pm_type == PM_DEAD || pm->ps->pm_type == PM_GRABBED )
+ if ( pm->ps->pm_type == PM_DEAD || pm->ps->pm_type == PM_GRABBED || pm->ps->pm_type == PM_KNOCKED )
PM_DeadMove( );
PM_DropTimers( );
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 393d278d..2fd58deb 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -50,6 +50,8 @@
#define LC_CHARGE_TIME 2000.0f
#define PCLOUD_TIME 10000
+#define KOVER_TIME 2000
+#define GETUP_TIME 1000
//
// config strings are a general means of communicating variable length strings
@@ -137,6 +139,7 @@ typedef enum {
PM_GRABBED, // like dead, but for when the player is still live
PM_DEAD, // no acceleration or turning, but free falling
PM_FREEZE, // stuck in place with no control
+ PM_KNOCKED, // knocked over
PM_INTERMISSION, // no movement or status bar
PM_SPINTERMISSION // no movement or status bar
} pmtype_t;
@@ -251,6 +254,8 @@ typedef enum {
#define SS_BOOSTED 0x00000200
#define SS_SLOWLOCKED 0x00000400
#define SS_POISONCLOUDED 0x00000800
+#define SS_KNOCKEDOVER 0x00001000
+#define SS_GETTINGUP 0x00002000
#define SB_VALID_TOGGLEBIT 0x00004000
@@ -333,12 +338,6 @@ typedef enum
{
WP_NONE,
- WP_MACHINEGUN,
- WP_CHAINGUN,
- WP_LOCKBLOB_LAUNCHER,
- WP_TESLAGEN,
- WP_FLAMER,
- WP_PLASMAGUN,
WP_VENOM,
WP_GRAB_CLAW,
WP_GRAB_CLAW_UPG,
@@ -346,12 +345,21 @@ typedef enum
WP_POUNCE_UPG,
WP_AREA_ZAP,
WP_DIRECT_ZAP,
+ WP_GROUND_POUND,
+
+ WP_MACHINEGUN,
+ WP_CHAINGUN,
+ WP_FLAMER,
+ WP_PLASMAGUN,
WP_MASS_DRIVER,
WP_PULSE_RIFLE,
WP_LUCIFER_CANON,
WP_LAS_GUN,
WP_PAIN_SAW,
+ WP_LOCKBLOB_LAUNCHER,
+ WP_TESLAGEN,
+
//build weapons must remain in a block
WP_ABUILD,
WP_ABUILD2,
@@ -366,8 +374,6 @@ typedef enum
{
UP_NONE,
- UP_TORCH,
- UP_NVG,
UP_CHESTARMOUR,
UP_LIMBARMOUR,
UP_HELMET,
@@ -587,7 +593,9 @@ typedef enum {
EV_MENU, //TA: menu event
EV_BUILD_DELAY, //TA: can't build yet
- EV_POISONCLOUD //TA: client poisoned
+ EV_POISONCLOUD, //TA: client poisoned
+ EV_KNOCKOVER, //TA: client knocked over
+ EV_GETUP //TA: client getting up
} entity_event_t;
typedef enum
@@ -1143,7 +1151,6 @@ typedef enum {
ET_INVISIBLE,
ET_GRAPPLE, // grapple hooked on wall
- ET_TORCH, //TA: torch type
ET_CORPSE,
ET_SPRITER,
ET_ANIMMAPOBJ,
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 934e2b78..6e6b7f1b 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -800,9 +800,6 @@ void ClientThink_real( gentity_t *ent ) {
usercmd_t *ucmd;
float speed;
- //TA: torch
- gentity_t *light;
-
//TA: creep variables
gentity_t *creepNode;
vec3_t temp_v;
@@ -884,6 +881,9 @@ void ClientThink_real( gentity_t *ent ) {
else if( client->ps.stats[ STAT_STATE ] & SS_BLOBLOCKED ||
client->ps.stats[ STAT_STATE ] & SS_GRABBED )
client->ps.pm_type = PM_GRABBED;
+ else if( client->ps.stats[ STAT_STATE ] & SS_GETTINGUP ||
+ client->ps.stats[ STAT_STATE ] & SS_KNOCKEDOVER )
+ client->ps.pm_type = PM_KNOCKED;
else
client->ps.pm_type = PM_NORMAL;
@@ -903,6 +903,29 @@ void ClientThink_real( gentity_t *ent ) {
client->lastPoisonCloudedTime + PCLOUD_TIME < level.time )
client->ps.stats[ STAT_STATE ] &= ~SS_POISONCLOUDED;
+ if( client->ps.stats[ STAT_STATE ] & SS_KNOCKEDOVER &&
+ client->lastKnockedOverTime + KOVER_TIME < level.time &&
+ ucmd->upmove > 0 )
+ {
+ client->lastGetUpTime = level.time;
+ G_AddPredictableEvent( ent, EV_GETUP, 0 );
+ client->ps.stats[ STAT_STATE ] &= ~SS_KNOCKEDOVER;
+ client->ps.stats[ STAT_STATE ] |= SS_GETTINGUP;
+
+ //FIXME: getup animation
+ client->ps.legsAnim =
+ ( ( client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH2;
+ client->ps.torsoAnim =
+ ( ( client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH2;
+ }
+
+ if( client->ps.stats[ STAT_STATE ] & SS_GETTINGUP &&
+ client->lastGetUpTime + GETUP_TIME < level.time )
+ {
+ client->ps.stats[ STAT_STATE ] &= ~SS_GETTINGUP;
+ VectorCopy( ent->client->ps.grapplePoint, ent->client->ps.viewangles );
+ }
+
client->ps.gravity = g_gravity.value;
if( BG_gotItem( UP_ANTITOXIN, client->ps.stats ) &&
@@ -965,36 +988,6 @@ void ClientThink_real( gentity_t *ent ) {
Weapon_HookFree(client->hook);
}*/
- //TA: torch stuff
- if( client->torch == NULL &&
- BG_activated( UP_TORCH, client->ps.stats ) &&
- BG_gotItem( UP_TORCH, client->ps.stats ) &&
- !( client->ps.pm_type == PM_DEAD )
- )
- {
- light = G_Spawn( );
- light->s.eType = ET_TORCH;
- light->r.ownerNum = ent->s.number;
- light->parent = ent;
- client->torch = light;
- }
-
- if( client->torch != NULL &&
- ( !BG_activated( UP_TORCH, client->ps.stats ) ||
- client->ps.pm_type == PM_DEAD ||
- !BG_gotItem( UP_TORCH, client->ps.stats )
- )
- )
- {
- G_FreeEntity( client->torch );
- trap_LinkEntity( client->torch );
- client->torch = NULL;
- }
-
-
- if( client->torch != NULL )
- ShineTorch( client->torch );
-
// set up for pmove
oldEventSequence = client->ps.eventSequence;
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index ef2b5b9f..3b789207 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -1525,18 +1525,6 @@ void Cmd_Stats_f( gentity_t *ent ) {
}
-/*
-=================
-Cmd_TorchOff_f
-=================
-*/
-void Cmd_TorchOff_f( gentity_t *ent )
-{
- G_FreeEntity( ent->client->torch );
- trap_LinkEntity( ent->client->torch );
- ent->client->torch = NULL;
-}
-
#define NUM_AC 3
/*
@@ -2454,9 +2442,15 @@ void Cmd_Spawnbody_f( gentity_t *ent )
void Cmd_Test_f( gentity_t *ent )
{
- ent->client->ps.stats[ STAT_STATE ] |= SS_POISONCLOUDED;
- ent->client->lastPoisonCloudedTime = level.time;
- G_AddPredictableEvent( ent, EV_POISONCLOUD, 0 );
+ ent->client->ps.stats[ STAT_STATE ] |= SS_KNOCKEDOVER;
+ ent->client->lastKnockedOverTime = level.time;
+ G_AddPredictableEvent( ent, EV_KNOCKOVER, 0 );
+ VectorCopy( ent->client->ps.viewangles, ent->client->ps.grapplePoint );
+
+ ent->client->ps.legsAnim =
+ ( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH1;
+ ent->client->ps.torsoAnim =
+ ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH1;
}
/*
diff --git a/src/game/g_local.h b/src/game/g_local.h
index bacf2f82..7e70f23d 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -327,8 +327,6 @@ struct gclient_s {
int switchTeamTime; // time the player switched teams
- gentity_t *torch; //TA: torch entity ( NULL if switched off )
-
// timeResidual is used to handle events that happen every second
// like health / armor countdowns and regeneration
//TA: two timers, one every 100 msecs, another every sec
@@ -346,6 +344,8 @@ struct gclient_s {
int lastLockTime;
int lastSlowTime;
int lastBoostedTime;
+ int lastKnockedOverTime;
+ int lastGetUpTime;
int pouncePayload; //TA: amount of damage pounce attack will do
qboolean allowedToPounce;
diff --git a/src/game/g_misc.c b/src/game/g_misc.c
index 5fcc9ed6..3562a142 100644
--- a/src/game/g_misc.c
+++ b/src/game/g_misc.c
@@ -335,24 +335,6 @@ void SP_shooter_grenade( gentity_t *ent ) {
======================================================================
*/
-//TA: position/colour/intensity calculating function
-void ShineTorch( gentity_t *self )
-{
- vec3_t origin, angles;
-
- VectorCopy( self->parent->s.pos.trBase, origin );
- VectorCopy( self->parent->s.apos.trBase, angles );
-
- G_SetOrigin( self, origin );
-
- VectorCopy( angles, self->s.apos.trBase );
-
- //so we can use the predicted values client side if available
- self->s.clientNum = self->parent->s.number;
-
- trap_LinkEntity( self );
-}
-
//TA: use function for spriter
void SP_use_spriter( gentity_t *self, gentity_t *other, gentity_t *activator )
{
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 59fe1877..fc32b16c 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -623,7 +623,6 @@ void poisonCloud( gentity_t *ent )
vec3_t mins, maxs, dir;
int i, num;
gentity_t *humanPlayer;
- float modifier = 1.0f;
VectorAdd( ent->client->ps.origin, range, maxs );
VectorSubtract( ent->client->ps.origin, range, mins );
@@ -635,9 +634,12 @@ void poisonCloud( gentity_t *ent )
if( humanPlayer->client && humanPlayer->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
- humanPlayer->client->ps.stats[ STAT_STATE ] |= SS_POISONCLOUDED;
- humanPlayer->client->lastPoisonCloudedTime = level.time;
- G_AddPredictableEvent( humanPlayer, EV_POISONCLOUD, 0 );
+ if( !( humanPlayer->client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED ) )
+ {
+ humanPlayer->client->ps.stats[ STAT_STATE ] |= SS_POISONCLOUDED;
+ humanPlayer->client->lastPoisonCloudedTime = level.time;
+ G_AddPredictableEvent( humanPlayer, EV_POISONCLOUD, 0 );
+ }
}
}
}
@@ -863,6 +865,56 @@ void directZapFire( gentity_t *ent )
}
}
+
+/*
+======================================================================
+
+GROUND POUND
+
+======================================================================
+*/
+
+/*
+===============
+groundPound
+===============
+*/
+void groundPound( gentity_t *ent )
+{
+ int entityList[ MAX_GENTITIES ];
+ vec3_t range = { 200, 200, 200 };
+ vec3_t mins, maxs, dir;
+ int i, num;
+ gentity_t *humanPlayer;
+
+ VectorAdd( ent->client->ps.origin, range, maxs );
+ VectorSubtract( ent->client->ps.origin, range, mins );
+
+ num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES );
+ for( i = 0; i < num; i++ )
+ {
+ humanPlayer = &g_entities[ entityList[ i ] ];
+
+ if( humanPlayer->client && humanPlayer->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ {
+ if( !( humanPlayer->client->ps.stats[ STAT_STATE ] & SS_KNOCKEDOVER ) )
+ {
+ humanPlayer->client->ps.stats[ STAT_STATE ] |= SS_KNOCKEDOVER;
+ humanPlayer->client->lastKnockedOverTime = level.time;
+ G_AddPredictableEvent( humanPlayer, EV_KNOCKOVER, 0 );
+
+ VectorCopy( humanPlayer->client->ps.viewangles, humanPlayer->client->ps.grapplePoint );
+
+ //FIXME: fallover anim
+ humanPlayer->client->ps.legsAnim =
+ ( ( humanPlayer->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH1;
+ humanPlayer->client->ps.torsoAnim =
+ ( ( humanPlayer->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | BOTH_DEATH1;
+ }
+ }
+ }
+}
+
//======================================================================
/*
@@ -907,6 +959,9 @@ void FireWeapon3( gentity_t *ent )
case WP_POUNCE_UPG:
slowBlobFire( ent );
break;
+ case WP_GROUND_POUND:
+ slowBlobFire( ent );
+ break;
default:
break;
@@ -946,9 +1001,14 @@ void FireWeapon2( gentity_t *ent )
case WP_DIRECT_ZAP:
areaZapFire( ent );
break;
+ case WP_GROUND_POUND:
+ groundPound( ent );
+ break;
+
case WP_LUCIFER_CANON:
LCChargeFire( ent, qtrue );
break;
+
case WP_ABUILD:
case WP_ABUILD2:
case WP_HBUILD:
@@ -982,9 +1042,24 @@ void FireWeapon( gentity_t *ent )
// fire the specific weapon
switch( ent->s.weapon )
{
- case WP_TESLAGEN:
- teslaFire( ent );
+ case WP_GRAB_CLAW:
+ case WP_GRAB_CLAW_UPG:
+ meleeAttack( ent, 32.0f, 5 );
+ break;
+ case WP_POUNCE:
+ case WP_POUNCE_UPG:
+ meleeAttack( ent, 32.0f, 50 );
+ break;
+ case WP_AREA_ZAP:
+ areaZapFire( ent );
break;
+ case WP_DIRECT_ZAP:
+ directZapFire( ent );
+ break;
+ case WP_GROUND_POUND:
+ meleeAttack( ent, 32.0f, 150 );
+ break;
+
case WP_MACHINEGUN:
bulletFire( ent, MACHINEGUN_SPREAD, MACHINEGUN_DAMAGE, MOD_MACHINEGUN );
break;
@@ -1003,23 +1078,6 @@ void FireWeapon( gentity_t *ent )
case WP_MASS_DRIVER:
massDriverFire( ent );
break;
- case WP_LOCKBLOB_LAUNCHER:
- lockBlobLauncherFire( ent );
- break;
- case WP_GRAB_CLAW:
- case WP_GRAB_CLAW_UPG:
- meleeAttack( ent, 32.0f, 5 );
- break;
- case WP_POUNCE:
- case WP_POUNCE_UPG:
- meleeAttack( ent, 32.0f, 50 );
- break;
- case WP_AREA_ZAP:
- areaZapFire( ent );
- break;
- case WP_DIRECT_ZAP:
- directZapFire( ent );
- break;
case WP_LUCIFER_CANON:
LCChargeFire( ent, qfalse );
break;
@@ -1029,6 +1087,14 @@ void FireWeapon( gentity_t *ent )
case WP_PAIN_SAW:
painSawFire( ent );
break;
+
+ case WP_LOCKBLOB_LAUNCHER:
+ lockBlobLauncherFire( ent );
+ break;
+ case WP_TESLAGEN:
+ teslaFire( ent );
+ break;
+
case WP_ABUILD:
buildFire( ent, MN_A_BUILD );
break;