[TUT] Plugin API y subplugins.
#1
Requerimientos previos:
- Dynamic Natives
- Arrays
- Manejo de menús
- Forwards (No encontré un buen tuto de esto así que lo explico aquí)

Opcional:
- Tries
- Bitsums

El objetivo de este tuto es poder crear un plugin que realice algunas funciones y se complemente con otros plugins que llamaremos "subplugins", a este plugin se le llamará Plugin API.
Tenemos 2 formas de comunicar plugins a través del entorno virtual: Forwards y Natives.

Explicaré lo que es una forward, con un ejemplo:
Código PHP:
public client_putinserver(id
Como vemos, esta es una función que se llama en todos los plugins que la tengan como "public" y la tengan registrada como una forward.

Si revisamos amxmodx.inc encontraremos esto:
Código PHP:
/* Called when client is entering to a game. */
forward client_putinserver(id); 
Es aquí donde se indica que es una forward.

Una forward es una función específica que se llama en todos los plugins que la contengan como una función pública y registrada como forward.
Otro ejemplo: zp_extra_item_selected (forward que se llama cuando se compra un extra item en ZP).

Para explicar mejor cómo hacer una API con forwards y natives, haré un ejemplo con una tienda, cuyos artículos se registran a través de subplugins.

1. Creando la tienda con hardcode.
Código PHP:
#include <amxmodx>
#include <cstrike>
#include <fun>

new g_callback;

public 
plugin_init()
{
    
register_plugin("Test Shop""0.1""Cajita De Leshe");
    
register_clcmd("say /shop""clcmd_shop");

    
g_callback menu_makecallback("menu_shop_cb");
}

public 
clcmd_shop(id)
{
    new 
menu menu_create("Tienda""menu_shop");
    
menu_additem(menu"Ak-47", .callback g_callback);
    
menu_additem(menu"M4a1", .callback g_callback);
    
menu_additem(menu"200 HP", .callback g_callback);

    
menu_display(idmenu);
}

public 
menu_shop_cb(idmenuitem)
{
    if (!
is_user_alive(id))
        return 
ITEM_DISABLED;

    return 
ITEM_ENABLED;
}

public 
menu_shop(idmenuitem)
{
    if (!
is_user_connected(id) || !is_user_alive(id))
    {
        
menu_destroy(menu);
        return 
PLUGIN_HANDLED;
    }

    switch (
item)
    {
        case 
0give_item(id"weapon_ak47");
        case 
1give_item(id"weapon_m4a1");
        case 
2set_user_health(id200);
    }

    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;

Es una tienda bastante simple, con los items hardcodeados.

2. Siguente paso: que se puedan editar los nombres de los ítems sin tocar el menú.
Código PHP:
#include <amxmodx>
#include <cstrike>
#include <fun>

new g_callback;

new const 
ITEMS[][] = { "AK47""M4A1""200 HP" }; // Ahora los items los tengo en una matriz constante.

public plugin_init()
{
    
register_plugin("Test Shop""0.1""Cajita De Leshe");
    
register_clcmd("say /shop""clcmd_shop");

    
g_callback menu_makecallback("menu_shop_cb");
}

public 
clcmd_shop(id)
{
    new 
menu menu_create("Tienda""menu_shop");

    for (new 
03i++)
        
menu_additem(menuITEMS[i], .callback g_callback);

    
menu_display(idmenu);
}

public 
menu_shop_cb(idmenuitem)
{
    if (!
is_user_alive(id))
        return 
ITEM_DISABLED;

    return 
ITEM_ENABLED;
}

public 
menu_shop(idmenuitem)
{
    if (!
is_user_connected(id) || !is_user_alive(id))
    {
        
menu_destroy(menu);
        return 
PLUGIN_HANDLED;
    }

    switch (
item)
    {
        case 
0give_item(id"weapon_ak47");
        case 
1give_item(id"weapon_m4a1");
        case 
2set_user_health(id200);
    }

    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;

Pero me dirán... y esto para qué sirve? Si aún hay hardcode en el handler del menú. Pues sí, no sirve de mucho, es aquí donde entra la utilidad de un plugin API.

3. Ahora haré que cada ítem se registre con una native, y cuando el ítem sea elegido se comunique al subplugin que registró el ítem a través de una forward. De esta forma el subplugin manejará lo que sea que se haya comprado.
Código PHP:
#include <amxmodx>
#include <cstrike>

new g_callback;
new 
g_items_count// Una variable para contar los ítems registrados
new Array:g_item_name, Array:g_item_cost// Arrays dinámicas para los nombres y costos de los ítems.
new forward_itemselected// Una variable para almacenar el id de la forward.

public plugin_natives()
{
    
// Una native para registrar ítems en la tienda.
    
register_native("tienda_registrar""native_register"0);
}

public 
plugin_init()
{
    
register_plugin("Test Shop""0.1""Cajita De Leshe");
    
register_clcmd("say /shop""clcmd_shop");

    
g_callback menu_makecallback("menu_shop_cb");
    
    
// Esta será la forward que se llamará cuando se seleccione un ítem.
    
forward_itemselected CreateMultiForward("tienda_item_seleccionado"ET_STOPFP_CELLFP_CELL);
    
// ET_STOP: Parámetro que indica detener la llamada si algún plugin retorna PLUGIN_HANDLED.
    // FP_CELL: Significa que se enviará una celda de dato. Ej, el índice de un jugador es una celda.
    // En este caso puse 2, 1 para el id del jugador, otra para el id del ítem seleccionado.

    // Arrays dinámicas
    
g_item_name ArrayCreate(32); // 32 celdas debe ser suficiente...
    
g_item_cost ArrayCreate();
}

// Aclaro: uso el estilo 0 de las natives porque me parece más cómodo
// Usar el estilo 0 o 1 es a gusto del cliente.
public native_register(pluginparams)
{
    
// La native tendrá esta estructura:
    // tienda_registrar(nombre[], precio)
    
new szNombre[32];
    
get_string(1szNombrecharsmax(szNombre));

    
ArrayPushString(g_item_nameszNombre); // Guardamos el nombre
    
ArrayPushCell(g_item_costget_param(2)); // Guardamos el costo

    
g_items_count++; // Incrementamos en 1 el contador de ítems.

    
return g_items_count// Retornamos el contador que servirá como un ID para el ítem. 
    // Un detalle: Al usar ArrayGetString/Cell, usaremos un número que es 1 menos que el ID del ítem.
    // ¿Por qué? Porque no es apropiado enviar un ID 0, por eso el primer ID será 1 y le corresponde el número 0 en las arrays dinámicas.
}

public 
clcmd_shop(id)
{
    new 
menu menu_create("Tienda""menu_shop");
    new 
szItem[50], lenbool:canbuycost;

    for (new 
0g_items_counti++)
    {
        
// Agregamos el costo
        
cost ArrayGetCell(g_item_costi);
        
canbuy = (cs_get_user_money(id) >= cost) ? true false;

        
len formatex(szItemcharsmax(szItem), "\%c[$%d]\%c "canbuy 'y' 'r'costcanbuy 'w' 'd');

        
// Ahora el nombre del item
        
ArrayGetString(g_item_nameiszItem[len], charsmax(szItem)-len);

        
menu_additem(menuszItem, .callback canbuy ? -g_callback/*Si no puede comprar, llamamos al callback para desactivar el ítem*/); 
    }

    
// Esto es solo estético
    
menu_setprop(menuMPROP_EXITNAME"\ySalir");
    
menu_setprop(menuMPROP_BACKNAME"Anterior");
    
menu_setprop(menuMPROP_NEXTNAME"Siguiente");

    
menu_display(idmenu);
}

public 
menu_shop_cb(idmenuitem)
{
    
// Este callback sólo se llama cuando no alcanza el dinero...
    
return ITEM_DISABLED;
}

public 
menu_shop(idmenuitem)
{
    if (!
is_user_connected(id) || !(<= item g_items_count))
    {
        
menu_destroy(menu);
        return 
PLUGIN_HANDLED;
    }

    
// Primero comprobamos que el usuario tenga dinero suficiente.
    
new cost ArrayGetCell(g_item_costitem);
    new 
money cs_get_user_money(id);
    if (
money >= cost)
    {
        
// Estamos listos, ahora avisaremos al subplugin que se quiere comprar el ítem
        // Aquí entra el trabajo de las forwards.
        
new ret// Una variable para almacenar el valor de retorno
        
ExecuteForward(forward_itemselectedretiditem+1);
        
// Como explique anteriormente, el ID del ítem es 1 unidad más que el número en los arrays y el menú.


        // Supongamos que tengo un subplugin que da un arma, pero qué pasa si lo compro mientras estoy muerto (por imbécil o por accidente).
        // El subplugin debe comprobar si el jugador está en condición de comprar el ítem.
        // Para eso es el valor de retorno, si el subplugin comprueba que no puedo comprar, debe retornar PLUGIN_HANDLED.

        
if (ret == PLUGIN_HANDLED// No puede comprar
            
client_print(idprint_chat"No puedes comprarlo ahora.");
        else 
// Se ha entregado el ítem, a cobrar!
        
{
            new 
szItemName[32];
            
ArrayGetString(g_item_nameitemszItemNamecharsmax(szItemName));
            
client_print(idprint_chat"Has comprado: %s"szItemName);
            
cs_set_user_money(idmoney-cost);
        }
    }
    else
        
client_print(idprint_chat"No tienes el dinero suficiente.");

    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;

Listo! Ya está, una tienda API completamente funcional.

4. Ahora veremos los subplugins. Anteriormente expliqué que para que funcione una forward se debe indicar como tal (como se hace en amxmodx.inc con client_putinserver). Para esto, crearemos una librería (include) para nuestra API.
Código PHP:
#if defined _shop_api_included // Si ya se definio _shop_api_included
    #endinput // Aqui terminamos, lo que sigue en el .inc no se agregara al plugin.
#endif

#define _shop_api_included // Definimos _shop_api_included
// Lo de arriba sirve para evitar líos si pones #include <libreria> 2 veces o más.

// Bastante simple, registré una native y una forward
// Aquí indico su estructura a los plugins que tengan esta librería incluida

// La native para registrar un ítem.
native tienda_registrar(const nombre[], precio);

// La forward que se llama cuando un jugador elige un ítem.
forward tienda_item_seleccionado(iditem_id); 

5. Crearemos un subplugin. Asumiendo que guardamos la librería con el nombre "tienda.inc". Este subplugin será de un ítem: +100 HP.
Código PHP:
#include <amxmodx>
#include <fun>
#include <tienda> // La librería de nuestra API

new g_item// Variable para almacenar el id del ítem.

public plugin_init()
{
    
register_plugin("[Tienda] +100 HP""0.1""Cajita De Leshe");
    
    
// Recordemos la native: va el nombre y el costo, retorna el id del item.
    
g_item tienda_registrar("+100 HP"700);
}

// Esta es la forward que se va a llamar cuando un ítem es seleccionado.
public tienda_item_seleccionado(iditem_id)
{
    
// La forward nos pasa el ID del ítem seleccionado.
    // Si el ID no es el ID de este ítem, entonces este subplugin no tiene nada que hacer.
    
if (item_id != g_item)
        return 
PLUGIN_CONTINUE// Plugin continue: continua la forward.
    
    // Si llegamos aquí, entonces el ítem es el de este subplugin.
    // Cada subplugin pone sus reglas
    // En este caso, este ítem es sólo para vivos!

    
if (!is_user_alive(id))
        return 
PLUGIN_HANDLED// Como pusimos en el API: PLUGIN_HANDLED = No se compró.

    // Si llegamos aquí, felicidades! Has comprado un ítem!
    
set_user_health(idget_user_health(id)+100); // Aquí entregamos el ítem, en este caso +100 HP.
    
    
return PLUGIN_CONTINUE;


Y eso es todo! Consulten cualquier duda, estoy para responder.
Responder
#2
Excelente Mario
Responder
#3
T.e a.m.o Mario gracias por este excelente tuto, este tuto lo hiciste por mi pregunta verdad?
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#4
excelente tutorial

podrías agregar en el tuto para que sirven las siguientes constantes de las forwards

Código PHP:
ET_IGNORE 
ET_STOP 
// este ya lo explicaste
ET_STOP2
ET_CONTINUE


FP_CELL 
// este ya lo explicaste , aunque los de abajo son un poco obvios 
FP_FLOAT
FP_STRING
FP_ARRAY 

solo para hacerlo mas completo pienso yo
Responder
#5
ET_IGNORE y ET_CONTINUE son bastante obvios, ET_STOP2 seria mejor preguntar para que sirve
Responder
#6
(05/01/2015, 05:32 PM)matrix123 escribió: ET_IGNORE y ET_CONTINUE son bastante obvios, ET_STOP2 seria mejor preguntar para que sirve

me refería a que los agregue al tutorial para que la gente que lo lea sepa que existen otros aparte de ET_STOP y FP_CELL, por si se les ocurre hacer otra cosa en vez del menú que explica
Responder
#7
(05/01/2015, 01:18 PM)elpapimejor escribió: T.e a.m.o Mario gracias por este excelente tuto, este tuto lo hiciste por mi pregunta verdad?

Por supuesto que no cómo se te ocurre e.e LolLolLol

(05/01/2015, 02:02 PM)ErikMav94 escribió: excelente tutorial

podrías agregar en el tuto para que sirven las siguientes constantes de las forwards

Código PHP:
ET_IGNORE 
ET_STOP 
// este ya lo explicaste
ET_STOP2
ET_CONTINUE


FP_CELL 
// este ya lo explicaste , aunque los de abajo son un poco obvios 
FP_FLOAT
FP_STRING
FP_ARRAY 

solo para hacerlo mas completo pienso yo
En otro momento hago un tutorial de forwards, para no desviarme del tema principal en este thread.
Responder
#8
Muy bueno y si estaria bien un tutorial de forwards..
Responder
#9
Oye Mario Trolleyes

Que buen tutorial!
Aprendi mucho :3
[Imagen: b_350_20_323957_202743_f19a15_111111.png]

Estudia siempre; el tiempo es oro, lo material se puede recuperar pero el tiempo no se puede recuperar.
(02/10/2016, 05:05 PM)meTaLiCroSS escribió: Siempre me gusta ayudar cuando alguien esta interesado realmente en ver que esta programando.
(08/08/2019, 05:32 PM)meTaLiCroSS escribió: grax x el dato cr4ck


Mis aportes

PLUGINS
MAPAS
Menú LANG [SF] Sistema de Frags
Say System (Admin Prefix)
Responder
#10
Nojoda Mario, y yo tratando de entender una tienda basebuilder rusa para hacer un tuto xD

Déjale oportunidad a los nuevos jajjajajaj
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#11
Mario una pregunta,
como hago para que la tienda se le abra solo a los ct
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#12
if (cs_get_user_team(id) == CS_TEAM_CT)

...
Responder
#13
(07/01/2015, 11:07 PM)Mario AR. escribió: if (cs_get_user_team(id) == CS_TEAM_CT)

...

||

if (cs_get_user_team(id) == CS_TEAM_T) return;
Facebook para preguntas/pedidos: Fb.com/scripterfrosst
Responder
#14
ya que comentas para sumar post, te falto agregar que verifique que esté conectado.
Ingeniero agrónomo y desarrollador de Software.

tutoriales-allied
buscas un zp?

"La imitación es la forma más sincera de admiración con la que puede pagar la mediocridad a la grandeza"

Merci Alliedmodders pour m'introduire dans la programmation.
Responder
#15
en esta no seria mas bonito

if (cs_get_user_team(id) = !CS_TEAM_CT)
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#16
?

Estoy seguro que ni vos sabes que estas haciendo
Responder
#17
(07/01/2015, 11:39 PM)Frosst escribió:
(07/01/2015, 11:07 PM)Mario AR. escribió: if (cs_get_user_team(id) == CS_TEAM_CT)

...

||

if (cs_get_user_team(id) == CS_TEAM_T) return;

Nope, si es spec se traspasa esa protección.

(08/01/2015, 12:17 AM)elpapimejor escribió: en esta no seria mas bonito

if (cs_get_user_team(id) = !CS_TEAM_CT)

Eso está mal, y tu pregunta no se relaciona con el tuto, pregunta en scripting Whatever
Responder
#18
Oye mario tengo un problemilla:
Agregue 2 items
la vida y le meti una dual infinity...
me pasa esto, cuando compro la vida me da las 2 cosas : vida y la infinity
como hago para solucionarlo?
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#19
(08/01/2015, 06:51 PM)elpapimejor escribió: Oye mario tengo un problemilla:
Agregue 2 items
la vida y le meti una dual infinity...
me pasa esto, cuando compro la vida me da las 2 cosas : vida y la infinity
como hago para solucionarlo?

Código PHP:
if (item_id != g_item)
        return 
PLUGIN_CONTINUE// Plugin continue: continua la forward. 
Agregaste eso a los 2 subplugins?
Responder
#20
emm nope
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#21
Como puedo hacer para agregar 2 items o más en un mismo plugin?
[Imagen: b_350_20_323957_202743_f19a15_111111.png]

Estudia siempre; el tiempo es oro, lo material se puede recuperar pero el tiempo no se puede recuperar.
(02/10/2016, 05:05 PM)meTaLiCroSS escribió: Siempre me gusta ayudar cuando alguien esta interesado realmente en ver que esta programando.
(08/08/2019, 05:32 PM)meTaLiCroSS escribió: grax x el dato cr4ck


Mis aportes

PLUGINS
MAPAS
Menú LANG [SF] Sistema de Frags
Say System (Admin Prefix)
Responder
#22
.-. Solo agregas una var mas igual que el ejemplo solo lo duplicas, no tiene chiste toto pacman me desepcionas :'v
Responder
#23
(26/04/2016, 01:37 AM)kikizon2 escribió: .-. Solo agregas una var mas igual que el ejemplo solo lo duplicas, no tiene chiste toto pacman me desepcionas :'v

Ya hice eso, muestra el mensaje pero no da lo que yo quiero, un ejemplo sería:
+100 HP $500
+200 HP $1000

Manda el mensaje del item que seleccioné sí, pero no me da la hp del item que seleciono..
[Imagen: b_350_20_323957_202743_f19a15_111111.png]

Estudia siempre; el tiempo es oro, lo material se puede recuperar pero el tiempo no se puede recuperar.
(02/10/2016, 05:05 PM)meTaLiCroSS escribió: Siempre me gusta ayudar cuando alguien esta interesado realmente en ver que esta programando.
(08/08/2019, 05:32 PM)meTaLiCroSS escribió: grax x el dato cr4ck


Mis aportes

PLUGINS
MAPAS
Menú LANG [SF] Sistema de Frags
Say System (Admin Prefix)
Responder
#24
Oye Mario, ando con un problemita, agregue un arma a la tienda, pero cada vez que la trato de comprar me dice no puedes comprarlo ahora
Código PHP:
// Aclaro: uso el estilo 0 de las natives porque me parece más cómodo
// Usar el estilo 0 o 1 es a gusto del cliente.
public native_register(pluginparams)
{
    
// La native tendrá esta estructura:
    // tienda_registrar(nombre[], precio)
    
new szNombre[32];
    
get_string(1szNombrecharsmax(szNombre));

    
ArrayPushString(g_item_nameszNombre); // Guardamos el nombre
    
ArrayPushCell(g_item_costget_param(2)); // Guardamos el costo

    
g_items_count++; // Incrementamos en 1 el contador de ítems.

    
return g_items_count// Retornamos el contador que servirá como un ID para el ítem. 
    // Un detalle: Al usar ArrayGetString/Cell, usaremos un número que es 1 menos que el ID del ítem.
    // ¿Por qué? Porque no es apropiado enviar un ID 0, por eso el primer ID será 1 y le corresponde el número 0 en las arrays dinámicas.
}

public 
clcmd_shop(id)
{
    new 
menu menu_create("\r[ZE]\y Armas Reset""menu_shop");
    new 
szItem[50], lenbool:canbuycost;

    for (new 
0g_items_counti++)
    {
        
// Agregamos el costo
        
cost ArrayGetCell(g_item_costi);
        
canbuy = (kReset[id] >= cost) ? true false;//Cambialo por tu variable g_reset..

        
len formatex(szItemcharsmax(szItem), "\%c[Reset %d]\%c "canbuy 'y' 'r'costcanbuy 'w' 'd');

        
// Ahora el nombre del item
        
ArrayGetString(g_item_nameiszItem[len], charsmax(szItem)-len);

        
menu_additem(menuszItem, .callback canbuy ? -g_callback/*Si no puede comprar, llamamos al callback para desactivar el ítem*/); 
    }

    
// Esto es solo estético
    
menu_setprop(menuMPROP_EXITNAME"\ySalir");
    
menu_setprop(menuMPROP_BACKNAME"Anterior");
    
menu_setprop(menuMPROP_NEXTNAME"Siguiente");

    
menu_display(idmenu);
}

public 
menu_shop_cb(idmenuitem)
{
    
// Este callback sólo se llama cuando no alcanza el dinero...
    
return ITEM_DISABLED;
}

public 
menu_shop(idmenuitem)
{
    if (!
is_user_connected(id) || !(<= item g_items_count) || g_zombie[id] || g_hm_special[id] > 0)
    {
        
menu_destroy(menu);
        return 
PLUGIN_HANDLED;
    }

    
// Primero comprobamos que el usuario tenga dinero suficiente.
    
new cost ArrayGetCell(g_item_costitem);
    new 
money kReset[id];
    if (
money >= cost)
    {
        
// Estamos listos, ahora avisaremos al subplugin que se quiere comprar el ítem
        // Aquí entra el trabajo de las forwards.
        
new ret// Una variable para almacenar el valor de retorno
        
ExecuteForward(forward_itemselectedretiditem+1);
        
// Como explique anteriormente, el ID del ítem es 1 unidad más que el número en los arrays y el menú.


        // Supongamos que tengo un subplugin que da un arma, pero qué pasa si lo compro mientras estoy muerto (por imbécil o por accidente).
        // El subplugin debe comprobar si el jugador está en condición de comprar el ítem.
        // Para eso es el valor de retorno, si el subplugin comprueba que no puedo comprar, debe retornar PLUGIN_HANDLED.

        
if (ret == PLUGIN_HANDLED// No puede comprar
        
client_print(idprint_chat"No puedes comprarlo ahora.");
        else 
// Se ha entregado el ítem, a cobrar!
        
{
            new 
szItemName[32];
            
ArrayGetString(g_item_nameitemszItemNamecharsmax(szItemName));
            
client_print(idprint_chat"Has comprado: %s"szItemName);
        }
    }
    else
    
client_print(idprint_chat"No tienes el Reset Necesario.");

    
menu_destroy(menu);
    return 
PLUGIN_HANDLED;

Asi tengo la tienda

Código PHP:
// En el init
    
g_item tienda_registrar(NAME_EXTRA_ITEMSCOST_EXTRA_ITEMS)

public 
tienda_item_seleccionado(iditemid)
{
    if(
itemid != g_item)
        return

    
give_item(id)
}

public 
give_item(id)
{
    
drop_weapons(id1)
    new 
iWeapon fm_give_item(idweapon_base_buffer)
    if(
iWeapon 0)
    {
        
cs_set_weapon_ammo(iWeaponget_pcvar_num(cvar_clip))
        
cs_set_user_bpammo(idCSW_BASEget_pcvar_num(cvar_ammo))
        
emit_sound(idCHAN_ITEM"items/gunpickup2.wav"VOL_NORMATTN_NORM,0,PITCH_NORM)
        
        
set_weapon_anim(idANIM_DRAW)
        
set_pdata_float(idm_flNextAttackDRAW_TIMEOFFSET_LINUX)
        
        
set_weapon_list(idweapon_name_buffer)
        
set_pdata_string(id, (492) * 4ANIMEXT, -20)
        
set_pdata_int(iWeapon74MODE_A)
    }
    
    
g_has_weapon[id] = true
    g_Mode
[id] = MODE_A
    remove_bitvar
(id)

Y asi el arma
[Imagen: EvoLogo.png.fbcccbc49fb32e6a4bf8f5e72d80c317.png]
nalgas

(03/08/2018, 03:13 PM)Skylar escribió: Está bien que pidas ayudas, pero no para que crees 20 post todos los días mogolico de mierda, me tenes re podrido ya, contraté 10000 sicarios para que te busquen y te maten toda la familia, y a vos que te revienten con una bazooka.
Responder
#25
Como cuando soy bien noob y no entiendo nada de esto...

Tengo los sma de unas armas portadas del zp para ponerlos en el CTF y que se compren con adrenalina y no he logrado hacerlo (repito, soy noob)

Por cierto, los editores que conseguí, tampoco saben Considered
Responder


Salto de foro:


Usuarios navegando en este tema: 1 invitado(s)