From 65f3a9b8dfc9c54013edfa4253535857ca360ebf Mon Sep 17 00:00:00 2001 From: Silent Date: Thu, 24 Jul 2014 14:11:46 +0200 Subject: [PATCH] Realtime shadows for vehicles! --- VCS PC/Frontend.h | 10 ++- VCS PC/Ped.cpp | 52 +++++++++++++++ VCS PC/Ped.h | 1 + VCS PC/Pools.cpp | 1 + VCS PC/Pools.h | 5 ++ VCS PC/RealTimeShadowMgr.cpp | 126 +++++++++++++++++++---------------- VCS PC/RealTimeShadowMgr.h | 22 ++++-- VCS PC/Shadows.cpp | 48 ++++++++++--- VCS PC/Shadows.h | 1 + VCS PC/StdAfx.h | 2 +- VCS PC/Tasks.cpp | 15 ++++- VCS PC/Tasks.h | 80 +++++++++++++++++++++- VCS PC/VCSPC.cpp | 19 +++++- VCS PC/Vehicle.cpp | 21 ++++++ VCS PC/Vehicle.h | 34 +++++++++- 15 files changed, 351 insertions(+), 86 deletions(-) diff --git a/VCS PC/Frontend.h b/VCS PC/Frontend.h index 25c9ac6..bffcc1e 100644 --- a/VCS PC/Frontend.h +++ b/VCS PC/Frontend.h @@ -29,9 +29,13 @@ #define MENU_ACTIVE_G 0xEC #define MENU_ACTIVE_B 0x93 -#define MENU_LOCKED_R 0x06 -#define MENU_LOCKED_G 0x33 -#define MENU_LOCKED_B 0x33 +#define MENU_LOCKED_R (MENU_INACTIVE_R*2/10) +#define MENU_LOCKED_G (MENU_INACTIVE_G*2/10) +#define MENU_LOCKED_B (MENU_INACTIVE_B*2/10) + +#define MENU_ACTIVE_LOCKED_R (MENU_ACTIVE_R*2/10) +#define MENU_ACTIVE_LOCKED_G (MENU_ACTIVE_G*2/10) +#define MENU_ACTIVE_LOCKED_B (MENU_ACTIVE_B*2/10) #define DEBUG_ORANGE_R 0xE7 #define DEBUG_ORANGE_G 0x8D diff --git a/VCS PC/Ped.cpp b/VCS PC/Ped.cpp index c8345cc..4aa3451 100644 --- a/VCS PC/Ped.cpp +++ b/VCS PC/Ped.cpp @@ -4,6 +4,7 @@ #include "ModelInfo.h" #include "Pools.h" #include "PcSave.h" +#include "RealTimeShadowMgr.h" // Wrappers WRAPPER void CPed::GiveWeapon(int WeaponType, int WeaponAmmo, bool bFlag) { WRAPARG(WeaponType); WRAPARG(WeaponAmmo); WRAPARG(bFlag); EAXJMP(0x5E6080); } @@ -42,6 +43,57 @@ bool CPed::Load() return true; } +void CPed::RenderForShadow(RpClump* pClump) +{ + RpClumpForAllAtomics(pClump, ShadowCameraRenderCB, nullptr); + + if ( m_pWeaponObject ) + { + RpHAnimHierarchy* pAnimHierarchy = GetAnimHierarchyFromSkinClump(pClump); + bool bHasParachute = weaponSlots[m_bActiveWeapon].m_eWeaponType == WEAPONTYPE_PARACHUTE; + + RwFrame* pFrame = RpClumpGetFrame(reinterpret_cast(m_pWeaponObject)); + *RwFrameGetMatrix(pFrame) = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy)[RpHAnimIDGetIndex(pAnimHierarchy, bHasParachute ? 3 : 24)]; + + if ( bHasParachute ) + { + const RwV3d vecParachuteTranslation = { 0.1f, -0.15f, 0.0f }; + const RwV3d vecParachuteRotation = { 0.0f, 1.0f, 0.0f }; + RwMatrixTranslate(RwFrameGetMatrix(pFrame), &vecParachuteTranslation, rwCOMBINEPRECONCAT); + RwMatrixRotate(RwFrameGetMatrix(pFrame), &vecParachuteRotation, 90.0f, rwCOMBINEPRECONCAT); + } + + RpGeometry* pWeaponGeometry = RpAtomicGetGeometry(GetFirstAtomic(reinterpret_cast(m_pWeaponObject))); + RwUInt32 weaponGeometryFlags = RpGeometryGetFlags(pWeaponGeometry); + RpGeometrySetFlags(pWeaponGeometry, weaponGeometryFlags & ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT| + rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2)); + + RwFrameUpdateObjects(pFrame); + //AtomicDefaultRenderCallBack(GetFirstAtomic(reinterpret_cast(pPed->m_pWeaponObject))); + RpClumpRender(reinterpret_cast(m_pWeaponObject)); + + // Dual weapons + if ( CWeaponInfo::GetWeaponInfo(weaponSlots[m_bActiveWeapon].m_eWeaponType, GetWeaponSkill())->hexFlags >> 11 & 1 ) + { + *RwFrameGetMatrix(pFrame) = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy)[RpHAnimIDGetIndex(pAnimHierarchy, 34)]; + + const RwV3d vecParachuteRotation = { 1.0f, 0.0f, 0.0f }; + const RwV3d vecParachuteTranslation = { 0.04f, -0.05f, 0.0f }; + RwMatrixRotate(RwFrameGetMatrix(pFrame), &vecParachuteRotation, 180.0f, rwCOMBINEPRECONCAT); + RwMatrixTranslate(RwFrameGetMatrix(pFrame), &vecParachuteTranslation, rwCOMBINEPRECONCAT); + + RwFrameUpdateObjects(pFrame); + RpClumpRender(reinterpret_cast(m_pWeaponObject)); + } + RpGeometrySetFlags(pWeaponGeometry, weaponGeometryFlags); + } + + // Render jetpack + auto* pJetPackTask = pPedIntelligence->GetTaskJetPack(); + if ( pJetPackTask ) + pJetPackTask->RenderJetPack(this); +} + CPed* CPedData::Initialise(CPed* pPed, short model) { diff --git a/VCS PC/Ped.h b/VCS PC/Ped.h index 554516b..938e273 100644 --- a/VCS PC/Ped.h +++ b/VCS PC/Ped.h @@ -304,6 +304,7 @@ class NOVMT CPed : public CPhysical long double GetCrosshairSize(); void Remap(); + void RenderForShadow(RpClump* pClump); }; class CPedData diff --git a/VCS PC/Pools.cpp b/VCS PC/Pools.cpp index 41f86ac..72d854c 100644 --- a/VCS PC/Pools.cpp +++ b/VCS PC/Pools.cpp @@ -6,6 +6,7 @@ CVehiclePool*& CPools::ms_pVehiclePool = *(CVehiclePool**)0xB74494; CBuildingPool*& CPools::ms_pBuildingPool = *(CBuildingPool**)0xB74498; CDummyPool*& CPools::ms_pDummyPool = *(CDummyPool**)0xB744A0; CColModelPool*& CPools::ms_pColModelPool = *(CColModelPool**)0xB744A4; +CTaskPool*& CPools::ms_pTaskPool = *(CTaskPool**)0xB744A8; CEmpireBuildingDataPool* CPools::ms_pEmpireBuildingDataPool; CPedPoolAux* CPools::ms_pPedPoolAux; diff --git a/VCS PC/Pools.h b/VCS PC/Pools.h index 340d994..8d25cb3 100644 --- a/VCS PC/Pools.h +++ b/VCS PC/Pools.h @@ -195,12 +195,14 @@ struct FakeClass : public T #include "Vehicle.h" #include "Building.h" #include "ModelInfo.h" +#include "Tasks.h" typedef CPool> CPedPool; typedef CPool> CVehiclePool; typedef CPool CBuildingPool; typedef CPool CDummyPool; typedef CPool CColModelPool; +typedef CPool> CTaskPool; typedef CPool CEmpireBuildingDataPool; @@ -214,6 +216,7 @@ class CPools static CBuildingPool*& ms_pBuildingPool; static CDummyPool*& ms_pDummyPool; static CColModelPool*& ms_pColModelPool; + static CTaskPool*& ms_pTaskPool; // VCS PC class extension static CEmpireBuildingDataPool* ms_pEmpireBuildingDataPool; @@ -230,6 +233,8 @@ class CPools { return ms_pDummyPool; } static inline CColModelPool* GetColModelPool() { return ms_pColModelPool; } + static inline CTaskPool* GetTaskPool() + { return ms_pTaskPool; } static inline CEmpireBuildingDataPool* GetEmpireBuildingDataPool() { return ms_pEmpireBuildingDataPool; } diff --git a/VCS PC/RealTimeShadowMgr.cpp b/VCS PC/RealTimeShadowMgr.cpp index aab0e5a..1000c87 100644 --- a/VCS PC/RealTimeShadowMgr.cpp +++ b/VCS PC/RealTimeShadowMgr.cpp @@ -21,13 +21,18 @@ WRAPPER void CShadowCamera::InvertRaster() { EAXJMP(0x705660); } WRAPPER void CRealTimeShadow::Destroy() { EAXJMP(0x705990); } WRAPPER bool CRealTimeShadow::SetShadowedObject(CPhysical* pObject) { WRAPARG(pObject); EAXJMP(0x706520); } -CShadowCamera CRealTimeShadowManager::m_BlurCamera_Player; -CShadowCamera CRealTimeShadowManager::m_GradientCamera_Player; - -static RpAtomic* ShadowCameraRenderCallback(RpAtomic* pAtomic, void* pData) +RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData) { UNREFERENCED_PARAMETER(pData); - return AtomicDefaultRenderCallBack(pAtomic); + + RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic); + RwUInt32 geometryFlags = RpGeometryGetFlags(pGeometry); + RpGeometrySetFlags(pGeometry, geometryFlags & ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT| + rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2)); + + auto* pOut = AtomicDefaultRenderCallBack(pAtomic); + RpGeometrySetFlags(pGeometry, geometryFlags); + return pOut; } void CShadowCamera::ReInit() @@ -42,61 +47,35 @@ void CShadowCamera::ReInit() RwTextureSetRaster(m_pTexture, pNewRaster); } -RwCamera* CShadowCamera::Update(RpClump* pClump, CPed* pPed) +static RpAtomic* PushGeometryFlags(RpAtomic* pAtomic, void* pData) +{ + std::pair** pGeometryStack = static_cast**>(pData); + RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic); + + *((*pGeometryStack)++) = std::make_pair(&RpGeometryGetFlags(pGeometry), RpGeometryGetFlags(pGeometry)); + return pAtomic; +} + +RwCamera* CShadowCamera::Update(RpClump* pClump, CPhysical* pEntity) { RwRGBA ClearColour = { 255, 255, 255, 0 }; RwCameraClear(m_pCamera, &ClearColour, rwCAMERACLEARIMAGE|rwCAMERACLEARZ); if ( RwCameraBeginUpdate(m_pCamera ) ) { - RpGeometry* pGeometry = RpAtomicGetGeometry(GetFirstAtomic(pClump)); - auto geometryFlags = RpGeometryGetFlags(pGeometry); + //std::pair GeometryFlagsPair[32]; - RpGeometrySetFlags(pGeometry, geometryFlags & ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT| - rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2)); - RpClumpForAllAtomics(pClump, ShadowCameraRenderCallback, nullptr); - RpGeometrySetFlags(pGeometry, geometryFlags); + //RpGeometry* pGeometry = RpAtomicGetGeometry(GetFirstAtomic(pClump)); + //RwUInt32 geometryFlags = RpGeometryGetFlags(pGeometry); - if ( pPed ) + //RpGeometrySetFlags(pGeometry, geometryFlags & ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT| + // rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2)); + if ( pEntity ) { - if ( pPed->m_pWeaponObject ) - { - RpHAnimHierarchy* pAnimHierarchy = GetAnimHierarchyFromSkinClump(pClump); - bool bHasParachute = pPed->weaponSlots[pPed->m_bActiveWeapon].m_eWeaponType == WEAPONTYPE_PARACHUTE; - - RwFrame* pFrame = RpClumpGetFrame(reinterpret_cast(pPed->m_pWeaponObject)); - *RwFrameGetMatrix(pFrame) = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy)[RpHAnimIDGetIndex(pAnimHierarchy, bHasParachute ? 3 : 24)]; - - if ( bHasParachute ) - { - const RwV3d vecParachuteTranslation = { 0.1f, -0.15f, 0.0f }; - const RwV3d vecParachuteRotation = { 0.0f, 1.0f, 0.0f }; - RwMatrixTranslate(RwFrameGetMatrix(pFrame), &vecParachuteTranslation, rwCOMBINEPRECONCAT); - RwMatrixRotate(RwFrameGetMatrix(pFrame), &vecParachuteRotation, 90.0f, rwCOMBINEPRECONCAT); - } - - RwFrameUpdateObjects(pFrame); - AtomicDefaultRenderCallBack(GetFirstAtomic(reinterpret_cast(pPed->m_pWeaponObject))); - - // Dual weapons - if ( CWeaponInfo::GetWeaponInfo(pPed->weaponSlots[pPed->m_bActiveWeapon].m_eWeaponType, pPed->GetWeaponSkill())->hexFlags >> 11 & 1 ) - { - *RwFrameGetMatrix(pFrame) = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy)[RpHAnimIDGetIndex(pAnimHierarchy, 34)]; - - const RwV3d vecParachuteRotation = { 1.0f, 0.0f, 0.0f }; - const RwV3d vecParachuteTranslation = { 0.04f, -0.05f, 0.0f }; - RwMatrixRotate(RwFrameGetMatrix(pFrame), &vecParachuteRotation, 180.0f, rwCOMBINEPRECONCAT); - RwMatrixTranslate(RwFrameGetMatrix(pFrame), &vecParachuteTranslation, rwCOMBINEPRECONCAT); - - RwFrameUpdateObjects(pFrame); - AtomicDefaultRenderCallBack(GetFirstAtomic(reinterpret_cast(pPed->m_pWeaponObject))); - } - } - - // Render jetpack - auto* pJetPackTask = pPed->GetPedIntelligencePtr()->GetTaskJetPack(); - if ( pJetPackTask ) - pJetPackTask->RenderJetPack(pPed); + if ( pEntity->nType == 3 ) + static_cast(pEntity)->RenderForShadow(pClump); + else if ( pEntity->nType == 2 ) + static_cast(pEntity)->RenderForShadow(pClump); } InvertRaster(); @@ -116,7 +95,7 @@ RwTexture* CRealTimeShadow::Update() if ( m_nRwObjectType == rpATOMIC ) m_Camera.Update(reinterpret_cast(m_pEntity->m_pRwObject)); else if ( m_nRwObjectType == rpCLUMP ) - m_Camera.Update(reinterpret_cast(m_pEntity->m_pRwObject), m_pEntity->nType == 3 ? static_cast(m_pEntity) : nullptr); + m_Camera.Update(reinterpret_cast(m_pEntity->m_pRwObject), m_pEntity); RwRaster* pRaster = RwCameraGetRaster(m_Camera.m_pCamera); @@ -124,10 +103,10 @@ RwTexture* CRealTimeShadow::Update() pRaster = m_ResampledCamera.RasterResample(pRaster); if ( m_dwBlurPasses ) - pRaster = m_bUsePlayerHelperCams ? CRealTimeShadowManager::m_BlurCamera_Player.RasterBlur(pRaster, m_dwBlurPasses) : g_realTimeShadowMan.m_BlurCamera.RasterBlur(pRaster, m_dwBlurPasses); + pRaster = m_bUsePlayerHelperCams ? g_realTimeShadowMan.m_BlurCamera_Player.RasterBlur(pRaster, m_dwBlurPasses) : g_realTimeShadowMan.m_BlurCamera.RasterBlur(pRaster, m_dwBlurPasses); if ( m_bDrawGradient ) - pRaster = m_bUsePlayerHelperCams ? CRealTimeShadowManager::m_GradientCamera_Player.RasterGradient(pRaster) : g_realTimeShadowMan.m_GradientCamera.RasterGradient(pRaster); + pRaster = m_bUsePlayerHelperCams ? g_realTimeShadowMan.m_GradientCamera_Player.RasterGradient(pRaster) : g_realTimeShadowMan.m_GradientCamera.RasterGradient(pRaster); return m_bDrawResample ? m_ResampledCamera.m_pTexture : m_Camera.m_pTexture; } @@ -317,9 +296,10 @@ void CRealTimeShadowManager::GetRealTimeShadow(CPhysical* pEntity) if ( pPlayerPed->pedFlags.bInVehicle ) { - CVehicle* pVehicle = pPlayerPed->pVehicle; + /*CVehicle* pVehicle = pPlayerPed->pVehicle; if ( pVehicle ) - bRender = pVehicle->GetLinearVelocity().MagnitudeSqr() <= 0.3f * 0.3f; + bRender = pVehicle->GetLinearVelocity().MagnitudeSqr() <= 0.3f * 0.3f;*/ + bIsPlayer = pPlayerPed->pVehicle == pEntity; } } @@ -339,14 +319,28 @@ void CRealTimeShadowManager::GetRealTimeShadow(CPhysical* pEntity) break; } } + + // Debug +#ifdef DEVBUILD + if ( !pOutShadow ) + { + static bool bLimitHit = false; + + if ( !bLimitHit ) + { + assert(!"Too many real time shadows at once, consider increasing limits."); + bLimitHit = true; + } + } +#endif } if ( pOutShadow ) { pOutShadow->SetShadowedObject(pEntity); + pOutShadow->ResetIntensity(); pEntity->SetRealTimeShadow(pOutShadow); pOutShadow->SetRenderedThisFrame(); - pOutShadow->ResetIntensity(); } } } @@ -387,4 +381,22 @@ static StaticPatcher Patcher([](){ Memory::InjectHook(0x706BA0, &CRealTimeShadowManager::DoShadowThisFrame, PATCH_JUMP); Memory::InjectHook(0x706AC2, &CRealTimeShadowManager::ReInit); Memory::InjectHook(0x706B29, &CRealTimeShadow::Update); + + // Increased shadows limit + Memory::Patch(0x45D412, &g_realTimeShadowMan); + Memory::Patch(0x53BE63, &g_realTimeShadowMan); + Memory::Patch(0x53C63F, &g_realTimeShadowMan); + Memory::Patch(0x53C9E5, &g_realTimeShadowMan); + Memory::Patch(0x53EA09, &g_realTimeShadowMan); + Memory::Patch(0x542487, &g_realTimeShadowMan); + Memory::Patch(0x5B1F38, &g_realTimeShadowMan); + Memory::Patch(0x5BA478, &g_realTimeShadowMan); + Memory::Patch(0x5E68A4, &g_realTimeShadowMan); + //Memory::Patch(0x854980, &g_realTimeShadowMan); + //Memory::Patch(0x856AD0, &g_realTimeShadowMan); + + Memory::Patch(0x5BA137, &g_realTimeShadowMan.m_bNeedsReinit); + + Memory::Patch(0x706AD4, NUM_MAX_REALTIME_SHADOWS); + Memory::Patch(0x706B80, NUM_MAX_REALTIME_SHADOWS); }); \ No newline at end of file diff --git a/VCS PC/RealTimeShadowMgr.h b/VCS PC/RealTimeShadowMgr.h index 1939471..b069108 100644 --- a/VCS PC/RealTimeShadowMgr.h +++ b/VCS PC/RealTimeShadowMgr.h @@ -1,7 +1,7 @@ #ifndef __REALTIMESHADOWMGR #define __REALTIMESHADOWMGR -#define NUM_MAX_REALTIME_SHADOWS 16 +#define NUM_MAX_REALTIME_SHADOWS 32 struct tShadowQualitySettings { @@ -32,7 +32,7 @@ class CShadowCamera RwRaster* RasterGradient(RwRaster* pRaster); void InvertRaster(); - RwCamera* Update(RpClump* pClump, class CPed* pPed); + RwCamera* Update(RpClump* pClump, CPhysical* pEntity); void ReInit(); }; @@ -60,6 +60,8 @@ class CRealTimeShadow { m_bRenderedThisFrame = true; } inline void ResetIntensity() { m_nIntensity = 0; } + inline void ForceFullIntensity() + { m_nIntensity = 100; } inline void ClearOwner() { m_pEntity = nullptr; } //void* operator new(size_t size) @@ -101,10 +103,16 @@ class CRealTimeShadowManager CShadowCamera m_GradientCamera; // VCS PC class extension - static CShadowCamera m_BlurCamera_Player; - static CShadowCamera m_GradientCamera_Player; + CShadowCamera m_BlurCamera_Player; + CShadowCamera m_GradientCamera_Player; public: + CRealTimeShadowManager() + : m_bInitialised(false), m_bNeedsReinit(false), m_bPlayerHelperCamsInUse(false) + { + memset(m_pShadows, 0, sizeof(m_pShadows)); + } + void ResetForChangedSettings() { for ( int i = 0; i < NUM_MAX_REALTIME_SHADOWS; i++ ) ReturnRealTimeShadow(m_pShadows[i]); Exit(); Init(); } @@ -117,9 +125,11 @@ class CRealTimeShadowManager void ReInit(); }; -extern CRealTimeShadowManager& g_realTimeShadowMan; +RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic, void* pData); + +extern CRealTimeShadowManager g_realTimeShadowMan; static_assert(sizeof(CRealTimeShadow) == 0x4C, "Wrong size: CRealTimeShadow"); -static_assert(sizeof(CRealTimeShadowManager) == 0x54, "Wrong size: CRealTimeShadowManager"); +//static_assert(sizeof(CRealTimeShadowManager) == 0x54, "Wrong size: CRealTimeShadowManager"); #endif \ No newline at end of file diff --git a/VCS PC/Shadows.cpp b/VCS PC/Shadows.cpp index 38c62b3..425c146 100644 --- a/VCS PC/Shadows.cpp +++ b/VCS PC/Shadows.cpp @@ -4,9 +4,12 @@ #include "3DMarkers.h" #include "Coronas.h" #include "RealTimeShadowMgr.h" +#include "Vehicle.h" eShadowQuality CShadows::m_bShadowQuality; +float& MAX_DISTANCE_PED_SHADOWS = *(float*)0x8D5240; + void CShadows::RenderIndicatorShadow(unsigned int nIndex, unsigned char, RwTexture*, CVector* pPos, float radiusX, float, float, float radiusY, short) { C3DMarkers::PlaceMarkerSet(nIndex, 1, *pPos, radiusX > -radiusY ? radiusX : -radiusY, MARKER_SET_COLOR_R, MARKER_SET_COLOR_G, MARKER_SET_COLOR_B, MARKER_SET_COLOR_A, 2048, 0.2f); @@ -17,17 +20,27 @@ void CShadows::InitialiseChangedSettings() g_realTimeShadowMan.ResetForChangedSettings(); } +bool CShadows::StoreRealTimeShadowForVehicle(CVehicle* pVehicle) +{ + if ( m_bShadowQuality > SHADOW_QUALITY_LOW ) + { + g_realTimeShadowMan.DoShadowThisFrame(pVehicle); + return true; + } + return false; +} + static const float f215 = 2.15f; static const float f115 = 1.15f; -static float gA; +//static float gA; static float gB; static CPhysical *gCurrentEntityStoresShadow; void * __fastcall SetLightParameters(int shd, int edx0, float a, float b, bool set) { - gA = a; + //gA = a; gB = b; return ((void *(__thiscall *)(int, float, float, bool))0x705900)(shd, a, b, set); } @@ -54,7 +67,7 @@ void CastShadow(void *a1, float a2, float a3, float a4, float a5, void *a6, floa void __fastcall SetupShadowBoundSphere(void *sphere, int edx0, float size, CVector const& center, unsigned char material, unsigned char flags, unsigned char lighting) { ((void (__thiscall *)(void *, float, CVector const&, unsigned char, unsigned char, unsigned char))0x40FD10) - (sphere, 2.0f, center, material, flags, lighting); + (sphere, 3.0f, center, material, flags, lighting); } #define NightState (*(float *)0x8D12C0) @@ -106,6 +119,17 @@ static void __declspec(naked) ShowShadowsConditionHack() } } +static void __declspec(naked) StoreRTVehicleShadowHack() +{ + _asm + { + push [esp+4Ch+4] + call CShadows::StoreRealTimeShadowForVehicle + add esp, 4 + retn + } +} + void CShadows::Inject() { Memory::InjectHook(0x70CCB0, RenderIndicatorShadow, PATCH_JUMP); @@ -126,15 +150,12 @@ void CShadows::Inject() static StaticPatcher Patcher([](){ #ifdef NEW_SHADOWS_TEST2 - // Disable stencil - Memory::Patch(0x53E159, 0xC3); - // CRealTimeShadow for vehicle (temp) - Memory::Patch(0x70BDA0, 0xC40350B9); + /*Memory::Patch(0x70BDA0, 0xC40350B9); Memory::Patch(0x70BDA4, 0x2474FF00); Memory::Patch(0x70BDA8, 0x04); Memory::InjectHook(0x70BDA9, 0x706BA0, PATCH_CALL); - Memory::Patch(0x70BDAE, 0xC3); + Memory::Patch(0x70BDAE, 0xC3);*/ Memory::Patch(0x707EF7, &f215); Memory::Patch(0x707F05, &f215); @@ -147,18 +168,25 @@ static StaticPatcher Patcher([](){ Memory::InjectHook(0x707E4F, SetLightParameters); Memory::InjectHook(0x70596A, RotateLightFrame); - // Same as TranlateShdMatrix + // Same as TranslateShdMatrix Memory::Patch(0x70A19D, 0.5f); //Memory::InjectHook(0x70A1AC, TranlateShdMatrix); - //Memory::InjectHook(0x707E2B, CompareSunZ, PATCH_JUMP); + Memory::InjectHook(0x707E2B, CompareSunZ, PATCH_JUMP); //Memory::InjectHook(0x70AD0D, CastShadow); Memory::InjectHook(0x70A2C8, SetupShadowBoundSphere); // matrix rotate Memory::Nop(0x70A0C9, 5); + + // Improved in car shadows + //Memory::Patch(0x5E682C, 0x26EB); + Memory::Patch(0x5E6813, 0xEB); + //Memory::Patch(0x5E683B, 0xEB); + Memory::InjectHook(0x70BDA4, StoreRTVehicleShadowHack); #endif //Memory::InjectHook(0x705590, &CShadowCamera::SetCenter, PATCH_JUMP); CShadows::Inject(); + }); \ No newline at end of file diff --git a/VCS PC/Shadows.h b/VCS PC/Shadows.h index c88084d..c24fc1e 100644 --- a/VCS PC/Shadows.h +++ b/VCS PC/Shadows.h @@ -25,6 +25,7 @@ class CShadows static inline eShadowQuality GetShadowQuality() { return m_bShadowQuality; } + static bool StoreRealTimeShadowForVehicle(class CVehicle* pVehicle); static void InitialiseChangedSettings(); static void Inject(); }; diff --git a/VCS PC/StdAfx.h b/VCS PC/StdAfx.h index d8f79d0..64de88b 100644 --- a/VCS PC/StdAfx.h +++ b/VCS PC/StdAfx.h @@ -70,7 +70,7 @@ //#define MULTITHREADING_TEST //#define NEW_SHADOWS_TEST -//#define NEW_SHADOWS_TEST2 +#define NEW_SHADOWS_TEST2 //#define MAKE_ZZCOOL_MOVIE_DEMO diff --git a/VCS PC/Tasks.cpp b/VCS PC/Tasks.cpp index ebd7a50..23542c0 100644 --- a/VCS PC/Tasks.cpp +++ b/VCS PC/Tasks.cpp @@ -1,4 +1,17 @@ #include "StdAfx.h" #include "Tasks.h" -WRAPPER void CTaskSimpleJetPack::RenderJetPack(CPed* pPed) { WRAPARG(pPed); EAXJMP(0x67F6A0); } \ No newline at end of file +#include "Pools.h" + +WRAPPER void CTaskSimpleJetPack::RenderJetPack(CPed* pPed) { WRAPARG(pPed); EAXJMP(0x67F6A0); } + +void* CTask::operator new(size_t size) +{ + UNREFERENCED_PARAMETER(size); + return CPools::GetTaskPool()->New(); +} + +void CTask::operator delete(void* ptr) +{ + CPools::GetTaskPool()->Delete(static_cast(ptr)); +} \ No newline at end of file diff --git a/VCS PC/Tasks.h b/VCS PC/Tasks.h index 08c91ca..004cf44 100644 --- a/VCS PC/Tasks.h +++ b/VCS PC/Tasks.h @@ -1,12 +1,88 @@ #ifndef __TASKS #define __TASKS -// TODO: Define stuff somewhat properly to at least have proper VMT and inheritance +class CTask +{ +private: + CTask* m_pParentTask; + +public: + virtual ~CTask() { }; + virtual CTask* Clone() const=0; + virtual CTask* GetSubTask() const=0; + virtual bool IsSimpleTask() const=0; + virtual unsigned int GetTaskType() const=0; + virtual void StopTimer(const class CEvent* pEvent) { UNREFERENCED_PARAMETER(pEvent); }; + virtual void MakeAbortable(class CPed* pPed, int nTaskType, const class CEvent* pEvent)=0; -class CTaskSimpleJetPack + void* operator new(size_t size); + void operator delete(void* ptr); + + CTask() + : m_pParentTask(nullptr) + { + } + + inline void SetParentTask(CTask* pParent) + { m_pParentTask = pParent; } +}; + +class CTaskSimple : public CTask +{ +public: + virtual CTask* GetSubTask() const override { return nullptr; }; + virtual bool IsSimpleTask() const override { return true; }; + + virtual bool ProcessPed(class CPed* pPed)=0; + virtual bool SetPedPosition(class CPed* pPed) { UNREFERENCED_PARAMETER(pPed); return false; }; +}; + +class CTaskComplex : public CTask +{ +private: + CTask* m_pSubTask; + +public: + virtual CTask* GetSubTask() const override { return m_pSubTask; }; + virtual bool IsSimpleTask() const override { return false; }; + virtual void MakeAbortable(class CPed* pPed, int nTaskType, const class CEvent* pEvent) override + { + m_pSubTask->MakeAbortable(pPed, nTaskType, pEvent); + } + + virtual void SetSubTask(CTask* pSubTask) + { + if ( pSubTask != m_pSubTask ) + { + if ( m_pSubTask ) + delete m_pSubTask; + m_pSubTask = pSubTask; + if ( pSubTask ) + pSubTask->SetParentTask(this); + } + } + virtual CTask* CreateNextSubTask(class CPed* pPed)=0; + virtual CTask* CreateFirstSubTask(class CPed* pPed)=0; + virtual CTask* ControlSubTask(class CPed* pPed)=0; + + CTaskComplex() + : m_pSubTask(nullptr) + { + } + + virtual ~CTaskComplex() + { + delete m_pSubTask; + m_pSubTask = nullptr; + } +}; + +class NOVMT CTaskSimpleJetPack : public CTaskSimple { public: void RenderJetPack(class CPed* pPed); }; +//static_assert(sizeof(CTaskSimpleJetPack) == 0x70, "Wrong size: CTaskSimpleJetPack"); + #endif \ No newline at end of file diff --git a/VCS PC/VCSPC.cpp b/VCS PC/VCSPC.cpp index 3d356b2..f7cd719 100644 --- a/VCS PC/VCSPC.cpp +++ b/VCS PC/VCSPC.cpp @@ -380,7 +380,7 @@ void** rwengine = (void**)0xC97B24; CControllerConfigManager& ControlsManager = *(CControllerConfigManager*)0xB70198; CMousePointerStateHelper& MousePointerStateHelper = *(CMousePointerStateHelper*)0xBA6744; -CRealTimeShadowManager& g_realTimeShadowMan = *(CRealTimeShadowManager*)0xC40350; +CRealTimeShadowManager g_realTimeShadowMan; void (*replacedTXDLoadFunc)(); void (*replacedTXDReleaseFunc)(); @@ -3148,8 +3148,9 @@ __forceinline void Main_Patches() Patch(0x6FB9A0, 0); // Relocated sun - Patch(0x560A76, 1.0f); - Nop(0x560A84, 6); + // TODO: FIX COMPATIBILITY WITH MOBILE SHADOWS + //Patch(0x560A76, 1.0f); + //Nop(0x560A84, 6); // More vehicles #if NUM_VEHICLE_MODELS > 212 @@ -4714,6 +4715,18 @@ char* ParseCommandlineArgument(char* pArg) return pArg; }*/ + /*if ( !_strnicmp(pArg, "-stencil", 8) ) + { + // Stencil shadows are back + Memory::Patch(0x53E159, 0xE9); + Memory::InjectHook(0x53C1AB, 0x711D90, PATCH_CALL); + + Memory::Patch(0x70F9B0, 0xAE00B953); + Memory::Patch(0x70F9B4, 0xDB3200A9); + Memory::Patch(0x70F9B8, 0x93E8); + Memory::Patch(0x70F9BA, 0xF0); + }*/ + #ifdef DEVBUILD if ( !_strnicmp(pArg, "-noautocheck", 13) ) { diff --git a/VCS PC/Vehicle.cpp b/VCS PC/Vehicle.cpp index 6475e00..b72c5b0 100644 --- a/VCS PC/Vehicle.cpp +++ b/VCS PC/Vehicle.cpp @@ -5,6 +5,7 @@ #include "Timer.h" #include "PlayerInfo.h" #include "Pad.h" +#include "RealTimeShadowMgr.h" WRAPPER void CVehicle::SetWindowOpenFlag(unsigned char nWindow) { WRAPARG(nWindow); EAXJMP(0x6D3080); } WRAPPER void CVehicle::ClearWindowOpenFlag(unsigned char nWindow) { WRAPARG(nWindow); EAXJMP(0x6D30B0); } @@ -33,6 +34,26 @@ void CVehicle::SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha) RpGeometryForAllMaterials(pGeometry, SetCompAlphaCB, reinterpret_cast(nAlpha)); } +void CVehicle::RenderForShadow(RpClump* pClump) +{ + RpClumpForAllAtomics(pClump, ShadowCameraRenderCB, nullptr); + + // Is open top? + if ( m_dwVehicleSubClass == VEHICLE_QUAD || m_dwVehicleSubClass == VEHICLE_BIKE || m_dwVehicleSubClass == VEHICLE_BMX ) + { + // Render driver + if ( m_pDriver ) + m_pDriver->RenderForShadow(reinterpret_cast(m_pDriver->m_pRwObject)); + + // Render passengers + for ( int i = 0; i < 8; i++ ) + { + if ( m_apPassengers[i] ) + m_apPassengers[i]->RenderForShadow(reinterpret_cast(m_apPassengers[i]->m_pRwObject)); + } + } +} + #include "Font.h" static float fCurrentY; diff --git a/VCS PC/Vehicle.h b/VCS PC/Vehicle.h index 88c76ae..8700e50 100644 --- a/VCS PC/Vehicle.h +++ b/VCS PC/Vehicle.h @@ -4,6 +4,22 @@ #include "General.h" #include "ModelInfo.h" +enum eVehicleType +{ + VEHICLE_AUTOMOBILE, + VEHICLE_MTRUCK, + VEHICLE_QUAD, + VEHICLE_HELI, + VEHICLE_PLANE, + VEHICLE_BOAT, + VEHICLE_TRAIN, + VEHICLE_FHELI, + VEHICLE_FPLANE, + VEHICLE_BIKE, + VEHICLE_BMX, + VEHICLE_TRAILER +}; + struct CVehicleFlags { //0x428 @@ -86,16 +102,24 @@ struct CVehicleFlags unsigned char bUsedForReplay: 1; // This car is controlled by replay and should be removed when replay is done. }; -class NOVMT CVehicle : public CPhysical +class NOVMT CVehicle : public CPhysical { protected: BYTE __pad1[752]; CVehicleFlags m_nVehicleFlags; - BYTE __pad2[160]; + BYTE __pad5[48]; + class CPed* m_pDriver; + class CPed* m_apPassengers[8]; + BYTE __pad2[76]; signed int m_nTimeTillWeNeedThisCar; BYTE __pad4[56]; CEntity* pDamagingEntity; - BYTE __pad3[144]; + BYTE __pad3[128]; + eVehicleType m_dwVehicleClass; + eVehicleType m_dwVehicleSubClass; + short m_wPreviousRemapTxd; + short m_wRemapTxd; + RwTexture* m_pRemapTexture; public: static bool& m_bEnableMouseSteering; @@ -105,12 +129,16 @@ class NOVMT CVehicle : public CPhysical { return m_nVehicleFlags; } CEntity* GetDamagingEntity() { return pDamagingEntity; } + eVehicleType GetSubClass() + { return m_dwVehicleSubClass; } virtual void Render() override; void SetWindowOpenFlag(unsigned char nWindow); void ClearWindowOpenFlag(unsigned char nWindow); + void RenderForShadow(RpClump* pClump); + static void SetComponentAtomicAlpha(RpAtomic* pAtomic, int nAlpha); };