Inhaltsverzeichnis

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“:

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“:

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 hier!