Jump to content

[IV|ASI|C++] Mods maken in C++ (introductie)


Recommended Posts

Geplaatst: (bewerkt)

Mods maken in C++

Introductie

Het is weer vakantie en dus weer tijd om te modden, en mensen te helpen.

In deze tutorial ga ik uitleggen hoe je in C++ een ASI mod kan maken.

Ik laat je zien hoe een script is opgebouwd, welke soorten scripts er zijn.

En tot slot laat ik ook nog 3 voorbeeld scripts zien met uitleg.

Benodigdheden

  1. GTA IV/GTA EFLC (maak niet uit welke patch)
  2. Visual C++ express /Visual Studio (2008 of 2010)
  3. Development Kit
  4. (beetje) kennis van programmeren in C++

Voorbereidingen

Ten eerste heb je Visual C++ express of Visual Studio nodig (als je dit nog niet hebt), Visual C++ express is gratis en is hier te downloaden: Link

Daarna heb je de Development kit nodig om de mods te maken, die is hier te downloaden: Link (directe link: Klik)

Introductie

Nadat je de Development Kit hebt gedownload en hebt uitgepakt, zie je een map en een aantal bestanden. Het makkelijkste is om de ScriptHook.sln te openen.

Hierin staan alle voorbeelden die aan de scripthook zijn gelinkt, dus dat het de informatie uit de scripthook haalt.

Open ScriptHook.sln

je ziet nu 4 projecten:

- SampleCustom

- SampleCustomFiber

- Scripthook

- Speedo

SampleCustom

Dit is een voorbeeld script die elke 'tick'(word elke ms uitgevoerd) de code uitvoert.

Alles moet ook in die lus staan.

SampleCustomFiber

Dit is een voorbeeld script die in een loop uitgevoerd word.

De functies die worden aangeroepen vanuit de loop, de functies staan buiten de loop!

Na elke loop moet er wel een wait in staan

Scripthook

Dit is het script waaruit alle informatie word gehaald om een script te maken.

De script doorkijken kan handig zijn voor bijvoorbeeld het opzoeken van de functies die er zijn, de voertuig namen, ped namen en nog veel meer.

Verderop in deze tutorial zal ik een aantal dingen van de scripthook uitleggen.

Speedo

Dit is een voorbeeld script die via DirectX een analoge (werkende) kilometer laat zien.

Een aantal handige scripts om door te kijken in Scripthook

De scripthook die zorgt ervoor dat je in C++ mods kan maken, deze bevat dus code. Een aantal daarvan zijn handig om door te kijken:

- Scripting.h en ScriptingDirty.h

Hierin staan functies die je in het script kunt gebruiken.

- ScriptingEnums.h

Hierin staan alle te gebruiken waardes, zoals: wapens, peds, voertuigen, statics, radiostations en nog veel meer

Let op! verander nooit iets in de scripthook!

Opbouw

Zoals bij elk C++ project heb je:

- Header files

- Resources Files

- Source Files

Header Files

Hierin kan je de functies of bepaalde waardes declareren die je wilt gebruiken in je script

Recources Files

Hierin kan je bestanden in zetten om te gebruiken in je mod, zoals bijvoorbeeld: Een afbeelding

Source Files

Hierin staat je script die uitgevoerd word

Aan de slag

Voor nu laat ik alleen zien hoe je een script maak op de "SampleCustom" manier, dus per 'tick'.

Om het niet te moeilijk te maken, en dus een heel nieuw project toe te voegen, gebruiken we een bestaand projecten als 'template'.

Ga naar CustomThread.cpp, je ziet nu een boel code, verwijder delen totdat je dit overhoud:

#include "CustomThread.h"
#include "Scripting.h"
#include "../ScriptHook/Log.h"

#include <windows.h>

using namespace Scripting;

CustomThread::CustomThread()
{
SetName("CustomThread"); 
}

void CustomThread::RunTick()
{


}

Verwijder in CustomThread.h de declaratie

Je houd dit over:

#pragma once

#include "../ScriptHook/ScriptThread.h"
#include "../ScriptHook/ScriptingEnums.h"

class CustomThread : 
public ScriptThread
{
private:

protected:
// We want a Tick based script, so we override RunTick.
void RunTick();

public:
CustomThread();
};

Nu ben je klaar om een eigen script te maken!

Een mod maken

Nu je een 'template' project hebt, kan je beginnen met het maken van je mod.

Ik laat 3 voorbeeld script zien:

  1. Het spawnen van een voertuig
  2. $10000 geven
  3. Een script waardoor je nooit meer hoeft te herladen.

Script 1: Spawnen van een voertuig:

Voordat je een voertuig kan laten spawnen moet je het eerst in het geheugen laden. Hiervoor moet je het model aanvragen, wachten totdat het geladen is, en dan pas kan je de auto spawnen. En daarna moet je ook niet vergeten om het model weer uit het geheugen te verwijderen.

Het voertuig die ik laat spawnen is de Turismo.

Met de toets F4

Ten eerste maken we een aantal variables die we gaan gebruiken. Deze variables declareer je in CustomThread.h

Omdat we een declaratie voor een model nodig hebben, en die niet normaal bestaat, moeten we die uit de scripthook halen.

Daarvoor moeten we scripting.h includen.

de variables die we nodig hebben:

Scripting::eModel VehicleModel;

bool LoadingModel;

Dat zijn de variables die we nodig hebben. Deze zet je onder de private waardoor je header er zo uit komt te zien:

#pragma once

#include "../ScriptHook/ScriptThread.h"
#include "../ScriptHook/ScriptingEnums.h"
#include "Scripting.h"

class CustomThread : 
public ScriptThread
{
private:
Scripting::eModel VehicleModel;
bool LoadingModel;
protected:
// We want a Tick based script, so we override RunTick.
void RunTick();

public:
CustomThread();
};

Nu we alles hebben gedeclareerd is het tijd voor het script gedeelte. Ga weer naar CustomThread.cpp.

Eerst maken we een functie die controleert of het voertuigmodel geladen moet worden.

Eerst moeten we controleren of de variable LoadingModel op true staat en daarna of het eengevraagde model al geladen is. Als dat zo is dan moet het voertuig gespawnt worden.

if (LoadingModel == true)
{
	if (HasModelLoaded(VehicleModel))
	{
		Vehicle vehicle; // declareer het voertuig

		Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
		Ped PlayerChar;
		GetPlayerChar(PlayerIndex, &PlayerChar);
	//Converteer de Player naar een ped zodat je de informatie daarvan kan gebruiken

		f32 x,y,z; // Declareer de posities voor het voertuig
		GetCharCoordinates(PlayerChar, &x, &y, &z); // Geef de x y en z de waardes van de player's positie.
		CreateCar(VehicleModel, x, y, z, &vehicle, true); // Spawn het voertuig op de aangegeven positie
	MarkModelAsNoLongerNeeded(VehicleModel); // verwijder het model uit het geheugen
	LoadingModel = false; //Zet LoadingModel op false omdat het model geladen is
	}
}

Nu we de functie hebben gemaakt om een voertuig te spawnen, moet er ook een manier zijn om die functie te activeren.

Daarvoor moeten we een key functie gebruiken, daarna het model aanvragen, en LoadingModel op true zetten.

if ((GetAsyncKeyState(VK_F4)& 1) != 0) //Als er op F4 word gedrukt
{
	VehicleModel = MODEL_TURISMO; //VehicleModel de waarde van Model_Turismo geven (te vinden in ScriptingEnums)
	RequestModel(VehicleModel); //vraag het model aan
	LoadingModel = true; // zet LoadingModel op true
}

Nu is dit script klaar.

Ga naar: Build > Build SampleCustom

Wacht totdat het builden klaar is. Nu zal je in de map van de Scripthook een mapje zien genaamd: Debug.

Hierin staat: SampleCustom.dll

Hernoem deze naar een naam naar keuze, met i.p.v. .dll erachter, zet je er .asi achter.

Script 2: $10000 geven

Dit is een heel simpel script sinds je alleen de functie hoef aan te roepen.

if ((GetAsyncKeyState(VK_F5)& 1) != 0) //als er op F5 gedrukt wordt...
{
	Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
	//We hebben nu alleen de PlayerIndex nodig

AddScore(PlayerIndex,10000); //roep de functie aan om geld te geven. (Te vinden in Scripting.h)
	PrintStringWithLiteralStringNow("STRING", "Je hebt $10000 gekregen!", 1500, true); // laat onderin beeld een tekst zien dat je $10000 hebt gekregen.
}

Plaats deze code gewoon onder de huidige, Let wel op dat het script nog in de void zit, dus niet onder het laatste haakje: } maar boven de laatste }

Script 3: NoReload Script

In dit script gaan we ervoor zorgen dat je nooit meer hoef te herladen.

Eerst moeten we nog even een variable declareren die aangeeft of NoReload ingeschakeld is of niet.

Dus eerst gaan we weer naar CustomThread.h (dus de header) en voegen het volgende toe: bool NoReload;

Deze zet je onder bool LoadingModel;.

Nadat je dat gedaan hebt, gaan we weer terug naar CustomThread.cpp

Eerst maken we een functie die NoReload op true of false zet.

if ((GetAsyncKeyState(VK_F6)& 1) != 0) //Als er op F6 Gedrukt wordt...
{
	NoReload = !NoReload; // Zet NoReload op het tegenovergesteld van wat de waarde was, dus was het false, dan is het nu true en omgekeerd
	if(NoReload)
	{
		PrintStringWithLiteralStringNow("STRING", "NoReload ingeschakeld!", 1500, true); // laten zien dat NoReload ingeschakeld is
	}
	else
	{
		PrintStringWithLiteralStringNow("STRING", "NoReload uitgeschakeld!", 1500, true); // laten zien dat NoReload uitgeschakeld is
	}
{

Nu we de 'aan en uit' gemaakt hebben, moeten we de functie nog maken.

Dit vereist wat meer werk om te maken.

 if (NoReload == true) //Controleren of NoReload Ingeschakeld is
{
	Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
	Ped PlayerChar;
	GetPlayerChar(PlayerIndex, &PlayerChar);
	//Zoals al eerder aangegeven: de player converteren naar een ped

	eWeapon wap;
	u32 amm;
	u32 maxamm;
	//declaratie voor: het (huidige) wapen, de ammo, en de maximale ammo

	GetCurrentCharWeapon(PlayerChar,&wap); //Huidig wapen van de player achterhalen
	GetAmmoInClip(PlayerChar,wap,&amm); //Huidige ammo in het magazijn achterhalen
	GetMaxAmmoInClip(PlayerChar,wap,&maxamm); //Maximale ammo die in het magazijn kan achterhalen

	if (amm < maxamm) // Als de ammo lager is dan de maximale ammo die in het magazijn kan...
	{
		SetAmmoInClip(PlayerChar,wap,maxamm); //Het magazijn aanvullen tot het maximale
	}
}

Dit script zet je onder het 'geld' script, dus niet onder het laatste haakje: } maar boven de laatste }

Het volledige script

De volledige code die er nu is ziet er als volgt uit:

De Header: CustomThread.h

#pragma once

#include "../ScriptHook/ScriptThread.h"
#include "../ScriptHook/ScriptingEnums.h"
#include "Scripting.h"

class CustomThread : 
public ScriptThread
{
private:
Scripting::eModel VehicleModel;
bool LoadingModel;
bool NoReload;
protected:
// We want a Tick based script, so we override RunTick.
void RunTick();

public:
CustomThread();
};

De Source: CustomThread.cpp

#include "CustomThread.h"
#include "Scripting.h"
#include "../ScriptHook/Log.h"

#include <windows.h>

using namespace Scripting;

CustomThread::CustomThread()
{
SetName("CustomThread"); 
}

void CustomThread::RunTick()
{

if (LoadingModel == true)
{
	if (HasModelLoaded(VehicleModel))
	{
		Vehicle vehicle;

		Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
		Ped PlayerChar;
		GetPlayerChar(PlayerIndex, &PlayerChar);

		f32 x,y,z;
		GetCharCoordinates(PlayerChar, &x, &y, &z);
		CreateCar(VehicleModel, x, y, z, &vehicle, true);
		MarkModelAsNoLongerNeeded(VehicleModel);
		LoadingModel = false;
	}
}

if ((GetAsyncKeyState(VK_F4)& 1) != 0)
{
	VehicleModel = MODEL_TURISMO;
	RequestModel(VehicleModel);
	LoadingModel = true;
}

if ((GetAsyncKeyState(VK_F5)& 1) != 0)
{ 
	Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
//We hebben nu alleen de PlayerIndex nodig
AddScore(PlayerIndex,10000); //roep de functie aan om geld te geven. (Te vinden in Scripting.h)
PrintStringWithLiteralStringNow("STRING", "Je hebt $10000 gekregen!", 1500, true); // laat onderin beeld een tekst zien dat je $10000 hebt gekregen. 
}

if ((GetAsyncKeyState(VK_F6)& 1) != 0)
{
	NoReload = !NoReload;
	if(NoReload)
	{
		PrintStringWithLiteralStringNow("STRING", "NoReload ingeschakeld!", 1500, true);
	}
	else
	{
		PrintStringWithLiteralStringNow("STRING", "NoReload uitgeschakeld!", 1500, true);
	}
}

if (NoReload == true)
{
	Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
	Ped PlayerChar;
	GetPlayerChar(PlayerIndex, &PlayerChar);

	eWeapon wap;
	u32 amm;
	u32 maxamm;

	GetCurrentCharWeapon(PlayerChar,&wap);
	GetAmmoInClip(PlayerChar,wap,&amm);
	GetMaxAmmoInClip(PlayerChar,wap,&maxamm);

	if (amm < maxamm)
	{
		SetAmmoInClip(PlayerChar,wap,maxamm);
	}
}

}

Tot Slot

Als je het script wilt testen doe dan het volgende:

Ga naar: Build > Build SampleCustom

build.png

Daarna zal je in de map van de Scripthook, een map genaamd Debug zien met daarin: SampleCustom.dll , hernoem het naar een eigen naam met de extensie .asi en dus niet dll!

Kopieer het naar je GTA IV/EFLC map en probeer je net gemaakte mod.

Download

Voor diegene die liever meteen het project downloaden: Klik

Algemene tips

- Begin met kleine dingen te maken en probeer steeds nieuwe dingen uit, ga niet meteen de grootste dingen proberen, want dat zal waarschijnlijk toch wel niet lukken.

- Wil je een variabele een waarde geven zet er dan & voor! anders werkt het niet en krijg je errors, dus let daar goed op!

- Bekijk andere voorbeelden en probeer ook te begrijpen wat er staat, kopiëren en plakken kan iedereen wel, maar het begrijpen van de code is wat anders!

- Neem eens een kijkje op gtamodding.com daar staan ook nog verschillende functies en andere handige informatie

Ik hoop dat het een beetje begrijpbaar is, en dat ik diegene die dit graag willen wat op weg heb geholpen.

Heb je commentaar of op/aanmerkingen post het a.u.b.

MVG,

BC7

Bewerkt: door BC7
Geplaatst: (bewerkt)

Bedankt :D

ben nu btw ook bezig met een tutorial om een (simpele) missie te maken :Y .

Die zal je een deze dagen ook wel online staan.

Bewerkt: door BC7
Geplaatst:

Mooie tutorial BC7, goed uitgelegd. Met basiskennis van programmeren (niet eens c++) is het erg makkelijk te volgen. Ik zal het toevoegen aan de mtl wanneer ik zo op mijn computer zit :tu:.

Geplaatst:

Dit is hertstikke geweldig :3 Ik probeer al maanden te proberen om te beginnen met C++ mods voor GTA, alleen lukt het voor geen meter omdat er nergens staat hoe je aan zoiets begint. :(

+1 voor jou :D

Geplaatst:

@dji-unit

Ja voor GTA IV :Y

@Beagle & Ikt

Bedankt _O_

Ben trouwens bijna klaar met de missie tut, hoop m morgen online te hebben :Y

Geplaatst:

Dat is Awesome, ik dacht dat dat niet mogelijk was.

IK bedoel dan niet precies zo'n 'officiële' missie maar gewoon een script waar je (achteopeenvolgend) opdrachten moet uitvoeren.

Ik had de laatste dagen niet veel tijd, maar hoe in het weekend het af te maken.

Geplaatst:

dat weet ik hoor ;) Ik heb de tutorial gevolgd, maar als ik het gebruik wil het spel niet opstarten. Jammer dus.

  • 3 weken later...
Geplaatst: (bewerkt)

Met de tutorial over een missie maken, heb ik wat problemen. Misschien dat ik het later als het goed werkt dat ik dan nog een tut erover schrijf.

@Hierboven

Heb je het project gebuild, en daarna in een asi extensie vernoemd? Heb je wel een scriptloader?

Heb ook maar een download link toegevoegd voor het project, in het geval dat het niet mocht lukken: Download

BC7

Bewerkt: door BC7
  • 3 maanden later...
  • 5 maanden later...
Geplaatst: (bewerkt)

Potverdikkeme, dit is moeilijk. Vooral als je niet weet waar je naar moet zoeken in scripting.h :puh:

Dit werkt trouwens niet: why?

if ((GetAsyncKeyState(VK_F12)& 1) != 0)
       {
               Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
               Ped PlayerChar;
               GetPlayerChar(PlayerIndex, &PlayerChar);
               AddArmourToChar(PlayerChar,1000);
               PrintStringWithLiteralStringNow("STRING", "Added armor!", 1500, true);
       }

Weet iemand toevallig hoe ik bijvoorbeeld aftel?

Bewerkt: door ikt
Geplaatst: (bewerkt)

Potverdikkeme, dit is moeilijk. Vooral als je niet weet waar je naar moet zoeken in scripting.h :puh:

Dit werkt trouwens niet: why?

if ((GetAsyncKeyState(VK_F12)& 1) != 0)
       {
               Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
               Ped PlayerChar;
               GetPlayerChar(PlayerIndex, &PlayerChar);
               AddArmourToChar(PlayerChar,1000);
               PrintStringWithLiteralStringNow("STRING", "Added armor!", 1500, true);
       }

Weet iemand toevallig hoe ik bijvoorbeeld aftel?

Ervan uitgaande dat je bedoelt dat je na een bepaalde tijds iets moet doen en dat je samplecustom gebruikt (de fiber thread is niet bepaald de meest stabiele scripthread :)

SetTimerA(0); //timer op 0

m_State = Stateblah; //veranderen van de state

case Stateblah:

{

if (TimerA() > 1000) //na een seconde

{

do something;

m_State= StateDefault; //terug naar de default state, keypresses en tick processing

}

}

break;

je moet alleen in de header nog even stateblah, toevoegen.

Maximum armor is trouwens 200 volgens mijn (niet onfeilbare) geheugen.

Bewerkt: door sjaak327

Een reactie plaatsen

Je kan nu een reactie plaatsen en pas achteraf registreren. Als je al lid bent, log eerst in om met je eigen account een reactie te plaatsen.

Gast
Op dit onderwerp reageren...

×   Je hebt text geplaatst met opmaak.   Opmaak verwijderen

  Only 75 emoji are allowed.

×   Je link is automatisch ingevoegd.   In plaats daarvan weergeven als link

×   Je vorige bewerkingen zijn hersteld.   Alles verwijderen

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent actief   0 leden

    • Er zijn hier geen geregistreerde gebruikers aanwezig.
×
×
  • Create New...