示例#1
0
LTBOOL ScaleSprite::Update()
{
	if (m_bStartOn)
	{
		g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, USRFLG_VISIBLE, USRFLG_VISIBLE);

		g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE);
	}

	SetNextUpdate(UPDATE_NEVER);
 
	// BUG - This isn't quite right.  Sometimes this works (flipping the sprite)
	// other times the sprite shouldn't be flipped...Not sure what the bug is.
	// For some reason the sprites are sometimes backwards...Get the rotation
	// so we can flip it...

    LTRotation rRot;
    LTVector vPos, vDir, vU, vR, vF;
	g_pLTServer->GetObjectPos(m_hObject, &vPos);
	g_pLTServer->GetObjectRotation(m_hObject, &rRot);
	vU = rRot.Up();
	vR = rRot.Right();
	vF = rRot.Forward();

	if (m_bFlushWithWorld)
	{
		// Align the sprite to the surface directly behind the sprite
		// (i.e., opposite the forward vector)...

		VEC_NORM(vF);
		VEC_MULSCALAR(vDir, vF, -1.0f);


		// Determine where on the surface to place the sprite...

		IntersectInfo iInfo;
		IntersectQuery qInfo;

		VEC_COPY(qInfo.m_From, vPos);
		VEC_COPY(qInfo.m_Direction, vDir);
		qInfo.m_Flags	 = IGNORE_NONSOLID | INTERSECT_OBJECTS | INTERSECT_HPOLY;
        qInfo.m_FilterFn = LTNULL;

        if (g_pLTServer->CastRay(&qInfo, &iInfo))
		{
            LTVector vTemp;
			VEC_COPY(vPos, iInfo.m_Point);
			VEC_COPY(vDir, iInfo.m_Plane.m_Normal);

			// Place the sprite just above the surface...

			VEC_MULSCALAR(vTemp, vDir, 1.0f);
			VEC_ADD(vPos, vPos, vTemp);

			g_pLTServer->SetObjectPos(m_hObject, &vPos);
		}
	}

    return LTTRUE;
}
bool CClientWeaponDisc::CalculateControlDirection( LTVector *pvControlDirection )
{
    //
    // safety check
    //

    // params
    ASSERT( 0 != pvControlDirection );

    // globals
    ASSERT( 0 != g_pLTClient );
    ASSERT( 0 != g_pPlayerMgr );


    //
    // The control direction is the direction the player is facing
    //

    // get the camera
    HOBJECT hCamera;
    hCamera = g_pPlayerMgr->GetCamera();
    ASSERT( 0 != hCamera );

    // determine the orientation of the segment
    LTRotation rRot;
    g_pLTClient->GetObjectRotation( hCamera, &rRot );

    // determine the direction of the segment
    LTVector vForward;
    *pvControlDirection = rRot.Forward();

    return true;
}
示例#3
0
bool CFallingStuffFX::Init(ILTClient *pClientDE, FX_BASEDATA *pBaseData, const CBaseFXProps *pProps)
{
    // Perform base class initialisation

    if (!CBaseFX::Init(pClientDE, pBaseData, pProps))
        return false;

    // Store the first position as the last position

    m_vLastPos = pBaseData->m_vPos;

    // If we have a parent object, get it and apply it's rotation
    // to the plane direction
    m_vPlaneDir = GetProps()->m_vPlaneDir;
    if (m_hParent)
    {
        LTRotation orient;
        m_pLTClient->GetObjectRotation(m_hParent, &orient);

        LTMatrix mRot;
        Mat_SetBasisVectors(&mRot, &orient.Right(), &orient.Up(), &orient.Forward());

        LTVector vTmp = m_vPlaneDir;

        MatVMul(&m_vPlaneDir, &mRot, &vTmp);
    }

    LTVector vUp;
    vUp.x = 0.0f;
    vUp.y = 1.0f;
    vUp.z = 0.0f;

    LTVector vTest = m_vPlaneDir;
    vTest.x = (float)fabs(vTest.x);
    vTest.y = (float)fabs(vTest.y);
    vTest.z = (float)fabs(vTest.z);

    if (vTest == vUp)
    {
        // Gotsta use another axis

        vUp.x = -1.0f;
        vUp.y = 0.0f;
        vUp.z = 0.0f;
    }

    m_vRight = m_vPlaneDir.Cross(vUp);
    m_vUp = m_vPlaneDir.Cross(m_vRight);


    // Create the base object

    CreateDummyObject();

    // Success !!

    return true;
}
示例#4
0
void CDestructibleModel::DoExplosion(char* pTargetName)
{
	CWeapons weapons;
	weapons.Init(m_hObject);
	weapons.ObtainWeapon(m_nExplosionWeaponId);
	weapons.ChangeWeapon(m_nExplosionWeaponId);

	CWeapon* pWeapon = weapons.GetCurWeapon();
	if (!pWeapon) return;

	weapons.SetAmmo(pWeapon->GetAmmoId());

	pWeapon->SetDamageFactor(m_fDamageFactor);

	LTRotation rRot;
	g_pLTServer->GetObjectRotation(m_hObject, &rRot);

	LTVector vF, vPos;
	g_pLTServer->GetObjectPos(m_hObject, &vPos);
	vF = rRot.Forward();

	// Just blow up in place if we're not supposed to fire along
	// forward vector and we don't have a target...

	if (!m_bFireAlongForward)
	{
		pWeapon->SetLifetime(0.0f);
		VEC_SET(vF, 0.0f, -1.0f, 0.0f);  // Fire down
	}

	// See if we have a target...If so, point at it.

	if (pTargetName)
	{
		ObjArray <HOBJECT, MAX_OBJECT_ARRAY_SIZE> objArray;
		g_pLTServer->FindNamedObjects(pTargetName, objArray);

		if (objArray.NumObjects())
		{
			LTVector vObjPos;
			g_pLTServer->GetObjectPos(objArray.GetObject(0), &vObjPos);
			vF = vObjPos - vPos;
			vF.Normalize();

			rRot = LTRotation(vF, LTVector(0.0f, 1.0f, 0.0f));
			g_pLTServer->SetObjectRotation(m_hObject, &rRot);
		}
	}

	WeaponFireInfo weaponFireInfo;
	weaponFireInfo.hFiredFrom	= m_hObject;
	weaponFireInfo.vPath		= vF;
	weaponFireInfo.vFirePos	= vPos;
	weaponFireInfo.vFlashPos	= vPos;

	pWeapon->Fire(weaponFireInfo);
}
示例#5
0
bool GunMount::FireWeapon( )
{
	CWeapon* pWeapon = m_Arsenal.GetCurWeapon( );
	if( !pWeapon )
		return false;

	// Get the direction we're firing.
	LTRotation rot;
	g_pLTServer->GetObjectRotation( m_hObject, &rot );
	LTVector vDir = rot.Forward( );

	LTVector vPos;
	if( !GetFirePos( vPos ))
	{
		g_pLTServer->GetObjectPos( m_hObject, &vPos );
	}

	// Tell the weapon to fire.
	WeaponFireInfo weaponFireInfo;
	static uint8 s_nCount = GetRandom( 0, 255 );
	s_nCount++;

	weaponFireInfo.hFiredFrom	= m_hObject;
	weaponFireInfo.hFiringWeapon = pWeapon->GetModelObject( );
	weaponFireInfo.vPath		= vDir;
	weaponFireInfo.vFirePos		= vPos;
	weaponFireInfo.vFlashPos	= vPos;
	weaponFireInfo.nSeed		= (uint8)GetRandom( 2, 255 );
	weaponFireInfo.nPerturbCount	= s_nCount;
	weaponFireInfo.nFireTimestamp = g_pLTServer->GetRealTimeMS( );

	WeaponState eWeaponState = pWeapon->UpdateWeapon( weaponFireInfo, true );
	if( eWeaponState == W_FIRED )
	{
		// Count the round as fired.
		if( m_nRoundsToFire > 0 )
			m_nRoundsToFire--;

	}

	// Keep ammo count up and clip loaded.  The weapon could have refused
	// firing due to weapon fire time limitations, but it still decrements
	// ammo.
	m_Arsenal.AddAmmo( pWeapon->GetAmmoRecord(), 10 );
	pWeapon->ReloadClip( false );

	return true;
}
示例#6
0
LTBOOL CLaserTriggerFX::CalcBeamCoords()
{
    if (!m_hServerObject) return LTFALSE;

	// The beam is relative to the server object's dims...

    LTVector vPos;
	g_pLTClient->GetObjectPos(m_hServerObject, &vPos);

    LTRotation rRot;
	g_pLTClient->GetObjectRotation(m_hServerObject, &rRot);

    LTVector vU, vR, vF;
	vU = rRot.Up();
	vR = rRot.Right();
	vF = rRot.Forward();


	// Okay, the beam is always along the object's longest dim...

    LTVector vDir = vF;
    LTFLOAT fLongestDim = m_cs.vDims.z; // Assume forward first...

	m_pls.fMaxWidth = (m_cs.vDims.x + m_cs.vDims.y); // Assume x/y are same...

	if (m_cs.vDims.y > fLongestDim)
	{
		vDir = vU;
		fLongestDim =  m_cs.vDims.y;
		m_pls.fMaxWidth = (m_cs.vDims.x + m_cs.vDims.z);
	}
	if (m_cs.vDims.x > fLongestDim)
	{
		vDir = vR;
		fLongestDim =  m_cs.vDims.x;
		m_pls.fMaxWidth = (m_cs.vDims.y + m_cs.vDims.z);
	}

	m_pls.vStartPos = vPos + (vDir * fLongestDim);
	m_pls.vEndPos	= vPos - (vDir * fLongestDim);

    return LTTRUE;
}
示例#7
0
bool ConstraintWheel::SetupBodySpaceData(const LTRigidTransform& tInvBody1, const LTRigidTransform& tInvBody2)
{
	//get the position of our object which will serve as the constraint point
	LTVector vConstraintPos;
	if(g_pLTServer->GetObjectPos(m_hObject, &vConstraintPos) != LT_OK)
		return false;

	LTRotation rConstraintOr;
	if(g_pLTServer->GetObjectRotation(m_hObject, &rConstraintOr) != LT_OK)
		return false;

	m_vPivotPt1 = tInvBody1 * vConstraintPos;
	m_vPivotPt2 = tInvBody2 * vConstraintPos;

	m_vRotation1 = tInvBody1.m_rRot.RotateVector(rConstraintOr.Forward());
	m_vRotation2 = tInvBody2.m_rRot.RotateVector(rConstraintOr.Forward());

	m_vSuspension2 = tInvBody2.m_rRot.RotateVector(rConstraintOr.Up());

	return true;
}
示例#8
0
void CFlashLight3rdPerson::GetLightPositions(LTVector& vStartPos, LTVector& vEndPos, LTVector& vUOffset, LTVector& vROffset)
{
	if ( !m_hObj ) return;

	HMODELSOCKET hSocket;
	if ( LT_OK == g_pModelLT->GetSocket(m_hObj, "LeftHand", hSocket) )
	{
		LTransform tf;

		if ( LT_OK == g_pModelLT->GetSocketTransform(m_hObj, hSocket, tf, LTTRUE) )
		{
			LTVector vPos = tf.m_Pos;
			LTRotation rRot = tf.m_Rot;

			LTVector vRight, vUp, vForward;
			vRight = rRot.Right();
			vUp = rRot.Up();
			vForward = rRot.Forward();

			//vStartPos = vPos - vUp*4.0f + vForward*8.0f;
			//vEndPos = vPos + vForward*200.0f;
			//vUOffset = vUp;
			//vROffset = vRight;

			vStartPos = vPos;
			vEndPos = vPos + (vForward * g_cvarFLLightOffsetForward.GetFloat());

  			vROffset = (vRight * g_cvarFLLightOffsetRight.GetFloat());
  			vUOffset = (vUp * g_cvarFLLightOffsetUp.GetFloat());

			// Update the Start/End position to addjust for any offset...

			vEndPos += vROffset;
			vEndPos += vUOffset;

			vStartPos += vROffset;
			vStartPos += vUOffset;
		}
	}
}
示例#9
0
void CDestructibleModel::SetSurfaceType()
{
	uint32 dwSurfUsrFlgs = 0;
	SurfaceType eSurfType = ST_UNKNOWN;

	// See if this object is a world model...

	if (GetObjectType(m_hObject) == OT_WORLDMODEL)
	{
        LTBOOL bDoBruteForce = LTTRUE;

		// See if we have a surface override...

		if (m_hstrSurfaceOverride)
		{
			const char* pSurfName = g_pLTServer->GetStringData(m_hstrSurfaceOverride);
			if (pSurfName)
			{
				SURFACE* pSurf = g_pSurfaceMgr->GetSurface(pSurfName);
				if (pSurf && pSurf->eType != ST_UNKNOWN)
				{
					eSurfType = pSurf->eType;
					bDoBruteForce = LTFALSE;
				}
			}
		}


		// Determine our surface...the hard way...

		if (bDoBruteForce)
		{
			IntersectQuery qInfo;
			IntersectInfo iInfo;

			LTVector vPos, vDims;
			LTRotation rRot;

			g_pLTServer->GetObjectPos(m_hObject, &vPos);
			g_pLTServer->GetObjectRotation(m_hObject, &rRot);
			g_pPhysicsLT->GetObjectDims(m_hObject, &vDims);

			LTFLOAT fMaxDims = vDims.x;
			fMaxDims = Max(fMaxDims, vDims.y);
			fMaxDims = Max(fMaxDims, vDims.z);

			qInfo.m_From = vPos + (rRot.Forward() * (fMaxDims + 1));
			qInfo.m_To   = vPos;

			qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;

			SurfaceType eType = ST_UNKNOWN;

			if (g_pLTServer->IntersectSegment(&qInfo, &iInfo))
			{
				if (iInfo.m_hObject == m_hObject)
				{
					eSurfType = GetSurfaceType(iInfo);
				}
			}
		}
	}
	else
	{
		DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_nDebrisId);
		if (pDebris)
		{
			eSurfType = pDebris->eSurfaceType;
		}
	}

	dwSurfUsrFlgs = SurfaceToUserFlag(eSurfType);
	g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, dwSurfUsrFlgs, dwSurfUsrFlgs);

	g_pCommonLT->GetObjectFlags(m_hObject, OFT_Flags, m_dwOriginalFlags);
}
示例#10
0
bool CCreateRayFX::Update( float tmFrameTime )
{
	//track our performance
	CTimedSystemBlock TimingBlock(g_tsClientFXCreateRayFX);

	//update our base object
	BaseUpdate(tmFrameTime);
	
	//we only want to create the effect as we become active
	if(IsInitialFrame() && (GetProps()->m_nNumToCreate > 0))
	{
		//determine the object position and orientation of our object
		LTVector vObjPos;
		LTRotation rObjRot;

		GetCurrentTransform(GetUnitLifetime(), vObjPos, rObjRot);

		//handle two special pipelines to gain performance when there is no scattering
		if(MATH_RADIANS_TO_DEGREES(GetProps()->m_fRandomCone) < 1.0f)
		{
			LTRigidTransform tHitTrans;
			HOBJECT hHitObj;

			//no scattering, just do a single intersection for all effects
			if(DetermineIntersection(vObjPos, rObjRot.Forward(), hHitObj, tHitTrans))
			{
				//and now generate all of our effects
				for(uint32 nCurrEffect = 0; nCurrEffect < GetProps()->m_nNumToCreate; nCurrEffect++)
				{
					CLIENTFX_CREATESTRUCT CreateStruct("", GetProps()->m_nFXFlags, hHitObj, tHitTrans);
					CBaseCreateFX::CreateEffect(CreateStruct);
				}
			}
		}
		else
		{
			//we need to scatter

			//extract our vectors from the orientation
			LTVector vObjRight, vObjUp, vObjForward;
			rObjRot.GetVectors(vObjRight, vObjUp, vObjForward);

			//and now generate all of our effects
			for(uint32 nCurrEffect = 0; nCurrEffect < GetProps()->m_nNumToCreate; nCurrEffect++)
			{
				LTRigidTransform tHitTrans;
				HOBJECT hHitObj;

				//now build up the forward within a specified cone

				//first off spin it randomly around the forward
				float fPlaneAngle = GetRandom(0.0f, MATH_CIRCLE);
				LTVector vPlaneVector = vObjRight * cosf(fPlaneAngle) + vObjUp * sinf(fPlaneAngle);

				//now tilt it away from the forward vector
				float fTiltPercent	= powf(GetRandom(0.0f, 1.0f), GetProps()->m_fCenterBias);
				float fTiltAngle	= fTiltPercent * GetProps()->m_fRandomCone;
				LTVector vRandomForward = vObjForward * cosf(fTiltAngle) + vPlaneVector * sinf(fTiltAngle);

				if(DetermineIntersection(vObjPos, vRandomForward, hHitObj, tHitTrans))
				{
					CLIENTFX_CREATESTRUCT CreateStruct("", GetProps()->m_nFXFlags, hHitObj, tHitTrans);
					CBaseCreateFX::CreateEffect(CreateStruct);
				}
			}
		}
	}

	//we always return false because we always want to be placed into a shutting down state since
	//we just emit and then do nothing
	return false;
}
示例#11
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CTronPlayerObj::GetDefensePercentage()
//
//	PURPOSE:	How much of the attack damage has our defenese prevented
//
//	NOTES:		There are actually 2 defense percentages.  One is based
//				on timing, i.e. player's reation speed, animation speed,
//				etc.  The other is based on the player's orientation to
//				the incoming projectile.  If the vector parameter is
//				specified, BOTH percentages will be computed and the
//				combined result will be returned.  If the vector is NOT
//				specified, only the timing will be computed.
//
// ----------------------------------------------------------------------- //
float CTronPlayerObj::GetDefensePercentage( LTVector const *pIncomingProjectilePosition /*=0*/) const
{
	if ( TRONPLAYEROBJ_NO_DEFEND == m_cDefendType )
	{
		// not blocking
		return 0.0f;
	}

	//
	// Do this in 2 passes.  The first pass willl determine
	// the contribution to the defense percentage due to the
	// timing of the player/animations.  The second pass
	// will add the contribution of the player's orientation.
	//
	float fDefenseTimingPercentage;
	float fDefenseOrientationPercentage;

	// get the weapon
	AMMO const *pAmmoData = g_pWeaponMgr->GetAmmo( m_cDefendAmmoId );
	ASSERT( 0 != pAmmoData );
	ASSERT( 0 != pAmmoData->pProjectileFX );

	// get the ammo specific data
	DISCCLASSDATA *pDiscData =
		dynamic_cast< DISCCLASSDATA* >(
			pAmmoData->pProjectileFX->pClassData
		);
	ASSERT( 0 != pDiscData );


	//
	// Determine Timing Percentage
	//

	switch ( m_cDefendType )
	{
		case MPROJ_START_SWAT_BLOCK:
		case MPROJ_START_ARM_BLOCK:
		{
			// get the current server time
			float fCurrentServerTime = g_pLTServer->GetTime() * 1000.0f;

			// make sure we're within the range of the block
			if ( ( static_cast< int >( fCurrentServerTime ) -
			       m_nDefendServerTimeStarted ) > m_nDefendDuration )
			{
				// nope, the block is over
				return 0.0f;
			}

			// Swat and Arm defenses are similar, so fill out these
			// variables uniquely (depending on which case we are
			// handling), then use the common generic math to figure
			// out the answer.
			float fMidpointTime;
			float fMaxStartTime;
			float fMaxEndTime;
			float fStartDefendPercentage;
			float fMaxDefendPercentage;
			float fEndDefendPercentage;

			if ( MPROJ_START_SWAT_BLOCK == m_cDefendType )
			{
				// determine at exactly what time the midpoint takes place
				// NOTE: this is relative time, not absolute
				fMidpointTime = 
					( pDiscData->fSwatDefendMidpoint * m_nDefendDuration );

				// determine at exactly what time the max starts
				// NOTE: this is relative time, not absolute
				fMaxStartTime =
					fMidpointTime - 
					fMidpointTime * pDiscData->fSwatDefendStartMaxDefendPercentage;

				// determine at exactly what time the max ends
				// NOTE: this is relative time, not absolute
				fMaxEndTime =
					fMidpointTime +
					(
						( m_nDefendDuration - fMidpointTime ) *
						pDiscData->fSwatDefendEndMaxDefendPercentage
					);

				// determine the starting defend percentage
				fStartDefendPercentage = pDiscData->fSwatDefendStartDefendPercentage;

				// detecmine the max defend percentage					
				fMaxDefendPercentage = pDiscData->fSwatDefendMaxDefendPercentage;

				// determine the ending defend percentage
				fEndDefendPercentage = pDiscData->fSwatDefendEndDefendPercentage;
			}
			else if ( MPROJ_START_ARM_BLOCK == m_cDefendType )
			{
				// Not implemented yet.  The main question I haven't figured
				// out yet is where does the information come from?
				fMidpointTime = 0.0f;
				fMaxStartTime = 0.0f;
				fMaxEndTime = 0.0f;
				fStartDefendPercentage = 0.0f;
				fMaxDefendPercentage = 0.0f;
				fEndDefendPercentage = 0.0f;
			}

			// determine at exactly how much time we've been in the block
			// NOTE: this is relative time, not absolute
			float fBlockTime = 
				fCurrentServerTime - m_nDefendServerTimeStarted;

			if ( ( -MATH_EPSILON <= fBlockTime ) && 
			     ( fBlockTime <= fMaxStartTime ) )
			{
				// somewhere on the uprise
				fDefenseTimingPercentage =
					fStartDefendPercentage + 
						(
							(
								( 
									fMaxDefendPercentage -
									fStartDefendPercentage
								) /
								fMaxStartTime 
							) * 
							fBlockTime
						);
			}
			else if ( ( fMaxStartTime < fBlockTime ) &&
			          ( fBlockTime <= fMaxEndTime ) )
			{
				// within the max range
				fDefenseTimingPercentage = fMaxDefendPercentage;
			}
			else if ( ( fMaxEndTime < fBlockTime ) &&
			          ( fBlockTime <= m_nDefendDuration ) )
			{
				// somewhere on the downfall
				fDefenseTimingPercentage =
					fMaxDefendPercentage - 
						(
							(
								( 
									fMaxDefendPercentage -
									fEndDefendPercentage
								) /
								( m_nDefendDuration - fMaxEndTime )
							) * 
							( fBlockTime - fMaxEndTime )
						);
			}
			else
			{
				// math problem, we should be here if we are outside
				// the bounds of the defense
				ASSERT( 0 );
				fDefenseTimingPercentage = 0.0f;
			}
		}
		break;


		case MPROJ_START_HOLD_BLOCK:
		{
			// get the current server time
			float fCurrentServerTime = g_pLTServer->GetTime() * 1000.0f;

			// determine the starting defend percentage
			float fStartDefendPercentage = pDiscData->fHoldDefendStartDefendPercentage;

			// determine the max defend percentage					
			float fMaxDefendPercentage = pDiscData->fHoldDefendMaxDefendPercentage;

			// determine at exactly how much time we've been in the block
			// NOTE: this is relative time, not absolute
			float fBlockTime = 
				fCurrentServerTime - m_nDefendServerTimeStarted;

			if ( ( -MATH_EPSILON <= fBlockTime ) && 
			     ( fBlockTime <= m_nDefendDuration ) )
			{
				// somewhere on the uprise
				fDefenseTimingPercentage =
					fStartDefendPercentage + 
						(
							(
								( 
									fMaxDefendPercentage -
									fStartDefendPercentage
								) /
								static_cast< float >( m_nDefendDuration )
							) * 
							fBlockTime
						);
			}
			else if ( m_nDefendDuration < fBlockTime )
			{
				// within the max range
				fDefenseTimingPercentage = fMaxDefendPercentage;
			}
			else
			{
				// math problem, we should be here if we are outside
				// the bounds of the defense
				ASSERT( 0 );
				fDefenseTimingPercentage = 0.0f;
			}
		}
		break;

		case MPROJ_END_HOLD_BLOCK:
		{
			// get the current server time
			float fCurrentServerTime = g_pLTServer->GetTime() * 1000.0f;

			// make sure we're within the range of the block
			if ( ( static_cast< int >( fCurrentServerTime ) -
			       m_nDefendServerTimeStarted ) > m_nDefendDuration )
			{
				// nope, the block is over
				return 0.0f;
			}

			// detecmine the max defend percentage					
			float fMaxDefendPercentage = pDiscData->fHoldDefendMaxDefendPercentage;

			// determine the ending defend percentage
			float fEndDefendPercentage = pDiscData->fHoldDefendEndDefendPercentage;

			// determine at exactly how much time we've been in the block
			// NOTE: this is relative time, not absolute
			float fBlockTime = 
				fCurrentServerTime - m_nDefendServerTimeStarted;

			// somewhere on the downfall
			fDefenseTimingPercentage =
				fMaxDefendPercentage - 
					(
						(
							( 
								fMaxDefendPercentage -
								fEndDefendPercentage
							) /
							( m_nDefendDuration )
						) * 
						( fBlockTime )
					);
		}
		break;

		default:
		{
			// There is some type of block defined that we
			// are not handling, and we SHOULD be handling it.
			ASSERT( 0 );

			return 0.0f;
		}
		break;
	};


	//TODO: skip this section of the camera position is too old?

	// check if the oriention percentage should be computed
	if ( 0 == pIncomingProjectilePosition )
	{
		// No vector specifed, there is no way
		// to compute orientation defense.
		return fDefenseTimingPercentage;
	}

	//
	// Determine Orientation percentage
	//

	// The 3 cases are the same, but they could have different
	// control values.  Figure out what the specific variables
	// are (depending on the specific type of block), then apply
	// the generic equations.

	float fOrientationMinDefendPercentage;
	float fOrientationMaxDefendPercentage;
	float fOrientationDeadZone;
	float fOrientationMaxZone;

	switch ( m_cDefendType )
	{
		case MPROJ_START_SWAT_BLOCK:
		{
			fOrientationMinDefendPercentage  = pDiscData->fSwatDefendOrientationMinDefendPercentage;
			fOrientationMaxDefendPercentage  = pDiscData->fSwatDefendOrientationMaxDefendPercentage;
			fOrientationDeadZone             = MATH_PI - pDiscData->fSwatDefendOrientationDeadZone;
			fOrientationMaxZone              = pDiscData->fSwatDefendOrientationMaxZone;
		}
		break;

		case MPROJ_START_HOLD_BLOCK:
		case MPROJ_END_HOLD_BLOCK:
		{
			fOrientationMinDefendPercentage  = pDiscData->fHoldDefendOrientationMinDefendPercentage;
			fOrientationMaxDefendPercentage  = pDiscData->fHoldDefendOrientationMaxDefendPercentage;
			fOrientationDeadZone             = MATH_PI - pDiscData->fHoldDefendOrientationDeadZone;
			fOrientationMaxZone              = pDiscData->fHoldDefendOrientationMaxZone;
		}
		break;

		case MPROJ_START_ARM_BLOCK:
		{
			// Not implemented yet.  The main question I haven't figured
			// out yet is where does the information come from?
			fOrientationMinDefendPercentage  = 0.0f;
			fOrientationMaxDefendPercentage  = 0.0f;
			fOrientationDeadZone             = 0.0f;
			fOrientationMaxZone              = 0.0f;
		}
		break;

		default:
		{
			// There is some type of block defined that we
			// are not handling, and we SHOULD be handling it.
			ASSERT( 0 );

			return 0.0f;
		}
		break;
	};

	LTRESULT ltResult;
	LTVector vDefendPos;
	LTVector vDefendPosToProjectile;

	// get the player's position
	ltResult = g_pLTServer->GetObjectPos( m_hObject, &vDefendPos );
	ASSERT( LT_OK == ltResult );

	// REMOVE THIS CODE FOR FINAL RELEASE, BUT LEAVE FOR TESTING MULTIPLAYER
	// print a warning if the time is new enough
	if ( TRONPLAYEROBJ_CLIENT_CAMERA_TIME_OLD_THRESHOLD < ( g_pLTServer->GetTime() - m_nClientCameraOffsetTimeReceivedMS ) )
	{
		g_pLTServer->CPrint( "Client Camera Offset time is low, possible lag\n" );
		g_pLTServer->CPrint( "   condition that will affect defensive accuracy.\n" );
		g_pLTServer->CPrint( "   Currnt value is %5.3f units old.\n", ( g_pLTServer->GetTime() - m_nClientCameraOffsetTimeReceivedMS ) );

	}
	
	// add the camera offset vDefendPos += m_vClientCameraOffset;

	// find a unit vector from us to the projectile
	vDefendPosToProjectile  = *pIncomingProjectilePosition -
	                         ( m_vClientCameraOffset +
	                           vDefendPos );
	vDefendPosToProjectile.y = 0;
	vDefendPosToProjectile.Normalize();

	// determine a forward vector reprensenting the direction the
	// player is facing
	LTRotation vPlayerViewOrientation;
	ltResult = g_pLTServer->GetObjectRotation( m_hObject, &vPlayerViewOrientation );
	ASSERT( LT_OK == ltResult );

	LTVector vPlayerViewForward = vPlayerViewOrientation.Forward();
	vPlayerViewForward.y = 0;
	vPlayerViewForward.Normalize();

	float fDotProd = vPlayerViewForward.Dot( vDefendPosToProjectile );

	// find the angle between the two vectors
	float fDefenseAngle = ltacosf( vPlayerViewForward.Dot( vDefendPosToProjectile ) );

	if ( ( MATH_EPSILON <= fDefenseAngle) && ( fDefenseAngle <= fOrientationMaxZone ) )
	{
		// it's within the max zone
		fDefenseOrientationPercentage = fOrientationMaxDefendPercentage;
	}
	else if ( ( fOrientationMaxZone < fDefenseAngle) && ( fDefenseAngle <= fOrientationDeadZone ) )
	{
		// it's within the dropoff range
		fDefenseOrientationPercentage = 
			fOrientationMaxDefendPercentage +
			( fDefenseAngle - fOrientationMaxZone ) *
				( fOrientationMinDefendPercentage - fOrientationMaxDefendPercentage ) /
				( fOrientationDeadZone - fOrientationMaxZone );
	}
	else if ( fOrientationDeadZone <= fDefenseAngle)
	{
		// it's within the dead zone
		fDefenseOrientationPercentage = 0.0f;
	}

	//
	// Final Defense Result
	//

	float fFinalDefensePercentage = fDefenseTimingPercentage -
	                                fDefenseOrientationPercentage;
	return fFinalDefensePercentage;
}
示例#12
0
void CTargetMgr::CheckForIntersect(float &fDistAway)
{
	m_hTarget = LTNULL;
	m_ActivationData.Init();

	uint32 dwUsrFlags = 0;
	const float fMaxDist = 100000.0f;

	// Cast ray from the camera to see if there is an object to activate...

    LTRotation rRot;
    LTVector vPos;

	HLOCALOBJ hCamera = g_pPlayerMgr->GetCamera();
	g_pLTClient->GetObjectPos(hCamera, &vPos);
	g_pLTClient->GetObjectRotation(hCamera, &rRot);

 	m_ActivationData.m_vPos = vPos;
	m_ActivationData.m_rRot = rRot;

	IntersectQuery IQuery;
	IntersectInfo IInfo;

	IQuery.m_From = vPos;
	IQuery.m_To   = IQuery.m_From + (rRot.Forward() * fMaxDist);

	// NOTE the use of the CHECK_FROM_POINT_INSIDE_OBJECTS flag.  This flag will
	// make sure that any objects that m_From is inside are considered
	IQuery.m_Flags = CHECK_FROM_POINT_INSIDE_OBJECTS | INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID;

	IQuery.m_FilterActualIntersectFn	= ActivateFilterFn;
	IQuery.m_pActualIntersectUserData	= (void*)&IQuery;
	IQuery.m_PolyFilterFn				= DoVectorPolyFilterFn;

	// [KLS 8/3/02] - ActivateFilterFn may save an object to use that may not be
	// the best activation choice (i.e., a fallback choice).  However, if a
	// better choice isn't found, the fallback choice should be used.  That
	// fallback choice is stored in g_adFallbackActivationObject so we clear
	// it here...
	g_adFallbackActivationObject.Init();

	if (g_pLTClient->IntersectSegment(&IQuery, &IInfo))
	{
		m_ActivationData.m_vIntersect = IInfo.m_Point;

        if (IsMainWorld(IInfo.m_hObject))
		{
			if (IInfo.m_hPoly != INVALID_HPOLY)
			{
				SurfaceType eType = GetSurfaceType(IInfo.m_hPoly);
				SURFACE *pSurf = g_pSurfaceMgr->GetSurface(eType);

				// See if the surface we tried to activate has an activation
				// sound...If so, the user can activate it...

				if (pSurf && pSurf->szActivationSnd[0] && pSurf->fActivationSndRadius > 0)
				{
					m_hTarget = IInfo.m_hObject;
					m_ActivationData.m_hTarget = m_hTarget;
					m_ActivationData.m_nSurfaceType = eType;
				}
			}
		}
		else
		{
			LTVector vObjPos = m_ActivationData.m_vIntersect;
			vObjPos -= vPos;

			if (vObjPos.Mag() <= fMaxDist)
			{
				m_hTarget = IInfo.m_hObject;
				m_ActivationData.m_hTarget = m_hTarget;
			}
		}

		// Calculate how far away the object is...

		LTVector vDist = m_ActivationData.m_vIntersect - vPos;
		fDistAway = vDist.Mag();
	}
	
	// [KLS 8/3/02] - Use the fallback object if we have one and we didn't 
	// find another object more suitable object... 

	bool bCanUseFallback = (m_ActivationData.m_hTarget ? false : true);
	if (!bCanUseFallback)
	{
		// We can still use the fallback object if it isn't the world or a
		// world model...

		if (IsMainWorld(m_ActivationData.m_hTarget) || 
			OT_WORLDMODEL == GetObjectType(m_ActivationData.m_hTarget))
		{
			bCanUseFallback = true;
		}
	}

	if ( bCanUseFallback && g_adFallbackActivationObject.m_hTarget )
	{
		// Ok we hit the fallback object reset some of our target data
	
		LTVector vObjPos;
		g_pLTClient->GetObjectPos(g_adFallbackActivationObject.m_hTarget, &vObjPos);

		m_ActivationData.m_vIntersect = vObjPos;

		vObjPos -= vPos;

		if (vObjPos.Mag() <= fMaxDist)
		{
			m_hTarget = g_adFallbackActivationObject.m_hTarget;
			m_ActivationData.m_hTarget = m_hTarget;
		}

		// Calculate how far away the object is...

		LTVector vDist = m_ActivationData.m_vIntersect - vPos;
		fDistAway = vDist.Mag();
	}
}
示例#13
0
bool CFallingStuffFX::Update(float tmFrameTime)
{
    // Base class update first

    m_vLastPos = m_vPos;

    if (!CBaseFX::Update(tmFrameTime))
        return false;

    //increment our emission time by the elapsed frame time
    m_tmElapsedEmission += tmFrameTime;

    if (!IsShuttingDown() && !IsSuspended() && (m_tmElapsedEmission > GetProps()->m_tmFallingStuffFXEmission))
    {
        ObjectCreateStruct ocs;
        INIT_OBJECTCREATESTRUCT(ocs);

        LTVector vScale;
        vScale.Init(m_scale, m_scale, m_scale);

        LTVector vInterp;
        LTVector vInterpCur  = m_vPos;

        // Calculate interpolant for particle system

        if (GetProps()->m_nFallingStuffFXEmission)
        {
            vInterp = m_vPos - m_vLastPos;
            vInterp /= (float)GetProps()->m_nFallingStuffFXEmission;
        }

        for (uint32 i = 0; i < GetProps()->m_nFallingStuffFXEmission; i ++)
        {
            ocs.m_ObjectType		= OT_SPRITE;
            ocs.m_Flags				= FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATABLESPRITE;

            // Compute the initial position

            float xRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f);
            float zRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f);

            ocs.m_Pos = m_vPos + (m_vRight * xRand) + (m_vUp * zRand);

            ocs.m_Scale				= vScale;
            strcpy(ocs.m_Filename, GetProps()->m_sSpriteName);

            // Move the start point

            vInterpCur += vInterp;

            HLOCALOBJ hNewSprite = m_pLTClient->CreateObject(&ocs);

            if (hNewSprite)
            {
                // Create a new sprite

                FALLING_THING *pNewSprite = debug_new( FALLING_THING );

                if (GetProps()->m_nImpactCreate)
                {
                    if (g_dwSplash > (uint32)GetProps()->m_nImpactCreate)
                    {
                        pNewSprite->m_bSplash = true;
                        g_dwSplash = 0;
                    }
                    else
                    {
                        pNewSprite->m_bSplash = false;
                    }
                }
                else
                {
                    pNewSprite->m_bSplash = false;
                }

                g_dwSplash ++;

                if (pNewSprite)
                {
                    LTVector v;

                    // Compute the initial velocity

                    v = m_vPlaneDir * GetProps()->m_fVel;

                    pNewSprite->m_hObject	= hNewSprite;
                    pNewSprite->m_vVel		= v;
                    pNewSprite->m_tmElapsed	= 0.0f;
                    pNewSprite->m_vPos		= ocs.m_Pos;
                    pNewSprite->m_vLastPos	= ocs.m_Pos;

                    m_collSprites.AddTail(pNewSprite);
                }
            }
        }

        m_tmElapsedEmission = 0.0f;

        // And store the last position

        m_vLastPos = m_vPos;
    }

    LTMatrix mSpin;

    if (GetProps()->m_bUseSpin)
    {
        // Setup rotation

        LTMatrix vRight;
        LTMatrix vUp;
        LTMatrix vForward;
        LTMatrix vTmp;

        Mat_SetupRot(&vRight, &m_vRight, m_xRot);
        Mat_SetupRot(&vUp, &m_vUp, m_yRot);
        Mat_SetupRot(&vForward, &m_vPlaneDir, m_zRot);

        MatMul(&vTmp, &vRight, &vUp);
        MatMul(&mSpin, &vTmp, &vForward);

        m_xRot += GetProps()->m_vRotAdd.x * tmFrameTime;
        m_yRot += GetProps()->m_vRotAdd.y * tmFrameTime;
        m_zRot += GetProps()->m_vRotAdd.z * tmFrameTime;
    }

    // Get the camera rotation

    LTRotation orient;
    m_pLTClient->GetObjectRotation(m_hCamera, &orient);

    LTRotation dRot(orient);

    LTVector vF = orient.Forward();

    float rot = (float)atan2(vF.x, vF.z);

    // Update the sprites....

    CLinkListNode<FALLING_THING *> *pNode = m_collSprites.GetHead();
    CLinkListNode<FALLING_THING *> *pDelNode;

    while (pNode)
    {
        pDelNode = NULL;

        FALLING_THING *pSprite = pNode->m_Data;

        //adjust our elapsed time
        pSprite->m_tmElapsed += tmFrameTime;

        // Check for expiration

        if (pSprite->m_tmElapsed > GetProps()->m_tmSpriteLifespan)
        {
            // Destroy this object

            m_pLTClient->RemoveObject(pSprite->m_hObject);

            pDelNode = pNode;
        }
        else
        {
            // Update !!

            pSprite->m_vLastPos = pSprite->m_vPos;

            pSprite->m_vPos += (pSprite->m_vVel * tmFrameTime);

            // Rotate if neccessary

            TVector3<float> vPos = pSprite->m_vPos;

            if (GetProps()->m_bUseSpin)
            {
                MatVMul_InPlace(&mSpin, &vPos);
            }

            // Add in wind

            vPos += (GetProps()->m_vWind * GetProps()->m_fWindAmount) * tmFrameTime;

            // Setup the new sprite position

            LTVector vPos2 = vPos;
            m_pLTClient->SetObjectPos(pSprite->m_hObject, &vPos2);


            // Setup the colour

            float r, g, b, a;

            m_pLTClient->GetObjectColor(pSprite->m_hObject, &r, &g, &b, &a);
            CalcColour(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &r, &g, &b, &a);
            m_pLTClient->SetObjectColor(pSprite->m_hObject, r, g, b, a);

            // Setup the scale

            float scale = 0.1f;

            CalcScale(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &scale);

            LTVector vScale;
            vScale.Init(scale, scale * GetProps()->m_fStretchMul, scale);
            m_pLTClient->SetObjectScale(pSprite->m_hObject, &vScale);

            // Setup the rotation

            dRot = LTRotation(0, 0, 0, 1);
            LTRotation orient(dRot);

            orient.Rotate( orient.Up(), rot );

            m_pLTClient->SetObjectRotation(pSprite->m_hObject, &orient);

            // Check to see if we need to start a splash sprite

            if (pSprite->m_bSplash)
            {
                ClientIntersectQuery ciq;
                ClientIntersectInfo  cii;

                ciq.m_From		= pSprite->m_vLastPos;
                ciq.m_To		= pSprite->m_vPos;

                if ((GetProps()->m_sImpactSpriteName[0]) && (m_pLTClient->IntersectSegment(&ciq, &cii)))
                {
                    // Create a splash sprite

                    SPLASH *pSplash = debug_new( SPLASH );

                    ObjectCreateStruct ocs;
                    INIT_OBJECTCREATESTRUCT(ocs);

                    LTVector vScale;
                    vScale.Init(0.0f, 0.0f, 0.0f);

                    ocs.m_ObjectType = OT_SPRITE;
                    ocs.m_Flags		 = FLAG_VISIBLE | FLAG_ROTATABLESPRITE | FLAG_NOLIGHT;
                    ocs.m_Pos		 = cii.m_Point + (cii.m_Plane.m_Normal * 2.0f);
                    ocs.m_Scale		 = vScale;

                    LTRotation dOrient( cii.m_Plane.m_Normal, LTVector(0.0f, 1.0f, 0.0f) );

                    strcpy(ocs.m_Filename, GetProps()->m_sImpactSpriteName);

                    pSplash->m_hObject = m_pLTClient->CreateObject(&ocs);
                    pSplash->m_scale = 0.0f;

                    LTRotation orient(dRot);
                    m_pLTClient->SetObjectRotation(pSplash->m_hObject, &orient);

                    pSplash->m_tmElapsed = 0.0f;

                    m_collSplashes.AddTail(pSplash);

                    // Destroy this object

                    m_pLTClient->RemoveObject(pSprite->m_hObject);

                    // Delete the sprite

                    pDelNode = pNode;
                }
            }
        }

        pNode = pNode->m_pNext;

        if (pDelNode) m_collSprites.Remove(pDelNode);
    }

    // Update our splashes

    CLinkListNode<SPLASH *> *pSplashNode = m_collSplashes.GetHead();

    while (pSplashNode)
    {
        CLinkListNode<SPLASH *> *pDelNode = NULL;

        SPLASH *pSplash = pSplashNode->m_Data;

        //update the elapsed time on the splash
        pSplash->m_tmElapsed += tmFrameTime;

        // Calculate the new scale

        float scale = GetProps()->m_fImpactScale1 + ((GetProps()->m_fImpactScale2 - GetProps()->m_fImpactScale1) * (pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan));

        LTVector vScale(scale, scale, scale);
        m_pLTClient->SetObjectScale(pSplash->m_hObject, &vScale);

        float r, g, b, a;

        m_pLTClient->GetObjectColor(pSplash->m_hObject, &r, &g, &b, &a);

        a = (float)(int)(pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan);
        if (a < 0.0f) a = 0.0f;
        if (a > 1.0f) a = 1.0f;

        m_pLTClient->SetObjectColor(pSplash->m_hObject, r, g, b, a);

        if (pSplash->m_tmElapsed > GetProps()->m_tmImpactLifespan)
        {
            m_pLTClient->RemoveObject(pSplash->m_hObject);
            pDelNode = pSplashNode;
        }

        pSplashNode = pSplashNode->m_pNext;

        if (pDelNode) m_collSplashes.Remove(pDelNode);
    }

    // Success !!

    return true;
}
示例#14
0
void CLaserBeam::Update(LTVector &vBeamStartPos, const LTRotation* pRDirRot,
                        LTBOOL b3rdPerson, LTBOOL bDetect)
{
	if (!m_bOn) return;

	// Calculate beam position...

	HOBJECT hCamera = g_pPlayerMgr->GetCamera();
	if (!hCamera) return;

    HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject();
	if (!hPlayerObj) return;

    HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL};

	IntersectQuery qInfo;
	IntersectInfo iInfo;

    LTVector vPos(0, 0, 0);
    LTRotation rRot;

    LTVector vU, vR, vF;

	if (pRDirRot && b3rdPerson)
	{
		vPos = vBeamStartPos;

		vU = pRDirRot->Up();
		vR = pRDirRot->Right();
		vF = pRDirRot->Forward();
	}
	else
	{
		g_pLTClient->GetObjectRotation(hCamera, &rRot);
		g_pLTClient->GetObjectPos(hCamera, &vPos);

		vU = rRot.Up();
		vR = rRot.Right();
		vF = rRot.Forward();

		if (g_cvarLaserBeamDebug.GetFloat() == 0.0f)
		{
			vBeamStartPos += vPos;
		}
		else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f)
		{
			vBeamStartPos = vPos;
		}
		else if (pRDirRot)
		{
			vU = pRDirRot->Up();
			vR = pRDirRot->Right();
			vF = pRDirRot->Forward();
			vBeamStartPos = vBeamStartPos;
		}

	}


    LTVector vEndPos = vPos + (vF * 10000.0f);

	qInfo.m_From = vPos;
	qInfo.m_To   = vEndPos;

	qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
	qInfo.m_FilterFn = ObjListFilterFn;
	qInfo.m_pUserData = hFilterList;

    if (g_pLTClient->IntersectSegment(&qInfo, &iInfo))
	{
		vEndPos = iInfo.m_Point;
	}


	// Show the light beam...

    LTVector vColor = LTVector(GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f), GetRandom(35.0f, 55.0f));;

    LTFLOAT fAlpha = g_cvarLaserBeamAlpha.GetFloat();

	if (iInfo.m_hObject && bDetect)
	{
        uint32 dwUsrFlgs = 0;
        g_pCommonLT->GetObjectFlags(iInfo.m_hObject, OFT_User, dwUsrFlgs);

		if (dwUsrFlgs & USRFLG_CHARACTER)
		{
			fAlpha	= 0.95f;
			vColor.Init(GetRandom(35.0f, 55.0f), GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f));;
		}
	}

    LTFLOAT fWidth = g_cvarLaserBeamThickness.GetFloat();
	fWidth = b3rdPerson ? fWidth*2.0f : fWidth;

	vBeamStartPos += (vF * g_cvarLaserBeamFOffset.GetFloat());
	vBeamStartPos += (vR * g_cvarLaserBeamROffset.GetFloat());
	vBeamStartPos += (vU * g_cvarLaserBeamUOffset.GetFloat());

	PLFXCREATESTRUCT pls;

	if (g_cvarLaserBeamDebug.GetFloat() >= 0.0f)
	{
        // g_pLTClient->CPrint("StartPos = %.2f, %.2f, %.2f", VEC_EXPAND(vBeamStartPos));
        // g_pLTClient->CPrint("EndPos = %.2f, %.2f, %.2f", VEC_EXPAND(vEndPos));
	}

	pls.vStartPos			= vBeamStartPos;
	pls.vEndPos				= vEndPos;
	pls.vInnerColorStart	= vColor;
	pls.vInnerColorEnd		= pls.vInnerColorStart;
    pls.vOuterColorStart    = LTVector(0, 0, 0);
    pls.vOuterColorEnd      = LTVector(0, 0, 0);
	pls.fAlphaStart			= fAlpha;
	pls.fAlphaEnd			= fAlpha;
	pls.fMinWidth			= 0;
	pls.fMaxWidth			= fWidth;
	pls.fMinDistMult		= 1.0f;
	pls.fMaxDistMult		= 1.0f;
	pls.fLifeTime			= 1.0f;
	pls.fAlphaLifeTime		= 1.0f;
	pls.fPerturb			= 0.0f;
    pls.bAdditive           = LTTRUE;
    pls.bAlignFlat          = b3rdPerson ? LTFALSE : LTTRUE;
	pls.nWidthStyle			= PLWS_CONSTANT;
	pls.nNumSegments		= (int)g_cvarLaserBeamNumSegments.GetFloat();

	if (m_LightBeam.HasBeenDrawn())
	{
		// Keep the light beam in the vis list...

		m_LightBeam.SetPos(vBeamStartPos);

		// Hide the beam in portals if 1st person...Also set flag really
		// close to true...

        uint32 dwFlags2, dwFlags;

		dwFlags = m_LightBeam.GetFlags();
		dwFlags2 = m_LightBeam.GetFlags2();

		if (b3rdPerson)
		{
			dwFlags &= ~FLAG_REALLYCLOSE;
		}
		else
		{
			if (g_cvarLaserBeamDebug.GetFloat() > 1.0f)
			{
				dwFlags |= FLAG_REALLYCLOSE;
                pls.bUseObjectRotation = LTTRUE;
			}
		}

		m_LightBeam.SetFlags(dwFlags);
		m_LightBeam.SetFlags2(dwFlags2);

		m_LightBeam.ReInit(&pls);
	}
	else
	{
		m_LightBeam.Init(&pls);
        m_LightBeam.CreateObject(g_pLTClient);
	}


	m_LightBeam.Update();
}
示例#15
0
void CLightningFX::EmitBolts( float tmFrameTime )
{
	// Make sure enough time between emissions has passed...
	m_tmElapsedEmission += tmFrameTime;

	if( m_fDelay < m_tmElapsedEmission )
	{
		LTransform		lTrans;
		LTVector		vAttractorPos;
		ILTModel		*pModelLT = m_pLTClient->GetModelLT();

		uint32	nActiveBolts = GetRandom( (int)GetProps()->m_nMinNumBolts, (int)GetProps()->m_nMaxNumBolts );
		uint32	nBolt;

		bool	bCanUseAttractors = (m_lstAttractors.size() > 0);
		bool	bCanUseRadius = (GetProps()->m_fOmniDirectionalRadius >= 1.0f);

		CLightningBolt *pBolt = LTNULL;
		LightningBolts::iterator iter;

		for( nBolt = 0, iter = m_lstBolts.begin(); iter != m_lstBolts.end(), nBolt < nActiveBolts; ++iter, ++nBolt )
		{
			pBolt = *iter;
			
			pBolt->m_fWidth = GetRandom( GetProps()->m_fMinBoltWidth, GetProps()->m_fMaxBoltWidth );
			pBolt->m_fLifetime = GetRandom( GetProps()->m_fMinLifetime, GetProps()->m_fMaxLifetime );
			pBolt->m_tmElapsed = 0.0f;
			pBolt->m_bActive = true;
			
			// Grab the position of the object to compensate for offset
		
			if( m_hTarget )
			{
				m_pLTClient->GetObjectPos( m_hTarget, &vAttractorPos );
			}
			else
			{
				vAttractorPos = m_vTargetPos;
			}

			// Decide if we should use an attractor or radius for the end pos...
			
			if( bCanUseAttractors && (!bCanUseRadius || GetRandom(0,1)) )
			{
				uint8	nIndex = GetRandom( 0, (int)(m_lstAttractors.size()) - 1 );
				CAttractor cAttractor = m_lstAttractors[nIndex];

				if( cAttractor.GetTransform( lTrans, true ) == LT_OK )
				{
					vAttractorPos = lTrans.m_Pos;
				}
			}	
			else if( bCanUseRadius )
			{
				LTVector vRandomPos;
				vRandomPos.x = GetRandom( -1.0f, 1.0f );
				vRandomPos.y = GetRandom( -1.0f, 1.0f );
				vRandomPos.z = GetRandom( -1.0f, 1.0f );
				
				vRandomPos.Normalize();
				vRandomPos *= GetRandom( -GetProps()->m_fOmniDirectionalRadius, GetProps()->m_fOmniDirectionalRadius );

				vAttractorPos = m_vPos + vRandomPos;

				IntersectQuery	iQuery;
				IntersectInfo	iInfo;

				iQuery.m_From	= m_vPos;
				iQuery.m_To		= vAttractorPos;

				if( m_pLTClient->IntersectSegment( &iQuery, &iInfo ))
				{
					vAttractorPos = iInfo.m_Point;
				}
			}

			
			LTVector vNew = m_vPos;
			LTVector vDir = vAttractorPos - vNew;
						
			float fStep = vDir.Length() / (float)pBolt->m_nNumSegments;
			float fPerturb = GetRandom( GetProps()->m_fMinPerturb, GetProps()->m_fMaxPerturb );
			
			vDir.Normalize();
			LTRotation rRot = LTRotation( vDir, LTVector( 0.0f, 1.0f, 0.0f ));
				
			CLinkListNode<PT_TRAIL_SECTION> *pNode = pBolt->m_collPathPts.GetHead();
			while( pNode )
			{
				pNode->m_Data.m_vPos = vNew;
				pNode->m_Data.m_tmElapsed = 0.0f;
				pNode->m_Data.m_vBisector.Init();
												
				// Add in some perturb going in the direction of the attractor pos for the next section...
				
				vNew +=	(rRot.Forward() * fStep );
				vNew += (rRot.Up() * GetRandom( -fPerturb, fPerturb ));
				vNew += (rRot.Right() * GetRandom( -fPerturb, fPerturb ));

				// Make sure the last section goes to the end pos...

				if( !pNode->m_pNext )
					pNode->m_Data.m_vPos = vAttractorPos;

				pNode = pNode->m_pNext;
			}
		}

		// Decide when the next emission will be...

		m_tmElapsedEmission = 0.0f;
		m_fDelay = GetRandom( GetProps()->m_fMinDelay, GetProps()->m_fMaxDelay );
	}
}
示例#16
0
bool CPolyTubeFX::Update(float tmFrameTime)
{
	// Base class update first
	if (!CBaseFX::Update(tmFrameTime)) 
		return false;

	if ((!m_hTexture) && (!m_bLoadFailed))
	{
		m_pLTClient->GetTexInterface()->CreateTextureFromName(m_hTexture, GetProps()->m_sPath);

		if (m_hTexture)
		{
			// Retrieve texture dims
			uint32 nHeight;
			m_pLTClient->GetTexInterface()->GetTextureDims(m_hTexture, m_dwWidth, nHeight);
		}
		else
		{
			m_bLoadFailed = true;
		}
	}

	if ((m_collPathPts.GetSize() < 2) && IsShuttingDown())
	{
		m_collPathPts.RemoveAll();
		return true;
	}
	
	float tmAddPtInterval = GetProps()->m_tmAddPtInterval * 2.0f;

	LTRotation rRot;
	m_pLTClient->GetObjectRotation( m_hObject, &rRot );

	//increase the emission time elapse
	m_tmElapsedEmission += tmFrameTime;

	if (!IsShuttingDown() && 
	    (m_collPathPts.GetSize() < GetProps()->m_nMaxTrailLength) && 
		((m_tmElapsedEmission > GetProps()->m_tmAddPtInterval) || (m_collPathPts.GetSize() == 1)))
	{
		LTVector vNew = m_vPos;
		
		// Only add the new point if it's not the same as the last one....

		// Add a new trail section

		PT_TRAIL_SECTION ts;
		ts.m_vPos		= vNew;
		ts.m_tmElapsed	= 0.0f;

		switch( GetProps()->m_eAllignment )
		{
			case ePTA_Up:
				ts.m_vBisector = rRot.Up();
			break;

			case ePTA_Right:
				ts.m_vBisector = rRot.Right();
			break;

			case ePTA_Forward:
				ts.m_vBisector = rRot.Forward();
			break;

			case ePTA_Camera:
			default:
				ts.m_vBisector.Init();
			break;
		}
		
		
		// Compute u coordinate

		if (m_collPathPts.GetSize())
		{
			LTVector vPrev = m_collPathPts.GetTail()->m_Data.m_vPos;
			float fUPrev = m_collPathPts.GetTail()->m_Data.m_uVal;
			
			float fWidth = (float)m_dwWidth;
			float fScalar = fWidth / GetProps()->m_fTrailWidth;

			ts.m_uVal = fUPrev + ((((vNew - vPrev).Mag()) / fWidth) * fScalar);

		}
		else
		{
			ts.m_uVal = 0.0f;
		}

		m_collPathPts.AddTail(ts);
		
		m_tmElapsedEmission = 0.0f;
	}

	// Render the tube....

	if (m_collPathPts.GetSize() < 2) return true;

	CLinkListNode<PT_TRAIL_SECTION> *pNode = m_collPathPts.GetHead();

	// Fudge the last point to be the current one...

	if( !IsShuttingDown() )
		m_collPathPts.GetTail()->m_Data.m_vPos = m_vPos;

	// Transform the path

	LTMatrix mCam;
	if( m_bReallyClose || (GetProps()->m_eAllignment != ePTA_Camera))
	{
		mCam.Identity();
	}
	else
	{
		mCam = GetCamTransform(m_pLTClient, m_hCamera);
	}
	 
	while (pNode)
	{
		MatVMul(&pNode->m_Data.m_vTran, &mCam, &pNode->m_Data.m_vPos);
		pNode = pNode->m_pNext;
	}

	// Do some precalculations

	pNode = m_collPathPts.GetHead();

	float fCurU = 0.0f;

	while (pNode)
	{
		pNode->m_Data.m_tmElapsed += tmFrameTime;

		if( GetProps()->m_eAllignment == ePTA_Camera )
		{
			LTVector vBisector;
			vBisector.z = 0.0f;

			// Compute the midpoint vectors

			if (pNode == m_collPathPts.GetHead())
			{
				LTVector vStart = pNode->m_Data.m_vTran;
				LTVector vEnd   = pNode->m_pNext->m_Data.m_vTran;
				
				vBisector.x = vEnd.y - vStart.y;
				vBisector.y = -(vEnd.x - vStart.x);
			}
			else if (pNode == m_collPathPts.GetTail())
			{
				LTVector vEnd   = pNode->m_Data.m_vTran;
				LTVector vStart = pNode->m_pPrev->m_Data.m_vTran;
				
				vBisector.x = vEnd.y - vStart.y;
				vBisector.y = -(vEnd.x - vStart.x);
			}
			else
			{
				LTVector vPrev  = pNode->m_pPrev->m_Data.m_vTran;
				LTVector vStart = pNode->m_Data.m_vTran;
				LTVector vEnd   = pNode->m_pNext->m_Data.m_vTran;

				float x1 = vEnd.y - vStart.y;
				float y1 = -(vEnd.x - vStart.x);
				float z1 = vStart.z - vEnd.z;

				float x2 = vStart.y - vPrev.y;
				float y2 = -(vStart.x - vPrev.x);
				float z2 = vPrev.z - vEnd.z;
				
				vBisector.x = (x1 + x2) / 2.0f;
				vBisector.y = (y1 + y2) / 2.0f;
			}

			pNode->m_Data.m_vBisector = vBisector;
		}
		
		LTFLOAT fWidth = CalcCurWidth();
		pNode->m_Data.m_vBisector.Norm( fWidth );

		// Setup the colour
		
		float r, g, b, a;			
		CalcColour(pNode->m_Data.m_tmElapsed, GetProps()->m_tmSectionLifespan, &r, &g, &b, &a);			

		int ir = (int)(r * 255.0f);
		int ig = (int)(g * 255.0f);
		int ib = (int)(b * 255.0f);
		int ia = (int)(a * 255.0f);

		pNode->m_Data.m_red = Clamp( ir, 0, 255 );
		pNode->m_Data.m_green = Clamp( ig, 0, 255 );
		pNode->m_Data.m_blue = Clamp( ib, 0, 255 );
		pNode->m_Data.m_alpha = Clamp( ia, 0, 255 );
	
		pNode = pNode->m_pNext;
	}

	pNode = m_collPathPts.GetHead();

	pNode = m_collPathPts.GetHead();

	// Delete any dead nodes

	while (pNode->m_pNext)
	{
		CLinkListNode<PT_TRAIL_SECTION> *pDelNode= NULL;

		if (pNode->m_Data.m_tmElapsed >= GetProps()->m_tmSectionLifespan)
		{
			pDelNode = pNode;
		}
		
		pNode = pNode->m_pNext;

		if (pDelNode) m_collPathPts.Remove(pDelNode);
	}

	// Increment the offset
	m_uOffset += tmFrameTime * GetProps()->m_uAdd;

	// Success !!

	return true;
}
示例#17
0
void CPolyGridFX::CreateModelWaves(uint32 nKernalSize, uint32 nBuffer, float fFrameTime)
{
	//maximum number of objects to find intersecting the grid
	static const uint32 knMaxObjToFind = 32;

	//find the radius of our polygrid
	float fPolyRad = m_vDims.Mag();

	//amount to displace for a model
	float fDisplaceAmount = m_fModelDisplace * fFrameTime;

	//just bail if the models aren't going to displace at all
	if(fDisplaceAmount < 0.01f)
		return;

	HLOCALOBJ hFound[knMaxObjToFind];
	uint32 nFound = 0;

	LTVector vPGPos;
	m_pClientDE->GetObjectPos(m_hObject, &vPGPos);

	LTVector vPGDims;
	m_pClientDE->Physics()->GetObjectDims(m_hObject, &vPGDims);

	//now run through all the characters and see which ones intersect
	CSpecialFXList* pCharacterList = g_pGameClientShell->GetSFXMgr()->GetFXList(SFX_CHARACTER_ID);

	LTVector vPGMin = vPGPos - vPGDims;
	LTVector vPGMax = vPGPos + vPGDims;

	for(uint32 nCurrChar = 0; nCurrChar < (uint32)pCharacterList->GetNumItems(); nCurrChar++)
	{
		if(!(*pCharacterList)[nCurrChar])
			continue;

		//determine the HOBJECT of this character
		HOBJECT hChar = (*pCharacterList)[nCurrChar]->GetServerObj();

		if(!hChar)
			continue;

		//get the object position and dimensions
		LTVector vCharPos, vCharDims;
		m_pClientDE->GetObjectPos(hChar, &vCharPos);
		m_pClientDE->Physics()->GetObjectDims(hChar, &vCharDims);

		LTVector vCharMin = vCharPos - vCharDims;
		LTVector vCharMax = vCharPos + vCharDims;

		//if it overlaps, add it to our list
		if( (vPGMin.x < vCharMax.x) && (vPGMax.x > vCharMin.x) &&
			(vPGMin.y < vCharMax.y) && (vPGMax.y > vCharMin.y) &&
			(vPGMin.z < vCharMax.z) && (vPGMax.z > vCharMin.z))
		{
			//they intersect, add it to the list
			hFound[nFound] = hChar;
			nFound++;

			//see if we need to stop looking for objects
			if(nFound >= knMaxObjToFind)
				break;
		}
	}

	//bail if none
	if(nFound == 0)
	{
		//make sure all objects are cleared from the list
		for(uint32 nCurrRemove = 0; nCurrRemove < MAX_MODELS_TO_TRACK; nCurrRemove++)
		{
			m_hTrackedModels[nCurrRemove] = NULL;
		}
		return;
	}

	//precalc info

	//find the orienation of the polygrid
	LTRotation rRot;
	m_pClientDE->GetObjectRotation(m_hObject, &rRot);

	//now get the basis vectors of the object space
	LTVector vRight		= rRot.Right();
	LTVector vForward	= rRot.Forward();

	//make sure the polygrid is valid
	if((m_dwNumPoliesX == 0) || (m_dwNumPoliesY == 0))
		return;

	//find the dimensions of the polygons of the polygrid
	float fXPolySize = (m_vDims.x * 2.0f) / (float)m_dwNumPoliesX;
	float fYPolySize = (m_vDims.z * 2.0f) / (float)m_dwNumPoliesY;

	//bail if not a valid size
	if((fXPolySize < 0.01f) || (fYPolySize < 0.01f))
		return;

	//flag indicating which tracked models should be kept around
	bool bTouchedTrackedModels[MAX_MODELS_TO_TRACK];

	for(uint32 nCurrTrack = 0; nCurrTrack < MAX_MODELS_TO_TRACK; nCurrTrack++)
	{
		bTouchedTrackedModels[nCurrTrack] = false;
	}

	//ok, now we run through all the objects we found and update our grid accordingly
	for(uint32 nCurrObj = 0; nCurrObj < nFound; nCurrObj++)
	{
		//the object we are checking
		HLOCALOBJ hObj = hFound[nCurrObj];

		//now lets see if this is a tracked model, if it is, we know where it was last
		//update and we can create a wave line, otherwise we have no clue, and should
		//track it for the next update
		bool bTracked = false;
		LTVector vPrevPos;

		LTVector vPos;
		m_pClientDE->GetObjectPos(hObj, &vPos);

		//if we aren't currently tracking it, this is where to put it
		uint32 nInsertPos = MAX_MODELS_TO_TRACK - 1;

		for(uint32 nCurrModel = 0; nCurrModel < MAX_MODELS_TO_TRACK; nCurrModel++)
		{
			if(m_hTrackedModels[nCurrModel] == hObj)
			{
				//we found a match, we need to save this value, move
				//it to the front of the list, and update it
				vPrevPos = m_vTrackedModelsPos[nCurrModel];

				//move all the items back so that this will be in the first slot
				for(uint32 nCurrMove = nCurrModel; nCurrMove > 0; nCurrMove--)
				{
					m_hTrackedModels[nCurrMove] = m_hTrackedModels[nCurrMove - 1];
					m_vTrackedModelsPos[nCurrMove] = m_vTrackedModelsPos[nCurrMove - 1];
					bTouchedTrackedModels[nCurrMove] = bTouchedTrackedModels[nCurrMove - 1];
				}

				//update the first element
				m_hTrackedModels[0] = hObj;
				m_vTrackedModelsPos[0] = vPos;
				bTouchedTrackedModels[0] = true;

				//all done
				bTracked = true;
				break;
			}

			//also bail if one of the slots is NULL
			if(m_hTrackedModels[nCurrModel] == NULL)
			{
				nInsertPos = nCurrModel;
			}
		}

		//see if this was tracked or not
		if(!bTracked)
		{
			//was not! We need to add it to the list
			m_hTrackedModels[nInsertPos] = hObj;
			m_vTrackedModelsPos[nInsertPos] = vPos;
			bTouchedTrackedModels[nInsertPos] = true;

			continue;
		}

		//make sure that the model is actually moving
		if((vPrevPos - vPos).MagSqr() < 0.5f)
			continue;

		//ok, we have a model that intersects our polygrid, let us create some waves

		//find out the endpoints of the line that will displace
		float fX1 = vRight.Dot(vPrevPos - vPGPos) + m_vDims.x;
		float fY1 = vForward.Dot(vPrevPos - vPGPos) + m_vDims.z;
		float fX2 = vRight.Dot(vPos - vPGPos) + m_vDims.x;
		float fY2 = vForward.Dot(vPos - vPGPos) + m_vDims.z;

		//now find the greater delta in polygon units
		float fXDelta = (float)fabs(fX1 - fX2) / fXPolySize;
		float fYDelta = (float)fabs(fY1 - fY2) / fYPolySize;

		//increments for the X and Y directions
		float fXInc, fYInc;
		float fCurrX, fCurrY;

		//the variable to use for threshold comparisons
		float *pfCompare;

		//the threshold
		float fThreshold;

		//now scan convert accordingly
		if(fYDelta > fXDelta)
		{
			//make sure Y1 is smaller
			if(fY2 < fY1)
			{
				Swap(fY1, fY2);
				Swap(fX1, fX2);
			}

			fYInc = fYPolySize;
			fXInc = (fX2 - fX1) / (fY2 - fY1) * fYInc;

			fThreshold = fY2 / fYPolySize;
			pfCompare = &fCurrY;
		}
		else
		{
			//make sure Y1 is smaller
			if(fX2 < fX1)
			{
				Swap(fY1, fY2);
				Swap(fX1, fX2);
			}
			fXInc = fXPolySize;
			fYInc = (fY2 - fY1) / (fX2 - fX1) * fXInc;

			fThreshold = fX2 / fXPolySize;
			pfCompare = &fCurrX;
		}

		//start out at the first point
		fCurrY = fY1 / fYPolySize;
		fCurrX = fX1 / fXPolySize;
		fXInc /= fXPolySize;
		fYInc /= fXPolySize;

		float fXFrac;
		float fYFrac;

		uint32 nPrevBuffer = (nBuffer + 1) % 2;

		//we need to scale the displacement amount by the speed at which we are moving
		fDisplaceAmount *= (vPrevPos - vPos).Mag() / (fFrameTime * g_cvarPGDisplaceMoveScale.GetFloat());

		//now scan convert!
		while(*pfCompare < fThreshold)
		{
			//convert this to an integer position
			int32 nXPos = (int32)(fCurrX);
			int32 nYPos = (int32)(fCurrY);

			//handle clipping
			if((nXPos >= (int32)nKernalSize) && (nYPos >= (int32)nKernalSize) &&
				(nXPos < (int32)m_dwNumPoliesX - (int32)nKernalSize - 1) &&
				(nYPos < (int32)m_dwNumPoliesY - (int32)nKernalSize - 1))
			{
				fXFrac = fCurrX - nXPos;
				fYFrac = fCurrY - nYPos;

				m_WaveBuffer[nBuffer].Get(nXPos, nYPos)  += fDisplaceAmount * (1.0f - fXFrac) * (1.0f - fYFrac);
				m_WaveBuffer[nBuffer].Get(nXPos + 1, nYPos) += fDisplaceAmount * fXFrac * (1.0f - fYFrac);
				m_WaveBuffer[nBuffer].Get(nXPos, nYPos + 1) += fDisplaceAmount * (1.0f - fXFrac) * fYFrac;
				m_WaveBuffer[nBuffer].Get(nXPos + 1, nYPos + 1) += fDisplaceAmount * fXFrac * fYFrac;
				
				m_WaveBuffer[nPrevBuffer].Get(nXPos, nYPos)  += fDisplaceAmount * (1.0f - fXFrac) * (1.0f - fYFrac);
				m_WaveBuffer[nPrevBuffer].Get(nXPos + 1, nYPos) += fDisplaceAmount * fXFrac * (1.0f - fYFrac);
				m_WaveBuffer[nPrevBuffer].Get(nXPos, nYPos + 1) += fDisplaceAmount * (1.0f - fXFrac) * fYFrac;
				m_WaveBuffer[nPrevBuffer].Get(nXPos + 1, nYPos + 1) += fDisplaceAmount * fXFrac * fYFrac;
			}

			//move along
			fCurrX += fXInc;
			fCurrY += fYInc;
		}
	}

	//now that we are done, clear out any models that were not touched
	for(uint32 nCurrRemove = 0; nCurrRemove < MAX_MODELS_TO_TRACK; nCurrRemove++)
	{
		if(!bTouchedTrackedModels[nCurrRemove])
			m_hTrackedModels[nCurrRemove] = NULL;
	}
}
bool CClientWeaponDisc::CalculatePointGuidedTarget( LTVector *pvTargetPoint )
{
    //
    // safety check
    //

    // params
    ASSERT( 0 != pvTargetPoint );

    // globals
    ASSERT( 0 != g_pLTClient );
    ASSERT( 0 != g_pPlayerMgr );


    //
    // Cast a ray from the camera to determine where
    // the point guided weapon's target is.
    //

    // get the camera
    HOBJECT hCamera;
    hCamera = g_pPlayerMgr->GetCamera();

    // determine the start point of the segment
    LTVector vStartPos;
    g_pLTClient->GetObjectPos( hCamera, &vStartPos );

    // determine the orientation of the segment
    LTRotation rRot;
    g_pLTClient->GetObjectRotation( hCamera, &rRot );

    // determine the direction of the segment
    LTVector vForward;
    vForward = rRot.Forward();

    // scale the direction to get the distance we're going to check
    LTVector vDistance;
    VEC_MULSCALAR( vDistance, vForward, CLIENTWEAPONDISC_PROBE_LENGTH );

    // determine the end point of the segment
    LTVector vEndPos;
    VEC_ADD( vEndPos, vStartPos, vDistance );

    // setup the intersect segment
    IntersectInfo iInfo;
    IntersectQuery qInfo;
    qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;

    // DON'T collide with these objects
    HOBJECT hFilterList[] = {
        g_pLTClient->GetClientObject()  // the player
        , g_pPlayerMgr->GetMoveMgr()->GetObject()  // the player
        , LTNULL
    };

    // callback function when we hit something
    // ObjListFilterFn: just filter out objects specified in above list,
    // otherwise register a hit
    qInfo.m_FilterFn  = ObjListFilterFn;
    qInfo.m_pUserData = hFilterList;

    // end points
    qInfo.m_From = vStartPos;
    qInfo.m_To = vEndPos;

    // do the intersect segment
    LTBOOL bResult;
    bResult = g_pLTClient->IntersectSegment( &qInfo, &iInfo );

    // if we hit something, set the point
    if ( bResult )
    {
        *pvTargetPoint = iInfo.m_Point;
    }

    return ( LTTRUE == bResult );
}
示例#19
0
bool CTracerFX::Init(const FX_BASEDATA *pBaseData, const CBaseFXProps *pProps)
{
	//track our performance
	CTimedSystemBlock TimingBlock(g_tsClientFXTracer);

	//cleanup any old data
	Term();

	// Perform base class initialisation
	if( !CBaseFX::Init(pBaseData, pProps))
		return false;

	//determine our starting position and orientation
	LTVector vPos;
	LTRotation rRot;

	GetCurrentTransform(0.0f, vPos, rRot);	
	m_vStartPos = vPos;

	//determine what target position we want to use
	LTVector vTargetPos;

	//if we are using target data, just get the transform from this
	if(GetProps()->m_bUseTargetPos && pBaseData->m_bUseTargetData)
	{
		LTRigidTransform tTargetOffset(pBaseData->m_vTargetOffset, LTRotation::GetIdentity());
		LTRigidTransform tWS = GetWorldSpaceTransform(NULL, pBaseData->m_hTargetObject, INVALID_MODEL_NODE, INVALID_MODEL_SOCKET, tTargetOffset);

		LTVector vToTarget = tWS.m_vPos - vPos;
		m_fRayLength	= vToTarget.Mag();
		m_vDirection	= vToTarget / m_fRayLength;
		vTargetPos		= tWS.m_vPos;
	}
	else
	{
		//determine the end point where we want to stop testing
		m_vDirection	= rRot.Forward();
		m_fRayLength	= GetProps()->m_fMaxDistance;
		vTargetPos		= vPos + m_vDirection * m_fRayLength;
	}

	//handle intersection if we need to
	if(GetProps()->m_bBlockedByGeometry)
	{
		//we need to perform a ray cast and determine if we actually hit anything in the world. If not,
		//we just want to use the maximum tracer length
		IntersectQuery	iQuery;
		IntersectInfo	iInfo;

		iQuery.m_Flags		= INTERSECT_HPOLY | INTERSECT_OBJECTS | IGNORE_NONSOLID;
		iQuery.m_FilterFn	= TracerListFilterFn;
		iQuery.m_pUserData	= NULL;
		iQuery.m_From		= m_vStartPos;
		iQuery.m_To			= vTargetPos;

		//now find the point of intersection
		if( g_pLTClient->IntersectSegment( iQuery, &iInfo ) )
		{
			//we hit something, so use that as our ending position
			m_fRayLength = (iInfo.m_Point - m_vStartPos).Mag();
		}
	}

	//now determine our starting position (this is zero unless we start emitted, in which case
	//it is the length of the tracer)
	if(GetProps()->m_bStartEmitted)
	{
		//determine the length of this tracer
		m_fRayPosition = GetTracerLength();
	}
	
	// Combine the direction we would like to face with our parents rotation...
	ObjectCreateStruct ocs;
	
	//create a custom render object with the associated material
	ocs.m_Pos				= vPos;
	ocs.m_Rotation			= rRot;
	ocs.m_ObjectType		= OT_CUSTOMRENDER;
	
	if(!GetProps()->m_bSolid)
		ocs.m_Flags2 |= FLAG2_FORCETRANSLUCENT;

	if(!GetProps()->m_bTranslucentLight)
		ocs.m_Flags |= FLAG_NOLIGHT;
	
	m_hObject = g_pLTClient->CreateObject( &ocs );
	if( !m_hObject )
		return false;

	//setup our rendering layer
	if(GetProps()->m_bPlayerView)
		g_pLTClient->GetRenderer()->SetObjectDepthBiasTableIndex(m_hObject, eRenderLayer_Player);

	//setup the callback on the object so that it will render us
	g_pLTClient->GetCustomRender()->SetRenderingSpace(m_hObject, eRenderSpace_World);
	g_pLTClient->GetCustomRender()->SetRenderCallback(m_hObject, CustomRenderCallback);
	g_pLTClient->GetCustomRender()->SetCallbackUserData(m_hObject, this);

	//load up the material for this particle system, and assign it to the object
	HMATERIAL hMaterial = g_pLTClient->GetRenderer()->CreateMaterialInstance(GetProps()->m_pszMaterial);
	g_pLTClient->GetCustomRender()->SetMaterial(m_hObject, hMaterial);
	g_pLTClient->GetRenderer()->ReleaseMaterialInstance(hMaterial);

	//we don't setup the visibility for this object yet since when it starts out it is not visible

	//setup the dynamic light object if the user specified a radius
	if(GetProps()->m_fLightRadius > 0.1f)
	{
		ObjectCreateStruct LightOCS;
		LightOCS.m_Pos			= vPos;
		LightOCS.m_Rotation		= rRot;
		LightOCS.m_ObjectType	= OT_LIGHT;

		m_hTracerLight = g_pLTClient->CreateObject( &LightOCS );

		//setup the properties of the light
		g_pLTClient->SetLightRadius(m_hTracerLight, GetProps()->m_fLightRadius);
		g_pLTClient->SetObjectColor(m_hTracerLight, VEC4_EXPAND(GetProps()->m_vLightColor));
		g_pLTClient->SetLightType(m_hTracerLight, eEngineLight_Point);
		g_pLTClient->SetLightDetailSettings(m_hTracerLight, GetProps()->m_eLightLOD, GetProps()->m_eWorldShadowsLOD, GetProps()->m_eObjectShadowsLOD);
	}

	// Success !!
	return true;
}
示例#20
0
//function that handles the custom rendering
void CParticleSystemGroup::RenderParticleSystem(ILTCustomRenderCallback* pInterface, const LTRigidTransform& tCamera)
{
	//track our performance
	CTimedSystemBlock TimingBlock(g_tsClientFXParticles);

	//setup our vertex declaration
	if(pInterface->SetVertexDeclaration(g_ClientFXVertexDecl.GetTexTangentSpaceDecl()) != LT_OK)
		return;

	//bind a quad index stream
	if(pInterface->BindQuadIndexStream() != LT_OK)
		return;

	//set the fact that we were visible
	*m_pVisibleFlag = true;

	//now determine the largest number of particles that we can render at any time
	uint32 nMaxParticlesPerBatch = QUAD_RENDER_INDEX_STREAM_SIZE / 6;
	nMaxParticlesPerBatch = LTMIN(nMaxParticlesPerBatch, DYNAMIC_RENDER_VERTEX_STREAM_SIZE / (sizeof(STexTangentSpaceVert) * 4));

	//determine the screen orientation
	LTRotation rCamera = tCamera.m_rRot;

	if (m_pProps->m_bObjectSpace)
	{
		LTRotation rObjectRotation;
		g_pLTClient->GetObjectRotation(m_hCustomRender, &rObjectRotation);
		rCamera = rObjectRotation.Conjugate() * rCamera;
	}

	LTVector vUp = rCamera.Up();
	LTVector vRight = rCamera.Right();

	//create some vectors to offset to each corner (avoids adding for displacement in the inner loop)
	//Each one can just be scaled by the size of the particle to get the final offset
	static const float kfHalfRoot2 = 0.5f * MATH_SQRT2;

	//premultiplied versions of up and right scaled by half the square root of two
	LTVector vUpHalfRoot2 = vUp * kfHalfRoot2;
	LTVector vRightHalfRoot2 = vRight * kfHalfRoot2;

	//precalculate the diagonals for non-rotating particles since these are constant
	LTVector vDiagonals[4];
	vDiagonals[0] =  vUpHalfRoot2 - vRightHalfRoot2; 
	vDiagonals[1] =  vUpHalfRoot2 + vRightHalfRoot2; 
	vDiagonals[2] = -vUpHalfRoot2 + vRightHalfRoot2; 
	vDiagonals[3] = -vUpHalfRoot2 - vRightHalfRoot2; 

	uint32 nNumParticlesLeft = m_Particles.GetNumParticles();

	//precalculate some data for the basis space of the particles
	LTVector	vNormal		= -rCamera.Forward();
	LTVector	vTangent	= vRight;
	LTVector	vBinormal	= -vUp;

	//the U scale for particle images
	float		fUImageWidth = 1.0f / (float)m_pProps->m_nNumImages;

	//variables used within the inner loop
	float		fSize;
	uint32		nColor;

	//now run through all the particles and render
	CParticleIterator itParticles = m_Particles.GetIterator();
	while(nNumParticlesLeft > 0)
	{
		//determine our batch size
		uint32 nBatchSize = LTMIN(nNumParticlesLeft, nMaxParticlesPerBatch);

		//lock down our buffer for rendering
		SDynamicVertexBufferLockRequest LockRequest;
		if(pInterface->LockDynamicVertexBuffer(nBatchSize * 4, LockRequest) != LT_OK)
			return;

		//fill in a batch of particles
		STexTangentSpaceVert* pCurrOut = (STexTangentSpaceVert*)LockRequest.m_pData;

		if(m_pProps->m_bRotate)
		{
			//we need to render the particles rotated
			for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++)
			{
				//sanity check
				LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch");

				//get the particle from the iterator
				SParticle* pParticle = (SParticle*)itParticles.GetParticle();

				GetParticleSizeAndColor(pParticle, nColor, fSize);

				//determine the sin and cosine of this particle angle
				float fAngle = pParticle->m_fAngle;
				float fSinAngle = LTSin(fAngle);
				float fCosAngle = LTCos(fAngle);

				LTVector vRotRight = (vRightHalfRoot2 * fCosAngle + vUpHalfRoot2 * fSinAngle) * fSize;
				LTVector vRotUp    = vNormal.Cross(vRotRight);

				LTVector vRotTangent  = vTangent * fCosAngle + vBinormal * fSinAngle;
				LTVector vRotBinormal = vTangent * fSinAngle + vBinormal * fCosAngle;

				SetupParticle(	pCurrOut, 
					pParticle->m_Pos + vRotUp - vRotRight,
					pParticle->m_Pos + vRotUp + vRotRight,
					pParticle->m_Pos - vRotUp + vRotRight,
					pParticle->m_Pos - vRotUp - vRotRight,
					nColor, vNormal, vRotTangent, vRotBinormal, 
					pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth);

				//move onto the next set of particles
				pCurrOut += 4;

				//move onto the next particle for processing
				itParticles.Next();
			}
		}
		else if (m_pProps->m_bStreak)
		{
			//the particles are non-rotated but streaked along their velocity
			for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++)
			{
				//sanity check
				LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch");

				//get the particle from the iterator
				SParticle* pParticle = (SParticle*)itParticles.GetParticle();

				GetParticleSizeAndColor(pParticle, nColor, fSize);

				//in order to render the streak, we determine a line that passes through
				//the particle and runs in the direction of the velocity of the particle

				//we need to project the velocity onto the screen
				LTVector2 vScreen;
				vScreen.x = -(pParticle->m_Velocity.Dot(vRight));
				vScreen.y = -(pParticle->m_Velocity.Dot(vUp));

				//we know that the up and right vectors are normalized, so we can save some work by
				//just doing a 2d normalization
				float fMag = vScreen.Mag();
				if(fMag == 0.0f)
					vScreen.Init(fSize, 0.0f);
				else
					vScreen *= fSize / fMag;

				//determine our actual screen space velocity
				LTVector vScreenRight = vUp * vScreen.y + vRight * vScreen.x;
				LTVector vScreenUp = vUp * -vScreen.x + vRight * vScreen.y;

				//and now compute the endpoint of the streak
				LTVector vEndPos = pParticle->m_Pos - pParticle->m_Velocity * m_pProps->m_fStreakScale;

				SetupParticle(	pCurrOut, 
					pParticle->m_Pos	- vScreenRight - vScreenUp,
					vEndPos				+ vScreenRight - vScreenUp,
					vEndPos				+ vScreenRight + vScreenUp,
					pParticle->m_Pos	- vScreenRight + vScreenUp,
					nColor, vNormal, vScreenRight, vScreenUp, 
					pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth);

				//move onto the next set of particles
				pCurrOut += 4;

				//move onto the next particle for processing
				itParticles.Next();
			}
		}
		else
		{
			//the particles are non-rotated
			for(uint32 nBatchParticle = 0; nBatchParticle < nBatchSize; nBatchParticle++)
			{
				//sanity check
				LTASSERT(!itParticles.IsDone(), "Error: Particle count and iterator mismatch");

				//get the particle from the iterator
				SParticle* pParticle = (SParticle*)itParticles.GetParticle();

				GetParticleSizeAndColor(pParticle, nColor, fSize);

				SetupParticle(	pCurrOut, 
					pParticle->m_Pos + vDiagonals[0] * fSize,
					pParticle->m_Pos + vDiagonals[1] * fSize,
					pParticle->m_Pos + vDiagonals[2] * fSize,
					pParticle->m_Pos + vDiagonals[3] * fSize,
					nColor, vNormal, vTangent, vBinormal, 
					pParticle->m_nUserData & PARTICLE_IMAGE_MASK, fUImageWidth);

				//move onto the next set of particles
				pCurrOut += 4;

				//move onto the next particle for processing
				itParticles.Next();
			}
		}

		//unlock and render the batch
		pInterface->UnlockAndBindDynamicVertexBuffer(LockRequest);
		pInterface->RenderIndexed(	eCustomRenderPrimType_TriangleList, 
			0, nBatchSize * 6, LockRequest.m_nStartIndex, 
			0, nBatchSize * 4);

		nNumParticlesLeft -= nBatchSize;
	}
}
示例#21
0
LTBOOL CProjectileFX::CreateObject(ILTClient* pClientDE)
{
    if (!CSpecialFX::CreateObject(pClientDE) || !m_hServerObject) return LTFALSE;

	CGameSettings* pSettings = g_pInterfaceMgr->GetSettings();
    if (!pSettings) return LTFALSE;

    uint8 nDetailLevel = pSettings->SpecialFXSetting();

    LTVector vPos;
    LTRotation rRot;
	g_pLTClient->GetObjectPos(m_hServerObject, &vPos);
	g_pLTClient->GetObjectRotation(m_hServerObject, &rRot);

	//m_pClientDE->CPrint("Client start pos (%.2f, %.2f, %.2f)", vPos.x, vPos.y, vPos.z);
	//m_fStartTime = m_pClientDE->GetTime();

	if (nDetailLevel != RS_LOW)
	{
		if (m_nFX & PFX_SMOKETRAIL)
		{
			CreateSmokeTrail(vPos, rRot);
		}

		if (m_nFX & PFX_LIGHT)
		{
			CreateLight(vPos, rRot);
		}
	}

	if (m_nFX & PFX_FLARE)
	{
		CreateFlare(vPos, rRot);
	}

	if (m_nFX & PFX_FLYSOUND)
	{
		CreateFlyingSound(vPos, rRot);
	}


	// Do client-side projectiles in multiplayer games...

	if ( g_pClientMultiplayerMgr->IsConnectedToRemoteServer( ))
	{
		// Set the velocity of the "server" object if it is really just a local
		// object...

		if (m_bLocal)
		{
			VEC_COPY(m_vFirePos, vPos);

			m_fStartTime = m_pClientDE->GetTime();

            LTVector vVel, vF;
			vF = rRot.Forward();

			m_vPath = vF;

			// Special case of adjusting the projectile speed...

            LTFLOAT fVel = (LTFLOAT) m_pProjectileFX->nVelocity;
			if (m_bAltFire)
			{
                fVel = (LTFLOAT) m_pProjectileFX->nAltVelocity;
			}

            LTFLOAT fMultiplier = 1.0f;
            if (m_pClientDE->GetSConValueFloat("MissileSpeed", fMultiplier) != LT_NOTFOUND)
			{
				fVel *= fMultiplier;
			}

			vVel = vF * fVel;
			g_pPhysicsLT->SetVelocity(m_hServerObject, &vVel);
		}
	}

    return LTTRUE;
}
示例#22
0
void DebugLineSystem::AddOrientation( const LTVector& vCenter, const LTRotation& rRot, float fLength, uint8 nAlpha)
{
	AddArrow(vCenter, vCenter + rRot.Right() * fLength, Color::Red, nAlpha);
	AddArrow(vCenter, vCenter + rRot.Up() * fLength, Color::Green, nAlpha);
	AddArrow(vCenter, vCenter + rRot.Forward() * fLength, Color::Blue, nAlpha);
}
示例#23
0
void CLTMessage_Write::WriteYRotation(CPacket_Write &cPacket, const LTRotation &cRotation)
{
	LTVector forward = cRotation.Forward();
	float fAngle = (float)atan2(forward.x, forward.z);
	cPacket.Writeint8((int8)(fAngle * (127.0f / MATH_PI)));
}
示例#24
0
void CFlashLightPlayer::GetLightPositions(LTVector& vStartPos, LTVector& vEndPos, LTVector& vUOffset, LTVector& vROffset)
{
	vStartPos.Init();
	vEndPos.Init();
	vUOffset.Init();
	vROffset.Init();

	CMoveMgr* pMoveMgr = g_pPlayerMgr->GetMoveMgr();
	if (!pMoveMgr) return;

	LTRotation rRot;

	if (pMoveMgr->GetVehicleMgr()->IsVehiclePhysics())
	{
		if (g_pPlayerMgr->IsFirstPerson())
		{
			pMoveMgr->GetVehicleMgr()->GetVehicleLightPosRot(vStartPos, rRot);
		}
		else // 3rd person vehicle
		{
			// Get light pos on 3rd-person vehicle...

			HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject();
			if (hPlayerObj)
			{
				g_pLTClient->GetObjectRotation(hPlayerObj, &rRot);
				g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos);
			}
		}
	}
	else if (g_pPlayerMgr->IsFirstPerson())
	{
		HOBJECT hCamera = g_pPlayerMgr->GetCamera();
		if (!hCamera) return;

		g_pLTClient->GetObjectRotation(hCamera, &rRot);
		g_pLTClient->GetObjectPos(hCamera, &vStartPos);
	}
	else // 3rd person
	{
		// Get light pos from 3rd-person model...

		HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject();
		if (hPlayerObj)
		{
			// g_pLTClient->GetObjectRotation(hPlayerObj, &rRot);
			// g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos);

			HMODELSOCKET hSocket;
			if ( LT_OK == g_pModelLT->GetSocket(hPlayerObj, "LeftHand", hSocket) )
			{
				LTransform tf;

				if ( LT_OK == g_pModelLT->GetSocketTransform(hPlayerObj, hSocket, tf, LTTRUE) )
				{
					vStartPos = tf.m_Pos;
					rRot = tf.m_Rot;
				}
			}
		}
	}

	vEndPos = vStartPos + (rRot.Forward() * g_cvarFLLightOffsetForward.GetFloat());

  	if (g_pPlayerMgr->IsFirstPerson())
  	{
  		vROffset = (rRot.Right() * g_cvarFLLightOffsetRight.GetFloat());
  		vUOffset = (rRot.Up() * g_cvarFLLightOffsetUp.GetFloat());

		// Update the Start/End position to addjust for any offset...

		vEndPos += vROffset;
		vEndPos += vUOffset;

		vStartPos += vROffset;
		vStartPos += vUOffset;
  	}
}