[[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]]!