Русское сообщество по скриптингу

[CS] Extra Items 1.0

Новые плагины для AMX Mod X, которые были добавлены в базу плагинов нашего форума. Плагины еще не утвеждены администратором/модератором.

Модератор: Leonidddd

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

Данный раздел форума служит для добавления новых плагинов в базу нашего форума. После того, как администратор/модератор утвердит плагин, он будет перемещен в раздел "Утвежденные плагины".

Правила при добавлении новых плагинов:

1. При вставке кода плагина необходимо использовать тег [pawn], в противном случае, если тег [pawn] не отображает ваш код, можно использовать тег [code].
2. Любые изображения должны быть загружены, как вложения к вашему сообщению.
3. Обязательно выкладывайте исходник sma плагина. Запрещено выкладывать amxx файл.
4. Обязательно указывайте настоящих авторов плагина, если вы использовали чьи-то наработки или функции, указывайте их авторов в сообщении.
5. Необходимо заполнять детальную информацию о плагине (версию, настройки, используемые модули, список изменений и другую).

[CS] Extra Items 1.0

Сообщение NightFury » 04 ноя 2016, 18:18

Автор: NightFury(406)
Версия: 1.0

[CS] Extra Items


Описание: Плагин добавляет меню дополнительных предметов.

Код: Выделить всё
#if defined _extraitems_included
#endinput
#endif
#define _extraitems_included

#define EXITEM_DISABLED 97

// Vyzyvaetsya kogda igrok vybiraet predmet.
// @param id - Indeks igroka
// @param item - Indeks predmeta
forward cs_extra_item(id, item)

// Registratsiya novogo predmeta.
// @param Name - Imya predmeta
// @param Cost - Stoimost' predmeta
// @param return - Vozvrashchaet id dannogo predmeta
native RegisterItem(Name[], Cost)

// Poluchaem kolichestvo deneg.
// @param id - Indeks igroka
native player_get_money(id)

// Ustanavlivaem kolichestvo deneg.
// @param id - Indeks igroka
// @param money - kolichestvo deneg
// @param flash - pokazyvat' izmeneniya deneg (1=da, 0=net)
native player_set_money(id, money, flash)
 


Создаем новый предмет:

Код: Выделить всё
#include <amxmodx>
#include <extraitems>    // инклуд для доп. предметов

#define EXNAME "Новый предмет"    // название предмета
#define EXCOST 50    // цена

new g_extra_new

public plugin_precache
()
{
    g_extra_new = RegisterItem(EXNAME, EXCOST)    // регистрируем предмет
}

public cs_extra_item(id, item)    // вызываем предмет
{
    if(item == g_extra_new)    // проверяем предмет
    {
        client_print(id, print_chat, "Привет!")    // что мы даем
    }
}
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Подпись: NightFury/406
Поддержка: vk.com/mashakrylova406
Аватара пользователя
NightFury
 
Сообщения: 85
Зарегистрирован: 10 авг 2016, 12:22
Благодарил (а): 8 раз.
Поблагодарили: 24 раз.
Опыт программирования: Больше трех лет
Языки программирования: Pawn, C, C++

Re: [CS] Extra Items 1.0

Сообщение Mistrick » 04 ноя 2016, 19:02

Код: Выделить всё
public cs_extra_items_func(id, menu, item)
{
    if(item == MENU_EXIT) return menu_destroy(menu)
    new szDummy, szCost, szData[3]
    new szMoney = player_get_money(id)
    menu_item_getinfo(menu, item, szDummy, szData, charsmax(szData), _, _, szDummy)
    item = str_to_num(szData); szCost = ArrayGetCell(ItemCost, item)
    player_set_money(id, szMoney - szCost, 1) // <---
    ExecuteForward(g_forward, g_result, id, item)
    if(g_result == EXITEM_DISABLED) player_set_money(id, szMoney, 0); // <---
return 1

Зачем отнимать деньги и потом возвращать если был блок? Можно только отнять, если не блокировали.
Код: Выделить всё
szBackMenuShop = menu_makecallback("cs_extra_items_back"

Зачем вы создаете Callback при каждом выводе меню? Получили утечку памяти.

В handler'e меню нет проверки на доступные деньги. Понятно что не нажать пункт, если денег не было, но если они были, потом уменьшились и жмем пункт, получаем отрицательный баланс.

Зачем этот callback? Можно было просто сделать заглушку, так вы делаете двойную работу. При составлении проверяете на доступность пункта, перекрашиваете его. А потом еще и callback делает тоже самое моментом позже.

Читаемость оставляет желать лучшего. Последний паблик с двумя ретурнами в строке очень помогает разобраться в работе кода.
Аватара пользователя
Mistrick
Скриптер
 
Сообщения: 2940
Зарегистрирован: 04 ноя 2012, 18:15
Благодарил (а): 43 раз.
Поблагодарили: 1247 раз.
Языки программирования: PAWN
С/С++(few above zero)

Re: [CS] Extra Items 1.0

Сообщение Xelson » 04 ноя 2016, 22:01

Mistrick,
Можно поподробнее про утечки памяти? Когда они еще могут происходить, кроме callback и AllocString?
Аватара пользователя
Xelson
 
Сообщения: 365
Зарегистрирован: 06 мар 2016, 14:41
Откуда: Беларусь
Благодарил (а): 16 раз.
Поблагодарили: 46 раз.
Опыт программирования: Больше трех лет

Re: [CS] Extra Items 1.0

Сообщение Mistrick » 04 ноя 2016, 22:38

Xelson, Сложный вопрос. Вы сами должны понимать где выделяется память и заботиться о ее высвобождении. Или не допускать ее утечки, как здесь с callback.
Аватара пользователя
Mistrick
Скриптер
 
Сообщения: 2940
Зарегистрирован: 04 ноя 2012, 18:15
Благодарил (а): 43 раз.
Поблагодарили: 1247 раз.
Языки программирования: PAWN
С/С++(few above zero)

Re: [CS] Extra Items 1.0

Сообщение NightFury » 04 ноя 2016, 23:16

Спасибо Mistrick то что указываешь на ошибки.
посмотрите пожалуйста такой вариант кода.

Код: Выделить всё
#include <amxmodx>
#include <fakemeta>
#include <extraitems>

#define player_valid_pev(%1) (bool:(pev_valid(%1) == 2))

#define m_iAccount 115

new Array:ItemName, Array:ItemCost
new g_result
, g_forward

public plugin_init
()
{
    register_plugin("[CS] Extra Items", "1.0", "406")
    g_forward = CreateMultiForward("cs_extra_item", ET_CONTINUE, FP_CELL, FP_CELL)
    register_clcmd("say /extraitems", "cs_menu_extra_items")
    register_dictionary("extra_items.txt")
}

public plugin_precache()
{
    ItemName = ArrayCreate(64, 1)
    ItemCost = ArrayCreate(1, 1)
}

public plugin_natives()
{
    register_library("extraitems")
    register_native("RegisterItem", "native_register_item", 1)
    register_native("player_get_money", "native_player_get_money", 1)
    register_native("player_set_money", "native_player_set_money", 1)
}

public native_register_item(const Name[], const Cost)
{
    param_convert(1)
    ArrayPushString(ItemName, Name)
    ArrayPushCell(ItemCost, Cost)
    return (ArraySize(ItemName) - 1)
}

public native_player_get_money(id) return !player_valid_pev(id) ? 0 : get_pdata_int(id, m_iAccount, 5)

public native_player_set_money(id, money, flash)
{
    if(!player_valid_pev(id)) return
    set_pdata_int
(id, m_iAccount, money, 5)
    #define msgid_Money 102
    message_begin(MSG_ONE, msgid_Money, _, id)
    write_long(money); write_byte(flash)
    message_end()
}

public cs_menu_extra_items(id, page)
{
    new szMenu[96], szName[64], szKey[3]
    new szCreateMenuShop, szCost
    new szSize 
= ArraySize(ItemName)
    format(szMenu, charsmax(szMenu), "%L\r", LANG_PLAYER, "CS_MENU_ITEM")
    szCreateMenuShop = menu_create(szMenu, "cs_extra_items_func")
    for(new i=0; i < szSize; i++)
    {
        num_to_str(i, szKey, charsmax(szKey))
        ArrayGetString(ItemName, i, szName, charsmax(szName))
        szCost = ArrayGetCell(ItemCost, i)
        if(player_get_money(id) >= szCost)
        formatex(szMenu, charsmax(szMenu), "%s \y[\r%d$\y]", szName, szCost)
        else formatex(szMenu, charsmax(szMenu), "\d%s \y[\r%d$\y]", szName, szCost)
        menu_additem(szCreateMenuShop, szMenu, szKey)
    }
    formatex(szMenu, charsmax(szMenu), "%L", LANG_PLAYER, "CS_EXIT")
    menu_setprop(szCreateMenuShop, MPROP_EXITNAME, szMenu)
    formatex(szMenu, charsmax(szMenu), "%L", LANG_PLAYER, "CS_NEXT")
    menu_setprop(szCreateMenuShop, MPROP_NEXTNAME, szMenu)
    formatex(szMenu, charsmax(szMenu), "%L", LANG_PLAYER, "CS_BACK")
    menu_setprop(szCreateMenuShop, MPROP_BACKNAME, szMenu)
    if(szSize) return menu_display(id, szCreateMenuShop, page)
    else client_print(id, print_chat, "%L", LANG_PLAYER, "CS_NO_ITEMS"); return 0
}

public cs_extra_items_func(id, menu, item)
{
    if(item == MENU_EXIT) return menu_destroy(menu)
    new szDummy, szCost, szData[3]
    new szMoney = player_get_money(id)
    menu_item_getinfo(menu, item, szDummy, szData, charsmax(szData), _, _, szDummy)
    item = str_to_num(szData); szCost = ArrayGetCell(ItemCost, item)
    if(szMoney < ArrayGetCell(ItemCost, item))
    return EXITEM_DISABLED
    else
    
{
        player_set_money(id, szMoney - szCost, 1)
        ExecuteForward(g_forward, g_result, id, item)
    }
    return 1
}
Подпись: NightFury/406
Поддержка: vk.com/mashakrylova406
Аватара пользователя
NightFury
 
Сообщения: 85
Зарегистрирован: 10 авг 2016, 12:22
Благодарил (а): 8 раз.
Поблагодарили: 24 раз.
Опыт программирования: Больше трех лет
Языки программирования: Pawn, C, C++

Re: [CS] Extra Items 1.0

Сообщение Mistrick » 04 ноя 2016, 23:42

NightFury, Можете посмотреть Вы должны зарегистрироваться, чтобы видеть ссылки.. Он к моду не привязан и является полным аналогом вашему. Только функций больше. Пример итемов есть в последнем посте топика Deathrun Mod.
Вот мои комментарии о вашем коде.
Код: Выделить всё
#include <amxmodx>
#include <fakemeta>
#include <extraitems>

#define player_valid_pev(%1) (bool:(pev_valid(%1) == 2))

#define m_iAccount 115

new Array:ItemName, Array:ItemCost
new g_resultg_forward
new g_callback_disable_item;

public 
plugin_init()
{
    
register_plugin("[CS] Extra Items""1.0""406")
    
g_forward CreateMultiForward("cs_extra_item"ET_CONTINUEFP_CELLFP_CELL)
    
register_clcmd("say /extraitems""cs_menu_extra_items")
    
register_dictionary("extra_items.txt")
    
    
g_callback_disable_item menu_makecallback("shop_disable_item");
}

public 
plugin_precache()
{
    
ItemName ArrayCreate(641)
    
ItemCost ArrayCreate(11)
}

public 
plugin_natives()
{
    
register_library("extraitems")
    
register_native("RegisterItem""native_register_item"1)
    
register_native("player_get_money""native_player_get_money"1)
    
register_native("player_set_money""native_player_set_money"1)
}

public 
native_register_item(const Name[], const Cost)
{
    
param_convert(1)
    
ArrayPushString(ItemNameName)
    
ArrayPushCell(ItemCostCost)
    return (
ArraySize(ItemName) - 1)
}

public 
native_player_get_money(id) return !player_valid_pev(id) ? get_pdata_int(idm_iAccount5)

public 
native_player_set_money(idmoneyflash)
{
    if(!
player_valid_pev(id)) return
    
set_pdata_int(idm_iAccountmoney5)
    
#define msgid_Money 102
    
message_begin(MSG_ONEmsgid_Money_id)
    
write_long(money); write_byte(flash)
    
message_end()
}

public 
cs_menu_extra_items(idpage)
{
    
    new 
szSize ArraySize(ItemName)
    
    if(!
szSize// почему данная проверка была в конце функции?
    
{
        
client_print(idprint_chat"%L"LANG_PLAYER"CS_NO_ITEMS");
        return 
0
    
}
    
    new 
szMenu[96], szName[64], szKey[3]
    new 
szCreateMenuShopszCost
    format
(szMenucharsmax(szMenu), "%L\r"LANG_PLAYER"CS_MENU_ITEM")
    
szCreateMenuShop menu_create(szMenu"cs_extra_items_func")
    
    new 
callback;
    
    for(new 
i=0szSizei++)
    {
        
num_to_str(iszKeycharsmax(szKey))
        
ArrayGetString(ItemNameiszNamecharsmax(szName))
        
szCost ArrayGetCell(ItemCosti)
        
        
formatex(szMenucharsmax(szMenu), "%s \y[\r%d$\y]"szNameszCost)
        
        
// если денег достаточно, разрешаем пункт, иначе отправляем в нащ Callback с заглушкой 
        // если итем отключили, то он сам перекрасится
        
callback = (player_get_money(id) >= szCost) ? -g_callback_disable_item;
        
        
menu_additem(szCreateMenuShopszMenuszKey0callback);
    }
    
formatex(szMenucharsmax(szMenu), "%L"LANG_PLAYER"CS_EXIT")
    
menu_setprop(szCreateMenuShopMPROP_EXITNAMEszMenu)
    
formatex(szMenucharsmax(szMenu), "%L"LANG_PLAYER"CS_NEXT")
    
menu_setprop(szCreateMenuShopMPROP_NEXTNAMEszMenu)
    
formatex(szMenucharsmax(szMenu), "%L"LANG_PLAYER"CS_BACK")
    
menu_setprop(szCreateMenuShopMPROP_BACKNAMEszMenu)
    
    
    
menu_display(idszCreateMenuShoppage)
    return 
PLUGIN_HANDLED;
}

public 
cs_extra_items_func(idmenuitem)
{
    if(
item == MENU_EXIT)
    {
        
menu_destroy(menu)
        return 
PLUGIN_HANDLED
    
}
    
    
// венгерскую натацию вы как-то неправильно используете =\
    
    
new szDummyszCostszData[3]
    new 
szMoney player_get_money(id)
    
menu_item_getinfo(menuitemszDummyszDatacharsmax(szData), __szDummy)
    
//item = str_to_num(szData); item который приходит параметром и так будет от 0 до ArraySize(ItemName) - 1
    
szCost ArrayGetCell(ItemCostitem)
    
    if(
szMoney ArrayGetCell(ItemCostitem)) // перестраховка на доступность денег
    
{
        
ExecuteForward(g_forwardg_resultiditem
        
// если итем не блокнули в форварде, снимаем деньги
        
if(g_result != EXITEM_DISABLED// вами же заложенная функция, блокировка покупки через ответ в форварде
        
{
            
player_set_money(idszMoney szCost1)
        }
    }
    
    
menu_destroy(menu);// удалять то меню надо в любом случае, если не статическое
    
    
return PLUGIN_HANDLED;
}
public 
shop_disable_item()
{
    return 
ITEM_DISABLED;
Аватара пользователя
Mistrick
Скриптер
 
Сообщения: 2940
Зарегистрирован: 04 ноя 2012, 18:15
Благодарил (а): 43 раз.
Поблагодарили: 1247 раз.
Языки программирования: PAWN
С/С++(few above zero)


Вернуться в Добавленные новые плагины

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0