//-----------------------------------------------------------------------------
// Purpose: Counts words which have either a valid start or end byte
// Input  : *outwords - 
// Output : int
//-----------------------------------------------------------------------------
int CountUnuseableWords( CSentence& outwords )
{
	int count = 0;
	int numwords = outwords.m_Words.Size();
	// Nothing to do
	if ( numwords <= 0 )
		return count;

	for ( int i = 0; i < numwords; i++ )
	{
		CWordTag *word = outwords.m_Words[ i ];
		if ( IsUseable( word ) )
			continue;

		count++;
	}

	return count;
}
int FindFirstUsableWord( CSentence& outwords )
{
	int numwords = outwords.m_Words.Size();
	if ( numwords < 1 )
	{
		Assert( 0 );
		return -1;
	}

	for ( int i = 0; i < numwords; i++ )
	{
		CWordTag *check = outwords.m_Words[ i ];
		if ( IsUseable( check ) )
		{
			return i;
		}
	}

	return -1;
}
Beispiel #3
0
void CBasePlayerWeapon::ItemPostFrame( void )
{
	if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) )
	{
		// Pcjoe: Regular HL weapon
		if(!MMWeapon())
		{
			// complete the reload. 
			int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);	

			// Add them to the clip
			m_iClip += j;
			
			// Removed by Pcjoe
		/*	m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
			m_pPlayer->TabulateAmmo();*/
		}
		// Pcjoe: Reload MM weapon
		else if(((CMMWeapon*)this)->RapidFireWeapon())
		{	CBaseRapidFireGun *pWeapon = (CBaseRapidFireGun*)this;

			// Reload ammo for non-power weapons
			if(!pWeapon->UsePowerPrimary())
			{	pWeapon->m_iPrimaryCur = pWeapon->MaxRounds();
				pWeapon->m_iClip = pWeapon->MaxRounds();
			}
			if(!pWeapon->UsePowerSecondary())
			{	pWeapon->m_iSecondaryCur = pWeapon->m_iSecondaryMax;
			}
		}

		m_fInReload = FALSE;
	}

	// Edited by Pcjoe
//	if ((m_pPlayer->pev->button & IN_ATTACK2) && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, UseDecrement() ) )
	if ((m_pPlayer->pev->button & IN_ATTACK2) && !m_pPlayer->m_fImpact && !m_pPlayer->m_fBoost && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, UseDecrement() ) )
	{
		if ( pszAmmo2() && !m_pPlayer->m_rgAmmo[SecondaryAmmoIndex()] )
		{
			m_fFireOnEmpty = TRUE;
		}

		// Removed by Pcjoe
//		m_pPlayer->TabulateAmmo();
		SecondaryAttack();
		m_pPlayer->pev->button &= ~IN_ATTACK2;
	}
	// Edited by Pcjoe
//	else if ((m_pPlayer->pev->button & IN_ATTACK) && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, UseDecrement() ) )
	else if ((m_pPlayer->pev->button & IN_ATTACK) && !m_pPlayer->m_fImpact && !m_pPlayer->m_fBoost && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, UseDecrement() ) )
	{
		if ( (m_iClip == 0 && pszAmmo1()) || (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
		{
			m_fFireOnEmpty = TRUE;
		}

		// Removed by Pcjoe
//		m_pPlayer->TabulateAmmo();
		PrimaryAttack();
	}
	else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload ) 
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.
		Reload();
	}
	else if ( !(m_pPlayer->pev->button & (IN_ATTACK|IN_ATTACK2) ) )
	{
		// no fire buttons down

		m_fFireOnEmpty = FALSE;

		if ( !IsUseable() && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) ) 
		{
			// weapon isn't useable, switch.
			if ( !(iFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && g_pGameRules->GetNextBestWeapon( m_pPlayer, this ) )
			{
				m_flNextPrimaryAttack = ( UseDecrement() ? 0.0 : gpGlobals->time ) + 0.3;
				return;
			}
		}
		else
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) )
			{	Reload();
				// Pcjoe: Allow mm weapons to call idle
				if(!MMWeapon())
				{	return;
				}
			}
		}

		WeaponIdle( );
		return;
	}
	
	// catch all
	if ( ShouldWeaponIdle() )
	{
		WeaponIdle();
	}
}
Beispiel #4
0
void CBasePlayerWeapon::ItemPostFrame( void )
{
	if ((m_fInReload) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) )
	{
		// complete the reload. 
		int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);	

		// Add them to the clip
		m_iClip += j;
		m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;

		m_pPlayer->TabulateAmmo();

		m_fInReload = FALSE;
	}

	if ( !(m_pPlayer->pev->button & IN_ATTACK ) )
	{
		m_flLastFireTime = 0.0f;
	}

	if ((m_pPlayer->pev->button & IN_ATTACK2) && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, UseDecrement() ) )
	{
		if ( pszAmmo2() && !m_pPlayer->m_rgAmmo[SecondaryAmmoIndex()] )
		{
			m_fFireOnEmpty = TRUE;
		}

		m_pPlayer->TabulateAmmo();
		SecondaryAttack();
		m_pPlayer->pev->button &= ~IN_ATTACK2;
	}
	else if ((m_pPlayer->pev->button & IN_ATTACK) && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, UseDecrement() ) )
	{
		if ( (m_iClip == 0 && pszAmmo1()) || (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
		{
			m_fFireOnEmpty = TRUE;
		}

		m_pPlayer->TabulateAmmo();
		PrimaryAttack();
	}
	else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload ) 
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.
		Reload();
	}
	else if ( !(m_pPlayer->pev->button & (IN_ATTACK|IN_ATTACK2) ) )
	{
		// no fire buttons down

		m_fFireOnEmpty = FALSE;

		if ( !IsUseable() && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) ) 
		{
			// weapon isn't useable, switch.
			if ( !(iFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && g_pGameRules->GetNextBestWeapon( m_pPlayer, this ) )
			{
				m_flNextPrimaryAttack = ( UseDecrement() ? 0.0 : gpGlobals->time ) + 0.3;
				return;
			}
		}
		else
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < ( UseDecrement() ? 0.0 : gpGlobals->time ) )
			{
				Reload();
				return;
			}
		}

		WeaponIdle( );
		return;
	}
	
	// catch all
	if ( ShouldWeaponIdle() )
	{
		WeaponIdle();
	}
}
void CWeaponDODBase::ItemPostFrame()
{
	if ( m_flSmackTime > 0 && gpGlobals->curtime > m_flSmackTime )
	{
		Smack();
		m_flSmackTime = -1;
	}

	CBasePlayer *pPlayer = GetPlayerOwner();

	if ( !pPlayer )
		return;

#ifdef _DEBUG
	CDODGameRules *mp = DODGameRules();
#endif

	assert( mp );

	if ((m_bInReload) && (pPlayer->m_flNextAttack <= gpGlobals->curtime))
	{
		// complete the reload. 
		int j = min( GetMaxClip1() - m_iClip1, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) );	

		// Add them to the clip
		m_iClip1 += j;
		pPlayer->RemoveAmmo( j, m_iPrimaryAmmoType );

		m_bInReload = false;

		FinishReload();
	}

	if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
	{
		if ( m_iClip2 != -1 && !pPlayer->GetAmmoCount( GetSecondaryAmmoType() ) )
		{
			m_bFireOnEmpty = TRUE;
		}

		SecondaryAttack();

		pPlayer->m_nButtons &= ~IN_ATTACK2;
	}
	else if ((pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime ) && !m_bInAttack )
	{
		if ( (m_iClip1 == 0/* && pszAmmo1()*/) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) ) )
		{
			m_bFireOnEmpty = TRUE;
		}

		if( CanAttack() )
			PrimaryAttack();
	}
	else if ( pPlayer->m_nButtons & IN_RELOAD && GetMaxClip1() != WEAPON_NOCLIP && !m_bInReload && m_flNextPrimaryAttack < gpGlobals->curtime) 
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.		
		Reload();	
	}
	else if ( !(pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ) )
	{
		// no fire buttons down

		m_bFireOnEmpty = false;

		m_bInAttack = false;	//reset semi-auto

		if ( !IsUseable() && m_flNextPrimaryAttack < gpGlobals->curtime ) 
		{
			// Intentionally blank -- used to switch weapons here
		}
		else if( ShouldAutoReload() )
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if ( m_iClip1 == 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime )
			{
				Reload();
				return;
			}
		}

		WeaponIdle( );
		return;
	}
}
void CWeaponCSBase::ItemPostFrame()
{
	CCSPlayer *pPlayer = GetPlayerOwner();


	//GOOSEMAN : Return zoom level back to previous zoom level before we fired a shot. This is used only for the AWP.
	if ( (m_flNextPrimaryAttack <= gpGlobals->curtime) && (pPlayer->m_bResumeZoom == TRUE) )
	{
		#ifndef CLIENT_DLL
			pPlayer->SetFOV( pPlayer->m_iLastZoom );

			if ( pPlayer->GetFOV() == pPlayer->m_iLastZoom )
			{
				// return the fade level in zoom.
				pPlayer->m_bResumeZoom = false;
			}
		#endif
	}

	//GOOSEMAN : Delayed shell ejection code..
	if ( (pPlayer->m_flEjectBrass != 0.0) && (pPlayer->m_flEjectBrass <= gpGlobals->curtime ) )
	{
		pPlayer->m_flEjectBrass = 0.0;
		EjectBrassLate();
	}


	if ((m_bInReload) && (pPlayer->m_flNextAttack <= gpGlobals->curtime))
	{
		// complete the reload. 
		int j = min( GetMaxClip1() - m_iClip1, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) );	

		// Add them to the clip
		m_iClip1 += j;
		pPlayer->RemoveAmmo( j, m_iPrimaryAmmoType );

		m_bInReload = false;
	}

	if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
	{
		if ( m_iClip2 != -1 && !pPlayer->GetAmmoCount( GetSecondaryAmmoType() ) )
		{
			m_bFireOnEmpty = TRUE;
		}
		SecondaryAttack();
		pPlayer->m_nButtons &= ~IN_ATTACK2;
	}
	else if ((pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime ))
	{
		if ( (m_iClip1 == 0/* && pszAmmo1()*/) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) ) )
		{
			m_bFireOnEmpty = TRUE;
		}

		// Can't shoot during the freeze period
		// Ken: Always allow firing in single player
		//---
		if ( !CSGameRules()->IsFreezePeriod() && 
			!pPlayer->m_bIsDefusing &&
			pPlayer->State_Get() == STATE_JOINED
			)
		{
			PrimaryAttack();
		}
		//---
	}
	else if ( pPlayer->m_nButtons & IN_RELOAD && GetMaxClip1() != WEAPON_NOCLIP && !m_bInReload && m_flNextPrimaryAttack < gpGlobals->curtime) 
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.
		
		//MIKETODO: add code for shields...
		//if ( !FBitSet( m_iWeaponState, WPNSTATE_SHIELD_DRAWN ) )
			  Reload();	
	}
	else if ( !(pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2) ) )
	{
		// no fire buttons down

		// The following code prevents the player from tapping the firebutton repeatedly 
		// to simulate full auto and retaining the single shot accuracy of single fire
		if (m_bDelayFire == TRUE)
		{
			m_bDelayFire = FALSE;
			if (m_iShotsFired > 15)
				m_iShotsFired = 15;
			m_flDecreaseShotsFired = gpGlobals->curtime + 0.4;
		}

		m_bFireOnEmpty = FALSE;

		// if it's a pistol then set the shots fired to 0 after the player releases a button
		if ( IsPistol() )
		{
			m_iShotsFired = 0;
		}
		else
		{
			if ( (m_iShotsFired > 0) && (m_flDecreaseShotsFired < gpGlobals->curtime)	)
			{
				m_flDecreaseShotsFired = gpGlobals->curtime + 0.0225;
				m_iShotsFired--;
			}
		}

		#ifndef CLIENT_DLL
			if ( !IsUseable() && m_flNextPrimaryAttack < gpGlobals->curtime ) 
			{
				// Intentionally blank -- used to switch weapons here
			}
			else
		#endif
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if ( m_iClip1 == 0 && !(GetFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime )
			{
				Reload();
				return;
			}
		}

		WeaponIdle( );
		return;
	}
}
/*
=====================
CBasePlayerWeapon::ItemPostFrame

Handles weapon firing, reloading, etc.
=====================
*/
void CBasePlayerWeapon::ItemPostFrame( void )
{
	WeaponTick();

	if( ( m_fInReload ) && ( m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase() ) )
	{
#ifdef SERVER_DLL // FIXME, need ammo on client to make this work right
		// complete the reload. 
		int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] );

		// Add them to the clip
		m_iClip += j;
		m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] -= j;
#else	
		m_iClip += 10;
#endif

		m_fInReload = false;
	}

#ifdef SERVER_DLL
	if( !m_pPlayer->GetButtons().Any( IN_ATTACK ) )
	{
		m_flLastFireTime = 0.0f;
	}
#endif

	if( m_pPlayer->GetButtons().Any( IN_ATTACK2 ) && CanAttack( m_flNextSecondaryAttack, gpGlobals->time, IsPredicted() ) )
	{
		if( pszAmmo2() && !m_pPlayer->m_rgAmmo[ SecondaryAmmoIndex() ] )
		{
			m_bFireOnEmpty = true;
		}

		SecondaryAttack();
		m_pPlayer->GetButtons().ClearFlags( IN_ATTACK2 );
	}
	else if( m_pPlayer->GetButtons().Any( IN_ATTACK ) && CanAttack( m_flNextPrimaryAttack, gpGlobals->time, IsPredicted() ) )
	{
		if( ( m_iClip == 0 && pszAmmo1() ) || ( iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[ PrimaryAmmoIndex() ] ) )
		{
			m_bFireOnEmpty = true;
		}

		PrimaryAttack();
	}
	else if( m_pPlayer->GetButtons().Any( IN_RELOAD ) && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
	{
		// reload when reload is pressed, or if no buttons are down and weapon is empty.
		Reload();
	}
	else if( !m_pPlayer->GetButtons().Any( IN_ATTACK | IN_ATTACK2 ) )
	{
		// no fire buttons down

		m_bFireOnEmpty = false;

		//Only the server checks for weapon switching. - Solokiller
#ifdef SERVER_DLL
		if( !IsUseable() && m_flNextPrimaryAttack < ( IsPredicted() ? 0.0 : gpGlobals->time ) )
		{
			// weapon isn't useable, switch.
			if( !( iFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY ) && g_pGameRules->GetNextBestWeapon( m_pPlayer, this ) )
			{
				m_flNextPrimaryAttack = ( IsPredicted() ? 0.0 : gpGlobals->time ) + 0.3;
				return;
			}
		}
		else
#endif
		{
			// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
			if( m_iClip == 0 && !( iFlags() & ITEM_FLAG_NOAUTORELOAD ) && CanReload( m_flNextPrimaryAttack, gpGlobals->time, IsPredicted() ) )
			{
				Reload();
				return;
			}
		}

		WeaponIdle();
		return;
	}

	// catch all
	if( ShouldWeaponIdle() )
	{
		WeaponIdle();
	}
}
void ComputeMissingByteSpans( int numsamples, CSentence& outwords )
{
	int numwords = outwords.m_Words.Size();
	// Nothing to do
	if ( numwords <= 0 )
		return;

	int interationcount = 1;

	while( 1 )
	{
		Log( "\nCompute %i\n", interationcount++ );
		LogWords( outwords );

		int wordNumber;

		// Done!
		if ( !CountUnuseableWords( outwords ) )
		{
			FixupZeroLengthWords( outwords );
			break;
		}

		if ( !CountUsableWords( outwords ) )
		{
			// Evenly space words across full sample time
			PartitionWords( outwords, 0, numwords - 1, 0, numsamples );
			break;
		}

		wordNumber = FindFirstUsableWord( outwords );
		// Not the first word
		if ( wordNumber > 0 )
		{
			// Repartition all of the unusables and the first one starting at zero over the range
			CWordTag *firstUsable = outwords.m_Words[ wordNumber ];
			Assert( firstUsable );

			if ( firstUsable->m_uiStartByte != 0 )
			{
				PartitionWords( outwords, 0, wordNumber - 1, 0, firstUsable->m_uiStartByte );
			}
			else
			{
				PartitionWords( outwords, 0, wordNumber, 0, firstUsable->m_uiEndByte );
			}

			// Start over
			continue;
		}

		wordNumber = FindLastUsableWord( outwords );
		// Not the last word
		if ( wordNumber >= 0 && wordNumber < numwords - 1 )
		{
			// Repartition all of the unusables and the first one starting at zero over the range
			CWordTag *lastUsable = outwords.m_Words[ wordNumber ];
			Assert( lastUsable );

			if ( lastUsable->m_uiEndByte != (unsigned int)numsamples )
			{
				PartitionWords( outwords, wordNumber + 1, numwords-1, lastUsable->m_uiEndByte, numsamples );
			}
			else
			{
				PartitionWords( outwords, wordNumber, numwords-1, lastUsable->m_uiStartByte, numsamples );
			}

			// Start over
			continue;
		}

		// If we get here it means that the start and end of the list are okay and we just have to
		//  iterate across the list and fix things in the middle
		int startByte = 0;
		int endByte = 0;
		for ( int i = 0; i < numwords ; i++ )
		{
			CWordTag *word = outwords.m_Words[ i ];
			if ( IsUseable( word ) )
			{
				startByte = word->m_uiEndByte;
				continue;
			}

			// Found the start of a chain of 1 or more unusable words
			// Find the startbyte of the next usable word and count how many words we check
			int wordCount = 1;
			for ( int j = i + 1; j < numwords; j++ )
			{
				CWordTag *next = outwords.m_Words[ j ];
				if ( IsUseable( next ) )
				{
					endByte = next->m_uiStartByte;
					break;
				}

				wordCount++;
			}

			// Now partition words across the gap and go to start again
			PartitionWords( outwords, i, i + wordCount - 1, startByte, endByte );
			break;
		}
	}
}
Beispiel #9
0
void SWrapMod::ModifyObject(
		TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{	SWrapObject *obj = (SWrapObject *)GetWSMObject(t);
	INode *pnode;
	TriObject *towrapOb=NULL;Object *pobj=NULL;
	if (obj) pnode=obj->custnode;
	if (obj && nodeRef && pnode) 
	{	Interval valid = FOREVER;
		if (!obj->cmValid.InInterval(t))
		{   pobj = pnode->EvalWorldState(t).obj;
			obj->cmValid=pobj->ObjectValidity(t);
			Matrix3 tm=pnode->GetObjectTM(t,&(obj->cmValid));
			TriObject *wrapOb=IsUseable(pobj,t);
			if (wrapOb)
			{ if (obj->cmesh) delete obj->cmesh; 
			  obj->cmesh=new Mesh;
			   obj->cmesh->DeepCopy(&wrapOb->GetMesh(),
			     PART_GEOM|SELECT_CHANNEL|PART_SUBSEL_TYPE|PART_TOPO|TM_CHANNEL);
			   for (int ic=0;ic<obj->cmesh->getNumVerts();ic++)
			     obj->cmesh->verts[ic]=obj->cmesh->verts[ic]*tm;
			  GetVFLst(obj->cmesh,&obj->vnorms,&obj->fnorms);
			  if (wrapOb!=pobj) wrapOb->DeleteThis();
			}
 		}
		if (!obj->cmesh) return;
		if ((obj->cmesh->getNumVerts()==0)||(obj->cmesh->getNumFaces()==0)) 
			return;		 
//		Matrix3 invtm=Inverse(obj->tm);
		valid=obj->cmValid;
		Matrix3 ctm;
		ctm = nodeRef->GetNodeTM(t,&valid);
		Ray ray;
		Point3 v=-ctm.GetRow(2);
//		Matrix3 nooff=invtm;nooff.NoTrans();
		ray.dir=v;//*nooff;
		int selverts;
		float kdef,standoff;
		obj->pblock->GetValue(PB_USESELVERTS,t,selverts,valid);
		obj->pblock->GetValue(PB_KIDEFAULT,t,kdef,valid);
		obj->pblock->GetValue(PB_STANDOFF,t,standoff,valid);
		BezierShape stowrapOb;
		int found=0;
		Matrix3 towtm(1);
		if (os->GetTM()) 
			towtm=*(os->GetTM());
		Matrix3 invtowtm=Inverse(towtm);
		Point3 vert;
		Class_ID cid=os->obj->ClassID(),es=EDITABLE_SURF_CLASS_ID,efp=FITPOINT_PLANE_CLASS_ID,ecv=EDITABLE_CVCURVE_CLASS_ID,ecfp=EDITABLE_FPCURVE_CLASS_ID;
		if (((cid==EDITABLE_SURF_CLASS_ID)||(cid==FITPOINT_PLANE_CLASS_ID))||((cid==EDITABLE_CVCURVE_CLASS_ID)||(cid==EDITABLE_FPCURVE_CLASS_ID)))
		{ Object* nurbobj=os->obj;
		  int num=nurbobj->NumPoints();
		  for (int i=0;i<num;i++)
		  {	vert=DoIntersect(nurbobj->GetPoint(i)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
		    nurbobj->SetPoint(i,(vert*invtowtm));
		  }
		}
#ifndef NO_PATCHES
		else if (os->obj->IsSubClassOf(patchObjectClassID))
		{ PatchObject* patchob=(PatchObject *)os->obj;
		  PatchMesh *pm=&(patchob->patch);
		  int nv=pm->getNumVerts();
		  BitArray sel = pm->VertSel();
		  for (int i=0;i<nv;i++)
		  { if (!selverts||sel[i])
			{ vert=DoIntersect(pm->getVert(i).p*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
		      vert=vert*invtowtm;
		      pm->setVert(i,vert);
			}
		  }
/*		  pm->buildLinkages();
		  pm->computeInteriors();
		  pm->InvalidateGeomCache();*/
		}
#endif // NO_PATCHES
		else if (towrapOb=IsUseable(os->obj,t))
		{	Point3 tvector;
			float dist;
			float *vssel = NULL;
		  if (selverts) 
			  vssel = towrapOb->GetMesh().getVSelectionWeights();
		  for (int i=0;i<towrapOb->GetMesh().getNumVerts();i++)
		  { 
				if ((!selverts)||(towrapOb->GetMesh().vertSel[i])
							   ||(vssel&&vssel[i]))
				{
					vert = DoIntersect(towrapOb->GetMesh().verts[i]*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
					vert = vert*invtowtm;
					if (vssel&&vssel[i])
					{
						tvector = vert - towrapOb->GetMesh().verts[i];
						dist = Length(tvector);
						if ((float)fabs(dist) > EPSILON)
							tvector = tvector/dist;
						else
							tvector = Zero;
						vert = towrapOb->GetMesh().verts[i] + dist*vssel[i]*tvector;
					}
					towrapOb->GetMesh().verts[i] = vert;
				}
		  }
		  if (towrapOb!=os->obj) 
			  towrapOb->DeleteThis();
		}
		else if((os->obj->IsSubClassOf(splineShapeClassID))||(os->obj->CanConvertToType(splineShapeClassID))) 
		{ SplineShape *attSplShape = (SplineShape *)os->obj->ConvertToType(t,splineShapeClassID);
		if (attSplShape) 
		{ stowrapOb=attSplShape->shape;
		  for (int poly=0; poly<stowrapOb.splineCount; ++poly)
		  { Spline3D *spline = stowrapOb.GetSpline(poly);
			int verts = spline->Verts();
			int knots = spline->KnotCount();
			BitArray sel = stowrapOb.VertexTempSel(poly);
			Point3 cknot,cknot2;
			{ for(int k=0; k<knots; ++k) 
			  {	int vert = k * 3 + 1;
				if (!selverts||sel[vert])  
				{ cknot=DoIntersect(spline->GetKnotPoint(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
				  attSplShape->shape.SetVert(poly,vert,cknot*invtowtm);
				  if (found)
				  { int knotType = spline->GetKnotType(k);
				    if(knotType & KTYPE_BEZIER) 
				    { cknot2= DoIntersect(spline->GetInVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
					attSplShape->shape.SetVert(poly,vert-1,(found?cknot2:cknot)*invtowtm);
				  	  cknot2= DoIntersect(spline->GetOutVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
					  attSplShape->shape.SetVert(poly,vert+1,(found?cknot2:cknot)*invtowtm);
					}
				  }
				}
			  }
			}
		  }
		  if (attSplShape!=os->obj) attSplShape->DeleteThis();
		}
	  }
//	os->obj->PointsWereChanged();
	os->obj->UpdateValidity(GEOM_CHAN_NUM,valid);	
//	NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);

  }
}