Herzlich Willkommen zu meinem ersten Tutorial.
Oh, ich bin ja so aufgeregt. Also wo fang ich am besten an ? Ja...also das ist ein Tutorial für ein eigenes Itemsystem.
Ihr solltet bereits einige Erfahrung mit dem RPGmaker gesammelt haben, bevor ihr euch dazu entschließt, ein eigenes Itemsystem in euer Spiel einzubauen.
Zumindest sollte ihr die folgenden Punkte beherrschen:
- Der Umgang mit Variablen und die Verwendung von Zeigern/Pointers.
- Der Umgang mit Switches.
- Der Umgang mit Labels
- Die Fähigkeit seine Skripte genügend zu kommentieren, damit man sich zurecht findet. (Okay das ist nicht notwendig, aber hilft enorm. Ihr solltet es machen.)
So nun zu grundlegenden Informationen...
~Die Idee~
Wenn ihr ein Itemsystem so machen wollt, wie ich es in diesem Tutorial beschreibe, braucht ihr auch ein eigenes Shopsystem, da die Items in Variablen gespeichert werden und komplett unabhängig von der Database sind.
Das setzt zwar noch einmal MEHR Aufwand vorraus, aber man kann damit seinem Spiel auch etwas individuelles verpassen und ein sich bspw. ein eigenes System für Item's überlegen.
Da die Item IDs in Variablen gespeichert werden, können diese theoretisch von -999.999 bis +999.999 gehen. Somit könnte man 2*999.999 also 1.999.998 verschiedene Items erstellen, da die 0 für "kein Item vorhanden" belegt wird.
Das macht allerdings relativ wenig Sinn, da es (vermutlich) keine Spiele gibt/geben wird in denen es notwendig ist, soviele verschiedene Items zu haben. Außerdem kann man so Items mehr/weniger als 99 mal stappeln.
~Sich ein System überlegen~ (Beispiel)
Bringen wir also ein bisschen System in die Sache:
- Man benutzt immer Item IDs mit einem Mindestwert von 100.000 (das ist kein Problem da man Variablen ja bis auf 999.999 stellen kann.)
- Man kann sich verschiedene "Kategorien" machen indem man die Hunderttausenderziffer verändert. Beispiele:
-> Items mit einer Hunderttausenderziffer von 1 sind Heilitems (also alle Items mit einer ID von 100.000 bis 199.999)
-> Items mit einer Hunderttausenderziffer von 2 sind Schlüsselitems
-> Items mit einer Hunderttausenderziffer von 3 sind Ausrüstung
-> Items mit einer Hunderttausenderziffer von 4 sind Monsterdrops
- Die Zehntausenderziffer kann dann zur Unterscheidung verwendet werden. Beispiele:
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 1 sind Heilitems, die HP heilen
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 2 sind Heilitems, die MP heilen
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 3 sind Heilitems, die HP & MP heilen
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 4 sind Heilitems, die wiederbeleben
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 5 sind Heilitems, die Statusveränderungen heilen
-Die Tausenderziffer kann dann beispielsweise den Grad oder das Level des Items zu bestimmen. Auch hier wieder Beispiele:
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 1 und einer Tausenderziffer von 1 ist das Item "Heilkraut"
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 1 und einer Tausenderziffer von 2 ist das Item "schwacher Heiltrank"
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 1 und einer Tausenderziffer von 3 ist das Item "Heiltrank"
-> Items mit einer Hunderttausenderziffer von 1 und Zehntausenderziffer von 1 und einer Tausenderziffer von 4 ist das Item "starker Heiltrank"
-Die Hunderterziffer kann angeben ob das Item im Menü benutzt werden darf (1= ja, 2= nein)
-Die Zehnerziffer gibt dann an ob das Item im Kampf verwendet werden kann oder nicht (Auch hier 1= ja, 2= nein)
-Die Einerziffer kann auch noch eine Funktion haben.
-So ist z.B. das Item mit der ID 114.110 ein "starker Heiltrank" und ist im Menü und Kampf benutzbar.
-Ein weiteres Beispiel: ItemID = 123.110 Item = "Manatrank" und ist im Menü und Kampf benutzbar.
Hinweis: Der RPGmaker2k kann Variablen bis 999.999 haben und der RPGmaker2k3 bis 9.999.999
So kann man ein einfaches System in die Variablen seiner Item IDs verbauen. Wie ihr an die einzelnen Ziffern kommt, sollte eigentlich klar sein, da ich das Verwenden von Variablen vorraussetze. Der Vollständigkeit halber sag ich es aber trotzdem
Ihr müsst die Modulusoperation benutzen. Modulus gibt euch den Rest einer ganzzahligen Division aus. D.h. wenn man die einer Ziffer abfragen möchte muss man die ItemID am Besten in eine neue Variable kopieren (ItemID 1er) und setzt diese gleich der ItemID.
Nun verwendet man die Modulusoperation auf die Variable "ItemID 1er".
Wenn man die 10er Stelle haben möchte benutzt man die Modulusoperation mit 100. Allerdings muss man dann abfragen ob die Variable über 90,80,70,60,50,40,30,20,10 ist. Dasselbe Verfahren gilt bei Hunderterziffer usw. Einfach eine 0 dranhängen.Zitat von EasyEventExporter
So genug zur Theorie hinter dem System. Nun kommen wir zu eigentlichen Umsetzung. Ihr solltet auch beachten dass ich den Makercode auch für mich mit Kommentaren ausgeschmückt habe. Hauptsächlich um sich wieder reinzufinden, nachdem man längere Zeit nicht dran gearbeitet hat.
~Einbauen des Systems~
~Die Truhe~
Als erstes brauchen wir eine Truhe die uns ein Item ausgibt. Dazu benötigen wir zwei Events. Ein Mapevent für die Truhe und ein Common Event für das eigentliche Ausgeben des Items, da das Event bzw. der Eventcode der Truhe nicht immer riesengroß sein soll.
Für die Truhe erstellen wir ganz normal ein Event auf der Map. In diesem Event setzen wir (beispielweise) die Variable 208:ItemID# auf die ID, welche das Item das wir erhalten sollen hat. In unserem Beispiel 114100 also einen "starken Heiltrank".
Dann rufen wir das Common Event "Itemausgabe eig Inv" auf.
Wie man hier sieht wird zuerst die "ItemID#" gesetzt und dann das CE zur Ausgabe aufgerufen. Danach wird abgefragt ob der "Switch 1:Item.Got" ON ist. Wenn dies der Fall ist wird der Switch der Truhe auf ON gesetzt und "Item.Got" auf OFF.
Die Truhe wird also nur umswitchen wenn man das Item wirklich bekommen hat. Wann der Switch "Item.Got" umgelegt wird, sieht man im CE. Der Rest in diesem Event ist nicht unbedingt notwendig und eher reine "Kosmetik".
~Die Ausgabe der Items~
Zum CE:
Okay nun haben wir ein schönes CE. Aber was macht das ganze ?
So als erstes setzten wir uns unsere Variablen zurecht.
Zuerst wird unsere Variable "ItemPointer" auf 1 gesetzt, da unsere Variablen bei 1 anfangen und 50 aufhören (das ist ein Beispiel, die Werte könnt ihr beliebig verändern) und wir zuerst das Item in diesem "Slot" abfragen wollen.
Dafür wird die Variable "PointedItem" benutzt. Wir setzen sie auf auf den Wert auf der in Variable 1 (unserem ersten ItemSlot) ist. Dafür benutzen wir Value Stored in Index.
Als nächstes machen wir dies mit den Variablen "StackPointer" und "PointedStack" (StackPointer nimmt den Wert 51 an, da unsere erste Variable für die Menge die 51. Variable ist).
Danach nochmal "ItemSlot" und "ItemSlotCheck". Dem ein oder anderem wird sicherlich aufgefallen sein, dass das dasselbe ist wie bei "ItemPointer" und "PointedItem", ich mache das so, damit ich die Gewissheit habe, dass sich diese Variablen nicht überschneiden werden, da ich sie für separate Zwecke benutze. Natürlich kann man das auch nur mit 2 von den 4 Variablen machen.
Als letztes setzen wir noch "StackSlot" auf 51.
Nachdem die Variablen gesetzt sind, fangen mir nun mit dem eigentlichem Event richtig an.
Als erstes soll überprüft werden, ob sich das Item bereits in unserem Inventar befindet damit wir nicht 2 separte Stacks von diesem Item haben.
Dafür wird mitels einer Conditional Branch (oder auch Fork) abgefragt ob "ItemID#" gleich "ItemSlotCheck" ist.
Wenn sie gleich sind, wird die Variable, welche die Menge bestimmt um 1 erhöht. Damit dies bei der richtigen geschieht, benutzen wir hier einen Zeiger/Pointer. Wenn man möchte das ein Item nur 99 mal stappelbar ist, nimmt man beispielsweise noch eine Variable "StackSlotCheck" und verfährt mit dieser genauso wie mit "ItemSlotCheck" und vor erhöhen der Menge wird abgefragt ob "StackSlotCheck" < 99 ist. Und "Item.Got" wird auf ON gestellt. Anschließend wird zum Ende des Events gesprungen.
Wenn sie ungleich sind wird "ItemSlot" um 1 erhöht und "ItemSlotCheck" mittels Value Stored in Index erneut ausgerichtet.
Diese Abfrage wird nun solange durchlaufen bis entweder ein Item gefunden wurde, oder "ItemSlot" den Wert 51 erreicht, da es nun bei den Variablen für den Mengen angekommen ist.
Ist das der Fall, so ist das Item noch nicht in unserem Inventar enthalten.
Also wird geprüft ob es noch einen freien Slot, in den ein Item kann, gibt.
Dafür brauchen wir wieder eine Conditional Branch.
Wenn "PointedItem" 0 ist, dann soll unser Item als neuer Slot im Inventar registriert werden. Also setzen wir Variable Reference "ItemPointer" auf den wert von "ItemID#" (wurde in der Truhe festgelegt). und erhöhen die zugehörige Mengenvariable um 1. Danach wird "Item.Got" auf ON gestellt und zum Ende des Common Events gesprungen.
Wenn das nicht der Fall ist, werden "ItemPointer" und "StackPointer" um 1 erhöht und "PointedItem" und "PointedStack" werden erneut ausgerichtet.
Auch diese Abfrage wiederholt sich so oft bis etwas gefunden wurde oder "ItemPointer" den Wert 51 erreicht und springt dann zum Ende des CE.
Wenn das Item also nicht schon im Inventar war und es auch keinen freien Platz gab, wird "Item.Got" nicht auf ON gestellt und die Truhe somit auch nicht deaktiviert.
So...das war der Teil zum Erhalten der Items.
~Das Sortieren der Items~
Jetzt kommen wir zum Sortieren der Items. Für das Sortieren verwende ich den Sortieralgorithmus Gnomesort, da dieser einfach im RPGmaker umzusetzen ist. (Gnomesort: http://de.wikipedia.org/wiki/Gnomesort).
Zuerst kopiere ich allerdings die Werte der Variablen 1-100 in die Variablen 101-200. (Das ist nicht unbedingt notwendig, aber wenn man nachher evtl noch andere Variablen sortieren will ist es einfacher, da man diese auch kopieren kann)
Den Code für's Kopieren werde ich allerdings nicht ausfürhlich kommentieren.
So nachdem die Items kopiert sind, beginnt das eigentliche Sortieren. Ich zeige euch hier wie man die Items nach der (selbst zugewiesenen) ID sortiert. Wenn ihr das System benutzt, dass ich oben beschrieben habe, dann sind eure Items gleich auch noch Kategorisch geordnet.
Erst einmal der Code:
Ich denke die Kommentare mit dem ich meinen Code versehen habe und die Wikipediaseite zu Gnomesort erklären dieses Event eigentlich ganz gut.
Also als erstes setzen wir "ItemPointerSort" und "ItemPointerSort2" auf 101 und 102, da wir an die beiden erstens Inventarslots wollen (wurden ja kopiert) und dann "StackPointerSort" und "StackPointerSort2" auf 151 und 152.
Nachdem wir das erledigt haben, setzen wir Label1 (Alternativ kann man hier auch eine Schleife (Loop/Cycle) starten lassen, aber ich arbeite lieber mit Labels).
Nach dem Label werden die Item IDs und die Stack IDs verteilt und in den Variablen "ItemID#","ItemID#2","StackID#" und "StackID#2" gespeichert.
Jetzt kommt die Abfrage.
Wenn "ItemID#" kleiner ist als "ItemID#2" dann sind die beiden Zahlen in der richtigen Reihenfolge und "ItemPointerSort", "ItemPointerSort2", "StackPointerSort" und "StackPointerSort2" werden um 1 erhöht.
Wenn dies allerdings nicht der Fall ist und "ItemID#" größer ist als "ItemID#2", dann sollen die beiden getauscht werden. Da es allerdings keine direkte Funktion zum Tauschen gibt, müssen wir uns anders helfen. Wir speichern "ItemID#" in "swapItemID" und "StackID#" in "swapStackID". Anschließend setzen wir "ItemID#" auf "ItemID#2" und "StackID#" auf "StackID#2" bevor wir "ItemID#2" auf "swapItemID" und "StackID#2" auf "swapStackID" setzen. Nun haben wir die beiden Werte vertauscht.
Nach dem Vertauschen müssen "ItemPointerSort", "ItemPointerSort2", "StackPointerSort" und "StackPointerSort2" um 1 reduziert werden.
Anschließend kommt noch eine Abfrage die abfragt, ob "ItemPointerSort" gleich 100 ist. Wenn es nämlich 100 ist ragt es aus dem Arbeitsarray raus wäre gleich dem Wert der 50. Mengenvariable der Items. Das wäre also der Fall, dass der Sortieralgorithmus 1 Schritt nach "links" will, aber dort begrenzt ist. Also müssen wir "ItemPointerSort", "ItemPointerSort2", "StackPointerSort" und "StackPointerSort2" auf 102,103 und 151,152 setzen (oder einfach 2 addieren).
Als vorletztes vom eigentlichen Sortieren kommt noch die Abfrage ob "ItemPointerSort" gleich 150 ist. (Alternativ könnte man abfragen ob "ItemPointerSort2" gleich 151 ist (und somit außerhalb des Arbeitsarrays ist)). Wenn das der Fall ist kommt ein JumpToLabel:2(oder wenn mein mit einer Loop arbeitet ein Break out of Lopp),da der Sortiervorgang abgeschlossen ist.
Nach der Abfrage kommt JumpToLabel:1 (bzw. das Ende der Loop).
So nun wird ganz am Ende dieses CE das CE "Items korrigieren" aufgerufen.
~Die Itempositionen korrigieren~
Mit dem eigentlichem Sortieren sind wir zwar fertig, aber die 0 wurde mitsortiert. Das heißt ihr werdet vielleicht erstmal eine gewisse Anzahl an Items mit der ID 0 haben bevor irgendwann ganz hinten (z.B. bei Itemslot 48,49 und 50 wenn man nur 3 Items hatte) eure sortierten Items kommen.
Um diesen "Missstand" zu beheben benutzen wir jetzt das CE "Items korrigieren". Natürlich könnte man das auch im Sortierevent dranhängen, aber ich habe lieber alles sortiert und weiß welcher Teil was bewirkt.
Der Code:
Auch hier werden zuerst alle nötigen Variablen gesetzt. Ich denke dazu muss ich nicht mehr viel sagen.
Nun fängt das System mit dem Nachrücken an.
Zuerst wird ein Label gesetzt, das nachher wieder mit einem JumpToLabel eine Schleife darstellt. Dann wird abgefragt ob die "ItemID#" an der Stelle gleich 0 ist.
Wenn das der Fall ist, dann müssen die hinteren Items nachrücken.
Als erstes stellen wir den Switch "ItemCorrector" auf ON. Warum erkläre ich später. Dann wird abgefragt ob die Variable "Sortierzähler" kleiner oder gleich 50 ist.
Wenn "Sortierzähler" kleiner oder gleich 50 ist, werden die Schritte für das Korrigieren ausgeführt. Das heißt in die Slotnummer die bei "ItemCorrectSlot" steht (Variable Reference) wird die "ItemID#2" (Value of Variable) reingeschrieben. Somit ist das 2. Item auf Platz 1 gerückt. Damit das auch mit der Menge geschieht, muss man das auch mit "StackCorrectSlot" und "StackID#2" machen. Danach werden die Variablen bearbeitet, damit das beim nächsten durchgang einen Slot höher passiert (Item 3 rutscht auf Plat 2 usw.) Anschließend wird "Sortierzähler" noch um 1 erhöht, da der Durchgang 50 mal (Anzahl der Itemslots) wiederholt werden soll.
Wenn "Sortierzähler" größer als 50 ist, werden die Variablen wieder auf die Anfangswerte (am Anfang des CE) gesetzt, damit erneut die erste Item ID geprüft wird.
Wenn diese gleich 0 ist fängt das ganze von vorne an. Andernfalls Wird das CE aus der Label-Schleife springen.
Nun wird überprüft ob der Switch "ItemCorrector" ON ist.
Wenn ja ist das Nachrücken mindestens einmal durchgelaufen und d.h. alle Variablen wurden verschoben und der letzte Slot muss eine 0 sein. Da er das aber nicht ist, wird jetzt sowohl bei dem letzten Itemslot als auch bei dem letzten Stackslot die Variable auf 0 gesetzt und der Switch "ItemCorrector" wieder auf OFF gestellt.
Jetzt sind alle unsere Items fertig sortiert und in einer schönen Reihenfolge. Alle Items die wir nicht haben (Item ID = 0) sind hinter allen anderen Variablen.
Somit sind wir nahezu komplett fertig. Allerdings müssen wir noch die Variablen aus dem Arbeitsarray zurück in das richtige Array kopieren. Hier gebe ich ebenfalls nur unkommentierten Code.
So das wäre es dann erstmal mit dem eigenem Itemsystem. Ihr müsstet aber noch ein eigenes Shopsystem machen um die Items zu kaufen bzw. mit ihnen zu handeln und ein eigenes Menü um sie zu benutzen. Das sollte aber keine allzu große Herausforderung mehr darstellen, da das hauptsächlich Abfragen sind und ein paar Bilder anzeigen lassen oder sich ein Menü auf eine Map basteln.
Also das war jetzt mein Tutorial zum Erstellen von einem eigenem Itemsystem. Da es mein allererstes Tutorial ist hoffe ich euch hat's gefallen, ihr konntet das ein oder andere lernen (dafür sind Tutorials ja da) und das man mich und meine Schreibweise verstehen konnte. (: Ich würde mich über konstruktive Kritik freuen. (:
LG Quetschi
PS: Ich hoffe es haben sich keine Rechtschreib- oder Grammatikfehler eingeschlichen.