Hola, bueno como dice el titulo yo vengo a enseñarles o darles una idea/guía/tutorial de como ustedes pueden crear sus propios extra items por niveles en el mismo menú de extra items, bueno, para comenzar, ESTE TUTORIAL/GUÍA ES PARA LA VERSIÓN 4.3/ADVANCE
Para Comenzar, debemos ir a:
y agregaremos una nueva array para los niveles:
Ahora, hiriamos a
y creamos la array:
Ahora con nuestra Array ya creada, nos dirigimos directamente al menú de extra items:
y cambiamos lo siguiente:
por
---->
nos quedaría así:
Luego nos vamos a la siguiente línea para bloquear el item, si NO cumple los requisitos.
Y reemplazamos:
por
----->
(Aquí es donde bloqueamos si el nivel o ammopacks no cumplen los requisitos del extra item)
Nos quedaría asi:
Luego nos dirigimos a la native de extra items
OJO! este paso es muy importante, aquí realizamos la conexión del item con el plugin de ZP, así que si anotan mal algo, no les funcionara y posiblemente un bug gigante.
y cambiamos:
por
---->
agregamos nos niveles.
Ahora reemplazamos esto:
por
---->
Ahora nos dirigimos a zombieplague.inc IMPORTANTE
y reemplazamos:
por
---->
Ahora para FINALIZAR. Les enseñare como deben registrar el extra item,
que es de la siguiente manera:
--->
Lo que traducimos a:
--->
No se olviden de nada!, si me falto solo díganme. Cada paso es IMPORTANTE
Así terminaría esta Guía/Tutorial de como crear Extra Items por nivel utilizando (NATIVES)
Para Comenzar, debemos ir a:
Código PHP:
new Array:g_extraitem_name // caption
new Array:g_extraitem_cost // cost
new Array:g_extraitem_team // team
new g_extraitem_i // loaded extra items counter
y agregaremos una nueva array para los niveles:
Código PHP:
new Array:g_extraitem_name // caption
new Array:g_extraitem_cost // cost
new Array:g_extraitem_team // team
new Array:g_extraitem_lvl // Nivel | Es nuestra array de nivel, IMPORTANTE
new g_extraitem_i // loaded extra items counter
Ahora, hiriamos a
Código PHP:
public plugin_precache()
{
// debajo de
g_extraitem_cost = ArrayCreate(1, 1)
y creamos la array:
Código PHP:
/*Importante!!!*/
g_extraitem_lvl = ArrayCreate(1, 1) //Registramos la Array de nivel que utilizaremos
Ahora con nuestra Array ya creada, nos dirigimos directamente al menú de extra items:
Código PHP:
show_menu_extras(id)
{
// Player dead?
if (!g_isalive[id])
return;
static menuid, menu[128], item, team, buffer[32]
// Title
formatex(menu, charsmax(menu), "%L [%L]\r", id, "MENU_EXTRA_TITLE", id, g_zombie[id] ? g_nemesis[id] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[id] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
menuid = menu_create(menu, "menu_extras")
// Item List
for (item = 0; item < g_extraitem_i; item++)
{
// Retrieve item's team
team = ArrayGetCell(g_extraitem_team, item)
// Item not available to player's team/class
if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
continue;
// Check if it's one of the hardcoded items, check availability, set translated caption
switch (item)
{
case EXTRA_NVISION:
{
if (!get_pcvar_num(cvar_extranvision)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
}
case EXTRA_ANTIDOTE:
{
if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
}
case EXTRA_MADNESS:
{
if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
}
case EXTRA_INFBOMB:
{
if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
}
default:
{
if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
}
}
// Add Item Name and Cost
/*Aquí es donde cambiara el MENU, para mostrar de un
color distinto y el nivel de item, cuando no cumplimos requisitos*/
formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
buffer[0] = item
buffer[1] = 0
menu_additem(menuid, menu, buffer)
}
// No items to display?
if (menu_items(menuid) <= 0)
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
menu_destroy(menuid)
return;
}
// Back - Next - Exit
formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
menu_setprop(menuid, MPROP_BACKNAME, menu)
formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
menu_setprop(menuid, MPROP_NEXTNAME, menu)
formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
menu_setprop(menuid, MPROP_EXITNAME, menu)
// If remembered page is greater than number of pages, clamp down the value
MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
// Fix for AMXX custom menus
if (pev_valid(id) == PDATA_SAFE)
set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
menu_display(id, menuid, MENU_PAGE_EXTRAS)
}
y cambiamos lo siguiente:
Código PHP:
formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
por
---->
Código PHP:
if (g_level[id] < ArrayGetCell(g_extraitem_lvl, item)) // Aqui es donde chequeamos si el nivel que le dimos al extra item es menor al nivel que tiene el jugador actualmente
formatex(menu, charsmax(menu), "\d%s [Nivel: \r%d\d]", buffer, ArrayGetCell(g_extraitem_lvl, item)) // Lo bloqueamos
else // Aqui es donde chequeamos si el nivel que le dimos al extraitem es mayor o igual al nivel que tiene el jugador actualmente
formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2") // Si el Jugador Cumple los requisitos de nivel, se le mostrara la información normal del item (Nombre, AmmoPacks)
nos quedaría así:
Código PHP:
show_menu_extras(id)
{
// Player dead?
if (!g_isalive[id])
return;
static menuid, menu[128], item, team, buffer[32]
// Title
formatex(menu, charsmax(menu), "%L [%L]\r", id, "MENU_EXTRA_TITLE", id, g_zombie[id] ? g_nemesis[id] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[id] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
menuid = menu_create(menu, "menu_extras")
// Item List
for (item = 0; item < g_extraitem_i; item++)
{
// Retrieve item's team
team = ArrayGetCell(g_extraitem_team, item)
// Item not available to player's team/class
if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
continue;
// Check if it's one of the hardcoded items, check availability, set translated caption
switch (item)
{
case EXTRA_NVISION:
{
if (!get_pcvar_num(cvar_extranvision)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
}
case EXTRA_ANTIDOTE:
{
if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
}
case EXTRA_MADNESS:
{
if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
}
case EXTRA_INFBOMB:
{
if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
}
default:
{
if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
}
}
// Add Item Name and Cost
if (g_level[id] < ArrayGetCell(g_extraitem_lvl, item)) // Si el nivel es mejor al nivel que obtenemos de la Array de nivel
formatex(menu, charsmax(menu), "\d%s [Nivel: \r%d\d]", buffer, ArrayGetCell(g_extraitem_lvl, item)) // Esta información aparecerá si el usuario no cumple con la condición de nivel.
else
formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2") // Si el usuario cumple con la condición de nivel mostraremos normalmente el nombre del item y su precio
buffer[0] = item
buffer[1] = 0
menu_additem(menuid, menu, buffer)
}
// No items to display?
if (menu_items(menuid) <= 0)
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
menu_destroy(menuid)
return;
}
// Back - Next - Exit
formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
menu_setprop(menuid, MPROP_BACKNAME, menu)
formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
menu_setprop(menuid, MPROP_NEXTNAME, menu)
formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
menu_setprop(menuid, MPROP_EXITNAME, menu)
// If remembered page is greater than number of pages, clamp down the value
MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
// Fix for AMXX custom menus
if (pev_valid(id) == PDATA_SAFE)
set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
menu_display(id, menuid, MENU_PAGE_EXTRAS)
}
Luego nos vamos a la siguiente línea para bloquear el item, si NO cumple los requisitos.
Código PHP:
buy_extra_item(id, itemid, ignorecost = 0) // Este public es cuando seleccionamos el item
Y reemplazamos:
Código PHP:
if (!ignorecost)
{
// Check that we have enough ammo packs
if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
return;
}
// Deduce item cost
g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
}
por
----->
Código PHP:
if (!ignorecost)
{
// Check that we have level required and enough ammopacks
/*Si el nivel es mejor al obtenido de la array (<)
le damos un print diciéndole que no cumple requisitos*/
if (g_level[id] < ArrayGetCell(g_extraitem_lvl, itemid) || g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
{
zp_colored_print(id, "^x04[ZP]^x01 Comando no disponible.")
show_menu_extras(id) // Volvemos a cargar el menú de extra items.
return; // return para que no continúe ninguna otra función
}
/*En el caso de que el jugador cumpla el nivel, le restamos los ammopacks correspondientes*/
g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
}
(Aquí es donde bloqueamos si el nivel o ammopacks no cumplen los requisitos del extra item)
Nos quedaría asi:
Código PHP:
buy_extra_item(id, itemid, ignorecost = 0)
{
// Retrieve item's team
static team
team = ArrayGetCell(g_extraitem_team, itemid)
// Check for team/class specific items
if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
return;
}
// Check for unavailable items
if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
|| (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
|| (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
|| (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
|| (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
return;
}
// Check for hard coded items with special conditions
if ((itemid == EXTRA_ANTIDOTE && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround || fnGetZombies() <= 1 || (get_pcvar_num(cvar_deathmatch) && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() == 1)))
|| (itemid == EXTRA_MADNESS && g_nodamage[id]) || (itemid == EXTRA_INFBOMB && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround)))
{
zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_CANTUSE")
return;
}
if (!ignorecost)
{
// Check that we have level required and enough ammopacks
/*Detectamos si el usuario no cumple los requisitos y damos un print diciéndole que no tiene acceso aún*/
if (g_level[id] < ArrayGetCell(g_extraitem_lvl, itemid) || g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
{
zp_colored_print(id, "^x04[ZP]^x01 Comando no disponible.") // Mensaje
show_menu_extras(id) // Volvemos a Cargar el menú
return; // return para que no se ejecute ninguna otra función
}
g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
}
// Check which kind of item we're buying
switch (itemid)
{
case EXTRA_NVISION: // Night Vision
{
g_nvision[id] = true
if (!g_isbot[id])
{
g_nvisionenabled[id] = true
// Custom nvg?
if (get_pcvar_num(cvar_customnvg))
{
remove_task(id+TASK_NVISION)
set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
}
else
set_user_gnvision(id, 1)
}
else
cs_set_user_nvg(id, 1)
}
case EXTRA_ANTIDOTE: // Antidote
{
// Increase antidote purchase count for this round
g_antidotecounter++
humanme(id, 0, 0)
}
case EXTRA_MADNESS: // Zombie Madness
{
// Increase madness purchase count for this round
g_madnesscounter++
g_nodamage[id] = true
set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
static sound[64]
ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
}
case EXTRA_INFBOMB: // Infection Bomb
{
// Increase infection bomb purchase count for this round
g_infbombcounter++
// Already own one
if (user_has_weapon(id, CSW_HEGRENADE))
{
// Increase BP ammo on it instead
cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
// Flash ammo in hud
message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
write_byte(1) // ammo amount
message_end()
// Play clip purchase sound
emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
return; // stop here
}
// Give weapon to the player
fm_give_item(id, "weapon_hegrenade")
}
default:
{
if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
{
// Get weapon's id and name
static weaponid, wname[32]
ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
weaponid = cs_weapon_name_to_id(wname)
// If we are giving a primary/secondary weapon
if (MAXBPAMMO[weaponid] > 2)
{
// Make user drop the previous one
if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
drop_weapons(id, 1)
else
drop_weapons(id, 2)
// Give full BP ammo for the new one
ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
}
// If we are giving a grenade which the user already owns
else if (user_has_weapon(id, weaponid))
{
// Increase BP ammo on it instead
cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
// Flash ammo in hud
message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
write_byte(AMMOID[weaponid]) // ammo id
write_byte(1) // ammo amount
message_end()
// Play clip purchase sound
emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
return; // stop here
}
// Give weapon to the player
fm_give_item(id, wname)
}
else // Custom additions
{
// Item selected forward
ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
// Item purchase blocked, restore buyer's ammo packs
if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
}
}
}
}
Luego nos dirigimos a la native de extra items
OJO! este paso es muy importante, aquí realizamos la conexión del item con el plugin de ZP, así que si anotan mal algo, no les funcionara y posiblemente un bug gigante.
Código PHP:
public native_register_extra_item(const name[], cost, team)
{
// ZP disabled
if (!g_pluginenabled)
return -1;
// Strings passed byref
param_convert(1)
// Arrays not yet initialized
if (!g_arrays_created)
{
log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item yet (%s)", name)
return -1;
}
if (strlen(name) < 1)
{
log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item with an empty name")
return -1;
}
new index, extraitem_name[32]
for (index = 0; index < g_extraitem_i; index++)
{
ArrayGetString(g_extraitem_name, index, extraitem_name, charsmax(extraitem_name))
if (equali(name, extraitem_name))
{
log_error(AMX_ERR_NATIVE, "[ZP] Extra item already registered (%s)", name)
return -1;
}
}
// For backwards compatibility
if (team == ZP_TEAM_ANY)
team = (ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN)
// Add the item
ArrayPushString(g_extraitem_name, name)
ArrayPushCell(g_extraitem_cost, cost)
ArrayPushCell(g_extraitem_team, team)
// Set temporary new item flag
ArrayPushCell(g_extraitem_new, 1)
// Override extra items data with our customizations
new i, buffer[32], size = ArraySize(g_extraitem2_realname)
for (i = 0; i < size; i++)
{
ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
// Check if this is the intended item to override
if (!equal(name, buffer))
continue;
// Remove new item flag
ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
// Replace caption
ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
// Replace cost
buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
// Replace team
buffer[0] = ArrayGetCell(g_extraitem2_team, i)
ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
}
// Increase registered items counter
g_extraitem_i++
// Return id under which we registered the item
return g_extraitem_i-1;
}
y cambiamos:
Código PHP:
public native_register_extra_item(const name[], cost, team)
por
---->
Código PHP:
public native_register_extra_item(const name[], lvl, cost, team) // Agregamos la constante de nivel para el extra item, muy importante
agregamos nos niveles.
Ahora reemplazamos esto:
Código PHP:
ArrayPushString(g_extraitem_name, name)
ArrayPushCell(g_extraitem_cost, cost)
ArrayPushCell(g_extraitem_team, team)
por
---->
Código PHP:
ArrayPushString(g_extraitem_name, name)
ArrayPushCell(g_extraitem_lvl, lvl) // Obtenemos un valor 'x' de la constante 'lvl' que tendra el item, y ese valor será el que determinará si el nivel que tiene el jugador corresponde al del item para detectar si lo deja disponible o bloqueado en el menú
ArrayPushCell(g_extraitem_cost, cost)
ArrayPushCell(g_extraitem_team, team)
Ahora nos dirigimos a zombieplague.inc IMPORTANTE
y reemplazamos:
Código PHP:
native zp_register_extra_item(const name[], cost, teams)
por
---->
Código PHP:
/*Agregamos la constante de nivel para poder registrar bien el extra item*/
native zp_register_extra_item(const name[], lvl, cost, teams) // Ahora podremos registrar el item con niveles.
Ahora para FINALIZAR. Les enseñare como deben registrar el extra item,
que es de la siguiente manera:
--->
Código PHP:
g_item = zp_register_extra_item("nombre", nivel, costo, equipo)
Lo que traducimos a:
--->
Código PHP:
/*Aquí es cuando conectamos el item que queremos con el plugin del ZP definiendo el nombre, nivel, valor, team*/
g_item = zp_register_extra_item("Super M4A1", 5, 100, ZP_TEAM_HUMAN)
No se olviden de nada!, si me falto solo díganme. Cada paso es IMPORTANTE
Así terminaría esta Guía/Tutorial de como crear Extra Items por nivel utilizando (NATIVES)
Party Time! , Saludos.
(ZP Assassin) 100% | 72% (Optimizando)
(ZP Assassin) 100% | 72% (Optimizando)