Grundlegende Scriptelemente

Abstrakt gesehen beruht jedes Script auf drei Dingen: Ereignisse, Bedingungen und vom Script ausgeführte Aktionen. Beispiele:

  • Ereignis
    • Die Karte wurde gestartet
    • Es ist eine Sekunde vergangen
    • Ein Briefing wurde beendet
    • Ein Tribut wurde bezahlt
  • Bedingung
    • Ist Dario bei der Brücke?
    • Existiert die Burg des Spielers noch?
    • Hat der Spieler 3 Kanonen gebaut?
  • Aktion:
    • Tor öffnen
    • Armee erstellen
    • Wetter verändern
    • Auftrag erstellen


Mit dem Script möchte man ja bestimmte Aktionen auf der Karte ausführen. Meistens sollen diese nicht alle sofort ausgeführt werden, sondern nur nach bestimmten Ereignissen und/oder unter bestimmten Bedingungen. Aktionen können nur ausgeführt werden, nachdem ein Ereignis eingetreten ist, denn nur Ereignisse führen Scriptcode aus.
Das bekannteste Ereignis dürfte der Start der Karte sein. Durch dieses Ereignis wird (auf Einzelspielerkarten) die Funktion FirstMapAction() ausgeführt. Hier führt man normalerweise die Aktionen aus, die sofort und unbedingt stattfinden sollen, beispielsweise die Erstellung von Armeen für den Computergegner oder den Start eines Briefings.

Nach diesem Ereignis wird nie wieder eine Funktion im Script ausgeführt, es sei denn, man legt fest, daß das Script bei bestimmten Ereignissen aufgerufen werden soll. Um also im weiteren Spielverlauf noch Aktionen ausführen zu können, muss man festlegen, daß das Script über weitere Ereignisse informiert werden soll. Hierzu kann man eine beliebige selbstgeschriebene Funktion angeben, die bei einem bestimmten Ereignis ausgeführt werden soll. Sehr oft wird hierbei das Ereignis “Es ist eine Sekunde vergangen” gewählt. Nun möchte man natürlich nicht jede Sekunde eine Aktion ausführen, wie zum Beispiel die Öffnung eines Tores.
Hier kommen die Bedingungen ins Spiel. Wenn das Ereignis “Es ist eine Sekunde vergangen” eintritt, prüft man beispielsweise zunächst die Bedingung “Hat der Spieler 3 Kanonen gebaut?”. Ist diese Bedingung erfüllt, führt man die Aktion “Tor öffnen” aus.

Es gibt also, wie einige es vielleicht von anderen Scripten gewohnt sind, keine festen Vorgaben wie “Dies muss hierhin geschrieben werden, und wenn man ABC machen will muss das genau zwischen GH und IJ”. Dies mag zu Anfang vielleicht ein wenig verwirren sein, bietet dem Scripter auch später eine sehr hohe Handlungsfreiheit.

Ein umfassendes Tutorial

In dieser Datei befindet sich ein umfangreiches, gut verständliches Tutorial für Einsteiger als PDF, welches die Erstellung eines Scriptes für eine Karte anhand der Karte Viertelland demonstriert. Die Karte, sowie die benötigten Scripte mit altem und neuen (Kurz-)Briefingstil sind im Download enthalten. Wer also erstmal einen geführten Einstieg haben (oder einfach nur schnell die erste “eigene” Karte erstellen) möchte, kann dieses Tutorial durcharbeiten.

WICHTIG! Bitte installiert euch die Map aus dem zip-file da diese das bereinigte Script im altem Stil enthält so kann es nicht zu Verwirrungen kommen sollte sich jemand das Script direkt in der Map anschauen. Bei der Viertelland Map auf der Mapbase ist noch das unbereinigte Script enthalten.

Falls es Verbesserungsvorschläge gibt: Das Tutorial wurde mit OpenOffice erstellt. Die entsprechende Datei, aus der das PDF erzeugt wurde, liegt vor. Bei Änderungsvorschlägen und Anregungen zu Verbesserung dieses Tutorials wendet euch bitte an die Ersteller. Der einfachste und schnellste Weg ist: schreibt euren Änderungstext oder Verbesserungsvorschlag per Persönlicher Nachricht an ninobi oderpewe, es wird dann entsprechend geändert.

Das Standardscript

Mit der Erstellung einer Map wird ein Script generiert, welcher alle grundlegend benötigten Script-Bestandteile enthält. Belasst die Einteilung, wie sie ist. Die Abarbeitung ist auf den vorhandenen Aufbau ausgelegt.

Die Script-Bestandteile

-- Include main function

Über die beiden vorhandenen Zeilen ist die grundlegende Funktionalität für jede Map und für jeden User-Script eingebunden.
Darunter könnt Ihr ausgelagerte Scripten einbinden.
Nutzt Ihr globale Variablen, die von mehreren Funktionen benötigt werden, tragt Ihr sie am besten hier an gemeinsamer Stelle im Kopf ein. So ist sichergestellt, dass sie bei jedem Bedarf auch tatsächlich bekannt gemacht (declariert) sind. Außerdem ergibt sich Übersichtlichkeit. Auch die Initialisierung (eine erste Wertzuweisung) könnt Ihr sofort vornehmen.

Hauptfunktionen

Die nachfolgend kurz beschriebenen Funktionen werden genau einmal, uzw. zum Mapstart aufgerufen. In ihnen könnt Ihr anweisen, mit welchen Grundeinstellungen Eure Map starten soll. Lasst Funktionen, die Ihr nicht benötigt, unverändert stehen.

function InitDiplomacy()

Grundsätzlich sind alle Player dem player1 (Spieler) gegenüber feindlich gesinnt, untereinander verhalten sie sich neutral. Ihr könnt andere Regelungen veranlassen.

SetNeutral( 1, 3 ) -- player3 wird sich dem Spieler gegenüber neutral verhalten.
SetHostile( 5, 8 ) -- zwischen player5 und player8 herrscht Krieg
SetFriendly( 1, 4 ) -- Der Spieler und player4 sind befreundet 

Mit den 3 Funktionen lässt sich die Diplomatie im Spiel beliebig ändern.

Sicher wollt Ihr die Diplomatiestasi der Aktionsparteien im Diplomatiemenü anzeigen lassen.

SetPlayerName( 2, "Schwarzenherz" ) -- player2 wird mit dem Name Schwarzenherz angezeigt 

function InitResources()

Die eingetragenen Ressourcen-Werte erhält der Spieler beim Spielstart. In der Grundeinstellung werden die AI-Player durch das Spiel versorgt. Deren Grundversorgung kann allerdings für die Ballance und die Spannung im Spiel sinnvoll sein. Mit einer Schleifen-Anweisung (for-Schleife) lassen sich alle player mit gleichen Ressourcen-Werten versorgen.

for i = 1, 4 do -- die ersten 4 player werden versorgt
    AddGold  ( i,2500 ) -- das i wird in 4 Schleifendurchgängen ersetzt
    AddSulfur( i,1150 )
    AddIron  ( i,1500 )
    AddWood  ( i,2500 )
    AddStone ( i,2500 )
    AddClay  ( i,2500 )
end

(Zu weiteren Erläuterungen der oben verwendeten Befehle siehe unter anderem AddGold)

function InitTechnologies()

Grundsätzlich können alle player alle Technologien erforschen und nutzen. Ihr könnt allerdings für alle oder für einzelne player Verbote oder gestattungen aussprechen bzw. ihnen sofort bestimmte Technologien freischalten.

-- der Spieler kann den gezogenen Lauf nicht erforschen
ForbidTechnology( GT_PulledBarrel, 1)
-- Spieler 3 kämpft von Anfang an mit verbesserten Eisenrüstungen
ResearchTechnology( Technologies.T_LeatherMailArmor, 3 )

Keine Anweisung muss für den gesamten Spielverlauf gelten. Haltet bereits bei der Erstellung der Story Ausschau nach spannenden Quests. Die nüchterne Technik lässt sich elegant in das Briefing-Geschehen und in die Aktionswege integrieren.

function InitWeatherGfxSets()

Passt das Wetter über die Wetter-Sets auf die Stimmung in Eurer Map an.

function InitWeather()

Der Scripter hat Macht über den Wetterverlauf. Die eingetragene Reihenflge und die Zeiten laufen starr durch, sofern Ihr keine random-Werte befehlt bzw. keine wechselnden Regelungen trefft.

-- Erst 140 Sekunden Sonnenschein, dann 1-minütiger Regen, auf den ein längerer Sommer und eine weitere Regenperiode folgen,
-- die wiederum den Winter einleiten? So geht's:
AddPeriodicSummer( 140 ) --Dauer der Wetterperiode in Sekunden
AddPeriodicRain( 60 )
AddPeriodicSummer( 480 )
AddPeriodicRain( 120 )
AddPeriodicWinter( 360 )
--Ab hier geht das Wetter wieder von vorne los 

Nach dem nassen Herbst wird mit Feindbesuch gerechnet? Nichts ist unmöglich. Die Zeiten davor garantieren den Burgfrieden, sofern umschließendes Wasser (incl. blockierende Gebirge), aber keine Brücken bestehen. Bei Verwendung des Beispielwetters würden die Belagerer nach 800 Sekunden (= 13:20 Minuten) anmarschieren.

function InitPlayerColorMapping()

Ist man es leid, blaue Truppen durch die Gegend zu kommandieren? Und soll der feindliche Kereros standesgemäß in Grau regieren? In dieser Funktion können den Spielern andere Farben zugewiesen werden.

function InitPlayerColorMapping()
    Display.SetPlayerColorMapping( 1, NEPHILIM_COLOR ) --Spieler 1 spielt unter dem roten Banner
    Display.SetPlayerColorMapping( 2, KERBEROS_COLOR ) --Kerberos (Spieler 2) erhält sein Grau
end

Eine Liste aller verfügbaren Farben findet ihr hier.

function FirstMapAction()

Aus der FirstMapAction (unter den Scriptern mit FMA abgekürzt) werden alle weiteren Funktionen im Spiel direkt (Aufruf in der FMA) bzw. indirekt (aus aktiven Funktionen heraus) gestartet. Vom ursprünglich vorhandenen Code benötigt Ihr nichts. Erstellt eigene Sieg- und Niederlage-Bedingungen.
Setzt die erste Kamera-Position.
Lasst Umlaute in Briefings automatisch umwandeln.
Üblich ist es, das Spiel mit einem Prelude-Briefing starten zu lassen. Alternativ kann ein bereitstehender oder herbeieilender NPC die ersten Einweisungen ins Spiel übernehmen.
Startet Ihr ohne Prelude-Briefing, empfielt es sich, zum Spielstart einen Mainquest zu kreieren.
Ruft alle Funktionen auf, die sofort ablaufen oder Ereignisse überwachen sollen.
Der Start der ersten oder aller Briefings wird in der FMA veranlasst.
Komplexere Scripten wie der Heiler-/Schamanen-Script, Foersterscript, aiscript usw. benötigen die Startaufrufe in der FMA. Bindet umfangreiche Scripten am besten extern ein, bei einigen geht es wegen des Umfanges gar nicht anders.

AutoUmlaut() -- Umlaute in Briefings umwandeln
Camera.ScrollSetLookAt( 6234.32, 13861.63 ) -- Startposition der Kamera mit Beispielkoordinaten
SetupPlayerAI_2( aiID,range,peacetime ) -- starten der KI 2
-- beispielhafte Funktionsaufrufe
Mainquest() -- Bei Bedarf Mainquest über eine Funktion
BriefingCassandra() -- Briefing-Aufruf
CallGrenzerWarnung() -- Briefing über callback-Funktion (Call als Kennzeichnung)
StartSimpleJob( "HaendlerEingetroffen" ) -- Ereignisüberwachung jede Sekunde 

Beispielfunktion, der Mainquest

function Mainquest()
    Logic.AddQuest( 1, GetQuestId(), MAINQUEST_OPEN, "Questtext", 1 )
end

Für die Nutzung benötigt Ihr noch eine Comfort-Funktion. Wenn Ihr die Funktion für alle Quests nutzt und GetQuestId() in alles Quests einbindet, braucht Ihr Euch über die Vergabe einmaliger ID’s keine Gedanken mehr machen, der Komfort-Script regelt es.
Ihr könnt alle Comfort-Funktionen z.B. im unteren Teil des Scripts platzieren. Eine aussagekräftige Kommentarüberschrift sorgt für Übersicht.

-- GetQuestID
--------------------------------------------------------------------------------------------------
function GetQuestId() -- Für id in jeden Quest einbinden.
    gvMission.QuestId = (gvMission.QuestId or 0) + 1
    return gvMission.QuestId
end

Limitierung der Scriptlänge

Der Editor akzeptiert (intern) 1) nur Scripte bis zu einer Länge von 128KB. Sollte das eigene Script dieses Limit überschreiten, kann man es aber noch durch folgende Maßnahmen verkleinern:

  • Leerzeilen entfernen
  • Kommentare entfernen
  • Einrückung entfernen
  • Überflüssige Leerzeichen in einer Zeile entfernen
  • Leerzeichen vor und hinter Operatoren und Klammern entfernen
  • Optionale Semikolons am Ende der Zeile entfernen

Die einfachste Möglichkeit ist, das Script automatisch verkleinern zu lassen. Hierdurch wird das Script allerdings extrem unleserlich. Man sollte also immer eine Sicherheitskopie aufbewahren, und das geschrumpfte Script nur in die fertige Map kopieren, aber nie direkt bearbeiten.

Inzwischen existiert auch die Möglichkeit, diese Anwendung als .EXE oder als .ZIP herunterzuladen. Sollte euer Antivirus die Datei nicht akzeptieren, kann diese Variante verwendet werden.
Anstatt des Map-Editors muss diese Anwendung gestartet werden. Danach akzeptiert der Editor Skripte bis zu 4 MB Länge.

Sonstiges

  • Wenn das Script größer als 128KB ist
    Wenn trotz maximaler Verkleinerung das Script größer als 128KB ist, dann muss es als externes Script eingebunden werden. Häufig wird das per
    Script.Load ( "Lfw:\\Pfadangabe\\Dateiname.lua" )

    mit einer absoluten Pfadangabe gemacht. Dieser Umstand bringt das Problem mit sich, dass wenn man seine Map (und die externe Scriptdatei nicht vergessen ;-)) zum Download anbietet, man die Verzeichnisstruktur auf dem fremden System ja nicht kennt. Folglich müsste derjenige, der sich die Map gedownloadet hat, diese Pfadangabe erst noch für sein System (im Editor) anpassen, bevor er die Map spielen könnte. Um das Editieren der Map zu umgehen, kann man sich aber eines Ordners bedienen, der auf jedem System vorhanden und gleich sein muss, nämlich des eigentlichen Map-Ordners. Dieser existiert jeweils unter:
    Lfw.\[Pfad zum Siedler-DEdK Verz.]\DIE SIEDLER - Das Erbe der Könige\extra1(Nebelreich)|extra2(Legenden)\shr\maps\user
    Um ein Script aus diesem Ordner in seine Map einzubinden, kann man es nun mit einer relativen Pfadangabe referenzieren:

    Script.Load ( "maps\\user\\Dateiname.lua" )

    wobei Dateiname natürlich durch den Namen deiner externen Scriptdatei zu ersetzen ist. Jetzt muss nichts mehr Editiert werden, sondern nur noch die Dateien (Map + Script) ins jeweils richtige Verzeichnis (extra1\shr\maps\user bzw. extra2\shr\maps\user) geschoben werden.

Tipp: Für einige Scriptbestandteile werdet Ihr zusätzlich sog. Comfort-Funktionen benötigen. Ordnet sie zweckmäßigerweise im unteren Teil des Scripts an und verseht sie mit aussagekräftigen Kommentar-Überschriften. Falls der Script zu umfangreich wird, könnt Ihr als erstes versuchen, nur durch die Auslagerung der Comfort-Funktionen mit dem Script doch noch innerhalb des Limits zu bleiben. Wählt einen passenden Namen, etwa MapNameComfort.lua. Die Einbindung erfolgt alalog zur obigen Anleitung mittels :

Script.Load ( "maps\\user\\MapNameComfort.lua" )

.

FIXME sollte immer mit einer evt. Ordner-Konvention abgeglichen werden, wie auch bei Old McDonalds AI-Script


  • FIXME Hier könnten noch andere allgemeine Hinweise hin, beispielsweise aus diesem Topic.
1) bezieht sich auf das in die Map direkt eingebundene Script - per Script.Load eingebundene Scripts können auch größer sein
 
tutorials/allgemeines.txt · Zuletzt geändert: 2009/08/29 10:41
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki