Beispiel #1
0
	/**
	 * @brief Moves a tag to the parent entity's bounding box center.
	 */
	static void UpdateTagLocation( gentity_t *ent, gentity_t *parent )
	{
		vec3_t mins, maxs, center;

		if ( !parent ) return;

		VectorCopy( parent->s.origin, center );

		if ( parent->client )
		{
			BG_ClassBoundingBox( parent->client->ps.stats[ STAT_CLASS ], mins, maxs, nullptr, nullptr, nullptr );
			BG_MoveOriginToBBOXCenter( center, mins, maxs );

			// Also update weapon for humans.
			if( parent->client->pers.team == TEAM_HUMANS )
			{
				ent->s.bc_data = BG_GetPlayerWeapon( &parent->client->ps );
			}
		}
		else if ( parent->s.eType == ET_BUILDABLE )
		{
			BG_BuildableBoundingBox( parent->s.modelindex, mins, maxs );
			BG_MoveOriginToBBOXCenter( center, mins, maxs );
		}

		Move( ent, center );
	}
Beispiel #2
0
/*
==================
CG_GhostBuildable
==================
*/
void CG_GhostBuildable( buildable_t buildable )
{
  refEntity_t     ent;
  playerState_t   *ps;
  vec3_t          angles, entity_origin;
  vec3_t          mins, maxs;
  trace_t         tr;
  float           scale;

  ps = &cg.predictedPlayerState;

  memset( &ent, 0, sizeof( ent ) );

  BG_BuildableBoundingBox( buildable, mins, maxs );

  BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, CG_Trace, entity_origin, angles, &tr );

  CG_PositionAndOrientateBuildable( ps->viewangles, entity_origin, tr.plane.normal, ps->clientNum,
                                    mins, maxs, ent.axis, ent.origin );

  //offset on the Z axis if required
  VectorMA( ent.origin, BG_BuildableConfig( buildable )->zOffset, tr.plane.normal, ent.origin );

  VectorCopy( ent.origin, ent.lightingOrigin );
  VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all

  ent.hModel = cg_buildables[ buildable ].models[ 0 ];

  if( ps->stats[ STAT_BUILDABLE ] & SB_VALID_TOGGLEBIT )
    ent.customShader = cgs.media.greenBuildShader;
  else
    ent.customShader = cgs.media.redBuildShader;

  //rescale the model
  scale = BG_BuildableConfig( buildable )->modelScale;

  if( scale != 1.0f )
  {
    VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] );
    VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] );
    VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] );

    ent.nonNormalizedAxes = qtrue;
  }
  else
    ent.nonNormalizedAxes = qfalse;

  // add to refresh list
  trap_R_AddRefEntityToScene( &ent );
}
Beispiel #3
0
/*
==================
CG_BuildableStatusDisplay
==================
*/
static void CG_BuildableStatusDisplay( centity_t *cent )
{
  entityState_t   *es = &cent->currentState;
  vec3_t          origin;
  float           healthScale;
  int             health;
  float           x, y;
  vec4_t          color;
  qboolean        powered;
  trace_t         tr;
  float           d;
  buildStat_t     *bs;
  int             i, j;
  int             entNum;
  vec3_t          trOrigin;
  vec3_t          right;
  qboolean        visible = qfalse;
  vec3_t          mins, maxs;
  entityState_t   *hit;
  int             anim;

  if( BG_Buildable( es->modelindex )->team == TEAM_ALIENS )
    bs = &cgs.alienBuildStat;
  else
    bs = &cgs.humanBuildStat;

  if( !bs->loaded )
    return;

  d = Distance( cent->lerpOrigin, cg.refdef.vieworg );
  if( d > STATUS_MAX_VIEW_DIST )
    return;

  Vector4Copy( bs->foreColor, color );

  // trace for center point
  BG_BuildableBoundingBox( es->modelindex, mins, maxs );

  // hack for shrunken barricades
  anim = es->torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT );
  if( es->modelindex == BA_A_BARRICADE &&
      ( anim == BANIM_DESTROYED || !( es->eFlags & EF_B_SPAWNED ) ) )
    maxs[ 2 ] = (int)( maxs[ 2 ] * BARRICADE_SHRINKPROP );

  VectorCopy( cent->lerpOrigin, origin );
  
    // hack for shrunken shield
  anim = es->torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT );
  if( es->modelindex == BA_H_SHIELD &&
      ( anim == BANIM_DESTROYED || !( es->eFlags & EF_B_SPAWNED ) ) )
    maxs[ 2 ] = (int)( maxs[ 2 ] * SHIELD_SHRINKPROP );

  VectorCopy( cent->lerpOrigin, origin );

  // center point
  origin[ 2 ] += mins[ 2 ];
  origin[ 2 ] += ( abs( mins[ 2 ] ) + abs( maxs[ 2 ] ) ) / 2;

  entNum = cg.predictedPlayerState.clientNum;

  // if first try fails, step left, step right
  for( j = 0; j < 3; j++ )
  {
    VectorCopy( cg.refdef.vieworg, trOrigin );
    switch( j )
    {
      case 1:
        // step right
        AngleVectors( cg.refdefViewAngles, NULL, right, NULL );
        VectorMA( trOrigin, STATUS_PEEK_DIST, right, trOrigin );
        break;
      case 2:
        // step left
        AngleVectors( cg.refdefViewAngles, NULL, right, NULL );
        VectorMA( trOrigin, -STATUS_PEEK_DIST, right, trOrigin );
        break;
      default:
        break;
    }
    // look through up to 3 players and/or transparent buildables
    for( i = 0; i < 3; i++ )
    {
      CG_Trace( &tr, trOrigin, NULL, NULL, origin, entNum, MASK_SHOT );
      if( tr.entityNum == cent->currentState.number )
      {
        visible = qtrue;
        break;
      }

      if( tr.entityNum == ENTITYNUM_WORLD )
        break;

      hit  = &cg_entities[ tr.entityNum ].currentState;

      if( tr.entityNum < MAX_CLIENTS || ( hit->eType == ET_BUILDABLE &&
          ( !( es->eFlags & EF_B_SPAWNED ) ||
            BG_Buildable( hit->modelindex )->transparentTest ) ) )
      {
        entNum = tr.entityNum;
        VectorCopy( tr.endpos, trOrigin );
      }
      else
        break;
    }
  }
  // hack to make the kit obscure view
  if( cg_drawGun.integer && visible &&
      cg.predictedPlayerState.stats[ STAT_TEAM ] == TEAM_HUMANS &&
      CG_WorldToScreen( origin, &x, &y ) )
  {
    if( x > 450 && y > 290 )
      visible = qfalse;
  }

  if( !visible && cent->buildableStatus.visible )
  {
    cent->buildableStatus.visible   = qfalse;
    cent->buildableStatus.lastTime  = cg.time;
  }
  else if( visible && !cent->buildableStatus.visible )
  {
    cent->buildableStatus.visible   = qtrue;
    cent->buildableStatus.lastTime  = cg.time;
  }

  // Fade up
  if( cent->buildableStatus.visible )
  {
    if( cent->buildableStatus.lastTime + STATUS_FADE_TIME > cg.time )
      color[ 3 ] = (float)( cg.time - cent->buildableStatus.lastTime ) / STATUS_FADE_TIME;
  }

  // Fade down
  if( !cent->buildableStatus.visible )
  {
    if( cent->buildableStatus.lastTime + STATUS_FADE_TIME > cg.time )
      color[ 3 ] = 1.0f - (float)( cg.time - cent->buildableStatus.lastTime ) / STATUS_FADE_TIME;
    else
      return;
  }

  health = es->generic1;
  healthScale = (float)health / BG_Buildable( es->modelindex )->health;

  if( health > 0 && healthScale < 0.01f )
    healthScale = 0.01f;
  else if( healthScale < 0.0f )
    healthScale = 0.0f;
  else if( healthScale > 1.0f )
    healthScale = 1.0f;

  if( CG_WorldToScreen( origin, &x, &y ) )
  {
    float  picH = bs->frameHeight;
    float  picW = bs->frameWidth;
    float  picX = x;
    float  picY = y;
    float  scale;
    float  subH, subY;
    float  clipX, clipY, clipW, clipH;
    vec4_t frameColor;

    // this is fudged to get the width/height in the cfg to be more realistic
    scale = ( picH / d ) * 3;

    powered = es->eFlags & EF_B_POWERED;

    picH *= scale;
    picW *= scale;
    picX -= ( picW * 0.5f );
    picY -= ( picH * 0.5f );

    // sub-elements such as icons and number
    subH = picH - ( picH * bs->verticalMargin );
    subY = picY + ( picH * 0.5f ) - ( subH * 0.5f );

    clipW = ( 640.0f * cg_viewsize.integer ) / 100.0f;
    clipH = ( 480.0f * cg_viewsize.integer ) / 100.0f;
    clipX = 320.0f - ( clipW * 0.5f );
    clipY = 240.0f - ( clipH * 0.5f );
    CG_SetClipRegion( clipX, clipY, clipW, clipH );

    if( bs->frameShader )
    {
      Vector4Copy( bs->backColor, frameColor );
      frameColor[ 3 ] = color[ 3 ];
      trap_R_SetColor( frameColor );
      CG_DrawPic( picX, picY, picW, picH, bs->frameShader );
      trap_R_SetColor( NULL );
    }

    if( health > 0 )
    {
      float hX, hY, hW, hH;
      vec4_t healthColor;

      hX = picX + ( bs->healthPadding * scale );
      hY = picY + ( bs->healthPadding * scale );
      hH = picH - ( bs->healthPadding * 2.0f * scale );
      hW = picW * healthScale - ( bs->healthPadding * 2.0f * scale );

      if( healthScale == 1.0f )
        Vector4Copy( bs->healthLowColor, healthColor );
      else if( healthScale >= 0.75f )
        Vector4Copy( bs->healthGuardedColor, healthColor );
      else if( healthScale >= 0.50f )
        Vector4Copy( bs->healthElevatedColor, healthColor );
      else if( healthScale >= 0.25f )
        Vector4Copy( bs->healthHighColor, healthColor );
      else
        Vector4Copy( bs->healthSevereColor, healthColor );

      healthColor[ 3 ] = color[ 3 ];
      trap_R_SetColor( healthColor );

      CG_DrawPic( hX, hY, hW, hH, cgs.media.whiteShader );
      trap_R_SetColor( NULL );
    }

    if( bs->overlayShader )
    {
      float oW = bs->overlayWidth;
      float oH = bs->overlayHeight;
      float oX = x;
      float oY = y;

      oH *= scale;
      oW *= scale;
      oX -= ( oW * 0.5f );
      oY -= ( oH * 0.5f );

      trap_R_SetColor( frameColor );
      CG_DrawPic( oX, oY, oW, oH, bs->overlayShader );
      trap_R_SetColor( NULL );
    }

    trap_R_SetColor( color );
    if( !powered )
    {
      float pX;

      pX = picX + ( subH * bs->horizontalMargin );
	  trap_R_SetColor( NULL );
      CG_DrawPic( pX, subY, subH, subH, bs->noPowerShader );
    }

    {
      float nX;
      int healthMax;
      int healthPoints;

      healthMax = BG_Buildable( es->modelindex )->health;
      healthPoints = (int)( healthScale * healthMax );
      if( health > 0 && healthPoints < 1 )
        healthPoints = 1;
      nX = picX + ( picW * 0.5f ) - 2.0f - ( ( subH * 4 ) * 0.5f );

      if( healthPoints > 999 )
        nX -= 0.0f;
      else if( healthPoints > 99 )
        nX -= subH * 0.5f;
      else if( healthPoints > 9 )
        nX -= subH * 1.0f;
      else
        nX -= subH * 1.5f;

      CG_DrawField( nX, subY, 4, subH, subH, healthPoints );
    }

    trap_R_SetColor( NULL );
    CG_ClearClipRegion( );
  }
}
Beispiel #4
0
/*
==================
CG_Buildable
==================
*/
void CG_Buildable( centity_t *cent )
{
  refEntity_t     ent;
  entityState_t   *es = &cent->currentState;
  vec3_t          angles;
  vec3_t          surfNormal, xNormal, mins, maxs;
  vec3_t          refNormal = { 0.0f, 0.0f, 1.0f };
  float           rotAngle;
  team_t          team = BG_Buildable( es->modelindex )->team;
  float           scale;
  int             health;

  //must be before EF_NODRAW check
  if( team == TEAM_ALIENS )
    CG_Creep( cent );

  // if set to invisible, skip
  if( es->eFlags & EF_NODRAW )
  {
    if( CG_IsParticleSystemValid( &cent->buildablePS ) )
      CG_DestroyParticleSystem( &cent->buildablePS );

    return;
  }

  memset ( &ent, 0, sizeof( ent ) );

  VectorCopy( cent->lerpOrigin, ent.origin );
  VectorCopy( cent->lerpOrigin, ent.oldorigin );
  VectorCopy( cent->lerpOrigin, ent.lightingOrigin );

  VectorCopy( es->origin2, surfNormal );

  VectorCopy( es->angles, angles );
  BG_BuildableBoundingBox( es->modelindex, mins, maxs );

  if( es->pos.trType == TR_STATIONARY )
  {
    // Positioning a buildable involves potentially up to two traces, and
    // seeing as buildables rarely move, we cache the results and recalculate
    // only if the buildable moves or changes orientation
    if( VectorCompare( cent->buildableCache.cachedOrigin, cent->lerpOrigin ) &&
        VectorCompare( cent->buildableCache.cachedNormal, surfNormal ) )
    {
      VectorCopy( cent->buildableCache.axis[ 0 ], ent.axis[ 0 ] );
      VectorCopy( cent->buildableCache.axis[ 1 ], ent.axis[ 1 ] );
      VectorCopy( cent->buildableCache.axis[ 2 ], ent.axis[ 2 ] );
      VectorCopy( cent->buildableCache.origin, ent.origin );
    }
    else
    {
      CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal,
                                        es->number, mins, maxs, ent.axis,
                                        ent.origin );
      VectorCopy( ent.axis[ 0 ], cent->buildableCache.axis[ 0 ] );
      VectorCopy( ent.axis[ 1 ], cent->buildableCache.axis[ 1 ] );
      VectorCopy( ent.axis[ 2 ], cent->buildableCache.axis[ 2 ] );
      VectorCopy( ent.origin, cent->buildableCache.origin );
      VectorCopy( cent->lerpOrigin, cent->buildableCache.cachedOrigin );
      VectorCopy( surfNormal, cent->buildableCache.cachedNormal );
    }
  }

  //offset on the Z axis if required
  VectorMA( ent.origin, BG_BuildableConfig( es->modelindex )->zOffset, surfNormal, ent.origin );

  VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all
  VectorCopy( ent.origin, ent.lightingOrigin );

  ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ];

  if( !( es->eFlags & EF_B_SPAWNED ) )
  {
    sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild;

    if( team == TEAM_HUMANS )
    {
      ent.customShader = cgs.media.humanSpawningShader;
      prebuildSound = cgs.media.humanBuildablePrebuild;
    }
    else if( team == TEAM_ALIENS )
      prebuildSound = cgs.media.alienBuildablePrebuild;

    trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound );
  }

  CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );

  //rescale the model
  scale = BG_BuildableConfig( es->modelindex )->modelScale;

  if( scale != 1.0f )
  {
    VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] );
    VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] );
    VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] );

    ent.nonNormalizedAxes = qtrue;
  }
  else
    ent.nonNormalizedAxes = qfalse;

  if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
    ent.customShader = cgs.media.redBuildShader;

  //add to refresh list
  trap_R_AddRefEntityToScene( &ent );

  CrossProduct( surfNormal, refNormal, xNormal );
  VectorNormalize( xNormal );
  rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) );

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 1 ] )
  {
    refEntity_t turretBarrel;
    vec3_t      flatAxis[ 3 ];

    memset( &turretBarrel, 0, sizeof( turretBarrel ) );

    turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ];

    CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin );
    AnglesToAxis( es->angles2, flatAxis );

    RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretBarrel.oldframe = ent.oldframe;
    turretBarrel.frame    = ent.frame;
    turretBarrel.backlerp = ent.backlerp;

    turretBarrel.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] );
      VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] );
      VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] );

      turretBarrel.nonNormalizedAxes = qtrue;
    }
    else
      turretBarrel.nonNormalizedAxes = qfalse;

    if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
      turretBarrel.customShader = cgs.media.redBuildShader;

    trap_R_AddRefEntityToScene( &turretBarrel );
  }

  //turret barrel bit
  if( cg_buildables[ es->modelindex ].models[ 2 ] )
  {
    refEntity_t turretTop;
    vec3_t      flatAxis[ 3 ];
    vec3_t      swivelAngles;

    memset( &turretTop, 0, sizeof( turretTop ) );

    VectorCopy( es->angles2, swivelAngles );
    swivelAngles[ PITCH ] = 0.0f;

    turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ];

    CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" );
    VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin );
    AnglesToAxis( swivelAngles, flatAxis );

    RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle );
    RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle );

    turretTop.oldframe = ent.oldframe;
    turretTop.frame    = ent.frame;
    turretTop.backlerp = ent.backlerp;

    turretTop.customShader = ent.customShader;

    if( scale != 1.0f )
    {
      VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] );
      VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] );
      VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] );

      turretTop.nonNormalizedAxes = qtrue;
    }
    else
      turretTop.nonNormalizedAxes = qfalse;

    if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) )
      turretTop.customShader = cgs.media.redBuildShader;

    trap_R_AddRefEntityToScene( &turretTop );
  }

  //weapon effects for turrets
  if( es->eFlags & EF_FIRING )
  {
    weaponInfo_t  *weapon = &cg_weapons[ es->weapon ];

    if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME ||
        BG_Buildable( es->modelindex )->turretProjType == WP_TESLAGEN )
    {
      if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] ||
          weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] )
      {
        trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ),
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ],
            weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] );
      }
    }

    if( weapon->wim[ WPM_PRIMARY ].firingSound )
    {
      trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin,
          weapon->wim[ WPM_PRIMARY ].firingSound );
    }
    else if( weapon->readySound )
      trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound );
  }

  health = es->generic1;

  if( health < cent->lastBuildableHealth &&
      ( es->eFlags & EF_B_SPAWNED ) )
  {
    if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time )
    {
      if( team == TEAM_HUMANS )
      {
        int i = rand( ) % 4;
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] );
      }
      else if( team == TEAM_ALIENS )
        trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage );

      cent->lastBuildableDamageSoundTime = cg.time;
    }
  }

  cent->lastBuildableHealth = health;

  //smoke etc for damaged buildables
  CG_BuildableParticleEffects( cent );
}
Beispiel #5
0
	/**
	 * @brief Tags an entity.
	 */
	void Tag( gentity_t *ent, team_t team, bool permanent )
	{
		int data;
		vec3_t origin, mins, maxs;
		bool dead, player;
		gentity_t *beacon, **attachment;
		team_t targetTeam;

		// Get the beacon attachment owned by the tagging team.
		switch( team ) {
			case TEAM_ALIENS: attachment = &ent->alienTag; break;
			case TEAM_HUMANS: attachment = &ent->humanTag; break;
			default:                                       return;
		}

		// Just refresh existing tags.
		if ( *attachment ) {
			RefreshTag( *attachment, true );
			return;
		}

		switch( ent->s.eType ) {
			case ET_BUILDABLE:
				targetTeam = ent->buildableTeam;
				data       = ent->s.modelindex;
				dead       = G_Dead( ent );
				player     = false;
				BG_BuildableBoundingBox( ent->s.modelindex, mins, maxs );
				break;

			case ET_PLAYER:
				targetTeam = (team_t)ent->client->pers.team;
				dead       = G_Dead( ent );
				player     = true;
				BG_ClassBoundingBox( ent->client->pers.classSelection, mins, maxs, nullptr, nullptr, nullptr );

				// Set beacon data to class (aliens) or weapon (humans).
				switch( targetTeam ) {
					case TEAM_ALIENS: data = ent->client->ps.stats[ STAT_CLASS ];    break;
					case TEAM_HUMANS: data = BG_GetPlayerWeapon( &ent->client->ps ); break;
					default:                                                         return;
				}

				break;

			default:
				return;
		}

		// Don't tag dead targets.
		if ( dead ) return;

		// Set beacon origin to center of target bounding box.
		VectorCopy( ent->s.origin, origin );
		BG_MoveOriginToBBOXCenter( origin, mins, maxs );

		// Create new beacon and attach it.
		beacon = New( origin, BCT_TAG, data, team );
		beacon->tagAttachment = attachment;
		*attachment = beacon;
		beacon->s.bc_target = ent - g_entities;

		// Reset the entity's tag score.
		ent->tagScore = 0;

		// Set flags.
		if( player )             beacon->s.eFlags |= EF_BC_TAG_PLAYER;
		if( team != targetTeam ) beacon->s.eFlags |= EF_BC_ENEMY;

		// Set expiration time.
		if( permanent ) beacon->s.bc_etime = 0;
		else            RefreshTag( beacon, true );

		// Update the base clusterings.
		if ( ent->s.eType == ET_BUILDABLE ) BaseClustering::Update( beacon );

		Propagate( beacon );
	}
Beispiel #6
0
	/**
	 * @brief Tags an entity.
	 * @todo Don't create a new beacon entity if retagged since that triggers regeneration of base
	 *       clusterings.
	 */
	void Tag( gentity_t *ent, team_t team, int owner, qboolean permanent )
	{
		int i, data;
		vec3_t origin, mins, maxs;
		qboolean dead, player;
		gentity_t *beacon, **attachment;
		team_t targetTeam;

		switch( ent->s.eType )
		{
			case ET_BUILDABLE:
				targetTeam = ent->buildableTeam;
				BG_BuildableBoundingBox( ent->s.modelindex, mins, maxs );
				data = ent->s.modelindex;
				dead = ( ent->health <= 0 );
				player = qfalse;
				break;

			case ET_PLAYER:
				targetTeam = (team_t)ent->client->pers.team;
				BG_ClassBoundingBox( ent->client->pers.classSelection, mins, maxs, NULL, NULL, NULL );
				dead = ( ent->client && ent->client->ps.stats[ STAT_HEALTH ] <= 0 );
				player = qtrue;

				// data is the class (aliens) or the weapon number (humans)
				switch( targetTeam )
				{
					case TEAM_ALIENS:
						data = ent->client->ps.stats[ STAT_CLASS ];
						break;

					case TEAM_HUMANS:
						data = BG_GetPlayerWeapon( &ent->client->ps );
						break;

					default:
						return;
				}

				break;

			default:
				return;
		}

		for( i = 0; i < 3; i++ )
			origin[ i ] = ent->s.origin[ i ] + ( mins[ i ] + maxs[ i ] ) / 2.0;

		switch( team )
		{
			case TEAM_ALIENS:
				attachment = &ent->alienTag;
				break;

			case TEAM_HUMANS:
				attachment = &ent->humanTag;
				break;

			default:
				return;
		}

		if ( *attachment )
			Delete( *attachment );

		beacon = New( origin, BCT_TAG, data, team, owner );
		beacon->tagAttachment = attachment;
		beacon->s.otherEntityNum2 = ent - g_entities;

		ent->tagScore = 0;

		if( player )
			beacon->s.eFlags |= EF_BC_TAG_PLAYER;

		if( team != targetTeam )
			beacon->s.eFlags |= EF_BC_ENEMY;

		if( permanent )
			beacon->s.time2 = 0;
		else
			RefreshTag( beacon, true );

		if( dead )
			Delete( beacon, true );
		else
		{
			*attachment = beacon;
			if ( ent->s.eType == ET_BUILDABLE ) BaseClustering::Update( beacon );
		}

		Propagate( beacon );
	}