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

3585 lines
112 KiB
C++

#include "script/script_debug.h"
// Framework headers
#include "fwdebug/debugbank.h"
#include "fwutil/idgen.h"
#include "input/keyboard.h"
#include "input/keys.h"
// Game headers
#include "animation/debug/animdebug.h"
#include "animation/debug/AnimPlacementTool.h"
#include "camera/CamInterface.h"
#include "control/restart.h"
#include "debug/DebugScene.h"
#include "game/config.h"
#include "Peds/ped.h"
#include "Peds/PedDebugVisualiser.h"
#include "Peds/PedFactory.h"
#include "Peds/pedpopulation.h"
#include "physics/physics.h"
#include "SaveLoad/GenericGameStorage.h"
#include "scene/world/GameWorld.h"
#include "scene/entities/compEntity.h"
#include "script/commands_debug.h"
#include "script/script.h"
#include "script/script_areas.h"
#include "script/script_cars_and_peds.h"
#include "script/script_channel.h"
#include "streaming/streaming.h"
#include "Vehicles/VehicleFactory.h"
#if __BANK
PARAM(scriptdebugger, "[script_debug] Activate script debugger");
PARAM(scriptdebugger_files, "[script_debug] comma-separated list of script files (without the .sc extension) that you want to debug");
PARAM(script_masks, "[script_debug] outputs a message whenever a script calls a mask command");
bool CScriptDebug::ms_bDisplayRunningScripts = false;
bool CScriptDebug::ms_bDisplayNumberOfScriptResources = false;
bool CScriptDebug::ms_bPrintCurrentContentsOfCleanupArray = false;
bool CScriptDebug::ms_bAutoSaveEnabled = true;
bool CScriptDebug::ms_bPerformAutoSave = false;
bool CScriptDebug::ms_bFadeInAfterLoadReadOnly = true;
bool CScriptDebug::ms_bDrawDebugLinesAndSpheres = false;
bool CScriptDebug::ms_bDebugMaskCommands = false;
bool CScriptDebug::ms_bPrintSuppressedCarModels = false;
bool CScriptDebug::ms_bPrintSuppressedPedModels = false;
bool CScriptDebug::ms_bPrintRestrictedPedModels = false;
bool CScriptDebug::ms_bOutputListOfAllScriptSpritesWhenLimitIsHit = false;
bool CScriptDebug::ms_bOutputScriptDisplayTextCommands = false;
s32 CScriptDebug::ms_NumberOfFramesToOutputScriptDisplayTextCommands = -1;
bool CScriptDebug::ms_bWriteNetworkCommandsToScriptLog = false;
bool CScriptDebug::ms_bDisplayNetworkCommandsInConsole = false;
bool CScriptDebug::ms_bFadeInAfterDeathArrestReadOnly = true;
bool CScriptDebug::ms_bPauseDeathArrestRestartReadOnly = false;
bool CScriptDebug::ms_bIgnoreNextRestartReadOnly = false;
bool CScriptDebug::ms_bWriteIS_NETWORK_SESSIONCommand = false;
bool CScriptDebug::ms_bWriteNETWORK_HAVE_SUMMONSCommand = false;
bool CScriptDebug::ms_bWriteIS_NETWORK_GAME_RUNNINGCommand = false;
bool CScriptDebug::ms_bWriteIS_NETWORK_PLAYER_ACTIVECommand = false;
bool CScriptDebug::ms_bWritePLAYER_WANTS_TO_JOIN_NETWORK_GAMECommand = false;
bool CScriptDebug::ms_bEnablePedDragging = false;
char CScriptDebug::ms_CreatePos[256] = "\0";
CScriptDebugPedHandler CScriptDebug::ms_PedHandler;
#if RSG_PC
bool CScriptDebug::ms_bFakeTampering = false;
#endif
CScriptDebugVehicleHandler CScriptDebug::ms_VehicleHandler;
CScriptDebugObjectHandler CScriptDebug::ms_ObjectHandler;
CScriptDebugLocateHandler CScriptDebug::ms_LocateHandler;
Vector3 CScriptDebug::ms_vClickedPos = VEC3_ZERO;
Vector3 CScriptDebug::ms_vClickedNormal = VEC3_ZERO;
Vector3 CScriptDebug::ms_vClickedPos2 = VEC3_ZERO;
Vector3 CScriptDebug::ms_vClickedNormal2 = VEC3_ZERO;
float CScriptDebug::ms_fPosFromCameraFront = 10.0f;
bool CScriptDebug::ms_bUseLineofSight = false;
char CScriptDebug::ms_FadeCommandTextContents[MAX_LENGTH_OF_FADE_COMMAND_TEXT_WIDGET];
fwDebugBank *CScriptDebug::ms_pBank = NULL;
const char *pNameOfScriptDebuggerBank = "Script Debugger";
bkCombo *CScriptDebug::ms_pComboBoxOfScriptThreads = NULL;
atArray<const char*> CScriptDebug::sm_ThreadNamesForDebugger;
s32 CScriptDebug::sm_ArrayIndexOfThreadToAttachDebuggerTo = 0;
bool CScriptDebug::sm_ComboBoxOfThreadNamesNeedsUpdated = false;
CScriptWidgetTree::CScriptWidgetNode *CScriptWidgetTree::ms_pCurrentWidgetNode = NULL;
CScriptDebugTextWidgets CScriptDebug::ms_TextWidgets;
CScriptDebugBitFieldWidgets CScriptDebug::ms_BitFieldWidgets;
atArray<CDebugAttachmentTool> CScriptDebug::ms_attachmentTools;
bkGroup* CScriptDebug::ms_pAttachmentGroup = NULL;
const char *CScriptDebug::ms_pScriptDebuggerPath = NULL;
atArray<atString> CScriptDebug::ms_ArrayOfNamesOfScriptsToBeDebugged;
char CScriptDebug::ms_ScriptThreadIdForDebugging[8];
#if SCRIPT_PROFILING
bool CScriptDebug::ms_bDisplayProfileOverview = false;
s32 CScriptDebug::ms_ProfileDisplayStartRow = 9;
#endif // SCRIPT_PROFILING
#endif // __BANK
#if !__FINAL
bool CScriptDebug::ms_bDbgFlag = false; // If true stuff gets printed out
PARAM(displayScriptRequests, "[script_debug] print to the TTY whenever a script calls REQUEST_SCRIPT or SET_SCRIPT_AS_NO_LONGER_NEEDED");
bool CScriptDebug::ms_bDisplayScriptRequests = false;
bool CScriptDebug::ms_bDisableDebugCamAndPlayerWarping = false; // For build for Image Metrics
// Some variables for controlling what gets displayed in the script model usage debug text
// bool CScriptDebug::ms_bDisplayModelUsagePerScript = true;
// bool CScriptDebug::ms_bCountModelUsage = true;
// bool CScriptDebug::ms_bCountAnimUsage = true;
// bool CScriptDebug::ms_bCountTextureUsage = true;
bool CScriptDebug::sm_bPlayerCoordsHaveBeenOverridden = false;
#endif // !__FINAL
#if __SCRIPT_MEM_DISPLAY
bool CScriptDebug::ms_bDisplayScriptMemoryUsage = false;
bool CScriptDebug::ms_bDisplayDetailedScriptMemoryUsage = false;
bool CScriptDebug::ms_bDisplayDetailedScriptMemoryUsageFiltered = false;
bool CScriptDebug::ms_bExcludeScriptFromMemoryUsage = false;
#endif // __SCRIPT_MEM_DISPLAY
ANIM_OPTIMISATIONS()
//////////////////////////////////////////////////////////////////////////
// Debug attachment tool implementation
//////////////////////////////////////////////////////////////////////////
#if __BANK
void CDebugAttachmentTool::Update()
{
if (m_bNeedsRebuild)
{
RegenerateWidgets();
}
//render the offsets here
Vector3 startPos(VEC3_ZERO);
Vector3 endPos(VEC3_ZERO);
if (m_parent)
{
if (GetParentBone() > -1)
{
// get the parent bone position
Matrix34 boneMtx(M34_IDENTITY);
m_parent->GetSkeleton()->GetGlobalMtx(GetParentBone(), RC_MAT34V(boneMtx));
startPos = boneMtx.d;
}
else
{
// get the parent entity matrix
startPos = VEC3V_TO_VECTOR3(m_parent->GetTransform().GetPosition());
}
if (GetChildBone() > -1)
{
// get the child bone position
Matrix34 boneMtx(M34_IDENTITY);
m_child->GetSkeleton()->GetGlobalMtx(GetChildBone(), RC_MAT34V(boneMtx));
endPos = boneMtx.d;
}
else
{
// get the child entity matrix
endPos = VEC3V_TO_VECTOR3(m_child->GetTransform().GetPosition());
}
grcDebugDraw::Line(startPos, endPos, Color_yellow, Color_yellow);
}
}
void CDebugAttachmentTool::AddWidgets(bkBank* pBank, const char * title)
{
if (m_child)
{
m_bankInstances.PushAndGrow(pBank->PushGroup(title));
{
CreateWidgets(pBank);
}
pBank->PopGroup();
}
}
void CDebugAttachmentTool::CreateWidgets(bkBank* pBank)
{
pBank->AddVector("Position offset", &m_positionOffset, -10000.0f, 10000.0f,0.1f,
datCallback(MFA(CDebugAttachmentTool::UpdatePositionOffset), (datBase*)this));
pBank->AddSlider("Heading", &m_rotationOffset.z, -180.0f,180.0f,1.0f,
datCallback(MFA(CDebugAttachmentTool::UpdateRotationOffset), (datBase*)this));
pBank->AddSlider("Pitch", &m_rotationOffset.x, -180.0f,180.0f,1.0f,
datCallback(MFA(CDebugAttachmentTool::UpdateRotationOffset), (datBase*)this));
pBank->AddSlider("Roll", &m_rotationOffset.y, -180.0f,180.0f,1.0f,
datCallback(MFA(CDebugAttachmentTool::UpdateRotationOffset), (datBase*)this));
// static const char * s_noBonesMessage = "No bones";
if (m_parentBoneList.GetCount()>0) // If bones are available, create a selectable list of them
{
//add a combo to track the bone names
pBank->AddCombo("Parent bone", &m_parentBone, m_parentBoneList.GetCount(), &m_parentBoneList[0]);
}
if (m_bAttachPhysically) //child bones are only available when attaching physically
{
if (m_childBoneList.GetCount()>0)
{
pBank->AddCombo("Child bone", &m_childBone, m_childBoneList.GetCount(), &m_childBoneList[0]);
}
}
else
{
if (m_childBoneList.GetCount()>0)
{
pBank->AddCombo("Child bone", &m_childBone, m_childBoneList.GetCount(),
&m_childBoneList[0], datCallback(MFA(CDebugAttachmentTool::BuildOffsetsFromChildBone), (datBase*)this));
}
}
if (m_child->GetIsTypePed()) //peds have special auto detachment options
{
pBank->AddToggle("Detach on death", &m_bDetachOnDeath);
pBank->AddToggle("Detach on ragdoll", &m_bDetachOnRagdoll);
}
else
{
if (m_parent)
{
if (m_parent->GetIsTypePed())
{
pBank->AddToggle("Detach on parent death", &m_bDetachOnDeath , datCallback(MFA(CDebugAttachmentTool::Attach), (datBase*)this));
}
}
}
if (!m_parent->GetIsTypePed()) //don't support physical attachment to peds
{
pBank->AddToggle("Attach physically", &m_bAttachPhysically , datCallback(MFA(CDebugAttachmentTool::TriggerRebuild), (datBase*)this));
if (m_bAttachPhysically)
{
pBank->PushGroup("Physical attachment options", false);
{
pBank->AddToggle("Constrain rotation", &m_bPhysicalConstrainRotation);
if (m_parent)
{
pBank->AddToggle("Child collides with parent", &m_bChildCollidesWithParent);
pBank->AddVector("Parent pivot offset", &m_physicalPivotOffset, -10000.0f, 10000.0f,0.1f);
}
pBank->AddSlider("Attachment strength", &m_strength, 0.0f,5000.0f, 1.0f);
}
pBank->PopGroup(); // "Physical attachment options"
}
}
pBank->AddButton("Apply changes", datCallback(MFA(CDebugAttachmentTool::Attach), (datBase*)this));
pBank->AddButton("Get script call", datCallback(MFA(CDebugAttachmentTool::OutputScript), (datBase*)this));
m_bNeedsRebuild = false;
}
void CDebugAttachmentTool::TriggerRebuild()
{
m_bNeedsRebuild = true;
}
void CDebugAttachmentTool::OutputScript()
{
CScriptDebug::OutputScript(GetScriptCall());
}
void CDebugAttachmentTool::RemoveWidgets()
{
//remove the widget groups we've created
while (m_bankInstances.GetCount()>0)
{
m_bankInstances.Top()->Destroy();
m_bankInstances.Top() = NULL;
m_bankInstances.Pop();
}
}
void CDebugAttachmentTool::RegenerateWidgets()
{
for (s32 i=0 ; i<m_bankInstances.GetCount(); i++)
{
// find the parent bank
bkBank* pBank = FindBank(m_bankInstances[i]);
if (pBank)
{
//destroy all the groups children
DestroyAllChildren(m_bankInstances[i]);
// set the current group
pBank->SetCurrentGroup(*m_bankInstances[i]);
// regenerate the widgets
CreateWidgets(pBank);
//unset the current group
pBank->UnSetCurrentGroup(*m_bankInstances[i]);
}
}
}
void CDebugAttachmentTool::BuildOffsetsFromChildBone()
{
// Set the position and orientation based on the
// current object space matrix of the selected child bone
s16 childBoneId = GetChildBone();
if (m_child->GetSkeleton())
{
Matrix34 boneMtx(M34_IDENTITY);
if (childBoneId>-1)
{
boneMtx.Set( RCC_MATRIX34(m_child->GetSkeleton()->GetObjectMtx(childBoneId)) );
boneMtx.Inverse();
boneMtx.ToEulersXYZ(m_rotationOffset);
m_positionOffset = boneMtx.d;
m_rotationOffset*=RtoD; // convert to degrees
}
Attach();
}
}
bkBank* CDebugAttachmentTool::FindBank(bkWidget* pWidget)
{
while (pWidget)
{
if (pWidget)
{
bkBank* pBank = dynamic_cast<bkBank*>(pWidget);
if (pBank)
{
return pBank;
}
}
pWidget = pWidget->GetParent();
}
return NULL;
}
void CDebugAttachmentTool::DestroyAllChildren(bkWidget* pWidget)
{
while (pWidget->GetChild())
{
pWidget->GetChild()->Destroy();
}
}
void CDebugAttachmentTool::Shutdown()
{
Detach();
m_child = NULL;
m_parent = NULL;
ClearSettings();
m_bankInstances.clear();
}
void CDebugAttachmentTool::ClearSettings()
{
m_parentBone=0; //Index for our bone selector combo boxes
m_childBone=0;
m_rotationOffset.Zero();
m_positionOffset.Zero();
m_bDetachOnDeath = false;
m_bDetachOnRagdoll = false;
m_bAttachPhysically = false;
m_bPhysicalConstrainRotation = false;
m_strength = 500.0f; // Higher values make the physical attachment harder to break
m_physicalPivotOffset.Zero(); // The offset on the target object to pivot about when attaching objects physically
m_bChildCollidesWithParent = false;
m_parentBoneList.clear(); //pointers to the bone names for the current parent
m_childBoneList.clear(); //pointers to the bone names for the current child
}
void CDebugAttachmentTool::LoadBoneList()
{
m_parentBoneList.clear();
if (m_parent)
{
m_parentBoneList.PushAndGrow("Entity");
if (m_parent->GetSkeleton())
{
const crSkeletonData& SkelData = m_parent->GetSkeletonData();
for (s32 i=0;i<SkelData.GetNumBones();i++)
{
m_parentBoneList.PushAndGrow(SkelData.GetBoneData(i)->GetName());
}
}
}
m_childBoneList.clear();
if (m_child)
{
m_childBoneList.PushAndGrow("Entity");
if (m_child->GetSkeleton())
{
const crSkeletonData& SkelData = m_child->GetSkeletonData();
for (s32 i=0;i<SkelData.GetNumBones();i++)
{
m_childBoneList.PushAndGrow(SkelData.GetBoneData(i)->GetName());
}
}
}
}
void CDebugAttachmentTool::Initialise(CPhysical* pChild, CPhysical* pParent)
{
animAssertf(pChild, "Can't initialise an attachment tool with a null child");
if (pChild)
{
m_child = pChild;
if (pParent)
{
//we're attaching to a parent
m_parent = pParent;
}
ClearSettings();
LoadBoneList();
Attach();
}
}
void CDebugAttachmentTool::UpdatePositionOffset()
{
if (m_bAttachPhysically)
{
Attach();
}
else
{
m_child->SetAttachOffset(m_positionOffset);
}
}
void CDebugAttachmentTool::UpdateRotationOffset()
{
Quaternion quat;
quat.FromEulers(DtoR*m_rotationOffset);
if (m_bAttachPhysically)
{
Attach();
}
else
{
m_child->SetAttachQuat(quat);
}
}
void CDebugAttachmentTool::Attach()
{
//make sure the child's not already attached to something
Detach();
//need to identify ped or other object
if (m_child)
{
if (m_child->GetIsTypePed())
{
// ped attachment
ScriptAttachPed();
}
else
{
//object and vehicle attachment
ScriptAttachOther();
}
}
}
void CDebugAttachmentTool::Detach()
{
if (m_child)
{
//detach the child if necessary
if (m_child->GetIsAttached())
{
//cast to a ped if it is one
if (m_child->GetIsTypePed())
{
CPed* pPed = static_cast<CPed*>(m_child.Get());
pPed->DetachFromParent(DETACH_FLAG_ACTIVATE_PHYSICS | DETACH_FLAG_NO_COLLISION_UNTIL_CLEAR);
}
m_child->DetachFromParent(DETACH_FLAG_ACTIVATE_PHYSICS | DETACH_FLAG_NO_COLLISION_UNTIL_CLEAR);
}
}
}
const char * CDebugAttachmentTool::GetScriptCall()
{
static char scriptCall[256] = "";
if (m_child->GetIsTypePed())
{ //ped commands
if (m_parent)
{
if (m_parent->GetIsTypePed())
{ //ped to ped commands
s16 ParentBone = GetParentBone();
eAnimBoneTag BoneTag = BONETAG_INVALID;
if(ParentBone !=-1)
{
BoneTag = static_cast<CPed*>(m_parent.Get())->GetBoneTagFromBoneIndex(ParentBone);
}
sprintf(scriptCall, "\r\nATTACH_PED_TO_PED ( ENTER_CHILD_PED, ENTER_PARENT_PED, %d, << %.3f, %.3f, %.3f >>, %.3f, %.3f, %s, %s )",
BoneTag, // TODO - convert this into the script enum name
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.z, m_rotationOffset.z,
CScriptDebug::GetScriptBool( m_bDetachOnDeath ),
CScriptDebug::GetScriptBool( m_bDetachOnRagdoll )
);
}
else if (m_parent->GetIsTypeVehicle())
{ //ped to vehicle commands
s16 ChildBone = GetChildBone();
eAnimBoneTag BoneTag = BONETAG_INVALID;
if(ChildBone != -1)
{
BoneTag = static_cast<CPed*>(m_child.Get())->GetBoneTagFromBoneIndex(GetChildBone());
}
if (m_bAttachPhysically)
{
sprintf(scriptCall, "\r\nATTACH_PED_TO_VEHICLE_PHYSICALLY ( ENTER_PED, ENTER_VEHICLE, %d, %d, << %.3f, %.3f, %.3f >>, %.3f, %s, %s )",
BoneTag, GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation ),
CScriptDebug::GetScriptBool( m_bChildCollidesWithParent )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_PED_TO_VEHICLE ( ENTER_PED , ENTER_VEHICLE, %d, %d, << %.3f, %.3f, %.3f >>, %.3f, %.3f, %s, %s)",
BoneTag, GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.z, m_rotationOffset.z,
CScriptDebug::GetScriptBool( m_bDetachOnDeath ),
CScriptDebug::GetScriptBool( m_bDetachOnRagdoll )
);
}
}
else
{ //ped to object commands
if (m_bAttachPhysically)
{
s16 ChildBone = GetChildBone();
eAnimBoneTag BoneTag = BONETAG_INVALID;
if(ChildBone != -1)
{
BoneTag = static_cast<CPed*>(m_child.Get())->GetBoneTagFromBoneIndex(GetChildBone());
}
sprintf(scriptCall, "\r\nATTACH_PED_TO_OBJECT_PHYSICALLY ( ENTER_PED, ENTER_OBJECT, %d, %d, << %.3f, %.3f, %.3f >>, %.3f, %s, %s )",
BoneTag, GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation ),
CScriptDebug::GetScriptBool( m_bChildCollidesWithParent )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_PED_TO_OBJECT ( ENTER_PED , ENTER_OBJECT, %d, << %.3f, %.3f, %.3f >>, %.3f, %.3f, %s, %s)",
GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.z, m_rotationOffset.z,
CScriptDebug::GetScriptBool( m_bDetachOnDeath ),
CScriptDebug::GetScriptBool( m_bDetachOnRagdoll )
);
}
}
}
else
{ //attach ped to world
if (m_bAttachPhysically)
{
s16 ChildBone = GetChildBone();
eAnimBoneTag BoneTag = BONETAG_INVALID;
if(ChildBone != -1)
{
BoneTag = static_cast<CPed*>(m_child.Get())->GetBoneTagFromBoneIndex(GetChildBone());
}
sprintf(scriptCall, "\r\nATTACH_PED_TO_WORLD_PHYSICALLY (ENTER_PED, %d , , << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %s)",
BoneTag,
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
0.0f, 0.0f, 0.0f,
CScriptDebug::GetScriptBool( m_bFixRotation )
);
}
}
}
else if (m_child->GetIsTypeVehicle())
{ //vehicle commands
if (m_parent)
{
if (m_parent->GetIsTypeVehicle())
{ //vehicle to vehicle commands
if (m_bAttachPhysically)
{
sprintf(scriptCall, "\r\nATTACH_VEHICLE_TO_VEHICLE_PHYSICALLY( CHILD_VEHICLE, PARENT_VEHICLE, %d, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %.3f, %s)",
GetChildBone(), GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_physicalPivotOffset.x, m_physicalPivotOffset.y, m_physicalPivotOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_VEHICLE_TO_VEHICLE( CHILD_VEHICLE, PARENT_VEHICLE, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>)",
GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z
);
}
}
else
{ //vehicle to object commands
if (m_bAttachPhysically)
{ //use object to object for this (there's no vehicle to object physically command)
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_OBJECT_PHYSICALLY( CHILD_VEHICLE, PARENT_VEHICLE, %d, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %.3f, %s)",
GetChildBone(), GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_physicalPivotOffset.x, m_physicalPivotOffset.y, m_physicalPivotOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_VEHICLE_TO_OBJECT( ENTER_VEHICLE, ENTER_OBJECT, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>)",
GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z
);
}
}
}
}
else
{ //object commands
if (m_parent)
{
if (m_parent->GetIsTypePed())
{ //object to ped commands
s16 ParentBone = GetParentBone();
eAnimBoneTag BoneTag = BONETAG_INVALID;
if(ParentBone !=-1)
{
BoneTag = static_cast<CPed*>(m_parent.Get())->GetBoneTagFromBoneIndex(ParentBone);
}
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_PED ( ENTER_OBJECT, ENTER_PED, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %s)",
BoneTag, // TODO - convert this into the script enum name
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z,
CScriptDebug::GetScriptBool( m_bDetachOnRagdoll )
);
}
else if (m_parent->GetIsTypeVehicle())
{ //object to vehicle commands
if (m_bAttachPhysically)
{
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_VEHICLE_PHYSICALLY( ENTER_OBJECT, ENTER_VEHICLE, %d, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %.3f, %s)",
GetParentBone(), GetChildBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_physicalPivotOffset.x, m_physicalPivotOffset.y, m_physicalPivotOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_VEHICLE( ENTER_OBJECT, ENTER_VEHICLE, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>)",
GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z
);
}
}
else
{ //generic object to object attachment
if (m_bAttachPhysically)
{
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_OBJECT_PHYSICALLY( CHILD_OBJECT, PARENT_OBJECT, %d, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>, %.3f, %s)",
GetChildBone(), GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_physicalPivotOffset.x, m_physicalPivotOffset.y, m_physicalPivotOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z,
m_strength, CScriptDebug::GetScriptBool( m_bPhysicalConstrainRotation )
);
}
else
{
sprintf(scriptCall, "\r\nATTACH_OBJECT_TO_OBJECT( CHILD_OBJECT, PARENT_OBJECT, %d, << %.3f, %.3f, %.3f >>, << %.3f, %.3f, %.3f >>)",
GetParentBone(),
m_positionOffset.x, m_positionOffset.y, m_positionOffset.z,
m_rotationOffset.x, m_rotationOffset.y, m_rotationOffset.z
);
}
}
}
}
return &scriptCall[0];
}
void CDebugAttachmentTool::ScriptAttachPed()
{
CPed* pPed = static_cast<CPed*>(m_child.Get());
if (pPed)
{
s16 childBoneId = GetChildBone();
s16 parentBoneId = GetParentBone();
u32 attachFlags = 0;
if (!m_parent)
{
//attach the ped to the world physically (There's no script command for doing this non physically)
m_bAttachPhysically = true;
pPed->AttachToWorldUsingPhysics(childBoneId, m_bPhysicalConstrainRotation, VEC3_ZERO, &m_positionOffset, m_strength);
}
else
{
if (!m_bAttachPhysically)
{
attachFlags = ATTACH_STATE_PED|ATTACH_FLAG_INITIAL_WARP;
if(m_bDetachOnDeath)
attachFlags |= ATTACH_FLAG_AUTODETACH_ON_DEATH;
if(m_bDetachOnRagdoll)
attachFlags |= ATTACH_FLAG_AUTODETACH_ON_RAGDOLL;
pPed->AttachPedToPhysical(m_parent, parentBoneId, attachFlags, &m_positionOffset, NULL, m_rotationOffset.z*DtoR, m_rotationOffset.z*DtoR);
}
else
{
attachFlags = ATTACH_STATE_RAGDOLL|ATTACH_FLAG_POS_CONSTRAINT;
if(m_bPhysicalConstrainRotation)
attachFlags |= ATTACH_FLAG_ROT_CONSTRAINT;
if(m_bChildCollidesWithParent)
attachFlags |= ATTACH_FLAG_DO_PAIRED_COLL;
pPed->AttachToPhysicalUsingPhysics(m_parent, parentBoneId, childBoneId, attachFlags, m_positionOffset, m_strength);
}
}
}
}
void CDebugAttachmentTool::ScriptAttachOther()
{
s16 childBoneId = GetChildBone();
s16 parentBoneId = GetParentBone();
u32 attachFlags = 0;
Quaternion quat;
quat.FromEulers(DtoR*m_rotationOffset);
if (m_parent)
{
if (m_bAttachPhysically)
{
attachFlags = ATTACH_STATE_PHYSICAL|ATTACH_FLAG_INITIAL_WARP|ATTACH_FLAG_POS_CONSTRAINT;
if(m_bPhysicalConstrainRotation)
attachFlags |= ATTACH_FLAG_ROT_CONSTRAINT;
m_child->AttachToPhysicalUsingPhysics(m_parent, parentBoneId, childBoneId, attachFlags, &m_positionOffset, &quat, &m_physicalPivotOffset, m_strength);
}
else
{
attachFlags = ATTACH_STATE_BASIC|ATTACH_FLAG_INITIAL_WARP;
if (m_parent->GetIsTypePed())
{
if (m_bDetachOnRagdoll)
{
attachFlags |= ATTACH_FLAG_AUTODETACH_ON_RAGDOLL;
}
}
m_child->AttachToPhysicalBasic(m_parent, parentBoneId, attachFlags, &m_positionOffset, &quat);
}
}
}
#endif // __BANK
//////////////////////////////////////////////////////////////////////////
// End of Debug attachment tool implementation
//////////////////////////////////////////////////////////////////////////
#if __BANK
//////////////////////////////////////////////////////////////////////////
// CScriptWidgetNode
//////////////////////////////////////////////////////////////////////////
CScriptWidgetTree::CScriptWidgetNode::CScriptWidgetNode(u32 UniqueId, eWidgetType Type)
: m_UniqueId(UniqueId),
m_WidgetType(Type)
{
m_pParent = NULL;
m_pChild = NULL;
m_pSibling = NULL;
}
CScriptWidgetTree::CScriptWidgetNode::~CScriptWidgetNode()
{
RemoveSelf();
ClearChildrenAndData();
}
void CScriptWidgetTree::CScriptWidgetNode::ClearChildrenAndData()
{
while(m_pChild)
{
scriptAssertf(WIDGETTYPE_GROUP == m_WidgetType, "CScriptWidgetNode::ClearChildrenAndData - only widget groups should have child nodes");
delete m_pChild;
}
ClearData();
}
void CScriptWidgetTree::CScriptWidgetNode::RemoveSelf()
{
if (m_pParent)
{
CScriptWidgetNode **owner = &m_pParent->m_pChild;
while (*owner != this)
owner = &(*owner)->m_pSibling;
*owner = m_pSibling;
}
else
{
scriptAssertf(m_pSibling==NULL, "CScriptWidgetNode::RemoveSelf - didn't expect a widget node without a parent to have a sibling. This should be the top level widget group for the script");
}
m_pParent = m_pSibling = NULL;
}
void CScriptWidgetTree::CScriptWidgetNode::ClearData()
{
switch (m_WidgetType)
{
case WIDGETTYPE_STANDARD :
{
scriptAssertf(0, "CScriptWidgetNode::ClearData - nodes of WIDGETTYPE_STANDARD should never appear in the widget tree");
// bkWidget* pWidget = CScriptWidgetTree::GetWidgetFromUniqueWidgetId(m_UniqueId);
// if(scriptVerifyf(pWidget != NULL, "CScriptWidgetNode::ClearData - Widget id is invalid"))
// {
// CScriptDebug::GetWidgetBank()->Remove(*pWidget);
// }
}
break;
case WIDGETTYPE_GROUP :
{
bkGroup* pGroup = static_cast<bkGroup*>(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(m_UniqueId));
if(scriptVerifyf(pGroup != NULL, "CScriptWidgetNode::ClearData - Widget group id is invalid"))
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
CScriptDebug::GetWidgetBank()->DeleteGroup(*pGroup);
}
}
}
break;
case WIDGETTYPE_TEXT :
{
bkText *pTextWidget = static_cast<bkText*>(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(m_UniqueId));
CScriptDebug::GetTextWidgets().ClearTextWidget(pTextWidget);
}
break;
case WIDGETTYPE_BITFIELD :
{
bkGroup *pBitFieldWidgetGroup = static_cast<bkGroup*>(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(m_UniqueId));
CScriptDebug::GetBitFieldWidgets().ClearBitFieldWidget(pBitFieldWidgetGroup);
}
break;
}
g_uniqueObjectIDGenerator.FreeID(m_UniqueId);
m_UniqueId = 0;
}
void CScriptWidgetTree::CScriptWidgetNode::AddChildNode(CScriptWidgetNode *pNewChild)
{
scriptAssertf(!pNewChild->m_pParent, "CScriptWidgetNode::AddChildNode - parent of new child should be NULL");
scriptAssertf(!pNewChild->m_pChild, "CScriptWidgetNode::AddChildNode - child of new child should be NULL");
scriptAssertf(!pNewChild->m_pSibling, "CScriptWidgetNode::AddChildNode - sibling of new child should be NULL");
pNewChild->m_pParent = this;
pNewChild->m_pSibling = this->m_pChild;
this->m_pChild = pNewChild;
}
CScriptWidgetTree::CScriptWidgetNode *CScriptWidgetTree::CScriptWidgetNode::FindWidget(u32 UniqueId)
{
if (m_UniqueId == UniqueId)
{
return this;
}
CScriptWidgetNode *pReturnNode = NULL;
if (m_pChild)
{
pReturnNode = m_pChild->FindWidget(UniqueId);
}
if (!pReturnNode)
{
if (m_pSibling)
{
pReturnNode = m_pSibling->FindWidget(UniqueId);
}
}
return pReturnNode;
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptWidgetNode
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptWidgetTree
//////////////////////////////////////////////////////////////////////////
CScriptWidgetTree::CScriptWidgetTree()
: m_pTopLevelWidget(NULL)
{
}
CScriptWidgetTree::~CScriptWidgetTree()
{
scriptAssertf(m_pTopLevelWidget == NULL, "~CScriptWidgetTree - expected all script widgets to have been cleaned up by now");
RemoveAllWidgetNodes();
}
CScriptWidgetTree::CScriptWidgetNode *CScriptWidgetTree::FindWidgetNodeWithThisUniqueId(u32 UniqueId)
{
if (m_pTopLevelWidget)
{
return m_pTopLevelWidget->FindWidget(UniqueId);
}
return NULL;
}
u32 CScriptWidgetTree::AddWidget(bkWidget *pWidget, eWidgetType WidgetType, const char *ASSERT_ONLY(pScriptName))
{
u32 ReturnUniqueId = 0;
bool bAllowCreation = true;
bool bTopLevelWidgetGroup = false;
if (ms_pCurrentWidgetNode == NULL)
{
bAllowCreation = false;
if (scriptVerifyf(m_pTopLevelWidget == NULL, "CScriptWidgetTree::AddWidget - SET_CURRENT_WIDGET_GROUP needs to be called before you can add to a pre-existing widget group for %s", pScriptName))
{
if (scriptVerifyf(WIDGETTYPE_GROUP == WidgetType, "CScriptWidgetTree::AddWidget - you must create a widget group to contain all other widgets for %s", pScriptName))
{
bAllowCreation = true;
bTopLevelWidgetGroup = true;
}
}
}
if (bAllowCreation)
{
// Widget groups and text widgets are referred to by script after they're created so they need to return a Unique ID.
// Bit field widgets require special cleanup in CScriptWidgetNode::ClearData() (as do widget groups and text widgets)
// so they also need added to the widget tree.
// Bit field widgets only need a Unique ID because ClearData() calls GetWidgetFromUniqueWidgetId()
if (WidgetType == WIDGETTYPE_STANDARD)
{
return 0;
}
ReturnUniqueId = g_uniqueObjectIDGenerator.GetID(pWidget);
CScriptWidgetNode *pNewWidgetNode = rage_new CScriptWidgetNode(ReturnUniqueId, WidgetType);
if (bTopLevelWidgetGroup)
{
m_pTopLevelWidget = pNewWidgetNode;
}
else
{
if (scriptVerifyf(ms_pCurrentWidgetNode, "CScriptWidgetTree::AddWidget - expected ms_pCurrentWidgetNode to be valid"))
{
ms_pCurrentWidgetNode->AddChildNode(pNewWidgetNode);
}
}
if (WIDGETTYPE_GROUP == WidgetType)
{
ms_pCurrentWidgetNode = pNewWidgetNode;
}
}
return ReturnUniqueId;
}
void CScriptWidgetTree::DeleteWidget(u32 UniqueId, bool bIsWidgetGroup, const char *ASSERT_ONLY(pScriptName))
{
CScriptWidgetNode *pWidgetNodeToDelete = FindWidgetNodeWithThisUniqueId(UniqueId);
if (scriptVerifyf(pWidgetNodeToDelete, "CScriptWidgetTree::DeleteWidget - failed to find a widget node with the specified Unique Id in %s", pScriptName))
{
if (bIsWidgetGroup)
{
scriptAssertf(WIDGETTYPE_GROUP == pWidgetNodeToDelete->GetWidgetType(), "CScriptWidgetTree::DeleteWidget - %s script called DELETE_WIDGET_GROUP but this isn't a widget group", pScriptName);
if (pWidgetNodeToDelete == m_pTopLevelWidget)
{
m_pTopLevelWidget = NULL;
scriptAssertf(ms_pCurrentWidgetNode == NULL, "CScriptWidgetTree::DeleteWidget - maybe missing a STOP_WIDGET_GROUP or a CLEAR_CURRENT_WIDGET_GROUP before calling DELETE_WIDGET_GROUP on the top level widget group in %s script", pScriptName);
ms_pCurrentWidgetNode = NULL;
}
}
else
{ // seems a bit pointless to check for widget groups, but not for text widgets and bit field widgets
scriptAssertf(WIDGETTYPE_GROUP != pWidgetNodeToDelete->GetWidgetType(), "CScriptWidgetTree::DeleteWidget - %s script called DELETE_WIDGET but this is a widget group", pScriptName);
}
delete pWidgetNodeToDelete;
}
}
void CScriptWidgetTree::SetCurrentWidgetGroup(u32 UniqueId, const char *ASSERT_ONLY(pScriptName))
{
scriptAssertf(ms_pCurrentWidgetNode==NULL, "CScriptWidgetTree::SetCurrentWidgetGroup - %s - STOP_WIDGET_GROUP or CLEAR_CURRENT_WIDGET_GROUP missing before this call to SET_CURRENT_WIDGET_GROUP", pScriptName);
bkGroup* pGroup = static_cast<bkGroup*>(GetWidgetFromUniqueWidgetId(UniqueId));
if (scriptVerifyf(pGroup, "CScriptWidgetTree::SetCurrentWidgetGroup - %s failed to find a widget group with the unique ID", pScriptName))
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
CScriptDebug::GetWidgetBank()->SetCurrentGroup(*pGroup);
}
CScriptWidgetNode *pWidgetNode = FindWidgetNodeWithThisUniqueId(UniqueId);
if (scriptVerifyf(pWidgetNode, "CScriptWidgetTree::SetCurrentWidgetGroup - failed to find a widget node with the specified id in the tree for %s", pScriptName))
{
if (scriptVerifyf(WIDGETTYPE_GROUP == pWidgetNode->GetWidgetType(), "CScriptWidgetTree::SetCurrentWidgetGroup - widget node with the specified unique id is not a WIDGETTYPE_GROUP"))
{
ms_pCurrentWidgetNode = pWidgetNode;
}
}
}
}
void CScriptWidgetTree::ClearCurrentWidgetGroup(u32 UniqueId, const char *ASSERT_ONLY(pScriptName))
{
bkGroup* pGroup = static_cast<bkGroup*>(GetWidgetFromUniqueWidgetId(UniqueId));
if (scriptVerifyf(pGroup, "CScriptWidgetTree::ClearCurrentWidgetGroup - %s failed to find a widget group with the unique ID", pScriptName))
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
CScriptDebug::GetWidgetBank()->UnSetCurrentGroup(*pGroup);
}
ms_pCurrentWidgetNode = NULL;
}
}
void CScriptWidgetTree::RemoveAllWidgetNodes()
{
if (m_pTopLevelWidget)
{
delete m_pTopLevelWidget;
m_pTopLevelWidget = NULL;
}
}
u32 CScriptWidgetTree::GetUniqueWidgetIdOfTopLevelWidget(const char *ASSERT_ONLY(pScriptName))
{
if (scriptVerifyf(m_pTopLevelWidget, "CScriptWidgetTree::GetUniqueWidgetIdOfTopLevelWidget - %s doesn't have a top level widget group yet", pScriptName))
{
return m_pTopLevelWidget->GetUniqueId();
}
return 0;
}
void CScriptWidgetTree::CloseWidgetGroup()
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
CScriptDebug::GetWidgetBank()->PopGroup();
}
if (scriptVerifyf(ms_pCurrentWidgetNode, "CScriptWidgetTree::CloseWidgetGroup - expected ms_pCurrentWidgetNode to point to a valid widget node when closing a widget group"))
{
ms_pCurrentWidgetNode = ms_pCurrentWidgetNode->GetParent();
}
}
void CScriptWidgetTree::CheckWidgetGroupsHaveBeenClosed(const char *ASSERT_ONLY(pScriptName))
{
if (ms_pCurrentWidgetNode)
{
scriptAssertf(0, "CScriptWidgetTree::CheckWidgetGroupsHaveBeenClosed - %s is missing either a STOP_WIDGET_GROUP or a CLEAR_CURRENT_WIDGET_GROUP", pScriptName);
ms_pCurrentWidgetNode = NULL;
}
}
bkWidget *CScriptWidgetTree::GetWidgetFromUniqueWidgetId(u32 UniqueId)
{
return static_cast<bkWidget*>(g_uniqueObjectIDGenerator.GetIDInstanceInfoFromID(UniqueId).m_uniqueBase);
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptWidgetTree
//////////////////////////////////////////////////////////////////////////
#endif // __BANK
//////////////////////////////////////////////////////////////////////////
// CScriptDebug
//////////////////////////////////////////////////////////////////////////
void CScriptDebug::Init(unsigned initMode)
{
if(initMode == INIT_CORE)
{
#if __BANK
ms_ScriptThreadIdForDebugging[0] = '\0';
ms_pScriptDebuggerPath = NULL;
if (!PARAM_scriptdebugger.GetParameter(ms_pScriptDebuggerPath))
{
//attempt to grab it from the config file.
ms_pScriptDebuggerPath = CGameConfig::Get().GetDebugScriptsPath().c_str();
}
scriptDisplayf("ms_pScriptDebuggerPath{%s}", ms_pScriptDebuggerPath);
const char *pFilesToBeDebugged = NULL;
PARAM_scriptdebugger_files.GetParameter(pFilesToBeDebugged);
s32 string_length = 0;
if (pFilesToBeDebugged && *pFilesToBeDebugged)
{
string_length = istrlen(pFilesToBeDebugged);
}
ms_ArrayOfNamesOfScriptsToBeDebugged.Reset();
const s32 MaxLengthOfFileName = 64;
char CurrentFileName[MaxLengthOfFileName];
s32 CurrentFileNameLength = 0;
for (s32 loop = 0; loop < string_length; loop++)
{
if ( ( (pFilesToBeDebugged[loop] >= 'a') && (pFilesToBeDebugged[loop] <= 'z') )
|| ( (pFilesToBeDebugged[loop] >= 'A') && (pFilesToBeDebugged[loop] <= 'Z') )
|| ( (pFilesToBeDebugged[loop] >= '0') && (pFilesToBeDebugged[loop] <= '9') )
|| (pFilesToBeDebugged[loop] == '_') )
{
if (scriptVerifyf(CurrentFileNameLength < (MaxLengthOfFileName-1), "CScriptDebug::Init - scriptdebugger_files command line param contains a file name that is longer than 63 characters"))
{
CurrentFileName[CurrentFileNameLength++] = pFilesToBeDebugged[loop];
}
}
else if (pFilesToBeDebugged[loop] == ',')
{
if (CurrentFileNameLength > 0)
{
CurrentFileName[CurrentFileNameLength] = '\0';
scriptDebugf3("Script to be debugged = %s\n", CurrentFileName);
ms_ArrayOfNamesOfScriptsToBeDebugged.PushAndGrow(atString(CurrentFileName));
CurrentFileNameLength = 0;
}
}
else
{
scriptAssertf(0, "CScriptDebug::Init - scriptdebugger_files command line param contains an invalid character %c", pFilesToBeDebugged[loop]);
}
}
if (CurrentFileNameLength > 0)
{
CurrentFileName[CurrentFileNameLength] = '\0';
scriptDebugf3("Script to be debugged = %s\n", CurrentFileName);
ms_ArrayOfNamesOfScriptsToBeDebugged.PushAndGrow(atString(CurrentFileName));
}
#endif // __BANK
#if !__FINAL
if (PARAM_displayScriptRequests.Get())
{
ms_bDisplayScriptRequests = true;
}
#endif // !__FINAL
}
else if(initMode == INIT_SESSION)
{
#if __BANK
ms_bDisplayRunningScripts = false;
ms_bDisplayNumberOfScriptResources = false;
ms_bPrintCurrentContentsOfCleanupArray = false;
ms_bAutoSaveEnabled = true;
ms_bPerformAutoSave = false;
ms_bDrawDebugLinesAndSpheres = false;
ms_bDebugMaskCommands = false;
if (PARAM_script_masks.Get())
{
ms_bDebugMaskCommands = true;
}
ms_bPrintSuppressedCarModels = false;
ms_bPrintSuppressedPedModels = false;
ms_bPrintRestrictedPedModels = false;
ms_bOutputScriptDisplayTextCommands = false;
ms_NumberOfFramesToOutputScriptDisplayTextCommands = -1;
ms_bEnablePedDragging = false;
ms_TextWidgets.Init();
ms_BitFieldWidgets.Init();
#if SCRIPT_PROFILING
ms_bDisplayProfileOverview = false;
#endif // SCRIPT_PROFILING
#endif // __BANK
#if !__FINAL
ms_bDbgFlag = false; // debugging off at start
// ms_bDisplayScriptRequests = false;
ms_bDisableDebugCamAndPlayerWarping = false; // For build for Image Metrics
#endif
}
}
void CScriptDebug::Shutdown(unsigned shutdownMode)
{
if(shutdownMode == SHUTDOWN_CORE)
{
}
else if(shutdownMode == SHUTDOWN_SESSION)
{
#if __BANK
if (ms_pBank)
{
#if __BANK
//remove the anim placement tool widgets before destroying the bank, or all hell's gonna break loose
CAnimPlacementEditor::RemoveWidgets();
CAnimPlacementEditor::Shutdown();
for (s32 i=0; i<ms_attachmentTools.GetCount(); i++)
{
ms_attachmentTools[i].Shutdown();
}
#endif // __BANK
CTheScripts::GetScriptHandlerMgr().ShutdownWidgets(ms_pBank);
ms_pBank->Shutdown();
ms_pBank = NULL;
}
ms_pComboBoxOfScriptThreads = NULL;
sm_ArrayIndexOfThreadToAttachDebuggerTo = 0;
sm_ComboBoxOfThreadNamesNeedsUpdated = false;
bkBank *pScriptDebuggerBank = BANKMGR.FindBank(pNameOfScriptDebuggerBank);
if (pScriptDebuggerBank)
{
BANKMGR.DestroyBank(*pScriptDebuggerBank);
}
#endif // __BANK
}
}
#if __BANK
bool CScriptDebug::ShouldThisScriptBeDebugged(const char *pScriptName)
{
u32 hashKey = 0;
char stringContainingHashKey[24];
if (ms_pScriptDebuggerPath) // There's no point in comparing the strings if a path to the .scd files has not been set
{
u32 length_of_input_string = ustrlen(pScriptName);
s32 SizeOfArray = ms_ArrayOfNamesOfScriptsToBeDebugged.GetCount();
for (s32 loop = 0; loop < SizeOfArray; loop++)
{
// Some scripts are now launched using the hash of their name instead of a string containing that name
hashKey = atStringHash(ms_ArrayOfNamesOfScriptsToBeDebugged[loop].c_str());
formatf(stringContainingHashKey, "0x%x", hashKey);
if (stricmp(pScriptName, stringContainingHashKey) == 0)
{
return true;
}
if (length_of_input_string == ms_ArrayOfNamesOfScriptsToBeDebugged[loop].length())
{
if (stricmp(pScriptName, ms_ArrayOfNamesOfScriptsToBeDebugged[loop].c_str()) == 0)
{
return true;
}
}
}
}
return false;
}
#endif // __BANK
void CScriptDebug::Process(void)
{
#if __BANK
if (ms_pComboBoxOfScriptThreads)
{
if (sm_ComboBoxOfThreadNamesNeedsUpdated)
{
GtaThread::UpdateArrayOfNamesOfRunningThreads(sm_ThreadNamesForDebugger);
ms_pComboBoxOfScriptThreads->UpdateCombo("Launch Debugger for Script", &sm_ArrayIndexOfThreadToAttachDebuggerTo,
sm_ThreadNamesForDebugger.GetCount(), &sm_ThreadNamesForDebugger[0]);
sm_ComboBoxOfThreadNamesNeedsUpdated = false;
}
}
static bool bSaveHasStarted = false;
ms_bFadeInAfterLoadReadOnly = CGenericGameStorage::ms_bFadeInAfterSuccessfulLoad;
ms_bFadeInAfterDeathArrestReadOnly = !CRestart::bSuppressFadeInAfterDeathArrest;
ms_bPauseDeathArrestRestartReadOnly = CRestart::bPausePlayerRespawnAfterDeathArrest;
ms_bIgnoreNextRestartReadOnly = CRestart::GetIgnoreNextRestart();
if (ms_bDisplayRunningScripts)
{
GtaThread::DisplayAllRunningScripts(true);
}
#if __REPORT_TOO_MANY_RESOURCES
if (ms_bDisplayNumberOfScriptResources)
{
CGameScriptResource::DisplayResourceUsage(true);
}
#endif // __REPORT_TOO_MANY_RESOURCES
if (ms_bPrintSuppressedCarModels)
{
CScriptCars::GetSuppressedCarModels().PrintSuppressedModels();
}
if (ms_bPrintSuppressedPedModels)
{
CScriptPeds::GetSuppressedPedModels().PrintSuppressedModels();
}
if (ms_bPrintRestrictedPedModels)
{
CScriptPeds::GetRestrictedPedModels().PrintRestrictedModels();
}
if (ms_bOutputScriptDisplayTextCommands)
{
if (ms_NumberOfFramesToOutputScriptDisplayTextCommands > 0)
{
ms_NumberOfFramesToOutputScriptDisplayTextCommands--;
if (ms_NumberOfFramesToOutputScriptDisplayTextCommands == 0)
{
ms_bOutputScriptDisplayTextCommands = false;
}
}
}
ms_BitFieldWidgets.UpdateBitFields();
ProcessScriptDebugTools();
if (ms_bPerformAutoSave)
{
if (bSaveHasStarted == false)
{
if (CGenericGameStorage::IsStorageDeviceBeingAccessed())
{
Displayf("Widget - Can't start an autosave just now\n");
}
else
{
CGenericGameStorage::QueueAutosave();
bSaveHasStarted = true;
}
}
if (!CGenericGameStorage::IsStorageDeviceBeingAccessed())
{
bSaveHasStarted = false;
ms_bPerformAutoSave = false;
}
}
if (ms_bPrintCurrentContentsOfCleanupArray)
{
#if __DEV
CTheScripts::GetScriptHandlerMgr().SpewObjectAndResourceInfo();
#endif // __DEV
ms_bPrintCurrentContentsOfCleanupArray = false;
}
#if SCRIPT_PROFILING
DisplayProfileOverviewOfAllThreads();
#endif // SCRIPT_PROFILING
#if __BANK
CAnimPlacementEditor::Update();
#endif // __BANK
#endif //__BANK
}
#if __BANK
void CScriptDebug::OutputScript(const char * text)
{
FileHandle file = CFileMgr::OpenFileForAppending(CScriptDebug::GetNameOfScriptDebugOutputFile());
scriptAssertf(file, "Could not open the script output file for writing");
//output the controlling variable first
Displayf( "%s", text );
if (CFileMgr::IsValidFileHandle(file))
{
CFileMgr::Write(file, text, istrlen(text));
CFileMgr::Write(file, "\r\n", 1);
CFileMgr::CloseFile(file);
}
}
void CScriptDebug::AttachSelectedObjects()
{
CEntity* pEntity0 = CDebugScene::FocusEntities_Get(0);
CEntity* pEntity1 = CDebugScene::FocusEntities_Get(1);
if (pEntity0 && pEntity1)
{
//if there's a selected entity
if (pEntity0->GetIsPhysical())
{
//cast to a CPhysical
CPhysical* pChild = static_cast<CPhysical*>(pEntity0);
CPhysical* pParent = NULL;
//is there a parent entity?
if (pEntity1)
{
if (pEntity1->GetIsPhysical())
{
pParent = static_cast<CPhysical*>(pEntity1);
}
}
if(pChild)
{
atString toolName("Attachment: ");
toolName += CModelInfo::GetBaseModelInfoName(pChild->GetModelId());
if (pParent)
{
toolName += "->";
toolName += CModelInfo::GetBaseModelInfoName(pParent->GetModelId());
}
CDebugAttachmentTool& tool = ms_attachmentTools.Grow();
tool.Initialise(pChild, pParent);
ms_pBank->SetCurrentGroup(*ms_pAttachmentGroup);
tool.AddWidgets(ms_pBank, toolName);
ms_pBank->UnSetCurrentGroup(*ms_pAttachmentGroup);
}
}
}
}
void CScriptDebug::ClearAttachments()
{
for (s32 i=0;i<ms_attachmentTools.GetCount(); i++)
{
ms_attachmentTools[i].RemoveWidgets();
ms_attachmentTools[i].Shutdown();
}
}
void CScriptDebug::UpdateAttachmentTools()
{
for (s32 i=0;i<ms_attachmentTools.GetCount(); i++)
{
ms_attachmentTools[i].Update();
}
}
u32 CScriptDebug::AddWidget(bkWidget *pWidget, eWidgetType WidgetType)
{
if (scriptVerifyf(CTheScripts::GetCurrentGtaScriptThread(), "CScriptDebug::AddWidget - can only add script widgets using script commands"))
{
#if __DEV
return CTheScripts::GetCurrentGtaScriptThread()->m_WidgetTree.AddWidget(pWidget, WidgetType, CTheScripts::GetCurrentScriptNameAndProgramCounter() );
#else
return CTheScripts::GetCurrentGtaScriptThread()->m_WidgetTree.AddWidget(pWidget, WidgetType, CTheScripts::GetCurrentGtaScriptThread()->GetScriptName() );
#endif
}
return 0;
}
u32 CScriptDebug::GetUniqueWidgetIdOfTopLevelWidget()
{
if (scriptVerifyf(CTheScripts::GetCurrentGtaScriptThread(), "CScriptDebug::GetUniqueWidgetIdOfTopLevelWidget - can only call this while processing scripts"))
{
#if __DEV
return CTheScripts::GetCurrentGtaScriptThread()->m_WidgetTree.GetUniqueWidgetIdOfTopLevelWidget(CTheScripts::GetCurrentScriptNameAndProgramCounter() );
#else
return CTheScripts::GetCurrentGtaScriptThread()->m_WidgetTree.GetUniqueWidgetIdOfTopLevelWidget(CTheScripts::GetCurrentGtaScriptThread()->GetScriptName() );
#endif
}
return 0;
}
extern void UpdatePos1(void);
extern void UpdatePos2(void);
void CScriptDebug::ActivateBank()
{
ms_pBank->PushGroup("Script Debug Tools", false);
ms_pBank->AddButton("Enable / Disable Debugging", ToggleClickingObjectsCB);
ms_pBank->AddToggle("Enable Debugging", &ms_bEnablePedDragging, ActivateClickingObjectsCB);
ms_pBank->AddText("Cursor Pos", ms_CreatePos, sizeof(ms_CreatePos),false);
ms_pBank->PushGroup("Floating Cursors (use in water / space levels where there is no ground) ", false);
ms_pBank->AddToggle("Activate floating cursor ", &ms_bUseLineofSight);
ms_pBank->AddSlider("Cursor offset (up/down arrows)", &ms_fPosFromCameraFront, 0.0f, 3000.0f, 0.01f, NullCB, "Locate z dimension" );
ms_pBank->PopGroup();
ms_PedHandler.CreateWidgets(ms_pBank);
ms_VehicleHandler.CreateWidgets(ms_pBank);
ms_ObjectHandler.CreateWidgets(ms_pBank);
ms_pAttachmentGroup = ms_pBank->PushGroup("Attach objects");
{
ms_pBank->AddButton("Attach selected objects", AttachSelectedObjects);
ms_pBank->AddButton("Clear all attachments", ClearAttachments);
}
ms_pBank->PopGroup();
ms_LocateHandler.CreateWidgets(ms_pBank);
ms_pBank->PushGroup("Measuring Tool",false);
ms_pBank->AddToggle( "Turn on tool", &CPhysics::ms_bDebugMeasuringTool );
ms_pBank->AddText("Pos1", CPhysics::ms_Pos1, sizeof(CPhysics::ms_Pos1), false, UpdatePos1);
ms_pBank->AddText("Pos2", CPhysics::ms_Pos2, sizeof(CPhysics::ms_Pos2), false, UpdatePos2);
ms_pBank->AddText("Diff", CPhysics::ms_Diff, sizeof(CPhysics::ms_Diff), false);
ms_pBank->AddText("HeadingBetween", CPhysics::ms_HeadingDiffRadians, sizeof(CPhysics::ms_HeadingDiffRadians), false);
ms_pBank->AddText("Distance", CPhysics::ms_Distance, sizeof(CPhysics::ms_Distance), false);
ms_pBank->AddText("Horizontal dist", CPhysics::ms_HorizDistance, sizeof(CPhysics::ms_HorizDistance), false);
ms_pBank->AddText("Vertical dist", CPhysics::ms_VerticalDistance, sizeof(CPhysics::ms_VerticalDistance), false);
ms_pBank->PopGroup();
ms_pBank->PopGroup();
}
void CScriptDebug::DeactivateBank()
{
ms_ObjectHandler.RemoveWidgets();
ms_VehicleHandler.RemoveWidgets();
ms_pAttachmentGroup = NULL;
bkGroup* group = static_cast<bkGroup*>(BANKMGR.FindWidget("Script/Script Debug Tools"));
if (group)
{
group->Destroy();
}
}
void CScriptDebug::InitWidgets()
{
if (AssertVerify(!ms_pBank))
{
ms_pBank = fwDebugBank::CreateBank("Script", MakeFunctor(ActivateBank), MakeFunctor(DeactivateBank), MakeFunctor(CreatePermanentWidgets));
}
bkBank *pScriptDebuggerBank = BANKMGR.FindBank(pNameOfScriptDebuggerBank);
if (AssertVerify(!pScriptDebuggerBank))
{
pScriptDebuggerBank = &BANKMGR.CreateBank(pNameOfScriptDebuggerBank);
if (AssertVerify(pScriptDebuggerBank))
{
GtaThread::UpdateArrayOfNamesOfRunningThreads(sm_ThreadNamesForDebugger);
ms_pComboBoxOfScriptThreads = pScriptDebuggerBank->AddCombo("Launch Debugger for Script", &sm_ArrayIndexOfThreadToAttachDebuggerTo,
sm_ThreadNamesForDebugger.GetCount(), &sm_ThreadNamesForDebugger[0]);
pScriptDebuggerBank->AddButton("Launch Debugger for selected script", LaunchDebuggerForThreadSelectedInCombo);
}
}
#if __BANK
CAnimPlacementEditor::Initialise();
#endif // __BANK
}
void CScriptDebug::CreatePermanentWidgets(fwDebugBank* pBank)
{
pBank->AddToggle("Display Running Scripts", &ms_bDisplayRunningScripts);
#if __REPORT_TOO_MANY_RESOURCES
pBank->AddToggle("Display Number of Script Resources", &ms_bDisplayNumberOfScriptResources);
#endif // __REPORT_TOO_MANY_RESOURCES
pBank->AddToggle("Display REQUEST_SCRIPT calls", &ms_bDisplayScriptRequests);
pBank->AddToggle("Print Current Contents of Cleanup Array", &ms_bPrintCurrentContentsOfCleanupArray);
pBank->AddToggle("Autosave Enabled", &ms_bAutoSaveEnabled);
pBank->AddToggle("Perform Autosave", &ms_bPerformAutoSave);
#if RSG_PC
pBank->AddToggle("Fake Script Tamper", &ms_bFakeTampering);
#endif
#if SCRIPT_PROFILING
if (scrThread::IsProfilingEnabled()) {
pBank->AddToggle("Display Script Profile Overview", &ms_bDisplayProfileOverview);
pBank->AddSlider("Profile Display Height", &ms_ProfileDisplayStartRow, 0, 60, 1);
pBank->AddCombo("Sort Profile by", &scrThread::sm_ProfileSortMethod, scrThread::sm_ProfileSortMethodCount, scrThread::sm_ProfileSortMethodStrings);
}
else
pBank->AddTitle("Add -scriptprofiling to cmd line for profiling");
#endif // SCRIPT_PROFILING
ms_FadeCommandTextContents[0] = '\0';
pBank->AddText("Last Fade Command", ms_FadeCommandTextContents, MAX_LENGTH_OF_FADE_COMMAND_TEXT_WIDGET, true);
pBank->AddToggle("Fade in after load (read-only)", &ms_bFadeInAfterLoadReadOnly);
pBank->AddToggle("Draw Debug Lines And Spheres", &ms_bDrawDebugLinesAndSpheres);
pBank->AddToggle("Debug Mask Commands", &ms_bDebugMaskCommands);
pBank->AddToggle("Print Suppressed Car Models", &ms_bPrintSuppressedCarModels);
pBank->AddToggle("Print Suppressed Ped Models", &ms_bPrintSuppressedPedModels);
pBank->AddToggle("Print Restricted Ped Models", &ms_bPrintRestrictedPedModels);
pBank->AddToggle("Output Script Display Text Commands", &ms_bOutputScriptDisplayTextCommands);
pBank->AddSlider("Number Of Frames To Output Script Display Text Commands", &ms_NumberOfFramesToOutputScriptDisplayTextCommands, -1, 300, 1);
pBank->AddToggle("Print List of Sprites When Limit is Hit", &ms_bOutputListOfAllScriptSpritesWhenLimitIsHit);
// pBank->AddText("ScriptId for debugging", ms_ScriptThreadIdForDebugging, sizeof(ms_ScriptThreadIdForDebugging), false);
// pBank->AddButton("Launch Debugger for this ScriptId", LaunchScriptDebuggerForSelectedId);
#if SCRIPT_PROFILING
if (scrThread::IsProfilingEnabled())
{
pBank->AddButton("Enable Profiling for selected script", EnableProfilingForThreadSelectedInCombo);
}
else
{
pBank->AddTitle("Add -scriptprofiling to cmd line for profiling");
}
#endif // SCRIPT_PROFILING
pBank->PushGroup("Markers for Area Check Commands");
pBank->AddSlider("Distance Threshold (Near)", &CScriptAreas::ms_distThreshNear, 0.0f, 100.0f, 0.25f);
pBank->AddSlider("Distance Threshold (Far)", &CScriptAreas::ms_distThreshFar, 0.0f, 100.0f, 0.25f);
pBank->AddSlider("Alpha (Near)", &CScriptAreas::ms_alphaNear, 0, 255, 1);
pBank->AddSlider("Alpha (Far)", &CScriptAreas::ms_alphaFar, 0, 255, 1);
pBank->AddToggle("Arrow - Enabled", &CScriptAreas::ms_arrowEnabled);
pBank->AddSlider("Arrow - Offset Z", &CScriptAreas::ms_arrowOffsetZ, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Arrow - Scale (Near)", &CScriptAreas::ms_arrowScaleNear, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Arrow - Scale (Far)", &CScriptAreas::ms_arrowScaleFar, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Cylinder - Offset Z", &CScriptAreas::ms_cylinderOffsetZ, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Cylinder - Scale XY (Near)", &CScriptAreas::ms_cylinderScaleXYNear, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Cylinder - Scale XY (Far)", &CScriptAreas::ms_cylinderScaleXYFar, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Cylinder - Scale Z (Near)", &CScriptAreas::ms_cylinderScaleZNear, -5.0f, 25.0f, 0.1f);
pBank->AddSlider("Cylinder - Scale Z (Far)", &CScriptAreas::ms_cylinderScaleZFar, -5.0f, 25.0f, 0.1f);
pBank->PopGroup();
pBank->PushGroup("DeathArrest Respawn Controls");
pBank->AddToggle("Fade in after DeathArrest (read-only)", &ms_bFadeInAfterDeathArrestReadOnly);
pBank->AddToggle("Pause Death Arrest Restart (read-only)", &ms_bPauseDeathArrestRestartReadOnly);
pBank->AddToggle("Ignore Next Restart (read-only)", &ms_bIgnoreNextRestartReadOnly);
pBank->PopGroup();
// bkGroup* pGroup =
pBank->PushGroup("Network Command Options", false);
pBank->AddToggle("Write IS_NETWORK_SESSION Command", &ms_bWriteIS_NETWORK_SESSIONCommand);
pBank->AddToggle("Write NETWORK_HAVE_SUMMONS Command", &ms_bWriteNETWORK_HAVE_SUMMONSCommand);
pBank->AddToggle("Write IS_NETWORK_GAME_RUNNING Command", &ms_bWriteIS_NETWORK_GAME_RUNNINGCommand);
pBank->AddToggle("Write IS_NETWORK_PLAYER_ACTIVE Command", &ms_bWriteIS_NETWORK_PLAYER_ACTIVECommand);
pBank->AddToggle("Write PLAYER_WANTS_TO_JOIN_NETWORK_GAME Command", &ms_bWritePLAYER_WANTS_TO_JOIN_NETWORK_GAMECommand);
pBank->AddToggle("Write Network Commands To Script log file", &ms_bWriteNetworkCommandsToScriptLog);
pBank->AddToggle("Display Network Commands In Console", &ms_bDisplayNetworkCommandsInConsole);
pBank->PopGroup();
CTheScripts::GetScriptHandlerMgr().InitWidgets(pBank);
}
void CScriptDebug::LaunchDebuggerForThreadSelectedInCombo()
{
GtaThread::AllocateDebuggerForThreadInSlot(sm_ArrayIndexOfThreadToAttachDebuggerTo);
}
void CScriptDebug::EnableProfilingForThreadSelectedInCombo()
{
GtaThread::EnableProfilingForThreadInSlot(sm_ArrayIndexOfThreadToAttachDebuggerTo);
}
void CScriptDebug::LaunchScriptDebuggerForSelectedId()
{
s32 string_length = istrlen(ms_ScriptThreadIdForDebugging);
for (s32 loop = 0; loop < string_length; loop++)
{
if ( (ms_ScriptThreadIdForDebugging[loop] < '0') || (ms_ScriptThreadIdForDebugging[loop] > '9') )
{
scriptAssertf(0, "ScriptId for debugging should only contain numbers");
return;
}
}
s32 threadId = atoi(ms_ScriptThreadIdForDebugging);
GtaThread::AllocateDebuggerForThread((scrThreadId) threadId);
}
void CScriptDebug::SetContentsOfFadeCommandTextWidget(const char *pFadeCommandString)
{
#if __DEV
if (CTheScripts::GetCurrentGtaScriptThread())
{
sprintf(ms_FadeCommandTextContents, "Frame = %d %s %s", fwTimer::GetSystemFrameCount(), CTheScripts::GetCurrentScriptNameAndProgramCounter(), pFadeCommandString);
}
else
#endif
{
sprintf(ms_FadeCommandTextContents, "Frame = %d %s", fwTimer::GetSystemFrameCount(), pFadeCommandString);
}
}
#if SCRIPT_PROFILING
static s32 profileY;
static s32 profInt;
static void profDisplayf(bool severe,const char *fmt,...)
{
va_list args;
va_start(args,fmt);
// don't run off the bottom of the screen
if (!profileY)
return;
Color32 sevColor;
if (severe)
sevColor.Set(240,0,0);
else
sevColor.Set(240,240,240);
// grcDebugDraw::PrintToScreenCoors(buffer, 10, profileY, sevColor, false);
grcDebugDraw::AddDebugOutputExV(false,sevColor,fmt,args);
va_end(args);
--profileY;
// Periodic spacing so it's easier to read
if (++profInt == 4)
{
grcDebugDraw::AddDebugOutputSeparator(3);
profInt = 0;
}
}
void CScriptDebug::DisplayProfileOverviewOfAllThreads()
{
if (ms_bDisplayProfileOverview)
{
profileY = ms_ProfileDisplayStartRow;
profInt = 3; // for inserting a gap periodically so it's easier to read
scrThread::DisplayProfileOverview(profDisplayf);
}
}
void CScriptDebug::DisplayProfileDataForThisThread(GtaThread *pThread)
{
profileY = ms_ProfileDisplayStartRow;
profInt = 3; // for inserting a gap periodically so it's easier to read
pThread->DisplayProfileData(profDisplayf);
}
#endif // SCRIPT_PROFILING
//Get the mouse position so we have coords to create a ped
void CScriptDebug::UpdateCreatePos()
{
Vector3 vPos;
Vector3 vNormal;
void *entity;
bool bHasPosition = false;
if(ms_bUseLineofSight)
{
UpdateFloatingCreatePos(vPos);
bHasPosition = true;
}
else
{
bHasPosition = CDebugScene::GetWorldPositionUnderMouse(vPos, ArchetypeFlags::GTA_MAP_TYPE_WEAPON | ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_OBJECT_TYPE , &vNormal, &entity);
}
static bool sbLeftButtonHeld = false;
static bool sbRightButtonHeld = false;
if( ioMouse::GetPressedButtons() & ioMouse::MOUSE_LEFT )
{
sbLeftButtonHeld = true;
}
if( sbLeftButtonHeld &&
ioMouse::GetReleasedButtons() & ioMouse::MOUSE_LEFT )
{
sbLeftButtonHeld = false;
}
if( ioMouse::GetPressedButtons() & ioMouse::MOUSE_RIGHT )
{
sbRightButtonHeld = true;
}
if( sbRightButtonHeld &&
ioMouse::GetReleasedButtons() & ioMouse::MOUSE_RIGHT )
{
sbRightButtonHeld = false;
}
if( bHasPosition )
{
if( sbLeftButtonHeld )
{
ms_vClickedPos = vPos;
ms_vClickedNormal = vNormal;
sprintf(ms_CreatePos, "%.2f, %.2f, %.2f", ms_vClickedPos.x, ms_vClickedPos.y, ms_vClickedPos.z);
}
if (sbRightButtonHeld)
{
ms_vClickedPos2 = vPos;
ms_vClickedNormal2 = vNormal;
sprintf(ms_CreatePos, "%.2f, %.2f, %.2f", ms_vClickedPos2.x, ms_vClickedPos2.y, ms_vClickedPos2.z);
}
}
grcDebugDraw::Sphere(ms_vClickedPos, 0.1f, Color32(1.0f, 0.0f, 0.0f) );
if(!ms_bUseLineofSight)
{
grcDebugDraw::Line(ms_vClickedPos, ms_vClickedPos+(ms_vClickedNormal*0.4f), Color32(1.0f, 0.0f, 0.0f) );
}
ms_LocateHandler.DisplaySpheresForNonAxisAlignedLocate();
}
void CScriptDebug::UpdateFloatingCreatePos(Vector3 &CreatePos)
{
Vector3 vMouseNear, vMouseFar;
CDebugScene::GetMousePointing( vMouseNear, vMouseFar, false);
CEntity* pEntity = CDebugScene::GetEntityUnderMouse();
Vector3 vecCreateOffset = camInterface::GetFront();
Vector3 VecNearToFar = vMouseFar - vMouseNear;
VecNearToFar.Normalize();
if(ioMapper::DebugKeyDown(KEY_UP))
{
ms_fPosFromCameraFront += 0.1f;
}
if(ioMapper::DebugKeyDown(KEY_DOWN))
{
ms_fPosFromCameraFront -= 0.1f;
}
if( ioMouse::GetPressedButtons() & ioMouse::MOUSE_LEFT )
{
if (pEntity && (pEntity->GetIsTypeVehicle() || pEntity->GetIsTypeObject() || pEntity->GetIsTypePed()) )
{
Vector3 EntityPos = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
ms_fPosFromCameraFront = (EntityPos - vMouseNear).Dot(VecNearToFar);
}
}
CreatePos = vMouseNear + (VecNearToFar * ms_fPosFromCameraFront );
}
void CScriptDebug::ToggleClickingObjectsCB()
{
ms_bEnablePedDragging = !ms_bEnablePedDragging;
ActivateClickingObjectsCB();
}
void CScriptDebug::ActivateClickingObjectsCB()
{
if(!ms_bEnablePedDragging)
{
CPedDebugVisualiser::SetDebugDisplay(CPedDebugVisualiser::eOff);
}
else
{
CPedDebugVisualiser::SetDebugDisplay(CPedDebugVisualiser::ePedNames);
}
CDebugScene::SetClickForObjects(ms_bEnablePedDragging);
}
//Updates the script tools
void CScriptDebug::ProcessScriptDebugTools()
{
if (ms_bEnablePedDragging)
{
UpdateCreatePos();
ms_LocateHandler.DisplayScriptLocates();
ms_PedHandler.Process();
ms_VehicleHandler.Process();
ms_ObjectHandler.Process();
UpdateAttachmentTools();
}
}
CEntity* CScriptDebug::CreateScriptEntity(u32 modelIndex)
{
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(fwModelId(strLocalIndex(modelIndex)));
if(pModelInfo==NULL)
{
Displayf ("CScriptDebug::CreateScriptEntity - Invalid model: %d", modelIndex);
return NULL;
}
if(pModelInfo)
{
if (pModelInfo->GetModelType() == MI_TYPE_PED)
{
return ms_PedHandler.CreateScriptPed(modelIndex);
}
else if (pModelInfo->GetModelType() == MI_TYPE_VEHICLE)
{
return ms_VehicleHandler.CreateScriptVehicle(modelIndex);
}
else
{
return ms_ObjectHandler.CreateScriptObject(modelIndex);
}
}
return NULL;
}
void SaveVectorToDebugFile(const Vector3 &VecToDisplay)
{
char text[256];
formatf(text, 256, "<<%f,%f,%f>>", VecToDisplay.x, VecToDisplay.y, VecToDisplay.z );
CScriptDebug::OutputScript(text);
}
//////////////////////////////////////////////////////////////////////////
// CScriptDebugTextWidgets
//////////////////////////////////////////////////////////////////////////
void CScriptDebugTextWidgets::Init()
{
for (u32 Counter = 0; Counter < MAX_NUMBER_OF_TEXT_WIDGETS; Counter++)
{
for (u32 Counter2 = 0; Counter2 < TextEditWidgetForScript::MAX_CHARACTERS_FOR_TEXT_WIDGET; Counter2++)
{
TextWidgets[Counter].WidgetTextContents[Counter2] = '\0';
}
TextWidgets[Counter].pWidget = NULL;
}
scriptDisplayf("CScriptDebugTextWidgets::Init - sizeof(TextEditWidgetForScript) = %d bytes, MAX_NUMBER_OF_TEXT_WIDGETS = %d, sizeof(CScriptDebugTextWidgets) = %d bytes",
(s32) sizeof(TextEditWidgetForScript), MAX_NUMBER_OF_TEXT_WIDGETS, (s32) sizeof(CScriptDebugTextWidgets) );
}
s32 CScriptDebugTextWidgets::FindFreeTextWidget()
{
s32 loop = 0;
while (loop < MAX_NUMBER_OF_TEXT_WIDGETS)
{
if (TextWidgets[loop].pWidget == NULL)
{
return loop;
}
loop++;
}
#if __ASSERT
scriptDisplayf("FindFreeTextWidget - no free text widgets. All %d text widgets have been used.", MAX_NUMBER_OF_TEXT_WIDGETS);
for (loop = 0; loop < MAX_NUMBER_OF_TEXT_WIDGETS; loop++)
{
if (TextWidgets[loop].pWidget)
{
scriptDisplayf("Text Widget %d has name %s", loop, TextWidgets[loop].pWidget->GetTitle());
}
}
scriptAssertf(0, "CTheScripts::FindFreeTextWidget - no free text widgets. All %d text widgets have been used.", MAX_NUMBER_OF_TEXT_WIDGETS);
#endif // __ASSERT
return -1;
}
s32 CScriptDebugTextWidgets::AddTextWidget(const char *pName)
{
s32 TextWidgetArrayIndex = FindFreeTextWidget();
if (TextWidgetArrayIndex >= 0)
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
strcpy(TextWidgets[TextWidgetArrayIndex].WidgetTextContents, "New text widget");
TextWidgets[TextWidgetArrayIndex].pWidget = CScriptDebug::GetWidgetBank()->AddText(pName, TextWidgets[TextWidgetArrayIndex].WidgetTextContents, TextEditWidgetForScript::MAX_CHARACTERS_FOR_TEXT_WIDGET, false);
return CScriptDebug::AddWidget(TextWidgets[TextWidgetArrayIndex].pWidget, WIDGETTYPE_TEXT);
}
}
return 0;
}
const char *CScriptDebugTextWidgets::GetContentsOfTextWidget(s32 UniqueTextWidgetIndex)
{
// scan through the existing widgets for the one that has a widget pointer that matches the widget pointer for TextWidgetIndex
if(scriptVerifyf(UniqueTextWidgetIndex > 0, "%s:CScriptDebug::GetContentsOfTextWidget - Text Widget Index should be 1 or greater", CTheScripts::GetCurrentScriptNameAndProgramCounter()))
{
bkText *pWidgetToMatch = static_cast<bkText*>(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(UniqueTextWidgetIndex));
for (s32 loop = 0; loop < MAX_NUMBER_OF_TEXT_WIDGETS; loop++)
{
if (TextWidgets[loop].pWidget == pWidgetToMatch)
{
return TextWidgets[loop].WidgetTextContents;
}
}
scriptAssertf(0, "%s:CScriptDebug::GetContentsOfTextWidget - couldn't find a text widget with this ID", CTheScripts::GetCurrentScriptNameAndProgramCounter());
}
return NULL;
}
void CScriptDebugTextWidgets::SetContentsOfTextWidget(s32 UniqueTextWidgetIndex, const char *pNewContents)
{
// scan through the existing widgets for the one that has a widget pointer that matches the widget pointer for TextWidgetIndex
if(scriptVerifyf(UniqueTextWidgetIndex > 0, "%s:CScriptDebug::SetContentsOfTextWidget - Text Widget Index should be 1 or greater", CTheScripts::GetCurrentScriptNameAndProgramCounter()))
{
bkText *pWidgetToMatch = static_cast<bkText*>(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(UniqueTextWidgetIndex));
for (s32 loop = 0; loop < MAX_NUMBER_OF_TEXT_WIDGETS; loop++)
{
if (TextWidgets[loop].pWidget == pWidgetToMatch)
{
strncpy(TextWidgets[loop].WidgetTextContents, pNewContents, TextEditWidgetForScript::MAX_CHARACTERS_FOR_TEXT_WIDGET);
TextWidgets[loop].WidgetTextContents[TextEditWidgetForScript::MAX_CHARACTERS_FOR_TEXT_WIDGET-1] = '\0';
return;
}
}
scriptAssertf(0, "%s:CScriptDebug::SetContentsOfTextWidget - couldn't find a text widget with this ID", CTheScripts::GetCurrentScriptNameAndProgramCounter());
}
}
void CScriptDebugTextWidgets::ClearTextWidget(bkText *pWidgetToMatch)
{
for (s32 loop = 0; loop < MAX_NUMBER_OF_TEXT_WIDGETS; loop++)
{
if (TextWidgets[loop].pWidget == pWidgetToMatch)
{
// Do I leave it up to the first widget group (the one that should contain all the other widgets)
// to actually delete this bkText widget?
TextWidgets[loop].pWidget = NULL;
}
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugTextWidgets
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptDebugBitFieldWidgets
//////////////////////////////////////////////////////////////////////////
void CScriptDebugBitFieldWidgets::WidgetBitFieldStruct::Init()
{
pGroup = NULL; // pointer to outermost widget group
for (s32 loop = 0; loop < 32; loop++)
{
bBits[loop] = false;
// pBitToggles[loop] = NULL; // or should these be pointers to bkWidget. Do I actually need to store these at all? Are they ever referred to?
}
pBitFieldWithinScript = NULL;
PreviousFrameBitField = 0;
}
void CScriptDebugBitFieldWidgets::Init()
{
for (u32 Counter = 0; Counter < MAX_NUMBER_OF_BIT_FIELD_WIDGETS; Counter++)
{
BitFields[Counter].Init();
}
}
s32 CScriptDebugBitFieldWidgets::FindFreeBitFieldWidget()
{
s32 loop = 0;
while (loop < MAX_NUMBER_OF_BIT_FIELD_WIDGETS)
{
if (BitFields[loop].pGroup == NULL)
{
return loop;
}
loop++;
}
scriptAssertf(0, "CScriptDebugBitFieldWidgets::FindFreeBitFieldWidget - no free bit field widgets");
return -1;
}
s32 CScriptDebugBitFieldWidgets::AddBitFieldWidget(const char *pName, s32& value)
{
s32 BitFieldWidgetArrayIndex = FindFreeBitFieldWidget();
if (BitFieldWidgetArrayIndex >= 0)
{
if (Verifyf(CScriptDebug::GetWidgetBank(), "There is no script widget bank"))
{
BitFields[BitFieldWidgetArrayIndex].pBitFieldWithinScript = &value;
BitFields[BitFieldWidgetArrayIndex].PreviousFrameBitField = 0;
BitFields[BitFieldWidgetArrayIndex].pGroup = CScriptDebug::GetWidgetBank()->PushGroup(pName, false);
s32 UniqueID = CScriptDebug::AddWidget(BitFields[BitFieldWidgetArrayIndex].pGroup, WIDGETTYPE_BITFIELD);
for (s32 byte_loop = 0; byte_loop < 4; byte_loop++)
{
s32 FirstBitIndex = byte_loop * 8;
s32 LastBitIndex = FirstBitIndex + 7;
char SubGroupName[16];
sprintf(SubGroupName, "Bits %d to %d", FirstBitIndex, LastBitIndex);
/* bkGroup* pByteGroup = */ CScriptDebug::GetWidgetBank()->PushGroup(SubGroupName, false);
for (s32 bit_loop = FirstBitIndex; bit_loop <= LastBitIndex; bit_loop++)
{
char BitName[8];
sprintf(BitName, "Bit %d", bit_loop);
BitFields[BitFieldWidgetArrayIndex].bBits[bit_loop] = false;
// BitFields[BitFieldWidgetArrayIndex].pBitToggles[bit_loop] =
CScriptDebug::GetWidgetBank()->AddToggle(BitName, &BitFields[BitFieldWidgetArrayIndex].bBits[bit_loop]);
}
CScriptDebug::GetWidgetBank()->PopGroup();
}
CScriptDebug::GetWidgetBank()->PopGroup();
return UniqueID;
}
}
return 0;
}
void CScriptDebugBitFieldWidgets::UpdateBitFields()
{
for (s32 loop = 0; loop < MAX_NUMBER_OF_BIT_FIELD_WIDGETS; loop++)
{
if (BitFields[loop].pBitFieldWithinScript)
{
for (s32 bit_loop = 0; bit_loop < 32; bit_loop++)
{
bool bCurrentBit = (*(BitFields[loop].pBitFieldWithinScript) & (0x01 << bit_loop)) != 0;
bool bPreviousBit = (BitFields[loop].PreviousFrameBitField & (0x01 << bit_loop)) != 0;
if (bCurrentBit != bPreviousBit)
{ // bit has been changed by script so update the widget and the previous bit
BitFields[loop].bBits[bit_loop] = bCurrentBit;
if (bCurrentBit)
{
BitFields[loop].PreviousFrameBitField |= (0x01 << bit_loop);
}
else
{
BitFields[loop].PreviousFrameBitField &= ~(0x01 << bit_loop);
}
}
else
{
if (BitFields[loop].bBits[bit_loop] != bPreviousBit)
{ // widget has changed so update the current and previous bit
if (BitFields[loop].bBits[bit_loop])
{
*(BitFields[loop].pBitFieldWithinScript) |= (0x01 << bit_loop);
BitFields[loop].PreviousFrameBitField |= (0x01 << bit_loop);
}
else
{
*(BitFields[loop].pBitFieldWithinScript) &= ~(0x01 << bit_loop);
BitFields[loop].PreviousFrameBitField &= ~(0x01 << bit_loop);
}
}
}
}
}
}
}
void CScriptDebugBitFieldWidgets::ClearBitFieldWidget(bkGroup *pWidgetGroupToMatch)
{
for (s32 loop = 0; loop < MAX_NUMBER_OF_BIT_FIELD_WIDGETS; loop++)
{
if (BitFields[loop].pGroup == pWidgetGroupToMatch)
{
// Do I leave it up to the first widget group (the one that should contain all the other widgets)
// to actually delete the bit field widget group (i.e. the bkGroup and all the bkToggle's it contains)?
BitFields[loop].Init();
}
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugBitFieldWidgets
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptDebugLocateHandler
//////////////////////////////////////////////////////////////////////////
CScriptDebugLocateHandler::CScriptDebugLocateHandler()
{
m_AxisAlignLocateName[0] = '\0';
m_NonAxisAlignLocateName[0] = '\0';
m_AxisAlignedLocate = false;
m_NonAxisAlignedLocate = false;
m_AreaWidth = 1.0f;
m_SphereLocate = false;
m_Radius = 1.0f;
m_fLocateOffset = 0.0f;
m_fLocateOffset2 = 1.0f;
m_VecLocateDimensions = VEC3_IDENTITY;
}
void CScriptDebugLocateHandler::CreateWidgets(bkBank* pBank)
{
const float MAX_LOCATE_SIZE = 10000.0f; //B*1756412
pBank->PushGroup("Locates", false);
pBank->PushGroup("Axis Aligned Locate", false);
pBank->AddToggle("Activate Axis aligned locate", &m_AxisAlignedLocate);
pBank->AddSlider("Locate dimension x", &m_VecLocateDimensions.x, 0.0f, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate x dimension" );
pBank->AddSlider("Locate dimension y", &m_VecLocateDimensions.y, 0.0f, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate y dimension" );
pBank->AddSlider("Locate dimension z", &m_VecLocateDimensions.z, 0.0f, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension" );
pBank->AddSlider("Offset z from ground", &m_fLocateOffset, -MAX_LOCATE_SIZE, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension");
pBank->AddText("Locate Name", m_AxisAlignLocateName, sizeof(m_AxisAlignLocateName), false);
pBank->AddButton("Print Axis aligned locate info", datCallback(MFA(CScriptDebugLocateHandler::GetLocateDebugInfo), (datBase*)this));
pBank->PopGroup();
pBank->PushGroup("Non-Axis Aligned Locate", false);
pBank->AddToggle("Activate Non-Axis aligned locate", &m_NonAxisAlignedLocate);
pBank->AddSlider("Pos Vec1 z offset (L Mouse Btn)", &m_fLocateOffset, -MAX_LOCATE_SIZE, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension" );
pBank->AddSlider("Pos Vec2f z offset (R Mouse Btn)", &m_fLocateOffset2, -MAX_LOCATE_SIZE, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension" );
pBank->AddSlider("Locate Width", &m_AreaWidth, 0.0f, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension" );
pBank->AddText("Locate Name", m_NonAxisAlignLocateName, sizeof(m_NonAxisAlignLocateName), false);
pBank->AddButton("Print non-Axis aligned locate info", datCallback(MFA(CScriptDebugLocateHandler::GetLocateDebugInfo), (datBase*)this));
pBank->PopGroup();
pBank->PushGroup("Sphere Locate");
pBank->AddToggle("Sphere locate", &m_SphereLocate);
pBank->AddSlider("Locate Radius", &m_Radius, 0.0f, MAX_LOCATE_SIZE, 0.25f, NullCB, "Sphere radius" );
pBank->AddSlider("Offset z from ground", &m_fLocateOffset, -MAX_LOCATE_SIZE, MAX_LOCATE_SIZE, 0.25f, NullCB, "Locate z dimension" );
pBank->AddButton("Print sphere locate info", datCallback(MFA(CScriptDebugLocateHandler::GetLocateDebugInfo), (datBase*)this));
pBank->PopGroup();
pBank->PopGroup();
}
void CScriptDebugLocateHandler::DisplayScriptLocates()
{
if (m_SphereLocate)
{
Vector3 VecCoors = CScriptDebug::GetClickedPos();
VecCoors.z += m_fLocateOffset;
grcDebugDraw::Sphere(VecCoors, m_Radius, Color32(0,0,255,255) ,false);
}
if (m_AxisAlignedLocate)
{
Vector3 VecCoors = CScriptDebug::GetClickedPos();
VecCoors.z += m_VecLocateDimensions.z + m_fLocateOffset;
CScriptDebug::DrawDebugCube((VecCoors.x - m_VecLocateDimensions.x), (VecCoors.y - m_VecLocateDimensions.y), (VecCoors.z - m_VecLocateDimensions.z),
(VecCoors.x + m_VecLocateDimensions.x), (VecCoors.y + m_VecLocateDimensions.y), (VecCoors.z + m_VecLocateDimensions.z));
}
if(m_NonAxisAlignedLocate)
{
Vector3 vAreaStart = CScriptDebug::GetClickedPos();
vAreaStart.z += m_fLocateOffset;
Vector3 vAreaEnd = CScriptDebug::GetClickedPos2();
vAreaEnd.z += m_fLocateOffset2;
float RadiansBetweenFirstTwoPoints;
float RadiansBetweenPoints1and4;
Vector3 temp_vec;
if (vAreaStart.z > vAreaEnd.z)
{
temp_vec = vAreaStart;
vAreaStart = vAreaEnd;
vAreaEnd = temp_vec;
}
// calculate the angle between vectors
RadiansBetweenFirstTwoPoints = fwAngle::GetRadianAngleBetweenPoints(vAreaStart.x, vAreaStart.y, vAreaEnd.x, vAreaEnd.y);
// get the right angle from these 2 points
RadiansBetweenPoints1and4 = RadiansBetweenFirstTwoPoints + (PI / 2);
//work out a right angle from point
while (RadiansBetweenPoints1and4 < 0.0f)
{
RadiansBetweenPoints1and4 += (2 * PI);
}
while (RadiansBetweenPoints1and4 > (2 * PI))
{
RadiansBetweenPoints1and4 -= (2 * PI);
}
const Vector2 vBottomLeft (((m_AreaWidth * 0.5f) * rage::Sinf(RadiansBetweenPoints1and4)) + vAreaStart.x, ((m_AreaWidth * 0.5f) * -rage::Cosf(RadiansBetweenPoints1and4)) + vAreaStart.y) ;
const Vector2 vBottomRight (((m_AreaWidth * 0.5f) * rage::Sinf(RadiansBetweenPoints1and4)) + vAreaEnd.x, ((m_AreaWidth * 0.5f) * -rage::Cosf(RadiansBetweenPoints1and4)) + vAreaEnd.y);
const Vector2 vTopLeft( vAreaStart.x, vAreaStart.y );
const Vector2 vTopRight( vAreaEnd.x, vAreaEnd.y );
//calculate the vectors across the locate and to one corner, used when checking against the players vector
// Vector2 vec1To2 = vTopRight - vTopLeft;
Vector2 vec1To4 = vTopLeft - vBottomLeft;
// used for drawing the locate area
Vector2 vec1To4Copy = vec1To4;
CScriptDebug::DrawDebugAngledCube(vAreaStart.x + vec1To4Copy.x, vAreaStart.y + vec1To4Copy.y, vAreaStart.z, vAreaEnd.x + vec1To4Copy.x, vAreaEnd.y + vec1To4Copy.y, vAreaEnd.z, vBottomRight.x, vBottomRight.y,
vBottomLeft.x, vBottomLeft.y);
}
}
void CScriptDebugLocateHandler::DisplaySpheresForNonAxisAlignedLocate()
{
if (m_NonAxisAlignedLocate)
{
Vector3 Clickpos = CScriptDebug::GetClickedPos();
Clickpos.z += m_fLocateOffset;
grcDebugDraw::Sphere(Clickpos, 0.05f, Color32(1.0f, 0.0f, 0.0f) );
Clickpos = CScriptDebug::GetClickedPos2();
grcDebugDraw::Sphere(Clickpos, 0.1f, Color32(1.0f, 0.0f, 1.0f) );
// Ask Tom if the following two lines should only be done if(!ms_bUseLineofSight)
Vector3 vecNormal = CScriptDebug::GetClickedNormal2();
grcDebugDraw::Line(Clickpos, Clickpos+(vecNormal*0.4f), Color32(1.0f, 0.0f, 1.0f) );
Clickpos.z += m_fLocateOffset2;
grcDebugDraw::Sphere(Clickpos, 0.05f, Color32(1.0f, 0.0f, 1.0f) );
}
}
void CScriptDebugLocateHandler::GetLocateDebugInfo()
{
Vector3 VecCoors = VEC3_ZERO;
char text[256];
if (m_SphereLocate)
{
VecCoors = CScriptDebug::GetClickedPos();
if (!CScriptDebug::GetUseLineofSight())
{
VecCoors.z += m_fLocateOffset;
}
formatf(text, 256, "\n//sphere Locate Info\nRadius = %f\nPos = <<%f,%f,%f>> ",m_Radius,VecCoors.x, VecCoors.y, VecCoors.z );
CScriptDebug::OutputScript(text);
}
if(m_AxisAlignedLocate)
{
VecCoors = CScriptDebug::GetClickedPos();
if (!CScriptDebug::GetUseLineofSight())
{
VecCoors.z += m_VecLocateDimensions.z + m_fLocateOffset;
}
formatf(text, 256, "\n// Locate Info\nLocate Name:%s\nVECTORv %spos = <<%f,%f,%f>> )", m_AxisAlignLocateName, m_AxisAlignLocateName,VecCoors.x, VecCoors.y, VecCoors.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nVECTOR v%sSize = <<%f,%f,%f>>\n", m_AxisAlignLocateName,m_VecLocateDimensions.x, m_VecLocateDimensions.y, m_VecLocateDimensions.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nIS_ENTITY_AT_COORD(PedIndex, v%sPos,v%sSize)", m_AxisAlignLocateName,m_AxisAlignLocateName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nIS_ENTITY_AT_COORD(PedIndex, <<%f,%f,%f>>,<<%f,%f,%f>>)", VecCoors.x,VecCoors.y,VecCoors.z ,m_VecLocateDimensions.x, m_VecLocateDimensions.y, m_VecLocateDimensions.z);
CScriptDebug::OutputScript(text);
sprintf(m_AxisAlignLocateName, "");
}
if(m_NonAxisAlignedLocate)
{
VecCoors = CScriptDebug::GetClickedPos();
VecCoors.z += m_fLocateOffset;
Vector3 VecCoors2 = CScriptDebug::GetClickedPos2();
VecCoors2.z += m_fLocateOffset2;
formatf(text, 256, "// Angled Area Info\nLocate name:%s\nVECTOR v%sPos1 = <<%f,%f,%f>>", m_NonAxisAlignLocateName, m_NonAxisAlignLocateName,VecCoors.x, VecCoors.y, VecCoors.z, m_NonAxisAlignLocateName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "VECTOR v%sPos2 = <<%f,%f,%f>> ",m_NonAxisAlignLocateName,VecCoors2.x, VecCoors2.y, VecCoors2.z );
CScriptDebug::OutputScript(text);
formatf(text, 256, "FLOAT f%sWidth = %f",m_NonAxisAlignLocateName,m_AreaWidth );
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nIS_ENTITY_IN_ANGLED_AREA( PedIndex, v%sPos1, v%sPos2, f%sWidth)",m_NonAxisAlignLocateName,m_NonAxisAlignLocateName, m_NonAxisAlignLocateName );
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nIS_ENTITY_IN_ANGLED_AREA( PedIndex, <<%f,%f,%f>>, <<%f,%f,%f>>, %f)",VecCoors.x, VecCoors.y, VecCoors.z,VecCoors2.x, VecCoors2.y, VecCoors2.z, m_AreaWidth);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_PED_ANGLED_DEFENSIVE_AREA( PedIndex, v%sPos1, v%sPos2, f%sWidth)",m_NonAxisAlignLocateName,m_NonAxisAlignLocateName, m_NonAxisAlignLocateName );
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_PED_ANGLED_DEFENSIVE_AREA( PedIndex, <<%f,%f,%f>>, <<%f,%f,%f>>, %f)",VecCoors.x, VecCoors.y, VecCoors.z,VecCoors2.x, VecCoors2.y, VecCoors2.z, m_AreaWidth);
CScriptDebug::OutputScript(text);
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugLocateHandler
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptDebugPedHandler
//////////////////////////////////////////////////////////////////////////
/* See if this is needed at all
CScriptDebugPedHandler::CScriptDebugPedHandler()
{
m_PedPos[0] = '\0';
m_PedHeading[0] = '\0';
m_PedName[0] = '\0';
m_PedModelName[0] = '\0';
}
*/
void CScriptDebugPedHandler::CreateWidgets(bkBank* pBank)
{
pBank->PushGroup("Peds", false);
pBank->AddButton("Create Ped",datCallback(MFA(CScriptDebugPedHandler::CreateScriptPedUsingTheSelectedModel), (datBase*)this));
m_pedSelector.AddWidgets(pBank, "Ped Model");
pBank->AddText("OR - enter vehicle name", &m_searchPedName[0], STORE_NAME_LENGTH);
pBank->AddButton("Delete Ped",datCallback(MFA(CScriptDebugPedHandler::DeleteScriptPed), (datBase*)this));
pBank->AddText("Ped pos", m_PedPos, sizeof(m_PedPos),false, datCallback(MFA(CScriptDebugPedHandler::SetPedPosCB), (datBase*)this));
pBank->AddText("Ped Heading", m_PedHeading, sizeof(m_PedHeading),false, datCallback(MFA(CScriptDebugPedHandler::SetPedHeadingCB), (datBase*)this));
pBank->AddText("Ped Model Name", m_PedModelName, sizeof(m_PedModelName),false);
pBank->AddText("Ped Debug Name", m_PedName, sizeof(m_PedName), false, datCallback(MFA(CScriptDebugPedHandler::SetDebugPedName), (datBase*)this));
pBank->AddButton("Print Ped info", datCallback(MFA(CScriptDebugPedHandler::GetPedDebugInfo), (datBase*)this));
pBank->PopGroup();
}
void CScriptDebugPedHandler::Process()
{
CPed *pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
const Vector3 vPedPosition = VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition());
sprintf(m_PedPos, "%.2f, %.2f, %.2f", vPedPosition.x, vPedPosition.y, vPedPosition.z);
sprintf(m_PedHeading, "%.2f", RtoD*pPed->GetTransform().GetHeading());
sprintf(m_PedName, "%s", pPed->m_debugPedName);
sprintf(m_PedModelName, "%s", CModelInfo::GetBaseModelInfoName(pPed->GetModelId()));
}
else
{
sprintf(m_PedPos, " ");
sprintf(m_PedHeading, " ");
sprintf(m_PedName, " ");
}
}
// RegdPed pPedScriptPed(NULL);
void CScriptDebugPedHandler::CreateScriptPedUsingTheSelectedModel()
{
u32 nModelIndex = CModelInfo::GetModelIdFromName(m_searchPedName).GetModelIndex();
if (CModelInfo::IsValidModelInfo(nModelIndex))
{
//load the entered ped
CreateScriptPed(nModelIndex);
}
else
{
//load the selected ped
nModelIndex = CModelInfo::GetModelIdFromName(m_pedSelector.GetSelectedModelName()).GetModelIndex();
CreateScriptPed(nModelIndex);
}
}
CPed* CScriptDebugPedHandler::CreateScriptPed(u32 modelIndex)
{
Matrix34 TempMat;
TempMat.Identity();
Vector3 vecCreateOffset = CScriptDebug::GetClickedPos();
vecCreateOffset.z += 1.0f;
TempMat.d += vecCreateOffset;
u32 pedInfoIndex = modelIndex;
const CControlledByInfo localAiControl(false, false);
// don't allow the creation of player ped type - it doesn't work!
if (pedInfoIndex == CGameWorld::FindLocalPlayer()->GetModelIndex()) {return NULL;}
fwModelId pedInfoId((strLocalIndex(pedInfoIndex)));
// ensure that the model is loaded and ready for drawing for this ped
if (!CModelInfo::HaveAssetsLoaded(pedInfoId))
{
CModelInfo::RequestAssets(pedInfoId, STRFLAG_FORCE_LOAD|STRFLAG_PRIORITY_LOAD);
CStreaming::LoadAllRequestedObjects(true);
}
CPed* pPed = CPedFactory::GetFactory()->CreatePed(localAiControl, pedInfoId, &TempMat, true, true, true);
pPed->SetVarRandom(PV_FLAG_NONE, PV_FLAG_NONE, NULL, NULL, NULL, PV_RACE_UNIVERSAL);
pPed->SetupMissionState();
pPed->PopTypeSet(POPTYPE_TOOL);
pPed->SetBlockingOfNonTemporaryEvents(true);
pPed->SetPedConfigFlag( CPED_CONFIG_FLAG_DrownsInWater, false );
pPed->GetPortalTracker()->RequestRescanNextUpdate();
pPed->GetPortalTracker()->Update(VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition()));
CGameWorld::Add(pPed, CGameWorld::OUTSIDE );
return pPed;
}
//delete a created ped
void CScriptDebugPedHandler::DeleteScriptPed()
{
CPed * pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
if (!pPed->IsLocalPlayer())
{
CPedFactory::GetFactory()->DestroyPed(pPed);
}
}
}
bool CScriptDebugPedHandler::GetVectorFromTextBox(Vector3 &vPos, const char* textbox)
{
Vector3 vecPos(VEC3_ZERO);
// Try to parse the line.
int nItems = 0;
{
// Make a copy of this string as strtok will destroy it.
Assertf( (strlen(textbox) < 256), "Warp position line is too long to copy.");
char warpPositionLine[256];
safecpy(warpPositionLine, textbox, 256);
// Get the locations to store the float values into.
float* apVals[3] = {&vecPos.x, &vecPos.y, &vecPos.z};
// 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 < 4), "Too many tokens in warp position line." );
}
pToken = strtok(NULL, seps);
}
}
if(nItems)
{
vPos.x = vecPos.x;
vPos.y = vecPos.y;
vPos.z = vecPos.z;
return true;
}
return false;
}
bool CScriptDebugPedHandler::GetFloatFromTextBox(float &fHeading, const char* textbox)
{
// Try to parse the line.
int nItems = 0;
{
// Make a copy of this string as strtok will destroy it.
Assertf( (strlen(textbox) < 256), "Warp position line is too long to copy.");
char warpPositionLine[256];
safecpy(warpPositionLine, textbox, 256);
// Get the locations to store the float values into.
float* apVals[1] = {&fHeading};
// Parse the line.
char* pToken = NULL;
const char* seps = " ,\t";
pToken = strtok(warpPositionLine, seps);
if(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 < 2), "Too many tokens in warp position line." );
}
pToken = strtok(NULL, seps);
}
}
if(nItems)
{
(void)fHeading;
return true;
}
return false;
}
void CScriptDebugPedHandler::SetPedPosCB()
{
CPed * pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
Vector3 vecPos(VEC3_ZERO);
if (GetVectorFromTextBox(vecPos, m_PedPos))
{
pPed->Teleport(vecPos, pPed->GetTransform().GetHeading());
}
}
}
void CScriptDebugPedHandler::SetPedHeadingCB()
{
CPed * pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
float fHeading =0.0f;
if (GetFloatFromTextBox(fHeading, m_PedHeading))
{
pPed->Teleport(VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition()), fHeading*DtoR);
}
}
}
//Give the script a debug name
void CScriptDebugPedHandler::SetDebugPedName()
{
CPed * pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
strncpy(pPed->m_debugPedName, m_PedName, 15);
pPed->m_debugPedName[15] = '\0';
}
}
void CScriptDebugPedHandler::GetPedDebugInfo()
{
CPed * pPed = CPedDebugVisualiserMenu::GetFocusPed();
if (pPed)
{
char text[256];
Vector3 vec = VEC3V_TO_VECTOR3(pPed->GetTransform().GetPosition());
formatf(text, 256, "// Ped Debug Info\nPED_INDEX\n VECTOR v%sPos = <<%f,%f,%f>>",pPed->m_debugPedName, pPed->m_debugPedName, vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "FLOAT f%sHeading = %f",pPed->m_debugPedName, RtoD*pPed->GetTransform().GetHeading());
CScriptDebug::OutputScript(text);
formatf(text, 256, "MODEL_NAMES %s",CModelInfo::GetBaseModelInfoName(pPed->GetModelId()));
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_PED_NAME_DEBUG (%s,%s)\n",pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "%s = CREATE_PED( PED_TYPE ,%s,v%sPos, f%sHeading) ",pPed->m_debugPedName, CModelInfo::GetBaseModelInfoName(pPed->GetModelId()), pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (%s, v%sPos) ",pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_PED_COORDS_KEEP_VEHICLE (%s, v%sPos) ",pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_HEADING (%s, f%sHeading)",pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_PED_NAME_DEBUG (PedIndex,%s)\n",pPed->m_debugPedName, pPed->m_debugPedName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "PedIndex = CREATE_PED (PED_TYPE ,%s, <<%f,%f,%f>>, %f) ",CModelInfo::GetBaseModelInfoName(pPed->GetModelId()),vec.x, vec.y, vec.z,RtoD*pPed->GetTransform().GetHeading() );
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (PedIndex, <<%f,%f,%f>>) ",vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_PED_COORDS_KEEP_VEHICLE (PedIndex, <<%f,%f,%f>>) ",vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_HEADING (PedIndex, %f) ",RtoD*pPed->GetTransform().GetHeading());
CScriptDebug::OutputScript(text);
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugPedHandler
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptDebugVehicleHandler
//////////////////////////////////////////////////////////////////////////
/* See if this is needed at all
CScriptDebugVehicleHandler::CScriptDebugVehicleHandler()
{
m_VehiclePos[0] = '\0';
m_VehicleHeading[0] = '\0';
m_VehicleName[0] = '\0';
m_VehicleModelName[0] = '\0';
}
*/
void CScriptDebugVehicleHandler::CreateWidgets(bkBank* pBank)
{
pBank->PushGroup("Vehicle", false);
pBank->AddButton("Create Vehicle", datCallback(MFA(CScriptDebugVehicleHandler::CreateScriptVehicleUsingTheSelectedModel), (datBase*)this));
m_vehicleSelector.AddWidgets(pBank, "Vehicle Model");
pBank->AddText("OR - enter vehicle name", &m_vehicleSearchName[0], STORE_NAME_LENGTH);
pBank->AddButton("Delete Vehicle", datCallback(MFA(CScriptDebugVehicleHandler::DeleteScriptVehicle), (datBase*)this));
pBank->AddText("Vehicle Pos", m_VehiclePos, sizeof(m_VehiclePos),false, datCallback(MFA(CScriptDebugVehicleHandler::SetVehiclePosCB), (datBase*)this));
pBank->AddText("Vehicle Heading", m_VehicleHeading, sizeof(m_VehicleHeading),false, datCallback(MFA(CScriptDebugVehicleHandler::SetVehicleHeadingCB), (datBase*)this));
pBank->AddText("Vehicle Debug Name", m_VehicleName, sizeof(m_VehicleName), false, datCallback(MFA(CScriptDebugVehicleHandler::SetDebugVehicleName), (datBase*)this));
pBank->AddText("Vehicle Model Name", m_VehicleModelName, sizeof(m_VehicleModelName),false);
pBank->AddButton("Set Vehicle on ground", datCallback(MFA(CScriptDebugVehicleHandler::SetVehicleOnGround), (datBase*)this));
pBank->AddButton("Print Vehicle info", datCallback(MFA(CScriptDebugVehicleHandler::GetVehicleDebugInfo), (datBase*)this));
pBank->PopGroup();
}
void CScriptDebugVehicleHandler::RemoveWidgets()
{
m_vehicleSelector.RemoveWidgets();
}
void CScriptDebugVehicleHandler::Process()
{
CVehicle * pVehicle = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetType()==ENTITY_TYPE_VEHICLE))
{
pVehicle = (CVehicle*)pEnt;
const Vector3 vVehiclePosition = VEC3V_TO_VECTOR3(pVehicle->GetTransform().GetPosition());
sprintf(m_VehiclePos, "%.2f, %.2f, %.2f", vVehiclePosition.x, vVehiclePosition.y, vVehiclePosition.z);
float ReturnHeading = ( RtoD * pVehicle->GetTransform().GetHeading());
if (ReturnHeading < 0.0f)
{
ReturnHeading += 360.0f;
}
if (ReturnHeading > 360.0f)
{
ReturnHeading -= 360.0f;
}
sprintf(m_VehicleHeading, "%.2f", ReturnHeading);
sprintf(m_VehicleName, "%s", pVehicle->GetDebugName());
sprintf(m_VehicleModelName, "%s", CModelInfo::GetBaseModelInfoName(pVehicle->GetModelId()));
}
}
if (!pVehicle)
{
sprintf(m_VehiclePos, " ");
sprintf(m_VehicleHeading, " ");
sprintf(m_VehicleName, " ");
}
}
void CScriptDebugVehicleHandler::CreateScriptVehicleUsingTheSelectedModel()
{
u32 nModelIndex = CModelInfo::GetModelIdFromName(m_vehicleSearchName).GetModelIndex();
if (CModelInfo::IsValidModelInfo(nModelIndex))
{
//load the entered object
CreateScriptVehicle(nModelIndex);
}
else
{
//load the selected object
nModelIndex = CModelInfo::GetModelIdFromName(m_vehicleSelector.GetSelectedName()).GetModelIndex();
CreateScriptVehicle(nModelIndex);
}
}
CVehicle* CScriptDebugVehicleHandler::CreateScriptVehicle(u32 vehicleModelIndex)
{
float carDropRotation = 0.0f;
fwModelId vehicleModelId((strLocalIndex(vehicleModelIndex)));
CVehicleModelInfo *pVehModelInfo = (CVehicleModelInfo *)CModelInfo::GetBaseModelInfo(vehicleModelId);
bool bForceLoad = false;
if(!CModelInfo::HaveAssetsLoaded(vehicleModelId))
{
CModelInfo::RequestAssets(vehicleModelId, STRFLAG_FORCE_LOAD|STRFLAG_PRIORITY_LOAD);
bForceLoad = true;
}
if(bForceLoad)
{
CStreaming::LoadAllRequestedObjects(true);
}
if(!CModelInfo::HaveAssetsLoaded(vehicleModelId))
{
return NULL;
}
Matrix34 tempMat;
tempMat.Identity();
tempMat.RotateZ(carDropRotation);
Vector3 vecCreateOffset = CScriptDebug::GetClickedPos();
vecCreateOffset.z -= (pVehModelInfo->GetBoundingBoxMin()).z;
tempMat.d += vecCreateOffset ;
CVehicle *pNewVehicle = CVehicleFactory::GetFactory()->Create(vehicleModelId, ENTITY_OWNEDBY_SCRIPT, POPTYPE_MISSION, &tempMat);
if(pNewVehicle)
{
pNewVehicle->SetupMissionState();
CGameWorld::Add(pNewVehicle, CGameWorld::OUTSIDE);
pNewVehicle->GetPortalTracker()->RequestRescanNextUpdate();
if (pNewVehicle->GetCarDoorLocks() == CARLOCK_LOCKED_INITIALLY) // The game creates police cars with doors locked. For debug cars we don't want this.
{
pNewVehicle->SetCarDoorLocks(CARLOCK_UNLOCKED);
}
pNewVehicle->PlaceOnRoadAdjust();
pNewVehicle->GetPortalTracker()->Update(VEC3V_TO_VECTOR3(pNewVehicle->GetTransform().GetPosition()));
}
return pNewVehicle;
}
void CScriptDebugVehicleHandler::DeleteScriptVehicle()
{
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetType()==ENTITY_TYPE_VEHICLE))
{
CVehicleFactory::GetFactory()->Destroy(static_cast<CVehicle*>(pEnt));
}
}
}
void CScriptDebugVehicleHandler::SetDebugVehicleName()
{
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetIsTypeVehicle()))
{
CVehicle * pVehicle = (CVehicle*)pEnt;
pVehicle->SetDebugName(m_VehicleName);
}
}
}
void CScriptDebugVehicleHandler::SetVehicleOnGround()
{
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetIsTypeVehicle()))
{
CVehicle * pVehicle = (CVehicle*)pEnt;
pVehicle->PlaceOnRoadAdjust();
}
}
}
void CScriptDebugVehicleHandler::SetVehicleHeadingCB()
{
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetIsTypeVehicle()))
{
float fHeading = 0.0f;
if (CScriptDebugPedHandler::GetFloatFromTextBox(fHeading, m_VehicleHeading))
{
CVehicle * pVehicle = (CVehicle*)pEnt;
pVehicle->SetHeading(fHeading*DtoR);
}
}
}
}
void CScriptDebugVehicleHandler::SetVehiclePosCB()
{
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetIsTypeVehicle()))
{
Vector3 vPos(VEC3_ZERO);
if (CScriptDebugPedHandler::GetVectorFromTextBox(vPos, m_VehiclePos))
{
CVehicle * pVehicle = (CVehicle*)pEnt;
pVehicle->Teleport(vPos, pVehicle->GetTransform().GetHeading());
}
}
}
}
void CScriptDebugVehicleHandler::GetVehicleDebugInfo()
{
CVehicle * pVehicle = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if(pEnt && (pEnt->GetType()==ENTITY_TYPE_VEHICLE))
{
pVehicle = (CVehicle*)pEnt;
char text[256];
Vector3 vec = VEC3V_TO_VECTOR3(pVehicle->GetTransform().GetPosition());
formatf(text, 256, "\n//Vehicle Debug Info\nVEHICLE_INDEX %s \n VECTOR v%sPos = <<%f,%f,%f>>",pVehicle->GetDebugName(), pVehicle->GetDebugName(), vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "FLOAT f%sHeading = %f",pVehicle->GetDebugName(), RtoD*pVehicle->GetTransform().GetHeading());
CScriptDebug::OutputScript(text);
formatf(text, 256, "MODEL_NAMES %s",CModelInfo::GetBaseModelInfoName(pVehicle->GetModelId()));
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_VEHICLE_NAME_DEBUG (%s,%s)\n",pVehicle->GetDebugName(), pVehicle->GetDebugName());
CScriptDebug::OutputScript(text);
formatf(text, 256, "%s = CREATE_VEHICLE( %s ,v%sPos, f%sHeading) ",pVehicle->GetDebugName(),CModelInfo::GetBaseModelInfoName(pVehicle->GetModelId()), pVehicle->GetDebugName(), pVehicle->GetDebugName());
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (%s, v%sPos) ",pVehicle->GetDebugName(), pVehicle->GetDebugName());
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_HEADING (%s, f%sHeading)",pVehicle->GetDebugName(), pVehicle->GetDebugName());
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nSET_VEHICLE_NAME_DEBUG (VehicleIndex,%s)\n",pVehicle->GetDebugName(), pVehicle->GetDebugName());
CScriptDebug::OutputScript(text);
formatf(text, 256, "VehicleIndex = CREATE_VEHICLE (%s, <<%f,%f,%f>>, %f) ",CModelInfo::GetBaseModelInfoName(pVehicle->GetModelId()),vec.x, vec.y, vec.z,RtoD*pVehicle->GetTransform().GetHeading() );
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (VehicleIndex, <<%f,%f,%f>>) ",vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_HEADING (VehicleIndex, %f) ",RtoD*pVehicle->GetTransform().GetHeading());
CScriptDebug::OutputScript(text);
}
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugVehicleHandler
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CScriptDebugObjectHandler
//////////////////////////////////////////////////////////////////////////
void CScriptDebugObjectHandler::CreateWidgets(bkBank* pBank)
{
pBank->PushGroup("Object", false);
m_objectSelector.AddWidgets(pBank, "Object model");
pBank->AddText("OR - enter object name", &m_ObjectModelName[0], STORE_NAME_LENGTH);
pBank->AddButton("Reload model names", datCallback(MFA(CScriptDebugObjectHandler::ReloadModelList), (datBase*)this));
pBank->AddButton("Create Object", datCallback(MFA(CScriptDebugObjectHandler::CreateScriptObjectUsingTheSelectedModel), (datBase*)this));
pBank->AddButton("Delete Object", datCallback(MFA(CScriptDebugObjectHandler::DeleteScriptObject), (datBase*)this));
const char *BuildingNameList[] = { "(none)" };
// pBank->AddCombo("Parent bone", &m_parentBone, m_parentBoneList.GetCount(), &m_parentBoneList[0]);
m_CreatedBuildingsList = pBank->AddCombo("BuildingNames", &CreatedBuildingIndex, m_CreatedBuildings.GetCount(), BuildingNameList);
pBank->AddText("Entity Type" , m_ObjectType, sizeof(m_ObjectType),false);
pBank->AddText("Pos z:shift&mse up-dwn)" , m_ObjectPos, sizeof(m_ObjectPos),false, datCallback(MFA(CScriptDebugObjectHandler::SetObjectPosCB), (datBase*)this));
pBank->AddText("Rotation" , m_ObjectRot, sizeof(m_ObjectRot),false, datCallback(MFA(CScriptDebugObjectHandler::SetObjectRotCB), (datBase*)this));
pBank->AddText("Model Name" , m_ObjectName, sizeof(m_ObjectName), false);
pBank->AddButton("Activate physics", datCallback(MFA(CScriptDebugObjectHandler::ActivateObjectPhysics), (datBase*)this));
pBank->AddText("Object Debug Name" , m_ObjectDebugName, sizeof(m_ObjectDebugName), false);
pBank->AddButton("Print Object info", datCallback(MFA(CScriptDebugObjectHandler::GetObjectDebugInfo), (datBase*)this));
pBank->PopGroup();
if(m_CreatedBuildingsList)
{
m_CreatedBuildingsList->UpdateCombo( "BuildingList", &CreatedBuildingIndex, 1, NULL );
m_CreatedBuildingsList->SetString(0,"none");
}
}
void CScriptDebugObjectHandler::RemoveWidgets()
{
m_objectSelector.RemoveWidgets();
}
void CScriptDebugObjectHandler::Process()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
pObject = (CObject*)pEnt;
Vector3 vOut = VEC3_ZERO;
Matrix34 m = MAT34V_TO_MATRIX34(pObject->GetMatrix());
m.ToEulersXYZ(vOut);
vOut *= RtoD;
sprintf(m_ObjectType, "Object");
const Vector3 vObjectPosition = VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition());
sprintf(m_ObjectPos, "%.2f, %.2f, %.2f", vObjectPosition.x, vObjectPosition.y, vObjectPosition.z);
sprintf(m_ObjectRot, "%.2f, %.2f, %.2f", vOut.x, vOut.y, vOut.z);
sprintf(m_ObjectName, "%s", CModelInfo::GetBaseModelInfoName(pObject->GetModelId()));
}
else
{
if(pEnt)
{
sprintf(m_ObjectType, "Building: Cannot create in script");
sprintf(m_ObjectName, "%s", CModelInfo::GetBaseModelInfoName(pEnt->GetModelId()));
}
}
}
}
void CScriptDebugObjectHandler::CreateScriptObjectUsingTheSelectedModel()
{
//check if the user typed in a name rather than selecting one
u32 nModelIndex = CModelInfo::GetModelIdFromName(m_ObjectModelName).GetModelIndex();
if (CModelInfo::IsValidModelInfo(nModelIndex))
{
//load the entered object
CreateScriptObject(nModelIndex);
}
else
{
//load the selected object
CreateScriptObject(m_objectSelector.GetSelectedModelId().GetModelIndex());
}
}
CObject* CScriptDebugObjectHandler::CreateScriptObject(u32 modelIndex)
{
fwModelId modelId((strLocalIndex(modelIndex)));
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(modelId);
if(pModelInfo==NULL)
{
Displayf ("CScriptDebug::CreateScriptObject - Invalid model: %d", modelIndex);
return NULL;
}
if(pModelInfo)
{
RegdEnt pEnt(NULL);
if(pModelInfo->GetIsTypeObject())
{
pEnt = CObjectPopulation::CreateObject(modelId, ENTITY_OWNEDBY_RANDOM, true);
}
else
{
scriptDisplayf("This is a building the asset will need to be changed if its going to be created by script");
if (pModelInfo->GetModelType() == MI_TYPE_COMPOSITE){
pEnt = rage_new CCompEntity( ENTITY_OWNEDBY_DEBUG );
} else {
pEnt = rage_new CBuilding( ENTITY_OWNEDBY_DEBUG );
}
if(pEnt)
{
pEnt->SetModelId(fwModelId(strLocalIndex(modelIndex)));
BuidlingDescription BuildingDesc;
BuildingDesc.pEnt = pEnt;
formatf(BuildingDesc.ObjectModelName, 256, "%s", pEnt->GetModelName());
m_CreatedBuildings.PushAndGrow(BuildingDesc);
PopulateBuidingList();
formatf(m_ObjectType, 256, "building, need asset fixed to be created by script");
}
}
if (pEnt)
{
Matrix34 tempMat;
tempMat.Identity();
Vector3 vecCreateOffset = CScriptDebug::GetClickedPos();
vecCreateOffset.z -= (pEnt->GetBoundingBoxMin()).z;
tempMat.d += vecCreateOffset ;
if(pEnt)
{
if (!pEnt->GetTransform().IsMatrix())
{
#if ENABLE_MATRIX_MEMBER
Mat34V trans = MATRIX34_TO_MAT34V(tempMat);
pEnt->SetTransform(trans);
pEnt->SetTransformScale(1.0f, 1.0f);
#else
fwMatrixTransform* trans = rage_new fwMatrixTransform(MATRIX34_TO_MAT34V(tempMat));
pEnt->SetTransform(trans);
#endif
}
pEnt->SetMatrix(tempMat);
if (fragInst* pInst = pEnt->GetFragInst())
{
pInst->SetResetMatrix(tempMat);
}
CGameWorld::Add(pEnt, CGameWorld::OUTSIDE );
}
if(pEnt->GetIsTypeObject())
{
CObject* pDynamicEnt = static_cast<CObject*>(pEnt.Get());
pDynamicEnt->GetPortalTracker()->RequestRescanNextUpdate();
pDynamicEnt->GetPortalTracker()->Update(VEC3V_TO_VECTOR3(pEnt->GetTransform().GetPosition()));
pDynamicEnt->SetupMissionState();
}
}
// pEnt physics for static xrefs
if (pEnt && pEnt->GetIsTypeBuilding()
&& pEnt->GetCurrentPhysicsInst()==NULL && pEnt->IsBaseFlagSet(fwEntity::HAS_PHYSICS_DICT))
{
// create physics
pEnt->InitPhys();
if (pEnt->GetCurrentPhysicsInst())
{
pEnt->AddPhysics();
}
}
if (pEnt && pEnt->GetIsTypeObject())
{
return static_cast<CObject*>(pEnt.Get());
}
}
return NULL;
}
void CScriptDebugObjectHandler::DeleteScriptObject()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
pObject = (CObject*)pEnt;
if (pObject->GetOwnedBy() == ENTITY_OWNEDBY_SCRIPT)
{
CObjectPopulation::DestroyObject(pObject);
}
}
}
if(CreatedBuildingIndex>0)
{
if(m_CreatedBuildings[CreatedBuildingIndex-1].pEnt)
{
CGameWorld::Remove(m_CreatedBuildings[CreatedBuildingIndex-1].pEnt);
delete m_CreatedBuildings[CreatedBuildingIndex-1].pEnt;
m_CreatedBuildings[CreatedBuildingIndex-1].pEnt = NULL;
m_CreatedBuildings.Delete(CreatedBuildingIndex-1);
PopulateBuidingList();
}
}
}
void CScriptDebugObjectHandler::ActivateObjectPhysics()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
pObject = (CObject*)pEnt;
pObject->ActivatePhysics();
}
}
}
void CScriptDebugObjectHandler::ReloadModelList()
{
m_objectSelector.RefreshList();
}
void CScriptDebugObjectHandler::SetObjectRotCB()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
Vector3 vRot(VEC3_ZERO);
if (CScriptDebugPedHandler::GetVectorFromTextBox(vRot, m_ObjectRot))
{
pObject = (CObject*)pEnt;
Matrix34 mMat;
mMat.Identity();
mMat.d = VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition());
mMat.FromEulersXYZ(vRot*DtoR);
pObject->SetMatrix(mMat);
}
}
}
}
void CScriptDebugObjectHandler::SetObjectPosCB()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
Vector3 vPos(VEC3_ZERO);
if (CScriptDebugPedHandler::GetVectorFromTextBox(vPos, m_ObjectPos))
{
pObject = (CObject*)pEnt;
pObject->Teleport(vPos, pObject->GetTransform().GetHeading());
}
}
}
}
void CScriptDebugObjectHandler::PopulateBuidingList()
{
if(m_CreatedBuildingsList)
{
m_CreatedBuildingsList->UpdateCombo( "BuildingList", &CreatedBuildingIndex, m_CreatedBuildings.GetCount()+1, NULL );
for (s32 i=0; i < m_CreatedBuildings.GetCount(); i++)
{
m_CreatedBuildingsList->SetString( i+1, m_CreatedBuildings[i].ObjectModelName);
}
}
}
void CScriptDebugObjectHandler::GetObjectDebugInfo()
{
CObject * pObject = NULL;
for(s32 i = 0; i < CDebugScene::FOCUS_ENTITIES_MAX; ++i)
{
CEntity* pEnt = CDebugScene::FocusEntities_Get(i);
if (pEnt && pEnt->GetIsTypeObject())
{
char text[256];
pObject = (CObject*)pEnt;
Vector3 vec = VEC3_ZERO;
Matrix34 m = MAT34V_TO_MATRIX34(pObject->GetMatrix());
m.ToEulersXYZ(vec);
vec *= RtoD;
Vector3 vecPos = VEC3V_TO_VECTOR3(pObject->GetTransform().GetPosition());
formatf(text, 256, "\n// Object Debug Info:\nOBJECT_INDEX %s \nVECTOR v%sPos = <<%f,%f,%f>>",m_ObjectDebugName, m_ObjectDebugName,vecPos.x, vecPos.y, vecPos.z );
CScriptDebug::OutputScript(text);
formatf(text, 256, "VECTOR v%Rot = <<%f,%f,%f>>",m_ObjectDebugName, vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "MODEL_NAMES %s",CModelInfo::GetBaseModelInfoName(pObject->GetModelId()));
CScriptDebug::OutputScript(text);
formatf(text, 256, "\n%s = CREATE_OBJECT( %s ,v%sPos)\n",m_ObjectDebugName, CModelInfo::GetBaseModelInfoName(pObject->GetModelId()), m_ObjectDebugName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (%s, v%sPos) ",m_ObjectDebugName, m_ObjectDebugName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_ROTATION (%s, v%sRot)",m_ObjectDebugName, m_ObjectDebugName);
CScriptDebug::OutputScript(text);
formatf(text, 256, "\nObjectIndex = CREATE_OBJECT (%s, <<%f,%f,%f>>)\n",CModelInfo::GetBaseModelInfoName(pObject->GetModelId()),vecPos.x, vecPos.y, vecPos.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_COORDS (ObjectIndex, <<%f,%f,%f>>)",vecPos.x, vecPos.y, vecPos.z);
CScriptDebug::OutputScript(text);
formatf(text, 256, "SET_ENTITY_ROTATION (ObjectIndex, <<%f,%f,%f>>)",vec.x, vec.y, vec.z);
CScriptDebug::OutputScript(text);
}
}
}
//////////////////////////////////////////////////////////////////////////
// End of CScriptDebugObjectHandler
//////////////////////////////////////////////////////////////////////////
#endif // __BANK
//////////////////////////////////////////////////////////////////////////
// Squares and Cubes
//////////////////////////////////////////////////////////////////////////
#if DEBUG_DRAW
const Color32 DbgLineColour(0, 0, 255, 255);
void CalculateGroundZForVector(Vector3 &vecCoord)
{
WorldProbe::CShapeTestProbeDesc probeDesc;
WorldProbe::CShapeTestHitPoint hitPoint;
WorldProbe::CShapeTestResults testResult(hitPoint);
probeDesc.SetStartAndEnd(Vector3(vecCoord.x, vecCoord.y, -1000.0f), Vector3(vecCoord.x, vecCoord.y, 1000.0f));
probeDesc.SetResultsStructure(&testResult);
probeDesc.SetExcludeEntity(NULL);
probeDesc.SetIncludeFlags(ArchetypeFlags::GTA_ALL_MAP_TYPES);
WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc, WorldProbe::PERFORM_SYNCHRONOUS_TEST);
vecCoord.z = testResult[0].GetHitPosition().z + 2.0f; // Small safety margin
}
void CScriptDebug::DrawDebugSquare(float X1, float Y1, float X2, float Y2)
{
Vector3 LinePoint1(X1, Y1, -1000.0f);
Vector3 LinePoint2(X2, Y1, -1000.0f);
Vector3 LinePoint3(X2, Y2, -1000.0f);
Vector3 LinePoint4(X1, Y2, -1000.0f);
CalculateGroundZForVector(LinePoint1);
CalculateGroundZForVector(LinePoint2);
CalculateGroundZForVector(LinePoint3);
CalculateGroundZForVector(LinePoint4);
grcDebugDraw::Line(LinePoint1, LinePoint2, DbgLineColour);
grcDebugDraw::Line(LinePoint2, LinePoint3, DbgLineColour);
grcDebugDraw::Line(LinePoint3, LinePoint4, DbgLineColour);
grcDebugDraw::Line(LinePoint4, LinePoint1, DbgLineColour);
}
void CScriptDebug::DrawDebugAngledSquare(float X1, float Y1, float X2, float Y2, float X3, float Y3, float X4, float Y4)
{
Vector3 LinePoint1(X1, Y1, -1000.0f);
Vector3 LinePoint2(X2, Y2, -1000.0f);
Vector3 LinePoint3(X3, Y3, -1000.0f);
Vector3 LinePoint4(X4, Y4, -1000.0f);
CalculateGroundZForVector(LinePoint1);
CalculateGroundZForVector(LinePoint2);
CalculateGroundZForVector(LinePoint3);
CalculateGroundZForVector(LinePoint4);
grcDebugDraw::Line(LinePoint1, LinePoint2, DbgLineColour);
grcDebugDraw::Line(LinePoint2, LinePoint3, DbgLineColour);
grcDebugDraw::Line(LinePoint3, LinePoint4, DbgLineColour);
grcDebugDraw::Line(LinePoint4, LinePoint1, DbgLineColour);
}
void CScriptDebug::DrawDebugCube(float X1, float Y1, float Z1, float X2, float Y2, float Z2)
{
grcDebugDraw::BoxAxisAligned(Vec3V(X1,Y1,Z1),Vec3V(X2,Y2,Z2),DbgLineColour, false);
}
void CScriptDebug::DrawDebugAngledCube(float X1, float Y1, float Z1, float X2, float Y2, float Z2, float X3, float Y3, float X4, float Y4, const Color32 &colour)
{
Vector3 LinePointTop1(X1, Y1, Z1);
Vector3 LinePointTop2(X2, Y2, Z1);
Vector3 LinePointTop3(X3, Y3, Z1);
Vector3 LinePointTop4(X4, Y4, Z1);
Vector3 LinePointBottom1(X1, Y1, Z2);
Vector3 LinePointBottom2(X2, Y2, Z2);
Vector3 LinePointBottom3(X3, Y3, Z2);
Vector3 LinePointBottom4(X4, Y4, Z2);
// Top square
grcDebugDraw::Line(LinePointTop1,LinePointTop2,colour);
grcDebugDraw::Line(LinePointTop2,LinePointTop3,colour);
grcDebugDraw::Line(LinePointTop3,LinePointTop4,colour);
grcDebugDraw::Line(LinePointTop4,LinePointTop1,colour);
// Bottom square
grcDebugDraw::Line(LinePointBottom1,LinePointBottom2,colour);
grcDebugDraw::Line(LinePointBottom2,LinePointBottom3,colour);
grcDebugDraw::Line(LinePointBottom3,LinePointBottom4,colour);
grcDebugDraw::Line(LinePointBottom4,LinePointBottom1,colour);
// Vertical lines
grcDebugDraw::Line(LinePointBottom1,LinePointTop1,colour);
grcDebugDraw::Line(LinePointBottom2,LinePointTop2,colour);
grcDebugDraw::Line(LinePointBottom3,LinePointTop3,colour);
grcDebugDraw::Line(LinePointBottom4,LinePointTop4,colour);
}
#else // DEBUG_DRAW
void CScriptDebug::DrawDebugSquare(float, float, float, float) { /* NoOp */ }
void CScriptDebug::DrawDebugAngledSquare(float, float, float, float, float, float, float, float) { /* NoOp */ }
void CScriptDebug::DrawDebugCube(float, float, float, float, float, float) { /* NoOp */ }
void CScriptDebug::DrawDebugAngledCube(float, float, float, float, float, float, float, float, float , float, const Color32 &) { /* NoOp */ }
#endif // DEBUG_DRAW
//////////////////////////////////////////////////////////////////////////
// End of Squares and Cubes
//////////////////////////////////////////////////////////////////////////