Are these API set out correctly?

Craig_Sutter

Deity
Joined
Aug 13, 2002
Messages
2,773
Location
Calgary, Canada
I am getting some unexpected print statements from a bit of code I am using. The intent is to check for a religion and check faith cost for a building vrs player's faith and ability to purchase, then to force buy the building if there is enough faith.

Code:
function BerserkerHallPurchase (iPlayer)
	
	local pPlayer = Players[iPlayer] 
	if (pPlayer:IsAlive ()) and not pPlayer:IsHuman() then		
			
		for pCity in pPlayer:Cities() do
				
			if pCity:GetReligiousMajority() == GameInfoTypes["RELIGION_CONFUCIANISM"] then	
					
				local iBuilding = GameInfoTypes.BUILDING_PAGODA
				local iBuildingCost = pCity:GetBuildingFaithPurchaseCost(iBuilding)
				local currentFaith = pPlayer:GetFaith()
				if not pCity:IsHasBuilding( iBuilding ) and pCity:IsCanPurchase(true, true, -1, iBuilding, -1, YieldTypes.YIELD_FAITH) and currentFaith >= iBuildingCost then

				Game.CityPurchaseBuilding(pCity, iBuilding, YieldTypes.YIELD_FAITH);		
				print(pPlayer:GetName(), " is installing Berserker Hall in ", pCity:GetName());
						
				end
			end
		end
	end	
end

And I may get a print statement like...

Code:
[15531.927] Cities: Alfred	 is installing Order Chapterhouse in 	Winchester
[15531.927] Cities: Alfred	 is installing Order Chapterhouse in 	Southampton
[15531.927] Cities: Alfred	 is installing Order Chapterhouse in 	Oxford
[15531.927] Cities: Alfred	 is installing Order Chapterhouse in 	Dorchester
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Glastonbury
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Exeter
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Llandrindad
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Gloucester
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Caerwent
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Edington
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Wroxeter
[15531.943] Cities: Alfred	 is installing Order Chapterhouse in 	Wareham
[15531.958] Cities: Alfred	 is installing Order Chapterhouse in 	Shaftesbury
[15531.958] Cities: Alfred	 is installing Order Chapterhouse in 	Chippenham

... repeated over several turns.

Which makes no sense as some of those cities have an Order Chapterhouse installed already and there is no way that enough faith could be acquired in a turn to pay for all those buildings even if none of the cities had a building already.

Which leads me to believed that one of the API functions below is firing unexpectedly...

I have matched each API against its wiki entry... it seems to me that they do not match up as far as how true/false entries match other variables. I did not create the entries, but copied ones that worked. And the functions seem to be working when I play test... but not when I set up autoplay.

Code:
pCity:IsCanPurchase(true, true, -1, iBuilding, -1, YieldTypes.YIELD_FAITH)

City:IsCanPurchase(UnitType unitType, int buildingType, int projectType, int projectID, int projectID = nil, YieldType yield = nil)

Code:
Game.CityPurchaseBuilding(pCity, iBuilding, YieldTypes.YIELD_FAITH);

Game.CityPurchaseBuilding(City city, UnitType unitType, int buildingType, ProjectType projectTypes)


There is another possibility in that the purchase restriction is not functioning correctly for religious buildings... maybe there is an unexpected problem in the actual functioning of the lua API, and it is not restricting purchases properly specifically for FAITH due to errors in the lua programming.

Thank-you.
 
In order to better debug what is happening, I re-wrote your code a little and pasted this into one of my mods:
Code:
function BerserkerHallPurchase (iPlayer)
	local pPlayer = Players[iPlayer] 
	for pCity in pPlayer:Cities() do
		print("for the city of " .. pCity:GetName() .. ":")
		local iBuilding = GameInfoTypes.BUILDING_PAGODA
		local iBuildingCost = pCity:GetBuildingFaithPurchaseCost(iBuilding)
		print("iBuildingCost = " .. iBuildingCost)
		local currentFaith = pPlayer:GetFaith()
		print("currentFaith = " .. currentFaith)
		local bCityHasPagoda = pCity:IsHasBuilding( iBuilding )
		if bCityHasPagoda then
			print("City has a GameInfoTypes.BUILDING_PAGODA")
		else
			print("City does not have a GameInfoTypes.BUILDING_PAGODA")
			if pCity:IsCanPurchase(true, true, -1, iBuilding, -1, YieldTypes.YIELD_FAITH) then
				print("City can puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result")
				Game.CityPurchaseBuilding(pCity, iBuilding, YieldTypes.YIELD_FAITH)
				if pCity:IsHasBuilding( iBuilding ) then
					print("City has a GameInfoTypes.BUILDING_PAGODA after the forced building purchase")
				else
					print("City does not have a GameInfoTypes.BUILDING_PAGODA after the forced building purchase")
				end
			else
				print("City cannot puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result")
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(BerserkerHallPurchase)
After using IGE to give me enough Faith to purchase one Pagoda (I had conveniently already managed to get the Pagodas belief), this is the print-out I got to the lua.log:
Code:
[391692.671] KatieBuff: for the city of Moscow:
[391692.687] KatieBuff: iBuildingCost = 200
[391692.687] KatieBuff: currentFaith = 247
[391692.687] KatieBuff: City does not have a GameInfoTypes.BUILDING_PAGODA
[391692.687] KatieBuff: City can puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result
[391692.687] KatieBuff: City does not have a GameInfoTypes.BUILDING_PAGODA after the forced building purchase
[391692.703] KatieBuff: for the city of St. Petersburg:
[391692.703] KatieBuff: iBuildingCost = 200
[391692.703] KatieBuff: currentFaith = 247
[391692.703] KatieBuff: City does not have a GameInfoTypes.BUILDING_PAGODA
[391692.703] KatieBuff: City cannot puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result
[391692.703] KatieBuff: for the city of Novgorod:
[391692.703] KatieBuff: iBuildingCost = 200
[391692.718] KatieBuff: currentFaith = 247
[391692.718] KatieBuff: City does not have a GameInfoTypes.BUILDING_PAGODA
[391692.718] KatieBuff: City cannot puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result
[391692.718] KatieBuff: for the city of Rostov:
[391692.718] KatieBuff: iBuildingCost = 200
[391692.718] KatieBuff: currentFaith = 247
[391692.734] KatieBuff: City does not have a GameInfoTypes.BUILDING_PAGODA
[391692.734] KatieBuff: City cannot puchase a GameInfoTypes.BUILDING_PAGODA via pCity:IsCanPurchase method result
  • Only Moscow at that time had my religion (ie, ability to purchase Pagodas)
  • Moscow was given the Pagoda as an auto-purchase
  • When turn processing was completed, my Faith score had 200 deducted for the cost of the Pagoda from my faith amount.
  • One would intuitively expect after the forced auto-purchase of the Pagoda that my Faith would have been reported as "47", but for the other cities in my empire this was not true
  • Game.CityPurchaseBuilding(pCity, iBuilding, YieldTypes.YIELD_FAITH) is deducting the Faith but is not doing so until after PlayerDoTurn events are processed. [edit]Or, at least, appears not to be executed until after the originating PlayerDoTurn event is completed. [endedit] The same appears to be true with actually adding the building(s) to the cities for which Game.CityPurchaseBuilding is executed. It is not therefore a 'realtime event', so is most likely the root cause of your troubles.
  • Also note that the pCity:IsHasBuilding( iBuilding ) is not updating the status until after the PlayerDoTurn is completed processing, most likely because the Game.CityPurchaseBuilding is not actually executing 'in real time' so far as the PlayerDoTurn event is concerned.
 
I wonder if switching to getnumberofrealbuildings = 0 with a counter of some type might address the building detection issue? I am not home right noe, so cannot check. The faith detection in realtime might be addressed or ignored rather, by having the code break after the first successful run through-- I don't really care if the building is not installed in all criteria fulfilling cities all at once... that it adds them incrementally is sufficient.

I will fiddle with alternate methods when I get home... worst comes to worst I can brute force building placement with setnobuildings and directly deduct faith.
 
If you are wondering why I have created this code when the AI purchases buildings on its own... I am tired of checking the AI and finding 1000s of unspent points. As well, one of my religions has 2 faith based buildings, however, it seems as if the AI does not like to purchase 2 in one city and seems to asidiously avoid it.
 
Game.CityPurchaseBuilding() et al, generates a network event. Networks events are sent to all systems in the game, to maintain synchronisation. This is required for multi-player, but is a PITA for single player and modding. Events are processed in sequence, the next does not start until the previous one finishes. It's the sequencing of events that's causing the issue.

The same is true if you cause a non-game event to trigger during event processing, eg the events update the map (such as the improvement/route created/destroyed ones).

Using SetNumRealBuildings() and deducting the faith directly will solve the problem, but expect complaints from anybody trying to merge your mod/civ into a multi-player pseudo-dlc.
 
Ahh... another landmine to watch out for.

Well, I think I'll keep the Game.CityPurchaseBuilding stuff... I will just break the code after the 1st successful run through. The code is for the AI players in any case, so building a structure in one city per turn is fine. The faith check and building checks are okay for the first build anyhow, as far as I know.

First, I'll introduce LeeS' error checking code, and make changes using that and go from there.

I'm assuming "break" after "Game.CityPurchaseBuilding(pCity, iBuilding, YieldTypes.YIELD_FAITH)YieldTypes.YIELD_FAITH)" will be sufficient to stop the code after one successful city iteration...
 
Back
Top Bottom