#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 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 CScriptDebug::ms_attachmentTools; bkGroup* CScriptDebug::ms_pAttachmentGroup = NULL; const char *CScriptDebug::ms_pScriptDebuggerPath = NULL; atArray 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 ; iSetCurrentGroup(*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(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;iGetName()); } } } m_childBoneList.clear(); if (m_child) { m_childBoneList.PushAndGrow("Entity"); if (m_child->GetSkeleton()) { const crSkeletonData& SkelData = m_child->GetSkeletonData(); for (s32 i=0;iGetName()); } } } } 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(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(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(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(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(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(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(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(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(CScriptWidgetTree::GetWidgetFromUniqueWidgetId(m_UniqueId)); CScriptDebug::GetTextWidgets().ClearTextWidget(pTextWidget); } break; case WIDGETTYPE_BITFIELD : { bkGroup *pBitFieldWidgetGroup = static_cast(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(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(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(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; iShutdown(); 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(pEntity0); CPhysical* pParent = NULL; //is there a parent entity? if (pEntity1) { if (pEntity1->GetIsPhysical()) { pParent = static_cast(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;im_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(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(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(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(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(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(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 //////////////////////////////////////////////////////////////////////////