Files
GTASource/game/script/script_shapetests.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

185 lines
6.2 KiB
C++

//
// script/script_shapetests.cpp
//
// Copyright (C) 1999-2011 Rockstar Games. All Rights Reserved.
//
// Rage headers
#include "fwsys/gameSkeleton.h"
#include "fwscript/scriptguid.h"
// Game headers
#include "script_shapetests.h"
//Only to be used by CScriptShapeTestManager
struct CScriptShapeTestResults : public fwExtensibleBase
{
FW_REGISTER_CLASS_POOL(CScriptShapeTestResults);
DECLARE_RTTI_DERIVED_CLASS(CScriptShapeTestResults, fwExtensibleBase);
public:
CScriptShapeTestResults();
~CScriptShapeTestResults();
//Results (contains the handle from WorldProbe)
WorldProbe::CShapeTestResults m_results;
//Progress tracking
bool m_polledThisFrame; //If this request is not polled every frame, we delete it
};
FW_INSTANTIATE_CLASS_POOL(CScriptShapeTestResults, SCRIPTSHAPETESTMANAGER_REQUESTPOOLSIZE, atHashString("ScriptShapeTestResult",0x302e7b2f));
INSTANTIATE_RTTI_CLASS(CScriptShapeTestResults,0x6f37e9db);
CScriptShapeTestResults::CScriptShapeTestResults()
: m_results(), m_polledThisFrame(true)
{
}
CScriptShapeTestResults::~CScriptShapeTestResults()
{
scrDebugf2( "CScriptShapeTestResults::~CScriptShapeTestResults(): %p", this );
// Don't want to leak script resources.
fwScriptGuid::DeleteGuid(*this);
}
//CScriptShapeTestManager
void CScriptShapeTestManager::Init(unsigned initMode)
{
if(initMode == INIT_CORE)
{
CScriptShapeTestResults::InitPool(MEMBUCKET_GAMEPLAY);
}
else if(initMode == INIT_SESSION)
{
}
}
void CScriptShapeTestManager::Shutdown(unsigned shutdownMode)
{
if(shutdownMode == SHUTDOWN_CORE)
{
CScriptShapeTestResults::ShutdownPool();
}
else if(shutdownMode == SHUTDOWN_SESSION)
{
//Deleting a queued request in the pool will remove it from the queue too
CScriptShapeTestResults::GetPool()->DeleteAll();
}
}
#if WORLD_PROBE_DEBUG
ScriptShapeTestGuid CScriptShapeTestManager::DebugCreateShapeTestRequest(const char *strCodeFile, u32 nCodeLine, WorldProbe::CShapeTestDesc& shapeTestParams, bool bSynchronousTest)
#else
ScriptShapeTestGuid CScriptShapeTestManager::CreateShapeTestRequest(WorldProbe::CShapeTestDesc& shapeTestParams, bool bSynchronousTest)
#endif
{
if( CScriptShapeTestResults::GetPool()->GetNoOfFreeSpaces() == 0 )
return 0;
CScriptShapeTestResults* pRequest = rage_new CScriptShapeTestResults();
int guid = fwScriptGuid::CreateGuid(*pRequest); //If guid creation fails then the request will be cleaned up next frame due to being unpolled
shapeTestParams.SetResultsStructure(&pRequest->m_results);
#if WORLD_PROBE_DEBUG
WorldProbe::GetShapeTestManager()->DebugSubmitTest(strCodeFile, nCodeLine, shapeTestParams, bSynchronousTest ? WorldProbe::PERFORM_SYNCHRONOUS_TEST : WorldProbe::PERFORM_ASYNCHRONOUS_TEST);
#else
WorldProbe::GetShapeTestManager()->SubmitTest(shapeTestParams, bSynchronousTest ? WorldProbe::PERFORM_SYNCHRONOUS_TEST : WorldProbe::PERFORM_ASYNCHRONOUS_TEST);
#endif
if( pRequest->m_results.GetResultsStatus() == WorldProbe::SUBMISSION_FAILED )
{
delete pRequest;
return 0;
}
return guid;
}
SHAPETEST_STATUS CScriptShapeTestManager::GetShapeTestResult(ScriptShapeTestGuid shapeTestGuid, WorldProbe::CShapeTestHitPoint& outNearestResultTemporary)
{
CScriptShapeTestResults* pRequest = fwScriptGuid::FromGuid<CScriptShapeTestResults>(shapeTestGuid);
scrDebugf2( "CScriptShapeTestManager::GetShapeTestResult guid: %d Results: %p Status: %d", shapeTestGuid, pRequest, pRequest ? (int)pRequest->m_results.GetResultsStatus() : 0 );
if(!pRequest) return SHAPETEST_STATUS_NONEXISTENT;
switch( pRequest->m_results.GetResultsStatus() )
{
case WorldProbe::WAITING_ON_RESULTS:
pRequest->m_polledThisFrame = true;
return SHAPETEST_STATUS_RESULTS_NOTREADY;
case WorldProbe::RESULTS_READY:
outNearestResultTemporary.Copy( pRequest->m_results[0] ); //This may or may not be a hit
delete pRequest;
return SHAPETEST_STATUS_RESULTS_READY;
case WorldProbe::TEST_NOT_SUBMITTED:
case WorldProbe::SUBMISSION_FAILED:
case WorldProbe::TEST_ABORTED:
physicsAssertf( false, "Script-initiated shape test results in a bad state: %d", pRequest->m_results.GetResultsStatus() );
delete pRequest;
return SHAPETEST_STATUS_NONEXISTENT;
default:
// B*6605259 - this code crashes the game sometimes as it appears to call the destructor for a vehicle
// it does seem that this is possible without any bad stuff appearing in the logs
// but it does so I've added some more logging
if( fwScriptGuid::IsType<fwEntity>( shapeTestGuid ) )
{
fwEntity* pEntity = fwScriptGuid::FromGuid<fwEntity>( shapeTestGuid );
const char* pModelName = "";
pModelName = pEntity->GetModelName();
Displayf( "CScriptShapeTestManager::GetShapeTestResult guid is an entity: %p %s",
pEntity, pModelName );
}
physicsAssertf( false, "Script-initiated shape test results in an invalid state: %d", pRequest->m_results.GetResultsStatus() );
delete pRequest;
return SHAPETEST_STATUS_NONEXISTENT;
}
}
void CScriptShapeTestManager::AbortShapeTestRequest(ScriptShapeTestGuid shapeTestGuid)
{
CScriptShapeTestResults* pRequest = fwScriptGuid::FromGuid<CScriptShapeTestResults>(shapeTestGuid);
scrDebugf2( "CScriptShapeTestManager::AbortShapeTestRequest guid: %d Results: %p", shapeTestGuid, pRequest );
if(!pRequest) return;
//Delete it, releasing the pool slot. Its fwScriptGuid will be deleted with it
//Its destructor will tell the shape test manager to abort it too
delete pRequest;
}
//Loop through queue and pool updating the requests
void CScriptShapeTestManager::Update()
{
//For all requests in the pool:
//1. Destroy requests that the script has ignored this frame
//2. Ask WorldProbe for results if we are waiting
CScriptShapeTestResults::Pool* requestPool = CScriptShapeTestResults::GetPool();
for(int i = 0 ; i < requestPool->GetSize(); i++)
{
CScriptShapeTestResults* pRequest = requestPool->GetSlot(i);
if(!pRequest) continue;
//The script didn't poll for the request this frame, so destroy it
if(!pRequest->m_polledThisFrame)
{
delete pRequest;
continue;
}
else
{
pRequest->m_polledThisFrame = false;
}
}
}