Esempio n. 1
0
LTBOOL CAIMovementHuman::Update()
{
    LTFLOAT fTimeDelta = g_pLTServer->GetFrameTime();

	switch ( m_eState )
	{
		case eStateUnset:
		{

		}
		break;

		case eStateSet:
		{
			// Set our speed based on our movement type

			if ( GetAI()->GetAnimationContext()->IsPropSet(aniWalk) )
			{
				GetAI()->Walk();
			}
			else if ( GetAI()->GetAnimationContext()->IsPropSet(aniRun) )
			{
				GetAI()->Run();
			}
			else if ( GetAI()->GetAnimationContext()->IsPropSet(aniSwim) )
			{
				GetAI()->Swim();
			}
			else
			{
				// We're not moving yet...

				GetAI()->Stop();
			}

			// Find our unit movement vector

			LTVector vMove = m_vDest - GetAI()->GetPosition();

			if ( !m_bUnderwater )
			{
				vMove.y = 0.0f;
			}

			// See if we'll overshoot our

			LTFLOAT fRemainingDist = vMove.Mag();
			LTFLOAT fMoveDist;

			fMoveDist = GetAI()->GetSpeed()*fTimeDelta;

			// If we'd overshoot our destination, just move us there

			if ( fRemainingDist < fMoveDist )
			{
				fMoveDist = fRemainingDist;
				m_eState = eStateDone;
			}

			// Scale based on our movement distance

			vMove.Norm();
			vMove *= fMoveDist;

			// Calculate our new position

			LTVector vNewPos = GetAI()->GetPosition() + vMove;

			// Move us - this is an expensive call

			GetAI()->Move(vNewPos);

			// Face us in the right direction

			GetAI()->FacePos(vNewPos);
		}
		break;

		case eStateDone:
		{

		}
		break;
	}

	return LTTRUE;
}
Esempio n. 2
0
LTBOOL CAIMovementHelicopter::Update()
{
    LTFLOAT fTimeDelta = g_pLTServer->GetFrameTime();

	switch ( m_eState )
	{
		case eStateUnset:
		{

		}
		break;

		case eStateSet:
		{
			// Find our unit movement vector

			LTVector vMove = m_vDest - GetAI()->GetPosition();
//			vMove.y = 0.0f;

			// See if we'll overshoot our

			LTFLOAT fRemainingDist = vMove.Mag();
			LTFLOAT fMoveDist;

			fMoveDist = GetAI()->GetSpeed()*fTimeDelta;

			vMove.Norm();

			LTBOOL bCrossed = LTFALSE;

			// See if we crossed the dest plane

			if ( (vMove.Dot(m_vDestDir) < 0.0f) )
			{
				bCrossed = LTTRUE;
			}

			// If we'd overshoot our destination, just move us there

			if ( (fRemainingDist < fMoveDist) || bCrossed )
			{
				fMoveDist = fRemainingDist;
				m_eState = eStateDone;
			}

			// Scale based on our movement distance

			vMove *= fMoveDist;

			// Calculate our new position

			LTVector vNewPos = GetAI()->GetPosition() + vMove;

			// Move us - this is an expensive call

//			GetAI()->Move(vNewPos);

			// Face us in the right direction

			GetAI()->FacePos(vNewPos);
		}
		break;

		case eStateDone:
		{
		}
		break;
	}

	return LTTRUE;
}
Esempio n. 3
0
void CAIBrain::GetDodgeStatus(DodgeStatus* peDodgeStatus, Direction* peDirection, DodgeAction* peDodgeAction, uint32* pdwNode)
{
	if ( !GetAI()->HasTarget() || !GetAI()->HasLastVolume() ) 
	{
		*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk;
		return;
	}

	if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeVector )
	{
		m_fDodgeStatusCheckTimeVector = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckTime);

		if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckChance) )
		{
			if ( GetAI()->GetTarget()->IsVisiblePartially() )
			{
				CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(GetAI()->GetTarget()->GetObject());
				if ( pCharacter->HasDangerousWeapon() )
				{
					LTRotation rRot;
					LTVector vNull, vForward;
					g_pLTServer->GetObjectRotation(GetAI()->GetTarget()->GetObject(), &rRot);
					g_pMathLT->GetRotationVectors(rRot, vNull, vNull, vForward);

					LTVector vDir;
					vDir = GetAI()->GetPosition() - GetAI()->GetTarget()->GetPosition();
					vDir.y = 0;
					vDir.Norm();

					// TODO: bute this

					const static LTFLOAT fThreshhold = 0.95f;

					if ( (vDir.Dot(vForward) > fThreshhold) && (GetAI()->GetForwardVector().Dot(vForward) < -fThreshhold) )
					{
						LTFLOAT fCheckDistance;

						LTFLOAT fRandom = GetRandom(0.0f, 1.0f);

						if ( fRandom > m_pBrain->fDodgeVectorCoverChance )
						{
							if ( fRandom > (m_pBrain->fDodgeVectorCoverChance + m_pBrain->fDodgeVectorRollChance) )
							{
								*peDodgeAction = eDodgeActionShuffle;
								fCheckDistance = 109.0f;
							}
							else
							{
								*peDodgeAction = eDodgeActionRoll;
								fCheckDistance = 140.0f;
							}

							// MAKE SURE WE WON'T DODGE OUT OF THE VOLUME 
							if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()+GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) )
							{
								*peDirection = eDirectionRight;
								*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector;
								return;
							}
							else if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()-GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) )
							{
								*peDirection = eDirectionLeft;
								*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector;
								return;
							}
							else
							{
								*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk;
								return;
							}
						}
						else
						{
							CAINode* pNode = g_pAINodeMgr->FindNearestCoverFromThreat(GetAI()->GetPosition(), GetAI()->GetTarget()->GetObject());

							if ( pNode )
							{
								*peDodgeAction = eDodgeActionCover;
								*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector;
								*pdwNode = pNode->GetID();
							}
							else
							{
								*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk;
							}
							return;
						}
					}
				}
			}
		}
	}

	if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeProjectile )
	{
		m_fDodgeStatusCheckTimeProjectile = g_pLTServer->GetTime() + RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckTime);

		if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckChance) )
		{
			CGrenade* pGrenade;
			if ( FindGrenadeDangerPosition(GetAI()->GetPosition(), 40000.0f, &m_vDodgeProjectilePosition, &pGrenade) )
			{
				FREE_HSTRING(m_hstrDodgeProjectileName);
				// $STRING
				m_hstrDodgeProjectileName = g_pLTServer->CreateString(g_pLTServer->GetObjectName(pGrenade->m_hObject));

				*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusProjectile;
				*peDodgeAction = eDodgeActionFlee;

				return;
			}
		}
	}

	*peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk;
	return;
}
Esempio n. 4
0
void CGrenade::HandleImpact(HOBJECT hObj)
{
	if (!g_vtGrenadeDampenPercent.IsInitted())
	{
        g_vtGrenadeDampenPercent.Init(g_pLTServer, "GrenadeDampenPercent", LTNULL, DEFAULT_GRENADE_DAMPEN_PERCENT);
	}

	if (!g_vtGrenadeMinVelMag.IsInitted())
	{
        g_vtGrenadeMinVelMag.Init(g_pLTServer, "GrenadeMinVelMag", LTNULL, DEFAULT_GRENADE_MIN_VELOCITY);
	}


    LTVector vVel;
    g_pLTServer->GetVelocity(m_hObject, &vVel);


	// See if we are impacting on liquid...

    LTBOOL bEnteringLiquid = LTFALSE;
    uint16 code;
    if (g_pLTServer->GetContainerCode(hObj, &code))
	{
		if (IsLiquid((ContainerCode)code))
		{
            bEnteringLiquid = LTTRUE;
		}
	}


	CollisionInfo info;
    g_pLTServer->GetLastCollision(&info);


	// Do the bounce, if the object we hit isn't liquid...

	if (!bEnteringLiquid)
	{
		vVel += (info.m_vStopVel * 2.0f);
	}


	// Dampen the grenade's new velocity based on the surface type...

    LTFLOAT fDampenPercent = g_vtGrenadeDampenPercent.GetFloat();

	m_eLastHitSurface = GetSurfaceType(info);
	SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface);
	if (pSurf)
	{
		// Play a bounce sound (based on the surface type) if one isn't
		// already playing...

		if ( ShouldPlayBounceSound(pSurf) )
		{
			// Only play one sound at a time...

			if (m_hBounceSnd)
			{
                g_pLTServer->KillSound(m_hBounceSnd);
                m_hBounceSnd = LTNULL;
			}

            uint32 dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME;

			int nVolume	= IsLiquid(m_eContainerCode) ? 50 : 100;

            LTVector vPos;
            g_pLTServer->GetObjectPos(m_hObject, &vPos);

			m_hBounceSnd = g_pServerSoundMgr->PlaySoundFromPos(vPos, (char*)GetBounceSound(pSurf),
				pSurf->fGrenadeSndRadius, SOUNDPRIORITY_MISC_MEDIUM, dwFlags, nVolume);
		}

		fDampenPercent = (1.0f - pSurf->fHardness);
	}

	fDampenPercent = fDampenPercent > 1.0f ? 1.0f : (fDampenPercent < 0.0f ? 0.0f : fDampenPercent);

	vVel *= (1.0f - fDampenPercent);


	// See if we should come to a rest...

    LTVector vTest = vVel;
	vTest.y = 0.0f;

	if (vTest.Mag() < g_vtGrenadeMinVelMag.GetFloat())
	{
		// If we're on the ground (or an object), stop movement...

		CollisionInfo standingInfo;
        g_pLTServer->GetStandingOn(m_hObject, &standingInfo);

		CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info;

		if (pInfo->m_hObject)
		{
			// Don't stop on walls...

			if (pInfo->m_Plane.m_Normal.y > 0.75f)
			{
				vVel.Init();

				// Turn off gravity, solid, and touch notify....

                uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject);
				dwFlags &= ~(FLAG_GRAVITY | FLAG_TOUCH_NOTIFY | FLAG_SOLID);

                g_pLTServer->SetObjectFlags(m_hObject, dwFlags);

				// Rotate to rest...

				RotateToRest();
			}
		}
	}


	// Reset rotation velocities due to the bounce...

	ResetRotationVel(&vVel, pSurf);


	// We need to subtact this out because the engine will add it back in,
	// kind of a kludge but necessary...

	vVel -= info.m_vStopVel;


    g_pLTServer->SetVelocity(m_hObject, &vVel);

	m_cBounces++;
}
Esempio n. 5
0
void Prop::HandleAttachmentImpact( CAttachmentPosition *pAttachPos, const LTVector& vDir )
{
	if( !pAttachPos )
		return;

	// TODO: Init these somewhere else
	if( !s_vtAttachmentMinVel.IsInitted() )
	{
		s_vtAttachmentMinVel.Init( g_pLTServer, "AttachmentMinVel", LTNULL, DEFAULT_ATTACH_MIN_VEL );
	}
	if( !s_vtAttachmentMaxVel.IsInitted() )
	{
		s_vtAttachmentMaxVel.Init( g_pLTServer, "AttachmentMaxVel", LTNULL, DEFAULT_ATTACH_MAX_VEL );
	}
	if( !s_vtAttachmentMinYAdd.IsInitted() )
	{
		s_vtAttachmentMinYAdd.Init( g_pLTServer, "AttachmentMinYAdd", LTNULL, DEFAULT_ATTACH_MIN_YADD );
	}
	if( !s_vtAttachmentMaxYAdd.IsInitted() )
	{
		s_vtAttachmentMaxYAdd.Init( g_pLTServer, "AttachmentMaxYAdd", LTNULL, DEFAULT_ATTACH_MAX_YADD );
	}
	if( !s_vtAttachmentFadeDelay.IsInitted() )
	{
		s_vtAttachmentFadeDelay.Init( g_pLTServer, "AttachmentFadeDelay", LTNULL, DEFAULT_ATTACH_FADE_DELAY );
	}
	if( !s_vtAttachmentFadeDuration.IsInitted() )
	{
		s_vtAttachmentFadeDuration.Init( g_pLTServer, "AttachmentFadeDuration", LTNULL, DEFAULT_ATTACH_FADE_DURATION );
	}
	
	// Set the owner of the attachment...
	
	m_hAttachmentOwner = pAttachPos->GetAttachment()->GetObject();

	uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY;
	g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, dwFlags, dwFlags | FLAG_GOTHRUWORLD );	

	// Play the world animation so the prop is flat when it comes to rest...

	HMODELANIM	hWorldAnim = INVALID_MODEL_ANIM;
	if( (g_pModelLT->GetAnimIndex( m_hObject, "WORLD", hWorldAnim ) == LT_OK) && (hWorldAnim != INVALID_MODEL_ANIM) )
	{
		g_pModelLT->SetLooping( m_hObject, MAIN_TRACKER, true );
		g_pModelLT->SetCurAnim( m_hObject, MAIN_TRACKER, hWorldAnim );
	}
	

	LTVector vVel = vDir;
	vVel.Normalize();
	vVel *= GetRandom( s_vtAttachmentMinVel.GetFloat(), s_vtAttachmentMaxVel.GetFloat() );
	vVel.y += GetRandom( s_vtAttachmentMinYAdd.GetFloat(), s_vtAttachmentMaxYAdd.GetFloat() );
	
	g_pPhysicsLT->SetVelocity( m_hObject, &vVel );

	// Don't play the touch animation and sounds when recieving a touch notify...

	m_bTouchable = LTFALSE;
	m_bAttachmentShotOff = LTTRUE;

	g_pLTServer->SetBlockingPriority( m_hObject, 0 );
	g_pPhysicsLT->SetForceIgnoreLimit( m_hObject, 0.0f );

	// Give it some rotation...

	float fVal	= MATH_PI;
    float fVal2	= MATH_CIRCLE;
	m_fPitchVel	= GetRandom( -fVal2, fVal2 );
	m_fYawVel	= GetRandom( -fVal2, fVal2 );
	m_fRollVel	= GetRandom( -fVal2, fVal2 );

	m_bRotating	= true;

	SetNextUpdate(UPDATE_NEXT_FRAME);
}
Esempio n. 6
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;
}
Esempio n. 7
0
//*
// ----------------------------------------------------------------------- //
// Returns the vector that the physics would have the object move by.
// ----------------------------------------------------------------------- //
void CalcMotion
(
    MotionInfo* pInfo,
    LTObject*   pObj,           //the object
    LTVector&   dr,             //displacement
    LTVector&   v,              //velocity
    LTVector&   a,              //acceleration
    const bool  bApplyGravity,
    const float dt              //time step
)
{
	LTVector velocityDelta, accelDelta;
	LTVector q, slopeVel, slopeAccel, vel;
	const LTVector *n;
	LTVector objectNormal, vTemp, vTemp2;

	float fExp;
	float timeIntegral;
	float velocityMagSqr, accelMagSqr;
	LTBOOL bFriction;

	bFriction = LTFALSE;
	timeIntegral = dt * dt * 0.5f;	
	velocityMagSqr = v.MagSqr();
	accelMagSqr = a.MagSqr();

	// [KLS - 3/12/02] - Added support for per-object force override...

	LTVector vForce = pObj->GetGlobalForceOverride();
	
	// If the global force override is zero, use the MotionInfo force...

	if (LTVector(0.0, 0.0, 0.0) == vForce)
	{
		vForce = pInfo->m_Force;
	}

	/* 
	// Debug variables
	LTVector vOldAccel, vOldVel, vOldPos;
	vOldAccel = a;
	vOldVel = v;
	vOldPos = pObj->GetPos();
	//*/

	// Stop objects that are moving very slowly...
	if(velocityMagSqr < 0.1f )
	{
		v.Init();
		velocityMagSqr = 0;
	}

	if( accelMagSqr < 0.1f )
	{
		a.Init();
		accelMagSqr = 0;
	}

	// Zero out the displacement to start with.
	dr.Init();

	// Update objects affected by gravity...
	if(bApplyGravity)
	{
		// Add friction to objects standing on something...
		if(pObj->m_pStandingOn)
		{
			// Try to disable their physics.
			if( velocityMagSqr < 0.1f && accelMagSqr < 0.1f )
			{
				pObj->m_Velocity.Init();
				pObj->m_Acceleration.Init();
				pObj->m_InternalFlags &= ~IFLAG_APPLYPHYSICS;
				return;
			}
			else
			{
				// Check if object on world geometry...
				if( pObj->m_pNodeStandingOn )
				{
					// Calculate vector parallel to plane...
					n = &pObj->m_pNodeStandingOn->GetPlane()->m_Normal;
				}
				else
				{
					// Object standing on another object, so assume opposite to gravity...
					n = &objectNormal;
					objectNormal = -pInfo->m_UnitForce;
				}

				// Calculate the acceleration including the force
				LTVector vAccelWithForce = a + vForce;

				// If we're on a slope that's at enough of an angle, allow it to slide
				LTVector vForceDir = vForce;
				vForceDir.Norm();
				if (vForceDir.Dot(*n) > pInfo->m_SlideRatio)
				{
					float fAccelMag = vAccelWithForce.Mag();
					a = vAccelWithForce - *n * n->Dot(vAccelWithForce);

					// Don't allow it to accelerate up the slope..
					float fAccelDotForce = a.Dot(vForceDir);
					if (fAccelDotForce < 0.0f)
					{
						a -= vForceDir * fAccelDotForce;
					}
					
					a.Norm(fAccelMag);

					// dsi_ConsolePrint("Steep");
				}				
				else
				{
					// Figure out what our new velocity would be if only the force was used (i.e. are they jumping?)
					LTVector vNewVel = v + vForce * dt;
					// If we're going to be moving away from the plane, use the full force
					if (vNewVel.Dot(*n) > 0.01f)
					{
						a = vAccelWithForce;
						// dsi_ConsolePrint("Jump");
					}
					// If the acceleration without the force isn't moving into the surface, project it there
					else if (a.Dot(*n) > 0.01f)
					{
						float fAccelMag = a.Mag();
						a -= *n * (n->Dot(a) + 1.0f);
						a.Norm(fAccelMag);

						bFriction = LTTRUE;

						// dsi_ConsolePrint("Downhill");
					}
					else
					{
						bFriction = LTTRUE;

						// dsi_ConsolePrint("Walk");
					}
				}
			}
		}
		// Otherwise just apply gravity
		else
		{
			a += vForce;
			// dsi_ConsolePrint("Fall");
		}
	}
	// If there's no gravity and they aren't moving, then disable their physics
	else if( velocityMagSqr < 0.1f && accelMagSqr < 0.1f )
	{
		pObj->m_Velocity.Init();
		pObj->m_Acceleration.Init();
		pObj->m_InternalFlags &= ~IFLAG_APPLYPHYSICS;
		return;
	}

	// If friction
	// new velocity is given by:		v = ( a / k ) + ( v_0 - a / k ) * exp( -k * t )
	// new position is given by:		x = x_0 + ( a / k ) * t + ( k * v_0 - a ) * ( 1 - exp( -k * t )) / k^2
	if( bFriction && pObj->m_FrictionCoefficient > 0.0f )
	{
		// Velocity...
		fExp = ( float )exp( -pObj->m_FrictionCoefficient * dt );
		vTemp = a / pObj->m_FrictionCoefficient;
		vTemp2 = v - vTemp;
		vTemp2 *= fExp;
		vel = vTemp2 + vTemp;

		// Position delta...
		dr = vTemp * dt;
		vTemp = v * pObj->m_FrictionCoefficient;
		vTemp -= a;
		vTemp *= (( 1.0f - fExp ) / pObj->m_FrictionCoefficient / pObj->m_FrictionCoefficient);
		dr += vTemp;
		pObj->m_Velocity = vel;
		v = pObj->m_Velocity;
	}
	// If no friction
	// new velocity is given by:	v = v_0 + a * t
	// new position is given by:	x = x_0 + v_0 * t + .5 * a * t^2
	else
	{
		// Find the change in velocity...
		velocityDelta = a * dt;

		// Position delta...
		dr = v * dt;

		vTemp = a * (timeIntegral * 0.5f);
		dr += vTemp;

		// Add the final velocity to the new velocity.
		pObj->m_Velocity += velocityDelta;
		v = pObj->m_Velocity;
	}

	/*
	// Show debug information, filtering out the server-side player object
	if(bApplyGravity)
	{
		dsi_ConsolePrint("Old - A:<%7.1f,%7.1f,%7.1f> V:<%7.1f,%7.1f,%7.1f> P:<%7.1f,%7.1f,%7.1f>",
			VEC_EXPAND(vOldAccel), VEC_EXPAND(vOldVel), VEC_EXPAND(vOldPos));

		LTVector vNewAccel, vNewVel, vNewPos;
		vNewAccel = a;
		vNewVel = v;
		vNewPos = vOldPos + dr;

		dsi_ConsolePrint("New   - A:<%7.1f,%7.1f,%7.1f> V:<%7.1f,%7.1f,%7.1f> P:<%7.1f,%7.1f,%7.1f>",
			VEC_EXPAND(vNewAccel), VEC_EXPAND(vNewVel), VEC_EXPAND(vNewPos));
	}
	//*/

	return;
}
Esempio n. 8
0
void CTransitionAggregate::Load( ILTMessage_Read *pMsg, uint32 dwLoadFlags )
{
	if( !pMsg ) return;
	
	LOAD_HOBJECT( m_hObject );

	// The rest is dependent on the load type...

	if( dwLoadFlags != LOAD_TRANSITION ) return;
	
	HOBJECT hTransArea = g_pTransMgr->GetTransitionArea();
	if( !hTransArea ) return;
	
	TransitionArea *pTransArea = (TransitionArea*)g_pLTServer->HandleToObject( hTransArea );
	if( !pTransArea ) return;

	LTransform tfLocal;
	LTransform tfObjectWorld;
	LTVector vVelRel;
	LTransform const& tfTransAreaWorld = pTransArea->GetWorldTransform( );
	LTMatrix mRotation;
	tfTransAreaWorld.m_Rot.ConvertToMatrix( mRotation );

	LOAD_VECTOR( tfLocal.m_Pos );
	LOAD_ROTATION( tfLocal.m_Rot );
	LOAD_VECTOR( vVelRel );
	
	// Calc pos and rot based on offsets and current TransArea...

	tfObjectWorld.m_Pos = tfTransAreaWorld.m_Pos + ( mRotation * tfLocal.m_Pos );
	tfObjectWorld.m_Rot = tfTransAreaWorld.m_Rot * tfLocal.m_Rot;
	LTVector vVel = mRotation * vVelRel;

	if( IsPlayer( m_hObject ))
	{
		// Since the PlayerObj is controlled by the client we need to notify the
		// client of the rotation.  We are only worried about the Yaw since Roll doesn't 
		// matter and Pitch can be preserved on the client.


		CPlayerObj *pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( m_hObject );
		if( !pPlayer ) return;

		
		LTFLOAT		fYaw;
		LTVector	vF = tfObjectWorld.m_Rot.Forward();

		// We don't care about Roll...

		vF.y = 0.0f; 
		vF.Normalize();

		// Yaw = arctan( vF.x / vF.z );
		// atan2 is well defined even for vF.z == 0

		fYaw = (LTFLOAT)atan2( vF.x, vF.z );
		
		// Inform the client of the correct camera/player orientation...

		LTVector vVec( 0.0f, fYaw, 0.0f );
		
		CAutoMessage cMsg;
		cMsg.Writeuint8( MID_PLAYER_ORIENTATION );
		cMsg.Writeuint8( MID_ORIENTATION_YAW );
		cMsg.WriteLTVector( vVec );
		g_pLTServer->SendToClient(cMsg.Read(), pPlayer->GetClient(), MESSAGE_GUARANTEED);
		
	}

	g_pLTServer->SetObjectPos( m_hObject, &tfObjectWorld.m_Pos );
	g_pLTServer->SetObjectRotation( m_hObject, &tfObjectWorld.m_Rot );
	g_pPhysicsLT->SetVelocity( m_hObject, &vVel );
}
Esempio n. 9
0
bool CAISensorPassTarget::NeedToHoldPosition( bool* pbCalledFindPath ) 
{
	// Sanity check.

	if( !pbCalledFindPath )
	{
		return false;	
	}

	// No need to hold position if not targeting a character.

	if( !m_pAI->HasTarget( kTarget_Character ) )
	{
		m_hVerifiedNode = NULL;
		return false;
	}

	// Only check for passing the target if we are within some distance of the target.

	LTVector vTargetPos = m_pAI->GetAIBlackBoard()->GetBBTargetPosition();
	float fDistSqr = vTargetPos.DistSqr( m_pAI->GetPosition() );
	if( fDistSqr > g_pAIDB->GetAIConstantsRecord()->fHoldPositionDistanceSqr )
	{
		m_hVerifiedNode = NULL;
		return false;	
	}

	// Character is outside of the NavMesh.

	ENUM_NMPolyID ePolyTarget = GetTargetNavMeshPoly();
	if( ePolyTarget == kNMPoly_Invalid )
	{
		m_hVerifiedNode = NULL;
		return false;
	}

	// Bail if AI is not going for cover or ambush.

	CAIWMFact factQuery;
	factQuery.SetFactType( kFact_Task );
	factQuery.SetTaskType( kTask_Cover );
	CAIWMFact* pFact = m_pAI->GetAIWorkingMemory()->FindWMFact( factQuery );
	if( !pFact )
	{
		factQuery.SetTaskType( kTask_Ambush );
		pFact = m_pAI->GetAIWorkingMemory()->FindWMFact( factQuery );
	}
	if( !( pFact && ( pFact->GetConfidence( CAIWMFact::kFactMask_TaskType ) == 1.f ) ) )
	{
		m_hVerifiedNode = NULL;
		return false;
	}

	// Bail if AI is scripted to go for cover.

	if( pFact->GetFactFlags() & kFactFlag_Scripted )
	{
		m_hVerifiedNode = NULL;
		return false;
	}

	// We have already determined that we can get to this node without
	// crossing the target's position.

	HOBJECT hNode = pFact->GetTargetObject();
	if( hNode == m_hVerifiedNode )
	{
		// AI is not going anywhere.

		CAIPathNavMesh* pNMPath = m_pAI->GetAINavigationMgr()->GetNMPath();
		if( ( !pNMPath ) ||
			( !m_pAI->GetAINavigationMgr()->IsNavSet() ) ||
			( m_pAI->GetAIBlackBoard()->GetBBDestStatus() != kNav_Set ) )
		{
			return false;
		}

		// Existing path is still valid.  Path does not cross target.

		if( !PathIncludesPoly( *pNMPath, ePolyTarget ) )
		{
			return false;
		}
	}

	// No path exists to node.

	*pbCalledFindPath = true;
	static CAIPathNavMesh NMPath;
	if( !FindPathToNode( hNode, &NMPath ) )
	{
		return false;
	}

	// Path does cross target's position.

	if( PathIncludesPoly( NMPath, ePolyTarget ) )
	{
		AvoidNode( hNode );
		return true;
	}

	// Path does not cross target's position.

	m_hVerifiedNode = hNode;
	return false; 
}
Esempio n. 10
0
void RenderPolyTrail(ILTClient *pClientDE, 
					 CLinkList<TRAIL_SECTION> *pList, 
					 HOBJECT hCamera, 
					 float fTrailWidth,
					 uint8 r,
					 uint8 g,
					 uint8 b,
					 uint8 a,
					 HTEXTURE hTexture,
					 uint32 dwExtraFlags)
{
	CLinkListNode<TRAIL_SECTION> *pNode = pList->GetHead();

	// Transform the path

	LTMatrix mCam = GetCamTransform(pClientDE, hCamera);

	while (pNode)
	{
		MatVMul(&pNode->m_Data.m_vTran, &mCam, &pNode->m_Data.m_vPos);	
		
		pNode = pNode->m_pNext;
	}

	// Do some precalculations

	pNode = pList->GetHead();

	float fCurU = 0.0f;
	
	while (pNode)
	{	
		LTVector vBisector;
		vBisector.z = 0.0f;

		// Compute the midpoint vectors

		if (pNode == pList->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 == pList->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 x2 = vStart.y - vPrev.y;
			float y2 = -(vStart.x - vPrev.x);
			
			vBisector.x = (x1 + x2) / 2.0f;
			vBisector.y = (y1 + y2) / 2.0f;
		}

		vBisector.Norm(fTrailWidth);
		pNode->m_Data.m_vBisector = vBisector;

		pNode->m_Data.m_red   = r;
		pNode->m_Data.m_green = g;
		pNode->m_Data.m_blue  = b;
		pNode->m_Data.m_alpha = a;

		pNode = pNode->m_pNext;
	}

	pNode = pList->GetHead();

	if (pList->GetSize() < 2) return;

	pNode = pList->GetHead();

	ILTDrawPrim *pDrawPrimLT;
	pDrawPrimLT = pClientDE->GetDrawPrim();

	pDrawPrimLT->SetTexture(hTexture);
	pDrawPrimLT->SetTransformType(DRAWPRIM_TRANSFORM_CAMERA);
	pDrawPrimLT->BeginDrawPrim();


	if (g_bAppFocus)
	{
		uint32 nTris = 0;
		uint32 nVerts = 0;

		LT_POLYGT3 *pTri = g_pTris;
		LTVector *pVerts = g_pVerts;

		while (pNode->m_pNext)
		{
			LTVector vStart = pNode->m_Data.m_vTran;
			LTVector vEnd   = pNode->m_pNext->m_Data.m_vTran;
		
			LTVector vBisector1 = pNode->m_Data.m_vBisector;
			LTVector vBisector2 = pNode->m_pNext->m_Data.m_vBisector;

			*pVerts ++ = vStart + vBisector1;
			*pVerts ++ = vEnd + vBisector2;
			*pVerts ++ = vEnd - vBisector2;
			*pVerts ++ = vStart - vBisector1;

			uint8 r1 = pNode->m_Data.m_red;
			uint8 g1 = pNode->m_Data.m_green;
			uint8 b1 = pNode->m_Data.m_blue;
			uint8 a1 = pNode->m_Data.m_alpha;
			float u1 = pNode->m_Data.m_uVal;

			uint8 r2 = pNode->m_pNext->m_Data.m_red;
			uint8 g2 = pNode->m_pNext->m_Data.m_green;
			uint8 b2 = pNode->m_pNext->m_Data.m_blue;
			uint8 a2 = pNode->m_pNext->m_Data.m_alpha;
			float u2 = pNode->m_pNext->m_Data.m_uVal;
			
			SetupVert(pTri, 0, g_pVerts[nVerts].x, g_pVerts[nVerts].y, g_pVerts[nVerts].z, r1, g1, b1, a1, u1, 0.0f);
			SetupVert(pTri, 1, g_pVerts[nVerts + 1].x, g_pVerts[nVerts + 1].y, g_pVerts[nVerts + 1].z, r2, g2, b2, a2, u2, 1.0f);
			SetupVert(pTri, 2, g_pVerts[nVerts + 2].x, g_pVerts[nVerts + 2].y, g_pVerts[nVerts + 2].z, r2, g2, b2, a2, u2, 1.0f);

			pTri ++;
			nTris ++;

			SetupVert(pTri, 0, g_pVerts[nVerts].x, g_pVerts[nVerts].y, g_pVerts[nVerts].z, r1, g1, b1, a1, u1, 0.0f);
			SetupVert(pTri, 1, g_pVerts[nVerts + 2].x, g_pVerts[nVerts + 2].y, g_pVerts[nVerts + 2].z, r2, g2, b2, a2, u2, 1.0f);
			SetupVert(pTri, 2, g_pVerts[nVerts + 3].x, g_pVerts[nVerts + 3].y, g_pVerts[nVerts + 3].z, r1, g1, b1, a1, u1, 0.0f);

			pTri ++;
			nTris ++;

			nVerts += 4;

			pNode = pNode->m_pNext;

			//see if we need to flush our buffer
			if(nTris >= MAX_BUFFER_TRIS - 2)
			{
				pDrawPrimLT->DrawPrim(g_pTris, nTris);
				nTris = 0;
			}
		}

		// Draw the polylist
		if(nTris > 0)
		{
			pDrawPrimLT->DrawPrim(g_pTris, nTris);
			nTris = 0;
		}
	}

	pDrawPrimLT->BeginDrawPrim();
}
void CNudge::Update(LTBOOL bMoving)
{
	m_eState = eStateNoNudge;

	// If we're moving or high priority, then we don't need to worry about nudging
	if ( bMoving || (m_ePriority == ePriorityHigh) )
	{
		return;
	}

	LTVector vPos = m_pAI->GetPosition();
	LTFLOAT fRadius = m_pAI->GetRadius();
/*
	// If we're not inside our volume, don't nudge
	if ( !m_pAI->GetLastVolume() || !m_pAI->GetLastVolume()->Inside2d(vPos, fRadius) )
	{
		return;
	}
*/
	HOBJECT hPlayer = LTNULL;
	CAIHuman* apAIs[64];
	uint32 cAIs = 0;

    static HCLASS hClass = g_pLTServer->GetClass("CAIHuman");

    ObjectList* pObjectList = g_pLTServer->FindObjectsTouchingSphere(&vPos, fRadius);
	ObjectLink* pObject = pObjectList ? pObjectList->m_pFirstLink : LTNULL;

	while ( pObject && cAIs < 64 )
	{
		HOBJECT hObject = pObject->m_hObject;
		if ( hObject != m_pAI->m_hObject )
		{
			if ( IsPlayer(hObject) )
			{
				hPlayer = hObject;
			}
            else if ( g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hObject), hClass) )
			{
                apAIs[cAIs++] = (CAIHuman*)g_pLTServer->HandleToObject(hObject);
			}
		}

		pObject = pObject->m_pNext;
	}

	if ( pObjectList )
	{
		g_pLTServer->RelinquishList(pObjectList);
	}

	if ( cAIs == 0 ) return;

	m_eState = eStateNudge;
	m_vNudge = LTVector(0,0,0);

	if ( hPlayer )
	{
		LTVector vPlayerPosition;
		g_pLTServer->GetObjectPos(hPlayer, &vPlayerPosition);

		LTVector vNudgeDir = m_pAI->GetPosition()-vPlayerPosition;
		vNudgeDir.y = 0.0f;
		vNudgeDir.Norm();
		m_vNudge += vNudgeDir*64.0f*g_pLTServer->GetFrameTime();
	}

	for ( uint32 iAI = 0 ; iAI < cAIs ; iAI++ )
	{
		CAIHuman* pAI = apAIs[iAI];
		CNudge* pNudge = pAI->GetNudge();

		LTVector vNudgeDir;
		LTFLOAT fNudgeAmount;

		if ( pNudge->GetPriority() == ePriorityLow )
		{
			fNudgeAmount = 24.0f;
			vNudgeDir = m_pAI->GetPosition()-pAI->GetPosition();
			vNudgeDir.y = 0.0f;
			vNudgeDir.Norm();
		}
		else // if ( pNudge->GetPriority() == ePriorityHigh )
		{
			fNudgeAmount = 48.0f;
			vNudgeDir = m_pAI->GetPosition()-pAI->GetPosition();
			vNudgeDir.y = 0.0f;
			vNudgeDir.Norm();
		}

        m_vNudge += vNudgeDir*fNudgeAmount*g_pLTServer->GetFrameTime();
	}

	_ASSERT((LTFLOAT)fabs(m_vNudge.y < MATH_EPSILON));
}
Esempio n. 12
0
static void d3d_DrawRotatableSprite(const ViewParams& Params, SpriteInstance *pInstance, SharedTexture *pShared)
{
	
	if(!d3d_SetTexture(pShared, 0, eFS_SpriteTexMemory))
		return;

	float fWidth = (float)((RTexture*)pShared->m_pRenderData)->GetBaseWidth();
	float fHeight = (float)((RTexture*)pShared->m_pRenderData)->GetBaseHeight();

	//cache the object position
	LTVector vPos = pInstance->GetPos();
	
	LTMatrix mRotation;
	d3d_SetupTransformation(&vPos, (float*)&pInstance->m_Rotation, &pInstance->m_Scale, &mRotation);

	//get our basis vectors
	LTVector vRight, vUp, vForward;
	mRotation.GetBasisVectors(&vRight, &vUp, &vForward);

	//scale the vectors to be the appropriate size
	vRight  *= fWidth;
	vUp		*= fHeight;

	// Setup the points.
	RGBColor Color;
	d3d_GetSpriteColor(pInstance, &Color);
	uint32 nColor = Color.color;

	CSpriteVertex SpriteVerts[4];
	SpriteVerts[0].SetupVert(vPos + vUp - vRight, nColor, 0.0f, 0.0f);
	SpriteVerts[1].SetupVert(vPos + vUp + vRight, nColor, 1.0f, 0.0f);
	SpriteVerts[2].SetupVert(vPos + vRight - vUp, nColor, 1.0f, 1.0f);
	SpriteVerts[3].SetupVert(vPos - vRight - vUp, nColor, 0.0f, 1.0f);


	//figure out our final vertices to use
	CSpriteVertex	*pPoints;
	uint32			nPoints;
	CSpriteVertex	ClippedSpriteVerts[40 + 5];

	if(pInstance->m_ClipperPoly != INVALID_HPOLY)
	{
		if(!d3d_ClipSprite(pInstance, pInstance->m_ClipperPoly, &pPoints, &nPoints, ClippedSpriteVerts))
		{
			return;
		}
	}
	else
	{
		pPoints = SpriteVerts;
		nPoints = 4;
	}

	if((pInstance->m_Flags & FLAG_SPRITEBIAS) && !(pInstance->m_Flags & FLAG_REALLYCLOSE))
	{
		//adjust the points
		for(uint32 nCurrPt = 0; nCurrPt < nPoints; nCurrPt++)
		{
			//get the sprite vertex that we are modifying
			LTVector& vPt = SpriteVerts[nCurrPt].m_Vec;

			//find a point relative to the viewer position
			LTVector vPtRelCamera = vPt - Params.m_Pos;

			//determine the distance from the camera
			float fZ = vPtRelCamera.Dot(Params.m_Forward);

			if(fZ <= NEARZ)
				continue;

			//find the bias, up to, but not including the near plane
			float fBiasDist = SPRITE_POSITION_ZBIAS;
			if((fZ + fBiasDist) < NEARZ)
				fBiasDist = NEARZ - fZ;
			
			//now adjust our vectors accordingly so that we can move it forward
			//but have it be the same size
			float fScale = 1 + fBiasDist / fZ;

			vPt = Params.m_Right * vPtRelCamera.Dot(Params.m_Right) * fScale +
				  Params.m_Up * vPtRelCamera.Dot(Params.m_Up) * fScale +
				  (fZ + fBiasDist) * Params.m_Forward + Params.m_Pos;
		}
	}
	
	LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pInstance->m_nEffectShaderID);
	if(pEffect)
	{
		pEffect->UploadVertexDeclaration();

		ID3DXEffect* pD3DEffect = pEffect->GetEffect();
		if(pD3DEffect)
		{
			RTexture* pTexture = (RTexture*)pShared->m_pRenderData;
			pD3DEffect->SetTexture("texture0", pTexture->m_pD3DTexture);

			i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton());

			UINT nPasses = 0;
			pD3DEffect->Begin(&nPasses, 0);

			for(int i = 0; i < nPasses; ++i)
			{
				pD3DEffect->BeginPass(i);
				D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex)));
				pD3DEffect->EndPass();
			}

			pD3DEffect->End();
		}

	}
	else
	{	
		D3D_CALL(PD3DDEVICE->SetVertexShader(NULL));
		D3D_CALL(PD3DDEVICE->SetFVF(SPRITEVERTEX_FORMAT));
		D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex)));
	}

	d3d_DisableTexture(0);
}
Esempio n. 13
0
//function that handles the custom rendering
void CBaseSpriteFX::RenderSprite(ILTCustomRenderCallback* pInterface, const LTRigidTransform& tCamera)
{
	//setup our vertex declaration
	if(pInterface->SetVertexDeclaration(g_ClientFXVertexDecl.GetTexTangentSpaceDecl()) != LT_OK)
		return;

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

	//determine how many indices we are going to need
	uint32 nNumIndices  = (GetProps()->m_bTwoSided) ? 12 : 6;
	uint32 nNumVertices = (GetProps()->m_bTwoSided) ? 8 : 4;

	//sanity check to ensure that we can at least render a sprite
	LTASSERT(QUAD_RENDER_INDEX_STREAM_SIZE >= nNumIndices, "Error: Quad index list is too small to render a sprite");
	LTASSERT(DYNAMIC_RENDER_VERTEX_STREAM_SIZE / sizeof(STexTangentSpaceVert) >= nNumVertices, "Error: Dynamic vertex buffer size is too small to render a sprite");

	//determine the up and right vectors for the sprite
	LTVector vTangent, vBinormal;

	//get the position of this sprite
	LTRigidTransform tObjTransform;
	g_pLTClient->GetObjectTransform(m_hObject, &tObjTransform);

	//determine the center of this sprite
	LTVector vCenter = tObjTransform.m_vPos;

	//determine the orientation of the sprite based upon its facing
	if(GetProps()->m_bAlignToCamera)
	{
		//apply the to camera offset
		LTVector vToCamera = tCamera.m_vPos - vCenter;
		float fScale = GetProps()->m_fToCameraOffset / vToCamera.Mag();
		vCenter += vToCamera * fScale;

		//perform the rotation
		float fCosAng = LTCos(m_fCurrRotationRad);
		float fSinAng = LTSin(m_fCurrRotationRad);

		LTVector vRight = tCamera.m_rRot.Right();
		LTVector vUp = -tCamera.m_rRot.Up();

		vTangent	= fCosAng * vRight + fSinAng * vUp;
		vBinormal	= fCosAng * vUp - fSinAng * vRight;
	}
	else if(GetProps()->m_bAlignAroundZ)
	{
		//we want to orient around the Z axis and align to the camera

		//we need to determine our U vector, which is always our forward
		LTVector vU = tObjTransform.m_rRot.Forward();

		//and now we want to offset our center so that we are anchored on the right hand
		//side of the sprite to the point
		vCenter += vU * (m_fWidth * 0.5f);

		//determine the axis from our camera to our object
		LTVector vToCamera = tCamera.m_vPos - vCenter;

		//and now derive our V vector from the forward and the direction to the camera
		LTVector vV = vToCamera.Cross(vU);

		//detect degenerate cases
		if(vV == LTVector::GetIdentity())
		{
			//degenerate case, any orientation will work fine since the sprite won't
			//be visible anyway
			vV.Init(0.0f, 1.0f, 0.0f);
		}

		//and normalize our vector
		vV.Normalize();

		//now we can determine our tangent and binormal vectors
		vTangent	= -vU;
		vBinormal	= vV;
	}
	else
	{
		vTangent	= -tObjTransform.m_rRot.Right();
		vBinormal	= -tObjTransform.m_rRot.Up();
	}
	
	LTVector vNormal = vBinormal.Cross(vTangent);

	//scale the right and down values to be the appropriate size
	LTVector vRight	= vTangent * m_fWidth * -0.5f;
	LTVector vDown	= vBinormal * m_fWidth * GetProps()->m_fAspectRatio * 0.5f;


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

	//fill in our sprite vertices
	STexTangentSpaceVert* pCurrOut = (STexTangentSpaceVert*)LockRequest.m_pData;

	uint32 nColor = SETRGBA(	(uint8)(m_vColor.x * 255.0f), 
								(uint8)(m_vColor.y * 255.0f), 
								(uint8)(m_vColor.z * 255.0f), 
								(uint8)(m_vColor.w * 255.0f));

	//fill in the particle vertices
	pCurrOut[0].m_vPos = vCenter + vRight - vDown;
	pCurrOut[0].m_vUV.Init(0.0f, 0.0f);
	
	pCurrOut[1].m_vPos = vCenter - vRight - vDown;
	pCurrOut[1].m_vUV.Init(1.0f, 0.0f);
	
	pCurrOut[2].m_vPos = vCenter - vRight + vDown;
	pCurrOut[2].m_vUV.Init(1.0f, 1.0f);

	pCurrOut[3].m_vPos = vCenter + vRight + vDown;
	pCurrOut[3].m_vUV.Init(0.0f, 1.0f);

	//setup the remaining vertex components
	for(uint32 nCurrVert = 0; nCurrVert < 4; nCurrVert++)
	{
		pCurrOut[nCurrVert].m_nPackedColor = nColor;
		pCurrOut[nCurrVert].m_vNormal = vNormal;
		pCurrOut[nCurrVert].m_vTangent = vTangent;
		pCurrOut[nCurrVert].m_vBinormal = vBinormal;
	}

	//and fill in the back side if appropriate
	if(GetProps()->m_bTwoSided)
	{
		pCurrOut[4].m_vPos = vCenter - vRight - vDown;
		pCurrOut[4].m_vUV.Init(1.0f, 0.0f);
		
		pCurrOut[5].m_vPos = vCenter + vRight - vDown;
		pCurrOut[5].m_vUV.Init(0.0f, 0.0f);
		
		pCurrOut[6].m_vPos = vCenter + vRight + vDown;
		pCurrOut[6].m_vUV.Init(0.0f, 1.0f);

		pCurrOut[7].m_vPos = vCenter - vRight + vDown;
		pCurrOut[7].m_vUV.Init(1.0f, 1.0f);

		//setup the remaining vertex components
		for(uint32 nCurrVert = 4; nCurrVert < 8; nCurrVert++)
		{
			pCurrOut[nCurrVert].m_nPackedColor = nColor;
			pCurrOut[nCurrVert].m_vNormal = -vNormal;
			pCurrOut[nCurrVert].m_vTangent = -vTangent;
			pCurrOut[nCurrVert].m_vBinormal = vBinormal;
		}
	}

	//unlock and render the batch
	pInterface->UnlockAndBindDynamicVertexBuffer(LockRequest);
	pInterface->RenderIndexed(	eCustomRenderPrimType_TriangleList, 
								0, nNumIndices, LockRequest.m_nStartIndex, 
								0, nNumVertices);
}
Esempio n. 14
0
void CAIHelicopterStrategyShoot::UpdateFiring(CWeapon* pWeapon, BURSTSTRUCT* pBurst)
{
	// Get our fire position

	LTVector vFirePos = GetAI()->GetAttachmentPosition(pWeapon->GetModelObject());
    LTRotation rFireRot = GetAI()->GetAttachmentRotation(pWeapon->GetModelObject());
	LTVector vFireRight, vFireUp, vFireForward;
	g_pMathLT->GetRotationVectors(rFireRot, vFireUp, vFireRight, vFireForward);

	// Get target's position

	LTVector vTargetPos;
    g_pLTServer->GetObjectPos(m_hTarget, &vTargetPos);

	// Get our firing vector

	LTVector vFireDir = vTargetPos - vFirePos;
	vFireDir.Norm();

	// Make sure it's in our field of firce

	LTFLOAT fDp = vFireDir.Dot(vFireForward);
//    g_pLTServer->CPrint("fireangle = %f", (acos(fDp)/MATH_PI)*180.0f);
	if ( fDp <= c_fFOV90 )
	{
		Aim(pWeapon, pBurst);
		return;
	}

	// Now fire the weapon

	WFireInfo fireInfo;
	fireInfo.hFiredFrom = GetAI()->GetObject();
	fireInfo.vPath		= vFireDir;
	fireInfo.vFirePos	= vFirePos;
	fireInfo.vFlashPos	= vFirePos;
	fireInfo.hTestObj	= m_hTarget;
	fireInfo.fPerturbR	= 4.0f*(1.0f - GetAI()->GetAccuracy());
	fireInfo.fPerturbU	= 4.0f*(1.0f - GetAI()->GetAccuracy());

    pWeapon->UpdateWeapon(fireInfo, LTTRUE);

	// Decrement our burst counter and update the last ammo count

	pBurst->m_nBurstShots -= Max<int>(0, pBurst->m_nLastAmmoInClip - pWeapon->GetAmmoInClip());
	pBurst->m_nLastAmmoInClip = pWeapon->GetAmmoInClip();

	if ( pBurst->m_nBurstShots <= 0 )
	{
		// We just finished our burst. Start waiting.

		CalculateBurst(pWeapon, pBurst);

		// And just aim.

		Aim(pWeapon, pBurst);
	}
	else
	{
		// Keep firing

		Fire(pWeapon, pBurst);
	}
}
void CAIVolumeNeighbor::Init(CAIVolume* pThis, CAIVolume* pNeighbor)
{
	m_iVolume = pNeighbor->GetIndex();

	// Compute the 2d intersection of the two volumes, and compute important
	// things about the geometry of the connection

    LTVector vFrontLeft(0,0,0);
    LTVector vFrontRight(0,0,0);
    LTVector vBackLeft(0,0,0);
    LTVector vBackRight(0,0,0);

	vFrontLeft.x = Max<LTFLOAT>(pThis->GetFrontTopLeft().x, pNeighbor->GetFrontTopLeft().x);
	vFrontLeft.z = Min<LTFLOAT>(pThis->GetFrontTopLeft().z, pNeighbor->GetFrontTopLeft().z);

	vFrontRight.x = Min<LTFLOAT>(pThis->GetFrontTopRight().x, pNeighbor->GetFrontTopRight().x);
	vFrontRight.z = Min<LTFLOAT>(pThis->GetFrontTopRight().z, pNeighbor->GetFrontTopRight().z);

	vBackLeft.x = Max<LTFLOAT>(pThis->GetBackTopLeft().x, pNeighbor->GetBackTopLeft().x);
	vBackLeft.z = Max<LTFLOAT>(pThis->GetBackTopLeft().z, pNeighbor->GetBackTopLeft().z);

	vBackRight.x = Min<LTFLOAT>(pThis->GetBackTopRight().x, pNeighbor->GetBackTopRight().x);
	vBackRight.z = Max<LTFLOAT>(pThis->GetBackTopRight().z, pNeighbor->GetBackTopRight().z);

	// We know connection position (the center of the intersection) easily.

	m_vConnectionPos = (vFrontLeft+vFrontRight+vBackLeft+vBackRight)/4.0f;

	// We need y for vertical movement

#define _A_b pThis->GetFrontBottomRight().y
#define _A_t pThis->GetFrontTopRight().y
#define _B_b pNeighbor->GetFrontBottomRight().y
#define _B_t pNeighbor->GetFrontTopRight().y

	if ( (_A_t >= _B_t) && (_A_t >= _B_b) && (_A_b >= _B_t) && (_A_b >= _B_b) )
	{
		m_vConnectionPos.y = _A_b; // or _B_t
	}
	else if ( (_A_t <= _B_t) && (_A_t <= _B_b) && (_A_b <= _B_t) && (_A_b <= _B_b) )
	{
		m_vConnectionPos.y = _A_t; // or _B_b
	}
	else if ( (_A_t >= _B_t) && (_A_t >= _B_b) && (_A_b <= _B_t) && (_A_b >= _B_b) )
	{
		m_vConnectionPos.y = (_A_b + _B_t)/2.0f;
	}
	else if ( (_A_t <= _B_t) && (_A_t >= _B_b) && (_A_b <= _B_t) && (_A_b <= _B_b) )
	{
		m_vConnectionPos.y = (_A_t + _B_b)/2.0f;
	}
	else if ( (_A_t >= _B_t) && (_A_t >= _B_b) && (_A_b <= _B_t) && (_A_b <= _B_b) )
	{
		m_vConnectionPos.y = (_B_b + _B_t)/2.0f;
	}
	else if ( (_A_t <= _B_t) && (_A_t >= _B_b) && (_A_b <= _B_t) && (_A_b >= _B_b) )
	{
		m_vConnectionPos.y = (_A_b + _A_t)/2.0f;
	}
	else
	{
		m_vConnectionPos.y = -float(INT_MAX);
        DANGER(g_pLTServer, blong);
	}

	// Find the endpoints of the line across the connection, and the vector perpendicular to this

	if ( pThis->Inside(pNeighbor->GetFrontTopLeft()) || pThis->Inside(pNeighbor->GetBackTopRight()) ||
		 pThis->Inside(pNeighbor->GetFrontBottomLeft()) || pThis->Inside(pNeighbor->GetBackBottomRight()) )
	{
        m_avConnectionEndpoints[0] = vFrontRight + LTVector(0, m_vConnectionPos.y, 0);
        m_avConnectionEndpoints[1] = vBackLeft + LTVector(0, m_vConnectionPos.y, 0);
		m_vConnectionPerpDir = vFrontRight - vBackLeft;
		m_vConnectionDir = m_avConnectionEndpoints[1] - m_avConnectionEndpoints[0];
		m_vConnectionDir.y = 0.0f;
		m_fConnectionLength = VEC_MAG(m_vConnectionDir);
		m_vConnectionDir.Norm();
	}
	else
	{
        m_avConnectionEndpoints[0] = vFrontLeft + LTVector(0, m_vConnectionPos.y, 0);
        m_avConnectionEndpoints[1] = vBackRight + LTVector(0, m_vConnectionPos.y, 0);
		m_vConnectionPerpDir = vFrontLeft - vBackRight;
		m_vConnectionDir = m_avConnectionEndpoints[1] - m_avConnectionEndpoints[0];
		m_vConnectionDir.y = 0.0f;
		m_fConnectionLength = VEC_MAG(m_vConnectionDir);
		m_vConnectionDir.Norm();
	}

	LTFLOAT fTemp = m_vConnectionPerpDir[0];
	m_vConnectionPerpDir[0] = m_vConnectionPerpDir[2];
	m_vConnectionPerpDir[2] = fTemp;
	m_vConnectionPerpDir.Norm();

	// Make sure it points into this volume

    LTVector vThisCenter = (pThis->GetFrontTopLeft()+pThis->GetBackTopRight())/2.0f;
    LTVector vThisCenterDir = vThisCenter - m_vConnectionPos;
	vThisCenterDir.y = 0;
	vThisCenterDir.Norm();

	if ( vThisCenterDir.Dot(m_vConnectionPerpDir) < 0.0f )
	{
		m_vConnectionPerpDir = -m_vConnectionPerpDir;
	}

//  g_pLTServer->CPrint("cxn @ %f,%f,%f in %f,%f,%f : %f,%f,%f",
//		EXPANDVEC(m_vConnectionPos), EXPANDVEC(vThisCenter), EXPANDVEC(m_vConnectionPerpDir));
}
bool CAIActionGotoValidPosition::GetValidPosition(CAI* pAI, LTVector& outValidPosition)
{
	// fail if the AI does not currently have a nav mesh poly.
	// find the nearest nav mesh poly that is not a border
	// find the nearest point on the poly
	// return this point

	//----

	// AI is not in a nav mesh poly.

	ENUM_NMPolyID eID = pAI->GetCurrentNavMeshPoly();
	if ( kNMPoly_Invalid == eID)
	{
		return false;
	}

	// Find the closest non edge poly.

	const LTVector vAIPosition(pAI->GetPosition().x, 0, pAI->GetPosition().z);

	float flBestDistance = FLT_MAX;
	LTVector vBestPosition(0.f, 0.f, 0.f);
	LTVector vBestCenter(0.f, 0.f, 0.f);
	CAINavMeshPoly* pNMPoly = g_pAINavMesh->GetNMPoly( eID );
	int nEdges = pNMPoly->GetNumNMPolyEdges();
	for (int i = 0; i < nEdges; ++i)
	{
		CAINavMeshEdge* pEdge = pNMPoly->GetNMPolyEdge(i);
		if (pEdge)
		{
			if (kNMEdgeType_Border == pEdge->GetNMEdgeType())
			{
				// This edge is a border, skip it.
				continue;
			}

			// Verify that the other poly is valid for entry

			CAINavMeshPoly* pNMOtherPoly = NULL;
			if ( eID == pEdge->GetNMPolyIDA())
			{
				pNMOtherPoly = g_pAINavMesh->GetNMPoly( pEdge->GetNMPolyIDB() );
			}
			else
			{
				pNMOtherPoly = g_pAINavMesh->GetNMPoly( pEdge->GetNMPolyIDA() );
			}

			// Verify that the other link, if there is one, is valid for entry

			if (pNMOtherPoly && (kNMLink_Invalid != pNMOtherPoly->GetNMLinkID()))
			{
				AINavMeshLinkAbstract* pLink = g_pAINavMesh->GetNMLink(pNMOtherPoly->GetNMLinkID());
				if (pLink)
				{
					if (!pLink->IsNMLinkEnabledToAI(pAI, !LINK_CHECK_TIMEOUT))
					{
						continue;
					}
				}
			}

			// Find the closest point on the poly

			LTVector vEdge0 = pEdge->GetNMEdge0();
			vEdge0.y = 0.f;

			LTVector vEdge1 = pEdge->GetNMEdge1();
			vEdge1.y = 0.f;

			LTVector vPos;
			float flDummy;
			float flDist = LTIntersect::Point_Segment_DistSqr(vAIPosition, vEdge0, vEdge1, vPos, flDummy);

			// Better exit location found.

			if (flDist < flBestDistance)
			{
				flBestDistance = flDist;
				vBestPosition = vPos;
				vBestCenter = pNMOtherPoly->GetNMPolyCenter();
			}
		}
	}

	// Failed to find a valid position.

	if (FLT_MAX == flBestDistance)
	{
		return false;
	}

	// Return the position (adjust it by moving the height to match the AIs 
	// current elevation, and adjust the point by a fraction in the direction the AI is 
	// moving to insure that he gets out of the disabled link.

	LTVector vDirection = vBestPosition - vAIPosition;
	vDirection.Normalize();
	LTVector vDestination = LTVector(vBestPosition.x, pAI->GetPosition().y, vBestPosition.z) + (vDirection * pAI->GetRadius());
	if( g_pAIPathMgrNavMesh->StraightPathExists( pAI, pAI->GetCharTypeMask(), pAI->GetPosition(), vDestination, pAI->GetLastNavMeshPoly(), pAI->GetRadius() ) )
	{
		outValidPosition = vDestination;
		return true;
	}

	// Failed to move to the ideal location.  Try moving to the center of the
	// poly.  This should always succeed.  If it doesn't, add a fix which will 
	// work to handle this case.
	AIASSERT(g_pAIPathMgrNavMesh->HasPath(pAI, pAI->GetCharTypeMask(), vBestCenter), pAI->GetHOBJECT(), 
		"CAIActionGotoValidPosition::GetValidPosition : Failed to find path to the center of a neighboring poly." );

	outValidPosition = vBestCenter;
	return true;
}
bool CAIActionSurpriseAttackLaunch::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning )
{
	if ( !super::ValidateContextPreconditions( pAI, wsWorldStateGoal, bIsPlanning ) )
	{
		return false;
	}

	// Verify the node has a smartobject.  (if it doesn't, this node will 
	// not be used.  This is an level design error, but an easy one to make,
	// so report it.

	if ( NULL == GetAtNodeSmartObjectRecord( *pAI->GetAIWorldState(), pAI->GetHOBJECT() ) )
	{
		return false;
	}

	// AI is either not at a surprise node, or the node does not have a 
	// valid action.

	if ( kAP_Invalid == GetAtNodeAttackProp(
		*pAI->GetAIWorldState(), pAI->GetHOBJECT(), 
		pAI->GetAIBlackBoard()->GetBBTargetObject() ) )
	{
		return false;
	}

	// Fail if the AI is not facing the node.

	SAIWORLDSTATE_PROP* pAtNodeProp = pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, pAI->GetHOBJECT() );
	if ( !pAtNodeProp ||
		( !pAtNodeProp->hWSValue ) )
	{
		return false;
	}

	AINode* pNode = AINode::HandleToObject( pAtNodeProp->hWSValue );
	if ( !pNode )
	{
		return false;
	}

	if ( pNode->GetFaceNode() )
	{
		LTVector vNodeDir = pNode->GetNodeFaceDir();
		vNodeDir.y = 0.0f;
		vNodeDir.Normalize();
		if ( vNodeDir == LTVector::GetIdentity() )
		{
			return false;
		}

		LTVector vAIForward = pAI->GetForwardVector();
		vAIForward.y = 0.0f;
		vAIForward.Normalize();
		if ( vAIForward == LTVector::GetIdentity() )
		{
			return false;
		}

		if ( vAIForward.Dot( vNodeDir ) < 0.9999f )
		{
			return false;
		}
	}

	// Success!

	return true;
}
void Breakable::UpdateFalling()
{
    LTVector vOldPos;
    g_pLTServer->GetObjectPos(m_hObject, &vOldPos);

    LTVector vPos = vOldPos;
    vPos += (m_vVel * g_pLTServer->GetFrameTime());

    LTBOOL bDone = LTFALSE;

	if (vPos.y < m_vFinalPos.y)
	{
		vPos.y = m_vFinalPos.y;
        bDone = LTTRUE;
	}

    g_pLTServer->TeleportObject(m_hObject, &vPos);

	if (vPos.Equals(m_vFinalPos, 10.0f))
	{
        bDone = LTTRUE;
	}

	if (bDone)
	{
        m_bFalling = LTFALSE;

        uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject);
		dwFlags |= FLAG_SOLID;
        g_pLTServer->SetObjectFlags(m_hObject, dwFlags);

        g_pLTServer->SetNextUpdate(m_hObject, 0.0f);


		// Create impact fx...

		CreateImpactFX();


		if (m_bDestroyOnImpact)
		{
			Destroy();
		}
		else
		{
			// Play the impact sound...

			if (m_hstrImpactSound)
			{
                LTVector vPos;
                g_pLTServer->GetObjectPos(m_hObject, &vPos);

                char* pSnd = g_pLTServer->GetStringData(m_hstrImpactSound);

				if (pSnd)
				{
					g_pServerSoundMgr->PlaySoundFromPos(vPos, pSnd, m_fImpactSoundRadius,
						SOUNDPRIORITY_MISC_MEDIUM);
				}
			}
		}
	}
}
Esempio n. 19
0
void CTriggerFX::CalcLocalClientDistance()
{
	m_fDistPercent = -1.0f;

	// Don't do anything if the trigger is locked or our distances are too small..

	if( m_cs.bLocked || (m_cs.fHUDAlwaysOnDist <= 0.0f && m_cs.fHUDLookAtDist <= 0.0f) )
		return;

	// See if the player is within the trigger...

	LTVector vTrigPos;
	g_pLTClient->GetObjectPos( m_hServerObject, &vTrigPos );
	g_pLTClient->SetObjectPos( m_hDimsObject, vTrigPos );

	HLOCALOBJ	hPlayerObj = g_pLTClient->GetClientObject();
	LTVector	vPlayerPos, vPlayerDims;

	g_pLTClient->GetObjectPos( hPlayerObj, &vPlayerPos );

	// Make sure we are within the display radius...
	
	float	fMaxRadius = LTMAX( m_cs.fHUDAlwaysOnDist, m_cs.fHUDLookAtDist );
	float	fDistSqr = vTrigPos.DistSqr( vPlayerPos );
	bool	bWithinLookAtDist = (fDistSqr < m_cs.fHUDLookAtDist * m_cs.fHUDLookAtDist);
	bool	bWithinAlwaysOnDist = (fDistSqr < m_cs.fHUDAlwaysOnDist * m_cs.fHUDAlwaysOnDist);

	if( !bWithinLookAtDist && !bWithinAlwaysOnDist )
	{
		// We are not close enough...
		
		m_bWithinIndicatorRadius = false;
		return;
	}

	m_bWithinIndicatorRadius = true;

	g_pPhysicsLT->GetObjectDims( hPlayerObj, &vPlayerDims );

	LTVector vTrigMin = vTrigPos - m_cs.vDims;
	LTVector vTrigMax = vTrigPos + m_cs.vDims;
	LTVector vPlayerMin = vPlayerPos - vPlayerDims;
	LTVector vPlayerMax = vPlayerPos + vPlayerDims;

	// Check if we are within the height of the trigger...

	bool bWithinHeight =false;
	if( vPlayerMax.y > vTrigMin.y && vPlayerMin.y < vTrigMax.y )
		bWithinHeight = true;
	
	// See if we are inside the trigger at all...

	if( bWithinHeight && (BoxesIntersect( vTrigMin, vTrigMax, vPlayerMin, vPlayerMax ) || bWithinAlwaysOnDist))
	{
		m_fDistPercent = 1.0f;
	}
	else
	{
		// We are within the height of the trigger, show how far from it we are...

		float fMinDist = (vPlayerDims.x + vPlayerDims.z) * 0.5f;
		float fMaxDist = 100000.0f;

		LTVector vDir;

		if( bWithinAlwaysOnDist )
		{
			vDir = vTrigPos - vPlayerPos;
			vDir.Normalize();
		}
		else
		{
			LTRotation const& rRot = g_pPlayerMgr->GetPlayerCamera()->GetCameraRotation( );
			vDir = rRot.Forward();
		}

		IntersectQuery IQuery;
		IntersectInfo IInfo;

		IQuery.m_From		= vPlayerPos + (vDir * fMinDist);
		IQuery.m_To			= IQuery.m_From + (vDir * fMaxDist);
		IQuery.m_Flags		= INTERSECT_OBJECTS | INTERSECT_HPOLY | IGNORE_NONSOLID;
				
		// We need to recieve rayhits for this intersect call...

		g_pCommonLT->SetObjectFlags( m_hDimsObject, OFT_Flags, FLAG_RAYHIT, FLAG_RAYHIT );

		if( g_pLTClient->IntersectSegment( IQuery, &IInfo ))
		{
			if( IInfo.m_hObject == m_hDimsObject )
			{
				IInfo.m_Point.y = vPlayerPos.y;
				float fDist = vPlayerPos.Dist( IInfo.m_Point );
				m_fDistPercent = 1.0f - (fDist / fMaxRadius);
			}
		}

		// No more rayhits...
		
		g_pCommonLT->SetObjectFlags( m_hDimsObject, OFT_Flags, 0, FLAG_RAYHIT );
	}
}
Esempio n. 20
0
void Prop::HandleAttachmentTouch( HOBJECT hToucher )
{
	if( !hToucher || !m_bAttachmentShotOff )
		return;

	// Don't touch the owner...

	if( hToucher == m_hAttachmentOwner )
		return;

	// Or any non-solid objects...
	
	uint32 dwToucherFlags;
	g_pCommonLT->GetObjectFlags( hToucher, OFT_Flags, dwToucherFlags );
	if( !(dwToucherFlags & FLAG_SOLID) )
		return;

	CollisionInfo info;
    g_pLTServer->GetLastCollision( &info );

	LTVector vVel;
	g_pPhysicsLT->GetVelocity( m_hObject, &vVel );

	// Calculate where we really hit the world...
    
	if( IsMainWorld( hToucher ))
	{
        LTVector vPos, vCurVel, vP0, vP1;
        g_pLTServer->GetObjectPos( m_hObject, &vPos );

		vP1 = vPos;
        vCurVel = vVel * g_pLTServer->GetFrameTime();
		vP0 = vP1 - vCurVel;
		vP1 += vCurVel;

        LTFLOAT fDot1 = VEC_DOT( info.m_Plane.m_Normal, vP0 ) - info.m_Plane.m_Dist;
        LTFLOAT fDot2 = VEC_DOT( info.m_Plane.m_Normal, vP1 ) - info.m_Plane.m_Dist;

		if( fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f )
		{
			vPos = vP1;
		}
		else
		{
            LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1);
			VEC_LERP( vPos, vP0, vP1, fPercent);
		}

		// Set our new "real" pos...

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

	// If we're on the ground (or an object), stop movement...

	CollisionInfo standingInfo;
    g_pLTServer->GetStandingOn( m_hObject, &standingInfo );

	CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info;

	if( pInfo->m_hObject )
	{
		// Don't stop on walls...

		if( pInfo->m_Plane.m_Normal.y > 0.75f )
		{
			vVel.Init();

			// Turn off gravity, solid, and touch notify....

			uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY;
			g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, 0, dwFlags );

			// Rotate to rest...

			if( m_bRotating )
			{
				LTRotation rRot( 0.0f, m_fYaw, 0.0f );
				g_pLTServer->SetObjectRotation( m_hObject, &rRot );

				m_bRotating = false;
				StartFade( s_vtAttachmentFadeDuration.GetFloat(), s_vtAttachmentFadeDelay.GetFloat() );
			}
		}
	}
	
	// Remove the stoping velocity...

	vVel = -info.m_vStopVel;
	g_pPhysicsLT->SetVelocity( m_hObject, &vVel );
}
Esempio n. 21
0
void CLaserBeam::Update(LTVector vBeamStartPos, LTRotation* pRDirRot,
                        LTBOOL b3rdPerson, LTBOOL bDetect)
{
	if (!m_bOn) return;

	// Calculate beam position...

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

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

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

	IntersectQuery qInfo;
	IntersectInfo iInfo;

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

    LTVector vU, vR, vF;

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

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

        g_pLTClient->GetRotationVectors(&rRot, &vU, &vR, &vF);

		if (g_cvarLaserBeamDebug.GetFloat() == 0.0f)
		{
			vBeamStartPos += vPos;
		}
		else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f)
		{
			vBeamStartPos = vPos;
		}
		else
		{
            g_pLTClient->GetRotationVectors(pRDirRot, &vU, &vR, &vF);
			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_pLTClient->GetObjectUserFlags(iInfo.m_hObject, &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;
			dwFlags2 &= ~FLAG2_PORTALINVISIBLE;
		}
		else
		{
			if (g_cvarLaserBeamDebug.GetFloat() > 1.0f)
			{
				dwFlags |= FLAG_REALLYCLOSE;
                pls.bUseObjectRotation = LTTRUE;
			}
			dwFlags2 |= FLAG2_PORTALINVISIBLE;
		}

		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();
}
Esempio n. 22
0
LTBOOL CSearchLightFX::Update()
{
    if (!m_pClientDE || !m_hServerObject || m_bWantRemove || !m_hBeam) return LTFALSE;

    uint32 dwFlags = 0;

	// Update the lens flare...

	m_LensFlare.Update();

	// Hide/show the fx if necessary...

	if (m_hServerObject)
	{
        uint32 dwUserFlags;
		m_pClientDE->GetObjectUserFlags(m_hServerObject, &dwUserFlags);

		if (!(dwUserFlags & USRFLG_VISIBLE))  // Hide fx
		{
			if (m_hBeam)
			{
				dwFlags = m_pClientDE->GetObjectFlags(m_hBeam);
				m_pClientDE->SetObjectFlags(m_hBeam, dwFlags & ~FLAG_VISIBLE);
			}
			if (m_hLight)
			{
				dwFlags = m_pClientDE->GetObjectFlags(m_hLight);
				m_pClientDE->SetObjectFlags(m_hLight, dwFlags & ~FLAG_VISIBLE);
			}

            return LTTRUE;
		}
		else  // Make all fx visible
		{
			if (m_hBeam)
			{
				dwFlags = m_pClientDE->GetObjectFlags(m_hBeam);
				m_pClientDE->SetObjectFlags(m_hBeam, dwFlags | FLAG_VISIBLE);
			}
			if (m_hLight)
			{
				dwFlags = m_pClientDE->GetObjectFlags(m_hLight);
				m_pClientDE->SetObjectFlags(m_hLight, dwFlags | FLAG_VISIBLE);
			}
		}
	}


	// Update the position/rotation of the beam...

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

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

    LTVector vU, vR, vF;
	m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);


	// See how long to make the beam...

    LTVector vDest = vPos + (vF * m_cs.fBeamLength);

	IntersectInfo iInfo;
	IntersectQuery qInfo;
	qInfo.m_Flags		= INTERSECT_OBJECTS | IGNORE_NONSOLID;
	qInfo.m_FilterFn	= AttackerLiquidFilterFn;
	qInfo.m_pUserData	= m_hServerObject;
	qInfo.m_From		= vPos;
	qInfo.m_To			= vDest;

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

    LTVector vDir = vDest - vPos;
    LTFLOAT fDistance = vDir.Mag();
	vDir.Norm();

    LTVector vNewPos = vPos + vDir * fDistance/2.0f;
	m_pClientDE->AlignRotation(&rRot, &vDir, NULL);

	if (m_cs.fBeamRotTime > 0.0f)
	{
		m_fBeamRotation += (360.0f/m_cs.fBeamRotTime * g_pGameClientShell->GetFrameTime());
		m_fBeamRotation = m_fBeamRotation > 360.0f ? m_fBeamRotation - 360.0f : m_fBeamRotation;
		m_pClientDE->RotateAroundAxis(&rRot, &vDir, DEG2RAD(m_fBeamRotation));
	}

	m_pClientDE->SetObjectRotation(m_hBeam, &rRot);
	m_pClientDE->SetObjectPos(m_hBeam, &vNewPos);

    LTVector vScale(m_cs.fBeamRadius, m_cs.fBeamRadius, fDistance);
	m_pClientDE->SetObjectScale(m_hBeam, &vScale);


	// Move the dynamic light...

	if (m_hLight)
	{
		vDest -= (vDir * 5.0f);
		m_pClientDE->SetObjectPos(m_hLight, &vDest);
	}

    return LTTRUE;
}
Esempio n. 23
0
void ModelDraw::SetupModelLight(ModelInstance* pInstance, const ModelHookData& HookData, CRelevantLightList& LightList)
{
	//setup our light list information
	uint32 nMaxLights = LTMIN((uint32)g_CV_MaxModelLights, MAX_LIGHTS_SUPPORTED_BY_D3D);

	LTVector vInstancePosition;

	// Should we skip the root node and use it's first child node
	// for lighting consideration?
	if(g_CV_ModelLightingSkipRootNode)
	{
		// Index of the root node (should be 0)
		uint32 iRootNode = pInstance->NodeGetRootIndex();
		
		// How many children nodes does it have?
		uint32 iRootNodeNumKids = pInstance->NodeGetNumChildren( iRootNode );
		
		// Is there atleast one?
		if(iRootNodeNumKids > 0)
		{
		    // Just get the first one.
			// This assumes the the first child-node translates with the rest
			// of the mesh.
			uint32 iNode = pInstance->NodeGetChild( iRootNode, 0 );
			LTransform tf;
			pInstance->GetNodeTransform( iNode, tf, true );
		
			// Set our calculation position to the node's position
			vInstancePosition = tf.m_Pos;
		}
		else
		{
		    // If the root node doesn't have any children,
			// fall back to the root node's position.
			vInstancePosition = pInstance->GetPos();
		}
	}
	else // No? Then just use the root node position
	{
		//figure out the world position of this instance
		vInstancePosition = pInstance->GetPos();
	}

	LightList.ClearList();
	LightList.SetMaxLights(nMaxLights);
	LightList.SetObjectPos(vInstancePosition);
	LightList.SetObjectDims(pInstance->GetDims());

	// If they don't want lighting, set the values for no lighting and skip out
	if((g_CV_LightModels.m_Val == 0) || (HookData.m_ObjectFlags & FLAG_NOLIGHT))
	{
		LightList.AddAmbient(LTVector(255.0f, 255.0f, 255.0f));
		return;
	}

	//determine if we are in really close space
	bool bReallyClose = (HookData.m_ObjectFlags & FLAG_REALLYCLOSE) != 0;

	////////////////////////////////////////////////////////////////////
	// Add light from the environment.
	CRenderLight RenderLight;

	if(bReallyClose)
	{
		//this is really close, we need to transform it into the world
		g_ViewParams.m_mInvView.Apply(vInstancePosition);
	}

	// Global directional light dir.
	float fDirLightAmount = 0.0f;

	if (g_have_world && g_CV_ModelApplySun.m_Val && 
		(g_pStruct->m_GlobalLightColor.x || g_pStruct->m_GlobalLightColor.y || g_pStruct->m_GlobalLightColor.z))
	{
		// Use the previous lighting amount if it hasn't moved
		if ((pInstance->m_LastDirLightAmount >= 0.0f) &&
			(((pInstance->m_Flags2 & FLAG2_DYNAMICDIRLIGHT) == 0) ||
			(vInstancePosition.NearlyEquals(pInstance->m_LastDirLightPos, g_CV_ModelSunVariance.m_Val + 0.001f))))
		{
			fDirLightAmount = pInstance->m_LastDirLightAmount;
		}
		else
		{
			// Remember where we were last time we did this
			pInstance->m_LastDirLightPos = vInstancePosition;

			// Calculate the lighting
			fDirLightAmount = GetDirLightAmount(pInstance, vInstancePosition);

			// Remember the result
			pInstance->m_LastDirLightAmount = fDirLightAmount;
		}
		
		//setup the direction of the light
		LTVector vDirLightDir = g_pStruct->m_GlobalLightDir;
		if (bReallyClose)
		{
			// Put the lighting in our space
			g_ViewParams.m_mView.Apply3x3(vDirLightDir);
		}

		LTVector vScaledLightColor = g_pStruct->m_GlobalLightColor * fDirLightAmount;

		//add the directional light to the light list
		RenderLight.SetupDirLight(vDirLightDir, vScaledLightColor, FLAG_CASTSHADOWS);
		LightList.InsertLight(RenderLight, g_pStruct->m_GlobalLightConvertToAmbient);
	}

	// Ambient lighting
	if(g_have_world && g_CV_ModelApplyAmbient)
	{
		LTRGBColor ambientColor;
		w_DoLightLookup(world_bsp_shared->LightTable(), &vInstancePosition, &ambientColor);

		LTVector vAmbientLight;
		vAmbientLight.x = ambientColor.rgb.r;
		vAmbientLight.y = ambientColor.rgb.g;
		vAmbientLight.z = ambientColor.rgb.b;

		LightList.AddAmbient(vAmbientLight);
	}


	////////////////////////////////////////////////////////////////////
	// Figure out the lights that will be directionally lighting it.
	
	// Dynamic lights..
	for(uint32 i=0; i < g_nNumObjectDynamicLights; i++)
	{
		DynamicLight* pSrcLight = g_ObjectDynamicLights[i];

		if ((pSrcLight->m_Flags & FLAG_ONLYLIGHTWORLD) != 0)
			continue;

		LTVector vPos = pSrcLight->GetPos();
		if (bReallyClose)
		{
			// Put the lighting in our space
			vPos = g_ViewParams.m_mView * vPos;
		}

		LTVector vColor((float)pSrcLight->m_ColorR, (float)pSrcLight->m_ColorG, (float)pSrcLight->m_ColorB);
		LTVector vAttCoeff(1.0f, 0.0f, 19.0f/(pSrcLight->m_LightRadius*pSrcLight->m_LightRadius));
		RenderLight.SetupPointLight(vPos, vColor, vAttCoeff, pSrcLight->m_LightRadius, eAttenuation_D3D, 0);
		LightList.InsertLight(RenderLight, 0.0f);
	}

	// Static lights..
	if(g_have_world)
	{
		//fill out the callback data structure
		SStaticLightCallbackData CallbackData;
		CallbackData.m_pInstance	= pInstance;
		CallbackData.m_pLightList	= &LightList;

		//figure out what radius to use for this model
		float fModelRadius = pInstance->GetModelDB()->m_VisRadius;

		FindObjInfo foInfo;
		foInfo.m_iObjArray = NOA_Lights;
		foInfo.m_Min = vInstancePosition - LTVector(fModelRadius, fModelRadius, fModelRadius);
		foInfo.m_Max = vInstancePosition + LTVector(fModelRadius, fModelRadius, fModelRadius);
		foInfo.m_CB = &ModelDraw::StaticLightCB;
		foInfo.m_pCBUser = &CallbackData;

		world_bsp_client->ClientTree()->FindObjectsInBox2(&foInfo);
	}
}
Esempio n. 24
0
LTBOOL CAIVolumeMgr::FindDangerScatterPosition(CAIVolume* pVolume, const LTVector& vAIPos, const LTVector& vDangerPos, LTFLOAT fDangerDistanceSqr, LTVector* pvScatterPosition, LTBOOL bNeighbor /* = LTFALSE */)
{
	// Is there a Position in this volume that is sufficiently far from the position in question?

	LTVector avCorners[] = 
	{
		pVolume->GetBackBottomLeft(),
		pVolume->GetBackBottomRight(),
		pVolume->GetFrontBottomLeft(),
		pVolume->GetFrontBottomRight() 
	};

	LTBOOL abCornerValid[] =
	{
		LTFALSE,
		LTFALSE,
		LTFALSE,
		LTFALSE
	};

	LTFLOAT fRandomRadiusModifier = GetRandom(1.0f, 1.0f);

	// Find all valid corners

	{for ( uint iCorner = 0 ; iCorner < 4 ; iCorner++ )
	{
		if ( avCorners[iCorner].DistSqr(vDangerPos) > fDangerDistanceSqr*fRandomRadiusModifier )
		{
			abCornerValid[iCorner] = LTTRUE;
		}
	}}

	// Decide which, if any, of the valid corners, is best for us to use (ie, don't run through the danger radius to get there)

	LTFLOAT fMinimumDistanceSqr = (LTFLOAT)INT_MAX;
	uint32 iCornerBest = -1;

	{for ( uint iCorner = 0 ; iCorner < 4 ; iCorner++ )
	{
		if ( !abCornerValid[iCorner] ) continue;

		LTFLOAT fDistanceSqr = avCorners[iCorner].DistSqr(vAIPos);
		if ( fDistanceSqr < fMinimumDistanceSqr )
		{
			iCornerBest = iCorner;
			fMinimumDistanceSqr = fDistanceSqr;
		}
	}}

	if ( iCornerBest != -1 )
	{
		// Find opposite corner

		_ASSERT(iCornerBest >= 0 && iCornerBest <= 3);

		uint32 iCornerOpposite;

		switch ( iCornerBest )
		{
			case 0:
				iCornerOpposite = 3;
				break;

			case 1:
				iCornerOpposite = 2;
				break;

			case 2:
				iCornerOpposite = 1;
				break;

			case 3:
				iCornerOpposite = 0;
				break;
		}

		// Extend towards opposite corner slightly

		LTVector vOffset = avCorners[iCornerOpposite] - avCorners[iCornerBest];
		vOffset.Norm();
		vOffset *= 50.0f;

		*pvScatterPosition = avCorners[iCornerBest] + vOffset;

		return LTTRUE;
	}

	// No - so look into all the neighbors (only 1 deep!)

	if ( !bNeighbor )
	{
		for ( int32 iNeighbor = 0 ; iNeighbor < pVolume->GetNumNeighbors() ; iNeighbor++ )
		{
			int32 iVolume = pVolume->GetNeighborByIndex(iNeighbor)->GetIndex();

			if ( FindDangerScatterPosition(&m_aVolumes[iVolume], vAIPos, vDangerPos, fDangerDistanceSqr, pvScatterPosition, LTTRUE) )
			{
				return LTTRUE;
			}
		}
	}

	return LTFALSE;
}
Esempio n. 25
0
bool RayIntersectBox(const LTVector& vBoxMin,
                     const LTVector& vBoxMax,
                     const LTVector& vOrigin,
                     const LTVector& vDest,
                     LTVector* pvIntersection)
{
    const uint8 kNumDimensions = 3;

    // Calculate direction of ray.

    LTVector vDir = vDest - vOrigin;
    vDir.Normalize();

    // Algorithm taken from Graphics Gems p.736.

    enum EnumQuadrant
    {
        kQuad_Right,
        kQuad_Left,
        kQuad_Middle,
    };

    bool bInside = true;
    EnumQuadrant eQuad[kNumDimensions];
    LTFLOAT fCandidatePlane[kNumDimensions];

    // Find candidate planes.

    for( uint32 iDim=0; iDim < kNumDimensions; ++iDim )
    {
        if( vOrigin[iDim] < vBoxMin[iDim] )
        {
            if( vDest[iDim] < vBoxMin[iDim] )
            {
                return false;
            }

            eQuad[iDim] = kQuad_Left;
            fCandidatePlane[iDim] = vBoxMin[iDim];
            bInside = false;
        }
        else if( vOrigin[iDim] > vBoxMax[iDim] )
        {
            if( vDest[iDim] > vBoxMax[iDim] )
            {
                return false;
            }

            eQuad[iDim] = kQuad_Right;
            fCandidatePlane[iDim] = vBoxMax[iDim];
            bInside = false;
        }
        else {
            eQuad[iDim] = kQuad_Middle;
        }
    }

    // Ray origin is inside volume.

    if( bInside )
    {
        *pvIntersection = vOrigin;
        return true;
    }

    uint32 nWhichPlane = 0;
    LTFLOAT fMaxT[kNumDimensions];

    // Calculate T distances to candidate planes.

    for(int iDim=0; iDim < kNumDimensions; ++iDim )
    {
        if( ( eQuad[iDim] != kQuad_Middle ) && ( vDir[iDim] != 0.f ) )
        {
            fMaxT[iDim] = ( fCandidatePlane[iDim] - vOrigin[iDim] ) / vDir[iDim];
        }
        else {
            fMaxT[iDim] = -1.f;
        }
    }

    // Get largest of the maxT's for final choice of intersection.

    for(int iDim=1; iDim < kNumDimensions; ++iDim )
    {
        if( fMaxT[nWhichPlane] < fMaxT[iDim] )
        {
            nWhichPlane = iDim;
        }
    }

    // Check final candidate actually inside volume.

    if( fMaxT[nWhichPlane] < 0.f )
    {
        return false;
    }

    for(int iDim=0; iDim < kNumDimensions; ++iDim )
    {
        if( nWhichPlane != iDim )
        {
            (*pvIntersection)[iDim] = vOrigin[iDim] + fMaxT[nWhichPlane] * vDir[iDim];
            if( ((*pvIntersection)[iDim] < vBoxMin[iDim]) ||
                    ((*pvIntersection)[iDim] > vBoxMax[iDim]) )
            {
                return false;
            }
        }
        else {
            (*pvIntersection)[iDim] = fCandidatePlane[iDim];
        }
    }

    return true;
}