Benutzer-Werkzeuge

Webseiten-Werkzeuge


scripting:tutorials:level2:setup_quest

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige ÜberarbeitungVorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
scripting:tutorials:level2:setup_quest [2023/10/28 10:55] fritz_98scripting:tutorials:level2:setup_quest [2023/11/11 14:07] (aktuell) fritz_98
Zeile 226: Zeile 226:
 ---- ----
  
-====Karawanen beschützen: SetupCaravan====+====Quests abbrechen====
  
-----+Mit ''DestroyQuest(_QuestDescription)'' können Quests vorzeitig wieder abgebrochen werden, sodass die Bedingung nicht mehr geprüft und das Callback nicht mehr aufgerufen wird.
  
-====Quests abbrechen====+Damit das funktioniert, ist es **wichtig**, dass das ''QuestDescription''-Table, die für die Erstellung der Quest verwendet wurde, als globale Variable definiert ist. Der Aufruf von ''Setup...'' trägt in dieses Table eine Trigger-Id ein, die für ''DestroyQuest'' gebraucht wird. 
 + 
 +Wir nehmen das Beispiel zum Auffinden von Helias [[scripting:tutorials:level2:setup_quest#orte_erreichensetupexpedition |oben]]. Wenn Helias aus irgendeinem Grund stirbt, soll die Quest ''QuestFindHelias'' beendet werden. Dafür können wir analog zu den [[ scripting:tutorials:level1:simple_job |Sieg- und Niederlagebedingungen aus Ebene 1]] einen //SimpleJob// starten, der prüft, ob Helias gestorben ist. Wenn das der Fall ist, beende die Quest ''QuestFindHelias''
 + 
 +<code lua> 
 +function FirstMapAction() 
 +    -- Wir erstellen gleichzeitig die Quest, Helias zu finden und den Job, 
 +    -- der Helias Tod prüfen soll 
 +    CreateQuestFindHelias() 
 +    StartSimpleJob("CheckHeliasDeath"
 +end 
 + 
 +function CheckHeliasDeath() 
 +    -- wenn Helias tot ist... 
 +    if IsDead("Helias") then 
 +        -- ...beende die Quest 
 +        DestroyQuest(QuestFindHelias) 
 +        -- Und beende die Quest nur 1 mal! Der Job wird nach Beenden der Quest ebenfalls 
 +        -- durch return true beendet 
 +        return true 
 +    end 
 +end 
 + 
 +-- Hierunter kommt der Beispielcode von oben. Wichtig ist, dass QuestFindHelias global definiert wird 
 +</code> 
 + 
 +----
  
 ====Zusätzliche Parameter==== ====Zusätzliche Parameter====
  
 +[[ scripting:tutorials:level2:npcs#zusaetzliche_parameter_der_callback-funktion |Analog zu den NPC-Callbacks]] werden auch bei allen Quest-Callbacks die Quest-Tables, die zur Definition der Quest verwendet wurden, als Parameter übergeben. Dies machen wir uns beispielsweise [[ scripting:tutorials:level2:find_entities#beispiel_anwendungsfall3 |im nächsten Kapitel]] zunutze, um nach einer ''SetupEstablish''-Quest die errichteten Gebäude dem Spieler des Auftraggebers zu übergeben.
 +
 +Eine Konsequenz daraus ist, dass im Quest-Table zusätzliche, frei wählbare Parameter angegeben werden können, die im Callback verfügbar sind. Das ist vor allem nützlich, wenn mehrere Quests die gleiche Callback-Funktion verwenden (da andernfalls jedes Callback auf eine einzigartige Quest zurückgeführt werden kann).
 +
 +Folgende Quest soll umgesetzt werden: Der Spieler hat die Wahl, ob er für den Auftraggeber eine Garnision oder eine Schießanlage errichten möchte. Je nach gewähltem Gebäude soll er einen Trupp Langschwertkämpfer oder Armbrustschützen erhalten. Wenn er sich für eines der Gebäude entschieden und die zugehörige Belohnung erhalten hat, soll die jeweils andere Quest automatisch [[ scripting:tutorials:level2:setup_quest#quests_abbrechen|beendet]] werden.
 +
 +Für dieses Setup existiert eine ''ScriptEntity'' mit dem Skriptnamen ''"EstablishMilitaryBuilding"'' und eine weitere mit dem Skriptnamen ''"SpawnRewardTroops"''.
 +
 +<code lua>
 +function FirstMapAction()
 +    -- Beide Quests werden mit der gleichen Funktion, aber unterschiedlichen Parametern gestartet
 +    -- Die Funktionen geben das Quest-Table zurück, damit sie in eine globale Variable gegeben werden können
 +    -- Das ist notwendig, weil die jeweils nicht erfüllte Quests automatisch beendet werden soll
 +    QuestBuildBarracks = CreateQuestBuildMilitaryBuilding(Entities.PB_Barracks2, Entities.PU_LeaderSword3)
 +    QuestBuildArchery = CreateQuestBuildMilitaryBuilding(Entities.PB_Archery2, Entities.PU_LeaderBow3)
 +    
 +    -- Um anzugeben, welche Quest beendet werden soll, geben wir diese Information ebenfalls noch in die
 +    -- Tables:
 +    QuestBuildBarracks.RemoveQuest = QuestBuildArchery
 +    QuestBuildArchery.RemoveQuest = QuestBuildBarracks
 +    -- Im Callback brauchen wir also nur auf den Eintrag RemoveQuest zuzugriefen, um zu wissen, welche
 +    -- Quest beendet werden muss
 +end
 +
 +function CreateQuestBuildMilitaryBuilding(_BuildingType, _RewardType)
 +    -- Da die Funktion 2 mal aufgerufen wird, muss die Questbeschreibung innerhalb der 
 +    -- Funktion lokal sein. Sie wird mit return zurückgegeben und beim Aufruf in einer
 +    -- globale Variable gespeichert
 +    local QuestDescription = {
 +        Player = 1,
 +        AreaPos = "EstablishMilitaryBuilding",
 +        AreaSize = 2000,
 +        EntityTypes = {
 +            -- Der Gebäudetyp wird aus dem Parameter geholt
 +            {_BuildingType, 1}
 +        },
 +        -- Hier geben wir den Truppentyp der Belohnung für den Bau des Gebäudes an
 +        -- Er wird vom Quest-Handling ignoriert, kann aber im Callback verwendet werden,
 +        -- um die korrekte Belohnung zu spawnen
 +        RewardType = _RewardType,
 +        Callback = CallbackQuestBuildMilitaryBuilding
 +    }
 + 
 +    SetupEstablish(QuestDescription)
 +    
 +    -- Rückgabe der QuestDescription, um sie in eine globale Variable geben zu können
 +    return QuestDescription
 +end
 +
 +function CallbackQuestBuildMilitaryBuilding(_QuestDescription)
 +    -- In dieser Funktion steht das Table _QuestDescription zur Verfügung, das genau dem Quest-Table
 +    -- mitsamt unserer zusätzlichen Einträge entspricht
 +
 +    -- Die Funktion CreateMilitaryGroup erstellt einen kompletten Trupp Soldaten vom angegebenen Typ
 +    -- Siehe die Comfort-Referenz oder den Artikel zu "Belohnungen" in Ebene 2
 +    -- Für den Typ des Hauptmanns wählen wir den RewardType, der beim erstellen der Quest
 +    -- abhängig von den Parametern festgelegt wurde
 +    CreateMilitaryGroup(1, _QuestDescription.RewardType, 8, GetPosition("SpawnRewardTroops"))
 +    -- Außerdem haben wir pro Quest angegeben, welche die jeweils andere Quest ist, die es nun zu
 +    -- beenden gilt
 +    DestroyQuest(_QuestDescription.RemoveQuest)
 +end
 +</code>
 +
 +----
 +
 +====Karawanen beschützen: SetupCaravan====
 +
 +Diese Art der Quest kennst du vielleicht aus der Nebelreich-Kampagnenkarte "Fahrende Händler". Eine bestimmte Anzahl an Händlern läuft die Handelsroute entlang vorgegebener Wegpunkte ab und verweilt an jedem Wegpunkt kurz. Aufgabe des Spielers ist es, diese Händler zu beschützen. Die Quest ist erfolgreich, wenn ausreichend Händler ihr Ziel erreichen - andernfalls scheitert sie.
 +
 +Die Funktion ''SetupCaravan(_QuestDescription)'' übernimmt dabei das Bewegen der Händler und den Check, ob alle Händler den Zielpunkt erreicht haben oder gestorben sind. Allerdings erschafft die Funktion die Händler **nicht von selbst**! Sie müssen also **vor** Beginn der Quest bereits existieren. Der Parameter ''_QuestDescription'' ist ein Table mit folgenden Einträgen:
 +
 +^Key^Value-Typ^Bedeutung^
 +| Unit | String | Präfix eines Skriptnamens für mehrere Entities, deren Namen auf der Karte durchnummeriert sind. „Trader“ stände beispielsweise für „Trader1“, „Trader2“, „Trader3“, usw. - abhängig davon, wie viele durchnummerierte Entities existieren |
 +| Unit | Table (Liste) | Liste mit Skriptnamen oder Entity-Ids aller Entities, die der Karawane angehören sollen |
 +| Waypoint | Table (Liste) | Liste von Tables, die für jeden Wegpunkt den Namen einer Positions-Entity und die zugehörige Wartezeit angeben |
 +| Remove | nil | Wenn ''~= nil'', werden die Entities in der Karawane automatisch gelöscht, wenn sie den Zielpunkt erreichen. Optionaler Parameter |
 +| Callback | Funktion | Funktion, die aufgerufen wird, sobald alle Entities entweder am Zielort oder tot sind |
 +| ArrivedCallback | Funktion | Funktion, die jedes mal aufgerufen wird, sobald eine Entity am Zielort ankommt. Optionaler Parameter |
 +
 +**Hinweis**: Die Angabe von ''Unit'' erfolgt entweder als String oder als Liste.
 +
 +Jedes mal, wenn ein Mitglied der Karawane den letzten Wegpunkt erreicht, wird außerdem eine Zählvariable im Quest-Table ''.ArrivedCount'' hochgezählt. Da das Quest-Table in den [[ scripting:tutorials:level2:setup_quest#zusaetzliche_parameter|Callbacks verfügbar ist]], können wir darin abfragen, wie viele der Entities erfolgreich am Ziel angekommen sind.
 +
 +Für folgendes Anwendungsbeispiel existieren auf der Karte einige ''ScriptEntities'', die duchnummeriert die Namen ''"QuestCaravanWaypoint1"'' bis ''"QuestCaravanWaypoint5"'' tragen, sowie ein ''ScriptEntity'' mit ''"QuestCaravanStart"''.
 +
 +Außerdem werden wir uns die Möglichkeit [[ scripting:tutorials:level2:setup_quest#zusaetzliche_parameter|zusätzlicher Parameter]] zunutze machen, um im Quest-Table zu definieren, wie viele der Händler, die gestartet sind, ankommen müssen.
 +
 +<code lua>
 +function CreateQuestCaravan()
 +    -- Die Händler existieren noch nicht, wir müssen sie also erst erstellen
 +    for i = 1, 5 do
 +        -- Skriptnamen werden beim Erstellen in der Schleife gleich durchnummeriert
 +        CreateEntity(4, Entities.PU_Travelling_Salesman, GetPosition("QuestCaravanStart"), "QuestCaravanTrader"..i)
 +    end
 +    
 +    local QuestDescription = {
 +        -- Alle 5 Händler sind gemeint - der gemeinsame Namenspräfix reicht
 +        Unit = "QuestCaravanTrader",
 +        
 +        -- Hier wird die Liste der Wegpunkte angegeben
 +        -- Jeder Wegpunkt hat einen Namen (Skriptname der Entity, deren Position der Wegpunkt ist)
 +        -- und eine Wartezeit
 +        Waypoint = {
 +            {Name = "QuestCaravanWaypoint1", WaitTime = 30},
 +            {Name = "QuestCaravanWaypoint2", WaitTime = 30},
 +            {Name = "QuestCaravanWaypoint3", WaitTime = 30},
 +            {Name = "QuestCaravanWaypoint4", WaitTime = 30},
 +            {Name = "QuestCaravanWaypoint5", WaitTime = 30}
 +        },
 +        
 +        -- Jeder angekommene Händler soll direkt von der Map entfernt werden
 +        Remove = true,
 +
 +        -- Dies ist ein eigener Parameter. Wir geben hier an, dass 3 der 5 Händler ankommen müssen
 +        -- Diese Bedingung prüfen wir später im Callback
 +        Necessary = 3,
 +        
 +        -- Zwei verschiedene Funktionen für zwei verschiedene Callbacks
 +        -- Einmal die Funktion, die bei jedem angekommenen Händler ausgelöst wird
 +        ArrivedCallback = CallbackArrivedQuestCaravan,
 +        -- und die Funktion, die ausgelöst wird, sobald alle Händler angekommen oder tot sind
 +        Callback = CallbackQuestCaravan,
 +    }
 +    
 +    SetupCaravan(QuestDescription)
 +end
 +
 +function CallbackArrivedQuestCaravan()
 +    -- In diesem Callback lassen wir den Spieler lediglich wissen, dass einer der Händler angekommen ist
 +    Message("Ein Händler ist an seinem Ziel angekommen!")
 +end
 +
 +function CallbackQuestCaravan(_QuestDescription)
 +    -- Hier prüfen wir, ob genug Händler ihre Reise überlebt haben
 +    -- Die Variable _QuestDescription.ArrivedCount wurde automatisch hochgezählt
 +    if _QuestDescription.ArrivedCount >= _QuestDescription.Necessary then
 +        Message("Ihr habt erfolgreich die Karawane beschützt!")
 +        -- hier folgt alles Weitere nach dem erfolgreichen Erfüllen der Quest
 +    else
 +        Message("Ihr habt es nicht geschafft, die Karawane zu beschützen!")
 +        -- hier folgt alles nach dem Scheitern der Quest (z.B. neuer Versuch, etc)
 +    end
 +end
 +</code>
 +
 +**Hinweis**: Die Karawane verhält sich so, dass der erste Händler vorausgeht und alle weiteren Händler ihrem Vordermann folgen. Wenn du nicht genug Wartezeit pro Wegpunkt angibst, fallen die letzten Händler in der Reihe möglicherweise zurück. Die Wartezeit an den Wegpunkten sollte also ungefähr mit der Größe der Karawane wachsen.
 +
 +----
 +
 +NPCs geben Aufträge, deren Bedingungen nun geprüft werden können. Im nächsten Kapitel stellen wir einige Funktionen vor, mit denen der Spieler für seine Aktionen belohnt werden kann.
 +
 +[[ scripting:tutorials:level2:npcs| Voriges Kapitel: NPCs ]] \\
 +[[ scripting:tutorials:level2:rewards| Nächstes Kapitel: Belohnungen ]] \\
 +[[ scripting:tutorials:level2:setup_quest | Zurück nach oben ]]
scripting/tutorials/level2/setup_quest.1698490504.txt.gz · Zuletzt geändert: 2023/10/28 10:55 von fritz_98