Skip to content

Commit

Permalink
Some big reworks
Browse files Browse the repository at this point in the history
Again...
- Replace CFonts::DrawText by CFonts::DrawLittleText
- Replace CFonts::DrawText by CFonts::GetLittleTextScreenSize
- Make texture always with even numbers
- Hook CEntity__GetDistanceToCamera call, so we can check if target is on screen first, then check if LineOfSightIsClear
- Begin rendering nicknames by +1 offset so upper-left outline can be rendered successfully
- Disable warnings in some pieces of code
  • Loading branch information
Northn committed Sep 7, 2021
1 parent 8f41dd7 commit f7596e5
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 67 deletions.
86 changes: 40 additions & 46 deletions OptimizedNametags/OptimizedNametags.cpp
@@ -1,13 +1,15 @@
#include "pch.h"
#include "OptimizedNametags.h"

#pragma intrinsic(_ReturnAddress)

bool OptimizedNametags::shouldRedrawNametag(NameTag& nt, const char* name, D3DCOLOR color, bool isAfk) {
bool ret = (!nt.sprite || !nt.texture || !nt.surface || !nt.renderToSurface) || nt.redraw || nt.isAfk != isAfk || nt.color != color;
if (nt.redraw) nt.redraw = false;
return ret;
}

bool OptimizedNametags::createElements(NameTag& nt, SIZE& size)
bool OptimizedNametags::createElements(NameTag& nt, SIZE& textureSize)
{
static D3DSURFACE_DESC desc;

Expand All @@ -17,9 +19,14 @@ bool OptimizedNametags::createElements(NameTag& nt, SIZE& size)
DX_SAFE_RELEASE(nt.texture);
DX_SAFE_RELEASE(nt.renderToSurface);
DX_SAFE_RELEASE(nt.surface);

textureSize.cx += 1 /*outline*/ + 1;
textureSize.cy += 1 /*outline*/ + 3 /*AFK padding*/ + 48 /*AFK icon*/;
if ((textureSize.cx % 2) != 0) textureSize.cx++;
if ((textureSize.cy % 2) != 0) textureSize.cy++;

if (FAILED(D3DXCreateSprite(mD3DDevice, &nt.sprite))) return false;
if (FAILED(D3DXCreateTexture(mD3DDevice, size.cx + 1, size.cy + 3 + 48, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &nt.texture)))
if (FAILED(D3DXCreateTexture(mD3DDevice, textureSize.cx, textureSize.cy, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &nt.texture)))
return false;
if (FAILED(nt.texture->GetSurfaceLevel(0, &nt.surface))) return false;
if (FAILED(nt.surface->GetDesc(&desc))) return false;
Expand All @@ -40,26 +47,26 @@ void __fastcall CPlayerTags__Draw(uintptr_t self, int id, CVector* playerPos, co
if (gInstance.shouldRedrawNametag(nt, szText, color, isAfk))
{
auto textSize = sampGetMeasuredTextSize(szText);
if (!gInstance.createElements(nt, textSize)) return;

RECT rect{ 0, 0, textSize.cx + 1, textSize.cy + 1 };
SIZE textureSize = textSize;
if (!gInstance.createElements(nt, textureSize)) return;
RECT rect{ 1, 1, textureSize.cx, textureSize.cy };

if (SUCCEEDED(nt.renderToSurface->BeginScene(nt.surface, NULL)))
{
pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 0, 0);
if (SUCCEEDED(nt.sprite->Begin(D3DXSPRITE_ALPHABLEND)))
{
pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_BLENDFACTOR);
nt.center = static_cast<float>(textSize.cx) / 2.f;
nt.center = 1.f + static_cast<float>(textSize.cx) / 2.f;
sampDrawText(nt.sprite, szText, rect, color, true);

if (isAfk)
{
auto auxFont = sampGetDeathWindowFont();
auto auxFont = sampGetAuxFont();

if (auxFont)
{
rect.top = textSize.cy + 3;
rect.top += textSize.cy + 3;
rect.left = static_cast<long>(nt.center / 2.6f);
auxFont->DrawTextA(nt.sprite, "C", 1, &rect, DT_NOCLIP | DT_LEFT, D3DCOLOR_XRGB(0, 0, 0));
rect.left += 3;
Expand All @@ -68,16 +75,15 @@ void __fastcall CPlayerTags__Draw(uintptr_t self, int id, CVector* playerPos, co
}
}
nt.sprite->End();

nt.color = color;
nt.isAfk = isAfk;
}
nt.renderToSurface->EndScene(0);
}

nt.color = color;
nt.isAfk = isAfk;
}

D3DXVECTOR3 TagPos(playerPos->x, playerPos->y, playerPos->z);
TagPos.z += 0.25f + (fDistanceToCamera * 0.047f);
D3DXVECTOR3 TagPos{ playerPos->x, playerPos->y, playerPos->z + 0.25f + (fDistanceToCamera * 0.047f) };

D3DVIEWPORT9 Viewport;
pDevice->GetViewport(&Viewport);
Expand All @@ -88,58 +94,46 @@ void __fastcall CPlayerTags__Draw(uintptr_t self, int id, CVector* playerPos, co

D3DXVec3Project(&Out, &TagPos, &Viewport, sampGetProjectionMatrix(), sampGetViewMatrix(), &matIdent);

if (Out.z > 1.f) return;

if (SUCCEEDED(nt.sprite->Begin(D3DXSPRITE_ALPHABLEND)))
{
D3DXVECTOR3 center{ nt.center, 0.f, 0.f };
nt.sprite->Draw(nt.texture, NULL, &center, &Out, 0xFFFFFFFF);
nt.sprite->End();
}

//if (bDrawStatus and nStatus == 2)
/*{
auto CDeathWindow = *reinterpret_cast<uintptr_t*>(sampGetBase() + 0x26E8D0);
if (!*reinterpret_cast<BOOL*>(CDeathWindow + 331))
{
reinterpret_cast<void(__thiscall*)(uintptr_t)>(sampGetBase() + 0x69440)(CDeathWindow);
}
ID3DXFont* auxFont = *reinterpret_cast<ID3DXFont**>(CDeathWindow + 339);
ID3DXFont* weapFont = *reinterpret_cast<ID3DXFont**>(CDeathWindow + 319);
if (auxFont && weapFont)
{
std::cout << reinterpret_cast<char*>(sampGetBase() + 0xE62F8) << std::endl;
RECT rect{ (int)Out.x - 33, (int)Out.y + 32, (int)Out.x + 1 - 33, (int)Out.y + 33 };
rect.left -= 2;
rect.right -= 2;
auxFont->DrawTextA(NULL, "C", 1, &rect, 261, D3DCOLOR_XRGB(0, 0, 0));
rect.left -= 2;
rect.right -= 2;
auxFont->DrawTextA(NULL, "E", 1, &rect, 261, -1);
}
}*/

/*reinterpret_cast<void(__thiscall*)(uintptr_t, CVector * playerPos, const char* szText,
D3DCOLOR color, float fDistanceToCamera, bool bDrawStatus, int nStatus)>(gInstance.mHooks.CPlayerTags__Draw->getHookedFunctionAddress())
(self, playerPos, szText, color, fDistanceToCamera, bDrawStatus, nStatus);*/
}

__declspec(naked) void CPlayerTags__Draw_Naked()
{
/*static CVector* coords;
static const char* text;*/
__asm {
mov edx, edi // id: save edi, push id to drawer function
/*mov edi, [esp + 4] // coords
mov coords, edi
mov edi, [esp + 8] // text
mov text, edi
mov edi, edx // return id to edi */
mov edx, edi
jmp CPlayerTags__Draw
}
}

double __fastcall CEntity__GetDistanceToCamera(uintptr_t self)
{
static void *label, *health;
uintptr_t CEntity = 0;

std::tie(label, health) = sampGetPedDistanceGetterReturnAddresses();
auto retAddress = _ReturnAddress();
if (retAddress != label && retAddress != health)
goto ret;

CEntity = *reinterpret_cast<uintptr_t*>(self + 0x40);

if (!reinterpret_cast<bool(__thiscall*)(uintptr_t)>(0x534540)(CEntity))
return DBL_MAX;

ret:
return reinterpret_cast<decltype(CEntity__GetDistanceToCamera)*>(gInstance.mHooks.CEntity__GetDistanceToCamera->getTrampoline())
(self);
}

void __fastcall CPlayerTags__OnLostDevice(void* self)
{
for (auto& nt : gInstance.mNametags)
Expand Down
10 changes: 6 additions & 4 deletions OptimizedNametags/OptimizedNametags.h
Expand Up @@ -23,24 +23,26 @@ class OptimizedNametags
NameTag mNametags[MAX_PLAYERS];

struct {
rtdhook* CPlayerTags__OnLostDevice = nullptr;
rtdhook
* CPlayerTags__OnLostDevice = nullptr,
* CEntity__GetDistanceToCamera = nullptr;
rtdhook_call* CPlayerTags__Draw = nullptr;
} mHooks;

IDirect3DDevice9* mD3DDevice = nullptr;

bool shouldRedrawNametag(NameTag& nt, const char* name, D3DCOLOR color, bool isAfk);
bool createElements(NameTag& nt, SIZE& size);
bool createElements(NameTag& nt, SIZE& textureSize);
};

#define DX_SAFE_RELEASE(p) if (p != nullptr) { p->Release(); p = nullptr; }

inline OptimizedNametags gInstance;

void* __fastcall CPlayerTags__CPlayerTags(void* self, void* edx, IDirect3DDevice9* pDevice);

void __fastcall CPlayerTags__Draw(uintptr_t self, int id, CVector* playerPos, const char* szText,
D3DCOLOR color, float fDistanceToCamera, bool bDrawStatus, int nStatus);
void CPlayerTags__Draw_Naked();

double __fastcall CEntity__GetDistanceToCamera(uintptr_t self);

void __fastcall CPlayerTags__OnLostDevice(void* self);
4 changes: 2 additions & 2 deletions OptimizedNametags/OptimizedNametags.vcxproj
Expand Up @@ -31,14 +31,14 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
Expand Down
4 changes: 4 additions & 0 deletions OptimizedNametags/dllmain.cpp
Expand Up @@ -7,13 +7,17 @@ rtdhook_call* mainloop_hook = nullptr;
void mainloop()
{
static bool loaded = false;
#pragma warning(disable : 26812)
if (!loaded && sampGetVersion() > SAMPVER::SAMP_UNKNOWN) // If SAMP loaded & is compatible version
#pragma warning(default : 26812)
{
gInstance.mHooks.CPlayerTags__Draw = new rtdhook_call(sampGetPlayerTagsDrawerCallPtr(), &CPlayerTags__Draw_Naked);
gInstance.mHooks.CPlayerTags__OnLostDevice = new rtdhook(sampGetPlayerTagsOnLostDevice(), &CPlayerTags__OnLostDevice, 6);
gInstance.mHooks.CEntity__GetDistanceToCamera = new rtdhook(sampGetPedDistanceGetterFuncPtr(), &CEntity__GetDistanceToCamera, 6);

gInstance.mHooks.CPlayerTags__Draw->install();
gInstance.mHooks.CPlayerTags__OnLostDevice->install();
gInstance.mHooks.CEntity__GetDistanceToCamera->install();

gInstance.mD3DDevice = *reinterpret_cast<IDirect3DDevice9**>(0xC97C28);

Expand Down
2 changes: 2 additions & 0 deletions OptimizedNametags/framework.h
Expand Up @@ -3,4 +3,6 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#pragma warning(disable : 26495)
#include <d3dx9core.h>
#pragma warning(default : 26495)
2 changes: 2 additions & 0 deletions OptimizedNametags/pch.h
Expand Up @@ -12,4 +12,6 @@
#include "rtdhook.hpp"
#include "samp.hpp"

#include <intrin.h>

#endif //PCH_H
43 changes: 28 additions & 15 deletions OptimizedNametags/samp.hpp
@@ -1,22 +1,17 @@
#pragma once

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <d3dx9core.h>

enum SAMPVER {
SAMP_NOT_LOADED,
SAMP_UNKNOWN,
SAMP_037_R1,
SAMP_037_R3_1
};

const uintptr_t samp_addressess[][11]
const uintptr_t samp_addressess[][14]
{
// CPlayerTags::CPlayerTags <- UNUSED, Drawer -> call CPlayerTags::DrawLabel, CPlayerTags::OnLostDevice, CPlayerTags::OnResetDevice <- UNUSED, CFonts, CFonts::DrawText, CFonts::GetTextScreenSize, D3DXMATRIX Projection, D3DXMATRIX View, CDeathWindow, CDeathWindow::CreateAuxFonts
{0x68610, 0x70F96, 0x68F70, 0x68FA0, 0x21A0FC, 0x66C80, 0x66B20, 0x12C980, 0x12C940, 0x21A0EC, 0x65F10},
{0x6C580, 0x74E8A, 0x6CEE0, 0x6CF10, 0x26E8E4, 0x6ABF0, 0x6AA90, 0x140B00, 0x140AC0, 0x26E8D0, 0x69440}
// CPlayerTags::CPlayerTags <- UNUSED, Drawer -> call CPlayerTags::DrawLabel, CPlayerTags::OnLostDevice, CPlayerTags::OnResetDevice <- UNUSED, CFonts, CFonts::DrawLittleText, CFonts::GetLittleTextScreenSize, D3DXMATRIX Projection, D3DXMATRIX View, CDeathWindow, CDeathWindow::CreateAuxFonts, CEntity::GetDistanceToCamera(), ReturnAddress from DrawLabel, ReturnAddress from DrawHealth
{0x68610, 0x70F96, 0x68F70, 0x68FA0, 0x21A0FC, 0x66E00, 0x66BD0, 0x12C980, 0x12C940, 0x21A0EC, 0x65F10, 0x9A7D0, 0x70E10, 0x6FD00},
{0x6C580, 0x74E8A, 0x6CEE0, 0x6CF10, 0x26E8E4, 0x6AD70, 0x6AB40, 0x140B00, 0x140AC0, 0x26E8D0, 0x69440, 0x9EA80, 0x74CFC, 0x73BEC}
};

inline uintptr_t sampGetBase()
Expand All @@ -27,8 +22,7 @@ inline uintptr_t sampGetBase()
return sampBase;
}

// https://github.com/imring/TimeFormat/blob/master/samp.hpp#L19

#pragma warning(disable : 26812)
inline SAMPVER sampGetVersion()
{
static SAMPVER sampVersion = SAMPVER::SAMP_NOT_LOADED;
Expand All @@ -55,6 +49,7 @@ inline SAMPVER sampGetVersion()

return sampVersion;
}
#pragma warning(default : 26812)

#define SAMP_OFFSET samp_addressess[sampGetVersion() - 2]

Expand Down Expand Up @@ -82,15 +77,15 @@ inline uintptr_t sampGetPlayerTagsOnLostDevice()

inline void sampDrawText(ID3DXSprite* sprite, const char* text, RECT& rect, DWORD color, BOOL shadow)
{
reinterpret_cast<void(__thiscall*)(void*, ID3DXSprite*, const char*, RECT, DWORD, BOOL)>(sampGetBase() + SAMP_OFFSET[5])
(*reinterpret_cast<void**>(sampGetBase() + SAMP_OFFSET[4]), sprite, text, rect, color, shadow);
reinterpret_cast<void(__thiscall*)(void*, ID3DXSprite*, const char*, RECT, int, DWORD, BOOL)>(sampGetBase() + SAMP_OFFSET[5])
(*reinterpret_cast<void**>(sampGetBase() + SAMP_OFFSET[4]), sprite, text, rect, DT_LEFT | DT_NOCLIP, color, shadow);
}

inline SIZE sampGetMeasuredTextSize(const char* text)
{
static SIZE size;
reinterpret_cast<void(__thiscall*)(void*, SIZE*, const char*, int)>(sampGetBase() + SAMP_OFFSET[6])
(*reinterpret_cast<void**>(sampGetBase() + SAMP_OFFSET[4]), &size, text, DT_LEFT);
(*reinterpret_cast<void**>(sampGetBase() + SAMP_OFFSET[4]), &size, text, DT_LEFT | DT_NOCLIP);
return size;
}

Expand All @@ -104,7 +99,7 @@ inline D3DXMATRIX* sampGetViewMatrix()
return reinterpret_cast<D3DXMATRIX*>(sampGetBase() + SAMP_OFFSET[8]);
}

inline ID3DXFont* sampGetDeathWindowFont()
inline ID3DXFont* sampGetAuxFont()
{
static ID3DXFont* auxFont = nullptr;
static uintptr_t CDeathWindow = 0;
Expand All @@ -125,4 +120,22 @@ inline ID3DXFont* sampGetDeathWindowFont()
return auxFont;
}

inline uintptr_t sampGetPedDistanceGetterFuncPtr()
{
return sampGetBase() + SAMP_OFFSET[11];
}

inline std::tuple<void*, void*> sampGetPedDistanceGetterReturnAddresses()
{
static void *label = nullptr, *health = nullptr;
if (label && health)
goto ret;

label = reinterpret_cast<void*>(sampGetBase() + SAMP_OFFSET[12]);
health = reinterpret_cast<void*>(sampGetBase() + SAMP_OFFSET[13]);

ret:
return std::make_tuple(label, health);
}

#undef SAMP_OFFSET

0 comments on commit f7596e5

Please sign in to comment.