Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

6314 lines
183 KiB
C++

// Title : Debug.cpp
// Author : G. Speirs
// Started : 10/08/99
#include "debug.h"
// STD headers
#if __XENON
#if defined NDEBUG && __ASSERT
#undef NDEBUG
#include <assert.h>
#define NDEBUG
#else
#include <assert.h>
#endif
#include "system/xtl.h"
#include "tracerecording.h"
#endif
// Rage headers
#include "audiohardware/device.h"
#include "audiohardware/driver.h"
#include "bank/bank.h"
#include "bank/bkmgr.h"
#include "bank/msgbox.h"
#include "debug/FrameDump.h"
#include "file/device_installer.h"
#include "diag/output.h"
#include "grcore/debugdraw.h"
#include "fwrenderer/renderlistgroup.h"
#include "fragment/tune.h"
#include "grcore/font.h"
#include "grcore/image.h"
#include "grmodel/setup.h"
#include "grprofile/ekg.h"
#include "grprofile/profiler.h"
#include "grprofile/timebars.h"
#include "parser/psodebug.h"
#include "rmptfx/ptxdebug.h"
#include "streaming/packfilemanager.h"
#include "streaming/streamingengine.h"
#include "streaming/streamingloader.h"
#include "streaming/streamingvisualize.h"
#include "system/ipc.h"
#include "system/exec.h"
#include "system/threadtype.h"
#include "grcore/debugdraw.h"
#include "system/stack.h"
#include "diag/tracker.h" // RAGE_TRACK()
#if __WIN32PC
#include "input/keyboard.h"
#include "input/mouse.h"
#include "grcore/diag_d3d.h"
#endif
//framework headers
#include "entity/archetypemanager.h"
// Game headers
#include "ai/debug/system/AIDebugLogManager.h"
#include "audio/dynamicmixer.h"
#include "audio/northaudioengine.h"
#include "animation/debug/animviewer.h"
#include "camera/CamInterface.h"
#include "camera/base/BaseCamera.h"
#include "camera/debug/FreeCamera.h"
#include "camera/Viewports/ViewportManager.h"
#include "camera/debug/DebugDirector.h"
#include "camera/helpers/frame.h"
#include "control/gamelogic.h"
#include "control/replay/ReplayControl.h"
#include "cutscene/CutSceneManagerNew.h"
#include "cutfile/cutfile2.h"
#include "debug/BankDebug.h"
#include "Debug/BlockView.h"
#include "Debug/BudgetDisplay.h"
#include "Debug/DebugDraw.h"
#include "Debug/DebugGlobals.h"
#include "Debug/DebugLocation.h"
#include "Debug/DebugRecorder.h"
#include "Debug/DebugScene.h"
#include "Debug/GtaPicker.h"
#include "debug/LightProbe.h"
#include "Debug/VectorMap.h"
#include "Debug/OverviewScreen.h"
#include "Debug/Rendering/DebugCamera.h"
#include "debug/Rendering/DebugLights.h"
#include "debug/SceneGeometryCapture.h"
#include "event/EventNetwork.h"
#include "frontend/PauseMenu.h"
#include "frontend/MiniMap.h"
#include "frontend/hud_colour.h"
#include "frontend/NewHud.h"
#include "frontend/scaleform/scaleformmgr.h"
#include "frontend/GameStreamMgr.h"
#include "fwnet/neteventmgr.h"
#include "game/clock.h"
#include "game/weather.h"
#include "game/zones.h"
#include "Network/Network.h"
#include "Network/Arrays/NetworkArrayMgr.h"
#include "Network/Bandwidth/NetworkBandwidthManager.h"
#include "Network/Debug/NetworkDebug.h"
#include "Network/General/NetworkUtil.h"
#include "Network/Objects/NetworkObjectMgr.h"
#include "network/Objects/Entities/NetObjPlayer.h"
#include "Network/Players/NetworkPlayerMgr.h"
#include "Network/Voice/NetworkVoice.h"
#include "objects/object.h"
#include "peds/ped.h"
#include "peds/pedfactory.h"
#include "Peds/PedCapsule.h"
#include "Peds/PedDebugVisualiser.h"
#include "Peds/PedIntelligence.h"
#include "peds/PedPopulation.h"
#include "peds/PlayerInfo.h"
#include "Peds/Rendering/PedVariationDebug.h"
#include "physics/physics.h"
#include "physics/debugplayback.h"
#include "renderer/renderListGroup.h"
#include "renderer/drawlists/drawList.h"
#include "renderer/PlantsMgr.h"
#include "scene/AnimatedBuilding.h"
#include "scene/entities/compEntity.h"
#include "scene/RefMacros.h"
#include "scene/RegdRefTypes.h"
#include "scene/scene.h"
#include "scene/streamer/SceneStreamerMgr.h"
#include "scene/LoadScene.h"
#include "scene/world/gameworld.h"
#include "scene/world/GameWorldHeightMap.h"
#include "scene/WarpManager.h"
#include "script/commands_streaming.h"
#include "shaders/CustomShaderEffectProp.h"
#include "streaming/streaming.h"
#include "streaming/streamingengine.h"
#include "streaming/streamingvisualize.h"
#include "system/bootmgr.h"
#include "system/controlMgr.h"
#include "system/AutoGPUCapture.h"
#include "system/SettingsManager.h"
#include "system/ThreadPriorities.h"
#include "vehicleAi/pathfind.h"
#include "vehicles/train.h"
#include "vehicles/vehiclefactory.h"
#include "vehicles/vehiclepopulation.h"
#include "fwdebug/picker.h"
#include "fwsys/timer.h"
#include "scene/debug/PostScanDebug.h"
#include "physics/WorldProbe/worldprobe.h"
#include "text/messages.h"
#include "control/videorecording/videorecording.h"
#include "script/commands_socialclub.h"
#include "text/TextConversion.h"
#include "system/bootmgr.h"
#include "system/tmcommands.h"
// bugstar headers
#if BUGSTAR_INTEGRATION_ACTIVE
// Rage Headers
#include "qa/bugstarinterface.h"
// Game Headers
#include "BugstarIntegration.h"
#include "debug/bugstar/MissionLookup.h"
bool CDebug::ms_invincibleBugger = false;
bool CDebug::ms_showInvincibleBugger = true;
bool CDebug::ms_disableSpaceBugScreenshots = false;
u32 CDebug::ms_screenShotFrameDelay = 0;
PARAM(bugstardescpedvar, "[debug] Prints local player ped variation data to description on new bug creation");
#endif //BUGSTAR_INTEGRATION_ACTIVE
RAGE_DEFINE_CHANNEL(debug)
AI_OPTIMISATIONS()
// EJ: Poor man's FPS capture
#define ENABLE_FPS_CAPTURE (0)
PARAM(debugstart, "Start at this co-ordinates with specific camera orientation");
PARAM(dontshowinvinciblebugger, "[debug] Don't show the invincible bugger message");
PARAM(peddebugvisualiser, "[debug] Default value for ped debug visualiser");
PARAM(dontdisplayforplayer, "[debug] Don't display information for players in the ped debug visualiser");
PARAM(enableBoundByGPUFlip, "PC-only: Enable us to be bound by the time spent in Present() - otherwise this is rolled into Render Thread");
PARAM(capturecard, "[debug] Capturecard is installed");
PARAM(debugrespot, "[debug] Debug MP vehicle respotting code");
PARAM(debugrespawninvincibility, "[debug] Debug MP respawn invincibility");
PARAM(debugdoublekill, "[debug] Debug MP double kill");
PARAM(debugexplosion, "[debug] Debug explosion at the player location");
PARAM(debuglicenseplate, "[debug] Debug license plate retrieval from SCS license plate system");
PARAM(debugaircraftcarrier, "[debug] Debug aircraft carrier");
PARAM(debugradiotest, "[debug] Debug radio test");
PARAM(dbgfontscale, "[debug] Init the debug fontscale with a specific value");
PARAM(dumpPedInfoOnBugCreation, "[debug] Dump ped info when a bug is created");
PARAM(displayNetInfoOnBugCreation, "[debug] Enable display of net object info when a bug is created");
PARAM(ekgdefault, "Startup ekg with the page");
PARAM(disableTimeSkipBreak, "Disable time skip detection");
PARAM(DR_RecordForBug, "Attach any debug recording to the bug, param is filename to store tmp recording in");
PARAM(licensePlate, "Text for the license plate");
#if BUGSTAR_INTEGRATION_ACTIVE
PARAM(disableSpaceBugScreenshots, "[debug] Prevents screenshots being added to bugs created using the Space bar");
#endif //BUGSTAR_INTEGRATION_ACTIVE
XPARAM(installremote);
XPARAM(gond);
#if RSG_DURANGO
namespace rage
{
XPARAM(forceboothdd);
XPARAM(forceboothddloose);
};
#endif
DR_ONLY(GameRecorder* CDebug::ms_GameRecorder);
namespace rage
{
XPARAM(nopopups);
}
namespace rage {
extern Vector2 g_previewCoords;
}
char CDebug::m_iVersionId[32] = {0};
char CDebug::m_sRawVersionId[32] = {0};
char CDebug::m_sOnlineVersionId[32] = {0};
#if !__FINAL
char CDebug::m_sFullVersionId[32];
#endif
char CDebug::m_iInstallVersionId[32];
int CDebug::m_iSavegameVersionId;
#if DEBUG_PAD_INPUT
//url:bugstar:4559363 - Can we bring the RDR style input debug back into GTAV?
//data source files: CONTROLLER_TEST.fla/.as/.swf/.gfx
s32 CDebug::m_iScaleformMovieId = -1;
Vector2 m_vPos = Vector2( 0.04f, 0.145f );
float fMovieWidth = 0.097f;
float fMovieHeight = 0.403f;
float fSizeScaler = 0.8f;
Vector2 m_vSize = Vector2( fMovieWidth * fSizeScaler, fMovieHeight * fSizeScaler );
#endif
#if GTA_REPLAY
u32 CDebug::m_iReplayVersionId = 0;
#endif //GTA_REPLAY
char CDebug::ms_currentMissionTag[256];
char CDebug::ms_currentMissionName[256];
float CDebug::sm_fWaitForRender = 0.0f;
float CDebug::sm_fWaitForGPU = 0.0f;
float CDebug::sm_fWaitForMain = 0.0f;
float CDebug::sm_fDrawlistQPop = 0.0f;
float CDebug::sm_fEndDraw = 0.0f;
float CDebug::sm_fWaitForDrawSpu = 0.0f;
float CDebug::sm_fFifoStallTimeSpu = 0.0f;
bool CDebug::sm_enableBoundByGPUFlip = false;
#if __ASSERT
int CDebug::sm_iBlockedPopups = 0;
#endif // __ASSERT
#if __BANK
bkBank* CDebug::ms_pRageDebugChannelBank;
bkBank* CDebug::ms_pToolsBank;
CBankDebug* CDebug::ms_pBankDebug;
bool CDebug::m_debugParamUsed = false;
float CDebug::sm_dbgFontscale = 1.0f;
static bkBank* s_LiveEditBank;
static bool g_bDisplayTimescale = true;
#if RSG_DURANGO
bool CDebug::sm_bDisplayLightSensorQuad = false;
#endif
static const u32 s_numRenderPhases = 5;
const char* s_renderPhaseNames[] = {"DL_DRAWSCENE", "DL_GBUF", "DL_SHADOWS", "DL_REFLECTIONMAP", "DL_WATER_REFLECTION" };
dlDrawListMgr::drawlistStatData s_renderPhaseData[s_numRenderPhases];
bool CDebug::sm_debugrespot = false;
bool CDebug::sm_debugrespawninvincibility = false;
bool CDebug::sm_debugdoublekill = false;
bool CDebug::sm_debugexplosion = false;
bool CDebug::sm_debuglicenseplate = false;
bool CDebug::sm_debugaircraftcarrier = false;
bool CDebug::sm_debugradiotest = false;
int CDebug::sm_token = 0;
#endif // __BANK
#if !__FINAL
debugLocationList ms_locationList;
bool gSmoothPerformanceResults = true;
#if __BANK
static bool s_renderObjects = false;
static bool s_renderShaders = false;
#if RSG_DURANGO
static bool s_showDebugTimeInfo = false;
#endif // RSG_DURANGO
#endif // __BANK
#endif // !__FINAL
extern bool g_render_lock;
extern bool gLastGenModeState;
void SwitchToSPVehicles()
{
const CDataFileMgr::ContentChangeSet *changeSet = DATAFILEMGR.GetContentChangeSet("MPtoSP");
Assert(changeSet);
CFileLoader::ExecuteContentChangeSet(*changeSet);
}
void SwitchToMPVehicles()
{
const CDataFileMgr::ContentChangeSet *changeSet = DATAFILEMGR.GetContentChangeSet("SPtoMP");
Assert(changeSet);
CFileLoader::ExecuteContentChangeSet(*changeSet);
}
#if DR_ENABLED
bool CDebug::IsDebugRecorderDisplayEnabled()
{
if(ms_GameRecorder && ms_GameRecorder->IsDisplayOn())
{
return true;
}
return false;
}
#endif // DR_ENABLED
//////////////////////////////////////////////////////////////////////////
#if BUGSTAR_INTEGRATION_ACTIVE
const char* gBugstarClassCombo[7] = {
"A", "B", "C", "D", "TODO", "WISH", "TASK"
};
static atString gBugstarDescription;
static char gBugstarSummary[256] = "";
static char gBugstarOwner[256] = "";
static s32 gBugstarClass = 4;
static bool gBugstarPedVariationInfo = false;
bool s_requestAddBug = false;
void CDebug::RequestAddBug(){
s_requestAddBug = true;
}
void CDebug::FillOutBugDetails(qaBug& bug)
{
char tmp[256];
Vector3 posn = camInterface::GetPos();
Vector3 front = camInterface::GetFront();
s32 hour = CClock::GetHour();
s32 minute = CClock::GetMinute();
#if __XENON
bug.SetField(BUG_REP_PLATFORM,(void*)"Xbox 360",8);
#elif __PPU
bug.SetField(BUG_REP_PLATFORM,(void*)"PS3",3);
#elif __WIN32PC
bug.SetField(BUG_REP_PLATFORM,(void*)"PC",2);
#elif RSG_ORBIS
bug.SetField(BUG_REP_PLATFORM,(void*)"PS4",3);
#elif RSG_DURANGO
bug.SetField(BUG_REP_PLATFORM,(void*)"Xbox One",8);
#endif
bug.SetProduct("GTA 5");
if(CTheScripts::GetPlayerIsOnAMission() || CTheScripts::GetPlayerIsOnARandomEvent() )
{
formatf(tmp,sizeof(tmp),"%s",CMissionLookup::GetMissionId(CDebug::ms_currentMissionName));
bug.BeginField("mission","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
}
// POS
formatf(tmp,sizeof(tmp),"%f",posn.x);
bug.BeginField("XCoord","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
formatf(tmp,sizeof(tmp),"%f",posn.y);
bug.BeginField("YCoord","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
formatf(tmp,sizeof(tmp),"%f",posn.z);
bug.BeginField("ZCoord","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
// FRONT
formatf(tmp,sizeof(tmp),"%f",front.x);
bug.BeginField("XFront","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
formatf(tmp,sizeof(tmp),"%f",front.y);
bug.BeginField("YFront","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
formatf(tmp,sizeof(tmp),"%f",front.z);
bug.BeginField("ZFront","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
// Hours
formatf(tmp,sizeof(tmp),"%d",hour);
bug.BeginField("TODHour","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
// Minutes
formatf(tmp,sizeof(tmp),"%d",minute);
bug.BeginField("TODMin","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
if (CBlockView::GetNumberOfBlocks())
{
FileHandle fHandle = CFileMgr::OpenFile("common:/data/levels/gta5_liberty/vector_map.xml");
if (fHandle)
{
bool exit = false;
atString blockName, splineCount, pointCount;
char line[256];
while (CFileMgr::ReadLine(fHandle, line, 256) && !exit)
{
atString str(line);
str.Trim();
if (str.StartsWith("<section"))
{
atString dump, dump2, dump3;
// 1 : Extract the name from the section
str.Split(dump, dump2, '"');
dump2.Split(blockName, dump, '"');
// 2 : Extract the spline count from the section
dump.Split(dump2, dump3, "spline_count=\"");
dump3.Split(splineCount, dump, '"');
// 3 : For each spline, extract the points and see if we are inside the polygon defined by those
int splines = atoi(splineCount.c_str());
CFileMgr::ReadLine(fHandle, line, 256); // ignore the line defining the colour of the section
for (int i = 0; i < splines; ++i)
{
// get the number of points
CFileMgr::ReadLine(fHandle, line, 256);
atString str(line), pointCount;
str.Trim();
if (str.StartsWith("<spline point_count=\""))
{
str.Split(dump, dump2, '"');
dump2.Split(pointCount, dump, '"');
int points = atoi(pointCount.c_str());
// 4 : construct the polygon from the set of points
atArray<Vec2V> polygon;
polygon.Reserve(points+1);
spdAABB aabb;
for (int pointIdx = 0; pointIdx < points; ++pointIdx)
{
CFileMgr::ReadLine(fHandle, line, 256);
atString str(line), xValue, yValue;
str.Trim();
str.Split(dump, dump2, '"');
dump2.Split(xValue, dump, '"');
dump.Split(dump2, dump3, "y=\"");
dump3.Split(yValue, dump, '"');
Vec2V pt(static_cast<float>(atof(xValue.c_str())), static_cast<float>(atof(yValue.c_str())));
polygon.Push( pt );
aabb.GrowPoint( Vec3V(pt.GetXf(), pt.GetYf(), 0.0f) );
}
polygon.Push(polygon[0]);
Vec2V pos(V_ZERO);
camDebugDirector& debugDirector = camInterface::GetDebugDirector();
if (debugDirector.IsFreeCamActive())
pos = Vec2V(debugDirector.GetFreeCamFrame().GetPosition().x, debugDirector.GetFreeCamFrame().GetPosition().y);
else
pos = Vec2V(CGameWorld::FindLocalPlayerCentreOfWorld().x, CGameWorld::FindLocalPlayerCentreOfWorld().y);
// 5 : Test if we are in the polygon only if we're in the aabb (for performance reasons)
if (aabb.ContainsPointFlat(pos))
{
int wn = 0;
for (int j=0; j<polygon.GetCount()-1; ++j)
{
Vec2V v1 = polygon[j];
Vec2V v2 = polygon[j+1];
if (v1.GetYf() <= pos.GetYf())
{
if (v2.GetYf() > pos.GetYf()) // an upward crossing
if ((v2.GetXf() - v1.GetXf()) * (pos.GetYf() - v1.GetYf()) - (pos.GetXf() - v1.GetXf()) * (v2.GetYf() - v1.GetYf()) > 0.0f) // pos left of edge
++wn; // have a valid up intersect
}
else
{
if (v2.GetYf() <= pos.GetYf()) // a downward crossing
if ((v2.GetXf() - v1.GetXf()) * (pos.GetYf() - v1.GetYf()) - (pos.GetXf() - v1.GetXf()) * (v2.GetYf() - v1.GetYf()) < 0.0f) // pos right of edge
--wn; // have a valid down intersect
}
}
if(wn != 0) // if we are inside the polygon
{
strcpy(tmp, blockName.c_str());
exit = true;
}
}
polygon.Reset();
CFileMgr::ReadLine(fHandle, line, 256); // ignore the </spline> tag line
}
else
{
Assertf(false, "No spline defined for the block %s", blockName.c_str());
}
}
}
}
CFileMgr::CloseFile(fHandle);
}
else
{
formatf(tmp,sizeof(tmp),"%s",(const char*)CBlockView::GetBlockName(CBlockView::GetCurrentBlockInside()));
}
}
else
tmp[0] = '\0';
bug.BeginField("grid","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
// Write out the streaming video ID if it's present, otherwise send "1".
if (CBugstarIntegration::GetStreamingVideoId(tmp, sizeof(tmp)) == false)
{
strcpy(tmp, "1");
}
bug.BeginField("video_id","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
if (GetVersionNumber())
{
formatf(tmp,sizeof(tmp),"%s - All", GetVersionNumber());
bug.BeginField("Found In","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
}
// MP Console log files...
if(CBugstarIntegration::AddConsoleLogsToBug())
{
int logFileNumber = diagChannel::GetLogFileNumber();
int minLogFileNumber = rage::Max(0, logFileNumber - 2);
char origConsoleLogNoExtention[256] = "\0";
strcpy(origConsoleLogNoExtention, diagChannel::GetLogFileName());
strtok(origConsoleLogNoExtention, ".");
if(logFileNumber)
{
char* underscore = strrchr(origConsoleLogNoExtention,'_');
if(underscore)
{
*underscore = '\0';
}
}
// we want the mpconsolelog fields to be mpconsolelogs1, mpconsolelogs2, mpconsolelogs3
int fieldnamedigit = 1;
for(int i = logFileNumber; i >= minLogFileNumber; --i)
{
tmp[0] = '\0';
if(!i)
{
formatf(tmp,sizeof(tmp),"%s.log", origConsoleLogNoExtention);
}
else
{
if(origConsoleLogNoExtention)
{
formatf(tmp,sizeof(tmp),"%s_%d.log", origConsoleLogNoExtention, i);
}
}
FileHandle handle = CFileMgr::OpenFile(tmp);
if( CFileMgr::IsValidFileHandle(handle) )
{
char buffer[32] = "\0";
formatf(buffer, 32, "mpconsolelogs%d", fieldnamedigit);
++fieldnamedigit;
bug.BeginField(buffer, "text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
CFileMgr::CloseFile(handle);
}
}
// AddNetLogToBug(NetworkInterface::GetMessageLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetArrayManager().GetLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetEventManager().GetLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetObjectManagerLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetObjectManager().GetReassignMgr().GetLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetPlayerMgr().GetLog(), bug, fieldnamedigit);
// AddNetLogToBug(NetworkInterface::GetBandwidthManager().GetLog(), bug, fieldnamedigit);
// if(CTheScripts::GetScriptHandlerMgr().GetLog())
// {
// AddNetLogToBug(*CTheScripts::GetScriptHandlerMgr().GetLog(), bug, fieldnamedigit);
// }
}
#if __BANK
if (CAILogManager::ShouldAutoAddLogWhenBugAdded())
{
int fieldnamedigit = 1;
AddNetLogToBug(CAILogManager::GetLog(), bug, fieldnamedigit);
}
#endif // __BANK
}
void CDebug::AddNetLogToBug(const netLoggingInterface& logInterface, qaBug& bug, int& fieldNameDigit)
{
char logNameNoExtention[256] = "";
char tmp[256] = "";
logInterface.GetFileName(tmp, sizeof(tmp));
formatf(logNameNoExtention, "%s%s", CFileMgr::GetCurrDirectory(), tmp);
// Remove extension
char* extSeperator = strrchr(logNameNoExtention,'.');
if (extSeperator)
{
*extSeperator = '\0';
}
for(int logPostfix = 1; /*break when it gets to an invalid file*/; ++logPostfix)
{
// The first log is logName.log, the second one is logName_2.log, Nth is logName_N.log
if(logPostfix == 1)
{
formatf(tmp,sizeof(tmp),"%s.log", logNameNoExtention);
}
else
{
formatf(tmp,sizeof(tmp),"%s_%d.log", logNameNoExtention, logPostfix);
}
FileHandle handle = CFileMgr::OpenFile(tmp);
if( CFileMgr::IsValidFileHandle(handle) )
{
CFileMgr::CloseFile(handle);
char buffer[32] = "\0";
formatf(buffer, 32, "mpconsolelogs%d", fieldNameDigit++);
bug.BeginField(buffer, "text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
}
else
{
break;
}
}
}
void CDebug::DumpPedInfo()
{
static const char* Names[] = {
"PED_TASK_PRIORITY_PHYSICAL_RESPONSE",
"PED_TASK_PRIORITY_EVENT_RESPONSE_TEMP",
"PED_TASK_PRIORITY_EVENT_RESPONSE_NONTEMP",
"PED_TASK_PRIORITY_PRIMARY",
"PED_TASK_PRIORITY_DEFAULT",
"PED_TASK_PRIORITY_MAX"
};
CPed::Pool* pPool = CPed::GetPool();
if(!Verifyf(pPool, "Ped pool doesn't exist!?"))
{
return;
}
Displayf("========================================================================");
Displayf("= PED DUMP BEGIN");
Displayf("========================================================================");
for( s32 pedIndex = 0; pedIndex < pPool->GetSize(); pedIndex++ )
{
CPed* pPed = pPool->GetSlot(pedIndex);
if(pPed)
{
// Ped Name
Displayf("%s:%s%s", pPed->GetLogName(), pPed->IsNetworkClone() ? " [Clone]" : "", pPed->IsAPlayerPed() ? " [Player]" : "");
// Model
Displayf("\tModel: %s", pPed->GetModelName());
// Position
Vector3 pos = VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition());
Displayf("\tPosition: %0.2f, %0.2f, %0.2f", pos.x, pos.y, pos.z);
// Tasks
CPedIntelligence* pIntel = pPed->GetPedIntelligence();
CPedTaskManager* pTaskMgr = pIntel ? static_cast<CPedTaskManager*>(pIntel->GetTaskManager()) : NULL;
if(Verifyf(pTaskMgr, "No task manager for %s", pPed->GetLogName()))
{
for(int p = PED_TASK_PRIORITY_PHYSICAL_RESPONSE; p < PED_TASK_PRIORITY_MAX; ++p)
{
CTask* task = static_cast<CTask*>(pTaskMgr->GetTask(PED_TASK_TREE_PRIMARY, p));
if(!task)
continue;
Displayf("\t%s:", Names[p]);
while(task)
{
if(task->IsClonedFSMTask())
{
// Format: TASK_NAME (TIME_IN_TASK) : STATE_NAME (TIME_IN_STATE) [NetState: STATE_FROM_NETWORK]
CTaskFSMClone* cloneTask = static_cast<CTaskFSMClone*>(task);
bool isLocal = !pPed->IsNetworkClone() || cloneTask->IsRunningLocally();
Displayf("\t\t%s (%0.2f) : %s (%0.2f)%s%s%s", TASKCLASSINFOMGR.GetTaskName(cloneTask->GetTaskType()), cloneTask->GetTimeRunning(), cloneTask->GetCurrentStateName(), cloneTask->GetTimeInState(),
!isLocal ? " [NetState: " : "", !isLocal ? cloneTask->GetStateName(cloneTask->GetStateFromNetwork()) : "", !isLocal ? "]" : "");
}
else
{
// Format: TASK_NAME (TIME_IN_TASK) : STATE_NAME (TIME_IN_STATE)
Displayf("\t\t%s (%0.2f) : %s (%0.2f)", TASKCLASSINFOMGR.GetTaskName(task->GetTaskType()), task->GetTimeRunning(), task->GetCurrentStateName(), task->GetTimeInState());
}
task = task->GetSubTask();
}
}
}
}
}
Displayf("========================================================================");
Displayf("= PED DUMP END");
Displayf("========================================================================");
}
//
// name: AddBug
// description: add the bug to Bug*
void CDebug::AddBug(bool requestAddBug, int bugType, bool requestDebugText, bool forceIgnoreVideoCapture, bool forceIgnoreScreenshot, bool forceSecondScreenshot)
{
static bool ignoreVideo = false;
static bool ignoreScreenshot = false;
static bool captureSecondScreenshot = false;
static bool sendSecondScreenshot = false;
static bool debugTextForced = false;
static bool createBug = true;
static bool addBug = false;
#if __BANK
static bool prevDisplayNetInfo = false;
#endif
if(requestDebugText)
debugTextForced = true;
if (forceIgnoreVideoCapture)
ignoreVideo = true;
if (forceIgnoreScreenshot)
{
ignoreScreenshot = true;
}
else
{
ignoreScreenshot = false;
}
if (forceSecondScreenshot)
{
captureSecondScreenshot = true;
sendSecondScreenshot = true;
}
#if __BANK
// if the debug text is not displayed and we need it to display and request a bug next frame
if(!grcDebugDraw::GetDisplayDebugText() && debugTextForced)
{
grcDebugDraw::SetDisplayDebugText(true);
}
#endif // __BANK
// Add in a bug
if (requestAddBug)
{
#if __BANK
if(PARAM_displayNetInfoOnBugCreation.Get() && !addBug)
{
// Cache the current setting
prevDisplayNetInfo = NetworkDebug::GetDebugDisplaySettings().m_displayObjectInfo;
// Enable network object info (so it shows up in the screenshot)
NetworkDebug::GetDebugDisplaySettings().m_displayObjectInfo = true;
}
#endif
addBug = true;
ms_screenShotFrameDelay = 3;
return;
}
if (ms_screenShotFrameDelay > 0 && addBug)
{
ms_screenShotFrameDelay--;
return;
}
if (!addBug)
{
return;
}
HANG_DETECT_SAVEZONE_ENTER();
#if !__NO_OUTPUT
const unsigned startTimestamp = sysTimer::GetSystemMsTime();
Displayf("AddBug - Adding Bug");
#endif
// Capturing screenshot/communicating with bugstar prevents
// audio vram requests from being serviced, leading to stream starvation.
// Mute and pause the mixer for the duration to prevent this.
if(audDriver::GetMixer())
{
audDriver::GetMixer()->SetPaused(true);
}
// the debug text was forced for this bug. turn it off again
#if __BANK
if(debugTextForced)
{
debugTextForced = false;
grcDebugDraw::SetDisplayDebugText(false);
}
#endif // __BANK
// Reset adding bug
if (addBug)
{
addBug = false;
}
#if DR_ENABLED
const char* debugRecordingName = 0;
if (PARAM_DR_RecordForBug.Get(debugRecordingName))
{
//If we've been recording data - add it to the bug
//Added early as this need un-fragmented debug heap for a big save file buffer
if (debugPlayback::DebugRecorder::GetInstance() && debugPlayback::DebugRecorder::GetInstance()->GetFirstFramePtr())
{
debugPlayback::DebugRecorder::GetInstance()->Save(debugRecordingName);
}
}
#endif //DR_ENABLED
#if !__WIN32PC
// if remote server is not running start it up
if(!fiRemoteServerIsRunning)
fiDeviceRemote::InitClass(0, NULL);
#endif
#if RSG_DURANGO
char* shotName = "X:/lastBug.jpg";
char* shotNameF9 = "X:/lastBugF9.jpg";
if(PARAM_forceboothdd.Get() || PARAM_forceboothddloose.Get())
{
shotName = "D:/lastBug.jpg";
}
#else
const char *shotName = "X:/lastBug.jpg";
const char *shotNameF9 = "X:/lastBugF9.jpg";
#endif
if(!ignoreScreenshot)
{
// if we take a second screenshot we need to wait 3 more frames
if (captureSecondScreenshot && ms_screenShotFrameDelay == 0)
{
addBug = true;
ms_screenShotFrameDelay = 3;
captureSecondScreenshot = false;
createBug = false;
#if RSG_DURANGO
shotNameF9 = "X:/lastBugF9.jpg";
if(PARAM_forceboothdd.Get() || PARAM_forceboothddloose.Get())
{
shotNameF9 = "D:/lastBugF9.jpg";
}
#else
shotNameF9 = "X:/lastBugF9.jpg";
#endif
USE_DEBUG_MEMORY();
#if RSG_PC
ASSERT_ONLY(sysMemStreamingCount++;)
ASSERT_ONLY(sysMemAllowResourceAlloc++;)
sysMemAllocator& temp_sma = sysMemAllocator::GetCurrent();
sysMemAllocator::SetCurrent(*sysMemAllocator::GetMaster().GetAllocator(MEMTYPE_RESOURCE_PHYSICAL));
#endif
if (!GRCDEVICE.CaptureScreenShotToJpegFile(shotNameF9))
{
Warningf("Unable to take screenshot for bug, will use most recently taken shot instead.");
}
#if RSG_PC
sysMemAllocator::SetCurrent(temp_sma);
ASSERT_ONLY(sysMemAllowResourceAlloc--;)
ASSERT_ONLY(sysMemStreamingCount--;)
#endif
// Remove the Mission Flow layout
CControlMgr::GetKeyboard().FakeKeyPress(KEY_F9);
}
else
{
// Save JPEG image
createBug = true;
USE_DEBUG_MEMORY();
#if RSG_PC
ASSERT_ONLY(sysMemStreamingCount++;)
ASSERT_ONLY(sysMemAllowResourceAlloc++;)
sysMemAllocator& temp_sma = sysMemAllocator::GetCurrent();
sysMemAllocator::SetCurrent(*sysMemAllocator::GetMaster().GetAllocator(MEMTYPE_RESOURCE_PHYSICAL));
#endif
if (!GRCDEVICE.CaptureScreenShotToJpegFile(shotName))
{
Warningf("Unable to take screenshot for bug, will use most recently taken shot instead.");
}
#if RSG_PC
sysMemAllocator::SetCurrent(temp_sma);
ASSERT_ONLY(sysMemAllowResourceAlloc--;)
ASSERT_ONLY(sysMemStreamingCount--;)
#endif
}
}
// Create Bug
if (createBug)
{
#if __BANK
// Restore the disply object info settings after the screenshot
if(PARAM_displayNetInfoOnBugCreation.Get())
{
NetworkDebug::GetDebugDisplaySettings().m_displayObjectInfo = prevDisplayNetInfo;
}
#endif
qaBugstarInterface BUGSTAR;
qaBug bug;
char tmp[128];
FillOutBugDetails(bug);
bug.SetSeverity(gBugstarClassCombo[gBugstarClass]);
// either get the owner of the current mission or get the current block we are inside along with the owner & add it to the bug details
if(bugType == BUG_TYPE_LEVELS &&
( CTheScripts::GetPlayerIsOnAMission() || CTheScripts::GetPlayerIsOnARandomEvent() ) )
{
bug.SetOwner(CMissionLookup::GetMissionOwner(CDebug::ms_currentMissionName));
}
if(gBugstarOwner[0] == '\0' && CBlockView::GetNumberOfBlocks())
{
bug.SetOwner(CBlockView::GetBlockUser(CBlockView::GetCurrentBlockInside()));
}
else
{
bug.SetOwner(gBugstarOwner);
}
if (gBugstarDescription.GetLength())
{
bug.SetDescription(gBugstarDescription.c_str());
gBugstarDescription.Clear();
}
else
{
bug.SetDescription(gBugstarSummary);
}
bug.SetSummary(gBugstarSummary);
formatf(tmp,sizeof(tmp),"%d", static_cast<int>(ignoreVideo));
bug.BeginField("IgnoreVideo","text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)tmp,sizeof(char) * strlen(tmp));
bug.EndCustomFieldData();
bug.EndField();
ignoreVideo = false;
#if !__FINAL
if(CReplayMgr::IsEditModeActive())
{
char clipSourcePath[REPLAYPATHLENGTH];
ReplayFileManager::getClipDirectory(clipSourcePath, true);
const char* clipSourceName = CReplayMgrInternal::sm_lastLoadedClip.c_str();
const char* clipDumpStore = ReplayFileManager::GetDumpFolder();
char clipDumpStorePlatform[RAGE_MAX_PATH];
sprintf(clipDumpStorePlatform, "%s\\%s\\", clipDumpStore, RSG_PLATFORM_ID);
const char* extensions[] = {".clip", ".jpg"};
for(int i = 0; i < sizeof(extensions) / sizeof(char*); ++i)
{
char fileName[RAGE_MAX_PATH];
sprintf(fileName, "%s%s", clipSourceName, extensions[i]);
ReplayFileManager::DumpReplayFile(clipSourcePath, fileName, clipDumpStorePlatform);
char dumpedFilepath[RAGE_MAX_PATH];
sprintf(dumpedFilepath, "%s%s", clipDumpStorePlatform, fileName);
if(rage::ASSET.Exists(dumpedFilepath, ""))
{
const rage::fiDevice *pDevice = fiDevice::GetDevice(dumpedFilepath);
if(pDevice)
{
char clippath[RAGE_MAX_PATH] = "";
pDevice->FixRelativeName(clippath, RAGE_MAX_PATH, dumpedFilepath);
if(rage::ASSET.Exists(clippath, "")) // just being cautious - better than the user getting a cryptic bugstar error if something went wrong
{
bug.BeginField("Filepath", "text");
bug.BeginCustomFieldData();
bug.AddCustomFieldData((void*)clippath, sizeof(char) * strlen(clippath));
bug.EndCustomFieldData();
bug.EndField();
}
}
}
}
}
#endif // !__FINAL
#if RSG_PC
// attach the settings.xml file to the bug
if (rage::ASSET.Exists(CSettingsManager::sm_settingsPath, ""))
{
const rage::fiDevice *pDevice=fiDevice::GetDevice(CSettingsManager::sm_settingsPath);
if (pDevice)
{
char settingspath[RAGE_MAX_PATH]="";
pDevice->FixRelativeName(settingspath,RAGE_MAX_PATH,CSettingsManager::sm_settingsPath);
if(rage::ASSET.Exists(settingspath, "")) // just being cautious - better than the user getting a cryptic bugstar error if something went wrong
bug.SetLogFile(settingspath);
}
}
#endif
#if DR_ENABLED
if (debugRecordingName)
{
bug.SetLogFile(debugRecordingName);
}
#endif
if(!ignoreScreenshot)
{
if (sendSecondScreenshot)
{
sendSecondScreenshot = false;
BUGSTAR.CreateBug(bug, shotName, -1, shotNameF9);
}
else
{
BUGSTAR.CreateBug(bug, shotName);
}
}
else
{
BUGSTAR.CreateBug(bug, NULL);
}
ignoreScreenshot = false;
if(PARAM_dumpPedInfoOnBugCreation.Get())
{
DumpPedInfo();
}
#if __BANK
if (NetworkInterface::IsGameInProgress())
{
NetworkDebug::AddFailMark("BUGSTAR BUG ADDED");
}
#endif // __BANK
}
if(audDriver::GetMixer())
{
audDriver::GetMixer()->SetPaused(false);
}
HANG_DETECT_SAVEZONE_EXIT(NULL);
#if !__NO_OUTPUT
Displayf("AddBug - Bottom, TimeTaken: %u", sysTimer::GetSystemMsTime() - startTimestamp);
#endif
}
#if RSG_DURANGO && __BANK
extern "C" {
WINBASEAPI
VOID
WINAPI
GetSystemTimePreciseAsFileTime(
_Out_ LPFILETIME lpSystemTimeAsFileTime
);
}
#endif // RSG_DURANGO && __BANK
void CDebug::HandleBugRequests()
{
#if RSG_DURANGO && __BANK
static u32 frame = 1;
static u32 framesShown = 1;
static time_t wallInitial;
static ULONGLONG gtcInitial;
static LARGE_INTEGER qpcInitial;
static LARGE_INTEGER qpfInitial;
static ULARGE_INTEGER gstInitial;
static u64 gtcSum, qpcSum, gstSum;
if(frame == 1)
{
wallInitial = time(NULL);
QueryPerformanceCounter(&qpcInitial);
QueryPerformanceFrequency(&qpfInitial);
gtcInitial = GetTickCount64();
FILETIME gstInitialFT;
GetSystemTimePreciseAsFileTime(&gstInitialFT);
gstInitial.HighPart = gstInitialFT.dwHighDateTime;
gstInitial.LowPart = gstInitialFT.dwLowDateTime;
}
else
{
u64 tscBegin, tscEnd;
LARGE_INTEGER qpf;
QueryPerformanceFrequency(&qpf);
if(qpf.QuadPart != qpfInitial.QuadPart)
{
diagLoggedPrintf("QueryPerformanceFrequency changed from %" SIZETFMT " to %" SIZETFMT "\n",
(size_t)qpfInitial.QuadPart, (size_t)qpf.QuadPart);
qpfInitial = qpf;
}
time_t wall = time(NULL);
float wallSec = (float)(wall - wallInitial);
LARGE_INTEGER qpc;
tscBegin = __rdtsc();
QueryPerformanceCounter(&qpc);
tscEnd = __rdtsc();
u64 tscQPC = tscEnd-tscBegin;
qpcSum += tscQPC;
float qpcSec = (float)(qpc.QuadPart - qpcInitial.QuadPart) / (float)qpf.QuadPart;
tscBegin = __rdtsc();
ULONGLONG gtc = GetTickCount64();
tscEnd = __rdtsc();
u64 tscGTC = tscEnd-tscBegin;
gtcSum += tscGTC;
float gtcSec = (float)(gtc - gtcInitial) / 1000.0f;
FILETIME gstFT;
tscBegin = __rdtsc();
GetSystemTimePreciseAsFileTime(&gstFT);
tscEnd = __rdtsc();
u64 tscGST = tscEnd-tscBegin;
gstSum += tscGST;
ULARGE_INTEGER gst;
gst.HighPart = gstFT.dwHighDateTime;
gst.LowPart = gstFT.dwLowDateTime;
float gstSec = (float)((double)(gst.QuadPart - gstInitial.QuadPart) * 1.0e-7);
// R*TM can cause GetTickCount to drift slightly
if(!PARAM_rockstartargetmanager.Get())
{
if(fabsf(qpcSec - wallSec) > 5.0f || fabsf(gtcSec - wallSec) > 5.0f || fabsf(gstSec - wallSec) > 5.0f)
{
static bool loggedDiscrepancy = false;
if(!loggedDiscrepancy)
{
loggedDiscrepancy = true;
diagLoggedPrintf("Timers out of sync! Wall: %f, QueryPerformanceCounter: %f, GetTickCount: %f, GetSystemTimePreciseAsFileTime: %f\n",
wallSec, qpcSec, gtcSec, gstSec);
if(sysBootManager::IsDebuggerPresent() && !PARAM_disableTimeSkipBreak.Get())
{
__debugbreak(); // Don't Assert(), since we care about BankRelease as much as Beta
}
}
}
}
if(s_showDebugTimeInfo)
{
char buff[256];
formatf(buff, "Frame %d:\n"
"Wall: %f\n"
"QPC : %f (%d, %d)\n"
"GTC : %f (%d, %d)\n"
"GSTP: %f (%d, %d)\n",
frame, wallSec,
qpcSec, (int)tscQPC, (int)(qpcSum / framesShown),
gtcSec, (int)tscGTC, (int)(gtcSum / framesShown),
gstSec, (int)tscGST, (int)(gstSum / framesShown)
);
Vector2 vPos(0.1f, 0.15f);
grcDebugDraw::TextFontPush(grcSetup::GetFixedWidthFont());
grcDebugDraw::Text(vPos, Color_white, buff, true, 1.0f, 1.0f);
grcDebugDraw::TextFontPop();
++framesShown;
}
}
++frame;
#endif // RSG_DURANGO && __BANK
bool requestAddBug = s_requestAddBug;
bool requestDebugText = false;
bool forceIgnoreVideoCapture = false;
bool forceIgnoreScreenshot = false;
bool writeGameplayLog = false;
bool forceSecondScreenshot = false;
int bugType = BUG_TYPE_ART;
s_requestAddBug = false;
if (ms_disableSpaceBugScreenshots)
forceIgnoreScreenshot = true;
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG, "Add bug to bugstar", "bugstar"))
{
STRVIS_MARK_BUG_REPORTED();
requestAddBug = true;
bugType = BUG_TYPE_ART;
writeGameplayLog = true;
// If "capturecard" is defined, then set to not capture a screenshot for default SPACEBAR usage
if(PARAM_capturecard.Get())
{
forceIgnoreScreenshot = true;
}
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT, "Add bug to bugstar with second screenshot", "bugstar"))
{
STRVIS_MARK_BUG_REPORTED();
requestAddBug = true;
writeGameplayLog = true;
forceSecondScreenshot = true;
bugType = BUG_TYPE_ART;
// If "capturecard" is defined, then set to not capture a screenshot for default SPACEBAR usage
if(PARAM_capturecard.Get())
{
forceIgnoreScreenshot = true;
}
#if RSG_ORBIS
ioKeyboard::OverrideKey(KEY_F9, true);
#else
CControlMgr::GetKeyboard().FakeKeyPress(KEY_F9);
#endif // RSG_ORBIS
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG_CTRL, "Add bug to bugstar without video", "bugstar"))
{
STRVIS_MARK_BUG_REPORTED();
requestAddBug = true;
writeGameplayLog = true;
bugType = BUG_TYPE_ART;
forceIgnoreVideoCapture = true;
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG_ALT, "Add bug with report", "bugstar"))
{
STRVIS_MARK_BUG_REPORTED();
requestAddBug = true;
writeGameplayLog = true;
bugType = BUG_TYPE_ART;
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_1, KEYBOARD_MODE_DEBUG_CTRL, "Sets the console streaming video settings for Bugstar", "bugstar"))
{
CBugstarIntegration::SetStreamingVideoSettings();
}
#if __BANK
if (CAILogManager::ShouldSpewOutputLogWhenBugAdded())
{
if (writeGameplayLog)
{
CAILogManager::PrintAllGameplayLogs(); // Needs to be done on main thread as regreffed pointers shouldn't be accessed on the render thread
CControlMgr::PrintDisabledInputsToGameplayLog();
}
}
#endif // __BANK
#if SYSTMCMD_ENABLE
if(PARAM_rockstartargetmanager.Get() && CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG_CNTRL_ALT, "Add bug with dump file"))
{
sysTmCmdCreateDump();
}
#endif // SYSTMCMD_ENABLE
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_LBRACKET, KEYBOARD_MODE_DEBUG, "Add with debug text to bugstar", "bugstar"))
{
requestAddBug = true;
requestDebugText = true;
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_RBRACKET, KEYBOARD_MODE_DEBUG, "Add level bug to bugstar", "bugstar"))
{
requestAddBug = true;
bugType = BUG_TYPE_LEVELS;
}
#if BUGSTAR_INTEGRATION_ACTIVE
static sysTimer lastBugTime;
if (requestAddBug && lastBugTime.GetMsTime() < 5500)
{
Displayf("Just added a bug %f - call back later...", lastBugTime.GetMsTime());
requestAddBug = false;
}
if (requestAddBug) {
Warningf("Adding a bug - making player invulnerable for 10 seconds.");
BANK_ONLY(audNorthAudioEngine::GetDynamicMixer().PrintDebug());
if (ms_showInvincibleBugger)
{
char *pString = TheText.Get("BUG_INVIN");
CGameStreamMgr::GetGameStream()->PostTicker( pString, false );
}
ms_invincibleBugger = true;
lastBugTime.Reset();
}
bool bWasInvincible = ms_invincibleBugger;
bool bStillInvincible = (lastBugTime.GetMsTime() < 10000);
if (bWasInvincible && !bStillInvincible)
{
if (ms_showInvincibleBugger)
{
char *pString = TheText.Get("BUG_NOINVIN");
CGameStreamMgr::GetGameStream()->PostTicker( pString, false );
}
ms_invincibleBugger = false;
}
#endif // BUGSTAR_INTEGRATION_ACTIVE
if (NetworkInterface::IsGameInProgress() || NetworkInterface::IsInSinglePlayerPrivateSession())
{
gBugstarDescription = "Gamer Tag: ";
CPed* player = CGameWorld::FindLocalPlayer();
if (player && player->GetPlayerInfo())
{
gBugstarDescription += player->GetPlayerInfo()->m_GamerInfo.GetName();
}
else
{
gBugstarDescription += "Not specified";
}
gBugstarDescription += " / Platform: " RSG_PLATFORM " " RSG_CONFIGURATION " v";
gBugstarDescription += m_sRawVersionId;
gBugstarDescription += "\n\n";
}
else
{
gBugstarDescription = "";
}
#if __BANK
#if RSG_PC
gBugstarDescription += atString(CDebugBar::GetSystemInfo());
gBugstarDescription += "\n";
#endif
if (g_PickerManager.IsEnabled() && g_PickerManager.GetNumberOfEntities())
{
gBugstarDescription += "Selected:\n";
for (int i = 0; i < g_PickerManager.GetNumberOfEntities(); ++i)
{
atString name;
atString packfile;
CEntity* entity = static_cast<CEntity*>(g_PickerManager.GetEntity(i));
// the entities can be NULL
if (entity)
{
EntityDetails_GetModelName(entity, name);
EntityDetails_GetPackfile(entity, packfile);
Vec3V pos = entity->GetTransform().GetPosition();
gBugstarDescription += atVarString("%s (in '%s') at %2.3f,%2.3f,%2.3f\n",
name.c_str(),
packfile.c_str(),
VEC3V_ARGS(pos));
}
if (i > 20) // don't blow our string
{
gBugstarDescription += "...\n";
break;
}
}
gBugstarDescription += "\n";
}
if (gBugstarPedVariationInfo)
{
CPed* pSelectedPed = NULL;
CEntity* pSelectedEntity = CDebugScene::FocusEntities_Get(0);
if (pSelectedEntity && pSelectedEntity->GetIsTypePed())
{
pSelectedPed = static_cast<CPed*>(pSelectedEntity);
}
else
{
pSelectedPed = CGameWorld::FindLocalPlayer();
}
if (pSelectedPed)
{
CPedModelInfo* pModelInfo = static_cast<CPedModelInfo*>(pSelectedPed->GetBaseModelInfo());
gBugstarDescription += atVarString("Ped Variation (%s):\n", pSelectedPed->GetModelName());
for (u32 i = 0; i < PV_MAX_COMP; i++)
{
if (pModelInfo->GetVarInfo()->IsValidDrawbl(i, pSelectedPed->GetPedDrawHandler().GetVarData().GetPedCompIdx((ePedVarComp)i)))
{
gBugstarDescription += atVarString("%s: (D:%d, T:%d, P:%d)\n", varSlotNames[i], pSelectedPed->GetPedDrawHandler().GetVarData().GetPedCompIdx((ePedVarComp)i),
pSelectedPed->GetPedDrawHandler().GetVarData().GetPedTexIdx((ePedVarComp)i),
pSelectedPed->GetPedDrawHandler().GetVarData().GetPedPaletteIdx((ePedVarComp)i));
}
}
gBugstarDescription += "\nPed Props:";
bool bHasProps = false;
for (u32 i = 0; i < MAX_PROPS_PER_PED; ++i)
{
eAnchorPoints anchor = pSelectedPed->GetPedDrawHandler().GetPropData().GetAnchor(i);
if (anchor != ANCHOR_NONE)
{
bHasProps = true;
s32 prop = pSelectedPed->GetPedDrawHandler().GetPropData().GetPropId(i);
s32 texture = pSelectedPed->GetPedDrawHandler().GetPropData().GetTextureId(i);
u8 distribution = pModelInfo->GetVarInfo()->GetPropTexDistribution((u8)anchor, (u8)prop, (u8)texture);
gBugstarDescription += atVarString("\n%s: (D:%d, T:%d, P:%d)", propSlotNamesClean[anchor], prop, texture, distribution);
}
}
if (!bHasProps)
{
gBugstarDescription += " None";
}
}
}
#endif // __BANK
if (gDrawListMgr->IsBuildingDrawList()){
DLC_Add( AddBug, requestAddBug, bugType, requestDebugText, forceIgnoreVideoCapture, forceIgnoreScreenshot, forceSecondScreenshot);
} else {
AddBug(requestAddBug, bugType, requestDebugText, forceIgnoreVideoCapture, forceIgnoreScreenshot, forceSecondScreenshot);
}
}
//////////////////////////////////////////////////////////////////////////
#endif // BUGSTAR_INTEGRATION_ACTIVE
//////////////////////////////////////////////////////////////////////////
//
// name: SetCurrentMissionTag
// description: sets the mission tag up for debug display. automatically setup by the 'SetMissionFlag' command retrieved from script
void CDebug::SetCurrentMissionTag(const char *missionTag)
{
#if STREAMING_VISUALIZE
STRVIS_ADD_MARKER(strStreamingVisualize::MARKER);
char markerString[128];
formatf(markerString, "Start mission %s", missionTag);
STRVIS_SET_MARKER_TEXT(missionTag);
#endif // STREAMING_VISUALIZE
strcpy(ms_currentMissionTag,missionTag);
strcpy(ms_currentMissionName,missionTag);
}
//
// name: SetCurrentMissionName
// description: sets the mission name up for bugstar to use
void CDebug::SetCurrentMissionName(const char *missionName)
{
SetCurrentMissionTag(missionName);
}
const char *CDebug::GetPackageType()
{
if (fiDeviceInstaller::GetIsBootedFromHdd())
{
return "HDD Install";
}
else if (sysBootManager::IsBootedFromDisc())
{
return "Disc Build";
}
else if (sysBootManager::IsPackagedBuild())
{
return "Packaged Build";
}
else
{
return "Loose Files (SysTrayRFS)";
}
}
const char *CDebug::GetFullVersionString(char *outBuffer, size_t bufferSize)
{
safecpy(outBuffer, GetVersionNumber(), bufferSize);
return outBuffer;
}
extern const char *diagAssertTitle;
// Name : SetVersionNumber
// Purpose : sets the games version number from the version.txt file
// Parameters : nothing
// Returns : true if success, false if failed
bool CDebug::SetVersionNumber()
{
#define STANDARD_VERSION_NUMBER_FILENAME "common:/data/version.txt"
char cLine[64];
char* pLine;
FileHandle fid;
CFileMgr::SetDir("");
fid = CFileMgr::OpenFile(STANDARD_VERSION_NUMBER_FILENAME);
if (!CFileMgr::IsValidFileHandle(fid))
{
// don't assert for now until everyone has syncd. Assertf(CFileMgr::IsValidFileHandle(fid), "No version number file found (DATA\\VERSION.TXT)" );
m_iVersionId[0] = '\0'; // we couldnt get a version id so set to nothing
return false;
}
while( ((pLine = CFileMgr::ReadLine(fid)) != NULL) )
{
if(*pLine == '#' || *pLine == '\0') continue;
sscanf(pLine, "%s", cLine);
// read in version number:
if (!strcmp(cLine, "[VERSION_NUMBER]"))
{
pLine = CFileMgr::ReadLine(fid);
sscanf(pLine, "%s", m_iVersionId); // sets the version number
// Strip out any extraneous suffix characters (i.e. "dev_xx") to set the raw version ID
int i = 0;
for(; i < NELEM(m_iVersionId)-1 && i < NELEM(m_sRawVersionId)-1; ++i)
{
if((fwTextUtil::IsNumeric(m_iVersionId[i]) || m_iVersionId[i] == '.'))
{
m_sRawVersionId[i] = m_iVersionId[i];
}
else
{
break;
}
}
m_sRawVersionId[i] = '\0';
#if !__FINAL
formatf(m_sFullVersionId, "%s-%c%s", m_iVersionId, RSG_PLATFORM_CODE, RSG_CONFIGURATION_CODE);
#endif
}
if (!strcmp(cLine, "[ONLINE_VERSION_NUMBER]"))
{
pLine = CFileMgr::ReadLine(fid);
sscanf(pLine, "%s", m_sOnlineVersionId);
}
// read in version number:
if (!strcmp(cLine, "[INSTALL_VERSION_NUMBER]"))
{
pLine = CFileMgr::ReadLine(fid);
sscanf(pLine, "%s", m_iInstallVersionId); // sets the install version number
}
if (!strcmp(cLine, "[SAVEGAME_VERSION_NUMBER]"))
{
pLine = CFileMgr::ReadLine(fid);
sscanf(pLine, "%d", &m_iSavegameVersionId); // sets the savegame version number
}
#if GTA_REPLAY
if (!strcmp(cLine, "[REPLAY_VERSION_NUMBER]"))
{
pLine = CFileMgr::ReadLine(fid);
sscanf(pLine, "%d", &m_iReplayVersionId); // sets the replay version number
}
#endif //GTA_REPLAY
}
Displayf("\n*********************************************\n");
Displayf("Version %s, Save version %d \n", m_iVersionId, m_iSavegameVersionId);
Displayf("Build timestamp is: " __TIME__ " " __DATE__ "\n");
Displayf("***********************************************\n");
static char assertVersion[128];
formatf(assertVersion, "GTAV "
#if __PS3
"PS3 "
#elif __XENON
"Xbox360 "
#elif __64BIT
#if RSG_DURANGO
"Durango "
#elif RSG_ORBIS
"Orbis "
#else
"x64 "
#endif
#else
"x86 "
#endif
RSG_CONFIGURATION
" %s", m_iVersionId);
diagAssertTitle = assertVersion;
CFileMgr::CloseFile(fid);
// Tell our favorite memory tracker about this.
#if RAGE_TRACKING
if (diagTracker::GetCurrent())
{
const char *packageType = GetPackageType();
char versionString[32];
GetFullVersionString(versionString, sizeof(versionString));
diagTracker::GetCurrent()->SetVersionInfo(versionString, packageType);
}
#endif // RAGE_TRACKING
return true;
}
#if USE_PROFILER
void CDebug::RockyCaptureControlCallback(Profiler::ControlState state, u32 /*mode*/)
{
if (state == Profiler::ROCKY_START)
{
static char foundInVersion[64];
formatf(foundInVersion, "%s - All", GetVersionNumber());
Profiler::AttachCaptureInfo("Version", foundInVersion);
Profiler::AttachCaptureInfo("Bugstar Project Name", "GTA 5 DLC");
Profiler::AttachCaptureInfo("Bugstar Project Id", "282246");
Profiler::AttachCaptureInfo("Build Config", RSG_CONFIGURATION);
Profiler::AttachCaptureInfo("Platform", RSG_PLATFORM_ID);
Profiler::AttachCaptureInfo("Multiplayer Mode", NetworkInterface::IsGameInProgress() ? "MP" : "SP");
// Render Resolution
char resolution[128] = { 0 };
formatf(resolution, "%dx%d", GRCDEVICE.GetWidth(), GRCDEVICE.GetHeight());
Profiler::AttachCaptureInfo("Render Resolution", resolution);
}
}
#endif
#if !__FINAL
PARAM(traceframe, "Frame to do a trace on");
#if __XENON
PARAM(pgolitetrace, "Trace main/render threads during automated metrics captures");
bool CDebug::sm_bPgoLiteTrace = false;
u32 CDebug::sm_iPgoLiteTraceTime = 0;
bool CDebug::sm_bTraceUpdateThread = false;
bool CDebug::sm_bStartedUpdateTrace = false;
unsigned int CDebug::sm_iUpdateTraceCount = 0;
bool CDebug::sm_bTraceRenderThread = false;
bool CDebug::sm_bStartedRenderTrace = false;
unsigned int CDebug::sm_iRenderTraceCount = 0;
static const char gTraceDirectory[] = "devkit:\\trace";
#endif // __XENON
void CDebug::Update()
{
Update_CDEBUG();
#if __XENON && !__FINAL
// check trace on frame parameter
u32 frame = 0;
if(PARAM_traceframe.Get(frame) && fwTimer::GetSystemFrameCount() == frame)
{
sm_bTraceUpdateThread = true;
}
if(sm_iPgoLiteTraceTime != 0 && sm_iPgoLiteTraceTime <= fwTimer::GetTimeInMilliseconds())
{
sm_bTraceUpdateThread = true;
sm_iPgoLiteTraceTime = 0;
}
TraceThread(sm_bTraceUpdateThread, sm_bStartedUpdateTrace, "update_trace", sm_iUpdateTraceCount);
#endif
#if __ASSERT
UpdateNoPopups(false);
#endif // __ASSERT
}
void CDebug::UpdateLoading()
{
#if __ASSERT
UpdateNoPopups(true);
#endif // __ASSERT
}
#if __ASSERT
void CDebug::UpdateNoPopups(bool UNUSED_PARAM(loading))
{
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT_ALT, "Toggle nopopups") )
{
if (PARAM_nopopups.Get())
{
Displayf("enabling popups: -nopopups OFF");
PARAM_nopopups.Set(NULL);
}
else
{
Displayf("disabling popups: -nopopups ON");
PARAM_nopopups.Set("");
}
}
//sm_iBlockedPopups = diagChannel::DetectBlockedPopups(loading);
}
#endif // __ASSERT
void CDebug::Init(unsigned initMode)
{
Init_CDEBUG(initMode);
#if(BUGSTAR_INTEGRATION_ACTIVE)
if (PARAM_disableSpaceBugScreenshots.Get())
ms_disableSpaceBugScreenshots = true;
#endif
#if __XENON && !__FINAL
const fiDevice *pDevice = fiDevice::GetDevice(gTraceDirectory, false);
if(pDevice != NULL)
{
sm_bPgoLiteTrace = PARAM_pgolitetrace.Get();
if(sm_bPgoLiteTrace)
{
pDevice->DeleteDirectory(gTraceDirectory, true);
}
pDevice->MakeDirectory(gTraceDirectory);
}
#endif // __XENON && !__FINAL
}
#if __XENON
void CDebug::TraceThread(bool& bTrace, bool& bTraceStarted, const char* pFilename, unsigned int& iTraceCount)
{
// if started trace
if(bTraceStarted)
{
XTraceStopRecording();
bTraceStarted = false;
}
// if a trace recording has been requested
if(bTrace)
{
#define TRACE_FILENAME_PADDING sizeof(gTraceDirectory) - 1 + sizeof("\\_4294967295.pix2")
Assertf(strlen(pFilename) + TRACE_FILENAME_PADDING <= 256, "Filename too long");
char buffer[256];
sprintf(buffer, "%s\\%s_%u.pix2", gTraceDirectory, pFilename, iTraceCount);
XTraceStartRecording(buffer);
bTraceStarted = true;
bTrace = false;
++iTraceCount;
}
}
#endif
#endif //!__FINAL
#if ENABLE_CDEBUG && __BANK
static bool gDisplayTimerBars = grcDebugDraw::GetDisplayDebugText();
#elif RAGE_TIMEBARS || DEBUG_DRAW
static bool gDisplayTimerBars = false;
#endif
#if ENABLE_CDEBUG
#if __BANK
s32 CDebug::m_iBugNumber = -1;
#endif
#if !__FINAL
#if __BANK
int gCurrentDisplayObjectIndex;
int gCurrentDisplayObjectCount;
static char** gCurrentDisplayObjectList;
char gCurrentDisplayObject[STORE_NAME_LENGTH];
char gStreamModelName[STORE_NAME_LENGTH];
strModelRequest gStreamModelReq;
static bkCombo* gDisplayObjectListCombo;
static bool gActivateDisplayObject = false;
static bool gDisplaySafeZone = false;
static bool gDisplayMapZone = false;
static bool gDisplaySpawnNodes = false;
static int gPackfileSource;
static const char *gPackfileSourceDummyList[] = { "[Press button above to populate]" };
static const char *gObjectToCreateDummyList[] = { "[Select packfile to populate]" };
static bkCombo *gPackfileSourceCombo;
static bkCombo *gObjectToCreateCombo;
static const char **gPackfileSourceList;
static int *gPackfileMapping; // Maps the combo index to the actual packfile index
static int gPackfileSourceCount;
static const char **gObjectNameList;
static fwModelId *gObjectModelIdList;
static int gObjectToCreateCount;
static int gObjectToCreateIndex;
#if __ASSERT
const char* CDebug::GetNoPopupsMessage(bool loading)
{
if (loading)
{
UpdateLoading();
}
if (PARAM_nopopups.Get() || CDebug::sm_iBlockedPopups)
{
static char msg[32] = "";
if (PARAM_nopopups.Get())
strcpy(msg, "No Popups");
else
sprintf(msg, "Blocked Popups (%d)", CDebug::sm_iBlockedPopups);
return msg;
}
else
{
return NULL;
}
}
#endif // __ASSERT
#if __DEV
bool CDebug::GetDisplaySpawnNodes()
{
return gDisplaySpawnNodes;
}
bool CDebug::GetDisplayTimerBars()
{
return gDisplayTimerBars;
}
#endif
#if __BANK
void CDebug::SetDisplayTimerBars(bool bEnable)
{
gDisplayTimerBars = bEnable;
}
#endif
RegdEnt gpDisplayObject(NULL);
#if __D3D && __WIN32PC
static bool showd3dresourceinfo = false;
#endif
static void DisplaySafeZone()
{
CSystem::GetRageSetup()->EnableSafeZoneDraw(gDisplaySafeZone, CHudTools::GetSafeZoneSize());
}
void DeleteObject()
{
if(gpDisplayObject)
{
CGameWorld::Remove(gpDisplayObject);
if(gpDisplayObject->GetIsTypeVehicle())
CVehicleFactory::GetFactory()->Destroy((CVehicle*)gpDisplayObject.Get());
else if(gpDisplayObject->GetIsTypePed())
CPedFactory::GetFactory()->DestroyPed((CPed*)gpDisplayObject.Get());
else if(gpDisplayObject->GetIsTypeObject())
CObjectPopulation::DestroyObject((CObject*)gpDisplayObject.Get());
else
delete gpDisplayObject;
gpDisplayObject = NULL;
}
}
void FixupObject(CEntity *pObject, const Matrix34 &testMat)
{
if(pObject)
{
if (!pObject->GetTransform().IsMatrix())
{
#if ENABLE_MATRIX_MEMBER
Mat34V matrix(MATRIX34_TO_MAT34V(testMat));
pObject->SetTransform(matrix);
pObject->SetTransformScale(1.0f, 1.0f);
#else
Mat34V matrix(MATRIX34_TO_MAT34V(testMat));
fwTransform *trans = rage_new fwMatrixTransform(matrix);
pObject->SetTransform(trans);
#endif
}
pObject->SetMatrix(testMat, true);
if (fragInst* pInst = pObject->GetFragInst())
{
pInst->SetResetMatrix(testMat);
}
CGameWorld::Add(pObject, CGameWorld::OUTSIDE );
if ( pObject->GetIsDynamic() )
{
CPortalTracker* pPT = static_cast< CDynamicEntity* >( pObject )->GetPortalTracker();
pPT->ScanUntilProbeTrue();
pPT->Update( VEC3V_TO_VECTOR3( pObject->GetTransform().GetPosition() ) );
}
}
// create physics for static xrefs
if (pObject && pObject->GetIsTypeBuilding()
&& pObject->GetCurrentPhysicsInst()==NULL && pObject->IsBaseFlagSet(fwEntity::HAS_PHYSICS_DICT))
{
// create physics
pObject->InitPhys();
if (pObject->GetCurrentPhysicsInst())
{
pObject->AddPhysics();
}
}
//If the entity being is an env cloth then we need to transform the cloth
//verts to the entity frame.
if(pObject && pObject->GetCurrentPhysicsInst() && pObject->GetCurrentPhysicsInst()->GetArchetype())
{
// TODO: Should this really be checking if it has the GTA_ENVCLOTH_OBJECT_TYPE flag, not that it has *only* the GTA_ENVCLOTH_OBJECT_TYPE flag?
if(PHLEVEL->GetInstanceTypeFlags(pObject->GetCurrentPhysicsInst()->GetLevelIndex()) == ArchetypeFlags::GTA_ENVCLOTH_OBJECT_TYPE)
{
//Now transform the cloth verts to the frame of the cloth entity.
phInst* pEntityInst=pObject->GetCurrentPhysicsInst();
Assertf(dynamic_cast<fragInst*>(pEntityInst), "Physical with cloth must be a frag");
fragInst* pEntityFragInst=static_cast<fragInst*>(pEntityInst);
Assertf(pEntityFragInst->GetCached(), "Cloth entity has no cache entry");
if(pEntityFragInst->GetCached())
{
fragCacheEntry* pEntityCacheEntry=pEntityFragInst->GetCacheEntry();
Assertf(pEntityCacheEntry, "Cloth entity has a null cache entry");
fragHierarchyInst* pEntityHierInst=pEntityCacheEntry->GetHierInst();
Assertf(pEntityHierInst, "Cloth entity has a null hier inst");
environmentCloth* pEnvCloth=pEntityHierInst->envCloth;
Assertf( pEnvCloth, "Object/entity is marked as cloth but doesn't have cloth attached" );
if( pEnvCloth )
{
Matrix34 clothMatrix = MAT34V_TO_MATRIX34(pObject->GetMatrix());
pEnvCloth->SetInitialPosition( VECTOR3_TO_VEC3V(clothMatrix.d) );
}
}
}
}// if(pObject && pObject->GetCurrentPhysicsInst() && pObject->GetCurrentPhysicsInst()->GetArchetype())...
if (pObject && pObject->GetCurrentPhysicsInst() && gActivateDisplayObject)
{
PHSIM->ActivateObject(pObject->GetCurrentPhysicsInst());
}
}
u32 gLegionCountX = 10;
u32 gLegionCountY = 10;
float gLegionSpacing = 0.f;
Vector3 gDisplayOffset(0, 0, 0);
atArray<RegdEnt> gLegion;
void DisplayObject(bool bDeletePrevious)
{
if(gpDisplayObject && bDeletePrevious)
{
DeleteObject();
}
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromName(gCurrentDisplayObject, &modelId);
if(pModelInfo==NULL)
{
Displayf("Couldn't get model info for '%s'.", gCurrentDisplayObject);
return;
}
gpDisplayObject = NULL;
Matrix34 testMat;
testMat.Identity();
Vector3 vecCreateOffset = camInterface::GetFront();
vecCreateOffset.z = 0.0f;
vecCreateOffset *= 2.0f + pModelInfo->GetBoundingSphereRadius();
camDebugDirector& debugDirector = camInterface::GetDebugDirector();
testMat.d = debugDirector.IsFreeCamActive() ? camInterface::GetPos() : CGameWorld::FindLocalPlayerCoors();
testMat.d += vecCreateOffset + gDisplayOffset;
if(debugDirector.IsFreeCamActive())
testMat.Set3x3(camInterface::GetMat());
else if(CGameWorld::FindLocalPlayer())
testMat.Set3x3(MAT34V_TO_MATRIX34(CGameWorld::FindLocalPlayer()->GetMatrix()));
if(pModelInfo)
{
//Allow cut scene props to be displayed, cutscene props have the prefix "CS" so use this to identify cut scene props
bool bIsCutSceneObject = false;
if (strnicmp("cs", pModelInfo->GetModelName(), 2) == 0)
{
bIsCutSceneObject = true;
}
if(pModelInfo->GetModelType()==MI_TYPE_VEHICLE || pModelInfo->GetModelType()==MI_TYPE_PED || pModelInfo->GetIsTypeObject()||bIsCutSceneObject)
{
bool bForceLoad = false;
if(!CModelInfo::HaveAssetsLoaded(modelId))
{
CModelInfo::RequestAssets(modelId, STRFLAG_DONTDELETE|STRFLAG_FORCE_LOAD|STRFLAG_PRIORITY_LOAD);
bForceLoad = true;
}
if(bForceLoad)
{
CStreaming::LoadAllRequestedObjects(true);
}
}
if(pModelInfo->GetModelType()==MI_TYPE_VEHICLE)
{
gpDisplayObject = CVehicleFactory::GetFactory()->Create(modelId, ENTITY_OWNEDBY_DEBUG, POPTYPE_TOOL, &testMat);
if (gpDisplayObject)
{
u8 nNewColour1, nNewColour2, nNewColour3, nNewColour4, nNewColour5, nNewColour6;
CVehicleModelInfo* vmi = (CVehicleModelInfo*)pModelInfo;
CVehicle* veh = (CVehicle*)gpDisplayObject.Get();
vmi->ChooseVehicleColourFancy(veh, nNewColour1, nNewColour2, nNewColour3, nNewColour4, nNewColour5, nNewColour6);
veh->SetBodyColour1(nNewColour1);
veh->SetBodyColour2(nNewColour2);
veh->SetBodyColour3(nNewColour3);
veh->SetBodyColour4(nNewColour4);
veh->SetBodyColour5(nNewColour5);
veh->SetBodyColour6(nNewColour6);
veh->UpdateBodyColourRemapping();
}
}
else if(pModelInfo->GetModelType()==MI_TYPE_PED)
{
const CControlledByInfo localAiControl(false, false);
gpDisplayObject = CPedFactory::GetFactory()->CreatePed(localAiControl, modelId, &testMat, true, true, false);
}
else if(pModelInfo->GetIsTypeObject()||bIsCutSceneObject)
{
gpDisplayObject = CObjectPopulation::CreateObject(modelId, ENTITY_OWNEDBY_DEBUG, false);
}
else
{
if (pModelInfo->GetModelType() == MI_TYPE_COMPOSITE)
{
gpDisplayObject = rage_new CCompEntity( ENTITY_OWNEDBY_DEBUG );
gpDisplayObject->GetLodData().SetLodType(LODTYPES_DEPTH_ORPHANHD);
}
else if(pModelInfo->GetClipDictionaryIndex() != -1 && pModelInfo->GetHasAnimation())
{
gpDisplayObject = rage_new CAnimatedBuilding( ENTITY_OWNEDBY_DEBUG );
}
else
{
gpDisplayObject = rage_new CBuilding( ENTITY_OWNEDBY_DEBUG );
}
gpDisplayObject->SetModelId(modelId);
}
}
FixupObject(gpDisplayObject, testMat);
if (gpDisplayObject != NULL)
{
gpDisplayObject->ProtectStreamedArchetype();
}
}
void DeleteLegion()
{
// free old list
for (s32 i = 0; i < gLegion.GetCount(); ++i)
{
if (gLegion[i])
{
CGameWorld::Remove(gLegion[i]);
if(gLegion[i]->GetIsTypeVehicle())
CVehicleFactory::GetFactory()->Destroy((CVehicle*)gLegion[i].Get());
else if(gLegion[i]->GetIsTypePed())
CPedFactory::GetFactory()->DestroyPed((CPed*)gLegion[i].Get());
else if(gLegion[i]->GetIsTypeObject())
CObjectPopulation::DestroyObject((CObject*)gLegion[i].Get());
else
delete gLegion[i];
}
}
gLegion.Reset();
}
void DisplayLegionObject()
{
DeleteLegion();
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromName(gCurrentDisplayObject, &modelId);
if(pModelInfo==NULL)
{
Displayf("Couldn't get model info for '%s'.", gCurrentDisplayObject);
return;
}
if (gpDisplayObject)
DeleteObject();
u32 totalCount = gLegionCountX * gLegionCountY;
gLegion.Reserve(totalCount);
float totalSpacing = gLegionSpacing + pModelInfo->GetBoundingSphereRadius();
Vector3 fwd = camInterface::GetFront();
fwd.z = 0.f;
fwd.Normalize();
Vector3 up(0.f, 0.f, 1.f);
Vector3 side;
side.Cross(fwd, up);
side.Normalize();
fwd *= totalSpacing;
side *= totalSpacing;
for (u32 x = 0; x < gLegionCountX; ++x)
{
for (u32 y = 0; y < gLegionCountY; ++y)
{
gDisplayOffset = ((float)x * fwd) + ((float)y * side);
DisplayObject(false);
gLegion.Push(gpDisplayObject);
}
}
gpDisplayObject = NULL;
}
void PlaceLastObjectOnGround()
{
if(gpDisplayObject && gpDisplayObject->GetIsTypeObject())
(static_cast<CObject*>(gpDisplayObject.Get()))->PlaceOnGroundProperly();
else if (gLegion.GetCount() > 0 && gLegion[0]->GetIsTypeObject())
{
for (s32 i = 0; i < gLegion.GetCount(); ++i)
(static_cast<CObject*>(gLegion[0].Get()))->PlaceOnGroundProperly();
}
}
void RepairLastObject()
{
if(gpDisplayObject && gpDisplayObject->GetIsTypeObject())
(static_cast<CObject*>(gpDisplayObject.Get()))->Fix();
else if (gLegion.GetCount() > 0 && gLegion[0]->GetIsTypeObject())
{
for (s32 i = 0; i < gLegion.GetCount(); ++i)
(static_cast<CObject*>(gLegion[0].Get()))->Fix();
}
}
bool gCacheTunedFragObject = true;
void FragTuneLastObject()
{
if(gpDisplayObject)
{
if (fragInst* pInst = gpDisplayObject->GetFragInst())
{
if (gCacheTunedFragObject && !pInst->GetCached())
{
pInst->PutIntoCache();
}
CPhysics::CreateFragTuneBank();
FRAGTUNE->SetType(const_cast<fragType*>(pInst->GetType()), 0, pInst);
}
}
}
void SelectDisplayObject()
{
strncpy(gCurrentDisplayObject, gCurrentDisplayObjectList[gCurrentDisplayObjectIndex], sizeof(gCurrentDisplayObject));
gCurrentDisplayObject[sizeof(gCurrentDisplayObject) - 1] = '\0';
DisplayObject(true);
}
void DisplayObjectDeleteOld() { DisplayObject(true); }
void DisplayObjectKeepOld() { DisplayObject(false); }
#endif // __BANK
PARAM(nomsgs, "[debug] Don't output log messages to the console");
PARAM(nowarnings, "[debug] Don't output warnings to the console");
namespace rage {
XPARAM(tracker);
}
void CDebug::SetPrinterFn()
{
u32 outputMask = diagOutput::OUTPUT_ALL;
if(PARAM_nowarnings.Get())
outputMask &= ~diagOutput::OUTPUT_WARNINGS;
if(PARAM_nomsgs.Get())
outputMask &= ~diagOutput::OUTPUT_DISPLAYS;
diagOutput::SetOutputMask(outputMask);
}
#if __ASSERT
namespace rage
{
//extern void (*g_ExternalPreAssertHandler)(const char *exp,const char *file,unsigned line, const char* message);
extern bool (*diagExternalCallback)(const diagChannel&,diagSeverity&,const char*,int,const char*);
extern int (*diagLogBugCallback)(const char*,const char*,u32,int);
}
extern bool (*spuLogBugCallback)(int spu, const char* summary,const char* details, u32 assetId, bool editBug);
extern int (*spuAssertCallback)(int spu, const char* summary, const char* assertText, int defaultIfNoServer);
#endif // __ASSERT
#if __PFDRAW
PARAM(pfdraw, "Memory reserved for RAGE profile draw, i.e. items controlled within the widget bank \"rage - Profile Draw\"");
#endif
XPARAM(bugAsserts);
XPARAM(debugtrain);
#endif // !__FINAL
#endif // ENABLE_CDEBUG
void CDebug::InitSystem(unsigned )
{
#if __ASSERT
if(PARAM_bugAsserts.Get())
{
diagLogBugCallback = OnLogBug;
#if __PS3
spuAssertCallback = OnSpuAssert;
#endif
}
#endif
SetVersionNumber();
#if STREAMING_VISUALIZE
char fullVersion[32];
STRVIS_SET_EXTRA_CLIENT_INFO(GetFullVersionString(fullVersion, sizeof(fullVersion)), GetPackageType());
#endif // STREAMING_VISUALIZE
}
#if ENABLE_CDEBUG
#if !__FINAL
void CDebug::Init_CDEBUG(unsigned /*initMode*/)
{
USE_DEBUG_MEMORY();
#if !__FINAL
ms_currentMissionName[0] = '\0';
ms_currentMissionTag[0] = '\0';
DebugDraw::Init();
CVectorMap::InitClass();
#if RAGE_TIMEBARS
//g_pfTB.SetTextCallback(&TimerBarTextCallback);
g_pfTB.SetTimebarDimensions(0.22f, 0.86f, 0.01f, 0.1f);
#endif // RAGE_TIMEBARS
m_iSavegameVersionId = -1;
m_iScaleformMovieId = -1;
CSystem::GetRageSetup()->SetScreenShotNamingConvention( grcSetup::NUMBERED_SCREENSHOTS );
#if __BANK
#if(BUGSTAR_INTEGRATION_ACTIVE)
gBugstarOwner[0] = '\0'; // make sure its empty before we create the bank
#endif
CDebug::m_iBugNumber = -1;
sm_enableBoundByGPUFlip = PARAM_enableBoundByGPUFlip.Get();
DR_ONLY(ms_GameRecorder = rage_new GameRecorder;);
DR_ONLY(ms_GameRecorder->Init(););
gDrawListMgr->RegisterStatExtraction(s_numRenderPhases, s_renderPhaseNames, s_renderPhaseData);
ms_showInvincibleBugger = !PARAM_dontshowinvinciblebugger.Get();
if (PARAM_peddebugvisualiser.Get())
{
int debugvalue = 0;
PARAM_peddebugvisualiser.Get(debugvalue);
CPedDebugVisualiser::SetDebugDisplay((CPedDebugVisualiser::ePedDebugVisMode)debugvalue);
}
if (PARAM_dontdisplayforplayer.Get())
{
CPedDebugVisualiserMenu::ms_menuFlags.m_bDontDisplayForPlayer = true;
}
sm_debugrespot = PARAM_debugrespot.Get();
sm_debugrespawninvincibility = PARAM_debugrespawninvincibility.Get();
sm_debugdoublekill = PARAM_debugdoublekill.Get();
sm_debugexplosion = PARAM_debugexplosion.Get();
sm_debuglicenseplate = PARAM_debuglicenseplate.Get();
sm_debugaircraftcarrier = PARAM_debugaircraftcarrier.Get();
sm_debugradiotest = PARAM_debugradiotest.Get();
CTrain::sm_bDebugTrain = PARAM_debugtrain.Get();
PARAM_dbgfontscale.Get(sm_dbgFontscale);
#endif // __BANK
#endif // !__FINAL
#if __STATS
GetRageProfiler().Init();
const char* defaultEKG = NULL;
if( PARAM_ekgdefault.Get(defaultEKG))
{
pfPage* apiPage = GetRageProfiler().GetPageByName(defaultEKG);
if( apiPage )
{
GetRageProfileRenderer().GetEkgMgr(0)->SetPage(apiPage);
}
}
#endif // __STATS
#if __PFDRAW
int nPfDrawMem = 16 * 1024;
PARAM_pfdraw.Get(nPfDrawMem);
GetRageProfileDraw().Init(nPfDrawMem, true, grcBatcher::BUF_FULL_IGNORE);
GetRageProfileDraw().SetEnabled(true);
#endif
#if ENABLE_STATS_CAPTURE
MetricsCapture::Init();
#endif // ENABLE_STATS_CAPTURE
}
//
// name: CDebug::Shutdown
// description: Shutdown debug code
void CDebug::Shutdown(unsigned /*shutdownMode*/)
{
DR_ONLY(delete ms_GameRecorder;);
CVectorMap::Shutdown();
CVectorMap::ShutdownClass();
DebugDraw::Shutdown();
#if __PFDRAW
GetRageProfileDraw().Shutdown();
#endif
#if __STATS
GetRageProfiler().Shutdown();
#endif
#if ENABLE_STATS_CAPTURE
MetricsCapture::Shutdown();
#endif // ENABLE_STATS_CAPTURE
}
// EJ: FPS Capture
#if ENABLE_FPS_CAPTURE
bool g_bFPSCapture = false;
float g_fMaxCaptures = 100.0f;
float g_fCaptureData[1000];
int g_nTotalCaptures = 0;
static void StartFPSCapture()
{
g_bFPSCapture = true;
}
static void CaptureFPS()
{
if (!g_bFPSCapture)
return;
if (g_nTotalCaptures >= g_fMaxCaptures)
{
float fTotalFPS = 0.0f;
for (int i = 0; i < g_nTotalCaptures; ++i)
fTotalFPS += g_fCaptureData[i];
const float fAverageFPS = fTotalFPS / g_nTotalCaptures;
Displayf(" *** Captures: %d, FPS: %0.3f *** ", g_nTotalCaptures, fAverageFPS);
g_bFPSCapture = false;
g_nTotalCaptures = 0;
return;
}
const float fFPS = 1.0f / rage::Max(0.001f, fwTimer::GetSystemTimeStep());
g_fCaptureData[g_nTotalCaptures++] = fFPS;
}
#endif
extern void populateCarWithDumbRandomsCB(void);
extern void populateCarWithRandomsCB(void);
void FindEntityFromPointer();
//
// name: CDebug::Update
// description: Update debug code
void CDebug::Update_CDEBUG()
{
#if ENABLE_FPS_CAPTURE
CaptureFPS();
#endif
PF_START_TIMEBAR("debug update");
// Update the currently active CTestCase
CTestCase::UpdateTestCase();
//if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_D, KEYBOARD_MODE_DEBUG_ALT))
//{
// DisplayObjectDeleteOld();
//}
#if __BANK
if (!bkManager::IsEnabled())
{
return;
}
// Set the fontscale every time since it may have changed via rag
grcFont::GetCurrent().SetInternalScale(sm_dbgFontscale);
#if WORLD_PROBE_DEBUG
if(!fwTimer::IsGamePaused())
{
WorldProbe::GetShapeTestManager()->ResetPausedRenderBuffer();
}
#endif // WORLD_PROBE_DEBUG
#endif // __BANK
#if DEBUG_DISPLAY_BAR
CDebug::UpdateReleaseInfoToScreen();
#endif
CTask::VerifyTaskCounts();
CEvent::VerifyEventCounts();
// dont display the version number here anymore
// grcDebugDraw::AddDebugOutput("v%s\n", CDebug::GetVersionNumber()); // output a version number
#if !__FINAL
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SEMICOLON, KEYBOARD_MODE_DEBUG, "Toggle LASTGEN"))
{
gLastGenModeState = !gLastGenModeState;
}
// toggle camera vertical axis - todo 11421 jimmy database
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_Y, KEYBOARD_MODE_DEBUG, "Toggle invert look"))
{
// cycle the different inversions.
s32 pref = CPauseMenu::GetMenuPreference(PREF_INVERT_LOOK);
if(pref == 0)
{
pref = 1;
}
else
{
pref = 0;
}
Displayf("[Debug::Keyboard] User just pressed Y key to toggle invert camera look, now it is %s", pref == 1 ? "inverted" : "not inverted");
CPauseMenu::SetMenuPreference(PREF_INVERT_LOOK, pref);
CControlMgr::SetDefaultLookInversions();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_BACK, KEYBOARD_MODE_DEBUG, "Lock Render List"))
{
g_render_lock=!g_render_lock;
if(g_render_lock)
{
CSetDrawableLODCalcPos::SetRenderLockCamPos(camInterface::GetPos()); // store current cam position for locked LOD calcs
if (!fwTimer::IsGamePaused())
{
fwTimer::StartUserPause(); //ensure game is paused
}
if (!CStreaming::IsStreamingPaused())
{
CStreaming::SetStreamingPaused(true);
}
}
else
{
if(fwTimer::IsGamePaused())
{
fwTimer::EndUserPause();
}
if (CStreaming::IsStreamingPaused())
{
CStreaming::SetStreamingPaused(false);
}
}
DebugCamera::SetCameraLock(g_render_lock);
}
#if !__FINAL
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_R, KEYBOARD_MODE_DEBUG_ALT, "Toggle GTA/RDR free camera mode") )
{
if(camInterface::GetDebugDirector().GetFreeCam())
camInterface::GetDebugDirector().GetFreeCam()->SetUseRdrMapping(!camInterface::GetDebugDirector().GetFreeCam()->GetUseRdrMapping());
}
#endif
#if __BANK
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_V, KEYBOARD_MODE_DEBUG_CTRL, "Visualise Peds In Vehicle"))
{
CPedDebugVisualiserMenu::ms_menuFlags.m_bVisualisePedsInVehicles = !CPedDebugVisualiserMenu::ms_menuFlags.m_bVisualisePedsInVehicles;
}
const bool bPopulateLastVehicleDumb = CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_SHIFT_ALT, "Populate last vehicle dumb");
XPARAM(nocheats);
if( !PARAM_nocheats.Get() &&
(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG, "Create car")||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_SHIFT, "Create car+warp")||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_CTRL, "Create car+populate") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_ALT, "Create car+populate dumb") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_SHIFT, "Populate last vehicle") ||
bPopulateLastVehicleDumb))
{
CVehicleFactory::CreateBank();
if (!CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_SHIFT, "Populate last vehicle") &&
!bPopulateLastVehicleDumb)
{
CVehicleFactory::CreateCar();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_SHIFT, "Create car+warp"))
{
CPed* pPlayer = CGameWorld::FindLocalPlayer();
if (pPlayer && CVehicleFactory::ms_pLastCreatedVehicle)
{
TUNE_GROUP_INT(VEHICLE_DEBUG, SEAT_TO_WARP_INTO, -1, -1, 16, 1)
const s32 iSeatIndex = CVehicleFactory::ms_pLastCreatedVehicle->IsSeatIndexValid(SEAT_TO_WARP_INTO) ? SEAT_TO_WARP_INTO : 0;
pPlayer->GetPedIntelligence()->FlushImmediately(true);
pPlayer->SetPedInVehicle(CVehicleFactory::ms_pLastCreatedVehicle, iSeatIndex, CPed::PVF_Warp);
CVehicleFactory::ms_pLastCreatedVehicle->SwitchEngineOn(true);
}
#if __BANK
if (PARAM_licensePlate.Get() && CVehicleFactory::ms_pLastCreatedVehicle)
{
CCustomShaderEffectVehicle* pShader = static_cast<CCustomShaderEffectVehicle*>(CVehicleFactory::ms_pLastCreatedVehicle->GetDrawHandler().GetShaderEffect());
Assert(pShader);
const char * license = NULL;
PARAM_licensePlate.Get(license);
pShader->SetLicensePlateText(license);
}
#endif
}
else if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_CTRL, "Create car+populate"))
{
CPedVariationDebug::ms_UseDefaultRelationshipGroups = true;
CPed::CreateBank();
populateCarWithRandomsCB();
CPedVariationDebug::ms_UseDefaultRelationshipGroups = false;
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_U, KEYBOARD_MODE_DEBUG_ALT, "Create car+populate dumb"))
{
CPedVariationDebug::ms_UseDefaultRelationshipGroups = true;
CPed::CreateBank();
populateCarWithDumbRandomsCB();
CPedVariationDebug::ms_UseDefaultRelationshipGroups = false;
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_SHIFT, "Populate last vehicle"))
{
CPedVariationDebug::ms_UseDefaultRelationshipGroups = true;
CPed::CreateBank();
populateCarWithRandomsCB();
CPedVariationDebug::ms_UseDefaultRelationshipGroups = false;
}
else if (bPopulateLastVehicleDumb)
{
CPedVariationDebug::ms_UseDefaultRelationshipGroups = true;
CPed::CreateBank();
populateCarWithDumbRandomsCB();
CPedVariationDebug::ms_UseDefaultRelationshipGroups = false;
}
if (NetworkInterface::IsGameInProgress())
GetEventScriptNetworkGroup()->Add(CEventNetworkCheatTriggered(CEventNetworkCheatTriggered::CHEAT_VEHICLE));
}
if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_H, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT, "Create horse+warp") )
{
CPed::CreateBank();
CPedVariationDebug::SetTypeIdByName("A_C_Horse");
CPedVariationDebug::CreatePedCB();
if(CPedFactory::GetLastCreatedPed() &&
CPedFactory::GetLastCreatedPed()->GetCapsuleInfo()->IsQuadruped() &&
CPedFactory::GetLastCreatedPed()->GetPedModelInfo()->GetLayoutInfo())
{
CPed * pPlayerPed = FindPlayerPed();
if(pPlayerPed)
{
pPlayerPed->SetPedOnMount(CPedFactory::GetLastCreatedPed());
}
}
}
else if( CControlMgr::GetKeyboard().GetKeyJustDown(KEY_H, KEYBOARD_MODE_DEBUG_SHIFT_ALT, "Create horse+populate") )
{
CPed::CreateBank();
s32 lastName = CPedVariationDebug::currPedNameSelection;
CPedVariationDebug::SetTypeIdByName("A_C_Horse");
CPedVariationDebug::CreatePedCB();
CPed* pHorse = CPedFactory::GetLastCreatedPed();
CPedVariationDebug::currPedNameSelection = lastName;
CPedVariationDebug::CreatePedCB();
CPed* pRider = CPedFactory::GetLastCreatedPed();
if (pRider && pHorse)
{
pRider->SetPedOnMount(pHorse);
}
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG, "Create ped")||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG_SHIFT, "Create ped+next")||
(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG_CTRL, "Create ped+control") && !NetworkInterface::IsGameInProgress()))
{
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG_SHIFT, "Create ped+next"))
{
CPedVariationDebug::CycleTypeId();
}
Displayf("******************************************************");
Displayf("CREATING DEBUG PED - PLAYER PRESSED \"Create ped\" KEY");
Displayf("******************************************************");
CPed::CreateBank();
CPedVariationDebug::CreatePedCB();
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DECIMAL, KEYBOARD_MODE_DEBUG_CTRL, "Create ped+control"))
{
if(CPedFactory::GetLastCreatedPed())
{
CPed * pPlayerPed = FindPlayerPed();
if(pPlayerPed)
{
CGameWorld::ChangePlayerPed(*pPlayerPed, *CPedFactory::GetLastCreatedPed());
}
}
}
}
TUNE_FLOAT(KILL_HOSTILE_PEDS_RADIUS, 15.0f, 0.0f, 100.0f, 1.0f);
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_K, KEYBOARD_MODE_DEBUG, "Kill Hostile Peds"))
{
CPed* pPlayer = CGameWorld::FindLocalPlayer();
if (pPlayer)
{
const Vec3V vPlayerPosition = pPlayer->GetTransform().GetPosition();
const ScalarV svKillRadius = ScalarVFromF32(KILL_HOSTILE_PEDS_RADIUS);
s32 PedPoolIndex = CPed::GetPool()->GetSize();
while (PedPoolIndex--)
{
CPed* pPed = CPed::GetPool()->GetSlot(PedPoolIndex);
if(pPed && !pPed->IsDead())
{
if (IsLessThanAll(Dist(pPed->GetTransform().GetPosition(), vPlayerPosition), svKillRadius))
{
bool bShouldKill = false;
const CRelationshipGroup* pRelGroup = pPed->GetPedIntelligence()->GetRelationshipGroup();
const int playerRelationshipGroupIndex = pPlayer->GetPedIntelligence()->GetRelationshipGroupIndex();
if( pRelGroup)
{
if( pRelGroup->CheckRelationship( (eRelationType)ACQUAINTANCE_TYPE_PED_WANTED, playerRelationshipGroupIndex )
|| pRelGroup->CheckRelationship( (eRelationType)ACQUAINTANCE_TYPE_PED_HATE, playerRelationshipGroupIndex ))
{
bShouldKill = true;
}
}
if (pPed->GetPedIntelligence()->GetQueriableInterface()->GetHostileTarget() == pPlayer)
{
bShouldKill = true;
}
if (bShouldKill && !pPed->IsNetworkClone())
{
pPed->SetHealth(0.0f);
}
}
}
}
}
}
#endif
#if __BANK
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_R, KEYBOARD_MODE_DEBUG_SHIFT, "display ped population multipliers"))
{
CPedPopulation::ms_bDisplayMultipliers = !CPedPopulation::ms_bDisplayMultipliers;
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_R, KEYBOARD_MODE_DEBUG, "display paths"))
{
static bool bDisplayPaths = false;
// 3 stage vehicle population debug - Paths/Mulipliers, Multipliers Only, Off
bool displayMultipliers = ThePaths.bDisplayMultipliers;
bool displayPaths = ThePaths.bDisplayPathsDebug_Allow;
if(!bDisplayPaths)
{
// turn on everything
bDisplayPaths = true;
displayMultipliers = true;
displayPaths = true;
CTrain::sm_bDisplayTrainAndTrackDebug = true;
}
else if(displayMultipliers && displayPaths)
{
// turn off paths, but leave on multipliers
displayPaths = false;
displayMultipliers = true;
CTrain::sm_bDisplayTrainAndTrackDebug = false;
}
else
{
// turn everything off
bDisplayPaths = false;
displayMultipliers = false;
displayPaths = false;
CTrain::sm_bDisplayTrainAndTrackDebug = false;
}
ThePaths.bDisplayPathsDebug_Allow = displayPaths;
ThePaths.bDisplayMultipliers = displayMultipliers;
ThePaths.bDisplayPathsDebug_Nodes_AllowDebugDraw = displayPaths;
ThePaths.bDisplayPathsDebug_Links_AllowDebugDraw = displayPaths;
}
#endif
#if __BANK
if (CTrain::sm_bDebugTrain)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CTrain::PerformDebugTeleportEngineCB();
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG_SHIFT))
{
CTrain::PerformDebugTeleportCB();
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG_ALT))
{
CTrain::PerformDebugTeleportToRoof();
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG_CTRL))
{
CTrain::PerformDebugTeleportIntoSeatCB();
}
}
if (sm_debugrespot)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CPed *pLocalPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pLocalPlayer && pLocalPlayer->GetIsDrivingVehicle())
{
CVehicle* pVehicle = pLocalPlayer->GetMyVehicle();
if (pVehicle)
{
pVehicle->SetRespotCounter(5000);
}
}
}
}
if (sm_debugrespawninvincibility)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CPed *pLocalPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pLocalPlayer && pLocalPlayer->GetNetworkObject())
{
CNetObjPlayer* pNetObjPlayer = static_cast<CNetObjPlayer*>(pLocalPlayer->GetNetworkObject());
if (pNetObjPlayer)
{
pNetObjPlayer->SetRespawnInvincibilityTimer(5000);
}
}
}
}
if (sm_debugdoublekill)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_K, KEYBOARD_MODE_DEBUG))
{
CPed *pPedLocalPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pPedLocalPlayer && pPedLocalPlayer->GetPlayerInfo())
{
//Just enough to keep the player alive -- 100 is the baseline
pPedLocalPlayer->SetHealth(101.f);
//Fire at the closest player
Vector3 vecTarget(Vector3::ZeroType);
CEntity* pEntity = pPedLocalPlayer->GetPlayerInfo()->GetTargeting().FindLockOnTarget();
CPed* pPedVictim = NULL;
if (pEntity && pEntity->GetIsTypePed())
pPedVictim = static_cast<CPed*>(pEntity);
if (pPedVictim)
{
pPedVictim->GetBonePosition(vecTarget, BONETAG_HEAD);
Vector3 vecStart, vecEnd;
CWeapon* pEquippedWeapon = pPedLocalPlayer->GetWeaponManager()->GetEquippedWeapon();
CObject* pWeaponObject = pPedLocalPlayer->GetWeaponManager()->GetEquippedWeaponObject();
if( pEquippedWeapon && pWeaponObject )
{
Matrix34 matWeapon;
if(pEquippedWeapon->GetWeaponModelInfo()->GetBoneIndex( WEAPON_MUZZLE ) != -1)
{
pWeaponObject->GetGlobalMtx( pEquippedWeapon->GetWeaponModelInfo()->GetBoneIndex( WEAPON_MUZZLE ), matWeapon );
}
else
{
pWeaponObject->GetMatrixCopy( matWeapon );
}
// Check to see if the target vector is valid
bool bvecTargetIsZero = vecTarget.IsZero();
if( !bvecTargetIsZero )
{
// calculate the END of the firing vector using the specific position
pEquippedWeapon->CalcFireVecFromPos(pPedLocalPlayer, matWeapon, vecStart, vecEnd, vecTarget);
// fire the weapon
CWeapon::sFireParams params( pPedLocalPlayer, matWeapon, &vecStart, &vecTarget );
params.iFireFlags.SetFlag( CWeapon::FF_ForceBulletTrace );
params.iFireFlags.SetFlag( CWeapon::FF_SetPerfectAccuracy );
pEquippedWeapon->Fire( params );
}
}
}
}
}
}
if (sm_debugexplosion)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CPed *pLocalPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pLocalPlayer)
{
CExplosionManager::CExplosionArgs explosionArgs(EXP_TAG_GRENADE, VEC3V_TO_VECTOR3(pLocalPlayer->GetTransform().GetPosition()));
explosionArgs.m_sizeScale = 50.0f;
explosionArgs.m_bMakeSound = true;
explosionArgs.m_bNoFx = false;
explosionArgs.m_fCamShake = false;
CExplosionManager::AddExplosion(explosionArgs);
}
}
}
if (sm_debuglicenseplate)
{
if (socialclub_commands::CommandCheckLicensePlate_IsValid(sm_token))
{
if (!socialclub_commands::CommandCheckLicensePlate_IsPending(sm_token))
{
if (socialclub_commands::CommandCheckLicensePlate_PassedValidityCheck(sm_token))
{
sm_token = 0;
Displayf("debuglicenseplate--PASSED");
}
else
{
sm_token = 0;
Displayf("debuglicenseplate--FAILED");
}
}
}
else if (sm_token == 0)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CPed *pLocalPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pLocalPlayer && pLocalPlayer->GetIsDrivingVehicle())
{
CVehicle* pVehicle = pLocalPlayer->GetMyVehicle();
if (pVehicle)
{
CCustomShaderEffectVehicle* pShader = static_cast<CCustomShaderEffectVehicle*>(pVehicle->GetDrawHandler().GetShaderEffect());
if (pShader)
{
const char* license = pShader->GetLicensePlateText();
if (license)
{
Displayf("debuglicenseplate--PLATE[%s]-->invoke CommandCheckLicensePlate",license);
sm_token = 1;
socialclub_commands::CommandCheckLicensePlate(license, sm_token);
}
}
}
}
}
}
}
if (sm_debugaircraftcarrier)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
Displayf("SPAWNED aircraft carrier");
streaming_commands::RequestIpl("hei_carrier");
streaming_commands::RequestIpl("hei_Carrier_int1");
streaming_commands::RequestIpl("hei_Carrier_int2");
streaming_commands::RequestIpl("hei_Carrier_int3");
streaming_commands::RequestIpl("hei_Carrier_int4");
streaming_commands::RequestIpl("hei_Carrier_int5");
streaming_commands::RequestIpl("hei_Carrier_int6");
}
}
#if NA_RADIO_ENABLED
if (sm_debugradiotest)
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG_SHIFT))
{
Displayf("RESET SetOverrideSpecatedVehicleRadio");
NetworkInterface::SetOverrideSpectatedVehicleRadio(false);
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_T, KEYBOARD_MODE_DEBUG))
{
CVehicle* pVehicle = NULL;
bool bLocalPlayer = false;
CPed *pPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
if (pPlayer && pPlayer->GetMyVehicle())
{
bLocalPlayer = true;
pVehicle = pPlayer->GetMyVehicle();
}
else
{
pPlayer = CGameWorld::FindFollowPlayer();
if (pPlayer && pPlayer->GetMyVehicle())
pVehicle = pPlayer->GetMyVehicle();
}
if(pVehicle && pVehicle->GetVehicleAudioEntity())
{
if (!bLocalPlayer)
NetworkInterface::SetOverrideSpectatedVehicleRadio(true);
if (pVehicle->GetVehicleAudioEntity()->IsRadioSwitchedOn())
{
Displayf("%s : SET RADIO OFF",bLocalPlayer ? "LOCALPLAYER" : "FOLLOWPLAYER : SET SetOverrideSpectatedVehicleRadio");
pVehicle->GetVehicleAudioEntity()->SetRadioOffState(true);
}
else
{
Displayf("%s : SET RADIO ON : SET RADIO STATION COUNTRY",bLocalPlayer ? "LOCALPLAYER" : "FOLLOWPLAYER : SET SetOverrideSpectatedVehicleRadio");
pVehicle->GetVehicleAudioEntity()->SetRadioOffState(false);
pVehicle->GetVehicleAudioEntity()->SetScriptRequestedRadioStation();
pVehicle->GetVehicleAudioEntity()->SetRadioStation(audRadioStation::FindStation("RADIO_06_COUNTRY"));
}
}
}
}
#endif
#endif
#if __DEV
TUNE_BOOL(ENABLE_MOVE_NETWORK_RELOAD_PRESSING_L, false);
if (ENABLE_MOVE_NETWORK_RELOAD_PRESSING_L && CControlMgr::GetKeyboard().GetKeyJustDown(KEY_L, KEYBOARD_MODE_DEBUG, "Reload Move Networks"))
{
CAnimViewer::ReloadAllNetworks();
}
#endif // __DEV
#if __BANK
TUNE_GROUP_FLOAT(VEHICLE_ON_SIDE_DEBUG, RAISE_AMOUNT, 1.0f, 0.0f, 5.0f, 0.1f);
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F7, KEYBOARD_MODE_DEBUG, "force player car upside down"))
{
if (CVehicle* pVehicle = FindPlayerVehicle())
{
Matrix34 carMat = MAT34V_TO_MATRIX34(pVehicle->GetMatrix());
Matrix34 carOriginalMat = carMat;
carMat.c = -carMat.c;
carMat.a = -carMat.a;
carMat.d.z += RAISE_AMOUNT;
pVehicle->SetMatrix(carMat);
pVehicle->UpdateGadgetsAfterTeleport(carOriginalMat);
}
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F7, KEYBOARD_MODE_DEBUG_CTRL, "force player car on left side"))
{
if (CVehicle* pVehicle = FindPlayerVehicle())
{
Matrix34 carMat = MAT34V_TO_MATRIX34(pVehicle->GetMatrix());
Matrix34 carOriginalMat = carMat;
carMat.RotateLocalY(-HALF_PI);
carMat.d.z += RAISE_AMOUNT;
pVehicle->SetMatrix(carMat);
pVehicle->UpdateGadgetsAfterTeleport(carOriginalMat);
}
}
else if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F7, KEYBOARD_MODE_DEBUG_ALT, "force player car on right side"))
{
if (CVehicle* pVehicle = FindPlayerVehicle())
{
Matrix34 carMat = MAT34V_TO_MATRIX34(pVehicle->GetMatrix());
Matrix34 carOriginalMat = carMat;
carMat.RotateLocalY(HALF_PI);
carMat.d.z += 1.0f;
pVehicle->SetMatrix(carMat);
pVehicle->UpdateGadgetsAfterTeleport(carOriginalMat);
}
}
#endif
#if __BANK
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_S, KEYBOARD_MODE_DEBUG, "reload all shaders"))
{
CDrawListMgr::RequestShaderReload();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_N, KEYBOARD_MODE_DEBUG_CTRL, "Display network info"))
{
NetworkDebug::ToggleDisplayObjectInfo();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_V, KEYBOARD_MODE_DEBUG_CTRL, "Display network visibility info"))
{
NetworkDebug::ToggleDisplayObjectVisibilityInfo();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_B)) // toggle timer bars with B
{
gDisplayTimerBars = !gDisplayTimerBars;
}
#if DR_ENABLED
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_D, KEYBOARD_MODE_DEBUG_CTRL, "Toggle debug recorder display"))
{
ms_GameRecorder->ToggleDisplay();
}
#endif
#endif
#if __BANK
#if RSG_PS3
s32 keyCutsceneLighting = KEY_KANJI; // equivalent to KEY_GRAVE (keyboard grave accent and tilde)
#else
s32 keyCutsceneLighting = KEY_GRAVE;
#endif
if (CControlMgr::GetKeyboard().GetKeyJustDown(keyCutsceneLighting, KEYBOARD_MODE_DEBUG, "Cutscene Lighting Budget"))
{
DebugLights::CycleCutsceneDebugInfo();
}
#endif // __BANK
#if __BANK
// Verbose failmark
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SPACE, KEYBOARD_MODE_DEBUG_SHIFT, "Add a verbose fail mark"))
{
grcDebugDraw::Text(0.f, 0.f, Color_blue, "FAILMARK", false, 3.0f, 3.0f, 120); //display on-screen visual notification to the user that this is happening - so they get some feedback. lavalley
NetworkDebug::AddFailMark("FAILMARK");
}
#endif
#endif
// Call CDebugScene::CheckMouse() even in BankRelease builds.
// But in BankRelease *only* if mouse has been clicked, as there's some overhead
// and we don't want to skew profile results by calling it ever frame.
// In __DEV builds this is called every frame to update WhatAmILookingAt, etc.
#if !__FINAL
CDebugScene::CheckMouse();
#endif
#if __DEV
if(gpDisplayObject)
{
CDebugScene::PrintInfoAboutEntity(gpDisplayObject);
}
#if __DEV
if (gDisplayMapZone)
{
camDebugDirector& debugDirector = camInterface::GetDebugDirector();
Vector3 vecCamPos = debugDirector.IsFreeCamActive() ? debugDirector.GetFreeCamFrame().GetPosition() : CGameWorld::FindLocalPlayerCoors();
const char* areaName = CMapAreas::GetAreaNameFromPosition(vecCamPos);
grcDebugDraw::AddDebugOutput(areaName);
grcDebugDraw::AddDebugOutput("\n");
}
#endif // __DEV
if (C2dEffect::m_PrintStats)
{
C2dEffect::PrintDebugStats();
}
#if __BANK
C2dEffectDebugRenderer::Update();
#endif //__BANK
#if __D3D && __WIN32PC && 0
if (showd3dresourceinfo==true)
{
#if 0
D3DRTYPE_SURFACE = 1,
D3DRTYPE_VOLUME = 2,
D3DRTYPE_TEXTURE = 3,
D3DRTYPE_VOLUMETEXTURE = 4,
D3DRTYPE_CUBETEXTURE = 5,
D3DRTYPE_VERTEXBUFFER = 6,
D3DRTYPE_INDEXBUFFER = 7,
BOOL bThrashing; /* indicates if thrashing */
DWORD ApproxBytesDownloaded; /* Approximate number of bytes downloaded by resource manager */
DWORD NumEvicts; /* number of objects evicted */
DWORD NumVidCreates; /* number of objects created in video memory */
DWORD LastPri; /* priority of last object evicted */
DWORD NumUsed; /* number of objects set to the device */
DWORD NumUsedInVidMem; /* number of objects set to the device, which are already in video memory */
// Persistent data
DWORD WorkingSet; /* number of objects in video memory */
DWORD WorkingSetBytes; /* number of bytes in video memory */
DWORD TotalManaged; /* total number of managed objects */
DWORD TotalBytes; /* total number of bytes of managed objects */
#endif
grcDebugDraw::AddDebugOutput("TX TH:%d DL:%d EV:%d VC:%d LP:%d US:%d/%d OBJ:%d/%d MEM:%d/%d\n", CSystem::ms_d3dResourceData.stats[3].bThrashing, CSystem::ms_d3dResourceData.stats[3].ApproxBytesDownloaded, CSystem::ms_d3dResourceData.stats[3].NumEvicts, CSystem::ms_d3dResourceData.stats[3].NumVidCreates, CSystem::ms_d3dResourceData.stats[3].LastPri, CSystem::ms_d3dResourceData.stats[3].NumUsed, CSystem::ms_d3dResourceData.stats[3].NumUsedInVidMem, CSystem::ms_d3dResourceData.stats[3].WorkingSet, CSystem::ms_d3dResourceData.stats[3].TotalManaged, CSystem::ms_d3dResourceData.stats[3].WorkingSetBytes, CSystem::ms_d3dResourceData.stats[3].TotalBytes);
grcDebugDraw::AddDebugOutput("VB TH:%d DL:%d EV:%d VC:%d LP:%d US:%d/%d OBJ:%d/%d MEM:%d/%d\n", CSystem::ms_d3dResourceData.stats[6].bThrashing, CSystem::ms_d3dResourceData.stats[6].ApproxBytesDownloaded, CSystem::ms_d3dResourceData.stats[6].NumEvicts, CSystem::ms_d3dResourceData.stats[6].NumVidCreates, CSystem::ms_d3dResourceData.stats[6].LastPri, CSystem::ms_d3dResourceData.stats[6].NumUsed, CSystem::ms_d3dResourceData.stats[6].NumUsedInVidMem, CSystem::ms_d3dResourceData.stats[6].WorkingSet, CSystem::ms_d3dResourceData.stats[6].TotalManaged, CSystem::ms_d3dResourceData.stats[6].WorkingSetBytes, CSystem::ms_d3dResourceData.stats[6].TotalBytes);
grcDebugDraw::AddDebugOutput("IB TH:%d DL:%d EV:%d VC:%d LP:%d US:%d/%d OBJ:%d/%d MEM:%d/%d\n", CSystem::ms_d3dResourceData.stats[7].bThrashing, CSystem::ms_d3dResourceData.stats[7].ApproxBytesDownloaded, CSystem::ms_d3dResourceData.stats[7].NumEvicts, CSystem::ms_d3dResourceData.stats[7].NumVidCreates, CSystem::ms_d3dResourceData.stats[7].LastPri, CSystem::ms_d3dResourceData.stats[7].NumUsed, CSystem::ms_d3dResourceData.stats[7].NumUsedInVidMem, CSystem::ms_d3dResourceData.stats[7].WorkingSet, CSystem::ms_d3dResourceData.stats[7].TotalManaged, CSystem::ms_d3dResourceData.stats[7].WorkingSetBytes, CSystem::ms_d3dResourceData.stats[7].TotalBytes);
}
#endif
#endif
// object placement bindings
#if __BANK
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT))
{
DisplayObjectAndPlaceOnGround();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_O, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT))
{
DeleteObject();
}
if(CControlMgr::GetKeyboard().GetKeyJustDown(KEY_L, KEYBOARD_MODE_DEBUG_CNTRL_SHIFT))
{
FragTuneLastObject();
}
#endif // __BANK
#if __BANK
if (PARAM_debugstart.Get() && !m_debugParamUsed && g_SceneToGBufferPhaseNew)
{
float params[16];
PARAM_debugstart.GetArray(&params[0], 16);
SetDebugParams(params, 16);
m_debugParamUsed = true;
}
#endif
#if DR_ENABLED
if (ms_GameRecorder)
{
ms_GameRecorder->SetRecorderFrameCount( fwTimer::GetFrameCount() );
ms_GameRecorder->SetRecorderNetworkTime( NetworkInterface::IsNetworkOpen() ? NetworkInterface::GetNetworkTime() : 0 ); }
#endif // DR_ENABLED
#if DEBUG_BANK
FindEntityFromPointer();
#endif
// QA debug physics rendering
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_P, KEYBOARD_MODE_DEBUG_CTRL))
{
phMaterialDebug::ToggleQAMode();
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_C, KEYBOARD_MODE_DEBUG_CTRL))
{
phMaterialDebug::ToggleRenderNonClimbableCollision();
}
// debug particle effect rendering
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F, KEYBOARD_MODE_DEBUG_CTRL))
{
ptxDebug::ToggleQuickDebug();
}
#if !__FINAL
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_I, KEYBOARD_MODE_DEBUG_ALT))
{
CInteriorProxy::EnableAndUncapAllInteriors();
}
#endif
BUDGET_DRAW();
}
//
// name: CDebug::RenderUpdate
// description:
void CDebug::RenderUpdate()
{
#if __XENON && !__FINAL
TraceThread(sm_bTraceRenderThread, sm_bStartedRenderTrace, "render_trace", sm_iRenderTraceCount);
// If we're tracing the main thread with -pgolitetrace enabled, automatically trace the render thread next
if(sm_bPgoLiteTrace && sm_bStartedUpdateTrace)
{
sm_bTraceRenderThread = true;
}
#endif
#if __BANK
// Process bugstar screenshots
CBugstarIntegration::ProcessScreenShot();
#endif
}
//
// name: CDebug::StartWithDebugParams
// description:
void CDebug::SetDebugParams(float *data, u32 numElements)
{
if (numElements == 16) // Pos + Full matrix + Hour
{
debugLocation debLoc;
CStreaming::SetIsPlayerPositioned(true);
debLoc.Set(data);
debLoc.BeamMeUp();
}
}
//
// name: CDebug::CameraDump
// description:
void CDebug::DumpDebugParams()
{
debugLocation debLoc;
if( debLoc.SetFromCurrent() )
{
char buffer[255];
debLoc.WriteOut(buffer);
Displayf("-debugstart=%s", buffer);
}
else
{
Displayf("[Debug Params] Need to have the debug camera active for this");
}
}
//
// name: CDebug::RenderProfiler
// description:
void CDebug::RenderProfiler()
{
#if __STATS
if (PFSTATS.IsActive() || GetRageProfileRenderer().AnyEkgsActive())
{
PFSTATS.Cull();
// Draw the ekg graphs.
GetRageProfileRenderer().Draw();
#if !__FINAL
if (GetRageProfiler().m_Enabled)
{
grcDebugDraw::SetDisplayDebugText(false);
}
#endif // !__FINAL
}
#endif // !__STATS
}
#endif
#if !__FINAL
#if __WIN32PC && 0
void CDebug::DebugSystemError(const char* , s32 )
{
if(GetLastError() != ERROR_SUCCESS)
{
char msgBuff[256];
Assertf(0, ("System error: %s", diagErrorCodes::Win32ErrorToString(GetLastError(), msgBuff, NELEM(msgBuff))));
}
}
#endif // __WIN32PC
#if ( DEBUG_RENDER_BUG_LIST )
//
// name: RenderBugList
// description: Render all the bugs stored in the current buglist
void CDebug::RenderTheBugList()
{
CBugstarIntegration::RenderTheBuglist();
}
#endif // DEBUG_RENDER_BUG_LIST
#if __ASSERT
static sysTimer s_AssertTimer;
static float s_TimeSinceLastAssert = FLT_MAX;
//
// name: OnAssertionFired
// description: Callback for when an assertion is about to fire
static bool OnAssertionFired(const diagChannel &channel,diagSeverity &severity,const char*,int,const char*message)
{
if(severity <= channel.PopupLevel)
{
STRVIS_MARK_ASSERT(message);
(void) message;
s_TimeSinceLastAssert = s_AssertTimer.GetTimeAndReset();
if(CSystem::IsThisThreadId(SYS_THREAD_UPDATE) && NetworkInterface::IsNetworkOpen())
{
static bool flushingLogFiles = false;
if(!flushingLogFiles)
{
flushingLogFiles = true;
Displayf("Frame %d, Assertion fired, flushing log files...\r\n", fwTimer::GetFrameCount());
NetworkInterface::GetPlayerMgr().GetLog().Log("Assertion fired, flushing log files...\r\n");
NetworkInterface::GetObjectManager().GetLog().Log("Assertion fired, flushing log files...\r\n");
NetworkInterface::GetObjectManager().GetReassignMgr().GetLog().Log("Assertion fired, flushing log files...\r\n");
NetworkInterface::GetEventManager().GetLog().Log("Assertion fired, flushing log files...\r\n");
NetworkInterface::GetArrayManager().GetLog().Log("Assertion fired, flushing log files...\r\n");
NetworkInterface::GetMessageLog().Log("Assertion fired, flushing log files...\r\n");
if(CTheScripts::GetScriptHandlerMgr().GetLog())
{
CTheScripts::GetScriptHandlerMgr().GetLog()->Log("Assertion fired, flushing log files...\r\n");
}
#if ENABLE_NETWORK_LOGGING
CNetwork::OnAssertionFired();
#endif // ENABLE_NETWORK_LOGGING
flushingLogFiles = false;
}
}
#if RSG_PC
if(!PARAM_nopopups.Get())
{
ioKeyboard::FlushKeyboard();
ioMouse::OnAssert();
}
#endif // RSG_PC
}
#if __BANK
strStreamingEngine::GetLoader().ResetLoadAllBailTimeout();
#endif // __BANK
// returning true indicates to the channel system that we still want an assertion popup to be displayed
return true;
}
#endif // __ASSERT
#endif // ENABLE_CDEBUG
#if __ASSERT
static atString s_assertCallstack;
static atString s_minimalAssertCallstack;
static int s_callstackDepth;
static void InitGenerateCallstack()
{
s_callstackDepth = 0;
}
//
//void CDebug::GenerateCallstack(u32 OUTPUT_ONLY(addr),const char *OUTPUT_ONLY(sym),u32 OUTPUT_ONLY(offset))
static void GenerateCallstack(size_t OUTPUT_ONLY(addr),const char *OUTPUT_ONLY(sym),size_t OUTPUT_ONLY(offset))
{
char buffer[256];
formatf(buffer, "%8" SIZETFMT "x - %s+%" SIZETFMT "x\n", addr, sym, offset, NELEM(buffer));
s_assertCallstack += buffer;
// Only record first 4 entries on callstack
if(s_callstackDepth < 4)
{
formatf(buffer, "%s\n", sym, NELEM(buffer));
// replace "(void)" in 360 callstacks with "()"
char* voidFunc = const_cast<char*>(strstr(buffer, "(void)"));
if(voidFunc)
strcpy(voidFunc, "()");
s_minimalAssertCallstack += buffer;
s_callstackDepth++;
}
}
#if RSG_PS3
static void GenerateCallstackSpu(u32 UNUSED_PARAM(frameNumber), u32 lsAddr, u32 UNUSED_PARAM(lsOffset), const char *sym, u32 symOffset)
{
GenerateCallstack(lsAddr, sym, symOffset);
}
#endif
static atString s_scriptCallstack;
void DumpThreadState(const char* fmt, ...)
{
char buffer[256];
va_list args;
va_start(args,fmt);
vformatf(buffer, sizeof(buffer), fmt, args);
va_end(args);
s_scriptCallstack += buffer;
s_scriptCallstack += "\n";
}
#define LOG_INTRO_SIZE 15*1024
#define LOG_OUTRO_SIZE 185*1024
#define LOG_INBETWEEN_TEXT "\n.\n.\n.\n.\n.\n.\n"
#define LOG_INBETWEEN_TEXT_SIZE 13
#define LOG_BUFFER_SIZE (LOG_INTRO_SIZE + LOG_INBETWEEN_TEXT_SIZE + LOG_OUTRO_SIZE + 1)
char* LoadOutputLog(int& logSize)
{
USE_DEBUG_MEMORY();
const char* logFilename = diagChannel::GetLogFileName();
diagChannel::FlushLogFile();
fiStream* pLogStream = ASSET.Open(logFilename, "");
if(pLogStream)
{
char* pBuffer = rage_new char[LOG_BUFFER_SIZE];
char* pPosn = pBuffer;
int fileSize = pLogStream->Size();
if(fileSize < LOG_BUFFER_SIZE)
{
int count = pLogStream->Read(pPosn, fileSize);
pPosn += count;
}
else
{
int count = pLogStream->Read(pPosn, LOG_INTRO_SIZE);
pPosn += count;
strcpy(pPosn, LOG_INBETWEEN_TEXT);
pPosn += LOG_INBETWEEN_TEXT_SIZE;
pLogStream->Seek(fileSize - LOG_OUTRO_SIZE);
count = pLogStream->Read(pPosn, LOG_OUTRO_SIZE);
pPosn += count;
}
pLogStream->Close();
// temporarily save out to file to see what I've got
//ASSET.CreateLeadingPath("assert.log");
//fiStream* pStream = ASSET.Create("assert.log", "");
//pStream->Write(pBuffer, pPosn - pBuffer);
//pStream->Close();
logSize = ptrdiff_t_to_int(pPosn - pBuffer);
*pPosn = '\0';
return pBuffer;
}
return NULL;
}
//
// name:
// description: Callback for after the assert dialog is shown to update/create a bug in bugstar
int CDebug::OnLogBug(const char* summary, const char* details, u32 assertId, int dialogResult)
{
USE_DEBUG_MEMORY();
// Generate a callstack
s_assertCallstack = "";
s_minimalAssertCallstack = "";
InitGenerateCallstack();
sysStack::PrintStackTrace(GenerateCallstack, __XENON ? 4 : 3);
// Extend the assert id with the callstack
assertId = atStringHash(s_minimalAssertCallstack.c_str(), assertId);
OnLogBug(summary, details, s_assertCallstack.c_str(), assertId, (dialogResult == IDCUSTOM4));
// Modify the result to something appropriate if IDCUSTOM4 was returned
if (dialogResult == IDCUSTOM4)
{
dialogResult = fiRemoteShowMessageBox(summary,diagAssertTitle?diagAssertTitle:sysParam::GetProgramName(), MB_ABORTRETRYIGNORE | MB_ICONQUESTION | MB_TOPMOST | MB_DEFBUTTON3 ,dialogResult);
}
s_AssertTimer.Reset();
return dialogResult;
}
#if __PS3
void SpuCallstackFromAssertString(sys_spu_thread_t thread, const char *text, void (*printFn)(u32,u32,u32,const char*,u32));
static struct {
int m_spu;
const char* m_summary;
const char* m_details;
u32 m_assertId;
bool m_showBug;
} s_spuBugDetails;
//
// name:
// description: Callback for after the assert dialog is shown to update/create a bug in bugstar
int CDebug::OnSpuAssert(int spu, const char* summary, const char* assertText, int defaultIfNoServer)
{
USE_DEBUG_MEMORY();
s_TimeSinceLastAssert = s_AssertTimer.GetTimeAndReset();
int answer = fiRemoteShowAssertMessageBox(assertText,diagAssertTitle? diagAssertTitle : sysParam::GetProgramName(),MB_ABORTRETRYIGNORE | MB_ICONQUESTION | MB_TOPMOST | MB_DEFBUTTON3,defaultIfNoServer);
// Generate a callstack
s_assertCallstack = "";
s_minimalAssertCallstack = "";
InitGenerateCallstack();
SpuCallstackFromAssertString(spu, summary, GenerateCallstackSpu);
// Extend the assert id with the callstack
u32 assertId = atStringHash(s_minimalAssertCallstack.c_str(), atStringHash(summary));
const bool showBug = (answer == IDCUSTOM4);
OnLogBug(summary, summary, s_assertCallstack.c_str(), assertId, showBug);
// Modify the result to something appropriate if IDCUSTOM4 was returned
if (answer == IDCUSTOM4)
{
answer = fiRemoteShowMessageBox(assertText,diagAssertTitle?diagAssertTitle:sysParam::GetProgramName(),MB_ABORTRETRYIGNORE | MB_ICONQUESTION | MB_TOPMOST | MB_DEFBUTTON3 | MB_SETFOREGROUND,defaultIfNoServer);
}
else
answer = IDIGNORE;
s_AssertTimer.Reset();
return answer;
}
#endif // __PS3
sysCriticalSectionToken s_OnLogBugCS;
bool CDebug::OnLogBug(const char* summary, const char* details, const char* callstack, u32 assertId, bool showBug)
{
SYS_CS_SYNC(s_OnLogBugCS);
// On PC, bugs are queued before some systems have fully initialised, so throwing an assert
// causes another assert, ad infinitum.
static bool preventingRecursion = false;
if (preventingRecursion)
return false;
else
preventingRecursion = true;
Vector3 posn(0.0f, 0.0f, 0.0f);
if (gVpMan.GetGameViewport() != NULL)
{
posn = VEC3V_TO_VECTOR3(gVpMan.GetGameViewport()->GetGrcViewport().GetCameraPosition());
}
int missionId = 0;
if(CTheScripts::GetPlayerIsOnAMission() || CTheScripts::GetPlayerIsOnARandomEvent() )
{
missionId = CMissionLookup::GetBugstarId(CDebug::GetCurrentMissionName());
}
// Commented out as there isn't currently a way to query bugstar via rest for a version id based on a name
int buildId = 0;
if (GetVersionNumber())
{
buildId = CBugstarIntegration::GetBuildLookup().GetBugstarId(GetVersionNumber());
}
int mapId = 0;
const char* levelBugstarName = CScene::GetLevelsData().GetBugstarName(CGameLogic::GetRequestedLevelIndex());
if(levelBugstarName)
{
mapId = CBugstarIntegration::GetMapLookup().GetBugstarId(levelBugstarName);
}
/*
// Commented out as there isn't currently a way to query bugstar via rest for a grid id based on a name
if (CBlockView::GetNumberOfBlocks())
formatf(tmp,sizeof(tmp),"%s",(const char*)CBlockView::GetBlockName(CBlockView::GetCurrentBlockInside()));
else
tmp[0] = '\0';
*/
// bugstar summary is limited to 255 characters
char bugSummary[255];
formatf(bugSummary, sizeof(bugSummary), "%s", summary);
s_scriptCallstack = "";
if(scrThread::GetActiveThread())
{
scrThread::GetActiveThread()->PrintStackTrace(DumpThreadState);
}
static char fullCallstack[2048];
formatf(fullCallstack, sizeof(fullCallstack), "%sCallstack:\n%s", s_scriptCallstack.c_str(), callstack);
//const char* log = GetOutputLog();
int logSize;
char* logBuffer = LoadOutputLog(logSize);
#if __WIN32PC && RSG_DXDIAG_ENABLED
int dxDiagSize;
char* dxDiagBuffer;
DXDiag::DumpDXDiagByCategory(&dxDiagBuffer, DXDiag::System | DXDiag::Display);
dxDiagSize = istrlen(dxDiagBuffer);
#endif
Displayf("Assert ID: %d", assertId);
CBugstarAssertUpdateQuery::BugDesc bugDesc;
bugDesc.assertId = assertId;
bugDesc.logBuffer = logBuffer;
bugDesc.logSize = logSize;
bugDesc.position = posn;
bugDesc.buildId = buildId;
bugDesc.mapId = mapId;
bugDesc.missionId = missionId;
bugDesc.timeSinceLastBug = s_TimeSinceLastAssert;
#if __WIN32PC
#if RSG_DXDIAG_ENABLED
bugDesc.dxDiagBuffer = dxDiagBuffer;
bugDesc.dxDiagSize = dxDiagSize;
#else
bugDesc.dxDiagBuffer = NULL;
bugDesc.dxDiagSize = 0;
#endif
#endif
char const* gamerTag = NULL;
CPed* player = CGameWorld::FindLocalPlayer();
if(player && player->GetPlayerInfo())
{
gamerTag = player->GetPlayerInfo()->m_GamerInfo.GetName();
}
CBugstarAssertUpdateQuery* pQuery = rage_new CBugstarAssertUpdateQuery(summary, details, fullCallstack, gamerTag ? gamerTag : "No Gamer Tag", bugDesc, showBug);
pQuery->AddQueryToQueue();
preventingRecursion = false;
return true;
}
#endif // __ASSERT
#if __BANK
// Name : JumpToBugCoords
// Purpose : parses the bug CSV file, figures out where the XYZ values are and teleports the player
// Parameters : none
// Returns : Nothing
void CDebug::JumpToBugCoords()
{
if (m_iBugNumber == -1)
return;
bool bFoundBugCoords = false;
Vector3 vBugPosition;
char tempString[1024];
FileHandle fid;
char* pLine;
CFileMgr::SetDir("");
fid = CFileMgr::OpenFile("common:/DATA/Bug List.CSV", "rb");
if (!CFileMgr::IsValidFileHandle(fid))
{
bkMessageBox("Jump To Bug Coords", "Cannot find your bug csv (common:/DATA/Bug List.csv)", bkMsgOk, bkMsgError);
m_iBugNumber = -1;
return;
}
s32 iTabX = -1;
bool bFoundAllTabs = false;
bool bFoundBugNumber = false;
while( !bFoundBugCoords && ((pLine = CFileMgr::ReadLine(fid, false)) != NULL) )
{
if (!bFoundAllTabs)
{
// need to find out where the X,Y,Z columns are - so count the commas on the 1st line:
s32 iCommaCount = 0;
for (s32 i = 0; i < 1024 && pLine != NULL && !bFoundAllTabs; i++)
{
sscanf(pLine, "%s", tempString);
tempString[5] = '\0'; // terminate so we should have a string of "X,Y,Z"
if (!strcmp(tempString, "X,Y,Z"))
{
// yes we found the string
iTabX = iCommaCount; // store number of tabs along the X,Y,Z begins
bFoundAllTabs = true;
}
if (*pLine == ',')
{
iCommaCount++;
}
pLine++;
}
}
else
// we have found the tabs so lets go to the bug number and get the coords for it
{
s32 NewBugNumber;
char* pBugNumber = pLine;
pBugNumber++;
sscanf(pBugNumber, "%d", &NewBugNumber);
if (NewBugNumber == CDebug::m_iBugNumber)
{
bFoundBugNumber = true;
// we found the correct bug number so get the XYZ coords:
s32 iTabCounter = 0;
for (s32 i = 0; i < 1024 && pLine != NULL; i++)
{
while (iTabCounter != iTabX)
{
if (*pLine == '"')
{
do
{
pLine++;
} while (*pLine != '"');
iTabCounter++;
pLine++;
}
pLine++;
}
if (iTabCounter == iTabX && *pLine == '"')
{
sscanf(pLine, "%*c%f%*c%*c%*c%f%*c%*c%*c%f", &vBugPosition.x,&vBugPosition.y,&vBugPosition.z);
bFoundBugCoords = true;
break;
}
}
}
}
}
CFileMgr::CloseFile(fid);
// if we found some bug coords, then teleport player to these positions:
if (bFoundBugCoords)
{
formatf(tempString, "You will now be warped to position %0.2f,%0.2f,%0.2f (Bug #%d)", vBugPosition.x,vBugPosition.y,vBugPosition.z,m_iBugNumber, NELEM(tempString));
bkMessageBox("Jump To Bug Coords", tempString, bkMsgOk, bkMsgInfo);
CVehicle *pVehicle = FindPlayerVehicle(CGameWorld::GetMainPlayerInfo(), true);
g_SceneStreamerMgr.LoadScene(vBugPosition);
CPhysics::LoadAboutPosition(RCC_VEC3V(vBugPosition));
if (pVehicle)
{
gRenderListGroup.Clear(); // clear any renderlists as this stuff probably has deleted entities that they are pointing to!
pVehicle->Teleport(vBugPosition, 0.0f, false);
}
else if(AssertVerify(FindPlayerPed()))////will change this to teleport once the ped stuff is okay
{
gRenderListGroup.Clear(); // clear any renderlists as this stuff probably has deleted entities that they are pointing to!
FindPlayerPed()->Teleport(vBugPosition, 0.0f);
}
}
else
{
if (bFoundBugNumber)
{
formatf(tempString, "Bug #%d does not have any coords!", m_iBugNumber, NELEM(tempString));
}
else
{
formatf(tempString, "Bug #%d does not exist in your csv file!", m_iBugNumber, NELEM(tempString));
}
bkMessageBox("Jump To Bug Coords", tempString, bkMsgOk, bkMsgError);
}
m_iBugNumber = -1; // reset to -1;
}
#endif // __BANK
#if !__FINAL
// dump as much useful info as possible about this entity
void CDebug::DumpEntity(const CEntity* pEntity){
if (pEntity){
Vector3 pos = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
Displayf ("\nDump Entity\n");
Displayf ("-----------\n");
Displayf ("Addr: %p\n",pEntity);
Displayf ("Pos : (%.2f,%.2f,%.2f)\n",pos.GetX(), pos.GetY(), pos.GetZ());
if (NetworkUtils::IsNetworkClone(pEntity)){
Displayf("Clone : Yes\n");
} else {
Displayf("Clone : No\n");
}
if (pEntity->m_nFlags.bInMloRoom){
Displayf("Inside : Yes\n");
} else {
Displayf("Inside : No\n");
}
if (pEntity->GetIsTypeDummyObject()){
Displayf("Dummy Obj: Yes\n");
} else {
Displayf("Dummy Obj: No\n");
}
if ( pEntity->GetIsPhysical() && static_cast< const CPhysical* >( pEntity )->GetChildAttachment() )
{
Displayf("Attached: Yes\n");
}
netObject* pNetObj = NetworkUtils::GetNetworkObjectFromEntity(pEntity);
if (pNetObj){
Displayf("Network Obj: %s\n", pNetObj->GetLogName());
} else {
Displayf("Network Obj: No\n");
}
if (pEntity->GetIsTypeObject()){
const CObject* pObject = static_cast<const CObject*>(pEntity);
Displayf("Is managed proc object: %d\n", pObject->GetIsAnyManagedProcFlagSet());
Displayf("Object created by %d\n",pObject->GetOwnedBy());
} else if (pEntity->GetIsTypeVehicle()){
Displayf("Vehicle created by %d\n",static_cast<const CVehicle*>(pEntity)->PopTypeGet());
} else if (pEntity->GetIsTypePed()){
Displayf("Ped created by %d\n", static_cast<const CPed*>(pEntity)->PopTypeGet());
}
CBaseModelInfo* pMI = pEntity->GetBaseModelInfo();
Assert(pMI);
if (pMI){
Displayf("Name : %s\n",pMI->GetModelName());
Displayf("Type : %d\n",pMI->GetModelType());
}
Displayf ("-<end>-----\n\n");
}
}
#endif
#endif // ENABLE_CDEBUG
#if !__FINAL && TRACK_COLLISION_TYPE_PAIRS
PARAM(dumpcollisionstats, "Enable dumping of physics collision statistics to network drive");
namespace rage {
extern void DumpCollisionTypePairTable(fiStream* stream);
extern void ClearCollisionTypePairTable();
}
void CDebug::DumpCollisionStatsToNetwork(const char* missionName)
{
if (PARAM_dumpcollisionstats.Get())
{
char userName[64];
sysGetEnv("USERNAME",userName,sizeof(userName));
char finalPath[RAGE_MAX_PATH];
formatf(finalPath, "N:\\RSGEDI\\Studio_Shared\\CollisionStats\\%s\\%s-%s-%d",
__DATE__ __TIME__,
userName,
missionName,
TIME.GetFrameCount()
);
// Normalize it -- invalid characters need to go.
char* ptr = finalPath + 2; // We need to skip the first colon.
while (*ptr)
{
if (*ptr == ':' || *ptr == ' ')
{
*ptr = '_';
}
ptr++;
}
ASSET.CreateLeadingPath(finalPath);
fiStream* stream = ASSET.Create(finalPath, "txt", false);
if (stream)
{
DumpCollisionTypePairTable(stream);
ClearCollisionTypePairTable();
stream->Close();
Displayf("Collision statistics have been sent to the network.");
}
else
{
Errorf("ERROR writing the collision statistics file to the network");
}
}
}
#endif // __FINAL
//////////////////////////////////////////////////////////////////////////
#if DEBUG_DISPLAY_BAR
// this function can hold all the debug stuff that gets directly rendered on release builds
// ie player coords, version numbers etc
bank_float s_object_x = 0.16f;
bank_float s_object_y = 0.925f;
bank_float s_object_scale = 1.0f;
bank_float s_shadercount_x = 0.16f;
bank_float s_shadercount_y = 0.905f;
bank_float s_shadercount_scale = 1.0f;
void CDebug::UpdateReleaseInfoToScreen()
{
#if DEBUG_DRAW
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F11, KEYBOARD_MODE_DEBUG))
{
s_renderObjects = !s_renderObjects;
CPostScanDebug::SetPvsStatsEnabled(s_renderObjects || s_renderShaders);
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_F11, KEYBOARD_MODE_DEBUG_SHIFT))
{
s_renderShaders = !s_renderShaders;
CPostScanDebug::SetPvsStatsEnabled(s_renderShaders || s_renderShaders);
}
#endif // DEBUG_DRAW
}
dev_float s_fpsBar_x = 0.6f;
dev_float s_fpsBar_y = 0.892f;
#if RAGE_TIMEBARS
static void SmoothTimer(float &dest,float src) {
const float beta = 1/100.0f;
const float alpha = 1.0f - beta;
if (fabsf(dest - src) > 5.0f)
dest = src;
else
dest = alpha * dest + beta * src;
}
#endif
#if DEBUG_PAD_INPUT
//
// name: CDebug::UpdateDebugScaleformInfo
// description: updates any DEBUG scaleform movies (currently just the debug pad movie)
void CDebug::UpdateDebugScaleformInfo()
{
UpdateDebugPadToScaleform();
}
//
// name: CDebug::RenderDebugScaleformInfo
// description: renders any DEBUG scaleform movies
void CDebug::RenderDebugScaleformInfo()
{
if (CControlMgr::IsDebugPadValuesOn())
{
if (m_iScaleformMovieId != -1 && CScaleformMgr::IsMovieActive(m_iScaleformMovieId))
{
CScaleformMgr::RenderMovie(m_iScaleformMovieId);
}
}
}
//
// name: CDebug::UpdateDebugPadMoviePositions
// description: updates the debug controller movie position - this is called when the safezone changes, so it adjusts accordingly
void CDebug::UpdateDebugPadMoviePositions()
{
if (m_iScaleformMovieId != -1 && CScaleformMgr::IsMovieActive(m_iScaleformMovieId))
{
Vector2 vPos = Vector2( CMiniMap::GetCurrentMiniMapMaskSize().x + m_vPos.x, m_vPos.y);
CScaleformMgr::ChangeMovieParams(m_iScaleformMovieId, CHudTools::CalculateHudPosition(vPos, m_vSize, 'L', 'B'), m_vSize, GFxMovieView::SM_ExactFit);
}
}
//
// name: CDebug::UpdateDebugPadToScaleform
// description: updates the controller button debug movie
void CDebug::UpdateDebugPadToScaleform()
{
if (CControlMgr::IsDebugPadValuesOn())
{
if (m_iScaleformMovieId == -1)
{
Vector2 vPos = Vector2( CMiniMap::GetCurrentMiniMapMaskSize().x + m_vPos.x, m_vPos.y );
m_iScaleformMovieId = CScaleformMgr::CreateMovie("CONTROLLER_TEST", CHudTools::CalculateHudPosition(vPos, m_vSize, 'L', 'B'), m_vSize, false); // fix 1806044 - this needs to persist between sessions
}
else
{
if ( !CPauseMenu::IsActive() )
{
if (CScaleformMgr::IsMovieActive(m_iScaleformMovieId))
{
// call shit on it
CPad *pPad = CControlMgr::GetPlayerPad();
if (pPad)
{
if (pPad->GetLeftShoulder1())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(4);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetLeftShoulder2())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(5);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetRightShoulder1())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(6);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetRightShoulder2())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(7);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetDPadUp())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(8);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetDPadDown())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(9);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetDPadLeft())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(10);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetDPadRight())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(11);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetStart())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(12);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetSelect() ORBIS_ONLY(|| pPad->GetTouchClick()))
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(13);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetButtonSquare())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(14);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetButtonTriangle())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(15);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetButtonCross())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(16);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetButtonCircle())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(17);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetShockButtonL())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(18);
CScaleformMgr::EndMethod();
}
}
if (pPad->GetShockButtonR())
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(19);
CScaleformMgr::EndMethod();
}
}
s32 XAxis = pPad->GetLeftStickX();
s32 YAxis = pPad->GetLeftStickY();
static bool bSentOriginLeft = true;
static bool bSentOriginRight = true;
if (!bSentOriginLeft)
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_ANALOG_STICK_INPUT"))
{
CScaleformMgr::AddParamInt(1);
CScaleformMgr::AddParamInt(XAxis);
CScaleformMgr::AddParamInt(YAxis);
CScaleformMgr::EndMethod();
}
}
if (XAxis == 0 && YAxis == 0)
bSentOriginLeft = true;
else
bSentOriginLeft = false;
XAxis = pPad->GetRightStickX();
YAxis = pPad->GetRightStickY();
if (!bSentOriginRight)
{
if (CScaleformMgr::BeginMethod(m_iScaleformMovieId, SF_BASE_CLASS_GENERIC, "SET_ANALOG_STICK_INPUT"))
{
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamInt(XAxis);
CScaleformMgr::AddParamInt(YAxis);
CScaleformMgr::EndMethod();
}
}
if (XAxis == 0 && YAxis == 0)
bSentOriginRight = true;
else
bSentOriginRight = false;
}
}
}
}
}
else
{
if (m_iScaleformMovieId != -1)
{
if (CScaleformMgr::RequestRemoveMovie(m_iScaleformMovieId))
{
m_iScaleformMovieId = -1;
}
}
}
}
#endif // #if DEBUG_PAD_INPUT
#if DEBUG_FPS
PARAM(fps, "Display frame rate, even in Release builds");
__forceinline static void SmoothFPSTimer (float &dest, float src)
{
const float beta = 1.0f/static_cast<float>(DESIRED_FRAME_RATE);
const float alpha = 1.0f - beta;
if (fabsf(dest - src) > 5.0f)
dest = src;
else
dest = alpha * dest + beta * src;
}
void CDebug::RenderFpsCounter()
{
if ( PARAM_fps.Get() )
{
//GRC_VIEWPORT_AUTO_PUSH_POP();
//grcViewport::SetCurrent(grcViewport::GetDefaultScreen());
grcStateBlock::SetDepthStencilState(grcStateBlock::DSS_IgnoreDepth);
static float fLastFPS = static_cast<float>(DESIRED_FRAME_RATE);
float fFPS = (1.0f / rage::Max(0.001f, fwTimer::GetSystemTimeStep()));
SmoothFPSTimer(fLastFPS, fFPS);
char pTmpBuffer[128];
// Green/Yellow/Red fps reporting based on how good or miserable things are going. Blue if system GPU reservation is enabled on Durango.
const float fRefreshRate = static_cast<float>( grcDevice::GetRefreshRate() );
const float fVSync = static_cast<float>( CSettingsManager::GetInstance().GetSettings().m_video.m_VSync );
const float fTargetFrameTime = (fVSync > 0.0f) && (fRefreshRate > 0.0f) ? (fVSync / fRefreshRate) : (1.0f / DESIRED_FRAME_RATE);
const float fDesiredFrameRate = 1.0f / fTargetFrameTime;
const float fGreenFPSThreshold = fDesiredFrameRate * (fDesiredFrameRate >= 59.0f ? 0.8333f : 0.9f); // 50 or 27 fps
const float fYellowFPSThreshold = DESIRED_FRAME_RATE * (fDesiredFrameRate >= 59.0f ? 0.5f : 0.8333f); // 30 or 20 fps
const Color32 GREEN_FPS_COLOR = Color32(80,255,80);
const Color32 YELLOW_FPS_COLOR = Color32(255,255,80);
const Color32 RED_FPS_COLOR = Color32(255,80,80);
Color32 fpsColor = (fLastFPS >= fGreenFPSThreshold) ? GREEN_FPS_COLOR : ((fLastFPS >= fYellowFPSThreshold) ? YELLOW_FPS_COLOR : RED_FPS_COLOR);
// Blue when GPU reservation is enabled
DURANGO_ONLY( const Color32 BLUE_FPS_COLOR = Color32(64,127,255) );
DURANGO_ONLY( const bool bGPUReserved = grcDevice::GetNuiGPUReservation() );
DURANGO_ONLY( fpsColor = bGPUReserved ? BLUE_FPS_COLOR : fpsColor );
const char* pStrExtraMsg = DURANGO_ONLY( bGPUReserved ? " [GPU RESERVATION]" : ) "";
formatf(pTmpBuffer, "FPS: %04.1f (%4.2fms)%s", fLastFPS, (1.0f/fLastFPS)*1000.0f, pStrExtraMsg);
const float fXPos = DURANGO_ONLY( bGPUReserved ? 0.413f : ) 0.471f;
const float fYPos = RSG_PC ? 0.9425f : 0.885f;
CTextLayout FPSDebugText;
FPSDebugText.SetScale(Vector2(0.1625f, 0.375f));
FPSDebugText.SetColor(fpsColor);
FPSDebugText.SetDropShadow(true);
FPSDebugText.Render(Vector2(fXPos, fYPos), pTmpBuffer);
CText::Flush();
}
}
#endif // DEBUG_FPS
void CDebug::RenderReleaseInfoToScreen()
{
#if __BANK
if (s_renderObjects)
{
const CPostScanDebugSimplePvsStats& stats = CPostScanDebug::GetPvsStats();
int gbufferCount = stats.m_numEntitiesVis_GBUF;
int reflectCount = stats.m_numEntitiesVis_REFLECTIONS;
int shadowCount = stats.m_numEntitiesVis_SHADOWS;
int drawListCount = gbufferCount + shadowCount + reflectCount;
char text[256];
{
formatf(text, "Objects: %d (Shadow-%d, Reflect-%d - TOTAL %d)", gbufferCount, shadowCount, reflectCount, drawListCount, NELEM(text));
}
CTextLayout ReleaseTextLayout;
Vector2 vTextPos = Vector2(s_object_x, s_object_y);
Vector2 vTextSize = Vector2(0.12f, 0.32f);
ReleaseTextLayout.SetScale(&vTextSize);
ReleaseTextLayout.SetColor(Color_white);
ReleaseTextLayout.SetWrap(Vector2(0.0f, 0.96f));
ReleaseTextLayout.SetOrientation(FONT_RIGHT);
ReleaseTextLayout.Render(&vTextPos, text );
}
#endif // __BANK
#if __BANK
if (s_renderShaders)
{
const CPostScanDebugSimplePvsStats& stats = CPostScanDebug::GetPvsStats();
int totalShaderCount = stats.m_numShadersInPvs_TOTAL;
int gbufShaderCount = stats.m_numShadersVis_GBUF;
int fwdAlphaShaderCount = stats.m_numShadersVis_ALPHA;
int selectedShaderCount = stats.m_numShadersInPvs_SELECTED;
char text[256];
fwEntity* pEntity = g_PickerManager.GetSelectedEntity();
if (pEntity)
{
u32 gbuf = s_renderPhaseData[1].drawCalls + s_renderPhaseData[1].skinnedDrawCalls;
u32 gbufSel = s_renderPhaseData[1].entityDrawCalls;
u32 drawScene = s_renderPhaseData[0].drawCalls + s_renderPhaseData[0].skinnedDrawCalls;
u32 drawSceneSel = s_renderPhaseData[0].entityDrawCalls;
u32 shadows = s_renderPhaseData[2].drawCalls + s_renderPhaseData[2].skinnedDrawCalls;
u32 shadowsSel = s_renderPhaseData[2].entityDrawCalls;
formatf(text, "Drawcalls(selected): (Gbuf-%4d(%4d), DrawScene-%4d(%4d), Shadows-%4d(%4d) - TOTAL %4d (G-%d, F-%d, S-%d - T %d)",
gbuf, gbufSel, drawScene, drawSceneSel, shadows, shadowsSel, s_renderPhaseData[0].totalDrawCalls,
gbufShaderCount, fwdAlphaShaderCount, selectedShaderCount, totalShaderCount, NELEM(text));
}
else
{
u32 gbuf = s_renderPhaseData[1].drawCalls + s_renderPhaseData[1].skinnedDrawCalls;
u32 drawScene = s_renderPhaseData[0].drawCalls + s_renderPhaseData[0].skinnedDrawCalls;
u32 shadows = s_renderPhaseData[2].drawCalls + s_renderPhaseData[2].skinnedDrawCalls;
formatf(text, "Drawcalls: (Gbuf-%4d, DrawScene-%4d, Shadows-%4d - TOTAL %4d (%d %d %d)",
gbuf, drawScene, shadows, s_renderPhaseData[0].totalDrawCalls,
gbufShaderCount, fwdAlphaShaderCount, totalShaderCount, NELEM(text));
}
CTextLayout ReleaseTextLayout;
Vector2 vTextPos = Vector2(s_shadercount_x, s_shadercount_y);
Vector2 vTextSize = Vector2(0.12f, 0.32f);
ReleaseTextLayout.SetScale(&vTextSize);
ReleaseTextLayout.SetColor(Color_white);
ReleaseTextLayout.SetWrap(Vector2(0.0f, 0.96f));
ReleaseTextLayout.SetOrientation(FONT_RIGHT);
ReleaseTextLayout.Render(&vTextPos, text );
}
#endif // __BANK
#if !__FINAL
if(CStreaming::IsStreamingPaused() && !g_render_lock)
{
CTextLayout StreamingDebugText;
StreamingDebugText.SetScale(Vector2(0.5f, 1.0f));
StreamingDebugText.SetBackground(TRUE);
StreamingDebugText.SetBackgroundColor(CRGBA(0,0,0,128));
StreamingDebugText.SetColor(CRGBA(225,80,80,255));
StreamingDebugText.Render(Vector2(0.65f, 0.8f), "Streaming Paused");
CText::Flush();
}
#if __ASSERT
if (SceneGeometryCapture::IsCapturingPanorama() ||
LightProbe::IsCapturingPanorama())
{
// don't display nopopups message if we're capturing panorama
}
#if __BANK
else if (CFrameDump::IsCapturing())
{
// don't display nopopups message if we're capturing cutscenes
}
#endif // __BANK
else
{
const char* msg = GetNoPopupsMessage(false);
if (msg)
{
CTextLayout PopupDebugText;
PopupDebugText.SetScale(Vector2(0.5f, 1.0f));
PopupDebugText.SetColor(CRGBA(173,255,47,255));
PopupDebugText.Render(Vector2(0.55f, 0.75f), msg);
CText::Flush();
}
#if GTA_REPLAY
msg = CReplayControl::GetRecordingDisabledMessage();
if (msg)
{
CTextLayout replayDebugText;
replayDebugText.SetScale(Vector2(0.5f, 1.0f));
replayDebugText.SetColor(CRGBA(255,0,0,255));
replayDebugText.Render(Vector2(0.002f, 0.87f), msg);
CText::Flush();
}
#endif // __GTA_REPLAY
}
#endif // __ASSERT
#if BUGSTAR_INTEGRATION_ACTIVE
char const* streamingVideoMessage = CBugstarIntegration::GetStreamingVideoMessage();
if (streamingVideoMessage != nullptr)
{
CTextLayout debugText;
debugText.SetScale(Vector2(0.5f, 1.0f));
debugText.SetColor(CRGBA(0xff, 0x00, 0x00, 0xa0));
debugText.Render(Vector2(0.025f, 0.025f), streamingVideoMessage);
CText::Flush();
}
#endif // BUGSTAR_INTEGRATION_ACTIVE
#if LIVE_STREAMING
if(strStreamingEngine::GetLive().GetPatched())
{
CTextLayout StreamingDebugText;
StreamingDebugText.SetScale(Vector2(0.5f, 1.0f));
StreamingDebugText.SetColor(CRGBA(225,80,80,255));
StreamingDebugText.Render(g_previewCoords, "Preview");
CText::Flush();
}
#endif // LIVE_STREAMING
#if __BANK || __TOOL
if ( g_bDisplayTimescale && fwTimer::GetDebugTimeScale() < 1.0f)
{
CTextLayout TimerDebugText;
TimerDebugText.SetScale(Vector2(0.25f, 0.5f));
TimerDebugText.SetColor(CRGBA(212,255,33,255));
char timerText[32];
sprintf(timerText, "Timescale : %f", fwTimer::GetDebugTimeScale());
TimerDebugText.Render(Vector2(0.55f, 0.25f), timerText);
CText::Flush();
}
if(CutfileNonParseData::m_FileTuningFlags.GetAllFlags() > 0 )
{
Vector2 vTuningCoords(0.7f, 0.85f);
CTextLayout StreamingDebugText;
StreamingDebugText.SetScale(Vector2(0.5f, 1.0f));
StreamingDebugText.SetColor(CRGBA(225,80,80,255));
StreamingDebugText.Render(vTuningCoords, "Tuning");
CText::Flush();
}
#endif // __BANK || __TOOL
#if (RAGE_TRACKING || STREAMING_VISUALIZE)
char textBuffer[64];
u32 displayFlags = 0;
enum
{
MEMVIS = 1,
STREAMVIS
};
#if RAGE_TRACKING
if( diagTracker::GetCurrent() )
{
displayFlags |= MEMVIS;
}
#endif // RAGE_TRACKING
#if STREAMING_VISUALIZE
if(strStreamingVisualize::IsInstantiated())
{
displayFlags |= STREAMVIS;
}
#endif
if( displayFlags == (MEMVIS + STREAMVIS) )
{
formatf(textBuffer, "Mem+Streaming Visualize", NELEM(textBuffer));
}
else if( displayFlags == MEMVIS )
{
formatf(textBuffer, "Mem Visualize", NELEM(textBuffer));
}
else if(displayFlags == STREAMVIS )
{
formatf(textBuffer, "Streaming Visualize", NELEM(textBuffer));
}
if( displayFlags != 0 )
{
if (strStreamingAllocator::GetSloshState())
{
CTextLayout StreamingDebugText;
StreamingDebugText.SetScale(Vector2(0.5f, 1.0f));
StreamingDebugText.SetColor(CRGBA(225,80,80,255));
StreamingDebugText.Render(Vector2(0.55f, 0.70f), "Mem Slosh" );
CText::Flush();
}
CTextLayout StreamingVisualiseDebugText;
StreamingVisualiseDebugText.SetScale(Vector2(0.5f, 1.0f));
StreamingVisualiseDebugText.SetColor(CRGBA(0,212,135,255));
StreamingVisualiseDebugText.Render(Vector2(0.55f, 0.75f), textBuffer );
CText::Flush();
}
#endif // (RAGE_TRACKING || STREAMING_VISUALIZE)
#if RAGE_TIMEBARS
bool bDisplayTimers = gDisplayTimerBars;
if (bDisplayTimers)
{
CTextLayout StreamingDebugText;
StreamingDebugText.SetScale(Vector2(0.2f, 0.3f));
StreamingDebugText.SetBackground(TRUE);
StreamingDebugText.SetBackgroundColor(CRGBA(0,0,0,128));
float fFps = 1.0f / rage::Max(0.001f, fwTimer::GetSystemTimeStep());
const float fSignificantAmountOfTime = 2.0f;
static Vector2 vPos(0.05f, 0.88f);
vPos.x = s_fpsBar_x;
vPos.y = s_fpsBar_y;
static float fLastFPS = 30.0f;
static float fWaitForMain = 0.0f;
static float fWaitForRender = 0.0f;
static float fWaitForGPU = 0.0f;
static float fEndDraw = 0.0f;
static float fWaitForDrawSpu = 0.0f;
static float fFifoStallTimeSpu = 0.0f;
const char astrBound[][32] = { "Update", "Render Thread", "GPU", "GPU Flip", "GPU DrawableSpu", "GPU Bubble" };
const char* pszLimiter = NULL;
if (gSmoothPerformanceResults)
{
float totalWaitForMain = sm_fWaitForMain + sm_fDrawlistQPop;
SmoothTimer(fLastFPS, fFps);
SmoothTimer(fWaitForMain, totalWaitForMain);
SmoothTimer(fWaitForRender,sm_fWaitForRender);
SmoothTimer(fWaitForGPU, sm_fWaitForGPU);
SmoothTimer(fEndDraw, sm_fEndDraw);
SmoothTimer(fWaitForDrawSpu, sm_fWaitForDrawSpu);
SmoothTimer(fFifoStallTimeSpu, sm_fFifoStallTimeSpu);
}
else
{
fLastFPS = fFps;
fWaitForMain = sm_fWaitForMain + sm_fDrawlistQPop;
fWaitForRender = sm_fWaitForRender;
fWaitForGPU = sm_fWaitForGPU;
fEndDraw = sm_fEndDraw;
fWaitForDrawSpu = sm_fWaitForDrawSpu;
fFifoStallTimeSpu = sm_fFifoStallTimeSpu;
}
// fWaitForMain also contains GPU time...
fWaitForMain -= Max(fWaitForGPU,fWaitForDrawSpu,fFifoStallTimeSpu);
fWaitForMain = Max(fWaitForMain,0.0f);
#if __D3D11 || RSG_ORBIS
// If fEndDraw (time spent inside Present()) isn't significant enough, ensure we ignore it.
if (fEndDraw < fSignificantAmountOfTime || !PARAM_enableBoundByGPUFlip.Get())
fEndDraw = 0.0f;
fEndDraw = (fEndDraw > fSignificantAmountOfTime) ? fEndDraw : 0.0f;
float fBoundTime = Max(fWaitForMain,fWaitForRender,fWaitForGPU,fEndDraw);
int maxIndex = MaximumIndex(fWaitForMain,fWaitForRender,fWaitForGPU,fEndDraw);
pszLimiter = &astrBound[maxIndex][0];
#else
float fBoundTime = Max(fWaitForGPU,fEndDraw,fWaitForDrawSpu,fFifoStallTimeSpu);;
if (fWaitForRender < fWaitForMain)
{ // Bound by main thread
pszLimiter = &astrBound[0][0];
fBoundTime = fWaitForMain;
}
else
{
if (Max(fEndDraw,fWaitForDrawSpu,fFifoStallTimeSpu) > fSignificantAmountOfTime)
{ // GPU, Gpu flip, other bound
int index = MaximumIndex(fWaitForGPU,fEndDraw,fWaitForDrawSpu,fFifoStallTimeSpu);
pszLimiter = &astrBound[index+2][0];
}
else
{ // Render thread bound
pszLimiter = &astrBound[1][0];
fBoundTime = fWaitForRender;
}
}
#endif // __D3D11 || RSG_ORBIS
const float fDesiredFrameRate = DESIRED_FRAME_RATE - 1;
Color32 col = Color32(80,255,80);
if (fLastFPS >= fDesiredFrameRate)
{
col = Color32(80,255,80);
}
else
{
col = Color32(255,80,80); StreamingDebugText.SetColor(CRGBA(255,80,80,255));
}
#if DEBUG_DRAW
if ( gDisplayTimerBars )
{
char buffer[128];
#if __D3D11 || RSG_ORBIS
formatf(buffer,"FPS: %04.1f (%4.2fms) Bound %04.2f ms by %s", fLastFPS, (1.0f/fLastFPS)*1000.0f, fBoundTime, pszLimiter, NELEM(buffer));
#else
formatf(buffer,"FPS: %04.1f Bound %04.2f ms by %s", fLastFPS, fBoundTime, pszLimiter, NELEM(buffer));
#endif // __WIN32PC
grcDebugDraw::TextFontPush(grcSetup::GetFixedWidthFont());
grcDebugDraw::Text(vPos, Color_white, buffer, true, 1.0f, 1.0f);
grcDebugDraw::Text(vPos, col, buffer, false, 1.0f, 1.0f);
float fYInc = ((float)grcSetup::GetFixedWidthFont()->GetHeight()/grcDevice::GetHeight())*1.25f;
vPos += Vector2(0.0f, fYInc);
formatf(buffer,"Wait for main Thread %4.2fms",fWaitForMain);
grcDebugDraw::Text(vPos, Color_white, buffer, true, 1.0f, 1.0f);
vPos += Vector2(0.0f,fYInc);
formatf(buffer,"Wait for render thread %4.2fms",fWaitForRender);
grcDebugDraw::Text(vPos, Color_white, buffer, true, 1.0f, 1.0f);
vPos += Vector2(0.0f,fYInc);
formatf(buffer,"Wait for GPU %4.2fms",fWaitForGPU);
grcDebugDraw::Text(vPos, Color_white, buffer, true, 1.0f, 1.0f);
grcDebugDraw::TextFontPop();
}
#else
(void)fBoundTime;
#endif
}
#endif
#endif //!__FINAL
}
#endif // DEBUG_DISPLAY_BAR
//////////////////////////////////////////////////////////////////////////
#if DEBUG_SCREENSHOTS
static bool g_bRequestTakeScreenShot = false;
static bool g_bScreenshotPNG = false;
static bool g_bNextScreenshotPNG = false;
PARAM(screenshotpng,"Take screenshots in PNG format instead of JPG");
static void TakeScreenShot()
{
if (!g_bRequestTakeScreenShot)
return;
g_bRequestTakeScreenShot = false;
if (PARAM_screenshotpng.Get() || g_bNextScreenshotPNG)
{
Displayf("Taking screenshot in PNG format");
CSystem::GetRageSetup()->TakeScreenShotPNG();
}
else
{
Displayf("Taking screenshot in JPG format");
CSystem::GetRageSetup()->TakeScreenShotJPG();
}
g_bNextScreenshotPNG = g_bScreenshotPNG;
}
void CDebug::HandleScreenShotRequests()
{
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SYSRQ, KEYBOARD_MODE_DEBUG, "{Take Screenshot") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SNAPSHOT, KEYBOARD_MODE_DEBUG, "{Take Screenshot") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SYSRQ, KEYBOARD_MODE_MARKETING, "Take screenshot") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SNAPSHOT, KEYBOARD_MODE_MARKETING, "Take screenshot"))
{
g_bRequestTakeScreenShot = true;
g_bNextScreenshotPNG = g_bScreenshotPNG;
}
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SYSRQ, KEYBOARD_MODE_DEBUG_SHIFT, "Take screenshot") ||
CControlMgr::GetKeyboard().GetKeyJustDown(KEY_SNAPSHOT, KEYBOARD_MODE_DEBUG_SHIFT, "Take screenshot"))
{
g_bRequestTakeScreenShot = true;
g_bNextScreenshotPNG = true;
}
// Request the screen shot from the main thread, it'll still get handled from the render thread appropriately.
// Also when done this way, we can query for the screen shot location from the Update thread where it won't crash the game.
TakeScreenShot();
}
void CDebug::RequestTakeScreenShot(bool bPng /*= false*/){
g_bRequestTakeScreenShot = true;
g_bNextScreenshotPNG = bPng;
}
//////////////////////////////////////////////////////////////////////////
#endif // DEBUG_SCREENSHOTS
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#if DEBUG_BANK
//////////////////////////////////////////////////////////////////////////
void ForceCrash(void)
{
__builtin_trap();
}
static char gCurrentWarpPosition[256];
static float gWarpStreamingRadius = 600.0f;
void WarpPlayer(void)
{
Vector3 vecPos(VEC3_ZERO);
Vector3 vecVel(VEC3_ZERO);
Vector3 vecCamPos(VEC3_ZERO);
Vector3 vecCamFront(VEC3_ZERO);
float hour = 0, minute = 0;
float fHeading = 0.0f;
// Try to parse the line.
int nItems = 0;
{
// Make a copy of this string as strtok will destroy it.
Assertf( (strlen(gCurrentWarpPosition) < 256), "Warp position line is too long to copy.");
char warpPositionLine[256];
strncpy(warpPositionLine, gCurrentWarpPosition, 256);
// Get the locations to store the float values into.
float* apVals[15] = {
&vecPos.x, &vecPos.y, &vecPos.z, // 3
&fHeading, // 4
&vecVel.x, &vecVel.y, &vecVel.z, // 7
&vecCamPos.x, &vecCamPos.y, &vecCamPos.z, // 10
&vecCamFront.x, &vecCamFront.y, &vecCamFront.z, // 13
&hour, &minute // 15
};
// Parse the line.
char* pToken = NULL;
const char* seps = " ,\t";
pToken = strtok(warpPositionLine, seps);
while(pToken)
{
// Try to read the token as a float.
int success = sscanf(pToken, "%f", apVals[nItems]);
Assertf(success, "Unrecognized token '%s' in warp position line.",pToken);
if(success)
{
++nItems;
Assertf((nItems < 16), "Too many tokens in warp position line." );
}
pToken = strtok(NULL, seps);
}
}
// If we were only provided with 2 items (x, y), determine the z coord
if (nItems == 2)
{
float fTest = CGameWorldHeightMap::GetMaxHeightFromWorldHeightMap(vecPos.x, vecPos.y);
vecPos.z = fTest;
CPhysics::LoadAboutPosition(RCC_VEC3V(vecPos));
g_SceneStreamerMgr.LoadScene(vecPos);
gRenderListGroup.Clear(); // clear any renderlists as this stuff probably has deleted entities that they are pointing to!
bool bFoundPosition = false;
float fGround = WorldProbe::FindGroundZFor3DCoord(TOP_SURFACE, vecPos.x, vecPos.y, 1000.0f, &bFoundPosition);
if(bFoundPosition)
{
vecPos.z = fGround;
}
FindPlayerPed()->Teleport(vecPos, 0.0f);
}
else if(nItems)
{
// Prevent double presses coming through from RAG (B*970723)
if( CWarpManager::IsActive() )
{
// Early out, warp is already going
return;
}
bool success = CWarpManager::SetWarp(vecPos, vecVel, fHeading, true, true, gWarpStreamingRadius);
if( success )
{
// B*1391089
CWarpManager::SetNoLoadScene();
CPed *pPlayerPed = FindPlayerPed();
if( pPlayerPed )
{
Vector3 pedPos = VEC3V_TO_VECTOR3(pPlayerPed->GetTransform().GetPosition());
float d2 = (vecPos - pedPos).Mag2();
if(d2 < (500.0f*500.0f))
{
CWarpManager::FadeOutAtStart(false);
CWarpManager::FadeInWhenComplete(false);
}
}
// Some error checking, was originally assumed that B* wouldn't send fields that don't exist, but it does, and init's them to zero! ARRRGGGHHHH!!!
// B*1041052
// Plan: 1.. Check if forward is all zeros, if it is, skip both camera and time of day.
// 2.. If forward isn't all zero's, normalise
bool setCamForward = true;
if(nItems >= 13)
{
float forwardLength = vecCamFront.Mag();
if( forwardLength <= 0.1f )
{
// Assmune zero
setCamForward = false;
}
else
{
vecCamFront.Normalize();
}
if( setCamForward )
{
// We must have had a camera pos and orientation
CWarpManager::SetPostWarpCameraPos(vecCamPos, vecCamFront);
}
}
if(nItems >= 15 && setCamForward)
{
// We must have had a time in hours/minutes
CWarpManager::SetPostWarpTimeOfDay((s32)hour,(s32)minute);
}
}
}
}
static char gFindEntityPointer[11];
void FindEntityFromPointer()
{
if (strlen(gFindEntityPointer) < 10 || gFindEntityPointer[0] != '0' || gFindEntityPointer[1] != 'x')
return;
size_t ptrVal = strtoul(&gFindEntityPointer[2], NULL, 16);
CEntity* ent = (CEntity*)ptrVal;
// try our best not to crash
if (!sysMemAllocator::GetMaster().IsValidPointer(ent) && !sysMemAllocator::GetCurrent().IsValidPointer(ent) && !strStreamingEngine::GetAllocator().IsValidPointer(ent))
return;
if (ent->GetType() < 0 || ent->GetType() >= ENTITY_TYPE_TOTAL)
return;
if (!ent->IsArchetypeSet())
return;
grcDebugDraw::SetDoDebugZTest(false);
grcDebugDraw::Sphere(ent->GetTransform().GetPosition(), ent->GetBoundSphere().GetRadiusf(), Color_GreenYellow, false);
}
#if ENABLE_CDEBUG
namespace object_commands{float CommandGetObjectFragmentDamageHealth(int ObjectIndex, bool bHealthPercentageByMass);};
void DebugLastObject(void)
{
if(gpDisplayObject)
{
int nObjectIndex = CTheScripts::GetGUIDFromEntity(*((CEntity*)gpDisplayObject.Get()));
static bool TEST_OBJECT_FRAGMENT_STATE_BYMASS = false;
float fResult = object_commands::CommandGetObjectFragmentDamageHealth(nObjectIndex, TEST_OBJECT_FRAGMENT_STATE_BYMASS);
formatf(gCurrentWarpPosition, "%f", fResult, NELEM(gCurrentWarpPosition));
}
}
#endif // ENABLE_CDEBUG
#define DISPLAY_OBJECTS_FILENAME "common:/data/displayobjects.txt"
const static int MAX_DISPLAY_OBJECTS = 128;
void LoadDisplayObjectsList()
{
for (int i = 1; i < gCurrentDisplayObjectCount; ++i)
{
delete [] gCurrentDisplayObjectList[i];
}
gCurrentDisplayObjectCount = 1;
if (!gCurrentDisplayObjectList)
{
gCurrentDisplayObjectList = rage_new char*[MAX_DISPLAY_OBJECTS];
gCurrentDisplayObjectList[0] = rage_new char[1];
gCurrentDisplayObjectList[0][0] = '\0';
}
CFileMgr::SetDir("");
FileHandle fid = INVALID_FILE_HANDLE;
if (ASSET.Exists(DISPLAY_OBJECTS_FILENAME, ""))
{
fid = CFileMgr::OpenFile(DISPLAY_OBJECTS_FILENAME);
}
if (CFileMgr::IsValidFileHandle(fid))
{
int iNumObjects = 1;
char* pLine;
while( ((pLine = CFileMgr::ReadLine(fid)) != NULL) )
{
if( *pLine != 0 )
{
if (!Verifyf(iNumObjects < MAX_DISPLAY_OBJECTS, "Too may objects in " DISPLAY_OBJECTS_FILENAME))
{
break;
}
size_t iLength = strlen(pLine);
gCurrentDisplayObjectList[iNumObjects] = rage_new char[iLength + 1];
strncpy(gCurrentDisplayObjectList[iNumObjects], pLine, iLength);
gCurrentDisplayObjectList[iNumObjects][iLength] = '\0';
++iNumObjects;
}
}
gCurrentDisplayObjectCount = iNumObjects;
CFileMgr::CloseFile(fid);
}
}
void ReloadDisplayObjectsList()
{
// Reload the list - this call will automatically free up the previous one.
LoadDisplayObjectsList();
// If the list got shorter, make sure we don't point to an invalid entry.
gCurrentDisplayObjectIndex = Min(gCurrentDisplayObjectIndex, gCurrentDisplayObjectCount-1);
// Update RAG.
gDisplayObjectListCombo->UpdateCombo("Display Object List", &gCurrentDisplayObjectIndex, gCurrentDisplayObjectCount, (const char**)gCurrentDisplayObjectList, &SelectDisplayObject);
}
void SaveDisplayObjectList()
{
CFileMgr::SetDir("");
FileHandle fid = CFileMgr::OpenFileForWriting(DISPLAY_OBJECTS_FILENAME);
if (CFileMgr::IsValidFileHandle(fid))
{
for (int i = 1; i < gCurrentDisplayObjectCount; ++i)
{
CFileMgr::Write(fid, gCurrentDisplayObjectList[i], istrlen(gCurrentDisplayObjectList[i]));
CFileMgr::Write(fid, "\n", istrlen("\n"));
}
CFileMgr::CloseFile(fid);
}
}
void AddObjectToList()
{
if (!Verifyf(gCurrentDisplayObjectCount < MAX_DISPLAY_OBJECTS, "Display object list full (increase MAX_DISPLAY_OBJECTS)"))
{
return;
}
for (int i = 1; i < gCurrentDisplayObjectCount; ++i)
{
if (!stricmp(gCurrentDisplayObjectList[i], gCurrentDisplayObject))
{
// Already in the list
return;
}
}
size_t iLength = strlen(gCurrentDisplayObject);
char* newObject = rage_new char[iLength + 1];
gCurrentDisplayObjectList[gCurrentDisplayObjectCount++] = newObject;
strncpy(newObject, gCurrentDisplayObject, iLength);
newObject[iLength] = '\0';
SaveDisplayObjectList();
gDisplayObjectListCombo->UpdateCombo("Display Object List", &gCurrentDisplayObjectIndex, gCurrentDisplayObjectCount, (const char**)gCurrentDisplayObjectList, &SelectDisplayObject);
gCurrentDisplayObjectIndex = gCurrentDisplayObjectCount - 1;
}
void RemoveObjectFromList()
{
if (gCurrentDisplayObjectIndex < 1 || gCurrentDisplayObjectIndex >= gCurrentDisplayObjectCount)
{
// Not removable
return;
}
delete [] gCurrentDisplayObjectList[gCurrentDisplayObjectIndex];
// Determine the new size of the list
--gCurrentDisplayObjectCount;
// Copy the rest down
for (int i = gCurrentDisplayObjectIndex; i < gCurrentDisplayObjectCount; ++i)
{
gCurrentDisplayObjectList[i] = gCurrentDisplayObjectList[i + 1];
}
SaveDisplayObjectList();
gDisplayObjectListCombo->UpdateCombo("Display Object List", &gCurrentDisplayObjectIndex, gCurrentDisplayObjectCount, (const char**)gCurrentDisplayObjectList, &SelectDisplayObject);
strncpy(gCurrentDisplayObject, gCurrentDisplayObjectList[gCurrentDisplayObjectIndex], sizeof(gCurrentDisplayObject));
}
#if DEBUG_BANK
PARAM(displayobject, "[debug] Display object name");
#endif // DEBUG_BANK
void UpdateStrModelRequest()
{
if(gStreamModelReq.HasLoaded())
{
DeleteObject(); // destroy the debug object if it is streamed - just in case gStreamModelReq was holding the archetype in memory
gCurrentDisplayObject[0] = '\0';
}
gStreamModelReq.Release();
gStreamModelReq.Request(gStreamModelName, STRFLAG_PRIORITY_LOAD|STRFLAG_FORCE_LOAD|STRFLAG_DONTDELETE);
while(gStreamModelReq.IsValid() && !gStreamModelReq.HasLoaded())
{
CStreaming::LoadAllRequestedObjects();
}
}
void InitLiveEditWidgets()
{
s_LiveEditBank = &BANKMGR.CreateBank("_LiveEdit_");
// Add bugstar section to live edit bank
s_LiveEditBank->PushGroup("Bugstar", false);
s_LiveEditBank->AddText("Warp Player x y z h vx vy vz", gCurrentWarpPosition, sizeof(gCurrentWarpPosition), false, &WarpPlayer);
s_LiveEditBank->AddButton("Warp now", WarpPlayer);
CBugstarIntegration::InitLiveEditWidgets(*s_LiveEditBank);
s_LiveEditBank->PopGroup();
#if __DEV
// Add MoVE network preview section to live edit bank
CAnimViewer::AddNetworkPreviewLiveEditWidgets(s_LiveEditBank);
#endif // __DEV
Assert(CDebug::GetLiveEditBank());
#if PLANTSMGR_DATA_EDITOR
gPlantMgrEditor.InitWidgets(*CDebug::GetLiveEditBank(), "PlantsMgr Data Edit");
#endif
}
static void TakeScreenshotCB()
{
CDebug::RequestTakeScreenShot(g_bScreenshotPNG);
}
static void SimulateReadError()
{
if(fiDevice::sm_FatalReadError)
{
fiDevice::sm_FatalReadError();
}
}
void CDebug::InitWidgets()
{
#if DEBUG_BANK
bkBank& bank = BANKMGR.CreateBank("Debug");
#if RSG_DURANGO && __BANK
bank.AddToggle("Show Timer Comparison", &s_showDebugTimeInfo);
#endif
gDrawListMgr->SetupWidgets(bank);
bank.AddButton("Reload Shaders", CDrawListMgr::RequestShaderReload);
#if ENABLE_FPS_CAPTURE
// EJ: FPS Capture
bank.AddSlider("Captures", &g_fMaxCaptures, 100.0f, 1000.0f, 1.0f);
bank.AddButton("Start Capture FPS", &StartFPSCapture);
#endif
#if DEBUG_SCREENSHOTS
bank.AddButton("Screen shot", TakeScreenshotCB);
bank.AddToggle("PNG Format", &g_bScreenshotPNG);
#endif // DEBUG_SCREENSHOTS
bank.AddButton("Crash now...", ForceCrash);
bank.AddText("Warp Player x y z h vx vy vz", gCurrentWarpPosition, sizeof(gCurrentWarpPosition), false, &WarpPlayer);
bank.AddSlider("Warp Player Range", &gWarpStreamingRadius, 10.0f, 5000.0f, 1.0f);
bank.AddButton("Warp now", WarpPlayer);
bank.AddSlider("Debug fontscale", &sm_dbgFontscale, 0.1f, 5.0f, 0.1f);
bank.AddToggle("Display timescale", &g_bDisplayTimescale);
bank.AddText("Find entity from pointer", gFindEntityPointer, sizeof(gFindEntityPointer), false, &FindEntityFromPointer);
// bank.PushGroup("TEMP - Vehicle.rpf test");
// bank.AddButton("Switch to SP vehicles", datCallback(SwitchToSPVehicles));
// bank.AddButton("Switch to MP vehicles", datCallback(SwitchToMPVehicles));
// bank.PopGroup();
#if RSG_DURANGO
bank.PushGroup("Light Sensor");
{
bank.AddToggle("Display Light Sensor Square", &sm_bDisplayLightSensorQuad);
}
bank.PopGroup();
#endif
#if(BUGSTAR_INTEGRATION_ACTIVE)
bank.PushGroup("Bugstar");
CBugstarIntegration::InitWidgets(bank);
bank.PushGroup("Add bug");
bank.AddButton("Add bug", RequestAddBug);
bank.AddText("Summary", gBugstarSummary, sizeof(gBugstarSummary));
bank.AddCombo("Class", &gBugstarClass, 7, gBugstarClassCombo);
bank.AddText("Owner", gBugstarOwner, sizeof(gBugstarOwner));
bank.AddSlider("Jump to Bug Number Coords", &CDebug::m_iBugNumber, -1, 299999, 1, &CDebug::JumpToBugCoords);
bank.AddToggle("Include Selected Ped Variation Info", &gBugstarPedVariationInfo);
gBugstarPedVariationInfo = PARAM_bugstardescpedvar.Get();
bank.PopGroup();
bank.PopGroup();
#endif //(BUGSTAR_INTEGRATION_ACTIVE)
#if ENABLE_CDEBUG
grcDebugDraw::AddWidgets(bank);
bank.PushGroup("Start-up");
bank.AddButton("Dump startup params", CFA(CDebug::DumpDebugParams));
bank.PopGroup();
ms_locationList.Init(&bank);
bank.AddButton("Dump ped and vehicle memory data", datCallback(CFA(COverviewScreenManager::DumpPedAndVehicleData)));
#if ENABLE_STATS_CAPTURE
MetricsCapture::SetLocationList(&ms_locationList);
MetricsCapture::AddWidgets(bank);
#endif // ENABLE_STATS_CAPTURE
#if __BANK
CInteriorProxy::AddWidgets(bank);
C2dEffectDebugRenderer::InitWidgets(bank);
CMPObjectUsage::AddWidgets(bank);
#endif //__BANK
LoadDisplayObjectsList();
gDisplayObjectListCombo = bank.AddCombo("Display Object List", &gCurrentDisplayObjectIndex, gCurrentDisplayObjectCount, (const char**)gCurrentDisplayObjectList, &SelectDisplayObject);
bank.AddButton("Reload Display Object List", datCallback(ReloadDisplayObjectsList));
bank.AddToggle("Display timer bars", &gDisplayTimerBars);
bank.AddToggle("Smooth Performance Limiting Results", &gSmoothPerformanceResults);
#if RSG_ORBIS
bank.AddButton("Start GPU trace capture", datCallback(CFA(CSystem::StartGPUTraceCapture)));
#endif // RSG_ORBIS
if (PARAM_displayobject.Get())
{
const char* displayobject = NULL;
PARAM_displayobject.Get(displayobject);
strcpy(gCurrentDisplayObject, displayobject);
}
bank.AddButton("Populate packfile source list", datCallback(CFA(CDebug::PopulatePackfileSourceCombo)));
gPackfileSourceCombo = bank.AddCombo("Packfile source for object", &gPackfileSource, 1, gPackfileSourceDummyList, NullCB);
gObjectToCreateCombo = bank.AddCombo("Object to create", &gObjectToCreateIndex, 1, gObjectToCreateDummyList, NullCB);
bank.AddText("strModelRequest test", gStreamModelName, sizeof(gStreamModelName), false, &UpdateStrModelRequest);
bank.AddText("Display Object", gCurrentDisplayObject, sizeof(gCurrentDisplayObject), false, &DisplayObjectDeleteOld);
bank.AddSlider("Legion count X", &gLegionCountX, 1, 100, 1);
bank.AddSlider("Legion count Y", &gLegionCountY, 1, 100, 1);
bank.AddSlider("Legion spacing", &gLegionSpacing, 0.f, 10.f, 0.1f);
bank.AddButton("Display legion", DisplayLegionObject);
bank.AddButton("Delete legion", DeleteLegion);
bank.AddButton("Add object to list",AddObjectToList);
bank.AddButton("Remove object from list",RemoveObjectFromList);
bank.AddSeparator();
bank.AddButton("Display Object Again", &DisplayObjectKeepOld);
bank.AddButton("Display and place on ground", &DisplayObjectAndPlaceOnGround);
bank.AddButton("Delete Last Object", &DeleteObject);
bank.AddButton("Debug Last Object", DebugLastObject);
bank.AddButton("Place last object on ground",PlaceLastObjectOnGround);
bank.AddButton("Repair last object",RepairLastObject);
bank.AddButton("Frag tune last object",FragTuneLastObject);
bank.AddToggle("Activate Display Object", &gActivateDisplayObject);
bank.AddToggle("Cache tuned frag object",&gCacheTunedFragObject);
bank.AddToggle("Display Safe Zone", &gDisplaySafeZone, &DisplaySafeZone);
//bank.AddSlider("Simulate Read Error", &fiDevice::sm_InjectReadError, 0, 1, 1);
bank.AddButton("Simulate Read Error", SimulateReadError );
#if __XENON
bank.AddToggle("Trace update thread", &sm_bTraceUpdateThread);
bank.AddToggle("Trace render thread", &sm_bTraceRenderThread);
#endif // __XENON
#if __DEV
bank.AddToggle("2dEffect stats", &C2dEffect::m_PrintStats);
bank.AddToggle("Allow Display of Vector Map", &CVectorMap::m_bAllowDisplayOfMap);
#endif // __DEV
bank.AddToggle("Display Map Zone", &gDisplayMapZone);
bank.AddToggle("Display network spawn nodes", &gDisplaySpawnNodes);
bank.AddButton("Dump hashed strings", CFA(atHashStringNamespaceSupport::SaveAllHashStrings));
CDebugScene::AddWidgets(bank);
bank.PushGroup("Measuring Tool",false);
bank.AddToggle( "Turn on tool", &CPhysics::ms_bDebugMeasuringTool );
bank.AddText("Pos1", CPhysics::ms_Pos1, sizeof(CPhysics::ms_Pos1), false, datCallback(CFA1(CPhysics::UpdateDebugPositionOne)));
bank.AddText("Ptr1", CPhysics::ms_Ptr1, sizeof(CPhysics::ms_Ptr1), false);
bank.AddText("Pos2", CPhysics::ms_Pos2, sizeof(CPhysics::ms_Pos2), false, datCallback(CFA1(CPhysics::UpdateDebugPositionTwo)));
bank.AddText("Ptr2", CPhysics::ms_Ptr2, sizeof(CPhysics::ms_Ptr2), false);
bank.AddText("Diff", CPhysics::ms_Diff, sizeof(CPhysics::ms_Diff), false);
bank.AddText("HeadingBetween (Radians)", CPhysics::ms_HeadingDiffRadians, sizeof(CPhysics::ms_HeadingDiffRadians), false);
bank.AddText("HeadingBetween (Degrees)", CPhysics::ms_HeadingDiffDegrees, sizeof(CPhysics::ms_HeadingDiffDegrees), false);
bank.AddText("Distance", CPhysics::ms_Distance, sizeof(CPhysics::ms_Distance), false);
bank.AddText("Horizontal dist", CPhysics::ms_HorizDistance, sizeof(CPhysics::ms_HorizDistance), false);
bank.AddText("Vertical dist", CPhysics::ms_VerticalDistance, sizeof(CPhysics::ms_VerticalDistance), false);
bank.AddText("Normal1", CPhysics::ms_Normal1, sizeof(CPhysics::ms_Normal1), false);
bank.AddText("Normal2", CPhysics::ms_Normal2, sizeof(CPhysics::ms_Normal2), false);
bank.PopGroup();
#if __D3D && __WIN32PC
bank.AddToggle("show d3d resource info", &showd3dresourceinfo);
bank.AddToggle("PC only: Enable bound by GPU Flip (time spent in Present())", &sm_enableBoundByGPUFlip);
#endif // __D3D && __WIN32PC
#if __BANK
CVectorMap::AddWidgets(bank);
#if __ASSERT
//g_ExternalPreAssertHandler = CDebug::OnAssertionFired;
diagExternalCallback = OnAssertionFired;
#endif // __ASSERT
#endif // __DEV
#endif // ENABLE_CDEBUG
#if CSE_PROP_EDITABLEVALUES
bkBank& propBank = BANKMGR.CreateBank("Props");
CCustomShaderEffectProp::InitWidgets(propBank);
#endif //CSE_PROP_EDITABLEVALUES...
// add the Rage widgets to get constant screenshots & viewer at the bottom:
bank.PushGroup("Screenshot Viewer" ,false);
CSystem::GetRageSetup()->AddScreenShotViewerWidgets(bank);
bank.PopGroup();
AddCrashWidgets(&bank);
bkBank* pBank = BANKMGR.FindBank("Optimization");
CTestCase::AddWidgets(*pBank);
InitLiveEditWidgets();
InitToolsWidgets();
psoDebugMismatchedFiles::InitClass();
#endif // DEBUG_BANK
}
bkBank* CDebug::GetLiveEditBank()
{
return s_LiveEditBank;
}
void CDebug::PopulatePackfileSourceCombo()
{
if (gPackfileSourceCombo)
{
ClearPackfileSourceCombo();
// Get a list of all packfiles.
int count = strPackfileManager::GetImageFileCount();
gPackfileSourceList = rage_new const char *[count];
gPackfileMapping = rage_new int[count];
int finalCount = 0;
// We want to ignore packfiles that don't contain models, so let's create a quick bitmask
// to see which packfiles contain models.
atBitSet usedPackfiles;
usedPackfiles.Init(count);
strStreamingModule *module = fwArchetypeManager::GetStreamingModule();
int archetypes = module->GetCount();
for (int x=0; x<archetypes; x++)
{
if (!CModelInfo::GetModelInfoFromLocalIndex(x))
{
continue;
}
/// strIndex index = module->GetStreamingIndex(x);
// Now the archetype itself is not going to be in this packfile (it's a dummy streamable), but its
// dependencies will.
strIndex deps[256];
int depCount = module->GetDependencies(strLocalIndex(x), deps, 256);
for (int dep=0; dep<depCount; dep++)
{
strStreamingInfo &depInfo = strStreamingEngine::GetInfo().GetStreamingInfoRef(deps[dep]);
strLocalIndex imageIndex = strPackfileManager::GetImageFileIndexFromHandle(depInfo.GetHandle());
if (imageIndex.Get() != -1)
{
usedPackfiles.Set(imageIndex.Get());
}
}
}
for (int x=0; x<count; x++)
{
if (usedPackfiles.IsSet(x))
{
strStreamingFile *file = strPackfileManager::GetImageFile(x);
Assert(file->m_name.GetCStr());
gPackfileSourceList[finalCount] = file->m_name.GetCStr();
gPackfileMapping[finalCount] = x;
finalCount++;
}
}
gPackfileSourceCount = finalCount;
gPackfileSourceCombo->UpdateCombo(gPackfileSourceCombo->GetTitle(), &gPackfileSource, gPackfileSourceCount, gPackfileSourceList, 0, datCallback(CFA(CDebug::PopulateObjectCombo)));
}
}
void CDebug::ClearPackfileSourceCombo()
{
if (gPackfileSourceCombo)
{
gPackfileSourceCombo->UpdateCombo(gPackfileSourceCombo->GetTitle(), &gPackfileSource, 1, gPackfileSourceDummyList, 0, NullCB);
}
delete[] gPackfileSourceList;
gPackfileSourceList = NULL;
delete[] gPackfileMapping;
gPackfileMapping = NULL;
}
void CDebug::ClearObjectComo()
{
if (gObjectToCreateCombo)
{
gObjectToCreateCombo->UpdateCombo(gObjectToCreateCombo->GetTitle(), &gObjectToCreateIndex, 1, gObjectToCreateDummyList, 0, NullCB);
}
delete[] gObjectNameList;
delete[] gObjectModelIdList;
gObjectNameList = NULL;
gObjectModelIdList = NULL;
}
void CDebug::PopulateObjectCombo()
{
if (gPackfileSourceList)
{
if (gPackfileSource >= 0 && gPackfileSource < gPackfileSourceCount)
{
int packfileIndex = gPackfileMapping[gPackfileSource];
// Find all the props within this file.
strStreamingModule *module = fwArchetypeManager::GetStreamingModule();
for (int pass=0; pass<2; pass++)
{
int count = module->GetCount();
int finalCount = 0;
for (int x=0; x<count; x++)
{
if (!CModelInfo::GetModelInfoFromLocalIndex(x))
{
continue;
}
/// strIndex index = module->GetStreamingIndex(x);
// Now the archetype itself is not going to be in this packfile (its a dummy streamable), but its
// dependencies will.
strIndex deps[256];
int depCount = module->GetDependencies(strLocalIndex(x), deps, 256);
bool isInRpf = false;
for (int dep=0; dep<depCount; dep++)
{
strStreamingInfo &depInfo = strStreamingEngine::GetInfo().GetStreamingInfoRef(deps[dep]);
strLocalIndex imageIndex = strPackfileManager::GetImageFileIndexFromHandle(depInfo.GetHandle());
if (imageIndex.Get() == packfileIndex)
{
isInRpf = true;
break;
}
}
if (isInRpf)
{
fwModelId modelId((strLocalIndex(x)));
CBaseModelInfo *modelInfo = CModelInfo::GetBaseModelInfo(modelId);
if (pass == 1)
{
gObjectNameList[finalCount] = modelInfo->GetModelName();
gObjectModelIdList[finalCount] = modelId;
}
finalCount++;
}
}
if (pass == 0)
{
// End of first pass - we now know how many objects there are.
gObjectNameList = rage_new const char *[finalCount];
gObjectModelIdList = rage_new fwModelId[finalCount];
gObjectToCreateCount = finalCount;
}
}
// We now have a list of names and model IDs. Let's populate the combo.
gObjectToCreateCombo->UpdateCombo(gObjectToCreateCombo->GetTitle(), &gObjectToCreateIndex, gObjectToCreateCount, gObjectNameList, 0, datCallback(CFA(CDebug::PickObjectToSpawn)));
// And refresh display object
PickObjectToSpawn();
}
}
}
void CDebug::PickObjectToSpawn()
{
if (gObjectModelIdList)
{
if (gObjectToCreateIndex >= 0 && gObjectToCreateIndex < gObjectToCreateCount)
{
fwModelId modelId(gObjectModelIdList[gObjectToCreateIndex]);
CBaseModelInfo *modelInfo = CModelInfo::GetBaseModelInfo(modelId);
safecpy(gCurrentDisplayObject, modelInfo->GetModelName());
DisplayObject(true);
}
}
}
void CDebug::DisplayObjectAndPlaceOnGround()
{
DisplayObject(false); PlaceLastObjectOnGround();
}
void CDebug::InitRageDebugChannelWidgets()
{
ms_pRageDebugChannelBank = BANKMGR.FindBank("rage - Debug Channels");
if (!ms_pRageDebugChannelBank)
{
ms_pRageDebugChannelBank = &BANKMGR.CreateBank("rage - Debug Channels");
ASSERT_ONLY(ms_pRageDebugChannelBank->AddButton("Clear ignored asserts", datCallback(CFA(diagChannel::ClearIgnoredAsserts))));
ms_pRageDebugChannelBank->AddButton("Create debug channel widgets", datCallback(CFA1(CDebug::AddRageDebugChannelWidgets), ms_pRageDebugChannelBank));
}
}
void CDebug::InitToolsWidgets()
{
ms_pToolsBank = BANKMGR.FindBank("Tools");
if (!ms_pToolsBank)
{
ms_pToolsBank = &BANKMGR.CreateBank("Tools");
ms_pToolsBank->AddButton("Create tools widgets", datCallback(CFA1(CDebug::AddToolsWidgets), ms_pToolsBank));
}
}
void CDebug::AddRageDebugChannelWidgets(bkBank *bank)
{
bkWidget *pWidget = BANKMGR.FindWidget("rage - Debug Channels/Create debug channel widgets");
if(pWidget == NULL)
return;
pWidget->Destroy();
diagChannel::InitWidgets(*bank);
}
void CDebug::AddToolsWidgets(bkBank *bank)
{
bkWidget *pWidget = BANKMGR.FindWidget("Tools/Create tools widgets");
if(pWidget == NULL)
return;
pWidget->Destroy();
if (ms_pBankDebug == NULL)
{
ms_pBankDebug = new CBankDebug();
ms_pBankDebug->InitWidgets(*bank);
}
}
void CDebug::ShutdownRageDebugChannelWidgets()
{
ClearObjectComo();
ClearPackfileSourceCombo();
if (ms_pRageDebugChannelBank)
{
ms_pRageDebugChannelBank->Destroy();
ms_pRageDebugChannelBank = NULL;
}
gPackfileSourceCombo = NULL;
gObjectToCreateCombo = NULL;
}
//////////////////////////////////////////////////////////////////////////
// CMPObjectUsage
#if __BANK
bool CMPObjectUsage::m_bActive = false;
void CMPObjectUsage::AddWidgets(bkBank &bank)
{
bank.AddToggle("Show Objects Not Used in MP", &m_bActive);
}
bool CMPObjectUsage::IsUsedInMP(CEntity *pEntity)
{
return pEntity->GetIsUsedInMP();
}
bool CMPObjectUsage::ShouldDisplayOnMap(CEntity *pEntity)
{
if( pEntity->GetIsTypeObject() )
{
if( !IsUsedInMP(pEntity) )
{
return true;
}
}
return false;
}
#endif //__BANK
//////////////////////////////////////////////////////////////////////////
// CTestCase
s32 CTestCase::ms_TestCaseIndex = 0;
s32 CTestCase::ms_CurrTestCaseIndex = -1;
//////////////////////////////////////////////////////////////////////////
// Test Cases - shared variables (could move into CTestCase now)
bool s_bPushedAllowPedGeneration = false;
bool s_bPushedDisableRandomTrains = false;
bool s_bPushedNoCops = false;
int s_iPushedMaxCars = -1;
int s_iPushedMaxAmbientPeds = -1;
int s_iPushedMaxScenarioPeds = -1;
bool s_bTeleportPlayerForTest = true;
bool s_bPreventPlayerProcessForTest = false;
int s_iPushedMaxAmbientVehicles = -1;
int s_iMaxVehicles = 100;
int s_iMaxAmbientPeds = 100;
//////////////////////////////////////////////////////////////////////////
// Cars Test Cases
float s_fCarsVehiclesPerMeterDensityLookup[16] = {};
static void InitCarsCore()
{
if(s_bTeleportPlayerForTest)
{
Vector3 position(1051.808105f,-1169.786499f,55.518246f);
Matrix34 camera( 0.999738f, 0.022884f, 0.000000f,
-0.021861f, 0.955070f, -0.295573f,
-0.006764f, 0.295496f, 0.955320f,
1051.854126f, -1173.770142f, 57.747871f);
debugLocation loc;
loc.Set(position, camera, 14);
loc.BeamMeUp();
}
if(!NetworkInterface::IsGameInProgress())
{
CVehiclePopulation::RemoveAllVehsHard();
CPedPopulation::RemoveAllPedsHardNotPlayer();
}
s_iPushedMaxCars = CVehiclePopulation::ms_overrideNumberOfCars;
CVehiclePopulation::ms_overrideNumberOfCars = s_iMaxVehicles;
s_iPushedMaxAmbientVehicles = CVehiclePopulation::ms_iAmbientVehiclesUpperLimit;
CVehiclePopulation::ms_iAmbientVehiclesUpperLimit = s_iMaxVehicles;
s_bPushedAllowPedGeneration = gbAllowAmbientPedGeneration;
gbAllowAmbientPedGeneration = false;
s_bPushedDisableRandomTrains = CTrain::sm_bDisableRandomTrains;
CTrain::sm_bDisableRandomTrains = true;
s_bPushedNoCops = CVehiclePopulation::ms_noPoliceSpawn;
CVehiclePopulation::ms_noPoliceSpawn = true;
for (int i = 0; i < NELEM(CVehiclePopulation::ms_fVehiclesPerMeterDensityLookup); ++i)
{
s_fCarsVehiclesPerMeterDensityLookup[i] = CVehiclePopulation::ms_fVehiclesPerMeterDensityLookup[i];
CVehiclePopulation::ms_fVehiclesPerMeterDensityLookup[i] = 0.3f;
}
CVehiclePopulation::ForcePopulationInit();
}
static void ShutdownCars()
{
CVehiclePopulation::ms_overrideNumberOfCars = s_iPushedMaxCars;
CVehiclePopulation::ms_iAmbientVehiclesUpperLimit = s_iPushedMaxAmbientVehicles;
CTrain::sm_bDisableRandomTrains = s_bPushedDisableRandomTrains;
CVehiclePopulation::ms_noPoliceSpawn = s_bPushedNoCops;
gbAllowAmbientPedGeneration = s_bPushedAllowPedGeneration;
#if __DEV
CDebugScene::bDisplayVehiclesToBeStreamedOutOnVMap = false;
CDebugScene::bDisplayVehicleCollisionsOnVMap = false;
#endif
for (int i = 0; i < NELEM(CVehiclePopulation::ms_fVehiclesPerMeterDensityLookup); ++i)
{
CVehiclePopulation::ms_fVehiclesPerMeterDensityLookup[i] = s_fCarsVehiclesPerMeterDensityLookup[i];
}
if(s_bTeleportPlayerForTest)
{
camInterface::GetDebugDirector().DeactivateFreeCam();
CControlMgr::SetDebugPadOn(false);
}
// Restore normal LOD
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = true;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = true;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = true;
}
static void InitCarsLodNormal()
{
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = true;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = true;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = true;
InitCarsCore();
}
static void InitCarsForceLodReal()
{
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = false;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = false;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = false;
InitCarsCore();
}
static void InitCarsForceLodDummy()
{
CVehicleAILodManager::ms_bForceDummyCars = true;
CVehicleAILodManager::ms_bUseDummyLod = true;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = false;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = false;
InitCarsCore();
}
static void InitCarsForceLodSuperDummy()
{
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = false;
CVehicleAILodManager::ms_bAllSuperDummys = true;
CVehicleAILodManager::ms_bUseSuperDummyLod = true;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = false;
InitCarsCore();
}
static void InitCarsForceLodSuperDummyInactive()
{
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = false;
CVehicleAILodManager::ms_bAllSuperDummys = true;
CVehicleAILodManager::ms_bUseSuperDummyLod = true;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = true;
InitCarsCore();
}
static void UpdateCarsCloseOnly()
{
static float fKeepDist2 = square(150.0f);
Vector3 vPlayerPos = CGameWorld::FindLocalPlayerCoors();
CVehicle::Pool *pool = CVehicle::GetPool();
for(int i=0; i<pool->GetSize(); i++)
{
if(CVehicle * pVeh = pool->GetSlot(i))
{
if(vPlayerPos.Dist2(VEC3V_TO_VECTOR3(pVeh->GetVehiclePosition()))>fKeepDist2)
{
CVehicleFactory::GetFactory()->Destroy(pVeh);
}
}
}
}
static void UpdateCarsCycleLod()
{
CVehicleAILodManager::ms_iTimeBetweenConversionAttempts = 0;
enum { eLodReal, eLodDummy, eLodSuperDummy, eLodLast };
static int iLodDurationMs = 1000;
static int iLod = -1;
static int iLodTimeRemainingMs = 0;
if((iLodTimeRemainingMs -= fwTimer::GetTimeStepInMilliseconds()) < 0)
{
iLodTimeRemainingMs = iLodDurationMs;
iLod = (iLod + 1) % eLodLast;
switch(iLod)
{
case eLodReal:
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = false;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = false;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = false;
break;
case eLodDummy:
CVehicleAILodManager::ms_bForceDummyCars = true;
CVehicleAILodManager::ms_bUseDummyLod = true;
CVehicleAILodManager::ms_bAllSuperDummys = false;
CVehicleAILodManager::ms_bUseSuperDummyLod = false;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = false;
break;
case eLodSuperDummy:
CVehicleAILodManager::ms_bForceDummyCars = false;
CVehicleAILodManager::ms_bUseDummyLod = false;
CVehicleAILodManager::ms_bAllSuperDummys = true;
CVehicleAILodManager::ms_bUseSuperDummyLod = true;
CVehicleAILodManager::ms_bDisablePhysicsInSuperDummyMode = true;
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Peds Test Cases
float Backup_ms_fPhysicsAndEntityPedLodDistance;
float Backup_ms_fMotionTaskPedLodDistance;
float Backup_ms_fMotionTaskPedLodDistanceOffscreen;
float Backup_ms_fEventScanningLodDistance;
float Backup_ms_fRagdollInVehicleDistance;
s32 Backup_ms_overrideNumberOfParkedCars;
void StoreNormalPedVars()
{
Backup_ms_fPhysicsAndEntityPedLodDistance = CPedAILodManager::ms_fPhysicsAndEntityPedLodDistance;
Backup_ms_fMotionTaskPedLodDistance = CPedAILodManager::ms_fMotionTaskPedLodDistance;
Backup_ms_fMotionTaskPedLodDistanceOffscreen = CPedAILodManager::ms_fMotionTaskPedLodDistanceOffscreen;
Backup_ms_fEventScanningLodDistance = CPedAILodManager::ms_fEventScanningLodDistance;
Backup_ms_fRagdollInVehicleDistance = CPedAILodManager::ms_fRagdollInVehicleDistance;
Backup_ms_overrideNumberOfParkedCars = CVehiclePopulation::ms_overrideNumberOfParkedCars;
}
void RestoreNormalPedVars()
{
CPedAILodManager::ms_fPhysicsAndEntityPedLodDistance = Backup_ms_fPhysicsAndEntityPedLodDistance;
CPedAILodManager::ms_fMotionTaskPedLodDistanceOffscreen = Backup_ms_fMotionTaskPedLodDistanceOffscreen;
CPedAILodManager::ms_fEventScanningLodDistance = Backup_ms_fEventScanningLodDistance;
CPedAILodManager::ms_fRagdollInVehicleDistance = Backup_ms_fRagdollInVehicleDistance;
CVehiclePopulation::ms_overrideNumberOfParkedCars = Backup_ms_overrideNumberOfParkedCars;
}
static void InitPedsCore()
{
// It would be nice to get the same scene every time... this didn't do it.
//fwRandom::SetRandomSeed(42);
//g_ReplayRand.SetFullSeed(42);
if(s_bTeleportPlayerForTest)
{
Vector3 vPlayerPos(159.4f,-986.9f,30.2f); // Persian square, maybe?
Matrix34 cameraMtx;
cameraMtx.Identity();
cameraMtx.d.Set(vPlayerPos - Vector3(2.0f,0,-1.0f));
cameraMtx.MakeRotateZ(270 * DtoR);
debugLocation loc;
loc.Set(vPlayerPos,cameraMtx,14);
loc.BeamMeUp();
}
s_bPushedAllowPedGeneration = gbAllowAmbientPedGeneration;
gbAllowAmbientPedGeneration = true;
CVehiclePopulation::RemoveAllVehsHard();
CPedPopulation::RemoveAllPedsHardNotPlayer();
s_iPushedMaxCars = CVehiclePopulation::ms_overrideNumberOfCars;
CVehiclePopulation::ms_overrideNumberOfCars = 0;
s_bPushedDisableRandomTrains = CTrain::sm_bDisableRandomTrains;
CTrain::sm_bDisableRandomTrains = true;
s_bPushedNoCops = CVehiclePopulation::ms_noPoliceSpawn;
CVehiclePopulation::ms_noPoliceSpawn = true;
s_iPushedMaxAmbientPeds = CPedPopulation::ms_popCycleOverrideNumberOfAmbientPeds;
s_iPushedMaxScenarioPeds = CPedPopulation::ms_popCycleOverrideNumberOfScenarioPeds;
CPedPopulation::ms_popCycleOverrideNumberOfAmbientPeds = s_iMaxAmbientPeds;
CPedPopulation::ms_popCycleOverrideNumberOfScenarioPeds = 0;
CPedPopulation::ForcePopulationInit();
}
static void ShutdownPeds()
{
CPedPopulation::ms_popCycleOverrideNumberOfAmbientPeds = s_iPushedMaxAmbientPeds;
CPedPopulation::ms_popCycleOverrideNumberOfScenarioPeds = s_iPushedMaxScenarioPeds;
CVehiclePopulation::ms_overrideNumberOfCars = s_iPushedMaxCars;
CTrain::sm_bDisableRandomTrains = s_bPushedDisableRandomTrains;
CVehiclePopulation::ms_noPoliceSpawn = s_bPushedNoCops;
gbAllowAmbientPedGeneration = s_bPushedAllowPedGeneration;
if(s_bTeleportPlayerForTest)
{
camInterface::GetDebugDirector().DeactivateFreeCam();
CControlMgr::SetDebugPadOn(false);
}
RestoreNormalPedVars();
};
static void InitPedsLowLOD()
{
StoreNormalPedVars();
CPedAILodManager::ms_fPhysicsAndEntityPedLodDistance = 0.0f;
CPedAILodManager::ms_fMotionTaskPedLodDistance = 0.0f;
CPedAILodManager::ms_fMotionTaskPedLodDistanceOffscreen = 0.0f;
CPedAILodManager::ms_fEventScanningLodDistance = 0.0f;
CPedAILodManager::ms_fRagdollInVehicleDistance = 0.0f;
CVehiclePopulation::ms_overrideNumberOfParkedCars = 0;
InitPedsCore();
}
static void InitPedsNormalLOD()
{
StoreNormalPedVars(); // Store 'em so they can be put back
// Default values
// CPedAILodManager::ms_fPhysicsAndEntityPedLodDistance = 30.0f;
// CPedAILodManager::ms_fMotionTaskPedLodDistance = 30.0f;
// CPedAILodManager::ms_fEventScanningLodDistance = 30.0f;
// CPedAILodManager::ms_fRagdollInVehicleDistance = 30.0f;
CVehiclePopulation::ms_overrideNumberOfParkedCars = 0;
InitPedsCore();
}
static void InitPedsHighLOD()
{
StoreNormalPedVars();
CPedAILodManager::ms_fPhysicsAndEntityPedLodDistance = 1000.0f;
CPedAILodManager::ms_fMotionTaskPedLodDistance = 1000.0f;
CPedAILodManager::ms_fMotionTaskPedLodDistanceOffscreen = 1000.0f;
CPedAILodManager::ms_fEventScanningLodDistance = 1000.0f;
CPedAILodManager::ms_fRagdollInVehicleDistance = 1000.0f;
CVehiclePopulation::ms_overrideNumberOfParkedCars = 0;
InitPedsCore();
}
//////////////////////////////////////////////////////////////////////////
// Pershing Square
void InitPershingSquare()
{
if(s_bTeleportPlayerForTest)
{
Vector3 vPlayerPos(132.5f,-986.1f,29.4f);
Matrix34 cameraMtx;
cameraMtx.Identity();
cameraMtx.d.Set(vPlayerPos - Vector3(3.0f,0,-1.0f));
cameraMtx.MakeRotateZ(200 * DtoR);
debugLocation loc;
loc.Set(vPlayerPos, cameraMtx, 14);
loc.BeamMeUp();
}
if(!NetworkInterface::IsGameInProgress())
{
CVehiclePopulation::RemoveAllVehsHard();
CPedPopulation::RemoveAllPedsHardNotPlayer();
}
s_iPushedMaxCars = CVehiclePopulation::ms_overrideNumberOfCars;
CVehiclePopulation::ms_overrideNumberOfCars = s_iMaxVehicles;
s_iPushedMaxAmbientVehicles = CVehiclePopulation::ms_iAmbientVehiclesUpperLimit;
CVehiclePopulation::ms_iAmbientVehiclesUpperLimit = s_iMaxVehicles;
s_bPushedAllowPedGeneration = gbAllowAmbientPedGeneration;
gbAllowAmbientPedGeneration = true;
s_bPushedDisableRandomTrains = CTrain::sm_bDisableRandomTrains;
CTrain::sm_bDisableRandomTrains = false;
s_bPushedNoCops = CVehiclePopulation::ms_noPoliceSpawn;
CVehiclePopulation::ms_noPoliceSpawn = true;
CVehiclePopulation::ForcePopulationInit();
CPedPopulation::ms_popCycleOverrideNumberOfAmbientPeds = s_iMaxAmbientPeds;
CPedPopulation::ms_popCycleOverrideNumberOfScenarioPeds = 0;
CPedPopulation::ForcePopulationInit();
}
void ShutdownPershingSquare()
{
CVehiclePopulation::ms_overrideNumberOfCars = s_iPushedMaxCars;
CVehiclePopulation::ms_iAmbientVehiclesUpperLimit = s_iPushedMaxAmbientVehicles;
CTrain::sm_bDisableRandomTrains = s_bPushedDisableRandomTrains;
CVehiclePopulation::ms_noPoliceSpawn = s_bPushedNoCops;
CPedPopulation::ms_popCycleOverrideNumberOfAmbientPeds = s_iPushedMaxAmbientPeds;
CPedPopulation::ms_popCycleOverrideNumberOfScenarioPeds = s_iPushedMaxScenarioPeds;
gbAllowAmbientPedGeneration = s_bPushedAllowPedGeneration;
if(s_bTeleportPlayerForTest)
{
camInterface::GetDebugDirector().DeactivateFreeCam();
CControlMgr::SetDebugPadOn(false);
}
RestoreNormalPedVars();
}
///////////////////////////////////////////////////////////////////////////////
// Test cases
struct TestCase
{
const char* name;
void (*InitFn)();
void (*ShutdownFn)();
void (*UpdateFn)();
const char* desc;
};
static TestCase s_TestCases[] =
{
// name init function shutdown function update function description
{ "Cars, LOD Normal", &InitCarsLodNormal, &ShutdownCars, NULL, "Heavy traffic location, vehicle pop maxed, normal LOD settings."},
{ "Cars, LOD Real", &InitCarsForceLodReal, &ShutdownCars, NULL, "Heavy traffic location, vehicle pop maxed, LOD force to Real."},
{ "Cars, LOD Real (close only)", &InitCarsForceLodReal, &ShutdownCars, &UpdateCarsCloseOnly,"Heavy traffic location, vehicle pop maxed, LOD force to Real. Delete vehicles that are far away to prevent fallthrough."},
{ "Cars, LOD Dummy", &InitCarsForceLodDummy, &ShutdownCars, NULL, "Heavy traffic location, vehicle pop maxed, LOD force to Dummy."},
{ "Cars, LOD Super Dummy", &InitCarsForceLodSuperDummy, &ShutdownCars, NULL, "Heavy traffic location, vehicle pop maxed, LOD force to Super Dummy."},
{ "Cars, LOD Super Dummy Inactive", &InitCarsForceLodSuperDummyInactive,&ShutdownCars, NULL, "Heavy traffic location, vehicle pop maxed, LOD force to Super Dummy Inactive."},
{ "Cars, Cycle LOD", &InitCarsLodNormal, &ShutdownCars, &UpdateCarsCycleLod,"Heavy traffic location, vehicle pop maxed, cycle through vehicle LODs."},
{ "Peds, All Low LODs", &InitPedsLowLOD, &ShutdownPeds, NULL, "Heavy ped density. Force All to Low LODs"},
{ "Peds, Normal LODs", &InitPedsNormalLOD, &ShutdownPeds, NULL, "Heavy ped density. Normal LODs"},
{ "Peds, All High LODs", &InitPedsHighLOD, &ShutdownPeds, NULL, "Heavy ped density. Force All to High LODs"},
{ "Pershing Square, Cars and Peds Normal", &InitPershingSquare, &ShutdownPershingSquare, NULL, "Pershing Square, vehicle pop maxed, normal LOD settings."}
};
void CTestCase::StopTestCase()
{
if (ms_CurrTestCaseIndex != -1)
{
if (s_TestCases[ms_CurrTestCaseIndex].ShutdownFn)
{
s_TestCases[ms_CurrTestCaseIndex].ShutdownFn();
}
}
ms_CurrTestCaseIndex = -1;
}
void CTestCase::StartTestCase()
{
StopTestCase();
ms_CurrTestCaseIndex = ms_TestCaseIndex;
if (ms_CurrTestCaseIndex != -1)
{
if (s_TestCases[ms_CurrTestCaseIndex].InitFn)
{
s_TestCases[ms_CurrTestCaseIndex].InitFn();
}
Vector2 position(0.1f, 0.2f);
grcDebugDraw::Text(position, Color_white, s_TestCases[ms_CurrTestCaseIndex].desc, false, 1.0f, 1.0f, 60);
}
}
void CTestCase::SetTestCase()
{
if (ms_TestCaseIndex != ms_CurrTestCaseIndex)
{
StopTestCase();
}
}
void CTestCase::UpdateTestCase()
{
if (ms_CurrTestCaseIndex != -1)
{
if (s_TestCases[ms_CurrTestCaseIndex].UpdateFn)
{
s_TestCases[ms_CurrTestCaseIndex].UpdateFn();
}
}
}
void CTestCase::AddWidgets(bkBank &bank)
{
atArray<const char*> names;
for (int i = 0; i < NELEM(s_TestCases); ++i)
{
names.PushAndGrow(s_TestCases[i].name);
}
bank.AddCombo("Test Cases", &ms_TestCaseIndex, names.GetCount(), names.GetElements(), SetTestCase);
bank.AddButton("Start", StartTestCase);
bank.AddButton("Stop", StopTestCase);
bank.AddToggle("Teleport player for test", &s_bTeleportPlayerForTest);
bank.AddToggle("Stop Player Processing", &s_bPreventPlayerProcessForTest);
bank.AddSlider("Shared - Max Num Vehicles", &s_iMaxVehicles, 0, 200, 1);
bank.AddSlider("Shared - Max Num Ambient Peds", &s_iMaxAmbientPeds, 0, 200, 1);
}
//////////////////////////////////////////////////////////////////////////
// Intentional crashing
void Crash()
{
*(volatile char*)(0x0) = 0; // Sabotage
}
void RunOutOfMemory()
{
while (true)
{
rage_new char[64 << 10]; // Leak
}
}
void CDebug::AddCrashWidgets(bkBank* bank)
{
bank->PushGroup("Intentional Crashing");
bank->AddButton("Crash", datCallback(Crash));
bank->AddButton("Run out of memory", datCallback(RunOutOfMemory));
bank->PopGroup();
}
//////////////////////////////////////////////////////////////////////////
#endif // DEBUG_BANK
//////////////////////////////////////////////////////////////////////////
#if !__FINAL
//
// name: CDebug::UpdateProfiler
// description:
void CDebug::UpdateProfiler()
{
PF_PUSH_TIMEBAR("update profiler");
#if __STATS
GetRageProfileRenderer().EndFrame();
GetRageProfileRenderer().BeginFrame();
GetRageProfileRenderer().Update();
GetRageProfileRenderer().UpdateInput();
#endif
float time = static_cast<float>(fwTimer::GetTimeInMilliseconds());
ms_locationList.Update(time);
#if ENABLE_STATS_CAPTURE
MetricsCapture::Update(time);
#endif // ENABLE_STATS_CAPTURE
PF_POP_TIMEBAR();
}
void CDebug::InitProfiler(unsigned /*initMode*/)
{
#if USE_PROFILER
Profiler::RegisterCaptureControlCallback(RockyCaptureControlCallback);
#endif
#if !__BANK
ms_locationList.Init(NULL);
#if ENABLE_STATS_CAPTURE
MetricsCapture::Init();
MetricsCapture::SetLocationList(&ms_locationList);
#endif // ENABLE_STATS_CAPTURE
#endif // !__BANK
}
#endif // !__FINAL
// eof