AI_FollowGroup_t *CAI_FollowManager::FindCreateGroup( CBaseEntity *pTarget )
{
	AI_FollowGroup_t *pGroup = FindGroup( pTarget );
	
	if ( !pGroup )
	{
		pGroup = new AI_FollowGroup_t;
		
		pGroup->pFormation = AIGetFormation( AIF_SIMPLE );
		pGroup->slotUsage.Resize( pGroup->pFormation->nSlots );
		pGroup->hFollowTarget = pTarget;
		
		m_groups.AddToHead( pGroup );
	}
	
	return pGroup;
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pFace - input face to test
//			*pbrush - brush to clip face against
//			**pOutputList - list of faces clipped from pFace
// Output : Returns true if the brush completely clips the face
//-----------------------------------------------------------------------------
// NOTE: This assumes the brushes have already been chopped so that no solid space
// is enclosed by more than one brush!!
bool ClipFaceToBrush( face_t *pFace, bspbrush_t *pbrush, face_t **pOutputList )
{
	int planenum = pFace->planenum & (~1);
	int foundSide = -1;

	CUtlVector<int> sortedSides;

	int i;
	for ( i = 0; i < pbrush->numsides && foundSide < 0; i++ )
	{
		int bplane = pbrush->sides[i].planenum & (~1);
		if ( bplane == planenum )
			foundSide = i;
	}

	Vector offset = -0.5f * (pbrush->maxs + pbrush->mins);
	face_t *currentface = CopyFace( pFace );

	if ( foundSide >= 0 )
	{
		sortedSides.RemoveAll();
		for ( i = 0; i < pbrush->numsides; i++ )
		{
			// don't clip to bevels
			if ( pbrush->sides[i].bevel )
				continue;

			if ( g_MainMap->mapplanes[pbrush->sides[i].planenum].type <= PLANE_Z )
			{
				sortedSides.AddToHead( i );
			}
			else
			{
				sortedSides.AddToTail( i );
			}
		}

		for ( i = 0; i < sortedSides.Size(); i++ )
		{
			int index = sortedSides[i];
			if ( index == foundSide )
				continue;
			
			plane_t *plane = &g_MainMap->mapplanes[pbrush->sides[index].planenum];
			winding_t *frontwinding, *backwinding;
			ClipWindingEpsilon_Offset(currentface->w, plane->normal, plane->dist, 0.001, &frontwinding, &backwinding, offset);
			
			// only clip if some part of this face is on the back side of all brush sides
			if ( !backwinding || WindingIsTiny(backwinding))
			{
				FreeFaceList( *pOutputList );
				*pOutputList = NULL;
				break;
			}
			if ( frontwinding && !WindingIsTiny(frontwinding) )
			{
				// add this fragment to the return list
				// make a face for the fragment
				face_t *f = NewFaceFromFace( pFace );
				f->w = frontwinding;
				
				// link the fragment in
				f->next = *pOutputList;
				*pOutputList = f;
			}

			// update the current winding to be the part behind each plane
			FreeWinding( currentface->w );
			currentface->w = backwinding;
		}

		// free the bit that is left in solid or not clipped (if we broke out early)
		FreeFace( currentface );

		// if we made it all the way through and didn't produce any fragments then the whole face was clipped away
		if ( !*pOutputList && i == sortedSides.Size() )
		{
			return true;
		}
	}
	return false;
}
void PhonemeEditor::CloseCaption_MergeSelected( void )
{
	CountSelected();
	if ( m_nSelectedPhraseCount < 2 )
	{
		Con_Printf( "CloseCaption_MergeSelected:  requires 2 or more selected phrases\n" );
		return;
	}

	if ( !CloseCaption_AreSelectedPhrasesContiguous() )
	{
		Con_Printf( "CloseCaption_MergeSelected:  selected phrases must be contiguous\n" );
		return;
	}

	SetDirty( true );

	PushUndo();

	CUtlVector< CCloseCaptionPhrase * > selected;

	float beststart = 100000.0f;
	float bestend = -100000.0f;

	int c = m_Tags.GetCloseCaptionPhraseCount( CC_ENGLISH );
	int i;
	int insertslot = c -1;

	// Walk backwards and remove
	for ( i = c - 1; i >= 0; i-- )
	{
		CCloseCaptionPhrase *phrase = m_Tags.GetCloseCaptionPhrase( CC_ENGLISH, i );
		if ( !phrase || !phrase->GetSelected() )
			continue;

		if ( phrase->GetStartTime() < beststart )
		{
			beststart = phrase->GetStartTime();
		}
		if ( phrase->GetEndTime() > bestend )
		{
			bestend = phrase->GetEndTime();
		}

		selected.AddToHead( new CCloseCaptionPhrase( *phrase ) );

		// Remember the earliest slot
		if ( i < insertslot )
		{
			insertslot = i;
		}

		m_Tags.RemoveCloseCaptionPhrase( CC_ENGLISH, i );
	}

	if ( selected.Count() <= 0 )
		return;

	CCloseCaptionPhrase *newphrase = new CCloseCaptionPhrase( selected[ 0 ]->GetStream() );
	Assert( newphrase );
	wchar_t sz[ 4096 ];
	delete selected[ 0 ];
	for ( i = 1; i < selected.Count(); i++ )
	{
		_snwprintf( sz, sizeof( sz ), newphrase->GetStream() );
		// Phrases don't have leading/trailing spaces so it should be safe to just append a space here
		wcscat( sz, L" " );
		wcscat( sz, selected[ i ]->GetStream() );
		newphrase->SetStream( sz );
		delete selected[ i ];
	}
	selected.RemoveAll();

	m_Tags.InsertCloseCaptionPhraseAtIndex( CC_ENGLISH, newphrase, insertslot );
	newphrase->SetSelected( true );
	newphrase->SetStartTime( beststart );
	newphrase->SetEndTime( bestend );

	PushRedo();

	redraw();
}