SA:MP Single курсор для левшей

solitudovskiy

Новичок
Автор темы
12
1
Версия SA-MP
  1. 0.3.7 (R1)
нужен отзеркаленный курсор для сампа
 

alexroq

Участник
111
12
нужен отзеркаленный курсор для сампа
у сампа системный курсор
 

solitudovskiy

Новичок
Автор темы
12
1
у сампа системный курсор
ну так я говорю, замену mouse.png, курсоры для винды кидать мне не надо

ну так я говорю, замену mouse.png, курсоры для винды кидать мне не надо
1765531876333.png
 

alexroq

Участник
111
12
ну так я говорю, замену mouse.png, курсоры для винды кидать мне не надо


Посмотреть вложение 283260

ну так я говорю, замену mouse.png, курсоры для винды кидать мне не надо


Посмотреть вложение 283260
в самом виндоусе даже есть отзеркаливание. нажимаешь на изменить и нажимаешь на иконку две стрелок влево вправо
 

solitudovskiy

Новичок
Автор темы
12
1


в самом виндоусе даже есть отзеркаливание. нажимаешь на изменить и нажимаешь на иконку две стрелок влево вправо
сайт не воркает. про отзеркаливание винды не надо мне говорить, меня не интересует курсор системы
 

БеzликиЙ

Автор темы
Проверенный
1,756
1,024
предупреждаю, пока не поставил: курсор в сампе работает по левому верхнему углу mouse.png, потому что samp.dll не поддерживает подгрузку и определение "активной точки" курсора. поэтому отзеркаленный курсор будет кликать этим углом картинки и это не так-то просто исправить

1765534342771.png
 
  • Нравится
Реакции: solitudovskiy

solitudovskiy

Новичок
Автор темы
12
1
предупреждаю, пока не поставил: курсор в сампе работает по левому верхнему углу mouse.png, потому что samp.dll не поддерживает подгрузку и определение "активной точки" курсора. поэтому отзеркаленный курсор будет кликать этим углом картинки и это не так-то просто исправить

Посмотреть вложение 283262
если фикс этой хуйни магическим образом где то появится, скинь сюда плз
 

moreveal

Известный
974
704
если фикс этой хуйни магическим образом где то появится, скинь сюда плз
оба файла в папку с игрой
меняет чтение файла mouse.png (есть фолбек на SAMP\mouse.png для некоторых экзотических лаунчеров), ожидая там кастомный чанк "chOT":
C++:
struct HotSpot
{
    UINT X, Y;
}
если он его находит - меняет поведение SetCursorProperties, смещая хотспот на нужную позицию

Python:
MOUSE_PATH = r"D:\GTA\mouse.png"

import struct
import zlib

PNG_SIGNATURE = b'\x89PNG\r\n\x1a\n'

def read_png_size(png_bytes):
    if not png_bytes.startswith(PNG_SIGNATURE):
        raise ValueError("Not a PNG")
 
    pos = len(PNG_SIGNATURE)
 
    length = struct.unpack(">I", png_bytes[pos:pos+4])[0]
    chunk_type = png_bytes[pos+4:pos+8]
 
    if chunk_type != b'IHDR' or length != 13:
        raise ValueError("Invalid IHDR")
 
    data = png_bytes[pos+8:pos+8+length]
    width, height = struct.unpack(">II", data[:8])
    return width, height

def make_chunk(chunk_type: bytes, data: bytes) -> bytes:
    length = struct.pack(">I", len(data))
    crc = struct.pack(">I", zlib.crc32(chunk_type + data) & 0xffffffff)
    return length + chunk_type + data + crc

def insert_chunk_after_ihdr(png_bytes, chunk_bytes):
    pos = len(PNG_SIGNATURE)

    ihdr_len = struct.unpack(">I", png_bytes[pos:pos+4])[0]
    ihdr_total = 4 + 4 + ihdr_len + 4

    insert_pos = pos + ihdr_total
    return png_bytes[:insert_pos] + chunk_bytes + png_bytes[insert_pos:]


def add_hotspot_top_right(input_png, output_png):
    with open(input_png, "rb") as f:
        png = f.read()

    width, height = read_png_size(png)

    hotspot_x = width - 1
    hotspot_y = 0

    print(f"PNG size: {width}x{height}")
    print(f"Hotspot: ({hotspot_x}, {hotspot_y})")

    data = struct.pack(">hh", hotspot_x, hotspot_y)
    chunk = make_chunk(b'chOT', data)

    new_png = insert_chunk_after_ihdr(png, chunk)

    with open(output_png, "wb") as f:
        f.write(new_png)


if __name__ == "__main__":
    add_hotspot_top_right(
        MOUSE_PATH,
        MOUSE_PATH
    )
    print('[+] Chunk was added')
C++:
static uint32_t read_u32_be(std::ifstream& f)
{
    uint8_t b[4];
    f.read(reinterpret_cast<char*>(b), 4);
    return (uint32_t(b[0]) << 24) |
           (uint32_t(b[1]) << 16) |
           (uint32_t(b[2]) << 8)  |
           (uint32_t(b[3]));
}

static int16_t read_i16_be(const uint8_t* p)
{
    return int16_t((p[0] << 8) | p[1]);
}

static std::optional<std::pair<UINT, UINT>> read_cursor_hotspot_from_png(const char* path)
{
    std::ifstream f(path, std::ios::binary);
    if (!f)
        return std::nullopt;

    // PNG signature
    uint8_t sig[8];
    f.read(reinterpret_cast<char*>(sig), 8);

    static const uint8_t png_sig[8] =
            { 0x89,'P','N','G',0x0D,0x0A,0x1A,0x0A };

    if (memcmp(sig, png_sig, 8) != 0)
        return std::nullopt;

    while (f)
    {
        uint32_t length = read_u32_be(f);

        char type[5] = {};
        f.read(type, 4);

        if (!f)
            break;

        if (memcmp(type, "chOT", 4) == 0 && length == 4)
        {
            uint8_t data[4];
            f.read(reinterpret_cast<char*>(data), 4);

            int16_t x = read_i16_be(data);
            int16_t y = read_i16_be(data + 2);

            return std::make_pair(UINT(x), UINT(y));
        }
        else
        {
            // skip data
            f.seekg(length, std::ios::cur);
        }

        // skip CRC
        f.seekg(4, std::ios::cur);

        if (memcmp(type, "IEND", 4) == 0)
            break;
    }

    return std::nullopt;
}

using SetCursorPropertiesSignature = HRESULT(__stdcall*)(IDirect3DDevice9*, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap);
kthook::kthook_simple<SetCursorPropertiesSignature> cursor_hook{ get_function_address(10) };
HRESULT on_cursor_properties(const decltype(cursor_hook)& hook, IDirect3DDevice9* pDevice, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap)
{
    static bool init = false;
    static UINT hx = 0, hy = 0;
    if (!init)
    {
        std::optional<std::pair<UINT, UINT>> hs;

        hs = read_cursor_hotspot_from_png("mouse.png");

        if (!hs)
            hs = read_cursor_hotspot_from_png("SAMP\\mouse.png");

        if (hs)
        {
            hx = hs->first;
            hy = hs->second;
        }

        init = true;
    }

    return hook.call_trampoline(pDevice, hx, hy, pCursorBitmap);
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        {
            cursor_hook.set_cb(on_cursor_properties);
            cursor_hook.install();
            break;
        }
        case DLL_PROCESS_DETACH:
        {
            cursor_hook.remove();
        }
    }
    return 1;
}
 

Вложения

  • cursor_hotspot.asi
    52 KB · Просмотры: 1
  • mouse.png
    mouse.png
    1.1 KB · Просмотры: 9
Последнее редактирование:

alexroq

Участник
111
12
сайт не воркает. про отзеркаливание винды не надо мне говорить, меня не интересует курсор системы
чел, я про фотошоп винды, просто открой свой mouse.png и нажми изменить и на иконку отзеркаливания. какой нахуй курсор системы