Erstellen eines Save/Load Systems (neu)

[contentad]


Erstellen eines Save/Load Systems (neu)

zum Anfang

1. Einleitung

Für Multiplayer RPGs sind Savesysteme heutzutage ein Muss. Doch wenn man dann speichern will, wird einem plötzlich dieser ellenlange Code aus Buchstaben, Zahlen und Sonderzeichen vorgeworfen, den man schnell abschreiben muss, bevor er verschwindet.

Viele dieser Probleme sind durch einen besseren Algorithmus vermeidbar. Wie man einen solchen erstellt, bleibt vielen jedoch oft ein Rätsel. Dieses Tutorial soll die Grundlagen des Savecode-Verfahrens erklären und verdeutlichen, wie man einen Savecode kurz, übersichtlich und sicher macht. Dabei werde ich der Einfachheit halber GUI-Trigger aufschreiben, obwohl viele davon eher als Funktionen genutzt werden und man daher mit Jass besser dran ist. Die beschriebenen Verfahren sind aber gleich.

Anmerkung: In den Trigger-Beispielen wurden Klammern entfernt, um das Ganze besser lesbar zu halten.

zum Anfang

2. Das Verfahren

Die grundlegende Idee hinter dem Savecode ist ein anderes Zahlensystem. Das bedeutet, dass man anstelle der üblichen zehn Ziffern (0,1,2,3,4,5,6,7,8,9) deutlich mehr nimmt. Je mehr Ziffern ein Zahlensystem hat, umso kleiner wird die Stellenzahl.

Einschub: Wie funktionieren Zahlensysteme?

Wenn ihr bereits wisst, wie Zahlensysteme funktionieren, dann könnt ihr diesen Einschub überspringen.

Wir rechnen normalerweise in einem Zahlensystem mit 10 Ziffern. Die erste Ziffer (also die Ziffer, die sich am weitesten “’rechts“‘ befindet) zählt einfach, die zweite zählt zehnfach, die dritte hundertfach (10*10), die vierte tausendfach (10*10*10) usw.

Im Allgemeinen hat man b Ziffern, die erste Stelle zählt 1-fach, die zweite zählt b-fach, die dritte b*b-fach usw.

Als Beispiel betrachten wir das 4er-System, in dem es nur die Ziffern 0,1,2 und 3 gibt. Um aus dem 4er-System ins 10er System um zurechnen genügt es die einzelnen Ziffern mit ihrer Wertigkeit zu multiplizieren und dann alles zu addieren. Da die erste Ziffer 1-fach zählt multiplizieren wir sie mit 1. Die zweite Ziffer mit 4, die dritte mit 16 (4*4), die vierte mit 64 (4*4*4) usw.

Aus der Zahl 1032 im 4er-System wird dann 2*1 + 3*4 + 0*4*4 + 1*4*4*4 = 2 + 12 + 0 + 64 = 78 im 10er-System.

Um eine Zahl vom 10er-System ins 64er System umzurechnen geht man am besten anders herum vor, fängt also bei der größten Ziffer an. Dann überprüft man immer, wie viel von der umzuwandelnden Zahl in die aktuell betrachtete Stelle passt, zieht dies anschließend von der umzuwandelnden Zahl ab (um den Rest der Division zu erhalten) und macht (mit dem Rest) an der nächsten Stelle weiter.

Als Beispiel wollen wir 78 vom 10er- ins 4er-System umwandeln.

Wir fangen mit einer Stelle an, die auf jeden Fall groß genug ist, zum Beispiel der fünften Stelle, die ja 256-fach zählt (4*4*4*4). Nun fragen wir uns wie oft die 78 in die 256 passt.

78 / 256 = 0 Rest 78 ´ die fünfte Stelle ist 0, weiter mit der vierten (64)
78 / 64 = 1 Rest 14 ´ die vierte Stelle ist 1, weiter mit der dritten (16)
14 / 16 = 0 Rest 14 ´ die dritte Stelle ist 0
14 / 4 = 3 Rest 2 ´ die zweite Stelle ist 3
2 / 1 = 2 Rest 0 ´ die erste Stelle ist 2

Damit erhalten wir im 4er-System die Zahl 01032.
Statt den Rest mit Minus aus zurechnen kann man auch die fertige Funktion Modulo benutzen, die den Rest der Division zweier Zahlen ausrechnet.

Nun solltet ihr so lange mit verschiedenen Zahlensystemen rechnen, bis ihr es verstanden habt, dann könnt ihr mit dem Tutorial fortfahren.

Beliebt ist vor allem das 64er System mit den Ziffern 0

  • 12.01.2010 um 00:02
Zwei Audiocomments von cZ-lueMmeL Stars War VI: Weitere Details bekannt

Erstellen eines Save/Load Systems (neu)


Erstellen eines Save/Load Systems (neu)

zum Anfang

1. Einleitung

Für Multiplayer RPGs sind Savesysteme heutzutage ein Muss. Doch wenn man dann speichern will, wird einem plötzlich dieser ellenlange Code aus Buchstaben, Zahlen und Sonderzeichen vorgeworfen, den man schnell abschreiben muss, bevor er verschwindet.

Viele dieser Probleme sind durch einen besseren Algorithmus vermeidbar. Wie man einen solchen erstellt, bleibt vielen jedoch oft ein Rätsel. Dieses Tutorial soll die Grundlagen des Savecode-Verfahrens erklären und verdeutlichen, wie man einen Savecode kurz, übersichtlich und sicher macht. Dabei werde ich der Einfachheit halber GUI-Trigger aufschreiben, obwohl viele davon eher als Funktionen genutzt werden und man daher mit Jass besser dran ist. Die beschriebenen Verfahren sind aber gleich.

Anmerkung: In den Trigger-Beispielen wurden Klammern entfernt, um das Ganze besser lesbar zu halten.

zum Anfang

2. Das Verfahren

Die grundlegende Idee hinter dem Savecode ist ein anderes Zahlensystem. Das bedeutet, dass man anstelle der üblichen zehn Ziffern (0,1,2,3,4,5,6,7,8,9) deutlich mehr nimmt. Je mehr Ziffern ein Zahlensystem hat, umso kleiner wird die Stellenzahl.

Einschub: Wie funktionieren Zahlensysteme?

Wenn ihr bereits wisst, wie Zahlensysteme funktionieren, dann könnt ihr diesen Einschub überspringen.

Wir rechnen normalerweise in einem Zahlensystem mit 10 Ziffern. Die erste Ziffer (also die Ziffer, die sich am weitesten “’rechts“‘ befindet) zählt einfach, die zweite zählt zehnfach, die dritte hundertfach (10*10), die vierte tausendfach (10*10*10) usw.

Im Allgemeinen hat man b Ziffern, die erste Stelle zählt 1-fach, die zweite zählt b-fach, die dritte b*b-fach usw.

Als Beispiel betrachten wir das 4er-System, in dem es nur die Ziffern 0,1,2 und 3 gibt. Um aus dem 4er-System ins 10er System um zurechnen genügt es die einzelnen Ziffern mit ihrer Wertigkeit zu multiplizieren und dann alles zu addieren. Da die erste Ziffer 1-fach zählt multiplizieren wir sie mit 1. Die zweite Ziffer mit 4, die dritte mit 16 (4*4), die vierte mit 64 (4*4*4) usw.

Aus der Zahl 1032 im 4er-System wird dann 2*1 + 3*4 + 0*4*4 + 1*4*4*4 = 2 + 12 + 0 + 64 = 78 im 10er-System.

Um eine Zahl vom 10er-System ins 64er System umzurechnen geht man am besten anders herum vor, fängt also bei der größten Ziffer an. Dann überprüft man immer, wie viel von der umzuwandelnden Zahl in die aktuell betrachtete Stelle passt, zieht dies anschließend von der umzuwandelnden Zahl ab (um den Rest der Division zu erhalten) und macht (mit dem Rest) an der nächsten Stelle weiter.

Als Beispiel wollen wir 78 vom 10er- ins 4er-System umwandeln.

Wir fangen mit einer Stelle an, die auf jeden Fall groß genug ist, zum Beispiel der fünften Stelle, die ja 256-fach zählt (4*4*4*4). Nun fragen wir uns wie oft die 78 in die 256 passt.

78 / 256 = 0 Rest 78 ??? die fünfte Stelle ist 0, weiter mit der vierten (64)
78 / 64 = 1 Rest 14 ??? die vierte Stelle ist 1, weiter mit der dritten (16)
14 / 16 = 0 Rest 14 ??? die dritte Stelle ist 0
14 / 4 = 3 Rest 2 ??? die zweite Stelle ist 3
2 / 1 = 2 Rest 0 ??? die erste Stelle ist 2

Damit erhalten wir im 4er-System die Zahl 01032.
Statt den Rest mit Minus aus zurechnen kann man auch die fertige Funktion Modulo benutzen, die den Rest der Division zweier Zahlen ausrechnet.

Nun solltet ihr so lange mit verschiedenen Zahlensystemen rechnen, bis ihr es verstanden habt, dann könnt ihr mit dem Tutorial fortfahren.

Beliebt ist vor allem das 64er System mit den Ziffern 0???9,a???z,A???Z,+, – . Mit diesen Ziffern kann man in einer x-stelligen Zahl Dezimalzahlen bis zu 64x speichern(als Beispiel: 2 Stellen: maximale Zahl 4096, 3 Stellen: 262144). Die Umrechnung ist einfach und schnell. Man benötigt dazu nur die Zahl selbst sowie ein String-Array, in dem alle 64 Ziffern stehen, nach Belieben auch durcheinander. Hier der Code für 4 Stellen:

 Set Stelle3 = Zahl mod 262144

 Set Stelle4 = Zahl / 262144

 Set Stelle2 = Stelle3 mod 4096

 Set Stelle3 = Stelle3 / 4096

 Set Stelle1 = Stelle2 mod 64

 Set Stelle2 = Stelle2 / 64

 Set Return = Ziffern[Stelle4] + Ziffern[Stelle3] + Ziffern[Stelle2] + Ziffern[Stelle1]

Der Wert Return stellt dann einen Teil des Savecodes dar. Falls die Zahl kleiner ist als 262144, kann man die ersten beiden Zeilen auslassen, (Und anstelle von Stelle3 Zahl einsetzen), für Zahlen kleiner 4096 sogar die ersten 4. Zahlen kleiner 64 kann man direkt übertragen.

Doch wie verwendet man dieses Algorithmus nun zum Speichern von Helden? Das macht man mithilfe von IDs. Jedem Held und jedem Item wird eine Nummer zugewiesen, welche dann umgewandelt wird. Dazu legt man zwei neue Arrays an, eines mit Einheitentypen und eins mit Itemtypen. Wenn man speichert, geht man diese Arrays durch und sucht die entsprechenden Nummern heraus. Dabei empfiehlt sich ein einstelliger Code für Helden (da man vermutlich selten mehr als 64 Helden auf der Karte hat) und ein zweistelliger für Items (außer man hat mehr als 4095 davon). Bei Items sollte man im Übrigen beachten, dass ein Itemslot auch leer sein kann und man für diese Information auch einen Platz in seinem Array haben sollte.

Gold und Holz kann man direkt speichern, da es sich dabei ja um Zahlenwerte handelt. Je nachdem, wie wertvoll diese Ressourcen sind, verwendet man bis zu 5 Zeichen. Auch EXP kann man direkt speichern. Dabei reichen 3 Zeichen für die EXP meistens aus, da man dann bis Level 24 kommen kann.

zum Anfang

3. Optimales Speichern

Wer den Vorherigen Absatz aufmerksam gelesen hat, wird feststellen, dass ich einigen Größen aus dem Weg gegangen bin. Dies liegt daran, dass man für diese durch geschickte Nutzung den Zeichenverbrauch bis auf 1/3 Zeichen und weniger reduzieren kann. Das klingt zwar komisch, geht aber tatsächlich. Das macht man auf drei Wegen: 1. Das weglassen redundanter Informationen 2. Das Kombinieren geringer Zahlen 3. Variable Codelänge

Das Weglassen redundanter Informationen

Als Beispiel seien hier zum Beispiel die Fähigkeiten eines Helden genannt. Diese könnte man durchaus auch alle in einem Array speichern und dann für jeden die ID verschlüsseln sowie die aktuelle Stufe. Allerdings braucht dergleichen äußerst viel Platz. Als Extrembeispiel gebe es in einer Map 64 Helden und keine Fähigkeit sei doppelt verwendet. Bei Standard WC3-Fähigkeitenverteilung bedeutet das 4 Zauber pro Held. Damit braucht man also zwei Stellen für die Fähigkeiten plus eine für die Stufe. Macht also 12 Stellen allein für die Fähigkeiten. Wenn man die oben beschriebenen Methoden für die Helden, Items , Ressourcen und EP verwendet, hat man bis zu 1+6*2+(2+1)*4+5+5+3=38 Stellen Savecode. Diese Länge ist unzumutbar, doch woher kommt sie eigentlich? Sie entsteht, weil wir eine Information mehrmals speichern. So ist zum Beispiel in unserem Code der Held und seine Zauber auf 5 verschiedene Weisen herauszulesen! Warum das so ist, sieht man bei folgendem Beispiel sofort ein: Über einen Helden sei bekannt, dass er Todesmantel geskillt hat. Jeder, der sich mit Warcraft auskennt, weiß natürlich, dass es sich bei dem Helden um einen Todesritter handelt und er außerdem noch die Zauber ???Unheilige Aura???, ???Todespakt??? und ???Tote beleben??? hat. Wozu also noch Stellen für die Fähigkeiten ausgeben? Man sieht, dass man so seinen Fähigkeitencode auf 4 Zeichen kürzen kann. Diese 4 Zeichen geben die Stufen an, die Fähigkeiten selbst liest man aus dem Helden aus. Wie das geschieht, sei später genauer erläutert. Bis jetzt erst einmal so viel: Diese 4 Zeichen sind noch nicht das Ende vom Lied. Denn es gibt noch …

Mehrere Zahlen pro Zeichen

Wenn man die Standard-Fähigkeiten verwendet, gibt es für die 3 normalen Fähigkeiten je 4 Zustände , die Level 0 bis 3. Also gibt es für die 3 Fähigkeiten insgesamt 4*4*4= 64 Zustände. Jetzt sieht man sofort, worauf ich hinaus will: für 64 Zustände braucht man nur 1 Zeichen! Doch wie wandelt man die 4 Zahlen in eine um? Das geht mithilfe des 4ersystems:

 Set Return = Ziffern[16 x (Level of Ability3 for Held) + 4 x (Level of Ability2 for Held) + (Level of Ability1 for Held)]

Nun muss man nur noch das Ultimate speichern. Das hat 2 Zustände: man hat es geskillt oder nicht. Das heißt, man kann es in einem Boolean speichern. Nun ist 64=2^6, das heißt man kann 6 Boolean Variablen ähnlich der oben beschriebenen Methode in ein Zeichen packen. Also kann man neben dem Ultimate noch 5 Informationen speichern, zum Beispiel ob man eine bestimmte Quest bereits erledigt hat oder ob man eine Bestimmte Auszeichnung erhalten hat. Wer nicht dergleichen unsinniger Informationen speichern will, kann das Ultimate auch an einem ungewöhnlicheren Ort aufbewahren: Im Held. Das funktioniert, falls man nur 32 Helden maximal hat. Dann kann man das Ultimate so im Heldenzeichen unterbringen:

 Set Return = Ziffern[ (Level of Ultimate for Held) +2 x HeroID)]

Und siehe: gerade mal 1 + 1/6 Zeichen anstelle von 12. Das ist eine deutliche Verbesserung.

Um es zusammenzufassen, man kann folgende Kombinationen in einem Zeichen speichern:

  • 2 Variablen mit Zahlen von 0-7
  • 3 Variablen mit Zahlen von 0-3
  • 6 Boolean Variablen
  • Eine Variable mit 0-31 und ein Boolean
  • Eine Variable mit 0-15 und Eine mit 0-3

Und ein paar mehr, aber das sollten die wichtigsten sein.

Variable Codelänge

Dieser Abschnitt zählt eigentlich nicht direkt in dieses Kapitel, denn eigentlich wird der Code eher verlängert als verkürzt, wenn man diese Methode anwendet. Doch stellt er vor allem für Items eine gute Verkürzung dar. Denn zum einen kann man Zeichen sparen, indem man nicht alle leeren Itemslots aufschreibt. Man kann zum Beispiel vereinbaren, dass die Items in maximal 12 Zeichen aufgezeichnet sind oder bis zum ersten freien Slot – der ID 0. Damit kann man bei einem Helden mit leeren Inventar 10 Zeichen weglassen, denn man speichert im Code bloß für die Items einmal 00 (falls Ziffern[0]=0) und ist fertig.

Das zweite wichtige Problem bei Items sind mehrere Ladungen. Wenn man die Ladungen nicht speichert, kann man das missbrauchen, indem man zum Beispiel von einer Heilsalbe 2 Ladungen aufbraucht, speichert, neu lädt und dann wieder 3 Ladungen hat. Also muss man die Ladungen speichern. Allerdings hat nicht jedes Item Ladungen und nur wenige mehr als 8, daher wäre es sinnlos, für jedes Item die Ladungen in einem neuen Zeichen zu speichern. Das lässt sich auf 2 Wegen verkürzen: 1. Wir finden heraus, welche Items Ladungen haben, zum Beispiel indem wir ein neues des gleichen Typs erstellen und dessen Ladungen zählen. 2. Wir speichern die Ladungen von mehreren Items in einem Zeichen. Auf diese Art und Weise erhält man maximal 3 Zeichen, die man hinten an die Itemzeichen hängt. Nun muss man nur noch den Loader intelligent genug bauen, um mit dieser Methode umzugehen. Doch dazu später mehr.

ACHTUNG: Man beachte, dass man kein extra Zeichen für 0 Ladungen braucht und daher anstelle des Bereiches 0-7 den Bereich 1-8 nehmen kann. Das bedeutet, dass man in Wirklichkeit nicht die Ladungen speichert, sondern Ladungen-1. Das muss dann beim Loader wieder rückgängig gemacht werden.

zum Anfang

4. Sicherheit

Nun hat man als Mapper sich die Mühe gemacht und sich ein Savecodesystem überlegt, und schon kommt der Hacker, findet heraus wie der Code funktioniert und erschafft sich einen highlevel Helden mit guten Items und viel Geld und rennt ohne Mühe durch das ganze Spiel. Um so etwas zu verhindern, muss man gewisse Sicherheitsmaßnahmen treffen. Die einfachste und platzsparendste Methode ist die der Prüfziffer. Eine Prüfziffer ist ein zusätzliches Zeichen, dass an den eigentlichen Code angehängt wird und sich aus den anderen Zeichen ergibt. Die einfachste Methode ist hierbei eine modifizierte Version des ISBN-Prüfzifferalgorithmus, die für bis zu 63 Zeichen lange Codes funktioniert. Man berechnet ihn, indem man jede Ziffer mit ihrer Position multipliziert und das über alle Ziffern aufaddiert und dann Modulo 64 nimmt. Wenn man diese Methode verwendet, ist es günstig, den Savecode nicht von Anfang an als String zu speichern, sondern zuerst als Array, das man nun durchgehen kann. Hier zum Beispiel für einen 20-stelligen Code:

 Set Pruefziffer = 0

 For each (Integer A) from 0 to 19, do (Actions)

 Schleifen – Aktionen

 Set Pruefziffer = (Pruefziffer + ((Integer A) + 1) x Code[(Integer A)]

 Set Code[20] = (Pruefziffer mod 64)

Im Loader wird dann wieder die Prüfziffer berechnet und mit der gegebenen verglichen. Sind sie gleich, ist der Code korrekt.

Ein zweiter Weg zu mehr Sicherheit ist die Verschlüsselung des Spielernamens im Savecode, so dass der Code an einen Account gebunden ist. Noch dazu wird der Code stark durcheinander gebracht, was die Wahrscheinlichkeit verringert, dass ein Hacker hinter den Code kommt. Dies macht man mithilfe der Vigenere-Verschlüsselung. Die Vigenere-Verschlüsselung ist eine erweiterte Form der Ceasar-Verschlüsselung und verwendet ein Codewort, was in diesem Fall der Spielername ist (wer mehr wissen will, der lese den Artikel auf der Wikipedia durch). Hier ist der Algorithmus wieder für einen 20-Stelligen Code. Name ist in diesem Fall ein Integer-Array mit den Buchstabenwerten des Namens (notfalls bereinigt) und Len ein Integer mit seiner Länge. Index ist eine Zählvariable, die den Namen durchläuft.

 Set Index = 0

 For each (Integer A) from 0 to 19, do (Actions)

 Schleifen – Aktionen

 Set Code[(Integer A)] = ((Code[(Integer A)] + Name[Index]) mod 64)

 Set Index = (Index + 1)

 If (Index Gleich Len) then do (Set Index = 0) else do (Do nothing)

Hier wird im Loader zuerst die Verschlüsselung rückgängig gemacht und danach die Prüfziffer auf Richtigkeit überprüft. Ist sie falsch, muss es wohl auch der falsche Name sein.

Eine letzte Sache möchte ich noch ansprechen, obwohl sie eher in den Bereich der Freundlichkeit denn Sicherheit fällt. Wenn man den Savecode einfach so ausgibt, wie er ausgerechnet wird, sind Fehler vorprogrammiert, denn in Warcraft sind 1 und l sowie 0, O und o schwer unterscheidbar. Um das zu verbessern, empfiehlt sich farbige Schrift. Das bedeutet, dass Großbuchstaben zum Beispiel rosa, Kleinbuchstaben blau und Zahlen grün sind, so dass man diese Problemfälle farblich unterscheiden kann. Das macht man mithilfe eines zweiten Ziffernarrays, in dem neben den Zeichen auch der Farbcode gespeichert ist. Wenn man den Savecode ausgibt, verwendet man dieses Farbarray, während man beim Einlesen weiterhin das reine Ziffernarray braucht.

zum Anfang

5. Das Laden

Nun sei ein Savecode erstellt worden, der zum Beispiel diese Form habe:

  • 1 Zeichen Held und Ultimate
  • 1 Zeichen Zauber
  • 5 Zeichen Gold
  • 3 Zeichen EXP
  • 2-15 Zeichen Items
  • 1 Zeichen Prüfziffer

Insgesamt also zwischen 13 und 26 Zeichen, je nachdem was für Items der Held hat.

Doch nun kommt der schwere Part: aus diesem Code wieder Held, Zauber, Gold, EXP und so weiter wiederherzustellen. Grundlage dazu ist eine Zurückumwandlung eines Zeichens in den Zahlwert. Der Algorithmus tut nichts weiter als das Zeichenarray durch zugehen und mit jeder Ziffer zu vergleichen. Wenn er eine gleiche findet, merkt er sich die Position. Findet er nichts, setzt er die Position auf 64. Dann weiß man, dass dieses Zeichen nicht entschlüsselt werden kann. Im Falle des Namens lässt man es weg, im Falle des Codes bricht man ab und beschwert sich.

 Set Index = 64

 For each (Integer A) from 0 to 63, do (Actions)

 Schleifen – Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Ziffern[(Integer A)] Gleich Ziffer

 ‚THEN‘-Aktionen

 Set Index = (Integer A)

 Custom script: exitwhen true

 ‚ELSE‘-Aktionen

Nun enthält Index den Zahlwert der gewählten Ziffer. Diesen können wir jetzt in einem Array speichern. Die Zeile Custom Script ist nicht zum entfernen eines Leaks, sondern zum beschleunigen der Prozedur. Wenn man einmal ein Zeichen gefunden hat, braucht man nicht weiter suchen. Damit lässt sich die Laufzeit der Schleife stochastisch auf die Hälfte verkürzen. Diesen Suchalgorithmus verwendet man im Übrigen auch für Umwandlung der Helden und Items in IDs.

Nun zum Zerlegen der Zeichen mit mehreren Informationen:

Auch hier arbeiten wir mit dem Zahlensystem-Trick. Hier einmal für den Held:

 Set HeroID = (Code[0] / 2)

 Set Ultistufe = (Code[0] mod 2)

 Set Ability2Stufe = (Code[1] mod 16)

 Set Ability3Stufe = (Code[1] / 16)

 Set Ability1Stufe = (Ability2Stufe mod 4)

 Set Ability2Stufe = (Ability2Stufe / 4)

 Einheit – Create 1 Helden[HeroID] for Spieler 1 (Rot) at Start facing Vorgabe für Gebäude-Ausrichtung degrees

Für die Fähigkeiten gibt es dummerweise keinen einfachen Weg, sie mit GUI zu erhöhen. Wir müssen auf ein Custom Script zurückgreifen:

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Ability1Stufe Ungleich 0

 ‚THEN‘-Aktionen

 For each (Integer A) from 0 to Ability1Stufe, do (Actions)

 Schleifen – Aktionen

 Custom script: call SelectHeroSkill( udg_Held , udg_Abilities[ udg_HeroID * 4 ] )

 ‚ELSE‘-Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Ability2Stufe Ungleich 0

 ‚THEN‘-Aktionen

 For each (Integer A) from 0 to Ability2Stufe, do (Actions)

 Schleifen – Aktionen

 Custom script: call SelectHeroSkill( udg_Held , udg_Abilities[ udg_HeroID * 4 + 1] )

 ‚ELSE‘-Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Ability3Stufe Ungleich 0

 ‚THEN‘-Aktionen

 For each (Integer A) from 0 to Ability3Stufe, do (Actions)

 Schleifen – Aktionen

 Custom script: call SelectHeroSkill( udg_Held , udg_Abilities[ udg_HeroID * 4 + 2] )

 ‚ELSE‘-Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Ultistufe Ungleich 0

 ‚THEN‘-Aktionen

 For each (Integer A) from 0 to Ultistufe, do (Actions)

 Schleifen – Aktionen

 Custom script: call SelectHeroSkill( udg_Held , udg_Abilities[ udg_HeroID * 4 + 3] )

 ‚ELSE‘-Aktionen

SelectHeroSkill() ist äquivalent zur GUI-Funktion Learn Skill, allerdings lassen sich dort nur vorgefertigte Fähigkeiten auswählen, obwohl die Funktion intern mit den gleichen Ability IDs herumrechnet wie auch ???Set Level of Ability???. Nun wird auch die Frage geklärt, wie man die Fähigkeiten herauskriegt, die der Held hat: Man legt ein zweidimensionales Array an . In diesem sind für jeden Helden die 4 Fähigkeiten hintereinander gespeichert, in der Reihenfolge der Helden. Wenn man also im Heldenarray an Stelle 0 die Wächterin und an Stelle 1 den Schattenjäger hat, beginnt das Fähigkeitenarray mit: Dolchfächer, Schattenschlag, Beflügelt, Rache, Heilwelle, Hexerei, Schlangenschutz, Großer böser Voodo. Genaueres zu dieser Technik findet man hier. Wer sich noch an die Zeile erinnert, in der wir die Fähigkeiten gespeichert haben, sollte jetzt verstanden haben, wie man sie erweitern muss, damit die Fähigkeiten wirklich aus den Helden berechnet werden.

Als nächstes haben wir den einfacheren Fall des Umrechnens einer Zahl mit mehreren Ziffern:

 Set Gold = 16777216 x Code[2] + 262144 x Code[3] + 4096 x Code[4] + 64 x Code[5] + Code[6]

 Set EXP = 4096 x Code[7] + 64 x Code[8] + Code[9]

Das ist die Rückumwandlung aus dem 64er-System und nicht weiter schwierig. Der schwierige Teil beginnt jetzt mit der Variablen Codelänge für die Items. Hier empfiehlt sich Jass deutlich, da Arbeit mit Schleifen in diesem Fall für GUI scheußlich ist:

 Set Modus = True

 ——– Modus gibt an, ob wir gerade Items lesen oder ob wir Charges zu den Items lesen ——–

 Set Index2 = 0

 For each (Integer Index) from 10 to (Len – 1), do (Actions)

 Schleifen – Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Modus Gleich True

 ‚THEN‘-Aktionen

 Set ItemID = ((64 x Code[Index]) + Code[(Index + 1)])

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 ItemID Gleich 0

 ‚THEN‘-Aktionen

 Set Modus = False

 Set Index2 = 0

 ‚ELSE‘-Aktionen

 Held – Create Items[ItemID] and give it to (Triggering unit)

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 (Charges remaining in (Last created item)) Größer als 1

 ‚THEN‘-Aktionen

 ——– Ein Item mit Ladungen! Das merken wir uns für später! ——–

 Set Chargeables[Index2] = (Last created item)

 Set Index2 = (Index2 + 1)

 ‚ELSE‘-Aktionen

 If (All Conditions are True) then do (Then Actions) else do (Else Actions)

 ‚IF‘-Bedingungen

 Index Gleich 20

 ‚THEN‘-Aktionen

 Set Modus = False

 Set Index2 = 0

 ‚ELSE‘-Aktionen

 Set Index = (Index + 1)

 ‚ELSE‘-Aktionen

 Set Charge1 = (Code[Index] / 8)

 Set Charge2 = (Code[Index] mod 8)

 Gegenstand – Set charges remaining in Chargeables[Index2] to Charge1

 Gegenstand – Set charges remaining in Chargeables[(Index2 + 1)] to Charge2

 Set Index2 = (Index2 + 2)

Dieser Code ist im übrigen nicht Hundertprozentig sicher, da zum Beispiel nicht überprüft wird, ob überhaupt genug Items für alle Chargestellen da sind (oder umgekehrt). Dies möchte ich dem fleißigen Leser als Übungsaufgabe hinterlassen. Nun haben wir also unseren Helden komplett erstellt und mit Items ausgerüstet. Was fehlt also noch? Richtig, Kapitel 3 ist komplett unter den Tisch gefallen. Dieses werde ich jetzt noch kurz erklären, da ich dazu bereits vorhin viel gesagt habe. Obwohl dieser Teil am Ende unseres Tutorials erklärt wird, gehört er AN DEN ANFANG DES LOADERS! Es bringt nichts, erst einen Helden zu erstellen und dann zu prüfen, ob er erlaubt ist. Dazu müssen wir also zuerst den Vigenere-Algorithmus rückgängig machen und dann die Prüfziffer bestimmen. Zu beachten ist dabei, dass man die Prüfziffer nicht fälschlicherweise ein zweites Mal ausliest, wenn man die Items läd. Die Umkehrung des Vigenere-Algorithmus ist denkbar einfach:

 Set Index = 0

 For each (Integer A) from 0 to 19, do (Actions)

 Schleifen – Aktionen

 Set Code[(Integer A)] = ((Code[(Integer A)] – Name[Index] + 64) mod 64)

 Set Index = (Index + 1)

 If (Index Gleich Len) then do (Set Index = 0) else do (Do nothing)

Zur Prüfziffer wurde bereits vorhin etwas erwähnt: Man berechnet sie einfach noch einmal und vergleicht. Bei gleicher Prüfziffer fährt man fort.

zum Anfang

6. Schlusswort

Damit sind wir auch schon am Ende unseres Save-Load-Tutorials. Ich hoffe, ihr habt verstanden, wie man mit Mathematik und Kreativität einen Code gleichzeitig kurz und sicher hält und wünsche mir für die Zukunft auch einmal einen kurzen Savecode abtippen zu dürfen!

Wer nicht ganz hinterhergekommen ist oder zu faul ist, alles zu Ende zu denken, kann sich hier hier eine Testmap mit einem funktionierenden Save-Load-System herunterladen.

zum Anfang

  • 11.01.2010 um 23:02
Die ESL Olympiade in Warcraft III Stars War VI: Weitere Details bekannt