Skip to content

Instantly share code, notes, and snippets.

@The-Musaigen
Created September 2, 2021 16:14
Show Gist options
  • Save The-Musaigen/64b31b8ac0b1c1f95a77128968d2c31c to your computer and use it in GitHub Desktop.
Save The-Musaigen/64b31b8ac0b1c1f95a77128968d2c31c to your computer and use it in GitHub Desktop.
GTA:SAMP modification that allows to see players identifiers on the radar.
#include <main.h>
IniFile gIniFile{ ".\\BlipsEnchancedByMusaigen.ini" };
CD3DFont* gFont{ nullptr };
Hook* hkPoolInstantiate{ nullptr };
Hook* hkProcess{ nullptr };
Hook* hkPresent{ nullptr };
Hook* hkReset{ nullptr };
CPlayerPool* gPool{ nullptr };
Bool gRenderReady{ false };
String gFontFace;
Int gFontSize;
Int gFontFlags;
Bool gRenderLocal;
Bool gRenderShadow;
Float gOffsetX;
Float gOffsetY;
using std::to_string;
HRESULT WINAPI OnPresent(IDirect3DDevice9* device, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
{
if (!gRenderReady)
{
gFont->Initialize(device);
gRenderReady = true;
}
if (BlipsEnchanced::CanRender())
{
auto scissor { BlipsEnchanced::BeginScissor(device) };
auto index { 0 };
for (; index < SAMP_MAX_PLAYERS; index++)
{
CPed* ped { nullptr };
if (index == gPool->m_nId && gRenderLocal)
ped = FindPlayerPed();
else
{
auto info{ gPool->m_pPlayerInfo[index] };
if (!gPool->m_bNotEmpty[index] ||
!info ||
!info->m_pPlayer ||
!info->m_pPlayer->m_pPed ||
!info->m_pPlayer->m_pPed->m_pGamePed)
continue;
ped = info->m_pPlayer->m_pPed->m_pGamePed;
}
if (!ped)
continue;
CVector& position = ped->GetPosition();
CVector2D radar;
CVector2D screen;
BlipsEnchanced::TransformRealWorldPointToRadarSpace(&radar, &CVector2D(position.x, position.y));
BlipsEnchanced::TransformRadarPointToScreenSpace(&screen, &radar);
gFont->PrintShadow(screen.x + gOffsetX, screen.y + gOffsetY, -1, to_string(index).c_str());
}
if (scissor)
BlipsEnchanced::EndScissor(device);
}
return hkPresent->Call<HRESULT, CT_STDCALL>(device, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
}
HRESULT WINAPI OnReset(IDirect3DDevice9* device, D3DPRESENT_PARAMETERS* pParameters)
{
if (gRenderReady)
{
gFont->Invalidate();
gRenderReady = false;
}
return hkReset->Call<HRESULT, CT_STDCALL>(device, pParameters);
}
Void OnProcess()
{
STATIC Bool initialized { false };
if (!initialized)
{
IDirect3DDevice9* device { MemoryWrapper::ReadMemory<IDirect3DDevice9*>(0xC97C28) };
if (device != nullptr)
{
Void** vtable { *reinterpret_cast<Void***>(device) };
hkReset = new Hook(vtable[16], OnReset);
hkReset->Install();
hkPresent = new Hook(vtable[17], OnPresent);
hkPresent->Install();
initialized = true;
}
}
return hkProcess->Call();
}
Void METHOD OnPoolInstantiate(CPlayerPool* pPlayerPool, Void* edx86)
{
gPool = pPlayerPool;
return hkPoolInstantiate->Call<Void, CT_THISCALL>(pPlayerPool);
}
BlipsEnchanced::BlipsEnchanced()
{
UInt32 constructor = MemoryWrapper::SearchPattern("samp.dll", "\x6A\xFF\x68\x00\x00\x00\x00\x64\xA1\x00\x00\x00\x00\x50\x64\x89\x25\x00\x00\x00\x00\x83\xEC\x08\x53\x56", "xxx????xx????xxxx????xxxxx");
gFontFace = gIniFile.ReadString("Main", "FontFace", "Arial");
gFontSize = gIniFile.ReadInteger("Main", "FontSize", 8);
gFontFlags = gIniFile.ReadInteger("Main", "FontFlags", FCR_BORDER);
gRenderLocal = gIniFile.ReadBoolean("Flags", "RenderLocal", true);
gRenderShadow = gIniFile.ReadBoolean("Flags", "RenderShadow", true);
gOffsetX = gIniFile.ReadFloat("Offsets", "OffsetX", .0F);
gOffsetY = gIniFile.ReadFloat("Offsets", "OffsetY", .0F);
gFont = new CD3DFont(gFontFace.c_str(), gFontSize, gFontFlags);
hkProcess = new Hook(0x53BEE0, OnProcess);
hkProcess->Install();
if (constructor > 0)
{
hkPoolInstantiate = new Hook(constructor, OnPoolInstantiate);
hkPoolInstantiate->Install();
}
}
BlipsEnchanced::~BlipsEnchanced()
{
if (hkPoolInstantiate)
delete hkPoolInstantiate;
delete hkProcess;
delete hkPresent;
delete hkReset;
delete gFont;
}
Void BlipsEnchanced::TransformRealWorldPointToRadarSpace(CVector2D* out, CVector2D* in)
{
CallWrapper::Call<Void>(0x583530, out, in);
}
Void BlipsEnchanced::TransformRadarPointToScreenSpace(CVector2D* out, CVector2D* in)
{
CallWrapper::Call<Void>(0x583480, out, in);
}
CONST D3DCAPS9* BlipsEnchanced::GetCaps()
{
return CallWrapper::Call<CONST D3DCAPS9*>(0x7FAD20);
}
Bool BlipsEnchanced::CanRender()
{
auto radarMode { MemoryWrapper::ReadMemory<Int>(0xBA676C) };
return (gFont != nullptr && gPool != nullptr && gRenderReady && !IsMenuOpened() && radarMode != 2);
}
Bool BlipsEnchanced::BeginScissor(IDirect3DDevice9* device)
{
auto caps { GetCaps() };
auto drawRadarOrMap { MemoryWrapper::ReadMemory<Bool>(0xBA67A1) };
if (!drawRadarOrMap && caps->RasterCaps & D3DPRASTERCAPS_SCISSORTEST)
{
// Taken from plugin-sdk: https://github.com/DK22Pac/plugin-sdk/blob/bb15c327c5fcab9bca766b76c5d6e2817b6cbe36/examples/GPS/Main.cpp#L86
RECT rect;
CVector2D posn;
BlipsEnchanced::TransformRadarPointToScreenSpace(&posn, &CVector2D(-1.0f, -1.0f));
rect.left = static_cast<LONG>(posn.x + 2.0f);
rect.bottom = static_cast<LONG>(posn.y - 2.0f);
BlipsEnchanced::TransformRadarPointToScreenSpace(&posn, &CVector2D(1.0f, 1.0f));
rect.right = static_cast<LONG>(posn.x - 2.0f);
rect.top = static_cast<LONG>(posn.y + 2.0f);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
device->SetScissorRect(&rect);
return true;
}
return false;
}
Void BlipsEnchanced::EndScissor(IDirect3DDevice9* device)
{
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment