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

Grey83

не пишу плагины с весны 2022
Сообщения
8,805
Реакции
5,254
@MurderCore, без понятия где брать геймдату под l4d2
 

Андрей83

Участник
Сообщения
60
Реакции
4
Всех приветствую !!! прочитал тут все и капец ужаснулся )))
Ребят помогите такой рес нужен
1). автоматически рес VIP игрока в начале раунда
2). (что бы можно было настроить в первые 5-10 секунд например) с начала раунда автоматически ресало игрока только в начале раунда
3). и только 1 рес.
 

BloodyAngel

Участник
Сообщения
72
Реакции
54
- Обновлён синтаксис.
- Проверена компиляция на sourcemod-1.12.0-git7210 для всех указанных игр.
- В папке plugins есть собранный плагин для каждой из указанных игр.
А также, в папке gamedata есть gamedata файл vip_respawn с сигнатурами для игр: L4D и L4D2.
 

Вложения

  • VIP_Respawn_1.6.zip
    43.6 КБ · Просмотры: 17

Synd1qate

Участник
Сообщения
999
Реакции
465
- Обновлён синтаксис.
- Проверена компиляция на sourcemod-1.12.0-git7210 для всех указанных игр.
- В папке plugins есть собранный плагин для каждой из указанных игр.
А также, в папке gamedata есть gamedata файл vip_respawn с сигнатурами для игр: L4D и L4D2.
Выражаю тебе от себя благодарность, что ты этим занимаешься.
 

skywalker

Участник
Сообщения
1,164
Реакции
265
- Обновлён синтаксис.
- Проверена компиляция на sourcemod-1.12.0-git7210 для всех указанных игр.
- В папке plugins есть собранный плагин для каждой из указанных игр.
А также, в папке gamedata есть gamedata файл vip_respawn с сигнатурами для игр: L4D и L4D2.
Я просмотрел плагин в целом. Краткий, предметный вердикт ниже.

Что в порядке​

  1. Структура и стиль
    • #pragma semicolon 1 и #pragma newdecls required — корректно.
    • Код в целом написан под SourceMod 1.11–1.12, стиль аккуратный.
    • Логика лимитов, режимов (LIMIT_MODE, MIN_ALIVE_MODE) реализована последовательно.
    • Использование StringMap вместо старых Trie — правильно.
    • Проверки на доступ VIP-фич (VIP_GetClientFeatureStatus, VIP_IsClientFeatureUse) сделаны корректно.
    • Разделение по играм (L4D/L4D2/DODS) концептуально верное.
  2. Логика безопасности
    • Есть проверки на минимальное количество живых.
    • Учитывается время после старта раунда.
    • Есть уведомления игроку при невозможности респавна.

Проблемы и потенциальные ошибки​

❗ Критическая ошибка препроцессора​

В коде есть синтаксически неверная директива:

#elseif defined GA
ME_DODS
Handle g_hPlayerRespawn = null;
#endif
Это 100% compile error.
Должно быть, например:

#elif defined GAME_DODS
Handle g_hPlayerRespawn = null;
#endif
Сейчас GA и ME_DODS интерпретируются как мусор, плагин не скомпилируется..
 

Synd1qate

Участник
Сообщения
999
Реакции
465
Я просмотрел плагин в целом. Краткий, предметный вердикт ниже.

Что в порядке​

  1. Структура и стиль
    • #pragma semicolon 1 и #pragma newdecls required — корректно.
    • Код в целом написан под SourceMod 1.11–1.12, стиль аккуратный.
    • Логика лимитов, режимов (LIMIT_MODE, MIN_ALIVE_MODE) реализована последовательно.
    • Использование StringMap вместо старых Trie — правильно.
    • Проверки на доступ VIP-фич (VIP_GetClientFeatureStatus, VIP_IsClientFeatureUse) сделаны корректно.
    • Разделение по играм (L4D/L4D2/DODS) концептуально верное.
  2. Логика безопасности
    • Есть проверки на минимальное количество живых.
    • Учитывается время после старта раунда.
    • Есть уведомления игроку при невозможности респавна.

Проблемы и потенциальные ошибки​

❗ Критическая ошибка препроцессора​

В коде есть синтаксически неверная директива:

#elseif defined GA
ME_DODS
Handle g_hPlayerRespawn = null;
#endif
Это 100% compile error.
Должно быть, например:

#elif defined GAME_DODS
Handle g_hPlayerRespawn = null;
#endif
Сейчас GA и ME_DODS интерпретируются как мусор, плагин не скомпилируется..
Посмотреть код через нейронку и написать вердикт? Сильно...
 

Nekro

Терра инкогнита
Сообщения
4,169
Реакции
2,500
Я просмотрел плагин в целом. Краткий, предметный вердикт ниже.

Что в порядке​

  1. Структура и стиль
    • #pragma semicolon 1 и #pragma newdecls required — корректно.
    • Код в целом написан под SourceMod 1.11–1.12, стиль аккуратный.
    • Логика лимитов, режимов (LIMIT_MODE, MIN_ALIVE_MODE) реализована последовательно.
    • Использование StringMap вместо старых Trie — правильно.
    • Проверки на доступ VIP-фич (VIP_GetClientFeatureStatus, VIP_IsClientFeatureUse) сделаны корректно.
    • Разделение по играм (L4D/L4D2/DODS) концептуально верное.
  2. Логика безопасности
    • Есть проверки на минимальное количество живых.
    • Учитывается время после старта раунда.
    • Есть уведомления игроку при невозможности респавна.

Проблемы и потенциальные ошибки​

❗ Критическая ошибка препроцессора​

В коде есть синтаксически неверная директива:

#elseif defined GA
ME_DODS
Handle g_hPlayerRespawn = null;
#endif
Это 100% compile error.
Должно быть, например:

#elif defined GAME_DODS
Handle g_hPlayerRespawn = null;
#endif
Сейчас GA и ME_DODS интерпретируются как мусор, плагин не скомпилируется..
Что ж творится та товарищи?! Компилится!
C-подобный:
SourcePawn Compiler 1.11.0.6927
Copyright (c) 1997-2006 ITB CompuPhase   
Copyright (c) 2004-2021 AlliedModders LLC

Code size:         12784 bytes
Data size:         5756 bytes
Stack/heap size:      16584 bytes
Total requirements:   35124 bytes

Done.

Так вы нам соврали про 100% ошибку? Вам не стыдно?

А чего сигнатуры та не проверили?

стиль аккуратный.
Не сказал бы, что поддерживать ряд игр в одном плагине это аккуратный стиль, который увеличивает количество кода в 2-3 раза

Чисто мельком пробежался


C-подобный:
#pragma semicolon 1
#pragma newdecls required

#include <cstrike>
#include <sdktools_gamerules>
#include <vip_core>

Handle g_hTimer = null;
StringMap g_hAuthTrie;

ConVar
    cvLimit,
    cvAutoReaspawn,
    cvMinAliveMode,
    cvEnable,
    cvMapLimit,
    cvEndDuration,
    cvMinAlive;

bool
    g_bAutoRespawn[MAXPLAYERS+1],
    g_bEnabledRespawn;

int
    g_iClientRespawns[MAXPLAYERS+1],
    g_iRoundStartTime;

float g_fDeathTime[MAXPLAYERS+1];

static const char
    g_szFeature[] = "Respawn",
    g_szFeatureRespawnWaitTime[] = "RespawnWaitTime",
    g_szFeatureAutoRespawn[] = "AutoRespawn";

public void OnPluginStart()
{
    g_hAuthTrie = new StringMap();

    cvLimit = CreateConVar("sm_vip_respawn_limit", "-1", "Режим работы лимита: 1 - X раз за раунд, 0 - X раз за карту; -1 выключен", 0, true, 0.0, true, 1.0);
    cvAutoReaspawn = CreateConVar("sm_vip_respawn_autoreaspawn", "0", "Использовать ли Авто Возрождение", 0, true, 0.0, true, 1.0);
    cvMinAliveMode = CreateConVar("sm_vip_respawn_minalivemod", "0", "режим автрореспавна: 0 — выкл, 1 — по своей команде, 2 — по противнику, 3 — по обеим командам.", 0, true, 0.0, true, 3.0);
    cvEnable = CreateConVar("sm_vip_respawn_enable", "1", "Включен ли плагин (0 - Отключен, 1 - Включен)", 0, true, -1.0, true, 1.0);
    cvMapLimit = CreateConVar("sm_vip_respawn_map_limit", "-1", "Ограничение респавнов за раунд/карту для карты (-1 - нет ограничения, 0 - запрещено, 1 и больше)", 0, true, -1.0);
    cvEndDuration = CreateConVar("sm_vip_respawn_end_duration", "0.0", "Сколько секунд после начала раунда игрок может возрождаться (0.0 - Отключено)", 0, true, 0.0);
    cvMinAlive = CreateConVar("sm_vip_respawn_min_alive", "0", "Сколько минимально должно быть живых игроков в команде чтобы игрок мог возрождаться (0 - Отключено)", 0, true, 0.0);

    AutoExecConfig(true, "VIP_Respawn", "vip");

    RegConsoleCmd("sm_respawn", Cmd_Respawn);

    HookEventEx("round_freeze_end", Event_RoundStart, EventHookMode_PostNoCopy);
    HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
    HookEvent("player_death", Event_PlayerDeath);

    LoadTranslations("vip_respawn.phrases");
    LoadTranslations("vip_modules.phrases");
    LoadTranslations("vip_core.phrases");

    if(VIP_IsVIPLoaded())
    {
        VIP_OnVIPLoaded();
    }
}

public void VIP_OnVIPLoaded()
{
    VIP_RegisterFeature(g_szFeature, INT, SELECTABLE, OnSelectItem, OnDisplayItem);
    VIP_RegisterFeature(g_szFeatureRespawnWaitTime, INT, HIDE);
    
    if(cvAutoReaspawn.BoolValue)
        VIP_RegisterFeature(g_szFeatureAutoRespawn, BOOL, TOGGLABLE, OnToggleItem, _, OnDrawItem);
}

public void OnPluginEnd()
{
    if(CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "VIP_UnregisterFeature") == FeatureStatus_Available)
    {
        VIP_UnregisterFeature(g_szFeature);
        VIP_UnregisterFeature(g_szFeatureRespawnWaitTime);
        if(cvAutoReaspawn.BoolValue)
            VIP_UnregisterFeature(g_szFeatureAutoRespawn);
    }
}

public void OnMapStart()
{
    if(cvLimit.IntValue != 0)
        return;

    g_hAuthTrie.Clear();
    for(int i = 1; i <= MaxClients; ++i) g_iClientRespawns[i] = 0;
}

public Action Cmd_Respawn(int iClient, int args)
{
    if(iClient)
    {
        if(!cvEnable.BoolValue)
        {
            VIP_PrintToChatClient(iClient, "%t", "RESPAWN_OFF");
        }
        if(VIP_IsClientVIP(iClient) && VIP_IsClientFeatureUse(iClient, g_szFeature))
        {
            RespawnClient(iClient);
        }
        else
        {
            VIP_PrintToChatClient(iClient, "%t", "COMMAND_NO_ACCESS");
        }
    }
    return Plugin_Handled;
}

public void Event_RoundStart(Event hEvent, const char[] name, bool dontBroadcast)
{
    if(cvLimit.IntValue == 1)
    {
        g_hAuthTrie.Clear();
        for(int i = 1; i <= MaxClients; ++i)
            g_iClientRespawns[i] = 0;
    }

    if (g_hTimer)
        delete g_hTimer;

    g_bEnabledRespawn = true;

    if (cvEndDuration.FloatValue)
    {
        g_hTimer = CreateTimer(cvEndDuration.FloatValue, Timer_DisableRespawn);
    }
    
    g_iRoundStartTime = GetTime();
}

public Action Timer_DisableRespawn(Handle hTimer)
{
    g_bEnabledRespawn = false;
    g_hTimer = null;
    return Plugin_Stop;
}

public void Event_RoundEnd(Event hEvent, const char[] name, bool dontBroadcast)
{
    g_bEnabledRespawn = false;

    if (g_hTimer)
        delete g_hTimer;
}

public void OnClientPutInServer(int iClient)
{
    if(cvAutoReaspawn.BoolValue)
        g_bAutoRespawn[iClient] = false;

    g_iClientRespawns[iClient] = 0;

    char sAuth[32];
    GetClientAuthId(iClient, AuthId_Engine, sAuth, sizeof(sAuth));
    g_hAuthTrie.GetValue(sAuth, g_iClientRespawns[iClient]);
}

public void Event_PlayerDeath(Event hEvent, const char[] name, bool dontBroadcast)
{
    int iClient = GetClientOfUserId(hEvent.GetInt("userid"));
    g_fDeathTime[iClient] = GetGameTime();

    if (!cvAutoReaspawn.BoolValue)
        return;

    if (!g_bAutoRespawn[iClient])
        return;

    if (!IsAllowedTimeAfterRoundStart(iClient))
        return;

    CreateTimer(1.0, Timer_RespawnClient, GetClientUserId(iClient), TIMER_FLAG_NO_MAPCHANGE);
}

public Action Timer_RespawnClient(Handle hTimer, any iUserID)
{
    if(!cvAutoReaspawn.BoolValue)
        return Plugin_Stop;

    int iClient = GetClientOfUserId(iUserID);
    if(iClient && IsClientInGame(iClient) && CheckRespawn(iClient, false))
    {
        VIP_PrintToChatClient(iClient, "%t", "AUTORESPAWN_NOTIFY");
        RespawnClient(iClient, false);
    }

    return Plugin_Stop;
}

stock void RespawnClient(int iClient, bool bCheck = true)
{
    if(bCheck && !CheckRespawn(iClient, true))
    {
        return;
    }

    ++g_iClientRespawns[iClient];

    char sAuth[32];
    GetClientAuthId(iClient, AuthId_Engine, sAuth, sizeof(sAuth));
    g_hAuthTrie.SetValue(sAuth, g_iClientRespawns[iClient]);

    CS_RespawnPlayer(iClient);
}

stock bool Fail(int iClient, bool bNotify, const char[] msg)
{
    if (bNotify)
        VIP_PrintToChatClient(iClient, "%t", msg);
    return false;
}

stock bool CheckRespawn(int iClient, bool bNotify)
{
    if (!cvEnable.BoolValue)
        return Fail(iClient, bNotify, "RESPAWN_OFF");

    if (cvMapLimit.IntValue == 0)
        return Fail(iClient, bNotify, "RESPAWN_OFF");

    if (!g_bEnabledRespawn)
        return Fail(iClient, bNotify, "RESPAWN_FORBIDDEN");

    if (GetGameTime() < g_fDeathTime[iClient] + 1.0)
        return false;

    int iClientTeam = GetClientTeam(iClient);
    if (iClientTeam < 2)
        return Fail(iClient, bNotify, "YOU_MUST_BE_ON_TEAM");

    if (IsPlayerAlive(iClient))
        return Fail(iClient, bNotify, "YOU_MUST_BE_DEAD");

    if (!IsAllowedTimeAfterRoundStart(iClient))
        return Fail(iClient, bNotify, "RESPAWN_NOT_AVAILABLE_YET");

    int iLimit     = VIP_GetClientFeatureInt(iClient, g_szFeature);
    int iMapLimit  = cvMapLimit.IntValue;

    if ((iMapLimit != -1 && (iLimit == -1 || iMapLimit < iLimit) && g_iClientRespawns[iClient] >= iMapLimit) ||
        (iLimit    != -1 && g_iClientRespawns[iClient] >= iLimit))
    {
        return Fail(
            iClient,
            bNotify,
            cvLimit.IntValue == 1 ? "REACHED_ROUND_LIMIT" : "REACHED_MAP_LIMIT"
        );
    }

    if (cvMinAlive.IntValue)
    {
        int iPlayers[2], iTeam;
        for (int i = 1; i <= MaxClients; i++)
        {
            if (IsClientInGame(i) && IsPlayerAlive(i) && (iTeam = GetClientTeam(i)) > 1)
                iPlayers[iTeam - 2]++;
        }

        bool bNotEnough;
        int min = cvMinAlive.IntValue;

        switch (cvMinAliveMode.IntValue)
        {
            case 0: bNotEnough = (iPlayers[iClientTeam == 2 ? 0 : 1] < min);
            case 1: bNotEnough = (iPlayers[iClientTeam == 2 ? 1 : 0] < min);
            case 2: bNotEnough = (iPlayers[0] + iPlayers[1] < min);
            case 3: bNotEnough = (iPlayers[0] < min || iPlayers[1] < min);
        }

        if (bNotEnough)
            return Fail(iClient, bNotify, "NOT_ENOUGH_ALIVE_PLAYERS");
    }

    return true;
}

stock bool IsAllowedTimeAfterRoundStart(int iClient)
{
    int iWaitRespawn = VIP_GetClientFeatureInt(iClient, g_szFeatureRespawnWaitTime);
    if (iWaitRespawn)
    {
        return (GetTime() < g_iRoundStartTime + iWaitRespawn);
    }

    return true;
}

public bool OnSelectItem(int iClient, const char[] sFeatureName)
{
    if (cvEnable.BoolValue && CheckRespawn(iClient, true))
        RespawnClient(iClient);

    return true;
}

public bool OnDisplayItem(int iClient, const char[] sFeatureName, char[] sDisplay, int maxlen)
{
    if(VIP_GetClientFeatureStatus(iClient, g_szFeature) == ENABLED)
    {
        int iLimit = VIP_GetClientFeatureInt(iClient, g_szFeature);
        if(iLimit != -1)
        {
            int iMapLimit = cvMapLimit.IntValue;
            if(iMapLimit != -1 && iMapLimit < iLimit)
            {
                iLimit = iMapLimit - g_iClientRespawns[iClient];
            }
            else
            {
                iLimit -= g_iClientRespawns[iClient];
            }

            FormatEx(sDisplay, maxlen, "%T [%T]", g_szFeature, iClient, "Left", iClient, iLimit);
            return true;
        }
    }

    return false;
}

public Action OnToggleItem(int iClient, const char[] sFeatureName, VIP_ToggleState OldStatus, VIP_ToggleState &NewStatus)
{
    if(cvAutoReaspawn.BoolValue)
        return Plugin_Continue;

    g_bAutoRespawn[iClient] = (VIP_IsClientFeatureUse(iClient, g_szFeature) && NewStatus == ENABLED);
    return Plugin_Continue;
}

public int OnDrawItem(int iClient, const char[] sFeatureName, int iStyle)
{
    if(cvAutoReaspawn.BoolValue)
        return ITEMDRAW_RAWLINE;

    if(VIP_GetClientFeatureStatus(iClient, g_szFeature) == ENABLED && VIP_GetClientFeatureStatus(iClient, g_szFeatureAutoRespawn) != NO_ACCESS)
    {
        return ITEMDRAW_DEFAULT;
    }

    return ITEMDRAW_RAWLINE;
}

public void VIP_OnVIPClientLoaded(int iClient)
{
    if(cvAutoReaspawn.BoolValue)
        return;

    g_bAutoRespawn[iClient] = VIP_IsClientFeatureUse(iClient, g_szFeature) && VIP_IsClientFeatureUse(iClient, g_szFeatureAutoRespawn);
}
 

Вложения

  • VIP_Respawn_1.6_.sp
    9.7 КБ · Просмотры: 13

Похожие темы

  • Закрыта
  • Закреплено
Ответы
36
Просмотры
29К
Сверху Снизу