======Spieler-Einheiten und -Gebäude finden======
Es gibt verschiedene Anwendungsfälle, in denen man bestimmte Gebäude oder Einheiten eines Spielers auf der Karte finden möchte. Beispielsweise könnte man ermitteln, wie viele Kanonentürme ein Spieler besitzt oder wie stark seine Militärpräsenz in einem gegebenen Gebiet ist. Auch im Zusammenhang mit [[ scripting:tutorials:level2:setup_quest#gebaeude_errichtensetupestablish |SetupEstablish]] wird so eine Funktion oft gebraucht, um das vom Spieler gebaute Gebäude dem Spieler des Auftraggebers zu überreichen.
In diesem Artikel wollen wir deshalb einige Funktionen beleuchten, die Spieler-Einheiten und -Gebäude nach einstellbaren Kriterien finden. Konkret werden bei jeder dieser Funktionen die [[ scripting:tutorials:level1:place_entities#exkursentity-id_vs_skriptname |Entity-Ids]] jener Entities ermittelt, auf die die Kriterien (wie zum Beispiel Ort und Entity-Typ) zutreffen.
Auch handelt es sich bei den folgenden Funktionen um ''Logic.''-Funktionen, sind also nicht mehr innerhalb des [[ scripting:reference:comfort |Comfort-Layers]]. Das bedeutet, dass wir Skriptnamen und Positions-Tables händisch verarbeiten müssen, da das nicht mehr automatisch im Hintergrund geschieht. Auch werden diese Funktionen mit [[ scripting:tutorials:level2:functions#mehrere_rueckgabewerte |mehreren Rückgabewerten]] und [[ scripting:tutorials:level2:functions#zu_viele_und_zu_wenige_parameter |optionalen Parametern]] arbeiten. Die entsprechenden Stellen im verlinkten Artikel sollten also geläufig sein.
----
=====Logic.GetEntities=====
''Logic.GetEntities(_EntityType, _Amount)'' gibt höchstens ''_Amount'' Entity-Ids zurück, deren Entities vom Typ ''_EntityType'' sind. 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:
-- In diesem Beispiel suchen wir nach höchstens zwei Tempelaltären
local NumberOfEntities, EntityId1, EntityId2 = Logic.GetEntities(Entities.XD_TemplarAltar, 2)
Die Funktion kann maximal 2 Tempelaltäre 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 Tempelaltars und ''EntityId2'' ist **nil**
* Wenn ''NumberFoundEntities == 2'', dann sind sowohl ''EntityId1'' als auch ''EntityId2'' Entity-Ids eines Tempelaltars
Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt auf der Karte existiert:
function IsEntityTypeOnMap(_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.GetEntities(_EntityType, 1)
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:
-- In diesem Beispiel suchen wir nach höchstens acht Tempelaltären
local FoundEntityIds = { Logic.GetEntities(Entities.XD_TemplarAltar, 8) }
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====
Um die Siedlungsplätze auf unserer Karte etwas heimeliger zu machen, wollen wir vor jedem eine kleine Sitzbank aufstellen. Mit ''Logic.GetEntities'' holen wir uns die Entity-Ids aller Siedlungsplätze, emitteln anhand der Ids deren Position und stellen versetzt zu diesen Positionen Bänke auf.
function PlaceBenches()
-- es sollten nicht mehr als 16 Siedlungsplätze auf der Karte sein
local VillageCenterIds = { Logic.GetEntities(Entities.XD_VillageCenter, 16) }
-- Im ersten Eintrag vom Table VillageCenterIds 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, VillageCenterIds[1] + 1 do
local VCPosition = GetPosition(VillageCenterIds[i])
-- 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
-- Die Parameter sind dafür etwas anders, siehe die Logic-Referenz
Logic.CreateEntity(Entities.XD_MiscBank1, VCPosition.X + 300, VCPosition.Y - 600, 0, 0)
end
end
----
=====Logic.GetEntitiesInArea=====
''Logic.GetEntitiesInArea(_EntityType, _PositionX, _PositionY, _Radius, _Amount)'' gibt höchstens ''_Amount'' Entity-Ids zurück, deren Entities vom Typ ''_EntityType'' sind und höchstens den Abstand ''_Radius'' von der Position ''(_PositionX, _PositionY)'' haben.
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.
**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.
**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:
-- In diesem Beispiel suchen wir nach höchstens zwei Mauertoren im Gebiet
local NumberOfEntities, EntityId1, EntityId2 = Logic.GetEntitiesInArea(Entities.XD_WallStraightGate, 4900, 13100, 3000, 2)
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 ''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 Mauertors
Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist:
function IsEntityTypeInArea(_EntityType, _Position, _Radius)
-- 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.GetEntitiesInArea(_EntityType, _Position.X, _Position.Y, _Radius, 1)
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:
-- In diesem Beispiel suchen wir nach höchstens acht Mauertoren in einem größeren Gebiet
local FoundEntityIds = { Logic.GetEntitiesInArea(Entities.XD_WallStraightGate, 4900, 13100, 8000, 8)) }
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====
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).
-- 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
----
=====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:
-- In diesem Beispiel suchen wir nach höchstens zwei Kathedralen von Spieler 1
local NumberOfEntities, EntityId1, EntityId2 = Logic.GetPlayerEntities(1, Entities.PB_Monastery3, 2)
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:
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
===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:
-- In diesem Beispiel suchen wir nach höchstens acht Kathedralen
local FoundEntityIds = { Logic.GetPlayerEntities(1, Entities.PB_Monastery3, 8) }
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====
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:
-- 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
----
=====Logic.GetPlayerEntitiesInArea=====
''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 **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.
**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.
**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:
-- 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 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
Diese Variante eignet sich vor allem, um zu prüfen, ob ein Entity-Typ überhaupt im gegebenen Gebiet vorhanden ist:
function IsPlayerEntityOfTypeInArea(_PlayerId, _EntityType, _Position, _Radius)
-- 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.GetPlayerEntitiesInArea(_PlayerId, _EntityType, _Position.X, _Position.Y, _Radius, 1)
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:
-- In diesem Beispiel suchen wir nach höchstens acht Mauertoren in einem größeren Gebiet
local FoundEntityIds = { Logic.GetPlayerEntitiesInArea(Entities.PU_Serf, 4900, 13100, 8000, 8)) }
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====
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:
-- Der Funktionsname CallbackQuestBuildCathedral wurde als Callback bei der Definition der Quest angegeben
-- Die Funktion wird automatisch bei Erfüllung der Quest aufgerufen
-- Das Argument _QuestDescription ist das Quest-Table, mit dem die Quest definiert wurde
function CallbackQuestBuildCathedral(_QuestDescription)
-- Der Key AreaPos der _QuestDescription enthält den Skriptnamen der Position der Quest
local QuestPosition = GetPosition(_QuestDescription.AreaPos)
-- Wir brauchen außerdem noch den Radius, innerhalb dessen die Kathedrale gebaut werden sollte
local QuestRadius = _QuestDescription.AreaSize
-- die Art und Anzahl der Gebäude, die wir übergeben wollen, ist ebenfalls bereits in der Quest enthalten
for _, EntityRequirement in ipairs(_QuestDescription.EntityTypes) do
-- Eine Erklärung zur Funktion unpack findest du im Artikel zur Lua-Standardbibliothek verlinkt
local EntityType, Amount = unpack(EntityRequirement)
local FoundEntities = { Logic.GetPlayerEntitiesInArea(_QuestDescription.Player, EntityType, QuestPosition.X, QuestPosition.Y, QuestRadius, Amount) }
for i = 2, FoundEntities[1] + 1 do
-- Wechsle die Spieler-Id der gefundenen Gebäude zu Spieler 4
-- Mehr Informationen zu ChangePlayer findest du in der Comfort-Referenz und
-- im Artikel zu "Belohnungen" auf Ebene 2
ChangePlayer(FoundEntities[i], 4)
end
end
end
====Beliebige Gebäude oder Einheiten eines Spielers im Gebiet finden====
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!
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:
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
Man kann sie auch dafür verwenden, um beispielsweise alle Gebäude eines Spielers in einem bestimmten Gebiet zu zerstören:
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] == 0
end
----
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 ]]