diff --git a/SAFix/GeneralSA.cpp b/SAFix/GeneralSA.cpp index b9242e2..49bdc47 100644 --- a/SAFix/GeneralSA.cpp +++ b/SAFix/GeneralSA.cpp @@ -1,10 +1,15 @@ #include "StdAfxSA.h" #include "GeneralSA.h" +#include "PedSA.h" + // Wrappers static void* EntityRender = AddressByVersion(0x534310, 0, 0); WRAPPER void CEntity::Render() { VARJMP(EntityRender); } +static void* varInvertRaster = AddressByVersion(0x705660, 0, 0); +WRAPPER void CShadowCamera::InvertRaster() { VARJMP(varInvertRaster); } + CWeaponInfo* (*CWeaponInfo::GetWeaponInfo)(eWeaponType, signed char) = AddressByVersion(0x743C60, 0, 0); static RwTexture*& ms_pRemapTexture = **AddressByVersion(0x59F1BD, 0, 0); @@ -26,6 +31,24 @@ static void ResetEditableMaterials(std::pair* pData) *static_cast(i->first) = i->second; } +RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData) +{ + UNREFERENCED_PARAMETER(pData); + + if ( RpAtomicGetFlags(pAtomic) & rpATOMICRENDER ) + { + RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic); + RwUInt32 geometryFlags = RpGeometryGetFlags(pGeometry); + + RpGeometrySetFlags(pGeometry, geometryFlags & ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT| + /*rpGEOMETRYNORMALS|*/rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2)); + + AtomicDefaultRenderCallBack(pAtomic); + RpGeometrySetFlags(pGeometry, geometryFlags); + } + return pAtomic; +} + void CObject::Render() { if ( m_bDoNotRender || !m_pRwObject ) @@ -53,4 +76,25 @@ void CObject::Render() if ( bCallRestore ) ResetEditableMaterials(materialRestoreData); +} + +RwCamera* CShadowCamera::Update(CEntity* pEntity) +{ + RwRGBA ClearColour = { 255, 255, 255, 0 }; + RwCameraClear(m_pCamera, &ClearColour, rwCAMERACLEARIMAGE|rwCAMERACLEARZ); + + if ( RwCameraBeginUpdate(m_pCamera ) ) + { + if ( pEntity ) + { + if ( pEntity->nType == 3 ) + static_cast(pEntity)->RenderForShadow(); + else + RpClumpForAllAtomics(reinterpret_cast(pEntity->m_pRwObject), ShadowCameraRenderCB, nullptr); + } + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + return m_pCamera; } \ No newline at end of file diff --git a/SAFix/GeneralSA.h b/SAFix/GeneralSA.h index 0f1f0a1..cdcbc95 100644 --- a/SAFix/GeneralSA.h +++ b/SAFix/GeneralSA.h @@ -549,6 +549,20 @@ public: static CWeaponInfo* (*GetWeaponInfo)(eWeaponType weaponID, signed char bType); }; +class CShadowCamera +{ +public: + RwCamera* m_pCamera; + RwTexture* m_pTexture; + +public: + void InvertRaster(); + + RwCamera* Update(CEntity* pEntity); +}; + +RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData); + static_assert(sizeof(CEntity) == 0x38, "Wrong size: CEntity"); static_assert(sizeof(CPhysical) == 0x138, "Wrong size: CPhysical"); static_assert(sizeof(CObject) == 0x17C, "Wrong size: CObject"); diff --git a/SAFix/PedSA.cpp b/SAFix/PedSA.cpp index 65212b0..d7e99af 100644 --- a/SAFix/PedSA.cpp +++ b/SAFix/PedSA.cpp @@ -8,6 +8,12 @@ WRAPPER void CPed::ResetGunFlashAlpha() { VARJMP(varResetGunFlashAlpha); } static void* varSetGunFlashAlpha = AddressByVersion(0x5DF400, 0, 0); WRAPPER void CPed::SetGunFlashAlpha(bool bSecondWeapon) { WRAPARG(bSecondWeapon); VARJMP(varSetGunFlashAlpha); } +static void* varGetTaskJetPack = AddressByVersion(0x601110, 0, 0); +WRAPPER CTaskSimpleJetPack* CPedIntelligence::GetTaskJetPack() const { VARJMP(varGetTaskJetPack); } + +static void* varRenderJetPack = AddressByVersion(0x67F6A0, 0, 0); +WRAPPER void CTaskSimpleJetPack::RenderJetPack(CPed* pPed) { WRAPARG(pPed); VARJMP(varRenderJetPack); } + static RwObject* GetFirstObjectCallback(RwObject* pObject, void* pData) { *static_cast(pData) = pObject; @@ -21,7 +27,7 @@ RwObject* GetFirstObject(RwFrame* pFrame) return pObject; } -void CPed::RenderWeapon(bool bMuzzleFlash) +void CPed::RenderWeapon(bool bMuzzleFlash, bool bForShadow) { if ( m_pWeaponObject ) { @@ -40,10 +46,10 @@ void CPed::RenderWeapon(bool bMuzzleFlash) } RwFrameUpdateObjects(pFrame); - if ( !bMuzzleFlash ) - { + if ( bForShadow ) + RpClumpForAllAtomics(reinterpret_cast(m_pWeaponObject), ShadowCameraRenderCB, nullptr); + else if ( !bMuzzleFlash ) RpClumpRender(reinterpret_cast(m_pWeaponObject)); - } else if ( m_pMuzzleFlashFrame ) { SetGunFlashAlpha(false); @@ -61,10 +67,10 @@ void CPed::RenderWeapon(bool bMuzzleFlash) RwMatrixTranslate(RwFrameGetMatrix(pFrame), &vecParachuteTranslation, rwCOMBINEPRECONCAT); RwFrameUpdateObjects(pFrame); - if ( !bMuzzleFlash ) - { + if ( bForShadow ) + RpClumpForAllAtomics(reinterpret_cast(m_pWeaponObject), ShadowCameraRenderCB, nullptr); + else if ( !bMuzzleFlash ) RpClumpRender(reinterpret_cast(m_pWeaponObject)); - } else if ( m_pMuzzleFlashFrame ) { SetGunFlashAlpha(true); @@ -74,4 +80,15 @@ void CPed::RenderWeapon(bool bMuzzleFlash) if ( bMuzzleFlash ) ResetGunFlashAlpha(); } +} + +void CPed::RenderForShadow() +{ + RpClumpForAllAtomics(reinterpret_cast(m_pRwObject), ShadowCameraRenderCB, nullptr); + RenderWeapon(false, true); + + // Render jetpack + auto* pJetPackTask = pPedIntelligence->GetTaskJetPack(); + if ( pJetPackTask ) + pJetPackTask->RenderJetPack(this); } \ No newline at end of file diff --git a/SAFix/PedSA.h b/SAFix/PedSA.h index 2ef18fb..cd37aa6 100644 --- a/SAFix/PedSA.h +++ b/SAFix/PedSA.h @@ -5,6 +5,19 @@ class CEntryExit; +// Stub +class CTaskSimpleJetPack +{ +public: + void RenderJetPack(class CPed* pPed); +}; + +class CPedIntelligence +{ +public: + class CTaskSimpleJetPack* GetTaskJetPack() const; +}; + class CPedFlags { public: @@ -297,7 +310,8 @@ public: void ResetGunFlashAlpha(); void SetGunFlashAlpha(bool bSecondWeapon); - void RenderWeapon(bool bMuzzleFlash); + void RenderWeapon(bool bMuzzleFlash, bool bForShadow); + void RenderForShadow(); }; static_assert(sizeof(CPed) == 0x79C, "Wrong size: CPed"); diff --git a/SAFix/SilentPatchSA.cpp b/SAFix/SilentPatchSA.cpp index ff488cc..15eb673 100644 --- a/SAFix/SilentPatchSA.cpp +++ b/SAFix/SilentPatchSA.cpp @@ -51,6 +51,21 @@ WRAPPER RwBool _rpD3D9VertexDeclarationInstColor(RwUInt8 *mem, RwUInt32 stride) { VARJMP(var_rpD3D9VertexDeclarationInstColor); } +RwCamera* RwCameraBeginUpdate(RwCamera* camera) +{ + return camera->beginUpdate(camera); +} + +RwCamera* RwCameraEndUpdate(RwCamera* camera) +{ + return camera->endUpdate(camera); +} + +RwCamera* RwCameraClear(RwCamera* camera, RwRGBA* colour, RwInt32 clearMode) +{ + return RWSRCGLOBAL(stdFunc[rwSTANDARDCAMERACLEAR])(camera, colour, clearMode) != FALSE ? camera : NULL; +} + RwFrame* RwFrameForAllChildren(RwFrame* frame, RwFrameCallBack callBack, void* data) { for ( RwFrame* curFrame = frame->child; curFrame; curFrame = curFrame->next ) @@ -452,7 +467,7 @@ void SetRendererForAtomic(RpAtomic* pAtomic) void RenderWeapon(CPed* pPed) { - pPed->RenderWeapon(false); + pPed->RenderWeapon(false, false); ms_weaponPedsForPC.Insert(pPed); } @@ -464,7 +479,7 @@ void RenderWeaponPedsForPC() for ( auto it = ms_weaponPedsForPC.m_lnListHead.m_pNext; it != &ms_weaponPedsForPC.m_lnListTail; it = it->m_pNext ) { it->V()->SetupLighting(); - it->V()->RenderWeapon(true); + it->V()->RenderWeapon(true, false); it->V()->RemoveLighting(); } } @@ -1327,6 +1342,13 @@ BOOL InjectDelayedPatches_10() Nop(0x6D6517, 2); } + // SSE conflicts + if ( GetModuleHandle("shadows.asi") == nullptr ) + { + Patch(0x70665C, 0x52909090); + InjectHook(0x706662, &CShadowCamera::Update); + } + // Bigger streamed entity linked lists // Increase only if they're not increased already if ( *(DWORD*)0x5B8E55 == 12000 )