void CSFXMgr::DirtyVisibleRenderTargets() { //run through all of our render targets and tell them to update CSpecialFXList* pRenderTargetList = GetFXList(SFX_RENDERTARGET_ID); if(pRenderTargetList && (pRenderTargetList->GetNumItems() > 0)) { //run through the list finding those that are initialized for(uint32 nCurrRenderTarget = 0; nCurrRenderTarget < (uint32)pRenderTargetList->GetSize(); nCurrRenderTarget++) { CSpecialFX* pEffect = (*pRenderTargetList)[nCurrRenderTarget]; if(pEffect) { //and now that we have found one, tell it to dirty ((CRenderTargetFX*)pEffect)->DirtyIfVisible(); } } } }
void CSFXMgr::UpdateRenderTargets(const LTRigidTransform& tCamera, const LTVector2& vCameraFOV) { //run through all of our render targets and tell them to update CSpecialFXList* pRenderTargetList = GetFXList(SFX_RENDERTARGET_ID); if(pRenderTargetList && (pRenderTargetList->GetNumItems() > 0)) { //run through the list finding those that are initialized for(uint32 nCurrRenderTarget = 0; nCurrRenderTarget < (uint32)pRenderTargetList->GetSize(); nCurrRenderTarget++) { CSpecialFX* pEffect = (*pRenderTargetList)[nCurrRenderTarget]; if(pEffect) { //and now that we have found one, tell it to update ((CRenderTargetFX*)pEffect)->UpdateRenderTarget(tCamera, vCameraFOV); } } } }
bool CTargetMgr::CheckForCharacters(LTVector vObjPos,LTVector vDims, uint8 nId) { float fLeashLen = GetConsoleFloat("LeashLen",0.0f); //give 'em some room vDims.x += fLeashLen; vDims.y += fLeashLen; vDims.z += fLeashLen; vDims *= 2.0f; CSpecialFXList* pList = g_pGameClientShell->GetSFXMgr()->GetFXList(SFX_CHARACTER_ID); if (!pList) return false; int nNumChars = pList->GetSize(); LTVector vCharPos, vCharDims; for (int i=0; i < nNumChars; i++) { if ((*pList)[i]) { CCharacterFX* pChar = (CCharacterFX*)(*pList)[i]; if (pChar->m_cs.bIsPlayer && pChar->m_cs.nClientID == nId) continue; g_pLTClient->GetObjectPos(pChar->GetServerObj(), &vCharPos); if (vObjPos.x - vDims.x < vCharPos.x && vCharPos.x < vObjPos.x + vDims.x && vObjPos.y - vDims.y < vCharPos.y && vCharPos.y < vObjPos.y + vDims.y && vObjPos.z - vDims.z < vCharPos.z && vCharPos.z < vObjPos.z + vDims.z) { return true; } } } return false; }
DBOOL CMarkSFX::CreateObject(CClientDE *pClientDE) { if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE; CSFXMgr* psfxMgr = g_pBloodClientShell->GetSFXMgr(); if (!psfxMgr) return DFALSE; // Before we create a new buillet hole see if there is already another // bullet hole close by that we could use instead... CSpecialFXList* pList = psfxMgr->GetBulletHoleFXList(); if (!pList) return DFALSE; int nNumBulletHoles = pList->GetSize(); HOBJECT hMoveObj = DNULL; HOBJECT hObj = DNULL; DFLOAT fClosestMarkDist = REGION_DIAMETER; DBYTE nNumInRegion = 0; DVector vPos; for (int i=0; i < nNumBulletHoles; i++) { if ((*pList)[i]) { hObj = (*pList)[i]->GetObject(); if (hObj) { pClientDE->GetObjectPos(hObj, &vPos); DFLOAT fDist = VEC_DISTSQR(vPos, m_Pos); if (fDist < REGION_DIAMETER) { if (fDist < fClosestMarkDist) { fClosestMarkDist = fDist; hMoveObj = hObj; } if (++nNumInRegion > MAX_MARKS_IN_REGION) { // Just move this bullet-hole to the correct pos, and // remove thyself... pClientDE->SetObjectPos(hMoveObj, &m_Pos); return DFALSE; } } } } } // Setup the mark... ObjectCreateStruct createStruct; INIT_OBJECTCREATESTRUCT(createStruct); createStruct.m_ObjectType = OT_SPRITE; _mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_pClientDE->GetStringData( m_hstrSprite )); createStruct.m_Flags = FLAG_VISIBLE | FLAG_ROTATEABLESPRITE; VEC_COPY(createStruct.m_Pos, m_Pos); ROT_COPY( createStruct.m_Rotation, m_Rotation ); m_hObject = pClientDE->CreateObject(&createStruct); m_pClientDE->SetObjectScale(m_hObject, &m_vScale); // See what it hit DVector vU, vR; pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &m_vForward); ClientIntersectQuery iq; ClientIntersectInfo ii; iq.m_Flags = INTERSECT_OBJECTS | INTERSECT_HPOLY; VEC_COPY(iq.m_From, vPos); // Get start point at the last known position. VEC_MULSCALAR(iq.m_To, m_vForward, -1.0f); VEC_ADD(iq.m_To, iq.m_To, iq.m_From); // Get destination point slightly past where we should be // Hit something! try to clip against it. (since this is only being used for bullet marks, if (pClientDE->IntersectSegment(&iq, &ii)) { HPOLY hPoly = ii.m_hPoly; pClientDE->ClipSprite(m_hObject, hPoly); } m_pClientDE->SetObjectColor(m_hObject, 0.1f, 0.1f, 0.1f, 1.0f); return DTRUE; }
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; } }
void CTriggerFX::CheckPlayersWithinTrigger() { if( m_cs.bLocked ) return; // Get a list of all the characters... CSpecialFXList *pList = g_pGameClientShell->GetSFXMgr()->GetFXList( SFX_CHARACTER_ID ); if( !pList ) return; int nListSize = pList->GetSize(); int nNumChars = pList->GetNumItems(); int nNumFoundChars = 0; int nNumPlayersFound = 0; uint32 dwLocalId = 0; g_pLTClient->GetLocalClientID( &dwLocalId ); LTVector vTrigPos, vPlayerPos, vPlayerDims, vPlayerMin, vPlayerMax; g_pLTClient->GetObjectPos( m_hServerObject, &vTrigPos ); // Setup the triggers box... LTVector vTrigMin = vTrigPos - m_cs.vDims; LTVector vTrigMax = vTrigPos + m_cs.vDims; bool bLocalPlayerIn = false; // Initialize our containers to zero. Don't call clear, since we'll be using // these vectors every frame and most likely they will have the same // number of elements across multiple frames. m_lstPlayersNotInTrigger.resize( 0 ); m_lstNewPlayersInTrigger.resize( 0 ); for( int i = 0; i < nListSize; ++i ) { // Try not to go through the entire list... if( nNumFoundChars == nNumChars ) break; if( (*pList)[i] ) { CCharacterFX *pChar = (CCharacterFX*)(*pList)[i]; if( !pChar ) continue; // Found another char.. ++nNumFoundChars; if( pChar->m_cs.bIsPlayer && pChar->m_cs.nClientID != ( uint8 )-1 ) { ++nNumPlayersFound; HOBJECT hPlayer = pChar->GetServerObj(); g_pLTClient->GetObjectPos( hPlayer, &vPlayerPos ); g_pPhysicsLT->GetObjectDims( hPlayer, &vPlayerDims ); vPlayerMin = vPlayerPos - vPlayerDims; vPlayerMax = vPlayerPos + vPlayerDims; // Check the current list of players in the trigger for this player... CharFXList::iterator iter; for( iter = m_lstCurPlayersInTrigger.begin(); iter != m_lstCurPlayersInTrigger.end(); ++iter ) { if( pChar == (*iter) ) break; } // Check if we are within the height of the trigger... bool bWithinHeight = false; if( vPlayerMax.y > vTrigMin.y && vPlayerMin.y < vTrigMax.y ) bWithinHeight = true; if( bWithinHeight && BoxesIntersect( vTrigMin, vTrigMax, vPlayerMin, vPlayerMax ) && !pChar->IsPlayerDead()) { if( dwLocalId == pChar->m_cs.nClientID ) bLocalPlayerIn = true; // If it wasn't in the list add it... if( iter == m_lstCurPlayersInTrigger.end() ) { m_lstCurPlayersInTrigger.push_back( pChar ); m_lstNewPlayersInTrigger.push_back( pChar ); } } else { if( iter != m_lstCurPlayersInTrigger.end() ) m_lstCurPlayersInTrigger.erase( iter ); m_lstPlayersNotInTrigger.push_back( pChar ); } } } } wchar_t wszBuffer[256]; if( (m_lstNewPlayersInTrigger.size() > 0) && (nNumPlayersFound > 1) ) { CClientInfoMgr *pInfoMgr = g_pInterfaceMgr->GetClientInfoMgr(); if( !pInfoMgr ) return; if( bLocalPlayerIn ) { // Display a general transmission and messages for each player you are waiting for... int nPlayersNotInTrig = m_lstPlayersNotInTrigger.size(); if( m_cs.nPlayerInsideID != (uint32)-1 ) { g_pTransmission->Show( StringIDFromIndex(m_cs.nPlayerInsideID) ); } else if( nPlayersNotInTrig > 1 ) { //sTransmission.Format( "You are waiting for %i players.", nPlayersNotInTrig ); FormatString( "IDS_EXIT_PLAYER_WAITING", wszBuffer, LTARRAYSIZE(wszBuffer), nPlayersNotInTrig ); g_pTransmission->Show( wszBuffer ); } else { //sTransmission.Format( "You are waiting for 1 player." ); FormatString( "IDS_EXIT_PLAYER_WAITING_1", wszBuffer, LTARRAYSIZE(wszBuffer) ); g_pTransmission->Show( wszBuffer ); } CharFXList::iterator iter; for( iter = m_lstPlayersNotInTrigger.begin(); iter != m_lstPlayersNotInTrigger.end(); ++iter ) { //sMessage.Format( "You are waiting for %s.", pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID )); FormatString( "IDS_EXIT_PLAYER_WAITING_NAME", wszBuffer, LTARRAYSIZE(wszBuffer), pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID) ); g_pGameMsgs->AddMessage( wszBuffer ); } } else { // Display a general transmission and messages for each player waiting for you... int nPlayersInTrig = m_lstCurPlayersInTrigger.size(); if( m_cs.nPlayerOutsideID != (uint32)-1 ) { g_pTransmission->Show( LoadString(m_cs.nPlayerOutsideID) ); } else if( nPlayersInTrig > 1 ) { // sTransmission.Format( "%i players are waiting for you",nPlayersInTrig ); FormatString( "IDS_EXIT_WAITING", wszBuffer, LTARRAYSIZE(wszBuffer), nPlayersInTrig ); g_pTransmission->Show( wszBuffer ); } else { // sTransmission.Format( "1 player is waiting for you." ); FormatString( "IDS_EXIT_WAITING_1", wszBuffer, LTARRAYSIZE(wszBuffer) ); g_pTransmission->Show( wszBuffer ); } CharFXList::iterator iter; for( iter = m_lstCurPlayersInTrigger.begin(); iter != m_lstCurPlayersInTrigger.end(); ++iter ) { FormatString( "IDS_EXIT_WAITING_NAME", wszBuffer, LTARRAYSIZE(wszBuffer), pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID) ); g_pGameMsgs->AddMessage( wszBuffer ); } } } }