Scripteditor - Anleitung&Beispiele - United Script Tutor

Hier ist der ideale Ort um über Scripts und Mods für X²: Die Bedrohung zu diskutieren.

Moderators: Moderatoren für Deutsches X-Forum, Scripting / Modding Moderators

Post Reply
jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Scripteditor - Anleitung&Beispiele - United Script Tutor

Post by jnrk » Thu, 25. Mar 04, 17:57

Diskussionen zu diesem Tutorial nur hier


Das Tutorial als HTML mit Navigation



Download


X2 Script Tutorial

Dieses Tutorial ist ein Werk von uns Allen für Uns selbst und vor allem für Jene die nach uns kommen und dieses Forum, X2 und die Gemeinschaft bereichern.

---------Externe Referenzen -----------------

X2soUrcerer's Script-Befehlsliste
XML Page-ID, Kommandokonsolenbefehle von MrMilti
0.1dat / Vollständiger Wavetable Katalog von esd
Sprach/Soundnachrichten von Moonraven
X² Math library - fixed point decimal & trig functions by Reven


Inhaltsverzeichniss

I. BurnIt!-Aktivierung des Scripteditors

II. Scripts ins Spiel einhängen

II.1 GothicK's Tutorial No1: Scripts in's Spiel einbinden.
II.1.1 Grundlagen
II.1.2 Bearbeiten der Textdateien
II.1.3 Der Scripteditor

II.2 Nemesi$ Tutorial-Wie hänge ich ein eigenes Script in die Menüs ein
II.2.1 Einleitung
II.2.2 Anforderungen
II.2.3 Vorgehensweise
II.2.4 Installation
II.2.5 Anmerkung

IV. Vanoblis - Der ScriptDebugger - Anleitung (v1.3 UPDATED)
IV.1 Allgemeines
IV.2 Menüpunkte des Debuggers
IV.3 Einstellungen des Debuggers
IV.4 Starten, Stoppen und Debugging von Scripten
IV.5 Debugmodi in Scripten von Metuelisator


X. jnrk's Programming Tutorial

X.0 Allgemeine Programmiertipps

X.1 Grundelemente
X.1.0 Ausgabe
X.1.1 Variable
X.1.2 Schleifen
X.1.3 Bedingungen

X.2 erweiterte Grundelemente

X.2.0 Formatierte Ausgabe von ArcaJeth[D6a]
X.2.1 Arrays
X.2.2 Gültigkeitsbereich/Sichtbarkeit von Variablen
X.2.3 erweiterte Schleifen
X.2.4 erweiterte Bedingungen

X.3. Scripte miteinander verbinden / Unterscripte
X.3.1 Teile und Herrsche - Scripte aufteilen
X.3.2 Übergabe- und Rückgabe-Parameter
X.3.3 präventive Fehlerbehandlung

X.4 Form und Stil von Scripten
X.4.1 Namenskonvention für Dateinamen
X.4.2 Variable initialisieren und Namenskonvention ungarische Notation
X.4.3 Dokumentation

X.6 Mathematik und Logik im Script
X.6.1 Mathematische und Logische Ausdrücke von ArcaJeth[D6a]

------Coming soon-----
X.5 Objekte
X.5.1 exists&get&set

--------------------

------Bits'n Bytes Nützliche Routinen-------
a) Flugblock und Andockcheck von mkess
b) Wurzel+Potenzfunktion von ArcaJeth[D6a]
c) Alle Schiffe/Stationen im Universum auflisten von ticaki und ArcaJeth[D6a]
d) Inhalte von Arrays ausgeben am Beispiel von Sprungtoren von SpaceTycoon



-----------Noch nicht Einsortiertes-------------

Waren nach Main und Subtypes von ArcaJeth[D6a]
Farbigen Text im Logbuch / Nachricht von ArcaJeth[D6a]
Sprachausgabe bei Stationswaren! von SpaceTycoon
Tinte/Toner sparen von SpaceTycoon
Last edited by jnrk on Wed, 5. May 04, 19:48, edited 20 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

a

Post by jnrk » Thu, 25. Mar 04, 17:58



I. BurnIt-Aktivierung des Scripteditors

Der Scripteditor oder auch das "Manuelle Schiffscomputer Interface" (M.S.C.I.) ist ein Werkzeug innerhalb des Spieles, mit dem Regeln für das Verhalten der KI im Spiel erzeugt oder verändert werden können. Es ermöglicht es außerdem Objekte innerhalb des Spieluniversums zu beeinflußen oder einzufügen.
Das bedeutet jedoch, dass es extrem einflussreich ist und durch unachtsamen Gebrauch erheblicher Schaden am Spieluniversum bewirkt werden kann.
Eine Warnung: Seid euch darüber im Klaren, dass die Benutzung des Scripteditors den Spielspaß vollkommen verderben kann!

Da die Freigabe des Editors auf ausdrücklichen Wunsch vieler Spieler früher als vorgesehen erfolgt, sollte jedem Nutzer dieses mächtigen Werkzeuges bewußt sein, dass, solange die Arbeiten an der Dokumentation noch andauern, es durch Egosoft und die Betatester keinerlei Unterstützung gibt und im Problemfall auch nicht geholfen werden kann. Bis zur Freigabe der offiziellen Dokumentation seid Ihr also auf Euch allein gestellt.

Die Arbeiten an der Dokumentation sollen bis Ende Januar 2004 abgeschlossen werden.

Wenn Ihr Euch sicher seid, dass Ihr auch ohne Unterstützung mit diesem Feature experimentieren wollt, gebt während Ihr im All fliegt Thereshallbewings (beachtet das große "T") ein. Das aktiviert den Menüpunkt "Script Editor" in der Kommandokonsole. Die korrekte Aktivierung wird durch einen Beep bestätigt.

Denkt daran, dass der Scripteditor ein optionales und sehr fortgeschrittenes Werkzeug ist; es ist nicht nötig ihn zu benutzen um X² zu spielen.
Wenn Ihr noch keinerlei Erfahrung mit der Programmierung von Scripts habt, ist es wahrscheinlich besser, wenn Ihr den Editor einfach ignoriert.

II. Scripts ins Spiel einhängen

II.1 GothicK's Tutorial No1: Scripts in's Spiel einbinden.

Wegen der regen Nachfrage gibts hier mal ne Anleitung zum Einbinden der Scripts in's Spiel.

Erst mal Grundsätzliches:
1. Legt euch einen Ordner an, in den ihr die neuen Scripts downloadet.
2. Entpackt jedes Scriptpaket in einen _extra_ Ordner. (WinRAR ist sehr empfehlenswert. Einfach mit Rechtsklick auf die .zip/.rar-Datei und 'entpacken in "Ordner" ' auswählen.
3. Legt je einen Testordner für Scripts und Textdateien an, in die ihr die neuen Dateien kopiert.
Wenn dann Scripts den selben Dateinamen benutzen merkt ihr das sofort.
3.a Im Test"t"-Ordner könnt ihr dann die Textdateien bearbeiten. Dazu später mehr.
3.b In den Test"scripts"-Ordner kopiert ihr noch die x2script.xsl aus dem X²/scripts-Ordner.
Die benötigt ihr um die Scripts im I-Explorer anzuzeigen.

Hier nochmal, für alle die's noch nicht wissen, die Grundlagen:
Aus allen Dateien 44xxxx.xml(english) und 49xxxx.xml(deutsch) lädt X² den Text, der im Spiel angezeigt wird.
Diese Dateien sind im X²/t-Ordner und neue Dateien dieses Typs gehören dann auch in diesen Ordner.
Alle anderen .xml-Dateien gehören in den X²/scripts-Ordner.

Und nun zu den Texten.
Hier liegen die grössten Probleme, wenn es um englishe Scripts geht.
Aber auch generell, weil immer wieder gleiche Dateinamen verwendet werden. Benennt erst einmal (beim deutschen Spiel) die mit 44 beginnenden Dateien um.
Die deutsche Version benötigt Dateien, die mit 49 anfangen.
Wenn ihr ein neues Script entpackt habt und die Dateien in euren Testordner kopieren wollt: Überschreibt nicht die schon vorhandenen Dateien!
In diesem Fall schaut nach, welche Datei überschrieben werden soll.
Öffnet beide Dateien und schaut erstmal, ob die Einträge, die die neue Datei setzen will, schon in der alten enthalten sind. oder andersherum.
Es gibt inzwischen einige Scripts, die die Texte anderer Scripts mitliefern.

Ist das der Fall, dann benutzt das File mit allen Einträgen.
Wenn nicht, gibt es zwei Möglichkeiten:

Jetzt ist es eine Frage, ob ihr die Möglichkeit behalten wollt, Scripts schnell wieder zu entfernen.
Wenn ja, dann müsst ihr den Dateinamen ändern.
z.B.: von 440013 in 440014.
Anschliessend müsst ihr aber auch das Script selbst noch etwas umschreiben. Dazu komme ich später.

Is das nicht so wichtig, könnt ihr auch die Einträge des neuen Scripts in die schon vorhandene Datei einfügen.
Alle Textdateien lassen sich einfach mit einem Texteditor öffnen und bearbeiten. Ich nutze das Windows-Notepad.
Rechtsklick auf die Datei -> bearbeiten.
Fügt alle neuen Einträge an den etsprechenden Position ein.
Wie erkläre ich im nächsten Post.

Jetzt müsst ihr noch schauen, ob das script den Text auch wirklich lädt.
Öffnet dafür die entsprechende Scriptdatei, die mit "init." anfängt.
Wie weiter oben schon geschrieben braucht ihr dafür die x2script.xsl-Datei im selben Ordner.
Jetzt sucht ihr nach dem Eintrag "load text: id=xxxx"
Dort wird festgehalten, welche Textdatei das Spiel lädt.
Wenn das Script mit der Datei 490012.xml arbeitet muss im init.-Script der Eintrag: "load text: id=12" stehen. (die vorn anstehenden Nullen werden ausgeblendet)
Ist das nicht der Fall, oder fehlt dieser Eintrag muss das Script im Editor angepasst werden.
Dazu später mehr.

Wenn alles passt könnt ihr die fertigen Dateien in die entsprechenden Ordner des Spieles kopieren.

II.1.2 Bearbeiten der Textdateien

Ich nehme als Beispiel hier den "Handelscomputer MK3" von Burnit und die erste Version des "Teladi Autotrader" von xscripting.com
Hier gab es nämlich schon die ersten Probleme, weil beide mit der 490003.xml daherkahmen. (der Autotrader eigendlich mit der 440003.xml aber das haben wir ja schon geändert)

Wie gesagt: Diese Dateien lassen sich mit dem InternetExplorer anschauen und mit einem Texteditor bearbeiten.

Ich erkläre jetzt die Datei des HandelscomputerMK3:

Code: Select all

<?xml version="1.0" encoding="UTF-8" ?>
<language id="49">
Die erste Zeile. Wenn hier statt der 49 eine 44 steht ändert das.
X² kann sonst, trotz geändertem Dateinamen, den Text nicht laden.

Code: Select all

<page id="17" title="Boardcomp. objects">
 <t id="5873">Handelssoftware MK3</t>
</page>
Diese Zeile tragt in die Seite 17 (page id=), an der Stelle 5873 (t id=), den Bordcomputer ein.
Damit weiss X² den Namen, den Produkttyp und den Preis des neuen Produkts. Aber damit schweife ich schon ins scripten ab.

Code: Select all

<page id="1500" title="Trader scripts" descr=" ">
 <t id="10">Der Pilot des Schiffes </t>
 <t id="11"> in Sektor </t>
 <t id="12"> braucht ihre Hilfe. </t>
 ,..,
 <t id="100">Der Pilot des Schiffes %s in Sektor %s braucht ihre Hilfe. </t>
 <t id="101"> Bisher verdientes Geld: %s Cr. Anzahl Handelsfahrten: %s.</t>
</page>
Hier lädt X² die Nachrichten, die vom script aufgerufen werden.

Code: Select all

<page id="2010" title="Commands" descr=" ">
 <t id="400">Starte Sektorhandel</t>
</page>
Damit wirds wichtig
Die Seite (page id) "2010" enthält die langen und...

Code: Select all

</page><page id="2011" title="Commands" descr=" ">
 <t id="400">Starte Sektorhandel</t>
</page>
...die Seite "2011" diekurzen Einträge, die im Bordcomputer als Befehl angezeigt werden. Die Zahlen stehen für die Befehlsgruppe (Nav =2xx, Handel =3xx usw) und den Befehlseintrag (z.B.:"Docke an")

Code: Select all

</language>
Damit wird die Datei beendet.

Schauen wir noch nach dem "Teladi.."Script:

Code: Select all

<?xml version="1.0" encoding="UTF-8" ?> 
<language id="44"> 
<page id="2008" title="Script Object Commands" descr="0">
 <t id="410">COMMAND_TELADI_AUTO_TRADE</t>
 <t id="411">COMMAND_TELADI_IMPORT</t>
 <t id="412">COMMAND_TELADI_EXPORT</t>
 <t id="413">COMMAND_TELADI_BUY_WARE</t>
 <t id="414">COMMAND_TELADI_SELL_WARE</t>
 <t id="415">COMMAND_TELADI_REPORT</t>
 <t id="729">COMMAND_TELADI_LOAD</t>
 <t id="730">COMMAND_TELADI_UNLOAD</t>
 <t id="731">COMMAND_TELADI_THINK</t>
</page>

<page id="2010" title="Script Cmd Names" descr=" "> 
<t id="410">Teladi Automated Trader</t> 
<t id="411">Teladi Importer</t>
<t id="412">Teladi Exporter</t>
<t id="413">Teladi Buy ware</t>
<t id="414">Teladi Sell Ware</t>
<t id="415">Request progress log</t>
<t id="729">Load ware...</t>
<t id="730">Unload ware...</t>
<t id="731">Calculating...</t>
</page> 

<page id="2011" title="Script Cmd Shorts" descr=" "> 
<t id="410">TAT</t> 
<t id="411">TIMP</t> 
<t id="412">TEXP</t> 
<t id="413">TBUY</t> 
<t id="414">TSELL</t> 
<t id="415">TREQ</t> 
</page> 
</language>
Jetzt könnt ihr alle Einträge an die entsprechende Stelle in der ersten Datei einfügen.
Alles unter "2010" gehört an die entsprechende Stelle unter "2010" im ersten Script usw.
Wenn, wie hier der Fall, eine neue "page id" auftaucht (2008) dann gehört die natürlich zwischen die "1500" und die "2010".

Wenn ihr fertig seid könnte das Ganze so aussehen:

Code: Select all

<?xml version="1.0" encoding="UTF-8" ?>
<language id="49">

<page id="17" title="Boardcomp. objects">
 <t id="5873">Handelssoftware MK3</t>
</page>

<page id="1500" title="Trader scripts" descr=" ">
 <t id="10">Der Pilot des Schiffes </t>
 <t id="11"> in Sektor </t>
 <t id="12"> braucht ihre Hilfe. </t>
 <t id="13"> Bisher verdientes Geld: </t>
 <t id="14"> Anzahl Handelsfahrten: </t>
 <t id="20"> Mein Laderaum ist voll. Ich kann nichts mehr kaufen.</t>
 <t id="21"> Ich habe keine Stationen gefunden, mir denen ich handeln kann. Was soll ich jetzt machen? </t>
 <t id="22"> Mein Schiff ist zu angeschlagen, um weiterzumachen. Sie finden mich in der Station </t>
 <t id="23"> Die Leute HASSEN mich hier, was soll ich jetzt machen? </t>
 <t id="24"> Ich konnte meine Ware nicht komplett verkaufen. Brauche Anweisungen. </t>
 <t id="25"> Ich bin jetzt im Sektor %s. Mein Schiff ist zu angeschlagen, um weiterzumachen. Sie finden mich in der Station %s.</t>
 <t id="100">Der Pilot des Schiffes %s in Sektor %s braucht ihre Hilfe. </t>
 <t id="101"> Bisher verdientes Geld: %s Cr. Anzahl Handelsfahrten: %s.</t>
</page>

<page id="2008" title="Script Object Commands" descr="0">
 <t id="410">COMMAND_TELADI_AUTO_TRADE</t>
 <t id="411">COMMAND_TELADI_IMPORT</t>
 <t id="412">COMMAND_TELADI_EXPORT</t>
 <t id="413">COMMAND_TELADI_BUY_WARE</t>
 <t id="414">COMMAND_TELADI_SELL_WARE</t>
 <t id="415">COMMAND_TELADI_REPORT</t>
 <t id="729">COMMAND_TELADI_LOAD</t>
 <t id="730">COMMAND_TELADI_UNLOAD</t>
 <t id="731">COMMAND_TELADI_THINK</t>
</page>

<page id="2010" title="Commands" descr=" ">
 <t id="400">Starte Sektorhandel</t>
 <t id="410">Teladi Automated Trader</t> 
 <t id="411">Teladi Importer</t>
 <t id="412">Teladi Exporter</t>
 <t id="413">Teladi Buy ware</t>
 <t id="414">Teladi Sell Ware</t>
 <t id="415">Request progress log</t>
 <t id="729">Load ware...</t>
 <t id="730">Unload ware...</t>
 <t id="731">Calculating...</t>
</page>

</page><page id="2011" title="Commands" descr=" ">
 <t id="400">Starte Sektorhandel</t>
 <t id="410">TAT</t> 
 <t id="411">TIMP</t> 
 <t id="412">TEXP</t> 
 <t id="413">TBUY</t> 
 <t id="414">TSELL</t> 
 <t id="415">TREQ</t> 
</page>

</language>
Es steht euch natürlich frei, die englishen Einträge zu übersetzen.
Beachtet dabei nur: Keine Umlaute und nur "," "." und "-" als zusätzliche Zeichen!
Wenn der InternetExplorer die Seite nicht anzeigen kann habt ihr einen Fehler gemacht. Meist sind das versehentlich benutzte Umlaute oder ähnliches.
Der Explorer sagt aber auch, in welcher Zeile der Fehler ist.
Fertig.

Jetzt das Ganze in den X²/t-Ordner kopieren und los gehts.


II.1.3 Nun gehts dem Scripteditor an den Kragen

Wenn ihr nicht den oben beschriebenen Weg gehen wollt oder in der init.-Datei des Scripts der Eintrag load text: id= fehlt müsst ihr in den Scripteditor des Spieles.

Erstmal aktivieren. Gebt irgendwo im Weltall (nicht angedockt) folgendes ein: Thereshallbewings und beachtet das grosse "T".
Daraufhin ertöhnt ein tülüt und der Scripteditor steht zur Benutzung frei.
Über die Commandokonsole des Hauptmenues ('Enter' dann 'S') oder im Commandomenue eines Schiffes ('S', 'C', und 'S') ist der Editor erreichbar.

Sucht im Editor die init.Datei und öffnet sie.
Ich nehme wieder den "TeladiTrader" als Beispiel.
Die Datei heist in diesem Fall init.mk2.bindCommands und sieht so aus:

Code: Select all

001   global ship map: set: key=COMMAND_TYPE_TRADE_10, class=Ship, race=Player, script='mk2.Command.localizedTrade', prio=0
002   global ship map: set: key=COMMAND_TYPE_TRADE_11, class=Ship, race=Player, script='mk2.Command.factoryBuy', prio=0
003   global ship map: set: key=COMMAND_TYPE_TRADE_12, class=Ship, race=Player, script='mk2.Command.factorySell', prio=0
004   global ship map: set: key=COMMAND_TYPE_TRADE_13, class=Ship, race=Player, script='mk2.Command.wareBuy', prio=0
005   global ship map: set: key=COMMAND_TYPE_TRADE_14, class=Ship, race=Player, script='mk2.Command.wareSell', prio=0
006   global ship map: set: key=COMMAND_TYPE_TRADE_15, class=Ship, race=Player, script='mk2.command.requestlog', prio=0
007   
008   set ship command upgrade: command=COMMAND_TYPE_TRADE_10  upgrade=Handelssoftware MK2
009   set ship command upgrade: command=COMMAND_TYPE_TRADE_11  upgrade=Handelssoftware MK1
010   set ship command upgrade: command=COMMAND_TYPE_TRADE_12  upgrade=Handelssoftware MK2
011   set ship command upgrade: command=COMMAND_TYPE_TRADE_13  upgrade=Handelssoftware MK1
012   set ship command upgrade: command=COMMAND_TYPE_TRADE_14  upgrade=Handelssoftware MK2
013   set ship command upgrade: command=COMMAND_TYPE_TRADE_15  upgrade=Handelscomputer Erweiterung
014   
015   return null
Wie ihr seht fehlt der Eintrag zum laden des Textes.
Gehen wir davon aus, dass wir die Textdatei in 491234.xml umbenannt haben.
Dann tragen wir die jetzt ein:

Geht mit dem Cursor auf eine Zeile am Anfang oder am Ende des Scripts und drückt 'Einfg'.
In die Neue Zeile kommt jetzt der Eintrag.
'Enter' drücken und aus dem folgenden Menue den ersten Punkt "Generell Commands" auswählen.
Im darauf folgenden Menue sucht ihr den Befehl "load text: id<Var\Num>" und drückt 'Enter'.
Der Befehl erscheint daraufhin im Script und der Cursor steht automatisch auf dem "<Var\Num>"-Teil.
Wieder 'Enter' gedückt und aus der erscheinenden Liste den Eintrag "<Nummer>" auswählen.
Dann könnt ihr die Zahl eintragen, die das Script benutzen soll.
In meinem Beispiel also die 1234.

So sollte das dann aussehen:

Code: Select all

015   load text: id=1234
Mit 'Esc' raus, Script speichern und das Spiel neu laden.
Jetzt weiss X² welchen Text es benutzen soll.

Fertig.

P.S.: Der Autor übernimmt keine Verantwortung für eventuell entstandene Schäden. :wink:
P.P.S.: Wenn ich was vergessen, übersehen oder falsch dargestellt hab bitte berichtigt mich.


II.2 Nemesi$ Tutorial-Wie hänge ich ein eigenes Script in die Menüs ein

Sodele..dann will ich mich mal hier an die Übersetzung von Revens Tutorial wagen. Das Original ist unter http://www.egosoft.com/x2/forum/viewtopic.php?t=21585 aufzufinden.
Alles was ich geändert habe, oder einfach meine Meinung dazu schreibe bekommt die Farbe Orange
-----------------------------------------------------------------


Einleitung
Wir alle kennen die InGame-Kommandomenüs der Schiffe. Navigation, Kampf, Handeln und Spezial. Egosoft hat X² extrem erweiterbar gemacht, inklusive dieser Menüs. Viele von uns haben sich Scripte aus dem Web geholt die die Funktionalität von X² erweitern. Und wenn es auch nur BurnIt's neue Trade Command Extension MK3 mit seinem "Start Sector Trader" Kommando ist. Hier werde ich nun eine (vom Original leicht erweiterte) Schritt-für-Schritt Anleitung schreiben, wie man seine eigenen Scripte in die vorhandenen Menüs von X² einhängt.

In diesem Tutorial wird ein Script von Reven als Beispiel verwendet, das er selber geschrieben hat, und das ins Trademenü eingehängt wird. Dieses Script versucht die Anzahl der Produkte einer Fabrik auf einem vorgegebenen Füllstand zu halten. Das ist dann von Vorteil wenn man eine Fabrik hat, die nur eine minimale Anzahle ihrer Produkte bereit halten kann und man nicht ständig von Hand die Produkte in einen Frachter transferieren will. Eine detaillierte Beschreibung des Script und dem Grund hinter diesem Script findet man hier (in Englisch)

Anforderungen
  • Eine Kopie der Beispielscripte von Frag-Warez.org
  • Ein XML-Editor wäre praktisch, ist aber kein muss. Reven empfiehlt da den simplen Peter's XML Editor
  • Ich selber habe den XMLMind XML Editor, habe aber meine ersten Gehversuche mit X²-Scripting und diesem Tutorial mit dem in X² eingebauten Editor gemacht.
Vorgehensweise
Es sind hauptsächlich 3 Schritte notwendig um ein Script in die Menüs einzuhängen. Als erstes benötigt man natürlich das Script welches man einhängen will. Zweitens braucht man eine XML-Sprachdatei die den Text enthält, den man zum Spiel hinzufügt. Und als drittes und letztes braucht man ein Script welches automatisch von X² aufgerufen wird und das eigentliche Script in den Menübaum einhängt.

1. Schritt
Das eigentliche Script. Da dies kein Tutorial über Scripting allgemein ist werde ich hier nicht wirklich in die Tiefe gehen. Soviel sei aber über Scripting gesagt, das der beste Weg es zu lernen ist, wenn man sich einfach vorhandene Scripte anschaut. Als Anregung wären da die original Egosoft-Scripte. Dazu braucht man den X2Modder von OlisJ um die Egosoft-Scripte auszupacken. Alternativ dazu kann man auch den X² Archiver benutzen. Der kommt nämlich auch ohne das .NET Frameset 1.1 aus. Egosoft war so nett uns ein hübsches XSL-Stylesheet zu überlassen, mit dem man die Scripte einfach per Doppelklick zB. im Internet-Explorer anschauen kann, sobald sie einmal entpackt sind.

2. Schritt
Hier kommen wir zum eigentlichen Kern der Sache. Die meisten Spieltexte für so ziemlich alles, angefangen von Gütern bis zu den Schiffsbeschreibungen und Menükommandos sind in externen XML-Sprachsdateien abgelegt. Diese Dateien sind an 2 Orten anzutreffen: Entweder im "X2\t" Verzeichniss oder innerhalb der Kontainerdateien (die Zip-Dateien entsprechen aber keine Zips sind). Das meiste der bisherigen Spieltexte sind ind den XML-Sprachdateien innerhalb der *.CAT/*.DAT Dateipaare im eigentlichen X² Verzeichniss. Jede Datei innerhalb dieser Kontainer wird wie eine Datei in den "normalen" Unterverzeichnissen von X² behandelt. Man kann mit X2Modder eben diese Kontainer entpacken und schauen was sie so alles enthalten. Wenn X² auf die Version 1.2 gepatcht ist enthält das 03.CAT/03.DAT Dateipaar die aktuellsten XML-Sprachdateien des Spieltextes. Das wären dann die Dateien 440001.XML und 440002.XML. Wenn BurnIt's Trade Command Sofware MK3 installiert wurde dann kann man in "X2\t" die 440003.XML finden. Diese Datei enthält die Texte für dieses neue Script.

Vielleicht hat der aufmerksame Leser bemerkt das ein Muster in den Dateinamen steckt. Die ersten zwei Stellen bezeichnen den Sprachcode; 44 ist Englisch. BurnIt's Erweiterung hat zusätzlich noch eine Datei mit '49' installiert, welche die deutschen Texte enthält. Wenn das neu eingehängte Script in mehreren Sprachen funktionieren soll muss man die XML-Sprachateien für jede Sprache mitliefern. Das mag keine dumme Idee sein, selbst wenn der Text in den anderen Sprachdateien der gleiche ist. Englisch ist da natürlich bevorzugt, da das die meisten Spieler verstehen

Nach dem Sprachcode enthält der Dateiname einfach eine Nummer um die Datei für alle Scripte, die die Datei benötigen, zu identifizieren. Diese Nummer wird benötigt um die den Text einer Sprachdatei von einem Script aus zu laden.

Wenn der Sprachcode und die ID-Nummer zusammengesetzt werden erhalten wir den ganzen Dateinamen "440003.XML".

Viele Leute schreiben Scripte mit Install-Routinen die die eigentliche 440003.XML modifizieren um ihre Texte zu speichern. Das ist der falsche Weg um das zu erreichen. Ich gehe mal davon aus das Sie diesen Weg gewählt haben, weil sie den korrekten Weg wie man Dateien zu X² hinzufügt, nicht kennen. Der ganze Sinn hinter der Möglichkeit mehrere Sprachdateien zu haben ist, das man sich nicht mit anderen (evtl. von anderen Scriptern) angelegten Sprachdateien rumschlagen muss. Man fügt einfach ein neue Datei ein.

Für eine neue Datei muss man sich eine ID raussuchen. Wichtig ist dabei, das die ID nicht in Konflikt mit anderen IDs kommt, die unter Umständen von einem anderen Script oder Mod benutzt werden. Es wird zwar bisher die Anstrengung unternommen dafür eine zentrale Stelle einzurichten, die einem diese IDs zuweist, allerdings ist das bisher noch nicht umgsetzt worden. Bis dahin empfehle Ich die folgende Richtlinie einzuhalten:
  • Am besten keine niedrigen IDs verwenden. 440001.XML bis 440003.XML wurden schon von Egosoft belegt. Und man kann ziemlich sicher davon ausgehen das offizielle Egosoft-Erweiterungen, die noch erscheinen werden, noch mehr dieser LowIDs belegen werden.
  • Wenn mehrere Scripts von einer Person geschrieben und veröffentlicht werden sollte man dafür nur eine Sprachdatei verwenden. Auf den Punkt gebracht bedeutet das: Man hat nur eine XML-Sprachdatei für ALLE seine Scripte. Wenn man die Scripte veröffentlicht, dann am Besten in 2 Teilen -> die Scripte getrennt von der Sprachdatei. Nach dieser Methode bekommt jeder immer die aktuellste Sprachdatei, die mit all euren veröffentlichen Scripten funktioniert. Obwohl das bedeuten kann, dass in der Sprachdatei ein Text für ein Script vorhanden ist, das diese Person gar nicht nutzt. Obwohl mehr IDs zur Verfügung stehen als in den XML-Sprachdateien benutzt werden wird es über kurz oder lang Konflikte zwischen verschiedenen Scripten geben, die die gleiche ID benutzen. Und genau deshalb wird eine zentrale Verwaltung benötigt.
So...jetzt aber genug über die Sprachdateien. Nun zu den eigentlichen Anforderungen, die an uns gestellt werden um ein Kommando in den Menübaum zu hängen (Ein kleiner Blick in die Beispieldatei 440021.XML (440069.XML) an diesem Punkt könnte nicht schaden). Dort müssen 2 Textstücke eingtragen werden: Der lange Namen des Kommandos und die dazugehörige, kurze Version. Jenachdem in welchen Menüs man sich gerade im Spiel aufhält sieht man die lange order die kurze Version. Im eigentlichen Menüsystem sieht man beide, wie folgende Illustration zeigt.

Image

In diesem Beispiel verwende Ich "Maintain Product Quantity" für den langen Namen und "MaintainQuant" für den kurzen.

Die Sprachdateien verwenden einen XML "PAGE" Tag um den Text für die verschiedenen Verwendungsmöglichkeiten zu identifizieren. Ein "PAGE" Tag mit einem ID Attribut von 2010 identifiziert den Text für einen langen Namen eines Kommandos, wohingegen 2011 den kurzen Namen des Kommandos identifiziert. Man sollte auch beachten das der "t" Text Tag, mit dem wir den Text bezeichnen ein ID Attribut von 421 (213) hat. Und das es bei beiden die gleiche ID ist, langer Name wir kurzer. Das wird in Schritt 3 wichtig.

Um nur ein Kommando einzuhängen ist das alles was man in der XML-Sprachdatei haben muss.

3. Schritt
Wir haben das Script, das wir für unser neues Kommando benutzen woll, und wir haben die zugehörige XML-Sprachdatei, die für den Text in den Menüs benötigt wird. Jetzt brauchen wir blos noch ein kleines Script, das diese 2 später im Spiel miteinander verknüpft. Und genau dafür benutzt man dann init-Scripte.

Jedes Script das im Dateinamen mit "init" beginnt ist automatisch ein init-Script und wird automatisch bei jedem Start von X² ausgeführt. Es ist absolut wichtig das man damit sehr vorsichtig umgeht. Ein Bug in einem der init-Scripte kann später beträchtliche Konsequenzen haben. Das Beispielscript hierzu hat den Namen "init.cmd.maintprod.xml".

Unser init-Script hat 3 Aufgaben: Es muss die XML-Sprachdatei laden, dem Spiel sagen welcher der Güter mit unserem Script verknüpft ist (Optional -> siehe mein Codebeispiel, wenn das Script immer verfügbar sein soll) und es muss unser Script noch mit einem Kommando verknüft werden und dem Spiel erklären welche Schiffe dieses Kommando verwenden können.

Als erstes wird die XML-Sprachdatei geladen. Der erste Ausdruck im Bespiel dafür ist:
Reven Code:

Code: Select all

load text: id=21
Nemesi$ Code:

Code: Select all

load text: id=69
Erinnert ihr euch an den XML-Sprachdateinamen, wie er den Sprachcode (44 für Englisch) und die ID am Ende hat, mit der wir die Datei laden wollen? Tja...das ist genau was diese Codezeile macht. Die englische Version von X² wird dann die Datei "440021.XML" ("4400069.XML")laden, die deutsche dagegen "490021.XML" ("490069.XML").

Jetzt müssen wir noch unser Script (Beispielscript: "ship.cmd.maintprod") mit einem Kommando vom Spiel verknüpfen. Ein X² "Kommando" ist einfach ein InGame Aktion die man durch die Menüsysteme erreichen kann. Es gibt (offensichtlich) eine ganze Menge vordefinierte InGame-Kommandos in X² -> und alle sind mit Scripten verbunden durch die im Spiel mitgelieferten init-Scripte. Es ist zwar möglich eigene Kommandos zu erstellen, aber das bringt auch wieder einen haufen Aufwand in die ganze Prozedur. Glücklicherweise müssen wir das aber nicht, denn Egosoft war so nett und hat uns 32 Extrakommandos für jeden Typ bereitgestellt. Das sind Kommandos, die noch mit keinem Script verknüpft sind -> der einzige Sinn dahinter ist, das sie von Leuten wie uns benutzt werden um unsere Scripte einzuhängen.

Um einen dieser Kommandos zu benutzen müssen wir dem Spiel erst erklären welches der Güter unser Kommando "enthält". Das bedeutet, was eine Person für ein Upgrade kaufen muss um das Kommando benutzen zu können. In diesem Fall wird die "Trade Command Software MK1" benötigt. So machen wir dem Spiel klar das jedes Schiff, das die "Trade Command Software MK1" eingebaut hat unser neues Kommando benutzen kann. Wie das geht? Nun, die nächtste Codezeile im init-Script will das verdeutlichen:

Reven Code:

Code: Select all

set ship command upgrade: command=COMMAND_TYPE_TRADE_21  upgrade=Trade Command Software MK1
Nemesi$ Code:

Code: Select all

set ship command upgrade: command=COMMAND_TYPE_NAV_13  upgrade=[TRUE]
Bei meinem Codebeispiel ist das Kommando ohne irgendwelche Vorraussetzungen verfügbar.

Erinnert ihr euch daran wie wir gesagt haben, das der Text ID Tag (412) (213) in der Sprachdatei später wichtig wird? Das ist er nämlich jetzt. ID #421 gehört zum Kommando COMMAND_TYPE_TRADE_21. Die "4" bezieht sich auf die Tradekommandos, die 21 auf die Nummer 21 (von 0 bis 31) aus der Kommandoliste.
ID #213 gehört zum Kommando COMMAND_TYPE_NAV_13. Die "2" bezieht sich auf die Navigationskommandos, die 13 auf die Nummer 13 (von 0 bis 31) aus der Kommandoliste.
Wenn wir zum Beispiel ein Commando zum Spezialmenü hinzufügen wollen, anstatt dem Handelsmenü, müssten wir im ID Tag der Sprachdatei "521" und das Kommando COMMAND_TYPE_SPECIAL_21 verwenden.
  • Nav hat ID "2"
  • Combat hat ID "3"
  • Trade hat ID "4"
  • Special hat ID "5"
Bisher haben wir die Sprachdatei geladen und dem Spiel erklärt das wir ein neues Kommando hinzugefügt haben, und wo dieses seinen Text findet. Ales was wir jetzt noch machen müssen ist unser eigentliches Script mit dem Kommando verknüpfen.

Reven Code:

Code: Select all

global ship map: set: key=COMMAND_TYPE_TRADE_21, class=Ship, race=Player, script='ship.cmd.maintprod', prio=0 
global ship map: ignore: key=COMMAND_TYPE_TRADE_21, class=Big Ship, race=Player
Nemesi$ Code:

Code: Select all

global ship map: set: key=COMMAND_TYPE_NAV_13, class=Ship, race=Player, script='ship.cmd.maintprod', prio=0 
global ship map: ignore: key=COMMAND_TYPE_NAV_13, class=Fight Drone, race=Player
In diesem Beispiel sind 2 Ausdrücke um unser Ziel zu erreichen. Der erste bedeutet: Erlaube das Kommando COMMAND_TYPE_TRADE_21 für alle Objekte der Klasse ship (die Klasse ship enthält alle Schiffe) die der Rasse Player gehören (das ist der Spieler) und das wir das Script "ship.cmd.maintprod" mit dem Kommando verknüpfen wollen. Zusaätzlich wird mit prio die Priorität festgelegt, mit der das Script ausgeführt werden soll wenn es aufgerufen wird (0 = normal).

Da dieses Kommando aber recht Nutzlos für ein Schiff der Klasse M6 oder grösser ist (da diese Schiffe sowieso nicht an Fabriken docken können), sagen wir in der zweiten Zeile dass der Verknüpfungsbefehl zwar für alle Schiffe gilt, aber eben nicht bei denen die der Klasse "Big Ships" angehören.

Wir hätten die auch anders machen können, indem wir einfach für jedes Schiff (M5, M4, M3, TS, TL, Goner) einzeln den Befehl ausgeführt hätten. Unsere Variante ist einfach ein wenig kürzer. ber man kann selber völlig frei entscheiden wierum man das ganze macht und was am besten für das eigene Script passt.

Installation
Jetzt haben wir ein Script, eine Sprachdatei für das zugehörige Kommando und haben das Kommando mit dem Script verknüpft. Alles was wir jetzt noch tun müssen ist unser neues Kommando an die passenden Orte kopieren. Die Scripte gehören nach "X2/scripts", die Sprachdatei nach "X2/t". Das wars schon. Wenn alles richtig gemacht wurde sollte man ein Menü wie das Folgende bekommen:
Image

Anmerkung
Ich habe die Nummer 21 hier zweimal benutzt. Einmal um die ID für die Sprachdatei festzulegen, und einmal um zu bezeichnen um welches Extra Trade Kommando es sich handelt. Das war möglicherweise eine schlechte Wahl und wird wohl bei so manchem etwas Verwirrung stiften. Wer mit dem Unterschied der zwei IDs nicht so ganz klar kommt sollte nochmal ganz sorgfältig den text durchgehen.
Und genau wegen dieser möglichen Fehlerquelle habe ich meine Orangefarbigen IDs noch hinzugefügt. Wer sich mit denen ein bisschen ausseinandersetzt sollte recht schnell auf den Trichter kommen.

Wer Fehler findet solls mir per PM oder hier im Topic mitteilen. Ich märze die dann nach Möglichkeit aus.

Und jetzt wünsche ich allen viel Spass beim ausprobieren ;]

Nemesi$




IV. Vanoblis - Der ScriptDebugger - Anleitung (v1.3 UPDATED)


Allgemeines
Der Debugger ist Bestandteil des Script Editors und ist "nur" Objektbezogen. Das heisst es werden alle Scriptbefehle eines Objektes mitgeloggt. (Hinweis: Will man z.b. nur das Flugscript untersuchen, sollte man die Turretscripte/Kommandos abschalten) Scripte, die auf keinem Ojekt(null) laufen, werden als Globale Scripte bezeichnet. Abhängig davon , auf welchem Objekt (zB einem Schiff) das Script läuft, das man debuggen will, muss man den Script Editor unterschiedlich aufrufen (Aktivierung mit "Thereshallbewings" vorrausgesetzt):

für Objektbezogene Scripte:
bestimmtes Schiffsmenu -> Kommando Konsole (des Schiffs) -> Script Editor
für Globale Scripte:
Main Menü -> Kommando Konsole -> Script Editor

Nun steht unter dem Menüpunkt "Script Debugging:XXX" bei XXX der Name des Objekts, das man debuggen will.


Menupunkte des Debuggers
Der Debugger besteht aus vier Menupunkten.
"Script Debugging:XXX"-Einstellung (XXX entweder "GLOBAL" oder ein Schiffsname),
"Clear Debug Messages" löscht alle Debugging Logs des aktuellen Objekts
"Script Debugger Menu". der eigentliche Debugger (Anzeige der Logs)
sei patch 1.3 neu:
"Global Script Tasks". hiermit kann man laufende globale Scripte beenden (Achtung! - Skripte die auf Stationen laufen können zur Zeit nicht abgebrochen werden!)


Einstellung des Debuggers
Diese Einstellung sollte man festlegen, bevor man das Script startet, das man debuggen will (ich hab mir schon mal bei laufendem Script und "Script Debugging:XXX" Wechsel mein Spiel zerschossen
unter dem Menupunkt :"Script Debugging:XXX" gibt es drei Einstellmöglichkeiten.
1) LOG
2) TRACE
3) OFF - deaktiviert den Debugger
---------------------------------

1) LOG:
Bei "LOG" werden alle Commandos, die im Script aufgerufen werden(sprich jede Zeile die auch wirklich ausgeführt wird) im "Script Debugger Menu" aufgelistet(also mitgeloggt). Das Loggen erfolgt so schnell wie die Befehle im Script von eurem Rechner abgearbeitet werden. Wenn also irgendwo im script zB ein " @ = wait 1000 ms" steht, hält der Loggingvorgang auch 1000 ms an. Rumscrollen geht mittels "Bild hoch/runter". Neue Logs werden einfach unten angehängt, solange man nicht mit "Clear Debug Messages" die Logs löscht(ein Menü höher).

die Logging Einträge haben diese Form (Beispiel):

Code: Select all

-----------Scriptname:Line:Stackdepth:Prio:PID:TaskID:Command--------
!trade.buywarebest.pl:22:0:0:164918987:$amount= This -> ....
!trade.buywarebest.pl:23:0:0:164918987:  ...undweiterimcode....
!trade.buywarebest.pl:24:0:0:164918987:  ...undweiterimcode....
...
in einer Zeile sind mehrer Informationen durch "Doppelpunkt" getrennt.

Scriptname : Name des Scripts, was gerade ausführt wird (bei Namenswechsel muss ein ScriptCall stattgefunden haben)
Line : Zeile des Befehls im Script (!ACHTUNG in X2 v1.2 weicht diese Zeilennummerierung von der im Script ab, da hier nur die "ausgeführten Zeilen" durchnummeriert wurden - war vermutlich nicht so gewollt)
Stackdepth : Anzahl der Scripte auf dem Stack des Objekts(jedes Objekt hat seinen eigenen Stack)
Prio : Priorität des Scripts
PID :
TaskID :
Command : Der ausgeführte Befehl im Script


2) TRACE:
Der unterschied zu LOG ist klein aber fein. Im Trace-Modus loggt der Debugger auch wie LOG alle ausgeführten Befehlszeilen im schon oben erklährten Format mit. Nur findet hier das Logging nicht automatisch statt, sondern man muss mit "ENTER" einen "Step" (Schritt)im Code machen. Das Script steht also zu Beginn still und man muss sich mit <ENTER> quasi Schritt für Schritt durch seinen Code "steppen" und nach Fehlern suchen. Die nächste auszuführende Zeile wird zudem noch grün hervorgehoben. Zusätzlich werden im Trace-Modus auch noch die deklarierten Variablen des aktuell laufenden Scripts und deren Inhalt angezeigt. So kann man zB schnell fehlerhafte Belegungen von Variablen finden.

wenn "Script Debugging:XXX" auf TRACE gestellt ist schauts ungefähr so aus:

Code: Select all

-----------Scriptname:Line:Stackdepth:Prio:PID:TaskID:Command----------
!trade.buywarebest.pl:22:0:0:164918987:$amount= This -> ....
!trade.buywarebest.pl:23:0:0:164918987:  ...undweiterimcode....
!trade.buywarebest.pl:24:0:0:164918987:  ...undweiterimcode....
                      ...

[b]VariableName: Datatype, Value (interger value) [/b]
$amount: DATATYP_NULL,null,(0)       <---------- hier stehen deklarierte Variablen und deren Inhalt
...nochmehrvariablen....
...
Starten, Stoppen und Debugging von Scripten
Objektbezogene Scripte können entweder in die Command Console Menüs eingebunden und somit per Schiffbefehl gestartet werden, oder man startet ein Script mit "r" in der Scriptliste des Script Editors. Beim Starten mit "r" wird sofort nach einem Referenz Objekt, gefragt (Station oder Schiff), also dem Objekt, auf dem das Script nun laufen soll. Wählt man hier "null" , läuft das Script auf keinem Objekt, und wird als "Globales Script" bezeichnet.
Ob ein Script wirklich läuft, kann man sehen, indem man den Namen seines Scripts in der "Script Task Statistik" sucht. Die "Script Task Statistik" findet man auch im Scripteditor - mit der "Bild runter Taste" (also wenn ein Script gestartet wurde, einfach mit ESC ein Menü zurück und dann "Bild runter")
Hat man vor dem Start seines Scripts den Debubber eingeschaltet, werden alle ausgeführten Scriptbefehle des Objekts im "Script Debugger Menu" mitgeloggt.
Beenden kann man Objektgebundene Scripte durch Zuweisen eines neuen Befehls in der "Kommando Console" des Objekts(Schiffs). Skripte die auf Stationen laufen können zur Zeit nicht abgebrochen werden!
Global laufende Scripte kann man mit dem (seit patch 1.3) neuen "Global Script Tasks" Menüpunkt im Script Editor beenden. Einfach das zu beendende Script in der Liste raussuchen und mit <DEL> entfernen.


Damit müssten eigentlich die gröbsten Unklarheiten bezgl. des Script Debuggers beseitigt sein. Sicherlich lassen sich damit viele Programmierfehler aufspüren
Ich hoffe es hilft jemandem weiter...

Vanoblis


Debugmodi in Scripten von Metuelisator

Gerade bei grösseren Scripts ist die Fehlersuche nicht immer einfach.
Solange man an einem Script arbeitet kann man mit Zwischenmeldungen von wichtigen Variablen einen möglichen Fehler schneller finden.

also weist man seinem Script zu Anfang ein Argument "debugmode" vor, unter Eingabe "Number", string debugmode.
Beim starten des Scripts gibt man "0" fur debugmode aus, "1" für debugmode ein an.

Im Script selbst kann dann an beliebig vielen Stellen

Code: Select all

if $debugmode = 1 
write to playerlogbook $wichtigeVariable1 
write to playerlogbook $nochwichtigereVariable2 
usw.... 
end 
eingesetzt werden. Diese Aufrufe müssen auch später nicht unbedingt aus dem Script rausgenommen werden wenn es erstmal läuft.

Ist nicht komplett auf meinem Mist gewachsen, bin in der Handel MK3 über was ähnliches gestolpert.
Last edited by jnrk on Tue, 20. Apr 04, 10:26, edited 16 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Post by jnrk » Thu, 25. Mar 04, 17:58

X. jnrk's Programming Tutorial

Vorwort

Ich gebe verwandte Kommandos möglichst mit Referenznummer zur Befehlsübersicht http://www.egosoft.com/x2/forum/viewtopic.php?t=29054 an.
Alle Beispiele, Lösungsansätze etc sind stets als nur eine Möglichkeit zur Problemlösung anzusehen und stellen nicht das Ultimativ-Perfekte dar.

Mein Dank (alphabetisch) an dieser Stelle für Bugreport und Verbesserungen an:
ArcaJeth[D6a]
BurnIt!
Mr.Gee
Orka
ticaki
Vanoblis


X.0 Allgemeine Programmiertipps

Bevor man ans Umsetzen geht, sollte man erstmal niederschreiben/skizzieren, was - wer - wann - wo - mit wem - wie oft machen soll. Damit hat man schonmal eine Grobgliederung zur Hand und verzettelt sich bei der Umsetzung nicht so leicht. Mit etwas Übung kann man aus der Grobgliederung eine Feingliederung ableiten und hat bereits alle benötigten Elemente aufgeführt. Dann muss man nur noch die zugehörigen Befehle zusammensuchen.


X.1 Grundelemente

X.1.0 Ausgabe
Damit man überhaupt sehen kann, was passiert (also zB welche Werte an welchen Stellen auftreten), benötigt man eine Form der Ausgabe. X² stellt zB die Funktion "3.001 write to player logbook <Value>".

Also erstmal solch ein Script zum laufen Bringen:
->Scripteditor-><New Script>->Namen eingeben
->New Line->Enter->Logbook Commands->write to player logbook
-><STRING> auswählen und "Hallo Welt" (oder was auch immer) eingeben
->ESC->Speichern JA
->mittels "r" ausführen->NULL auswählen (dies gibt an wer das Script ausführen soll,
NULL=global, Schiff oder Station -kann auch NavSat oder Turret sein-)
->dann im Logbuch nachsehen, wenns funktioniert steht hier jetzt der Text

X.1.1 Variable

Damit man Werte/Texte/Objekte weiterverarbeiten kann, müssen sie irgendwo gespeichert werden, damit man dieses "Irgendwo" wiederfindet bekommen diese Speicherplätze Namen.
Laut Lehrbuch sind Variable Platzhalter bestehend aus Name, Typ und Inhalt zB. testtext='Hallo Welt', Typ wäre hierbei <STRING>

Ergänzen wir unser obiges Beispiel wie folgt:
-> Zeile mittels "Einfg" einfügen->Enter->General Commands->1.001 <RetVar/IF><Expression>
->Enter-><VARIABLE>->Name zB Outtext->Enter
das <?> wieder mittels Enter auswählen-><String>->"Wieder Hallo" eingeben
jetzt auf unsere "write to player ..." Zeile navigieren und Enter
->Outtext auswählen->Enter

Das Script müsste jetzt so aussehen:

Code: Select all

001   $Outtext = 'Wieder  Hallo'
002   write to player logbook $Outtext
Ausführen und tada ... jetzt sollte im Logbuch 'Wieder Hallo' eingetragen sein.

Der Typ heißt korrekterweise Datentyp und bestimmt in welcher Form die zu speichernden Informationen vorliegen, grundsätzlich sind die unterschiedlichen Typen nicht miteinander zu mischen. X² kennt jede Menge vorbestimmter Typen, die einfachsten sind <STRING> und <NUMBER>. <STRING> wie zuvor verwandt, speichert Text und <NUMBER> Zahlenwerte. Es können aber auch komplexe Dinge wie <Objects> (zB Schiffe mit all Ihren Daten und Ausrüstungen) hinterlegt, abgefragt und verändert werden. Dazu ein anderes mal mehr.

Zeit für ein weiteres Beispiel, ich denke die Eingabeschritte spar ich mir fortan, die Systematik ist ja trivial. Ich kommentiere die Zeilen/Fkten im Quellcode.

Code: Select all

001   $Werta = 30    
002   $Wertb = 12
(bei Beiden ist der Typ <Number>)
003   $summe = $Werta + $Wertb
004   write to player logbook $summe
(so einfach geht das Rechnen mit Variablen :) )
005   $summe = $summe + $Werta
(unlogisch ? nicht für den Compi, er addiert einfach $Werta zur $summe und speichert das
Ergebnis wieder in $summe)
006   write to player logbook $summe
X.1.2 Schleifen

Möchte man eine Aktion (also einzelne Befehle oder Befehlsblöcke) mehrfach ausführen,
bietet es sich an dies mit einer Schleife zu realisieren. Ausgangsbasis ist die Funktion
1.001 <RetVar/IF><Expression> diesmal mit der Unterfunktion "while". Die Anzahl der
Durchläufe wird in einer hochzählenden Zählvariablen festgehalten.
(engl. while = dt. solange)

Code: Select all

001   $zaehler = 0
(Startwert ist unabdingbar, sonst gehts früher oder später schief)
002   while $zaehler < 5
(die Schleife soll also 5 mal durchlaufen werden von 0 bis 4)
003    write to player logbook 'X2 ist cool'
004    write to player logbook $zaehler
005    inc zaehler
(1.002 inc <RetVar> = erhöht den zaehler um 1, dieser muss erhöht werden, sonst befinden
wir uns in einer Endlosschleife. Es geht natürlich auch 005  $zaehler = $zaehler + 1)
006   end
(1.1.001 end conditional dient stets zum beenden eines Blocks, hier der While-Schleife) 
X.1.3 Bedingungen

Wollen wir das etwas in Abhängig von etwas anderem geschieht, hilft uns wiedereinmal
1.001 <RetVar/IF><Expression> weiter, wobei wir diesmal die Unterfunktion "if" benötigen.

Code: Select all

001   $Werta = 5
002   $Wertb = 7
003   if $Wertb > $Werta
004    write to player logbook 'b groesser a'
005   end
006   if $Werta > $Wertb
007    write to player logbook 'a groesser b'
008   end
009   if $Werta == $Wertb
010    write to player logbook 'a ist gleich b'
011   end
Soll ich hierzu noch etwas sagen ?
Interessanter wirds, wenn wir uns für $Werta und $Wertb Information aus dem Spiel nehmen.
Nach dem Ausführen mit "r" diesmal das Schiff als auszuführende Plattform heranziehen.

Code: Select all

001   $Werta = 0
002   $Wertb = 100
003   $Werta = THIS-> get free volume of cargo bay 
(5.1.008 <RetVar/IF> <RefObj> get free volume of cargo bay 
gibt uns den freien Laderaum der Plattform von dem dieses Script ausgeführt wird.)
004   if $Wertb > $Werta
005    write to player logbook 'Nicht mehr viel Platz im Laderaum'
006   end
007   if $Werta > $Wertb
008    write to player logbook 'Noch genuegend Platz zum shoppen'
009   end
Ein Goody zum Schluss der Missile-Missile-Defender:

Code: Select all

Arguments
1: schiff , Var/Ship , 'schiff' 

001   
002   wdh:
003   $missile2kill = $schiff -> find nearest missile aiming to me
004   $verfuegbare = $schiff -> get current missile
005   = $schiff -> fire missile $verfuegbare on $missile2kill
006 @ = wait randomly from 2000 to 3000 ms
007   goto label wdh
008   
009   
010   return null
Kommentar mal anders:

Diesem Script wird mit dem Argument 1: übergeben welches Schiff sich verteidigen soll.
Praktischerweise kann es zB auf einer Station ausgeführt werden, damit ein Schiff sich
verteidigt. So ist es möglich mehrere Scripte gleichzeitig für ein Schiff arbeiten zu
lassen.

Code: Select all

002 das Label "wdh" damit das Skript endlos durchlaufen werden kann
003 in $missile2kill wird die nächste Rakete die auf das $schiff zielt abgelegt
004 die derzeit ausgewählte oder nächstbest-verfügbare Rakete des $schiff holen
005 das $schiff feuert seine Rakete vom Typ $verfuegbar auf die Angreifende
006 damit nicht alle Raketen nacheinander abgeschossen werden, gibts hier eine kleine
    Zufallspause von 2-3 Sekunden
007 Springe zum Label
X.2 erweiterte Grundelemente

X.2.0 Formatierte Ausgabe von ArcaJeth[D6a]

Um die Logbuchnachrichten/incoming+blackboard messages etwas besser zu gestalten oder einfach nur übersichtlicher zu machen gibt es verschiedene Möglichkeiten.
Hier einmal 2 Bilder mit allem was mir so einfiel *g*

http://www.x2map.de.vu/X2Format-1.jpg
http://www.x2map.de.vu/X2Format-2.jpg

Bild 1:

Code: Select all

[author]hier könnte Ihr Name stehen[/author][title]Formatierungsbeispiele[/title]Hallo,\ndas ist ein normaler Text. Aber man kann auch viele bunte Farben hinein bringen:\n\033Agrau\033X \033Bblau\033X \033Ccyan\033X \033Ggrün\033X \033Mmagenta\033X \033Rrot\033X \033Wweiss\033X \033Ygelb\033X\nEbenfalls kann man einen Text [u]unterstreichen[/u].\n[center]Und sogar zentrierte[/center]\n[right]oder rechtsbündige Textpassagen sind möglich :-\)[/right]
[author] hier könnte Ihr Name stehen [/author]: legt fest von wem die Nachricht kommt und erscheint links oben
[title] Formatierungsbeispiele [/title]: der Titel der Nachricht - wird zentriert und unterstrichen

Farben werden mit \033 und einem Buchstaben eingeleitet, dabei gilt:
A = Grau, B = Blau, C = Cyan, G = Grün, M = Magenta, R = Rot, W = Weiss, Y = Gelb und X beendet die Farbformatierung

[center] Text [/center]: zentiriert den Text
[right] Text [/right]: stellt den Text rechtsbündig dar

Bestimmte Zeichen werden innerhalb der Sprach-XMLs ignoriert - so zum Beispiel die Klammern ( ) und deren Inhalt. Um sie dennoch zu nutzen muss man einen Backslash \ davor setzen. Also \( und \)
Mit \n erzeugt man einen Zeilenumbruch.

Bild 2:

Code: Select all

[title]Text im Blocksatz und etwas eingeengt[/title][text colwidth='500'][justify]Deaktivieren Sie jede Art [..] die ständig im Hintergrund läuft.[/justify][/text]
Genutzt wird wieder [title] [/title] für die Überschrift gefolgt von [text colwidth='500'] [/text]. Dieser Befehl ist nötig wenn man einen Absatz formatieren möchte und das colwidth='500' legt die Breite des Absatzes fest. Zusätzlich noch [justify] [/justify] welches den Blocksatz aktiviert. Das heißt, der Text wird so verteilt, dass die Ränder möglichst geradlinig verlaufen.

Code: Select all

[title]Text in 2 Spalten[/title][text cols="2"][/text][justify]Deaktivieren Sie jede Art [..] die ständig im Hintergrund läuft.[/justify][/text]
Hier wurde der Text mit cols='2' nun in 2 Spalten aufgeteilt und wieder [justify] [/justify] genutzt.

Code: Select all

[title]Text in 3 Spalten und höherem Spaltenabstand[/title][text cols="3" colspacing='50'][justify]Deaktivieren Sie jede Art [..] die ständig im Hintergrund läuft.[/justify][/text]
Dieses Mal 3 Spalten und ein etwas größerer Abstand zwischen den einzelnen Spalten durch colspacing='50'


X.2.1 Arrays

Vielseitig, mächtig und empfindlich im Umgang ist das erste was mir im Bezug auf Arrays
einfällt. Arrays sind im normalen Sprachgebrauch Listen, wobei eine Liste immer nur
Daten eines einzigen Datentyps aufnehmen kann. Die einzelnen Zellen der Liste werden
über ihren Index angesprochen. Eine der Besonderheiten, was immer wieder für
Schwierigkeiten sorgt, ist der Umstand das der Index bei Arrays bei 0 beginnt. Dh. der
erste Inhalt liegt im Folgenden bei $liste[0].

Code: Select all

001   $zaehler = 0
002   $anzahl = 0
003   $liste = array alloc: size=0
004   $liste = THIS get formation follower ships 
005   $anzahl = size of array $liste
006   while $zaehler < $anzahl
007    $folgeschiff = $liste[$zaehler]
008    write to player logbook $folgeschiff
009   end

003  Fkt 1.3.001 legt im Speicher ein Array mit 0 Elementen an
004  Fkt 4.019 liefert eine Tabelle der Schiffe, die einem Führungsschiff folgen
005  Fkt 1.3.004 gibt einem die Anzahl der Elemente des Arrays zurück
006  Fkt 1.3.002 hier erhalten wir einen Eintrag aus dem Array mit dem Index $zaehler
Einer der Hauptvorteile von Arrays zeigt sich in diesem Beispiel. Es ist sehr einfach
beliebig viele Werte mit einem Namen greif und vor allem verarbeitbar zu machen.


X.2.2 Gültigkeitsbereich/Sichtbarkeit von Variablen

X2 kennt insgesamt 3 unterschiedliche Sichtbarkeitsvarianten, Script, Lokale (funktionieren
noch nicht korrekt in V1.3) und Globale-Variable (seit V1.3 sind leider noch nicht in der
Befehls-Übersicht).

Alle bisherigen verwandten Variablen sind immer nur innerhalb des jeweiligen Scripts gültig.
Ist auch naheliegend, schließlich soll ein Script gleichzeitig mehrfach ausgeführt werden
können, ohne das sich die einzelnen Abläufe gegenseitig beeinflussen. Ich nenne diese
Script-Variable.

Dank an ArcaJeth[D6a] für die Ausführung zu Lokalen-Variablen

Lokale-Variable, sind an das Objekt gebunden und können mit Bezug auf das jeweilige Objekt
abgefragt und gesetzt werden. So ist es möglich zB bei Bau einer Station mit der Ausführung
des folgenden 2-Zeilers seine Bauzeit zu speichern.

Code: Select all

001   $Time = get playtime 
002   $Station -> set locale variable: name='Time' value=$Time

Später kann dies von einem beliebigen Script aus abgefragt werden:

001   $Time = $Station -> get local variable: name='Time' 
002   write to player logbook $Time

oder um rauszufinden wie lange die Station besteht:

001   $Time.now = get playtime 
002   $Time = $Station -> get local variable: name='Time' 
003   $Time.diff = $Time - $Time.now 
004   write to player logbook: printf: fmt='%s %s', $Station, $Time.diff, null, null, null
Globale-Variable sind, wie der Name bereits sagt, von überall verfügbar.

Folgende Beispiel zeigt nur die Systematik, da ich nur V1.2 im Einsatz habe.

Script1:

Code: Select all

001   $wert = 10
002   set global variable : name='globvar', value=$wert
003   while $wert > 0
004    $wert = get global variable : name='globvar' 
005    write to player logbook $wert
006    @ = wait 2000 ms 
007   end
Script2:

Code: Select all

001   $wert = 0
002   $wert = get global variable : name='globvar'  
003   while $wert > 0
004    $wert = get global variable : name='globvar'  
005    dec $wert = 
006    set global variable : name='globvar', value=$wert
007    @ = wait 5000 ms 
008   end
Beide Skripte auf unterschiedlichen Objekten zB einem Schiff und einer Station ausführen.
Das Logbuch füllt sich mit Einträgen von 10 an runter auf 1, wobei Werte mehrfach vorkommen,
da die Pausen im Script2 deutlich größer sind als in Script1.

Unter Global Commands ganz unten aufgeführt:
set global variable : name=<String>, value=<Value>
<Retvar/value> get global variable : name=<String>


X.2.3 erweiterte Schleifen

Gerade wenn man Überwachungs-oder generell Endlosfunktionen in X2 einbauen will, benötigt
man Endlosschleifen. Doch wie beendet man solche Scripte, besonders wenn sie global, also
auf NULL ausgeführt werden ? Wie immer gibt es hierzu mehrere Möglichkeiten.

Code: Select all

001   $raus=0
002   while $raus == 0
       tu irgend etwas
004    $raus = Ergebnis einer Funktion/Abfrage/Wasauchimmer
005   end

004 Die Schleife beendet sich also, wenn $raus durch diese Zeile != 0 wird


001   $raus=get global variable : name='globvar'
002   while $raus == 0
       tu irgend etwas
004    $raus=get global variable : name='globvar'
005   end

004 Diese Schleife endet also, wenn ein anderes Script die 'globvar' != 0 setzt

001   $raus=0
001   $globalraus=get global variable : name='globvar'
002   while $raus == 0 AND $globalraus == 0
       tu irgend etwas
004    $raus = Ergebnis einer Funktion/Abfrage/Wasauchimmer
005    $globalraus=get global variable : name='globvar'
006   end
Durch die Und-Verknüpfung der while-Bedingungen, müssen stets beide Bedingungen erfüllt
sein, damit die while-Schleife ausgeführt wird. Wird $raus oder $globalraus
!= (ungleich) 0 , ists aus mit dem While-Zauber.

Achja, eine hätte ich beinahe vergessen:

Code: Select all

001   $raus=0
002   $raus2=0
003   while $raus == 0
004    tu irgend etwas
005    if $raus2 != 0
006     break
007    end
008   end
Also die simple Beendigung der while-Schleife durch 'break'


X.2.4 erweiterte Bedingungen

Code: Select all

001   $Werta = 5
002   $Wertb = 7
003   if $Wertb > $Werta
004    write to player logbook 'b groesser a'
005   else if $Werta > $Wertb
007    write to player logbook 'a groesser b'
008   else if $Werta == $Wertb
010    write to player logbook 'a ist gleich b'
011   end
Sieht bekannt aus, oder ? Ich hab die Zeilennummern aus Kap 1.3 belassen, damit man
den Einsparungseffekt bewundern kann. Dennoch gibt es einen Unterschied in der
Funktionsweise beider Beispiele, denn bei der "else if" Kombination wird der nachfolgende
"else if"-Zweig nur auf Gültigkeit überprüft, wenn alle vorangegangenen ungültig waren.
Dh. hier, wenn $wertb > $werta wird nicht mehr überprüft ob $werta > $wertb oder
$werta == $wertb ist. Nicht schlimm möchte man meinen, doch was geschieht wenn zuerst
$wertb > $werta ist und anstelle unserer Zeile 004 "004 $werta = $werta * 2". Dann
kommt es garnicht zur Ausführung von Zeile 007, da die Überprüfung in 005 nicht mehr
durchgeführt wird.
=> Hier ist besondere Vorsicht geboten.

IF THEN ELSE - WENN DANN SONST

Code: Select all

001   $kontakta=Khaak
002   $beziehung='nix'
003   $beziehung = PLAYERSHIP get notoriery to race $kontakta
004   if $beziehung == FEIND
005    write to player logbook 'Das hab ich mir gedacht'
006   else
007    write to player logbook 'Das wundert mich aber'
008   end
Also, WENN $beziehung == FEIND DANN 005 SONST 007, ganz einfach oder ?

003 6.026 <RetVar/IF> <RefObj> get notoriery to race <Var/Race>


X.3. Scripte miteinander verbinden / Unterscripte

X.3.1 Teile und Herrsche - Scripte aufteilen

Bislang haben wir unsere Funktionen immer in ein Script integriert, doch mit der Zeit
wachsen unsere Wünsche und Anforderungen. Hier eine neue Funktion, dort eine kleine
Erweiterung, mein Ehrenwort irgendwann wird es richtig unübersichtlich (eine Gegenmassnahme
gibts in 4.4). Zudem gibt es einige Funktionen, die man in unterschiedlichen Scripten
oder sogar demselben Script immer wieder benötigt und Copy&Paste von Blöcken über
Scriptgrenzen hinweg gibt der (ansonsten gute) Scripteditor nicht her.

Die Lösung besteht im Aufteilen von funktionalen Scriptblöcken und dem Auslagern in weitere
Scriptdateien. Der Aufruf von anderen Scripten erfolgt mit der Funktion:

-----Ergänzung von Mr.Gee-------
Wird
(1.2.001) @ <RetVar/IF/START> <RefObj> call script <Script Name>:<Parameter>

ohne Variable aufgerufen als z.B

@ =[This] -> call sript '!ship.cmd.attack.std' : the victim=$target do not follow in new sector=[false]

Wartet das aktuelle script bis der call befehl bzw. das aufgerufene script beendet wurde.
Wird hingegen START vorne angestellt z. B

@ START [This] -> call sript '!ship.cmd.attack.std' : the victim=$target do not follow in new sector=[false]

wird in diesem Beispiel das script !ship.cmd.attack.std gestartet, jedoch läuft das aktuelle script weiter ohne auf eine Rückmeldung zu warten.

Ergänzung von mkess:
Es ist noch ein bischen kniffliger. wenn das Script starten auf einem anderen Object ausgeführt wird, dann beendet sich das rein ge-call-te script, wenn das Aufrufscript endet.

Es ist also unerlässlich, bei den Start eines scriptes auf fremden Objektes ein START voranzustellen, damit es auch nach beenden des "anwerfscriptes" noch weiterlaufen soll. (wer hat da gesagt, scripten ist einfach )
-------------------------------

Wenn man Kapitel 0 berücksichtigt hat, fällt eine sinnvolle Aufteilung viel
leichter. Daher hier ein Konzept mit (noch nicht guter) Umsetzung.

Die Idee:
AutoPatrol über ausgewählte Sektoren zur Sicherung meiner Transporter

Grobgliederung:
-Sektoren auf Feinde scannen
-Gegner gefunden ?
-Gegner bekämpfen bis Friede
-Weitersuchen

Feingliederung:
a) Sektoren per Eingabe abfragen
b) Sektoren zu einem Array zusammenfügen
c) Ein Sektor auswählen
d) Sektor überprüfen <- hier erkennt man das diese Fkt mehrfach benötigt wird
e) Wer ist überhaupt der Feind <-Feinderkennung oft benötigt, wäre also auch praktisch
f) Feind im Sektor suchen
g) Gefunden ?
h) Ja: Hinspringen, EZ Auffüllen wenn benötigt, Angreifen
Springen und Auffüllen sind ebenfalls vielseitig => ??? :)
i) Nein: such im nächsten Sektor

Umsetzung:

Code: Select all

a)
Arguments
1: PatrolSektor1 , Var/Sector , 'PatrolSektor1' 
2: PatrolSektor2 , Var/Sector , 'PatrolSektor2' 
3: PatrolSektor3 , Var/Sector , 'PatrolSektor3' 
4: PatrolSektor4 , Var/Sector , 'PatrolSektor4' 

b)
001   write to player logbook 'Patrol-Script-neu-gestartet'
002   $PatrolSektors =  array alloc: size=0
003   $i = 0
004   append $PatrolSektor1 to array $PatrolSektors
005   if $PatrolSektor2 != null
006    append $PatrolSektor2 to array $PatrolSektors
007   end
008   if $PatrolSektor3 != null
009    append $PatrolSektor3 to array $PatrolSektors
010   end
011   if $PatrolSektor4 != null
012    append $PatrolSektor4 to array $PatrolSektors
013   end
026   $anzahl =  size of array $PatrolSektors

c+i) 
029   while $i < $anzahl
030    $aktuellersektor = $PatrolSektors[$i]
031 @  = [THIS] -> call script 'jk.cmd.patrol2' :  Bitte Sektor eingeben=$aktuellersektor
032    inc $i = 
033   end

d) durch Zeile 031 gestartet

g)
049   while $gegner != null
050    if $anzahl > 0
051     $aktuellersektor = [THIS] -> get sector
052     if $aktuellersektor != $sekt
053 @    = [THIS] -> call script 'jk.cmd.jump' :  Schiff=[THIS]  Sprungziel=$sekt
064     end
065 @    = [THIS] -> call script '!fight.attack.object' :  the victim=$gegner  follow in new sector=[FALSE]
066    end
067   *write to player logbook 'Einer Hinne'
068     $gegner = [THIS] -> find nearest enemy ship: max.dist=9999999
069   end

h)
002   $menge = $schiff -> needed jump drive energy for jump to sector $Ziel
003   $ez = $schiff -> get volume of ware Energiezellen in cargo bay
004   if $ez < $menge
005 @  = [THIS] -> call script 'jk.cmd.refill' :  schiff=$schiff
006   end
007   = $schiff -> use jump drive: target=$Ziel
Download des AutoPatrol-Script


X.3.2 Übergabe- und Rückgabe-Parameter

Durch das Aufteilen unseres Scripts in mehrere Einzelne, haben wir allerdings ein Problem,
denn unsere Variable sind alles Script-Variable (vgl. Kapitel 1.1) und somit nur im
jeweiligen Script verwendtbar. Einer der gegebenen Auswege stellen Übergabe und
Rückgabeparameter dar. Mit diesen können wir Werte an ein Script übergeben und von ihm
zurückerhalten. Aufrufparameter werden in den "Arguments" festgelegt und Rückgabeparameter
per "return" zurückgegeben, beim "return" nur ein einzelner Wert (kann auch ein
Objekt oder Array).

script1:

Code: Select all

001   $werta = 7
002   $wertb = 0
003   @ $wertb = [THIS] -> call script 'script2' :  wert=$werta
004   write to player logbook $wertb
script2:

Code: Select all

Arguments
1: wert , Var , 'Rechenwert' 

001   $wert = $wert * $wert
002   return $wert

X.3.3 präventive Fehlerbehandlung

In den vorangegangenen Beispielen haben wir sie kaun genutzt obwohl sie in der Befehlsliste
mehr als reichlich vorhanden sind. Die Rede ist von den <RetValue>, sie liefern uns nicht nur
ab und an die gewünschten Ergebnisse sondern stets auch Informationen ob das Kommando wie
gewünscht ausgeführt wurde. Es liegt an uns diese zusätzlichen Rückgabewerte auszuwerten und
somit Fehler rechtzeitig abzufangen.

So liefert die Funktion:
5.003 <RetVar/IF> <RefObj> add <Var/Number> units of <Var/Ware>
die tatsächliche Anzahl der hinzugefügten Ware zurück.

Ein Code sagt mehr als 1000 Worte

Code: Select all

001   $anzahl = 0
002   $menge = 0
003   $preis = get max price of ware Energiezelle
004   $kosten = 0
005   $negkosten = 0
006   $anzahl = THIS add 99999 units of Energiezelle
007   $kosten = $anzahl * $preis + 1000
008   $negkosten = - $kosten
009   add money to player: $negkosten

5.014 <RetVar> = get max price of ware <Var/Ware>
um diese "einfache" Einkaufsvariante zu rechtfertigen, bezahlen wir den Max-Preis der Ware
zzgl eines kleinen Lieferbonus von 1000Cr

5.002 add money to player: <Var/Number>
Fügt dem Spielerkonto Geld hinzu, damit etwas abgezogen wird, drehen wir die $kosten zu 
$negkosten um


Doch dies ist nur ein Teil der Fehlerprävention, der Andere besteht darin, zu überprüfen ob
die Werte die man an andere Scripte/Funktionen/Schleifen/Abfragen übergibt, auch im erwarteten
Rahmen liegen.


Erweitertes Beispiel:

Code: Select all

$anzahl = 0
$menge = 0
$preis = 0
$kosten = 0
$preis = get max price of ware Energiezelle
$anzahl = THIS add 99999 units of Energiezelle
if $anzahl != NULL AND $preis != NULL
 $kosten = $anzahl * $preis + 1000
 $negkosten = - $kosten
 add money to player: $negkosten
end

Somit hätten wir auf einen Schlag überprüft ob überhaupt ein Preis ermittelt und Ware geladen
wurde.
Noch typischere Fehler ergeben sich bei komplexen Funktionen wie:

Code: Select all


001   $rueck find ship: sector=TRANTOR class or type=MOVEABLE race=Khaak flags=NULL refobj=NULL maxdist=NULL maxnum=9999 refpos=NULL
002   if $rueck != NULL
003    $jumprueck = THIS use jump drive: target=TRANTOR
004    if $jumprueck != NULL
005     write to player logbook 'Sprung erfolgt'
006    else
007     write to player logbook 'Etwas stimmt nicht...'
008    end
009   end
 
6.066 <RetVar/IF> find ship: sector=<Var/Sector> class or type=<Value> race=<Var/Race> 
flags=<Var/Number> refobj=<Value> maxdist=<Var/Number> maxnum=<Var/Number> refpos=<Var/Array>
stimmen die Aufrufparameter dieser Funktion nicht, kommt nur NULL raus. Ansonsten ein ganzes
Array.

4.068 <RetVar/IF> <RefObj> use jump drive: target=<Value>
springt wenn möglich mit dem <RefObj> ans Ziel <value>

X.4 Form und Stil von Scripten

[Anmerkung: Bei Form+Stil scheiden sich die Geister, aber egal welcher Linie man folgt
hauptsache man folgt einer konsequent.]

Daher möchte ich hier nur einige wenige Tipps zur besseren Gestaltung von Programmcode geben.

X.4.1 Namenskonvention für Dateinamen

Bei X2 bietet es sich förmlich an, die Konvention von Egosoft zu übernehmen bzw. leicht zu
erweitern. Dies führt zu der einfachen Form:

{init.}autorkürzel.Ziel.{Typ.}name.xml

{}=muss nicht kann aber
init = wenn es beim Spielstart gestartet werden soll
Typ = cmd, bc (=battle-command), trade ...
Ziel = ship, turret, station, global, universal


X.4.2 Variable initialisieren und Namenskonvention ungarische Notation

Einen leichteren Überblick über die im Script verwandten Variablen erhält man, indem man sie
alle zu beginn bereits zB mit 0 als Wert anlegt. Dies hilft gleichzeitig Fehler zu vermeiden.
Dies läßt sich auch leicht in meinen Beispielen ersehen. Es ist definitiv in X2 nicht notwendig,
aber praktisch, denn hat man sie einmal eingegeben, kann man sie jederzeit im Script mit der
Auswahlbox auswählen.

Was ist die Ungarische Notation? von www.bytelords.de

Die ungarische Notation ist eine Konvention zur Benennung von Variablen. Sie hat in C und C++, vor allem unter Windows weite Verbreitung gefunden. Ungarisch deshalb, weil der Vater dieser Notation, Charles Simonyi, ein gebürtiger Ungar ist.

Namenskonventionen sollen die Lesbarkeit von Programmen erhöhen. Gerade, wenn Programme im Team entwickelt werden, ist die Standardisierung von Bezeichnungen sehr wichtig. Aber auch für die Wartung und die Verständlichkeit von Programmen ist es vorteilhaft, sich an bestimmte Regeln zu halten.

Der Aufbau des Variablennamens besteht bei der ungarischen Notation aus: Präfix und Bezeichner. Als Bezeichner sollte man einen aussagekräftigen Namen benutzen, die durchaus aus mehreren Teilworten bestehen sollen. Besteht der Bezeichner aus mehreren Teilworten, werden die einzelnen Teilworte jeweils mit einem Großbuchstaben begonnen z.B. SchleifenZaehleroder FehlerTextMain.

Ergänzt wird der Bezeichner durch den Präfix, der anzeigt, welchen Datentyp die Variable besitzt. Präfixe sind dem Bezeichner vorangestellt und werden immer klein geschrieben. Es ist möglich, mehrere Präfixe zu kombinieren, um zusammengesetzte Datentypen zu kennzeichnen, wie beispielsweise einen Zeiger auf eine int-Variable.

Folgende Tabelle enthält die wichtigsten Prefixe: (angepaßt für X2)

Code: Select all

Datentyp            Präfix      Beispiel

globale Variable     g           gVariable
lokale Variable      l           lPosition
script Variable      sc          scZaehler
Feld (Array)         a           aiFeld
Number/Int(Ganzzahl) i           iNummer
Float                f           fGehalt
string(Zeichenkette) sz          szString
Ware                 w           wEnergiez
Kommando             co          coSuche
Signal               si          siAlarm
Rasse                r           rFreund
Objekt               o           oSchiff
X.4.3 Dokumentation/ReadMe

Da testet und schreib man schön ein Script nach dem anderen und alles funktioniert soweit. Mit
der Zeit sammeln sich immer mehr eigene, aber auch Fremde Scripte an. Eine gewisse Zeit weiß
man selbst WAS man WO in welchem Script angestellt hat, aber woher wissen bei der Weitergabe
eigener Scripte andere Scripter dies. Und was ist wenn diese Verweilzeit des Wissens im Hirn
abgelaufen ist ? Ansehen und reinfuchsen in alte Arbeiten ist zeitintensiv und nervig.
In X2 lassen sich Kommentare nur bedingt gut einfügen, daher sollte die Beschreibung nicht nut
zur Anwendung, sondern auch zur Funktionsweise in der obligatorischen ReadMe ausführlicher sein.

im Code:
- Zu Beginn jeder Funktion eine kurze-Kurzbeschreibung
- Wichtige Zeile im Code kommentieren

in der ReadMe:
- Anwendung des Scripts
- Funktionen beschreiben, optimalerweise mit Aufruf und Rückgabeparameter
- Danksagungen
- Kontaktmöglichkeit

X.5 Objekte
X.5.1 exists&get&set


X.6 Mathematik und Logik im Script

X.6.1 Mathematische und Logische Ausdrücke von ArcaJeth[D6a]

Für Berechnungen, Vergleiche, If-Abfragen und While-Schleifen steht in X2 der Befehl
1.001 <RetVar/IF><Expression> zur Verfügung. Hier einige Ausdrücke die mit selbigem
genutzt werden können.

Code: Select all

==    - für (if-)Vergleiche -> 'ist gleich'
!=    - für (if-)Vergleiche -> 'ist nicht (gleich)'
>     - für (if-)Vergleiche -> 'ist größer als'
<     - für (if-)Vergleiche -> 'ist kleines als' 
>=    - für (if-)Vergleiche -> 'ist größer oder gleich'
<=    - für (if-)Vergleiche -> 'ist kleiner oder gleich'
&     - Binär 'und'
|     - Binär 'nicht'
^     - Binär 'exklusiv und'
AND   - zum verbinden von Voraussetzungen ('if a AND b') -> beide müssen wahr sein
OR    - zum verbinden von Voraussetzungen ('if a OR b') -> eins muss wahr sein
+     - Grundrechenart Addition
-     - Grundrechenart Subtraktion
*     - Grundrechenart Multiplikation
/     - Grundrechenart Division
mod   - Modulo -> Rest der Division (13 mod 4 = 1 ... 13 / 4 = 3 Rest 1)
[     - Klammer auf
]     - Klammer zu
~     - Addiert eins zum Wert und nimmt *-1 zB ~5 => -6
!     - Negierer zB TRUE<->FALSE

-to be continued-

Anregungen, Kritik und Verbesserungen wie immer allerherzlichst an mich:
jk@cinso.de
Last edited by jnrk on Fri, 30. Apr 04, 14:32, edited 8 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Post by jnrk » Thu, 25. Mar 04, 17:59

-----------Bits'n Bytes Nützliche Routinen--------------

a) Flugblock und Andockcheck von mkess

Code: Select all

init: 

... 

startloop: 
.... 


Landinwhatever: 
skip if DOCKEDAT == $targetstation 
    @ THIS-> !move.movetostation Station: $targetstation 
if DOCKEDAT == $targetstation 
   .... Aktionen innerhalb der Station. 
   if not .....  --- Preis nicht in ordnung, Kram nicht zu bekommen, oder was auch immer 
   $targetstation = find:station ........  neue Station suchen. 
    skip if not $targetstation 
        goto Landinwhatever: -- zur neuen Station 
    goto exceptions: 
  end; 
  @ wait randomly 1000 to 5000 ms 
end; 

dothenextthing: 
.... 
goto startloop: 
return null 

exceptions: 
... 
fehlerbehandlung 
return FALSE; 
---------------Kommentar---------------------------

!move.movetostation sollte man deswegen verwenden, weil damit relativ sichergestellt ist, da auch wirklich anzukommen.

Dadurch, das man das Movetostation( flytostation, !move.Jumptostation) mit in dem Ladeblock unterbringt, braucht man nur , wenn in der Station was nicht stimmt, eine neue Station finden, und wenn man eine gefunden hat, einfach nur zum label "Landinwhatever:" springen.

Exceptions sollte man auslagern. Eventuell kann man sie in weiteren Modulen gebrauchen. So wie man das übrigens mit allen immer wieder vorkommenden Programmteilen tun sollte (Sektorcheck, Refuelling, usw)

Dadurch kann man zum Beispiel eine "refueling" Routine bis zum Äußersten verbessern, und alle Scripte, die sie verwenden profitieren direkt davon.


b) Wurzel+Potenzfunktion von von ArcaJeth[D6a]

Wurzelfunktion:

Code: Select all

Arguments
1: Zahl , Var/Number , 'Zahl' 

001   $Ergebnis = 1
002   while 1
003    $Ergebnis.alt = ( $Ergebnis + ( $Zahl / $Ergebnis ) ) / 2
004    if $Ergebnis.alt == $Ergebnis
005     return $Ergebnis.alt
006    else
007     $Ergebnis = $Ergebnis.alt
008    end
009   end
010   return null
... nennt sich 'Heron-Verfahren' ... man muss aber eben beachten, dass X² nur Integerzahlen (also ohne Komma) kennt - daher wird die Wurzel am Ende gerundet ausgegeben ... aber es reicht IMO :)

Die Potenzfunktion sieht so aus: b^e also Basis hoch Exponent

=>

Code: Select all

Arguments:
basis, <Number>, Basis
exponent, <Number>, Exponent

i = 1
erg = basis
if exponent = 0
 return 1
else if exponent = 1
 return basis
end
while i < exponent
 erg = erg * basis
 inc i
end
return erg

c) Alle Schiffe/Stationen im Universum auflisten

von ticaki

Code: Select all

001   $ym = get max sectors in y direction
002   $xm = get max sectors in x direction
003   $x = 0
004   while $x < $xm
005    $y = 0
006    while $y < $ym
007     $Sector = get sector from universe index: x=$x, y=$y
008     $race = Player
009     $List =  find ship: sector=$Sector class or type=Ship race=$race flags=[Find.Multiple] refobj=null maxdist=9999999 maxnum=99999 refpos=null
010     $high =  size of array $List
011     $a = 0
012     while $a < $high
013      $Station = $List[$a]
014      $dummy = $Station -> install 1 units of BPH-Erweiterungskit MK1
015      skip if not $Station -> get amount of ware BPH-Erweiterungskit MK1 in cargo bay
016 @     START $Station -> call script 'TiCaKi.BPHE.Command.Standard' : 
017      inc $a = 
018     end
019     inc $y = 
020    end
021    inc $x = 
022   end
023   return null
Anstatt Find Ship nimmst du Find Station und alles bis auf das inc in der nächsten Whileschleife löschen und eigene Funktionen einfügen. Ist mein universal Einfügescript, lass dich nicht durch die Station bezeichnung täuschen da oben sind deine Schiffe drin :wink:

von ArcaJeth[D6a]

Code: Select all

001   * Station.list - Array  das  am  Ende  wieder uebergeben  wird
002   $Stations.list =  array alloc: size=0
003   $Universe.maxX = get max sectors in x direction
004   $Universe.maxY = get max sectors in y direction
005   
006   * Schleifen zum Durchlaufen aller Sektoren
007   $Universe.y = 0
008   while $Universe.y < $Universe.maxY
009    $Universe.x = 0
010    while $Universe.x < $Universe.maxX
011     
012   * Pruefen ob  Sektor bei Universe.x, Universe.y  existriert
013     $Universe.sector = get sector from universe index: x=$Universe.x, y=$Universe.y
014     if $Universe.sector != null
015   * Sektor existiert - alle Stationen suchen
016      $Stations.result =  find station: sector=$Universe.sector class or type=null race=$par.race flags=[Find.Multiple] refobj=null maxdist=null maxnum=1000 refpos=null
017      $Stations.result.size =  size of array $Stations.result
018   * Gefundene  Stationen an Stations.list anhaengen
019      $tmp.i = 0
020      while $tmp.i < $Stations.result.size
021       $Stations.result.tmp = $Stations.result[$tmp.i]
022       append $Stations.result.tmp to array $Stations.list
023       inc $tmp.i = 
024      end
025      
026     end
027     
028     inc $Universe.x = 
029    end
030    inc $Universe.y = 
031   end
032   return $Stations.list
... ich hatte mir mal das Script hier geschrieben, das gibt einen Array zurück, in dem alle Stationen der $par.race sind ... da wird in Zeile 16 auch das find.multiple genutzt und klappt wunderbar


d) Inhalte von Arrays ausgeben von SpaceTycoon

Man möchte gerne mal die Inhalte eines Arrays wissen.
Folgendes Script trägt in das Logbuch den Inhalt des Arrays ein ("null" im Log bedeutet dabei dann: der Indexwert hat keinen Inhalt):

Code: Select all

 
Script help.objektarrays.anzeigen 
Version: 1 
for Script Engine Version: 24 

Description 
Inhalte von ArrayVariablen ins Log 
Arguments 
1: ARRAY , Value , 'ArrayVariable' 
Source Text 

001    
002   $Spaces = '    ' 
003   $Size =  size of array $ARRAY 
004   $counter1 = 0 
005   while $counter1 < $Size 
006    $Value = $ARRAY[$counter1] 
007    $TempStore = $Value + $Spaces 
008    skip if $Message == null 
009     $Message = $Message + $TempStore 
010    skip if $Message != null 
011     $Message = $TempStore 
012    inc $counter1 = 
013   end 
014   send incoming message $Message to player: display it=[TRUE] 
015   return null 
Beipiel:
Ich erzeuge folgendes Array:

Code: Select all

008   $GateN = $sector -> get north warp gate
009   $GateS = $sector -> get south warp gate
010   $GateE = $sector -> get east warp gate
011   $GateW = $sector -> get west warp gate
012   $AllGates =  array alloc: size=4
013   insert $GateN into array $AllGates at index 0
014   insert $GateS into array $AllGates at index 1
015   insert $GateE into array $AllGates at index 2
016   insert $GateW into array $AllGates at index 3
Was steht aber denn nun drin im Array?
Innerhalb eines Scripts das obige Hilfsscript wie folgt aufrufen:

Code: Select all

@  = [THIS] -> call script help.objektarrays.anzeigen' :  ArrayVariable angeben=$AllGates
und im Logbuch stehen die Werte aus dem Array. Genauso kann man das Array einer gewählten Sektorposition (wird mit Koordinaten und Sektorname in ein Array geschrieben) angeben, etc.


---------Zur weiteren Verwendung------------
1.016 <RefObj> connect ship command/signal <Object Command/Signal> to script <Script Name> with prio <Var/Number>
1.016 <RefObj> connect ship command/signal x to script y with prio 10
für x zB "unterattack", dann wird bei einem Angriff das Script y ausgeführt
Last edited by jnrk on Thu, 29. Apr 04, 21:31, edited 6 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Post by jnrk » Thu, 25. Mar 04, 18:00

Von ArcaJeth[D6a] :

... die ganzen Waren sind in Maintypes Kategorisiert
8 Waffen
9 Schilde
10 Raketen
11 Waren Stufe 0 (Energiezellen)
12 Waren mit denen man nicht handeln kann es aber wahrscheinlich in SB-Missionen gibt
13 Waren Stufe 1 (benötigen Stufe 0 zur Herstellung)
14 Waren Stufe 2 (Benötigen 0 & 1)
15 Mineralien
16 Erweiterungen aber auch z.B. Kristalle, Quantumröhren ...

... ab Maintype 16 Subtype 11 sind nur die Erweiterungen die man in ein Schiff einbauen kann

... wie gewünscht hier mal die Liste der Waren, geordnet nach Main & Subtype

Code: Select all

Maintype Subtype Ware 
8 0 Alpha Impulsstrahlen-Emitter 
8 1 Beta Impulsstrahlen-Emitter 
8 2 Gamma Impulsstrahlen-Emitter 
8 3 Alpha Partikelbeschleunigerkanone 
8 4 Beta Partikelbeschleunigerkanone 
8 5 Gamma Partikelbeschleunigerkanone 
8 6 Alpha Energieplasma-Werfer 
8 7 Beta Energieplasma-Werfer 
8 8 Gamma Energieplasma-Werfer 
8 9 Alpha Schockwellen Generator 
8 10 Beta Schockwellen Generator 
8 11 Gamma Schockwellen Generator 
8 12 Mobiles Bohrsystem 
8 13 Unbekanntes Objekt 
8 14 Unbekanntes Objekt 
8 15 Unbekanntes Objekt 
8 16 Projektilkanone 
8 17 Ionen-Disruptor 
8 18 Alpha Photonenimpulskanone 
8 19 Beta Photonenimpulskanone 
8 20 Gamma Photonenimpulskanone 
8 21 Geschützturmlaser 
8 22 Gamma Kyonen Emitter 
8 23 Unbekanntes Objekt 
9 0 1 MW Schild 
9 1 5 MW Schild 
9 2 25 MW Schild 
9 3 125 MW Schild 
10 0 Moskito 
10 1 Wespe 
10 2 Libelle 
10 3 Hummel 
10 4 Hornisse 
10 5 Unbekanntes Objekt 
10 7 Unbekanntes Objekt 
11 0 Energiezellen 
12 0 Wasser 
12 1 Artefakte 
12 2 Kunstdünger 
12 3 Mikroorganismen 
12 4 Kartographie-Chips 
12 5 Bauausrüstung 
12 6 Antriebselemente 
12 7 Unterhaltungs-Chips 
12 8 Nahrungsmittelrationen 
12 9 Militärische Handfeuerwaffen 
12 10 Luxus-Nahrungsmittel 
12 11 Medizinische Ausrüstung 
12 12 Bergbau-Ausrüstung 
12 13 Nividium 
12 14 Radioaktiver Abfall 
12 15 Teladianiumplatten 
12 16 Waffenkopplungs-Chip 
12 17 Drogen 
12 18 Nervenimplantate 
12 19 Raumfliegeneier 
12 20 Handfeuerwaffen der Piraten 
12 21 Hackerchips 
12 22 Militärisches Personal 
12 23 Passagiere 
12 24 Prominente Persönlichkeiten 
13 0 Delexianischer Weizen 
13 1 Argnufleisch 
13 2 Plankton 
13 3 BoGas 
13 4 Scruffinknollen 
13 5 Cheltfleisch 
13 6 Sojabohnen 
13 7 Maja Schnecken 
13 8 Sonnenblumen 
13 9 Teladianium 
13 10 Sumpfpflanzen 
14 0 Stoff-Rheime 
14 1 Cahoona Fleischblöcke 
14 2 Raumsprit 
14 3 Stott-Gewürze 
14 4 BoFu 
14 5 Massom-Puder 
14 6 Rastar-Öl 
14 7 Majaglit 
14 8 Sojagrütze 
14 9 Nostropöl 
14 10 Raumkraut 
15 0 Erz 
15 1 Siliziumscheiben 
15 2 Nividium 
16 0 Gefechtsköpfe 
16 1 Kristalle 
16 2 Quantumröhren 
16 3 Mikrochips 
16 4 Computerkomponenten 
16 5 Raumfliegen 
16 6 Sklaven 
16 7 Navigationssatellit 
16 8 SQUASH Mine 
16 9 Geschützturm 
16 10 Kampfdrohne 
16 11 Bergungsversicherung 
16 13 Frachtscanner 
16 14 Handelscomputer Erweiterung 
16 16 Laderaumerweiterung 
16 17 Triebwerkstuning 
16 18 Ruder-Optimierung 
16 19 Landecomputer 
16 20 Ziel Projektions Erweiterung 
16 22 Digitales Sichtverbesserungssystem 
16 23 Singularitäts Zeitverzerrungsantrieb 
16 24 SINZA Boost Erweiterung 
16 25 Ekliptik Projektor 
16 26 Argon Polizeilizenz 
16 27 Boron Polizeilizenz 
16 28 Split Polizeilizenz 
16 29 Paraniden Polizeilizenz 
16 30 Teladi Polizeilizenz 
16 31 Datenspeicher 
16 32 Schnäppchen Finder 
16 33 Verkaufspreis Finder 
16 34 Transporter 
16 35 Sprungantrieb 
16 39 Lebenserhaltung für Frachtraum 
16 40 Boost Erweiterung 
16 41 Steuerdüsenerweiterung 
16 43 Kameradrohne 
16 44 Erweiterter Satellit 
16 45 Mineralien Kollektor 
16 46 Tarnvorrichtung 
16 49 Raumfliegen Fangvorrichtung 
16 50 Projektilkanone Munition 
16 51 Duplex Scanner 
16 52 Triplex Scanner 
16 53 Navigationssoftware MK1 
16 54 Handelssoftware MK1 
16 55 Handelssoftware MK2 
16 56 Kampfsoftware MK1 
16 57 Kampfsoftware MK2 
16 58 Spezialsoftware MK1 
16 71 Handelssoftware MK3 
Von SpaceTycoon:

Beispiel, wie man mit den Maintypes und Subtypes umgeht/umgehen kann...

Wenn ich ein Produkt mit der Liste aller Produkte abgleichen will, gibt es dafür nichts. Ich muß mir aus den Main- und Subtypes erst eine Produktliste 'basteln', die ich dann für Vergleichsoperationen heranziehen kann:

Code: Select all

010   * Figure out all products, write into array 
011   $AllProducts =  array alloc: size=0 
012   $No.Maintype = 17 
013   while $No.Maintype > 8 
014    dec $No.Maintype = 
015    $No.Subtype =  get number of subtypes of maintype $No.Maintype 
016    while $No.Subtype > 0 
017     dec $No.Subtype = 
018     $Product =  get ware from maintype $No.Maintype and subtype $No.Subtype 
019     skip if $Product == null 
020      append $Product to array $AllProducts 
021    end 
022   end 
Achtung: Durch die Verwendung von DEC ist die Liste verkehrt herum, also die letzte Ware steht am Anfang im Array, die erste Ware dann am Ende. Für Vergleiche ist das allerdings egal, in welcher Reihenfolge die Tabelle ist. Dieses große Array kann man sich mit dem oberen neuen Code dann auch wiederum komplett anzeigen lassen .
Last edited by jnrk on Wed, 28. Apr 04, 21:09, edited 3 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Post by jnrk » Thu, 25. Mar 04, 18:09

Farbigen Text im Logbuch / Nachricht von Arca

... farblich gehts nur wenn du das über eine Sprach-XML machst ...
Mit "\033R Text \033X" bekommst du den Text dann rot.
\033 + Farbcode:
B -> Blau
C -> Cyan
G -> Grün
M -> Magenta
R -> Rot
W -> Weiss
Y -> Geld
X -> Standard (bzw. Farbformat löschen)

PS: ohne XML ginge es sicher auch wenn man den \ in einen String bekommen könnte

sci wrote:Jeder der ein zusätzliches Ausrüstungsobjekt per script einbinden will muss dazu ein "Read-Text-Object" benutzen. Naja und ohne Modding muss man sich eines mit dem, für die neue Erweiterung passenden, Preis aussuchen. Damit ihr euch nicht dumm und dämlich sucht, hier als ganz ganz ganz kleine hilfe: die preislister in der version 1.3

Bitte die bereits durch bestimmte scripts belegten Objekte beachten!
Weitere infos dazu: http://www.egosoft.com/x2/forum/viewtopic.php?t=33680

...

392 = ReadText-17-5773
476 = ReadText-17-5763
1.572 = ReadText-17-5783
2.472 = ReadText-17-5793
7.944 = ReadText-17-5803
10.027 = ReadText-17-5813 GothicK *SDS Delivery*
38.996 = ReadText-17-5823 ticaki *?*
95.344 = ReadText-17-5833
118.336 = ReadText-17-5843
158.204 = ReadText-17-5853
995.124 = ReadText-17-5883 Mr.Milti *Return to Sender*
1.002.676 = ReadText-17-5753
1.845.524 = ReadText-17-5863 sci *Kampfsoftware MK3*
6.338.116 = ReadText-17-5913
9.110.824 = ReadText-17-5893
17.926.236 = ReadText-17-5903
54.228.224 = ReadText-17-5923
62.022.316 = ReadText-17-5933
188.877.700 = ReadText-17-5943

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

...

Post by jnrk » Tue, 20. Apr 04, 11:11

Sprachausgabe bei Stationswaren! von SpaceTycoon

ich bin nach langer Suche :gruebel: drauf gekommen, wie die Sprachausgabe (und parallele Textausgabe unten rechts im Bildschirm) bei Stationswaren funktioniert. :D

Anmerkung:
@Alle Autoren der Beiträge die das Einbinden von Scripten und Sprachdateien erklärten, sollten vielleicht Ihre Beiträge ergänzen/ändern. :wink:

Und so sieht das aus:

Bisher ist in allen Tutorials zu lesen, man solle die Sprachdateien 49xxxx.xml/44xxxx.xml im Verzeichnis \t so aufbauen (Beispiel für eine Schiffsausrüstung für 1572 Credits in einem Ausrüstungsdock):

Code: Select all

- <language id="49">
- <page id="17" title="Boardcomp. objects" descr="Produktname">
  <t id="5793">Irgendeine neue Schiffsausrüstung</t> 
  </page>
Nachdem ich die entpackte 490001.xml aus der 04.dat mal genauer unter die Lupe nahm ist mir aufgefallen:

Im Abschnitt Page ID 17 dieser Datei ist dort jede Ware aufgeführt, die in irgendeiner Fabrik zu kaufen ist. Einmal mit ihrer Bezeichnung, so wie man sie in der Fabrik/Dock in der Liste sieht und darunter mit nächst höherer Nummer steht der Text, welcher bei Markierung der Ware in Dock oder Fabrik vorgelesen wird und rechts unten erscheint.
Insofern: Wenn obiger Code in einer eigenen 49xxxx.xml wie folgt ergänzt wird:

Code: Select all

- <language id="49">
- <page id="17" title="Boardcomp. objects" descr="Produktname">
  <t id="5793">Irgendeine neue Schiffsausrüstung</t> 
  <t id="5794">{17,5665}</t> 
  </page>
bekommt man vom Computer per Sprachausgabe in der Fabrik/Dock den Text angesagt sowie unten rechts angezeigt, der in der Originaldatei 490001.xml bzw. 440001.xml unter Page ID 17, Text ID 5665 eingetragen ist. Text ID {17,5665} in 490001.xml ist übrigens (müßt nicht nachschauen):

Code: Select all

<t id="5665">Dies ist eine Softwareerweiterung für alle gängigen Schiffscomputer Modelle. Erweiterte Kommandos werden durch ihre Installation der Kommandokonsole eines Schiffs hinzugefügt.</t> 
Würde man in seiner eigenen Sprachdatei 49xxxx.xml unter Page ID 17 Boardcomp. objects statt der im obigen Beispiel zu sehenden
<t id="5794">{17,5665}</t>
die Nummer {17,9002} eintragen, käme in der Fabrik bei Markierung der Ware zum Beispiel der Text und die Sprachausgabe

Code: Select all

<t id="9002">Über dieses Objekt sind in der Datenbank des Bordcomputers keine Daten verfügbar.</t> 
D.h. - Sprachausgabe innerhalb einer Fabrik bei Warenein-/verkauf wird über die Sprachdatei im \t-Verzeichnis gesteuert - nicht im Scriptcode.
Die obige Nummer 5794 gibt es übrigens im ganzen X2-Programm nicht. Ich hab sie einfach "erfunden". Da in der originalen "490001.xml" der Sprachtext immer eine Nummer höher ist als die Nummer der Warenbezeichnung, habe ich das in der eigenen Sprachdatei (sh. obiges Beispiel) einfach mal genauso gemacht - und siehe da - es klappt. Das heißt, alle freien Artikelnummern von 17-57xx bis 17-59xx können mit einer vorhandenen Sprachausgabe aus der 490001.xml belegt werden, wenn man dafür einfach so vorgeht wie oben zu sehen.

-------------------------------

Und vielleicht noch zur Ergänzung, wie man passend zur üblichen "Verhaltensweise" von X2 einen Logbucheintrag gestalten sollte:

Code: Select all

001   play sample 1008
002  *Spielt das "Jingle" vor/bei Ansage "Eingehende Nachricht"
003  wait 500
004  * etwas Warten schadet bei Audiosachen nie sonst überschlägt sichs
005
006  play sample: incoming transmission [IncomingTransmission.Message], from object null
007  * Spricht eine von vier möglichen Sprachausgaben, die unter den
008  * Systemkonstanten (Select Constant - "Incoming..." aufgeführt sind
009  * in diesem Fall: "Eingehende Nachricht"
010
011   $nachricht = sprintf: pageid={DeineID} textid={DeineID}, [THIS], [ENVIRONMENT], null, null, null
012  * Die Nachricht, die aus Deinem Sprachfile 49xxxx.xml gelesen wird
013
014   send incoming message $nachricht to player: display it=[TRUE]
015  * Eintrag ins Log und gleichzeitige Anzeige
So läuft eine Lognachricht von einem Schiff an den Player genauso ab, wie es im Programm normal und üblich ist (abgesehen von der sofortigen Anzeige "display it=True").

Um die Sache komplett zu machen, hier die Textzeile, die in obiger Codezeile 11 aus der Sprachdatei im \t-Verzeichnis gelesen wird:

Code: Select all

<t id="1001">[author] Schiff [b]%s[/b][/author][text colwidth='500'][b]Ziel %s erreicht![/b] ...gehe in Bereitschaft...[/text]</t>
Das erste "%s" wird in der Nachricht durch [This] ersetzt, das zweite durch [Environment] und die b /b in eckigen Klammern schalten gelbe Schrift für den darin eingefaßten Textteil an bzw. aus.

Ergänzung von ArcaJeth[D6a]
So läuft eine Lognachricht von einem Schiff an den Player genauso ab, wie es im Programm normal und üblich ist (abgesehen von der sofortigen Anzeige "display it=True").
... dazu braucht man eigentlich auch nur das "send incoming message $nachricht to player: display it=[FLASE]" ... da kommt das "Palingpaling ... Eingehende Nachricht" und auch das kleine Symbol blinkt :) ... mit "display it=[TRUE]" kommt zwar keine akustische Meldung jedoch sieht man das ja ;)


Tinte/Toner sparen von SpaceTycoon

Hier hab ich dann noch ne' Kleinigkeit:
Wen hat es nicht schon angek***t wieviel Tinte/Toner durch den Ausdruck eines Scriptes verbraucht wird?
Daher hier noch eine geänderte x2script.xsl mit der das DRUCKEN von Scripten mehr Freude macht:
X2script.xsl zum Drucken von Scripten
Handhabung:
Die originale x2script.xsl im Ordner Scripts umbenennen. Dann diese Datei hineinkopieren. Man kann sie auch dauerhaft verwenden, hat keinen Einfluß auf das Scripten oder die Spielfunktion. Und man kann endlich Scripte auch ohne Horrorverbrauch an Tinte/Toner ausdrucken.
Last edited by jnrk on Thu, 29. Apr 04, 21:34, edited 2 times in total.

jnrk
Posts: 231
Joined: Thu, 11. Mar 04, 13:00
x2

Post by jnrk » Tue, 20. Apr 04, 11:11

Diskussionen zu diesem Tutorial nur hier - Danke

Autoren, Beiträge, Codeschnipsel...zu mir...

ticaki
Posts: 4585
Joined: Wed, 6. Nov 02, 21:31
x3

Post by ticaki » Sun, 3. Oct 04, 22:42

bis zu X² - Die Rückkehr können wir den wohl abhängen... ist ja in der Linkliste :)

Gruß ticaki

P.S. und ich öffne ihn für entweilige Erweiterungen :)
Zur Zeit nicht aktiv

omegasnow
Posts: 32
Joined: Tue, 3. Jan 06, 15:37
x3

Post by omegasnow » Wed, 11. Jan 06, 16:43

Wie wärs mit ner PDF Version :D

User avatar
Samuel Creshal
Posts: 4327
Joined: Sat, 6. Mar 04, 17:38
x3tc

Post by Samuel Creshal » Wed, 11. Jan 06, 17:48

Wenn jnrk nochg da und damit einverstanden ist kann ich das gerne machen... :)

Post Reply

Return to “X²: Die Bedrohung - Scripts und Modding”