2014-08-03 15:38:53 +02:00
|
|
|
#include "StdAfxSA.h"
|
|
|
|
#include "GeneralSA.h"
|
2014-05-30 20:14:47 +02:00
|
|
|
|
2014-08-19 13:16:38 +02:00
|
|
|
#include "PedSA.h"
|
2017-09-07 21:27:47 +02:00
|
|
|
#include "ModelInfoSA.h"
|
2017-09-09 18:47:07 +02:00
|
|
|
#include "PoolsSA.h"
|
2014-08-19 13:16:38 +02:00
|
|
|
|
2014-05-30 20:14:47 +02:00
|
|
|
// Wrappers
|
2014-08-22 00:10:23 +02:00
|
|
|
static void* EntityRender = AddressByVersion<void*>(0x534310, 0x5347B0, 0x545B30);
|
2014-08-04 14:30:16 +02:00
|
|
|
WRAPPER void CEntity::Render() { VARJMP(EntityRender); }
|
2014-05-30 20:14:47 +02:00
|
|
|
|
2017-09-09 18:47:07 +02:00
|
|
|
static void* varEntityIsVisible = AddressByVersion<void*>( 0x536BC0, 0, 0 ); // TODO
|
|
|
|
WRAPPER bool CEntity::IsVisible() { VARJMP(varEntityIsVisible); }
|
|
|
|
|
2014-08-22 00:10:23 +02:00
|
|
|
static void* varInvertRaster = AddressByVersion<void*>(0x705660, 0x705E90, 0x7497A0);
|
2014-08-19 13:16:38 +02:00
|
|
|
WRAPPER void CShadowCamera::InvertRaster() { VARJMP(varInvertRaster); }
|
|
|
|
|
2014-08-22 00:10:23 +02:00
|
|
|
CWeaponInfo* (*CWeaponInfo::GetWeaponInfo)(eWeaponType, signed char) = AddressByVersion<CWeaponInfo*(*)(eWeaponType, signed char)>(0x743C60, 0x744490, 0x77D940);
|
2014-08-19 12:57:35 +02:00
|
|
|
|
2017-09-07 21:27:47 +02:00
|
|
|
static RwTexture*& ms_pRemapTexture = **AddressByVersion<RwTexture***>(0x59F1BD, 0x6D6E53, 0x5B811D);
|
2014-06-16 02:21:05 +02:00
|
|
|
|
2014-08-22 00:10:23 +02:00
|
|
|
auto SetEditableMaterialsCB = AddressByVersion<RpAtomic*(*)(RpAtomic*,void*)>(0x4C83E0, 0x4C8460, 0x4D2CE0);
|
2014-06-16 02:21:05 +02:00
|
|
|
|
|
|
|
static void ResetEditableMaterials(std::pair<void*,int>* pData)
|
|
|
|
{
|
2017-03-25 13:46:35 +01:00
|
|
|
for ( auto* i = pData; i->first != nullptr; i++ )
|
2014-06-16 02:21:05 +02:00
|
|
|
*static_cast<int*>(i->first) = i->second;
|
|
|
|
}
|
|
|
|
|
2017-03-27 21:17:43 +02:00
|
|
|
RpAtomic* ShadowCameraRenderCB(RpAtomic* pAtomic)
|
2014-08-19 13:16:38 +02:00
|
|
|
{
|
|
|
|
if ( RpAtomicGetFlags(pAtomic) & rpATOMICRENDER )
|
|
|
|
{
|
|
|
|
RpGeometry* pGeometry = RpAtomicGetGeometry(pAtomic);
|
|
|
|
|
2017-03-25 13:46:35 +01:00
|
|
|
if ( pGeometry->repEntry != nullptr ) // Only switch to optimized flags if already instanced so as not to break the instanced model
|
|
|
|
{
|
|
|
|
RwUInt32 geometryFlags = RpGeometryGetFlags(pGeometry);
|
|
|
|
pGeometry->flags &= ~(rpGEOMETRYTEXTURED|rpGEOMETRYPRELIT|rpGEOMETRYNORMALS|rpGEOMETRYLIGHT|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYTEXTURED2);
|
|
|
|
pAtomic = AtomicDefaultRenderCallBack(pAtomic);
|
|
|
|
RpGeometrySetFlags(pGeometry, geometryFlags);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pAtomic = AtomicDefaultRenderCallBack(pAtomic);
|
|
|
|
}
|
2014-08-19 13:16:38 +02:00
|
|
|
}
|
|
|
|
return pAtomic;
|
|
|
|
}
|
|
|
|
|
2014-06-16 02:21:05 +02:00
|
|
|
void CObject::Render()
|
|
|
|
{
|
2014-08-03 15:38:53 +02:00
|
|
|
if ( m_bDoNotRender || !m_pRwObject )
|
2014-06-16 02:21:05 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
bool bCallRestore;
|
|
|
|
std::pair<void*,int> materialRestoreData[16];
|
|
|
|
|
2017-09-09 20:46:10 +02:00
|
|
|
const int32_t carPartModelIndex = m_wCarPartModelIndex.Get();
|
2017-09-09 18:47:07 +02:00
|
|
|
if ( carPartModelIndex != -1 && m_objectCreatedBy == TEMP_OBJECT && bObjectFlag7 && RwObjectGetType(m_pRwObject) == rpATOMIC )
|
2014-06-16 02:21:05 +02:00
|
|
|
{
|
|
|
|
auto* pData = materialRestoreData;
|
|
|
|
|
|
|
|
ms_pRemapTexture = m_pPaintjobTex;
|
2017-09-07 21:27:47 +02:00
|
|
|
|
2017-09-09 20:46:10 +02:00
|
|
|
static_cast<CVehicleModelInfo*>(ms_modelInfoPtrs[ carPartModelIndex ])->SetVehicleColour( m_nCarColor[0].Get(),
|
|
|
|
m_nCarColor[1].Get(), m_nCarColor[2].Get(), m_nCarColor[3].Get() );
|
2014-06-16 02:21:05 +02:00
|
|
|
|
|
|
|
SetEditableMaterialsCB(reinterpret_cast<RpAtomic*>(m_pRwObject), &pData);
|
|
|
|
pData->first = nullptr;
|
|
|
|
|
2014-10-31 14:29:39 +01:00
|
|
|
// Disable backface culling for the part
|
|
|
|
#ifdef _DEBUG
|
|
|
|
RwCullMode oldCullMode;
|
|
|
|
RwRenderStateGet(rwRENDERSTATECULLMODE, &oldCullMode);
|
|
|
|
assert(oldCullMode == rwCULLMODECULLBACK);
|
|
|
|
#endif
|
|
|
|
RwRenderStateSet(rwRENDERSTATECULLMODE, reinterpret_cast<void*>(rwCULLMODECULLNONE));
|
|
|
|
|
2014-06-16 02:21:05 +02:00
|
|
|
bCallRestore = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
bCallRestore = false;
|
|
|
|
|
|
|
|
CEntity::Render();
|
|
|
|
|
|
|
|
if ( bCallRestore )
|
2014-10-31 14:29:39 +01:00
|
|
|
{
|
2014-06-16 02:21:05 +02:00
|
|
|
ResetEditableMaterials(materialRestoreData);
|
2014-10-31 14:29:39 +01:00
|
|
|
RwRenderStateSet(rwRENDERSTATECULLMODE, reinterpret_cast<void*>(rwCULLMODECULLBACK));
|
|
|
|
}
|
2014-08-19 13:16:38 +02:00
|
|
|
}
|
|
|
|
|
2017-09-09 18:47:07 +02:00
|
|
|
extern void (*WorldRemove)(CEntity*);
|
|
|
|
void CObject::TryToFreeUpTempObjects_SilentPatch( int numObjects )
|
|
|
|
{
|
|
|
|
int numProcessed, numFreed;
|
|
|
|
std::tie( numProcessed, numFreed ) = TryOrFreeUpTempObjects( numObjects, false );
|
|
|
|
if ( numProcessed >= numObjects && numObjects > numFreed )
|
|
|
|
{
|
|
|
|
TryOrFreeUpTempObjects( numObjects - numFreed, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::tuple<int,int> CObject::TryOrFreeUpTempObjects( int numObjects, bool force )
|
|
|
|
{
|
|
|
|
int numProcessed = 0, numFreed = 0;
|
|
|
|
|
|
|
|
auto& pool = CPools::GetObjectPool();
|
|
|
|
for ( auto& obj : pool )
|
|
|
|
{
|
|
|
|
if ( numFreed >= numObjects ) break;
|
|
|
|
|
|
|
|
CObject* const objPtr = &obj;
|
|
|
|
if ( pool.IsValidPtr( objPtr ) )
|
|
|
|
{
|
|
|
|
if ( objPtr->m_objectCreatedBy == TEMP_OBJECT )
|
|
|
|
{
|
|
|
|
numProcessed++;
|
|
|
|
if ( force || !objPtr->IsVisible() )
|
|
|
|
{
|
|
|
|
numFreed++;
|
|
|
|
WorldRemove( objPtr );
|
|
|
|
delete objPtr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_tuple( numProcessed, numFreed );
|
|
|
|
}
|
|
|
|
|
2014-08-19 13:16:38 +02:00
|
|
|
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<CPed*>(pEntity)->RenderForShadow();
|
|
|
|
else
|
2017-03-27 21:17:43 +02:00
|
|
|
RpClumpForAllAtomics(reinterpret_cast<RpClump*>(pEntity->m_pRwObject), ShadowCameraRenderCB);
|
2014-08-19 13:16:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
InvertRaster();
|
|
|
|
RwCameraEndUpdate(m_pCamera);
|
|
|
|
}
|
|
|
|
return m_pCamera;
|
2016-04-24 20:37:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CEntity*> CEscalator::ms_entitiesToRemove;
|
|
|
|
void CEscalator::SwitchOffNoRemove()
|
|
|
|
{
|
|
|
|
if ( !m_bExists )
|
|
|
|
return;
|
|
|
|
|
2016-09-12 00:11:17 +02:00
|
|
|
for ( ptrdiff_t i = 0, j = field_7C + field_80 + field_84; i < j; ++i )
|
2016-04-24 20:37:14 +02:00
|
|
|
{
|
|
|
|
if ( m_pSteps[i] != nullptr )
|
|
|
|
{
|
|
|
|
ms_entitiesToRemove.push_back( m_pSteps[i] );
|
|
|
|
m_pSteps[i] = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_bExists = false;
|
2014-06-16 02:21:05 +02:00
|
|
|
}
|