Склад функций SourcePawn

Vit_ amin

Добрая душа
Сообщения
1,565
Реакции
749
Плагин для получения степени ослепления от слеповой гранаты и контроль ослепления для определённых игроков (расширенная версия Blind Hook без его использования).
Работы была сделана для одного проекта на бесплатной основе
Для работы требуются:
  • Linux версия CS: Source Steam
  • Сигнатуры
  • Получение интерфейса IMemAlloc для alloc/free memory или аналог
  • Заполнение methodmap под класс CCSPlayer или замена на API SourcePawn
  • Понимание сути кода (при обновлении бинарного кода библиотеки server) - при поломки кода от выделенной памяти в куче
C-подобный:
#pragma newdecls required
#pragma semicolon 1

#include <cs_main_plugin>
#include <dhooks>

#define PLUGIN_VERSION "1.1.0.0"

Address g_addrRadiusFlashHook;
Address g_addrReturnNormal;
Address g_addrReturnBlock;
Address g_pDummyFunc;
Address g_pShellcode;
DynamicDetour g_hFlashMidHook;

public Plugin myinfo =
{
    name = "[CS:S] Flashbang Stuff",
    author = "Vitamin",
    description = "Private plugin for managment player's blind",
    version = PLUGIN_VERSION,
    url = "https://gunserver.ru"
};

public void OnPluginStart()
{
    CreateConVar("sv_flashbang_stuff_version", PLUGIN_VERSION, "Version of the Plugin", FCVAR_NOTIFY);

    g_hGameData = new GameData(GAMEDATA_NAME);

    g_addrRadiusFlashHook = g_hGameData.GetAddress("RadiusFlash_MidHookPoint");
    g_addrReturnNormal = g_addrRadiusFlashHook + 0x05;
    g_addrReturnBlock = g_hGameData.GetAddress("RadiusFlash_BlockJumpPoint");

    g_pMemAlloc = CStdMemAlloc();
    g_pShellcode = g_pMemAlloc.Alloc(0x60);
    g_pDummyFunc = g_pMemAlloc.Alloc(0x20);
    if (!g_pShellcode || !g_pDummyFunc)
    {
        SetFailState("Failed to allocate memory for shellcode");
    }
    int dummyCode[] =
    {
        0x55,                               // push ebp
        0x89, 0xE5,                         // mov ebp, esp
        0x90, 0x90, 0x90, 0x90, 0x90,       // nop
        0x31, 0xC0,                         // xor eax, eax
        0x5D,                               // pop ebp
        0xC2, 0x10, 0x00                    // ret 0x10 (4 arg * sizeof(x86))
    };
    WriteBytes(g_pDummyFunc, dummyCode, sizeof(dummyCode));

    int sc[] =
    {
        0x60, 0x9C,                         // [0x00] pushad, pushfd
        0x83, 0xEC, 0x30,                   // [0x02] sub esp, 48
        0x0F, 0x11, 0x04, 0x24,             // [0x05] movups [esp], xmm0
        0x0F, 0x11, 0x4C, 0x24, 0x10,       // [0x09] movups [esp+16], xmm1
        0x0F, 0x11, 0x54, 0x24, 0x20,       // [0x0E] movups [esp+32], xmm2
        0xFF, 0x75, 0x1C,                   // [0x13] push [ebp+1Ch] (maxDamage)
        0x83, 0xEC, 0x04,                   // [0x16] sub esp, 4
        0xF3, 0x0F, 0x11, 0x04, 0x24,       // [0x19] movss [esp], xmm0 (fadeTime)
        0xFF, 0x75, 0x18,                   // [0x1E] push [ebp+18h] (Attacker)
        0x57,                               // [0x21] push edi (Victim)
        0xB8, 0x00, 0x00, 0x00, 0x00,       // [0x22] mov eax, dummy_addr
        0xFF, 0xD0,                         // [0x27] call eax
        0x0F, 0x10, 0x04, 0x24,             // [0x29] movups xmm0, [esp]
        0x0F, 0x10, 0x4C, 0x24, 0x10,       // [0x2D] movups xmm1, [esp+16]
        0x0F, 0x10, 0x54, 0x24, 0x20,       // [0x32] movups xmm2, [esp+32]
        0x83, 0xC4, 0x30,                   // [0x37] add esp, 48
        0x89, 0x44, 0x24, 0x20,             // [0x3A] mov [esp+32], eax
        0x9D, 0x61,                         // [0x3E] popfd, popad
        0x83, 0xF8, 0x01,                   // [0x40] cmp eax, 1
        0x74, 0x0B,                         // [0x43] je BLOCK
        0x8B, 0x4D, 0x18,                   // [0x45] mov ecx, [ebp+18h]
        0x85, 0xC9,                         // [0x48] test ecx, ecx
        0x68, 0x00, 0x00, 0x00, 0x00,       // [0x4A] push addrNormal
        0xC3,                               // [0x4F] ret
        0x68, 0x00, 0x00, 0x00, 0x00,       // [0x50] push addrBlock
        0xC3                                // [0x55] ret
    };
    WriteBytes(g_pShellcode, sc, sizeof(sc));

    StoreToAddress(g_pShellcode + 0x23, g_pDummyFunc, NumberType_Int32);
    StoreToAddress(g_pShellcode + 0x4B, g_addrReturnNormal, NumberType_Int32);
    StoreToAddress(g_pShellcode + 0x51, g_addrReturnBlock, NumberType_Int32);

    g_hFlashMidHook = new DynamicDetour(g_pDummyFunc, CallConv_STDCALL, ReturnType_Int, ThisPointer_Ignore);
    g_hFlashMidHook.AddParam(HookParamType_CBaseEntity); // Victim
    g_hFlashMidHook.AddParam(HookParamType_CBaseEntity); // Attacker
    g_hFlashMidHook.AddParam(HookParamType_Float);       // fadeTime
    g_hFlashMidHook.AddParam(HookParamType_Float);       // maxDamage
    g_hFlashMidHook.Enable(Hook_Pre, DHookCB_RadiusFlash);

    if (!g_MemPatcher.InstallJMP("RadiusFlash_MidHook", g_addrRadiusFlashHook, g_pShellcode))
    {
        SetFailState("Failed to install JMP from RadiusFlash to Shellcode");
    }
}
public void OnPluginEnd()
{
    g_MemPatcher.RestoreAll();
    g_hFlashMidHook.Disable(Hook_Pre, DHookCB_RadiusFlash);
    delete g_hFlashMidHook;

    if (g_pShellcode)
    {
        g_pMemAlloc.Free(g_pShellcode);
    }

    if (g_pDummyFunc)
    {
        g_pMemAlloc.Free(g_pDummyFunc);
    }
}
static stock MRESReturn DHookCB_RadiusFlash(DHookReturn hReturn, DHookParam hParams)
{
    CCSPlayer pVictim = hParams.Get(1);
    if (pVictim.GetTeamNumber() == CS_TEAM_SPECTATOR)
    {
        if (GetUserFlagBits(pVictim.entindex()) & (ADMFLAG_GENERIC | ADMFLAG_ROOT))
        {
            color32 clr;
            clr.r = 220;
            clr.g = 220;
            clr.b = 220;
            clr.a = 80;

            float fadeTime = hParams.Get(3);
            float maxDamage = hParams.Get(4);

            float maxPossible = maxDamage * 2.5 * 0.957;
            float totalIntensity = (maxPossible > 0.01) ? (fadeTime / maxPossible) : 0.0;
            if (totalIntensity > 1.0)
            {
                totalIntensity = 1.0;
            }

            int iPercent = RoundToNearest(totalIntensity * 100.0);
            UTIL_ScreenFade(pVictim.entindex(), clr, 0.1, 0.05, FFADE_IN);
            PrintToChat(pVictim.entindex(), "Была попытка ослепления. Степень ослепления: %d%%", iPercent);
 
            hReturn.Value = 1;
            return MRES_Supercede;
        }

        hReturn.Value = 0;
        return MRES_Supercede;
    }

    CCSPlayer pAttacker = hParams.Get(2);
    if (pAttacker.entindex() == pVictim.entindex())
    {
        hReturn.Value = 0;
        return MRES_Supercede;
    }

    if (pAttacker.GetTeamNumber() == pVictim.GetTeamNumber())
    {
        hReturn.Value = 1;
        return MRES_Supercede;
    }

    hReturn.Value = 0;
    return MRES_Supercede;
}
Happy new year ..
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,642
Реакции
5,114
получения степени ослепления от слеповой гранаты и контроль ослепления для определённых игроков
емнип, для такого даже сигнатуры не нужны, а вот напрямую получить кто ослепил - никак
 

Vit_ amin

Добрая душа
Сообщения
1,565
Реакции
749
емнип, для такого даже сигнатуры не нужны, а вот напрямую получить кто ослепил - никак
Ну если я таким образом написал код, значит это сделано не просто так - вы так не думали?

P. S. Каким образом вы собрались получать максимальное значение при конкретном случае броска, чтобы из него извлечь процент от максимума?
Именно для этого был введён 4-ый аргумент, так как через него - есть получить максимальное значение на текущей сесси броска (так как damage - не постоянное значение), при этом не забывайте - что нам надо блокировать функционал, связанный с ослеплением (blind + deafen), если вы попробуйте получить NetProp'ы (судя по всему вы хотите в ними работать) - то вы не сможете их использовать - так как слишком рано для их получения.
Либо предоставьте иное решение, возможно я чего-то не знаю.
 
Последнее редактирование:
Сверху Снизу