[.NET] [C#] [SHVDN] Modding Basics and How to Start Modding In C#! [PART 1]
-
Hello guys, it's been a long time since I've been here, and since then, looking back at my older tutorials they just don't feel really good and everything feels really un-organized. So this time, I'm going to guide you, from the very basics and guide you up to the very top.
One thing, however, is that I don't know where to lead with this series. Do you want this to be more of a Lets Make a Mod or like fundamentals of modding? If you want it to be a former, tell me what mod you'd like to see be made(or re-made).
REQUIREMENTS
Intermediate knowledge of C#
ScriptHookVDotNet(SHVDN)
ScriptHookV(SHV)
Visual Studio CommunitySetting Up
First of all, after downloading the above files, drag everything from SHVDN and SHV rars to your game folder. THATS IT. Also, make a scripts folder if not already made in you game directory. After doing that, this is how your game directory should look like:
I do have extra files, that's because I have RAGE Plugin Hook, but you don't need that.
After installing the hooks, you should make a folder where all your coding stuff goes. I'll make a folder at my desktop named GTA 5 Coding:
After that, drag your SDK folder (from the SHVDN rar) into that folder. Keep in mind this is all for organisation and if you don't want to do it, certainly don't.
After that, open up Visual Studio Community that you installed earlier and this is the screen you will be greeted with:
Click File->New->Project and then this screen will show up:
Make sure Class Library is selected and in the Name write down the name of your mod, in our case, I'll just name it "First Script" (without the quotation marks. ALSO the location has to be that GTA 5 Coding folder we created earlier so make sure it is like mine. After you hit OK, you will be greeted with the C# script:
First of all, we need to setup the "references" to our SDK which we dropped into our GTA 5 Coding folder, so in the right of the window there is a "Solution Explorer". In there, there is a References key. Right click it and click Add Reference:
Click on Browse and browse to your SDK folder, in which you will find this:
Click on Add and make sure it is ticked after it appears in the Reference Manager. However, we still need to add one more Reference for handling Keypresses. It is inside the Assemblies section, to the left on the Reference Manager window.
In here, find System.Windows.Forms, check it and click OK:
After that, we need to add on to our "using" namespaces so that we can "use" all the functions inside of the .NET Hook so that we can manipulate the game world. We have three main using namespaces to add:
using GTA - This using reference is basically for everything revolving the GTA game world, like creating vehicles, handling weather, everything. However, we still need to add two more references:
using GTA.Native - This using reference allows us to call native functions DIRECTLY to the main C++ hook. You don't need to understand what that all means yet, we'll talk about that later.
using GTA.Math - This using reference allows us to use GTA or 3D math, as far as we are concerned. We will learn about these later.With these three out of the way, we also need to add the System.Windows.Forms reference.
This is needed only for the KeyEventArgs class which is used for keypress handling and for you C# dudes, I know, crosire(the .net hook dev) should've added a KeyEventArgs class in his own hook so we wouldn't have to add this reference but oh wellNow, we have to make the hook know that this class is a Script, and not any other class that just randomly happened to end up in our project
and to do that we need to inherit from the main Script class. If you don't know what that means, I suggest you read the REQUIREMENTS note at the top and then continue
The random and boring "Class1" class seems too uninformational for us so lets change that to something like "Main". To do that, go over to your Solution Explorer and right click Class1.cs and rename it to Main.cs:
Now, the final thing we need to do for setting up, is to make the constructor and add the Tick and Keydown event handler! (Again, if you don't know what an eventhandler is, read the requirements note)
This code hooks the Tick and KeyDown events from the Script class we inherited from to our two event handlers, OnTick and OnKeyDown.
We are done setting up! We can now continue to the actual fun stuff!Coding A Simple Script
Let's code a script, that, if we press J, we set our Wanted Level to 0? It's quite easy to do, but first, we need to detect a keypress. We do this in our OnKeyDown method. The KeyEventArgs class gives us all the info we need to know what key was pressed.
Now we need a way to manipulate the Player, we can easily do using Game.Player. Game.Player has a property WantedLevel that we can edit, and set to anything we want(setting it to more than 5 just doesn't work so don't try it :P)
Pretty straight-forward code, nothing a C# noob couldn't understand.
This checks if the key we have pressed was J and if it was, set our Wanted Level to 0. We can also let the player know that the script works and there aren't any errors, for two reasons:- It looks good
- For debugging, so we could know why it didn't work. When modding or scripting, keep this habbit in mind since it is very useful when code doesn't work.
How do we do this, you ask? Well, the .NET hook gives us an ENTIRE class full of goodies we can mess around lol which is the UI class. Inside it we can mess with anything UI related, but we are going to find one specific method:
ShowSubtitle
This method, as it says, shows a subtitle for a duration we can set(it is in milliseconds so be careful) and the text we want it to display, like this:
The first parameter is the text (it is a string) and the second parameter is the time we want it to display, which I have set to 3 seconds or 3000 milliseconds.
This script now functions, but how do we put it in the game? Look down!Compiling and running the script
To build the script, hover over Build and click Build FirstScript:
If your script didn't have any errors, it would build successfully and show you the path to where it was compiled. Since we put the project in our GTA 5 Coding folder, navigate to this directory:GTA 5 Coding\FirstScript\FirstScript\bin\Debug
Over here, you would find the two files which are important:
FirstScript.dll and FirstScript.pdb
The dll is the actual compiled script and the pdb contains info about the script. This is good for debugging so if the script crashes we can know exactly at which line it crashed at. Copy both these files to your scripts folder in you GTA 5 directoryIMPORTANT: DO NOT COPY THE SCRIPTHOOKVDOTNET.DLL WHICH WAS COMPILED
After this, run your game and press J. Did the script work for you? It did for me!
Keep experimenting with what you just learnt today. Explore. In the next tutorial we'll cover different things like 3D space and model spawning. Until then, bye.
- It looks good
-
@TobsiCred I have created a similar post on GTA Forums for holding keys, and this is what I came up with:
bool isHoldKeyPressed; int secondsForStuff = 4000; int secsPressed; void OnTick(object sender, EventArgs e) { if(isHoldKeyPressed) { secsPressed += 1000; } if(secsPressed == secondsForStuff) { ExplodeCurrentVehicle(); secsPressed = 0; isHoldKeyPressed = false; } } void ExplodeCurrentVehicle() { Vehicle veh; if (Game.Player.Character.IsInVehicle()) veh = Game.Player.Character.CurrentVehicle; else return; veh.Explode(); } void OnKeyDown(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.J) { isHoldKeyPressed = true; } else { isHoldKeyPressed = false; } }
Basically change the secondsForStuff variable to the amount of seconds you should hold. In the OnKeyDown event you can change the Key that has to be held down. The ExplodeCurrentVehicle is just a placeholder, you can replace that code with anything you want to do when you hold the key.
For changing the player ped, you need to use this native:
-
@TobsiCred I forgot to mention, in your constructor put in Interval = 1000;
at the start.
-
@TobsiCred post your code in a new thread, so as to not confuse my readers
I'll look at it first thing.
-
@TobsiCred It is recommended that you don't have the same name for both Namespace and Class, apparently it can cause reference problems.
-
@LeeC2202 Compiled everything into a .dll succesfully; but .dll is only 5k, and when I rename it to .asi, it doesn't appear to get loaded. What step am I missing?
-
@meimeiriver Why are you renaming to an asi? If it's a C# script, it's a dll and it goes in your scripts folder.
-
@LeeC2202 said in [.NET] [C#] [SHVDN] Modding Basics and How to Start Modding In C#! [PART 1]:
@meimeiriver Why are you renaming to an asi? If it's a C# script, it's a dll and it goes in your scripts folder.
It's the NoBlood script I tried compiling:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using GTA; using GTA.Native; namespace NoBloodV { public class NoBlood : Script { public static int busy = 0; public NoBlood () { Interval = 100; Tick += onTick; } private void onTick (object sender, EventArgs e) { if (busy == 0) { busy = 1; Ped playerPed = Game.Player.Character; if ((playerPed.HasCollidedWithAnything) || (playerPed.IsSwimming)) { playerPed.ClearBloodDamage (); playerPed.ResetVisibleDamage (); Function.Call (Hash.CLEAR_PED_LAST_WEAPON_DAMAGE, playerPed); } busy = 0; } } } }
It compiles fine (VS 2017). I thought you needed to rename it to .asi, to get ScriptHookV to pick up on it.
I put the .dll in the scripts folder now, but it doesn't seem to work. I best pull out the SubTitle thingy again.
-
@LeeC2202 All is well again.
Removed the busy flag, which was preventing it from running correctly somehow. But, without it, things run just fine.
-
@LeeC2202 For completion's sake, here is the new script I'm using for car collision (see below). I think I've been using HasCollidedWithAnything wrong. Although defined for playerPed too, I really think it's meant to be used on CurrentVehicle, like:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using GTA; using GTA.Native; namespace NoBloodV { public class NoBlood : Script { public NoBlood () { Interval = 100; Tick += onTick; } private void onTick (object sender, EventArgs e) { Ped playerPed = Game.Player.Character; if (playerPed.IsInVehicle ()) { if (playerPed.CurrentVehicle.HasCollidedWithAnything) { playerPed.ClearBloodDamage (); playerPed.ResetVisibleDamage (); Function.Call (Hash.CLEAR_PED_LAST_WEAPON_DAMAGE, playerPed); } } } } }
I didn't get the spurious crashes any more (although that might have just been a coincidence).
-
@AHK1221 Thanks for this tutorials serie and keep the good work going on please, it really help.
May i suggest you to edit your posts to add links to other parts of the tutorial ? It would be helpfull in my opinion.
-
Did everything the same no error while building, but ingame nothing happens, tried using different keys and such but no luck here. what am i missing ?Oo
and ofc copied the dll into the script folder like the tutorial states.
-
@clusterfunk Can you show me your code? Also, make sure ScriptHookVDotNet.dll is NOT present in your scripts folder. If it is, delete it.
-
@AHK1221 hello me friend , Can I add an object to make a gun for a boat?