initial commit: change in oryx is only outcommenting KickClient. Change in oryx-scroll is changing the message send to the native
This commit is contained in:
		
							parent
							
								
									153f1c28ce
								
							
						
					
					
						commit
						2c5820dd3d
					
				
							
								
								
									
										38
									
								
								oryx-mini-edit/scripting/include/bTimes-tas.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								oryx-mini-edit/scripting/include/bTimes-tas.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| #if defined _tas_included
 | ||||
|   #endinput
 | ||||
| #endif
 | ||||
| #define _tas_included
 | ||||
| 
 | ||||
| native bool      TAS_InEditMode(int client); | ||||
| 
 | ||||
| native bool      TAS_IsPaused(int client); | ||||
| 
 | ||||
| native ArrayList TAS_GetRunHandle(int client); | ||||
| 
 | ||||
| native int       TAS_GetCurrentFrame(int client); | ||||
| 
 | ||||
| forward void OnTASPauseChanged(int client, bool paused); | ||||
| 
 | ||||
| forward void OnTASFrameRecorded(int client, int frame); | ||||
| 
 | ||||
| public SharedPlugin __pl_tas =  | ||||
| { | ||||
| 	name = "tas", | ||||
| 	file = "bTimes-tas.smx", | ||||
| #if defined REQUIRE_PLUGIN
 | ||||
| 	required = 1, | ||||
| #else
 | ||||
| 	required = 0, | ||||
| #endif
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #if !defined REQUIRE_PLUGIN
 | ||||
| public void __pl_tas_SetNTVOptional() | ||||
| { | ||||
| 	MarkNativeAsOptional("TAS_InEditMode"); | ||||
| 	MarkNativeAsOptional("TAS_IsPaused"); | ||||
| 	MarkNativeAsOptional("TAS_GetRunHandle"); | ||||
| 	MarkNativeAsOptional("TAS_GetCurrentFrame"); | ||||
| } | ||||
| #endif
 | ||||
							
								
								
									
										89
									
								
								oryx-mini-edit/scripting/include/bTimes-timer_hack.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								oryx-mini-edit/scripting/include/bTimes-timer_hack.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| #if defined _btimes_timer_included
 | ||||
|   #endinput
 | ||||
| #endif
 | ||||
| #define _btimes_timer_included
 | ||||
| 
 | ||||
| enum styleConfig | ||||
| { | ||||
| 	String:Name[32], | ||||
| 	String:Name_Short[32], | ||||
| 	bool:Enabled, | ||||
| 	bool:TempEnabled, | ||||
| 	bool:AllowType[2], | ||||
| 	bool:Freestyle, | ||||
| 	bool:Freestyle_Unrestrict, | ||||
| 	bool:Freestyle_EzHop, | ||||
| 	bool:Freestyle_Auto, | ||||
| 	bool:Auto, | ||||
| 	bool:EzHop, | ||||
| 	Float:Gravity, | ||||
| 	Float:RunSpeed, | ||||
| 	Float:MaxVel, | ||||
| 	Float:MinFps, | ||||
| 	bool:CalcSync, | ||||
| 	bool:Prevent_Left, | ||||
| 	bool:Prevent_Right, | ||||
| 	bool:Prevent_Back, | ||||
| 	bool:Prevent_Forward, | ||||
| 	bool:Require_Left, | ||||
| 	bool:Require_Right, | ||||
| 	bool:Require_Back, | ||||
| 	bool:Require_Forward, | ||||
| 	bool:Hud_Style, | ||||
| 	bool:Hud_Strafes, | ||||
| 	bool:Hud_Jumps, | ||||
| 	bool:Count_Left_Strafe, | ||||
| 	bool:Count_Right_Strafe, | ||||
| 	bool:Count_Back_Strafe, | ||||
| 	bool:Count_Forward_Strafe, | ||||
| 	bool:Ghost_Use[2], | ||||
| 	bool:Ghost_Save[2], | ||||
| 	Float:PreSpeed, | ||||
| 	Float:SlowedSpeed, | ||||
| 	bool:Special, | ||||
| 	String:Special_Key[32], | ||||
| 	bool:GunJump, | ||||
| 	String:GunJump_Weapon[64], | ||||
| 	bool:UnrealPhys, | ||||
| 	AirAcceleration, | ||||
| 	bool:EnableBunnyhopping, | ||||
| 	StyleConfig | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
| * Gets a client's style (Normal, Sideways, etc..). | ||||
| *  | ||||
| * @param client        Client index | ||||
| *  | ||||
| * @return              The client's style. | ||||
| */ | ||||
| native int GetClientStyle(int client); | ||||
| 
 | ||||
| /* | ||||
| * Gets the complete configuration for a specified style. | ||||
| *  | ||||
| * @param Style         The style to get a configuration for. | ||||
| * @param Properties    The buffer to store all the style properties, (properties are listed in the StyleConfig enum) | ||||
| *  | ||||
| * @return              True if the style exists, false otherwise. | ||||
| */ | ||||
| native bool Style_GetConfig(int Style, any Properties[StyleConfig]); | ||||
| 
 | ||||
| public SharedPlugin __pl_btimes_timer = | ||||
| { | ||||
| 	name = "timer", | ||||
| 	file = "bTimes-timer.smx", | ||||
| #if defined REQUIRE_PLUGIN
 | ||||
| 	required = 1 | ||||
| #else
 | ||||
| 	required = 0 | ||||
| #endif
 | ||||
| }; | ||||
| 
 | ||||
| #if !defined REQUIRE_PLUGIN
 | ||||
| public void __pl_btimes_timer_SetNTVOptional() | ||||
| { | ||||
| 	MarkNativeAsOptional("GetClientStyle"); | ||||
| 	MarkNativeAsOptional("Style_GetConfig"); | ||||
| } | ||||
| #endif
 | ||||
							
								
								
									
										484
									
								
								oryx-mini-edit/scripting/include/dhooks.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										484
									
								
								oryx-mini-edit/scripting/include/dhooks.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,484 @@ | ||||
| // code by Dr!fter https://forums.alliedmods.net/showthread.php?t=180114
 | ||||
| 
 | ||||
| #if defined _dhooks_included
 | ||||
| #endinput
 | ||||
| #endif
 | ||||
| #define _dhooks_included
 | ||||
| 
 | ||||
| enum ObjectValueType | ||||
| { | ||||
| 	ObjectValueType_Int = 0, | ||||
| 	ObjectValueType_Bool, | ||||
| 	ObjectValueType_Ehandle, | ||||
| 	ObjectValueType_Float, | ||||
| 	ObjectValueType_CBaseEntityPtr, | ||||
| 	ObjectValueType_IntPtr, | ||||
| 	ObjectValueType_BoolPtr, | ||||
| 	ObjectValueType_EhandlePtr, | ||||
| 	ObjectValueType_FloatPtr, | ||||
| 	ObjectValueType_Vector, | ||||
| 	ObjectValueType_VectorPtr, | ||||
| 	ObjectValueType_CharPtr, | ||||
| 	ObjectValueType_String | ||||
| }; | ||||
| 
 | ||||
| enum ListenType | ||||
| { | ||||
| 	ListenType_Created, | ||||
| 	ListenType_Deleted | ||||
| }; | ||||
| 
 | ||||
| enum ReturnType | ||||
| { | ||||
| 	ReturnType_Unknown, | ||||
| 	ReturnType_Void, | ||||
| 	ReturnType_Int, | ||||
| 	ReturnType_Bool, | ||||
| 	ReturnType_Float, | ||||
| 	ReturnType_String, //Note this is a string_t
 | ||||
| 	ReturnType_StringPtr, //Note this is a string_t *
 | ||||
| 	ReturnType_CharPtr, | ||||
| 	ReturnType_Vector, | ||||
| 	ReturnType_VectorPtr, | ||||
| 	ReturnType_CBaseEntity, | ||||
| 	ReturnType_Edict | ||||
| }; | ||||
| 
 | ||||
| enum HookParamType | ||||
| { | ||||
| 	HookParamType_Unknown, | ||||
| 	HookParamType_Int, | ||||
| 	HookParamType_Bool, | ||||
| 	HookParamType_Float, | ||||
| 	HookParamType_String, //Note this is a string_t
 | ||||
| 	HookParamType_StringPtr, //Note this is a string_t *
 | ||||
| 	HookParamType_CharPtr, | ||||
| 	HookParamType_VectorPtr, | ||||
| 	HookParamType_CBaseEntity, | ||||
| 	HookParamType_ObjectPtr, | ||||
| 	HookParamType_Edict, | ||||
| 	HookParamType_Object | ||||
| }; | ||||
| 
 | ||||
| enum ThisPointerType | ||||
| { | ||||
| 	ThisPointer_Ignore, | ||||
| 	ThisPointer_CBaseEntity, | ||||
| 	ThisPointer_Address | ||||
| }; | ||||
| 
 | ||||
| enum HookType | ||||
| { | ||||
| 	HookType_Entity, | ||||
| 	HookType_GameRules, | ||||
| 	HookType_Raw | ||||
| }; | ||||
| 
 | ||||
| enum MRESReturn | ||||
| { | ||||
| 	MRES_ChangedHandled = -2,	// Use changed values and return MRES_Handled
 | ||||
| 	MRES_ChangedOverride,		// Use changed values and return MRES_Override
 | ||||
| 	MRES_Ignored,				// plugin didn't take any action
 | ||||
| 	MRES_Handled,				// plugin did something, but real function should still be called
 | ||||
| 	MRES_Override,				// call real function, but use my return value
 | ||||
| 	MRES_Supercede				// skip real function; use my return value
 | ||||
| }; | ||||
| 
 | ||||
| enum DHookPassFlag | ||||
| { | ||||
| 	DHookPass_ByVal = (1<<0), | ||||
| 	DHookPass_ByRef = (1<<1) | ||||
| }; | ||||
| 
 | ||||
| typeset ListenCB | ||||
| { | ||||
| 	//Deleted
 | ||||
| 	function void (int entity); | ||||
| 
 | ||||
| 	//Created
 | ||||
| 	function void (int entity, const char[] classname); | ||||
| }; | ||||
| 
 | ||||
| typeset DHookRemovalCB | ||||
| { | ||||
| 	function void (int hookid); | ||||
| }; | ||||
| typeset DHookCallback | ||||
| { | ||||
| 	//Function Example: void Ham::Test() with this pointer ignore
 | ||||
| 	function MRESReturn (); | ||||
| 
 | ||||
| 	//Function Example: void Ham::Test() with this pointer passed
 | ||||
| 	function MRESReturn (int pThis); | ||||
| 
 | ||||
| 	//Function Example: void Ham::Test(int cake) with this pointer ignore
 | ||||
| 	function MRESReturn (Handle hParams); | ||||
| 
 | ||||
| 	//Function Example: void Ham::Test(int cake) with this pointer passed
 | ||||
| 	function MRESReturn (int pThis, Handle hParams); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test() with this pointer ignore
 | ||||
| 	function MRESReturn (Handle hReturn); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test() with this pointer passed
 | ||||
| 	function MRESReturn (int pThis, Handle hReturn); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test(int cake) with this pointer ignore
 | ||||
| 	function MRESReturn (Handle hReturn, Handle hParams); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test(int cake) with this pointer passed
 | ||||
| 	function MRESReturn (int pThis, Handle hReturn, Handle hParams); | ||||
| 
 | ||||
| 	//Address NOW
 | ||||
| 
 | ||||
| 	//Function Example: void Ham::Test() with this pointer passed
 | ||||
| 	function MRESReturn (Address pThis); | ||||
| 
 | ||||
| 	//Function Example: void Ham::Test(int cake) with this pointer passed
 | ||||
| 	function MRESReturn (Address pThis, Handle hParams); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test() with this pointer passed
 | ||||
| 	function MRESReturn (Address pThis, Handle hReturn); | ||||
| 
 | ||||
| 	//Function Example: int Ham::Test(int cake) with this pointer passed
 | ||||
| 	function MRESReturn (Address pThis, Handle hReturn, Handle hParams); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| /* Adds an entity listener hook | ||||
|  * | ||||
|  * @param type			Type of listener to add | ||||
|  * @param callback		Callback to use | ||||
|  * | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookAddEntityListener(ListenType type, ListenCB callback); | ||||
| 
 | ||||
| /* Removes an entity listener hook | ||||
|  * | ||||
|  * @param type			Type of listener to remove | ||||
|  * @param callback		Callback this listener was using | ||||
|  * | ||||
|  * @return True if one was removed false otherwise. | ||||
| */ | ||||
| native bool DHookRemoveEntityListener(ListenType type, ListenCB callback); | ||||
| 
 | ||||
| /* Creates a hook | ||||
|  * | ||||
|  * @param offset		vtable offset for function to hook | ||||
|  * @param hooktype		Type of hook | ||||
|  * @param returntype	Type type of return | ||||
|  * @param thistype		Type of this pointer or ignore (ignore can be used if not needed) | ||||
|  * @param callback		Callback function
 | ||||
|  * | ||||
|  * @return Returns setup handle for the hook or INVALID_HANDLE. | ||||
| */ | ||||
| native Handle DHookCreate(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype, DHookCallback callback); | ||||
| 
 | ||||
| /* Adds param to a hook setup | ||||
|  * | ||||
|  * @param setup			Setup handle to add the param to. | ||||
|  * @param type			Param type | ||||
|  * @param size			Used for Objects (not Object ptr) to define the size of the object. | ||||
|  * @param flag			Used to change the pass type. | ||||
|  * | ||||
|  * @error	Invalid setup handle or too many params added (request upping the max in thread) | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookAddParam(Handle setup, HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal); | ||||
| //native DHookAddParam(Handle:setup, HookParamType:type);
 | ||||
| 
 | ||||
| /* Hook entity | ||||
|  * | ||||
|  * @param setup			Setup handle to use to add the hook. | ||||
|  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||
|  * @param entity		Entity index to hook on. | ||||
|  * @param removalcb		Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) | ||||
|  * | ||||
|  * @error Invalid setup handle, invalid entity or invalid hook type. | ||||
|  * @return -1 on fail a hookid on success | ||||
| */ | ||||
| native int DHookEntity(Handle setup, bool post, int entity, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||
| 
 | ||||
| /* Hook gamerules | ||||
|  * | ||||
|  * @param setup			Setup handle to use to add the hook. | ||||
|  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||
|  * @param removalcb		Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will call this callback) | ||||
|  * | ||||
|  * @error Invalid setup handle, failing to get gamerules pointer or invalid hook type. | ||||
|  * @return -1 on fail a hookid on success | ||||
| */ | ||||
| native int DHookGamerules(Handle setup, bool post, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||
| 
 | ||||
| /* Hook a raw pointer | ||||
|  * | ||||
|  * @param setup			Setup handle to use to add the hook. | ||||
|  * @param post			True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) | ||||
|  * @param addr			This pointer address. | ||||
|  * @param removalcb		Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) | ||||
|  * | ||||
|  * @error Invalid setup handle, invalid address or invalid hook type. | ||||
|  * @return -1 on fail a hookid on success | ||||
| */ | ||||
| native int DHookRaw(Handle setup, bool post, Address addr, DHookRemovalCB removalcb=INVALID_FUNCTION); | ||||
| 
 | ||||
| /* Remove hook by hook id | ||||
|  * | ||||
|  * @param hookid		Hook id to remove | ||||
|  * | ||||
|  * @return true on success false otherwise | ||||
|  * @note This will not fire the removal callback! | ||||
| */ | ||||
| native bool DHookRemoveHookID(int hookid); | ||||
| 
 | ||||
| /* Get param value (Only use for: int, entity, bool or float param types) | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1. 0 Will return the number of params stored) | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @return value if num greater than 0. If 0 returns paramcount. | ||||
| */ | ||||
| native any DHookGetParam(Handle hParams, int num); | ||||
| 
 | ||||
| /* Get vector param value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) | ||||
|  * @param vec			Vector buffer to store result. | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetParamVector(Handle hParams, int num, float vec[3]); | ||||
| 
 | ||||
| /* Get string param value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) | ||||
|  * @param buffer		String buffer to store result | ||||
|  * @param size			Buffer size | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetParamString(Handle hParams, int num, char[] buffer, int size); | ||||
| 
 | ||||
| /* Set param value (Only use for: int, entity, bool or float param types) | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||
|  * @param value			Value to set it as (only pass int, bool, float or entity index) | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetParam(Handle hParams, int num, any value); | ||||
| 
 | ||||
| /* Set vector param value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||
|  * @param vec			Value to set vector as. | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetParamVector(Handle hParams, int num, float vec[3]); | ||||
| 
 | ||||
| /* Set string param value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @params num			Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) | ||||
|  * @param value			Value to set string as. | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetParamString(Handle hParams, int num, char[] value); | ||||
| 
 | ||||
| /* Get return value (Only use for: int, entity, bool or float return types) | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @return Returns default value if prehook returns actual value if post hook. | ||||
| */ | ||||
| native any DHookGetReturn(Handle hReturn); | ||||
| 
 | ||||
| /* Get return vector value | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * @param vec			Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0)) | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetReturnVector(Handle hReturn, float vec[3]); | ||||
| 
 | ||||
| /* Get return string value | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * @param buffer		String buffer to store result in. (In pre hooks will be default value "") | ||||
|  * @param size			String buffer size | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetReturnString(Handle hReturn, char[] buffer, int size); | ||||
| 
 | ||||
| /* Set return value (Only use for: int, entity, bool or float return types) | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * @param value			Value to set return as | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetReturn(Handle hReturn, any value); | ||||
| 
 | ||||
| /* Set return vector value | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * @param vec			Value to set return vector as | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetReturnVector(Handle hReturn, float vec[3]); | ||||
| 
 | ||||
| /* Set return string value | ||||
|  * | ||||
|  * @param hReturn		Handle to return structure | ||||
|  * @param value			Value to set return string as | ||||
|  * | ||||
|  * @error Invalid Handle, invalid type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetReturnString(Handle hReturn, char[] value); | ||||
| 
 | ||||
| //WE SHOULD WRAP THESE AROUND STOCKS FOR NON PTR AS WE SUPPORT BOTH WITH THESE NATIVE'S
 | ||||
| 
 | ||||
| /* Gets an objects variable value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. | ||||
|  * @param offset		Offset within the object to the var to get. | ||||
|  * @param type			Type of var it is | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||
|  * @return Value of the objects var. If EHANDLE type or entity returns entity index. | ||||
| */ | ||||
| native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type); | ||||
| 
 | ||||
| /* Sets an objects variable value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to set. | ||||
|  * @param offset		Offset within the object to the var to set. | ||||
|  * @param type			Type of var it is | ||||
|  * @param value			The value to set the var to. | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type, any value); | ||||
| 
 | ||||
| /* Gets an objects vector variable value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. | ||||
|  * @param offset		Offset within the object to the var to get. | ||||
|  * @param type			Type of var it is | ||||
|  * @param buffer		Buffer to store the result vector | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float buffer[3]); | ||||
| 
 | ||||
| /* Sets an objects vector variable value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to set. | ||||
|  * @param offset		Offset within the object to the var to set. | ||||
|  * @param type			Type of var it is | ||||
|  * @param value			The value to set the vector var to. | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float value[3]); | ||||
| 
 | ||||
| /* Gets an objects string variable value | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to get. | ||||
|  * @param offset		Offset within the object to the var to get. | ||||
|  * @param type			Type of var it is | ||||
|  * @param buffer		Buffer to store the result vector | ||||
|  * @param size			Size of the buffer | ||||
|  * | ||||
|  * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. | ||||
|  * @noreturn | ||||
| */ | ||||
| native void DHookGetParamObjectPtrString(Handle hParams, int num, int offset, ObjectValueType type, char[] buffer, int size); | ||||
| 
 | ||||
| /* Checks if a pointer param is null | ||||
|  * | ||||
|  * @param hParams		Handle to params structure | ||||
|  * @param num			Param number to check. | ||||
|  * | ||||
|  * @error Non pointer param | ||||
|  * @return True if null false otherwise. | ||||
| */ | ||||
| native bool DHookIsNullParam(Handle hParams, int num); | ||||
| 
 | ||||
| public Extension __ext_dhooks = | ||||
| { | ||||
| 	name = "dhooks", | ||||
| 	file = "dhooks.ext", | ||||
| #if defined AUTOLOAD_EXTENSIONS
 | ||||
| 	autoload = 1, | ||||
| #else
 | ||||
| 	autoload = 0, | ||||
| #endif
 | ||||
| #if defined REQUIRE_EXTENSIONS
 | ||||
| 	required = 1, | ||||
| #else
 | ||||
| 	required = 0, | ||||
| #endif
 | ||||
| }; | ||||
| 
 | ||||
| #if !defined REQUIRE_EXTENSIONS
 | ||||
| public void __ext_dhooks_SetNTVOptional() | ||||
| { | ||||
| 	MarkNativeAsOptional("DHookAddEntityListener"); | ||||
| 	MarkNativeAsOptional("DHookRemoveEntityListener"); | ||||
| 	MarkNativeAsOptional("DHookCreate"); | ||||
| 	MarkNativeAsOptional("DHookAddParam"); | ||||
| 	MarkNativeAsOptional("DHookEntity"); | ||||
| 	MarkNativeAsOptional("DHookGamerules"); | ||||
| 	MarkNativeAsOptional("DHookRaw"); | ||||
| 	MarkNativeAsOptional("DHookRemoveHookID"); | ||||
| 	MarkNativeAsOptional("DHookGetParam"); | ||||
| 	MarkNativeAsOptional("DHookGetParamVector"); | ||||
| 	MarkNativeAsOptional("DHookGetParamString"); | ||||
| 	MarkNativeAsOptional("DHookSetParam"); | ||||
| 	MarkNativeAsOptional("DHookSetParamVector"); | ||||
| 	MarkNativeAsOptional("DHookSetParamString"); | ||||
| 	MarkNativeAsOptional("DHookGetReturn"); | ||||
| 	MarkNativeAsOptional("DHookGetReturnVector"); | ||||
| 	MarkNativeAsOptional("DHookGetReturnString"); | ||||
| 	MarkNativeAsOptional("DHookSetReturn"); | ||||
| 	MarkNativeAsOptional("DHookSetReturnVector"); | ||||
| 	MarkNativeAsOptional("DHookSetReturnString"); | ||||
| 	MarkNativeAsOptional("DHookGetParamObjectPtrVar"); | ||||
| 	MarkNativeAsOptional("DHookSetParamObjectPtrVar"); | ||||
| 	MarkNativeAsOptional("DHookGetParamObjectPtrVarVector"); | ||||
| 	MarkNativeAsOptional("DHookSetParamObjectPtrVarVector"); | ||||
| 	MarkNativeAsOptional("DHookIsNullParam"); | ||||
| 	MarkNativeAsOptional("DHookGetParamObjectPtrString"); | ||||
| } | ||||
| #endif
 | ||||
							
								
								
									
										156
									
								
								oryx-mini-edit/scripting/include/oryx.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								oryx-mini-edit/scripting/include/oryx.inc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,156 @@ | ||||
| /*  Oryx AC: collects and analyzes statistics to find some cheaters in CS:S, CS:GO, and TF2 bunnyhop. | ||||
|  *  Copyright (C) 2018  Nolan O. | ||||
|  *  Copyright (C) 2018  shavit. | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| */ | ||||
| 
 | ||||
| #if defined _oryx_included
 | ||||
| 	#endinput
 | ||||
| #endif
 | ||||
| #define _oryx_included
 | ||||
| 
 | ||||
| #define ORYX_VERSION "1.3.1"
 | ||||
| 
 | ||||
| /** | ||||
| * List of current detection descriptions: | ||||
| *  | ||||
| * "Acute TR formatter" | ||||
| * "+left/right bypasser" | ||||
| * "Prestrafe tool" | ||||
| * "Average strafe too close to 0" | ||||
| * "Too many perfect strafes" | ||||
| * "Movement config" | ||||
| * "Unsynchronised movement" | ||||
| * "Invalid wish velocity" | ||||
| * "Script on scroll" | ||||
| * "Hyperscroll" | ||||
| */ | ||||
| 
 | ||||
| enum | ||||
| { | ||||
| 	TRIGGER_LOW,			// Reachable by skilled players occasionally. Not always necessary before a med detect.
 | ||||
| 	TRIGGER_MEDIUM,			// Reachable by skilled players by unlikely chance.
 | ||||
| 	TRIGGER_HIGH,			// Only theoretically reachable by the aligning of stars by the gods.
 | ||||
| 	TRIGGER_HIGH_NOKICK,	// This should really only be used for a follow up definitive detection.
 | ||||
| 	TRIGGER_DEFINITIVE,		// Non-skill-based detection type. 100% sure detection.
 | ||||
| 	TRIGGER_TEST			// Allows you to develop new detections on live servers with minimal side effects.
 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Called when Oryx gets triggered on a client. | ||||
|  * | ||||
|  * @param client				Client entity index. | ||||
|  * @param level					Level of detection as defined in the above enum. | ||||
|  * @param cheat					Short description or name of the cheat being detected. 32 cells char array. | ||||
|  * @return						Plugin_Continue to do nothing. Plugin_Changed to modify values. Plugin_Handled to abort kicks. Plugin_Stop to completely ignore the trigger. | ||||
|  */ | ||||
| forward Action Oryx_OnTrigger(int client, int &level, char[] cheat); | ||||
| 
 | ||||
| /** | ||||
|  * Call to activate Oryx's trigger procedure (logging, kicking, admin notifications, etc..). | ||||
|  * | ||||
|  * @param client				Client entity index. | ||||
|  * @param level					Level of detection as defined in the above enum. | ||||
|  * @param cheat					Short description or name of the cheat being detected. | ||||
|  * @return						Return value of the Oryx_OnTrigger forward. | ||||
|  */ | ||||
| native Action Oryx_Trigger(int client, int level, const char[] cheat); | ||||
| 
 | ||||
| /** | ||||
|  * Prints a message to admins' chat. | ||||
|  * | ||||
|  * @param format					Formatting rules. | ||||
|  * @param any						Variable number of format parameters. | ||||
|  * @noreturn | ||||
|  */ | ||||
| native void Oryx_PrintToAdmins(const char[] format, any ...); | ||||
| 
 | ||||
| /** | ||||
|  * Prints a message to admins' console. | ||||
|  * | ||||
|  * @param format					Formatting rules. | ||||
|  * @param any						Variable number of format parameters. | ||||
|  * @noreturn | ||||
|  */ | ||||
| native void Oryx_PrintToAdminsConsole(const char[] format, any ...); | ||||
| 
 | ||||
| /** | ||||
|  * Logs an entry to Oryx's log file. | ||||
|  * | ||||
|  * @param format					Formatting rules. | ||||
|  * @param any						Variable number of format parameters. | ||||
|  * @noreturn | ||||
|  */ | ||||
| native void Oryx_LogMessage(const char[] format, any ...); | ||||
| 
 | ||||
| /** | ||||
|  * Checks if f1 is inbetween a specified threshold of f12. | ||||
|  * | ||||
|  * @param f1					First value. | ||||
|  * @param f2					Second value. | ||||
|  * @param frac					Used as a threshold of f2 for f1 to be within. | ||||
|  * @return 						True if the test passed. | ||||
|  */ | ||||
| native bool Oryx_WithinThreshold(float f1, float f2, float threshold); | ||||
| 
 | ||||
| /** | ||||
|  * Checks if the player has permissions to bypass Oryx. | ||||
|  * Will return false if `oryx_allow_bypass` is set to 0. | ||||
|  * With bhoptimer or bTimes v1.8.3, will return true for styles with the `oryx_bypass` special flag. | ||||
|  * For bTimes2, will return true if the player is in edit mode (rewind/fastforward etc). | ||||
|  * | ||||
|  * @param client				Client index. | ||||
|  * @return 						True if the player can bypass the anticheat. | ||||
|  */ | ||||
| native bool Oryx_CanBypass(int client); | ||||
| 
 | ||||
| /** | ||||
|  * A tiny function to veify if the player fits gameplay. | ||||
|  * | ||||
|  * @param client				Client entity index. | ||||
|  * @param watrer				Check for water level? | ||||
|  * @return 						True if the test passed. | ||||
|  */ | ||||
| stock bool IsLegalMoveType(int client, bool water = true) | ||||
| { | ||||
| 	MoveType iMoveType = GetEntityMoveType(client); | ||||
| 
 | ||||
| 	return (!water || GetEntProp(client, Prop_Data, "m_nWaterLevel") < 2) && | ||||
| 		(GetEntityFlags(client) & FL_ATCONTROLS) == 0 && | ||||
| 		(iMoveType == MOVETYPE_WALK || iMoveType == MOVETYPE_ISOMETRIC || iMoveType == MOVETYPE_LADDER); | ||||
| } | ||||
| 
 | ||||
| public SharedPlugin __pl_oryx = | ||||
| { | ||||
| 	name = "oryx", | ||||
| 	file = "oryx.smx", | ||||
| #if defined REQUIRE_PLUGIN
 | ||||
| 	required = 1 | ||||
| #else
 | ||||
| 	required = 0 | ||||
| #endif
 | ||||
| }; | ||||
| 
 | ||||
| #if !defined REQUIRE_PLUGIN
 | ||||
| public void __pl_oryx_SetNTVOptional() | ||||
| { | ||||
| 	MarkNativeAsOptional("Oryx_CanBypass"); | ||||
| 	MarkNativeAsOptional("Oryx_LogMessage"); | ||||
| 	MarkNativeAsOptional("Oryx_PrintToAdmins"); | ||||
| 	MarkNativeAsOptional("Oryx_PrintToAdminsConsole"); | ||||
| 	MarkNativeAsOptional("Oryx_Trigger"); | ||||
| 	MarkNativeAsOptional("Oryx_WithinThreshold"); | ||||
| } | ||||
| #endif
 | ||||
							
								
								
									
										2880
									
								
								oryx-mini-edit/scripting/include/shavit.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2880
									
								
								oryx-mini-edit/scripting/include/shavit.inc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										690
									
								
								oryx-mini-edit/scripting/oryx-scroll.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										690
									
								
								oryx-mini-edit/scripting/oryx-scroll.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,690 @@ | ||||
| /*  Oryx AC: collects and analyzes statistics to find some cheaters in CS:S, CS:GO, and TF2 bunnyhop. | ||||
|  *  Copyright (C) 2018  shavit. | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| */ | ||||
| 
 | ||||
| // This module is a complete rewrite, and doesn't work like the simple one written by Rusty. //' | ||||
| 
 | ||||
| #include <sourcemod> | ||||
| #include <sdktools> | ||||
| #include <oryx> | ||||
| 
 | ||||
| #undef REQUIRE_PLUGIN | ||||
| #include <shavit> | ||||
| 
 | ||||
| #pragma newdecls required | ||||
| #pragma semicolon 1 | ||||
| 
 | ||||
| // Some features from my old anticheat. | ||||
| #define DESC1 "Scripted jumps (havg)" // 91%+ perf over sample size | ||||
| #define DESC2 "Scripted jumps (havgp)" // 87%+ perf, consistent scrolls | ||||
| #define DESC3 "Scripted jumps (patt1)" // 85%+ perf, very consistent scrolls | ||||
| #define DESC4 "Scripted jumps (patt2)" // 80%+ perf, inhumanly consistent scrolls | ||||
| #define DESC5 "Scripted jumps (wpatt1)" // 75%+ perf, inhumanly consistent scrolls | ||||
| #define DESC6 "Scripted jumps (wpatt2)" // 85%+ perf, obviously randomized scrolls | ||||
| 
 | ||||
| #define DESC7 "Scripted jumps (nobf)" // 40%+ perf, no scrolls before touching the ground | ||||
| #define DESC8 "Scripted jumps (bf-af)" // 55%+ perf, same number of scrolls before and after touching the ground | ||||
| #define DESC9 "Scripted jumps (noaf)" // 40%+ perf, no scrolls after leaving the ground | ||||
| 
 | ||||
| #define DESC10 "Scroll macro (highn)" // scrolls per jump are 17+, either high perf% (80%+) or consistent scrolls | ||||
| 
 | ||||
| // ORYX exclusive: | ||||
| #define DESC11 "Scroll cheat (interval)" // interval between scrolls is consistent (<=2, and is over 3/4 of the jumps) | ||||
| 
 | ||||
| // TODO: Implement this: | ||||
| #define DESC12 "Scroll cheat (ticks)" // average ticks on ground are inhuman | ||||
| 
 | ||||
| // Decrease this to make the scroll anticheat more sensitive. | ||||
| // Samples will be taken from the last X jumps' data. | ||||
| // If the number is too high, logs might be cut off due to the scroll patterns being too long. | ||||
| #define SAMPLE_SIZE_MIN 45 | ||||
| #define SAMPLE_SIZE_MAX 55 | ||||
| 
 | ||||
| // Amount of ticks between jumps to not count one. | ||||
| #define TICKS_NOT_COUNT_JUMP 8 | ||||
| 
 | ||||
| // Maximum airtime per jump in ticks before we stop measuring. This is to prevent low-gravity style bans and players spamming their scroll wheel while falling to purposely make the anti-cheat ban them. | ||||
| #define TICKS_NOT_COUNT_AIR 135 | ||||
| 
 | ||||
| // Fill scroll stats array with junk data. | ||||
| // #define DEBUG_SCROLL 50 | ||||
| 
 | ||||
| public Plugin myinfo =  | ||||
| { | ||||
| 	name = "ORYX scroll module", | ||||
| 	author = "shavit", | ||||
| 	description = "Advanced bunnyhop script/macro detection.", | ||||
| 	version = ORYX_VERSION, | ||||
| 	url = "https://github.com/shavitush/Oryx-AC" | ||||
| } | ||||
| 
 | ||||
| ConVar sv_autobunnyhopping = null; | ||||
| 
 | ||||
| bool gB_AutoBunnyhopping = false; | ||||
| bool gB_Shavit = false; | ||||
| 
 | ||||
| int gI_SampleSize = 50; | ||||
| 
 | ||||
| enum | ||||
| { | ||||
| 	StatsArray_Scrolls, | ||||
| 	StatsArray_BeforeGround, | ||||
| 	StatsArray_AfterGround, | ||||
| 	StatsArray_AverageTicks, | ||||
| 	StatsArray_PerfectJump, | ||||
| 	STATSARRAY_SIZE | ||||
| } | ||||
| 
 | ||||
| enum | ||||
| { | ||||
| 	State_Nothing, | ||||
| 	State_Landing, | ||||
| 	State_Jumping, | ||||
| 	State_Pressing, | ||||
| 	State_Releasing | ||||
| } | ||||
| 
 | ||||
| // 5 cells: | ||||
| // Scrolls before this jump. | ||||
| // Scrolls before touching ground (33 units from ground). | ||||
| // Scrolls after leaving ground (33 units from ground). | ||||
| // Average ticks between each scroll input. | ||||
| // Is it a perfect jump? | ||||
| ArrayList gA_JumpStats[MAXPLAYERS+1]; | ||||
| any gA_StatsArray[MAXPLAYERS+1][STATSARRAY_SIZE]; | ||||
| 
 | ||||
| int gI_GroundTicks[MAXPLAYERS+1]; | ||||
| int gI_ReleaseTick[MAXPLAYERS+1]; | ||||
| int gI_AirTicks[MAXPLAYERS+1]; | ||||
| 
 | ||||
| bool gB_PreviousGround[MAXPLAYERS+1] = { true, ... }; // Initialized as trues to prevent the first data being wrong. | ||||
| int gI_PreviousButtons[MAXPLAYERS+1]; | ||||
| int gI_CurrentJump[MAXPLAYERS+1]; | ||||
| 
 | ||||
| char gS_LogPath[PLATFORM_MAX_PATH]; | ||||
| 
 | ||||
| public void OnPluginStart() | ||||
| { | ||||
| 	sv_autobunnyhopping = FindConVar("sv_autobunnyhopping"); | ||||
| 
 | ||||
| 	if(sv_autobunnyhopping != null) | ||||
| 	{ | ||||
| 		sv_autobunnyhopping.AddChangeHook(OnAutoBunnyhoppingChanged); | ||||
| 	} | ||||
| 
 | ||||
| 	for(int i = 1; i <= MaxClients; i++) | ||||
| 	{ | ||||
| 		if(IsClientInGame(i)) | ||||
| 		{ | ||||
| 			OnClientPutInServer(i); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	RegConsoleCmd("scroll_stats", Command_PrintScrollStats, "Print the scroll stat buffer for a given player."); | ||||
| 
 | ||||
| 	LoadTranslations("common.phrases"); | ||||
| 
 | ||||
| 	gB_Shavit = LibraryExists("shavit"); | ||||
| 	 | ||||
| 	BuildPath(Path_SM, gS_LogPath, PLATFORM_MAX_PATH, "logs/oryx-ac-scroll.log");  | ||||
| } | ||||
| 
 | ||||
| public void OnMapStart() | ||||
| { | ||||
| 	gI_SampleSize = GetRandomInt(SAMPLE_SIZE_MIN, SAMPLE_SIZE_MAX); | ||||
| } | ||||
| 
 | ||||
| public void OnClientPutInServer(int client) | ||||
| { | ||||
| 	gA_JumpStats[client] = new ArrayList(STATSARRAY_SIZE); | ||||
| 	gI_CurrentJump[client] = 0; | ||||
| 	ResetStatsArray(client); | ||||
| 
 | ||||
| 	#if defined DEBUG_SCROLL | ||||
| 	gA_JumpStats[client].Resize(DEBUG_SCROLL); | ||||
| 
 | ||||
| 	for(int i = 0; i < DEBUG_SCROLL; i++) | ||||
| 	{ | ||||
| 		int scrolls = GetRandomInt(7, 15); | ||||
| 		int before = GetRandomInt(0, scrolls); | ||||
| 		int after = scrolls - before; | ||||
| 
 | ||||
| 		gA_JumpStats[client].Set(i, scrolls, StatsArray_Scrolls); | ||||
| 		gA_JumpStats[client].Set(i, before, StatsArray_BeforeGround); | ||||
| 		gA_JumpStats[client].Set(i, after, StatsArray_AfterGround); | ||||
| 		gA_JumpStats[client].Set(i, GetRandomInt(1, 2), StatsArray_AverageTicks); | ||||
| 	} | ||||
| 	#endif | ||||
| } | ||||
| 
 | ||||
| public void OnClientDisconnect(int client) | ||||
| { | ||||
| 	delete gA_JumpStats[client]; | ||||
| } | ||||
| 
 | ||||
| public void OnLibraryAdded(const char[] name) | ||||
| { | ||||
| 	if(StrEqual(name, "shavit")) | ||||
| 	{ | ||||
| 		gB_Shavit = true; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnLibraryRemoved(const char[] name) | ||||
| { | ||||
| 	if(StrEqual(name, "shavit")) | ||||
| 	{ | ||||
| 		gB_Shavit = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnAutoBunnyhoppingChanged(ConVar convar, const char[] oldValue, const char[] newValue) | ||||
| { | ||||
| 	gB_AutoBunnyhopping = view_as<bool>(StringToInt(newValue)); | ||||
| } | ||||
| 
 | ||||
| public void OnConfigsExecuted() | ||||
| { | ||||
| 	if(sv_autobunnyhopping != null) | ||||
| 	{ | ||||
| 		gB_AutoBunnyhopping = sv_autobunnyhopping.BoolValue; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public Action Command_PrintScrollStats(int client, int args) | ||||
| { | ||||
| 	if(args < 1) | ||||
| 	{ | ||||
| 		ReplyToCommand(client, "Usage: scroll_stats <target>"); | ||||
| 
 | ||||
| 		return Plugin_Handled; | ||||
| 	} | ||||
| 	 | ||||
| 	char[] sArgs = new char[MAX_TARGET_LENGTH]; | ||||
| 	GetCmdArgString(sArgs, MAX_TARGET_LENGTH); | ||||
| 
 | ||||
| 	int target = FindTarget(client, sArgs); | ||||
| 
 | ||||
| 	if(target == -1) | ||||
| 	{ | ||||
| 		return Plugin_Handled; | ||||
| 	} | ||||
| 
 | ||||
| 	if(GetSampledJumps(target) == 0) | ||||
| 	{ | ||||
| 		ReplyToCommand(client, "\x03%N\x01 does not have recorded jump stats.", target); | ||||
| 
 | ||||
| 		return Plugin_Handled; | ||||
| 	} | ||||
| 
 | ||||
| 	char[] sScrollStats = new char[300]; | ||||
| 	GetScrollStatsFormatted(target, sScrollStats, 300); | ||||
| 
 | ||||
| 	ReplyToCommand(client, "Scroll stats for %N: %s", target, sScrollStats); | ||||
| 
 | ||||
| 	return Plugin_Handled; | ||||
| } | ||||
| 
 | ||||
| void GetScrollStatsFormatted(int client, char[] buffer, int maxlength) | ||||
| { | ||||
| 	FormatEx(buffer, maxlength, "%d%% perfs, %d sampled jumps: {", GetPerfectJumps(client), GetSampledJumps(client)); | ||||
| 
 | ||||
| 	int iSize = gA_JumpStats[client].Length; | ||||
| 	int iEnd = (iSize >= gI_SampleSize)? (iSize - gI_SampleSize):0; | ||||
| 
 | ||||
| 	for(int i = iSize - 1; i >= iEnd; i--) | ||||
| 	{ | ||||
| 		Format(buffer, maxlength, "%s %d,", buffer, gA_JumpStats[client].Get(i, StatsArray_Scrolls)); | ||||
| 	} | ||||
| 
 | ||||
| 	// Beautify the text output so that the jumps are separated inside the curly braces, without irrelevant commas. | ||||
| 	int iPos = strlen(buffer) - 1; | ||||
| 
 | ||||
| 	if(buffer[iPos] == ',') | ||||
| 	{ | ||||
| 		buffer[iPos] = ' '; | ||||
| 	} | ||||
| 
 | ||||
| 	StrCat(buffer, maxlength, "}"); | ||||
| } | ||||
| 
 | ||||
| int GetSampledJumps(int client) | ||||
| { | ||||
| 	if(gA_JumpStats[client] == null) | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	int iSize = gA_JumpStats[client].Length; | ||||
| 	int iEnd = (iSize >= gI_SampleSize)? (iSize - gI_SampleSize):0; | ||||
| 
 | ||||
| 	return (iSize - iEnd); | ||||
| } | ||||
| 
 | ||||
| int GetPerfectJumps(int client) | ||||
| { | ||||
| 	int iPerfs = 0; | ||||
| 	int iSize = gA_JumpStats[client].Length; | ||||
| 	int iEnd = (iSize >= gI_SampleSize)? (iSize - gI_SampleSize):0; | ||||
| 	int iTotalJumps = (iSize - iEnd); | ||||
| 
 | ||||
| 	for(int i = iSize - 1; i >= iEnd; i--) | ||||
| 	{ | ||||
| 		if(view_as<bool>(gA_JumpStats[client].Get(i, StatsArray_PerfectJump))) | ||||
| 		{ | ||||
| 			iPerfs++; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if(iTotalJumps == 0) // Don't throw a divide-by-zero error. | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return RoundToZero((float(iPerfs) / iTotalJumps) * 100); | ||||
| } | ||||
| 
 | ||||
| public Action OnPlayerRunCmd(int client, int &buttons) | ||||
| { | ||||
| 	if(gB_Shavit || !IsPlayerAlive(client) || IsFakeClient(client)) | ||||
| 	{ | ||||
| 		return Plugin_Continue; | ||||
| 	} | ||||
| 
 | ||||
| 	return SetupMove(client, buttons); | ||||
| } | ||||
| 
 | ||||
| public Action Shavit_OnUserCmdPre(int client, int &buttons, int &impulse, float vel[3], float angles[3], TimerStatus status, int track, int style, int mouse[2]) | ||||
| { | ||||
| 	// Ignore autobhop styles. | ||||
| 	if(Shavit_GetStyleSettingBool(style, "autobhop")) | ||||
| 	{ | ||||
| 		return Plugin_Continue; | ||||
| 	} | ||||
| 
 | ||||
| 	return SetupMove(client, buttons); | ||||
| } | ||||
| 
 | ||||
| void ResetStatsArray(int client) | ||||
| { | ||||
| 	for(int i = 0; i < STATSARRAY_SIZE; i++) | ||||
| 	{ | ||||
| 		gA_StatsArray[client][i] = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	gI_ReleaseTick[client] = GetGameTickCount(); | ||||
| 	gI_AirTicks[client] = 0; | ||||
| } | ||||
| 
 | ||||
| public bool TRFilter_NoPlayers(int entity, int mask, any data) | ||||
| { | ||||
| 	return (entity != view_as<int>(data) || (entity < 1 || entity > MaxClients)); | ||||
| } | ||||
| 
 | ||||
| float GetGroundDistance(int client) | ||||
| { | ||||
| 	if(GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") == 0) | ||||
| 	{ | ||||
| 		return 0.0; | ||||
| 	} | ||||
| 
 | ||||
| 	float fPosition[3]; | ||||
| 	GetClientAbsOrigin(client, fPosition); | ||||
| 	TR_TraceRayFilter(fPosition, view_as<float>({90.0, 0.0, 0.0}), MASK_PLAYERSOLID, RayType_Infinite, TRFilter_NoPlayers, client); | ||||
| 
 | ||||
| 	float fGroundPosition[3]; | ||||
| 
 | ||||
| 	if(TR_DidHit() && TR_GetEndPosition(fGroundPosition)) | ||||
| 	{ | ||||
| 		return GetVectorDistance(fPosition, fGroundPosition); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0.0; | ||||
| } | ||||
| 
 | ||||
| Action SetupMove(int client, int buttons) | ||||
| { | ||||
| 	if((sv_autobunnyhopping != null && gB_AutoBunnyhopping) || Oryx_CanBypass(client)) | ||||
| 	{ | ||||
| 		return Plugin_Continue; | ||||
| 	} | ||||
| 
 | ||||
| 	bool bOnGround = ((GetEntityFlags(client) & FL_ONGROUND) > 0 || GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2); | ||||
| 
 | ||||
| 	if(bOnGround) | ||||
| 	{ | ||||
| 		gI_GroundTicks[client]++; | ||||
| 	} | ||||
| 
 | ||||
| 	float fAbsVelocity[3]; | ||||
| 	GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fAbsVelocity); | ||||
| 
 | ||||
| 	float fSpeed = (SquareRoot(Pow(fAbsVelocity[0], 2.0) + Pow(fAbsVelocity[1], 2.0))); | ||||
| 
 | ||||
| 	// Player isn't really playing but is just trying to make the anticheat go nuts. | ||||
| 	if(fSpeed > 225.0 && IsLegalMoveType(client, false)) | ||||
| 	{ | ||||
| 		CollectJumpStats(client, bOnGround, buttons, fAbsVelocity[2]); | ||||
| 	} | ||||
| 
 | ||||
| 	else | ||||
| 	{ | ||||
| 		ResetStatsArray(client); | ||||
| 	} | ||||
| 
 | ||||
| 	gB_PreviousGround[client] = bOnGround; | ||||
| 	gI_PreviousButtons[client] = buttons; | ||||
| 
 | ||||
| 	return Plugin_Continue; | ||||
| } | ||||
| 
 | ||||
| void CollectJumpStats(int client, bool bOnGround, int buttons, float fAbsVelocityZ) | ||||
| { | ||||
| 	// States | ||||
| 	int iGroundState = State_Nothing; | ||||
| 	int iButtonState = State_Nothing; | ||||
| 
 | ||||
| 	if(bOnGround && !gB_PreviousGround[client]) | ||||
| 	{ | ||||
| 		iGroundState = State_Landing; | ||||
| 	} | ||||
| 
 | ||||
| 	else if(!bOnGround && gB_PreviousGround[client]) | ||||
| 	{ | ||||
| 		iGroundState = State_Jumping; | ||||
| 	} | ||||
| 
 | ||||
| 	if((buttons & IN_JUMP) > 0 && (gI_PreviousButtons[client] & IN_JUMP) == 0) | ||||
| 	{ | ||||
| 		iButtonState = State_Pressing; | ||||
| 	} | ||||
| 
 | ||||
| 	else if((buttons & IN_JUMP) == 0 && (gI_PreviousButtons[client] & IN_JUMP) > 0) | ||||
| 	{ | ||||
| 		iButtonState = State_Releasing; | ||||
| 	} | ||||
| 
 | ||||
| 	int iTicks = GetGameTickCount(); | ||||
| 
 | ||||
| 	if(iButtonState == State_Pressing) | ||||
| 	{ | ||||
| 		gA_StatsArray[client][StatsArray_Scrolls]++; | ||||
| 		gA_StatsArray[client][StatsArray_AverageTicks] += (iTicks - gI_ReleaseTick[client]); | ||||
| 		 | ||||
| 		if(bOnGround) | ||||
| 		{ | ||||
| 			if((buttons & IN_JUMP) > 0) | ||||
| 			{ | ||||
| 				gA_StatsArray[client][StatsArray_PerfectJump] = !gB_PreviousGround[client]; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		else | ||||
| 		{ | ||||
| 			float fDistance = GetGroundDistance(client); | ||||
| 
 | ||||
| 			if(fDistance < 33.0) | ||||
| 			{ | ||||
| 				if(fAbsVelocityZ > 0.0 && gI_CurrentJump[client] > 1) | ||||
| 				{ | ||||
| 					// 'Inject' data into the previous recorded jump. | ||||
| 					int iJump = (gI_CurrentJump[client] - 1); | ||||
| 					int iAfter = gA_JumpStats[client].Get(iJump, StatsArray_AfterGround); | ||||
| 					gA_JumpStats[client].Set(iJump, iAfter + 1, StatsArray_AfterGround); | ||||
| 				} | ||||
| 
 | ||||
| 				else if(fAbsVelocityZ < 0.0) | ||||
| 				{ | ||||
| 					gA_StatsArray[client][StatsArray_BeforeGround]++; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	else if(iButtonState == State_Releasing) | ||||
| 	{ | ||||
| 		gI_ReleaseTick[client] = iTicks; | ||||
| 	} | ||||
| 
 | ||||
| 	if(!bOnGround && gI_AirTicks[client]++ > TICKS_NOT_COUNT_AIR) | ||||
| 	{ | ||||
| 		ResetStatsArray(client); | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if(iGroundState == State_Landing) | ||||
| 	{ | ||||
| 		int iScrolls = gA_StatsArray[client][StatsArray_Scrolls]; | ||||
| 
 | ||||
| 		if(iScrolls == 0) | ||||
| 		{ | ||||
| 			ResetStatsArray(client); | ||||
| 
 | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if(gI_GroundTicks[client] < TICKS_NOT_COUNT_JUMP) | ||||
| 		{ | ||||
| 			int iJump = gI_CurrentJump[client]; | ||||
| 			gA_JumpStats[client].Resize(iJump + 1); | ||||
| 
 | ||||
| 			gA_JumpStats[client].Set(iJump, iScrolls, StatsArray_Scrolls); | ||||
| 			gA_JumpStats[client].Set(iJump, gA_StatsArray[client][StatsArray_BeforeGround], StatsArray_BeforeGround); | ||||
| 			gA_JumpStats[client].Set(iJump, 0, StatsArray_AfterGround); | ||||
| 			gA_JumpStats[client].Set(iJump, (gA_StatsArray[client][StatsArray_AverageTicks] / iScrolls), StatsArray_AverageTicks); | ||||
| 			gA_JumpStats[client].Set(iJump, gA_StatsArray[client][StatsArray_PerfectJump], StatsArray_PerfectJump); | ||||
| 
 | ||||
| 			#if defined DEBUG | ||||
| 			PrintToChat(client, "{ %d, %d, %d, %d, %d, %d }", gA_StatsArray[client][StatsArray_Scrolls], | ||||
| 				gA_StatsArray[client][StatsArray_BeforeGround], | ||||
| 				(iJump > 0)? gA_JumpStats[client].Get(iJump - 1, gA_StatsArray[client][StatsArray_AfterGround]):0, | ||||
| 				gA_StatsArray[client][StatsArray_GroundTicks], | ||||
| 				(gA_StatsArray[client][StatsArray_AverageTicks] / iScrolls), | ||||
| 				gA_StatsArray[client][StatsArray_PerfectJump]); | ||||
| 			#endif | ||||
| 
 | ||||
| 			gI_CurrentJump[client]++; | ||||
| 		} | ||||
| 
 | ||||
| 		gI_GroundTicks[client] = 0; | ||||
| 		 | ||||
| 		ResetStatsArray(client); | ||||
| 	} | ||||
| 
 | ||||
| 	else if(iGroundState == State_Jumping && gI_CurrentJump[client] >= gI_SampleSize) | ||||
| 	{ | ||||
| 		AnalyzeStats(client); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int Min(int a, int b) | ||||
| { | ||||
| 	return (a < b)? a:b; | ||||
| } | ||||
| 
 | ||||
| int Max(int a, int b) | ||||
| { | ||||
| 	return (a > b)? a:b; | ||||
| } | ||||
| 
 | ||||
| int Abs(int num) | ||||
| { | ||||
| 	return (num < 0)? -num:num; | ||||
| } | ||||
| 
 | ||||
| void AnalyzeStats(int client) | ||||
| { | ||||
|     int iPerfs = GetPerfectJumps(client); | ||||
| 
 | ||||
|     // "Pattern analysis" | ||||
|     int iVeryHighNumber = 0; | ||||
|     int iSameAsNext = 0; | ||||
|     int iCloseToNext = 0; | ||||
|     int iBadIntervals = 0; | ||||
|     int iLowBefores = 0; | ||||
|     int iLowAfters = 0; | ||||
|     int iSameBeforeAfter = 0; | ||||
| 
 | ||||
|     for(int i = (gI_CurrentJump[client] - gI_SampleSize); i < gI_CurrentJump[client] - 1; i++) | ||||
|     { | ||||
|         // TODO: Cache iNextScrolls for the next time this code is ran. I'm tired and can't really think right now.. | ||||
|         int iCurrentScrolls = gA_JumpStats[client].Get(i, StatsArray_Scrolls); | ||||
|         int iTicks = gA_JumpStats[client].Get(i, StatsArray_AverageTicks); | ||||
|         int iBefores = gA_JumpStats[client].Get(i, StatsArray_BeforeGround); | ||||
|         int iAfters = gA_JumpStats[client].Get(i, StatsArray_AfterGround); | ||||
| 
 | ||||
|         if(i != gI_SampleSize - 1) | ||||
|         { | ||||
|             int iNextScrolls = gA_JumpStats[client].Get(i + 1, StatsArray_Scrolls); | ||||
| 
 | ||||
|             if(iCurrentScrolls == iNextScrolls) | ||||
|             { | ||||
|                 iSameAsNext++; | ||||
|             } | ||||
| 
 | ||||
|             if(Abs(Max(iCurrentScrolls, iNextScrolls) - Min(iCurrentScrolls, iNextScrolls)) <= 2) | ||||
|             { | ||||
|                 iCloseToNext++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if(iCurrentScrolls >= 17) | ||||
|         { | ||||
|             iVeryHighNumber++; | ||||
|         } | ||||
| 
 | ||||
|         if(iTicks <= 2) | ||||
|         { | ||||
|             iBadIntervals++; | ||||
|         } | ||||
| 
 | ||||
|         if(iBefores <= 1) | ||||
|         { | ||||
|             iLowBefores++; | ||||
|         } | ||||
| 
 | ||||
|         if(iAfters <= 1) | ||||
|         { | ||||
|             iLowAfters++; | ||||
|         } | ||||
| 
 | ||||
|         if(iBefores == iAfters) | ||||
|         { | ||||
|             iSameBeforeAfter++; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     float fIntervals = (float(iBadIntervals) / gI_SampleSize); | ||||
| 
 | ||||
|     bool bTriggered = true; | ||||
| 
 | ||||
|     char[] sScrollStats = new char[300]; | ||||
|     GetScrollStatsFormatted(client, sScrollStats, 300); | ||||
| 
 | ||||
|     char stats_desc[1024]; | ||||
| 
 | ||||
|     // Ugly code below, I know. | ||||
|     if(iPerfs >= 91) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC1 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC1, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_DEFINITIVE, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 87 && (iSameAsNext >= 13 || iCloseToNext >= 18)) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC2 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC2, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_DEFINITIVE, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 85 && iSameAsNext >= 13) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC3 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC3, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_DEFINITIVE, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 80 && iSameAsNext >= 15) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC4 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC4, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_HIGH, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 75 && iVeryHighNumber >= 4 && iSameAsNext >= 3 && iCloseToNext >= 10) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC5 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC5, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_HIGH, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 85 && iCloseToNext >= 16) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC6 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC6, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_HIGH, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 40 && iLowBefores >= 45) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC7 ... ") (%d): %s", client, iLowBefores, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s (%d):\n%s", DESC7, iLowBefores, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_MEDIUM, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 55 && iSameBeforeAfter >= 25) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC8 ... ") (bf %d | af %d | bfaf %d): %s", client, iLowBefores, iLowAfters, iSameBeforeAfter, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n(bf %d | af %d | bfaf %d):  %s", DESC8, iLowBefores, iLowAfters, iSameBeforeAfter, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_HIGH_NOKICK, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iPerfs >= 40 && iLowAfters >= 45) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC9 ... ") (%d): %s", client, iLowAfters, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n(%d): %s", DESC9, iLowAfters, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_LOW, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(iVeryHighNumber >= 15 && (iCloseToNext >= 13 || iPerfs >= 80)) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC10 ... "): %s", client, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\n%s", DESC10, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_HIGH, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else if(fIntervals > 0.75) | ||||
|     { | ||||
|         LogToFileEx(gS_LogPath, "%L - (" ... DESC11 ... ", intervals: %.2f): %s", client, fIntervals, sScrollStats); | ||||
|         Format(stats_desc, sizeof(stats_desc), "%s :\nintervals: %.2f: %s", DESC11, fIntervals, sScrollStats); | ||||
|         Oryx_Trigger(client, TRIGGER_MEDIUM, stats_desc); | ||||
|     } | ||||
| 
 | ||||
|     else | ||||
|     { | ||||
|         bTriggered = false; | ||||
|     } | ||||
| 
 | ||||
|     if(bTriggered) | ||||
|     { | ||||
|         // Hard reset stats after logging, to prevent spam. | ||||
|         ResetStatsArray(client); | ||||
|         gI_CurrentJump[client] = 0; | ||||
|         gA_JumpStats[client].Clear(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										414
									
								
								oryx-mini-edit/scripting/oryx.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								oryx-mini-edit/scripting/oryx.sp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,414 @@ | ||||
| /*  Oryx AC: collects and analyzes statistics to find some cheaters in CS:S, CS:GO, and TF2 bunnyhop. | ||||
|  *  Copyright (C) 2018  Nolan O. | ||||
|  *  Copyright (C) 2018  shavit. | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| */ | ||||
| 
 | ||||
| #include <sourcemod> | ||||
| #include <sdktools> | ||||
| #include <oryx> | ||||
| 
 | ||||
| #undef REQUIRE_PLUGIN | ||||
| #include <shavit> | ||||
| #include <bTimes-tas> | ||||
| #include <bTimes-timer_hack> | ||||
| 
 | ||||
| #pragma newdecls required | ||||
| #pragma semicolon 1 | ||||
| 
 | ||||
| enum | ||||
| { | ||||
| 	Timer_None, | ||||
| 	Timer_Shavit, | ||||
| 	Timer_Blacky2, | ||||
| 	Timer_Blacky183 | ||||
| } | ||||
| 
 | ||||
| int gI_Timer = Timer_None; | ||||
| char gS_SpecialString[128]; | ||||
| 
 | ||||
| ConVar gCV_AllowBypass = null; | ||||
| 
 | ||||
| EngineVersion gEV_Type = Engine_Unknown; | ||||
| 
 | ||||
| Handle gH_Forwards_OnTrigger = null; | ||||
| 
 | ||||
| char gS_LogPath[PLATFORM_MAX_PATH]; | ||||
| char gS_BeepSound[PLATFORM_MAX_PATH]; | ||||
| bool gB_NoSound = false; | ||||
| 
 | ||||
| bool gB_Testing[MAXPLAYERS+1]; | ||||
| bool gB_Locked[MAXPLAYERS+1]; | ||||
| 
 | ||||
| public Plugin myinfo =  | ||||
| { | ||||
| 	name = "ORYX bunnyhop anti-cheat", | ||||
| 	author = "Rusty, shavit", | ||||
| 	description = "Cheat detection interface.", | ||||
| 	version = ORYX_VERSION, | ||||
| 	url = "https://github.com/shavitush/Oryx-AC" | ||||
| } | ||||
| 
 | ||||
| public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) | ||||
| { | ||||
| 	CreateNative("Oryx_CanBypass", Native_CanBypass); | ||||
| 	CreateNative("Oryx_Trigger", Native_OryxTrigger); | ||||
| 	CreateNative("Oryx_WithinThreshold", Native_WithinThreshold); | ||||
| 	CreateNative("Oryx_PrintToAdmins", Native_PrintToAdmins); | ||||
| 	CreateNative("Oryx_PrintToAdminsConsole", Native_PrintToAdminsConsole); | ||||
| 	CreateNative("Oryx_LogMessage", Native_LogMessage); | ||||
| 
 | ||||
| 	// registers library, check "bool LibraryExists(const char[] name)" in order to use with other plugins | ||||
| 	RegPluginLibrary("oryx"); | ||||
| 
 | ||||
| 	return APLRes_Success; | ||||
| } | ||||
| 
 | ||||
| public void OnAllPluginsLoaded() | ||||
| { | ||||
| 	// workaround | ||||
| 	if(gI_Timer == Timer_None && | ||||
| 		GetFeatureStatus(FeatureType_Native, "GetClientStyle") == FeatureStatus_Available && | ||||
| 		GetFeatureStatus(FeatureType_Native, "Style_GetConfig") == FeatureStatus_Available) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_Blacky183; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnPluginStart() | ||||
| { | ||||
| 	gH_Forwards_OnTrigger = CreateGlobalForward("Oryx_OnTrigger", ET_Event, Param_Cell, Param_CellByRef, Param_String); | ||||
| 
 | ||||
| 	gEV_Type = GetEngineVersion(); | ||||
| 
 | ||||
| 	gCV_AllowBypass = CreateConVar("oryx_allow_bypass", "1", "Allow specific styles to bypass Oryx? Refer to README.md for information.", 0, true, 0.0, true, 1.0); | ||||
| 
 | ||||
| 	CreateConVar("oryx_version", ORYX_VERSION, "Plugin version.", (FCVAR_NOTIFY | FCVAR_DONTRECORD)); | ||||
| 	 | ||||
| 	RegAdminCmd("sm_otest", Command_OryxTest, ADMFLAG_BAN, "Enables the TRIGGER_TEST detection level."); | ||||
| 	RegAdminCmd("sm_lock", Command_LockPlayer, ADMFLAG_BAN, "Disables movement for a player."); | ||||
| 
 | ||||
| 	LoadTranslations("common.phrases"); | ||||
| 	 | ||||
| 	BuildPath(Path_SM, gS_LogPath, PLATFORM_MAX_PATH, "logs/oryx-ac.log"); | ||||
| 
 | ||||
| 	if(LibraryExists("shavit")) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_Shavit; | ||||
| 	} | ||||
| 
 | ||||
| 	else if(LibraryExists("tas")) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_Blacky2; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnLibraryAdded(const char[] name) | ||||
| { | ||||
| 	if(StrEqual(name, "shavit")) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_Shavit; | ||||
| 	} | ||||
| 
 | ||||
| 	else if(StrEqual(name, "tas")) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_Blacky2; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnLibraryRemoved(const char[] name) | ||||
| { | ||||
| 	if((StrEqual(name, "shavit") && gI_Timer == Timer_Shavit) || | ||||
| 		(StrEqual(name, "tas") && gI_Timer == Timer_Blacky2)) | ||||
| 	{ | ||||
| 		gI_Timer = Timer_None; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public void OnMapStart() | ||||
| { | ||||
| 	// Beep sounds. | ||||
| 	Handle hConfig = LoadGameConfigFile("funcommands.games"); | ||||
| 
 | ||||
| 	if(hConfig == null) | ||||
| 	{ | ||||
| 		SetFailState("Unable to load game config funcommands.games"); | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	if(GameConfGetKeyValue(hConfig, "SoundBeep", gS_BeepSound, PLATFORM_MAX_PATH)) | ||||
| 	{ | ||||
| 		PrecacheSound(gS_BeepSound, true); | ||||
| 	} | ||||
| 
 | ||||
| 	delete hConfig; | ||||
| } | ||||
| 
 | ||||
| public void OnClientPutInServer(int client) | ||||
| { | ||||
| 	gB_Locked[client] = false; | ||||
| 	gB_Testing[client] = false; | ||||
| } | ||||
| 
 | ||||
| public Action Command_OryxTest(int client, int args) | ||||
| { | ||||
| 	gB_Testing[client] = !gB_Testing[client]; | ||||
| 	ReplyToCommand(client, "Testing is %s.", (gB_Testing[client])? "on":"off"); | ||||
| 
 | ||||
| 	return Plugin_Handled; | ||||
| } | ||||
| 
 | ||||
| public Action Command_LockPlayer(int client, int args) | ||||
| { | ||||
| 	if(args < 1) | ||||
| 	{ | ||||
| 		ReplyToCommand(client, "Usage: sm_lock <target>"); | ||||
| 
 | ||||
| 		return Plugin_Handled; | ||||
| 	} | ||||
| 	 | ||||
| 	char[] sArgs = new char[MAX_TARGET_LENGTH]; | ||||
| 	GetCmdArgString(sArgs, MAX_TARGET_LENGTH); | ||||
| 
 | ||||
| 	int target = FindTarget(client, sArgs); | ||||
| 
 | ||||
| 	if(target == -1) | ||||
| 	{ | ||||
| 		return Plugin_Handled; | ||||
| 	} | ||||
| 	 | ||||
| 	gB_Locked[target] = !gB_Locked[target]; | ||||
| 	ReplyToCommand(client, "Player has been %s.", (gB_Locked[target])? "locked":"unlocked"); | ||||
| 	PrintToChat(target, "An admin has %s your ability to move!", (gB_Locked[target])? "locked":"unlocked"); | ||||
| 
 | ||||
| 	return Plugin_Handled; | ||||
| } | ||||
| 
 | ||||
| public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3]) | ||||
| { | ||||
| 	// Movement is locked, don't allow anything. | ||||
| 	if(gB_Locked[client]) | ||||
| 	{ | ||||
| 		buttons = 0; | ||||
| 		vel[0] = 0.0; | ||||
| 		vel[1] = 0.0; | ||||
| 		impulse = 0; | ||||
| 
 | ||||
| 		return Plugin_Changed; | ||||
| 	} | ||||
| 
 | ||||
| 	return Plugin_Continue; | ||||
| } | ||||
| 
 | ||||
| public int Native_CanBypass(Handle plugin, int numParams) | ||||
| { | ||||
| 	if(!gCV_AllowBypass.BoolValue) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	int client = GetNativeCell(1); | ||||
| 
 | ||||
| 	switch(gI_Timer) | ||||
| 	{ | ||||
| 		case Timer_Shavit: | ||||
| 		{ | ||||
| 			Shavit_GetStyleStrings(Shavit_GetBhopStyle(client), sSpecialString, gS_SpecialString, 128); | ||||
| 
 | ||||
| 			if(StrContains(gS_SpecialString, "oryx_bypass", false) != -1) | ||||
| 			{ | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		case Timer_Blacky2: | ||||
| 		{ | ||||
| 			return TAS_InEditMode(client); | ||||
| 		} | ||||
| 
 | ||||
| 		case Timer_Blacky183: | ||||
| 		{ | ||||
| 			any styleconfig[StyleConfig]; | ||||
| 			Style_GetConfig(GetClientStyle(client), styleconfig); | ||||
| 
 | ||||
| 			if(StrContains(styleconfig[Special_Key], "oryx_bypass", false) != -1) | ||||
| 			{ | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| public int Native_OryxTrigger(Handle plugin, int numParams) | ||||
| { | ||||
| 	int client = GetNativeCell(1); | ||||
| 	int level = GetNativeCell(2); | ||||
| 	 | ||||
| 	char[] sLevel = new char[16]; | ||||
| 	char[] sCheatDescription = new char[32]; | ||||
| 
 | ||||
| 	GetNativeString(3, sCheatDescription, 32); | ||||
| 
 | ||||
| 	Action result = Plugin_Continue; | ||||
| 	Call_StartForward(gH_Forwards_OnTrigger); | ||||
| 	Call_PushCell(client); | ||||
| 	Call_PushCellRef(level); | ||||
| 	Call_PushStringEx(sCheatDescription, 32, SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); | ||||
| 	Call_Finish(result); | ||||
| 
 | ||||
| 	if(result == Plugin_Stop) | ||||
| 	{ | ||||
| 		return view_as<int>(Plugin_Stop); | ||||
| 	} | ||||
| 
 | ||||
| 	if(level == TRIGGER_LOW) | ||||
| 	{ | ||||
| 		strcopy(sLevel, 16, "LOW"); | ||||
| 		gB_NoSound = true; // Don't play the annoying beep sound for LOW detections. | ||||
| 	} | ||||
| 
 | ||||
| 	else if(level == TRIGGER_MEDIUM) | ||||
| 	{ | ||||
| 		strcopy(sLevel, 16, "MEDIUM"); | ||||
| 	} | ||||
| 
 | ||||
| 	else if(level == TRIGGER_HIGH) | ||||
| 	{ | ||||
| 		strcopy(sLevel, 16, "HIGH"); | ||||
| 
 | ||||
| 		if(result != Plugin_Handled) | ||||
| 		{ | ||||
| 			//KickClient(client, "[ORYX] %s", sCheatDescription); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	else if(level == TRIGGER_HIGH_NOKICK) | ||||
| 	{ | ||||
| 		strcopy(sLevel, 16, "HIGH-NOKICK"); | ||||
| 	} | ||||
| 
 | ||||
| 	else if(level == TRIGGER_DEFINITIVE) | ||||
| 	{ | ||||
| 		strcopy(sLevel, 16, "DEFINITIVE"); | ||||
| 
 | ||||
| 		if(result != Plugin_Handled) | ||||
| 		{ | ||||
| 			//KickClient(client, "[ORYX] %s", sCheatDescription); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	else if(level == TRIGGER_TEST) | ||||
| 	{ | ||||
| 		char[] sBuffer = new char[128]; | ||||
| 		Format(sBuffer, 128, "(\x03%N\x01) - %s | Level: \x04TESTING", client, sCheatDescription); | ||||
| 
 | ||||
| 		for(int i = 1; i <= MaxClients; i++) | ||||
| 		{ | ||||
| 			if(gB_Testing[i] && IsClientInGame(i)) | ||||
| 			{ | ||||
| 				PrintToChat(i, "%s", sBuffer); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return view_as<int>(result); | ||||
| 	} | ||||
| 
 | ||||
| 	char[] sAuth = new char[32]; | ||||
| 	GetClientAuthId(client, AuthId_Steam3, sAuth, 32); | ||||
| 
 | ||||
| 	char[] sBuffer = new char[128]; | ||||
| 	Format(sBuffer, 128, "\x03%N\x01 - \x05%s\x01 Cheat: %s | Level: %s", client, sAuth, sCheatDescription, sLevel); | ||||
| 	Oryx_PrintToAdmins("%s", sBuffer); | ||||
| 	 | ||||
| 	LogToFileEx(gS_LogPath, "%L - Cheat: %s | Level: %s", client, sCheatDescription, sLevel); | ||||
| 
 | ||||
| 	return view_as<int>(result); | ||||
| } | ||||
| 
 | ||||
| public int Native_WithinThreshold(Handle plugin, int numParams) | ||||
| { | ||||
| 	float f1 = GetNativeCell(1); | ||||
| 	float f2 = GetNativeCell(2); | ||||
| 	float threshold = GetNativeCell(3); | ||||
| 
 | ||||
| 	return view_as<int>(FloatAbs(f1 - f2) <= threshold); | ||||
| } | ||||
| 
 | ||||
| public int Native_PrintToAdmins(Handle plugin, int numParams) | ||||
| { | ||||
| 	static int iWritten = 0; // Useless? | ||||
| 
 | ||||
| 	char[] sBuffer = new char[300]; | ||||
| 	FormatNativeString(0, 1, 2, 300, iWritten, sBuffer); | ||||
| 
 | ||||
| 	for(int i = 1; i <= MaxClients; i++) | ||||
| 	{ | ||||
| 		if(CheckCommandAccess(i, "oryx_admin", ADMFLAG_GENERIC)) | ||||
| 		{ | ||||
| 			PrintToChat(i, "%s\x04[ORYX]\x01 %s", (gEV_Type == Engine_CSGO)? " ":"", sBuffer); | ||||
| 
 | ||||
| 			if(!gB_NoSound) | ||||
| 			{ | ||||
| 				if(gEV_Type == Engine_CSS || gEV_Type == Engine_TF2) | ||||
| 				{ | ||||
| 					EmitSoundToClient(i, gS_BeepSound); | ||||
| 				} | ||||
| 
 | ||||
| 				else | ||||
| 				{ | ||||
| 					ClientCommand(i, "play */%s", gS_BeepSound); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	gB_NoSound = false; | ||||
| } | ||||
| 
 | ||||
| public int Native_PrintToAdminsConsole(Handle plugin, int numParams) | ||||
| { | ||||
| 	static int iWritten = 0; // Useless? | ||||
| 
 | ||||
| 	char[] sBuffer = new char[300]; | ||||
| 	FormatNativeString(0, 1, 2, 300, iWritten, sBuffer); | ||||
| 
 | ||||
| 	for(int i = 1; i <= MaxClients; i++) | ||||
| 	{ | ||||
| 		if(CheckCommandAccess(i, "oryx_admin", ADMFLAG_GENERIC)) | ||||
| 		{ | ||||
| 			PrintToConsole(i, "[ORYX] %s", sBuffer); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| public int Native_LogMessage(Handle plugin, int numParams) | ||||
| { | ||||
| 	char[] sPlugin = new char[32]; | ||||
| 
 | ||||
| 	if(!GetPluginInfo(plugin, PlInfo_Name, sPlugin, 32)) | ||||
| 	{ | ||||
| 		GetPluginFilename(plugin, sPlugin, 32); | ||||
| 	} | ||||
| 
 | ||||
| 	static int iWritten = 0; // Useless? | ||||
| 
 | ||||
| 	char[] sBuffer = new char[300]; | ||||
| 	FormatNativeString(0, 1, 2, 300, iWritten, sBuffer); | ||||
| 	 | ||||
| 	LogToFileEx(gS_LogPath, "[%s] %s", sPlugin, sBuffer); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user