XML for city-connections or internal trading?

Damirith

Prince
Joined
Mar 11, 2015
Messages
379
Is there any XML code that can be used for buildings that applies a production bonus to cities with a connection to the capital? Pretty much like as if you had built railroad between the two cities, but that the bonus is coming from the building.

What about any XML that allows a building to increase the production, food, or religious pressure that you can trade among your own cities with a internal trade route?

Or am I going back to LUA writing? :D
 
Macchavielli designed some lua-code so that policies can give dummy buildings. He used it in his Reform and Rule mod.

I added some more cases where a policy can give a dummy building in every city with a connection to the Capital, and retrieve it when the policy is blocked or the connection broken.

If it answers your case, I can provide you with the files.
 
Sure! Yeah that would be great. I am still lost with writing LUA so seeing other examples helps me to figure out how the language functions.
 
Sorry for the late answer, I was out in the past days.

Here are the files.

You just have to copy it to your mod : the SQL file with Action / on mod activated / Update Database. The lua file with Content / InGameUIAddin.

Here is an example of a "Prefecture" Policy I have designed for a Classical Civ Scenario I am working on. It gives +2 :c5production: Production in cities with a connection to the Capital.

Code:
-- let's define the building class first
INSERT INTO BuildingClasses ( Type , DefaultBuilding , Description ) VALUES ( 'BUILDINGCLASS_PREFECTURES' , 'BUILDING_PREFECTURES' , 'TXT_KEY_POLICY_CENTRALISM_HELP'  ) ; 

-- let's define the building
INSERT INTO Buildings ( Type ,						BuildingClass ,					Cost ,	NeverCapture,	NukeImmune ,IconAtlas ,		PortraitIndex ,	Description 					) 
VALUES			      (	'BUILDING_PREFECTURES' ,	'BUILDINGCLASS_PREFECTURES' ,	 -1 ,	1 ,				1 ,			'BW_ATLAS_1' ,	19 ,			'TXT_KEY_POLICY_BRANCH_TRADITION'  ) ;

-- the building gives +2 Production  
INSERT INTO Building_YieldChanges ( BuildingType, YieldType, Yield ) 
VALUES ( 'BUILDING_PREFECTURES' , 'YIELD_PRODUCTION' , 2 ) ; 

-- so that the building is not visible in the civy view :
UPDATE Buildings SET GreatWorkCount = -1 WHERE Type = 'BUILDING_PREFECTURES' ; 

-- now fill the adequate table
INSERT INTO Policy_FreeBuildingClassIfCapitalConnected ( PolicyType , BuildingClassType ) 
VALUES ( 'POLICY_PREFECTURES' , 'BUILDINGCLASS_PREFECTURES' )  ; 

-- flavor of the policy
INSERT INTO Policy_Flavors ( PolicyType, FlavorType, Flavor) VALUES ( 'POLICY_PREFECTURES' , 'FLAVOR_EXPANSION', 10 ) ; 
INSERT INTO Policy_Flavors ( PolicyType, FlavorType, Flavor) VALUES ( 'POLICY_PREFECTURES' , 'FLAVOR_PRODUCTION', 10 ) ;
 

Attachments

Ok, so I have been looking through this code as well as the Dummy Building guide by LeeS and I am a bit lost and also trying to piece together what I actually need for this to work.

In the end I would like to have it that when you build/control the wonder, all cities connected will have +4 production.

In the xml of my wonder, I have added the building class, type, the +4 production, etc. under "BUILDING_HOOVERDAM_MARKER" as instructed by LeeS's guide on how to make a dummy building.

Now its a matter of completing the parts:
A) Telling the game to put the dummy building in all cities with a city connection when the wonder is built
B) Make sure the dummy building is being added to new cities that get connected
C) Make sure the dummy building is removed when the city-connections are broken

This is what LUA I have pieced together so far. Will this accomplish Part A?

Code:
aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER

function HooverDamBuilt(playerId, cityId, buildingType, bGold, bFaithOrCulture)
	local player = Players[playerId];
	local city = player:GetCityByID(cityID)
	local buildingType;

	if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

		if (not city:IsCapital() and player:IsCapitalConnectedToCity(city) and not city:IsBlockaded()) then
				city:SetNumRealBuilding(aHooverDummy, 1);
			end
	end
end
GameEvents.CityConstructed.Add(HooverDamBuilt);
 
That code has a critical error that will cause it to fail:

Code:
function HooverDamBuilt(playerId, [B][COLOR="Red"]cityId[/COLOR][/B], buildingType, bGold, bFaithOrCulture)
	local player = Players[playerId];
	local city = player:GetCityByID([B][COLOR="Red"]cityID[/COLOR][/B])

'cityID' doesn't exist, so it will fail because you've actually defined 'cityId' instead. Moral of the story: Lua is case-sensitive.

Otherwise, while SetNumRealBuilding() is the correct method to use to provide free buildings (not necessarily dummies, but dummies are part of the set of all buildings,) you have the logic for it set incorrectly in terms of what you intend for it to do.

The logic in that code only fires once - when the Wonder is completed. This inherently means it cannot do parts B and C for you, because it will never run again. Furthermore, that particular function only ever calls one City -- the City in which the Wonder was built. Thus, that code will only ever place a single dummy building in the one City that the Wonder was built in.

What you want to do is to loop through the Player's Cities (using the pPlayer:Cities() iterator) and apply your logic there. Parts B and C can be done with PlayerDoTurn checks over all Cities with the same logic.
 
Yeah I knew I was only writing this for Part A and that I would need more functions to do B and C.

So how can I prevent the dummy from going into the city the wonder was built? I DONT want it there, I only want the dummies in all the other cities connected. I was thinking " if not city:IsCapital() and " would take care of this but then again they might not build the wonder in the capital.

On a side note, is there some setting I need to turn on to better catch my case-sensitive errors? I would have thought the debug would have pointed that out.

Any better?

Code:
aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER

function HooverDamBuilt(playerId, cityId, buildingType, bGold, bFaithOrCulture)
	local pPlayer = Players[playerId];

	if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

	for pCity in pPlayer:Cities()
		if (pPlayer:IsCapitalConnectedToCity(city) and not city:IsBlockaded()) then
				city:SetNumRealBuilding(aHooverDummy, 1);
			end
	end
end
GameEvents.CityConstructed.Add(HooverDamBuilt);
 
Yeah I knew I was only writing this for Part A and that I would need more functions to do B and C.

So how can I prevent the dummy from going into the city the wonder was built? I DONT want it there, I only want the dummies in all the other cities connected. I was thinking " if not city:IsCapital() and " would take care of this but then again they might not build the wonder in the capital.

On a side note, is there some setting I need to turn on to better catch my case-sensitive errors? I would have thought the debug would have pointed that out.

Any better?

Code:
aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER

function HooverDamBuilt(playerId, cityId, buildingType, bGold, bFaithOrCulture)
	local pPlayer = Players[playerId];

	if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

	for pCity in pPlayer:Cities()
		if (pPlayer:IsCapitalConnectedToCity(city) and not city:IsBlockaded()) then
				city:SetNumRealBuilding(aHooverDummy, 1);
			end
	end
end
GameEvents.CityConstructed.Add(HooverDamBuilt);
Getting better. City method pCity:IsHasBuilding(GameInfoTypes["BUILDING_HOOVER_DAM"]) will tell you whether or not an individual city has the Hoover Dam World Wonder. It will give you a true/false result, so if I wanted to disable the city that has the Hoover Dam wonder in it, I would add an "if not xxxx then xxxx end" block of code so that the player's city that has the Hoover Dam will not get the marker, and I would probably wrap that around the line city:SetNumRealBuilding(aHooverDummy, 1);

In your "for" loop looking through the player's cities, you have another mismatch of variable names: pCity is not equal in lua to city. Your "for" line is telling the lua that each individual city a player has will be referenced within the "for" loop as pCity, therefore all references to a player's individual cities must also be referred to using pCity.
 
On a side note, is there some setting I need to turn on to better catch my case-sensitive errors? I would have thought the debug would have pointed that out.

Use a different text editor. If you're using ModBuddy to type the Lua code, well, it's workable, but I'm not sure it really helps you detect these kinds of issues. Any sort of 'advanced' text editor designed for writing code should help you here. I use Sublime Text myself, but Notepad++ should be fine as well.

For me, Sublime will automatically suggest (and allow me to simply hit Enter to autocomplete) the exact spelling of whatever I am trying to reference. In effect, if I make a typo, it will at least ensure that it's properly typo'd everywhere.
 
Ok how am I doing now? Would this actually do EVERYTHING I want (Part A,B, and C)? Does this work for being just 1 function?

I figured line 09 - "if(not pPlayer:IsAlive() or pPlayer:IsMinorCiv() or pPlayer:IsBarbarian() or not buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then " - would serve to end the function early so that its not taking up much time every turn, after all this will be firing even after the 1st turn of the game.

IF I actually got this right (my money is on that I'm still fu$king this up some how :lol:), is there a better way I could write it to not take up much resources every turn when the wonder doesn't exist? Would it be better if broken up into 2-3 functions or is just 1 big one fine?

Code:
aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER
--------------------
-- adds/remove dummy buildings as more cities get conected/disconnected
--------------------
function UpdateOrRemoveHooverDummies(playerId, cityId, buildingType)
	local pPlayer = Players[playerId];
	local pCity;

	if(not pPlayer:IsAlive() or pPlayer:IsMinorCiv() or pPlayer:IsBarbarian() or not buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then
		-- Do nothing if not player isnt alive, a CS, a Barb, or if they dont have the Hoover Dam
	else
	     
	  if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

		for pCity in pPlayer:Cities()
			
			-- Adds dummies to cities that are connected and not blocked. DOESNT put a dummy in the city with Hoover Dam.
			if(not pCity:IsHasBuilding(GameInfoTypes["BUILDING_HOOVER_DAM"]) and player:IsCapitalConnectedToCity(city) and not city:IsBlockaded() ) then 
				if city:GetNumRealBuilding(aHooverDummy) == 0 then
						city:SetNumRealBuilding(aHooverDummy, 1);
				end
			end
		
			--  Removes dummies to cities that are not connect or become blocked
			if(not player:IsCapitalConnectedToCity(city) or city:IsBlockaded() ) then 
				if city:GetNumRealBuilding(aHooverDummy) == 1 then
				   		city:SetNumRealBuilding(aHooverDummy, 0);
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(UpdateOrRemoveHooverDummies);
 
  1. You still have the mis-match between pCity and city
  2. Overall -> Nope, you've actually taken a step backwards
    • PlayerDoTurn and CityConstructed do not pass the same variable arguments to the functions that are "Added" to them.
    • PlayerDoTurn only passes one variable argument. In the way you are using it (and that part is actually OK) it will be playerId.
    • The two trailing arguments cityId, buildingType will not have any information provided for them because PlayerDoTurn only passes one variable argument.
  3. I would keep the CityConstructed function you had going, and merely change it by:
    • fixing the city reference mis-matches I noted before
    • adding code I suggested for keeping the Dummy Marker building from being added to the same city that constructed the wonder.
  4. Make a seperate function to run on PlayerDoTurn to handle the issues on a turn-by-turn basis after the wonder is completed.
  5. Take baby steps and make haste more slowly!
    • Get the function for when the wonder is constructed to work properly and verify that it is only adding the dummy markers in the appropriate cities.
      • Hint: IGE is great for this kind of thing since even dummy and hidden buildings are shown in IGE when examining what buildings are present in a city.
    • Tackle the PlayerDoTurn only after you have the 1st part working properly. Otherwise, you are just chasing your own tail and shooting yourself in the foot.
I took about two weeks and much patient coaching from whoward69 to get my 1st mod that used lua up and running. It too was a wonder mod, and at that time there was no CityConstructed hook event to make my life easier in determining when and where a wonder had just been constructed.

Patience and testing in a methodical step-by-step process really is best.
 
Also, when using IGE to test things, never add a wonder directly to a city using IGE. CityConstructed does not fire in such cases. Use IGE to give yourself the required tech, then add a couple of Great Engineers in the city where you want to test-build the wonder. Exit IGE, select the wonder as the city's build-project and use the GEngineers to rush-complete the wonder. Then press NEXT TURN. After the turn processing you can now use IGE to look through your cities to determine if every city got the marker building in the correct circumstances : connected or not connected.
 
I have checked through a couple of in game examples and it seems for their lua "local pCity;" was enough or they just start using " for pCity in pPlayer:Cities() " with nothing above it telling what pCity is.

This this what I am missing to get pCity to work right ? " local pCity = Players[cityId]; "

Thanks for the tip on IGE, never knew about that mod.

edit: I am guessing local pCity = Players[cityId]; isn't right because I can see the hoover marker listed in IGE but the wonder isn't putting them into the 2 extra cities i have connected when the wonder is built by popping a GE.
 
check the lua log. I'm betting you have an error message there aboout a missing 'end', and perhaps about a missing 'do'.

You omitted the command 'do' from the end of the 'for' line.

This is another reason why it is good to look at your lua file with something besides ModBuddy. I always use Notepad because it makes the tab indents more clear and helps more clearly define which end goes with which 'if', which goes with which 'for', and which is the 'end' terminator of the function itself.
Code:
aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER

function HooverDamBuilt(playerId, cityId, buildingType, bGold, bFaithOrCulture)
	local pPlayer = Players[playerId];

	if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

		for pCity in pPlayer:Cities() [color="blue"]do[/color]
			if (pPlayer:IsCapitalConnectedToCity(pCity) and not pCity:IsBlockaded()) then
				if not pCity:IsHasBuilding(GameInfoTypes["BUILDING_HOOVER_DAM"]) then
					pCity:SetNumRealBuilding(aHooverDummy, 1);
				end
			end
		end
	[color="blue"]end[/color]
end
GameEvents.CityConstructed.Add(HooverDamBuilt);
Defining local pCity prior to the for pCity in pPlayer:Cities() do does not actually accomplish much because you are defining it strictly for use within the 'for' loop on the line where the 'for' loop is stated.
 
Checking and copying code from others as "examples" without first thinking about what the code is doing or why it does it is largely why you are running into issues. Referencing code is fine, but you really need to understand what's going on, which your complaints are telling me that you're not.

LeeS pointed out that "You still have the mis-match between pCity and city" to which you respond "I have checked through a couple of in game examples and it seems for their lua "local pCity;" was enough" -- this definition is not what LeeS was referring to.

Let's look at the section of relevant code we're referring to (and compare with the corrected segment LeeS posted above):
Code:
for [COLOR="Blue"]pCity[/COLOR] in pPlayer:Cities()

	-- Adds dummies to cities that are connected and not blocked. DOESNT put a dummy in the city with Hoover Dam.
	if(not [COLOR="Blue"]pCity[/COLOR]:IsHasBuilding(GameInfoTypes["BUILDING_HOOVER_DAM"]) and player:IsCapitalConnectedToCity(city) and not [COLOR="Red"]city[/COLOR]:IsBlockaded() ) then 
		if [COLOR="Red"]city[/COLOR]:GetNumRealBuilding(aHooverDummy) == 0 then
			[COLOR="Red"]city[/COLOR]:SetNumRealBuilding(aHooverDummy, 1);
How is Lua supposed to know that 'city' is the same as 'pCity'? You've defined pCity, but attempt to use city randomly, which tells me you're not very carefully going over your code. As a human you can probably assume that city and pCity are the same here, but to Lua, they might as well say Pizza and Zephyrus.

You do not need to define local pCity prior to a for pCity in pPlayer:Cities() do loop, because you're already defining pCity explicitly through the loop iterator.

Players[cityID] will not work, because the Players table contains information about the actual players in the game where the index value (in your case, you're using cityID as the index value) matches with the game's Player ID value for that player. A City ID is not the same as a Player ID, so that lookup will not get the results you expect.

If you want to get data about a player, you have to first get that particular player's table, which is typically Players[iPlayer], which, as I explained above, will get you the Players table for that specific player. Once you have that, then you can query it for information about that player's Cities. If you have a City ID, you can query pPlayer:GetCityByID(cityID), but if you're needing to iterate through all of a player's Cities anyway, you might as well just use the iterator.
 
Ok, so the GameEvents.CityConstructed.Add(HooverDamBuilt) function works and does only add the dummy buildings in the cities connected at the time the wonder is built.

Now I am stuck on the PlayerDoTurn part that will add dummy buildings to the cities that become connected after the wonder is built.

I have tried writing it a few different ways but either what I write causes the CityConstructed event to fail or that part still works, but new dummy buildings aren't being added to cities that become connected after the wonder is built.

I tried writing it with just one function, however with this version it prevents the initial dummy buildings from being placed (so I'm guessing something is wrong enough that it's killing the whole LUA). Since you said PlayerDoTurn can only carry one variable, I made aHooverDummy a local variable in case PlayerDoTurn doesn't even take global variables. I also remember my c++ teacher yelling at me for using global variables, so I even made it a local variable in the CityConstructed part.

Code:
function UpdateOrRemoveHooverDummies(playerId)
	local pPlayer = Players[playerId];

	if(pPlayer:IsMinorCiv() or pPlayer:IsBarbarian() ) then return end
		-- Do nothing if player is a CS or Barb

		local aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER
		local HooverWonder = GameInfoTypes.BUILDING_HOOVER_DAM

		for pCity in pPlayer:Cities() do

			if pCity:IsHasBuilding(HooverWonder) then
				-- Adds dummies to cities that are connected and noy blocked
				if(pPlayer:IsCapitalConnectedToCity(pCity) and not pCity:IsBlockaded and not pCity:IsHasBuilding(aHooverDummy) ) then 
					if pCity:GetNumRealBuilding(aHooverDummy) == 0 then
						pCity:SetNumRealBuilding(aHooverDummy, 1);
					end
				end
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(UpdateOrRemoveHooverDummies);

I even tried a nested for loop thinking that when the initial "if pCity:IsHasBuilding(HooverWonder) then" fires it might make all of the other instances of pCity set to just the city that the wonder is in. Since the following code already tells us not to do anything with the city that has the wonder, nothing would happen. However, even with the nested for loop to "ensure that it's still checking and adding to all of the players cities", the code was still killing the whole LUA cause nothing was happening when the wonder was built.

Code:
for pCity in pPlayer:Cities() do

	if pCity:IsHasBuilding(HooverWonder) then
		for pCity in pPlayer:Cities() do
			-- Adds dummies to cities that are connected and noy blocked
			if(pPlayer:IsCapitalConnectedToCity(pCity) and not pCity:IsBlockaded and not pCity:IsHasBuilding(aHooverDummy) ) then 
				if pCity:GetNumRealBuilding(aHooverDummy) == 0 then
								pCity:SetNumRealBuilding(aHooverDummy, 1);
				end
			end
		end
	end
end


Here is one way I wrote it by breaking the above function into 2 functions. One is PlayerDoTurn which should look to see if the hoover dam exists and if so, it fires the other function to add the dummy buildings. This code "works enough" to allow the initial dummy buildings to be placed when the wonder is built, but doesn't adding the new dummy buildings to cities that are newly connected after the wonder is built.

Code:
--------------------
-- Checks to see if it needs to run the add dummy function
--------------------
function UpdateOrRemoveChecker(playerId)
	local pPlayer = Players[playerId];

	if(pPlayer:IsMinorCiv() or pPlayer:IsBarbarian() ) then return end
		-- Do nothing if player is a CS or Barb
		
		local HooverWonder = GameInfoTypes.BUILDING_HOOVER_DAM

		for pCity in pPlayer:Cities() do
			if pCity:IsHasBuilding(HooverWonder) then
				function AddHooverDummies(playerID, cityId, buildingType)
			end
		end
	end
end
GameEvents.PlayerDoTurn.Add(UpdateOrRemoveChecker);

--------------------
-- adds dummy buildings as more cities get connected
--------------------
function AddHooverDummies(playerId, cityId, buildingType)
	local pPlayer = Players[playerId];
	local aHooverDummy = GameInfoTypes.BUILDING_HOOVERDAM_MARKER

	if(buildingType == GameInfoTypes["BUILDING_HOOVER_DAM"]) then

		for pCity in pPlayer:Cities() do

			if(pPlayer:IsCapitalConnectedToCity(pCity) and not pCity:IsBlockaded() and not pCity:IsHasBuilding(aHooverDummy) ) then 
					if pCity:GetNumRealBuilding(aHooverDummy) == 0 then
						pCity:SetNumRealBuilding(aHooverDummy, 1);
					end
			end
		end
	end
end

What am I missing this time? Shouldn't this work as just 1 function, why is it "working better" as 2 functions? Did I have the right thinking with the nested for loop?

If I go with the 2 function version, do I need to wrap the function AddHooverDummies with something at the end? I saw LuaEvents as a possible option. If that is what I need would it be LuaEvents.HooverDummy.Add(AddHooverDummies); ?

Edit: I noticed an error at the "function within the function" part at "function AddHooverDummies(playerID, cityId, buildingType)". I corrected it to playerId, but it still no new dummy buildings in newly connected cities.
 
Well, props to you for not giving up at least. You've given this more attempts than some others.
Responding to your code snippets in order...

On the surface, your code technically should, and probably does, run fine. It's simply not doing what you are expecting, because your logic is incorrect.

You have to understand what exactly is happening when you call iterators such as pPlayer:Cities() and pPlayer:Units().

Here is a hypothetical scenario:
Let us assume you have a fairly small Empire right now - You only have 3 Cities.
They are creatively named CityA, CityB, and CityC.
Let us also assume that you have managed to construct your wonder in CityB.
CityB is already connected to your Capital, which is CityA. CityC will be connected in a few more turns, but for now is unconnected.

Setting aside all the other logic for now, let us look specifically at the loop iterator:
Code:
for [B]pCity[/B] in [B]pPlayer:Cities()[/B] do
As I've mentioned before, pPlayer:Cities() is an iterator -- this means it iterates, or goes through a list of items (in this case, Cities) one by one.

The game knows that you only have 3 Cities, so this means that this loop will run three times.
The first part of the loop declaration defines the name of a variable that you want to temporarily hold the data for each iteration. In this case, every City the game finds from pPlayer:Cities() is assigned temporarily to the variable pCity. This is why you do not need to "define" or "declare" pCity beforehand.

Now, let's look at this in action:
What do you think pCity holds during each iteration?

On loop #1, pCity holds...
Spoiler :
...The data for CityA.

On loop #2, pCity holds...
Spoiler :
...The data for CityB.

On loop #3, pCity holds...
Spoiler :
...The data for CityC.

On loop #4, pCity holds...
Spoiler :
...Nothing. It shouldn't hold anything. If you expected anything here, you weren't paying attention, because you only have 3 Cities to begin with, so the loop has already ended.

With that out of the way, let us inject the next part of your logic:
Code:
for pCity in pPlayer:Cities() do
	if pCity:[B]IsHasBuilding[/B](HooverWonder) then
Notice anything?

You're checking for the presence of your Wonder in that City before proceeding with any of your functions!

Let's apply this logic to the above information:
On loop #1, pCity holds the data for CityA...It doesn't have the Wonder, and there's no commands for what to do in this case, so it skips it and moves on.
On loop #2, pCity holds the data for CityB...It does have the Wonder, so it proceeds to fire off the bit of code attached to this condition -- namely, adding the dummy building to CityB.
On loop #3, pCity holds the data for CityC...It doesn't have the Wonder again, so it skips this City as well and moves on. Except there are no more Cities, so the whole function ends, because no other commands come after this.

Unrelated, but I also personally disagree with the whole "then return end" line, because if your conditions are set properly, it will end anyway without this explicit declaration. It just makes code more annoying to read for me. It also means that your first function will fail spectacularly because you've now got an extra "end" in there. I know you tried to match up the indents to properly "close" each if/for block, except that one line already has an end! That means you have an extra dangling end in that function, causing Lua to go on a fritz and probably give you an eof error. (Hard to tell? Delete everything inside that indented pair of if/end, and you'll see that you have: if ... then return end end)

Your second function is very bad as well. You do not want to be nesting loops over the same list like that, as all that means is that you are exponentially increasing the resource load of your function for no benefit at all.

Normally calling the Cities iterator will net you 3 loops: once per City you own (from the above example.)

Nesting a Cities iterator inside a Cities iterator means that you loop over your Cities at every individual City loop, thus making your code run 12 loops for those same three Cities:
Loop #1 - CityA -> Loop through CityA, CityB, and CityC
Loop #2 - CityB -> Loop through CityA, CityB, and CityC
Loop #3 - CityC -> Loop through CityA, CityB, and CityC

However, since you stuck a condition there, you will actually only run 6 loops, since the secondary loop would only fire for CityB. Still bad, though, as those extra loops are unnecessary.
It would be better if you simply queried the game to see if the player had the Wonder or not directly, since that is essentially the only reason for your checking of the Cities to find it. I believe there's a Player method that will return the number of buildings in a specified building class, though I'm having trouble remembering what it is. Maybe pPlayer:GetNumBuildingClass() or something. LeeS will probably know this one.

Having said that, it should theoretically be able to add the dummies to connected Cities, but as that's not shown to be hooked up to anything, I don't know. If it was hooked up, it would properly provide the dummy to CityA, but not CityC until it completed its connection to CityA.

Now, your third code snippet is probably close, but it's fairly inefficient.
First, separating functions into separate smaller functions is not necessarily a bad idea, and technically could even be a good idea, since it allows more modularity for re-using code between different functions.

The big problem is that the word function is a word reserved for creating functions in Lua. This is important, because this is the error you have.

This is fine:
Code:
function UpdateOrRemoveChecker(playerId)
As is this:
Code:
function AddHooverDummies(playerId, cityId, buildingType)
However! This is bad:
Code:
[COLOR="Blue"][B]if[/B][/COLOR] pCity:IsHasBuilding(HooverWonder) then
	[B][COLOR="Red"]function[/COLOR][/B] AddHooverDummies(playerId, cityId, buildingType)
[COLOR="Blue"][B]end[/B][/COLOR]
There are two problems:
  1. When this if block runs, instead of calling your function, you end up trying to define a new one.
  2. This new function declaration does not have an associated end paired with it.
These two issues would cause that piece of the code to fail.

Removing the word function would likely have that pair of functions start working, but in the end, you've still got the problem of snippet #2 -- double loops over the same list going on. Your functions also won't handle the scenario where a City's connection to CityA becomes broken.
Again, the word function is reserved for creating functions. If you only want to call the function, you must omit the word function.

You really need to enable logging and check your Lua logs, because most of these issues would have produced an error in the logs which would allow you to pinpoint the issues, instead of forcing you to guess randomly.
 
Thank you for the lesson, makes much more sense to me!

I did try to use logging to figure out whats going on at times but I dont notice any difference between what the logs says when I dont load the mod and when I do load it. So I stopped using it.

http://forums.civfanatics.com/showthread.php?t=487482

Followed it to a T when I was working on the gold check for Fort Knox: enabled logging, start and play 1 round with the mod not on, closed out of Civ 5, looked at the logs, closed them, opened Civ 5 again and loaded up the mod, tabbed out to the logs and looked at them again, i don't see anything that seems specific to my mod. I'll try it again with this Hoover Dam mod to see if it says anything.
 
If the Lua is loaded at all, it will output errors to Lua.log; Make sure you're looking at the right ones. If you want to check, you can load up my Civ, or something, since it's set to output a bunch of stuff to the logs prior to game start.

If you don't notice a difference in the logs between having and not having your mod enabled, there may be bigger problems going on, but unfortunately, we don't have access to your logs.
 
Just double checking, so if I stick with "method 2" where I break what I need for Parts B and C of the Mod into separate functions....when I make function AddHooverDummies(playerId, cityId, buildingType) I only need to finish it off with end? I am fine with not wrapping it with some object since its only ever going to trigger when the previous function " function UpdateOrRemoveChecker(playerId)" tells it to?

I'm at work ATM, so I can write stuff but not test.
 
Back
Top Bottom