Benutzer-Werkzeuge

Webseiten-Werkzeuge


scripting:tutorials:level2:find_entities

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Nächste Überarbeitung
Vorherige Überarbeitung
scripting:tutorials:level2:find_entities [2023/11/08 10:01] – angelegt fritz_98scripting: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 "Bench", nicht "Bank"! :<         -- Liebes BlueByte, die Sitzbank heißt auf Englisch "Bench", nicht "Bank"! :<
         -- Wir verwenden hier Logic.CreateEntity, um die Rotation der Bank einstellen zu können         -- Wir verwenden hier Logic.CreateEntity, um die Rotation der Bank einstellen zu können
 +        -- Die Parameter sind dafür etwas anders, siehe die Logic-Referenz
         Logic.CreateEntity(Entities.XD_MiscBank1, VCPosition.X + 300, VCPosition.Y - 600, 0, 0)         Logic.CreateEntity(Entities.XD_MiscBank1, VCPosition.X + 300, VCPosition.Y - 600, 0, 0)
     end     end
Zeile 86: Zeile 87:
  
 **Achtung**: ''_Amount'' ist auf den Maximalwert **16** beschränkt! Mehr Entity-Ids kann die Funktion nicht zurückgeben. Wenn du beispielsweise bei ''_Amount'' 20 angibst, werden trotzdem maximal 16 Entity-Ids zurückgegeben. **Achtung**: ''_Amount'' ist auf den Maximalwert **16** beschränkt! Mehr Entity-Ids kann die Funktion nicht zurückgeben. Wenn du beispielsweise bei ''_Amount'' 20 angibst, werden trotzdem maximal 16 Entity-Ids zurückgegeben.
 +
 +**Tipp**: Du kannst deinen gewünschten Radius durch [[ scripting:tutorials:level1:place_entities#ambient_sounds |Platzieren eines XS_Ambient]] auf die Position ermitteln. Das 100-fache der angegebenen Größe der Ambient-Entity entspricht genau dem anzugebenden ''_Radius''.
  
 Wie im Artikel zu [[ scripting:tutorials:level2:functions#mehrere_rueckgabewerte |mehreren Rückgabewerten]] beschrieben, können diese Rückgabewerte auf unterschiedliche Arten in Variablen geschrieben werden. Wie im Artikel zu [[ scripting:tutorials:level2:functions#mehrere_rueckgabewerte |mehreren Rückgabewerten]] beschrieben, können diese Rückgabewerte auf unterschiedliche Arten in Variablen geschrieben werden.
 +
 +**Hinweis**: Unabhängig von der verwendeten Variante sind die zurückgegebenen Entity-Ids nach dem Abstand zur Zielplosition sortiert - das nächstgelegene Entity zuerst.
  
 ===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, EntityId1, EntityId2 = Logic.GetEntities(Entities.XD_TemplarAltar, 2)+local NumberOfEntities, EntityId1, EntityId2 = Logic.GetEntitiesInArea(Entities.XD_WallStraightGate, 4900, 13100, 3000, 2)
 </code> </code>
-Die Funktion kann maximal 2 Tempelaltäre finden, aber auch weniger. Davon abhängig resultieren unterschiedliche Rückgabewerte: +Die Funktion kann maximal 2 Mauertore finden, aber auch weniger. Davon abhängig resultieren unterschiedliche Rückgabewerte: 
   * Wenn ''NumberOfEntities== 0'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' beide **nil**   * Wenn ''NumberOfEntities== 0'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' beide **nil**
-  * Wenn ''NumberFoundEntities == 1'', dann ist ''EntityId1'' die Entity-Id eines Tempelaltars und ''EntityId2'' ist **nil** +  * Wenn ''NumberFoundEntities == 1'', dann ist ''EntityId1'' die Entity-Id eines Mauertors und ''EntityId2'' ist **nil** 
-  * Wenn ''NumberFoundEntities == 2'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' Entity-Ids eines Tempelaltars+  * Wenn ''NumberFoundEntities == 2'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' Entity-Ids eines Mauertors
  
 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, 4900, 13100, 8000, 8)) }
 </code> </code>
 Die größe des Tables ist dabei immer 1 + #Entities, wobei in ''FoundEntityIds[1]'' die Anzahl der gefundenen Entities steht. Wenn ''FoundEntityIds[1] == 0'' ist, ist das Table an der Stelle zuende. Andernfalls ist genau die Anzahl an EntityIds ebenfalls mit im Table (bei ''FoundEntities[1] == 4'' sind beispielsweise ''FoundEntities[2]'' bis ''FoundEntities[5]'' befüllt). Die größe des Tables ist dabei immer 1 + #Entities, wobei in ''FoundEntityIds[1]'' die Anzahl der gefundenen Entities steht. Wenn ''FoundEntityIds[1] == 0'' ist, ist das Table an der Stelle zuende. Andernfalls ist genau die Anzahl an EntityIds ebenfalls mit im Table (bei ''FoundEntities[1] == 4'' sind beispielsweise ''FoundEntities[2]'' bis ''FoundEntities[5]'' befüllt).
Zeile 123: Zeile 128:
 ====Beispiel Anwendungsfall==== ====Beispiel Anwendungsfall====
  
-Bestimmte Bäume durch tote Bäume ersetzen (Winter)+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 ''TreeNorth'' und ''DeadTreeNorth'' funktioniert das allerdings sehr gut. 
 + 
 +Wir ersetzen also in einem bestimmten Gebiet alle Entities vom Typ ''XD_TreeNorth1'' durch ''XD_DeadTreeNorth1'' (für ''TreeNorth2'' und ''3'' entsprechend auch). 
 + 
 +<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 eines Typs auf der Karte stehen, muss die Funktion an verschiedenen Stellen 
 +-- auf der Karte (möglicherweise wiederholt) aufgerufen werden 
 +function TreeNorthLoseLeaves(_Position, _Radius) 
 +    -- Wir definieren ein Table, das angibt, welche Baumtypen durch die blattlosen zu ersetzen sind 
 +    local ReplaceTypes = { 
 +        [Entities.XD_TreeNorth1] = Entities.XD_DeadTreeNorth1, 
 +        [Entities.XD_TreeNorth2] = Entities.XD_DeadTreeNorth2, 
 +        [Entities.XD_TreeNorth3] = Entities.XD_DeadTreeNorth3 
 +    } 
 +    for SummerTreeType, WinterTreeType in pairs(ReplaceTypes) do 
 +        local TreeIds = { Logic.GetEntitiesInArea(SummerTreeType, _Position.X, _Position.Y, _Radius, 16) } 
 +        -- 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 "Belohnungen" auf Ebene 2 
 +            ReplaceEntity(TreeIds[i], WinterTreeType) 
 +        end 
 +    end 
 +end 
 +</code> 
 + 
 +----
  
 =====Logic.GetPlayerEntities===== =====Logic.GetPlayerEntities=====
 +
 +''Logic.GetPlayerEntities(_PlayerId, _EntityType, _Amount)'' gibt höchstens ''_Amount'' Entity-Ids zurück, deren Entities vom Typ ''_EntityType'' sind und Spieler ''_PlayerId'' gehören. Die Entity-Suche ist nicht weiter beschränkt, bezieht sich also auf die komplette Karte.
 +
 +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 ''_EntityType''. Dabei entspricht die Anzahl der Rückgabewerte der Anzahl an gefundenen Entities und deshalb nicht notwendigerweise ''_Amount'' (wenn weniger als ''_Amount'' Entities vom Typ ''_EntityType'' auf der Karte existieren). \\
 +Das bedeutet, dass die Funktion genau 1 + #Entities Rückgabewerte hat.
 +
 +**Achtung**: ''_Amount'' ist auf den Maximalwert **16** beschränkt! Mehr Entity-Ids kann die Funktion nicht zurückgeben. Wenn du beispielsweise bei ''_Amount'' 20 angibst, werden trotzdem maximal 16 Entity-Ids zurückgegeben.
 +
 +Wie im Artikel zu [[ scripting:tutorials:level2:functions#mehrere_rueckgabewerte |mehreren Rückgabewerten]] beschrieben, können diese Rückgabewerte auf unterschiedliche Arten in Variablen geschrieben werden.
 +
 +===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, EntityId1, EntityId2 = Logic.GetPlayerEntities(1, Entities.PB_Monastery3, 2)
 +</code>
 +Die Funktion kann maximal 2 Kathedralen finden, aber auch weniger. Davon abhängig resultieren unterschiedliche Rückgabewerte: 
 +  * Wenn ''NumberOfEntities== 0'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' beide **nil**
 +  * Wenn ''NumberFoundEntities == 1'', dann ist ''EntityId1'' die Entity-Id einer Kathedrale und ''EntityId2'' ist **nil**
 +  * Wenn ''NumberFoundEntities == 2'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' Entity-Ids einer Kathedrale
 +
 +Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt auf der Karte existiert:
 +<code lua>
 +function IsPlayerEntityOfTypeOnMap(_PlayerId, _EntityType)
 +    -- Es ist guter Stil, mit dem Unterstrich anzuzeigen, dass dieser Wert ignoriert wird. 
 +    -- Auf der Logikebene macht es keinen Unterschied, für den Leser wird aber schneller ersichtlich, 
 +    -- welche Variablen von Bedeutung sind
 +    local NumberOfEntities, _ = Logic.GetPlayerEntities(_PlayerId, _EntityType, 1)
 +    return NumberOfEntities > 0
 +end
 +</code>
 +
 +===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, Entities.PB_Monastery3, 8) }
 +</code>
 +Die größe des Tables ist dabei immer 1 + #Entities, wobei in ''FoundEntityIds[1]'' die Anzahl der gefundenen Entities steht. Wenn ''FoundEntityIds[1] == 0'' ist, ist das Table an der Stelle zuende. Andernfalls ist genau die Anzahl an EntityIds ebenfalls mit im Table (bei ''FoundEntities[1] == 4'' sind beispielsweise ''FoundEntities[2]'' bis ''FoundEntities[5]'' befüllt).
  
 ====Beispiel Anwendungsfall==== ====Beispiel Anwendungsfall====
  
-Alle kleinen Wohnhäuser automatisch ausbauen+Ein großzügiger Architekt kommt in die Stadt und bietet an, alle kleinen Wohnhäuser für den Spieler zu mittleren Wohnhäusern auszubauen. Wir ermitteln die Entity-Ids aller Wohnhäuser von Spieler 1 mit ''Logic.GetPlayerEntities'' und bauen diese per Skript aus: 
 +<code lua> 
 +-- Wir hoffen in diesem Fall, dass der Spieler nicht mehr als 16 kleine Wohnhäuser hat 
 +local ResidenceIds = { Logic.GetPlayerEntities(1, Entities.PB_Residence1, 16) } 
 +-- 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 "Belohnungen" auf Ebene 2 
 +    ReplaceEntity(ResidenceIds[i], Entities.PB_Residence2) 
 +end 
 +</code> 
 + 
 +----
  
 =====Logic.GetPlayerEntitiesInArea===== =====Logic.GetPlayerEntitiesInArea=====
  
-Dafür brauchst du die Funktion ''Logic.GetPlayerEntitiesInArea(_playerId_entityType_posX_posY_range_amountaccessCategory)''. Damit kann man Entities eines Spielers in einem bestimmten Gebiet finden.+''Logic.GetPlayerEntitiesInArea(_PlayerId_EntityType_PositionX_PositionY_Radius_Amount_AccessCategory)'' gibt höchstens ''_Amount'' Entity-Ids zurück, deren Entities vom Typ ''_EntityType'' sind, höchstens den Abstand ''_Radius'' von der Position ''(_PositionX, _PositionY)'' haben und Spieler ''_PlayerId'' gehören. Der Parameter ''_AccessCategory'' ist optional und greift auch nur in einem Sonderfall, den wir [[ scripting:tutorials:level2:find_entities#beliebige_gebaeude_oder_einheiten_eines_spielers_im_gebiet_finden |weiter unten]] behandeln.
  
-Die Funktion gibt alle gefundenen Entities als EntityId einzeln auswas möglicherweise ein bisschen ungewohnt ist. Außerdem ist der erste Rückgabewert keine EntityId, sondern die Anzahl der gefundenen EntityIds.+Die Funktion gibt **mehrere** Werte zurückwovon der erste die Anzahl der gefundenen Entities ist und **deshalb keine gültige Entity-Id ist**! 
  
-Ein Beispielaufruf zur Anschauung, bei dem an Position {X=4200Y=4200} 2 kleine Wohnhäuser von Spieler 5 im Umkreis von 1500 Siedler-cm gesucht werden:+Alle weiteren Rückgabewerte sind Entity-Ids der gefundenen Entities vom Typ ''_EntityType''. Dabei entspricht die Anzahl der Rückgabewerte der Anzahl an gefundenen Entities und deshalb nicht notwendigerweise ''_Amount'' (wenn weniger als ''_Amount'' Entities vom Typ ''_EntityType'' auf der Karte existieren). \\ 
 +Das bedeutetdass die Funktion genau 1 + #Entities Rückgabewerte hat. 
 + 
 +**Achtung**: ''_Amount'' ist auf den Maximalwert **16** beschränkt! Mehr Entity-Ids kann die Funktion nicht zurückgeben. Wenn du beispielsweise bei ''_Amount'' 20 angibst, werden trotzdem maximal 16 Entity-Ids zurückgegeben. 
 + 
 +**Tipp**: Du kannst deinen gewünschten Radius durch [[ scripting:tutorials:level1:place_entities#ambient_sounds |Platzieren eines XS_Ambient]] auf die Position ermitteln. Das 100-fache der angegebenen Größe der Ambient-Entity entspricht genau dem anzugebenden ''_Radius''
 + 
 +Wie im Artikel zu [[ scripting:tutorials:level2:functions#mehrere_rueckgabewerte |mehreren Rückgabewerten]] beschriebenkönnen diese Rückgabewerte auf unterschiedliche Arten in Variablen geschrieben werden. 
 + 
 +**Hinweis**: Unabhängig von der verwendeten Variante sind die zurückgegebenen Entity-Ids nach dem Abstand zur Zielplosition sortiert - das nächstgelegene Entity zuerst. 
 + 
 +===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> <code lua>
-NumberFoundEntities, EntityId1, EntityId2 = Logic.GetPlayerEntitiesInArea(5, Entities.PB_Residence1420042001500, 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_Serf4900131003000, 2)
 </code> </code>
-(die accessCategory kann man weglassen)+Die Funktion kann maximal 2 Leibeigene finden, aber auch weniger. Davon abhängig resultieren unterschiedliche Rückgabewerte:  
 +  * Wenn ''NumberOfEntities== 0'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' beide **nil** 
 +  * Wenn ''NumberFoundEntities == 1'', dann ist ''EntityId1'' die Entity-Id eines Leibeigenen und ''EntityId2'' ist **nil** 
 +  * Wenn ''NumberFoundEntities == 2'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' Entity-Ids eines Leibeigenen
  
-Die Funktion kann maximal 2 Wohnhäuser findenaber auch weniger. Davon abhängig bekommst du unterschiedliche Rückgabewerte+Diese Variante eignet sich vor allemum zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist
- Wenn ''NumberFoundEntities == 0''dann sind sowohl ''EntityId1'' als auch ''EntityId2'' beide ''nil'' +<code lua> 
- Wenn ''NumberFoundEntities == 1''dann ist ''EntityId1'' die EntityId eines kleinen Wohnhauses von Spieler 5 im Gebiet und ''EntityId2'' ist ''nil'' +function IsPlayerEntityOfTypeInArea(_PlayerId, _EntityType, _Position, _Radius) 
- Wenn ''NumberFoundEntities == 2''dann sind sowohl ''EntityId1'' als auch ''EntityId2'' EntityIds eines kleinen Wohnhauses von Spieler 5 im Gebiet+    -- Es ist guter Stilmit dem Unterstrich anzuzeigen, dass dieser Wert ignoriert wird.  
 +    -- Auf der Logikebene macht es keinen Unterschied, für den Leser wird aber schneller ersichtlich,  
 +    -- welche Variablen von Bedeutung sind 
 +    local NumberOfEntities,Logic.GetPlayerEntitiesInArea(_PlayerId_EntityType, _Position.X, _Position.Y, _Radius, 1) 
 +    return NumberOfEntities > 0 
 +end 
 +</code>
  
-Wenn man mehr als 2 Gebäude sucht (in deinem Fall nicht, aber zur Vollständigkeit), bekommt man da eine riesige Schreibarbeit. Deshalb gibt man meistens die Ergebnisse der Funktion in ein Table, indem man um den Funktionsaufruf herum geschweifte Klammern setzt. Angenommen wir suchen stattdessen 10 Wohnhäuser:+===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> <code lua>
-FoundEntities = { Logic.GetPlayerEntitiesInArea(5, Entities.PB_Residence142004200150010) }+-- In diesem Beispiel suchen wir nach höchstens acht Mauertoren in einem größeren Gebiet 
 +local FoundEntityIds = { Logic.GetPlayerEntitiesInArea(Entities.PU_Serf49001310080008)) }
 </code> </code>
-In dem Fall ist ''FoundEntities[1]'' immer die Anzahl der gefundenen Entities und kann auch 0 seinDann ist das Table dort zuende. Wenn sie größer 0 ist, ist genau die Anzahl an EntityIds ebenfalls mit im Table (bei ''FoundEntities[1] == 4'' sind beispielsweise ''FoundEntities[2]'' bis ''FoundEntities[5]'' befüllt)+Die größe des Tables ist dabei immer 1 + #Entities, wobei in ''FoundEntityIds[1]'' die Anzahl der gefundenen Entities stehtWenn ''FoundEntityIds[1] == 0'' ist, ist das Table an der Stelle zuende. Andernfalls ist genau die Anzahl an EntityIds ebenfalls mit im Table (bei ''FoundEntities[1] == 4'' sind beispielsweise ''FoundEntities[2]'' bis ''FoundEntities[5]'' befüllt)
 + 
 + 
 +====Beispiel Anwendungsfall==== 
 + 
 +Wir führen das Beispiel aus [[ scripting:tutorials:level2:setup_quest#gebaeude_errichtensetupestablish |SetupEstablish]] fort und wollen im Callback der Quest die Kathedrale, das Wohnhaus und den Gutshof an Spieler 4 übergeben. Alle Namen, Positionen, etc. sind vom verlinkten Beispiel übernommen:
  
-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 bei Erfüllung der Quest aufgerufen 
--- Diese Funktion wird nach dem Bau der Garnision bei Position "kaserne" im Zusammenhang mit der Quest ??? aufgerufen  +-- Das Argument _QuestDescription ist das Quest-Tablemit dem die Quest definiert wurde 
--- Sie übergibt die errichtete Garnision an Spieler 2  +function CallbackQuestBuildCathedral(_QuestDescription
--- (usw. was auch immer noch folgt) +    -- Der Key AreaPos der _QuestDescription enthält den Skriptnamen der Position der Quest 
--Falls mal etwas nicht funktioniertkannst du anhand solcher Notizen schneller prüfen, ob die Funktion +    local QuestPosition = GetPosition(_QuestDescription.AreaPos
--- das tut, was sie soll +    -- Wir brauchen außerdem noch den Radius, innerhalb dessen die Kathedrale gebaut werden sollte 
-function Kasernefertig() +    local QuestRadius = _QuestDescription.AreaSize 
-    -- Du lässt die Kaserne an Position "kaserne" mit Umkreis 3000 Siedler-cm bauen. Die Position muss man erst + 
-    -- holen: +    -- die Art und Anzahl der Gebäudedie wir übergeben wollenist ebenfalls bereits in der Quest enthalten 
-    local QuestPosition = GetPosition("kaserne"+    for _, EntityRequirement in ipairs(_QuestDescription.EntityTypes) do 
-    -- Wir brauchen die Variablen hier nur lokalKein Grund, sie global zu definieren +        -- Eine Erklärung zur Funktion unpack findest du im Artikel zur Lua-Standardbibliothek verlinkt 
-    -- Die Position ist jetzt in QuestPosition, der Umkreis ist 3000Spieler hat Id 1 und wir suchen genau die eine Kaserne+        local EntityTypeAmount = unpack(EntityRequirement) 
-    -- die gebaut werden sollte +        local FoundEntities Logic.GetPlayerEntitiesInArea(_QuestDescription.Player, EntityType, QuestPosition.X, QuestPosition.Y, QuestRadiusAmount} 
-    local NumberFoundEntitiesEntityId1 = Logic.GetPlayerEntitiesInArea(1, Entities.PB_Barracks2, QuestPosition.X, QuestPosition.Y, 30001+ 
-    -- Wenn die Quest korrekt funktioniertsollte diese Bedingung immer zutreffen +        for i = 2FoundEntities[1] + 1 do 
-    if NumberFoundEntities > 0 then +            -- Wechsle die Spieler-Id der gefundenen Gebäude zu Spieler 
-        -- Wechsle die Spieler-Id der gefundenen Kaserne zu Spieler 2 +            -- Mehr Informationen zu ChangePlayer findest du in der Comfort-Referenz und 
-        ChangePlayer(EntityId12)+            -- im Artikel zu "Belohnungen" auf Ebene 
 +            ChangePlayer(FoundEntities[i]4) 
 +        end
     end     end
 end end
 </code> </code>
  
-====Beispiel Anwendungsfall====+====Beliebige Gebäude oder Einheiten eines Spielers im Gebiet finden====
  
-Gebäude nach Quest übergeben+Weiter oben wurde bereits der zusätzliche Parameter ''_AccessCategory'' erwähnt. ''Logic.GetPlayerEntitiesInArea'' ist die einzige "Entity-Suchfunktion", die diesen Parameter besitzt. Er wird dazu benutzt, Entities einer bestimmten Kategorie zu finden (im Wesentlichen Siedler oder Gebäude). Dazu **muss** als Entity-Typ ''0'' angegeben werden!
  
-====Beliebige Gebäude oder Einheiten eines Spielers im Gebiet finden====+Mit ''_AccessCategory'' 2 (für Siedler) oder ''_AccessCategory'' 8 (für Gebäude) können dann Entities der entsprechenden Kategorie gesucht werden. Wenn die ''_AccessCategory'' nicht angegeben wurde, beträgt sie standardmäßig 10, sodass sowohl nach beliebigen Siedlern als auch Gebäuden gesucht wird (denn 2 + 8 10). 
 + 
 +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, _Position, _Radius) 
 +    -- _EntityType muss 0 sein, um _AccessCategory verwenden zu können 
 +    -- Wir müssen nur 1 Entity der Kategorie 2 Siedler finden 
 +    local NumberOfEntities,Logic.GetPlayerEntitiesInArea(_PlayerId, 0, _Position.X, _Position.Y, _Radius, 1, 2) 
 +    return NumberOfEntities > 0 
 +end 
 + 
 +function IsPlayerBuildingInArea(_PlayerId, _Position, _Radius) 
 +    -- _EntityType muss 0 sein, um _AccessCategory verwenden zu können 
 +    -- Wir müssen nur 1 Entity der Kategorie 8 = Gebäude finden 
 +    local NumberOfEntities, _ = Logic.GetPlayerEntitiesInArea(_PlayerId, 0, _Position.X, _Position.Y, _Radius, 1, 8) 
 +    return NumberOfEntities > 0 
 +end 
 +</code> 
 + 
 +Man kann sie auch dafür verwenden, um beispielsweise alle Gebäude eines Spielers in einem bestimmten Gebiet zu zerstören: 
 +<code lua> 
 +function DestroyAllPlayerBuildingsInArea(_PlayerId, _Position, _Radius) 
 +    -- Initialisiere ein lokales Table 
 +    local FoundEntities {} 
 +    repeat 
 +        -- Suche alle Gebäude von Spieler _PlayerId im Bereich 
 +        FoundEntities { Logic.GetPlayerEntitiesInArea(_PlayerId, 0, _Position.X, _Position.Y, _Radius, 16, 8) } 
 +        -- 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 
 +</code> 
 + 
 +---- 
 + 
 +Dies war ein erster Ausflug in die ''Logic.''-Funktionen außerhalb des Comfort-Layers. Im nächsten Kapitel behandeln wir deutlich leichter zu hantierende Tribute. 
 + 
 +[[ scripting:tutorials:level2:rewards| Voriges Kapitel: Belohnungen ]] \\ 
 +[[ scripting:tutorials:level2:tribute | Nächstes Kapitel: Tribute ]] \\ 
 +[[ scripting:tutorials:level2:find_entities | Zurück nach oben ]]
scripting/tutorials/level2/find_entities.1699437691.txt.gz · Zuletzt geändert: 2023/11/08 10:01 von fritz_98