void CFlashLight::Update() { if (!m_bOn || !m_hLight) return; // Calculate light position... HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (!hPlayerObj) return; HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL}; IntersectQuery qInfo; IntersectInfo iInfo; LTVector vPos, vEndPos, vUOffset, vROffset; GetLightPositions(vPos, vEndPos, vUOffset, vROffset); qInfo.m_From = vPos; qInfo.m_To = vEndPos; qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; qInfo.m_FilterFn = NonSolidFilterFn; qInfo.m_pUserData = hFilterList; if (g_pLTClient->IntersectSegment(&qInfo, &iInfo)) { vEndPos = iInfo.m_Point; } g_pLTClient->SetObjectPos(m_hLight, &vEndPos); LTVector vDir = vEndPos - vPos; LTFLOAT fDist = vDir.Length(); vDir *= 1.0f / fDist; LTFLOAT fLightRadius = g_cvarFLMinLightRadius.GetFloat() + ((g_cvarFLMaxLightRadius.GetFloat() - g_cvarFLMinLightRadius.GetFloat()) * fDist / g_cvarFLLightOffsetForward.GetFloat()); g_pLTClient->SetLightRadius(m_hLight, fLightRadius); LTVector vColor; vColor.y = vColor.z = vColor.x = GetRandom(g_cvarFLMinLightColor.GetFloat(), g_cvarFLMaxLightColor.GetFloat()); LTVector vLightColor = vColor / 255.0f; g_pLTClient->SetLightColor(m_hLight, vLightColor.x, vLightColor.y, vLightColor.z); }
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 ); } }
LTBOOL CAIMovement::UpdateMovementEncoding( EnumAnimMovement eMovementType, LTVector* pvNewPos ) { // Encode_NG means encoding with NoGravity. if( ( eMovementType == kAM_Encode_NG ) || ( eMovementType == kAM_Encode_V ) ) { // Turn off gravity m_pAI->SetCheapMovement(LTFALSE); m_bIgnoreVolumes = LTTRUE; } LTVector vHintPosDelta; LTRotation rHintRotDelta; g_pTransLT->Get( m_pAI->GetLastHintTransform(), vHintPosDelta, rHintRotDelta ); LTRotation rRot; g_pLTServer->GetObjectRotation( m_pAI->m_hObject, &rRot ); rRot = rRot * rHintRotDelta; LTFLOAT fInvMag = 1.0f/(LTFLOAT)sqrt(rRot.m_Quat[0]*rRot.m_Quat[0] + rRot.m_Quat[1]*rRot.m_Quat[1] + rRot.m_Quat[2]*rRot.m_Quat[2] + rRot.m_Quat[3]*rRot.m_Quat[3]); rRot.m_Quat[0] *= fInvMag; rRot.m_Quat[1] *= fInvMag; rRot.m_Quat[2] *= fInvMag; rRot.m_Quat[3] *= fInvMag; g_pLTServer->SetObjectRotation( m_pAI->m_hObject, &rRot ); LTVector vOldPos; g_pLTServer->GetObjectPos( m_pAI->m_hObject, &vOldPos ); // No destination is set, so just add the hint vector. if( m_eState != eStateSet ) { *pvNewPos = vOldPos + vHintPosDelta; } // A destination has been set, so just use the magnitude of // the xz compnents of the hint vector, to guarantee we're // headed to our dest. else { if( vOldPos == m_vDest ) { Clear(); m_eState = eStateDone; return LTFALSE; } LTVector vOldDirToDest; LTVector vNewDirToDest; if( eMovementType == kAM_Encode_V ) { // Get the direction from the old pos to the dest. vOldDirToDest = m_vDest - vOldPos; vOldDirToDest.Normalize(); // Set the new pos to the sum of the old pos, and the // magnitude of the xz components of the hint, towards // the dest. Then add the y component. *pvNewPos = vOldPos + ( vOldDirToDest * vHintPosDelta.Length() ); // See if we'll overshoot our dest. vNewDirToDest = m_vDest - *pvNewPos; vNewDirToDest.Normalize(); } else { // Get the direction from the old pos to the dest. vOldDirToDest = m_vDest - vOldPos; vOldDirToDest.y = 0.f; vOldDirToDest.Normalize(); // Get the x and z components of the hint vector. LTVector vHintXZ = vHintPosDelta; vHintXZ.y = 0.f; // Set the new pos to the sum of the old pos, and the // magnitude of the xz components of the hint, towards // the dest. Then add the y component. *pvNewPos = vOldPos + ( vOldDirToDest * vHintXZ.Length() ); pvNewPos->y += vHintPosDelta.y; // See if we'll overshoot our dest. vNewDirToDest = m_vDest - *pvNewPos; vNewDirToDest.y = 0.f; vNewDirToDest.Normalize(); } if( vOldDirToDest.Dot(vNewDirToDest) < 0.f ) { Clear(); m_eState = eStateDone; *pvNewPos = m_vDest; // If the movement is not vertical, then do not affect the // elevation of the AI. Let CheapMovement take care of // putting the AI on the ground. if( eMovementType != kAM_Encode_V ) { pvNewPos->y = m_pAI->GetPosition().y; } } else if( m_bFaceDest ) { // Face backwards. if( eMovementType == kAM_Encode_GB ) { LTVector vFacePos = vOldPos - vOldDirToDest; m_pAI->FacePosMoving( vFacePos ); } // Face forwards. else { m_pAI->FacePosMoving( m_vDest ); } } } return LTTRUE; }