Das heruntergeladene Zip wird hier hin entpackt:
ICH\Dokumente\Mygames\Unreal tournament 3\UTGame\Src
ACHTUNG: In dem Zip sind ein paar mehr Ordner. Irgendwann kommt man zu ziemlich vielen Ordnern. DIE müssen da rein! Nichts anderes!
-----------------------------------
Um dich nicht mit dem ollen Texteditor von Windoof herum plagen zu müssen, gibt’s WOTGreal.
2 Sachen brauchst du:
Das hier:
http://www.wotgreal.com/wotgreal/fil...taller3005.exe Und außerdem das hier:
http://www.wotgreal.com/wotgreal/fil...lDeveloper.zip Nach dem Installieren musst du die Dateien im Installationsordner mit denen aus dem 2ten zip überschreiben.
Das ist nur eine Testversion, aber
keine die nach 30 Tagen nicht mehr läuft! Die haben das anders gemacht:
Pro Start wartet WOT immer eine Millisekunde länger. Wenn du das Programm
also zum 10ten mal aufmachst, musst du 1 Sek. warten. Bei 100 mal 10 sek. usw.
Damit kann man aber leben
Beim allerersten Start wirst du gefragt, ob du die Pfade einstellen möchtest. Drücke dort "Ja" und wechsle in dem sich daraufhin öffnenden Fenster zum Punkt "Game Information":

(Bild: WOT1)
Dort oben bei GameType sollte UDK/UT3/DeinSpiel hin. Falls das nicht in der Liste ist, kannst du es per EditGameTypes-Button hinzufügen, du musst aber nicht.
Du kannst sonst alle Boxen freilassen, bis auf zwei:
UCC.exe File:
Source Root Dir(s):
Bei "UCC.exe File:" kommt die .exe-Datei des UDKs hinein. Die findet man in seinem UDK-Ordner im Binaries-Ordner, etwa hier: "C:\UDK\Binaries\UDK.exe"
Natürlich kann der Pfad bei dir etwas abweichen.
Nun zu "Source Root Dir(s):"
Bei UDK-Nutzern muss dort dieser Pfad hin: UDK\Development\Src
Komplett könnte das so aussehen: C:\UDK\Development\Src
Bei UT3-Nutzern muss dort der Pfad zu den oben heruntergeladenen Dateien hin.
Das wäre also: ICH\Dokumente\Mygames\Unreal tournament 3\UTGame\Src
Danach auf Apply klicken und WOT laden lassen. Dauert ein wenig.
Jetzt kanns immer noch nicht losgehen
Links in dem kleinen Fenster ist der Class-Tree (Da wo „Classes“ drüber steht!)
Nun in Unreal ist es so. Jede Klasse erweitert eine andere. Eine Klasse ist ein Script.
So wirst du ganz oben das „Object“ finden. Dort gibt’s die Basic-Sachen. Eben +,-,* und / oder auch komplexeres wie Sinus und Kosinus. Auch
Configs und und und.
Tipp:
Mit einem Doppelklick öffnest du die Klasse!
Wenn du jetzt auf das + vor Object klickst, wirst du eine weitere Flut von sachen sehen, die du vielleicht nicht aus dem ACB (Actor Class Browser) im UnrealEditor kennst.
All diese Klassen die jetzt dort sind können alles was das Object kann, und haben auch eigene Funktionen.
Interessant für uns ist erstmal nur der „Actor“. Der ist ganz oben in der Liste. Ab hier kennst sicherlich einige Actoren. Aber nicht alle
Jetzt aber wieder ans Werk!
Rechtsklick auf „Actor“. Das hier erscheint:

(Bild: WOT2)
Jetzt wird ein neues, fast leeres Script erstellt (Pass auf, dass dieser Harken dort bei „Use Extends instead of...“ an ist!) . Aber loslegen könne wir immer noch nicht!
Das was jetzt kommt, musst du immer dann machen, wenn du ein neues Package erstellt hast! (Also nicht sooo oft)
Tipp:
Packages kennst du schon aus dem ED. Dort werden Staticmeshes, Texturen und Materials in innen gespeichert. Diese PCKs haben die Endung „.upk“.
In Script-Packages werden halt Scripts gespeichert. Die haben die Endung „.u“.
Damit der Editor weiß, welche Pakete es durchsehen soll, musst du es ihm sagen.
So wirds fürs UDK gemacht: Man öffne die Datei /UDK/UTGame/Config/DefaultEngine.ini mit einem Texteditor. In dieser muss man nun nach „+EditPackages=“ suchen (STRG+F drücken!). Es sollten nun ein paar Einträge gefunden werden. Du musst deinen ans Ende der Liste mit den EditPackages schreiben, also direkt unter den letzten „+EditPackages“ Eintrag.
Der könnte so aussehen:
Code:
+EditPackages=MyFirstPackage
Abspeichern und schließen. Danach musst du ALLE Dateien des Config-Ordners löschen, bei denen
nicht „default“ vor steht! (Keine sorge, sie werden beim nächsten Start neu erstellt)
Beachte, dass du zum abspeichern den Schreibschutz entfernen musst! (Rechtsklick->Eigenschaften auf die Datei)
Eine Sache wäre da noch. Seit einem Update des UDKs werden keine ScriptLogs mehr im Editor angezeigt. Ich weiß leider auch nicht wie man sie dort wieder sichtbar macht. Deswegen benutzen wir einen kleinen Workaround um das Problem zu beheben:
- Falls du noch keine hast, erstelle dir eine Verknüpfung zum UDK auf deinem Desktop.
- Rechtsklicke diese und wähle "Eigenschaften" aus.
- Suche die Box neben der "Ziel:" steht und schreibe folgendes
hinter alles was dort drin steht:
Das könnte wenn es fertig ist etwa so aussehen:
Code:
"C:\UDK\Binaries\udk.exe" -log
Bei dir könnte im Pfad einiges anders heißen, wichtig ist, dass du -log hinten stehen hast.
Wenn sich beim starten des UDKs über diese Verknüpfung nun ein schwarzes Fenster mit einer menge Text öffnet hast du alles richtig gemacht.
------------------------------------------------------------------
So wirds für UT3 gemacht: Im Dokumente\Mygames\UT3\UTGame\Config Ordner gibt es die Datei „UTEditor.ini“. Aufmachen und nach [ModPackages] suchen. Ja, mit den [ ].
Dazu kannst du den Windows – Editor nehmen.
Die suche ist auf STRG+F.
Füge in dem Gefundenen Block diese Zeile hinzu!
Code:
ModPackages=MyFirstPackage
das sieht dann etwa so aus:
Code:
[ModPackages]
ModPackagesInPath=..\UTGame\Src
ModOutputDir=..\UTGame\Unpublished\CookedPC\Script
ModPackages=MyFirstPackage
Speichern, fertig.
------------------------------------------------------------------
Jetzt aber zurück zu unserem leeren Script, das darauf wartet gefüllt zu werden
Die ersten Schritte Jetzt geht’s endlich los
Noch ein Tipp von mir: Ziehe deine Verknüpfung vom UnrealED neben deinen Windows-Start-Knopf. Du wirst sie SEHR oft brauchen... Also. Los geht’s!
Das ist das Script:
Code:
//-----------------------------------------------------------
// MyFirstScript – Coded by [Wutz]! Blabla loool
//-----------------------------------------------------------
class MyFirstScript extends Actor;
DefaultProperties
Diese // bedeuten einen Kommentar. Alles, was dahinter ist, wird von UT ignoriert. Das gleiche geht auch mit /* und */
nur, das diese beiden Dinger über mehrere Zeilen funktionieren.
Dieses
Code:
class MyFirstScript extends Actor;
nennt man „Class-Scope“. Dort stehen sachen über das Script.
Also zuerst der Name des Scriptes und von welcher klasse es abstammt.
Tipp:
Du musst immer eine neue klasse machen. Versuche nicht die originalen UT-Klassen zu verändern! Das klappt nicht 
Wir müssen da noch etwas reinschreiben. So muss das aussehen:
Code:
class MyFirstScript extends Actor
placeable;
Tipp: Benutze die TAB-Taste, damit der Code übersichtlich bleibt! Damit sagen wir UT: Ich will den Actor aus dem ACB auswählbar machen und ihn ins Level stellen können!
Jetzt weiß ich gar nicht wo ich weitermachen soll
Öhm... Ersetze mal den DefaultProperties-Block mit diesem hier. Das sieht danach so aus:
Code:
//-----------------------------------------------------------
// MyFirstScript – Coded by [Wutz]! Blabla loool
//-----------------------------------------------------------
class MyFirstScript extends Actor;
DefaultProperties
Tipp:
Groß- und Kleinschreibung ist in UnrealScript völlig egal 
Musst du nicht verstehen. Dann hat unser Actor diesen Adler-Kopf im Editor. Sonst wäre er unsichtbar...
Zu Components komm ich später.
Jetzt machen wir mal etwas ganz einfaches: Wir schreiben etwas ins Log! (Im GenericBrowser(GB) ganz rechts. Falls du es nicht kennst...)
Dazu brauchen wir eine Funktion. Es gibt bestimmte Funktionen, die zu bestimmten Zeiten aufgerufen werden.
Das hier nennt man Funktion:
Alles, was du an Code in dein Script schreibst, kommt IMMER zwischen dem Class-Scope und dem DefProp-Block! Sonst gibt’s nen Fehler...
Jede Funktion hat diese . Sie sagen wo der „Anfang“ und das „Ende“ der Funktion ist.
Außerhalb dieser Klammern kann man nichts schreiben. Wäre ja auch unsinnig

Wann sollte das aufgerufen werden?
Wenn man eine leere Funktion hat, die sowieso nie aufgerufen wird, bringt das einem ziemlich wenig. Also nichts.
Gibt man dieser Funktion allerdings einen bestimmten Namen, wird sie sehr wohl aufgerufen. Hier ist eine Liste mit solch ein paar Namen:
PreBeginPlay: Wird vor Beginn des Spiels aufgerufen
PostBeginPlay: Wird nach dem Beginn des Spiels aufgerufen
Tick: Wird jede Sekunde so an die 1000 mal aufgerufen
Jetzt kommt Action ins Script!
Füge diese Funktionen hinzu:
Code:
Function PreBeginPlay()
Function PostBeginPlay()
Function MachWas()
Die `log Funktion ist etwas besonderes. Es ist ein „Makro“. Das erkennt man an diesem `. Der MUSS da hin! Aber NUR bei `Log! Wirklich nur da!
Es ist auch egal wenn WOTGreal das ` rot hinterlegt.Â
Variablen Als „Variable“ bezeichnet man etwas, in dem man Daten speichern kann. Also zahlen, Buchstaben und so weiter.
Erstelle eine neue Klasse, die du „MyFirstVariables“ nennst. Pass aber auf, dass du den richtigen Package Namen einträgst!
Den UnrealEditor, ich nenne ihn ihn ab jetzt ED, kannst du wieder schließen. Den brauchen wir erstmal nicht. Mit offenem ED
kann man nämlich keine Scripts compen.
Schreibe in dieses neue Script wieder „Placeable“ und das, was du oben schon in die DefaultProperties schreiben solltest rein.
Jetzt wollen wir ein bisschen rechnen
Erstelle eine Leere PreBeginPlay() Funktion. Also so was:
Code:
Function PreBeginPlay()
Und nun schreibst du direkt unter den Class-Scope das hier:
So sieht das Script jetzt aus:
Code:
//-----------------------------------------------------------
// MyFirstVariables - Coded by [Wutz]!
//-----------------------------------------------------------
class MyFirstVariables extends Actor
placeable;
var() int zahl;
var() string Text;
var int NochNeZahl;
function PreBeginPlay()
DefaultProperties
Mit dem Wörtchen „Var“ sagt man: Jetzt kommt eine Variable! Schreibt man noch () dahinter, kann man die Variable im ED einstellen.
Also in den Properties (Ich nenn die ab jetzt Props) des Actors. Ohne die klammern sieht man sie dort nicht. Man kann aber beide Typen gleich benutzen.
Hinter Var kommt der Typ der Variable. Also Text, Zahl oder was auch immer. Und da hinter kommt der Name. Gefolgt von einem ;
Tipp:
Schreibt man Var(Hallo) int Zahl; Wird die variable in den Props in der Gruppe „Hallo“ angezeigt. Probiers mal aus
Nur keine Leerzeichen...
Ohne einen Namen sind die Variablen in einer Gruppe, die so heißt wie die klasse.
Du könntest das Script jetzt compen und die Props im ED verstellen. Nur um zu sehen, was das ist
Hier ist eine Liste mit den meist gebrauchten Variablen Typen:
Int → Zahl
Byte → zahl von 0 bis 255
float → Zahl mit Komma. Also 2.5 oder 0.543 (Int und Byte können das nicht!)
Bool → Eine Art Schalter. Kann nur True oder False sein.
String → Ein ganz normaler Text. Benutz ihn nur, wenn du ihn wirklich brauchst!
Name → Ein Spezieller Text: Keine Leerzeichen oder Sonderzeichen. Braucht weniger Speicher als ein String. Du solltest alles Script interne, was mit
Texten zu tun hat, die man nicht sehen wird hiermit machen.
Class<KlassenName> → Hält eine klasse
Die Object-Variablen kommen später noch. Erstmal zeig ich dir, was du hiermit machen kannst.
Fangen wir mit int an:
function PreBeginPlay()
Der Variable NochNeZahl, die man nicht im ED einstellen kann (Das ist völlig egal und geht auch mit im ED einstellbaren), wird der wert 5-2 zugewiesen.
Also 3. Das macht man mit dem = Operator.
Hier ist eine Liste mit ein paar Operatoren:
= → Weißt etwas zu
+= → Addiert etwas hinzu
-= → zieht etwas ab
*= → Multipliziert
/= → Dividiert
Warum +=?
Zahl+NochNeZahl geht nicht!!
Zahl+=NochNeZahl schon.
Zahl=NochNeZahl+5; geht auch.
+= hat den gleichen Effekt wie
Zahl=Zahl+5
Ist nur schneller zu schreiben, außerdem sind die Prozessoren heutzutage für so was optimiert. Dann geht’s schneller
Dann gibt’s noch 2 Stück:
++ → Fügt 1 hinzu
-- → Zieht 1 ab
Auch hierfür sind Prozessoren optimiert. Außerdem kann man das noch schneller schreiben
Jetzt ist noch das Log übrig:
`log("Der Text ist: "$Text$". Die erste Zahl ist: "$Zahl$". Die zweite Zahl ist: "$NochNeZahl);
Alles, was mit " geschrieben wird ist eine String-Variable. Also ein Text. Also hat die Log-Funktion einen String-Parameter.
Auch Strings kann man mit = zuweisen. Und noch was können sie:
Man kann Variablen in sie hinein packen! So was ist sehr nützlich, wenn man etwa sagen möchte:
Du hast 47 Leben!
In Code-Form würde das etwa so aussehen:
Text="Du hast “$Health$“ Leben!";
Also um eine Variable da rein zu packen schreibst du mitten im string "$EineVariable$". Wenn die Variable am Anfang oder Ende steht musst du
das an der richtigen Seite weglassen:
Text=Health$“ ist ganz schön wenig...";
oder
Text=“Leben: “$Health;
Nichts anders hab ich in die Log-Funktion geschrieben. Nur ohne =, da es ein Parameter ist. Kommt noch
Hier ist eine Liste mit Beispielen für Variablen Zuweisungen:
Zahl=5;
bTod=true;
bTod=false;
Name='HeyHey';
PI=3.1415926535897932;
Bool variablen (Die Schalter) schreibt man normalerweise mit einem b vor dem Namen.
So weiß man sofort, dass es ein Bool ist. Du musst das nicht machen. Kannst aber
Funktionen mit Parametern Du hast sie ja schon gesehen. Aber hier nochmal genauer:
Code:
function PreBeginPlay()
function TuWasTolles(String Msg)
Das kann man auch noch erweitern:
Code:
function GanzVieleSachen(int a,int b, byte Hallo, bool bLol)
Die kann man alle benutzen, als wären es ganz normale variablen.
Sie gelten allerdings nur in dieser Funktion. Und sie sind beim Funktions-Start auf die werte gesetzt, die man eben eingetragen hat.
Gute Gelegenheit um einen kleinen Abstecher zu den Local variablen zu machen:
Code:
function WasTolles(int i)
Diese Locals kommen immer ganz oben in die Funktion. Auch diese Variablen kannst du benutzen, wie jede andere auch. Allerdings
eben nur in dieser Funktion. So muss man nicht den Arbeitsspeicher mit tausenden variablen zumüllen, die man nur ein mal kurz braucht.
Tipp:
Gebe nur Locals einen Namen der nur einen Buchstaben lang ist! Das verwirrt nicht so.
Tipp:
Findest du eine Local variable die i heißt ist es fast immer ein int!
Object Variables (Pointer) Zeit um dir mal die Funktionsweise von Unreal zu erklären:
Wie du schon weißt, ist dein Script im ED in einem „Actor“ untergebracht. Hast du 100 von diesen
Actoren in der Map, existiert dein Script auch 100 mal. Sie machen alles für sich alleine. Alle Variablen sind
ebenfalls voneinander getrennt. Die haben rein gar nichts miteinander zu tun.
Allerdings müssen die ja irgendwie miteinander „reden“ können. Dazu gibt es so genannte Pointer. Das sind variablen (Jep, die kannst du in Funktionen, hinter Var oder hinter Local benutzen) Die auf einen anderen Actor „zeigen“.
Schau dir das mal an:

(Bild: Pointer)
Die Kreise sollen hier Variablen darstellen. Würde ich etwas anhand einer Float-Variable zeigen wollen, wären da zwei Kreise. Du kannst so viele
Pointer machen, wie du willst.
Wie die jetzt wohin zeigen, und wie viele Verbindungen die haben ist vollkommen egal. Aber entscheidend ist, dass man Funktionen über diese Verbindung aufrufen kann. Auch Variablen kann man umsetzen. Man hat vollen Zugriff auf den anderen Actor. (Ausnahmen gibt es, ist erstmal egal, sind sehr wenige)
Um so einen Pointer anzulegen musst du nur
var() Actor DerAndere;
zu den Variablen schreiben.
Var() bedeutet wie gewohnt, dass eine Variable deklariert wird. Danach kommt eben der Typ der Variable, wie zb. Ind oder Float. Hier ist es eben
der Name einer Klasse. Sie sagt, welche Klassen in den Pointer rein können. Also eine Art Filter. Außerdem lässt sich einfacher mit ihnen arbeiten, wenn
man nicht extra einen Cast (Erkläre ich später) durchführen muss. Und man sieht gleich für was die Variable gedacht sein könnte.
Statt Actor kannst du jede andere klasse nehmen. Wenn du dort zb. Trigger hin schreibst, kann man nur Trigger „anzeigen“.
Dieses mal bitte var MIT (). Ich will dir nämlich was zeigen. → Compen und den ED aufmachen.

(Bild: PointerED)
1.: Den MyFirstVariables Actor auswählen und die Props aufmachen
2.: Das Prop Fenster auf „Locked“ stellen. Nun ändert es sich nicht mehr, wenn du einen anderen Actor auswählst.
3.: Irgendeinen anderen Actor auswählen (Zb. Den PlayerStart)
4.: Zuweisen
Fertig

So was hast du bestimmt schon man gesehen. Mit einem Material oder so geht das genau so. In einem Content-Package funktioniert das nämlich ähnlich.
Jetzt weißt du, wie man eine Pointer-Prop im ED zu weißt. Also ED zumachen und zurück zu Script
Im Script ist die Variable zwar noch leer, also sie zeigt auf nichts, aber wir können davon ausgehen, dass du sie beim nächsten
Test setzt. Man kann immer nur davon ausgehen, das die nicht leer sind. Deshalb muss man sicherstellen, das sie auf etwas zeigen,
bevor man sie benutzt. Sonst gibt’s ne Log-Warnung. „Accesed none blabla“ Steht dann da. Das sollte eigentlich keine Warnung sein. Betrachte es als einen
Fehler! Denn sonst wird nichts funktionieren!
Dazu noch ein Beispiel:
Du bist auf einem Klo mit 3 Kabinen. In alle drei setzt du Leute. Von jedem Notierst du den nahmen (Packst sie in einen Pointer).
Nur vom 3. nicht.
Im Code sähe das so aus:
Var() UTPawn KloMensch1;
Var() UTPawn KloMensch2;
Var() UTPawn KloMensch3;
Tipp:
Du kannst Vars und locals (Keine Parameter) mit Kommas trennen! Also zb.: Var int Huhu,Hallo,LOL;
(UTPawn ist die Klasse der „Spielfiguren“, die man steuert.)
Jetzt sagst du KloMensch1: „Spülen!“ Und er spült.
KloMensch2 sagst du „Aufstehen!“ Und er steht auf.
KloMensch3 willst du sagen „Leg dich hin!“ Aber du hast den Namen nicht, weißt nicht wen du rufen sollst, hast keine Ahnung ob da überhaupt jemand drin ist,
du weißt gar nichts! Aber du sagst trotzdem „Leg dich hin!“. Keiner Legt sich hin, und UT Loggt den Fehler: „KloMensch3 zeigt nirgendwo hin!“.
Pointer können so lange auf „none“ stehen, bis sie benutzt werden sollen. Es ist also nicht zwingend notwendig, dass sie IMMER auf etwas zeigen.
Aber wenn man sie benutzen möchte muss man erst sicher gehen, dass dort wirklich etwas drin ist. Sonst funktioniert das Script ja nicht
Damit keine Fehler entstehen gibt es ein nützliches Werkzeug:
If
Mit If kann man Dinge checken. Also ist meine Variable=2? Oder ist bTod=true? Oder ist KloMensch3=none?
So wird es benutzt:
Code:
var() Actor DerActor;
var() int Nummer;
function EinIf()
If(Nummer>2)
else
If(DerActor!=none)
if(Nummer<=5 && DerActor!=none)
}
An diesen Beispielen solltest du sehen können, wie es geht. Hier ist eine List mit If-Operatoren:
== Ist gleich (Nicht verwechseln mit = , da dieses nur zum zuweisen einer variable ist!)
< Kleiner als
<= Kleiner als oder gleich
> Größer als
>= Größer als oder Gleich
!= Ungleich
Im letzten Beispiel Steht &&. Das heißt „Und“. Also Wenn „Nummer kleiner als oder gleich 5 ist UND DerActor ist nicht none“: TU WAS!!!
Das gleiche geht auch mit || Das heißt „Oder“.
Tipp:
Dieses Symbol: | Macht man mit Alt-Gr + < Klammern gehen auch!
if(Nummer==5 && (bTod==false && DerActor!=none))
Also, wenn du nicht 100%ig sicher bist, dass der Pointer auf etwas zeigt, benutz if(DerActor!=none).
Wie du Pointer im ED zu weißt weißt du jetzt.
Du musst noch lernen, wie man so was im Script macht.
Das ist nicht einfach (Eigentlich schon, aber du kennst die ganzen Klassen und Variablen noch nicht auswendig).
Wir wollen uns jetzt mal die GameInfo angeln. In der GameInfo Klasse stehen die Spielregeln für zb. Deathmatch oder CTF. Das sind auch Actoren.
Es gibt immer eine Möglichkeit an die GameInfo (Kurz GI) ran zukommen: Die WorldInfo. Da stehen sachen über die Map drin. Der Autor, usw.
Und eben die GameInfo!
Da unsere kleine Klasse alles kann, was die klasse „Actor“ kann, haben wir schon die Variable „Worldinfo“. Diese zeigt direkt auf die Worldinfo.
Du siehst keine Variable, die „Worldinfo“ heißt in deinem Script? Schau mal in die Klasse Actor bei Zeile 218.
Jetzt lernst du, wie man auf variablen durch einen Pointer zugreift.
In der Actor-Klasse sieht die Variable Worldinfo so aus:
var const transient WorldInfo WorldInfo;
Denke dir den ersten Kram einfach weg. Also so:
var WorldInfo WorldInfo;
Lass dich nicht verwirren! Es gibt eine Klasse, die Worldinfo heißt! Die von Epic haben die Variable halt genau so genannt.
Dann wollen wir uns mal die GI holen:
Code:
var() float NewSpeed;
function PreBeginPlay()
In der Klasse Worldinfo gibt es einen Pointer, der „Game“ heißt und direkt auf die GameInfo zeigt.
Pointer weist du natürlich wie ganz normale Variablen mit dem = zu.
Tipp:
Wenn du STRG gedrückt hältst und auf eine Variable, Funktion oder den Namen einer Klasse Klickst, springt WOT direkt dorthin oder
öffnet die Klasse. Praktisch praktisch 
Wenn du den . Hinter Worldinfo machst, öffnen WOT ein kleines Fenster, mit allen sachen, die die klasse Worldinfo kann.
Musst nur Game eingeben und Enter drücken.
Sobald du die ( machst, kommt ein kleines gelbes Fensterchen. Es zeigt alle Props der Funktion. Ein cooles Feature von WOTGreal.
Mit dem Punkt sagst du: Ich will eine variable haben oder eine Funktion aufrufen! Und zwar aus dem Actor, auf den der Pointer zeigt.
Nun zeigt die variable GI auf die GameInfo. Und wir können mit ihr arbeiten. Und zwar mit der Funktion SetGameSpeed.
Dort kommt die variable NewSpeed hinein. (Die du natürlich im ED einstellst, sie hat zwei klammern

).
Für so was braucht man eigentlich keine eigene Variable. Man kann so oft „weiter verbunden“ werden, wie man will.
Code:
Worldinfo.Game.SetGameSpeed(NewSpeed);
Würde es also auch tun.
Variablen kannst du so auch ganz bequem zuweisen. Etwa so;
Code:
Zahl=EinActor.EineZahl;
Das geht auch anders herum:
Code:
EinActor.EineZahl=Zahl;
Jetzt weißt du, wie man von einem Actor auf den Anderen zugreift!
Funktionen überschreiben Das, was wir jetzt machen wollen, ist etwas komplexer. Funktionen werden ja irgendwann aufgerufen.
Pre und PostBeginPlay() kennst du ja schon. Aber es gibt noch tausende mehr! Du musst dir nur mal eine der längeren Klassen
von UT anschauen. Bevor wir anfangen können, brauchen wir noch einen kleinen Actor, der die Controller-Klasse, die für alle
Spieler benutzt werden soll umstellt. (Nur zum Testen! Nicht Online kompatibel(Glaub ich)! Mach das später in einen Mutator!)
Controller sind Actoren die alles was der Spieler kann verwalten. Durch sie kann man schießen, laufen, sich um gucken und so weiter.
Dazu braucht man noch einen „Pawn“. Pawn bedeutet auf Deutsch so viel wie „Spielfigur“. Es ist also der Typ, den man Steuert,
Wir brauchen hier nur den Controller. Wie du eine neue Pawn und ein neues Hud machst sag ich dir aber gleich trotzdem.
Ein Controller ist unsichtbar. Man sieht ihn nicht. Dazu ist der Pawn da. Damit UT weiß, dass es deinen Controller statt dem Standard Controller benutzen soll,
musst du es ihm sagen. Ist ja klar
Dazu musst du jetzt eine neue Klasse unter Actor erstellen. Nenn sie wie du willst (Ich nenn die teile immer GameModificator). Mach sie Placeable und
pack den Kram von oben wieder in die DefProps. Nun musst du noch die PreBeginPlay() Funktion hinzufügen. So:
Schreib es nicht ab, sondern versuche es aus den Texten zu machen! Vergleiche es nur mit dem hier! Du musst üben, bzw. fähig dazu sein das selber zu schreiben
Code:
//-----------------------------------------------------------
// MyGameModificator - Coded by [WuTz]!
//-----------------------------------------------------------
class MyGameModificator extends Actor
placeable;
function PreBeginPlay()
DefaultProperties
Da wir jetzt wieder einen Grundstein haben, könne wir anfangen. Dieser Actor kann dir später wirklich noch von nutzen sein.
In dem Modificator (Dem Modi

), den ich für Tre – Last Life gemacht habe sind mehr als 250 variablen, mit denen man das Spiel verändern und
anpassen kann
So was wollen wir auch machen. Aber nicht so groß

Hier reicht nur eine Variable. Und zwar eine vom Typ „Class<PlayerController>“.
Nenne sie MyControllerClass.
Code:
var() class<PlayerController> MyControllerClass;
Und damit etwas passiert musst du die variable PlayerControllerClass aus der GameInfo in der PreBeginPlay() Funktion mit der
MyControllerClass variable überschreiben.
Code:
function PreBeginPlay()
Wenn du das nun Compst, und den Actor in ein Level stellst, kannst du die Controller klasse verändern. Da du aber nur die Standard Controller (Also 2 Stück) von
UT hast bringt das noch nicht viel. Also musst du dir einen eigenen machen.
Erstelle nun einen Neue klasse unter UTPlayerController. Du findest den UTController unter Object->Actor->Controller->PlayerController->UTPlayerController.
Nenn sie MyController oder so.
Da man diesen Actor nicht in die Map packen muss, brauchst du ihn nicht Placeable zu machen. Er kann auch unsichtbar bleiben. Also reicht das leere Script.
Bis jetzt:
Schreibe die Funktion StartFire hinzu! Dort sind EINGIGE neu sachen dran.
So sieht sie aus (Leer in der MyController klasse):
Code:
exec function StartFire( optional byte FireModeNum )
1.Exec: Wenn du einmal ein Exec vor der Funktion sehen solltest, kannst du sie aus der Console aufrufen.
Du kannst also die Console mit der TAB-Taste öffnen und den Namen eintippen. Gefolgt von den Parametern.
Also für StartFire müsstest du das hier eintippen:
StartFire <FeuerModusNummer>
Mehr nicht. <FeuerModusNummer> kannst du durch die nummern 0 oder 1 ersetzen, oder du lässt es weg...
Du kannst Exec Funktionen natürlich, wie jede andere Funktion auch, durchs Script aufrufen. Sind aber nützlich zum testen,
und außerdem kann man sie auf Tasten legen.
2.Optional: Vor der Variable steht Optional. Das heißt, man kann einen Parameter eintragen, man muss aber nicht.
Ob man nun StartFire(); Oder StartFire(0); Schreibt ist völlig egal. Ohne Optional würde UT bei der ersten Version einen
Fehler ausspucken.
Tipp:
Du kannst Optionalen Parametern einen Standardwert zuweisen! Der wird automatisch benutzt, wenn der Parameter weg gelassen wurde:
Function MachWas(optional int Zahl=5)
Hätten wir das auch geklärt.
Die Funktion StartFire gibt es erst seit der PlayerController klasse. In Actor gibt es sie noch nicht. Man kann sie deshalb dort auch noch nicht aufrufen.
Da wir jetzt aber eine Controller klasse haben können wir sie benutzen. Allerdings wurde sie ja schon in der Controller klasse von UT benutzt...
Egal. Wenn du sie in eine Neue klasse schreibst, und auch diese klasse des Actors benutzt wird, werden auch alle alten Funktionen der übergeordneten Klassen
mit den Neuen aus deiner Klasse ersetzt! Wenn UT also von irgendwo aus StartFire() aufruft, wird nicht mehr die UT-Version benutzt, sondern deine! Dadurch, dass
du sie in deine Klasse geschrieben hast, hast du sie überschrieben! Das gleiche hast du übrigens schon mit PreBeginPlay() gemacht. Die stammt nämlich aus der Actor Klasse.
Das geht übrigens mit fast allen Funktionen.
Ausnahmen sind:
Funktionen vor denen Native steht.
Funktionen vor denen Final steht.
In der Regel ist es aber nicht wichtig diese Funktionen zu überschreiben.
Da diese Funktion in deiner Klasse leer ist, wird man nicht mehr Schießen können. Du hast sie ja überschrieben. Das ist erstmal egal. Später sag ich dir,
wie man das umgehen kann.
Eine recht einfache Methode, dir das ganze zu demonstrieren ist, etwas mit den Leben des Spielers anzustellen. Jeder Controller hat einen Pawn.
Und damit man ihn benutzen kann, gibt es einen Pointer zu diesem Pawn. Nicht verwirrt sein, aber die Variable heißt wie die Klasse „Pawn“. Nämlich auch
Pawn. Ist das gleiche, wie mit Worldinfo.
Die Leben des Spielers werden in der Variable „Health“ im Pawn gespeichert. Mit Pawn.Health erhält man also den Zugriff.
Jetzt kannst du in der StartFire Funktion die Leben des Spielers mit zb. 2 multiplizieren. Oder auch andere tolle sachen machen
Pawn.Health*=2;
Und fertig. Compen und Ab in den ED!
Du darfst nicht vergessen deinen Modi in die Map zu packen und deine Controller klasse aus der List auszuwählen.
(Speichern nicht vergessen! Sonst könnte es abstürzen...)
Jetzt werden sich deine Leben bei jedem Aufruf von StartFire() verdoppeln

Und diese Exec Funktion wurde auf zwei tasten gelegen...
Nämlich auf die Maus tasten! Immer wenn du eine davon drückst, wird StartFire(0); Oder StartFire(1); aufgerufen! Also bekommst
du bei jedem klick mehr leben

(Bild: Health)
3200 Leben

Toll sowas!
Nachteil: Du hast die Funktion überschrieben. Der Code, der dafür sorgt, dass man schießen kann ist also weg. Aber das ist kein Problem!
→ ED Zumachen und zurück zu WOTGreal.
Es gibt den Befehl „Super“, was auf Deutsch soviel wie „Über“ heißt (Nicht „todschick“ oder „echt geil“, wie mein Englisch-Übersetzer meint

, es kommt aus dem Lateinischen.(Obs in Englisch auch so ist bin ich mir nicht sicher)).
Damit kann man Funktionen aus der Übergeordneten klasse aufrufen. Also welche in denen der fehlende Code noch vorhanden ist.
Tipp:
Die übergeordnete Klasse nennt man „Parent-Class“. Alle Untergeordneten Klassen nennt man „Sub-Class“ oder „Child-class“.
Super kann man wie einen Pointer benutzen.
Super.MeineFunktion(DieParameter);
Schreib das in deine StartFire Funktion.
Tipp:
Manchmal ist es wichtig, wo du es hinschreibst. Möchtest du mit etwas arbeiten, was in der „Alten“ Funktion ausgerechnet wurde, so muss es am Anfang stehen.
Soll erst zb. Einer der Parameter geändert werden muss es ans Ende. Hier ist es aber egal.
Damit alles richtig funktioniert muss die StartFire Funktion aus der Parent-Class noch den Feuermodus wissen. Gib ihr einfach den FireModeNum-Parameter.
So sieht das aus:
Super.StartFire( FireModeNum);
Wenn du das jetzt Compst kannst du schießen, und deine Leben füllen sich dabei auf.
Casting
Wie du vielleicht gesehen hast, ist die Variable „Pawn“ ein Pointer der Klasse „Pawn“. Drück mal STRG und klicke auf das Wort „Pawn“ (In WOTgreal), und
wähle „Class: Pawn, Package: Engine“-> OK.
Die Klasse „Pawn“ öffnet sich. Diese hat ein paar SubClasses. Mitunter den UTPawn. Dieser wird von UT benutzt. Und er hat viele Funktionen, die der
„normale“ Pawn nicht hat! Zb.
exec simulated function FeignDeath()
Das gibt’s erst im UTPawn.
Tipp:
Die Klassen, die ein UT vorne im Namen haben, sind die Unreal Tournamet 3 Klassen. Alle anderen sind Engine-Klassen, die immer in der UnrealEngine3 dabei sind.
Auch bei anderen spielen, wie Bioshock oder Mirrors Edge gibt’s die.
Tipp:
„Simulated“ hat was mit Online-Coding zu tun, was weiß ich aber auch nicht!
Ignoriere es erstmal.
Ich hab eben bis jetzt nur Singleplayer Mods gemacht...
Da der Pointer „Pawn“ nur die Funkionen aufrufen kann, die die klasse „Pawn“ kann, kann man FeignDeath() von dort aus nicht auf den Normalen weg aufrufen,
da sie schon in der neueren UTPawn-Klasse ist.
Tipp:
Du kannst in einen Pointer der auch alle SubClasses des erwarteten Typs eintragen. Bei einem Pawn-Pointer kannst du also auch einen UTPawn hinein tun.
Wie macht man das denn jetzt? Ganz einfach! Man kann UT Sagen, Konvertiere die Variable vom Typ Pawn in eine Variable vom Typ UTPawn! So kann man dessen
Funktionen aufrufen.
So wird’s gemacht:
Code:
UTPawn(Pawn).FeignDeath();
Zuerst den Namen der Klasse, die man wünscht, dann in Klammern der Pointer, von dem man Konvertieren möchte, gefolgt vom Punkt Und der Funktion oder Variable. So wird der Pointer der Klasse „Pawn“ wie ein Pointer der Klasse „