Strona główna
Witaj, nieznajomy!

Podstawy

Do pisania skryptów w GTA IV będziemy potrzebować silnika, który nam dostarczy wszystko czego potrzebujemy. Jest ich kilka, ale jako przykład dam Alice autorstwa Alexandra Blade'a, który bazuje na języku skryptowym LUA. Niektórzy być może kojarzą go z tworzenia map do MTA.
Na marginesie powiem, że jest możliwość tworzenia tego typu skryptów w języku C++ dzięki specjalnym bibliotekom.

Instalacja

Najpierw ściągnij pliki silnika stąd:
- Alice
Następnie skopiuj zawartość katalogu copy do głównego katalogu z GTA IV. Pliki, które powinny się tam znaleźć:
Kod:
- Alice (katalog)
Alice.asi
binkhooked.dll
binkw32.dll
lua.dll
lualib.dll


W katalogu Alice będą przechowywane pliki ze skryptami *.lua.

Podstawowe informacje

GTA IV ma wiele skryptowych funkcji zwanych "funkcjami natywnymi". Alice umożliwia wykonanie każdej z nich. Kilka podstawowych operacji:

PushInt(wartość) - Służy do przekazania liczby całkowitej jako parametru do funkcji.
PushFloat(wartość) - To samo, tylko z liczbą po przecinku.
Zmienna = GetIntParam(NumerParametru) - Służy do odczytania liczby całkowitej jako parametru, który został wcześniej przekazany do funkcji. Zwrócona wartość będzie przekazywana w zmiennej o podanej nazwie. Tu: "Zmienna".
Zmienna = GetFloatParam(NumerParametru) - To samo, tylko z liczbą po przecinku.
Wynik = GetIntResult() - Zwraca wynik (w postaci liczby całkowitej) wcześniej wykonanej funkcji.
Wynik = GetFloatResult() - To samo, tylko zwraca liczbę po przecinku.
CallNative("NAZWA_FUNKCJI") - Wywołanie funkcji o podanej nazwie.

Przekazywanie i odczytywanie parametrów może wydawać się nieco skomplikowane, ale można szybko do tego przywyknąć. Wszystkie wątpliwości powinny zostać rozwiane po analizie dalszego przykładu.

Istotnym elementem jest to, że funkcje natywne mogą zostać wywołane tylko podczas gry. Dlatego na początku każdego skryptu jesteśmy zmuszeni sprawdzić, czy gracz został stworzony.
Kod:
IsPlayerPoolCreated()


Na koniec jeszcze dodam, że komentarze w kodzie tworzymy za pomocą dwóch myślników (--).
Kod:
-- To jest komentarz
IsPlayerPoolCreated()


Pierwszy skrypt

Przykładem w tym poradniku będzie skrypt na tzw. Bullet Time, czyli spowolnienie czasu. Będziemy aktywować ten tryb poprzez wciśnięcie klawisza TAB. Wyłączanie będzie odbywało się po wciśnięciu tego samego klawisza.

Kod:
--zmienne globalne
  PLAYER_ID, PLAYER_INDEX, PLAYER_CHAR, Time = 0

function InitScript()
  Wait(10000)
end

function WaitForPlayerPoolCreation()
  while (IsPlayerPoolCreated() == 0) do
    Wait(2000)
  end
end


Tworzymy standardowe funkcje, które są niezbędne na początku skryptu. Inicjalizujemy go, a następnie sprawdzamy, czy gracz został stworzony. Należy pamiętać, że są to tylko stworzone przez Nas funkcje i na razie nie zostały one wywołane. Wszystko zostanie wykonane w głównej funkcji o nazwie main().

Kod:
function WaitForValidPlayer()
  PLAYER_CHAR = 0
  repeat 
    CallNative("GET_PLAYER_ID")
PLAYER_ID = GetIntResult()
if (PLAYER_ID >= 0) then
  PushInt(PLAYER_ID)
  CallNative("CONVERT_INT_TO_PLAYERINDEX")
  PLAYER_INDEX = GetIntResult()
  PushInt(PLAYER_INDEX)
      PushVarPtr()
  CallNative("GET_PLAYER_CHAR")
  PLAYER_CHAR = GetIntParam(1)
  if (PLAYER_CHAR <= 0) then
    Wait(1000)
  end  
end 
  until (PLAYER_CHAR > 0)  
end


Sprawdzamy poprawność gracza. Mówiąc bardziej szczegółowo, najpierw pobieramy jego ID. Zauważ, że najpierw zostaje wywołana funkcja "GET_PLAYER_ID", a dopiero później przekazujemy wynik tej funkcji do zmiennej PLAYER_ID. Następnie sprawdzamy, czy ID gracza jest większe lub równe zeru. Jeśli tak, to wywołujemy funkcję "CONVERT_INT_TO_PLAYERINDEX". Warto zauważyć, że przed wywołaniem tej funkcji przekazujemy do niej parametr w postaci pobranego wcześniej ID gracza.
Dalej odczytujemy wynik wcześniejszej funkcji i mamy indeks gracza, który przekazujemy do kolejnej funkcji o nazwie "GET_PLAYER_CHAR". Znowu pobieramy wynik funkcji i sprawdzamy, czy zmienna PLAYER_CHAR jest mniejsza lub równa zeru. Kończymy funkcję tylko wtedy, gdy zmienna PLAYER_CHAR będzie większa od zera. Będzie to oznaczać, że gracz został już poprawnie stworzony.

Na początku może wydawać się to trochę skomplikowane. Generalnie to wszystko opiera się na schemacie:

Kod:
Przekazujemy parametry -> wywołujemy funkcję -> odczytujemy wynik funkcji


Powyższy kod będziemy wykorzystywać na początku każdego skryptu, dlatego nie musimy zgłębiać się w jego znaczenie czy sens, aczkolwiek warto poznać jego działanie.

Kod:
function BulletTime()
 if Time == 0 then
  Time = 1
 else
  Time = 0
 end

if Time == 1 then
     PushFloat(0.2)
     CallNative("SET_TIME_SCALE")
   end
if Time == 0 then
    PushFloat(1.0)
    CallNative("SET_TIME_SCALE")
  end
end


Tworzymy nową funkcję o nazwie "BulletTime". Będzie ona miała za zadanie odpowiednie ustawienie szybkości gry.
W pierwszej konstrukcji if (jeśli) sprawdzamy, czy zmienna Time jest równa "1". Jeśli wywołamy tą funkcję po raz pierwszy, zmienna Time będzie miała wartość "0", gdyż tak ustawiliśmy na początku skryptu. W zależności od obecnego stanu tej zmiennej ustawiamy ją ponownie zmieniając wartości.
Dalej mamy kolejną funkcję if, w której znów sprawdzamy stan zmiennej Time. Jeśli ma wartość "1", to zwalniamy czas. Funkcja "SET_TIME_SCALE" przyjmuje tylko 1 parametr typu FLOAT (liczba po przecinku) oznaczającego współczynnik prędkości czasu. Ustawiamy go na 0.2 i wywołujemy wspomnianą funkcję.
Dalej tworzymy kolejny warunek, tym razem dla Time równego zeru. W takim przypadku ustawiamy współczynnik prędkości czasu na 1.0, czyli normę. Na koniec zamykamy konstrukcję if i całą funkcję słówami kluczowymi end.

Kod:
function main()
 InitScript()
 while true do
  if (IsKeyPressed(9) == 1) then
   WaitForPlayerPoolCreation()
   WaitForValidPlayer()

   BulletTime()
   Wait(1000)
  end
  Wait(100)
 end
end


No i mamy naszą główną funkcję o nazwie "main". Tutaj "sklejamy" wszystko, co stworzyliśmy wcześniej. Odwołujemy się do funkcji InitScript(), następnie zapętlamy sprawdzanie, czy gracz wcisnął klawisz "TAB". Jeśli tak, to sprawdzamy, czy gracz został poprawnie stworzony (tj. gra już się zaczęła). Dalej wykonujemy funkcję BulletTime(), która odpowiada za zmianę prędkości gry. Po jej wykonaniu odczekujemy sekundę (1000 ms = 1 sek.), aby skrypt nie wykonał nam kilka razy tej funkcji, gdy np. przytrzymam klawisz.
Pierwszy słowem kluczowym end zamykamy konstrukcję if. Po tym odczekujemy 100 ms. Gdybyśmy to pominęli, gra bardzo straciłaby na płynności, gdyż za szybko odbywałoby się sprawdzanie wciśnięcia klawisza.
Drugim end zamykamy pętlę, a ostatnim end całą funkcję main().

Kod:
main();

I wreszcie wywołujemy funkcję main(), aby skrypt zaczął działać.

Jeśli czegoś nie rozumiecie, coś jest nie jasne, zapytajcie na Naszym FORUM.
Tutaj można ściągnąć kod źródłowy tego skryptu.
Dodane przez: MakG
Posting comments to this article is disabled.
Created & Powered by MakG
Wszelkie prawa zastrzeżone