LUA help?

You've no test for iPlayer actually being Morocco, so every player in the game will get the benefit

This was merely going off the above code he provided in his work. I figured I would keep the original, but didn't check to make sure it was completely correct. My bad will make adjustments.

You're mixing and matching "pPlayer" and "player" (multiple places) so the code will throw an error at

Yes, and this was not intentional, I had made a typo in some of my modifications. I was very tired when I wrote this. I'm not surprised there are some errors.

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

This is probably true, however again I just copied what he had in the original and tacked on the code at the bottom. I will make some fixes after I respond to you.

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)

Yep something else I didn't catch, I was going off some firaxis code in the diplocorner.lua file. Indeed they used iPlayer, not the pointer object. I transcribed an error. Will fix.

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

This whole section will be re written.

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")

but the sequence doesn't matter as there's a Lua iterator for this (and also units)

Was not aware of this, will correct. Thanks.

Not checked the maths/API functions

I double checked everything here, should be correct. I'll look again and test just to be safe.
 
  • I made some changes in the code within post #18 based on William's comments and on something that OuroborosOrder caught (namely, the desire to cap the effect at 30%)
  • The general reason we use Dummy Buildings rather than direct lua changes is that the direct lua-changes don't show as being in effect anywhere for the User of the Game. By using a dummy building, the game both handles the mathematics of (in this case) modifying Great People generation, as well as showing the human User of the Game that there is a modification in effect.
    • When we don't do something that will show in an intuitive way to the User of the Game, we get bogged down in interminable rounds of:
      • User 1: The mod is not working, I see no % modification being reported.
      • Us: Check the actual # of great people points on turn X and compare to turn X+1. The code is not written to actually show the modification in the city view.
      • User 1: Oh, OK. Yup, it's working.
      • User 2: Well, that's just a silly and bad way to make a mod.
      • User 2: I don't see it is working for me. I'm unsubbing from the mod
      • Us: Well, OK.
      • User 3: The mod isn't working for me!
      • User 4: It isn't working for me either, I don't see a % modification being reported anywhere when I mouse over a city's Great People Counters.
      • Us: :wallbash:
  • Dummy Buildings don't deal with all of the UI issues, but they deal with a great many of them, and reduce the number of mods that are all adding custom versions of CityView.lua, for instance, which reduces the number of incompatible mods.
 
Version 2 of my script:

See Version 3.

Spoiler :
Code:
[COLOR="Sienna"]
-- MoroccoUniqueAbility.lua (v2)
-- 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);

	-- Make sure this is Morocco.
	-- CIVILIZATION_MOROCCO needs to be modded in as well.
	if pPlayer:GetCivilizationType() ~= GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] then
		return;
	end;

	-- Retrieve the database defines for our mod. This adds flexibility!
	-- We need the mods to be at least 1 so that 
	local pMoroccoTrait = GameInfo.Traits.EXOTIC_NATION;
	local fAbilityGPTFromTourismMod = pMoroccoTrait.GoldFromTourismPerTurnMod;
	local fAbilityCPTFromTourismMod = pMoroccoTrait.CultureFromTourismPerTurnMod;
	local fAbilityGoldenAgeMod = pMoroccoTrait.GoldenAgeMod;

	-- Now for the benefit stuff! +gold and +tourism perturn!
	local iPlayerTourism = pPlayer:GetTourism();
	local iPlayerGPTFromTourism = math.floor(iTourism * fAbilityGPTFromTourismMod);
	local iPlayerCPTFromTourism = math.floor(iTourism * fAbilityCPTFromTourismMod);

	-- Make sure our golen age mod is not 0 before we apply it.
	if g_fAbilityGoldenAgeMod ~= 0 then
		-- If the player is in a Golden Age they recieve an increase to the gold and culture gain!
		if pPlayer:IsGoldenAge() then
			iPlayerGPTFromTourism = math.floor(iPlayerGPTFromTourism * fAbilityGoldenAgeMod)
			iPlayerCPTFromTourism = math.floor(iPlayerCPTFromTourism * fAbilityGoldenAgeMod)
		end
	end

	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerCPTFromTourism ~= 0 then
		-- Update Player Gold.
		pPlayer:ChangeGold(iPlayerCPTFromTourism)
	end
	
	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerCPTFromTourism ~= 0 then
		-- Update Player Culture.
		pPlayer:ChangeJONSCulture(iPlayerCPTFromTourism);
	end

	-- Used for counting the number of players we have EXOTIC cultural influence with.
	local iExoticInfluenceCount = 0;

	-- 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 pOtherPlayer = Players[i];

		-- Check to make sure we are not trying to compare to ourself or a dead player. lol...
		local bPlayerNotSelf = (i ~= iPlayer);
		local bPlayerIsAlive = pOtherPlayer:IsAlive();

		-- If everything checks out...
		if(bPlayerNotSelf and bPlayerIsAlive) then
			-- Check to make sure we've met the player.
			local pTeam = Teams[pPlayer:GetTeam()];
			local pOtherTeam = Teams[pOtherPlayer:GetTeam()];
			local bPlayerHasMet = pTeam.HasMet(pOtherTeam);

			if(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.
					iExoticInfluenceCount = iExoticInfluenceCount + 1;
				end
			end
		end

		-- Get the max mod to allow for our benefit.
		local iMaxGPMod = pMoroccoTrait.MaxGreatPersoMod;
		-- Get the great person per exotic influence civ mod.
		local iGPPerExoticInfluenceMod = pMoroccoTrait.GreatPersonPerExoticInfluenceMod;
		-- Calculate the max count allowed for our benefit.
		local iMaxExoticInfluenceCount = iMaxGPMod / iGPPerExoticInfluenceMod;
		-- Check to make sure our civs with Exotic influence is not more than we want. :)
		if(iExoticInfluenceCount > iMaxExoticInfluenceCount)
			iExoticInfluenceCount = iMaxExoticInfluenceCount;
		end

		-- Cycle through all of the player's cities.
		for pCity in pPlayer.Cities() do
			-- 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 = iExoticInfluenceCount * iGPPerExoticInfluenceMod;

			-- Calculate our great person rate adjustment to be added into the equation.
			--====================================================================================================
			-- 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 target 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]
 
Version 2 of my script:

Spoiler :
Code:
[COLOR="Sienna"]
-- MoroccoUniqueAbility.lua (v2)
-- 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);

	-- Make sure this is Morocco.
	-- CIVILIZATION_MOROCCO needs to be modded in as well.
	if pPlayer:GetCivilizationType() ~= GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] then
		return;
	end;

	-- Retrieve the database defines for our mod. This adds flexibility!
	-- We need the mods to be at least 1 so that 
	local pMoroccoTrait = GameInfo.Traits.EXOTIC_NATION;
	local fAbilityGPTFromTourismMod = pMoroccoTrait.GoldFromTourismPerTurnMod;
	local fAbilityCPTFromTourismMod = pMoroccoTrait.CultureFromTourismPerTurnMod;
	local fAbilityGoldenAgeMod = pMoroccoTrait.GoldenAgeMod;

	-- Now for the benefit stuff! +gold and +tourism perturn!
	local iPlayerTourism = pPlayer:GetTourism();
	local iPlayerGPTFromTourism = math.floor(iTourism * fAbilityGPTFromTourismMod);
	local iPlayerCPTFromTourism = math.floor(iTourism * fAbilityCPTFromTourismMod);

	-- Make sure our golen age mod is not 0 before we apply it.
	if g_fAbilityGoldenAgeMod ~= 0 then
		-- If the player is in a Golden Age they recieve an increase to the gold and culture gain!
		if pPlayer:IsGoldenAge() then
			iPlayerGPTFromTourism = math.floor(iPlayerGPTFromTourism * fAbilityGoldenAgeMod)
			iPlayerCPTFromTourism = math.floor(iPlayerCPTFromTourism * fAbilityGoldenAgeMod)
		end
	end

	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerCPTFromTourism ~= 0 then
		-- Update Player Gold.
		pPlayer:ChangeGold(iPlayerCPTFromTourism)
	end
	
	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerCPTFromTourism ~= 0 then
		-- Update Player Culture.
		pPlayer:ChangeJONSCulture(iPlayerCPTFromTourism);
	end

	-- Used for counting the number of players we have EXOTIC cultural influence with.
	local iExoticInfluenceCount = 0;

	-- 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 pOtherPlayer = Players[i];

		-- Check to make sure we are not trying to compare to ourself or a dead player. lol...
		local bPlayerNotSelf = (i ~= iPlayer);
		local bPlayerIsAlive = pOtherPlayer:IsAlive();

		-- If everything checks out...
		if(bPlayerNotSelf and bPlayerIsAlive) then
			-- Check to make sure we've met the player.
			local pTeam = Teams[pPlayer:GetTeam()];
			local pOtherTeam = Teams[pOtherPlayer:GetTeam()];
			local bPlayerHasMet = pTeam.HasMet(pOtherTeam);

			if(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.
					iExoticInfluenceCount = iExoticInfluenceCount + 1;
				end
			end
		end

		-- Get the max mod to allow for our benefit.
		local iMaxGPMod = pMoroccoTrait.MaxGreatPersoMod;
		-- Get the great person per exotic influence civ mod.
		local iGPPerExoticInfluenceMod = pMoroccoTrait.GreatPersonPerExoticInfluenceMod;
		-- Calculate the max count allowed for our benefit.
		local iMaxExoticInfluenceCount = iMaxGPMod / iGPPerExoticInfluenceMod;
		-- Check to make sure our civs with Exotic influence is not more than we want. :)
		if(iExoticInfluenceCount > iMaxExoticInfluenceCount)
			iExoticInfluenceCount = iMaxExoticInfluenceCount;
		end

		-- Cycle through all of the player's cities.
		for pCity in pPlayer.Cities() do
			-- 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 = iExoticInfluenceCount * iGPPerExoticInfluenceMod;

			-- Calculate our great person rate adjustment to be added into the equation.
			--====================================================================================================
			-- 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 target 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]


  1. This will only ever check City-States and the Barbarian player, none of whom will the required civilization ever be "Exotic" or higher in terms of Tourism
    Code:
    for(i = GameInfo.Defines.MAX_MAJOR_CIVS, GameInfo.Defines.MAX_CIV_PLAYERS-1, 1) do
    To run through the major players, the code needs
    Code:
    for(i = 0, GameInfo.Defines.MAX_MAJOR_CIVS-1, 1) do
    Within lua and in single-player games (as opposed to multiplayer), the human player is always player #0.
  2. These will result in 'nil' unless the mod also adds such columns to the <Traits> table:
    Code:
    local fAbilityGPTFromTourismMod = pMoroccoTrait.GoldFromTourismPerTurnMod;
    local fAbilityCPTFromTourismMod = pMoroccoTrait.CultureFromTourismPerTurnMod;
    local fAbilityGoldenAgeMod = pMoroccoTrait.GoldenAgeMod
    They may also cause fatal syntax error to the lua. I've never tested what happens when you try to get the value for a non-existant column.
  3. Typo oops
    Code:
    pPlayer:ChangeGold(iPlayerCPTFromTourism)
  4. Move this up above the loop through players. No need to keep creating and then discarding the same variable
    Code:
    local pTeam = Teams[pPlayer:GetTeam()];
  5. Syntax error here
    Code:
    local bPlayerHasMet = pTeam.HasMet(pOtherTeam);
    • There is no "HasMet" in "Teams".
    • You want
      Code:
      Team:IsHasMet(TeamID index)
    • You want the Team ID# and not the pointer object for "pOtherTeam"
    • You can use "." rather than ":" syntax, but this requires as I recall a syntax as
      Code:
      pTeam.IsHasMet(pTeam, iOtherTeamID)
  6. You are only using the "IsHasMet" once in the code of the loop, so it may actually make more sense to drop the creation of the boolean local variable and just check directly whether the two teams have met:
    Code:
    if pTeam:IsHasMet(iOtherTeamID) then
  7. Same issue as mentioned before with non-existant columns
    Code:
    -- Get the max mod to allow for our benefit.
    local iMaxGPMod = pMoroccoTrait.MaxGreatPersoMod;
    -- Get the great person per exotic influence civ mod.
    local iGPPerExoticInfluenceMod = pMoroccoTrait.GreatPersonPerExoticInfluenceMod;
 
You can use "." rather than ":" syntax, but this requires as I recall a syntax as
Code:
pTeam.IsHasMet(pTeam, iOtherTeamID)

Go stand in the corner! This syntax should NOT be encouraged :eek:

Code:
GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"]
Is an error ('Type' is a string, not an array)
Should be
Code:
GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ID
or just
Code:
GameInfoTypes.CIVILIZATION_MOROCCO
see http://forums.civfanatics.com/showthread.php?t=485884

Also, no standard Firaxis table has a float/real database column (due to multiplayer issues between machines with different FPU architectures), so the new trait columns should be integers representing percentages and divided internally by 100
 
Morocco Civilization (v3)

Note: MorrocoCivilizationText.xml file needs to be created and filled in for all the Moroccan text key entries.

Edit: Made minor corrections to MoroccoUniqueAbility.lua




========================MoroccoUniqueAbility.lua (v3)========================

Spoiler :
Code:
[COLOR="Sienna"]
-- MoroccoUniqueAbility.lua (v3)
-- Author: Ouroboros
-- DateCreated: 4/8/2016
--------------------------------------------------------------

 -- replace this tag to call the civ whatever you want, but make sure to change it in the XML file as well!
local  iCivID = GameInfo.Civilizations.CIVILIZATION_MOROCCO.ID;

-- 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);

	-- Make sure this is Morocco.
	-- CIVILIZATION_MOROCCO needs to be modded in as well.
	if pPlayer:GetCivilizationType() ~= iCivID then
		return;
	end;

	-- Retrieve the database defines for our mod. This adds flexibility!
	-- We need the mods to be at least 1 so that 
	local pMoroccoTrait = GameInfo.Traits.Type.EXOTIC_NATION;
	local fAbilityGPTFromTourismMod = pMoroccoTrait.GoldFromTourismPerTurnMod / 100;
	local fAbilityCPTFromTourismMod = pMoroccoTrait.CultureFromTourismPerTurnMod / 100;
	local fAbilityGoldenAgeMod = pMoroccoTrait.GoldenAgeMod / 100;

	-- Now for the benefit stuff! +gold and +tourism perturn!
	local iPlayerTourism = pPlayer:GetTourism();
	local iPlayerGPTFromTourism = math.floor(iTourism * fAbilityGPTFromTourismMod);
	local iPlayerCPTFromTourism = math.floor(iTourism * fAbilityCPTFromTourismMod);

	-- Make sure our golen age mod is not 0 before we apply it.
	if g_fAbilityGoldenAgeMod ~= 0 then
		-- If the player is in a Golden Age they recieve an increase to the gold and culture gain!
		if pPlayer:IsGoldenAge() then
			iPlayerGPTFromTourism = math.floor(iPlayerGPTFromTourism * fAbilityGoldenAgeMod)
			iPlayerCPTFromTourism = math.floor(iPlayerCPTFromTourism * fAbilityGoldenAgeMod)
		end
	end

	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerGPTFromTourism ~= 0 then
		-- Update Player Gold.
		pPlayer:ChangeGold(iPlayerGPTFromTourism)
	end
	
	-- No point in updating if there is no change. I.E. someone set our modifiers to 0!
	if iPlayerCPTFromTourism ~= 0 then
		-- Update Player Culture.
		pPlayer:ChangeJONSCulture(iPlayerCPTFromTourism);
	end

	-- Used for counting the number of players we have EXOTIC cultural influence with.
	local iExoticInfluenceCount = 0;

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

		-- Check to make sure we are not trying to compare to ourself or a dead player. lol...
		local bPlayerNotSelf = (i ~= iPlayer);
		local bPlayerIsAlive = pOtherPlayer:IsAlive();

		-- If everything checks out...
		if(bPlayerNotSelf and bPlayerIsAlive) then
			-- Check to make sure we've met the player.
			local pTeam = Teams[pPlayer:GetTeam()];
			local iOtherTeam = pOtherPlayer:GetTeam();
			local bPlayerHasMet = pTeam:IsHasMet(iOtherTeam);

			if(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.
					iExoticInfluenceCount = iExoticInfluenceCount + 1;
				end
			end
		end

		-- Get the max mod to allow for our benefit.
		local iMaxGPMod = pMoroccoTrait.MaxGreatPersonMod;
		-- Get the great person per exotic influence civ mod.
		local iGPPerExoticInfluenceMod = pMoroccoTrait.GreatPersonPerExoticInfluenceMod;
		-- Calculate the max count allowed for our benefit.
		local iMaxExoticInfluenceCount = iMaxGPMod / iGPPerExoticInfluenceMod;
		-- Check to make sure our civs with Exotic influence is not more than we want. :)
		if(iExoticInfluenceCount > iMaxExoticInfluenceCount)
			iExoticInfluenceCount = iMaxExoticInfluenceCount;
		end

		-- Cycle through all of the player's cities.
		for pCity in pPlayer.Cities() do
			-- 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 = iExoticInfluenceCount * iGPPerExoticInfluenceMod;

			-- Calculate our great person rate adjustment to be added into the equation.
			--====================================================================================================
			-- 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 target 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]

======================= END MoroccoUniquAbility.lua (v3)======================






========================MoroccoCivilization.xml (v3)=========================

Spoiler :
Code:
[COLOR="Sienna"]
<?xml version="1.0" encoding="utf-8"?>

<!-- MoroccoCivilization.xml (v3) -->
<!-- Author: Ouroboros -->
<!-- DateCreated: 4/8/2016 -->
<!--**************************************-->

<GameData>
	<Civilizations>
		<Row>
			<Type>CIVILIZATION_MOROCCO</Type>
			<Description>TXT_KEY_CIV_MOROCCO_DESC</Description>
			<ShortDescription>TXT_KEY_CIV_MOROCCO_SHORT_DESC</ShortDescription>
			<Adjective>TXT_KEY_CIV_MOROCCO_ADJECTIVE</Adjective>
			<CivilopediaTag>TXT_KEY_CIV5_MOROCCO</CivilopediaTag>
			<DefaultPlayerColor>PLAYERCOLOR_MOROCCO</DefaultPlayerColor>
			<ArtDefineTag>ART_DEF_CIVILIZATION_MOROCCO</ArtDefineTag>
			<ArtStyleType>ARTSTYLE_MIDDLE_EAST</ArtStyleType>
			<PortraitIndex></PortraitIndex>
			<IconAtlas>CIV_COLOR_ATLAS</IconAtlas>
			<AlphaIconAtlas>CIV_ALPHA_ATLAS</AlphaIconAtlas>
			<MapImage>MapMorocco512.dds</MapImage>
			<ArtStyleSuffix>_AFRI</ArtStyleSuffix>
			<ArtStylePrefix>AFRICAN </ArtStylePrefix>
			<DawnOfManQuote>TXT_KEY_CIV5_DAWN_MOROCCO_TEXT</DawnOfManQuote>
			<DawnOfManImage>DOM_MoroccanLeader.dds</DawnOfManImage>
			<DawnOfManAudio>AS2D_DOM_SPEECH_MOROCCO</DawnOfManAudio>
		</Row>
	</Civilizations>
</GameData>
[/COLOR]

======================= END MoroccoCivilization.xml (v3)=======================






===========================MoroccoTrait.sql (v3)==========================

Spoiler :
Code:
[COLOR="Sienna"]

-- MoroccoTrait.sql (v3)
-- Author: Ouroboros
-- DateCreated: 4/8/2016
--------------------------------------------------------------

ALTER TABLE Traits COLUMN 'GoldFromTourismPerTurnMod' INTEGER DEFAULT 0;
ALTER TABLE Traits COLUMN 'CultureFromTourismPerTurnMod' INTEGER DEFAULT 0;
ALTER TABLE Traits COLUMN 'GoldenAgeMod' INTEGER DEFAULT 0;

[/COLOR]

======================= END MoroccoTrait.sql (v3)===========================






=======================MoroccoTraitText.xml (v3)===========================

Spoiler :
Code:
[COLOR="sienna"]
<?xml version="1.0" encoding="utf-8"?>

<!-- MoroccoTraitText.xml (v3) -->
<!-- Author: Ouroboros -->
<!-- DateCreated: 4/8/2016 -->
<!--**************************************-->

<GameData>
	<Language_en_US>
		<Row Tag = "TXT_KEY_DESC_EXOTIC_NATION">
			<Text>
				For every 2 [ICON_TOURISM] Tourism output by your civilization gain +2 [ICON_GOLD] Gold and +1 [ICON_CULTURE] Culture , however this is increased by 15% during a [ICON_GOLDEN_AGE] Golden Age. [ICON_GREAT_PEOPLE] Great People are earned +5% faster for every civilization you have become [ICON_CULTURE] Exotic with. (Max: 30%)
			</Text>
		</Row>
		<Row Tag = "TXT_KEY_DESC_SHORT_EXOTIC_NATION">
			<Text>
				For every 2 [ICON_TOURISM] Tourism output by your civilization gain +2 [ICON_GOLD] Gold and +1 [ICON_CULTURE] Culture , however this is increased by 15% during a [ICON_GOLDEN_AGE] Golden Age. [ICON_GREAT_PEOPLE] Great People are earned +5% faster for every civilization you have become [ICON_CULTURE] Exotic with. (Max: 30%)
			</Text>
		</Row>
	</Language_en_US>
</GameData>
[/COLOR]

====================== END MoroccoTraitText.xml (v3)=========================






=========================MoroccoTrait.xml (v3)============================

Spoiler :
Code:
[COLOR="Sienna"]
<?xml version="1.0" encoding="utf-8"?>

<!-- MoroccoTrait.xml (v3) -->
<!-- Author: Ouroboros -->
<!-- DateCreated: 4/8/2016 -->
<!--**************************************-->

<GameData>
	<Traits>
		<Row>
			<Type>EXOTIC_NATION</Type>
			<Description>TXT_KEY_DESC_EXOTIC_NATION</Description>
			<ShortDescription>TXT_KEY_DESC_SHORT_EXOTIC_NATION</ShortDescription>
			<GoldFromTourismPerTurnMod>100</GoldFromTourismPerTurnMod>
			<CultureFromTourismPerTurnMod>50</CultureFromTourismPerTurnMod>
			<GoldenAgeMod>115</GoldenAgeMod>
		</Row>
	</Traits>
</GameData>

[/COLOR]

========================= END MoroccoTrait.xml (v3)=========================
 
@LeeS and Whoward thanks for checking my work guys. I was actually already making the corresponding xml files. Anyways hope this starter mod helps our author here. :)
 
@LeeS and Whoward thanks for checking my work guys. I was actually already making the corresponding xml files. Anyways hope this starter mod helps our author here. :)
Well, you still have the GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] and the pPlayer:ChangeGold(iPlayerCPTFromTourism) typo whoops.

I would just replace this construction GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] with a cached variable at the top of the file, as in
Code:
[COLOR="Blue"]local iCivID = GameInfoTypes.CIVILIZATION_MOROCCO[/COLOR]

-- 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);

	-- Make sure this is Morocco.
	-- CIVILIZATION_MOROCCO needs to be modded in as well.
	if pPlayer:GetCivilizationType() ~= [COLOR="Blue"]iCivID[/COLOR] then
		return;
	end;
	--etc.......
Because the OP was only using Morocco as a placeholder for testing the lua code, and this makes it easier to find the point in the code where the Civilization's name needs to be changed. But the construction to do it your way needs to be
Code:
GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ID

Your type whoops with the gold thing is that you are using the variable-name you assigned for the Culture Change. Typos will drive you to insanity, especially if the two modifier columns you are introducing to <Traits> have a differing value for the same Trait.
 
Well, you still have the GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] and the pPlayer:ChangeGold(iPlayerCPTFromTourism) typo whoops.

I would just replace this construction GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"] with a cached variable at the top of the file, as in
Code:
[COLOR="Blue"]local iCivID = GameInfoTypes.CIVILIZATION_MOROCCO[/COLOR]

-- 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);

	-- Make sure this is Morocco.
	-- CIVILIZATION_MOROCCO needs to be modded in as well.
	if pPlayer:GetCivilizationType() ~= [COLOR="Blue"]iCivID[/COLOR] then
		return;
	end;
	--etc.......
Because the OP was only using Morocco as a placeholder for testing the lua code, and this makes it easier to find the point in the code where the Civilization's name needs to be changed. But the construction to do it your way needs to be
Code:
GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ID

Your type whoops with the gold thing is that you are using the variable-name you assigned for the Culture Change. Typos will drive you to insanity, especially if the two modifier columns you are introducing to <Traits> have a differing value for the same Trait.

Everything should be fixed now. :)
 
You're still missing the issue with the reference to get the civilization's ID#. Column 'Type' cannot be indexed as a table in lua.

This construction treats XML-game Table 'Civilizations' as an lua-table, and gets the ID# for the matching civilization within the game-table:
Code:
GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ID
.

This part
Code:
Civilizations["CIVILIZATION_MOROCCO"]
is like doing this in an lua table
Code:
tDogs["GreyHound"]
Except that the GameInfo system is set-up to recognize and match any string that also matches with a valid 'Type' designation from within a primary game-table, and to stick all the info within the matching row into a table. In this case that table becomes GameInfo.Civilizations["CIVILIZATION_MOROCCO"], and within that table the keys are the column-names and the values are the data within each respective column. So GameInfo.Civilizations["CIVILIZATION_MOROCCO"].Type is equal to CIVILIZATION_MOROCCO, but it is not a table within lua, it is a text string. GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ShortDescription would give the TXT_KEY tag-name for Morocco's <ShortDescription> setting.

We generally don't try to grab the info for a row within a primary game-table via the ID# because for modded civs, buildings, etc., we don't know what the ID# is. Even for the Firaxis-supplied buildings, we cannot rely on the ID# that normally applies to BUILDING_LONGHOUSE for example, because we cannot be sure within the code of any mod that another mod has not made major changes to table <Buildings> which have resulted in the usual ID# for BUILDING_LONGHOUSE having been changed or otherwise made invalid.


If you do this
Code:
print(GameInfo.Civilizations.Type["CIVILIZATION_MOROCCO"])
you'll get an error for attempting to index 'Type'.

This will print to the lua log the ID# of CIVILIZATION_MOROCCO
Code:
print(GameInfo.Civilizations["CIVILIZATION_MOROCCO"].ID)

This will print to the lua log the 'Type' of CIVILIZATION_MOROCCO
Code:
print(GameInfo.Civilizations["CIVILIZATION_MOROCCO"].Type)
which will be "CIVILIZATION_MOROCCO".
 
Ah! I see what you mean... I still had that line wrong. There is so much to process being new to Civ modding that it's hard to keep track of. Indeed, Type is a field, not a value for said field.

So what I want is:

Code:
local  iCivID = GameInfo.Civilizations.CIVILIZATION_MOROCCO.ID;

This can be confirmed by setting print(GameInfo.Civilizations.CIVILIZATION_SWEDEN.ID) in the firetuner (I happened to have it open because I'm testing some stuff). It prints 35 because 35 is the civ ID of sweden.

Changing this now.
 
Use GameInfoTypes.CIVILIZATION_MOROCCO

(It's one table lookup as opposed to three!!!)

(See the tutorial linked in post #25)
 
Here's a bit of code I use to generate GP and Golden Age and Gold Bonuses via a lua governed trait. I think i took elements of it from Iceco's - not another city state's mod. It allocates Great Person points amongst all of a player's cities every turn based upon certain bonuses (you could probably set up your own bonus system). As well, there are Golden Age length and points added per turn based upon map speed. Likewise, the way bonuses are determined can be customized to your needs. The Gold Bonus is another part of the trait.

All three elements can be used separately and can be adjusted with if...then contingencies at to when the function will fire and how big of a bonus is given.

This is dependent upon whether you wish to continue using dummy buildings or wish to have a purely code driven trait.

Anyhow, here it is...

Code:
function GreatPersonEffect( iHRE, pHRE, GreatPersonBonus )
	
	--print(string.format("GreatPersonBonus of %d for %s:", GreatPersonBonus, pHRE:GetName()))
	if GreatPersonBonus >= 6 then
		local pCapital = pHRE:GetCapitalCity()
		if pCapital ~= nil then
			local Remainder = GreatPersonBonus % 6
			GreatPersonBonus = GreatPersonBonus - Remainder
			local CapitalExtraBonus = GreatPersonBonus / 6
			
			local ClosestGP = 0
			local GPAmount = 0
			-- Determine the GP for which the progress is currently the highest
			for specialist in GameInfo.Specialists() do
				--print(string.format("%s: %d", pCapital:GetName(), specialist.ID))
				-- GP with ID one is the citizen specialist, which isn't a proper specialist, so should always be trumped by another
				if ClosestGP == 0 and specialist.ID ~= 0 then
					ClosestGP = specialist.ID
					--print(string.format("  ClosestGP in %s was citizen specialist (default), now %d", pCapital:GetName(), specialist.ID))
				elseif ( pCapital:GetSpecialistGreatPersonProgressTimes100( specialist.ID ) > pCapital:GetSpecialistGreatPersonProgressTimes100( ClosestGP ) and specialist.ID ~= 0 ) then
					ClosestGP = specialist.ID
					--print(string.format("  new ClosestGP in %s: %d", pCapital:GetName(), specialist.ID))
				end
				GPAmount = specialist.ID
			end
			-- Apply bonus to that GP
			if pCapital:GetSpecialistGreatPersonProgressTimes100( ClosestGP ) ~= 0 then
				pCapital:ChangeSpecialistGreatPersonProgressTimes100( ClosestGP, CapitalExtraBonus * 100 )
				--print(string.format("  GreatPersonBonus applied! (%s, %s) - %d points left", pHRE:GetName(), pCapital:GetName(), GreatPersonBonus - CapitalExtraBonus + Remainder))
			else 
				ClosestGP = Game.Rand( GPAmount, "random GP" ) + 1 -- "+ 1" to avoid picking the citizen specialist
				pCapital:ChangeSpecialistGreatPersonProgressTimes100( ClosestGP, CapitalExtraBonus * 100 )
				--print(string.format("  GreatPersonBonus applied! (%s, %s) - %d points left (random pick)", pHRE:GetName(), pCapital:GetName(), GreatPersonBonus - CapitalExtraBonus + Remainder))
			end
			GreatPersonBonus = GreatPersonBonus - CapitalExtraBonus + Remainder
		end
	end
	repeat
		for pCity in pHRE:Cities() do
			if GreatPersonBonus > 0 then
				local ClosestGP = 0
				local GPAmount = 0
				-- Determine the GP for which the progress is currently the highest
				for specialist in GameInfo.Specialists() do
					--print(string.format("%s: %d", pCity:GetName(), specialist.ID))
					-- GP with ID one is the citizen specialist, which isn't a proper specialist, so should always be trumped by another
					if ClosestGP == 0 and specialist.ID ~= 0 then
						ClosestGP = specialist.ID
						--print(string.format("  ClosestGP in %s was citizen specialist (default), now %d", pCity:GetName(), specialist.ID))
					elseif ( pCity:GetSpecialistGreatPersonProgressTimes100( specialist.ID ) > pCity:GetSpecialistGreatPersonProgressTimes100( ClosestGP ) and specialist.ID ~= 0 ) then
						ClosestGP = specialist.ID
						--print(string.format("  new ClosestGP in %s: %d", pCity:GetName(), specialist.ID))
					end
					GPAmount = specialist.ID
				end
				-- Apply bonus to that GP
				if pCity:GetSpecialistGreatPersonProgressTimes100( ClosestGP ) ~= 0 then
					pCity:ChangeSpecialistGreatPersonProgressTimes100( ClosestGP, 100 )
					GreatPersonBonus = GreatPersonBonus - 1
					--print(string.format("  GreatPersonBonus applied! (%s, %s) - %d points left", pHRE:GetName(), pCity:GetName(), GreatPersonBonus))
				else 
					ClosestGP = Game.Rand( GPAmount, "random GP" ) + 1 -- "+ 1" to avoid picking the citizen specialist
					pCity:ChangeSpecialistGreatPersonProgressTimes100( ClosestGP, 100 )
					GreatPersonBonus = GreatPersonBonus - 1
					--print(string.format("  GreatPersonBonus applied! (%s, %s) - %d points left (random pick)", pHRE:GetName(), pCity:GetName(), GreatPersonBonus))
				end
			end
		end
	until GreatPersonBonus < 1
end


-- Sets up Holy Roman Empire
-- Determines if HRE is alive
-- Determine bonus level based puppeted cities
-- Distribute points to Capital and then other cities

function HREGoldBonus(iPlayer)

--Set up HRE

	local pHRE = Players[iPlayer]
	local civHRE = false
  	if (GameInfo.Civilizations.CIVILIZATION_PERSIA.ID == pHRE:GetCivilizationType()) then
	
	civHRE = true

	end
	
-- Set up bonus
	
	if ( pHRE:IsAlive () ) and civHRE == true then
			
		local CityBonus = pHRE:GetNumCities()
		local RathausBonus = pHRE:CountNumBuildings(GameInfoTypes["BUILDING_RATHAUS"])
		local Bonus = (CityBonus+1)*2 + RathausBonus --palace +1
		local GoldBonus = (Bonus*2) + math.ceil(pHRE:GetCurrentEra() * (Bonus))
		pHRE:ChangeGold( GoldBonus )
		--print (pHRE:GetName() ,"has increased Gold by ",GoldBonus, "gold due to Imperial tribute");
		
	else	
	end
		return	
end



local modData = Modding.OpenSaveData()
local modGoldenAgeKey = "GoldenAge"
local haveGoldenAge = (modData.GetValue(modGoldenAgeKey) == 1)

-- Sets up Holy Roman Empire
-- Determines if HRE is alive
-- Determine bonus level based on number of puppeted cities
-- no Golden Age adds bonus to progress and sets mod data to false
-- if Golden Age sets mod data to true and increases Golden Age length

function HREGoldenAges(iPlayer)
	--Set up HRE

	local pHRE = Players[iPlayer]
	local civHRE = false
  	if (GameInfo.Civilizations.CIVILIZATION_PERSIA.ID == pHRE:GetCivilizationType()) then
	
	civHRE = true

	end
	
	-- Set up bonus
	
	if ( pHRE:IsAlive () ) and civHRE == true then

		local CityBonus = pHRE:GetNumCities()
		local Bonus = math.ceil(CityBonus/2)
		local iGoldenAgePercent = GameInfo.GameSpeeds[Game.GetGameSpeedType()].GoldenAgePercent/ 100
		local BonusMod = math.ceil(iGoldenAgePercent*Bonus)			
		local GoldenAgeProgressBonus = Bonus + (pHRE:GetCurrentEra() * Bonus )
		local IsGoldenAge = pHRE:IsGoldenAge()

		if not IsGoldenAge then

		pHRE:ChangeGoldenAgeProgressMeter( GoldenAgeProgressBonus )
		haveGoldenAge = false
		modData.SetValue(modGoldenAgeKey, 1)
		--print (pHRE:GetName() ,"is getting",GoldenAgeProgressBonus, "points towards a Golden Age from Free Imperial Cities");

		elseif IsGoldenAge then

			if (haveGoldenAge == false) then

			pHRE:ChangeGoldenAgeTurns( BonusMod )
			haveGoldenAge = true
			modData.SetValue(modGoldenAgeKey, 1)
			--print (pHRE:GetName() ,"has increased Golden Age by ",Bonus, "turns from Free Imperial Cities");

			end
		end
	else
	end
		return
end



--Operate functions to loop through all players

local function OnAllPlayersDoTurn(iPlayer)		
		
		HREGreatPersons(iPlayer)
		HREGoldBonus(iPlayer)
		HREGoldenAges(iPlayer)

end
GameEvents.PlayerDoTurn.Add(OnAllPlayersDoTurn)

Hope this helps a bit.
 
Back
Top Bottom