[[http://www.siedler-games.de|{{:sg-link.jpg|}}]]
====== GetAllPlayerBuildings ======
Hier mal ein "Funktionen-Paket" mittels dessen es möglich ist, sämtliche Gebäude des Spielers, also alle Entities von Player 1 die mit "PB_" beginnen, permanent in einem globalen Table (gvPlayerBuildings) zur Verfügung zu haben.
==== Erläuterung ====
Wenn man alle Gebäude des Spielers in einem globalen Table erfassen will, muss man zunächst einmal alle die Gebäude erfassen, die zu Spielbeginn bereits auf der Map vorhanden sind.
Dies erledigt die Funktion GetAllExistingBuildingsOnGameStart().
Nachdem diese also schon mal in unserem Table gespeichert sind, müssen wir ab jetzt die folgenden Ereignisse "überwachen":
* Spieler baut ein Gebäude
* Spieler erhält per Script ein Gebäude (entweder per [[reference:createentity|CreateEntity()]] oder [[reference:changeplayer|ChangePlayer()]])
Alle diese Ereignisse lösen das Event Events.LOGIC_EVENT_ENTITY_CREATED aus. Also starten wir in der FMA einen entsprechenden Trigger
Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_CREATED, "", "ActionOnEntityCreated", 1)
(da dieser ja das gesamte Spiel über laufen soll, brauchen wir uns auch die zurückgelieferte ID nicht in einer Variablen zu merken!)
Natürlich müssen wir auch die umgekehrten Ereignisse "überwachen":
* Spieler reißt ein Gebäude ab
* Spieler verliert per Script ein Gebäude (entweder per [[reference:destroyentity|DestroyEntity()]] oder [[reference:changeplayer|ChangePlayer()]])
Alle diese Ereignisse wiederum lösen das Event Events.LOGIC_EVENT_ENTITY_DESTROYED aus. Auch hierzu starten wir wiederum in der FMA einen entsprechenden Trigger
Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_DESTROYED, "", "ActionOnEntityDestroyed", 1)
Eine Besonderheit stellt der Fall dar, wenn der Spieler selbst ein Gebäude baut. Denn sobald der Bauauftrag erteilt wurde, werden sofort zwei neue Entities erstellt. Zum einen das "Baustellen-Entity" (ZB_ConstructionSitexyz), und zum anderen das eigentliche "Gebäude-Entity" (PB_xyz). Eigentlich ist es egal, ob man prüft, ob ein Gebäude bereits fertig gebaut wurde oder nicht, da auch ein Abriss während der Bauphase das Ereignis Events.LOGIC_EVENT_ENTITY_DESTROYED auslöst.
Ich habe mich allerdings dafür entschieden, dies doch getrennt zu betrachten, damit auch sichergestellt ist, dass wirklich alle in unserem globalen Table vorhandenen Gebäude auch tatsächlich "voll funktionsfähig", sprich komplett zu Ende gebaut sind.
Dafür werden die IDs von noch im Bau befindlichen Gebäuden zuerst in ein anderes Table gepackt. Wenn in diesem Table Elemente (also Gebäude-IDs) vorhanden sind wird, sofern er nicht bereits läuft, der SimpleJob "Job_ConstructionComplete" gestartet. Dieser prüft nun die entsprechenden Gebäude auf Fertigstellung. Ist diese erfolgt, wird die jeweilige ID in unser eigentliches Table gepackt und in dem anderen Table gelöscht. Sind keine Elemente mehr im Table vorhanden (also befinden sich gerade keine Gebäude im Bau), dann wird der Job beendet.
==== Code ====
Folgende Codezeilen müssen in die FMA (möglichst ganz zu Beginn):
function FirstMapAction()
gvBuildingTypes = {}
gvPlayerBuildings = {}
gvUnderConstruction = {}
GetAllExistingBuildingsOnGameStart()
Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_CREATED, "", "ActionOnEntityCreated", 1)
Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_DESTROYED, "", "ActionOnEntityDestroyed", 1)
-- Optional für Gebäude-Upgrades
GameCallback_OnBuildingUpgradeCompleteOrig = GameCallback_OnBuildingUpgradeComplete
GameCallback_OnBuildingUpgradeComplete = function (_oldId, _newId)
GameCallback_OnBuildingUpgradeCompleteOrig(_oldId, _newId)
Message("Upgrade Building complete! Old-Id: ".._oldId.." - New-Id: ".._newId)
end
-- hier folgt dann der weitere Code in der FMA
end
Diese Funktionen können an beliebiger Stelle (nur nicht innerhalb anderer Funktionen) ins Script eingefügt werden:
function ActionOnEntityCreated()
local createdEntityId = Event.GetEntityID()
if Logic.IsBuilding(createdEntityId) == 1 and GetPlayer(createdEntityId) == 1 and gvBuildingTypes[Logic.GetEntityType(createdEntityId)] then
if Logic.IsConstructionComplete(createdEntityId) ~= 1 then
table.insert(gvUnderConstruction, createdEntityId)
if JobIsRunning(JobId_ConstructionComplete) ~= 1 then
JobId_ConstructionComplete = StartSimpleJob("Job_ConstructionComplete")
end
else
table.insert(gvPlayerBuildings[Logic.GetEntityTypeName(Logic.GetEntityType(createdEntityId))], createdEntityId)
end
end
return
end
function ActionOnEntityDestroyed()
local destroyedEntityId = Event.GetEntityID()
if Logic.IsBuilding(destroyedEntityId) == 1 and GetPlayer(destroyedEntityId) == 1 and gvBuildingTypes[Logic.GetEntityType(destroyedEntityId)] then
local idRemoved = 0
if gvPlayerBuildings[Logic.GetEntityTypeName(Logic.GetEntityType(destroyedEntityId))] then
local entityTypeName = Logic.GetEntityTypeName(Logic.GetEntityType(destroyedEntityId))
for i = table.getn(gvPlayerBuildings[entityTypeName]), 1, -1 do
if destroyedEntityId == gvPlayerBuildings[entityTypeName][i] then
table.remove(gvPlayerBuildings[entityTypeName], i)
idRemoved = 1
end
end
end
if idRemoved ~= 1 then
for i = table.getn(gvUnderConstruction), 1, -1 do
if destroyedEntityId == gvUnderConstruction[i] then
table.remove(gvUnderConstruction, i)
idRemoved = 1
end
end
end
if idRemoved ~= 1 then
Message("Ein Fehler ist aufgetreten - die ID wurde nicht gefunden!")
end
end
return
end
function Job_ConstructionComplete()
if table.getn(gvUnderConstruction) > 0 then
for i = table.getn(gvUnderConstruction), 1, -1 do
if Logic.IsConstructionComplete(gvUnderConstruction[i]) == 1 then
table.insert(gvPlayerBuildings[Logic.GetEntityTypeName(Logic.GetEntityType(gvUnderConstruction[i]))], gvUnderConstruction[i])
table.remove(gvUnderConstruction, i)
end
end
else
EndJob(JobId_ConstructionComplete)
end
end
function GetAllExistingBuildingsOnGameStart()
table.foreach(Entities, function(key,value)
if string.find(key, "PB_") then
gvBuildingTypes[value] = true
gvPlayerBuildings[key] = {}
local temp = {Logic.GetPlayerEntities(1, value,1)}
if temp[1] > 0 then
local latestEntity = temp[2]
for i = 1, Logic.GetNumberOfEntitiesOfTypeOfPlayer(1, value) do
latestEntity = Logic.GetNextEntityOfPlayerOfType(latestEntity);
if latestEntity ~= 0 then
table.insert(gvPlayerBuildings[key], latestEntity)
end
end
end
end
end)
end
==== Anwendungsbeispiele ====
FIXME: Hier sollten noch ein paar Beispiele zur praktischen Verwendung hin! Wer welche kennt - nur zu!
==== Forums-Beitrag ====
Den entsprechenden Beitrag im Siedler-Portal Forum findet ihr [[http://siedler-portal.de/vb3/showthread.php?t=13269|hier]]!