What happens when a building is constructed?

bouncymischa

Synthetic Genie
Joined
Nov 28, 2012
Messages
1,537
Location
In a bottle
I've been trying to start learning Lua, and figured a good starting point would be to implement the trait from Hambil's tutorial here. However, I'm running into problems getting the lua function to execute, so I suspect I'm missing something in the enormous amount of Lua code the CivUP project used.

I know the Lua code is loading and executing as the print statement at the start executes, but the function itself never seems to get called. I can't get FireTuner to work, so I can't test it out that way. I took at look at the modiki, but it's difficult to navigate through with bunches of the material missing or causing errors. As near as I can tell, the event I'm trying to tie the event to doesn't exist.

This is the code I'm trying to use:

Code:
function BuildingCreated(player, city, buildingID)
	local playerID		= player:GetID()
	local plot			= city:Plot()

	local buildingInfo	= GameInfo.Buildings[buildingID]
	local query			= ""
	local trait			= player:GetTraitInfo()
	
	print("***[ Calling BuildingCreated ]***")
	
	if city:IsCapital() then
		for row in GameInfo.Trait_YieldFromConstructionInCapital() do
			if trait.Type == row.TraitType and buildingInfo.Type == row.BuildingType then

				if row.Yield ~= 0 then
					player:ChangeYieldStored(GameInfo.Yields[row.YieldType].ID, row.Yield)
					--log:Debug("+%s %s from science building constructed in %s", row.Yield, GameInfo.Yields[row.YieldType].Type, city:GetName())
				end
				if row.YieldMod ~= 0 then
					local prereqTech = buildingInfo.PrereqTech or "TECH_AGRICULTURE"
					local yieldAdded = row.YieldMod/100 * GameInfo.Technologies[prereqTech].Cost * Game.GetSpeedInfo().ResearchPercent/100
					player:ChangeYieldStored(GameInfo.Yields[row.YieldType].ID, yieldAdded)
					--log:Debug("+%s %s from science building constructed in %s", yieldAdded, GameInfo.Yields[row.YieldType].Type, city:GetName())
				end
			end
		end
	end
	
	for row in GameInfo.Trait_YieldFromConstruction() do
		if trait.Type == row.TraitType and buildingInfo.Type == row.BuildingType then
			local yieldInfo = GameInfo.Yields[row.YieldType]
			City_ChangeYieldStored(city, yieldInfo.ID, row.Yield)
			if playerID == Game.GetActivePlayer() then
				Events.GameplayAlertMessage(string.format(
					"%s gained %s %s %s from constructing a %s.",
					city:GetName(),
					row.Yield, 
					yieldInfo.IconString,
					Locale.ConvertTextKey(yieldInfo.Description),
					Locale.ConvertTextKey(buildingInfo.Description)
				))
			end
		end
	end
end

LuaEvents.BuildingConstructed.Add( BuildingCreated )

Looking at the modiki, I can't find any sign of "BuildingConstructed" in the event handlers, so I'm not sure if it's something in the CivUP code and not an event in the core game, or what... so I'm wondering what events DO trigger when a building is constructed? I'm assuming this code could be linked to them...
 
Definitely NOT a core event (those are usually GameEvents/Events), so probably something added by CivUP
 
Bleagh. I took another look through the CivUP files, and you do seem to be right -- there's a file that appears to define a whole ton of unique Lua functions. Trying to look through the modiki again, I can't seem to find anything that might trigger when a building is completed, so I'm guessing that trying to get this code is going to be a lot harder than I thought, probably too difficult for a novice like myself. :(
 
Would the function City.IsHasBuilding work, as from the name I can assume it registers when a city has a specific building - which it would, obviously, after the building has been built?

EDIT: Or maybe you could do something along the lines of "if (pCity:GetNumRealBuilding(pBuilding) == 1) then" - of course, you'd have to define pCity and pBuilding. Would that work too?
 
It would, but the check for IsHasBuilding would need to be linked to a game event, of which none exist for when a building is completed.

The only way I have checked building completion is via PlayerDoTurn and that is by calling the above function. In my case if a player completes an industrial building type, a manufactory would be automatically placed near the city.
 
It would, but the check for IsHasBuilding would need to be linked to a game event, of which none exist for when a building is completed.
I guess I forgot that City.IsHasBuilding is a condition so can't be used as an event - or can it, in some bizarre case?
 
I managed to find a solution in Pouakai's Tuscany civ, since its UA triggers whenever a building with Great Work slots is constructed. The method he used, at least, is to use saveutils to log whenever a building is constructed, then at the start of the player's turn it steps through each building to see whether or not the building existed in the previous turn. If not, it executes the appropriate code.

His version only checked the capital, but I got a version to work that checks each city for new construction. Admittedly, so far I only know how to generate a new unit in the city, so my code generates a free Worker when a Granary is built. It's also not very modular -- while I'm pretty sure it's possible to tie an array of buildings and units to a trait the way Hambil's code did, I haven't been able to figure it out yet. Still, it's my first functioning bit of Lua code, so I'm happy with that.

Not sure if I should post the final code here for people to take a look at, particularly since it's just derived from Pouakai's code... but it may be helpful for people in the future who want the same kind of function.
 
:lol: if that's all you want to do, you can simply use the XML <Building_FreeUnits> table to generate free units upon completion of specific buildings.

True, but that would mean needing to make a UB replacement for each building I wanted to add the <Building_FreeUnits> code to, unless I wanted everyone to get a free unit upon completing a certain building.

Another factor is that so far I only know how to create units, because that's what Pouakai's code did. But I'm hoping to figure out how to change a player's faith and other values next, so once I've figured out that, I could use the same code to, say, give a player a faith bonus when he completes a faith-related building, or something.
 
Not sure if I should post the final code here for people to take a look at, particularly since it's just derived from Pouakai's code... but it may be helpful for people in the future who want the same kind of function.
Actually, I'm the author the Lua used in the Tuscan civ, not Pouakai, though truth be told, Putmalk basically walked me through all the code for the entirety of the UA since I'd never coded Lua before that.

Feel free to post it.

Be forewarned! Depending on how much you've used my code as a basis, it'll only trigger the first time it's built (i.e. you can't sell and rebuild/rebuy to trigger the effect again)

But I'm hoping to figure out how to change a player's faith and other values next, so once I've figured out that, I could use the same code to, say, give a player a faith bonus when he completes a faith-related building, or something.

Player:ChangeFaith() should work for that. You can check the Modiki if you need other functions
 
Actually, I'm the author the Lua used in the Tuscan civ, not Pouakai, though truth be told, Putmalk basically walked me through all the code for the entirety of the UA since I'd never coded Lua before that.

Feel free to post it.

Be forewarned! Depending on how much you've used my code as a basis, it'll only trigger the first time it's built (i.e. you can't sell and rebuild/rebuy to trigger the effect again)

Ahh, sorry about that! I'll give you credit, then. :3

I noticed that the trigger was designed to only go off when the building was first made, and figured that it was intentional -- otherwise you could just sell and then rebuild a particular building to keep spamming its triggers.

Player:ChangeFaith() should work for that. You can check the Modiki if you need other functions

I was figuring that was probably the necessary code -- haven't had much chance to play around with SDK to test it yet.
 
Back
Top Bottom