summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2005-06-05 22:16:54 +0000
committerTim Angus <tim@ngus.net>2005-06-05 22:16:54 +0000
commitfb6006e34c1fe83acfb7976e50cb2f498e9c70b6 (patch)
treeb8b3f26b52c3b2e71b51d40ff84e86b5bfb9d52d
parent47221c9c78f4a027211a041eb2ad527339b4d54b (diff)
* Added flashing alien icon if already at maximum class
* Improved scanner render and refactored scanner code * Added animated projectiles * Grenade * Changed model names to be human name agnostic * Added sounds for lev1 grab and lev4 charge * Added sound for failed evolution * Added battery pack rendering code * Added functionality to particle system to allow attachment of particle systems to particles (for nice explosions) * Implemented CG_FileExists * Added some code to gracefully handle missing sounds (easier than making the sounds :D) * cg_drawBBOX now draws player BBOXen * Renamed the alien classes (now done in class override scripts) * Implemented Vector4Add * The usual assorted bug fixes
-rw-r--r--src/cgame/cg_draw.c56
-rw-r--r--src/cgame/cg_ents.c121
-rw-r--r--src/cgame/cg_event.c92
-rw-r--r--src/cgame/cg_local.h41
-rw-r--r--src/cgame/cg_main.c38
-rw-r--r--src/cgame/cg_particles.c251
-rw-r--r--src/cgame/cg_players.c57
-rw-r--r--src/cgame/cg_scanner.c177
-rw-r--r--src/cgame/cg_view.c24
-rw-r--r--src/cgame/cg_weapons.c32
-rw-r--r--src/game/bg_misc.c236
-rw-r--r--src/game/bg_pmove.c41
-rw-r--r--src/game/bg_public.h75
-rw-r--r--src/game/g_active.c115
-rw-r--r--src/game/g_buildable.c16
-rw-r--r--src/game/g_client.c50
-rw-r--r--src/game/g_cmds.c34
-rw-r--r--src/game/g_combat.c32
-rw-r--r--src/game/g_local.h3
-rw-r--r--src/game/g_missile.c67
-rw-r--r--src/game/g_weapon.c239
-rw-r--r--src/game/q_shared.h1
-rw-r--r--src/game/tremulous.h212
-rw-r--r--src/ui/ui_main.c14
24 files changed, 1397 insertions, 627 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 88e1ffc0..a2b2186f 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -533,6 +533,35 @@ void CG_SetPrintString( int type, const char *p )
}
}
+/*
+===============
+CG_AtHighestClass
+
+Is the local client at the highest class possible?
+===============
+*/
+static qboolean CG_AtHighestClass( void )
+{
+ int i;
+ qboolean superiorClasses = qfalse;
+
+ for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
+ {
+ if( BG_ClassCanEvolveFromTo(
+ cg.predictedPlayerState.stats[ STAT_PCLASS ], i,
+ ALIEN_MAX_KILLS, 0 ) >= 0 &&
+ BG_FindStagesForClass( i, cgs.alienStage ) )
+ {
+ superiorClasses = qtrue;
+ break;
+ }
+ }
+
+ return !superiorClasses;
+}
+
+#define NO_CREDITS_TIME 2000
+
static void CG_DrawPlayerCreditsValue( rectDef_t *rect, vec4_t color, qboolean padding )
{
int value;
@@ -550,6 +579,16 @@ static void CG_DrawPlayerCreditsValue( rectDef_t *rect, vec4_t color, qboolean p
value = ps->persistant[ PERS_CREDIT ];
if( value > -1 )
{
+ if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS &&
+ !CG_AtHighestClass( ) )
+ {
+ if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME )
+ {
+ if( ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) % 2 )
+ color[ 3 ] = 0.0f;
+ }
+ }
+
trap_R_SetColor( color );
if( padding )
@@ -975,10 +1014,10 @@ static void CG_DrawAlienSense( rectDef_t *rect )
CG_DrawHumanScanner
==============
*/
-static void CG_DrawHumanScanner( rectDef_t *rect, qhandle_t shader )
+static void CG_DrawHumanScanner( rectDef_t *rect, qhandle_t shader, vec4_t color )
{
if( BG_InventoryContainsUpgrade( UP_HELMET, cg.snap->ps.stats ) )
- CG_Scanner( rect, shader );
+ CG_Scanner( rect, shader, color );
}
@@ -1065,7 +1104,7 @@ static void CG_DrawPlayerBuildTimer( rectDef_t *rect, vec4_t color )
if( cg.time - cg.lastBuildAttempt <= BUILD_DELAY_TIME )
{
- if( ( cg.time / 300 ) % 2 )
+ if( ( ( cg.time - cg.lastBuildAttempt ) / 300 ) % 2 )
{
color[ 0 ] = 1.0f;
color[ 1 ] = color[ 2 ] = 0.0f;
@@ -2192,6 +2231,15 @@ void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color )
}
}
+ if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS && CG_AtHighestClass( ) )
+ {
+ if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME )
+ {
+ if( ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) % 2 )
+ color[ 3 ] = 0.0f;
+ }
+ }
+
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].weaponIcon );
trap_R_SetColor( NULL );
@@ -2426,7 +2474,7 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
CG_DrawAlienSense( &rect );
break;
case CG_PLAYER_HUMAN_SCANNER:
- CG_DrawHumanScanner( &rect, shader );
+ CG_DrawHumanScanner( &rect, shader, color );
break;
case CG_PLAYER_USABLE_BUILDABLE:
CG_DrawUsableBuildable( &rect, shader, color );
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c
index 01314df0..1b4a1639 100644
--- a/src/cgame/cg_ents.c
+++ b/src/cgame/cg_ents.c
@@ -347,14 +347,15 @@ CG_Missile
*/
static void CG_Missile( centity_t *cent )
{
- refEntity_t ent;
- entityState_t *es;
- const weaponInfo_t *wi;
- vec3_t up;
- float fraction;
- int index;
- weapon_t weapon;
- weaponMode_t weaponMode;
+ refEntity_t ent;
+ entityState_t *es;
+ const weaponInfo_t *wi;
+ vec3_t up;
+ float fraction;
+ int index;
+ weapon_t weapon;
+ weaponMode_t weaponMode;
+ const weaponInfoMode_t *wim;
es = &cent->currentState;
@@ -365,26 +366,28 @@ static void CG_Missile( centity_t *cent )
wi = &cg_weapons[ weapon ];
weaponMode = es->generic1;
+ wim = &wi->wim[ weaponMode ];
+
// calculate the axis
VectorCopy( es->angles, cent->lerpAngles );
// add dynamic light
- if( wi->wim[ weaponMode ].missileDlight )
+ if( wim->missileDlight )
{
- trap_R_AddLightToScene( cent->lerpOrigin, wi->wim[ weaponMode ].missileDlight,
- wi->wim[ weaponMode ].missileDlightColor[ 0 ],
- wi->wim[ weaponMode ].missileDlightColor[ 1 ],
- wi->wim[ weaponMode ].missileDlightColor[ 2 ] );
+ trap_R_AddLightToScene( cent->lerpOrigin, wim->missileDlight,
+ wim->missileDlightColor[ 0 ],
+ wim->missileDlightColor[ 1 ],
+ wim->missileDlightColor[ 2 ] );
}
// add missile sound
- if( wi->wim[ weaponMode ].missileSound )
+ if( wim->missileSound )
{
vec3_t velocity;
BG_EvaluateTrajectoryDelta( &cent->currentState.pos, cg.time, velocity );
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, wi->wim[ weaponMode ].missileSound );
+ trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, wim->missileSound );
}
// create the render entity
@@ -392,12 +395,12 @@ static void CG_Missile( centity_t *cent )
VectorCopy( cent->lerpOrigin, ent.origin );
VectorCopy( cent->lerpOrigin, ent.oldorigin );
- if( wi->wim[ weaponMode ].usesSpriteMissle )
+ if( wim->usesSpriteMissle )
{
ent.reType = RT_SPRITE;
- ent.radius = wi->wim[ weaponMode ].missileSpriteSize;
+ ent.radius = wim->missileSpriteSize;
ent.rotation = 0;
- ent.customShader = wi->wim[ weaponMode ].missileSprite;
+ ent.customShader = wim->missileSprite;
ent.shaderRGBA[ 0 ] = 0xFF;
ent.shaderRGBA[ 1 ] = 0xFF;
ent.shaderRGBA[ 2 ] = 0xFF;
@@ -405,22 +408,42 @@ static void CG_Missile( centity_t *cent )
}
else
{
- ent.hModel = wi->wim[ weaponMode ].missileModel;
- ent.renderfx = wi->wim[ weaponMode ].missileRenderfx | RF_NOSHADOW;
+ ent.hModel = wim->missileModel;
+ ent.renderfx = wim->missileRenderfx | RF_NOSHADOW;
// convert direction of travel into axis
if( VectorNormalize2( es->pos.trDelta, ent.axis[ 0 ] ) == 0 )
ent.axis[ 0 ][ 2 ] = 1;
// spin as it moves
- if( es->pos.trType != TR_STATIONARY && wi->wim[ weaponMode ].missileRotates )
+ if( es->pos.trType != TR_STATIONARY && wim->missileRotates )
RotateAroundDirection( ent.axis, cg.time / 4 );
else
RotateAroundDirection( ent.axis, es->time );
+
+ if( wim->missileAnimates )
+ {
+ int timeSinceStart = cg.time - es->time;
+
+ if( wim->missileAnimLooping )
+ {
+ ent.frame = wim->missileAnimStartFrame +
+ (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate ) %
+ wim->missileAnimNumFrames;
+ }
+ else
+ {
+ ent.frame = wim->missileAnimStartFrame +
+ (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate );
+
+ if( ent.frame > ( wim->missileAnimStartFrame + wim->missileAnimNumFrames ) )
+ ent.frame = wim->missileAnimStartFrame + wim->missileAnimNumFrames;
+ }
+ }
}
//only refresh if there is something to display
- if( wi->wim[ weaponMode ].missileSprite || wi->wim[ weaponMode ].missileModel )
+ if( wim->missileSprite || wim->missileModel )
trap_R_AddRefEntityToScene( &ent );
}
@@ -1045,57 +1068,8 @@ void CG_AddPacketEntities( void )
// lerp the non-predicted value for lightning gun origins
CG_CalcEntityLerpPositions( &cg_entities[ cg.snap->ps.clientNum ] );
- //TA: "empty" item position arrays
- cg.ep.numAlienBuildables = 0;
- cg.ep.numHumanBuildables = 0;
- cg.ep.numAlienClients = 0;
- cg.ep.numHumanClients = 0;
-
- for( num = 0; num < cg.snap->numEntities; num++ )
- {
- cent = &cg_entities[ cg.snap->entities[ num ].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, cg.ep.alienBuildablePos[ cg.ep.numAlienBuildables ] );
- cg.ep.alienBuildableTimes[ cg.ep.numAlienBuildables ] = cent->miscTime;
-
- if( cg.ep.numAlienBuildables < MAX_GENTITIES )
- cg.ep.numAlienBuildables++;
- }
- else if( cent->currentState.modelindex2 == BIT_HUMANS )
- {
- VectorCopy( cent->lerpOrigin, cg.ep.humanBuildablePos[ cg.ep.numHumanBuildables ] );
-
- if( cg.ep.numHumanBuildables < MAX_GENTITIES )
- cg.ep.numHumanBuildables++;
- }
- }
- else if( cent->currentState.eType == ET_PLAYER )
- {
- int team = cent->currentState.powerups & 0x00FF;
-
- if( team == PTE_ALIENS )
- {
- VectorCopy( cent->lerpOrigin, cg.ep.alienClientPos[ cg.ep.numAlienClients ] );
-
- if( cg.ep.numAlienClients < MAX_CLIENTS )
- cg.ep.numAlienClients++;
- }
- else if( team == PTE_HUMANS )
- {
- VectorCopy( cent->lerpOrigin, cg.ep.humanClientPos[ cg.ep.numHumanClients ] );
-
- if( cg.ep.numHumanClients < MAX_CLIENTS )
- cg.ep.numHumanClients++;
- }
- }
- }
-
- //Com_Printf( "%d %d\n", cgIP.numAlienClients, cgIP.numHumanClients );
+ // scanner
+ CG_UpdateEntityPositions( );
for( num = 0; num < MAX_GENTITIES; num++ )
cg_entities[ num ].valid = qfalse;
@@ -1140,7 +1114,6 @@ void CG_AddPacketEntities( void )
switch( es->eType )
{
- case ET_PLAYER:
case ET_BUILDABLE:
case ET_MISSILE:
case ET_CORPSE:
diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c
index 9b60df70..3a1138e6 100644
--- a/src/cgame/cg_event.c
+++ b/src/cgame/cg_event.c
@@ -32,6 +32,7 @@ static void CG_Obituary( entityState_t *ent )
const char *attackerInfo;
char targetName[ 32 ];
char attackerName[ 32 ];
+ char className[ 64 ];
gender_t gender;
clientInfo_t *ci;
@@ -57,7 +58,7 @@ static void CG_Obituary( entityState_t *ent )
if( !targetInfo )
return;
- Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) - 2);
+ Q_strncpyz( targetName, Info_ValueForKey( targetInfo, "n" ), sizeof( targetName ) - 2 );
strcat( targetName, S_COLOR_WHITE );
message2 = "";
@@ -145,6 +146,15 @@ static void CG_Obituary( entityState_t *ent )
message = "irradiated himself";
break;
+ case MOD_GRENADE:
+ if( gender == GENDER_FEMALE )
+ message = "blew herself up";
+ else if( gender == GENDER_NEUTER )
+ message = "blew itself up";
+ else
+ message = "blew himself up";
+ break;
+
default:
if( gender == GENDER_FEMALE )
message = "killed herself";
@@ -221,50 +231,70 @@ static void CG_Obituary( entityState_t *ent )
message = "was caught in the fallout of";
message2 = "'s lucifer cannon";
break;
+ case MOD_GRENADE:
+ message = "couldn't escape";
+ message2 = "'s grenade";
+ break;
case MOD_ABUILDER_CLAW:
message = "should leave";
message2 = "'s buildings alone";
break;
- case MOD_SOLDIER_BITE:
+ case MOD_LEVEL0_BITE:
message = "was bitten by";
break;
- case MOD_HYDRA_CLAW:
+ case MOD_LEVEL1_CLAW:
message = "was swiped by";
- message2 = "'s hydra";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL1 ) );
+ message2 = className;
break;
- case MOD_DRAGOON_CLAW:
+ case MOD_LEVEL3_CLAW:
message = "was clawed by";
- message2 = "'s dragoon";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) );
+ message2 = className;
break;
- case MOD_DRAGOON_POUNCE:
+ case MOD_LEVEL3_POUNCE:
message = "was pounced upon by";
- message2 = "'s dragoon";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) );
+ message2 = className;
break;
- case MOD_CHIMERA_CLAW:
+ case MOD_LEVEL2_CLAW:
message = "was clawed by";
- message2 = "'s chimera";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) );
+ message2 = className;
break;
- case MOD_CHIMERA_ZAP:
+ case MOD_LEVEL2_ZAP:
message = "was zapped by";
- message2 = "'s chimera";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL3 ) );
+ message2 = className;
break;
- case MOD_BMOFO_CLAW:
+ case MOD_LEVEL4_CLAW:
message = "was mauled by";
- message2 = "'s big mofo";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) );
+ message2 = className;
break;
- case MOD_BMOFO_CHARGE:
+ case MOD_LEVEL4_CHARGE:
message = "should have gotten out of the way of";
- message2 = "'s big mofo";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL4 ) );
+ message2 = className;
break;
case MOD_POISON:
message = "should have used antitox against";
message2 = "'s poison";
break;
- case MOD_HYDRA_PCLOUD:
+ case MOD_LEVEL1_PCLOUD:
message = "was gassed by";
- message2 = "'s hydra";
+ Com_sprintf( className, 64, "'s %s",
+ BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL1 ) );
+ message2 = className;
break;
@@ -580,6 +610,22 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
break;
+ case EV_LEV1_GRAB:
+ DEBUGNAME( "EV_LEV1_GRAB" );
+ trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL1Grab );
+ break;
+
+ case EV_LEV4_CHARGE_PREPARE:
+ DEBUGNAME( "EV_LEV4_CHARGE_PREPARE" );
+ trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargePrepare );
+ break;
+
+ case EV_LEV4_CHARGE_START:
+ DEBUGNAME( "EV_LEV4_CHARGE_START" );
+ //FIXME: stop cgs.media.alienL4ChargePrepare playing here
+ trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.alienL4ChargeStart );
+ break;
+
case EV_TAUNT:
DEBUGNAME( "EV_TAUNT" );
trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*taunt.wav" ) );
@@ -882,6 +928,16 @@ void CG_EntityEvent( centity_t *cent, vec3_t position )
cg.spawnTime = cg.time;
break;
+ case EV_ALIEN_EVOLVE_FAILED:
+ DEBUGNAME( "EV_ALIEN_EVOLVE_FAILED" );
+ if( clientNum == cg.predictedPlayerState.clientNum )
+ {
+ //FIXME: change to "negative" sound
+ trap_S_StartLocalSound( cgs.media.buildableRepairedSound, CHAN_LOCAL_SOUND );
+ cg.lastEvolveAttempt = cg.time;
+ }
+ break;
+
case EV_ALIEN_ACIDTUBE:
DEBUGNAME( "EV_ALIEN_ACIDTUBE" );
{
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 1d22e308..6b93f142 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -219,6 +219,12 @@ typedef struct baseParticle_s
pLerpValues_t alpha;
pLerpValues_t rotation;
+ char childSystemName[ MAX_QPATH ];
+ qhandle_t childSystemHandle;
+
+ char onDeathSystemName[ MAX_QPATH ];
+ qhandle_t onDeathSystemHandle;
+
//particle invariant stuff
char shaderNames[ MAX_QPATH ][ MAX_SHADER_FRAMES ];
qhandle_t shaders[ MAX_SHADER_FRAMES ];
@@ -267,7 +273,8 @@ typedef enum
{
PSA_STATIC,
PSA_TAG,
- PSA_CENT_ORIGIN
+ PSA_CENT_ORIGIN,
+ PSA_PARTICLE
} psAttachmentType_t;
@@ -277,6 +284,7 @@ typedef struct psAttachment_s
qboolean tagValid;
qboolean centValid;
qboolean normalValid;
+ qboolean particleValid;
//PMT_STATIC
vec3_t origin;
@@ -342,6 +350,8 @@ typedef struct particle_s
int lastEvalTime;
+ int nextChildTime;
+
pLerpValues_t radius;
pLerpValues_t alpha;
pLerpValues_t rotation;
@@ -349,6 +359,8 @@ typedef struct particle_s
qboolean valid;
int sortKey;
+
+ particleSystem_t *childSystem;
} particle_t;
@@ -692,6 +704,11 @@ typedef struct weaponInfoMode_s
int missileSpriteSize;
qhandle_t missileParticleSystem;
qboolean missileRotates;
+ qboolean missileAnimates;
+ int missileAnimStartFrame;
+ int missileAnimNumFrames;
+ int missileAnimFrameRate;
+ int missileAnimLooping;
sfxHandle_t firingSound;
qboolean loopFireSound;
@@ -785,6 +802,10 @@ typedef struct
vec3_t humanClientPos[ MAX_CLIENTS ];
int numHumanClients;
+
+ int lastUpdateTime;
+ vec3_t origin;
+ vec3_t vangles;
} entityPos_t;
typedef struct
@@ -1013,9 +1034,8 @@ typedef struct
float mediaFraction;
float buildablesFraction;
- entityPos_t ep;
-
int lastBuildAttempt;
+ int lastEvolveAttempt;
char consoleText[ MAX_CONSOLE_TEXT ];
consoleLine_t consoleLines[ MAX_CONSOLE_LINES ];
@@ -1194,6 +1214,10 @@ typedef struct
sfxHandle_t humanBuildablePrebuild;
sfxHandle_t humanBuildableDamage[ 4 ];
+ sfxHandle_t alienL1Grab;
+ sfxHandle_t alienL4ChargePrepare;
+ sfxHandle_t alienL4ChargeStart;
+
qhandle_t cursor;
qhandle_t selectCursor;
qhandle_t sizeCursor;
@@ -1210,6 +1234,7 @@ typedef struct
qhandle_t jetpackModel;
qhandle_t jetpackFlashModel;
+ qhandle_t battpackModel;
sfxHandle_t repeaterUseSound;
@@ -1443,6 +1468,7 @@ extern vmCvar_t cg_lightFlare;
extern vmCvar_t cg_debugParticles;
extern vmCvar_t cg_debugPVS;
extern vmCvar_t cg_disableBuildWarnings;
+extern vmCvar_t cg_disableScannerPlane;
//TA: hack to get class an carriage through to UI module
extern vmCvar_t ui_currentClass;
@@ -1479,6 +1505,8 @@ void CG_EventHandling( int type );
void CG_SetScoreSelection( void *menu );
void CG_BuildSpectatorString( );
+qboolean CG_FileExists( char *filename );
+
//
// cg_view.c
@@ -1656,7 +1684,8 @@ void CG_DrawItemSelectText( rectDef_t *rect, float scale, int textStyle )
//
// cg_scanner.c
//
-void CG_Scanner( rectDef_t *rect, qhandle_t shader );
+void CG_UpdateEntityPositions( void );
+void CG_Scanner( rectDef_t *rect, qhandle_t shader, vec4_t color );
void CG_AlienSense( rectDef_t *rect );
//
@@ -1781,8 +1810,10 @@ void CG_AttachParticleSystemToCent( particleSystem_t *ps );
void CG_SetParticleSystemTag( particleSystem_t *ps, refEntity_t parent, qhandle_t model, char *tagName );
void CG_AttachParticleSystemToTag( particleSystem_t *ps );
void CG_SetParticleSystemOrigin( particleSystem_t *ps, vec3_t origin );
-void CG_AttachParticleSystemOrigin( particleSystem_t *ps );
+void CG_AttachParticleSystemToOrigin( particleSystem_t *ps );
void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal );
+void CG_AttachParticleSystemToParticle( particleSystem_t *ps );
+void CG_SetParticleSystemParentParticle( particleSystem_t *ps, particle_t *p );
void CG_AddParticles( void );
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index 782db516..1ca58707 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -201,6 +201,7 @@ vmCvar_t cg_lightFlare;
vmCvar_t cg_debugParticles;
vmCvar_t cg_debugPVS;
vmCvar_t cg_disableBuildWarnings;
+vmCvar_t cg_disableScannerPlane;
//TA: hack to get class and carriage through to UI module
vmCvar_t ui_currentClass;
@@ -305,6 +306,7 @@ static cvarTable_t cvarTable[ ] =
{ &cg_debugParticles, "cg_debugParticles", "0", CVAR_CHEAT },
{ &cg_debugPVS, "cg_debugPVS", "0", CVAR_CHEAT },
{ &cg_disableBuildWarnings, "cg_disableBuildWarnings", "0", CVAR_ARCHIVE },
+ { &cg_disableScannerPlane, "cg_disableScannerPlane", "0", CVAR_ARCHIVE },
{ &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},
{ &ui_currentClass, "ui_currentClass", "0", 0 },
@@ -569,6 +571,28 @@ const char *CG_Argv( int arg )
/*
=================
+CG_FileExists
+
+Test if a specific file exists or not
+=================
+*/
+qboolean CG_FileExists( char *filename )
+{
+ fileHandle_t f;
+
+ if( trap_FS_FOpenFile( filename, &f, FS_READ ) > 0 )
+ {
+ //file exists so close it
+ trap_FS_FCloseFile( f );
+
+ return qtrue;
+ }
+ else
+ return qfalse;
+}
+
+/*
+=================
CG_RegisterSounds
called during a precache command
@@ -587,6 +611,10 @@ static void CG_RegisterSounds( void )
cgs.media.alienOvermindDying = trap_S_RegisterSound( "sound/announcements/overminddying.wav", qtrue );
cgs.media.alienOvermindSpawns = trap_S_RegisterSound( "sound/announcements/overmindspawns.wav", qtrue );
+ cgs.media.alienL1Grab = trap_S_RegisterSound( "sound/player/level1/grab.wav", qtrue );
+ cgs.media.alienL4ChargePrepare = trap_S_RegisterSound( "sound/player/level4/charge_prepare.wav", qtrue );
+ cgs.media.alienL4ChargeStart = trap_S_RegisterSound( "sound/player/level4/charge_start.wav", qtrue );
+
cgs.media.tracerSound = trap_S_RegisterSound( "sound/weapons/machinegun/buletby1.wav", qfalse );
cgs.media.selectSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse );
cgs.media.wearOffSound = trap_S_RegisterSound( "sound/items/wearoff.wav", qfalse );
@@ -749,8 +777,7 @@ static void CG_RegisterGraphics( void )
cgs.media.creepShader = trap_R_RegisterShader( "creep" );
cgs.media.scannerBlipShader = trap_R_RegisterShader( "gfx/2d/blip" );
- cgs.media.scannerLineShader = trap_R_RegisterShader( "white" );
- /*cgs.media.scannerShader = trap_R_RegisterShader( "gfx/2d/scanner" );*/
+ cgs.media.scannerLineShader = trap_R_RegisterShader( "gfx/2d/stalk" );
cgs.media.waterBubbleShader = trap_R_RegisterShader( "waterBubble" );
@@ -958,12 +985,13 @@ static void CG_RegisterClients( void )
trap_UpdateScreen( );
}
- cgs.media.larmourHeadSkin = trap_R_RegisterSkin( "models/players/trooper/head_light.skin" );
- cgs.media.larmourLegsSkin = trap_R_RegisterSkin( "models/players/trooper/lower_light.skin" );
- cgs.media.larmourTorsoSkin = trap_R_RegisterSkin( "models/players/trooper/upper_light.skin" );
+ cgs.media.larmourHeadSkin = trap_R_RegisterSkin( "models/players/human_base/head_light.skin" );
+ cgs.media.larmourLegsSkin = trap_R_RegisterSkin( "models/players/human_base/lower_light.skin" );
+ cgs.media.larmourTorsoSkin = trap_R_RegisterSkin( "models/players/human_base/upper_light.skin" );
cgs.media.jetpackModel = trap_R_RegisterModel( "models/players/human_base/jetpack.md3" );
cgs.media.jetpackFlashModel = trap_R_RegisterModel( "models/players/human_base/jetpack_flash.md3" );
+ cgs.media.battpackModel = trap_R_RegisterModel( "models/players/human_base/battpack.md3" );
cg.charModelFraction = 1.0f;
trap_UpdateScreen( );
diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c
index 9b37382a..7f4ac64c 100644
--- a/src/cgame/cg_particles.c
+++ b/src/cgame/cg_particles.c
@@ -80,6 +80,33 @@ static void CG_SpreadVector( vec3_t v, float spread )
/*
===============
+CG_DestroyParticle
+
+Destroy an individual particle
+===============
+*/
+static void CG_DestroyParticle( particle_t *p )
+{
+ //this particle has an onDeath particle system attached
+ if( p->class->onDeathSystemName[ 0 ] != '\0' )
+ {
+ particleSystem_t *ps;
+
+ ps = CG_SpawnNewParticleSystem( p->class->childSystemHandle );
+
+ if( CG_IsParticleSystemValid( &ps ) )
+ {
+ CG_SetParticleSystemOrigin( ps, p->origin );
+ CG_SetParticleSystemNormal( ps, p->velocity );
+ CG_AttachParticleSystemToOrigin( ps );
+ }
+ }
+
+ p->valid = qfalse;
+}
+
+/*
+===============
CG_SpawnNewParticle
Introduce a new particle into the world
@@ -146,6 +173,32 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p
VectorCopy( cent->lerpOrigin, p->origin );
break;
+
+ case PSA_PARTICLE:
+ if( !ps->attachment.particleValid )
+ return NULL;
+
+ //find a particle which has ps as a child
+ for( j = 0; j < MAX_PARTICLES; j++ )
+ {
+ particle_t *parentParticle = &particles[ j ];
+
+ if( parentParticle->valid && parentParticle->childSystem == ps )
+ {
+ VectorCopy( parentParticle->origin, p->origin );
+ break;
+ }
+ }
+
+ if( j == MAX_PARTICLES )
+ {
+ //didn't find the parent, so it's probably died already
+
+ //prevent further (expensive) attempts at particle creation
+ ps->attachment.particleValid = qfalse;
+ return NULL;
+ }
+ break;
}
VectorAdd( p->origin, bp->displacement, p->origin );
@@ -191,18 +244,18 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p
break;
- case PMT_NORMAL:
-
- if( !ps->attachment.normalValid )
- return NULL;
-
- VectorCopy( ps->attachment.normal, p->velocity );
+ case PMT_NORMAL:
+
+ if( !ps->attachment.normalValid )
+ return NULL;
+
+ VectorCopy( ps->attachment.normal, p->velocity );
- //normal displacement
- VectorNormalize( p->velocity );
- VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin );
-
- break;
+ //normal displacement
+ VectorNormalize( p->velocity );
+ VectorMA( p->origin, bp->normalDisplacement, p->velocity, p->origin );
+
+ break;
}
VectorNormalize( p->velocity );
@@ -222,6 +275,21 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p
p->valid = qtrue;
+ //this particle has a child particle system attached
+ if( bp->childSystemName[ 0 ] != '\0' )
+ {
+ particleSystem_t *ps;
+
+ ps = CG_SpawnNewParticleSystem( bp->childSystemHandle );
+
+ if( CG_IsParticleSystemValid( &ps ) )
+ {
+ CG_SetParticleSystemParentParticle( ps, p );
+ CG_SetParticleSystemNormal( ps, p->velocity );
+ CG_AttachParticleSystemToParticle( ps );
+ }
+ }
+
break;
}
}
@@ -418,6 +486,10 @@ qhandle_t CG_RegisterParticleSystem( char *name )
if( !strcmp( bps->name, name ) )
{
+ //already registered
+ if( bps->registered )
+ return i + 1;
+
for( j = 0; j < bps->numEjectors; j++ )
{
bpe = bps->ejectors[ j ];
@@ -428,6 +500,21 @@ qhandle_t CG_RegisterParticleSystem( char *name )
for( k = 0; k < bp->numFrames; k++ )
bp->shaders[ k ] = trap_R_RegisterShader( bp->shaderNames[ k ] );
+
+ //recursively register any children
+ if( bp->childSystemName[ 0 ] != '\0' )
+ {
+ //don't care about a handle for children since
+ //the system deals with it
+ CG_RegisterParticleSystem( bp->childSystemName );
+ }
+
+ if( bp->onDeathSystemName[ 0 ] != '\0' )
+ {
+ //don't care about a handle for children since
+ //the system deals with it
+ CG_RegisterParticleSystem( bp->onDeathSystemName );
+ }
}
}
@@ -980,6 +1067,26 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p )
continue;
}
+ else if( !Q_stricmp( token, "childSystem" ) )
+ {
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( bp->childSystemName, token, MAX_QPATH );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "onDeathSystem" ) )
+ {
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( bp->onDeathSystemName, token, MAX_QPATH );
+
+ continue;
+ }
else if( !Q_stricmp( token, "}" ) )
return qtrue; //reached the end of this particle
else
@@ -1306,13 +1413,34 @@ Load particle systems from .particle files
*/
void CG_LoadParticleSystems( void )
{
- int i;
+ int i, j;
const char *s[ MAX_PARTICLE_FILES ];
+ //clear out the old
numBaseParticleSystems = 0;
numBaseParticleEjectors = 0;
numBaseParticles = 0;
+ for( i = 0; i < MAX_BASEPARTICLE_SYSTEMS; i++ )
+ {
+ baseParticleSystem_t *bps = &baseParticleSystems[ i ];
+ memset( bps, 0, sizeof( baseParticleSystem_t ) );
+ }
+
+ for( i = 0; i < MAX_BASEPARTICLE_EJECTORS; i++ )
+ {
+ baseParticleEjector_t *bpe = &baseParticleEjectors[ i ];
+ memset( bpe, 0, sizeof( baseParticleEjector_t ) );
+ }
+
+ for( i = 0; i < MAX_BASEPARTICLES; i++ )
+ {
+ baseParticle_t *bp = &baseParticles[ i ];
+ memset( bp, 0, sizeof( baseParticle_t ) );
+ }
+
+
+ //and bring in the new
for( i = 0; i < MAX_PARTICLE_FILES; i++ )
{
s[ i ] = CG_ConfigString( CS_PARTICLE_FILES + i );
@@ -1325,6 +1453,62 @@ void CG_LoadParticleSystems( void )
else
break;
}
+
+ //connect any child systems to their psHandle
+ for( i = 0; i < numBaseParticles; i++ )
+ {
+ baseParticle_t *bp = &baseParticles[ i ];
+
+ if( bp->childSystemName[ 0 ] )
+ {
+ //particle class has a child, resolve the name
+ for( j = 0; j < numBaseParticleSystems; j++ )
+ {
+ baseParticleSystem_t *bps = &baseParticleSystems[ j ];
+
+ if( !Q_stricmp( bps->name, bp->childSystemName ) )
+ {
+ //FIXME: add checks for cycles and infinite children
+
+ bp->childSystemHandle = j + 1;
+
+ break;
+ }
+ }
+
+ if( j == numBaseParticleSystems )
+ {
+ //couldn't find named particle system
+ CG_Printf( S_COLOR_YELLOW "WARNING: failed to find child %s\n", bp->childSystemName );
+ bp->childSystemName[ 0 ] = '\0';
+ }
+ }
+
+ if( bp->onDeathSystemName[ 0 ] )
+ {
+ //particle class has a child, resolve the name
+ for( j = 0; j < numBaseParticleSystems; j++ )
+ {
+ baseParticleSystem_t *bps = &baseParticleSystems[ j ];
+
+ if( !Q_stricmp( bps->name, bp->onDeathSystemName ) )
+ {
+ //FIXME: add checks for cycles and infinite children
+
+ bp->onDeathSystemHandle = j + 1;
+
+ break;
+ }
+ }
+
+ if( j == numBaseParticleSystems )
+ {
+ //couldn't find named particle system
+ CG_Printf( S_COLOR_YELLOW "WARNING: failed to find onDeath system %s\n", bp->onDeathSystemName );
+ bp->onDeathSystemName[ 0 ] = '\0';
+ }
+ }
+ }
}
@@ -1447,6 +1631,44 @@ void CG_SetParticleSystemOrigin( particleSystem_t *ps, vec3_t origin )
/*
===============
+CG_AttachParticleSystemToParticle
+
+Attach a particle system to a particle
+===============
+*/
+void CG_AttachParticleSystemToParticle( particleSystem_t *ps )
+{
+ if( ps == NULL || !ps->valid )
+ {
+ CG_Printf( S_COLOR_YELLOW "WARNING: tried to modify a NULL particle system\n" );
+ return;
+ }
+
+ ps->attachType = PSA_PARTICLE;
+ ps->attached = qtrue;
+}
+
+/*
+===============
+CG_SetParticleSystemParentParticle
+
+Set a particle system attachment means
+===============
+*/
+void CG_SetParticleSystemParentParticle( particleSystem_t *ps, particle_t *p )
+{
+ if( ps == NULL || !ps->valid )
+ {
+ CG_Printf( S_COLOR_YELLOW "WARNING: tried to modify a NULL particle system\n" );
+ return;
+ }
+
+ ps->attachment.particleValid = qtrue;
+ p->childSystem = ps;
+}
+
+/*
+===============
CG_SetParticleSystemNormal
Set a particle system attachment means
@@ -1462,6 +1684,7 @@ void CG_SetParticleSystemNormal( particleSystem_t *ps, vec3_t normal )
ps->attachment.normalValid = qtrue;
VectorCopy( normal, ps->attachment.normal );
+ VectorNormalize( ps->attachment.normal );
}
@@ -1760,7 +1983,7 @@ static void CG_EvaluateParticlePhysics( particle_t *p )
if( ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) ||
( bp->cullOnStartSolid && trace.startsolid ) || bp->bounceCull )
{
- p->valid = qfalse;
+ CG_DestroyParticle( p );
return;
}
@@ -1979,7 +2202,7 @@ void CG_AddParticles( void )
CG_RenderParticle( p );
}
else
- p->valid = qfalse;
+ CG_DestroyParticle( p );
}
}
diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c
index 2a1ca0f4..0dadbb8f 100644
--- a/src/cgame/cg_players.c
+++ b/src/cgame/cg_players.c
@@ -557,9 +557,33 @@ static void CG_LoadClientInfo( clientInfo_t *ci )
if( !s )
break;
- ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse );
- if( !ci->sounds[ i ] )
- ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse );
+ // fanny about a bit with sounds that are missing
+ if( !CG_FileExists( va( "sound/player/%s/%s", dir, s + 1 ) ) )
+ {
+ //file doesn't exist
+
+ if( i == 11 || i == 8 ) //fall or falling
+ {
+ ci->sounds[ i ] = trap_S_RegisterSound( "sound/null.wav", qfalse );
+ }
+ else
+ {
+ if( i == 9 ) //gasp
+ s = cg_customSoundNames[ 7 ]; //pain100_1
+ else if( i == 10 ) //drown
+ s = cg_customSoundNames[ 0 ]; //death1
+
+ ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse );
+ if( !ci->sounds[ i ] )
+ ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse );
+ }
+ }
+ else
+ {
+ ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse );
+ if( !ci->sounds[ i ] )
+ ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse );
+ }
}
if( ci->footsteps == FOOTSTEP_CUSTOM )
@@ -1526,6 +1550,7 @@ static void CG_PlayerUpgrades( centity_t *cent, refEntity_t *torso )
{
int held, active;
refEntity_t jetpack;
+ refEntity_t battpack;
refEntity_t flash;
entityState_t *es = &cent->currentState;
@@ -1627,6 +1652,24 @@ static void CG_PlayerUpgrades( centity_t *cent, refEntity_t *torso )
cent->jetPackState = JPS_OFF;
}
+ if( held & ( 1 << UP_BATTPACK ) )
+ {
+ memset( &battpack, 0, sizeof( battpack ) );
+ VectorCopy( torso->lightingOrigin, battpack.lightingOrigin );
+ battpack.shadowPlane = torso->shadowPlane;
+ battpack.renderfx = torso->renderfx;
+
+ battpack.hModel = cgs.media.battpackModel;
+
+ //identity matrix
+ AxisCopy( axisDefault, battpack.axis );
+
+ //FIXME: change to tag_back when it exists
+ CG_PositionRotatedEntityOnTag( &battpack, torso, torso->hModel, "tag_head" );
+
+ trap_R_AddRefEntityToScene( &battpack );
+ }
+
if( es->eFlags & EF_BLOBLOCKED )
{
vec3_t temp, origin, up = { 0.0f, 0.0f, 1.0f };
@@ -2044,6 +2087,14 @@ void CG_Player( centity_t *cent )
return;
}
+ if( cg_drawBBOX.integer )
+ {
+ vec3_t mins, maxs;
+
+ BG_FindBBoxForClass( class, mins, maxs, NULL, NULL, NULL );
+ CG_DrawBoundingBox( cent->lerpOrigin, mins, maxs );
+ }
+
memset( &legs, 0, sizeof( legs ) );
memset( &torso, 0, sizeof( torso ) );
memset( &head, 0, sizeof( head ) );
diff --git a/src/cgame/cg_scanner.c b/src/cgame/cg_scanner.c
index 2c410f20..16e79a51 100644
--- a/src/cgame/cg_scanner.c
+++ b/src/cgame/cg_scanner.c
@@ -13,20 +13,121 @@
#include "cg_local.h"
+static entityPos_t entityPositions;
+
+#define HUMAN_SCANNER_UPDATE_PERIOD 300
+
+/*
+=============
+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;
- RotatePointAroundVector( drawOrigin, up, origin, -cg.refdefViewAngles[ 1 ] - 90 );
+ 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 );
+
+ colour[ 3 ] *= alphaMod;
+
+ if( colour[ 3 ] > 1.0f )
+ colour[ 3 ] = 1.0f;
+ else if( colour[ 3 ] < 0.0f )
+ colour[ 3 ] = 0.0f;
+
trap_R_SetColor( colour );
if( drawOrigin[ 2 ] > 0 )
@@ -47,6 +148,13 @@ static void CG_DrawBlips( rectDef_t *rect, vec3_t origin, vec4_t colour )
#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;
@@ -68,7 +176,7 @@ static void CG_DrawDir( rectDef_t *rect, vec3_t origin, vec4_t colour )
else
VectorSet( normal, 0.0f, 0.0f, 1.0f );
- AngleVectors( cg.refdefViewAngles, view, NULL, NULL );
+ AngleVectors( entityPositions.vangles, view, NULL, NULL );
ProjectPointOnPlane( noZOrigin, origin, normal );
ProjectPointOnPlane( noZview, view, normal );
@@ -107,23 +215,23 @@ void CG_AlienSense( rectDef_t *rect )
vec4_t buildable = { 1.0f, 0.0f, 0.0f, 0.7f };
vec4_t client = { 0.0f, 0.0f, 1.0f, 0.7f };
- VectorCopy( cg.refdef.vieworg, origin );
+ VectorCopy( entityPositions.origin, origin );
//draw human buildables
- for( i = 0; i < cg.ep.numHumanBuildables; i++ )
+ for( i = 0; i < entityPositions.numHumanBuildables; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanBuildablePos[ i ], origin, relOrigin );
+ VectorSubtract( entityPositions.humanBuildablePos[ i ], origin, relOrigin );
if( VectorLength( relOrigin ) < ALIENSENSE_RANGE )
CG_DrawDir( rect, relOrigin, buildable );
}
//draw human clients
- for( i = 0; i < cg.ep.numHumanClients; i++ )
+ for( i = 0; i < entityPositions.numHumanClients; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanClientPos[ i ], origin, relOrigin );
+ VectorSubtract( entityPositions.humanClientPos[ i ], origin, relOrigin );
if( VectorLength( relOrigin ) < ALIENSENSE_RANGE )
CG_DrawDir( rect, relOrigin, client );
@@ -135,95 +243,104 @@ void CG_AlienSense( rectDef_t *rect )
CG_Scanner
=============
*/
-void CG_Scanner( rectDef_t *rect, qhandle_t shader )
+void CG_Scanner( rectDef_t *rect, qhandle_t shader, vec4_t color )
{
int i;
vec3_t origin;
vec3_t relOrigin;
- vec4_t hIabove = { 0.0f, 1.0f, 0.0f, 1.0f };
- vec4_t hIbelow = { 0.0f, 0.5f, 0.0f, 1.0f };
- vec4_t aIabove = { 1.0f, 0.0f, 0.0f, 1.0f };
- vec4_t aIbelow = { 0.5f, 0.0f, 0.0f, 1.0f };
+ 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( cg.refdef.vieworg, origin );
+ VectorCopy( entityPositions.origin, origin );
//draw human buildables below scanner plane
- for( i = 0; i < cg.ep.numHumanBuildables; i++ )
+ for( i = 0; i < entityPositions.numHumanBuildables; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanBuildablePos[ i ], origin, 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 < cg.ep.numAlienBuildables; i++ )
+ for( i = 0; i < entityPositions.numAlienBuildables; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.alienBuildablePos[ i ], origin, 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 < cg.ep.numHumanClients; i++ )
+ for( i = 0; i < entityPositions.numHumanClients; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanClientPos[ i ], origin, 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 < cg.ep.numAlienClients; i++ )
+ for( i = 0; i < entityPositions.numAlienClients; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.alienClientPos[ i ], origin, relOrigin );
+ VectorSubtract( entityPositions.alienClientPos[ i ], origin, relOrigin );
if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] < 0 ) )
CG_DrawBlips( rect, relOrigin, aIbelow );
}
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ 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 < cg.ep.numHumanBuildables; i++ )
+ for( i = 0; i < entityPositions.numHumanBuildables; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanBuildablePos[ i ], origin, 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 < cg.ep.numAlienBuildables; i++ )
+ for( i = 0; i < entityPositions.numAlienBuildables; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.alienBuildablePos[ i ], origin, 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 < cg.ep.numHumanClients; i++ )
+ for( i = 0; i < entityPositions.numHumanClients; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.humanClientPos[ i ], origin, 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 < cg.ep.numAlienClients; i++ )
+ for( i = 0; i < entityPositions.numAlienClients; i++ )
{
VectorClear( relOrigin );
- VectorSubtract( cg.ep.alienClientPos[ i ], origin, relOrigin );
+ VectorSubtract( entityPositions.alienClientPos[ i ], origin, relOrigin );
if( VectorLength( relOrigin ) < HELMET_RANGE && ( relOrigin[ 2 ] > 0 ) )
CG_DrawBlips( rect, relOrigin, aIabove );
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index bb0816d9..d3173024 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -463,19 +463,19 @@ static void CG_OffsetFirstPersonView( void )
bob2 = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
-#define BMOFO_FEEDBACK 10.0f
+#define LEVEL4_FEEDBACK 10.0f
//give a charging player some feedback
- if( ps->weapon == WP_BIGMOFO )
+ if( ps->weapon == WP_ALEVEL4 )
{
if( ps->stats[ STAT_MISC ] > 0 )
{
- float fraction = (float)ps->stats[ STAT_MISC ] / (float)BMOFO_CHARGE_TIME;
+ float fraction = (float)ps->stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME;
if( fraction > 1.0f )
fraction = 1.0f;
- bob2 *= ( 1.0f + fraction * BMOFO_FEEDBACK );
+ bob2 *= ( 1.0f + fraction * LEVEL4_FEEDBACK );
}
}
@@ -499,11 +499,11 @@ static void CG_OffsetFirstPersonView( void )
angles[ ROLL ] += delta;
}
-#define DRAGOON_FEEDBACK 20.0f
+#define LEVEL3_FEEDBACK 20.0f
//provide some feedback for pouncing
- if( cg.predictedPlayerState.weapon == WP_DRAGOON ||
- cg.predictedPlayerState.weapon == WP_DRAGOON_UPG )
+ if( cg.predictedPlayerState.weapon == WP_ALEVEL3 ||
+ cg.predictedPlayerState.weapon == WP_ALEVEL3_UPG )
{
if( cg.predictedPlayerState.stats[ STAT_MISC ] > 0 )
{
@@ -513,14 +513,14 @@ static void CG_OffsetFirstPersonView( void )
AngleVectors( angles, forward, NULL, NULL );
VectorNormalize( forward );
- fraction1 = (float)( cg.time - cg.weapon2Time ) / (float)DRAGOON_POUNCE_TIME;
+ fraction1 = (float)( cg.time - cg.weapon2Time ) / (float)LEVEL3_POUNCE_TIME;
if( fraction1 > 1.0f )
fraction1 = 1.0f;
fraction2 = -sin( fraction1 * M_PI / 2 );
- VectorMA( origin, DRAGOON_FEEDBACK * fraction2, forward, origin );
+ VectorMA( origin, LEVEL3_FEEDBACK * fraction2, forward, origin );
}
}
@@ -583,8 +583,8 @@ static void CG_OffsetFirstPersonView( void )
float fraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 2 * PCLOUD_ROLL_FREQUENCY );
float pitchFraction = sin( ( (float)cg.time / 1000.0f ) * M_PI * 5 * PCLOUD_ROLL_FREQUENCY );
- fraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
- pitchFraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
+ fraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME );
+ pitchFraction *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME );
angles[ ROLL ] += fraction * PCLOUD_ROLL_AMPLITUDE;
angles[ YAW ] += fraction * PCLOUD_ROLL_AMPLITUDE;
@@ -795,7 +795,7 @@ static int CG_CalcFov( void )
{
phase = cg.time / 1000.0 * PCLOUD_ZOOM_FREQUENCY * M_PI * 2;
v = PCLOUD_ZOOM_AMPLITUDE * sin( phase );
- v *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)HYDRA_PCLOUD_TIME );
+ v *= 1.0f - ( ( cg.time - cg.poisonedTime ) / (float)LEVEL1_PCLOUD_TIME );
fov_x += v;
fov_y += v;
}
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index 02427daa..3c4e1d3e 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -210,7 +210,7 @@ void CG_AlienZap( vec3_t start, vec3_t end, int srcENum, int destENum )
le->destENum = destENum;
le->vOffset = 6.0f;
- le->maxRange = CHIMERA_AREAZAP_RANGE * M_ROOT3;
+ le->maxRange = LEVEL2_AREAZAP_RANGE * M_ROOT3;
VectorCopy( start, re->origin );
VectorCopy( end, re->oldorigin );
@@ -338,6 +338,36 @@ static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p
continue;
}
+ else if( !Q_stricmp( token, "missileAnimates" ) )
+ {
+ wim->missileAnimates = qtrue;
+
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->missileAnimStartFrame = atoi( token );
+
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->missileAnimNumFrames = atoi( token );
+
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->missileAnimFrameRate = atoi( token );
+
+ token = COM_Parse( text_p );
+ if( !token )
+ break;
+
+ wim->missileAnimLooping = atoi( token );
+
+ continue;
+ }
else if( !Q_stricmp( token, "missileParticleSystem" ) )
{
token = COM_Parse( text_p );
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 807b8a3a..9c756e54 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -1429,7 +1429,7 @@ classAttributes_t bg_classList[ ] =
0 //int value;
},
{
- PCL_A_B_BASE, //int classnum;
+ PCL_ALIEN_BUILDER0, //int classnum;
"builder", //char *className;
"Builder", //char *humanName;
"builder", //char *modelname;
@@ -1462,12 +1462,12 @@ classAttributes_t bg_classList[ ] =
100.0f, //float stopSpeed;
130.0f, //float jumpMagnitude;
1.0f, //float knockbackScale;
- { PCL_A_B_LEV1, PCL_A_O_BASE, PCL_NONE }, //int children[ 3 ];
+ { PCL_ALIEN_BUILDER0_UPG, PCL_ALIEN_LEVEL0, PCL_NONE }, //int children[ 3 ];
ABUILDER_COST, //int cost;
ABUILDER_VALUE //int value;
},
{
- PCL_A_B_LEV1, //int classnum;
+ PCL_ALIEN_BUILDER0_UPG, //int classnum;
"builderupg", //char *classname;
"Advanced Builder", //char *humanname;
"builder", //char *modelname;
@@ -1500,13 +1500,13 @@ classAttributes_t bg_classList[ ] =
100.0f, //float stopSpeed;
270.0f, //float jumpMagnitude;
1.0f, //float knockbackScale;
- { PCL_A_O_BASE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ { PCL_ALIEN_LEVEL0, PCL_NONE, PCL_NONE }, //int children[ 3 ];
ABUILDER_UPG_COST, //int cost;
ABUILDER_UPG_VALUE //int value;
},
{
- PCL_A_O_BASE, //int classnum;
- "soldier", //char *classname;
+ PCL_ALIEN_LEVEL0, //int classnum;
+ "level0", //char *classname;
"Soldier", //char *humanname;
"jumper", //char *modelname;
0.2f, //float modelScale;
@@ -1521,31 +1521,31 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 4 }, //vec3_t deadmaxs;
-8.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
- SOLDIER_HEALTH, //int health;
+ LEVEL0_HEALTH, //int health;
0.0f, //float fallDamage;
- SOLDIER_REGEN, //int regenRate;
+ LEVEL0_REGEN, //int regenRate;
SCA_WALLCLIMBER|SCA_NOWEAPONDRIFT|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_SOLDIER, //weapon_t startWeapon
+ WP_ALEVEL0, //weapon_t startWeapon
0.0f, //float buildDist;
140, //int fov;
0.0f, //float bob;
2.5f, //float bobCycle;
25, //int steptime;
- SOLDIER_SPEED, //float speed;
+ LEVEL0_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
400.0f, //float stopSpeed;
250.0f, //float jumpMagnitude;
2.0f, //float knockbackScale;
- { PCL_A_O_LEV1, PCL_NONE, PCL_NONE }, //int children[ 3 ];
- SOLDIER_COST, //int cost;
- SOLDIER_VALUE //int value;
+ { PCL_ALIEN_LEVEL1, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL0_COST, //int cost;
+ LEVEL0_VALUE //int value;
},
{
- PCL_A_O_LEV1, //int classnum;
- "hydra", //char *classname;
+ PCL_ALIEN_LEVEL1, //int classnum;
+ "level1", //char *classname;
"Hydra", //char *humanname;
"spitter", //char *modelname;
0.6f, //float modelScale;
@@ -1560,31 +1560,31 @@ classAttributes_t bg_classList[ ] =
{ 18, 18, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
- HYDRA_HEALTH, //int health;
+ LEVEL1_HEALTH, //int health;
0.0f, //float fallDamage;
- HYDRA_REGEN, //int regenRate;
+ LEVEL1_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|
SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
- WP_HYDRA, //weapon_t startWeapon
+ WP_ALEVEL1, //weapon_t startWeapon
0.0f, //float buildDist;
120, //int fov;
0.001f, //float bob;
1.8f, //float bobCycle;
25, //int steptime;
- HYDRA_SPEED, //float speed;
+ LEVEL1_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
300.0f, //float stopSpeed;
270.0f, //float jumpMagnitude;
1.2f, //float knockbackScale;
- { PCL_A_O_LEV2, PCL_A_O_LEV1_UPG, PCL_NONE }, //int children[ 3 ];
- HYDRA_COST, //int cost;
- HYDRA_VALUE //int value;
+ { PCL_ALIEN_LEVEL2, PCL_ALIEN_LEVEL1_UPG, PCL_NONE }, //int children[ 3 ];
+ LEVEL1_COST, //int cost;
+ LEVEL1_VALUE //int value;
},
{
- PCL_A_O_LEV1_UPG, //int classnum;
- "hydraupg", //char *classname;
+ PCL_ALIEN_LEVEL1_UPG, //int classnum;
+ "level1upg", //char *classname;
"Hydra Upgrade", //char *humanname;
"spitter", //char *modelname;
0.7f, //float modelScale;
@@ -1599,31 +1599,31 @@ classAttributes_t bg_classList[ ] =
{ 20, 20, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
- HYDRA_UPG_HEALTH, //int health;
+ LEVEL1_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
- HYDRA_UPG_REGEN, //int regenRate;
+ LEVEL1_UPG_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|SCA_FOVWARPS|
SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities;
- WP_HYDRA_UPG, //weapon_t startWeapon
+ WP_ALEVEL1_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
120, //int fov;
0.001f, //float bob;
1.8f, //float bobCycle;
25, //int steptime;
- HYDRA_UPG_SPEED, //float speed;
+ LEVEL1_UPG_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
300.0f, //float stopSpeed;
270.0f, //float jumpMagnitude;
1.1f, //float knockbackScale;
- { PCL_A_O_LEV2, PCL_NONE, PCL_NONE }, //int children[ 3 ];
- HYDRA_UPG_COST, //int cost;
- HYDRA_UPG_VALUE //int value;
+ { PCL_ALIEN_LEVEL2, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL1_UPG_COST, //int cost;
+ LEVEL1_UPG_VALUE //int value;
},
{
- PCL_A_O_LEV2, //int classnum;
- "chimera", //char *classname;
+ PCL_ALIEN_LEVEL2, //int classnum;
+ "level2", //char *classname;
"Chimera", //char *humanname;
"tarantula", //char *modelname;
0.75f, //float modelScale;
@@ -1638,31 +1638,31 @@ classAttributes_t bg_classList[ ] =
{ 22, 22, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
10, 10, //int viewheight, crouchviewheight;
- CHIMERA_HEALTH, //int health;
+ LEVEL2_HEALTH, //int health;
0.0f, //float fallDamage;
- CHIMERA_REGEN, //int regenRate;
+ LEVEL2_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_CHIMERA, //weapon_t startWeapon
+ WP_ALEVEL2, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
0.001f, //float bob;
1.5f, //float bobCycle;
60, //int steptime;
- CHIMERA_SPEED, //float speed;
+ LEVEL2_SPEED, //float speed;
10.0f, //float acceleration;
2.0f, //float airAcceleration;
6.0f, //float friction;
100.0f, //float stopSpeed;
400.0f, //float jumpMagnitude;
0.8f, //float knockbackScale;
- { PCL_A_O_LEV3, PCL_A_O_LEV2_UPG, PCL_NONE }, //int children[ 3 ];
- CHIMERA_COST, //int cost;
- CHIMERA_VALUE //int value;
+ { PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL2_UPG, PCL_NONE }, //int children[ 3 ];
+ LEVEL2_COST, //int cost;
+ LEVEL2_VALUE //int value;
},
{
- PCL_A_O_LEV2_UPG, //int classnum;
- "chimeraupg", //char *classname;
+ PCL_ALIEN_LEVEL2_UPG, //int classnum;
+ "level2upg", //char *classname;
"Chimera Upgrade", //char *humanname;
"tarantula", //char *modelname;
0.9f, //float modelScale;
@@ -1677,31 +1677,31 @@ classAttributes_t bg_classList[ ] =
{ 24, 24, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
12, 12, //int viewheight, crouchviewheight;
- CHIMERA_UPG_HEALTH, //int health;
+ LEVEL2_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
- CHIMERA_UPG_REGEN, //int regenRate;
+ LEVEL2_UPG_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_CHIMERA_UPG, //weapon_t startWeapon
+ WP_ALEVEL2_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
0.001f, //float bob;
1.5f, //float bobCycle;
60, //int steptime;
- CHIMERA_UPG_SPEED, //float speed;
+ LEVEL2_UPG_SPEED, //float speed;
10.0f, //float acceleration;
2.0f, //float airAcceleration;
6.0f, //float friction;
100.0f, //float stopSpeed;
400.0f, //float jumpMagnitude;
0.7f, //float knockbackScale;
- { PCL_A_O_LEV3, PCL_NONE, PCL_NONE }, //int children[ 3 ];
- CHIMERA_UPG_COST, //int cost;
- CHIMERA_UPG_VALUE //int value;
+ { PCL_ALIEN_LEVEL3, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL2_UPG_COST, //int cost;
+ LEVEL2_UPG_VALUE //int value;
},
{
- PCL_A_O_LEV3, //int classnum;
- "dragoon", //char *classname;
+ PCL_ALIEN_LEVEL3, //int classnum;
+ "level3", //char *classname;
"Dragoon", //char *humanname;
"prowl", //char *modelname;
1.0f, //float modelScale;
@@ -1716,31 +1716,31 @@ classAttributes_t bg_classList[ ] =
{ 32, 32, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
24, 24, //int viewheight, crouchviewheight;
- DRAGOON_HEALTH, //int health;
+ LEVEL3_HEALTH, //int health;
0.0f, //float fallDamage;
- DRAGOON_REGEN, //int regenRate;
+ LEVEL3_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_DRAGOON, //weapon_t startWeapon
+ WP_ALEVEL3, //weapon_t startWeapon
0.0f, //float buildDist;
110, //int fov;
0.0005f, //float bob;
1.3f, //float bobCycle;
25, //int steptime;
- DRAGOON_SPEED, //float speed;
+ LEVEL3_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
200.0f, //float stopSpeed;
270.0f, //float jumpMagnitude;
0.5f, //float knockbackScale;
- { PCL_A_O_LEV4, PCL_A_O_LEV3_UPG, PCL_NONE }, //int children[ 3 ];
- DRAGOON_COST, //int cost;
- DRAGOON_VALUE //int value;
+ { PCL_ALIEN_LEVEL4, PCL_ALIEN_LEVEL3_UPG, PCL_NONE }, //int children[ 3 ];
+ LEVEL3_COST, //int cost;
+ LEVEL3_VALUE //int value;
},
{
- PCL_A_O_LEV3_UPG, //int classnum;
- "dragoonupg", //char *classname;
+ PCL_ALIEN_LEVEL3_UPG, //int classnum;
+ "level3upg", //char *classname;
"Dragoon Upgrade", //char *humanname;
"prowl", //char *modelname;
1.0f, //float modelScale;
@@ -1755,31 +1755,31 @@ classAttributes_t bg_classList[ ] =
{ 32, 32, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
27, 27, //int viewheight, crouchviewheight;
- DRAGOON_UPG_HEALTH, //int health;
+ LEVEL3_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
- DRAGOON_UPG_REGEN, //int regenRate;
+ LEVEL3_UPG_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_DRAGOON_UPG, //weapon_t startWeapon
+ WP_ALEVEL3_UPG, //weapon_t startWeapon
0.0f, //float buildDist;
110, //int fov;
0.0005f, //float bob;
1.3f, //float bobCycle;
25, //int steptime;
- DRAGOON_UPG_SPEED, //float speed;
+ LEVEL3_UPG_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
200.0f, //float stopSpeed;
270.0f, //float jumpMagnitude;
0.4f, //float knockbackScale;
- { PCL_A_O_LEV4, PCL_NONE, PCL_NONE }, //int children[ 3 ];
- DRAGOON_UPG_COST, //int cost;
- DRAGOON_UPG_VALUE //int value;
+ { PCL_ALIEN_LEVEL4, PCL_NONE, PCL_NONE }, //int children[ 3 ];
+ LEVEL3_UPG_COST, //int cost;
+ LEVEL3_UPG_VALUE //int value;
},
{
- PCL_A_O_LEV4, //int classnum;
- "bigmofo", //char *classname;
+ PCL_ALIEN_LEVEL4, //int classnum;
+ "level4", //char *classname;
"Big Mofo", //char *humanname;
"mofo", //char *modelname;
1.0f, //float modelScale;
@@ -1794,18 +1794,18 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 4 }, //vec3_t deadmaxs;
0.0f, //float zOffset
35, 35, //int viewheight, crouchviewheight;
- BMOFO_HEALTH, //int health;
+ LEVEL4_HEALTH, //int health;
0.0f, //float fallDamage;
- BMOFO_REGEN, //int regenRate;
+ LEVEL4_REGEN, //int regenRate;
SCA_NOWEAPONDRIFT|
SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities;
- WP_BIGMOFO, //weapon_t startWeapon
+ WP_ALEVEL4, //weapon_t startWeapon
0.0f, //float buildDist;
90, //int fov;
0.001f, //float bob;
1.1f, //float bobCycle;
60, //int steptime;
- BMOFO_SPEED, //float speed;
+ LEVEL4_SPEED, //float speed;
10.0f, //float acceleration;
1.0f, //float airAcceleration;
6.0f, //float friction;
@@ -1813,12 +1813,12 @@ classAttributes_t bg_classList[ ] =
170.0f, //float jumpMagnitude;
0.1f, //float knockbackScale;
{ PCL_NONE, PCL_NONE, PCL_NONE }, //int children[ 3 ];
- BMOFO_COST, //int cost;
- BMOFO_VALUE //int value;
+ LEVEL4_COST, //int cost;
+ LEVEL4_VALUE //int value;
},
{
- PCL_H_BASE, //int classnum;
- "human", //char *classname;
+ PCL_HUMAN, //int classnum;
+ "human_base", //char *classname;
"Human", //char *humanname;
"sarge", //char *modelname;
1.0f, //float modelScale;
@@ -1858,7 +1858,7 @@ classAttributes_t bg_classList[ ] =
{
//this isn't a real class, but a dummy to force the client to precache the model
//FIXME: one day do this in a less hacky fashion
- PCL_H_BSUIT, "bsuit", "bsuit",
+ PCL_HUMAN_BSUIT, "human_bsuit", "bsuit",
"keel",
1.0f,
@@ -1924,6 +1924,9 @@ char *BG_FindHumanNameForClassNum( int pclass )
{
int i;
+ if( bg_classOverrideList[ pclass ].humanName[ 0 ] != 0 )
+ return bg_classOverrideList[ pclass ].humanName;
+
for( i = 0; i < bg_numPclasses; i++ )
{
if( bg_classList[ i ].classNum == pclass )
@@ -2841,6 +2844,16 @@ static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides
continue;
}
+ else if( !Q_stricmp( token, "name" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cao->humanName, token, sizeof( cao->humanName ) );
+
+ continue;
+ }
Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
@@ -3115,6 +3128,30 @@ weaponAttributes_t bg_weapons[ ] =
WUT_HUMANS //WUTeam_t team;
},
{
+ WP_GRENADE, //int weaponNum;
+ GRENADE_PRICE, //int price;
+ ( 1 << S2 )|( 1 << S3 ), //int stages
+ SLOT_NONE, //int slots;
+ "grenade", //char *weaponName;
+ "Grenade", //char *weaponHumanName;
+ 1, //int quan;
+ 0, //int clips;
+ 0, //int maxClips;
+ qfalse, //int infiniteAmmo;
+ qfalse, //int usesEnergy;
+ GRENADE_REPEAT, //int repeatRate1;
+ 0, //int repeatRate2;
+ 0, //int repeatRate3;
+ 0, //int reloadTime;
+ qfalse, //qboolean hasAltMode;
+ qfalse, //qboolean hasThirdMode;
+ qfalse, //qboolean canZoom;
+ 90.0f, //float zoomFov;
+ qtrue, //qboolean purchasable;
+ 0, //int buildDelay;
+ WUT_HUMANS //WUTeam_t team;
+ },
+ {
WP_HBUILD, //int weaponNum;
HBUILD_PRICE, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
@@ -3211,7 +3248,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_SOLDIER, //int weaponNum;
+ WP_ALEVEL0, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3222,7 +3259,7 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- SOLDIER_BITE_REPEAT, //int repeatRate1;
+ LEVEL0_BITE_REPEAT, //int repeatRate1;
0, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
@@ -3235,7 +3272,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_DRAGOON, //int weaponNum;
+ WP_ALEVEL3, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3246,7 +3283,7 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- DRAGOON_CLAW_REPEAT, //int repeatRate1;
+ LEVEL3_CLAW_REPEAT, //int repeatRate1;
0, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
@@ -3259,7 +3296,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_DRAGOON_UPG, //int weaponNum;
+ WP_ALEVEL3_UPG, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3270,9 +3307,9 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- DRAGOON_CLAW_U_REPEAT,//int repeatRate1;
+ LEVEL3_CLAW_U_REPEAT,//int repeatRate1;
0, //int repeatRate2;
- DRAGOON_BOUNCEBALL_REPEAT,//int repeatRate3;
+ LEVEL3_BOUNCEBALL_REPEAT,//int repeatRate3;
0, //int reloadTime;
qfalse, //qboolean hasAltMode;
qtrue, //qboolean hasThirdMode;
@@ -3283,7 +3320,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_HYDRA, //int weaponNum;
+ WP_ALEVEL1, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3294,7 +3331,7 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- HYDRA_CLAW_REPEAT, //int repeatRate1;
+ LEVEL1_CLAW_REPEAT, //int repeatRate1;
0, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
@@ -3307,7 +3344,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_HYDRA_UPG, //int weaponNum;
+ WP_ALEVEL1_UPG, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3318,8 +3355,8 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- HYDRA_CLAW_U_REPEAT, //int repeatRate1;
- HYDRA_PCLOUD_REPEAT, //int repeatRate2;
+ LEVEL1_CLAW_U_REPEAT, //int repeatRate1;
+ LEVEL1_PCLOUD_REPEAT, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
qtrue, //qboolean hasAltMode;
@@ -3331,7 +3368,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_CHIMERA, //int weaponNum;
+ WP_ALEVEL2, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3342,7 +3379,7 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- CHIMERA_CLAW_REPEAT, //int repeatRate1;
+ LEVEL2_CLAW_REPEAT, //int repeatRate1;
0, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
@@ -3355,7 +3392,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_CHIMERA_UPG, //int weaponNum;
+ WP_ALEVEL2_UPG, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3366,8 +3403,8 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- CHIMERA_CLAW_U_REPEAT,//int repeatRate1;
- CHIMERA_AREAZAP_REPEAT,//int repeatRate2;
+ LEVEL2_CLAW_U_REPEAT,//int repeatRate1;
+ LEVEL2_AREAZAP_REPEAT,//int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
qtrue, //qboolean hasAltMode;
@@ -3379,7 +3416,7 @@ weaponAttributes_t bg_weapons[ ] =
WUT_ALIENS //WUTeam_t team;
},
{
- WP_BIGMOFO, //int weaponNum;
+ WP_ALEVEL4, //int weaponNum;
0, //int price;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
SLOT_WEAPON, //int slots;
@@ -3390,7 +3427,7 @@ weaponAttributes_t bg_weapons[ ] =
0, //int maxClips;
qtrue, //int infiniteAmmo;
qfalse, //int usesEnergy;
- BMOFO_CLAW_REPEAT, //int repeatRate1;
+ LEVEL4_CLAW_REPEAT, //int repeatRate1;
0, //int repeatRate2;
0, //int repeatRate3;
0, //int reloadTime;
@@ -4318,6 +4355,10 @@ char *eventnames[ ] =
"EV_ALIENZAP",
"EV_BULLET", // otherEntity is the shooter
+ "EV_LEV1_GRAB",
+ "EV_LEV4_CHARGE_PREPARE",
+ "EV_LEV4_CHARGE_START",
+
"EV_PAIN",
"EV_DEATH1",
"EV_DEATH2",
@@ -4338,6 +4379,7 @@ char *eventnames[ ] =
"EV_ALIEN_BUILDABLE_DAMAGE",
"EV_ALIEN_EVOLVE",
+ "EV_ALIEN_EVOLVE_FAILED",
"EV_DEBUG_LINE",
"EV_STOPLOOPINGSOUND",
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index c1afd750..b2606c23 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -382,8 +382,9 @@ static float PM_CmdScale( usercmd_t *cmd )
}
}
- if( pm->ps->weapon == WP_BIGMOFO && pm->ps->pm_flags & PMF_CHARGE )
- modifier *= ( 1.0f + ( pm->ps->stats[ STAT_MISC ] / (float)BMOFO_CHARGE_TIME ) * ( BMOFO_CHARGE_SPEED - 1.0f ) );
+ if( pm->ps->weapon == WP_ALEVEL4 && pm->ps->pm_flags & PMF_CHARGE )
+ modifier *= ( 1.0f + ( pm->ps->stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME ) *
+ ( LEVEL4_CHARGE_SPEED - 1.0f ) );
if( pm->ps->pm_type == PM_GRABBED )
modifier = 0.0f;
@@ -466,7 +467,7 @@ PM_CheckCharge
*/
static void PM_CheckCharge( void )
{
- if( pm->ps->weapon != WP_BIGMOFO )
+ if( pm->ps->weapon != WP_ALEVEL4 )
return;
if( pm->cmd.buttons & BUTTON_ATTACK2 )
@@ -488,8 +489,8 @@ PM_CheckPounce
*/
static qboolean PM_CheckPounce( void )
{
- if( pm->ps->weapon != WP_DRAGOON &&
- pm->ps->weapon != WP_DRAGOON_UPG )
+ if( pm->ps->weapon != WP_ALEVEL3 &&
+ pm->ps->weapon != WP_ALEVEL3_UPG )
return qfalse;
if( pm->cmd.buttons & BUTTON_ATTACK2 )
@@ -600,10 +601,10 @@ static qboolean PM_CheckWallJump( void )
dir, pm->ps->velocity );
//for a long run of wall jumps the velocity can get pretty large, this caps it
- if( VectorLength( pm->ps->velocity ) > CHIMERA_WALLJUMP_MAXSPEED )
+ if( VectorLength( pm->ps->velocity ) > LEVEL2_WALLJUMP_MAXSPEED )
{
VectorNormalize( pm->ps->velocity );
- VectorScale( pm->ps->velocity, CHIMERA_WALLJUMP_MAXSPEED, pm->ps->velocity );
+ VectorScale( pm->ps->velocity, LEVEL2_WALLJUMP_MAXSPEED, pm->ps->velocity );
}
PM_AddEvent( EV_JUMP );
@@ -644,13 +645,13 @@ static qboolean PM_CheckJump( void )
return PM_CheckWallJump( );
//can't jump and pounce at the same time
- if( ( pm->ps->weapon == WP_DRAGOON ||
- pm->ps->weapon == WP_DRAGOON_UPG ) &&
+ if( ( pm->ps->weapon == WP_ALEVEL3 ||
+ pm->ps->weapon == WP_ALEVEL3_UPG ) &&
pm->ps->stats[ STAT_MISC ] > 0 )
return qfalse;
//can't jump and charge at the same time
- if( ( pm->ps->weapon == WP_BIGMOFO ) &&
+ if( ( pm->ps->weapon == WP_ALEVEL4 ) &&
pm->ps->stats[ STAT_MISC ] > 0 )
return qfalse;
@@ -2426,7 +2427,7 @@ static void PM_Footsteps( void )
{
bobmove = 0.4f; // faster speeds bob faster
- if( pm->ps->weapon == WP_BIGMOFO && pm->ps->pm_flags & PMF_CHARGE )
+ if( pm->ps->weapon == WP_ALEVEL4 && pm->ps->pm_flags & PMF_CHARGE )
PM_ContinueLegsAnim( NSPA_CHARGE );
else if( pm->ps->pm_flags & PMF_BACKWARDS_RUN )
{
@@ -2797,7 +2798,7 @@ static void PM_Weapon( void )
//check if non-auto primary/secondary attacks are permited
switch( pm->ps->weapon )
{
- case WP_SOLDIER:
+ case WP_ALEVEL0:
//venom is only autohit
attack1 = attack2 = attack3 = qfalse;
@@ -2809,8 +2810,8 @@ static void PM_Weapon( void )
}
break;
- case WP_DRAGOON:
- case WP_DRAGOON_UPG:
+ case WP_ALEVEL3:
+ case WP_ALEVEL3_UPG:
//pouncing has primary secondary AND autohit procedures
attack1 = pm->cmd.buttons & BUTTON_ATTACK;
attack2 = pm->cmd.buttons & BUTTON_ATTACK2;
@@ -2867,7 +2868,7 @@ static void PM_Weapon( void )
if( BG_WeaponHasThirdMode( pm->ps->weapon ) )
{
//hacky special case for slowblob
- if( pm->ps->weapon == WP_DRAGOON_UPG && !ammo )
+ if( pm->ps->weapon == WP_ALEVEL3_UPG && !ammo )
{
PM_AddEvent( EV_NOAMMO );
pm->ps->weaponTime += 200;
@@ -2912,14 +2913,14 @@ static void PM_Weapon( void )
{
switch( pm->ps->weapon )
{
- case WP_SOLDIER:
+ case WP_ALEVEL0:
pm->ps->generic1 = WPM_PRIMARY;
PM_AddEvent( EV_FIRE_WEAPON );
addTime = BG_FindRepeatRate1ForWeapon( pm->ps->weapon );
break;
- case WP_DRAGOON:
- case WP_DRAGOON_UPG:
+ case WP_ALEVEL3:
+ case WP_ALEVEL3_UPG:
pm->ps->generic1 = WPM_SECONDARY;
PM_AddEvent( EV_FIRE_WEAPON2 );
addTime = BG_FindRepeatRate2ForWeapon( pm->ps->weapon );
@@ -2953,7 +2954,7 @@ static void PM_Weapon( void )
}
else
{
- if( pm->ps->weapon == WP_BIGMOFO )
+ if( pm->ps->weapon == WP_ALEVEL4 )
{
//hack to get random attack animations
//FIXME: does pm->ps->weaponTime cycle enough?
@@ -2998,7 +2999,7 @@ static void PM_Weapon( void )
BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips, maxclips );
}
- else if( pm->ps->weapon == WP_DRAGOON_UPG && attack3 )
+ else if( pm->ps->weapon == WP_ALEVEL3_UPG && attack3 )
{
//special case for slowblob
ammo--;
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index d8c6053f..a90bf0cc 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -328,14 +328,14 @@ typedef enum
{
WP_NONE,
- WP_SOLDIER,
- WP_HYDRA,
- WP_HYDRA_UPG,
- WP_CHIMERA,
- WP_CHIMERA_UPG,
- WP_DRAGOON,
- WP_DRAGOON_UPG,
- WP_BIGMOFO,
+ WP_ALEVEL0,
+ WP_ALEVEL1,
+ WP_ALEVEL1_UPG,
+ WP_ALEVEL2,
+ WP_ALEVEL2_UPG,
+ WP_ALEVEL3,
+ WP_ALEVEL3_UPG,
+ WP_ALEVEL4,
WP_BLASTER,
WP_MACHINEGUN,
@@ -347,6 +347,7 @@ typedef enum
WP_PULSE_RIFLE,
WP_FLAMER,
WP_LUCIFER_CANNON,
+ WP_GRENADE,
WP_LOCKBLOB_LAUNCHER,
WP_HIVE,
@@ -529,6 +530,10 @@ typedef enum
EV_ALIENZAP,
EV_BULLET, // otherEntity is the shooter
+ EV_LEV1_GRAB,
+ EV_LEV4_CHARGE_PREPARE,
+ EV_LEV4_CHARGE_START,
+
EV_PAIN,
EV_DEATH1,
EV_DEATH2,
@@ -549,6 +554,7 @@ typedef enum
EV_ALIEN_BUILDABLE_DAMAGE,
EV_ALIEN_EVOLVE,
+ EV_ALIEN_EVOLVE_FAILED,
EV_DEBUG_LINE,
EV_STOPLOOPINGSOUND,
@@ -778,22 +784,22 @@ typedef enum
PCL_NONE,
//builder classes
- PCL_A_B_BASE,
- PCL_A_B_LEV1,
+ PCL_ALIEN_BUILDER0,
+ PCL_ALIEN_BUILDER0_UPG,
//offensive classes
- PCL_A_O_BASE,
- PCL_A_O_LEV1,
- PCL_A_O_LEV1_UPG,
- PCL_A_O_LEV2,
- PCL_A_O_LEV2_UPG,
- PCL_A_O_LEV3,
- PCL_A_O_LEV3_UPG,
- PCL_A_O_LEV4,
+ PCL_ALIEN_LEVEL0,
+ PCL_ALIEN_LEVEL1,
+ PCL_ALIEN_LEVEL1_UPG,
+ PCL_ALIEN_LEVEL2,
+ PCL_ALIEN_LEVEL2_UPG,
+ PCL_ALIEN_LEVEL3,
+ PCL_ALIEN_LEVEL3_UPG,
+ PCL_ALIEN_LEVEL4,
//human class
- PCL_H_BASE,
- PCL_H_BSUIT,
+ PCL_HUMAN,
+ PCL_HUMAN_BSUIT,
PCL_NUM_CLASSES
} pClass_t;
@@ -826,6 +832,7 @@ typedef enum
MOD_LCANNON_SPLASH,
MOD_FLAMER,
MOD_FLAMER_SPLASH,
+ MOD_GRENADE,
MOD_WATER,
MOD_SLIME,
MOD_LAVA,
@@ -837,16 +844,16 @@ typedef enum
MOD_TRIGGER_HURT,
MOD_ABUILDER_CLAW,
- MOD_SOLDIER_BITE,
- MOD_HYDRA_CLAW,
- MOD_HYDRA_PCLOUD,
- MOD_DRAGOON_CLAW,
- MOD_DRAGOON_POUNCE,
- MOD_DRAGOON_BOUNCEBALL,
- MOD_CHIMERA_CLAW,
- MOD_CHIMERA_ZAP,
- MOD_BMOFO_CLAW,
- MOD_BMOFO_CHARGE,
+ MOD_LEVEL0_BITE,
+ MOD_LEVEL1_CLAW,
+ MOD_LEVEL1_PCLOUD,
+ MOD_LEVEL3_CLAW,
+ MOD_LEVEL3_POUNCE,
+ MOD_LEVEL3_BOUNCEBALL,
+ MOD_LEVEL2_CLAW,
+ MOD_LEVEL2_ZAP,
+ MOD_LEVEL4_CLAW,
+ MOD_LEVEL4_CHARGE,
MOD_SLOWBLOB,
MOD_POISON,
@@ -927,6 +934,7 @@ typedef struct
char skinName[ MAX_QPATH ];
float shadowScale;
char hudName[ MAX_QPATH ];
+ char humanName[ MAX_STRING_CHARS ];
vec3_t mins;
vec3_t maxs;
@@ -1264,6 +1272,13 @@ void ProjectPointOntoVector( vec3_t point, vec3_t vStart,
float VectorDistance( vec3_t v1, vec3_t v2 );
// done.
+//call roundf in place of round on non VM platforms
+#ifdef Q3_VM
+#define roundf round
+#else
+#define round roundf
+#endif
+
#define M_ROOT3 1.732050808f
float VectorMinComponent( vec3_t v );
float VectorMaxComponent( vec3_t v );
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 836ae90c..820586d9 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -214,7 +214,7 @@ void ClientImpacts( gentity_t *ent, pmove_t *pm )
ent->touch( ent, other, &trace );
//charge attack
- if( ent->client->ps.weapon == WP_BIGMOFO &&
+ if( ent->client->ps.weapon == WP_ALEVEL4 &&
ent->client->ps.stats[ STAT_MISC ] > 0 &&
ent->client->charging )
ChargeAttack( ent, other );
@@ -505,17 +505,17 @@ void ClientTimerActions( gentity_t *ent, int msec )
}
//client is charging up for a pounce
- if( client->ps.weapon == WP_DRAGOON || client->ps.weapon == WP_DRAGOON_UPG )
+ if( client->ps.weapon == WP_ALEVEL3 || client->ps.weapon == WP_ALEVEL3_UPG )
{
int pounceSpeed;
- if( client->ps.weapon == WP_DRAGOON )
- pounceSpeed = DRAGOON_POUNCE_SPEED;
- else if( client->ps.weapon == WP_DRAGOON_UPG )
- pounceSpeed = DRAGOON_POUNCE_UPG_SPEED;
+ if( client->ps.weapon == WP_ALEVEL3 )
+ pounceSpeed = LEVEL3_POUNCE_SPEED;
+ else if( client->ps.weapon == WP_ALEVEL3_UPG )
+ pounceSpeed = LEVEL3_POUNCE_UPG_SPEED;
if( client->ps.stats[ STAT_MISC ] < pounceSpeed && ucmd->buttons & BUTTON_ATTACK2 )
- client->ps.stats[ STAT_MISC ] += ( 100.0f / (float)DRAGOON_POUNCE_TIME ) * pounceSpeed;
+ client->ps.stats[ STAT_MISC ] += ( 100.0f / (float)LEVEL3_POUNCE_TIME ) * pounceSpeed;
if( !( ucmd->buttons & BUTTON_ATTACK2 ) )
{
@@ -533,24 +533,32 @@ void ClientTimerActions( gentity_t *ent, int msec )
}
//client is charging up for a... charge
- if( client->ps.weapon == WP_BIGMOFO )
+ if( client->ps.weapon == WP_ALEVEL4 )
{
- if( client->ps.stats[ STAT_MISC ] < BMOFO_CHARGE_TIME && ucmd->buttons & BUTTON_ATTACK2 &&
- ( ucmd->forwardmove > 0 ) )
+ if( client->ps.stats[ STAT_MISC ] < LEVEL4_CHARGE_TIME && ucmd->buttons & BUTTON_ATTACK2 &&
+ ( ucmd->forwardmove > 0 ) && !client->charging )
{
client->charging = qfalse; //should already be off, just making sure
- client->ps.stats[ STAT_MISC ] += (int)( 100 * (float)BMOFO_CHARGE_CHARGE_RATIO );
+ //trigger charge sound
+ if( client->ps.stats[ STAT_MISC ] <= 0 )
+ G_AddEvent( ent, EV_LEV4_CHARGE_PREPARE, 0 );
+
+ client->ps.stats[ STAT_MISC ] += (int)( 100 * (float)LEVEL4_CHARGE_CHARGE_RATIO );
- if( client->ps.stats[ STAT_MISC ] > BMOFO_CHARGE_TIME )
- client->ps.stats[ STAT_MISC ] = BMOFO_CHARGE_TIME;
+ if( client->ps.stats[ STAT_MISC ] > LEVEL4_CHARGE_TIME )
+ client->ps.stats[ STAT_MISC ] = LEVEL4_CHARGE_TIME;
}
- if( !( ucmd->buttons & BUTTON_ATTACK2 ) )
+ if( !( ucmd->buttons & BUTTON_ATTACK2 ) || client->charging )
{
if( client->ps.stats[ STAT_MISC ] > 0 )
{
client->ps.stats[ STAT_MISC ] -= 100;
+
+ if( client->charging == qfalse )
+ G_AddEvent( ent, EV_LEV4_CHARGE_START, 0 );
+
client->charging = qtrue;
//if the charger has stopped moving take a chunk of charge away
@@ -623,10 +631,10 @@ void ClientTimerActions( gentity_t *ent, int msec )
{
client->time1000 -= 1000;
- //client is hydra poisoned
+ //client is poison clouded
if( client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED )
G_Damage( ent, client->lastPoisonCloudedClient, client->lastPoisonCloudedClient, NULL, NULL,
- HYDRA_PCLOUD_DMG, 0, MOD_HYDRA_PCLOUD );
+ LEVEL1_PCLOUD_DMG, 0, MOD_LEVEL1_PCLOUD );
//client is poisoned
if( client->ps.stats[ STAT_STATE ] & SS_POISONED )
@@ -653,7 +661,7 @@ void ClientTimerActions( gentity_t *ent, int msec )
if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
{
int entityList[ MAX_GENTITIES ];
- vec3_t range = { BMOFO_REGEN_RANGE, BMOFO_REGEN_RANGE, BMOFO_REGEN_RANGE };
+ vec3_t range = { LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE, LEVEL4_REGEN_RANGE };
vec3_t mins, maxs, dir;
int i, num;
gentity_t *alienPlayer;
@@ -668,9 +676,9 @@ void ClientTimerActions( gentity_t *ent, int msec )
alienPlayer = &g_entities[ entityList[ i ] ];
if( alienPlayer->client && alienPlayer->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS &&
- alienPlayer->client->ps.stats[ STAT_PCLASS ] == PCL_A_O_LEV4 )
+ alienPlayer->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_LEVEL4 )
{
- modifier = BMOFO_REGEN_MOD;
+ modifier = LEVEL4_REGEN_MOD;
break;
}
}
@@ -688,17 +696,17 @@ void ClientTimerActions( gentity_t *ent, int msec )
{
client->time10000 -= 10000;
- if( client->ps.weapon == WP_DRAGOON_UPG )
+ if( client->ps.weapon == WP_ALEVEL3_UPG )
{
int ammo, maxAmmo;
- BG_FindAmmoForWeapon( WP_DRAGOON_UPG, &maxAmmo, NULL, NULL );
- BG_UnpackAmmoArray( WP_DRAGOON_UPG, client->ps.ammo, client->ps.powerups, &ammo, NULL, NULL );
+ BG_FindAmmoForWeapon( WP_ALEVEL3_UPG, &maxAmmo, NULL, NULL );
+ BG_UnpackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, &ammo, NULL, NULL );
if( ammo < maxAmmo )
{
ammo++;
- BG_PackAmmoArray( WP_DRAGOON_UPG, client->ps.ammo, client->ps.powerups, ammo, 0, 0 );
+ BG_PackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, ammo, 0, 0 );
}
}
}
@@ -794,6 +802,40 @@ void ClientEvents( gentity_t *ent, int oldEventSequence )
FireWeapon3( ent );
break;
+ case EV_NOAMMO:
+ //if we just ran out of grenades, remove the inventory item
+ if( ent->s.weapon == WP_GRENADE )
+ {
+ int j;
+
+ BG_RemoveWeaponFromInventory( ent->s.weapon, ent->client->ps.stats );
+
+ //force a weapon change
+ ent->client->ps.pm_flags |= PMF_WEAPON_SWITCH;
+
+ //switch to the first non blaster weapon
+ for( j = WP_NONE + 1; j < WP_NUM_WEAPONS; j++ )
+ {
+ if( j == WP_BLASTER )
+ continue;
+
+ if( BG_InventoryContainsWeapon( j, ent->client->ps.stats ) )
+ {
+ trap_SendServerCommand( ent - g_entities, va( "weaponswitch %d", j ) );
+ break;
+ }
+ }
+
+ //only got the blaster to switch to
+ if( j == WP_NUM_WEAPONS )
+ trap_SendServerCommand( ent - g_entities, va( "weaponswitch %d", WP_BLASTER ) );
+
+ //update ClientInfo
+ ClientUserinfoChanged( ent->client->ps.clientNum );
+ }
+
+ break;
+
default:
break;
}
@@ -992,7 +1034,7 @@ void ClientThink_real( gentity_t *ent )
client->ps.pm_type = PM_NORMAL;
if( client->ps.stats[ STAT_STATE ] & SS_GRABBED &&
- client->lastGrabTime + HYDRA_GRAB_TIME < level.time )
+ client->lastGrabTime + LEVEL1_GRAB_TIME < level.time )
client->ps.stats[ STAT_STATE ] &= ~SS_GRABBED;
if( client->ps.stats[ STAT_STATE ] & SS_BLOBLOCKED &&
@@ -1010,7 +1052,7 @@ void ClientThink_real( gentity_t *ent )
client->ps.stats[ STAT_STATE ] &= ~SS_BOOSTED;
if( client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED &&
- client->lastPoisonCloudedTime + HYDRA_PCLOUD_TIME < level.time )
+ client->lastPoisonCloudedTime + LEVEL1_PCLOUD_TIME < level.time )
client->ps.stats[ STAT_STATE ] &= ~SS_POISONCLOUDED;
if( client->ps.stats[ STAT_STATE ] & SS_POISONED &&
@@ -1035,9 +1077,9 @@ void ClientThink_real( gentity_t *ent )
client->ps.speed = g_speed.value * BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] );
//TA: slow player if charging up for a pounce
- if( ( client->ps.weapon == WP_DRAGOON || client->ps.weapon == WP_DRAGOON_UPG ) &&
+ if( ( client->ps.weapon == WP_ALEVEL3 || client->ps.weapon == WP_ALEVEL3_UPG ) &&
ucmd->buttons & BUTTON_ATTACK2 )
- client->ps.speed *= DRAGOON_POUNCE_SPEED_MOD;
+ client->ps.speed *= LEVEL3_POUNCE_SPEED_MOD;
//TA: slow the player if slow locked
if( client->ps.stats[ STAT_STATE ] & SS_SLOWLOCKED )
@@ -1070,18 +1112,18 @@ void ClientThink_real( gentity_t *ent )
{
switch( client->ps.weapon )
{
- case WP_SOLDIER:
+ case WP_ALEVEL0:
if( client->ps.weaponTime <= 0 )
pm.autoWeaponHit[ client->ps.weapon ] = CheckVenomAttack( ent );
break;
- case WP_HYDRA:
- case WP_HYDRA_UPG:
+ case WP_ALEVEL1:
+ case WP_ALEVEL1_UPG:
CheckGrabAttack( ent );
break;
- case WP_DRAGOON:
- case WP_DRAGOON_UPG:
+ case WP_ALEVEL3:
+ case WP_ALEVEL3_UPG:
if( client->ps.weaponTime <= 0 )
pm.autoWeaponHit[ client->ps.weapon ] = CheckPounceAttack( ent );
break;
@@ -1261,6 +1303,11 @@ void ClientThink_real( gentity_t *ent )
//no nearby objects and alien - show class menu
G_TriggerMenu( ent->client->ps.clientNum, MN_A_INFEST );
}
+ else
+ {
+ //flash frags
+ G_AddEvent( ent, EV_ALIEN_EVOLVE_FAILED, 0 );
+ }
}
}
}
@@ -1310,11 +1357,11 @@ void ClientThink_real( gentity_t *ent )
{
if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
{
- G_AddCreditToClient( ent->client, FREEKILL_ALIEN );
+ G_AddCreditToClient( ent->client, FREEKILL_ALIEN, qtrue );
}
else if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
- G_AddCreditToClient( ent->client, FREEKILL_HUMAN );
+ G_AddCreditToClient( ent->client, FREEKILL_HUMAN, qtrue );
}
ent->client->lastKillTime = level.time;
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index a959e087..f74715ba 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -83,7 +83,7 @@ gentity_t *G_CheckSpawnPoint( vec3_t origin, vec3_t normal, buildable_t spawn, v
}
else if( spawn == BA_H_SPAWN )
{
- BG_FindBBoxForClass( PCL_H_BASE, cmins, cmaxs, NULL, NULL, NULL );
+ BG_FindBBoxForClass( PCL_HUMAN, cmins, cmaxs, NULL, NULL, NULL );
VectorCopy( origin, localOrigin );
localOrigin[ 2 ] += maxs[ 2 ] + fabs( cmins[ 2 ] ) + 1.0f;
@@ -581,9 +581,9 @@ void ASpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
if( attacker && attacker->client && attacker->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
if( self->s.modelindex == BA_A_OVERMIND )
- G_AddCreditToClient( attacker->client, OVERMIND_VALUE );
+ G_AddCreditToClient( attacker->client, OVERMIND_VALUE, qtrue );
else if( self->s.modelindex == BA_A_SPAWN )
- G_AddCreditToClient( attacker->client, ASPAWN_VALUE );
+ G_AddCreditToClient( attacker->client, ASPAWN_VALUE, qtrue );
}
}
@@ -1086,8 +1086,8 @@ void AHovel_Use( gentity_t *self, gentity_t *other, gentity_t *activator )
//this hovel is in use
G_TriggerMenu( activator->client->ps.clientNum, MN_A_HOVEL_OCCUPIED );
}
- else if( ( ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_BASE ) ||
- ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_A_B_LEV1 ) ) &&
+ else if( ( ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 ) ||
+ ( activator->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG ) ) &&
activator->health > 0 && self->health > 0 )
{
if( AHovel_Blocked( self, activator, qfalse ) )
@@ -2144,9 +2144,9 @@ void HSpawn_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
if( attacker && attacker->client && attacker->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
{
if( self->s.modelindex == BA_H_REACTOR )
- G_AddCreditToClient( attacker->client, REACTOR_VALUE );
+ G_AddCreditToClient( attacker->client, REACTOR_VALUE, qtrue );
else if( self->s.modelindex == BA_H_SPAWN )
- G_AddCreditToClient( attacker->client, HSPAWN_VALUE );
+ G_AddCreditToClient( attacker->client, HSPAWN_VALUE, qtrue );
}
}
@@ -2421,7 +2421,7 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
vec3_t builderMins, builderMaxs;
//this assumes the adv builder is the biggest thing that'll use the hovel
- BG_FindBBoxForClass( PCL_A_B_LEV1, builderMins, builderMaxs, NULL, NULL, NULL );
+ BG_FindBBoxForClass( PCL_ALIEN_BUILDER0_UPG, builderMins, builderMaxs, NULL, NULL, NULL );
if( APropHovel_Blocked( angles, origin, normal, ent ) )
reason = IBE_HOVELEXIT;
diff --git a/src/game/g_client.c b/src/game/g_client.c
index 83d3e8e6..7e3cebb3 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -77,22 +77,42 @@ void SP_info_human_intermission( gentity_t *ent )
G_AddCreditToClient
===============
*/
-void G_AddCreditToClient( gclient_t *client, short credit )
+void G_AddCreditToClient( gclient_t *client, short credit, qboolean cap )
{
if( !client )
return;
- client->ps.persistant[ PERS_CREDIT ] += credit;
-
- if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ //if we're already at the max and trying to add credit then stop
+ if( cap )
{
- if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS )
- client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS;
+ if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ {
+ if( client->ps.persistant[ PERS_CREDIT ] >= ALIEN_MAX_KILLS &&
+ credit > 0 )
+ return;
+ }
+ else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ {
+ if( client->ps.persistant[ PERS_CREDIT ] >= HUMAN_MAX_CREDITS &&
+ credit > 0 )
+ return;
+ }
}
- else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+
+ client->ps.persistant[ PERS_CREDIT ] += credit;
+
+ if( cap )
{
- if( client->ps.persistant[ PERS_CREDIT ] > HUMAN_MAX_CREDITS )
- client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS;
+ if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ {
+ if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS )
+ client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS;
+ }
+ else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ {
+ if( client->ps.persistant[ PERS_CREDIT ] > HUMAN_MAX_CREDITS )
+ client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS;
+ }
}
if( client->ps.persistant[ PERS_CREDIT ] < 0 )
@@ -996,10 +1016,10 @@ void ClientUserinfoChanged( int clientNum )
client->pers.maxHealth = 0;
// set model
- if( client->ps.stats[ STAT_PCLASS ] == PCL_H_BASE && BG_InventoryContainsUpgrade( UP_BATTLESUIT, client->ps.stats ) )
+ if( client->ps.stats[ STAT_PCLASS ] == PCL_HUMAN && BG_InventoryContainsUpgrade( UP_BATTLESUIT, client->ps.stats ) )
{
- Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_H_BSUIT ),
- BG_FindSkinNameForClass( PCL_H_BSUIT ) );
+ Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_HUMAN_BSUIT ),
+ BG_FindSkinNameForClass( PCL_HUMAN_BSUIT ) );
}
else if( client->pers.classSelection == PCL_NONE )
{
@@ -1007,8 +1027,8 @@ void ClientUserinfoChanged( int clientNum )
//model details to that of the spawning class or the info change will not be
//registered and an axis appears instead of the player model. There is zero chance
//the player can spawn with the battlesuit, hence this choice.
- Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_H_BSUIT ),
- BG_FindSkinNameForClass( PCL_H_BSUIT ) );
+ Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_HUMAN_BSUIT ),
+ BG_FindSkinNameForClass( PCL_HUMAN_BSUIT ) );
}
else
{
@@ -1366,7 +1386,7 @@ void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles
client->pers.maxHealth = client->ps.stats[ STAT_MAX_HEALTH ] = 100;
// clear entity values
- if( ent->client->pers.classSelection == PCL_H_BASE )
+ if( ent->client->pers.classSelection == PCL_HUMAN )
{
BG_AddWeaponToInventory( WP_BLASTER, client->ps.stats );
weapon = client->pers.humanItemSelection;
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 7d6e6a92..0e67824f 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -280,9 +280,9 @@ void Cmd_Give_f( gentity_t *ent )
int credits = atoi( name + 6 );
if( !credits )
- G_AddCreditToClient( ent->client, 1 );
+ G_AddCreditToClient( ent->client, 1, qtrue );
else
- G_AddCreditToClient( ent->client, credits );
+ G_AddCreditToClient( ent->client, credits, qtrue );
if( !give_all )
return;
@@ -1109,17 +1109,17 @@ void Cmd_Class_f( gentity_t *ent )
clientNum = ent->client - level.clients;
trap_Argv( 1, s, sizeof( s ) );
- if( BG_FindStagesForClass( PCL_A_B_LEV1, g_alienStage.integer ) )
+ if( BG_FindStagesForClass( PCL_ALIEN_BUILDER0_UPG, g_alienStage.integer ) )
{
- allowedClasses[ 0 ] = PCL_A_B_BASE;
- allowedClasses[ 1 ] = PCL_A_B_LEV1;
- allowedClasses[ 2 ] = PCL_A_O_BASE;
+ allowedClasses[ 0 ] = PCL_ALIEN_BUILDER0;
+ allowedClasses[ 1 ] = PCL_ALIEN_BUILDER0_UPG;
+ allowedClasses[ 2 ] = PCL_ALIEN_LEVEL0;
numClasses = 3;
}
else
{
- allowedClasses[ 0 ] = PCL_A_B_BASE;
- allowedClasses[ 1 ] = PCL_A_O_BASE;
+ allowedClasses[ 0 ] = PCL_ALIEN_BUILDER0;
+ allowedClasses[ 1 ] = PCL_ALIEN_LEVEL0;
numClasses = 2;
}
@@ -1200,7 +1200,7 @@ void Cmd_Class_f( gentity_t *ent )
if( numLevels >= 0 && BG_FindStagesForClass( ent->client->pers.classSelection, g_alienStage.integer ) )
{
//remove credit
- G_AddCreditToClient( ent->client, -(short)numLevels );
+ G_AddCreditToClient( ent->client, -(short)numLevels, qtrue );
ClientUserinfoChanged( clientNum );
VectorCopy( infestOrigin, ent->s.pos.trBase );
@@ -1260,7 +1260,7 @@ void Cmd_Class_f( gentity_t *ent )
}
ent->client->pers.classSelection =
- ent->client->ps.stats[ STAT_PCLASS ] = PCL_H_BASE;
+ ent->client->ps.stats[ STAT_PCLASS ] = PCL_HUMAN;
//set the item to spawn with
if( !Q_stricmp( s, BG_FindNameForWeapon( WP_MACHINEGUN ) ) )
@@ -1569,7 +1569,7 @@ void Cmd_Buy_f( gentity_t *ent )
ent->client->ps.stats[ STAT_MISC ] = 0;
//subtract from funds
- G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ) );
+ G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ), qfalse );
}
else if( upgrade != UP_NONE )
{
@@ -1654,7 +1654,7 @@ void Cmd_Buy_f( gentity_t *ent )
}
//subtract from funds
- G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ) );
+ G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ), qfalse );
}
else
{
@@ -1730,7 +1730,7 @@ void Cmd_Sell_f( gentity_t *ent )
BG_RemoveWeaponFromInventory( weapon, ent->client->ps.stats );
//add to funds
- G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ) );
+ G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ), qfalse );
}
//if we have this weapon selected, force a new selection
@@ -1765,7 +1765,7 @@ void Cmd_Sell_f( gentity_t *ent )
}
//add to funds
- G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ) );
+ G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ), qfalse );
}
//if we have this upgrade selected, force a new selection
@@ -1781,7 +1781,7 @@ void Cmd_Sell_f( gentity_t *ent )
BG_RemoveWeaponFromInventory( i, ent->client->ps.stats );
//add to funds
- G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ) );
+ G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ), qfalse );
}
//if we have this weapon selected, force a new selection
@@ -1819,7 +1819,7 @@ void Cmd_Sell_f( gentity_t *ent )
}
//add to funds
- G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ) );
+ G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ), qfalse );
}
//if we have this upgrade selected, force a new selection
@@ -2210,7 +2210,7 @@ void Cmd_PTRCRestore_f( gentity_t *ent )
// set the correct credit
ent->client->ps.persistant[ PERS_CREDIT ] = 0;
- G_AddCreditToClient( ent->client, connection->clientCredit );
+ G_AddCreditToClient( ent->client, connection->clientCredit, qtrue );
}
}
}
diff --git a/src/game/g_combat.c b/src/game/g_combat.c
index 96708979..d89adadc 100644
--- a/src/game/g_combat.c
+++ b/src/game/g_combat.c
@@ -115,16 +115,16 @@ char *modNames[ ] =
"MOD_TRIGGER_HURT",
"MOD_ABUILDER_CLAW",
- "MOD_SOLDIER_BITE",
- "MOD_HYDRA_CLAW",
- "MOD_HYDRA_PCLOUD",
- "MOD_DRAGOON_CLAW",
- "MOD_DRAGOON_POUNCE",
- "MOD_DRAGOON_BOUNCEBALL",
- "MOD_CHIMERA_CLAW",
- "MOD_CHIMERA_ZAP",
- "MOD_BMOFO_CLAW",
- "MOD_BMOFO_CHARGE",
+ "MOD_LEVEL0_BITE",
+ "MOD_LEVEL1_CLAW",
+ "MOD_LEVEL1_PCLOUD",
+ "MOD_LEVEL3_CLAW",
+ "MOD_LEVEL3_POUNCE",
+ "MOD_LEVEL3_BOUNCEBALL",
+ "MOD_LEVEL2_CLAW",
+ "MOD_LEVEL2_ZAP",
+ "MOD_LEVEL4_CLAW",
+ "MOD_LEVEL4_CHARGE",
"MOD_SLOWBLOB",
"MOD_POISON",
@@ -223,9 +223,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
//punish team kills and suicides
if( attacker->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
- G_AddCreditToClient( attacker->client, -1 );
+ G_AddCreditToClient( attacker->client, -1, qtrue );
else if( attacker->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
- G_AddCreditToClient( attacker->client, -ASPAWN_VALUE );
+ G_AddCreditToClient( attacker->client, -ASPAWN_VALUE, qtrue );
}
else
{
@@ -269,7 +269,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
//add credit
G_AddCreditToClient( player->client,
- (int)( classValue * ( (float)self->credits[ i ] / totalDamage ) ) );
+ (int)( classValue * ( (float)self->credits[ i ] / totalDamage ) ), qtrue );
}
}
else if( self->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
@@ -302,7 +302,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
if( frags > 0 )
{
//add kills
- G_AddCreditToClient( player->client, frags );
+ G_AddCreditToClient( player->client, frags, qtrue );
//can't revist this account later
self->credits[ i ] = 0;
@@ -343,7 +343,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
player = g_entities + topClient;
//add kills
- G_AddCreditToClient( player->client, 1 );
+ G_AddCreditToClient( player->client, 1, qtrue );
//can't revist this account again
self->credits[ topClient ] = 0;
@@ -1065,7 +1065,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
{
if( !( targ->client->ps.stats[ STAT_STATE ] & SS_POISONED ) &&
!BG_InventoryContainsUpgrade( UP_BATTLESUIT, targ->client->ps.stats ) &&
- mod != MOD_CHIMERA_ZAP )
+ mod != MOD_LEVEL2_ZAP )
{
targ->client->ps.stats[ STAT_STATE ] |= SS_POISONED;
targ->client->lastPoisonTime = level.time;
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 2885da8b..b974cf7d 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -732,6 +732,7 @@ gentity_t *fire_paraLockBlob( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_slowBlob( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_bounceBall( gentity_t *self, vec3_t start, vec3_t dir );
gentity_t *fire_hive( gentity_t *self, vec3_t start, vec3_t dir );
+gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir );
//
@@ -767,7 +768,7 @@ void ChargeAttack( gentity_t *ent, gentity_t *victim );
//
// g_client.c
//
-void G_AddCreditToClient( gclient_t *client, short credit );
+void G_AddCreditToClient( gclient_t *client, short credit, qboolean cap );
team_t TeamCount( int ignoreClientNum, int team );
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
gentity_t *SelectTremulousSpawnPoint( pTeam_t team, vec3_t origin, vec3_t angles );
diff --git a/src/game/g_missile.c b/src/game/g_missile.c
index 9efbd3e1..a1070cad 100644
--- a/src/game/g_missile.c
+++ b/src/game/g_missile.c
@@ -120,7 +120,18 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace )
return;
}
- if( !strcmp( ent->classname, "lockblob" ) )
+ if( !strcmp( ent->classname, "grenade" ) )
+ {
+ //grenade doesn't explode on impact
+ G_BounceMissile( ent, trace );
+
+ //only play a sound if requested
+ if( !( ent->s.eFlags & EF_NO_BOUNCE_SOUND ) )
+ G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
+
+ return;
+ }
+ else if( !strcmp( ent->classname, "lockblob" ) )
{
if( other->client && other->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
{
@@ -455,6 +466,50 @@ gentity_t *fire_luciferCannon( gentity_t *self, vec3_t start, vec3_t dir, int da
return bolt;
}
+/*
+=================
+launch_grenade
+
+=================
+*/
+gentity_t *launch_grenade( gentity_t *self, vec3_t start, vec3_t dir )
+{
+ gentity_t *bolt;
+
+ VectorNormalize( dir );
+
+ bolt = G_Spawn( );
+ bolt->classname = "grenade";
+ bolt->nextthink = level.time + 5000;
+ bolt->think = G_ExplodeMissile;
+ bolt->s.eType = ET_MISSILE;
+ bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
+ bolt->s.weapon = WP_GRENADE;
+ bolt->s.eFlags = EF_BOUNCE_HALF;
+ bolt->s.generic1 = self->s.generic1; //weaponMode
+ bolt->r.ownerNum = self->s.number;
+ bolt->parent = self;
+ bolt->damage = GRENADE_DAMAGE;
+ bolt->splashDamage = GRENADE_DAMAGE;
+ bolt->splashRadius = GRENADE_RANGE;
+ bolt->methodOfDeath = MOD_GRENADE;
+ bolt->splashMethodOfDeath = MOD_GRENADE;
+ bolt->clipmask = MASK_SHOT;
+ bolt->target_ent = NULL;
+ bolt->r.mins[ 0 ] = bolt->r.mins[ 1 ] = bolt->r.mins[ 2 ] = -3.0f;
+ bolt->r.maxs[ 0 ] = bolt->r.maxs[ 1 ] = bolt->r.maxs[ 2 ] = 3.0f;
+ bolt->s.time = level.time;
+
+ bolt->s.pos.trType = TR_GRAVITY;
+ bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
+ VectorCopy( start, bolt->s.pos.trBase );
+ VectorScale( dir, GRENADE_SPEED, bolt->s.pos.trDelta );
+ SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
+
+ VectorCopy( start, bolt->r.currentOrigin );
+
+ return bolt;
+}
//=============================================================================
/*
@@ -719,22 +774,22 @@ gentity_t *fire_bounceBall( gentity_t *self, vec3_t start, vec3_t dir )
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
- bolt->s.weapon = WP_DRAGOON_UPG;
+ bolt->s.weapon = WP_ALEVEL3_UPG;
bolt->s.generic1 = self->s.generic1; //weaponMode
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
- bolt->damage = DRAGOON_BOUNCEBALL_DMG;
+ bolt->damage = LEVEL3_BOUNCEBALL_DMG;
bolt->splashDamage = 0;
bolt->splashRadius = 0;
- bolt->methodOfDeath = MOD_DRAGOON_BOUNCEBALL;
- bolt->splashMethodOfDeath = MOD_DRAGOON_BOUNCEBALL;
+ bolt->methodOfDeath = MOD_LEVEL3_BOUNCEBALL;
+ bolt->splashMethodOfDeath = MOD_LEVEL3_BOUNCEBALL;
bolt->clipmask = MASK_SHOT;
bolt->target_ent = NULL;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
- VectorScale( dir, DRAGOON_BOUNCEBALL_SPEED, bolt->s.pos.trDelta );
+ VectorScale( dir, LEVEL3_BOUNCEBALL_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy( start, bolt->r.currentOrigin );
/*bolt->s.eFlags |= EF_BOUNCE;*/
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 26454f59..ddb5e0a7 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -356,6 +356,21 @@ void flamerFire( gentity_t *ent )
/*
======================================================================
+GRENADE
+
+======================================================================
+*/
+
+void throwGrenade( gentity_t *ent )
+{
+ gentity_t *m;
+
+ m = launch_grenade( ent, muzzle, forward );
+}
+
+/*
+======================================================================
+
LAS GUN
======================================================================
@@ -665,7 +680,7 @@ void slowBlobFire( gentity_t *ent )
/*
======================================================================
-SOLDIER
+LEVEL0
======================================================================
*/
@@ -684,15 +699,15 @@ qboolean CheckVenomAttack( gentity_t *ent )
int damage;
vec3_t mins, maxs;
- VectorSet( mins, -SOLDIER_BITE_WIDTH, -SOLDIER_BITE_WIDTH, -SOLDIER_BITE_WIDTH );
- VectorSet( maxs, SOLDIER_BITE_WIDTH, SOLDIER_BITE_WIDTH, SOLDIER_BITE_WIDTH );
+ VectorSet( mins, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH );
+ VectorSet( maxs, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH );
// set aiming directions
AngleVectors( ent->client->ps.viewangles, forward, right, up );
CalcMuzzlePoint( ent, forward, right, up, muzzle );
- VectorMA( muzzle, SOLDIER_BITE_RANGE, forward, end );
+ VectorMA( muzzle, LEVEL0_BITE_RANGE, forward, end );
trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT );
@@ -720,7 +735,7 @@ qboolean CheckVenomAttack( gentity_t *ent )
tent->s.generic1 = ent->s.generic1; //weaponMode
}
- G_Damage( traceEnt, ent, ent, forward, tr.endpos, SOLDIER_BITE_DMG, DAMAGE_NO_KNOCKBACK, MOD_SOLDIER_BITE );
+ G_Damage( traceEnt, ent, ent, forward, tr.endpos, LEVEL0_BITE_DMG, DAMAGE_NO_KNOCKBACK, MOD_LEVEL0_BITE );
return qtrue;
}
@@ -728,7 +743,7 @@ qboolean CheckVenomAttack( gentity_t *ent )
/*
======================================================================
-HYDRA
+LEVEL1
======================================================================
*/
@@ -749,7 +764,7 @@ void CheckGrabAttack( gentity_t *ent )
CalcMuzzlePoint( ent, forward, right, up, muzzle );
- VectorMA( muzzle, HYDRA_GRAB_RANGE, forward, end );
+ VectorMA( muzzle, LEVEL1_GRAB_RANGE, forward, end );
trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
if( tr.surfaceFlags & SURF_NOIMPACT )
@@ -775,10 +790,14 @@ void CheckGrabAttack( gentity_t *ent )
traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );
}
+ if( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
+ {
+ //event for client side grab effect
+ G_AddPredictableEvent( ent, EV_LEV1_GRAB, 0 );
+ }
+
traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;
traceEnt->client->lastGrabTime = level.time;
-
- //FIXME: event for some client side grab effect?
}
/*
@@ -789,7 +808,7 @@ poisonCloud
void poisonCloud( gentity_t *ent )
{
int entityList[ MAX_GENTITIES ];
- vec3_t range = { HYDRA_PCLOUD_RANGE, HYDRA_PCLOUD_RANGE, HYDRA_PCLOUD_RANGE };
+ vec3_t range = { LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE };
vec3_t mins, maxs, dir;
int i, num;
gentity_t *humanPlayer;
@@ -828,10 +847,84 @@ void poisonCloud( gentity_t *ent )
}
}
+
/*
======================================================================
-DRAGOON
+LEVEL2
+
+======================================================================
+*/
+
+/*
+===============
+areaZapFire
+===============
+*/
+void areaZapFire( gentity_t *ent )
+{
+ int entityList[ MAX_GENTITIES ];
+ int targetList[ MAX_GENTITIES ];
+ vec3_t range = { LEVEL2_AREAZAP_RANGE, LEVEL2_AREAZAP_RANGE, LEVEL2_AREAZAP_RANGE };
+ vec3_t mins, maxs, dir;
+ int i, num, numTargets = 0;
+ gentity_t *enemy;
+ gentity_t *tent;
+ trace_t tr;
+ int damage;
+
+ 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++ )
+ {
+ enemy = &g_entities[ entityList[ i ] ];
+
+ if( ( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ||
+ ( enemy->s.eType == ET_BUILDABLE && BG_FindTeamForBuildable( enemy->s.modelindex ) == BIT_HUMANS ) )
+ {
+ trap_Trace( &tr, muzzle, NULL, NULL, enemy->s.origin, ent->s.number, MASK_SHOT );
+
+ //can't see target from here
+ if( tr.entityNum == ENTITYNUM_WORLD )
+ continue;
+
+ targetList[ numTargets++ ] = entityList[ i ];
+ }
+ }
+
+ damage = (int)( (float)LEVEL2_AREAZAP_DMG / (float)numTargets );
+ for( i = 0; i < numTargets; i++ )
+ {
+ enemy = &g_entities[ targetList[ i ] ];
+
+ VectorSubtract( enemy->s.origin, muzzle, dir );
+ VectorNormalize( dir );
+
+ //do some damage
+ G_Damage( enemy, ent, ent, dir, tr.endpos,
+ damage, DAMAGE_NO_KNOCKBACK | DAMAGE_NO_LOCDAMAGE, MOD_LEVEL2_ZAP );
+
+ // snap the endpos to integers to save net bandwidth, but nudged towards the line
+ SnapVectorTowards( tr.endpos, muzzle );
+
+ // send arc effect
+ tent = G_TempEntity( enemy->s.pos.trBase, EV_ALIENZAP );
+
+ VectorCopy( ent->client->ps.origin, tent->s.origin2 );
+
+ tent->s.generic1 = ent->s.number; //src
+ tent->s.clientNum = enemy->s.number; //dest
+ }
+}
+
+
+/*
+======================================================================
+
+LEVEL3
======================================================================
*/
@@ -850,8 +943,8 @@ qboolean CheckPounceAttack( gentity_t *ent )
int damage;
vec3_t mins, maxs;
- VectorSet( mins, -DRAGOON_POUNCE_WIDTH, -DRAGOON_POUNCE_WIDTH, -DRAGOON_POUNCE_WIDTH );
- VectorSet( maxs, DRAGOON_POUNCE_WIDTH, DRAGOON_POUNCE_WIDTH, DRAGOON_POUNCE_WIDTH );
+ VectorSet( mins, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH );
+ VectorSet( maxs, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH );
if( !ent->client->allowedToPounce )
return qfalse;
@@ -867,7 +960,7 @@ qboolean CheckPounceAttack( gentity_t *ent )
CalcMuzzlePoint( ent, forward, right, up, muzzle );
- VectorMA( muzzle, DRAGOON_POUNCE_RANGE, forward, end );
+ VectorMA( muzzle, LEVEL3_POUNCE_RANGE, forward, end );
trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
@@ -893,9 +986,9 @@ qboolean CheckPounceAttack( gentity_t *ent )
if( !traceEnt->takedamage )
return qfalse;
- damage = (int)( ( (float)ent->client->pouncePayload / (float)DRAGOON_POUNCE_SPEED ) * DRAGOON_POUNCE_DMG );
+ damage = (int)( ( (float)ent->client->pouncePayload / (float)LEVEL3_POUNCE_SPEED ) * LEVEL3_POUNCE_DMG );
- G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_DRAGOON_POUNCE );
+ G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_LEVEL3_POUNCE );
ent->client->allowedToPounce = qfalse;
@@ -911,84 +1004,11 @@ void bounceBallFire( gentity_t *ent )
// VectorAdd( m->s.pos.trDelta, ent->client->ps.velocity, m->s.pos.trDelta ); // "real" physics
}
-/*
-======================================================================
-
-CHIMERA
-
-======================================================================
-*/
-
-/*
-===============
-areaZapFire
-===============
-*/
-void areaZapFire( gentity_t *ent )
-{
- int entityList[ MAX_GENTITIES ];
- int targetList[ MAX_GENTITIES ];
- vec3_t range = { CHIMERA_AREAZAP_RANGE, CHIMERA_AREAZAP_RANGE, CHIMERA_AREAZAP_RANGE };
- vec3_t mins, maxs, dir;
- int i, num, numTargets = 0;
- gentity_t *enemy;
- gentity_t *tent;
- trace_t tr;
- int damage;
-
- 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++ )
- {
- enemy = &g_entities[ entityList[ i ] ];
-
- if( ( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ||
- ( enemy->s.eType == ET_BUILDABLE && BG_FindTeamForBuildable( enemy->s.modelindex ) == BIT_HUMANS ) )
- {
- trap_Trace( &tr, muzzle, NULL, NULL, enemy->s.origin, ent->s.number, MASK_SHOT );
-
- //can't see target from here
- if( tr.entityNum == ENTITYNUM_WORLD )
- continue;
-
- targetList[ numTargets++ ] = entityList[ i ];
- }
- }
-
- damage = (int)( (float)CHIMERA_AREAZAP_DMG / (float)numTargets );
- for( i = 0; i < numTargets; i++ )
- {
- enemy = &g_entities[ targetList[ i ] ];
-
- VectorSubtract( enemy->s.origin, muzzle, dir );
- VectorNormalize( dir );
-
- //do some damage
- G_Damage( enemy, ent, ent, dir, tr.endpos,
- damage, DAMAGE_NO_KNOCKBACK | DAMAGE_NO_LOCDAMAGE, MOD_CHIMERA_ZAP );
-
- // snap the endpos to integers to save net bandwidth, but nudged towards the line
- SnapVectorTowards( tr.endpos, muzzle );
-
- // send arc effect
- tent = G_TempEntity( enemy->s.pos.trBase, EV_ALIENZAP );
-
- VectorCopy( ent->client->ps.origin, tent->s.origin2 );
-
- tent->s.generic1 = ent->s.number; //src
- tent->s.clientNum = enemy->s.number; //dest
- }
-}
-
-
/*
======================================================================
-BIG MOFO
+LEVEL4
======================================================================
*/
@@ -1007,7 +1027,7 @@ void ChargeAttack( gentity_t *ent, gentity_t *victim )
if( level.time < victim->chargeRepeat )
return;
- victim->chargeRepeat = level.time + BMOFO_CHARGE_REPEAT;
+ victim->chargeRepeat = level.time + LEVEL4_CHARGE_REPEAT;
VectorSubtract( victim->s.origin, ent->s.origin, forward );
VectorNormalize( forward );
@@ -1025,9 +1045,9 @@ void ChargeAttack( gentity_t *ent, gentity_t *victim )
if( !victim->takedamage )
return;
- damage = (int)( ( (float)ent->client->ps.stats[ STAT_MISC ] / (float)BMOFO_CHARGE_TIME ) * BMOFO_CHARGE_DMG );
+ damage = (int)( ( (float)ent->client->ps.stats[ STAT_MISC ] / (float)LEVEL4_CHARGE_TIME ) * LEVEL4_CHARGE_DMG );
- G_Damage( victim, ent, ent, forward, victim->s.origin, damage, 0, MOD_BMOFO_CHARGE );
+ G_Damage( victim, ent, ent, forward, victim->s.origin, damage, 0, MOD_LEVEL4_CHARGE );
}
//======================================================================
@@ -1071,7 +1091,7 @@ void FireWeapon3( gentity_t *ent )
// fire the specific weapon
switch( ent->s.weapon )
{
- case WP_DRAGOON_UPG:
+ case WP_ALEVEL3_UPG:
bounceBallFire( ent );
break;
@@ -1106,10 +1126,10 @@ void FireWeapon2( gentity_t *ent )
// fire the specific weapon
switch( ent->s.weapon )
{
- case WP_HYDRA_UPG:
+ case WP_ALEVEL1_UPG:
poisonCloud( ent );
break;
- case WP_CHIMERA_UPG:
+ case WP_ALEVEL2_UPG:
areaZapFire( ent );
break;
@@ -1150,22 +1170,22 @@ void FireWeapon( gentity_t *ent )
// fire the specific weapon
switch( ent->s.weapon )
{
- case WP_HYDRA:
- case WP_HYDRA_UPG:
- meleeAttack( ent, HYDRA_CLAW_RANGE, HYDRA_CLAW_WIDTH, HYDRA_CLAW_DMG, MOD_HYDRA_CLAW );
+ case WP_ALEVEL1:
+ case WP_ALEVEL1_UPG:
+ meleeAttack( ent, LEVEL1_CLAW_RANGE, LEVEL1_CLAW_WIDTH, LEVEL1_CLAW_DMG, MOD_LEVEL1_CLAW );
break;
- case WP_DRAGOON:
- case WP_DRAGOON_UPG:
- meleeAttack( ent, DRAGOON_CLAW_RANGE, DRAGOON_CLAW_WIDTH, DRAGOON_CLAW_DMG, MOD_DRAGOON_CLAW );
+ case WP_ALEVEL3:
+ case WP_ALEVEL3_UPG:
+ meleeAttack( ent, LEVEL3_CLAW_RANGE, LEVEL3_CLAW_WIDTH, LEVEL3_CLAW_DMG, MOD_LEVEL3_CLAW );
break;
- case WP_CHIMERA:
- meleeAttack( ent, CHIMERA_CLAW_RANGE, CHIMERA_CLAW_WIDTH, CHIMERA_CLAW_DMG, MOD_CHIMERA_CLAW );
+ case WP_ALEVEL2:
+ meleeAttack( ent, LEVEL2_CLAW_RANGE, LEVEL2_CLAW_WIDTH, LEVEL2_CLAW_DMG, MOD_LEVEL2_CLAW );
break;
- case WP_CHIMERA_UPG:
- meleeAttack( ent, CHIMERA_CLAW_RANGE, CHIMERA_CLAW_WIDTH, CHIMERA_CLAW_DMG, MOD_CHIMERA_CLAW );
+ case WP_ALEVEL2_UPG:
+ meleeAttack( ent, LEVEL2_CLAW_RANGE, LEVEL2_CLAW_WIDTH, LEVEL2_CLAW_DMG, MOD_LEVEL2_CLAW );
break;
- case WP_BIGMOFO:
- meleeAttack( ent, BMOFO_CLAW_RANGE, BMOFO_CLAW_WIDTH, BMOFO_CLAW_DMG, MOD_BMOFO_CLAW );
+ case WP_ALEVEL4:
+ meleeAttack( ent, LEVEL4_CLAW_RANGE, LEVEL4_CLAW_WIDTH, LEVEL4_CLAW_DMG, MOD_LEVEL4_CLAW );
break;
case WP_BLASTER:
@@ -1198,6 +1218,9 @@ void FireWeapon( gentity_t *ent )
case WP_PAIN_SAW:
painSawFire( ent );
break;
+ case WP_GRENADE:
+ throwGrenade( ent );
+ break;
case WP_LOCKBLOB_LAUNCHER:
lockBlobLauncherFire( ent );
diff --git a/src/game/q_shared.h b/src/game/q_shared.h
index 64ef9f30..69496267 100644
--- a/src/game/q_shared.h
+++ b/src/game/q_shared.h
@@ -634,6 +634,7 @@ typedef struct {
#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define Vector4Add(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
#define SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));}
// just in case you do't want to use the macros
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index 7e723ecc..53e07a0b 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -38,61 +38,61 @@
#define ABUILDER_BLOB_SPEED_MOD 0.5f
#define ABUILDER_BLOB_TIME 5000
-#define SOLDIER_BITE_DMG ADM(60)
-#define SOLDIER_BITE_RANGE 64.0f
-#define SOLDIER_BITE_WIDTH 6.0f
-#define SOLDIER_BITE_REPEAT 500
-
-#define HYDRA_CLAW_DMG ADM(40)
-#define HYDRA_CLAW_RANGE 96.0f
-#define HYDRA_CLAW_WIDTH 10.0f
-#define HYDRA_CLAW_REPEAT 600
-#define HYDRA_CLAW_U_REPEAT 500
-#define HYDRA_GRAB_RANGE 64.0f
-#define HYDRA_GRAB_TIME 1000
-#define HYDRA_PCLOUD_DMG ADM(5)
-#define HYDRA_PCLOUD_RANGE 200.0f
-#define HYDRA_PCLOUD_REPEAT 2000
-#define HYDRA_PCLOUD_TIME 10000
-
-#define CHIMERA_CLAW_DMG ADM(50)
-#define CHIMERA_CLAW_RANGE 96.0f
-#define CHIMERA_CLAW_WIDTH 12.0f
-#define CHIMERA_CLAW_REPEAT 500
-#define CHIMERA_CLAW_U_REPEAT 400
-#define CHIMERA_AREAZAP_DMG ADM(100)
-#define CHIMERA_AREAZAP_RANGE 200.0f
-#define CHIMERA_AREAZAP_REPEAT 3000
-#define CHIMERA_WALLJUMP_MAXSPEED 1000.0f
-
-#define DRAGOON_CLAW_DMG ADM(100)
-#define DRAGOON_CLAW_RANGE 96.0f
-#define DRAGOON_CLAW_WIDTH 16.0f
-#define DRAGOON_CLAW_REPEAT 700
-#define DRAGOON_CLAW_U_REPEAT 600
-#define DRAGOON_POUNCE_DMG ADM(200)
-#define DRAGOON_POUNCE_RANGE 96.0f
-#define DRAGOON_POUNCE_WIDTH 16.0f
-#define DRAGOON_POUNCE_SPEED 700
-#define DRAGOON_POUNCE_UPG_SPEED 800
-#define DRAGOON_POUNCE_SPEED_MOD 0.75f
-#define DRAGOON_POUNCE_TIME 700
-#define DRAGOON_BOUNCEBALL_DMG ADM(150)
-#define DRAGOON_BOUNCEBALL_REPEAT 1000
-#define DRAGOON_BOUNCEBALL_SPEED 1000.0f
-
-#define BMOFO_CLAW_DMG ADM(150)
-#define BMOFO_CLAW_RANGE 128.0f
-#define BMOFO_CLAW_WIDTH 20.0f
-#define BMOFO_CLAW_REPEAT 750
-#define BMOFO_REGEN_RANGE 200.0f
-#define BMOFO_REGEN_MOD 2.0f
-#define BMOFO_CHARGE_SPEED 2.0f
-#define BMOFO_CHARGE_TIME 3000
-#define BMOFO_CHARGE_CHARGE_TIME 1000
-#define BMOFO_CHARGE_CHARGE_RATIO (BMOFO_CHARGE_TIME/BMOFO_CHARGE_CHARGE_TIME)
-#define BMOFO_CHARGE_REPEAT 500
-#define BMOFO_CHARGE_DMG ADM(200)
+#define LEVEL0_BITE_DMG ADM(60)
+#define LEVEL0_BITE_RANGE 64.0f
+#define LEVEL0_BITE_WIDTH 6.0f
+#define LEVEL0_BITE_REPEAT 500
+
+#define LEVEL1_CLAW_DMG ADM(40)
+#define LEVEL1_CLAW_RANGE 96.0f
+#define LEVEL1_CLAW_WIDTH 10.0f
+#define LEVEL1_CLAW_REPEAT 600
+#define LEVEL1_CLAW_U_REPEAT 500
+#define LEVEL1_GRAB_RANGE 64.0f
+#define LEVEL1_GRAB_TIME 1000
+#define LEVEL1_PCLOUD_DMG ADM(5)
+#define LEVEL1_PCLOUD_RANGE 200.0f
+#define LEVEL1_PCLOUD_REPEAT 2000
+#define LEVEL1_PCLOUD_TIME 10000
+
+#define LEVEL2_CLAW_DMG ADM(50)
+#define LEVEL2_CLAW_RANGE 96.0f
+#define LEVEL2_CLAW_WIDTH 12.0f
+#define LEVEL2_CLAW_REPEAT 500
+#define LEVEL2_CLAW_U_REPEAT 400
+#define LEVEL2_AREAZAP_DMG ADM(100)
+#define LEVEL2_AREAZAP_RANGE 200.0f
+#define LEVEL2_AREAZAP_REPEAT 3000
+#define LEVEL2_WALLJUMP_MAXSPEED 1000.0f
+
+#define LEVEL3_CLAW_DMG ADM(100)
+#define LEVEL3_CLAW_RANGE 96.0f
+#define LEVEL3_CLAW_WIDTH 16.0f
+#define LEVEL3_CLAW_REPEAT 700
+#define LEVEL3_CLAW_U_REPEAT 600
+#define LEVEL3_POUNCE_DMG ADM(200)
+#define LEVEL3_POUNCE_RANGE 96.0f
+#define LEVEL3_POUNCE_WIDTH 16.0f
+#define LEVEL3_POUNCE_SPEED 700
+#define LEVEL3_POUNCE_UPG_SPEED 800
+#define LEVEL3_POUNCE_SPEED_MOD 0.75f
+#define LEVEL3_POUNCE_TIME 700
+#define LEVEL3_BOUNCEBALL_DMG ADM(150)
+#define LEVEL3_BOUNCEBALL_REPEAT 1000
+#define LEVEL3_BOUNCEBALL_SPEED 1000.0f
+
+#define LEVEL4_CLAW_DMG ADM(150)
+#define LEVEL4_CLAW_RANGE 128.0f
+#define LEVEL4_CLAW_WIDTH 20.0f
+#define LEVEL4_CLAW_REPEAT 750
+#define LEVEL4_REGEN_RANGE 200.0f
+#define LEVEL4_REGEN_MOD 2.0f
+#define LEVEL4_CHARGE_SPEED 2.0f
+#define LEVEL4_CHARGE_TIME 3000
+#define LEVEL4_CHARGE_CHARGE_TIME 1000
+#define LEVEL4_CHARGE_CHARGE_RATIO (LEVEL4_CHARGE_TIME/LEVEL4_CHARGE_CHARGE_TIME)
+#define LEVEL4_CHARGE_REPEAT 500
+#define LEVEL4_CHARGE_DMG ADM(200)
@@ -124,53 +124,53 @@
#define ABUILDER_UPG_REGEN 3
#define ABUILDER_UPG_COST 0
-#define SOLDIER_SPEED 1.3f
-#define SOLDIER_VALUE AVM(175)
-#define SOLDIER_HEALTH AHM(25)
-#define SOLDIER_REGEN 1
-#define SOLDIER_COST 0
-
-#define HYDRA_SPEED 1.25f
-#define HYDRA_VALUE AVM(225)
-#define HYDRA_HEALTH AHM(75)
-#define HYDRA_REGEN 2
-#define HYDRA_COST 1
-
-#define HYDRA_UPG_SPEED 1.25f
-#define HYDRA_UPG_VALUE AVM(275)
-#define HYDRA_UPG_HEALTH AHM(100)
-#define HYDRA_UPG_REGEN 2
-#define HYDRA_UPG_COST 1
-
-#define CHIMERA_SPEED 1.2f
-#define CHIMERA_VALUE AVM(350)
-#define CHIMERA_HEALTH AHM(150)
-#define CHIMERA_REGEN 3
-#define CHIMERA_COST 1
-
-#define CHIMERA_UPG_SPEED 1.2f
-#define CHIMERA_UPG_VALUE AVM(450)
-#define CHIMERA_UPG_HEALTH AHM(175)
-#define CHIMERA_UPG_REGEN 4
-#define CHIMERA_UPG_COST 1
-
-#define DRAGOON_SPEED 1.1f
-#define DRAGOON_VALUE AVM(500)
-#define DRAGOON_HEALTH AHM(200)
-#define DRAGOON_REGEN 5
-#define DRAGOON_COST 1
-
-#define DRAGOON_UPG_SPEED 1.1f
-#define DRAGOON_UPG_VALUE AVM(600)
-#define DRAGOON_UPG_HEALTH AHM(250)
-#define DRAGOON_UPG_REGEN 6
-#define DRAGOON_UPG_COST 1
-
-#define BMOFO_SPEED 1.2f
-#define BMOFO_VALUE AVM(800)
-#define BMOFO_HEALTH AHM(400)
-#define BMOFO_REGEN 7
-#define BMOFO_COST 2
+#define LEVEL0_SPEED 1.3f
+#define LEVEL0_VALUE AVM(175)
+#define LEVEL0_HEALTH AHM(25)
+#define LEVEL0_REGEN 1
+#define LEVEL0_COST 0
+
+#define LEVEL1_SPEED 1.25f
+#define LEVEL1_VALUE AVM(225)
+#define LEVEL1_HEALTH AHM(75)
+#define LEVEL1_REGEN 2
+#define LEVEL1_COST 1
+
+#define LEVEL1_UPG_SPEED 1.25f
+#define LEVEL1_UPG_VALUE AVM(275)
+#define LEVEL1_UPG_HEALTH AHM(100)
+#define LEVEL1_UPG_REGEN 2
+#define LEVEL1_UPG_COST 1
+
+#define LEVEL2_SPEED 1.2f
+#define LEVEL2_VALUE AVM(350)
+#define LEVEL2_HEALTH AHM(150)
+#define LEVEL2_REGEN 3
+#define LEVEL2_COST 1
+
+#define LEVEL2_UPG_SPEED 1.2f
+#define LEVEL2_UPG_VALUE AVM(450)
+#define LEVEL2_UPG_HEALTH AHM(175)
+#define LEVEL2_UPG_REGEN 4
+#define LEVEL2_UPG_COST 1
+
+#define LEVEL3_SPEED 1.1f
+#define LEVEL3_VALUE AVM(500)
+#define LEVEL3_HEALTH AHM(200)
+#define LEVEL3_REGEN 5
+#define LEVEL3_COST 1
+
+#define LEVEL3_UPG_SPEED 1.1f
+#define LEVEL3_UPG_VALUE AVM(600)
+#define LEVEL3_UPG_HEALTH AHM(250)
+#define LEVEL3_UPG_REGEN 6
+#define LEVEL3_UPG_COST 1
+
+#define LEVEL4_SPEED 1.2f
+#define LEVEL4_VALUE AVM(800)
+#define LEVEL4_HEALTH AHM(400)
+#define LEVEL4_REGEN 7
+#define LEVEL4_COST 2
@@ -329,6 +329,12 @@
#define PAINSAW_DAMAGE HDM(20)
#define PAINSAW_RANGE 48.0f
+#define GRENADE_PRICE 300
+#define GRENADE_REPEAT 0
+#define GRENADE_DAMAGE HDM(350)
+#define GRENADE_RANGE 192.0f
+#define GRENADE_SPEED 400.0f
+
#define SHOTGUN_PRICE 150
#define SHOTGUN_SHELLS 8
#define SHOTGUN_PELLETS 8 //used to sync server and client side
@@ -549,4 +555,4 @@
#define FREEKILL_PERIOD 180000 //msec
#define FREEKILL_ALIEN 1
-#define FREEKILL_HUMAN SOLDIER_VALUE
+#define FREEKILL_HUMAN LEVEL0_VALUE
diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
index 4389074c..60480b90 100644
--- a/src/ui/ui_main.c
+++ b/src/ui/ui_main.c
@@ -3349,16 +3349,16 @@ static void UI_LoadTremAlienClasses( void )
uiInfo.tremAlienClassCount = 2;
uiInfo.tremAlienClassList[ 0 ].text =
- String_Alloc( BG_FindHumanNameForClassNum( PCL_A_O_BASE ) );
+ String_Alloc( BG_FindHumanNameForClassNum( PCL_ALIEN_LEVEL0 ) );
uiInfo.tremAlienClassList[ 0 ].cmd =
- String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( PCL_A_O_BASE ) ) );
+ String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( PCL_ALIEN_LEVEL0 ) ) );
uiInfo.tremAlienClassList[ 0 ].infopane =
- UI_FindInfoPaneByName( va( "%sclass", BG_FindNameForClassNum( PCL_A_O_BASE ) ) );
+ UI_FindInfoPaneByName( va( "%sclass", BG_FindNameForClassNum( PCL_ALIEN_LEVEL0 ) ) );
- if( BG_FindStagesForClass( PCL_A_B_LEV1, UI_GetCurrentAlienStage( ) ) )
- bClass = PCL_A_B_LEV1;
+ if( BG_FindStagesForClass( PCL_ALIEN_BUILDER0_UPG, UI_GetCurrentAlienStage( ) ) )
+ bClass = PCL_ALIEN_BUILDER0_UPG;
else
- bClass = PCL_A_B_BASE;
+ bClass = PCL_ALIEN_BUILDER0;
uiInfo.tremAlienClassList[ 1 ].text =
String_Alloc( BG_FindHumanNameForClassNum( bClass ) );
@@ -6042,6 +6042,8 @@ void _UI_Init( qboolean inGameLoad ) {
const char *menuSet;
int start;
+ BG_InitClassOverrides( );
+
//uiInfo.inGameLoad = inGameLoad;
UI_RegisterCvars();