Chat related variables and functions for SA-MP 0.3.7 R4

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
Since I'm too lazy to write documentation on the things I found, I'll just leave this code here for reference. If you need help on how to implement this in your DLL, this is not the place and I can't be bothered to help doing that. My aim is to share the functions/variables I've found (specifically for SA-MP 0.3.7 R4) and hopefully people contribute whatever they found. If you don't like my codingstyle, don't be an asshat but just tell me what's wrong and how to improve it.

I've got a request as well. Anyone can share where to find info for the scoreboard, like player names/id/score? I'm asking specifically for 0.3.7 R4. Thank you!

C++:
#include <vector>
#include <string>
#include <windows.h>

uintptr_t sampModuleBase = 0;
bool initialized = false;

void Initialize()
{
    sampModuleBase = (uintptr_t)GetModuleHandle("samp.dll");
    if(sampModuleBase != 0)
        initialized = true;
}

uintptr_t ReadPointerChain(uintptr_t base_address, std::vector<unsigned int> offsets)
{
    uintptr_t address = base_address;

    for(size_t i = 0; i < offsets.size(); i++)
    {      
        address = *(uintptr_t*)address;
        address += offsets[i];
    }

    return address;
}

bool IsChatOpen()
{
    if(!initialized) return false;

    bool open = *(bool*)ReadPointerChain(sampModuleBase + 0x26E9FC, {0x14E0});
    return open;
}

bool IsDialogOpen()
{
    if(!initialized) return false;

    bool open = *(bool*)ReadPointerChain(sampModuleBase + 0x0026EAA8, {0x13});
    return open;  
}

bool IsScoreboardOpen()
{
    if(!initialized) return false;

    bool open = *(bool*)ReadPointerChain(sampModuleBase + 0x26E9C4, {0x0});
    return open;
}

void SendLocalMessage(const std::string& message)
{
    if(!initialized) return;

    DWORD chatpointer = sampModuleBase + (0x26E9FC - 4);
    DWORD chatInfo = *(DWORD*)chatpointer;  
    void* cInfo = (void*)chatInfo;
    char* msg = &message[0];
    reinterpret_cast<void(__cdecl*)(void*, char*)>(sampModuleBase + 0x680B0)(cInfo, msg);  
}

void SendChatMessage(const std::string& message)
{
    if(!initialized) return;

    char* msg = &message[0];
    reinterpret_cast<void(__cdecl*)(char*, bool)>(sampModuleBase + 0x5A00)(msg, false);
}

void SendCommand(const std::string& command)
{
    if(!initialized) return;

    char* msg = &command[0];
    reinterpret_cast<void(__cdecl*)(char*, bool)>(sampModuleBase + 0x698C0)(msg, false);  
}

std::string GetLastReceivedChatText()
{
    if(!initialized) return std::string("");

    DWORD offset = 0x132 + (99 * 0xFC) + 0x20;
    char* msg = (char*)ReadPointerChain(sampModuleBase + 0x26E9F8, {offset});
    return std::string(msg);
}

std::string GetLastReceivedChatSender()
{
    if(!initialized) return std::string("");

    DWORD offset = 0x132 + (99 * 0xFC) + 4;
    char* msg = (char*)ReadPointerChain(sampModuleBase + 0x26E9F8, {offset});
    return std::string(msg);
}

std::string GetChatLogPath()
{
    if(!initialized) return std::string("");

    char* msg = (char*)ReadPointerChain(sampModuleBase + 0x26E9F8, {0x011});
    return std::string(msg);  
}
 
Last edited:

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
I can't seem to edit my first post but I'd like to point out 2 important things:

  • The offset for SendChatMessage is 0x684A0 (and not 0x5A00).
  • SA-MP R4 has gotten an update and so far I can only say that none of the offsets mentioned here work in that version. I have no intention (yet) to make it compatible with this newer version.
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
I can't seem to edit my first post but I'd like to point out 2 important things:

  • The offset for SendChatMessage is 0x684A0 (and not 0x5A00).
  • SA-MP R4 has gotten an update and so far I can only say that none of the offsets mentioned here work in that version. I have no intention (yet) to make it compatible with this newer version.
Do you still looking for specific memories?
 

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
Do you still looking for specific memories?
Yes in fact I'm trying to find out where player colors are located (color for their blip and name). I've looked through the region where player names (on the scoreboard) are stored, but other than name/ping/score I couldn't find anything.
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
Yes in fact I'm trying to find out where player colors are located (color for their blip and name). I've looked through the region where player names (on the scoreboard) are stored, but other than name/ping/score I couldn't find anything.
All that information is stored from player pool, i will post memories which you need to get that information after my job.
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
0.3.7 R4
C++:
CPlayerPool  = samp.dll + 0x26EA0C + 0x3DE + 0x4


C++:
const char* CPlayerPool::GetName(ID nId) {
    return ((const char*(__thiscall*)(CPlayerPool*, ID))GetAddress(0x175C0))(this, nId);
}
C++:
int CPlayerPool::GetScore(ID nPlayer) {
    return ((int(__thiscall*)(CPlayerPool*, ID))GetAddress(0x6E850))(this, nPlayer);
}
C++:
int CPlayerPool::GetPing(ID nPlayer) {
    return ((int(__thiscall*)(CPlayerPool*, ID))GetAddress(0x6E880))(this, nPlayer);
}
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
C++:
BOOL CPlayerPool::IsConnected(ID nId) {
    return ((BOOL(__thiscall*)(CPlayerPool*, ID))GetAddress(0x10B0))(this, nId);
}
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
Almost forgot.., you need update score board data every 2.5 sec or less don't remeber now..
Othervise you will stop receiving information from it...
C++:
FUNC_UPDATESCOREBOARD = samp.dll + 0x8F00
 

Parazitas

God
Joined
Jan 2, 2017
Messages
3,116
Solutions
5
Reaction score
882
Location
Lithuania
Since i can't edit old posts i'm forced to do double posting...
C++:
samp.dll + 0x113E68 + PLAYER_ID*4 = player color
 

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
Thanks we talked about how to get the player colors, and despite it looking legit at first, it turned out to give wrong colors for given ID. That said, I've been looking for quite some time to find an offset (or function) that gives you access to incoming chat messages. I've found some things but they often contained garbage. Ideally I wanted to find the place where messages are written to the chatlog.txt files inside your userfiles folder. This is what I have finally found:

C++:
typedef void (__thiscall *tChatLogWrite)(void* pThis, int param_1, char* message, char* sender);

The memory location is sampModuleBase + 0x67790

Here is what the decompiled code looks like

C++:
void __thiscall WriteToChatLogFile(void *this,int param_1,char *message,char *sender)
{
    FILE *_File;
    tm *_Tm;
    __time32_t local_48;
    char local_44 [68];
    local_48 = FID_conflict:__time32((__time32_t *)0x0);
    _File = *(FILE **)((int)this + 0xd);
    if (_File != (FILE *)0x0) 
    {
        OpenFileForWriting((char *)((int)this + 0x11),"a");
        
        if (_File != (FILE *)0x0) 
        {
            _Tm = _localtime((time_t *)&local_48);
            _strftime(local_44,0x40,"[%H:%M:%S]",_Tm);
            
            if (param_1 == 2) 
            {
                _fprintf(_File,"%s <%s> %s\r\n",local_44,sender,message);
            }
            else if ((param_1 == 4) || (param_1 == 8)) 
            {
                _fprintf(_File,"%s %s\r\n",local_44,message);
                _fclose(_File);
                return;
            }
            _fclose(_File);
        }
    }
    return;
}

To be able to get these messages you need to create a detour (which I won't be going into, just look around on google on how to do that). I can confirm this is the actual function because I tested it.
 

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
This 2 minute timeframe to be able to edit your post is way too short... Anyway. I have some more information about 'param_1' in WriteToChatLogFile. This parameter is the type of message and it can have 3 different values:

2: whenever receiving a chat message (whether sent by yourself or someone else)
4: whenever receiving a server notification
8: whenever receiving a local debug message

The 'sender' parameter can only be read whenever param_1 is equal to 2, otherwise it's null and it'll crash the application if you try to read it.
 

SIGKILL

Active member
Joined
Apr 29, 2020
Messages
37
Reaction score
22
Location
Earth
I can't seem to edit my first post but I'd like to point out 2 important things:

  • The offset for SendChatMessage is 0x684A0 (and not 0x5A00).
  • SA-MP R4 has gotten an update and so far I can only say that none of the offsets mentioned here work in that version. I have no intention (yet) to make it compatible with this newer version.
I have to correct myself gain. The address 0x684A0 is wrong. I am testing on Linux and somehow there it works, but on windows it does not. You actually do want to use 0x5A00. I was looking through old code and noticed I had both addresses there but forgot exactly why.
 
Top