Пишем свой SCP:Containment Breach (SCP:CB) [Создаем D-Класс и SCP-173]

Nico Yazawa

Бывший MrChester =(
Сообщения
326
Реакции
303
Ну что же, я думаю эта идея будет интересна в CS:GO.
Сегодня мы будем стремиться к игре SCP:Containment Breach. Всю необходимую информацию можно глянуть тут: Клик (качать не надо))

Начало
Чтобы начать писать плагин нам будут необходимы:
- Знания языка SourcePawn (уроков от R1KO хватит)
- Программа в которой мы будем этим заниматься (в моем случае NotePad++)
- Руки и голову на плечах

Итак, вот мы уже создали файл SCP-SB.sp и готовы в нем писать.
Если Вы пишите в NotePad++ рекомендую изменить Синтаксис (сверху в баре) на C#
Дальше подключаем необходимые инклуды и остальные "штучки":
C-подобный:
#include <sourcemod>    // Необходимые инклуды
#include <cstrike>
#include <sdktools>

#pragma tabsize 0    // Чтобы предовратить лишние Warnings (баг с табуляцией в NotePad++)

Дальше давайте сделаем информацию о игроках, создав Enum и двумерный массив: (потом покажу как им пользоваться)
C-подобный:
enum player        // Создаем Enum, который после дополним
{

}
any player_info[MAXPLAYERS + 1][player];    // Создаем двумерный массив
Добавим авторства:
C-подобный:
public Plugin myinfo =        // Авторство
{
    name = "SCP:Containment Breach",    // Название
    author = "Nico Yazawa",                // Автор
    version = "1.0"                        // Версия
};
На этом начальная подготовка окончена, переходим к более важному.
Создаем D-Класс и SCP-173
В начале каждого раунда мы будем распределять все важные роли (то есть все роли кроме D-Класса), пока что у нас их будет две: D-Класс и SCP-173
Хукаем событие Round_Start:
C-подобный:
public void OnPluginStart()        // Когда плагин стартует
{
    HookEvent("round_start", Event_RoundStart);        // Хукаем событие
}

public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{

}
В enum player вписываем следующее:
C-подобный:
any:Role,    // Роль игрока
Не забудем обнулить при заходе нового игрока:
C-подобный:
public void OnClientPutInServer(int client)    // Когда игрок полностью входит на сервер
{
    player_info[client][Role] = NONE;     // Обнуляем роль
}
И создаем enum SCP_ROLES:
C-подобный:
enum SCP_ROLES
{
    NONE = 0,        // Нету роли
    ROLE_D,            // Роль D-Класса
    ROLE_SCP173,    // Роль SCP-173
}
Давайте проверим, есть ли в начале раунда игроки. Создадим функцию подсчитывающее кол-во игроков:
C-подобный:
public int GetClientsOnServer()
{
    int count;    // Кол-во клиентов
    bool realPlayers = false;    // Имеются ли не боты
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент на сервере?
        {
            count++;    // Прибавляем кол-во людей на сервере на 1
            if(!IsFakeClient(i))    // Это не бот?
            {
                realPlayers = true;        // Не боты есть на сервере
            }
        }
    }
    if(realPlayers)        // Есть ли не боты на сервере?
    {
        return count;    // Возвращаем кол-во клиентов на сервере
    }
    else    // Срабатывает если нет настоящих игроков на сервере
    {
        return 0;        // Возвращаем 0, то есть никого нет
    }
}
И впишем ее в начало раунда:
C-подобный:
public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    int clients = GetClientsOnServer();        // Создаем переменную с кол-вом игроков на сервере
    if(clients)        // Если игроки есть на сервере?
    {

    }
}
Теперь создадим функцию, выбирающая рандомного игрока:
C-подобный:
int GetRandomClient(bool HaveRole = true)    // Функция за выбор рандомного игрока (HaveRole - выбирать ли тех игроков у которых уже есть роль?)
{
    int count;    // Кол-во клиентов, которое будет подходить условиям
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            if(HaveRole && !player_info[i][Role] && !IsFakeClient(i))    // Надо ли выбирать игрока у которого уже есть роль? Игрок с ролью? Это настоящий игрок?
            {
                count++;    // Прибавляем возможное кол-во клиентов на 1
            }
            else if(!HaveRole && !IsFakeClient(i))                // В ином случае
            {
                count++;    // Прибавляем возможное кол-во клиентов на 1
            }
        }
    }
    int random = GetRandomInt(1, count);    // Создаем переменную которая выберет нужного игрока
    for(int i = 1; i <= MaxClients; i++)    // Еще один цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            if(HaveRole && !player_info[i][Role] && !IsFakeClient(i))    // Надо ли выбирать игрока у которого уже есть роль? Игрок с ролью? Это настоящий игрок?
            {
                random--;    // Убавляем значение переменной на 1
            }
            else if(!HaveRole && !IsFakeClient(i))                // В ином случае
            {
                random--;    // Убавляем значение переменной на 1
            }
            if(random == 0)        // Если перебор игроков окончен
            {
                return i;    // Возвращаем нашего рандомного игрока
            }
        }
    }
    return 0;
}
Ну и выдадим роль SCP-173 игроку, в случае если на сервере больше 3 человек и не забудем очистить все роли в конце раунда:
C-подобный:
public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    int clients = GetClientsOnServer();        // Создаем переменную с кол-вом игроков на сервере
    if(clients)        // Если игроки есть на сервере?
    {
        if(clients >= 3)
        {
            player_info[GetRandomClient()][Role] = ROLE_SCP173;
        }
    }
}
Теперь надо хукнуть конец раунда и очистить роли:
C-подобный:
public void OnPluginStart()        // Когда плагин стартует
{
    HookEvent("round_end", Event_RoundEnd);            // Хукаем событие конца раунда
    HookEvent("round_start", Event_RoundStart);        // Хукаем событие начала раунда
}
C-подобный:
public void Event_RoundEnd(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            player_info[i][Role] = NONE;     // Обнуляем роль
        }
    }
}
В начале раунда мы должны выдать всем тем, кто не получил роль, роль D-Класса:
C-подобный:
public void Event_RoundStart(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    int clients = GetClientsOnServer();        // Создаем переменную с кол-вом игроков на сервере
    if(clients)        // Если игроки есть на сервере?
    {
        if(clients >= 3)
        {
            player_info[GetRandomClient()][Role] = ROLE_SCP173;
        }
    }

    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            if(!player_info[i][Role])    // Клиент имеет роль?
            {
                player_info[i][Role] = ROLE_D;    // Даем роль класса D
            }
        }
    }
}
Отлично! Мы сделали разделение между D-Классом и SCP-173
Дальше нам надо поставить разные спавны клиентам, мы будем использовать данную карту: Клик
Создадим точки спавна для каждой роли:
C-подобный:
float Spawns_D[][] =
{
    {3211.904296, -448.181030, 0.031250},
    {3210.809570, -320.227081, 0.031250},
    {3200.620361, -192.031250, 0.031250},
    {3206.063232, -64.046592, 0.031250},
    {3215.756103, 63.997200, 0.031250},
    {3197.142578, 191.882644, 0.031250},
    {3214.819091, 319.860290, 0.031250},
    {3196.372314, 831.968750, 0.031250},
    {3194.241210, 959.968750, 0.031250},
    {3195.770751, 1087.968750, 0.031250}
};

float Spawns_SCP173
{
    {1318.366943, 132.984420, 0.031250}
};
Ну и сделаем телепорт игрока на позицию при спавне:
C-подобный:
public void OnPluginStart()        // Когда плагин стартует
{
    HookEvent("round_end", Event_RoundEnd);            // Хукаем событие конца раунда
    HookEvent("round_start", Event_RoundStart);        // Хукаем событие начала раунда
    HookEvent("player_spawn", Event_PlayerSpawn);    // Хукаем событие начала раунда
}

public void Event_PlayerSpawn(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    int client = GetClientOfUserId(hEvent.GetInt("userid"));    // Получаем клиент игрока, который зареспавнился
    if(!player_info[client][Role])    // Если у игрока нету роли
    {
        player_info[client][Role] = ROLE_D;        // Выдаем роль D-Класса
    }
    int random;        // Создаем переменную для случайного спавна
    switch(player_info[client][Role])    // Рассматриваем варианты ролей клиента
    {
        case ROLE_D:    // Если роль Д-Класса
        {
            random = GetRandomInt(0, sizeof(Spawns_D) - 1);        // Выбираем рандомный спавн
            TeleportEntity(client, Spawns_D[random], NULL_VECTOR, NULL_VECTOR);        // Телепортируем клиента на спавн
        }
        case ROLE_SCP173:    // Если роль SCP-173
        {
            random = GetRandomInt(0, sizeof(Spawns_SCP173) - 1);        // Выбираем рандомный спавн
            TeleportEntity(client, Spawns_SCP173[random], NULL_VECTOR, NULL_VECTOR);        // Телепортируем клиента на спавн
        }
    }
}
Теперь мы можем распределять спавны по ролям

Первый урок на сегодня окончивается, в следующем будем делать функционал SCP и добавлять результат игры
Выслушаю любую критику)
Свои пожелания можете писать ниже

Также приложу код, который должен был получиться
 

Вложения

  • SCP-SB.sp
    7.4 КБ · Просмотры: 8
Последнее редактирование:

Nico Yazawa

Бывший MrChester =(
Сообщения
326
Реакции
303
Ну что же, продолжим создание SCP:CB
В прошлом уроке мы сделали 2 роли и спавны им, сегодня займемся функционалом ролей

Функционал SCP-173

Расскажу вкратце как работает SCP-173:
Это бетонная статуя, которая двигается с огромной скоростью, а при приближение к человеку, она за секунду может свернуть ему шею.
Если смотреть на SCP-173, она не сможет двигаться. Мы также реализуем моргание игрока, при котором SCP-173 сможет двигаться.

Для начала сделаем повторяющийся таймер с задержкой в 0.1 секунду:
C-подобный:
public void OnMapStart()    // Когда карта стартует
{
    CreateTimer(0.1, Timer_Second, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);    // Создаем таймер с повторением в 0.1 секунду, каллбек: Timer_Second, передавать ничего не будем
}

public Action Timer_Checker(Handle hTimer, any UserID)        // Каллбек таймера
{
        CheckVisibleSCP173();    // Вызываем функцию
}
Таймер готов, теперь давайте сделаем цикл на всех игроков и проверим, смотрят ли они на SCP-173:
Функции ClientViews и ClientViewsFilter объяснить, к сожалению, не смогу. Они отвечают за то, смотрит ли клиент на клиента?
C-подобный:
public void CheckVisibleSCP173()    // Функция, проверяющая смотрят ли на SCP-173?
{
    bool CanMove = true;    // Создаем переменную, будет ли двигаться SCP-173?
    int clientSCP;
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            for(int x = 1; x <= MaxClients; x++)    // Цикл по всем возможным клиентам
            {
                if(IsClientInGame(x) && player_info[x][Role] == ROLE_SCP173)    // Клиент в игре? клиент жив? у клиента роль SCP-173?
                {
                    clientSCP = x;        // Присваеваем значение переменной
                    if(ClientViews(i, x))    // Смотрит ли клиент на SCP-173
                    {
                        CanMove = false;    // Не разрешим SCP-173 двигаться
                    }
                }
            }
        }
    }
    if(clientSCP)        // SCP-173 вообще есть?
    {
        if(CanMove)        // SCP-173 сможет двигаться?
        {
            SetEntPropFloat(clientSCP, Prop_Data, "m_flLaggedMovementValue", 5.0);        // Устанавливаем скорость 5.0 (1.0 - стандарт) SCP-173
        }
        else
        {
            SetEntPropFloat(clientSCP, Prop_Data, "m_flLaggedMovementValue", 0.0);        // Устанавливаем скорость 0.0 (1.0 - стандарт) SCP-173
        }
    }
}

stock bool:ClientViews(Viewer, Target, Float:fMaxDistance=0.0, Float:fThreshold=0.73)
{
    // Original: https://forums.alliedmods.net/showpost.php?p=973411&postcount=4
    // Retrieve view and target eyes position
    decl Float:fViewPos[3];   GetClientEyePosition(Viewer, fViewPos);
    decl Float:fViewAng[3];   GetClientEyeAngles(Viewer, fViewAng);
    decl Float:fViewDir[3];
    decl Float:fTargetPos[3]; GetClientEyePosition(Target, fTargetPos);
    decl Float:fTargetDir[3];
    decl Float:fDistance[3];
 
    // Calculate view direction
    fViewAng[0] = fViewAng[2] = 0.0;
    GetAngleVectors(fViewAng, fViewDir, NULL_VECTOR, NULL_VECTOR);
 
    // Calculate distance to viewer to see if it can be seen.
    fDistance[0] = fTargetPos[0]-fViewPos[0];
    fDistance[1] = fTargetPos[1]-fViewPos[1];
    fDistance[2] = 0.0;
    if (fMaxDistance != 0.0)
    {
        if (((fDistance[0]*fDistance[0])+(fDistance[1]*fDistance[1])) >= (fMaxDistance*fMaxDistance))
            return false;
    }
 
    // Check dot product. If it's negative, that means the viewer is facing
    // backwards to the target.
    NormalizeVector(fDistance, fTargetDir);
    if (GetVectorDotProduct(fViewDir, fTargetDir) < fThreshold) return false;
 
    // Now check if there are no obstacles in between through raycasting
    new Handle:hTrace = TR_TraceRayFilterEx(fViewPos, fTargetPos, MASK_PLAYERSOLID_BRUSHONLY, RayType_EndPoint, ClientViewsFilter);
    if (TR_DidHit(hTrace)) { CloseHandle(hTrace); return false; }
    CloseHandle(hTrace);
 
    // Done, it's visible
    return true;
}

public bool:ClientViewsFilter(Entity, Mask, any:Junk)
{
    if (Entity >= 1 && Entity <= MaxClients) return false;
    return true;
}
Теперь, если на SCP-173 смотрят, он не сможет двигаться. Мы помним, что SCP-173 сворачивает шеи свои жертвам.
Мы отловим событие удара ножом и сделаем урон, убивающий жертву.

Сначала добавим инклуд:
C-подобный:
#include <sdkhooks>

Потом разрешим дружественный огонь:
C-подобный:
public void OnPluginStart()        // Когда плагин стартует
{
    RegConsoleCmd("sm_cord", cmd_Cord);
   
    HookEvent("round_end", Event_RoundEnd);            // Хукаем событие конца раунда
    HookEvent("round_start", Event_RoundStart);        // Хукаем событие начала раунда
    HookEvent("player_spawn", Event_PlayerSpawn);    // Хукаем событие спавна игрока
   
    SetConVarInt(FindConVar("mp_friendlyfire"), 1);        // Устанавливаем значение квару. Делаем доступным огонь по своим
    SetConVarInt(FindConVar("ff_damage_reduction_bullets"), 1);        // Устанавливаем значение квару. Делаем доступным огонь по своим
    SetConVarInt(FindConVar("ff_damage_reduction_grenade"), 1);        // Устанавливаем значение квару. Делаем доступным огонь по своим
    SetConVarInt(FindConVar("ff_damage_reduction_grenade_self"), 1);        // Устанавливаем значение квару. Делаем доступным огонь по своим
    SetConVarInt(FindConVar("ff_damage_reduction_other"), 1);        // Устанавливаем значение квару. Делаем доступным огонь по своим
}

Теперь отловим событие урона:
C-подобный:
public void OnClientPutInServer(int client)    // Когда игрок полностью входит на сервер
{
    player_info[client][Role] = NONE;     // Обнуляем роль
   
    SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);    // Отлавливаем событие урона
}

Ну и его каллбек:
C-подобный:
public Action OnTakeDamage(client, &attacker, &inflictor, &Float:damage, &damagetype)        // Вызывается при получении урона игроком
{
    if(0 < client <= MaxClients && 0 < inflictor <= MaxClients)        // Проверяем на валидность атакующего и жертву
    {
        if(player_info[client][Role] == player_info[attacker][Role])    // Если игроки одной роли
        {
            damage = 0.0;        // Блокируем урон, уставляя дамагу значение 0
            return Plugin_Changed;
        }
       
        if(player_info[attacker][Role] == ROLE_SCP173)        // Если роль игрока: SCP-173
        {
            damage = 9999.0;    // Устанавливаем смертельный урон
        }
        return Plugin_Changed;
    }
    return Plugin_Continue;
}
Теперь SCP-173 может убивать всех с первого удара (сворачивая шеи) и игроки одинаковых ролей не смогут убить друг друга

Также на нашей карте нож по стандарту не выдается, давайте выдадим его SCP-173:
C-подобный:
public void Event_PlayerSpawn(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    int client = GetClientOfUserId(hEvent.GetInt("userid"));    // Получаем клиент игрока, который зареспавнился
    if(!player_info[client][Role])    // Если у игрока нету роли
    {
        player_info[client][Role] = ROLE_D;        // Выдаем роль D-Класса
    }
    int random;        // Создаем переменную для случайного спавна
    switch(player_info[client][Role])    // Рассматриваем варианты ролей клиента
    {
        case ROLE_D:    // Если роль Д-Класса
        {
            random = GetRandomInt(0, sizeof(Spawns_D) - 1);        // Выбираем рандомный спавн
            TeleportEntity(client, Spawns_D[random], NULL_VECTOR, NULL_VECTOR);        // Телепортируем клиента на спавн
        }
        case ROLE_SCP173:    // Если роль SCP-173
        {
            random = GetRandomInt(0, sizeof(Spawns_SCP173) - 1);        // Выбираем рандомный спавн
            TeleportEntity(client, Spawns_SCP173[random], NULL_VECTOR, NULL_VECTOR);        // Телепортируем клиента на спавн
            GivePlayerItem(client, "weapon_knife");        // Выдаем нож
        }
    }
}
Отлично! Главный функционал SCP-173 готов, в следующем уроке постараемся сделать моргание и результат игры

Домашнее Задание если вдруг кто это читает): В начале раунда показывать оверлей, содержащий:
- Роль игрока
- Его цель
Оверлей сделать надо самому и функцию отвечающую за оверлеи можно узнать тут: Клик
Кто сделает правильно задание, самолично лайкну 3>

Исходники приложил.
 

Вложения

  • SCP-SB.sp
    12.8 КБ · Просмотры: 1
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #3
C++:
public void Event_RoundEnd(Event hEvent, const char[] sEvName, bool bDontBroadcast)        // Каллбек события
{
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            player_info[i][Role] = NONE;     // Обнуляем роль
        }
    }
    
    int clients = GetClientsOnServer();        // Создаем переменную с кол-вом игроков на сервере
    if(clients)        // Если игроки есть на сервере?
    {
        if(clients >= 3)
        {
            player_info[GetRandomClient()][Role] = ROLE_SCP173;
        }
    }
}

int GetRandomClient(bool HaveRole = true)    // Функция за выбор рандомного игрока (HaveRole - выбирать ли тех игроков у которых уже есть роль?)
{
    int count;    // Кол-во клиентов, которое будет подходить условиям
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            if(HaveRole && !player_info[i][Role] && !IsFakeClient(i))    // Надо ли выбирать игрока у которого уже есть роль? Игрок с ролью? Это настоящий игрок?
            {
                count++;    // Прибавляем возможное кол-во клиентов на 1
            }
            else if(!HaveRole && !IsFakeClient(i))        // В ином случае
            {
                count++;    // Прибавляем возможное кол-во клиентов на 1
            }
        }
    }
    int random = GetRandomInt(1, count);    // Создаем переменную которая выберет нужного игрока
    for(int i = 1; i <= MaxClients; i++)    // Еще один цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            if(HaveRole && !player_info[i][Role] && !IsFakeClient(i))    // Надо ли выбирать игрока у которого уже есть роль? Игрок с ролью? Это настоящий игрок?
            {
                random--;    // Убавляем значение переменной на 1
            }
            else if(!HaveRole && !IsFakeClient(i))        // В ином случае
            {
                random--;    // Убавляем значение переменной на 1
            }
            if(random == 0)        // Если перебор игроков окончен
            {
                return i;    // Возвращаем нашего рандомного игрока
            }
        }
    }
    return 0;
}

public int GetClientsOnServer()
{
    int count;    // Кол-во клиентов
    bool realPlayers = false;    // Имеются ли не боты
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент на сервере?
        {
            count++;    // Прибавляем кол-во людей на сервере на 1
            if(!IsFakeClient(i))    // Это не бот?
            {
                realPlayers = true;        // Не боты есть на сервере
            }
        }
    }
    if(realPlayers)        // Есть ли не боты на сервере?
    {
        return count;    // Возвращаем кол-во клиентов на сервере
    }
    else    // Срабатывает если нет настоящих игроков на сервере
    {
        return 0;        // Возвращаем 0, то есть никого нет
    }
}

Это всё можно в одном цикле сделать


C++:
public Action OnTakeDamage(client, &attacker, &inflictor, &Float:damage, &damagetype)        // Вызывается при получении урона игроком
{
    if(0 < client <= MaxClients && 0 < inflictor <= MaxClients)        // Проверяем на валидность атакующего и жертву
    {
        if(player_info[client][Role] == player_info[attacker][Role])    // Если игроки одной роли
        {
            damage = 0.0;        // Блокируем урон, уставляя дамагу значение 0
        }
        
        if(player_info[attacker][Role] == ROLE_SCP173)        // Если роль игрока: SCP-173
        {
            damage = 9999.0;    // Устанавливаем смертельный урон
        }
    }
}
Если в форварде изменяются значения - нужно возвращать Plugin_Changed
Даже если иногда (как в данном случае) это не влияет на работу, то визуально при чтении это сразу дает понять что в форварде изменяются значения по ссылке.
К тому же после первой проверки ролей (Если игроки одной роли) можно сразу делать ретурн дабы избежать лишних проверок.


C++:
public void CheckVisibleSCP173()    // Функция, проверяющая смотрят ли на SCP-173?
{
    bool CanMove = true;    // Создаем переменную, будет ли двигаться SCP-173?
    int clientSCP;
    for(int i = 1; i <= MaxClients; i++)    // Цикл по всем возможным клиентам
    {
        if(IsClientInGame(i))    // Клиент в игре?
        {
            for(int x = 1; x <= MaxClients; x++)    // Цикл по всем возможным клиентам
            {
                if(IsClientInGame(x) && IsPlayerAlive(x) && player_info[x][Role] == ROLE_SCP173)    // Клиент в игре? клиент жив? у клиента роль SCP-173?
                {
                    clientSCP = x;        // Присваеваем значение переменной
                    if(ClientViews(i, x))    // Смотрит ли клиент на SCP-173
                    {
                        CanMove = false;    // Не разрешим SCP-173 двигаться
                    }
                }
            }
        }
    }
    if(clientSCP)        // SCP-173 вообще есть?
    {
        if(CanMove)        // SCP-173 сможет двигаться?
        {
            SetEntPropFloat(clientSCP, Prop_Data, "m_flLaggedMovementValue", 5.0);        // Устанавливаем скорость 5.0 (1.0 - стандарт) SCP-173
        }
        else
        {
            SetEntPropFloat(clientSCP, Prop_Data, "m_flLaggedMovementValue", 1.0);        // Устанавливаем скорость 0.0 (1.0 - стандарт) SCP-173
        }
    }
}
Думаю в первом цикле тоже стоит исключить мертвых
 

Nico Yazawa

Бывший MrChester =(
Сообщения
326
Реакции
303
Это всё можно в одном цикле сделать
Хотелось бы поподробнее узнать как и что именно (там много функций))

Если в форварде изменяются значения - нужно возвращать Plugin_Changed
Даже если иногда (как в данном случае) это не влияет на работу, то визуально при чтении это сразу дает понять что в форварде изменяются значения по ссылке.
К тому же после первой проверки ролей (Если игроки одной роли) можно сразу делать ретурн дабы избежать лишних проверок.
Спасибо, подправлю

Думаю в первом цикле тоже стоит исключить мертвых
А если SCP-173 будет убит? Получается будет ложно срабатывать (а там и ерроры, что клиент не доступен для изменения скорости)
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #5
Хотелось бы поподробнее узнать как и что именно (там много функций))
там 4 цикла в 3-х функциях, которые нигде кроме как в 1-й не вызываются.
Если в будущем будут - то ок, а если нет, то все действия из 4-х циклов можно в одном сделать.

А если SCP-173 будет убит? Получается будет ложно срабатывать (а там и ерроры, что клиент не доступен для изменения скорости)
ну как я понял 1-й цикл это игроки, которые могут смотреть на SCP-173, мертвых зачем проверять?
Если он будет мертв то еще вот тут не пройдет
1571245300332.png

А если его не будет или мертв то
1571245325587.png

тут всегда false будет


хотя возможно я бы сделал одним из 2-х вариантов:
  1. отдельный цикл для поиска SCP-173 и другой цикл для проверки видимости.
  2. Поменять циклы местами т.к. удобнее и оптимальнее сначала найти нужного игрока, а затем гонять цикл по остальным чтобы узнать смотрят ли.

При чем это всё лучше делать в отдельной функции для возможности делать ретурны в циклах. Хотя и так сойдет если break юзать.
 

Nico Yazawa

Бывший MrChester =(
Сообщения
326
Реакции
303
там 4 цикла в 3-х функциях, которые нигде кроме как в 1-й не вызываются.
Если в будущем будут - то ок, а если нет, то все действия из 4-х циклов можно в одном сделать.
Да, буду использовать

ну как я понял 1-й цикл это игроки, которые могут смотреть на SCP-173, мертвых зачем проверять?
Если он будет мертв то еще вот тут не пройдет
Теперь согласен) Спасибо

Раз в такой теме встретились, не подскажешь в чем ты пишешь?
Видел однажды ты отвечал на темах и там был подсвечен хорошо синтаксис (скриншотами кидал) и темное все было)
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #7
Раз в такой теме встретились, не подскажешь в чем ты пишешь?
Видел однажды ты отвечал на темах и там был подсвечен хорошо синтаксис (скриншотами кидал) и темное все было)
когда как. notepad++ (со своей кастомной подсветкой) или sublime3/visual studio code с синтаксисом с++
 

JDW

Мы открываем бизнес
Сообщения
376
Реакции
325
Да, буду использовать


Теперь согласен) Спасибо

Раз в такой теме встретились, не подскажешь в чем ты пишешь?
Видел однажды ты отвечал на темах и там был подсвечен хорошо синтаксис (скриншотами кидал) и темное все было)
Для visual studio code есть плагин: SourcePawn - Visual Studio Marketplace
 
Сверху Снизу