Lua - Adding X Culture and Faith per each Y Gold from Trade Routes

Genghis.Khan

Person
Joined
Jun 9, 2012
Messages
934
Location
Somewhere
I am currently creating an Armenian Civilization, for the RFE Project. I would like to implement the following Trait:

Crossroads of Caucasus- Generate Faith and Culture per each Trade Route

I am aware that this requires Lua coding and that I am only a very begginer with Lua, but I'd like to know if it is doable (even if it requires C++) and how.

I spent some time and I found the following method, which I think is a way to implement this Trait:

GetCityConnectionGold (and GetCityConnectionGoldTimes100)

I had already found a sample of code (in some scenario, the Fall of Rome or the Mongol one) in which a yield (not sure which, I think culture) was added , based on City Capture (or something like that). So would it be possible to code something like this:

Code:
-- Crossroads of Caucasus.lua
-- File Version: 0.1 (25-05-2013)
-- Author: Genghis.Khan
-- Special Thanks:  
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
if Player:GetCivilizationType() == GameInfoTypes["CIVILIZATION_ARMENIA"]) then
Player.GetCityConnectionGold --Times100?
-- Add Culture and Faith Equal to  1/5 of Gold Generation from Trade Routes
end
 
Checking to see if a city is connected to the capitol is easy enough:
Code:
pPlayer.IsCapitalConnectedToCity(pCity)
After that you probably (as far as I can tell so far) want to use City:ChangeCultureRateModifier() and City:ChangeBaseYieldRateFromReligion() but those are poorly documented functions so I'd have to check the dll/lua code to be sure.

You could do the check every turn to see if a city is connected (in Events.PlayerDoTurn) and keep a table of ones you've already given a bonus to. If it's in the table don't give the bonus. If it's in the table but not connected remove it from the table. If it's not in the table but connected, give the bonus and put it in the table.

But, those functions listed above are unknown to me so this is more of a 'might help you get started in the right direction' answer then a known working solution.
 
Code:
void CvCity::changeCultureRateModifier(int iChange)
{
	VALIDATE_OBJECT
	if (iChange != 0)
	{
		m_iCultureRateModifier = (m_iCultureRateModifier + iChange);
	}
}
So that function does pretty much what you'd expect. It adds an integer to the rate multiplier. The only question is does it represent a percentage or a straight forward add?

Code:
//	--------------------------------------------------------------------------------
/// Base yield rate from Religion
void CvCity::ChangeBaseYieldRateFromReligion(YieldTypes eIndex, int iChange)
{
	VALIDATE_OBJECT
	CvAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	CvAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");

	if(iChange != 0)
	{
		m_aiBaseYieldRateFromReligion[eIndex] = m_aiBaseYieldRateFromReligion[eIndex] + iChange;

		if(getTeam() == GC.getGame().getActiveTeam())
		{
			if(isCitySelected())
			{
				DLLUI->setDirty(CityScreen_DIRTY_BIT, true);
			}
		}
	}
}
So this one actually takes two parameters, a little more interesting. It's takes a yield type but it looks like it only works if the city has a religion. Which makes sense.

It looks like you might be better off using:
Code:
//	--------------------------------------------------------------------------------
/// Base yield rate from Misc
void CvCity::ChangeBaseYieldRateFromMisc(YieldTypes eIndex, int iChange)
{
	VALIDATE_OBJECT
	CvAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	CvAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex expected to be < NUM_YIELD_TYPES");

	if(iChange != 0)
	{
		m_aiBaseYieldRateFromMisc.setAt(eIndex, m_aiBaseYieldRateFromMisc[eIndex] + iChange);

		if(getTeam() == GC.getGame().getActiveTeam())
		{
			if(isCitySelected())
			{
				DLLUI->setDirty(CityScreen_DIRTY_BIT, true);
			}
		}
	}
}
Which is very similar, but just not tide to a religion. In fact, I don't see why you couldn't use it for both.

Code:
local m_ConnectedCities = {}
local g_bDebug = true
local AMOUNT_TO_CHANGE = 1

function DoTurn(iPlayer)
  pPlayer = Players[iPlayer]
  -- loop through players cities
    -- check if city is connected
    -- if connected and not in m_ConnectedCities then add it to m_ConnectedCities and give bonus
      -- pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, AMOUNT_TO_CHANGE)
      -- pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, AMOUNT_TO_CHANGE)
    -- end
    -- else if not connected and in m_ConnectedCities remove from m_ConnectedCities and take back bonus
      -- pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, -AMOUNT_TO_CHANGE)
      -- pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, -AMOUNT_TO_CHANGE)
    -- end
 -- end
end

function P_DoTurn(iPlayer)
	local bSuccess
	local sResult
	bSuccess, sResult = pcall(DoTurn, iPlayer)
	if (not bSuccess) then
		print(sResult)
	end
end

GameEvents.PlayerDoTurn.Add(g_bDebug and DoTurn or P_DoTurn)
 
Another Question : How do I define the Civilization to be Armenia? I can understand it is related to iPlayer, but what do I have to add/change? Sorry for the Ignorance.

EDIT: After some Tutorials, I understood (possibily wrong) that what I need is a Generic Loop like (for i (Player Civilization Armenia), v in iterator (Cities) do action (Check if is Connected to Capital) end). My question is: how to define the Player?
 
So, the final code would be this... Have I managed to make less than 200 errors in this piece of code? The awnser is no:

Code:
local m_ConnectedCities = {}
local g_bDebug = true
local AMOUNT_TO_CHANGE = 3

function DoTurn(iPlayer)
  pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_ARMENIA) then
        for pCity in pPlayer:Cities() do
            pPlayer.IsCapitalConnectedToCity(pCity)  -- Does this actually does stuff?
	            if pPlayer.IsCapitalConnectedToCity(pCity) then -- Does this means it is true
			        if m_ConnectedCities[pCity] then do -- Would this Work?
			        end 
				else -- if connected and not in m_ConnectedCities then add it to m_ConnectedCities and give bonus
			        table.insert (m_ConnectedCities, pCity)  -- Would this Work?
                    pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, AMOUNT_TO_CHANGE)
                    pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, AMOUNT_TO_CHANGE)
                else -- else if not connected and in m_ConnectedCities remove from m_ConnectedCities and take back bonus
				    if m_ConnectedCities[pCity] then -- Would this Work, Again? 
                    table.remove (m_ConnectedCities, pCity) -- This doesn't work for sure again			
                    pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, -AMOUNT_TO_CHANGE)
                    pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, -AMOUNT_TO_CHANGE)
                end
            end
        end
	end
end

function P_DoTurn(iPlayer)
	local bSuccess
	local sResult
	bSuccess, sResult = pcall(DoTurn, iPlayer)
	if (not bSuccess) then
		print(sResult)
	end
end

GameEvents.PlayerDoTurn.Add(g_bDebug and DoTurn or P_DoTurn)

P.S: Sorry for being a pain in the ass trying to learn Lua. I should buy a book or something and read it during classes.
 
You're getting close. I haven't tested it but probably something like this:

Code:
local m_ConnectedCities = {}
local g_bDebug = true
local AMOUNT_TO_CHANGE = 3

function DoTurn(iPlayer)
    pPlayer = Players[iPlayer]
    if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_ARMENIA) then
      for pCity in pPlayer:Cities() do
        if (pPlayer:IsCapitalConnectedToCity(pCity) and not m_ConnectedCities[pCity]) then
	  m_ConnectedCities[pCity] = true
          pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, AMOUNT_TO_CHANGE)
          pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, AMOUNT_TO_CHANGE)
        elseif (not pPlayer:IsCapitalConnectedToCity(pCity) and m_ConnectedCities[pCity]) then
          m_ConnectedCities[pCity] = nil
          pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_FAITH, -AMOUNT_TO_CHANGE)
          pCity.ChangeBaseYieldRateFromMisc(GameInfoTypes.YIELD_CULTURE, -AMOUNT_TO_CHANGE)
       end
    end
end

function P_DoTurn(iPlayer)
	local bSuccess
	local sResult
	bSuccess, sResult = pcall(DoTurn, iPlayer)
	if (not bSuccess) then
		print(sResult)
	end
end

GameEvents.PlayerDoTurn.Add(g_bDebug and DoTurn or P_DoTurn)
 
Top Bottom