diff options
Diffstat (limited to 'src/cgame')
| -rw-r--r-- | src/cgame/cg_draw.c | 56 | ||||
| -rw-r--r-- | src/cgame/cg_ents.c | 121 | ||||
| -rw-r--r-- | src/cgame/cg_event.c | 92 | ||||
| -rw-r--r-- | src/cgame/cg_local.h | 41 | ||||
| -rw-r--r-- | src/cgame/cg_main.c | 38 | ||||
| -rw-r--r-- | src/cgame/cg_particles.c | 251 | ||||
| -rw-r--r-- | src/cgame/cg_players.c | 57 | ||||
| -rw-r--r-- | src/cgame/cg_scanner.c | 177 | ||||
| -rw-r--r-- | src/cgame/cg_view.c | 24 | ||||
| -rw-r--r-- | src/cgame/cg_weapons.c | 32 | 
10 files changed, 723 insertions, 166 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 = ¢->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( ¢->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 = ¢->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 );  | 
