示例#1
0
文件: CMisc.cpp 项目: 9iky6/amxmodx
void CPlayer::Disconnect()
{
	ingame = false;
	initialized = false;
	authorized = false;
	teamIdsInitialized = false;

	if (newmenu != -1)
	{
		Menu *pMenu = g_NewMenus[newmenu];
		if (pMenu)
		{
			//prevent recursion
			newmenu = -1;
			menu = 0;
			executeForwards(pMenu->func, 
				static_cast<cell>(ENTINDEX(pEdict)),
				static_cast<cell>(pMenu->thisId),
				static_cast<cell>(MENU_EXIT));
		}
	}

	List<ClientCvarQuery_Info *>::iterator iter, end=queries.end();
	for (iter=queries.begin(); iter!=end; iter++)
	{
		unregisterSPForward((*iter)->resultFwd);
		delete [] (*iter)->params;
		delete (*iter);
	}
	queries.clear();

	menu = 0;
	newmenu = -1;
}
示例#2
0
static cell AMX_NATIVE_CALL menu_destroy(AMX *amx, cell *params)
{
	GETMENU_R(params[1]);

	if (pMenu->isDestroying)
	{
		return 0;	//prevent infinite recursion
	}

	pMenu->isDestroying = true;

	CPlayer *player;
	for (int i=1; i<=gpGlobals->maxClients; i++)
	{
		player = GET_PLAYER_POINTER_I(i);
		if (player->newmenu == pMenu->thisId)
		{
			player->newmenu = -1;
			player->menu = 0;
			executeForwards(pMenu->func, 
				static_cast<cell>(i), 
				static_cast<cell>(pMenu->thisId),
				static_cast<cell>(MENU_EXIT));
		}
	}
	g_NewMenus[params[1]] = NULL;
	delete pMenu;
	g_MenuFreeStack.push(params[1]);

	return 1;
}
示例#3
0
void LogEventsMngr::executeLogEvents()
{
	bool valid;

	for (CLogEvent* a = logevents[logArgc]; a; a = a->next)
	{
		valid = true;
		
		for (CLogEvent::LogCond* b = a->filters; b; b = b->next)
		{
			valid = false;

			for (CLogEvent::LogCondEle* c = b->list; c; c = c->next)
			{
				if (c->cmp->compareCondition(logArgs[b->argnum]) == 0)
				{
					valid = true;
					break;
				}
			}
			
			if (!valid) 
				break;
		}
		
		if (valid)
		{
			executeForwards(a->func);
		}
	}
}
示例#4
0
static cell AMX_NATIVE_CALL menu_cancel(AMX *amx, cell *params)
{
	int index = params[1];

	if (index < 1 || index > gpGlobals->maxClients)
	{
		LogError(amx, AMX_ERR_NATIVE, "Player %d is not valid", index);
		return 0;
	}

	CPlayer *player = GET_PLAYER_POINTER_I(index);
	if (!player->ingame)
	{
		LogError(amx, AMX_ERR_NATIVE, "Played %d is not in game", index);
		return 0;
	}

	int menu = player->newmenu;
	if (menu < 0 || menu >= (int)g_NewMenus.size() || !g_NewMenus[menu])
		return 0;

	Menu *pMenu = g_NewMenus[menu];

	player->newmenu = -1;
	player->menu = 0;
	executeForwards(pMenu->func, 
		static_cast<cell>(index),
		static_cast<cell>(pMenu->thisId),
		static_cast<cell>(MENU_EXIT));

	return 1;
}
示例#5
0
// Pause a plugin
void CPluginMngr::CPlugin::pausePlugin()
{
	if (isValid())
	{
		// call plugin_pause if provided
		if (m_PauseFwd != -1)
			executeForwards(m_PauseFwd);

		setStatus(ps_paused);
	}
}
示例#6
0
int SortArrayList(const void *elem1, const void *elem2)
{
	return executeForwards(
		SortInfo.func,
		SortInfo.array_hndl,
		((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize,
		((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize,
		SortInfo.data,
		SortInfo.size
	);
}
示例#7
0
int SortArrayListExCell(const void *elem1, const void *elem2)
{
	size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
	size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;

	return executeForwards(
		SortInfo.func,
		SortInfo.array_hndl,
		*&SortInfo.array_base[index1 * SortInfo.array_bsize], 
		*&SortInfo.array_base[index2 * SortInfo.array_bsize],
		SortInfo.data,
		SortInfo.size
	);
}
示例#8
0
// Unpause a plugin
void CPluginMngr::CPlugin::unpausePlugin()
{
	if (isValid() && (getStatusCode() != ps_stopped))
	{
		// set status first so the function will be marked executable
		setStatus(ps_running);

		// call plugin_unpause if provided
		if (m_UnpauseFwd != -1)
		{
			executeForwards(m_UnpauseFwd);
		}
	}
}
示例#9
0
void plugin_srvcmd()
{
	const char* cmd = CMD_ARGV(0);

	CmdMngr::iterator a = g_commands.srvcmdbegin();

	while (a)
	{
		if ((*a).matchCommand(cmd) && (*a).getPlugin()->isExecutable((*a).getFunction()))
		{
			cell ret = executeForwards((*a).getFunction(), static_cast<cell>(g_srvindex),
									   static_cast<cell>((*a).getFlags()), static_cast<cell>((*a).getId()));
			if (ret) break;
		}
		++a;
	}
}
示例#10
0
// On InconsistentFile call	forward	function from plugins
int	C_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message)
{
	if (FF_InconsistentFile < 0)
		RETURN_META_VALUE(MRES_IGNORED,	FALSE);

	if (MDLL_InconsistentFile(player, filename, disconnect_message))
	{
		CPlayer	*pPlayer = GET_PLAYER_POINTER((edict_t *)player);

		if (executeForwards(FF_InconsistentFile, static_cast<cell>(pPlayer->index),
			filename, disconnect_message) == 1)
			RETURN_META_VALUE(MRES_SUPERCEDE, FALSE);
		
		RETURN_META_VALUE(MRES_SUPERCEDE, TRUE);
	}

	RETURN_META_VALUE(MRES_IGNORED, FALSE);
}
示例#11
0
//Builds the menu string for a specific page (set title to 0 to not include title)
//page indices start at 0!
static cell AMX_NATIVE_CALL menu_display(AMX *amx, cell *params)
{
	GETMENU(params[2]);
	
	int player = params[1];
	int page = params[3];
	CPlayer* pPlayer = GET_PLAYER_POINTER_I(player);
	
	/* If the stupid handler keeps drawing menus, 
	 * We need to keep cancelling them.  But we put in a quick infinite loop
	 * counter to prevent this from going nuts.
	 */
	int menu;
	int loops = 0;
	while ((menu = pPlayer->newmenu) >= 0)
	{
		if ((size_t)menu >= g_NewMenus.size() || !g_NewMenus[menu])
		{
			break;
		}

		Menu *pOther = g_NewMenus[menu];

		pPlayer->newmenu = -1;
		pPlayer->menu = 0;
		executeForwards(pOther->func, 
			static_cast<cell>(player),
			static_cast<cell>(pOther->thisId),
			static_cast<cell>(MENU_EXIT));

		/* Infinite loop counter */
		if (++loops >= 10)
		{
			LogError(amx, AMX_ERR_NATIVE, "Plugin called menu_display when item=MENU_EXIT");
			return 0;
		}
	}

	// This will set the expire time of the menu to infinite
	pPlayer->menuexpire = INFINITE;

	return pMenu->Display(player, page);
}
示例#12
0
void Menu::Close(int player) 
{
	CPlayer *pPlayer = GET_PLAYER_POINTER_I(player);

	int status;
	if (gpGlobals->time > pPlayer->menuexpire)
		status = MENU_TIMEOUT;
	else
		status = MENU_EXIT;

	pPlayer->keys = 0;
	pPlayer->menu = 0;
	pPlayer->newmenu = -1;

	executeForwards(func,
		static_cast<cell>(player),
		static_cast<cell>(thisId),
		static_cast<cell>(status));
}
示例#13
0
int SortArrayListExArray(const void *elem1, const void *elem2)
{
	size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
	size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;

	cell *addr1 = get_amxaddr(SortInfo.amx, SortInfo.addr1);
	cell *addr2 = get_amxaddr(SortInfo.amx, SortInfo.addr2);

	memcpy(addr1, &SortInfo.array_base[index1 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));
	memcpy(addr2, &SortInfo.array_base[index2 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));

	return executeForwards(
		SortInfo.func,
		SortInfo.array_hndl,
		SortInfo.addr1,
		SortInfo.addr2,
		SortInfo.data,
		SortInfo.size
	);
}
示例#14
0
void EventsMngr::executeEvents()
{
	static unsigned int reentrant = 0;
	if (!m_ParseFun)
	{
		return;
	}

	// Store old read data, which are either default values or previous event data
	int oldMsgType = m_ReadMsgType, oldReadPos = m_ReadPos;
	MsgDataEntry *oldReadVault = m_ReadVault, *readVault = NULL;
	
	// We have a re-entrant call
	if (reentrant++)
	{
		// Create temporary read vault
		readVault = new MsgDataEntry[m_ParsePos + 1];
		m_ReadVault = readVault;
	} else if (m_ReadVaultSize != m_ParseVaultSize) {
		// Extend read vault size if necessary
		delete [] m_ReadVault;
		m_ReadVault = new MsgDataEntry[m_ParseVaultSize];
		m_ReadVaultSize = m_ParseVaultSize;
		
		// Update old read vault so we don't restore to a wrong pointer
		oldReadVault = m_ReadVault;
	}

	// Copy data over to readvault
	m_ReadPos = m_ParsePos;
	m_ReadMsgType = m_ParseMsgType;

	if (m_ParseVault)
	{
		memcpy(m_ReadVault, m_ParseVault, (m_ParsePos + 1) * sizeof(MsgDataEntry));
	}

	// Reset this here so we don't trigger re-entrancy for unregistered messages
	ClEventVec *parseFun = m_ParseFun;
	m_ParseFun = NULL;

	for (ClEventVecIter iter = parseFun->begin(); iter; ++iter)
	{
		if ((*iter).m_Done) 
		{
			(*iter).m_Done = false;
			continue;
		}
		
		(*iter).m_Stamp = (float)*m_Timer;

		executeForwards((*iter).m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
	}
	
	// Restore old read data, either resetting to default or to previous event data
	m_ReadMsgType = oldMsgType;
	m_ReadPos = oldReadPos;
	m_ReadVault = oldReadVault;
	
	delete [] readVault;

	--reentrant;
}
示例#15
0
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value)
{
	CvarInfo* info = nullptr;

	if (!var || !value                                    // Sanity checks against bogus pointers.
		|| strcmp(var->string, value) == 0                // Make sure old and new values are different to not trigger callbacks.
		|| !g_CvarManager.CacheLookup(var->name, &info))  // No data in cache, nothing to do.
	{
		DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
		return;
	}

	if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here.
	{
		float fvalue = atof(value);
		bool oob = false;

		if (info->bound.hasMin && fvalue < info->bound.minVal)
		{
			oob = true;
			fvalue = info->bound.minVal;
		}
		else if (info->bound.hasMax && fvalue > info->bound.maxVal)
		{
			oob = true;
			fvalue = info->bound.maxVal;
		}

		if (oob) // Found value out of bound, set new value and block original call.
		{
			CVAR_SET_FLOAT(var->name, fvalue);
			return;
		}
	}

	ke::AString oldValue; // We save old value since it will be likely changed after original function called.

	if (!info->hooks.empty())
	{
		oldValue = var->string;
	}

	DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);

	if (!info->binds.empty())
	{
		for (size_t i = 0; i < info->binds.length(); ++i)
		{
			CvarBind* bind = info->binds[i];

			switch (bind->type)
			{
				case CvarBind::CvarType_Int:
				{
					*bind->varAddress = atoi(var->string);
					break;
				}
				case CvarBind::CvarType_Float:
				{
					float fvalue = atof(var->string);
					*bind->varAddress = amx_ftoc(fvalue);
					break;
				}
				case CvarBind::CvarType_String:
				{
					set_amxstring_simple(bind->varAddress, var->string, bind->varLength);
					break;
				}
			}
		}
	}

	if (!info->hooks.empty())
	{
		for (size_t i = 0; i < info->hooks.length(); ++i)
		{
			CvarHook* hook = info->hooks[i];

			if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives.
			{
				executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), oldValue.chars(), var->string);
			}
		}
	}
}
示例#16
0
// Very	first point	at map load
// Load	AMX	modules	for	new	native functions
// Initialize AMX stuff	and	load it's plugins from plugins.ini list
// Call	precache forward function from plugins
int	C_Spawn(edict_t *pent)
{
	if (g_initialized)
	{
		RETURN_META_VALUE(MRES_IGNORED, 0);
	}

	g_activated = false;
	g_initialized = true;
	g_forcedmodules = false;
	g_forcedsounds = false;

	g_srvindex = IS_DEDICATED_SERVER() ? 0 : 1;

	hostname = CVAR_GET_POINTER("hostname");
	mp_timelimit = CVAR_GET_POINTER("mp_timelimit");

	// Fix for crashing on mods that do not have mp_timelimit
	if (mp_timelimit == NULL)
	{
		static cvar_t timelimit_holder;

		timelimit_holder.name = "mp_timelimit";
		timelimit_holder.string = "0";
		timelimit_holder.flags = 0;
		timelimit_holder.value = 0.0;

		CVAR_REGISTER(&timelimit_holder);

		mp_timelimit = &timelimit_holder;

	}

	g_forwards.clear();

	g_log.MapChange();

	// ###### Initialize task manager
	g_tasksMngr.registerTimers(&gpGlobals->time, &mp_timelimit->value, &g_game_timeleft);

	// ###### Initialize commands prefixes
	g_commands.registerPrefix("amx");
	g_commands.registerPrefix("amxx");
	g_commands.registerPrefix("say");
	g_commands.registerPrefix("admin_");
	g_commands.registerPrefix("sm_");
	g_commands.registerPrefix("cm_");

	// make sure localinfos are set
	get_localinfo("amxx_basedir", "addons/amxmodx");
	get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins");
	get_localinfo("amxx_modulesdir", "addons/amxmodx/modules");
	get_localinfo("amxx_configsdir", "addons/amxmodx/configs");
	get_localinfo("amxx_customdir", "addons/amxmodx/custom");

	// make sure bcompat localinfos are set
	get_localinfo("amx_basedir", "addons/amxmodx");
	get_localinfo("amx_configdir", "addons/amxmodx/configs");
	get_localinfo("amx_langdir", "addons/amxmodx/data/amxmod-lang");
	get_localinfo("amx_modulesdir", "addons/amxmodx/modules");
	get_localinfo("amx_pluginsdir", "addons/amxmodx/plugins");
	get_localinfo("amx_logdir", "addons/amxmodx/logs");

	FlagMan.LoadFile();

	ArrayHandles.clear();
	TrieHandles.clear();
	TrieSnapshotHandles.clear();
	DataPackHandles.clear();
	TextParsersHandles.clear();
	GameConfigHandle.clear();

	char map_pluginsfile_path[256];
	char prefixed_map_pluginsfile[256];
	char configs_dir[256];

	// ###### Load modules
	loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini"), PT_ANYTIME);

	get_localinfo_r("amxx_configsdir", "addons/amxmodx/configs", configs_dir, sizeof(configs_dir)-1);
	g_plugins.CALMFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini"));
	LoadExtraPluginsToPCALM(configs_dir);
	char temporaryMap[64], *tmap_ptr;

	ke::SafeSprintf(temporaryMap, sizeof(temporaryMap), "%s", STRING(gpGlobals->mapname));

	prefixed_map_pluginsfile[0] = '\0';
	if ((tmap_ptr = strchr(temporaryMap, '_')) != NULL)
	{
		// this map has a prefix

		*tmap_ptr = '\0';
		ke::SafeSprintf(prefixed_map_pluginsfile,
			sizeof(prefixed_map_pluginsfile),
			"%s/maps/plugins-%s.ini",
			configs_dir,
			temporaryMap);
		g_plugins.CALMFromFile(prefixed_map_pluginsfile);
	}

	ke::SafeSprintf(map_pluginsfile_path,
		sizeof(map_pluginsfile_path),
		"%s/maps/plugins-%s.ini",
		configs_dir,
		STRING(gpGlobals->mapname));
	g_plugins.CALMFromFile(map_pluginsfile_path);

	int loaded = countModules(CountModules_Running); // Call after attachModules so all modules don't have pending stat
	
	// Set some info about amx version and modules
	CVAR_SET_STRING(init_amxmodx_version.name, AMXX_VERSION);
	char buffer[32];
	sprintf(buffer, "%d", loaded);
	CVAR_SET_STRING(init_amxmodx_modules.name, buffer);

	// ###### Load Vault
	char file[255];
	g_vault.setSource(build_pathname_r(file, sizeof(file) - 1, "%s", get_localinfo("amxx_vault", "addons/amxmodx/configs/vault.ini")));
	g_vault.loadVault();

	// ###### Init time and freeze tasks
	g_game_timeleft = g_bmod_dod ? 1.0f : 0.0f;
	g_task_time = gpGlobals->time + 99999.0f;
	g_auth_time = gpGlobals->time + 99999.0f;
#ifdef MEMORY_TEST
	g_next_memreport_time = gpGlobals->time + 99999.0f;
#endif
	g_players_num = 0;

	// Set server flags
	memset(g_players[0].flags, -1, sizeof(g_players[0].flags));

	g_opt_level = atoi(get_localinfo("optimizer", "7"));
	if (!g_opt_level)
		g_opt_level = 7;

	// ###### Load AMX Mod X plugins
	g_plugins.loadPluginsFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini"));
	LoadExtraPluginsFromDir(configs_dir);
	g_plugins.loadPluginsFromFile(map_pluginsfile_path, false);
	if (prefixed_map_pluginsfile[0] != '\0')
	{
		g_plugins.loadPluginsFromFile(prefixed_map_pluginsfile, false);
	}

	g_plugins.Finalize();
	g_plugins.InvalidateCache();

	// Register forwards
	FF_PluginInit = registerForward("plugin_init", ET_IGNORE, FP_DONE);
	FF_ClientCommand = registerForward("client_command", ET_STOP, FP_CELL, FP_DONE);
	FF_ClientConnect = registerForward("client_connect", ET_IGNORE, FP_CELL, FP_DONE);
	FF_ClientDisconnect = registerForward("client_disconnect", ET_IGNORE, FP_CELL, FP_DONE);
	FF_ClientDisconnected = registerForward("client_disconnected", ET_IGNORE, FP_CELL, FP_CELL, FP_ARRAY, FP_CELL, FP_DONE);
	FF_ClientRemove = registerForward("client_remove", ET_IGNORE, FP_CELL, FP_CELL, FP_STRING, FP_DONE);
	FF_ClientInfoChanged = registerForward("client_infochanged", ET_IGNORE, FP_CELL, FP_DONE);
	FF_ClientPutInServer = registerForward("client_putinserver", ET_IGNORE, FP_CELL, FP_DONE);
	FF_PluginCfg = registerForward("plugin_cfg", ET_IGNORE, FP_DONE);
	FF_PluginPrecache = registerForward("plugin_precache", ET_IGNORE, FP_DONE);
	FF_PluginLog = registerForward("plugin_log", ET_STOP, FP_DONE);
	FF_PluginEnd = registerForward("plugin_end", ET_IGNORE, FP_DONE);
	FF_InconsistentFile = registerForward("inconsistent_file", ET_STOP, FP_CELL, FP_STRING, FP_STRINGEX, FP_DONE);
	FF_ClientAuthorized = registerForward("client_authorized", ET_IGNORE, FP_CELL, FP_STRING, FP_DONE);
	FF_ChangeLevel = registerForward("server_changelevel", ET_STOP, FP_STRING, FP_DONE);
	FF_ClientConnectEx = registerForward("client_connectex", ET_STOP, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE);

	CoreCfg.OnAmxxInitialized();

#if defined BINLOG_ENABLED
	if (!g_BinLog.Open())
	{
		LOG_ERROR(PLID, "Binary log failed to open.");
	}
	g_binlog_level = atoi(get_localinfo("bin_logging", "17"));
	g_binlog_maxsize = atoi(get_localinfo("max_binlog_size", "20"));
#endif

	modules_callPluginsLoaded();

	TypeConversion.init();

	// ###### Call precache forward function
	g_dontprecache = false;
	executeForwards(FF_PluginPrecache);
	g_dontprecache = true;

	for (CList<ForceObject>::iterator a = g_forcegeneric.begin(); a; ++a)
	{
		PRECACHE_GENERIC((char*)(*a).getFilename());
		ENGINE_FORCE_UNMODIFIED((*a).getForceType(),
		(*a).getMin(), (*a).getMax(), (*a).getFilename());
	}

	RETURN_META_VALUE(MRES_IGNORED, 0);
}
示例#17
0
const char *Menu::GetTextString(int player, page_t page, int &keys)
{
	page_t pages = GetPageCount();
	item_t numItems = GetItemCount();

	if (page >= pages)
		return NULL;

	m_Text = nullptr;

	char buffer[255];
	if (items_per_page && (pages != 1))
	{
		if (m_AutoColors)
			ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s %d/%d\n\\w\n", m_Title.chars(), page + 1, pages);
		else
			ke::SafeSprintf(buffer, sizeof(buffer), "%s %d/%d\n\n", m_Title.chars(), page + 1, pages);
	} else {
		if (m_AutoColors)
			ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s\n\\w\n", m_Title.chars());
		else
			ke::SafeSprintf(buffer, sizeof(buffer), "%s\n\n", m_Title.chars());
	}
	
	m_Text = m_Text + buffer;

	enum
	{
		Display_Back = (1<<0),
		Display_Next = (1<<1),
	};

	int flags = Display_Back|Display_Next;

	item_t start = page * items_per_page;
	item_t end = 0;
	if (items_per_page)
	{
		if (start + items_per_page >= numItems)
		{
			end = numItems;
			flags &= ~Display_Next;
		} else {
			end = start + items_per_page;
		}
	} else {
		end = numItems;
		if (end > 10)
		{
			end = 10;
		}
	}

	if (page == 0)
	{
		flags &= ~Display_Back;
	}
	
	menuitem *pItem = NULL;
	
	int option = 0;
	keys = 0;
	bool enabled = true;
	int ret = 0;
	int slots = 0;
	int option_display = 0;
	
	for (item_t i = start; i < end; i++)
	{
		// reset enabled
		enabled = true;
		pItem = m_Items[i];
		
		if (pItem->access && !(pItem->access & g_players[player].flags[0]))
		{
			enabled = false;
		}
		
		if (pItem->handler != -1)
		{
			ret = executeForwards(pItem->handler, static_cast<cell>(player), static_cast<cell>(thisId), static_cast<cell>(i));
			if (ret == ITEM_ENABLED)
			{
				enabled = true;
			} else if (ret == ITEM_DISABLED) {
				enabled = false;
			}
		}
		
		if (pItem->pfn)
		{
			ret = (pItem->pfn)(player, thisId, i);
			if (ret == ITEM_ENABLED)
			{
				enabled = true;
			} else if (ret == ITEM_DISABLED) {
				enabled = false;
			}
		}

		if (pItem->isBlank)
		{
			enabled = false;
		}

		if (enabled)
		{
			keys |= (1<<option);
		}
		
		option_display = ++option;
		if (option_display == 10)
		{
			option_display = 0;
		}

		if (pItem->isBlank)
		{
			ke::SafeSprintf(buffer, sizeof(buffer), "%s\n", pItem->name.chars());
		}
		else if (enabled)
		{
			if (m_AutoColors) 
			{
				ke::SafeSprintf(buffer, sizeof(buffer), "%s%d.\\w %s\n", m_ItemColor.chars(),option_display, pItem->name.chars());
			} else {
				ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s\n", option_display, pItem->name.chars());
			}
		} else {
			if (m_AutoColors)
			{
				ke::SafeSprintf(buffer, sizeof(buffer), "\\d%d. %s\n\\w", option_display, pItem->name.chars());
			} else {
				ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", pItem->name.chars());
			}
		}
		slots++;

		m_Text = m_Text + buffer;

		//attach blanks
		if (pItem->blanks.length())
		{
			for (size_t j=0; j<pItem->blanks.length(); j++)
			{
				if (pItem->blanks[j].EatNumber())
				{
					option++;
				}
				m_Text = m_Text + pItem->blanks[j].GetDisplay();
				m_Text = m_Text + "\n";
				slots++;
			}
		}
	}

	if (items_per_page)
	{
		/* Pad spaces until we reach the end of the max possible items */
		for (unsigned int i=(unsigned)slots; i<items_per_page; i++)
		{
			m_Text = m_Text + "\n";
			option++;
		}
		/* Make sure there is at least one visual pad */
		m_Text = m_Text + "\n";

		/* Don't bother if there is only one page */
		if (pages > 1)
		{
			if (flags & Display_Back)
			{
				keys |= (1<<option++);
				if (m_AutoColors)
				{
					ke::SafeSprintf(buffer,
						sizeof(buffer), 
						"%s%d. \\w%s\n", 
						m_ItemColor.chars(), 
						option == 10 ? 0 : option, 
						m_OptNames[abs(MENU_BACK)].chars());
				} else {
					ke::SafeSprintf(buffer,
						sizeof(buffer), 
						"%d. %s\n", 
						option == 10 ? 0 : option, 
						m_OptNames[abs(MENU_BACK)].chars());
				}
			} else {
				option++;
				if (m_AutoColors)
				{
					ke::SafeSprintf(buffer,
						sizeof(buffer),
						"\\d%d. %s\n\\w",
						option == 10 ? 0 : option,
						m_OptNames[abs(MENU_BACK)].chars());
				} else {
					ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", m_OptNames[abs(MENU_BACK)].chars());
				}
			}
			m_Text = m_Text + buffer;
	
			if (flags & Display_Next)
			{
				keys |= (1<<option++);
				if (m_AutoColors)
				{
					ke::SafeSprintf(buffer,
						sizeof(buffer), 
						"%s%d. \\w%s\n", 
						m_ItemColor.chars(), 
						option == 10 ? 0 : option, 
						m_OptNames[abs(MENU_MORE)].chars());
				} else {
					ke::SafeSprintf(buffer,
						sizeof(buffer), 
						"%d. %s\n", 
						option == 10 ? 0 : option, 
						m_OptNames[abs(MENU_MORE)].chars());
				}
			} else {
				option++;
				if (m_AutoColors)
				{
					ke::SafeSprintf(buffer,
						sizeof(buffer),
						"\\d%d. %s\n\\w",
						option == 10 ? 0 : option,
						m_OptNames[abs(MENU_MORE)].chars());
				} else {
					ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", m_OptNames[abs(MENU_MORE)].chars());
				}
			}
			m_Text = m_Text + buffer;
		} else {
			/* Keep padding */
			option += 2;
		}
	}
	
	if ((items_per_page && !m_NeverExit) || (m_ForceExit && numItems < 10))
	{
		/* Visual pad has not been added yet */
		if (!items_per_page)
			m_Text = m_Text + "\n";
		
		keys |= (1<<option++);
		if (m_AutoColors)
		{
			ke::SafeSprintf(buffer,
				sizeof(buffer), 
				"%s%d. \\w%s\n", 
				m_ItemColor.chars(), 
				option == 10 ? 0 : option, 
				m_OptNames[abs(MENU_EXIT)].chars());
		} else {
			ke::SafeSprintf(buffer,
				sizeof(buffer), 
				"%d. %s\n", 
				option == 10 ? 0 : option, 
				m_OptNames[abs(MENU_EXIT)].chars());
		}
		m_Text = m_Text + buffer;
	}
	
	return m_Text.ptr();
}
示例#18
0
文件: util.cpp 项目: Javivi/amxmodx
// UTIL_FakeClientCommand
// PURPOSE: Sends a fake client command to GameDLL
// HOW DOES IT WORK:
//  1) Stores command and arguments into a global and sets the global "fake" flag to true
//  2) Invokes ClientCommand in GameDLL
//  3) meta_api.cpp overrides Cmd_Args, Cmd_Argv, Cmd_Argc and gives them fake values if the "fake" flag is set
//  4) unsets the global "fake" flag
void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1, const char *arg2, bool fwd)
{
	if (!cmd) 
		return;						// no command 

	// store command
	g_fakecmd.argv[0] = cmd;
	// if only arg2 is passed, swap the arguments
	if (!arg1 && arg2)
	{
		arg1 = arg2;
		arg2 = NULL;
	}

	// store arguments
	if (arg2)
	{								// both arguments passed
		g_fakecmd.argc = 3;			// 2 arguments + 1 command
		// store arguments
		g_fakecmd.argv[1] = arg1;
		g_fakecmd.argv[2] = arg2;
		// build argument line
		ke::SafeSprintf(g_fakecmd.args, sizeof(g_fakecmd.args), "%s %s", arg1, arg2);
	}
	else if (arg1)
	{								// only one argument passed
		g_fakecmd.argc = 2;			// 1 argument + 1 command
		// store argument
		g_fakecmd.argv[1] = arg1;
		// build argument line
		ke::SafeSprintf(g_fakecmd.args, sizeof(g_fakecmd.args), "%s", arg1);
	}
	else
		g_fakecmd.argc = 1;			// no argmuents -> only one command

	/* Notify plugins about this command */
	if (fwd)
	{
		/* Set flag so read_argc/v/s functions will give proper value */
		g_fakecmd.notify = true;

		if (executeForwards(FF_ClientCommand, static_cast<cell>(GET_PLAYER_POINTER(pEdict)->index)) > 0)
		{
			g_fakecmd.notify = false;
			return;
		}

		/* check for command and if needed also for first argument and call proper function */
		CmdMngr::iterator aa = g_commands.clcmdprefixbegin(cmd);

		if (!aa)
		{
			aa = g_commands.clcmdbegin();
		}

		while (aa)
		{
			if ((*aa).matchCommandLine(cmd, arg1) && (*aa).getPlugin()->isExecutable((*aa).getFunction()))
			{
				if (executeForwards((*aa).getFunction(), static_cast<cell>(GET_PLAYER_POINTER(pEdict)->index)),
					static_cast<cell>((*aa).getFlags()), static_cast<cell>((*aa).getId()) > 0)
				{
					g_fakecmd.notify = false;
					return;
				}	
			}
			++aa;
		}

		/* Unset flag */
		g_fakecmd.notify = false;
	}
	
	// set the global "fake" flag so the Cmd_Arg* functions will be superceded
	g_fakecmd.fake = true;
	// tell the GameDLL that the client sent a command
	MDLL_ClientCommand(pEdict);
	// unset the global "fake" flag
	g_fakecmd.fake = false;
}