(Mit Screenhots)
Ganz ganz vorweg: Da ich keine Ahnung habe, wie die Kenntnisstände aussehen, gehe ich einfach von einem Minimum aus und erkläre alles, womit ich vor einem Jahr selber nichts anfangen konnte – da ich aber eben selber bloß Laie bin, kann ich nicht ausschließen, von den Hintergrundsachverhalten Dinge falsch verstanden zu haben, bei allem anderen Stütze ich mich auf das, was nach meiner Erfahrung funktioniert.
Und noch eine Anmerkung zur bei Magellan eingebauten "Hilfe" für das Thema: Bei mir jedenfalls ist die nichts weniger, als hilfreich, weil die entsprechenden Dokumente leer sind oder nicht mehr existieren.
Grundlagen
Die erweiterten Befehle (Skripte) sind eine von mehreren Möglichkeiten (neben Vorlage und Forlage), automatisch Befehle für Einheiten zu generieren, Routineaufgaben erledigen zu lassen oder längerfristig geplante Vorgänge am Laufen zu halten. Jedes Tool hat seine eigenen Vor- und Nachteile. Skripte werden programmiert, haben keine Ähnlichkeit mit der Anweisungssprache von Fantasya und erfordern ein zusätzliches Tab im Magellan-Desktop -- dafür macht es ihnen nichts aus, wenn man mal einen Zug verpasst hat und mit genug Kenntnissen kann man angeblich nahezu alles programmieren (inklusive einer künstlich-intelligent laufenden Partei auf Autopilot(?)).
Die Programmiersprache ist der Java-Ableger Beanshell, zu dem sich dort eine Dokumentation (auf Englisch) findet:
http://www.beanshell.org/manual/contents.html
Technisches:
Die Erweiterten Befehle werden für Container gegeben und gespeichert. Die wichtigsten Container sind World, die Parteien, Regionen, Gebäude, Schiffe und Einheiten. (Verbessere mich jemand, wenn ich hier stuss erzähle)
Alles, was man unter erweiterte Befehle eingibt, wird in einem XML-Dokument gespeichert. Dieses finde man im FMagellan-Ordner in einem Unterordner namens "default" mit dem Dateinamen "extendedcommands". Ist ganz nützlich, wenn man großflächigere Löschungen anstehen und man nicht alles einzeln raussuchen will.
(allerdings sollte man dann vorher ein Backup machen.)
Noch viel Praktischer ist es allerdings, um mit den Fehlermeldungen abreiten zu können. Wenn diese nämlich Textkoordinaten (Position) angeben, ist das auf genau dieses Dokument bezogen.
Aufruf:
Um die erweiterten Befehle schreiben, verwenden und verändern zu können, braucht man das entsprechende Tab auf dem Magellan-Desktop. Dieses lässt sich öffnen über das Menü "Desktop-Erweiterte Befehle" oder über "Plugins-Erweiterte Befehle-Bibliothek bearbeiten"

- Aufruf2.jpg (88 KiB) 17227 mal betrachtet
Das dann irgendwo auf dem Desktop auftauchende Tab kann man per Drag and Drop am Kartenreiter an eine Stelle schieben, wo es einem passt (Ich hab es neben dem Detail-Reiter am rechten Rand, aber das ist reine Geschmackssache).
Das Interface
Der Arbeitsbereich unterteilt sich in den Kopf mit verschiedenen Buttons, den Hauptbereich mit den Unterreitern, in denen die Textfelder für die Skripte sich befinden, und den Fußbereich.

- Interface.jpg (32.56 KiB) 17227 mal betrachtet
..Die Buttons:
..."Öffnen": Öffnet einen Unterreiter für den Container, der in der Übersicht gerade (blau) markiert ist.
..."Ausführen": Löscht den Text im geöffneten Textfeld. Ist ein Bug. Lasst die Finger von diesem Button.
..."Speichern": Speichert den Text in dem Textfeld, das man gerade im Fokus hat.
..."Alles speichern": Speichert den Text in allen Textfeldern, die gerade offen sind.
..Der Hauptbereich: Ist eigentlich selbsterklärend: In verschiedenen Unterreitern werden die Skripte der verschiedenen Container dargestellt und können bearbeitet werden.
..Der Fubereich:
..."Priorität": Hier lässt sich grob die Reihenfolge einstellen, in der die erweiterten Befehle bei der Ausführung abgearbeitet werden. Container mit höherer Priorität werden vor Containern mit niedrigerer Priorität abgearbeitet. Das kann zB nützlich sein, wenn man erreichen will, dass Partei- oder Regionsweit kurze Befehle hinzugefügt werden.
..."Element": Gibt an, welcher Container gerade offen ist.
..."Position": Gibt an, wo im gerade offenen Textfeld der Cursor sich befindet. Bedingt hilfreich (die Fehlermeldungen benutzen leider ein anderes Koordinatensystem)
Ausführung
Bei der Ausführung der Skripte gibt es zwei Möglichkeiten: Man kann alles ausführen lassen, oder nur die für einen einzelnen Contaier.
Um nur die Skripte eines einzelnen Containers auszuführen, muss dieser in der Übersicht markiert sein. Dann rechtklick, Contextmenü "Erweiterte Befehle-Führe alle Befehle für <n> aus".

- Einzelausfuehrung.jpg (189.84 KiB) 17227 mal betrachtet
Die Bibliothek
HIer werden die Funktionen gespeichert, also die Skripte, die dann von den Containern aufgerufen werden können (sodass man nicht für wiederkehrende Aufgaben 200 mal den selben Dreißigzeilentextblock durchkopieren muss (Fehlermultiplikation!), sondern bloß eine Zeile – und eventuelle Skriptfehler zentral beheben kann.
Auf jeden Fall muss (?) folgendes in der Bibliothek stehen, damit überhaupt etwas an den erweiterten Befehlen Funktioniert:
Code: Alles auswählen
import magellan.client.*;
import magellan.client.extern.*;
import magellan.library.*;
import magellan.library.rules.*;
import magellan.plugin.extendedcommands.*;
Die Allgemeine Form der Funktionen ist:
("<" und ">" schließen bloß Platzhalter ein und gehören nicht wirklich zum Code (außer als mathematische Vergleichsoperatoren))
<name>(<Klasse> <variable1>, <Klasse> <variable2>, <etc.>) {
<Befehle> }
In den Containern aufgerunfen werden sie mit
<name>(<variable1>, <variable2>, <etc.>);
Ein erstes Beispiel mit Erläuterungen
Eine Funktion, die in der Bibliothek stehen würde ist etwa:
Code: Alles auswählen
lernen(Unit unit, String skill, int ziel, String nextOrder)
{
if (helper.getLevel(unit,""+skill+"") < ziel)
{unit.setOrdersConfirmed(true);}
else
{
helper.setOrder(unit,"; +++Skript kann raus+++");
helper.addOrder(unit,""+nextOrder+"");
unit.setOrdersConfirmed(false);
}
helper.addOrder(unit,"; extdcmd: lernen: "+skill+" "+ziel+"");
}
(Ja, normalerweise setzt man die geschweiften Klammern anders, aber so ist es für mich übersichtlicher.)
Was tut das Skript: Es überprüft, ob ein Talentwert unter einem bestimmten Wert liegt und bestätigt die Einheit, wenn dies der Fall ist. Weder sagt es der Einheit, was sie zu tun hat (das mache ich per Hand oder überlasse es Forlage), noch ordnet es Lehrer und Schüler einander zu. Der Sinn ist, sich mit einer Einheit nicht beschäftigen zu müssen, bis sie das kann, was sie können soll.
Um das Skript anzuwenden, ist die Einheit zu öffnen, die es ausführen soll, und dann zum Beispiel mit
lernen(unit, "Magie", 22, "GIB Bauern 100 PERSONEN");
aufzurufen.
Der Reihe nach:
"lernen": der Name der Funktion. Schreibe ich immer vorne klein. Keine Ahnung, ob das notwendig ist.
"(Unit unit, String skill, int ziel, String nextOrder)": Die Variablen-Deklaration; Immer in Klammern, immer ohne Leerzeichen davor, imer gefolgt von geschweifter Klammer (die anzeigt, dass der Befehlsteil losgeht – entsprechend wird die Funktion auch mit einer geschweiften Klammer geschlossen).
"Unit unit": Unit ist eine Klasse (darum groß gechrieben", unit der Name der Variable. Die deklariere ich grundsätzlich immer als erstes. Wieder, ohne zu wissen, ob das wirklich notwendig ist, aber es funktioniert (die Variable selbst kann man natürlich nennen, wie man will).
"String skill": String ist die Klasse Zeichenfolge und eher eine Notlösung, weil ich nicht weiß, ob es eine Klasse für die Talente gibt. Funktioniert jedenfalls, solange man beim Aufruf an die Anführungszeichen denkt. Und das Talent richtig schreibt. (Beim Aufruf zB "Uunterhaltung" zu übergeben, würde zu keiner Fehlermeldung führen, sondern einfach nur dazu führen, dass Uunterhaltung, statt Unterhaltung überprüft wird.)
"int ziel": Klasse ist Integer, also ganze Zahlen. Gibt an, bei welchem Talentwert von "skill" die Einheit unbestätigt sein soll.
"String nextOrder": Wenn man schon weiß, was die Einheit tun soll, wenn sie mit lernen fertig ist. Wenn nicht, kann man beim Aufruf einfach "" an der Stelle setzen (die Stelle ganz leer zu lasen, würde zu einem Fehler führen).
helper.getLevel(unit,""+skill+""): unit und skill sind die Variablen. Die Anführungszeichen kommen so zu stande: .getLevel() erwartet einen String, man könnte also auch helper.getLevel(unit,"Unterhaltung") schreiben und alles wäre gut, wenn die Einheit auf Unterhaltung geprüft werden soll. Da das Skript aber für alle Talente gehen soll, wird die Variable eingefügt, wofür "++" als Rahmung notwendig ist.
unit.setOrdersConfirmed(true); : Das ist der eigentliche Befehl, nämlich, dass die Einheit bestätigt werden soll, und zwar unter der Bedingung dass der Talentwert von skill kleiner als ziel ist. Die Bedingung hinter dem if ist immer in Klammern, der Befehlsblock immer in geschweiften Klammern und jede Befehlszeile wird mit Semikolon beendet.
else: also dann, wenn der Talentwert von skill nicht kleiner als ziel (also gleich oder größer) ist.
helper.setOrder(unit,"; +++Skript kann raus+++");
helper.addOrder(unit,""+nextOrder+"");
unit.setOrdersConfirmed(false);
HIer ist ein wichtiger Unterschied zu beachten: setOrder(unit,""+befehl+"") löscht alle Befehle der Einheit und schreibt eine neue Befehlszeile, addOrder(unit,""+befehl+"") hingegen behält den Befehlsblock der Einheit bei und fügt lediglich eine Zeile an. In beiden Fällen kann es sich um einen Fantasya-Befehl oder auch um einen Kommentar handeln, mit // und ; im Befehlsstring kommt das Programm problemlos klar.
unit.setOrdersConfirmed(false) ist das Gegenstück zu unit.setOrdersConfirmed(true). Warum habe ich das extra eingebaut: Weil nicht auszuschließen ist, dass die Einheit durch irgendein anderes Skript doch schon bestätigt ist und in dem Fall wird sie dann eben wieder auf unbestätigt gesetzt, ansonsten passiert nichts.
Und zuletzt noch zu den Ressourcen
In den Beispielbefehlen von log-out.net ist an einer Stelle von
unit.getRegion().getHorses()
die Rede. Dies wird
nicht funktionieren. Weil bei FMagellan sämtliche Tiere, Bäume, Eisen, Steine und Gold unter
helper.getResourceAmount(""+resource+"")
subsummiert ist, und zwar mit den deutschen Bezeichnungen. Funktioniert also mit: Pferd, Kamel, Elefant, Alpaka, Zotte, Mastodon, Holz, Eisen, Stein, Gold. (die je für "+resource+" einzusetzen sind)
Für Regionssilber hingegen fukntioniert
unit,getRegion().getSilver()
, spuckt dann aber das Altsilber aus, also die Menge, die ohne den voraussichtlichen Verdienst der Bauern in der aktuellen Runde vorhanden ist.
Die anzahl der bauern erreicht man mit
unit. getRegion().getPeasants()
Die anzahl der rekruten mit
unit. getRegion().getPeasants() / 20