Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // NOTICE: This example is not meant to be executed, but is simply to show how to invoke natives.
- /**
- * The RAGE Plugin Hook API includes a lot of functionality, but sometimes
- * you may need to invoke one of the game's natives for functionality not (or not yet) provided by
- * RAGE Plugin Hook.
- *
- * You can find lists of the game's natives using Google.
- *
- * Natives can be called using the dynamic object returned by NativeFunction.Natives.
- * Being dynamic, means that the compiler will not check whether an operation on the object is valid,
- * and any errors will only occur at runtime.
- *
- * This means that you can invoke members on it, as if any member existed.
- * Eg. NativeFunction.Natives.Yolo(1, 2, 3); would compile fine, despite no such method actually existing.
- *
- * The object will validate members at runtime, and you can use this to call natives.
- * Natives can be invoked using the method call syntax with the same name as the native.
- *
- * For example, to call GET_PLAYER_PED, you can type
- * NativeFunction.Natives.GET_PLAYER_PED(0);
- *
- * This will cause the API to invoke the native GET_PLAYER_PED with signed integer zero as the argument.
- **/
- Ped playerPed = Game.LocalPlayer.Character;
- // Technically, the API takes instances of Rage.Native.NativeArgument as arguments for the native invocations.
- NativeFunction.Natives.SET_ENTITY_HAS_GRAVITY(new NativeArgument(playerPed.Handle), new NativeArgument(true));
- // However, NativeArgument has implicit operators to convert common types to a NativeArgument,
- // meaning you can pass an argument directly, and an instance of NativeArgument will be created implicitly.
- NativeFunction.Natives.SET_ENTITY_HAS_GRAVITY(playerPed.Handle, true); // Implicit conversions from int and bool to NativeArgument.
- // While natives take the handles of entities like Peds, Vehicles, etc.
- // NativeArgument also has implicit operators for common API types like Ped, Vehicle, Blip, Player, Group, etc.
- // allowing you to pass objects of these types directly, without appending .Id, .Handle, etc.
- // Passing an entity will create an instance of NativeArgument with the entity's handle as value.
- NativeFunction.Natives.SET_ENTITY_HAS_GRAVITY(playerPed, true); // Implicit conversions from Ped and bool to NativeArgument.
- // Some natives return a value. For these natives,
- // you must specify a return type if you want to get the returned value.
- // Return type is specfied as the one and only generic type on the method.
- int money = NativeFunction.Natives.GET_PED_MONEY<int>(playerPed, true);
- // You can also specify common API types as the return type, like Ped, Vehicle, Group, Blip, Task, Vector3, etc.
- // When specifying one of these types as the return type, the API assumes that the native returns their corresponding handle or id.
- Ped ped = NativeFunction.Natives.x218297BF0CFD853B<Ped>(playerPed.CurrentVehicle, 0);
- // If you use the method in an expression without specifying the return type, it will compile,
- // but at runtime you'll get an exception.
- money = NativeFunction.Natives.GET_PED_MONEY(playerPed, true);
- // Some natives take a position as 3 separate parameters, consisting of the X, Y and Z components.
- System.Diagnostics.Debugger.Launch();
- Vector3 position = new Vector3(202.3442f, 3107.727f, 42.14632f);
- NativeFunction.Natives.SetEntityCoords(playerPed, position.X, position.Y, position.Z, true, true, true, false);
- // However, if you pass a Vector3 specifically, the API will split it, and pass it as 3 separate parameters.
- // The following statement, and the one above both pass 8 arguments.
- NativeFunction.Natives.SetEntityCoords(playerPed, position, true, true, true, false);
- // The same behaviour is supported for the following types: Vector2, Vector3, Vector4, Quaternion, Rotator.
- // When passing any of these types, their fields will be passed as separate arguments:
- NativeFunction.Natives.SetEntityQuaternion(playerPed, playerPed.CurrentVehicle.Orientation);
- // Is equivalent to:
- NativeFunction.Natives.SetEntityQuaternion(playerPed, playerPed.CurrentVehicle.Orientation.X, playerPed.CurrentVehicle.Orientation.Y, playerPed.CurrentVehicle.Orientation.Z);
- // To conform to naming conventions (and simply to make the code prettier),
- // it is possible to specify the name in PascalCase.
- // The API will convert PascalCase names to the native name format.
- // Eg. if you type GetPedMoney, the API will convert this to GET_PED_MONEY, based on the upper case letters in the name.
- money = NativeFunction.Natives.GetPedMoney(playerPed, true);
- // To call a native by name, its actual name must be used (guessed or speculated names will not work).
- // For some natives, the actual name is not known, and thus you must call these natives by their original 64-bit value (aka. hash).
- // The original hash of GET_PED_MONEY is 0x3F69145BBA87BAE7.
- // To call a native by its hash, start the method name with 'x', followed by the 64-bit value in hex.
- money = NativeFunction.Natives.x3F69145BBA87BAE7<int>(playerPed, true);
- // Same natives outputs values by reference. That is, they take a pointer to a variable.
- // You can of course enable unsafe code, and then pass the address of your variables, as follows.
- // Note: Pointers cannot be passed to a dynamically dispatched operation, so you must cast it to IntPtr,
- // or another 64-bit type.
- unsafe
- {
- uint boneId = 0;
- bool value = NativeFunction.Natives.GetPedLastDamageBone<bool>(playerPed, (IntPtr)(&boneId));
- }
- // Another way is to use the NativePointer class, which internally has a variable
- // which the API passes a pointer to, to the native.
- // After the call, the value can then be retrieved.
- // This allows the user of pointers, but without requiring unsafe code.
- using (NativePointer nativePointer = new NativePointer(sizeof(int)))
- {
- bool value2 = NativeFunction.Natives.GetPedLastDamageBone<bool>(playerPed, nativePointer);
- uint boneId2 = nativePointer.GetValue<uint>();
- }
- // Of course, both of these methods are cumbersome.
- // Another, much more preferable way, is to use the ref and out keywords.
- // Whether a native uses the pointer as only in, or only out, you can use both ref and out, but if you use out, you cannot pass a value to the native.
- uint boneId3; // Doesn't need to be initialized, since the value will not be passed to the native.
- bool value3 = NativeFunction.Natives.GetPedLastDamageBone<bool>(playerPed, out boneId3);
- uint boneId4 = 0; // Must be initialied, as its value will be passed to the native.
- bool value4 = NativeFunction.Natives.GetPedLastDamageBone<bool>(playerPed, ref boneId4);
- // For natives taking a char*, it is not necessary to use pointers. Instead, simply pass a regular string,
- // and the API will take care of marshalling it to the native.
- uint hash = NativeFunction.Natives.GetHashKey<uint>("Hello World");
- // For natives returning a char*, you can also pass string as the return type,
- // and the API will automatically marshal it for you.
- string liveryName = NativeFunction.Natives.GetLiveryName<string>(playerPed.CurrentVehicle, 0);
- // Note, pointers cannot be used in generic types, so if you absolutely need the raw byte pointer returned by the native,
- // specify a 64-bit type, then cast it yourself.
- // You must cast to the return type first, since dynamic operations do not support casts to pointer types.
- // Note: char in C++ is byte in C#. a char in C# is a wchar_t in C++.
- unsafe
- {
- byte* liveryName2 = (byte*)(IntPtr)NativeFunction.Natives.GetLiveryName<IntPtr>(playerPed.CurrentVehicle, 0);
- IntPtr liveryNameAddress = NativeFunction.Natives.GetLiveryName<IntPtr>(playerPed.CurrentVehicle, 0);
- }
- /**
- * This concludes the guide for invoking natives. A couple of notes:
- * Using PascalCase naming convention is prefered over original native names (GetPlayerPed vs GET_PLAYER_PED).
- * Using the ref and out keywords is prefered over using raw pointers or NativePointer.
- **/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement