L 11/28/2021 - 19:08:11: Invalid index -4 (count: 15)
L 11/28/2021 - 19:08:11: [AMXX] Displaying debug trace (plugin "ze_bonus_manager.amxx", version "1.2")
L 11/28/2021 - 19:08:11: [AMXX] Run time error 10: native error (native "ArrayGetCell")
L 11/28/2021 - 19:08:11: [AMXX] [0] ze_bonus_manager.sma::Handler_Bonus (line 289)
Code: Select all
#include <zombie_escape>
#include <ze_levels>
// Settings file.
new const g_szSettingsFile[] = "ze_bonus.ini"
// Enums.
enum
{
ENABLE_DISABLE = 0,
ENABLE_ALWAYS,
ENABLE_COOLDOWN,
ENABLE_MAXTIMES,
ENABLE_ONCEROUND,
ENABLE_ONCEMAP
}
// Dynamic Arrays.
new Array:g_szBonusName,
Array:g_szBonusHandler,
Array:g_szBonusPlugin,
Array:g_iBonusReqLevel,
Array:g_szPlayerAuthID
// Cvars Variables.
new g_pCvarEnableType,
g_pCvarCooldown,
g_pCvarMaxTimes
// Global Variables.
new g_iBonusCount,
g_iMaxTimes[MAX_CLIENTS+1],
Float:g_flCooldownTime[MAX_CLIENTS+1],
g_iBounsType[MAX_CLIENTS+1]
// Forward called after server activation.
public plugin_init()
{
// Load plugin.
register_plugin("[ZE] Bonus Manager", "1.2", "z0h1r-LK")
// Events.
register_event("HLTV", "Event_NewRound", "a", "1=0", "2=0")
// Cvars.
g_pCvarEnableType = register_cvar("ze_bonus_enable", "5")
g_pCvarCooldown = register_cvar("ze_bonus_cooldown", "60")
g_pCvarMaxTimes = register_cvar("ze_bonus_maxtimes", "1")
// Client command(s).
register_clcmd("say", "clcmd_SayText")
register_clcmd("say_team", "clcmd_SayText")
// Initialize dynamic arrays
g_szBonusPlugin = ArrayCreate(128) // File name.
g_szPlayerAuthID = ArrayCreate(35)
g_szBonusHandler = ArrayCreate(32)
g_szBonusName = ArrayCreate(32)
g_iBonusReqLevel = ArrayCreate(1)
// Default Values.
arrayset(g_iMaxTimes, 1, sizeof(g_iMaxTimes))
}
// Forward allows registering natives.
public plugin_natives()
{
register_native("ze_bonus_register", "_native_ze_bonus_register", 0)
register_native("ze_bonus_get_name", "_native_ze_bonus_get_name", 0)
register_native("ze_bonus_get_id", "_native_ze_bonus_get_id", 0)
register_native("ze_bonus_get_reqlevel", "_native_ze_bonus_get_reqlevel", 0)
register_native("ze_open_bonus_menu", "_native_ze_open_bonus_menu", 1)
}
// Forward called before server deactivation or plugin fail.
public plugin_end()
{
// Destroy (remove) all dynamic arrays.
ArrayDestroy(g_szPlayerAuthID)
}
// Forward called after player join server.
public client_putinserver(iPlayer)
{
// Bonus Menu is once time in map (Fix enable menu after player reconnect or retry).
if (get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEMAP)
{
// Variables.
new szDynArr[35], szAuthID[35], iNum
// Get Auth ID of player (Valve ID or Steam ID).
get_user_authid(iPlayer, szAuthID, charsmax(szAuthID))
// Check from authid player is already in dynamic array.
for (iNum = 0; iNum < ArraySize(g_szPlayerAuthID); iNum++)
{
// Get Auth ID's from dynamic array.
ArrayGetString(g_szPlayerAuthID, iNum, szDynArr, charsmax(szDynArr))
// We find Auth ID of player, So, Him is already use a bonus menu.
if (equali(szAuthID, szDynArr))
{
g_iMaxTimes[iPlayer] = 0 // Suspende the menu on player.
break; // Stop finding for Auth ID in dynamic array.
}
}
}
if (g_iMaxTimes[iPlayer])
{
g_iBounsType[iPlayer] = -1;
}
}
// Hook called every new round.
public Event_NewRound()
{
// Re-enable getting bonus.
if ((get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEROUND))
{
// Re-enable the bonus menu for all players.
arrayset(g_iMaxTimes, 1, sizeof(g_iMaxTimes))
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_MAXTIMES) // Reset maximum times for all players.
{
// Re-enable the bonus menu for all players.
arrayset(g_iMaxTimes, get_pcvar_num(g_pCvarMaxTimes), sizeof(g_iMaxTimes))
}
}
public ze_user_humanized(id)
{
if (g_iBounsType[id] >= 0)
{
set_task(1.0, "DelayReset", id)
}
}
public DelayReset(id)
{
ReGive(id, g_iBounsType[id])
}
// Hook called when sent any message in say/say_team.
public clcmd_SayText(iPlayer)
{
// Bonus menu is disabled.
if (!get_pcvar_num(g_pCvarEnableType))
return;
// Read arguments from say and say_team commands (Message).
static szArgs[32]
read_args(szArgs, charsmax(szArgs))
remove_quotes(szArgs) // Remove quotes from message "Hi!".
// Check the player is trying open the bonus menu.
if (equali(szArgs, ".bonus") || equali(szArgs, "/bonus") || equali(szArgs, "!bonus"))
{
// Player is a zombie.
if (ze_is_user_zombie(iPlayer))
{
// Alert a player!
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_ISZOMBIE")
return;
}
// Player is not a alive.
if (!is_user_alive(iPlayer))
{
// Alert a player!
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_NOTALIVE")
return;
}
// Enable type is once round, So, Player is already use bonus menu.
if (get_pcvar_num(g_pCvarEnableType) == ENABLE_ALWAYS)
{
// Menu without limit.
if (!g_iMaxTimes[iPlayer])
g_iMaxTimes[iPlayer] = 1
}
else if ((get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEROUND) && !g_iMaxTimes[iPlayer])
{
// Alert a player!
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_NEXTROUND")
return;
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_COOLDOWN) // Enable type is cooldown
{
// Get a game (halflife) time.
new Float:flGameTime = get_gametime()
// Alert a player, Cooldown time is not over.
if (flGameTime < g_flCooldownTime[iPlayer])
{
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_COOLDOWN", floatround(g_flCooldownTime[iPlayer] - flGameTime))
return;
}
// Re-enable bonus menu for player.
g_iMaxTimes[iPlayer] = 1
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEMAP) // Enable type is once time in map.
{
// Player is open bonus menu.
if (!g_iMaxTimes[iPlayer])
{
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_ONCETIME")
return;
}
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_MAXTIMES) // Enable type is maximum times.
{
// Player can't open bonus menu, Because is reached maximum times.
if (!g_iMaxTimes[iPlayer])
{
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_MAXTIME")
return;
}
}
// Open the bonus menu for player.
Menu_Bonus(iPlayer)
}
}
public Menu_Bonus(iPlayer)
{
new szLang[64], szName[32], iLevelPlr, iLevelReq, iNum, iMenu
// Get current Level of the player.
iLevelPlr = ze_get_user_level(iPlayer)
// Create a new menu with title.
formatex(szLang, charsmax(szLang), "\r%L:", LANG_PLAYER, "MENU_TITLE_BONUS", iLevelPlr)
iMenu = menu_create(szLang, "Handler_Bonus")
// Add all bonus name to menu.
for (iNum = 0; iNum < g_iBonusCount; iNum++)
{
// Get name of bonus from dynamic array.
ArrayGetString(g_szBonusName, iNum, szName, charsmax(szName))
// Get a required level to get the bonus.
iLevelReq = ArrayGetCell(g_iBonusReqLevel, iNum)
// Sort names in menu.
if (iLevelReq == 0)
formatex(szLang, charsmax(szLang), "\w%s - \r%L", szName, LANG_PLAYER, "FREE")
else if (iLevelPlr < iLevelReq)
formatex(szLang, charsmax(szLang), "\d%s - \r[%d %L]", szName, iLevelReq, LANG_PLAYER, "LVL")
else
formatex(szLang, charsmax(szLang), "\y%s - \r%L", szName, LANG_PLAYER, "UNLOCKED")
// Add bonus name to menu.
menu_additem(iMenu, szLang, "", 0)
}
// Set menu property (exit, back, next).
formatex(szLang, charsmax(szLang), "\y%L", LANG_PLAYER, "NEXT")
menu_setprop(iMenu, MPROP_NEXTNAME, szLang)
formatex(szLang, charsmax(szLang), "\y%L", LANG_PLAYER, "BACK")
menu_setprop(iMenu, MPROP_BACKNAME, szLang)
formatex(szLang, charsmax(szLang), "\y%L", LANG_PLAYER, "EXIT")
menu_setprop(iMenu, MPROP_EXITNAME, szLang)
// Display menu for player and close menu after 30s.
menu_display(iPlayer, iMenu, 0, 30)
}
// Hook handle command from bonus menu.
public Handler_Bonus(iPlayer, iMenu, iKey)
{
// Close and destroy menu.
if (iKey == MENU_EXIT)
{
// Destroy (remove) menu.
menu_destroy(iMenu)
return PLUGIN_HANDLED;
}
// Variables.
new szName[32], szHandler[32], szPlugin[128], iLevelPlr, iLevelReq
// Get current Level of player.
iLevelPlr = ze_get_user_level(iPlayer)
// Get a required Level to get the bonus.
iLevelReq = ArrayGetCell(g_iBonusReqLevel, iKey)
// Check the player is not getting a bonus yet.
if (g_iMaxTimes[iPlayer])
{
// The player's level is greater than the required level (Getting a bonus).
if (iLevelPlr >= iLevelReq)
{
// Get bonus name from dynamic array.
ArrayGetString(g_szBonusName, iKey, szName, charsmax(szName))
// Get bonus handler function from dynamic array.
ArrayGetString(g_szBonusHandler, iKey, szHandler, charsmax(szHandler))
// Get bonus plugin filename from dynamic array.
ArrayGetString(g_szBonusPlugin, iKey, szPlugin, charsmax(szPlugin))
// Call a function in plugin of the bonus
new iRet = callfunc_begin(szHandler, szPlugin)
// Handler function is not found in plugin of bonus.
if (iRet == -1)
{
log_error(AMX_ERR_NOTFOUND, "[AMX] Function (%s) not found in plugin (%s)", szHandler, szPlugin)
return PLUGIN_HANDLED;
}
// Plugin file is not found.
if (iRet == -2)
{
log_error(AMX_ERR_NOTFOUND, "[AMX] Plugin (%s) is not found.", szPlugin)
return PLUGIN_HANDLED;
}
callfunc_push_int(iPlayer) // Add Player ID to handler function.
callfunc_push_int(iKey) // Add Bonus ID to handler function.
callfunc_end()
g_iBounsType[iPlayer] = iKey
// Sent colored message in chat, (claiming bonus msg).
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_DONE", szName)
// Player has taken the bonus.
if (get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEROUND)
{
// Player has claim some bonus from menu.
--g_iMaxTimes[iPlayer]
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_COOLDOWN)
{
// Make a cooldown time for bonus menu on player.
g_flCooldownTime[iPlayer] = get_gametime() + get_pcvar_float(g_pCvarCooldown)
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_ONCEMAP) // That for Fix problem enable menu when player reconnect or retry.
{
// Get auth ID of player.
new szAuthID[35]
get_user_authid(iPlayer, szAuthID, charsmax(szAuthID))
// Push AuthID of player in dynamic array.
ArrayPushString(g_szPlayerAuthID, szAuthID)
// Bonus has claimed.
--g_iMaxTimes[iPlayer]
}
else if (get_pcvar_num(g_pCvarEnableType) == ENABLE_MAXTIMES) // Max times in every round.
{
--g_iMaxTimes[iPlayer]
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_REMTIMES", g_iMaxTimes[iPlayer])
}
}
else // Player haven't Level enough.
{
Menu_Bonus(iPlayer)
ze_colored_print(iPlayer, "%L", LANG_PLAYER, "BONUS_LEVEL_ENOUGH")
}
}
// Destroy (remove) menu.
menu_destroy(iMenu)
return PLUGIN_HANDLED;
}
public ReGive(iPlayer, iKey)
{
new szName[32], szHandler[32], szPlugin[128]
// Get bonus name from dynamic array.
ArrayGetString(g_szBonusName, iKey, szName, charsmax(szName))
// Get bonus handler function from dynamic array.
ArrayGetString(g_szBonusHandler, iKey, szHandler, charsmax(szHandler))
// Get bonus plugin filename from dynamic array.
ArrayGetString(g_szBonusPlugin, iKey, szPlugin, charsmax(szPlugin))
if (equal(szHandler, "Handler_PlusTenArmor") || equal(szHandler, "Handler_PlusTenSpeed") || equal(szHandler, "Handler_PlusDamage") || equal(szHandler, "Handler_PlusTenHealth200") || equal(szHandler, "Handler_PlusTenHealth10k") || equal(szHandler, "Handler_PlusTenSpeed30") || equal(szHandler, "Handler_PlusTenArmor100"))
{
// Call a function in plugin of the bonus
new iRet = callfunc_begin(szHandler, szPlugin)
// Handler function is not found in plugin of bonus.
if (iRet == -1)
{
log_error(AMX_ERR_NOTFOUND, "[AMX] Function (%s) not found in plugin (%s)", szHandler, szPlugin)
return PLUGIN_HANDLED;
}
// Plugin file is not found.
if (iRet == -2)
{
log_error(AMX_ERR_NOTFOUND, "[AMX] Plugin (%s) is not found.", szPlugin)
return PLUGIN_HANDLED;
}
callfunc_push_int(iPlayer) // Add Player ID to handler function.
callfunc_push_int(iKey) // Add Bonus ID to handler function.
callfunc_end()
}
return PLUGIN_HANDLED;
}
// Functions of natives.
public _native_ze_bonus_register(iPlugin_iIndex, iParam_iNum)
{
new szName[32], szHandler[32], szPlugin[128], iReqLevel
get_string(1, szName, charsmax(szName)) // Get name of bonus.
get_string(2, szHandler, charsmax(szHandler)) // Get handler function of bonus.
iReqLevel = get_param(3) // Get require level.
// Bonus without name.
if (strlen(szName) < 0)
{
log_error(AMX_ERR_NATIVE, "[AMX] Bonus without name.")
return INVALID_HANDLE;
}
// Bonus without handler.
if (strlen(szHandler) < 0)
{
log_error(AMX_ERR_NATIVE, "[AMX] Bonus without handler.")
return INVALID_HANDLE;
}
// Get plugin name.
get_plugin(iPlugin_iIndex, szPlugin, charsmax(szPlugin))
// Bonus name is already registered
new szDynArr[32], iIndex
for (iIndex = 0; iIndex < g_iBonusCount; iIndex++)
{
// Get bonus name from dynamic array.
ArrayGetString(g_szBonusName, iIndex, szDynArr, charsmax(szDynArr))
if (equali(szDynArr, szName))
{
log_error(AMX_ERR_NATIVE, "[AMX] Bonus name already is registered.")
return INVALID_HANDLE;
}
}
// Load bonus data's from external file.
if (!amx_load_setting_string(g_szSettingsFile, szName, "NAME", szName, charsmax(szName)))
{
amx_save_setting_string(g_szSettingsFile, szName, "NAME", szName)
}
if (!amx_load_setting_int(g_szSettingsFile, szName, "LEVEL", iReqLevel))
{
amx_save_setting_int(g_szSettingsFile, szName, "LEVEL", iReqLevel)
}
// Register new bonus.
g_iBonusCount++
ArrayPushString(g_szBonusName, szName)
ArrayPushString(g_szBonusHandler, szHandler)
ArrayPushString(g_szBonusPlugin, szPlugin)
ArrayPushCell(g_iBonusReqLevel, iReqLevel)
return g_iBonusCount - 1
}
public _native_ze_bonus_get_name(iPlugin_iIndex, iParam_iNum)
{
// Get a bonus ID.
new iBonus = get_param(1)
// Invalid bonus.
if (iBonus > g_iBonusCount)
{
log_error(AMX_ERR_NATIVE, "[AMX] Bonus id is not found (%d)", iBonus)
return 0;
}
new szName[32]
// Get name of bonus.
ArrayGetString(g_szBonusName, iBonus, szName, charsmax(szName))
// Store name in array.
set_string(2, szName, get_param(3))
return 1;
}
public _native_ze_bonus_get_id(iPlugin_iIndex, iParam_iNum)
{
// Get a bonus name
new szName[32]
get_string(1, szName, charsmax(szName))
// Find for bonus id by name.
new szCheck[32], iIndex
for (iIndex = 0; iIndex < g_iBonusCount; iIndex++)
{
// Get bonus name from dynamic array.
ArrayGetString(g_szBonusName, iIndex, szCheck, charsmax(szCheck))
// Return bonus ID
if (equal(szName, szCheck))
{
return iIndex
}
}
// Doesn't find bonus, Invalid bonus.
return INVALID_HANDLE
}
public _native_ze_bonus_get_reqlevel(iPlugin_iIndex, iParam_iNum)
{
// Get a bonus name
new szName[32]
get_string(2, szName, charsmax(szName))
// Get required level by bonus name.
if (strlen(szName) < 1)
{
// Find for bonus id by name.
new szDynArr[32], iNum
for (iNum = 0; iNum < g_iBonusCount; iNum++)
{
// Get bonus name from dynamic array.
ArrayGetString(g_szBonusName, iNum, szDynArr, charsmax(szDynArr))
// Return bonus Level required.
if (equal(szDynArr, szName))
{
return ArrayGetCell(g_iBonusReqLevel, iNum)
}
}
}
// Get bonus ID.
new iBonus = get_param(1)
// Get required level by bonus id.
if (iBonus > g_iBonusCount)
{
log_error(AMX_ERR_NATIVE, "[AMX] Bonus id is not found (%d)", iBonus)
return INVALID_HANDLE;
}
// Return bonus ID.
return ArrayGetCell(g_iBonusReqLevel, iBonus)
}
public _native_ze_open_bonus_menu(const iPlayer)
{
// Player is not found.
if (!is_user_connected(iPlayer))
{
log_error(AMX_ERR_NATIVE, "[AMX] Invalid player (%d)", iPlayer)
return 0;
}
// Open menu for player.
Menu_Bonus(iPlayer)
return 1;
}