merged bcompat changed into trunk
removed amxmod compat files for now
This commit is contained in:
		| @@ -33,6 +33,7 @@ | ||||
| #include "amxmodx.h" | ||||
| #include "CLang.h" | ||||
| #include "format.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| #ifdef __linux__ | ||||
| #define _snprintf snprintf | ||||
| @@ -287,7 +288,23 @@ char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len) | ||||
| 	static char outbuf[4096]; | ||||
| 	cell *addr = get_amxaddr(amx, params[parm++]); | ||||
|  | ||||
| 	len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); | ||||
| 	if (amx->flags & AMX_FLAG_OLDFILE) | ||||
| 	{ | ||||
| 		if (*addr & BCOMPAT_TRANSLATE_BITS) | ||||
| 		{ | ||||
| 			const char *key, *def; | ||||
| 			if (!translate_bcompat(amx, addr, &key, &def)) | ||||
| 			{ | ||||
| 				goto normal_string; | ||||
| 			} | ||||
| 			len = atcprintf(outbuf, sizeof(outbuf)-1, def, amx, params, &parm); | ||||
| 		} else { | ||||
| 			goto normal_string; | ||||
| 		} | ||||
| 	} else { | ||||
| normal_string: | ||||
| 		len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); | ||||
| 	} | ||||
|  | ||||
| 	return outbuf; | ||||
| } | ||||
|   | ||||
| @@ -89,6 +89,7 @@ void CModule::clear(bool clearFilename) | ||||
|  | ||||
| 	m_DestroyableIndexes.clear(); | ||||
| 	m_Natives.clear(); | ||||
| 	m_NewNatives.clear(); | ||||
| } | ||||
|  | ||||
| bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now) | ||||
|   | ||||
| @@ -117,6 +117,7 @@ public: | ||||
| 	void CallPluginsUnloading(); | ||||
|  | ||||
| 	CVector<AMX_NATIVE_INFO*> m_Natives; | ||||
| 	CVector<AMX_NATIVE_INFO*> m_NewNatives; // Natives for new (AMXX, not AMX) plugins only | ||||
| 	CVector<size_t> m_DestroyableIndexes; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -447,7 +447,8 @@ char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize) | ||||
|  | ||||
| 	pl->file = new CAmxxReader(file, sizeof(cell)); | ||||
| 	pl->buffer = NULL; | ||||
| 	if (pl->file->GetStatus() != CAmxxReader::Err_None) | ||||
| 	if (pl->file->GetStatus() != CAmxxReader::Err_None || | ||||
| 		pl->file->IsOldFile()) | ||||
| 	{ | ||||
| 		delete pl->file; | ||||
| 		delete pl; | ||||
|   | ||||
| @@ -19,7 +19,8 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules | ||||
| 	srvcmd.cpp strptime.cpp amxcore.cpp amxtime.cpp power.cpp amxxlog.cpp fakemeta.cpp \ | ||||
| 	amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \ | ||||
| 	CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \ | ||||
| 	optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp | ||||
| 	optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \ | ||||
| 	amxmod_compat.cpp | ||||
|  | ||||
| LINK = -lgcc -static-libgcc | ||||
|  | ||||
|   | ||||
							
								
								
									
										136
									
								
								amxmodx/amxmod_compat.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								amxmodx/amxmod_compat.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| #include "amxmodx.h" | ||||
| #include "amxmod_compat.h" | ||||
| #include "format.h" | ||||
|  | ||||
| struct translate_result | ||||
| { | ||||
| 	int suki; | ||||
| 	int dest; | ||||
| 	int lang; | ||||
| }; | ||||
|  | ||||
| CVector<translate_result *> g_tr_results; | ||||
| CStack<size_t> g_old_ids; | ||||
|  | ||||
| bool GetTranslation(int id, int &key, int &dest, int &lang) | ||||
| { | ||||
| 	if (id < 0 || (unsigned int)id > g_tr_results.size()) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	translate_result *pRes = g_tr_results[id]; | ||||
|  | ||||
| 	key = pRes->suki; | ||||
| 	dest = pRes->dest; | ||||
| 	lang = pRes->lang; | ||||
|  | ||||
| 	g_old_ids.push((size_t)id); | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void ClearTransCache() | ||||
| { | ||||
| 	for (size_t i=0; i<g_tr_results.size(); i++) | ||||
| 	{ | ||||
| 		delete g_tr_results[i]; | ||||
| 	} | ||||
| 	g_tr_results.clear(); | ||||
|  | ||||
| 	while (!g_old_ids.empty()) | ||||
| 	{ | ||||
| 		g_old_ids.pop(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def) | ||||
| { | ||||
| 	unsigned int trans = static_cast<unsigned int>(*source); | ||||
| 	trans &= ~BCOMPAT_TRANSLATE_BITS; | ||||
| 	int key, _dest, lang; | ||||
| 	if (!GetTranslation(trans, key, _dest, lang)) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	cell amx_addr, *phys_addr; | ||||
| 	if (amx_Allot(amx, 3, &amx_addr, &phys_addr) != AMX_ERR_NONE) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (_dest == -1) | ||||
| 	{ | ||||
| 		*phys_addr = LANG_PLAYER; | ||||
| 	} else if (_dest == 0) { | ||||
| 		*phys_addr = LANG_SERVER; | ||||
| 	} else if (lang >= 0 && lang < g_langMngr.GetLangsNum()) { | ||||
| 		const char *name = g_langMngr.GetLangName(lang); | ||||
| 		phys_addr[0] = static_cast<cell>(name[0]); | ||||
| 		phys_addr[1] = static_cast<cell>(name[1]); | ||||
| 		phys_addr[2] = static_cast<cell>('\0'); | ||||
| 	} else { | ||||
| 		*phys_addr = LANG_SERVER; | ||||
| 	} | ||||
|  | ||||
| 	//not optimized but it works, eh | ||||
| 	//if someone cares they can make a translate() wrapper that takes the key # in directly | ||||
| 	const char *r_key = g_langMngr.GetKey(key); | ||||
| 	const char *def = translate(amx, amx_addr, r_key); | ||||
| 	if (!def) | ||||
| 	{ | ||||
| 		def = r_key; | ||||
| 	} | ||||
| 	amx_Release(amx, amx_addr); | ||||
|  | ||||
| 	*_key = g_langMngr.GetKey(key); | ||||
| 	*_def = def; | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL amx_translate(AMX *amx, cell *params) | ||||
| { | ||||
| 	int len; | ||||
| 	char *key = get_amxstring(amx, params[1], 0, len); | ||||
|  | ||||
| 	translate_result *pRes; | ||||
| 	size_t id; | ||||
| 	if (g_old_ids.empty()) | ||||
| 	{ | ||||
| 		pRes = new translate_result; | ||||
| 		id = g_tr_results.size(); | ||||
| 		g_tr_results.push_back(pRes); | ||||
| 	} else { | ||||
| 		if (g_tr_results.size() >= BCOMPAT_TRANSLATE_MAX) | ||||
| 		{ | ||||
| 			LogError(amx, AMX_ERR_NATIVE, "Exceeded bcompat translation limit of %d!", BCOMPAT_TRANSLATE_MAX); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		id = g_old_ids.front(); | ||||
| 		g_old_ids.pop(); | ||||
| 		pRes = g_tr_results[id]; | ||||
| 	} | ||||
|  | ||||
| 	pRes->suki = g_langMngr.GetKeyEntry(key); | ||||
|  | ||||
| 	//Some AMX Mod plugins do not register everything they need.  Prevent a crash. | ||||
| 	if (pRes->suki == -1) | ||||
| 	{ | ||||
| 		pRes->suki = g_langMngr.AddKeyEntry(key); | ||||
| 	} | ||||
|  | ||||
| 	pRes->dest = params[2]; | ||||
| 	pRes->lang = params[3]; | ||||
|  | ||||
| 	return (cell)((unsigned int)BCOMPAT_TRANSLATE_BITS | (unsigned int)id); | ||||
| } | ||||
|  | ||||
| AMX_NATIVE_INFO g_BcompatNatives[] =  | ||||
| { | ||||
| 	{"translate",				amx_translate}, | ||||
|  | ||||
| 	{NULL,						NULL}, | ||||
| }; | ||||
|  | ||||
							
								
								
									
										12
									
								
								amxmodx/amxmod_compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								amxmodx/amxmod_compat.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #ifndef _INCLUDE_AMXMOD_CORE_COMPAT_H | ||||
| #define _INCLUDE_AMXMOD_CORE_COMPAT_H | ||||
|  | ||||
| #define BCOMPAT_TRANSLATE_BITS		0xFFFFF400 | ||||
| #define BCOMPAT_TRANSLATE_MAX		0x400 | ||||
|  | ||||
| bool GetTranslation(int id, int &key, int &dest, int &lang); | ||||
| void ClearTransCache(); | ||||
|  | ||||
| extern AMX_NATIVE_INFO g_BcompatNatives[]; | ||||
|  | ||||
| #endif //_INCLUDE_AMXMOD_CORE_COMPAT_H | ||||
| @@ -608,6 +608,7 @@ const char *Debugger::_GetFilename() | ||||
| void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength) | ||||
| { | ||||
| 	const char *filename = ""; | ||||
| 	char native[sNAMEMAX+1]; | ||||
|  | ||||
| 	CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx); | ||||
| 	if (a) | ||||
| @@ -625,6 +626,9 @@ void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLengt | ||||
| 	if (error == AMX_ERR_EXIT) | ||||
| 	{ | ||||
| 		_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT)); | ||||
| 	} else if (error == AMX_ERR_NATIVE) { | ||||
| 		amx_GetNative(amx, (int)amx->usertags[UT_NATIVE], native); | ||||
| 		_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native); | ||||
| 	} else { | ||||
| 		_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename); | ||||
| 	} | ||||
|   | ||||
| @@ -424,6 +424,54 @@ static cell AMX_NATIVE_CALL n_floatatan2(AMX *amx, cell *params) | ||||
| 	return amx_ftoc(fC); | ||||
| } | ||||
|  | ||||
| #if defined __BORLANDC__ || defined __WATCOMC__ | ||||
|   #pragma argsused | ||||
| #endif | ||||
| /* Added by DS */ | ||||
| static cell AMX_NATIVE_CALL n_floatsinh(AMX *amx, cell *params) | ||||
| { | ||||
| 	/* | ||||
| 	 * params[1] = angle | ||||
| 	 * params[2] = radix | ||||
| 	 */ | ||||
| 	REAL fA = amx_ctof(params[1]); | ||||
| 	fA = ToRadians(fA, params[2]); | ||||
| 	fA = sinh(fA); | ||||
| 	return amx_ftoc(fA); | ||||
| } | ||||
|  | ||||
| #if defined __BORLANDC__ || defined __WATCOMC__ | ||||
|   #pragma argsused | ||||
| #endif | ||||
| /* Added by DS */ | ||||
| static cell AMX_NATIVE_CALL n_floatcosh(AMX *amx, cell *params) | ||||
| { | ||||
| 	/* | ||||
| 	 * params[1] = angle | ||||
| 	 * params[2] = radix | ||||
| 	 */ | ||||
| 	REAL fA = amx_ctof(params[1]); | ||||
| 	fA = ToRadians(fA, params[2]); | ||||
| 	fA = cosh(fA); | ||||
| 	return amx_ftoc(fA); | ||||
| } | ||||
|  | ||||
| #if defined __BORLANDC__ || defined __WATCOMC__ | ||||
|   #pragma argsused | ||||
| #endif | ||||
| /* Added by DS */ | ||||
| static cell AMX_NATIVE_CALL n_floattanh(AMX *amx, cell *params) | ||||
| { | ||||
| 	/* | ||||
| 	 * params[1] = angle | ||||
| 	 * params[2] = radix | ||||
| 	 */ | ||||
| 	REAL fA = amx_ctof(params[1]); | ||||
| 	fA = ToRadians(fA, params[2]); | ||||
| 	fA = tanh(fA); | ||||
| 	return amx_ftoc(fA); | ||||
| } | ||||
|  | ||||
| #if defined __BORLANDC__ || defined __WATCOMC__ | ||||
|   #pragma argsused | ||||
| #endif | ||||
| @@ -456,6 +504,9 @@ AMX_NATIVE_INFO float_Natives[] = { | ||||
|   { "floatacos",   n_floatacos  }, | ||||
|   { "floatatan",   n_floatatan  }, | ||||
|   { "floatatan2",  n_floatatan2 }, | ||||
|   { "floatsinh",   n_floatsinh  }, | ||||
|   { "floatcosh",   n_floatcosh  }, | ||||
|   { "floattanh",   n_floattanh  }, | ||||
|   { NULL, NULL }        /* terminator */ | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "amxmodx.h" | ||||
| #include "format.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| //Adapted from Quake3's vsprintf | ||||
| // thanks to cybermind for linking me to this :) | ||||
| @@ -422,6 +423,24 @@ reswitch: | ||||
| 			break; | ||||
| 		case 's': | ||||
| 			CHECK_ARGS(0); | ||||
| 			if (amx->flags & AMX_FLAG_OLDFILE) | ||||
| 			{ | ||||
| 				cell *addr = get_amxaddr(amx, params[arg]); | ||||
| 				if (*addr & BCOMPAT_TRANSLATE_BITS) | ||||
| 				{ | ||||
| 					const char *key, *def; | ||||
| 					if (!translate_bcompat(amx, addr, &key, &def)) | ||||
| 					{ | ||||
| 						goto break_to_normal_string; | ||||
| 					} | ||||
| 					arg++; | ||||
| 					size_t written = atcprintf(buf_p, llen, def, amx, params, &arg); | ||||
| 					buf_p += written; | ||||
| 					llen -= written; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| break_to_normal_string: | ||||
| 			AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec); | ||||
| 			arg++; | ||||
| 			break; | ||||
|   | ||||
| @@ -5,4 +5,7 @@ | ||||
| template <typename D, typename S> | ||||
| size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param); | ||||
|  | ||||
| const char *translate(AMX *amx, cell amxaddr, const char *key); | ||||
| bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def); | ||||
|  | ||||
| #endif //_INCLUDE_FORMATTING_H | ||||
|   | ||||
| @@ -45,6 +45,7 @@ | ||||
| #include "optimizer.h" | ||||
| #include "libraries.h" | ||||
| #include "messages.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| plugin_info_t Plugin_info =  | ||||
| { | ||||
| @@ -357,6 +358,14 @@ int	C_Spawn(edict_t *pent) | ||||
| 	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"); | ||||
|  | ||||
| 	char map_pluginsfile_path[256]; | ||||
|  | ||||
| 	// ###### Load modules | ||||
| @@ -619,6 +628,7 @@ void C_ServerDeactivate_Post() | ||||
| 	g_xvars.clear(); | ||||
| 	g_plugins.clear(); | ||||
| 	ClearPluginLibraries(); | ||||
| 	ClearTransCache(); | ||||
| 	modules_callPluginsUnloaded(); | ||||
|  | ||||
| 	ClearMessages(); | ||||
|   | ||||
| @@ -48,6 +48,7 @@ | ||||
| #include "binlog.h" | ||||
| #include "libraries.h" | ||||
| #include "messages.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| CList<CModule, const char*> g_modules; | ||||
| CList<CScript, AMX*> g_loadedscripts; | ||||
| @@ -165,6 +166,7 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 | ||||
| 	*error = 0; | ||||
| 	size_t bufSize; | ||||
| 	*program = (void *)g_plugins.ReadIntoOrFromCache(filename, bufSize); | ||||
| 	bool oldfile = false; | ||||
| 	if (!*program) | ||||
| 	{ | ||||
| 		CAmxxReader reader(filename, PAWN_CELL_SIZE / 8); | ||||
| @@ -218,6 +220,8 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 | ||||
| 				strcpy(error, "Unknown error"); | ||||
| 				return (amx->error = AMX_ERR_NOTFOUND); | ||||
| 		} | ||||
|  | ||||
| 		oldfile = reader.IsOldFile(); | ||||
| 	} else { | ||||
| 		g_plugins.InvalidateFileInCache(filename, false); | ||||
| 	} | ||||
| @@ -369,6 +373,17 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	if (oldfile) | ||||
| 	{ | ||||
| 		amx->flags |= AMX_FLAG_OLDFILE; | ||||
| 	} else { | ||||
| 		cell addr; | ||||
| 		if (amx_FindPubVar(amx, "__b_old_plugin", &addr) == AMX_ERR_NONE) | ||||
| 		{ | ||||
| 			amx->flags |= AMX_FLAG_OLDFILE; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	CScript* aa = new CScript(amx, *program, filename); | ||||
|  | ||||
| 	g_loadedscripts.put(aa); | ||||
| @@ -542,6 +557,12 @@ int set_amxnatives(AMX* amx, char error[128]) | ||||
| 		{ | ||||
| 			amx_Register(amx, cm->m_Natives[i], -1); | ||||
| 		} | ||||
|  | ||||
| 		for (size_t i = 0; i < cm->m_NewNatives.size(); i++) | ||||
| 		{ | ||||
| 			if (!(amx->flags & AMX_FLAG_OLDFILE)) | ||||
| 				amx_Register(amx, cm->m_NewNatives[i], -1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	amx_Register(amx, string_Natives, -1); | ||||
| @@ -557,6 +578,11 @@ int set_amxnatives(AMX* amx, char error[128]) | ||||
| 	amx_Register(amx, msg_Natives, -1); | ||||
| 	amx_Register(amx, vector_Natives, -1); | ||||
| 	amx_Register(amx, g_SortNatives, -1); | ||||
| 	 | ||||
| 	if (amx->flags & AMX_FLAG_OLDFILE) | ||||
| 	{ | ||||
| 		amx_Register(amx, g_BcompatNatives, -1); | ||||
| 	} | ||||
|  | ||||
| 	//we're not actually gonna check these here anymore | ||||
| 	amx->flags |= AMX_FLAG_PRENIT; | ||||
| @@ -1178,6 +1204,18 @@ int MNF_AddNatives(AMX_NATIVE_INFO* natives) | ||||
| 	return TRUE; | ||||
| } | ||||
|  | ||||
| int MNF_AddNewNatives(AMX_NATIVE_INFO *natives) | ||||
| { | ||||
| 	CList<CModule, const char *>::iterator a = g_modules.begin(); | ||||
|  | ||||
| 	if (!g_CurrentlyCalledModule || g_ModuleCallReason != ModuleCall_Attach) | ||||
| 		return FALSE;				// may only be called from attach | ||||
|  | ||||
| 	g_CurrentlyCalledModule->m_NewNatives.push_back(natives); | ||||
|  | ||||
| 	return TRUE; | ||||
| } | ||||
|  | ||||
| const char *MNF_GetModname(void) | ||||
| { | ||||
| 	// :TODO: Do we have to do this??  | ||||
| @@ -1870,6 +1908,7 @@ void Module_CacheFunctions() | ||||
|  | ||||
| 	// Natives / Forwards | ||||
| 	REGISTER_FUNC("AddNatives", MNF_AddNatives) | ||||
| 	REGISTER_FUNC("AddNewNatives", MNF_AddNewNatives) | ||||
| 	REGISTER_FUNC("RaiseAmxError", amx_RaiseError) | ||||
| 	REGISTER_FUNC("RegisterForward", registerForward) | ||||
| 	REGISTER_FUNC("RegisterSPForward", registerSPForward) | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| #include "amxmodx.h" | ||||
| #include "format.h" | ||||
| #include "binlog.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| const char* stristr(const char* str, const char* substr) | ||||
| { | ||||
| @@ -115,8 +116,21 @@ extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, in | ||||
| 	register char *dest = destination; | ||||
| 	char *start = dest; | ||||
|  | ||||
| 	while (maxlen-- && *source) | ||||
| 		*dest++=(char)(*source++); | ||||
| 	if ( (amx->flags & AMX_FLAG_OLDFILE) && | ||||
| 		(*source & BCOMPAT_TRANSLATE_BITS) ) | ||||
| 	{ | ||||
| 		const char *def, *key; | ||||
| 		if (!translate_bcompat(amx, source, &key, &def)) | ||||
| 		{ | ||||
| 			goto normal_string; | ||||
| 		} | ||||
| 		while (maxlen-- && *def) | ||||
| 			*dest++=(*source++); | ||||
| 	} else { | ||||
| normal_string: | ||||
| 		while (maxlen-- && *source) | ||||
| 			*dest++=(char)(*source++); | ||||
| 	} | ||||
|  | ||||
| 	*dest = '\0'; | ||||
|  | ||||
| @@ -132,16 +146,29 @@ extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, in | ||||
| 	return dest - start; | ||||
| } | ||||
|  | ||||
| char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len) | ||||
| char *get_amxstring(AMX *amx, cell amx_addr, int id, int& len) | ||||
| { | ||||
| 	static char buffor[4][3072]; | ||||
| 	register cell* source = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr)); | ||||
| 	register char* dest = buffor[id]; | ||||
| 	char* start = dest; | ||||
| 	 | ||||
| 	while ((*dest++=(char)(*source++))); | ||||
|  | ||||
| 	len = --dest - start; | ||||
| 	if ( (amx->flags & AMX_FLAG_OLDFILE) && | ||||
| 		 (*source & BCOMPAT_TRANSLATE_BITS) ) | ||||
| 	{ | ||||
| 		const char *def, *key; | ||||
| 		if (!translate_bcompat(amx, source, &key, &def)) | ||||
| 		{ | ||||
| 			goto normal_string; | ||||
| 		} | ||||
| 		while ( (*dest++ = (*def++)) ); | ||||
| 		len = --dest - start; | ||||
| 	} else { | ||||
| normal_string: | ||||
| 		while ((*dest++=(char)(*source++))); | ||||
|  | ||||
| 		len = --dest - start; | ||||
| 	} | ||||
|  | ||||
| #if defined BINLOG_ENABLED | ||||
| 	if (g_binlog_level & 2) | ||||
|   | ||||
| @@ -14,7 +14,8 @@ NAME = engine | ||||
| BIN_SUFFIX_32 = amxx_i386.so | ||||
| BIN_SUFFIX_64 = amxx_amd64.so | ||||
|  | ||||
| OBJECTS = amxxmodule.cpp amxxapi.cpp engine.cpp entity.cpp globals.cpp forwards.cpp  | ||||
| OBJECTS = amxxmodule.cpp amxxapi.cpp engine.cpp entity.cpp globals.cpp forwards.cpp \ | ||||
| 	amxmod_compat.cpp | ||||
|  | ||||
| LINK =  | ||||
|  | ||||
|   | ||||
							
								
								
									
										453
									
								
								dlls/engine/amxmod_compat.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										453
									
								
								dlls/engine/amxmod_compat.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,453 @@ | ||||
| #include "engine.h" | ||||
| #include <cbase.h> | ||||
|  | ||||
| static cvar_t *sv_knockback1 = NULL; | ||||
| static cvar_t *sv_knockback2 = NULL; | ||||
| static cvar_t *sv_friendlyfire = NULL; | ||||
| static bool g_ff_check = false; | ||||
| static bool g_kb1_check = false; | ||||
| static bool g_kb2_check = false; | ||||
| static int gmsgDamage = 0; | ||||
| static int gmsgDeathMsg = 0; | ||||
| static int gmsgScoreInfo = 0; | ||||
|  | ||||
| //From VexdUM (AMX Mod 2006.2) | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| BOOL is_breakable(edict_t* pBreak) | ||||
| { | ||||
| 	if (FStrEq("func_breakable", STRING(pBreak->v.classname)) | ||||
| 		|| FStrEq("func_pushable", STRING(pBreak->v.classname)) | ||||
| 		&& pBreak->v.spawnflags & SF_PUSH_BREAKABLE) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| //From VexdUM (AMX Mod 2006.2) | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| BOOL is_monster(edict_t* pMonster) | ||||
| { | ||||
| 	if(pMonster->v.flags & FL_MONSTER) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| //From VexdUM (AMX Mod 2006.2) | ||||
| // Damage Monsters | ||||
| void hurt_monster(edict_t* pMonster, float dmg, int bit, const float *origin) | ||||
| { | ||||
| 	int mdmg = (int)pMonster->v.health; | ||||
| 	pMonster->v.health -= dmg; | ||||
|  | ||||
| 	// No need to create a trigger_hurt unless we are going to kill the monster ;) | ||||
| 	if((int)pMonster->v.health < 1) | ||||
| 	{ | ||||
| 		int hurt = MAKE_STRING("trigger_hurt"); | ||||
| 		char hbit[16]; | ||||
| 		char horigin[16]; | ||||
| 		snprintf(hbit, 15, "%i", bit); | ||||
| 		snprintf(horigin, 15, "%f %f %f", origin[0], origin[1], origin[2]); | ||||
|  | ||||
| 		edict_t* pEntity = CREATE_NAMED_ENTITY(hurt); | ||||
| 		KeyValueData pkvd1; | ||||
| 		pkvd1.szClassName = "trigger_hurt"; | ||||
| 		pkvd1.szKeyName = "dmg"; | ||||
| 		pkvd1.szValue = "1.0"; | ||||
| 		pkvd1.fHandled = FALSE; | ||||
| 		MDLL_KeyValue(pEntity, &pkvd1); | ||||
|  | ||||
| 		KeyValueData pkvd2; | ||||
| 		pkvd2.szClassName = "trigger_hurt"; | ||||
| 		pkvd2.szKeyName = "damagetype"; | ||||
| 		pkvd2.szValue = hbit; | ||||
| 		pkvd2.fHandled = FALSE; | ||||
| 		MDLL_KeyValue(pEntity, &pkvd2); | ||||
|  | ||||
| 		KeyValueData pkvd3; | ||||
| 		pkvd3.szClassName = "trigger_hurt"; | ||||
| 		pkvd3.szKeyName = "origin"; | ||||
| 		pkvd3.szValue = horigin; | ||||
| 		pkvd3.fHandled = FALSE; | ||||
| 		MDLL_KeyValue(pEntity, &pkvd3); | ||||
|  | ||||
| 		MDLL_Spawn(pEntity); | ||||
| 		MDLL_Touch(pEntity, pMonster); | ||||
| 		REMOVE_ENTITY(pEntity); | ||||
| 	} | ||||
| 	mdmg -= (int)pMonster->v.health; | ||||
| 	//~dvander - Note, not porting the forward until this function is known to be truly wrapped | ||||
| 	//g_forwards.executeForward(FF_MonsterHurt, ENTINDEX(pMonster), ENTINDEX(pMonster->v.dmg_inflictor), mdmg); | ||||
| } | ||||
|  | ||||
| //From VexdUM (AMX Mod 2006.2) | ||||
| //This appears to be from the HLSDK CBasePlayer::TakeDamage() function. | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| float ArmorDamage(edict_t* pVictim, float dmg, int bit) | ||||
| { | ||||
| 	float flRatio = 0.2; | ||||
| 	float flBonus = 0.5; | ||||
| 	if(bit & DMG_BLAST) | ||||
| 	{ | ||||
| 		// blasts damage armor more. | ||||
| 		flBonus *= 2; | ||||
| 	} | ||||
| 	if(pVictim->v.armorvalue && !(bit & (DMG_FALL | DMG_DROWN))) | ||||
| 	{ | ||||
| 		// armor doesn't protect against fall or drown damage! | ||||
| 		float flNew = dmg * flRatio; | ||||
| 		float flArmor = (dmg - flNew) * flBonus; | ||||
|  | ||||
| 		// Does this use more armor than we have? | ||||
| 		if(flArmor > pVictim->v.armorvalue) | ||||
| 		{ | ||||
| 			flArmor = pVictim->v.armorvalue; | ||||
| 			flArmor *= (1/flBonus); | ||||
| 			flNew = dmg - flArmor; | ||||
| 			pVictim->v.armorvalue = 0; | ||||
| 		} else { | ||||
| 			pVictim->v.armorvalue -= flArmor; | ||||
| 		} | ||||
| 		dmg = flNew; | ||||
| 	} | ||||
| 	// Lets knock the view about abit | ||||
| 	pVictim->v.punchangle.x = -4; | ||||
| 	return dmg; | ||||
| } | ||||
|  | ||||
| // Death emulation | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| void Death(edict_t* pVictim, edict_t* pKiller, const char* weapon, int hs) | ||||
| { | ||||
|  | ||||
| 	if (!gmsgDeathMsg) | ||||
| 	{ | ||||
| 		gmsgDeathMsg = GET_USER_MSG_ID(PLID, "DeathMsg", NULL); | ||||
| 	} | ||||
|  | ||||
| 	if (!gmsgScoreInfo) | ||||
| 	{ | ||||
| 		gmsgScoreInfo = GET_USER_MSG_ID(PLID, "ScoreInfo", NULL); | ||||
| 	} | ||||
|  | ||||
| 	// Make sure an entity is allowed to take damage | ||||
| 	if(pVictim->v.takedamage > DAMAGE_NO) | ||||
| 	{ | ||||
| 		// Breakable Check | ||||
| 		if(is_breakable(pVictim)) | ||||
| 		{ | ||||
| 			MDLL_Use(pVictim, pKiller); | ||||
| 		} | ||||
| 		// Monster Check | ||||
| 		if (is_monster(pVictim)) | ||||
| 		{ | ||||
| 			pVictim->v.dmg_inflictor = pKiller; | ||||
| 			float dmg = pVictim->v.health; | ||||
| 			int bit = DMG_BULLET; | ||||
| 			const float *origin = pVictim->v.origin; | ||||
| 			hurt_monster(pVictim, dmg, bit, origin); | ||||
| 		} | ||||
| 		// Player Check | ||||
| 		if (pVictim->v.flags & (FL_CLIENT | FL_FAKECLIENT)) | ||||
| 		{ | ||||
| 			pVictim->v.dmg_inflictor = pKiller; | ||||
| 			edict_t* inflictor = pKiller->v.owner; | ||||
| 			int inflictorId = FNullEnt(inflictor) ? ENTINDEX(inflictor) : 0; | ||||
|  | ||||
| 			// See if it is a player attacking with a default weapon | ||||
| 			if (pKiller->v.flags & (FL_CLIENT | FL_FAKECLIENT)) | ||||
| 			{ | ||||
| 				// We only modify the weapon if it = 0, otherwise its been specified | ||||
| 				if(strcmp(weapon, "") == 0) | ||||
| 				{ | ||||
| 					char view_weapon[64]; | ||||
| 					// Get the name from the view model | ||||
| 					weapon = STRING(pKiller->v.viewmodel); | ||||
|  | ||||
| 					// Strip out the beginning of the viewmodel (models/v_) | ||||
| 					if(strncmp(weapon, "models/v_", 9) == 0) | ||||
| 					{ | ||||
| 						strcpy(view_weapon, weapon + 9); | ||||
| 					} | ||||
|  | ||||
| 					// Strip out the end of viewmodel (.mdl) | ||||
| 					view_weapon[strlen(view_weapon) - 4] = '\0'; | ||||
| 					weapon = view_weapon; | ||||
| 				} | ||||
| 				// See if its an entity attacking, if so lets find its owner | ||||
| 			} else if (inflictorId >= 1 && inflictorId <= gpGlobals->maxClients) { | ||||
| 				// We only modify the weapon if it = 0, otherwise its been specified | ||||
| 				if(strcmp(weapon, "") == 0) | ||||
| 				{ | ||||
| 					weapon = STRING(pKiller->v.classname); | ||||
| 					// Strip out the default part of weapon name (HLSDK) | ||||
| 					if(strncmp(weapon, "weapon_", 7) == 0) | ||||
| 					{ | ||||
| 						weapon += 7; | ||||
| 					} else if(strncmp(weapon, "monster_", 8) == 0) { | ||||
| 						weapon += 8; | ||||
| 					} else if(strncmp(weapon, "func_", 5) == 0) { | ||||
| 						weapon += 5; | ||||
| 					} | ||||
| 				} | ||||
| 				// Check to see if the victim is the owner | ||||
| 				if(inflictor == pVictim) | ||||
| 				{ | ||||
| 					pKiller = pVictim; | ||||
| 				} else { | ||||
| 					pKiller = inflictor; | ||||
| 				} | ||||
| 			} | ||||
| 			// Send the Death Event | ||||
| 			int killerId = ENTINDEX(pKiller); | ||||
| 			int victimId = ENTINDEX(pVictim); | ||||
| 			MESSAGE_BEGIN( MSG_ALL, gmsgDeathMsg ); | ||||
| 			WRITE_BYTE( killerId > gpGlobals->maxClients ? 0 : killerId ); | ||||
| 			WRITE_BYTE( victimId ); | ||||
| 			WRITE_BYTE( hs ); | ||||
| 			WRITE_STRING( weapon ); | ||||
| 			MESSAGE_END(); | ||||
| 			// Log this kill | ||||
| 			if(pVictim == pKiller) | ||||
| 			{ | ||||
| 				// killed self | ||||
| 				UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed self with \"%s\"\n", | ||||
| 					STRING( pVictim->v.netname ), | ||||
| 					GETPLAYERUSERID( pVictim ), | ||||
| 					GETPLAYERAUTHID( pVictim ), | ||||
| 					MF_GetPlayerTeam(victimId), | ||||
| 					weapon ); | ||||
| 				// Killed by another player | ||||
| 			} else if(pKiller->v.flags & (FL_CLIENT | FL_FAKECLIENT)) { | ||||
| 				UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", | ||||
| 					STRING( pKiller->v.netname ), | ||||
| 					GETPLAYERUSERID( pKiller ), | ||||
| 					GETPLAYERAUTHID( pKiller ), | ||||
| 					MF_GetPlayerTeam(killerId), | ||||
| 					STRING( pVictim->v.netname ), | ||||
| 					GETPLAYERUSERID( pVictim ), | ||||
| 					GETPLAYERAUTHID( pVictim ), | ||||
| 					MF_GetPlayerTeam(victimId), | ||||
| 					weapon); | ||||
|  | ||||
| 				int killerTeam = MF_GetPlayerTeamID(killerId); | ||||
| 				int victimTeam = MF_GetPlayerTeamID(victimId); | ||||
| 				if (killerTeam != victimTeam) | ||||
| 				{ | ||||
| 					// Give Killer credit for this kill | ||||
| 					pKiller->v.frags += 1; | ||||
| 				} else { | ||||
| 					pKiller->v.frags -= 1; | ||||
| 				} | ||||
| 				// Update the scoreboard for the killer | ||||
| 				if (gmsgScoreInfo) | ||||
| 				{ | ||||
| 					MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo); | ||||
| 					WRITE_BYTE( killerId ); | ||||
| 					WRITE_SHORT( (int)pKiller->v.frags ); | ||||
| 					WRITE_SHORT( MF_GetPlayerDeaths(killerId) ); | ||||
| 					WRITE_SHORT( 0 ); | ||||
| 					WRITE_SHORT( MF_GetPlayerTeamID(killerId) ); | ||||
| 					MESSAGE_END(); | ||||
| 				} | ||||
| 				// Give Victim back 1 point since they didn't kill themselves | ||||
| 				pVictim->v.frags += 1; | ||||
| 			} | ||||
| 			// Killed by something else? | ||||
| 			else { | ||||
| 				UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed by \"%s\"\n", | ||||
| 					STRING( pVictim->v.netname ), | ||||
| 					GETPLAYERUSERID( pVictim ), | ||||
| 					GETPLAYERAUTHID( pVictim ), | ||||
| 					MF_GetPlayerTeam(victimId), | ||||
| 					weapon ); | ||||
| 				// Give Victim back 1 point since they didn't commit suicide | ||||
| 				pVictim->v.frags += 1; | ||||
| 			} | ||||
| #if 0 | ||||
| 			//still a todo on this one | ||||
| 			gInfo.logBlock = true; | ||||
| #endif | ||||
| 			int opt = BLOCK_ONCE; | ||||
| 			MF_MessageBlock(MSGBLOCK_SET, gmsgDeathMsg, &opt); | ||||
| 			// Kill the client, since the relevent logging blocks are in place | ||||
| 			MDLL_ClientKill(pVictim); | ||||
| 			// Restore the old message type | ||||
| 			MF_MessageBlock(MSGBLOCK_SET, gmsgDeathMsg, &opt); | ||||
| 			// Show the Victim the killing location | ||||
| 			pVictim->v.iuser3 = (killerId > gpGlobals->maxClients) ? 0 : killerId; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Damage emulation | ||||
| // From VexdUM (AMX Mod 2006.2) | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| void Damage(edict_t *pVictim,  | ||||
| 			edict_t *pAttacker,  | ||||
| 			const float *origin,  | ||||
| 			float dmg,  | ||||
| 			int bit,  | ||||
| 			const char *weapon,  | ||||
| 			int hs) | ||||
| { | ||||
| 	if (!g_ff_check && !sv_friendlyfire) | ||||
| 	{ | ||||
| 		sv_friendlyfire = CVAR_GET_POINTER("sv_friendlyfire"); | ||||
| 		g_ff_check = true; | ||||
| 	} | ||||
|  | ||||
| 	if (!gmsgDamage) | ||||
| 	{ | ||||
| 		gmsgDamage = GET_USER_MSG_ID(PLID, "Damage", NULL); | ||||
| 	} | ||||
|  | ||||
| 	// Make sure an entity is allowed to take damage | ||||
| 	if(pVictim->v.takedamage > DAMAGE_NO) | ||||
| 	{ | ||||
| 		// Breakable Check | ||||
| 		if(is_breakable(pVictim) && (int)dmg > 0) | ||||
| 		{ | ||||
| 			MDLL_Use(pVictim, pAttacker); | ||||
| 		} | ||||
| 		// Monster Check | ||||
| 		if(is_monster(pVictim) && (int)dmg > 0) | ||||
| 		{ | ||||
| 			pVictim->v.dmg_inflictor = pAttacker; | ||||
| 			hurt_monster(pVictim, dmg, bit, origin); | ||||
| 		} | ||||
| 		// Player Check | ||||
| 		if(pVictim->v.flags & (FL_CLIENT | FL_FAKECLIENT)) | ||||
| 		{ | ||||
| 			int AttackerId = ENTINDEX(pAttacker); | ||||
| 			int AttackerOwnerId = ENTINDEX(pAttacker->v.owner); | ||||
| 			int VictimId = ENTINDEX(pVictim); | ||||
| 			int vTeam = MF_GetPlayerTeamID(VictimId); | ||||
| 			int aTeam = 0; | ||||
| 			if (AttackerId >= 1 && AttackerId <= gpGlobals->maxClients) | ||||
| 			{ | ||||
| 				aTeam = MF_GetPlayerTeamID(AttackerId); | ||||
| 			} else if (AttackerOwnerId >= 1 && AttackerOwnerId <= gpGlobals->maxClients) { | ||||
| 				aTeam = MF_GetPlayerTeamID(AttackerOwnerId); | ||||
| 			} | ||||
| 			if((sv_friendlyfire && (int)sv_friendlyfire->value) || (vTeam != aTeam)) | ||||
| 			{ | ||||
| 				// Recalculate the damage since we might have armor | ||||
| 				dmg = ArmorDamage(pVictim, dmg, bit); | ||||
| 				// Only allow damage to process if more than 0.5 | ||||
| 				if((int)dmg > 0) | ||||
| 				{ | ||||
| 					// Setting to externally flag who last attacked the Victim, pretty neat huh? | ||||
| 					pVictim->v.dmg_inflictor = pAttacker; | ||||
| 					pVictim->v.dmg_take += dmg; | ||||
| 					// Register the Damage Event | ||||
| 					MESSAGE_BEGIN( MSG_ONE, gmsgDamage, NULL, pVictim ); | ||||
| 					WRITE_BYTE( (int)pVictim->v.dmg_save ); | ||||
| 					WRITE_BYTE( (int)pVictim->v.dmg_take ); | ||||
| 					WRITE_LONG( bit ); | ||||
| 					WRITE_COORD( origin[0] ); | ||||
| 					WRITE_COORD( origin[1] ); | ||||
| 					WRITE_COORD( origin[2] ); | ||||
| 					MESSAGE_END(); | ||||
|  | ||||
| 					if((int)dmg >= (int)pVictim->v.health) | ||||
| 					{ | ||||
| 						// Kill the victim | ||||
| 						pVictim->v.health = 0.0; | ||||
| 						// Send info to Death system | ||||
| 						Death(pVictim, pAttacker, weapon, hs); | ||||
| 					}else { | ||||
| 						// Take health away from victim | ||||
| 						pVictim->v.health -= dmg; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Radius Damage emulation -  | ||||
| // From VexdUM (AMX Mod 2006.2) | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| void RadiusDamage_AMXMod_Base(edict_t *pAttacker,  | ||||
| 							  float dmg,  | ||||
| 							  Vector vecSrc,  | ||||
| 							  float rad,  | ||||
| 							  int bit,  | ||||
| 							  const char *weapon,  | ||||
| 							  int hs) | ||||
| { | ||||
| 	edict_t *pTarget = NULL; | ||||
| 	TraceResult tr; | ||||
| 	float falloff; | ||||
| 	Vector vecSpot; | ||||
| 	Vector vecSee; | ||||
|  | ||||
| 	if (!g_kb1_check && !sv_knockback1) | ||||
| 	{ | ||||
| 		sv_knockback1 = CVAR_GET_POINTER("sv_knockback1"); | ||||
| 		g_kb1_check = true; | ||||
| 	} | ||||
| 	if (!g_kb2_check && !sv_knockback2) | ||||
| 	{ | ||||
| 		sv_knockback2 = CVAR_GET_POINTER("sv_knockback2"); | ||||
| 		g_kb2_check = true; | ||||
| 	} | ||||
|  | ||||
| 	if(rad > 0.0) | ||||
| 	{ | ||||
| 		falloff = dmg / rad; | ||||
| 	} else { | ||||
| 		falloff = 1.0; | ||||
| 	} | ||||
| 	vecSrc.z += 1; // In case grenade is lying on the ground | ||||
|  | ||||
| 	int hitId; | ||||
| 	int targetId; | ||||
|  | ||||
| 	while ((pTarget = UTIL_FindEntityInSphere(pTarget, vecSrc, rad)) != NULL) | ||||
| 	{ | ||||
| 		// Make sure an entity is allowed to take damage | ||||
| 		if (pTarget->v.takedamage > DAMAGE_NO) | ||||
| 		{ | ||||
| 			//none of this code was working so I simplified it | ||||
| 			//damage doesn't check for visibility now (it probably shouldn't anyway) | ||||
| 			//for this to work it seems like an exception needs to be made for world OR | ||||
| 			// the spot/see things aren't being calculated right. | ||||
| #if 0 | ||||
| 			vecSpot = (pTarget->v.absmin + pTarget->v.absmax) * 0.5; | ||||
| 			vecSee = (pAttacker->v.absmin + pAttacker->v.absmax) * 0.5; | ||||
| 			TRACE_LINE(vecSee, vecSpot, FALSE, pAttacker, &tr); | ||||
| 			// Explosion can 'see' this entity, so hurt them! | ||||
| #endif | ||||
| 			TRACE_LINE(vecSrc, pTarget->v.origin, FALSE, pAttacker, &tr); | ||||
| 			hitId = ENTINDEX(tr.pHit); | ||||
| 			targetId = ENTINDEX(pTarget); | ||||
| 			if(tr.flFraction < 1.0 || (hitId == targetId)) | ||||
| 			{ | ||||
| 				// Work out the distance between impact and entity | ||||
| 				float dist = (tr.vecEndPos - vecSrc).Length() * falloff; | ||||
| 				// Damage algorithm, its just that easy :) | ||||
| 				dmg -= dist; | ||||
| 				// Knockback Effect | ||||
| 				if(pTarget->v.flags & (FL_CLIENT | FL_FAKECLIENT) && (bit & (DMG_BLAST | DMG_CLUB | DMG_SHOCK | DMG_SONIC | DMG_ENERGYBEAM | DMG_MORTAR))) | ||||
| 				{ | ||||
| 					Vector vecPush = (pTarget->v.origin - (pAttacker->v.absmin + pAttacker->v.absmax) * 0.5).Normalize(); | ||||
| 					if(dmg < 60.0) | ||||
| 					{ | ||||
| 						pTarget->v.velocity = pTarget->v.velocity + vecPush * dmg * (sv_knockback1 ? sv_knockback1->value : 1.0f); | ||||
| 					} else { | ||||
| 						pTarget->v.velocity = pTarget->v.velocity + vecPush * dmg * (sv_knockback2 ? sv_knockback2->value : 1.0f); | ||||
| 					} | ||||
| 				} | ||||
| 				// Send info to Damage system | ||||
| 				Damage(pTarget, pAttacker, vecSrc, dmg, bit, weapon, hs); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	pTarget = NULL; | ||||
| } | ||||
							
								
								
									
										25
									
								
								dlls/engine/amxmod_compat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								dlls/engine/amxmod_compat.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| #ifndef _INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ | ||||
| #define _INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ | ||||
|  | ||||
| BOOL is_breakable(edict_t* pBreak); | ||||
| BOOL is_monster(edict_t* pMonster); | ||||
| void hurt_monster(edict_t* pMonster, float dmg, int bit, const float *origin); | ||||
| float ArmorDamage(edict_t* pVictim, float dmg, int bit); | ||||
| void Death(edict_t* pVictim, edict_t* pKiller, const char* weapon, int hs); | ||||
| void Damage(edict_t *pVictim,  | ||||
| 			edict_t *pAttacker,  | ||||
| 			const float *origin,  | ||||
| 			float dmg,  | ||||
| 			int bit,  | ||||
| 			const char *weapon,  | ||||
| 			int hs); | ||||
| void RadiusDamage_AMXMod_Base(edict_t *pAttacker,  | ||||
| 							  float dmg,  | ||||
| 							  Vector vecSrc,  | ||||
| 							  float rad,  | ||||
| 							  int bit,  | ||||
| 							  const char *weapon,  | ||||
| 							  int hs); | ||||
|  | ||||
| #endif //_INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ | ||||
|  | ||||
| @@ -37,7 +37,9 @@ void OnAmxxAttach() | ||||
| 	CmdStartForward = 0; | ||||
| 	StartFrameForward = 0; | ||||
| 	MF_AddNatives(ent_Natives); | ||||
| 	MF_AddNewNatives(ent_NewNatives); | ||||
| 	MF_AddNatives(engine_Natives); | ||||
| 	MF_AddNewNatives(engine_NewNatives); | ||||
| 	MF_AddNatives(global_Natives); | ||||
| 	memset(glinfo.szLastLights, 0x0, 128); | ||||
| 	memset(glinfo.szRealLights, 0x0, 128); | ||||
|   | ||||
| @@ -2437,6 +2437,7 @@ static amxx_module_info_s g_ModuleInfo = | ||||
|  | ||||
| // Storage for the requested functions | ||||
| PFN_ADD_NATIVES				g_fn_AddNatives; | ||||
| PFN_ADD_NEW_NATIVES			g_fn_AddNewNatives; | ||||
| PFN_BUILD_PATHNAME			g_fn_BuildPathname; | ||||
| PFN_BUILD_PATHNAME_R		g_fn_BuildPathnameR; | ||||
| PFN_GET_AMXADDR				g_fn_GetAmxAddr; | ||||
| @@ -2513,6 +2514,9 @@ PFN_ADDLIBRARIES			g_fn_AddLibraries; | ||||
| PFN_REMOVELIBRARIES			g_fn_RemoveLibraries; | ||||
| PFN_OVERRIDENATIVES			g_fn_OverrideNatives; | ||||
| PFN_GETLOCALINFO			g_fn_GetLocalInfo; | ||||
| PFN_AMX_REREGISTER			g_fn_AmxReRegister; | ||||
| PFN_REGISTERFUNCTIONEX		g_fn_RegisterFunctionEx; | ||||
| PFN_MESSAGE_BLOCK			g_fn_MessageBlock; | ||||
|  | ||||
| // *** Exports *** | ||||
| C_DLLEXPORT int AMXX_Query(int *interfaceVersion, amxx_module_info_s *moduleInfo) | ||||
| @@ -2563,6 +2567,7 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) | ||||
| 	REQFUNC("MergeDefinitionFile", g_fn_MergeDefinition_File, PFN_MERGEDEFINITION_FILE); | ||||
| 	REQFUNC("Format", g_fn_Format, PFN_FORMAT); | ||||
| 	REQFUNC("RegisterFunction", g_fn_RegisterFunction, PFN_REGISTERFUNCTION); | ||||
| 	REQFUNC("RegisterFunctionEx", g_fn_RegisterFunctionEx, PFN_REGISTERFUNCTIONEX); | ||||
|  | ||||
| 	// Amx scripts | ||||
| 	REQFUNC("GetAmxScript", g_fn_GetAmxScript, PFN_GET_AMXSCRIPT); | ||||
| @@ -2588,6 +2593,7 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) | ||||
|  | ||||
| 	// Natives / Forwards | ||||
| 	REQFUNC("AddNatives", g_fn_AddNatives, PFN_ADD_NATIVES); | ||||
| 	REQFUNC("AddNewNatives", g_fn_AddNewNatives, PFN_ADD_NEW_NATIVES); | ||||
| 	REQFUNC("RaiseAmxError", g_fn_RaiseAmxError, PFN_RAISE_AMXERROR); | ||||
| 	REQFUNC("RegisterForward", g_fn_RegisterForward, PFN_REGISTER_FORWARD); | ||||
| 	REQFUNC("RegisterSPForward", g_fn_RegisterSPForward, PFN_REGISTER_SPFORWARD); | ||||
| @@ -2627,11 +2633,15 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) | ||||
| 	REQFUNC("RegAuthFunc", g_fn_RegAuthFunc, PFN_REG_AUTH_FUNC); | ||||
| 	REQFUNC("UnregAuthFunc", g_fn_UnregAuthFunc, PFN_UNREG_AUTH_FUNC); | ||||
|  | ||||
| 	//Added in 1.75  | ||||
| 	REQFUNC("FindLibrary", g_fn_FindLibrary, PFN_FINDLIBRARY); | ||||
| 	REQFUNC("AddLibraries", g_fn_AddLibraries, PFN_ADDLIBRARIES); | ||||
| 	REQFUNC("RemoveLibraries", g_fn_RemoveLibraries, PFN_REMOVELIBRARIES); | ||||
| 	REQFUNC("OverrideNatives", g_fn_OverrideNatives, PFN_OVERRIDENATIVES); | ||||
| 	REQFUNC("GetLocalInfo", g_fn_GetLocalInfo, PFN_GETLOCALINFO); | ||||
| 	REQFUNC("AmxReregister", g_fn_AmxReRegister, PFN_AMX_REREGISTER); | ||||
|  | ||||
| 	REQFUNC("MessageBlock", g_fn_MessageBlock, PFN_MESSAGE_BLOCK); | ||||
|  | ||||
| #ifdef MEMORY_TEST | ||||
| 	// Memory | ||||
| @@ -2766,6 +2776,7 @@ void ValidateMacros_DontCallThis_Smiley() | ||||
| 	MF_GetPlayerEdict(0); | ||||
| 	MF_Format("", 4, "str"); | ||||
| 	MF_RegisterFunction(NULL, ""); | ||||
| 	MF_RegisterFunctionEx(NULL, ""); | ||||
| 	MF_SetPlayerTeamInfo(0, 0, ""); | ||||
| 	MF_PlayerPropAddr(0, 0); | ||||
| 	MF_RegAuthFunc(NULL); | ||||
| @@ -2773,7 +2784,8 @@ void ValidateMacros_DontCallThis_Smiley() | ||||
| 	MF_FindLibrary(NULL, LibType_Class); | ||||
| 	MF_AddLibraries(NULL, LibType_Class, NULL); | ||||
| 	MF_RemoveLibraries(NULL); | ||||
| 	MF_OverrideNatives(NULL, ""); | ||||
| 	MF_OverrideNatives(NULL, NULL); | ||||
| 	MF_MessageBlock(0, 0, NULL); | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -2095,9 +2095,16 @@ enum LibType | ||||
| 	LibType_Class | ||||
| }; | ||||
|  | ||||
| #define MSGBLOCK_SET	0 | ||||
| #define MSGBLOCK_GET	1 | ||||
| #define BLOCK_NOT 0 | ||||
| #define BLOCK_ONCE 1 | ||||
| #define BLOCK_SET 2 | ||||
|  | ||||
| typedef void (*AUTHORIZEFUNC)(int player, const char *authstring); | ||||
|  | ||||
| typedef int				(*PFN_ADD_NATIVES)				(const AMX_NATIVE_INFO * /*list*/); | ||||
| typedef int				(*PFN_ADD_NEW_NATIVES)			(const AMX_NATIVE_INFO * /*list*/); | ||||
| typedef char *			(*PFN_BUILD_PATHNAME)			(const char * /*format*/, ...); | ||||
| typedef char *			(*PFN_BUILD_PATHNAME_R)			(char * /*buffer*/, size_t /* maxlen */, const char * /* format */, ...); | ||||
| typedef cell *			(*PFN_GET_AMXADDR)				(AMX * /*amx*/, cell /*offset*/); | ||||
| @@ -2183,8 +2190,10 @@ typedef void			(*PFN_OVERRIDENATIVES)			(AMX_NATIVE_INFO * /*natives*/, const ch | ||||
| typedef const char *	(*PFN_GETLOCALINFO)				(const char * /*name*/, const char * /*def*/); | ||||
| typedef int				(*PFN_AMX_REREGISTER)			(AMX * /*amx*/, AMX_NATIVE_INFO * /*list*/, int /*list*/); | ||||
| typedef void *			(*PFN_REGISTERFUNCTIONEX)		(void * /*pfn*/, const char * /*desc*/); | ||||
| typedef void			(*PFN_MESSAGE_BLOCK)			(int /* mode */, int /* message */, int * /* opt */); | ||||
|  | ||||
| extern PFN_ADD_NATIVES				g_fn_AddNatives; | ||||
| extern PFN_ADD_NEW_NATIVES			g_fn_AddNewNatives; | ||||
| extern PFN_BUILD_PATHNAME			g_fn_BuildPathname; | ||||
| extern PFN_BUILD_PATHNAME_R			g_fn_BuildPathnameR; | ||||
| extern PFN_GET_AMXADDR				g_fn_GetAmxAddr; | ||||
| @@ -2257,11 +2266,13 @@ extern PFN_OVERRIDENATIVES			g_fn_OverrideNatives; | ||||
| extern PFN_GETLOCALINFO				g_fn_GetLocalInfo; | ||||
| extern PFN_AMX_REREGISTER			g_fn_AmxReRegister; | ||||
| extern PFN_REGISTERFUNCTIONEX		g_fn_RegisterFunctionEx; | ||||
| extern PFN_MESSAGE_BLOCK			g_fn_MessageBlock; | ||||
|  | ||||
| #ifdef MAY_NEVER_BE_DEFINED | ||||
| // Function prototypes for intellisense and similar systems | ||||
| // They understand #if 0 so we use #ifdef MAY_NEVER_BE_DEFINED | ||||
| int				MF_AddNatives				(const AMX_NATIVE_INFO *list) { } | ||||
| int				MF_AddNewNatives			(const AMX_NATIVE_INFO *list) { } | ||||
| char *			MF_BuildPathname			(const char * format, ...) { } | ||||
| char *			MF_BuildPathnameR			(char *buffer, size_t maxlen, const char *fmt, ...) { } | ||||
| cell *			MF_GetAmxAddr				(AMX * amx, cell offset) { } | ||||
| @@ -2328,9 +2339,11 @@ void			MF_OverrideNatives			(AMX_NATIVE_INFO *natives, const char *myname) { } | ||||
| const char *	MF_GetLocalInfo				(const char *name, const char *def) { } | ||||
| int				MF_AmxReRegister			(AMX *amx, AMX_NATIVE_INFO *list, int number) { return 0; } | ||||
| void *			MF_RegisterFunctionEx		(void *pfn, const char *description) { } | ||||
| void *			MF_MessageBlock				(int mode, int msg, int *opt) { } | ||||
| #endif	// MAY_NEVER_BE_DEFINED | ||||
|  | ||||
| #define MF_AddNatives g_fn_AddNatives | ||||
| #define MF_AddNewNatives g_fn_AddNewNatives | ||||
| #define MF_BuildPathname g_fn_BuildPathname | ||||
| #define MF_BuildPathnameR g_fn_BuildPathnameR | ||||
| #define MF_FormatAmxString g_fn_FormatAmxString | ||||
| @@ -2404,6 +2417,7 @@ void MF_LogError(AMX *amx, int err, const char *fmt, ...); | ||||
| #define MF_GetLocalInfo g_fn_GetLocalInfo | ||||
| #define MF_AmxReRegister g_fn_AmxReRegister | ||||
| #define MF_RegisterFunctionEx g_fn_RegisterFunctionEx | ||||
| #define MF_MessageBlock g_fn_MessageBlock | ||||
|  | ||||
| #ifdef MEMORY_TEST | ||||
| /*** Memory ***/ | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| #include "engine.h" | ||||
| #include "amxmod_compat.h" | ||||
|  | ||||
| struct usercmd_s *g_cmd; | ||||
| struct PlayerInfo plinfo[33]; | ||||
| @@ -97,11 +98,33 @@ static cell AMX_NATIVE_CALL halflife_time(AMX *amx, cell *params) | ||||
| 	return amx_ftoc(fVal); | ||||
| } | ||||
|  | ||||
| // RadiusDamage. Damages players within a certain radius. ToDo: add the | ||||
| // damage messaging so players know where the damage is coming from | ||||
| // (the red arrow-like things on the screen). | ||||
| //(vexd) | ||||
| static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) { | ||||
| //This is not exposed, and is only provided as a compatibility helper. | ||||
| static cell AMX_NATIVE_CALL RadiusDamage_AMXMod(AMX *amx, cell *params) | ||||
| { | ||||
| 	int ent = params[1]; | ||||
| 	CHECK_ENTITY_SIMPLE(ent); | ||||
| 	edict_t* pEntity = INDEXENT(ent); | ||||
| 	float dmg = amx_ctof(params[2]); | ||||
| 	cell *vInput = MF_GetAmxAddr(amx, params[3]); | ||||
| 	float vOrig[3]; | ||||
|  | ||||
| 	vOrig[0] = amx_ctof(vInput[0]); | ||||
| 	vOrig[1] = amx_ctof(vInput[1]); | ||||
| 	vOrig[2] = amx_ctof(vInput[2]); | ||||
|  | ||||
| 	float rad = amx_ctof(params[4]); | ||||
| 	int bit = params[5]; | ||||
| 	int iLen; | ||||
| 	char *vxWeapon = MF_GetAmxString(amx, params[6], 0, &iLen); | ||||
| 	int hs = params[7]; | ||||
|  | ||||
| 	RadiusDamage_AMXMod_Base(pEntity, dmg, vOrig, rad, bit, vxWeapon, hs); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL RadiusDamage_AMXModX(AMX *amx, cell *params) | ||||
| { | ||||
| 	cell *cAddr = MF_GetAmxAddr(amx,params[1]); | ||||
|  | ||||
| 	REAL fCurrentX = amx_ctof(cAddr[0]); | ||||
| @@ -164,6 +187,24 @@ static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) { | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| // RadiusDamage. Damages players within a certain radius. ToDo: add the | ||||
| // damage messaging so players know where the damage is coming from | ||||
| // (the red arrow-like things on the screen). | ||||
| //(vexd) | ||||
| static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) | ||||
| { | ||||
| 	cell numParams = params[0] / sizeof(cell); | ||||
|  | ||||
| 	if (numParams == 3) | ||||
| 	{ | ||||
| 		return RadiusDamage_AMXModX(amx, params); | ||||
| 	} else if (numParams == 7) { | ||||
| 		return RadiusDamage_AMXMod(amx, params); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static cell AMX_NATIVE_CALL PointContents(AMX *amx, cell *params) | ||||
| { | ||||
| 	cell *cAddr = MF_GetAmxAddr(amx, params[1]); | ||||
| @@ -926,6 +967,12 @@ static cell AMX_NATIVE_CALL trace_forward(AMX *amx, cell *params) | ||||
|    return 1; | ||||
| } | ||||
|  | ||||
| AMX_NATIVE_INFO engine_NewNatives[] =  | ||||
| { | ||||
| 	{"trace_line",			trace_line}, | ||||
| 	{NULL,					NULL} | ||||
| }; | ||||
|  | ||||
| AMX_NATIVE_INFO engine_Natives[] = { | ||||
| 	{"halflife_time",		halflife_time}, | ||||
|  | ||||
| @@ -934,7 +981,6 @@ AMX_NATIVE_INFO engine_Natives[] = { | ||||
| 	{"radius_damage",		RadiusDamage}, | ||||
| 	{"point_contents",		PointContents}, | ||||
| 	{"trace_normal",		trace_normal}, | ||||
| 	{"trace_line",			trace_line}, | ||||
| 	{"trace_hull",			trace_hull}, | ||||
| 	{"traceresult",			traceresult}, | ||||
|  | ||||
| @@ -965,6 +1011,6 @@ AMX_NATIVE_INFO engine_Natives[] = { | ||||
| 	{"is_visible",			is_visible}, | ||||
| 	{"trace_forward",		trace_forward}, | ||||
|  | ||||
| 	{NULL,					NULL}, | ||||
| 	{NULL,					NULL} | ||||
| 	 /////////////////// | ||||
| }; | ||||
|   | ||||
| @@ -210,6 +210,7 @@ extern struct usercmd_s *g_cmd; | ||||
| extern struct PlayerInfo plinfo[33]; | ||||
| extern struct GlobalInfo glinfo; | ||||
| extern AMX_NATIVE_INFO engine_Natives[]; | ||||
| extern AMX_NATIVE_INFO engine_NewNatives[]; | ||||
| extern CVector<Impulse *> Impulses; | ||||
| extern CVector<EntClass *> Thinks; | ||||
| extern CVector<Touch *> Touches; | ||||
|   | ||||
| @@ -117,6 +117,9 @@ | ||||
| 			Name="Source Files" | ||||
| 			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" | ||||
| 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> | ||||
| 			<File | ||||
| 				RelativePath=".\amxmod_compat.cpp"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath=".\amxxapi.cpp"> | ||||
| 			</File> | ||||
| @@ -137,6 +140,9 @@ | ||||
| 			Name="Header Files" | ||||
| 			Filter="h;hpp;hxx;hm;inl;inc;xsd" | ||||
| 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> | ||||
| 			<File | ||||
| 				RelativePath=".\amxmod_compat.h"> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath=".\CString.h"> | ||||
| 			</File> | ||||
|   | ||||
| @@ -1509,6 +1509,12 @@ static cell AMX_NATIVE_CALL get_grenade_id(AMX *amx, cell *params)  /* 4 param * | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| AMX_NATIVE_INFO ent_NewNatives[] = | ||||
| { | ||||
| 	{"DispatchKeyValue",	DispatchKeyValue}, | ||||
| 	{NULL,					NULL} | ||||
| }; | ||||
|  | ||||
| AMX_NATIVE_INFO ent_Natives[] = { | ||||
| 	{"create_entity",		create_entity}, | ||||
| 	{"remove_entity",		remove_entity}, | ||||
| @@ -1532,7 +1538,6 @@ AMX_NATIVE_INFO ent_Natives[] = { | ||||
| 	{"entity_set_origin",	entity_set_origin}, | ||||
| 	{"entity_set_model",	entity_set_model}, | ||||
| 	{"entity_set_size",		entity_set_size}, | ||||
| 	{"DispatchKeyValue",	DispatchKeyValue}, | ||||
| 	{"DispatchSpawn",		DispatchSpawn}, | ||||
|  | ||||
| 	{"call_think",			call_think}, | ||||
| @@ -1554,7 +1559,7 @@ AMX_NATIVE_INFO ent_Natives[] = { | ||||
|  | ||||
| 	{"copy_keyvalue",		copy_keyvalue}, | ||||
|  | ||||
| 	{NULL,					NULL}, | ||||
| 	{NULL,					NULL} | ||||
| 	 /////////////////// | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -151,6 +151,7 @@ enum { | ||||
| void UTIL_SetSize(edict_t *pev, const Vector &vecMin, const Vector &vecMax); | ||||
|  | ||||
| extern AMX_NATIVE_INFO ent_Natives[]; | ||||
| extern AMX_NATIVE_INFO ent_NewNatives[]; | ||||
|  | ||||
| #endif //_INCLUDE_ENGINE_ENTSTUFF | ||||
|  | ||||
|   | ||||
| @@ -1,104 +0,0 @@ | ||||
| /* Vexd Utility backwards compatibility | ||||
| * | ||||
| * by the AMX Mod X Development Team | ||||
| * | ||||
| * This file is provided as is (no warranties). | ||||
| */ | ||||
|  | ||||
| #if defined _Vexd_Utilities_included | ||||
|   #endinput | ||||
| #endif | ||||
| #define _Vexd_Utilities_included | ||||
|  | ||||
| #include <engine> | ||||
|  | ||||
| stock Entvars_Get_Int(iIndex, iVariable) | ||||
| 	return entity_get_int(iIndex, iVariable) | ||||
|  | ||||
| stock Entvars_Set_Int(iIndex, iVariable, iNewValue) | ||||
| 	return entity_set_int(iIndex, iVariable, iNewValue) | ||||
|  | ||||
| stock Float:Entvars_Get_Float(iIndex, iVariable) | ||||
| 	return entity_get_float(iIndex, iVariable) | ||||
|  | ||||
| stock Entvars_Set_Float(iIndex, iVariable, Float:fNewValue) | ||||
| 	return entity_set_float(iIndex, iVariable, fNewValue) | ||||
|  | ||||
| stock Entvars_Get_Vector(iIndex, iVariable, Float:vRetVector[3]) | ||||
| 	return entity_get_vector(iIndex, iVariable, vRetVector) | ||||
|  | ||||
| stock Entvars_Set_Vector(iIndex, iVariable, Float:vNewVector[3]) | ||||
| 	return entity_set_vector(iIndex, iVariable, vNewVector) | ||||
|  | ||||
| stock Entvars_Get_Edict(iIndex, iVariable) | ||||
| 	return entity_get_edict(iIndex, iVariable) | ||||
|  | ||||
| stock Entvars_Set_Edict(iIndex, iVariable, iNewIndex) | ||||
| 	return entity_set_edict(iIndex, iVariable, iNewIndex) | ||||
|  | ||||
| stock Entvars_Get_String(iIndex, iVariable, szReturnValue[], iReturnLen) | ||||
| 	return entity_get_string(iIndex, iVariable, szReturnValue, iReturnLen) | ||||
|  | ||||
| stock Entvars_Set_String(iIndex, iVariable, szNewValue[]) | ||||
| 	return entity_set_string(iIndex, iVariable, szNewValue) | ||||
|  | ||||
| stock Entvars_Get_Byte(iIndex, iVariable) | ||||
| 	return entity_get_byte(iIndex, iVariable) | ||||
|  | ||||
| stock Entvars_Set_Byte(iIndex, iVariable, iNewValue) | ||||
| 	return entity_set_byte(iIndex, iVariable, iNewValue) | ||||
|  | ||||
| stock CreateEntity(szClassname[]) | ||||
| 	return create_entity(szClassname) | ||||
|  | ||||
| stock ENT_SetModel(iIndex, szModel[]) | ||||
| 	return entity_set_model(iIndex, szModel) | ||||
|  | ||||
| stock ENT_SetOrigin(iIndex, Float:fNewOrigin[3]) | ||||
| 	return entity_set_origin(iIndex, fNewOrigin) | ||||
|  | ||||
| stock FindEntity(iIndex, szValue[]) | ||||
| 	return find_ent_by_class(iIndex, szValue) | ||||
|  | ||||
| stock RemoveEntity(iIndex) | ||||
| 	return remove_entity(iIndex) | ||||
|  | ||||
| stock TraceLn(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]) | ||||
| 	return trace_line(iIgnoreEnt, fStart, fEnd, vReturn) | ||||
|  | ||||
| stock TraceNormal(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]) | ||||
| 	return trace_normal(iIgnoreEnt, fStart, fEnd, vReturn) | ||||
|  | ||||
| stock VecToAngles(Float:fVector[3], Float:vReturn[3]) | ||||
| 	return vector_to_angle(fVector, vReturn) | ||||
|  | ||||
| stock Float:VecLength(Float:vVector[3]) | ||||
| 	return vector_length(vVector) | ||||
|  | ||||
| stock Float:VecDist(Float:vVector[3], Float:vVector2[3]) | ||||
| 	return vector_distance(vVector, vVector2) | ||||
|  | ||||
| stock MessageBlock(iMessage, iMessageFlags) | ||||
| 	return set_msg_block(iMessage, iMessageFlags) | ||||
|  | ||||
| stock GetMessageBlock(iMessage) | ||||
| 	return get_msg_block(iMessage) | ||||
|  | ||||
| stock Float:HLTime() | ||||
| 	return halflife_time() | ||||
|  | ||||
| stock FakeTouch(iToucher, iTouched) | ||||
| 	return fake_touch(iToucher, iTouched) | ||||
|  | ||||
| stock AttachView(iIndex, iTargetIndex) | ||||
| 	return attach_view(iIndex, iTargetIndex) | ||||
|  | ||||
| stock SetView(iIndex, ViewType) | ||||
| 	return set_view(iIndex, ViewType) | ||||
|  | ||||
| stock SetSpeak(iIndex, iSpeakFlags) | ||||
| 	return set_speak(iIndex, iSpeakFlags) | ||||
|  | ||||
| forward vexd_pfntouch(pToucher, pTouched) | ||||
|  | ||||
| forward ServerFrame() | ||||
| @@ -11,6 +11,14 @@ | ||||
| #endif | ||||
| #define _amxmisc_included | ||||
|  | ||||
| #if defined AMXMOD_BCOMPAT | ||||
| #if defined _translator_included | ||||
| #define SIMPLE_T(%1)	_T(%1) | ||||
| #else | ||||
| #define SIMPLE_T(%1)	%1 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| stock is_user_admin(id) | ||||
| { | ||||
|   return ( get_user_flags(id)>0 && !(get_user_flags(id)&ADMIN_USER) ) | ||||
| @@ -30,13 +38,21 @@ stock cmd_access(id,level,cid,num) { | ||||
|   } | ||||
|  | ||||
|   if ( has_access==0 ) { | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|     console_print(id, SIMPLE_T("You have no access to that command.")) | ||||
| #else | ||||
|     console_print(id,"%L",id,"NO_ACC_COM") | ||||
| #endif | ||||
|     return 0 | ||||
|   } | ||||
|   if (read_argc() < num) { | ||||
|     new hcmd[32], hinfo[128], hflag | ||||
|     get_concmd(cid,hcmd,31,hflag,hinfo,127,level) | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|     console_print(id, SIMPLE_T("Usage:  %s %s"), hcmd, SIMPLE_T(hinfo)) | ||||
| #else | ||||
|     console_print(id,"%L:  %s %s",id,"USAGE",hcmd,hinfo) | ||||
| #endif | ||||
|     return 0 | ||||
|   } | ||||
|   return 1 | ||||
| @@ -58,21 +74,33 @@ stock cmd_target(id,const arg[],flags = 1) { | ||||
|   new player = find_player("bl",arg) | ||||
|   if (player) { | ||||
|     if ( player != find_player("blj",arg) ) { | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|       console_print(id, SIMPLE_T("There are more clients matching to your argument")) | ||||
| #else | ||||
|       console_print(id,"%L",id,"MORE_CL_MATCHT") | ||||
| #endif | ||||
|       return 0 | ||||
|     } | ||||
|   } | ||||
|   else if ( ( player = find_player("c",arg) )==0 && arg[0]=='#' && arg[1] ) | ||||
|     player = find_player("k",str_to_num(arg[1])) | ||||
|   if (!player) { | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|     console_print(id, SIMPLE_T("Client with that name or userid not found")) | ||||
| #else | ||||
|     console_print(id,"%L",id,"CL_NOT_FOUND") | ||||
| #endif | ||||
|     return 0 | ||||
|   } | ||||
|   if (flags & 1) { | ||||
|     if ((get_user_flags(player)&ADMIN_IMMUNITY) && ((flags&2)?(id!=player):true) ) { | ||||
|       new imname[32] | ||||
|       get_user_name(player,imname,31) | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|       console_print(id, SIMPLE_T("Client ^"%s^" has immunity"), imname) | ||||
| #else | ||||
|       console_print(id,"%L",id,"CLIENT_IMM",imname) | ||||
| #endif | ||||
|       return 0 | ||||
|     } | ||||
|   } | ||||
| @@ -80,7 +108,11 @@ stock cmd_target(id,const arg[],flags = 1) { | ||||
|     if (!is_user_alive(player)) { | ||||
|       new imname[32] | ||||
|       get_user_name(player,imname,31) | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|       console_print(id, SIMPLE_T("That action can't be performed on dead client ^"%s^""), imname) | ||||
| #else | ||||
|       console_print(id,"%L",id,"CANT_PERF_DEAD",imname) | ||||
| #endif | ||||
|       return 0 | ||||
|     } | ||||
|   } | ||||
| @@ -88,7 +120,11 @@ stock cmd_target(id,const arg[],flags = 1) { | ||||
|     if (is_user_bot(player)) { | ||||
|       new imname[32] | ||||
|       get_user_name(player,imname,31) | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|       console_print(id, SIMPLE_T("That action can't be performed on bot ^"%s^""), imname) | ||||
| #else | ||||
|       console_print(id,"%L",id,"CANT_PERF_BOT",imname) | ||||
| #endif | ||||
|       return 0 | ||||
|     } | ||||
|   } | ||||
| @@ -98,11 +134,20 @@ stock cmd_target(id,const arg[],flags = 1) { | ||||
| stock show_activity( id, const name[], {Float,_}: ... ) { | ||||
|   new buffer[128] | ||||
|   format_args( buffer , 127 , 2 ) | ||||
|   switch(get_cvar_num("amx_show_activity")) { | ||||
|     case 2: client_print(0,print_chat,"%L %s: %s", | ||||
|       id, is_user_admin(id) ? "ADMIN" : "PLAYER" , name , buffer ) | ||||
|     case 1: client_print(0,print_chat,"%L: %s", | ||||
|       id, is_user_admin(id) ? "ADMIN" : "PLAYER", buffer ) | ||||
|   switch(get_cvar_num("amx_show_activity")) | ||||
|   { | ||||
|     case 2: | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|        client_print(0, print_chat, "%s %s: %s", is_user_admin(id) ? SIMPLE_T("ADMIN") : SIMPLE_T("PLAYER"), name, buffer) | ||||
| #else | ||||
|        client_print(0, print_chat, "%L %s: %s", id, is_user_admin(id) ? "ADMIN" : "PLAYER" , name , buffer ) | ||||
| #endif | ||||
|     case 1:  | ||||
| #if defined AMXMOD_BCOMPAT | ||||
|        client_print(0, print_chat, "%s: %s", is_user_admin(id) ? SIMPLE_T("ADMIN") : SIMPLE_T("PLAYER"), buffer) | ||||
| #else | ||||
|        client_print(0, print_chat, "%L: %s", id, is_user_admin(id) ? "ADMIN" : "PLAYER", buffer ) | ||||
| #endif | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,42 +0,0 @@ | ||||
| /* AMX Mod X Backwards Compatibility | ||||
| * | ||||
| * by the AMX Mod X Development Team | ||||
| * | ||||
| * This file is provided as is (no warranties). | ||||
| */ | ||||
|  | ||||
| #if defined _amxmod_included | ||||
|   #endinput | ||||
| #endif | ||||
| #define _amxmod_included | ||||
|  | ||||
| #include <amxmodx> | ||||
| #include <cstrike> | ||||
| #include <engine> | ||||
| #include <fun> | ||||
|  | ||||
| stock user_spawn(index) | ||||
|   return spawn(index) | ||||
|  | ||||
| stock get_logfile( name[], len ) | ||||
|   return get_time("admin%m%d.log",name,len) | ||||
|  | ||||
| stock get_user_money(index) | ||||
|   return cs_get_user_money(index) | ||||
|  | ||||
| stock set_user_money(index,money,flash=1) | ||||
|   return cs_set_user_money(index,money,flash) | ||||
|  | ||||
| stock numtostr(num,string[],len) | ||||
|   return num_to_str(num,string,len) | ||||
|  | ||||
| stock strtonum(const string[]) | ||||
|   return str_to_num(string) | ||||
|  | ||||
| stock build_path( path[] , len , {Float,_}:... ) | ||||
| { | ||||
|   new basedir[32] | ||||
|   get_localinfo("amxx_basedir",basedir,31) | ||||
|   format_args(path,len,2) | ||||
|   return replace(path,len,"$basedir",basedir) | ||||
| } | ||||
| @@ -121,7 +121,9 @@ native fake_touch(entTouched, entToucher); | ||||
| /* 2 formats. | ||||
|    Format: DispatchKeyValue("KeyName","Value") - sets keyvalues for the entity specified in the keyvalue() forward. | ||||
|    Format: DispatchKeyValue(index,"KeyName","Value") - Sets keyvalue for entity not specified in keyvalue() forward. */ | ||||
| #if !defined AMXMOD_BCOMPAT | ||||
| native DispatchKeyValue(...); | ||||
| #endif | ||||
|  | ||||
| native get_keyvalue(entity, szKey[], value[], maxLength); | ||||
|  | ||||
| @@ -131,14 +133,18 @@ native copy_keyvalue(szClassName[],sizea,szKeyName[],sizeb,szValue[],sizec); | ||||
| native DispatchSpawn(iIndex); | ||||
|  | ||||
| /* Hurts/Kills players in a sphere, like an explosion, Multiplier determines damage. */ | ||||
| #if !defined AMXMOD_BCOMPAT | ||||
| native radius_damage(Float:fExplodeAt[3], iDamageMultiplier, iRadiusMultiplier); | ||||
| #endif | ||||
|  | ||||
| /* Will return the contents of a point (inside map? in sky? outside map? etc.). */ | ||||
| native point_contents(Float:fCheckAt[3]); | ||||
|  | ||||
| /* Trace a line from Start(X, Y, Z) to End(X, Y, Z), will return the point hit in vReturn[3] | ||||
|  * and an entity index if an entity is hit. */ | ||||
| #if !defined AMXMOD_BCOMPAT | ||||
| native trace_line(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]); | ||||
| #endif | ||||
|  | ||||
| /* Traces a hull. */ | ||||
| native trace_hull(Float:origin[3],hull,ignoredent=0,ignoremonsters=0); | ||||
|   | ||||
| @@ -66,14 +66,22 @@ native Float:floatpower(Float:value, Float:exponent); | ||||
| native Float:floatlog(Float:value, Float:base=10.0); | ||||
|  | ||||
| /* Return the sine, cosine or tangent. | ||||
| * The input angle may be in radian, degrees or grades. */ | ||||
|  * The input angle may be in radians, degrees or grades. */ | ||||
| native Float:floatsin(Float:value, anglemode:mode=radian); | ||||
| native Float:floatcos(Float:value, anglemode:mode=radian); | ||||
| native Float:floattan(Float:value, anglemode:mode=radian); | ||||
|  | ||||
| /* Return the hyperbolic sine, cosine or tangent. | ||||
|  * The input angle may be in radians, degrees or grades. */ | ||||
| native Float:floatsinh(Float:angle, anglemode:mode=radian); | ||||
| native Float:floatcosh(Float:angle, anglemode:mode=radian); | ||||
| native Float:floattanh(Float:angle, anglemode:mode=radian); | ||||
|  | ||||
| /* Return the absolute value */ | ||||
| native Float:floatabs(Float:value); | ||||
|  | ||||
| /* Return the angle of a sine, cosine or tangent. | ||||
|  * The output angle may be in radians, degrees, or grades. */ | ||||
| native Float:floatatan(Float:angle, radix); | ||||
| native Float:floatacos(Float:angle, radix); | ||||
| native Float:floatasin(Float:angle, radix); | ||||
|   | ||||
| @@ -159,6 +159,12 @@ | ||||
| #define DMG_MORTAR                      (1<<23)     // Hit by air raid (done to distinguish grenade from mortar) | ||||
| #define DMG_TIMEBASED                   (~(0x3fff)) // Mask for time-based damage | ||||
|  | ||||
| // The fNoMonsters parameter of EngFunc_TraceLine, EngFunc_TraceMonsterHull, EngFunc_TraceHull, and EngFunc_TraceSphere | ||||
| #define DONT_IGNORE_MONSTERS            0 | ||||
| #define IGNORE_MONSTERS                 1 | ||||
| #define IGNORE_MISSILE                  2 | ||||
| #define IGNORE_GLASS                    0x100 | ||||
|  | ||||
| // The hullnumber paramater of EngFunc_TraceHull, EngFunc_TraceModel and DLLFunc_GetHullBounds | ||||
| #define HULL_POINT                      0 | ||||
| #define HULL_HUMAN                      1 | ||||
|   | ||||
| @@ -1,95 +0,0 @@ | ||||
| /* Xtrafun backwards compatibility | ||||
| * | ||||
| * by the AMX Mod X Development Team | ||||
| * These natives were originally made by SpaceDude, EJ, and JustinHoMi. | ||||
| * | ||||
| * This file is provided as is (no warranties). | ||||
| */ | ||||
|  | ||||
| #if !defined _xtrafun_included | ||||
| 	#define _xtrafun_included | ||||
|  | ||||
| #if !defined _engine_included | ||||
| 	#include <engine.inc> | ||||
| #endif | ||||
|  | ||||
| /* Gets the velocity of an entity */ | ||||
| stock get_entity_velocity(index, velocity[3]) { | ||||
| 	new Float:vector[3] | ||||
| 	entity_get_vector(index, EV_VEC_velocity, vector) | ||||
| 	FVecIVec(vector, velocity) | ||||
| } | ||||
|  | ||||
| /* Sets the velocity of an entity */ | ||||
| stock set_entity_velocity(index, velocity[3]) { | ||||
| 	new Float:vector[3] | ||||
| 	IVecFVec(velocity, vector) | ||||
| 	entity_set_vector(index, EV_VEC_velocity, vector) | ||||
| } | ||||
|  | ||||
| /* Gets the origin of an entity */ | ||||
| stock get_entity_origin(index, origin[3]) { | ||||
| 	new Float:vector[3] | ||||
| 	entity_get_vector(index, EV_VEC_origin, vector) | ||||
| 	FVecIVec(vector, origin) | ||||
| } | ||||
|  | ||||
| /* Sets the origin of an entity */ | ||||
| stock set_entity_origin(index, origin[3]) { | ||||
| 	new Float:vector[3] | ||||
| 	IVecFVec(origin, vector) | ||||
| 	entity_set_vector(index, EV_VEC_origin, vector) | ||||
| } | ||||
|  | ||||
| /* Get the index of the grenade belonging to index. | ||||
|  * Model of grenade is returned in model[]. | ||||
|  * Specify the grenadeindex to start searching from, | ||||
|  * or leave it at 0 to search from the start. | ||||
|  * Returns grenade index. | ||||
|  * Paths + models of grenades in Counter-Strike: | ||||
|  * HEGRENADE = "models/w_hegrenade.mdl" | ||||
|  * FLASHBANG = "models/w_flashbang.mdl" | ||||
|  * SMOKEGRENADE = "models/w_smokegrenade.mdl" */ | ||||
| stock get_grenade_index(index, model[], len, grenadeindex = 0) { | ||||
| 	new entfind = grenadeindex | ||||
| 	new entowner = index | ||||
|  | ||||
| 	for (;;) { | ||||
| 		entfind = find_ent_by_class(entfind, "grenade") | ||||
|  | ||||
| 		if (entfind && is_valid_ent(entfind)) { | ||||
| 			if (entity_get_edict(entFind, EV_ENT_owner) == entowner) { | ||||
| 				entity_get_string(entfind, EV_SZ_model, model) | ||||
| 				return entfind | ||||
| 			} | ||||
| 		} | ||||
| 		else { | ||||
| 			// Eventually comes here if loop fails to find a grenade with specified owner. | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Find the number of entities in the game */ | ||||
| stock current_num_ents() { | ||||
| 	return entity_count(); | ||||
| } | ||||
|  | ||||
| enum { | ||||
|    classname = 0, | ||||
|    target, | ||||
|    targetname | ||||
| } | ||||
|  | ||||
| /* Find an entity ID from start_from_ent id (use 0 to start from | ||||
|  * the beginning, category is either "classname", "target" or | ||||
|  * "targetname", value is the name you are searching for */ | ||||
| stock find_entity(start_from_ent, category, value[]) { | ||||
| 	switch (category) { | ||||
| 		case target: return find_ent_by_target(start_from_ent, value) | ||||
| 		case targetname: return find_ent_by_tname(start_from_ent, value) | ||||
| 	} | ||||
| 	return find_ent_by_class(start_from_ent, value) | ||||
| } | ||||
|  | ||||
| #endif // _xtrafun_included | ||||
		Reference in New Issue
	
	Block a user