LUA help?

Keniisu

YouTuber | Modder
Joined
Dec 17, 2015
Messages
501
Location
United States
This is my current code: (Not yet tested so corrections would be nice. :) )
Code:
local iCiv_ID = GameInfoTypes.CIVILIZATION_MOROCCO -- Morroco is placeholder Civ

function GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players(iPlayer) --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	local iTourism = pPlayer:GetTourism()
	local iGold = iTourism
	local iCulture = math.floor(iTourism/2)
	local pCity = pPlayer:GetCapitalCity()
	if pPlayer:IsGoldenAge()
		iGold = iTourism + 2
		iCulture = math.floor(iTourism/2) + 2
	else
	end
end

I'm trying to add this:
For every 2 Tourism :tourism: output by your civilization gain +2 Gold :c5gold: and +1 Culture :c5culture:, however this is increased by 15% during a Golden Age :c5goldenage:. Great People :c5greatperson: are earned +5% faster for every civilization you have become Exotic :tourism: with. (Max: 30%)

If anybody could help, I'd be grateful.
 
This is my current code: (Not yet tested so corrections would be nice. :) )
Code:
local iCiv_ID = GameInfoTypes.CIVILIZATION_MOROCCO -- Morroco is placeholder Civ

[COLOR="Red"]function[/COLOR] GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players[COLOR="Red"]([/COLOR]iPlayer[COLOR="red"])[/COLOR] --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	local iTourism = pPlayer:GetTourism()
	local iGold = iTourism
	[COLOR="red"]local iCulture = math.floor(iTourism/2)[/COLOR]
	[COLOR="red"]local pCity = pPlayer:GetCapitalCity()[/COLOR]
	[COLOR="red"]if pPlayer:IsGoldenAge()
		iGold = iTourism + 2
		iCulture = math.floor(iTourism/2) + 2
	else
	end[/COLOR]
end
Mistakes/logical errors highlighted in red.

Adding a Lua hook isn't a function.

Getting the player from the database should be surrounded in brackets:
Code:
local pPlayer = Players[iPlayer]
(you had it surrounded in parentheses)

Getting the Capital City isn't needed.

That's the only outright mistakes I could find, but there are logic errors in how you're getting your numbers.
Assuming this UA is what you mean:
Every 2 :tourism: Tourism from your Civilization also generates +2 :c5gold: Gold and +1 :c5culture: Culture (increased by 15% if in a :c5goldenage: Golden Age).
(I know I'm leaving out the GP generation part, but that's not what this code is for)
...then you're missing a bit of math. You also never actually give the player any Culture or Gold.

The gold calculation is fine (2 tourism = 2 gold), cool. The culture calculation is also fine. Where you're going wrong is the logic. You want to assign a different value (multiply the base values by 1.15) if the player is in a Golden Age, otherwise you want to give them the normal values. You'd have to do something like this:
Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players(iPlayer) --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	if (pCiv == iCiv_ID) then
		local iTourism = pPlayer:GetTourism()
		local iGold = iTourism
		local iCulture = math.floor(iTourism/2)
		if pPlayer:IsGoldenAge()
			iGold = math.floor(iGold * 1.15)
			iCulture = math.floor(iCulture * 1.15)
		end
		pPlayer:ChangeJONSCulture(iCulture)
		pPlayer:ChangeGold(iGold)
	end
end)
Note that these will not show up in any yields anywhere; they aren't added to the per-turn yields of Gold, Culture, etc. They'd be invisible to the player unless you'd be willing to add a separate UI element that tracked them (which is a mess in and of itself, though luckily the math isn't really that hard to do on the player's end).
 
Thanks so much, ha. How would I start doing the Great Person aspect of the code? I assume just use a math equation for it as well? And how would I find out if they're Exotic or not?
 
Thanks so much, ha. How would I start doing the Great Person aspect of the code? I assume just use a math equation for it as well? And how would I find out if they're Exotic or not?
The actual GP bonus would have to be done through a series of dummy Policies or dummy buildings placed in all of the players' Cities.

I believe Tourism influence is handled through "CULTURE_LEVEL_X" in the GameDefines, where "CULTURE_LEVEL_EXOTIC"=10 (i.e. any amount of Tourism greater than 10% of the player's total Culture).

So the GP bonus would have to be done by looping through all other players, using:
Code:
Player:GetInfluenceOn(eOtherPlayer)
in order to see if the player's Tourism influence is greater than Exotic (Influence in this case refers to Tourist influence, not City-State). Every time it is, give the player a dummy Policy that increases GP generation by 5%/give all their Cities dummy buildings that increase GP generation by 5%. Note: you'd probably need to add a failsafe in this case where you can also remove the Policies/dummy buildings in case the Tourism influence dips below Exotic again (or just have it so the UA's bonuses are permanent as soon as you get Exotic with someone, no matter where they go afterward).
 
How would I mass add buildings? I know how to add to the capital, but to all cities at once is an unfamiliar concept...
Also how's this code?
Code:
function GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players[iPlayer] --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	local iTourism = pPlayer:GetTourism()
	local iGold = iTourism
	local iCulture = math.floor(iTourism/2)
	if pPlayer:IsGoldenAge()
		iGold = math.floor(iGold * 1.15)
		iCulture = math.floor(iCulture * 1.15)
	end
	pPlayer:ChangeJONSCulture(iCulture)
	pPlayer:ChangeGold(iGold)
	if Player:GetInfluenceOn(eOtherPlayer) = 10
		-- add buildings to all cities
	end
end
 
First off, glancing at your code, I've also just realized I forgot the most important part: making sure you were using the Civ before applying its bonuses! I edited my previous post for those changes.

As for how to add buildings (and check Tourism), it's a bit more complex than just plug and play, unfortunately. You have to cycle through the players, check and increment how many of them are at least exotic, and then add the number of dummies you need. Here's how I'd do it (and keep in mind I've never done something like this before, I'm only working on theory here):
Code:
for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
	local iExoticPlayers = 0
	pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
	if (not (pPlayer == pOtherPlayer) and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
		if (pPlayer:GetInfluenceOn(pOtherPlayer) >= 10) then -- if it's exotic
			iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
		end
	end
end
for pCity in pPlayer:Cities() do -- cycle through all player cities
	pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers) -- add a number of GP dummies equal to the amount of exotic players
end
Disclaimer: I'm not sure entirely how the :GetInfluenceOn() function works, but assuming it works like I think it does, this should work. I also don't know whether or not Great Person generation stacks on dummy buildings; with luck, LeeS will show up and elaborate (and correct any errors I might have).

Regardless, put some form of this within the new Civ check I added to my original post and, in theory, you should be good (I've not tested the code, so if it has errors I wouldn't know).
 
Code:
for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
	local iExoticPlayers = 0
	pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
	if (not (pPlayer == pOtherPlayer) and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
		if (pPlayer:GetInfluenceOn(pOtherPlayer) >= 10) then -- if it's exotic
			iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
		end
	end
end
for pCity in pPlayer:Cities() do -- cycle through all player cities
	pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers) -- add a number of GP dummies equal to the amount of exotic players
end
Disclaimer: I'm not sure entirely how the :GetInfluenceOn() function works, but assuming it works like I think it does, this should work. I also don't know whether or not Great Person generation stacks on dummy buildings; with luck, LeeS will show up and elaborate (and correct any errors I might have).
  1. I haven't played around with that method either, nor the one I would more-likely have chosen to use: Player:GetInfluenceLevel(ePlayer)
  2. From looking at W.Howard's lua as XML, I think either of these methods want the "ePlayer" argument as a Player ID# rather than as a player object.
  3. You can use either <GlobalGreatPeopleRateModifier> in the xml of a dummy building that is added to the capital city, or you can use <GreatPeopleRateModifier> in the xml of a dummy building that is added in every city. I believe both of these 'stack' for multiple copies of the same building within the same city. I have not, however, verified this and updated the chart in the tutorial on dummy-building effect-stacking etc.
  4. Besides the issue that I think you want iOtherPlayer instead of pOtherPlayer in pPlayer:GetInfluenceOn(pOtherPlayer) there are a couple of small oops in the code here:
    Code:
    for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
    	[color="red"]local iExoticPlayers = 0[/color]
    	[color="red"]local[/color] pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
    	if ([color="red"]not (pPlayer == pOtherPlayer)[/color] and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
    		if (pPlayer:GetInfluenceOn([color="red"]pOtherPlayer[/color]) >= 10) then -- if it's exotic
    			iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
    		end
    	end
    end
    for pCity in pPlayer:Cities() do -- cycle through all player cities
    	pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers) -- add a number of GP dummies equal to the amount of exotic players
    end
    • You've localed iExoticPlayers within the 'for' loop, so not only will it get reset to '0' upon each iteration through the loop, it will be completely forgotten when the 'for' loop completes its work
    • Because of the iExoticPlayers localization error, it will be 'nil', and cause error messages in this line of the code
      Code:
      pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers)
    • I highlighted this simply because it is more difficult to 'parse' than is really needed, and with all the parentheticals, is even a bit more complicated on that line to determine what should be 'not'
      Code:
      [color="red"]not (pPlayer == pOtherPlayer)[/color]
      Simplify such constructions to
      Code:
      (pPlayer ~= pOtherPlayer)
      and drop the need for the 'not'.
    • So you would want
      Code:
      local iExoticPlayers = 0
      for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
      	local pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
      	if ((pPlayer ~= pOtherPlayer) and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
      		if (pPlayer:GetInfluenceOn(iOtherPlayer) >= 10) then -- if it's exotic
      			iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
      		end
      	end
      end
      for pCity in pPlayer:Cities() do -- cycle through all player cities
      	pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers) -- add a number of GP dummies equal to the amount of exotic players
      end
  5. Overall code would want to be
    Code:
    local iCiv_ID = GameInfoTypes.CIVILIZATION_MOROCCO -- Morroco is placeholder Civ
    
    GameEvents.PlayerDoTurn.Add(function(iPlayer)
    	local pPlayer = Players(iPlayer) --get Player ID
    	if (pPlayer:GetCivilizationType() == iCiv_ID) then
    		local iTourism = pPlayer:GetTourism()
    		local iGold = iTourism
    		local iCulture = math.floor(iTourism/2)
    		if pPlayer:IsGoldenAge() then
    			iGold = math.floor(iGold * 1.15)
    			iCulture = math.floor(iCulture * 1.15)
    		end
    		pPlayer:ChangeJONSCulture(iCulture)
    		pPlayer:ChangeGold(iGold)
    		local iExoticPlayers = 0
    		for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
    			local pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
    			if ((pPlayer ~= pOtherPlayer) and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
    				if (pPlayer:GetInfluenceOn(iOtherPlayer) >= 10) then -- if it's exotic
    					iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
    				end
    			end
    		end
    		for pCity in pPlayer:Cities() do -- cycle through all player cities
    			pCity:SetNumRealBuilding(GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], iExoticPlayers) -- add a number of GP dummies equal to the amount of exotic players
    		end
    	end
    end)
    And this assumes that "BUILDING_GREAT_PERSON_DUMMY" uses the <GreatPeopleRateModifier> column as is used with a Garden to adjust only that City's Great People generation.
 
Yeah, I had looked at the possible methods to check Tourism influence and decided upon GetInfluenceOn rather than GetInfluenceLevel. Presumably, they both do the same thing (they certainly sound like they should), but I've no idea. I had also forgotten <GlobalGreatPeopleRateModifier> was even a possibility, and would probably be the better option simply because it wouldn't require iterating through every city.

And thank you for the error corrections as always! No excuses this time, I was just quick in typing it up and made a few simple mistakes (especially the misplaced integer to track the number of exotic influences--I'm usually decent with variable scope, so that's an embarassing mistake to make :lol:)

EDIT: Retroactively noticed an oops in my first batch of code:
Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players(iPlayer) --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	if (pCiv == iCiv_ID) then
		local iTourism = pPlayer:GetTourism()
		local iGold = iTourism
		local iCulture = math.floor(iTourism/2)
		if pPlayer:IsGoldenAge() [COLOR="Red"]then[/COLOR]
			iGold = math.floor(iGold * 1.15)
			iCulture = math.floor(iCulture * 1.15)
		end
		pPlayer:ChangeJONSCulture(iCulture)
		pPlayer:ChangeGold(iGold)
	end
end)

Forgot the "then" in the if-statement for checking if the player was in a Golden Age.
 
Yeah, I had looked at the possible methods to check Tourism influence and decided upon GetInfluenceOn rather than GetInfluenceLevel. Presumably, they both do the same thing (they certainly sound like they should), but I've no idea. I had also forgotten <GlobalGreatPeopleRateModifier> was even a possibility, and would probably be the better option simply because it wouldn't require iterating through every city.

And thank you for the error corrections as always! No excuses this time, I was just quick in typing it up and made a few simple mistakes (especially the misplaced integer to track the number of exotic influences--I'm usually decent with variable scope, so that's an embarassing mistake to make :lol:)

EDIT: Retroactively noticed an oops in my first batch of code:
Code:
GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players(iPlayer) --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	if (pCiv == iCiv_ID) then
		local iTourism = pPlayer:GetTourism()
		local iGold = iTourism
		local iCulture = math.floor(iTourism/2)
		if pPlayer:IsGoldenAge() [COLOR="Red"]then[/COLOR]
			iGold = math.floor(iGold * 1.15)
			iCulture = math.floor(iCulture * 1.15)
		end
		pPlayer:ChangeJONSCulture(iCulture)
		pPlayer:ChangeGold(iGold)
	end
end)

Forgot the "then" in the if-statement for checking if the player was in a Golden Age.
I missed that missing "then" as well. Fixed in my previous post.
 
I had also forgotten <GlobalGreatPeopleRateModifier> was even a possibility, and would probably be the better option simply because it wouldn't require iterating through every city.
Wouldn't a caveat for just having a building in the capital be that you need to keep track of when the capital changes? For example, if it is captured by another civ, or the original civ captures it back.
 
Wouldn't a caveat for just having a building in the capital be that you need to keep track of when the capital changes? For example, if it is captured by another civ, or the original civ captures it back.

I thought so initially, but because the check and adding the buildings are done on a turn-by-turn basis, the buildings will appear in the new Capital on the next turn. If you wanted it to switch instantly though, then yeah, it would require monitoring.
 
I thought so initially, but because the check and adding the buildings are done on a turn-by-turn basis, the buildings will appear in the new Capital on the next turn. If you wanted it to switch instantly though, then yeah, it would require monitoring.
I'm thinking specifically of the circumstance of when the original capital is regained. If you don't perform some sort of check on the other cities, then wouldn't it be possible you'd have more than one copy of the building?

For example, if this civ was America, and Washington had been captured by the Aztecs, your current capital might be New York, and that city would get these dummy buildings. That's all fine so far, but if you then recapture Washginton, and your PlayerDoTurn function only adds the building to the capital, then both Washington and New York would have the dummy building and the dummy building's effect would be doubled.

Actually, now that I think about it... would setting "MaxPlayerInstances = 1" for the dummy building's building class work for this? I'm not sure what would happen if you tried to add a dummy building with that setting that already exists somewhere in the empire. Unless someone else already knows, you'd have to test it.
 
I'm thinking specifically of the circumstance of when the original capital is regained. If you don't perform some sort of check on the other cities, then wouldn't it be possible you'd have more than one copy of the building?

Ah, I see what you mean; good point. This means that you would essentially need to iterate through every city to get rid of them elsewhere, and then put them in the Capital... which means that, if you want to be safe, iterating through every city is pretty much required, so it doesn't much matter which way you end up doing it, I guess.

Actually, now that I think about it... would setting "MaxPlayerInstances = 1" for the dummy building's building class work for this? I'm not sure what would happen if you tried to add a dummy building with that setting that already exists somewhere in the empire. Unless someone else already knows, you'd have to test it.

Probably not, simply because we're stacking multiple copies of the dummy building (e.g. the maximum GPP it can give is 30%, which, in incrememts of 5%, means there could be 6 dummy buildings at a time).
 
Probably not, simply because we're stacking multiple copies of the dummy building (e.g. the maximum GPP it can give is 30%, which, in incrememts of 5%, means there could be 6 dummy buildings at a time).
I just thought about that - that setting might work if you'll only have one copy at a time, but not if it's a variable effect that uses stacking. :p
 
In all cases you just set the dummy building to never be capturable. This is something you should do as a matter of course for any dummy buildng.
Code:
<NeverCapture>true</NeverCapture>
And as a matter of habit for a dummy building you should generally also set Nuke Immunity
Code:
<NukeImmune>true</NukeImmune>
to avoid lua code-oddities especially for dummy buildings that have no function other than to act as 'markers'

This will keep Shaka from getting his greedy hands on dummy buildings when he captures Washington, but won't deal with the issue of America re-capturing Washington. Give me a few while I ginny up a toolkit function to deal with this issue.
 
Typhlo is referring to the case where city conquest wasn't a factor.

Let's say you've got this situation:

  • A Capital with 4 dummies (in this case, +20% GP generation)
  • The Capital is conquered. All the dummies are destroyed due to <NeverCapture>, and next turn the Lua runs again and puts 4 dummies in the new Capital
  • At some point in the game, the player reconquers his old Capital. Next turn, the game will read this new Capital and place 4 dummies there, but it has not removed the 4 dummies from the old city
  • End result: +40% GP generation
Obviously that's unintended, which means that iterating through cities is required to make sure outstanding situations like these don't occur.
 
Typhlo is referring to the case where city conquest wasn't a factor.

Let's say you've got this situation:

  • A Capital with 4 dummies (in this case, +20% GP generation)
  • The Capital is conquered. All the dummies are destroyed due to <NeverCapture>, and next turn the Lua runs again and puts 4 dummies in the new Capital
  • At some point in the game, the player reconquers his old Capital. Next turn, the game will read this new Capital and place 4 dummies there, but it has not removed the 4 dummies from the old city
  • End result: +40% GP generation
Obviously that's unintended, which means that iterating through cities is required to make sure outstanding situations like these don't occur.
See my edit. Give me a few minutes
 
Code:
-------------------------------------------------------------------------------------------------
-- AddDummiesToCapitalAndCleanOffendingNonCapitalDummies
-- Author: LeeS
-- DateCreated: 4/7/2016
-- 'iPlayer' is the player's ID#
-- 'iBuildingType' is the dummy building's ID# (ie, GameInfoTypes["BUILDING_DUMMY_BUILDING"])
-- 'iCorrectNumBuildings' is the correct numnber of buildings the player should have in their capital city
---------------------------------------------------------------------------------------------------

function AddDummiesToCapitalAndCleanOffendingNonCapitalDummies(iPlayer, iBuildingType, iCorrectNumBuildings)
	local pPlayer = Players[iPlayer]
	local pCapitalCity = pPlayer:GetCapitalCity()
	if pCapitalCity ~= nil and pPlayer:IsAlive() then
		pCapitalCity:SetNumRealBuilding(iBuildingType, iCorrectNumBuildings)
		if pPlayer:CountNumBuildings(iBuildingType) > iCorrectNumBuildings then
			for pCity in pPlayer:Cities() do
				if not pCity:IsCapital() then
					pCity:SetNumRealBuilding(iBuildingType, 0)
				end 
			end
		end
	end
end
So if we are going to add the dummy building(s) only in the capital city, the overall code would change to:
Spoiler :
Code:
-------------------------------------------------------------------------------------------------
-- AddDummiesToCapitalAndCleanOffendingNonCapitalDummies
-- Author: LeeS
-- DateCreated: 4/7/2016
-- 'iPlayer' is the player's ID#
-- 'iBuildingType' is the dummy building's ID# (ie, GameInfoTypes["BUILDING_DUMMY_BUILDING"])
-- 'iCorrectNumBuildings' is the correct numnber of buildings the player should have in their capital city
---------------------------------------------------------------------------------------------------

function AddDummiesToCapitalAndCleanOffendingNonCapitalDummies(iPlayer, iBuildingType, iCorrectNumBuildings)
	local pPlayer = Players[iPlayer]
	local pCapitalCity = pPlayer:GetCapitalCity()
	if pCapitalCity ~= nil and pPlayer:IsAlive() then
		pCapitalCity:SetNumRealBuilding(iBuildingType, iCorrectNumBuildings)
		if pPlayer:CountNumBuildings(iBuildingType) > iCorrectNumBuildings then
			for pCity in pPlayer:Cities() do
				if not pCity:IsCapital() then
					pCity:SetNumRealBuilding(iBuildingType, 0)
				end 
			end
		end
	end
end

local iCiv_ID = GameInfoTypes.CIVILIZATION_MOROCCO -- Morroco is placeholder Civ
local iGAModifier = 15
local iGreatPeopleDummy, iMaxGreatPeopleDummy = GameInfoTypes["BUILDING_GREAT_PERSON_DUMMY"], 6

GameEvents.PlayerDoTurn.Add(function(iPlayer)
	local pPlayer = Players(iPlayer) --get Player ID
	if (pPlayer:GetCivilizationType() == iCiv_ID) then
		local iTourism = pPlayer:GetTourism()
		local iGold = iTourism
		local iCulture = math.floor(iTourism/2)
		if pPlayer:IsGoldenAge() then
			iGold = math.floor(iGold * (1 + (iGAModifier/100)))
			iCulture = math.floor(iCulture * (1 + (iGAModifier/100)))
		end
		pPlayer:ChangeJONSCulture(iCulture)
		pPlayer:ChangeGold(iGold)
		local iExoticPlayers = 0
		for iOtherPlayer = 0, GameDefines.MAX_MAJOR_CIVS-1, 1 do -- this will cycle through checking every major civ in the game
			local pOtherPlayer = Players[iOtherPlayer] -- get the other player we're looking at
			if ((iPlayer ~= iOtherPlayer) and (pPlayer:IsAlive()) and (pOtherPlayer:IsAlive())) then -- check to make sure we're not looking at ourselves and that both people are alive
				if (pPlayer:GetInfluenceOn(iOtherPlayer) >= 10) then -- if it's exotic
					iExoticPlayers = iExoticPlayers + 1 -- increment the exotic counter
				end
			end
		end
		if iExoticPlayers > iMaxGreatPeopleDummy then
			iExoticPlayers = iMaxGreatPeopleDummy
		end
		AddDummiesToCapitalAndCleanOffendingNonCapitalDummies(iPlayer, iGreatPeopleDummy, iExoticPlayers)
	end
end)
If the player's original capital were captured there would be up to one turn of 'Anarchy' (as it were) during which the player wouldn't have any city with BUILDING_GREAT_PERSON_DUMMY, but this would be solved the next time the player did NEXT TURN.

I edited to fix the things William pointed to a few posts down re (primarily) OuroborosOrder's post, but some of them applied as much to me as to OuroborosOrder
 
This is my current code: (Not yet tested so corrections would be nice. :) )
Code:
local iCiv_ID = GameInfoTypes.CIVILIZATION_MOROCCO -- Morroco is placeholder Civ

function GameEvents.PlayerDoTurn.Add(function(iPlayer)
	pPlayer = Players(iPlayer) --get Player ID
	local pCiv = pPlayer:GetCivilizationType() --get Civ ID
	local iTourism = pPlayer:GetTourism()
	local iGold = iTourism
	local iCulture = math.floor(iTourism/2)
	local pCity = pPlayer:GetCapitalCity()
	if pPlayer:IsGoldenAge()
		iGold = iTourism + 2
		iCulture = math.floor(iTourism/2) + 2
	else
	end
end

I'm trying to add this:


If anybody could help, I'd be grateful.

Here is a solution to your problem above:

Link: Try version 2 of the script instead.

Link: Version 3

Spoiler :
Code:
[COLOR="Sienna"]-- MoroccoUniqueAbility.lua
-- Author: Ouroboros
-- DateCreated: 4/7/2016
--------------------------------------------------------------

-- Function to setup the Moroccan civilization's unique ability.
function SetMoroccoUniqueAbility(iPlayer)
	-- Get the Player object by the Player ID (iPlayer).
	local pPlayer = Players(iPlayer);

	-- Now for the benefit stuff! +2 gold and +1 culture for every 2 tourism/turn.
	local iTourism = player:GetTourism();
	local iGold = iTourism;
	local iCulture = math.floor(iTourism/2);
	local iExoticCount = 0;

	-- If the player is in a Golden Age they recieve a 15% increase to the gold and culture gain!
	if player:IsGoldenAge() then
		iGold = math.floor(iGold * 1.15)
		iCulture = math.floor(iCulture * 1.15)
	end

	-- Next we update the benefit values so the game gives us our gold and culture each turn!
	pPlayer:ChangeJONSCulture(iCulture)
	pPlayer:ChangeGold(iGold)

	-- For each player in the list of players do...
	for(i = GameInfo.Defines.MAX_MAJOR_CIVS, GameInfo.Defines.MAX_CIV_PLAYERS-1, 1) do
		-- Current player in the list.
		local p = Players[i];

		-- Check to make sure we are not trying to compare to ourself or a dead player or someone we haven't met. lol...
		local bPlayerNotSelf = (p ~= pPlayer);
		local bPlayerIsAlive = p:IsAlive();
		local bPlayerHasMet = Teams[pPlayer:GetTeam()].HasMet(Teams[p:GetTeam()]);

		-- If everything checks out...
		if(bPlayerNotSelf and bPlayerIsAlive and bPlayerHasMet) then
			-- Then get the influence level and compare it to the influence level to see if it's EXOTIC.
			if(pPlayer:GetInfluenceLevel(i) >= InfluenceLevelTypes.INFLUENCE_LEVEL_EXOTIC) then
				-- If it is EXOTIC increase our count of the players we have Exotic influence over by 1.
				iExoticCount = iExoticCount + 1;
			end
		end

		-- Check to make sure our civs with Exotic influence from us is no more than 6.
		-- This is for calculation purposes. :)
		if(iExoticCount > 6)
			iExoticCount = 6;
		end

		-- Cycle through all of the player's cities.
		for(c = 0, pPlayer:GetNumCities(), 1)
			-- Get the current city in the list
			local pCity = pPlayer:GetCityByID(c);
			-- Get the current BASE great person rate. This means unaltered, before any modifiers.
			local iCurrentBaseGPR = pCity:GetBaseGreatPeopleRate();
			-- Get the current total great person rate modifier. This is after the modifiers have been added in.
			local iTotalGPRMod = pCity:GetTotalGreatPeopleRateModifier();
			-- Calculate the Moroccan great person rate modifier.
			local iMoroccoGPRMod = iExoticCount * 5;

			-- Calculate an adjusted great person rate.
			--====================================================================================================
			-- This is done by setting the two equations of the form a(x + b) which is the one we want...
			-- Equal to b(x + a) which is the one we would be creating if we do not do the following and simply
			-- add in our iMoroccoGPRMod. 
			-- 
			-- To set them equal we must include the slope between the two equations:
			-- a(x + b) = m[b(x + a)]. Then we solve for m like so: m = [a(x + b) / b(x + a)]. We then multiply
			-- the sum of the current base GPR and our Morocco GPR mod by the adjustment modifier we calculated.
			--====================================================================================================
			local iNumerator = iCurrentBaseGPR * (iMoroccoGPRMod + iTotalGPRMod);
			local iDenominator = iTotalGPRMod * (iMoroccoGPRMod + iCurrentBaseGPR);
			local fAdjustmentMod = iNumerator / iDenominator;
			local iAdjustment = math.floor((iCurrentBaseGPR + iMoroccoGPRMod) * fAdjustmentMod);
			
			-- Now change our base great person rate to the adjusted rate.
			pCity:ChangeBaseGreatPeopleRate(iAdjustment);
		end
	end
end
-- Register the function with the do turn event which is run on each player turn. 
-- This is called making a "hook" into the game engine from script in programming terminology.
GameEvents.PlayerDoTurn.Add(SetMoroccoUniqueAbility);
[/COLOR]

Hope this helps! :)
 
You've no test for iPlayer actually being Morocco, so every player in the game will get the benefit

You're mixing and matching "pPlayer" and "player" (multiple places) so the code will throw an error at
Code:
local iTourism = player:GetTourism();
with a nil pointer error

For ease of tweaking (what if 15% is too much/little), the hard-coded constants of 1.15 should be pulled out into a file scoped variable

Code:
local iGAModifier = 15

...

	iGold = math.floor(iGold * (100 + iGAModifier) / 100)
	-- and the same for iCulture

Comparing objects (p and pPlayer) is a bad idea (the compare is undefined, it may be being done as C++ pointers, internal Lua structures, as a member-by-member comparision, or somehow else)
Code:
local bPlayerNotSelf = (p ~= pPlayer);
you should be comparing their IDs
Code:
local bPlayerNotSelf = (p:GetID() ~= pPlayer:GetID());
But in both cases you already know their IDs as you constructed the objects from them
Code:
local bPlayerNotSelf = (i ~= iPlayer);
But, as i will always be a city state, and (once you've fixed the test for the player being Morocco) iPlayer will always be a major, bPlayerNotSelf will always be false, so the test is superfluous and can be removed

If p (the city state) is not alive, the return value for p:GetTeam() is undefined, so HasMet() may throw an error,
Code:
	local bPlayerIsAlive = p:IsAlive();
	local bPlayerHasMet = Teams[pPlayer:GetTeam()].HasMet(Teams[p:GetTeam()]);

	-- If everything checks out...
	if(bPlayerNotSelf and bPlayerIsAlive and bPlayerHasMet) then
the assignment either needs to be after the test for IsAlive() being true, or guaranteed not to be evaluated (due to lazy evaluation of conditions)
Code:
	-- If everything checks out...
	if(p:IsAlive() and Teams[pPlayer:GetTeam()].HasMet(Teams[p:GetTeam()])) then

Aside for others: Lazy evaluation guarantees that for "A and B" if A is false, B will never be evaluated (as "false and anything" is always false). And for "C or D" if C is true, D will never be evaluated (as "true or anything" is always true). This is why you can write "if (pUnit and pUnit:SomeMethod()) then" safe in the knowledge that if pUnit is nil, you WON'T get a nil pointer error at the "pUnit:SomeMethod()" part (as in Lua nil is false).

City IDs are not sequentially ascending from 0 (the first is 8196, the second 16384 or something like that) (for loop is also missing the "do")
Code:
	-- Cycle through all of the player's cities.
	for(c = 0, pPlayer:GetNumCities(), 1)
		-- Get the current city in the list
		local pCity = pPlayer:GetCityByID(c);
but the sequence doesn't matter as there's a Lua iterator for this (and also units)
Code:
	-- Cycle through all of the player's cities.
	for pCity in pPlayer:GetCities() do

Not checked the maths/API functions
 
Back
Top Bottom