Scripting: Einstieg

  • Diese Anleitung habe ich für die Modding-University im TWZ geschrieben, sie mag deswegen an manchen Stellen etwas komisch formuliert klingen.
    Nichtsdestotrotz erlernt man hiermit DIE Grundlagen, die man für das Scripten braucht.


    Proseminar Scripting: Der Einstieg


    Benötigte Dateien und Programme, bitte herunterladen:


    Notepad++
    Retrofit
    Docudemons
    Script-Sammlung


    (Durchgestrichenes nicht unbedingt nötig bei Tutorial-Form dieser Anleitung)


    Gebräuchliche Abkürzungen/Namen:


    EDB: export_descr_buildings; die Datei für die Gebäude
    EDA: export_descr_ancillaries; die Datei für Ancillaries
    EDU: export_descr_units; die Datei für die Einheiten
    EDCT: export_descr_character_traits; die Datei für Traits
    Vanilla: Ungemoddetes Medieval II
    GTW: Gothic Total War; das Hauptprojekt an dem ich scripte, werde ich vermutlich des öfteren als Beispiel hernehmen


    Zuerst einmal zu den Programmen die man braucht. Beim Scripten wird eigentlich nur ein einziges Programm benötigt oder würde ausreichen, der Standard-Texteditor von Windows.
    Dieser lässt aber stark zu wünschen übrig, ist umständlich zu handhaben, unkomfortabel und es gibt auch noch weitaus bessere alternativen. Deswegen:


    Notepad++: Dieser Texteditor mag erstmal erschlagend sein (verglichen mit dem Standard-Editor) wenn man die ganzen Buttons und Möglichkeiten in der oberen Zeile sieht. Doch was braucht man davon? Speichern und Alle Speichern, mehr nicht.
    Notepad bietet eine Tab-Funktion, die bei vielen Arbeiten mit den Scripts, aber auch allgemein beim Modden, eine unheimlich praktische Sache ist, so muss man nicht umständlich mit tausenden Fenstern sich rumärgern, sondern hat alles in einem Programmfenster praktisch zur Verfügung.
    Daneben hat man auch unter Datei eine Auflistung aller bisher aufgerufener Dateien (bis zu 20 Stück), er zeigt einem direkt die Zeilennummer an, die Suchen-Funktion ist deutlich komfortabler und Suchen+Ersetzen ist auch sehr anwenderfreundlich.
    In meinen Augen DAS Programm, das verhindert hat, dass ich mit dem Scripten aufhöre nachdem mich der Editor immer wieder und wieder frustriert hat.


    Retrofit: Die Grundmod schlechthin, die meißten Modifikationen bauen auf dieser Mod auf, denn sie bietet nicht nur einen praktischen Modfolder mit den meißten Dateien, die man zu Anfang braucht, sondern auch ein gebalanctes Medieval II Vanilla.
    Ich bitte jeden diese Mod zu installieren, wir werden hierdran unsere Scripte austesten.


    Docudemons: Die wichtigste Datei für jeden Scripter. Hier steht alles wichtige drin, von Events, Conditions und Commands über die Limits und Maximas, bis hin zu Erklärungen von Einstellungen die man in der cfg machen kann, Gebäudeeigenschaften, Charaktereigenschaften, Console Commands und so weiter und so weiter.
    Absolut essentiell und wenn man weiß, wie man damit umzugehen hat, eine reine Goldgrube.


    Scriptsammlung: Zuletzt noch, was mir in meiner Anfangszeit sehr geholfen hat: Der Blick in andere Scripte, hauptsächlich welche, von denen ich die Mod selbst gut kannte. Das hilft ungemein, wenn man sich anschaut wie es dort gemacht wurde und daraus lernt.
    Völlig falsche Wege beschreitet hier der, der nun auf die Idee kommt einfach Scripte zu kopieren, sich die Arbeit zu sparen und den Ruhm anderer einzuheimsen. Lerneffekt gleich 0, Fehlerhaft und nicht wirklich angebracht.
    Der Blick in andere Scripte dient nur dazu, um zu lernen an Beispielen. Wenn man etwa nicht weiß wie eine Condition verwendet wird oder genau geschrieben wird, sucht man in anderen Scripten wie genau das geschrieben wird.
    Will man etwas ähnliches wie in einer anderen Mod machen, schaut man sich an wie es gemacht wurde.
    Gerade zu Beginn ist das sehr hilfreich, hierfür kann man sich am besten eine kleine Kollektion an Scripten anlegen, ich hab zB. sehr häufig das Script von dhRR genutzt, hier finden sich häufige Verwendungen von recht komplexen Scripten.


    Wenn ihr dann alle diese Sachen habt - und euch vielleicht auch mal darin umgeschaut habt und die Funktionen ausprobiert habt - kommen wir nun zum Script.


    Geht dazu nach:
    \mods\retrofit\data\world\maps\campaign\imperial_campaign
    Und öffnet die Datei campaign_script.txt.
    Willkommen! Eurer Arbeitsplatz.


    Und jetzt: Strg+A und dann Entfernen drücken.
    Das Vanilla-Kampagnenscript hat kaum Ordnung, wirkt unübersichtlich und ist für uns unwichtig, wir werden ein neues Script erschaffen.
    Zuerst einmal ist das wichtigste im Script eine Ordnung und Übersichtlichkeit, wenn einmal eure Scripte auf Größen von 10.000-20.000 Zeilen anwachsen oder darüber hinaus, dann ist eine gewisse Ordnung lebenswichtig, sonst findet man rein gar nichts wieder.
    Deswegen legen wir zuerst ein Inhaltsverzeichnis an und hierzu gleich eine wichtige Info: Mit dem Semikolon; deaktiviert man im Script (und auch in manchen anderen Datein von M2) alles folgende in dieser Zeile.
    Wenn man also ein bestimmtes Command oder eine Condition deaktivieren will, nutzt man ; , auch wenn man eine Ordnung anlegt, wird genau das benutzt.


    So kann man hiermit logische Einteilungen schaffen innerhalb des Scripts und verschiedene Sachen voneinander abgrenzen. Hier ein Beispiel aus GTW:




    Ganz neue Scriptabschnitte, mit Überschrift:


    [spoil]

    Code
    ;#############################################################################################################################
    ;##########################  II. 12 Runden pro Jahr ##########################################################################
    ;#############################################################################################################################


    Unterteilungen innerhalb eines Abschnittes:


    Code
    ;########################### Provinzen Endeckt -> Nordmar ##########################################################################################


    Oder:


    Code
    ;------------------------------------------- Abgelehnt


    [/spoil]


    Gerade bei größeren und komplexeren Scripten ist es ziemlich wichtig eine gewisse Ordnung zu wahren, so kann man auch schnell etwas wiederfinden/verändern/anpassen oder verbessern.
    Wenn das Script anwächst und immer neue Abschnitte hinzukommen, sollte man wissen wo was ist und es schnell wiederfinden können.
    Aus diesem Grund sollte man am Anfang des Scriptes ein Inhaltsverzeichnis anlegen, das kann so aussehen:



    [spoil]


    [/spoil]


    Man sollte natürlich dann in den Überschriften der Scriptabschnitte die exakte Bezeichnung und richtige römische Ziffer verwenden, wie man sie auch im Inhaltsverzeichnis selbst gewählt hat.
    Hält man sich daran, hat man immer eine wunderbare Ordnung in seinem Script und diese ist wichtig für das saubere und exakte arbeiten, was nötig ist beim Scripten.



    Nachdem diese Grundaspekte nun durch sind, kommen wir zu wichtigen Dingen.
    Zu ganz oberst eures Scriptes muss immer stehen (Davor werden keine Scripts gelesen):


    Code
    script


    Immer am Ende des Scriptes (Danach darf nichts mehr kommen)


    Code
    wait_monitors
    end_script


    Beides steht einmal zu Anfang, bzw. zu Ende des Scriptes.


    Nun kommen wir zum Standard-Mäßigen Aufbau eines Scriptes, dieser ist in der Regel immer gleich, aber wichtig, also Aufpassen (!):


    Event -> Wann wird es abgeprüft?
    Conditions -> Was wird abgeprüft/Was muss gegeben sein?
    Commands -> Was passiert dann?


    Das sind die drei Grundaspekte, auch zu finden in den Docudemons (Die ersten drei Excel-Tabellen-Blätter).


    Ein jedes Script besteht aus einem "monitor". Dieser wird immer gestartet mit:
    monitor_event
    monitor_conditions


    monitor_conditions sind für den Anfänger die beste Wahl, dieser Monitor benötigt kein Event, er prüft alle Events ab, d.h. wenn die Runde startet, wenn die Runde endet, wenn man einen Charakter anklickt, bevor die Runde startet usw., die Liste der Events ist recht lang, auch wenn man hauptsächlich nur ein paar immer wieder braucht und der Rest nur sehr selten zum Einsatz kommt. Auf jeden Fall wird mit monitor_conditions im Prinzip die ganze Zeit geprüft ob die Conditions eintreten, praktisch, da man kein Event braucht, aber unheimlich resourcenfressend und verlangsamend, Scripter die häufig hiermit arbeiten sorgen immer für eine längere Rundenberechnung. Deswegen sollte man von der Verwendung absehen (Oder zumindest auf ein Minimum beschränken)


    monitor_event ist die deutlich bessere Wahl. Ein monitor_event erfordert immer ein Event, was der maßgebliche Unterschied zu monitor_conditions ist. Nichtsdestotrotz sollte dieser Art des Monitors immer die erste Wahl sein und am besten ausschließlich Verwendung finden. Nach monitor_event folgt immer direkt das jeweiligeEvent, also wann das Script abgeprüft werden soll, dass sieht dann so aus:
    monitor_event FactionTurnStart


    Die wichtigsten Events sind:
    FactionTurnStart -> Rundenstart einer Fraktion (Fraktion per Condition evt. gegeben, ansonsten 1. Fraktion)
    FactionTurnEnd -> Das selbe, nur zum Ende der Runde einer Fraktion
    PreFactionTurnStart -> Direkt vor dem Start der Runde einer Fraktion (Fraktion per Condition evt. gegeben, ansonsten 1. Fraktion)


    Das sind eigentlich die drei allgemeinen, die am häufigsten vorkommen. Bei GTW zB. 227x FactionTurnStart, 166x bei Third Age, 111x bei HRR 0.7 und 100x bei DLV.
    Daneben gibt es natürlich noch viele weitere, diese entnehmt ihr am besten den Docudemons.
    Hierfür eine kurze Erklärung: Öffnet die Ultimate Docudemons 4.0 und öffnet das Tabellenblatt "Events". Da wir uns nicht mit Schlacht-Scripte beschäftigen, sind die meißten die was mit "battle" zu tun haben unwichtig für uns.


    Identifier: FactionTurnEnd -> Der exakte Name des Events.
    Event: A Faction has ended its turn -> Kurze Beschreibung, nützlich
    Exports: faction -> Wichtig! Welche Infos kann man damit abprüfen lassen, nicht immer ganz einfach, hier können nur Fraktionsrelevante Dinge abgeprüft werden, etwa ob die Fraktion von der KI gesteuert wird, ob es Fraktion X ist und so weiter. Mit der Zeit weiß man welches Event man in Verbindung mit welchen Conditions nehmen kann.
    Class: ET_FACTION_TURN_END -> Unwichtig für uns


    Nach dem Start des Monitors und des Events folgen die Conditions, also die Bedingungen für das Auslösen des Scripts.
    Hierfür gibt es sehr viele verschiedene Möglichkeiten, die meißten benötigen auch noch unterschiedliche Parameter, seien es Zahlen oder konkrete Angaben oder Verweise auf Fraktionen.
    Ruft bitte wieder die Docudemons auf und schaut eucht die Seite Conditions an. Battleconditions sind wieder einmal ziemlich unwichtig. (Machen einen ziemlich großen Teil der Conditions aus... also relativ weit runterscrollen). Es existieren sehr, sehr viele verschiedene Conditions, doch ähnlich wie bei den Events, braucht man wirklich beim Arbeiten nur einen Bruchteil, der Rest wird entweder nie zum Einsatz kommen, oder ganz sporadisch bei speziellen Dingen verwendet.
    Schauen wir uns mal einen Eintrag an:


    Die einfachste Condition:


    Identifier: I_TurnNumber -> der genaue Name
    Trigger requirements: -> Hier wird keine genaue Angabe benötigt, bei anderen Conditions aber schon, etwa die region_id
    Parameters: logic token, turn number -> Welchen Parameter man angeben muss, hier die jeweilige Rundennummer
    Sample use: I_TurnNumber > 50 -> Beispiel für die Verwendung
    Description: The current turn number (starts at 0) -> Beschreibung
    Battle or Strat: Either
    Class: TURN_NUMBER


    Man kann so viele Conditions nach dem Start des Monitors und des Events machen, wie man möchte.
    Die erste Condition kommt direkt nach dem Event, weitere Conditions werden mit "and" in der jeweils nächsten Zeile drangehängt. Man kann auch die Negation einer Condition als Bedingung machen, dann benutzt man "not".
    Beispiel:


    monitor_event FactionTurnStart I_TurnNumber = 4
    and I_SettlementOwner Khorinis = hre
    and not I_LocalFaction hre



    Nun kommen wir zu den Commands, also dem, was das Scipt auslöst, sobald die Conditions erfüllt sind, etwa das Spawnen einer Armee, das hinzufügen von Gold, das Töten eines Charakters, die Erstellung eines Gebäudes...
    Wie schon zuvor öffnet ihr erstmal die Docudemons und schaut euch die Seite Commands an.
    Hier ein Beispiel:


    Identifier: set_kings_purse
    Parameters: faction, amount
    Description: Changes the money granted by the king's purse.
    Sample use: set_kings_purse England 40000
    Class: SET_KINGS_PURSE


    Sollte mittlerweile selbsterklärend sein.
    Ein Monitor kann nebenbei bemerkt beliebig viele Commands haben.


    Um ein Monitor (und damit das jeweilige Script) abzuschließen kommt am Ende immer:
    terminate_monitor
    end_monitor


    end_monitor muss vorhanden sein, lässt man das weg oder vergisst es, wird das gesamte Script nicht mehr ausgelesen, ist also nicht funktionsfähig.
    terminate_monitor sorgt dafür, dass das Script nur einmal ausgeführt wird. Wenn man zB. eine bestimmte Runde als Bedingung festlegt, macht es keinen Sinn terminate_monitor wegzulassen, wenn man aber zB. abprüft, ob Fraktion X Stadt Y hält, kann man terminate_monitor weglassen, wenn man etwa mit einbeziehen will, dass Fraktion X die Stadt zwar verlieren kann, aber ja auch immer wieder zurückerobern könnte.


    Zusammenfassend nochmal ein Beispiel, dass alle aufgeführten Dinge beinhaltet:


    monitor_event, Event, Conditions (and/not)/(Parameter), Commands (Parameter) und Abschluss.


    monitor_event FactionTurnStart I_TurnNumber = 209
    and I_SettlementOwner Wolfsclan = denmark
    and not I_LocalFaction denmark
    historic_event hetzer_wolfsclan
    console_command add_population Wolfsclan, -700
    terminate_monitor
    end_monitor


    Alle Monitore/Scripte sind genau so oder mit Abwandlungen aufgebaut wie das Beispiel hierdrüber.


    Damit nähern wir uns auch schon dem Ende des Tutorials.
    Zuletzt noch ein paar nützliche Kleinigkeiten für eurer Script und eure Arbeit damit und das Testen in der Mod (Was gerade zu Beginn einen beträchtlichen Teil eurer Arbeit ausmachen wird ;) :(
    Fügt am besten dies einfach direkt oben ein (Nach "script" natürlich!)



    restrict_strat_radar false -> Entfernen des "Amerika-Radarmap-Balkens"
    console_command toggle_perfect_spy -> Ihr seht immer genau was die KI hat, als ob ihr einen Spion in der Stadt/Armee hättet und das überall.
    console_command toggle_fow -> Kein schwarzer und grauer Nebel, ihr seht alles
    console_command show_cursorstat -> benutzt man häufig, startet man die Mod, öffnet mit ö die Konsole und drückt die Pfeil-Hoch-Taste hat man sofort diesen Befehl und braucht ihn nicht eintippen. Für die ganz Faulen.


    Man braucht übrigens hierfür keinen monitor starten (und somit auch nicht beenden). Wenn man das weglässt, wird einfach zu Beginn einer Kampagne einmalig das Script ausgeführt.
    Diese Befehle sind nur zum Testen und bei der Entwicklung der Mod drinnen, danach verschwinden sie natürlich wieder.


    Ende. :wink:

  • Deswegen legen wir zuerst ein Inhaltsverzeichnis an und hierzu gleich eine wichtige Info: Mit dem Semikolon; deaktiviert man im Script (und auch in manchen anderen Datein von M2) alles folgende in dieser Zeile.
    Wenn man also ein bestimmtes Command oder eine Condition deaktivieren will, nutzt man ; , auch wenn man eine Ordnung anlegt, wird genau das benutzt.


    Ist zwar nebensächlich, aber was man mit dem ; erreicht wird ist folgendes: Der Parser erkennt anhand dieses ";", dass die Zeile bzw. Anweisung abgeschlossen ist und springt somit in die nächste Zeile. Alles was folgt ignoriert er folglich. Alles was er so ignoriert, also hinter dem ";" steht bezeichnet man gemeinhin als "Kommentar".


    Und wenn wir schon beim Thema "Ordnung" sind. Eine Konsole öffnet sich per default exakt 80 Zeichen breit, weshalb man nach üblicherweise nach 80 Zeichen einen Zeilenumbruch im Code macht. Auch Kommentar wie


    Code
    ;#############################################################################################################################
    ;##########################  II. 12 Runden pro Jahr ##########################################################################
    ;#############################################################################################################################


    macht man in der Regel 80 Zeichen breit

    "I think there is a profound and enduring beauty in simplicity. In clarity. In Efficiency.
    True simplicity is derived from so much more than the absence of clutter and ornamentation.
    It's about bringing order to complexity."


    Jony Ive

  • Danke für die Info, immer schön die Hintergründe mal zu erfahren :)


    Zitat


    Und wenn wir schon beim Thema "Ordnung" sind. Eine Konsole öffnet sich per default exakt 80 Zeichen breit, weshalb man nach üblicherweise nach 80 Zeichen einen Zeilenumbruch im Code macht.

    Ich habe nie Auswirkungen festellen können wenn das überschritten wird. Oder sind diese eher unscheinbar (bzw. überhaupt existent)?
    Ist es relevant für das Script?

  • Danke für die Info, immer schön die Hintergründe mal zu erfahren :)


    Ich habe nie Auswirkungen festellen können wenn das überschritten wird. Oder sind diese eher unscheinbar (bzw. überhaupt existent)?
    Ist es relevant für das Script?


    Er stellt dann in der Konsole einen Zeilenumbruch dar, auf das Skript selbst hat es aber keine Auswirkung. Rein kosmetischer Natur ;) (die aber enorm wichtig ist, wenn man damit arbeiten muss)
    Es ist einfach schöner zu lesen, wenn der Verfasser diese Grenze im Hinterkopf gehabt hat und in der Konsole alles ordentlich formatiert ist. Für den Parser, der dann den Code liest, ist im Prinzip eh alles nur eine Zeile

    "I think there is a profound and enduring beauty in simplicity. In clarity. In Efficiency.
    True simplicity is derived from so much more than the absence of clutter and ornamentation.
    It's about bringing order to complexity."


    Jony Ive

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!