static inline bool CheckRefreshTag( gentity_t *ent, team_t team ) { gentity_t *existingTag = ( team == TEAM_ALIENS ) ? ent->alienTag : ent->humanTag; if( existingTag ) RefreshTag( existingTag ); return existingTag != nullptr; }
/** * @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 ); }
/** * @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 ); }