From 4ef633c60e23ad61f9b9afff583ac2c8e9f24364 Mon Sep 17 00:00:00 2001 From: Disquse Date: Thu, 1 Feb 2024 15:14:27 +0300 Subject: [PATCH] feat(extra-natives/rdr3): add GET_WORLD_COORD_FROM_SCREEN_COORD --- .../include/GamePrimitives.h | 40 +++++++++++++++++++ .../src/GraphicsNatives.cpp | 29 ++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/code/components/extra-natives-rdr3/include/GamePrimitives.h b/code/components/extra-natives-rdr3/include/GamePrimitives.h index 28279905d1..08c3aa5a81 100644 --- a/code/components/extra-natives-rdr3/include/GamePrimitives.h +++ b/code/components/extra-natives-rdr3/include/GamePrimitives.h @@ -51,4 +51,44 @@ struct spdRay Vec3V start; Vec3V end; }; + +struct grcViewport +{ + float m_mat1[16]; + float m_mat2[16]; + float m_viewProjection[16]; + float m_inverseView[16]; + char m_pad[64]; + float m_projection[16]; +}; +} + +struct CViewportGame +{ +public: + virtual ~CViewportGame() = 0; + +private: + char m_pad[8]; + +public: + rage::grcViewport viewport; +}; + +extern CViewportGame** g_viewportGame; + +inline rage::Vec3V Unproject(const rage::grcViewport& viewport, const rage::Vec3V& viewPos) +{ + using namespace DirectX; + + auto composite = XMMatrixMultiply(XMLoadFloat4x4((const XMFLOAT4X4*)&viewport.m_projection), XMLoadFloat4x4((const XMFLOAT4X4*)&viewport.m_viewProjection)); + auto invVP = XMMatrixInverse(NULL, composite); + auto inVec = XMVectorSet((viewPos.x * 2.0f) - 1.0f, ((1.0 - viewPos.y) * 2.0f) - 1.0f, viewPos.z, 1.0f); + auto outCoord = XMVector3TransformCoord(inVec, invVP); + + return { + XMVectorGetX(outCoord), + XMVectorGetY(outCoord), + XMVectorGetZ(outCoord) + }; } diff --git a/code/components/extra-natives-rdr3/src/GraphicsNatives.cpp b/code/components/extra-natives-rdr3/src/GraphicsNatives.cpp index 61bf5e4a18..e0e24e4444 100644 --- a/code/components/extra-natives-rdr3/src/GraphicsNatives.cpp +++ b/code/components/extra-natives-rdr3/src/GraphicsNatives.cpp @@ -5,6 +5,7 @@ #include "CfxRGBA.h" #include "Hooking.Stubs.h" #include "GamePrimitives.h" +#include "scrEngine.h" enum ScriptImDrawType : uint32_t { @@ -104,6 +105,8 @@ struct WorldhorizonManager static WorldhorizonManager* g_worldhorizonMgr; +CViewportGame** g_viewportGame; + static HookFunction hookFunction([]() { static_assert(sizeof(ScriptImRequest) == 64); @@ -111,6 +114,7 @@ static HookFunction hookFunction([]() static_assert(sizeof(DrawOriginStore) == 1040); { + g_viewportGame = hook::get_address(hook::get_pattern("0F 2F F0 76 ? 4C 8B 35", 8)); g_worldhorizonMgr = hook::get_address(hook::get_pattern("89 44 24 40 48 8D 0D ? ? ? ? 8B 84 24 90 00", 7)); } @@ -286,4 +290,29 @@ static HookFunction hookFunction([]() g_worldhorizonMgr->m_disableRendering = flag; } }); + + fx::ScriptEngine::RegisterNativeHandler("GET_WORLD_COORD_FROM_SCREEN_COORD", [](fx::ScriptContext& context) + { + float screenX = context.GetArgument(0); + float screenY = context.GetArgument(1); + + using namespace DirectX; + rage::Vec3V start = Unproject((*g_viewportGame)->viewport, rage::Vec3V{ screenX, screenY, 0.0f }); + rage::Vec3V end = Unproject((*g_viewportGame)->viewport, rage::Vec3V{ screenX, screenY, 1.0f }); + + auto startVector = XMLoadFloat3((XMFLOAT3*)&start); + auto endVector = XMLoadFloat3((XMFLOAT3*)&end); + auto normalVector = XMVector3Normalize(XMVectorSubtract(endVector, startVector)); + + scrVector* worldOut = context.GetArgument(2); + scrVector* normalOut = context.GetArgument(3); + + worldOut->x = start.x; + worldOut->y = start.y; + worldOut->z = start.z; + + normalOut->x = XMVectorGetX(normalVector); + normalOut->y = XMVectorGetY(normalVector); + normalOut->z = XMVectorGetZ(normalVector); + }); });