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

Реклама


**Как получить V.I.P** (Перейти)
Чтобы заказать рекламу на Pro-Pawn.Ru, обращайтесь в Skype.
Баннерная реклама 200руб/мес, Текстовая 100руб/мес.
Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 16
  1. #1
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,360
    Репутация:
    113 ±

    ResetPlayerWeaponSlot

    Описание:
    Функция (ResetPlayerWeaponSlot) удаляющая оружие с выбранного слота

    Наверное все замечали что в SA:MP нету функции удаления оружия с выбранного слота,
    или может замечали такой момент когда истратив весь б/к в GetPlayerWeaponData
    нагло показывает что у Вас есть оружие, а патронов к нему "тю-тю",
    баг? или фича такая чтобы патроны потом пополнять? каждый по разному на это посмотрит.

    ResetPlayerWeaponSlot возвращает 2 значения(0,1)
    0 - Игрок не в сети
    1 - Слот успешно обнулён

    Код:
     Клац =3
    PHP код:
    #define MAX_SLOT_WEAP    (13) //макс. оружейных слотов

    stock ResetPlayerWeaponSlot(playeridslot//[slot 0-12]
    {
        if(
    IsPlayerConnected(playerid) == 0) return 0;
        goto 
    no_init_arrays;
        new 
    weapon[MAX_SLOT_WEAP], ammo[MAX_SLOT_WEAP], i_value;
    no_init_arrays:
        for(
    0MAX_SLOT_WEAPi++)
        {
            if(
    != slot)
            {
                
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]);
            }
        }
        
    ResetPlayerWeapons(playerid);
        for(
    0MAX_SLOT_WEAPi++)
        {
            if((
    _value ammo[i]) != 0)
            {
                
    GivePlayerWeapon(playeridweapon[i], _value);
            }
        }
        return 
    1;



    Пример использования:
     Клац =3
    PHP код:
    CMD:resetslot(playeridparams[])
    {
        new 
    gunslot;
        if(
    sscanf(params"d"gunslot))
            return 
    SendClientMessage(playerid, -1, !"Использование: /resetslot [slot 0-12]");
        if(
    ResetPlayerWeaponSlot(playeridgunslot) == 0)
            return 
    SendClientMessage(playerid, -1, !"Игрок не в сети!");
        
    SendClientMessage(playerid, -1, !"Выбранный слот был обнулён!");
        return 
    1;



    Автор темы:
    vovandolg
    Помогали:
    VVWVV, Anton Styazhkin
    Последний раз редактировалось vovandolg; 03.08.2016 в 23:34.
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  2. Пользователь сказал cпасибо:
    HarrWe (30.08.2016)
  3. #2
    Аватар для VVWVV
    Проверенный

    Статус
    Оффлайн
    Регистрация
    09.07.2015
    Сообщений
    607
    Репутация:
    289 ±
    - Вы не указали проверку на нахождения игрока в игре (IsPlayerConnected), а это означает, что все циклы, массивы будут инициализироваться/итерироваться без участия игрока.
    - Стоило бы вынести переменную "sl" из циклов, ибо переменная инициализируется несколько раз. (Зачем так называть переменную?)
    - Доступ к элементу массива очень затратный, поэтому стоило бы кешировать значение.

    Пример моей функции:
    PHP код:
    stock
        ResetPlayerWeaponSlot
    (playeridslot)
    {
        if (
    IsPlayerConnected(playerid) == 0)
            return 
    0;
        goto 
    no_init_arrays;
        new 
    weapon[MAX_WEAPON_SLOTS], ammo[MAX_WEAPON_SLOTS], i_value;
    no_init_arrays:
        for (
    0MAX_WEAPON_SLOTS; ++i)
        {
            if (
    == slot)
                continue;
            
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]);
        }
        
    ResetPlayerWeapons(playerid);
        for (
    0!= MAX_WEAPON_SLOTS; ++i)
        {
            if ((
    _value ammo[i]) == 0)
                continue;
            
    GivePlayerWeapon(playeridweapon[i], _value);
        }
        return 
    1;

    Последний раз редактировалось VVWVV; 28.07.2016 в 05:14.

  4. #3
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,035
    Репутация:
    702 ±
    Цитата Сообщение от vovandolg Посмотреть сообщение
    Пару циклов на 13 итераций и 3 разных функции нам в помощь(ибо по другому не как):
    Ошибаешься, в fixes.inc эту проблему решили следующим образом:
    PHP код:
    stock FIX_GetPlayerWeaponData(playeridslot, &weapons, &ammo)
    {
        return
            
    slot GetPlayerWeaponData(playeridslotweaponsammo),
            
    weapons ammo weapons 0,
            
    slot;
    }
    #if defined _ALS_GetPlayerWeaponData
        #undef GetPlayerWeaponData
    #else
        #define _ALS_GetPlayerWeaponData
    #endif

    #define GetPlayerWeaponData FIX_GetPlayerWeaponData 
    То есть при вызове GetPlayerWeaponData проверяется наличие патронов и, если их 0, то weaponid передаётся в виде 0. Как мне кажется, так гораздо проще и эффективнее.
    Последний раз редактировалось ziggi; 28.07.2016 в 16:15.

  5. 2 пользователя(ей) сказали cпасибо:
    seriu (19.10.2016)Роуди. (28.07.2016)
  6. #4
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,360
    Репутация:
    113 ±
      Открыть/закрыть
    Цитата Сообщение от VVWVV Посмотреть сообщение
    - Вы не указали проверку на нахождения игрока в игре (IsPlayerConnected), а это означает, что все циклы, массивы будут инициализироваться/итерироваться без участия игрока.
    Я привык что у меня все такие проверки в команде или ещё где до работы этого кода, ну да ладно щас черканём..

    Цитата Сообщение от VVWVV Посмотреть сообщение
    - Стоило бы вынести переменную "sl" из циклов, ибо переменная инициализируется несколько раз. (Зачем так называть переменную?)
    Вот тут я не понял ты к моему невинному коду придрался
    sl - slot сокращённо, так я делал и мне так удобнее видеть было =3

    Цитата Сообщение от VVWVV Посмотреть сообщение
    - Доступ к элементу массива очень затратный, поэтому стоило бы кешировать значение.

    Пример моей функции:
    PHP код:
    stock
        ResetPlayerWeaponSlot
    (playeridslot)
    {
        if (
    IsPlayerConnected(playerid) == 0)
            return 
    0;
        goto 
    no_init_arrays;
        new 
    weapon[MAX_WEAPON_SLOTS], ammo[MAX_WEAPON_SLOTS], i_value;
    no_init_arrays:
        for (
    0MAX_WEAPON_SLOTS; ++i)
        {
            if (
    == slot)
                continue;
            
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]);
        }
        
    ResetPlayerWeapons(playerid);
        for (
    0!= MAX_WEAPON_SLOTS; ++i)
        {
            if ((
    _value ammo[i]) == 0)
                continue;
            
    GivePlayerWeapon(playeridweapon[i], _value);
        }
        return 
    1;

    Можно ссылочку где про кеширование почитать можно?)

    Цитата Сообщение от ziggi Посмотреть сообщение
    Ошибаешься, в fixes.inc это проблему решили следующим образом:
    PHP код:
    stock FIX_GetPlayerWeaponData(playeridslot, &weapons, &ammo)
    {
        return
            
    slot GetPlayerWeaponData(playeridslotweaponsammo),
            
    weapons ammo weapons 0,
            
    slot;
    }
    #if defined _ALS_GetPlayerWeaponData
        #undef GetPlayerWeaponData
    #else
        #define _ALS_GetPlayerWeaponData
    #endif

    #define GetPlayerWeaponData FIX_GetPlayerWeaponData 
    То есть при вызове GetPlayerWeaponData проверяется наличие патронов и, если их 0, то weaponid передаётся в виде 0. Как мне кажется, так гораздо проще и эффективнее.
    Ну это как же я пропустил, то ли инклуд старый у меня...
    По крайней мере слоты заданные не очищает даже если там есть оружие, поэтому моя функция ещё в силе =3


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

    Ещё не понял момента в отрывке кода....
    Зачем вызывать лишний раз оператора
    PHP код:
    if (== slot)
        continue;
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]); 
    Когда можно просто вот так сделать
    PHP код:
    if (!= slot)
        
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]); 
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  7. #5
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,931
    Репутация:
    1502 ±
    Цитата Сообщение от vovandolg Посмотреть сообщение
    Ещё не понял момента в отрывке кода....
    Зачем вызывать лишний раз оператора
    PHP код:
    if (== slot)
        continue;
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]); 
    Когда можно просто вот так сделать
    PHP код:
    if (!= slot)
        
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]); 
    Либо ты вызываешь "continue" явно, либо делаешь это неявно - разницы не вижу
    Связаться со мной можно в личных сообщениях этой группы

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  8. #6
    Аватар для untonyst
    Младший сержант

    Статус
    Оффлайн
    Регистрация
    15.03.2015
    Адрес
    Slobodskoy
    Сообщений
    664
    Репутация:
    234 ±
    Цитата Сообщение от VVWVV Посмотреть сообщение
    - Вы не указали проверку на нахождения игрока в игре (IsPlayerConnected), а это означает, что все циклы, массивы будут инициализироваться/итерироваться без участия игрока.
    - Стоило бы вынести переменную "sl" из циклов, ибо переменная инициализируется несколько раз. (Зачем так называть переменную?)
    - Доступ к элементу массива очень затратный, поэтому стоило бы кешировать значение.

    Пример моей функции:
    PHP код:
    stock
        ResetPlayerWeaponSlot
    (playeridslot)
    {
        if (
    IsPlayerConnected(playerid) == 0)
            return 
    0;
        goto 
    no_init_arrays;
        new 
    weapon[MAX_WEAPON_SLOTS], ammo[MAX_WEAPON_SLOTS], i_value;
    no_init_arrays:
        for (
    0MAX_WEAPON_SLOTS; ++i)
        {
            if (
    == slot)
                continue;
            
    GetPlayerWeaponData(playeridiweapon[i], ammo[i]);
        }
        
    ResetPlayerWeapons(playerid);
        for (
    0!= MAX_WEAPON_SLOTS; ++i)
        {
            if ((
    _value ammo[i]) == 0)
                continue;
            
    GivePlayerWeapon(playeridweapon[i], _value);
        }
        return 
    1;

    Зачем пропускать инициализацию, если ты не получишь профита, но сделаешь код для других запутанней?

      Открыть/закрыть
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Пропуск инициализации ячеек массива нулями.
    При объявлении локальных массивов внутри функций компилятор не только резервирует место в стеке под массив, но и инициализирует все его ячейки нулями, чтобы в них не было мусорных значений.
    Сделано это из-за быдлокодеров, которые, пользуются переменными, забывая их инициализировать.
    Тем не менее, инициализация занимает некоторое время, да и польза от этого сомнительная, если вы способны отдавать отчёт своим действиям.
    К счастью, есть способ избежать потерь во времени, пропустив инициализацию:
    PHP код:
        SomeFunction()
        {
            
    // перед объявлением массива перейдём на метку skip_array_init
            
    goto skip_array_init;
            
    // объявляем массив
            
    new arr[256];
        
    skip_array_init:
            
    // в этом месте массив arr будет существовать, но он не будет инициализирован:
            // код инициализации существует, но он находится _до_ метки skip_array_init,
            // т.е. мы обошли этот код

            // дальше - код с использованием массива
        

    Скомпилируем код, а затем дизассемблируем его.
    Получим следующую последовательность инструкций:
    Код HTML:
    	; Начало функции SomeFunction.
    	proc
    	; И сразу же - переход на метку l.0 (см. далее).
    	jump		0
    	; Выделение места в стеке под массив из 16 ячеек (ffffffc0 означает "-16")
    	; (этот код никогда не сработает, переход на l.0 был безусловным).
    	stack		ffffffc0
    	; Заполнение массива нулями происходит побайтово,
    	; 16 ячеек - 64 байта (40 в шестнадцатеричной системе счисления).
    	zero.pri
    	addr.alt	ffffffc0
    	fill		40
    ; Метка, с помощью которой пропускается инициализация массива.
    l.0
    	; Установка вершины стека в то положение, когда выделено 16 ячеек под массив,
    	; Обратите внимание: в отличие от обычного создания массива,
    	; здесь массив не заполняется никакими значениями,
    	; происходит только резервирование пространства,
    	lctrl		5
    	add.c		ffffffc0
    	sctrl		4
    	; Код с использованием массива.
    	; ...
    	; Высвобождение пространства в стеке и возврат из функции.
    	stack		40
    	zero.pri
    	retn
    Если кому интересно, вот тест скорости:
      Открыть/закрыть
    PHP код:
    #include <a_samp>

    const PROFILE_ITERATIONS_MAJOR 1000;
    const 
    PROFILE_ITERATIONS_MINOR 1000;

    const 
    STRING_SIZE 512;


    const 
    SZ STRING_SIZE;

    #define _m1();\
        
    {new a[SZ];}
    #define method1();\
        
    _m1();_m1();_m1();_m1();_m1();_m1();_m1();_m1();_m1();_m1();

    #define _m2();\
        
    {goto skip_init;new a[SZ];skip_init:}
    #define method2();\
        
    _m2();_m2();_m2();_m2();_m2();_m2();_m2();_m2();_m2();_m2();


    bool:IsJITEnabled()
    {
        
    #emit    lctrl    7
        #emit    retn
        
    return true;
    }

    main()
    {
        
    printf(
            
    "Testing array initialization..." "\n"\
            
    "(%dx%d iterations, array size: %d, JIT status: %sabled)",
            
    PROFILE_ITERATIONS_MAJORPROFILE_ITERATIONS_MINOR,
            
    STRING_SIZEIsJITEnabled() ? ("en") : ("dis")
        );
        new 
    t1t2tij;
        
    t1 0t2 0;
        for(
    0PROFILE_ITERATIONS_MAJOR; ++i)
        {
            
    GetTickCount();
            for(
    0PROFILE_ITERATIONS_MINOR; ++j)
            {
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
                
    method1();
            }
            
    t1 += GetTickCount()-t;
            
    GetTickCount();
            for(
    0PROFILE_ITERATIONS_MINOR; ++j)
            {
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
                
    method2();
            }
            
    t2 += GetTickCount()-t;
        }
        
    printf(
            
    "method 1: %d" "\n"\
            
    "method 2: %d",
            
    t1t2
        
    );


    Макросы method1 и method2 сделаны, чтобы повторить в них создание локальных массивов по 10 раз.
    Кроме того сами макросы используются в функции main по 10 раз (итого получается 10x10 = 100 повторов).
    Это не что иное, как развёртывание циклов. Я сделал именно так, чтобы уменьшить погрешность от циклов и вызовов GetTickCount, таким образом, увеличив точность измерений.
    Также в процессе компиляции выдаётся куча варнингов, но они, опять же, из-за макросов, не обращайте на них внимания.
    Тест я запускал на массивах из 32, 256 и 512 ячеек, с включенным и выключенным JIT.
    Результаты следующие:
      Открыть/закрыть

    Код:
    Testing array initialization...
    (1000x1000 iterations, array size: 32, JIT status: disabled)
    method 1: 5581
    method 2: 47
    
    Testing array initialization...
    (1000x1000 iterations, array size: 32, JIT status: enabled)
    method 1: 2640
    method 2: 4
    Код:
    Testing array initialization...
    (1000x1000 iterations, array size: 256, JIT status: disabled)
    method 1: 31324
    method 2: 42
    
    Testing array initialization...
    (1000x1000 iterations, array size: 256, JIT status: enabled)
    method 1: 15106
    method 2: 3
    Код:
    Testing array initialization...
    (1000x1000 iterations, array size: 512, JIT status: disabled)
    method 1: 63840
    method 2: 40
    
    Testing array initialization...
    (1000x1000 iterations, array size: 512, JIT status: enabled)
    method 1: 29161
    method 2: 4

    Из измерений можно сделать вывод, что размер массива никак не влияет на результаты метода с пропуском инициализации массива.
    Но всё же от трюка не сильно много пользы. Да, цифры в тесте, казалось бы, большие, но не стоит забывать, что они получены с помощью 100 миллионов итераций. В нормальных же условиях время инициализации массива в 512 ячеек составит всего ~0.0006384 мс или ~0.0000006 секунды.
    Младший сержант Стяжкин | ЧСВ группа в ВКонтакте NEW

  9. Пользователь сказал cпасибо:
    vovandolg (28.07.2016)
  10. #7
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,360
    Репутация:
    113 ±
    Так вот тут не пойму,
    no_init_arrays: будет пропускать инициализацию до ResetPlayerWeapons(playerid);
    или до конца всей функции?

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

    И зачем вот эта переменная _value
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  11. #8
    Аватар для untonyst
    Младший сержант

    Статус
    Оффлайн
    Регистрация
    15.03.2015
    Адрес
    Slobodskoy
    Сообщений
    664
    Репутация:
    234 ±
    Цитата Сообщение от vovandolg Посмотреть сообщение
    Так вот тут не пойму,
    no_init_arrays: будет пропускать инициализацию до ResetPlayerWeapons(playerid);
    или до конца всей функции?

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

    И зачем вот эта переменная _value
    1. Просто "перепрыгнем" через заполнение массива нулями. "Прыжок" буде с goto no_init_arrays; на "no_init_arrays:".
    2. Обращаться к элементу массива затратно. Этого можно избежать, если при одном из вызовов сохранить значение элемента в переменную и дальше уже пользоваться переменной со значением элемента массива.
    Младший сержант Стяжкин | ЧСВ группа в ВКонтакте NEW

  12. Пользователь сказал cпасибо:
    vovandolg (28.07.2016)
  13. #9
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,360
    Репутация:
    113 ±
    Ну и)) наинициализировались?
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  14. #10
    Аватар для untonyst
    Младший сержант

    Статус
    Оффлайн
    Регистрация
    15.03.2015
    Адрес
    Slobodskoy
    Сообщений
    664
    Репутация:
    234 ±
    Цитата Сообщение от vovandolg Посмотреть сообщение
    Ну и)) наинициализировались?
    VVWVV просто забыл кое что добавить. Бывает)

    Код:
    stock
        ResetPlayerWeaponSlot(playerid, slot)
    {
        if (IsPlayerConnected(playerid) == 0)
            return 0;
        goto no_init_arrays;
        new weapon[MAX_WEAPON_SLOTS], ammo[MAX_WEAPON_SLOTS], i, _value;
        no_init_arrays:
        for (i = 0; != MAX_WEAPON_SLOTS; ++i)
        {
            if (i == slot)
                continue;
            GetPlayerWeaponData(playerid, i, weapon[i], ammo[i]);
        }
        ResetPlayerWeapons(playerid);
        for (i = 0; i != MAX_WEAPON_SLOTS; ++i)
        {
            if ((_value = ammo[i]) == 0)
                continue;
            GivePlayerWeapon(playerid, weapon[i], _value);
        }
        return 1;
    }
    Младший сержант Стяжкин | ЧСВ группа в ВКонтакте NEW

  15. Пользователь сказал cпасибо:
    vovandolg (29.07.2016)
 

 
Страница 1 из 2 12 ПоследняяПоследняя

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

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

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

Ваши права

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