#include "StdAfxSA.h" #include "VehicleSA.h" #include "TimerSA.h" void (*CVehicle::SetComponentAtomicAlpha)(RpAtomic* pAtomic, int nAlpha) = AddressByVersion(0x6D2960, 0, 0); static void* varVehicleRender = AddressByVersion(0x6D0E60, 0, 0); WRAPPER void CVehicle::Render() { VARJMP(varVehicleRender); } static void* varIsLawEnforcementVehicle = AddressByVersion(0x6D2370, 0, 0); WRAPPER bool CVehicle::IsLawEnforcementVehicle() { VARJMP(varIsLawEnforcementVehicle); } static RwObject* GetCurrentAtomicObjectCB(RwObject* pObject, void* data) { if ( RpAtomicGetFlags(pObject) & rpATOMICRENDER ) { *static_cast(data) = pObject; return nullptr; } return pObject; } static RwFrame* GetFrameFromNameCB(RwFrame* pFrame, void* pData) { // Is this a frame we want? std::pair* pFindData = static_cast*>(pData); if ( !strncmp(pFindData->first, GetFrameNodeName(pFrame), 24) ) { pFindData->second = pFrame; return nullptr; } // Try children RwFrameForAllChildren(pFrame, GetFrameFromNameCB, pData); return !pFindData->second ? pFrame : nullptr; } bool CVehicle::CustomCarPlate_TextureCreate(CVehicleModelInfo* pModelInfo) { char PlateText[8]; const char* pOverrideText = pModelInfo->GetCustomCarPlateText(); if ( pOverrideText ) strncpy(PlateText, pOverrideText, 8); else CCustomCarPlateMgr::GeneratePlateText(PlateText, 8); PlateTexture = CCustomCarPlateMgr::CreatePlateTexture(PlateText, pModelInfo->m_nPlateType); //PlateDesign = pModelInfo->m_nPlateType != -1 ? pModelInfo->m_nPlateType : CCustomCarPlateMgr::GetMapRegionPlateDesign(); if ( pModelInfo->m_nPlateType != -1 ) PlateDesign = pModelInfo->m_nPlateType; else if ( IsLawEnforcementVehicle() ) PlateDesign = CCustomCarPlateMgr::GetMapRegionPlateDesign(); else PlateDesign = random(0, 20) == 0 ? random(0, 3) : CCustomCarPlateMgr::GetMapRegionPlateDesign(); assert(PlateDesign >= 0 && PlateDesign < 3); pModelInfo->m_plateText[0] = '\0'; pModelInfo->m_nPlateType = -1; return true; } //static RwTexture* pPushedTextures[NUM_MAX_PLATES]; void CVehicle::CustomCarPlate_BeforeRenderingStart(CVehicleModelInfo* pModelInfo) { //CCustomCarPlateMgr::SetupPlates(reinterpret_cast(pModelInfo->pRwObject), PlateTexture, PlateDesign); for ( int i = 0; i < NUM_MAX_PLATES; i++ ) { if ( pModelInfo->m_apPlateMaterials[i] ) { //RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]); //RwTextureAddRef(pPlateTex); //pPushedTextures[i] = pPlateTex; RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture); } if ( pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i] ) CCustomCarPlateMgr::SetupMaterialPlatebackTexture(pModelInfo->m_apPlateMaterials[NUM_MAX_PLATES+i], PlateDesign); //RwTexture* pPlatebackTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[4+i]); //RwTextureAddRef(pPlatebackTex); //pPushedTextures[4+i] = pPlateTex; //RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], PlateTexture); } } // This is not needed /*void CVehicle::CustomCarPlate_AfterRenderingStop(CVehicleModelInfo* pModelInfo) { for ( int i = 0; i < NUM_MAX_PLATES; i++ ) { if ( pModelInfo->m_apPlateMaterials[i] ) { //RwTexture* pPlateTex = RpMaterialGetTexture(pModelInfo->m_apPlateMaterials[i]); //RwTextureAddRef(pPlateTex); //pPushedTextures[i] = pPlateTex; //RpMaterialSetTexture(pModelInfo->m_apPlateMaterials[i], pPushedTextures[i]); //RwTextureDestroy(pPushedTextures[i]); //pPushedTextures[i] = nullptr; } } }*/ void CHeli::Render() { double dRotorsSpeed, dMovingRotorSpeed; bool bHasMovingRotor = m_pCarNode[13] != nullptr; bool bHasMovingRotor2 = m_pCarNode[15] != nullptr; m_nTimeTillWeNeedThisCar = CTimer::m_snTimeInMilliseconds + 3000; if ( m_fRotorSpeed > 0.0 ) dRotorsSpeed = min(1.7 * (1.0/0.22) * m_fRotorSpeed, 1.5); else dRotorsSpeed = 0.0; dMovingRotorSpeed = dRotorsSpeed - 0.4; if ( dMovingRotorSpeed < 0.0 ) dMovingRotorSpeed = 0.0; int nStaticRotorAlpha = static_cast(min((1.5-dRotorsSpeed) * 255.0, 255)); int nMovingRotorAlpha = static_cast(min(dMovingRotorSpeed * 175.0, 175)); if ( m_pCarNode[12] ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor ? nStaticRotorAlpha : 255); } if ( m_pCarNode[14] ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, bHasMovingRotor2 ? nStaticRotorAlpha : 255); } if ( bHasMovingRotor ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); } if ( bHasMovingRotor2 ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[15], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); } CEntity::Render(); } void CPlane::Render() { double dRotorsSpeed, dMovingRotorSpeed; bool bHasMovingProp = m_pCarNode[13] != nullptr; bool bHasMovingProp2 = m_pCarNode[15] != nullptr; m_nTimeTillWeNeedThisCar = CTimer::m_snTimeInMilliseconds + 3000; if ( m_fPropellerSpeed > 0.0 ) dRotorsSpeed = min(1.7 * (1.0/0.31) * m_fPropellerSpeed, 1.5); else dRotorsSpeed = 0.0; dMovingRotorSpeed = dRotorsSpeed - 0.4; if ( dMovingRotorSpeed < 0.0 ) dMovingRotorSpeed = 0.0; int nStaticRotorAlpha = static_cast(min((1.5-dRotorsSpeed) * 255.0, 255)); int nMovingRotorAlpha = static_cast(min(dMovingRotorSpeed * 175.0, 175)); if ( m_pCarNode[12] ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[12], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp ? nStaticRotorAlpha : 255); } if ( m_pCarNode[14] ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[14], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, bHasMovingProp2 ? nStaticRotorAlpha : 255); } if ( bHasMovingProp ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[13], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); } if ( bHasMovingProp2 ) { RpAtomic* pOutAtomic = nullptr; RwFrameForAllObjects(m_pCarNode[15], GetCurrentAtomicObjectCB, &pOutAtomic); if ( pOutAtomic ) SetComponentAtomicAlpha(pOutAtomic, nMovingRotorAlpha); } CVehicle::Render(); } void CPlane::Fix_SilentPatch() { // Reset bouncing panels for ( int i = 0; i < 3; i++ ) { // No reset on Vortex if ( i == 0 && m_nModelIndex == 539 ) continue; m_aBouncingPanel[i].m_nNodeIndex = -1; } } void CAutomobile::Fix_SilentPatch() { ResetFrames(); // Reset bouncing panels for ( int i = 0; i < 3; i++ ) { // Towtruck/Tractor fix if ( i == 0 && ((m_nModelIndex == 525 && m_pCarNode[21]) || (m_nModelIndex == 531 && m_pCarNode[17])) ) continue; m_aBouncingPanel[i].m_nNodeIndex = -1; } } void CAutomobile::ResetFrames() { RpClump* pOrigClump = reinterpret_cast(ms_modelInfoPtrs[m_nModelIndex]->pRwObject); if ( pOrigClump ) { // Instead of setting frame rotation to (0,0,0) like R* did, obtain the original frame matrix from CBaseNodelInfo clump for ( int i = 8; i < 25; i++ ) { if ( m_pCarNode[i] ) { // Find a frame in CBaseModelInfo object std::pair FindData = std::make_pair(GetFrameNodeName(m_pCarNode[i]), nullptr); RwFrameForAllChildren(RpClumpGetFrame(pOrigClump), GetFrameFromNameCB, &FindData); if ( FindData.second ) { // Found a frame, reset it *RwFrameGetMatrix(m_pCarNode[i]) = *RwFrameGetMatrix(FindData.second); RwMatrixUpdate(RwFrameGetMatrix(m_pCarNode[i])); } } } } }