Иконка ресурса

[ReAPI] Migraine 1.0.7

Нет прав для скачивания
  • Автор темы Автор темы Gramm
  • Дата начала Дата начала

Gramm

Участник
Сообщения
15
Реакции
6
Помог
1 раз(а)
Баллы
3
Gramm добавил(а) новый ресурс:

[ReAPI] Migraine - Переворачиваем экран игрокам

Плагин позволяет администратору "перевернуть" экран игроку или целой команде

Отличие от оригинала:
Работает на последних hlds/rehlds
Ham_Player_PreThink заменен на более оптимизированный RG_CBasePlayer_PostThink
Добавлен аргумент для выбора угла наклона (от -360 до 360). По умолчанию 180
Добавлена команда amx_migraine_info для просмотра списка игроков, на которых действует эффект
Сохраняется угол при рестарте/спавне игрока


Узнать больше об этом ресурсе...
 
Всем привет.
Если никто не против, я немного изменил плагин Migraine:
— слегка подправил код
добавил удобное меню управления (вызов через команду)

Функционал остался тем же, просто стало удобнее пользоваться.
migraine.png


Код:
#pragma semicolon 1
#pragma compress 1

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <reapi>

#define PLUGIN  "Migraine [ReAPI] + Menu"
#define VERSION "1.1.0"
#define AUTHOR  "ConnorMcLeod | Gramm "

#define MAX_PLAYERS 32
#define MaskEnt(%0) (1 << ((%0) & 31))

new g_bitMigraineux;
#define SetUserReversed(%0)     (g_bitMigraineux |= MaskEnt(%0))
#define ClearUserReversed(%0)   (g_bitMigraineux &= ~MaskEnt(%0))
#define HasUserMigraine(%0)     (g_bitMigraineux & MaskEnt(%0))

enum globalState { None, Terrorists, Cts, All }

new Float:g_fAngle[MAX_PLAYERS + 1];
new g_iGlobalState;
new Float:g_fGlobalAngle = 180.0;

new HookChain:g_hPostThink;
new HookChain:g_hSpawn;

// ===== СОСТОЯНИЕ МЕНЮ (для админа) =====
new g_iMenuTargetType[33];   // 0=игрок, 1=@ALL, 2=@T, 3=@CT
new g_iMenuTargetPlayer[33]; // если targetType=0
new g_iMenuOnOff[33];        // 0/1
new Float:g_fMenuAngle[33];  // угол

new const Float:g_fAnglesList[] = { 90.0, 180.0, 270.0, -180.0, -90.0, 360.0, -360.0 };

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR);

    // Старые команды (консоль)
    register_concmd("amx_migraine", "AdminCommand_Migraine", ADMIN_BAN, "- <name/@CT/@T/@ALL> <0/1> [angle]");
    register_concmd("amx_migraine_info", "AdminCommand_MigraineInfo", ADMIN_BAN, "- показывает список игроков с эффектом");

    // Меню
    register_clcmd("say /migraine", "CmdOpenMigraineMenu");
    register_clcmd("say_team /migraine", "CmdOpenMigraineMenu");
    register_concmd("amx_migraine_menu", "CmdOpenMigraineMenu", ADMIN_BAN, "- открыть меню Migraine");
}

public client_putinserver(id)
{
    ClearUserReversed(id);
    g_fAngle[id] = 0.0;

    // Значения меню по умолчанию
    g_iMenuTargetType[id] = 0;
    g_iMenuTargetPlayer[id] = id;
    g_iMenuOnOff[id] = 1;
    g_fMenuAngle[id] = 180.0;

    CheckForwards();
}

public client_disconnected(id)
{
    ClearUserReversed(id);
    g_fAngle[id] = 0.0;
    CheckForwards();
}

// ==================== ХУКИ ====================

public OnPlayerSpawn(id)
{
    // Post Spawn
    if (!is_user_alive(id))
        return HC_CONTINUE;

    switch (g_iGlobalState)
    {
        case Terrorists, Cts:
        {
            if (g_iGlobalState == _:cs_get_user_team(id))
            {
                SetUserReversed(id);
                g_fAngle[id] = g_fGlobalAngle;
            }
            else
            {
                ClearUserReversed(id);
                g_fAngle[id] = 0.0;
            }
        }
        case All:
        {
            SetUserReversed(id);
            g_fAngle[id] = g_fGlobalAngle;
        }
        default:
        {
            ClearUserReversed(id);
            g_fAngle[id] = 0.0;
        }
    }

    CheckForwards();

    if (HasUserMigraine(id))
        RequestFrame("ApplyAngleAfterSpawn", id);

    return HC_CONTINUE;
}

public ApplyAngleAfterSpawn(id)
{
    if (is_user_alive(id) && HasUserMigraine(id))
    {
        new Float:vecPunch[3];
        vecPunch[2] = g_fAngle[id];
        set_entvar(id, var_punchangle, vecPunch);
    }
}

public OnPlayerPostThink(id)
{
    if (!is_user_alive(id) || !HasUserMigraine(id))
        return HC_CONTINUE;

    new Float:vecPunch[3];
    vecPunch[2] = g_fAngle[id];
    set_entvar(id, var_punchangle, vecPunch);

    return HC_CONTINUE;
}

// ==================== ПРИМЕНЕНИЕ ЭФФЕКТА (ядро) ====================

stock Migraine_ResetPunch(id)
{
    new Float:vec[3];
    set_entvar(id, var_punchangle, vec);
}

stock Migraine_ResetAllPunch()
{
    for (new i = 1; i <= MaxClients; i++)
    {
        if (is_user_connected(i))
            Migraine_ResetPunch(i);

        g_fAngle[i] = 0.0;
        ClearUserReversed(i);
    }
}

stock Migraine_Apply(admin, const target[], onoff, Float:angle)
{
    // Ограничение угла
    if (angle > 360.0) angle = 360.0;
    else if (angle < -360.0) angle = -360.0;

    g_fGlobalAngle = angle;

    new szAdminName[32];
    get_user_name(admin, szAdminName, charsmax(szAdminName));

    // ======= ГЛОБАЛЬНЫЕ ЦЕЛИ (@...) =======
    if (target[0] == '@')
    {
        if (!onoff)
        {
            g_bitMigraineux = 0;
            g_iGlobalState = None;
            g_fGlobalAngle = 180.0;

            Migraine_ResetAllPunch();

            client_print_color(0, print_team_default,
                "^4[Migraine]^1 Администратор ^4%s^1 отключил эффект для всех.", szAdminName);

            CheckForwards();
            return 1;
        }

        new szTeamName[64];

        switch (target[1])
        {
            case 'a', 'A': { g_iGlobalState = All;        copy(szTeamName, charsmax(szTeamName), "всех игроков"); }
            case 't', 'T': { g_iGlobalState = Terrorists; copy(szTeamName, charsmax(szTeamName), "Террористов"); }
            case 'c', 'C': { g_iGlobalState = Cts;        copy(szTeamName, charsmax(szTeamName), "Контр-Террористов"); }
            default: return 0;
        }

        for (new i = 1; i <= MaxClients; i++)
        {
            if (!is_user_connected(i))
                continue;

            if (g_iGlobalState == All ||
                (g_iGlobalState == Terrorists && cs_get_user_team(i) == CS_TEAM_T) ||
                (g_iGlobalState == Cts        && cs_get_user_team(i) == CS_TEAM_CT))
            {
                SetUserReversed(i);
                g_fAngle[i] = g_fGlobalAngle;

                if (is_user_alive(i))
                {
                    new Float:vecPunch[3];
                    vecPunch[2] = g_fAngle[i];
                    set_entvar(i, var_punchangle, vecPunch);
                }
            }
            else
            {
                ClearUserReversed(i);
                g_fAngle[i] = 0.0;

                if (is_user_alive(i))
                    Migraine_ResetPunch(i);
            }
        }

        client_print_color(0, print_team_default,
            "^4[Migraine]^1 Администратор ^4%s^1 перевернул экран для ^3%s^1 на ^4%.0f^1 градусов.",
            szAdminName, szTeamName, g_fGlobalAngle);

        CheckForwards();
        return 1;
    }

    // ======= ОДНА ЦЕЛЬ (ник / #userid) =======
    new iPlayer = cmd_target(admin, target, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_ALLOW_SELF);
    if (!iPlayer) return 0;

    if (onoff)
    {
        SetUserReversed(iPlayer);
        g_fAngle[iPlayer] = g_fGlobalAngle;

        if (is_user_alive(iPlayer))
        {
            new Float:vecPunch[3];
            vecPunch[2] = g_fAngle[iPlayer];
            set_entvar(iPlayer, var_punchangle, vecPunch);
        }

        client_print_color(0, print_team_default,
            "^4[Migraine]^1 Администратор ^4%s^1 перевернул экран игроку ^3%n^1 на ^4%.0f^1 градусов.",
            szAdminName, iPlayer, g_fGlobalAngle);
    }
    else
    {
        ClearUserReversed(iPlayer);
        g_fAngle[iPlayer] = 0.0;
        Migraine_ResetPunch(iPlayer);

        client_print_color(0, print_team_default,
            "^4[Migraine]^1 Администратор ^4%s^1 вернул нормальный экран игроку ^3%n^1.",
            szAdminName, iPlayer);
    }

    CheckForwards();
    return 1;
}

// ==================== КОМАНДЫ ====================

public AdminCommand_Migraine(id, level, cid)
{
    if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED;

    new szTarget[32], szOnOff[2], szAngle[16];
    read_argv(1, szTarget, charsmax(szTarget));
    read_argv(2, szOnOff, charsmax(szOnOff));

    new iOnOff;
    if (szOnOff[0] == '1') iOnOff = 1;
    else if (szOnOff[0] == '0') iOnOff = 0;
    else return PLUGIN_HANDLED;

    new Float:angle = 180.0;
    if (read_argc() >= 4)
    {
        read_argv(3, szAngle, charsmax(szAngle));
        angle = str_to_float(szAngle);
    }

    Migraine_Apply(id, szTarget, iOnOff, angle);
    return PLUGIN_HANDLED;
}

public AdminCommand_MigraineInfo(id, level, cid)
{
    if (!cmd_access(id, level, cid, 1))
        return PLUGIN_HANDLED;

    new iCount, szName[32], szTeam[16];

    console_print(id, "^n========================================");
    console_print(id, "[Migraine] Список игроков с эффектом:");
    console_print(id, "========================================");

    switch (g_iGlobalState)
    {
        case All:        console_print(id, "Режим: ВСЕ игроки (%.0f градусов)", g_fGlobalAngle);
        case Terrorists: console_print(id, "Режим: Террористы (%.0f градусов)", g_fGlobalAngle);
        case Cts:        console_print(id, "Режим: Контр-Террористы (%.0f градусов)", g_fGlobalAngle);
        default:         console_print(id, "Режим: Отключен");
    }

    console_print(id, "----------------------------------------");

    for (new i = 1; i <= MaxClients; i++)
    {
        if (is_user_connected(i) && HasUserMigraine(i))
        {
            get_user_name(i, szName, charsmax(szName));

            switch (cs_get_user_team(i))
            {
                case CS_TEAM_T:         copy(szTeam, charsmax(szTeam), "T");
                case CS_TEAM_CT:        copy(szTeam, charsmax(szTeam), "CT");
                case CS_TEAM_SPECTATOR: copy(szTeam, charsmax(szTeam), "SPEC");
                default:                copy(szTeam, charsmax(szTeam), "NONE");
            }

            console_print(id, "%2d. %s [%s] - Угол: %.0f %s",
                ++iCount, szName, szTeam, g_fAngle[i], is_user_alive(i) ? "" : "(мертв)");
        }
    }

    if (!iCount) console_print(id, "Нет игроков с активным эффектом.");
    else
    {
        console_print(id, "----------------------------------------");
        console_print(id, "Всего игроков с эффектом: %d", iCount);
    }

    console_print(id, "========================================^n");
    return PLUGIN_HANDLED;
}

// ==================== МЕНЮ ====================

public CmdOpenMigraineMenu(id)
{
    if (!(get_user_flags(id) & ADMIN_BAN))
        return PLUGIN_HANDLED;

    // Если "слетело" — ставим нормальную цель
    if (!is_user_connected(g_iMenuTargetPlayer[id]))
        g_iMenuTargetPlayer[id] = id;

    if (g_fMenuAngle[id] == 0.0)
        g_fMenuAngle[id] = 180.0;

    ShowMigraineMenu(id);
    return PLUGIN_HANDLED;
}

ShowMigraineMenu(id)
{
    new menu = menu_create("\yMigraine Menu \r[ReAPI]", "MigraineMenu_Handler");

    new sz[192];
    new const targetNames[][] = { "Игрок", "@ALL", "@T", "@CT" };

    formatex(sz, charsmax(sz), "\wЦель: \y%s", targetNames[g_iMenuTargetType[id]]);
    menu_additem(menu, sz, "1");

    if (g_iMenuTargetType[id] == 0)
    {
        formatex(sz, charsmax(sz), "\wИгрок: \y%n \d(следующий)", g_iMenuTargetPlayer[id]);
        menu_additem(menu, sz, "2");
    }
    else
    {
        menu_additem(menu, "\dИгрок: (не требуется)", "2");
    }

    formatex(sz, charsmax(sz), "\wРежим: \y%s", g_iMenuOnOff[id] ? "ON (перевернуть)" : "OFF (выключить)");
    menu_additem(menu, sz, "3");

    formatex(sz, charsmax(sz), "\wУгол: \y%.0f \d(клик — изменить)", g_fMenuAngle[id]);
    menu_additem(menu, sz, "4");

    menu_additem(menu, "\rПрименить", "5");
    menu_additem(menu, "\wСписок в консоль", "6");

    menu_setprop(menu, MPROP_EXITNAME, "Выход");
    menu_display(id, menu);
}

public MigraineMenu_Handler(id, menu, item)
{
    if (item == MENU_EXIT)
    {
        menu_destroy(menu);
        return PLUGIN_HANDLED;
    }

    new info[8], access, callback;
    menu_item_getinfo(menu, item, access, info, charsmax(info), _, _, callback);
    new key = str_to_num(info);

    switch (key)
    {
        case 1:
        {
            g_iMenuTargetType[id]++;
            if (g_iMenuTargetType[id] > 3) g_iMenuTargetType[id] = 0;
        }
        case 2:
        {
            if (g_iMenuTargetType[id] == 0)
            {
                new start = g_iMenuTargetPlayer[id];
                if (start < 1 || start > MaxClients) start = 0;

                for (new i = 1; i <= MaxClients; i++)
                {
                    new p = start + i;
                    if (p > MaxClients) p -= MaxClients;

                    if (is_user_connected(p))
                    {
                        g_iMenuTargetPlayer[id] = p;
                        break;
                    }
                }
            }
        }
        case 3:
        {
            g_iMenuOnOff[id] = !g_iMenuOnOff[id];
        }
        case 4:
        {
            new idx = -1;
            for (new i = 0; i < sizeof(g_fAnglesList); i++)
            {
                if (floatabs(g_fAnglesList[i] - g_fMenuAngle[id]) < 0.1)
                {
                    idx = i;
                    break;
                }
            }
            idx++;
            if (idx >= sizeof(g_fAnglesList)) idx = 0;
            g_fMenuAngle[id] = g_fAnglesList[idx];
        }
        case 5:
        {
            new target[32];

            switch (g_iMenuTargetType[id])
            {
                case 0: formatex(target, charsmax(target), "#%d", get_user_userid(g_iMenuTargetPlayer[id]));
                case 1: copy(target, charsmax(target), "@ALL");
                case 2: copy(target, charsmax(target), "@T");
                case 3: copy(target, charsmax(target), "@CT");
            }

            Migraine_Apply(id, target, g_iMenuOnOff[id], g_fMenuAngle[id]);
        }
        case 6:
        {
            AdminCommand_MigraineInfo(id, ADMIN_BAN, 0);
        }
    }

    menu_destroy(menu);
    ShowMigraineMenu(id);
    return PLUGIN_HANDLED;
}

// ==================== ДИНАМИЧЕСКИЕ ХУКИ ====================

CheckForwards()
{
    static bool:bEnabled = false;
    new bool:bNeed = (g_bitMigraineux != 0);

    if (bNeed == bEnabled)
        return;

    if (bNeed)
    {
        if (!g_hPostThink)
        {
            g_hPostThink = RegisterHookChain(RG_CBasePlayer_PostThink, "OnPlayerPostThink", false);
            g_hSpawn     = RegisterHookChain(RG_CBasePlayer_Spawn, "OnPlayerSpawn", true); // post
        }
        else
        {
            EnableHookChain(g_hPostThink);
            EnableHookChain(g_hSpawn);
        }
    }
    else
    {
        if (g_hPostThink) DisableHookChain(g_hPostThink);
        if (g_hSpawn)     DisableHookChain(g_hSpawn);
    }

    bEnabled = bNeed;
}
 

Кто просматривает тему

Назад
Верх