scripting:tutorials:level2:find_entities
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
Nächste Überarbeitung | Vorherige Überarbeitung | ||
scripting:tutorials:level2:find_entities [2023/11/08 10:01] – angelegt fritz_98 | scripting:tutorials:level2:find_entities [2023/11/10 11:32] (aktuell) – [Beliebige Gebäude oder Einheiten eines Spielers im Gebiet finden] fritz_98 | ||
---|---|---|---|
Zeile 69: | Zeile 69: | ||
-- Liebes BlueByte, die Sitzbank heißt auf Englisch " | -- Liebes BlueByte, die Sitzbank heißt auf Englisch " | ||
-- Wir verwenden hier Logic.CreateEntity, | -- Wir verwenden hier Logic.CreateEntity, | ||
+ | -- Die Parameter sind dafür etwas anders, siehe die Logic-Referenz | ||
Logic.CreateEntity(Entities.XD_MiscBank1, | Logic.CreateEntity(Entities.XD_MiscBank1, | ||
end | end | ||
Zeile 86: | Zeile 87: | ||
**Achtung**: | **Achtung**: | ||
+ | |||
+ | **Tipp**: Du kannst deinen gewünschten Radius durch [[ scripting: | ||
Wie im Artikel zu [[ scripting: | Wie im Artikel zu [[ scripting: | ||
+ | |||
+ | **Hinweis**: | ||
===Variante 1: Direkt in Variablen=== | ===Variante 1: Direkt in Variablen=== | ||
Zeile 93: | Zeile 98: | ||
Diese Variante ist vor allem sinnvoll, wenn nicht mehr als 1 oder 2 Entities gesucht werden, da für jede potenziell gefundene Entity eine eigene Variable angelegt werden muss: | Diese Variante ist vor allem sinnvoll, wenn nicht mehr als 1 oder 2 Entities gesucht werden, da für jede potenziell gefundene Entity eine eigene Variable angelegt werden muss: | ||
<code lua> | <code lua> | ||
- | -- In diesem Beispiel suchen wir nach höchstens zwei Tempelaltären | + | -- In diesem Beispiel suchen wir nach höchstens zwei Mauertoren im Gebiet |
- | local NumberOfEntities, | + | local NumberOfEntities, |
</ | </ | ||
- | Die Funktion kann maximal 2 Tempelaltäre | + | Die Funktion kann maximal 2 Mauertore |
* Wenn '' | * Wenn '' | ||
- | * Wenn '' | + | * Wenn '' |
- | * Wenn '' | + | * Wenn '' |
Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist: | Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist: | ||
Zeile 116: | Zeile 121: | ||
Wenn man deutlich mehr als zwei Entities sucht, bekommt man über //Variante 1// eine unübersichtliche Schreibarbeit. Wir suchen den selben Entity-Typ diesmal deutlich öfter: | Wenn man deutlich mehr als zwei Entities sucht, bekommt man über //Variante 1// eine unübersichtliche Schreibarbeit. Wir suchen den selben Entity-Typ diesmal deutlich öfter: | ||
<code lua> | <code lua> | ||
- | -- In diesem Beispiel suchen wir nach höchstens acht Tempelaltären | + | -- In diesem Beispiel suchen wir nach höchstens acht Mauertoren in einem größeren Gebiet |
- | local FoundEntityIds = { Logic.GetEntities(Entities.XD_TemplarAltar, 8) } | + | local FoundEntityIds = { Logic.GetEntitiesInArea(Entities.XD_WallStraightGate, |
</ | </ | ||
Die größe des Tables ist dabei immer 1 + #Entities, wobei in '' | Die größe des Tables ist dabei immer 1 + #Entities, wobei in '' | ||
Zeile 123: | Zeile 128: | ||
====Beispiel Anwendungsfall==== | ====Beispiel Anwendungsfall==== | ||
- | Bestimmte Bäume | + | Im Winter sollen Laubbäume ihre Blätter verlieren. Das macht Siedler nicht automatisch und meistens fehlen dafür auch die passenden Entity-Typen. Für '' |
+ | |||
+ | Wir ersetzen also in einem bestimmten Gebiet alle Entities vom Typ '' | ||
+ | |||
+ | <code lua> | ||
+ | -- Wir formulieren das oben Beschriebene als wiederverwendbare Funktion | ||
+ | -- Das hat den Grund, dass Logic.GetEntitiesInArea maximal 16 Entities zurückgeben kann. Da meistens | ||
+ | -- deutlich mehr als 16 Bäume | ||
+ | -- auf der Karte (möglicherweise wiederholt) aufgerufen werden | ||
+ | function TreeNorthLoseLeaves(_Position, | ||
+ | -- Wir definieren ein Table, das angibt, welche Baumtypen durch die blattlosen zu ersetzen | ||
+ | local ReplaceTypes = { | ||
+ | [Entities.XD_TreeNorth1] = Entities.XD_DeadTreeNorth1, | ||
+ | [Entities.XD_TreeNorth2] = Entities.XD_DeadTreeNorth2, | ||
+ | [Entities.XD_TreeNorth3] = Entities.XD_DeadTreeNorth3 | ||
+ | } | ||
+ | for SummerTreeType, | ||
+ | local TreeIds = { Logic.GetEntitiesInArea(SummerTreeType, | ||
+ | -- Im ersten Eintrag vom Table TreeIds steht die Anzahl der gefundenen Entities | ||
+ | -- Die benutzen wir direkt für die Schleife | ||
+ | -- Die Zählvariable beginnt bei 2, da der erste Eintrag keine Entity-Id ist | ||
+ | for i = 2, TreeIds[1] + 1 do | ||
+ | -- ReplaceEntity ersetzt eine Entity durch den angegebenen Entity-Typ | ||
+ | -- Mehr zu dieser Funktion findest du in der Comfort-Referenz und im Artikel | ||
+ | -- zu " | ||
+ | ReplaceEntity(TreeIds[i], | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ---- | ||
=====Logic.GetPlayerEntities===== | =====Logic.GetPlayerEntities===== | ||
+ | |||
+ | '' | ||
+ | |||
+ | Die Funktion gibt **mehrere** Werte zurück, wovon der erste die Anzahl der gefundenen Entities ist und **deshalb keine gültige Entity-Id ist**! | ||
+ | |||
+ | Alle weiteren Rückgabewerte sind Entity-Ids der gefundenen Entities vom Typ '' | ||
+ | Das bedeutet, dass die Funktion genau 1 + #Entities Rückgabewerte hat. | ||
+ | |||
+ | **Achtung**: | ||
+ | |||
+ | Wie im Artikel zu [[ scripting: | ||
+ | |||
+ | ===Variante 1: Direkt in Variablen=== | ||
+ | |||
+ | Diese Variante ist vor allem sinnvoll, wenn nicht mehr als 1 oder 2 Entities gesucht werden, da für jede potenziell gefundene Entity eine eigene Variable angelegt werden muss: | ||
+ | <code lua> | ||
+ | -- In diesem Beispiel suchen wir nach höchstens zwei Kathedralen von Spieler 1 | ||
+ | local NumberOfEntities, | ||
+ | </ | ||
+ | Die Funktion kann maximal 2 Kathedralen finden, aber auch weniger. Davon abhängig resultieren unterschiedliche Rückgabewerte: | ||
+ | * Wenn '' | ||
+ | * Wenn '' | ||
+ | * Wenn '' | ||
+ | |||
+ | Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt auf der Karte existiert: | ||
+ | <code lua> | ||
+ | function IsPlayerEntityOfTypeOnMap(_PlayerId, | ||
+ | -- Es ist guter Stil, mit dem Unterstrich anzuzeigen, dass dieser Wert ignoriert wird. | ||
+ | -- Auf der Logikebene macht es keinen Unterschied, | ||
+ | -- welche Variablen von Bedeutung sind | ||
+ | local NumberOfEntities, | ||
+ | return NumberOfEntities > 0 | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ===Variante 2: Rückgabe in ein Table=== | ||
+ | |||
+ | Wenn man deutlich mehr als zwei Entities sucht, bekommt man über //Variante 1// eine unübersichtliche Schreibarbeit. Wir suchen den selben Entity-Typ diesmal deutlich öfter: | ||
+ | <code lua> | ||
+ | -- In diesem Beispiel suchen wir nach höchstens acht Kathedralen | ||
+ | local FoundEntityIds = { Logic.GetPlayerEntities(1, | ||
+ | </ | ||
+ | Die größe des Tables ist dabei immer 1 + #Entities, wobei in '' | ||
====Beispiel Anwendungsfall==== | ====Beispiel Anwendungsfall==== | ||
- | Alle kleinen Wohnhäuser | + | Ein großzügiger Architekt kommt in die Stadt und bietet an, alle kleinen Wohnhäuser |
+ | <code lua> | ||
+ | -- Wir hoffen in diesem Fall, dass der Spieler nicht mehr als 16 kleine Wohnhäuser hat | ||
+ | local ResidenceIds = { Logic.GetPlayerEntities(1, | ||
+ | -- Im ersten Eintrag vom Table ResidenceIds steht die Anzahl der gefundenen Entities | ||
+ | -- Die benutzen wir direkt für die Schleife | ||
+ | -- Die Zählvariable beginnt bei 2, da der erste Eintrag keine Entity-Id ist | ||
+ | for i = 2, ResidenceIds[1] + 1 do | ||
+ | -- ReplaceEntity ersetzt eine Entity durch den angegebenen Entity-Typ | ||
+ | -- Mehr zu dieser Funktion findest du in der Comfort-Referenz und im Artikel | ||
+ | -- zu " | ||
+ | ReplaceEntity(ResidenceIds[i], | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ---- | ||
=====Logic.GetPlayerEntitiesInArea===== | =====Logic.GetPlayerEntitiesInArea===== | ||
- | Dafür brauchst du die Funktion | + | '' |
- | Die Funktion gibt alle gefundenen Entities als EntityId einzeln aus, was möglicherweise ein bisschen ungewohnt ist. Außerdem ist der erste Rückgabewert keine EntityId, sondern | + | Die Funktion gibt **mehrere** Werte zurück, wovon der erste die Anzahl der gefundenen |
- | Ein Beispielaufruf zur Anschauung, bei dem an Position | + | Alle weiteren Rückgabewerte sind Entity-Ids der gefundenen Entities vom Typ '' |
+ | Das bedeutet, dass die Funktion genau 1 + #Entities Rückgabewerte hat. | ||
+ | |||
+ | **Achtung**: | ||
+ | |||
+ | **Tipp**: Du kannst deinen gewünschten Radius durch [[ scripting: | ||
+ | |||
+ | Wie im Artikel zu [[ scripting: | ||
+ | |||
+ | **Hinweis**: | ||
+ | |||
+ | ===Variante 1: Direkt in Variablen=== | ||
+ | |||
+ | Diese Variante ist vor allem sinnvoll, wenn nicht mehr als 1 oder 2 Entities | ||
<code lua> | <code lua> | ||
- | NumberFoundEntities, EntityId1, EntityId2 = Logic.GetPlayerEntitiesInArea(5, Entities.PB_Residence1, 4200, 4200, 1500, 2) | + | -- In diesem Beispiel suchen wir nach höchstens zwei Leibeigene von Spieler 1 im Gebiet |
+ | local NumberOfEntities, EntityId1, EntityId2 = Logic.GetPlayerEntitiesInArea(1, Entities.PU_Serf, 4900, 13100, 3000, 2) | ||
</ | </ | ||
- | (die accessCategory | + | Die Funktion |
+ | * Wenn '' | ||
+ | * Wenn '' | ||
+ | * Wenn '' | ||
- | Die Funktion kann maximal 2 Wohnhäuser finden, aber auch weniger. Davon abhängig bekommst du unterschiedliche Rückgabewerte: | + | Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist: |
- | | + | <code lua> |
- | | + | function IsPlayerEntityOfTypeInArea(_PlayerId, |
- | | + | |
+ | -- Auf der Logikebene macht es keinen Unterschied, | ||
+ | -- welche Variablen von Bedeutung sind | ||
+ | local NumberOfEntities, | ||
+ | return NumberOfEntities > 0 | ||
+ | end | ||
+ | </ | ||
- | Wenn man mehr als 2 Gebäude | + | ===Variante 2: Rückgabe in ein Table=== |
+ | |||
+ | Wenn man deutlich | ||
<code lua> | <code lua> | ||
- | FoundEntities | + | -- In diesem Beispiel suchen wir nach höchstens acht Mauertoren in einem größeren Gebiet |
+ | local FoundEntityIds | ||
</ | </ | ||
- | In dem Fall ist '' | + | Die größe des Tables |
+ | |||
+ | |||
+ | ====Beispiel Anwendungsfall==== | ||
+ | |||
+ | Wir führen das Beispiel aus [[ scripting: | ||
- | Für deinen Fall würde ich deshalb Folgendes schreiben: | ||
<code lua> | <code lua> | ||
- | -- Eigentlich sollte man nicht auf deutsch programmieren. Versuche, auf englische Namen umzusteigen | + | -- Der Funktionsname CallbackQuestBuildCathedral wurde als Callback bei der Definition der Quest angegeben |
- | -- Kommentare kannst du dann dafür nutzen, zu erklären, was die Funktion macht, also z.B: | + | -- Die Funktion wird automatisch |
- | -- Diese Funktion wird nach dem Bau der Garnision | + | -- Das Argument _QuestDescription ist das Quest-Table, mit dem die Quest definiert wurde |
- | -- Sie übergibt die errichtete Garnision an Spieler 2 | + | function |
- | -- (usw. was auch immer noch folgt) | + | -- Der Key AreaPos der _QuestDescription enthält den Skriptnamen der Position |
- | -- Falls mal etwas nicht funktioniert, kannst du anhand solcher Notizen schneller prüfen, ob die Funktion | + | local QuestPosition = GetPosition(_QuestDescription.AreaPos) |
- | -- das tut, was sie soll | + | -- Wir brauchen |
- | function | + | local QuestRadius = _QuestDescription.AreaSize |
- | -- Du lässt die Kaserne an Position | + | |
- | -- holen: | + | -- die Art und Anzahl |
- | local QuestPosition = GetPosition(" | + | |
- | -- Wir brauchen die Variablen hier nur lokal. Kein Grund, sie global zu definieren | + | |
- | -- Die Position ist jetzt in QuestPosition, | + | local EntityType, Amount = unpack(EntityRequirement) |
- | -- die gebaut werden sollte | + | local FoundEntities |
- | local NumberFoundEntities, EntityId1 | + | |
- | -- Wenn die Quest korrekt funktioniert, sollte diese Bedingung immer zutreffen | + | for i = 2, FoundEntities[1] + 1 do |
- | if NumberFoundEntities > 0 then | + | -- Wechsle die Spieler-Id der gefundenen |
- | | + | -- Mehr Informationen zu ChangePlayer findest du in der Comfort-Referenz und |
- | ChangePlayer(EntityId1, 2) | + | -- im Artikel zu " |
+ | ChangePlayer(FoundEntities[i], 4) | ||
+ | end | ||
end | end | ||
end | end | ||
</ | </ | ||
- | ====Beispiel Anwendungsfall==== | + | ====Beliebige Gebäude oder Einheiten eines Spielers im Gebiet finden==== |
- | Gebäude | + | Weiter oben wurde bereits der zusätzliche Parameter '' |
- | ====Beliebige | + | Mit '' |
+ | |||
+ | Am nützlichsten ist diese Funktion, um zu prüfen, ob ein Spieler ein Gebäude oder einen Siedler in einem bestimmten Gebiet hat: | ||
+ | <code lua> | ||
+ | function IsPlayerSettlerInArea(_PlayerId, | ||
+ | -- _EntityType muss 0 sein, um _AccessCategory verwenden zu können | ||
+ | -- Wir müssen nur 1 Entity der Kategorie 2 = Siedler finden | ||
+ | local NumberOfEntities, | ||
+ | return NumberOfEntities > 0 | ||
+ | end | ||
+ | |||
+ | function IsPlayerBuildingInArea(_PlayerId, | ||
+ | -- _EntityType muss 0 sein, um _AccessCategory verwenden zu können | ||
+ | -- Wir müssen nur 1 Entity der Kategorie 8 = Gebäude | ||
+ | local NumberOfEntities, | ||
+ | return NumberOfEntities > 0 | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | Man kann sie auch dafür verwenden, um beispielsweise alle Gebäude | ||
+ | <code lua> | ||
+ | function DestroyAllPlayerBuildingsInArea(_PlayerId, | ||
+ | -- Initialisiere ein lokales Table | ||
+ | local FoundEntities | ||
+ | repeat | ||
+ | -- Suche alle Gebäude von Spieler _PlayerId im Bereich | ||
+ | FoundEntities | ||
+ | -- Zerstöre alle gefundenen Gebäude | ||
+ | for i = 2, FoundEntities[1] + 1 do | ||
+ | DestroyEntity(FoundEntities[i]) | ||
+ | end | ||
+ | -- Die Schleife hört auf zu iterieren, sobald keine weiteren Gebäude mehr im Bereich sind | ||
+ | until FoundEntities[1] | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Dies war ein erster Ausflug in die '' | ||
+ | |||
+ | [[ scripting: | ||
+ | [[ scripting: | ||
+ | [[ scripting: |
scripting/tutorials/level2/find_entities.1699437691.txt.gz · Zuletzt geändert: 2023/11/08 10:01 von fritz_98