Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.

Реклама


**Как получить V.I.P** (Перейти)
Чтобы заказать рекламу на Pro-Pawn.Ru, обращайтесь в Skype.
Баннерная реклама 200руб/мес, Текстовая 100руб/мес.
Страница 1 из 5 123 ... ПоследняяПоследняя
Показано с 1 по 10 из 42
  1. #1
    Аватар для Daniel_Cortez
    new fuck_logic[0] = EOS;

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    1,662
    Репутация:
    2145 ±

    Перехват функций, часть 2: практика - пишем античит на HP

    Оглавление:


    Sup.
    В этой части мы рассмотрим создание простого античита на HP, подходящего к любому моду*.
    * За исключением тех, на которых уже есть аналогичный античит,
    в этом случае два разных античита могут конфликтовать друг с другом.


    Прежде, чем начать разбор примера, давайте рассмотрим несколько советов, которые помогут избежать самых распространённых ошибок, связанных с перехватами функций, и улучшить качество вашего кода.
    Внимание: данные советы ещё не рассматривались ни в одной из известных мне статей по перехватам (в.т.ч. в статье Y_Less'а на оффе). Поэтому, даже если Вы уже знакомы с техникой перехватов, эти советы достойны Вашего внимания.
    1. Внутри инклуда задавайте переменным и функциям (в т.ч. перехватываемым) один и тот же префикс, связанный с названием инклуда.
      Главное, чтобы этот префикс и названия переменных и функций в этом скрипте были уникальными, т.е. не повторялись в других инклудах и в основном скрипте.
      Также название префикса должно быть как можно менее общим. Плохие примеры: "ac", "fix".
      Античиты и багфиксы могут быть разные, поэтому старайтесь, отразить суть своего багфикса или античита. Например, "ac_spect__" (античит на невидимость, получаемую имитацией перехода в спект) (на самом деле, после "ac_hp" только 1 символ подчёркивания - это из-за ограничения названий до 31 символов в Pawn) или "ac_hp__" (античит на читерское HP).
      Если префиксы будут повторяться в разных перехватах, то эти перехваты будут конфликтовать друг с другом, что, в свою очередь, помешает компиляции скрипта.
      Пример: если есть инклуд "afk_system.inc", в котором реализована система AFK, можно использовать в нём префикс "afk_sys__" для перехватов, переменных, констант и функций (кроме тех функций, которые будут видны за пределами инклуда, например IsPlayerAFK).

    2. Перехватчик не должен менять аргументы перехватываемой функции, её логику работы и предназначение.
      Изменение возвращаемых значений допускается только в том случае, если это не нарушает совместимости с оригинальной функцией.
      Например, в античите на HP перехватчик GetPlayerHealth возвращает не то значение, которое возвратит оригинальная функция, а кол-во HP игрока, хранящееся в античите. Но в то же время перехватчик должен возвращать именно HP, а не сумму HP и брони или ещё что-нибудь, что поменяет логику работы функции.
      То же самое относится к изменению аргументов функции. Если с помощью перехвата добавить в какую-либо функцию дополнительные параметры, а потом убрать перехватчик, то компилятор будет выдавать ошибки и код не будет компилироваться без перехватчика, т.к. в оригинальной функции тех дополнительных параметров нет.
      Иными словами, работа перехватчика должна быть незаметной для того кода, который использует перехватываемую функцию, как будто того перехватчика и нет.
      Если же вам нужна функция, работающая по-другому - сделайте отдельную функцию, но не нужно путать её с оригиналом с помощью перехвата. Вмешательство в стандартную логику обычно приводит только к проблемам.

    3. Если название перехватываемой функции (в случае с коллбэками) или перехватчика (для нативных функций) длиннее 31 символов, его следует сократить до этого лимита. Сокращение производится путём отсечения лишних символов справа (например, ac_veh_hp__OnVehicleDamageStatusUpdate -> ac_veh_hp__OnVehicleDamageStatu), строго до длины в 31 символ (не больше и не меньше!).
      Пример:
      PHP код:
      public OnVehicleDamageStatusUpdate(vehicleidplayerid)
      {
          
      // ...
          #if defined ac_veh_hp__OnVehicleDamageStatu    // "урезаем" название до 31 символа
              
      ac_veh_hp__OnVehicleDamageStatu(vehicleidplayerid);
          
      #endif
          
      return 1;
      }
      #if    defined    _ALS_OnVehicleDamageStatusUpdat    // "урезаем" название до 31 символа
          #undef    OnVehicleDamageStatusUpdate
      #else
          #define    _ALS_OnVehicleDamageStatusUpdat
      #endif
      #define    OnVehicleDamageStatusUpdate    ac_veh_hp__OnVehicleDamageStatu
      #if    defined    ac_veh_hp__OnVehicleDamageStatu
      forawrd    ac_veh_hp__OnVehicleDamageStatu(vehicleidplayerid);
      #endif 
    4. Всё, что должно использоваться только внутри инклуда (в данном уроке это переменные для записи HP - нельзя допустить, чтобы они изменялись из мода), должно иметь атрибут static.
      Пример:
      PHP код:
      static some_var;    // переменная не будет видна из мода

      static stock DoSomething()    // функция не будет видна из мода
      {
          
      // ...

    5. Если перехватываемая функция не обязательно должна возвращать значение (пример: коллбэк OnPlayerConnect), вызывайте её из перехватчика следующим образом:
      PHP код:
      #if defined LibName__Func
          
      LibName__Func();
      #endif
          
      return 1
      Благодаря этому удастся избежать варнингов, если перехватываемая функция ничего не возвращает.
    6. Если в коде внутри перехватчика используются локальные переменные, ограничивайте этот код локальным блоком.
      PHP код:
      public Func(param1param2)
      {
          
      // локальные переменные ограничены локальным блоком
          
      {
              new 
      string[256];
              
      // ...
          
      }
      #if defined LibName__Func
          
      return Libname_Func(param1param2);
      #endif

      Таким образом локальные переменные перехватчика не будут занимать место в стеке при вызове перехватываемой функции, благодаря чему перехватчики почти не будут потреблять дополнительного стекового пространства в моде.



    Перейдём обратно к заданию - написанию античита на HP.
    Сначала нужно определиться, как мы назовём инклуд с античитом и какой префикс будем использовать для переменных/функций.
    Для примера подойдёт название "ac_health.inc" или "ac_hp.inc". Соответственно, будем использовать префикс "ac_hp__".

    Дальше создадим массив, в который будем записывать здоровье игроков, устанавливаемое сервером:
    PHP код:
    static Float:ac_hp__health[MAX_PLAYERS]; 
    Вместо new массив объявлен с помощью ключевого слова static - так, если перенести весь античит в отдельный инклуд, массив будет виден только внутри инклуда и не будет мешаться в моде.

    Дальше можно было бы найти все вызовы SetPlayerHealth и под ними дублировать устанавливаемое кол-во HP в ac_health__health:
    PHP код:
    SetPlayerHealth(playerid100.0);
    ac_hp__health[playerid] = 100.0
    НО для этого вам придётся:
    • Выискивать вручную все вызовы и точно так же вручную "прицеплять" к каждому из них дублирование HP в массив. И ни в коем случае не пропустить ни одного из них!
    • Всегда при использовании SetPlayerHealth держать в голове, что нужно добавить дублирование в ac_health.

    Кроме того, стоит помнить, что чем больше сделано модификаций кода, тем больше вероятность того, что туда вкрадётся какая-нибудь ошибка. Человеческий фактор.
    А может быть вы уже используете такой подход в своём RLS и даже не подозреваете, что в вашем античите на HP уже куча подобных ошибок, которые никогда не заметите ни вы, ни компилятор?
    Причём одна такая ошибка - и в один прекрасный момент недоантичит начнёт банить ни в чём не повинных игроков, а репутация проекта будет испорчена. Если же попытаетесь отыскать источник ошибки, столкнётесь с новой проблемой: забаненный игрок может не помнить всех подробностей (да и не факт, что он вообще что-то захочет говорить скриптеру) - придётся перепроверять каждый вызов SetPlayerHealth и устраивать кучу тестов на локальном сервере.

    Но ведь можно просто найти все вызовы SetPlayerHealth и под ними копировать устанавливаемое кол-во HP в ac_health!
    И именно поэтому такой подход всегда был и будет считаться быдлокодерством - абсолютно никаких гарантий надёжности и куча проблем, причину которых очень трудно найти. От человеческого фактора нельзя полностью избавиться, лучшее, что можно сделать - минимизировать риск, избавившись от дублирования кода.

    С техникой перехвата ситуация намного проще.
    Поскольку перехватчик всего один, достаточно лишь адекватно протестировать хотя бы 1 случай его использования.
    Затем во всех остальных случаях вызова SetPlayerHealth компилятор возьмёт всю рутинную работу по разбору перехватов на себя и перехватчик всегда будет вести себя так, как было запланировано.
    В результате вероятность возникновения ошибки сводится к нулю. Такой код поддерживать намного проще.

    Сделаем перехват функции SetPlayerHealth и в этом перехватчике осуществим дублирование выдаваемого кол-ва HP в массив:
    PHP код:
    stock ac_hp__SetPlayerHealth(playerid, &Float:health)
    {
        
    ac_hp__health[playerid] = health;
        return 
    SetPlayerHealth(playeridhealth);
    }
    #if    defined    _ALS_SetPlayerHealth
        #undef    SetPlayerHealth
    #else
        #define    _ALS_SetPlayerHealth
    #endif
    #define SetPlayerHealth ac_hp__SetPlayerHealth 
    Теперь нужно будет в функцию OnPlayerUpdate добавить проверку игрока на несанкционированное восстановление HP и последующую выдачу бана.
    Всё это, как вы уже могли догадаться, будет сделано с помощью перехватов.
    PHP код:
    public OnPlayerUpdate(playerid)
    {
            
    // код перехвата вынесен в отдельный блок,
        
    {    // чтобы после его выполнения переменные не занимали место в стеке
            
    new Float:health;
            
    GetPlayerHealth(playeridhealth);
            
    // если кол-во HP изменилось с момента предыдущего обновления
            // сравниваемые значения трактуются, как целочисленные, чтобы избежать лишнего вызова floatcmp
            // (внимание! такой оптимизационный приём можно применять только при сравнении
            // с помощью знаков "==" и "!=", но ни в коем случае не с ">", "<", ">=" или "<=")
            
    if(_:ac_hp__health[playerid] != _:health)
            {
            
    // если игрок потерял HP, упав с высоты или с помощью чита - запоминаем новое значение
            // (пусть отнимает HP читами сколько угодно, всё равно восстановить его он уже не сможет)
                
    if(ac_hp__health[playerid] > health)
                {
                    
    ac_hp__health[playerid] = health;
                }
                
    // если HP больше, чем записано в античите - HAX detected!
                
    else if(ac_hp__health[playerid] < health)
                {
                    
    SetPlayerHealth(playeridac_hp__health[playerid]);
                }
            }
        }
        
    // на wiki.sa-mp.com написано, что возвращаемое коллбэком значение ни на что не влияет
        // и может быть пропущено, поэтому не стоит "требовать" это значение у перехватываемой функции -
        // вместо этого лучше использовать "return 1" отдельно от её вызова
    #if    defined    ac_hp__OnPlayerUpdate
        
    ac_hp__OnPlayerUpdate(playerid);
    #endif
        
    return 1;
    }
    #if    defined    _ALS_OnPlayerUpdate
        #undef    OnPlayerUpdate
    #else
        #define    _ALS_OnPlayerUpdate
    #endif
    #define    OnPlayerUpdate    ac_hp__OnPlayerUpdate
    #if    defined    ac_hp__OnPlayerUpdate
    forward ac_hp__OnPlayerUpdate(playerid);
    #endif 
    Теперь сделаем перехват GetPlayerHealth. По идее он не обязателен и никак не отразится на работе античита.
    Но в случае с функцией GetPlayerHealth предоставляется возможность избавиться от вызова нативной функции, подменив её на функцию, написанную на Pawn - таким образом повысится производительность работы сервера при вызове функции.
    При этом на возвращаемом функцией значении это никак не отразится, т.к. античит теперь имеет полный контроль над HP игрока.
    PHP код:
    stock ac_hp__GetPlayerHealth(playerid, &Float:health)
    {
        
    health ac_hp__health[playerid];
        return 
    1;
    }
    #if    defined    _ALS_GetPlayerHealth
        #undef    GetPlayerHealth
    #else
        #define    _ALS_GetPlayerHealth
    #endif
    #define GetPlayerHealth ac_hp__GetPlayerHealth 
    Внимание! Перехват OnPlayerUpdate следует делать выше перехватов GetPlayerHealth/SetPlayerHealth, иначе они будут влиять на работу перехватчика в OnPlayerUpdate, если в нём используются те функции.

    Но это ещё не всё. Если выдать игроку здоровье, оно выдастся ему не сразу из-за пинга.
    Античит проверит здоровье со следующим вызовом OnPlayerUpdate ещё до того, как здоровье обновится у игрока, в результате сервер запишет то кол-во HP, которое было ещё до выдачи.
    Как только у игрока обновится HP, в античите будет записано прежнее значение, и после ещё одной проверки в OnPlayerUpdate античит выдаст ложное срабатывание.
    Нужно исправить эту ситуацию. Сделаем так, чтобы античит игнорировал уменьшение HP у игрока в течение 1 секунды после выдачи.

    К переменным (под ac_hp__health):
    PHP код:
    static ac_hp__ignore_timestamp[MAX_PLAYERS]; 
    Добавим перед переменными константу, в которой укажем время для игнорирования:
    PHP код:
    #if    !defined    AC_HP__IGNORE_TIME
        #define    AC_HP__IGNORE_TIME    1000
    #endif 
    Почему вокруг объявления константы используется #if defined? Это мы разберём позже.
    А пока что добавим игнорирование в перехвате OnPlayerUpdate.
    Найдите строку:
    PHP код:
                if(ac_hp__health[playerid] > health
    и замените её на:
    PHP код:
                if((ac_hp__health[playerid] > health)
                && (
    GetTickCount() > ac_hp__ignore_timestamp[playerid])) 
    И остаётся лишь сделать запись времени, до которого античит будет игнорировать игрока.
    В перехвате SetPlayerHealth найдите строки:
    PHP код:
        ac_hp__health[playerid] = health;
        return 
    SetPlayerHealth(playeridhealth); 
    и замените их на:
    PHP код:
        ac_hp__ignore_timestamp[playerid] = GetTickCount()+AC_HP__IGNORE_TIME;
        
    ac_hp__health[playerid] = health;
        return 
    SetPlayerHealth(playeridhealth); 
    Теперь античит не будет выдавать ложных срабатываний при выдаче HP.
    Но остаётся ещё одна проблема: игрок будет умирать во время спавна.
    Суть в том, что при спавне у игрока всегда 100 HP, а в античите в это время записано 0.
    Если сервер не выдаст игроку новое кол-во HP, античит выдаст ложное срабатывание и установит игроку 0 HP.
    Чтобы исправить эту проблему, добавим под перехватом OnPlayerUpdate перехват OnPlayerSpawn, в котором запишем у игрока 100 HP.
    PHP код:
    public OnPlayerSpawn(playerid)
    {
        
    ac_hp__ignore_timestamp[playerid] = GetTickCount()+AC_HP__IGNORE_TIME;
        
    ac_hp__health[playerid] = 100.0;
    #if    defined    ac_hp__OnPlayerSpawn
        
    ac_hp__OnPlayerSpawn(playerid);
    #endif
        
    return 1;
    }
    #if    defined    _ALS_OnPlayerSpawn
        #undef    OnPlayerSpawn
    #else
        #define    _ALS_OnPlayerSpawn
    #endif
    #define    OnPlayerSpawn    ac_hp__OnPlayerSpawn
    #if    defined    ac_hp__OnPlayerSpawn
    forward ac_hp__OnPlayerSpawn(playerid);
    #endif 

    Итак, если игрок накручивает HP читами, античит будет понижать здоровье обратно.
    Но что, если нам нужно не только нейтрализовать читера, но и оповестить администрацию?
    Можно добавить после понижения здоровья вызов какой-нибудь функции из мода (например, SendAdminMessage) для вывода модераторам сообщения о читере, НО такая функция есть не везде, а потому модуль не будет работать на всех модах.
    Поэтому мы поступим иначе: добавим в мод коллбэк OnHPCheatDetected и в нём будем записывать весь код, который "привязан" к тому моду.
    Здесь же сделаем вызов коллбэка. В перехвате OnPlayerUpdate находим строку:
    PHP код:
                    SetPlayerHealth(playeridac_hp__health[playerid]); 
    и заменяем её на:
    PHP код:
                    SetPlayerHealth(playeridac_hp__health[playerid]);
                
    #if    defined    OnHPCheatDetected
                    
    OnHPCheatDetected(playeridac_hp__health[playerid], health);
                
    #endif 
    И не забудем добавить опережающее объявление коллбэка для мода. В конец инклуда:
    PHP код:
    #if    defined    OnHPCheatDetected
    forward OnHPCheatDetected(playeridFloat:hp_expectedFloat:hp_got);
    #endif 
    Обратите внимание: в обоих отрывках присутствует "#if defined" - это сделано для того, чтобы убедиться, что коллбэк OnHPCheatDetected реализован в моде.
    Если его в моде нет, он не будет вызван из инклуда - иначе были бы ошибки из-за вызова несуществующей функции.


    Наконец, составим весь код воедино и вынесем его в отдельный инклуд (например, "ac__health.inc", здесь "ac" - сокращение от "AntiCheat").
    Результат должен выглядеть примерно так, как в этой теме.

    В итоге получается система, совершенно никак не привязанная к конкретному моду.
    Поскольку она готова, остаётся лишь использовать её в вашем моде.
    Сохраним инклуд в папке "pawno/include" и подключим его:
    PHP код:
    #include <dc_ac__health> 
    После этого добавим в мод коллбэк OnHPCheatDetected, который уже сделан в инклуде:
    PHP код:
    public OnHPCheatDetected(playeridFloat:hp_expectedFloat:hp_got)
    {
        
    // здесь Ваш код для оповещения модераторов, бан игрока и т.д. и т.п.

    Если у Вас получилось всё вышеперечисленное - поздравляю, Вы написали свой первый модуль на Pawn с использованием перехватов.
    К следующей неделе придумаю ещё несколько примеров для 3-й части урока.

    Автор: Daniel_Cortez

    Специально для Pro-Pawn.ru
    Копирование данной статьи на других ресурсах без разрешения автора запрещено!
    Индивидуально в PM и Skype по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).
    SA-MP 0.4 is a lie

  2. 15 пользователя(ей) сказали cпасибо:
    $continue$ (13.10.2014)BadPawn (29.02.2016)Battista (18.06.2016)codeo (14.10.2014)DeimoS (13.10.2014)Dima_Tushin (14.11.2014)Londlem (13.10.2014)Nurick (13.10.2014)Osetin (13.10.2014)Profyan (09.11.2014)qwezert (17.01.2017)Rasta (14.10.2014)Reim (12.07.2015)Salvacore (13.10.2014)Sp1ke (26.08.2015)
  3. #2
    Аватар для Dima_Tushin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    21.04.2013
    Адрес
    Россия
    Сообщений
    111
    Репутация:
    1 ±
    Сейчас попробую сделать!

    -----Добавлено-----------

    а вот теперь все получилось и без ошибок! сейчас буду тестировать!
    Последний раз редактировалось Dima_Tushin; 13.10.2014 в 22:10.

  4. #3
    Аватар для Dima_Tushin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    21.04.2013
    Адрес
    Россия
    Сообщений
    111
    Репутация:
    1 ±
    вчера я сделал но у меня не ловило читерское хп жалко блин ладно еще раз попробую!

  5. #4
    Аватар для Dima_Tushin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    21.04.2013
    Адрес
    Россия
    Сообщений
    111
    Репутация:
    1 ±
    Помоги Daniel посмотри что я не правильного сделал?
      Открыть/закрыть
    PHP код:
    /*=============================================================================
            Health Anticheat
                by Daniel_Cortez

            www.pro-pawn.ru

    Copyright (c) 2014 Daniel_Cortez
    This software is provided 'as-is', without any express or implied warranty.
    In no event will the authors be held liable for any damages arising from the
    use of this software. Permission is granted to anyone to use this software for
    any purpose, including commercial applications, and to alter it and
    redistribute it freely, subject to the following restrictions:
        1.    The origin of this software must not be misrepresented; you must not
            claim that you wrote the original software. If you use this software in
            a product, an acknowledgment in the product documentation would be
            appreciated but is not required.
        2.    Altered source versions must be plainly marked as such, and must not be
            misrepresented as being the original software.
        3. This notice may not be removed or altered from any source distribution.
    =============================================================================*/
    static FloatHealth[MAX_PLAYERS];
    /************************************************/
    stock SetPlayerHealthAC(playeridFloathealthe)
    {
        
    Health[playerid] = healthe;
        return 
    SetPlayerHealth(playeridhealthe);
    }
    #if defined _ASC_SetPlayerHealth
    #undef SetPlayerHealth
    #else
    #define _ASC_SetPlayerHealth
    #endif
    #define SetPlayerHealth SetPlayerHealthAC
    /************************************************/
    public OnPlayerUpdate(playerid)
    {
        {
            new 
    Floathealth;
            
    GetPlayerHealth(playeridhealth);
            if((
    Health[playerid] != health))
            {
                if(
    Health[playerid] > health)
                {
                    
    Health[playerid] = health;
                
    #if defined OnHPCheatDetected
                    
    OnHPCheatDetected(playeridHealth[playerid], health);
                
    #endif 
                
    }
                else if(
    Health[playerid] < health)
                {
                    
    Health[playerid] = health;
                
    #if defined OnHPCheatDetected
                    
    OnHPCheatDetected(playeridHealth[playerid], health);
                
    #endif 
                
    }
            }
        }
    #if defined OnPlayerUpdateAC
        
    OnPlayerUpdateAC(playerid);
    #endif
        
    return 1;
    }
    #if    defined    _ALS_OnPlayerUpdate
        #undef    OnPlayerUpdate
    #else
        #define    _ALS_OnPlayerUpdate
    #endif
    #define    OnPlayerUpdate    OnPlayerUpdateAC
    #if    defined    OnPlayerUpdateAC
    forward OnPlayerUpdateAC(playerid);
    #endif
    /************************************************/
    public OnPlayerSpawn(playerid)
    {
        
    Health[playerid] = 100;
    #if defined OnPlayerSpawnAC
        
    OnPlayerSpawnAC(playerid);
    #endif
        
    return 1;
    }
    #if defined _ALS_OnPlayerSpawn
    #undef OnPlayerSpawn
    #else
    #define _ALS_OnPlayerSpawn
    #endif
    #define OnPlayerSpawn OnPlayerSpawnAC
    #if defined OnPlayerSpawnAC
    forward OnPlayerSpawnAC(playerid);
    #endif
    /************************************************/
    stock GetPlayerHealthAC(playerid, &Float:healths)
    {
        
    healths Health[playerid];
        return 
    1;
    }
    #if defined _ALS_GetPlayerHealth
    #undef GetPlayerHealth
    #else
    #define _ALS_GetPlayerHealth
    #endif
    #define GetPlayerHealth GetPlayerHealthAC
    /************************************************/
    #if defined OnHPCheatDetected
    forward OnHPCheatDetected(playeridFloat:hp_expectedFloat:hp_got);
    #endif 

    PHP код:
    GetPlayerHealth заменил GetPlayerHealthAC 
    PHP код:
    SetPlayerHealth заменил SetPlayerHealthAC в моде не в Include 
    помоги что то не правильно сделал поправь, подскажи
    Последний раз редактировалось Dima_Tushin; 14.10.2014 в 17:08.

  6. #5
    Аватар для Londlem
    Модератор

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Сообщений
    1,360
    Репутация:
    767 ±
    Самая большая ошибка в данном случае это присвоение работы за свою. :/
    Цитата Сообщение от Dima_Tushin Посмотреть сообщение
    /*================================================= ============================
    Health Anticheat
    by Dima_Tuhin

    www.pro-pawn.ru

    Copyright (c) 2014 Dima_Tuhin
    И перечитайте ещё раз первый пост, заменять функции не стоит.

  7. Пользователь сказал cпасибо:
    Daniel_Cortez (14.10.2014)
  8. #6
    Аватар для Dima_Tushin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    21.04.2013
    Адрес
    Россия
    Сообщений
    111
    Репутация:
    1 ±
    да это не важно я же не выкладываю и не говорю что я автор
    просто спросил в чем проблема

    да функции можно любые делать вот что обязательно в каждой переменной или функции делать пробелы вот такие ______
    Последний раз редактировалось Dima_Tushin; 14.11.2014 в 20:11.

  9. #7
    Аватар для Osetin
    •Администратор•

    Статус
    Оффлайн
    Регистрация
    26.03.2013
    Адрес
    Pro-Pawn.Ru
    Сообщений
    3,428
    Репутация:
    1079 ±
    Цитата Сообщение от Dima_Tushin Посмотреть сообщение
    да это не важно я же не выкладываю и не говорю что я автор
    просто спросил в чем проблема

    да функции можно любые делать вот что обязательно в каждой переменной или функции делать пробелы вот такие ______
    Как раз таки это важно. Люди старались, описывали вам все, а вы взяли и тупо сменили ник автора на свой ник. Т.е вы присвоили чужую работу, которую вам преподнесли с подробным разъяснением. А автор сидел несколько дней и пытался написать статью. Не очень приятно бывает, когда так поступают.

  10. #8
    Аватар для Dima_Tushin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    21.04.2013
    Адрес
    Россия
    Сообщений
    111
    Репутация:
    1 ±
    на конец то получилось :) теперь все античиты переведу на Includе

    - - - Добавлено - - -

    Цитата Сообщение от Osetin Посмотреть сообщение
    Как раз таки это важно. Люди старались, описывали вам все, а вы взяли и тупо сменили ник автора на свой ник. Т.е вы присвоили чужую работу, которую вам преподнесли с подробным разъяснением. А автор сидел несколько дней и пытался написать статью. Не очень приятно бывает, когда так поступают.
    ладно понял я больше не буду присваивать авторство!!!

  11. #9
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    560
    Репутация:
    272 ±
    Цитата Сообщение от Dima_Tushin Посмотреть сообщение
    да это не важно я же не выкладываю и не говорю что я автор
    просто спросил в чем проблема

    да функции можно любые делать вот что обязательно в каждой переменной или функции делать пробелы вот такие ______
    Ахринеть, а давайте я хакну библиотеки сампа, и вместо "SA-MP Team" напишу "Seregamil"?

  12. #10
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,441
    Репутация:
    261 ±
    Цитата Сообщение от Seregamil Посмотреть сообщение
    Ахринеть, а давайте я хакну библиотеки сампа, и вместо "SA-MP Team" напишу "Seregamil"?
    go cho

 

 
Страница 1 из 5 123 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •