Jump to content

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

Geplaatst:
comment_1676866

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

Featured Replies

Geplaatst:
comment_1831378

Dankje, eens kijken of het nu wel lukt :) Hoe moet ik SampleCustom trouwens organiseren? Ik zie een hoop spullen waar ik geen snars van snap :(

Praat ik overgens met de maker van die geniale trainer voor GTA IV? :D

Edit: Nope, het werkt nog steeds niet. Ik heb nu dit:

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

#include <windows.h>

// Pull in all our scripting functions/types
using namespace Scripting;

CustomThread::CustomThread()
{
   // Give your own name here!
SetName("CustomThreadMT");
}

void CustomThread::RunTick()
{
if ((GetAsyncKeyState(VK_F1)& 1) != 0)
       {
		Armor = !Armor;
		if(Armor)
		{
			PrintStringWithLiteralStringNow("STRING", "ARMOR MODE ENABLED", 1500, true);
		}
		else
		{
			PrintStringWithLiteralStringNow("STRING", "ARMOR MODE DISABLED", 1500, true);
		}
       }

if (Armor == true)
{ 
	Player PlayerIndex = ConvertIntToPlayerIndex(GetPlayerId());
       Ped PlayerChar;
       GetPlayerChar(PlayerIndex, &PlayerChar);
	AddArmourToChar(PlayerChar,10);
}

}

Het werkt niet als ik op F1 druk.

Nevermind, ik ben dom, niet hernoemd naar .asi. tactical facepalm!

Bool doet trouwens hetzelfde als State...? Zoja, welke is efficiënter/beter? En welke dan makkelijker?

Hoe werkt dit?

GetCharArmour(PlayerChar, aArmor)

aArmor wil ik gebruiken, maar wat moet dat dan zijn?

nvm.

Ik wil de wapens wat vager maken, maar het lukt niet! :O

		eWeapon wap;
       GetCurrentCharWeapon(PlayerChar,&wap);
	SetObjectAlpha(wap, 110);

Wat doe ik hier fout? :O

Bewerkt: door ikt

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...

Recent actief 0

  • Er zijn hier geen geregistreerde gebruikers aanwezig.