Modding with religion and happiness

AW Arcaeca

Deus Vult
Joined
Mar 10, 2013
Messages
2,984
Location
Operation Padlock ground zero
In this thread I was trying to figure out how to detect when a player founds a religion, and it seems to be mostly figured out. Maybe.

Now I'm trying to figure out how to add happiness if the player is the first to found a religion. Specifically it should be 1 happiness per 2 cities that follow the religion, but the code shows 1 happiness per 4 citizens because I accidentally asked for the wrong function in the last thread.

Incidentally, it's for a UA, so it should only be working with one civ. It's also based off Machiavelli24's Race for Religion.

Detection method:
Spoiler :
Code:
GameEvents.CityConvertsReligion.Add(
function(iPlayer, iReligion, iX, iY)

	-- First set up boolean variable firstConversion to be used later	

	local plot = Map.GetPlot(iX, iY);
	if not (plot:IsCity()) then
		return;
	end
	
	local city = plot:GetPlotCity();
	local isReligion = GameInfoTypes.BUILDING_GEORGIA_DUMMY_IS_RELIGION
	local hasBeenReligion = GameInfoTypes.BUILDING_GEORGIA_DUMMY_HAS_BEEN_RELIGION
	
	
	if (city:GetOwner() == iPlayer)
	and (iPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
		if (iPlayer:HasCreatedReligion()) then
			local iReligion = iPlayer:GetReligionCreatedByPlayer()
			
			if (city:GetReligiousMajority() == iReligion) then
				if not (city:IsHasBuilding(isReligion)) then
					city:SetNumRealBuilding(isReligion, 1)
				else
					if not (city:IsHasBuilding(hasBeenReligion)) then
						firstConversion = true;
						city:SetNumRealBuilding(hasBeenReligion, 1)
					else
						firstConversion = false;
					end
				end
			else
				city:SetNumRealBuilding(isReligion, 0)
			end
		end
	end
	print("Georgian City Converts Religon Event: (iPlayer: " ..tostring(iPlayer).. " iX: " ..tostring(iX).. " iY: " ..tostring(iY).. "iReligion: " ..tostring(iReligion).. "firstConversion: " ..tostring(firstConversion).. ")");
	LuaEvents.GeorgianCityConvertsReligionFirstTime(iPlayer, iX, iY, iReligion, firstConversion);		
end)
The attempt at adding happiness:
Spoiler :
Code:
LuaEvents.GeorgianCityConvertsReligionFirstTime.Add(
function(iPlayer, iX, iY, iReligion, firstConversion)
	for i = 0, GameDefines.MAX_MAJOR_CIVS -1, 1 do
		local pPlayer = Players[i]
		local mPlayer = Players[m]
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
			if (pPlayer:IsAlive()) then
				local city = Map.GetPlot(iX, iY):GetPlotCity()
					if (firstConversion) and (city:IsHolyCityForReligion(iReligion)) then
						-- Happiness if first to found a religion
						if not (mPlayer:HasCreatedReligion()) then
							local followers = Game.GetNumFollowers(iReligion)
							local happiness = pPlayer:GetHappiness()	
							local followers_fixed = (math.floor(followers / 4)
							happiness_fixed = (math.floor(happiness + followers_fixed)
							pPlayer:SetHappiness(happiness_fixed)
						else
							return
						end
					end
				end
			end
		end
	end
end)
But I think someone said long ago that modding with happiness is hard because of all the times the game recalculates it. I also couldn't find a "change" function for happiness rather than a "set" function, which is why there's two more variables than there probably needs to be. Unless, is there a function called "Player.ChangeHappiness()"?
Furthermore, doesn't the code I have now effectively double the player's happiness every turn? :crazyeye:

I'm also vaguely unsure if the "if (pPlayer:GetCivilizationType())" line is unnecessary because it's redundant. My guess is probably.

Lastly - I'm still searching for an idea for the UA that would be a bonus for founding a religion in general. For now the idea is cities following that religion are 25% harder to convert, although whoward69 informs me that it's not possible without DLL modding. Unless anyone has any idea about whether it's possible with lua?
 
Providing happiness isn't too hard. You'll most likely want to implement it as a "no limit" building that provides +1 happiness and then add as many copies as you need to the player's capital. I have some code that can handles moving the buildings automatically when a capital moved. It wouldn't be hard to reuse.

To provide happiness per quantity of followers you'll need to update the quantity of the bonus any time the follower count changes. There is an event, GameEvents.CityConvertsReligion that fires when follower count changes. You'll need to hook into that.
 
Providing happiness isn't too hard. You'll most likely want to implement it as a "no limit" building that provides +1 happiness and then add as many copies as you need to the player's capital. I have some code that can handles moving the buildings automatically when a capital moved. It wouldn't be hard to reuse.
Where would I find that code? Also in Race for Religion, or one of your other mods?
Ideally I would like to do it with as few dummy buildings as possible, but whatever works will do.
To provide happiness per quantity of followers you'll need to update the quantity of the bonus any time the follower count changes. There is an event, GameEvents.CityConvertsReligion that fires when follower count changes. You'll need to hook into that.
:confused: I thought the code was already hooked into that event? (Well, technically, hooked into an event that's hooked into CityConvertsReligion)
 
Where would I find that code? Also in Race for Religion, or one of your other mods?
Ideally I would like to do it with as few dummy buildings as possible, but whatever works will do.
You can find it in "Reform and Rule (BNW)" look for Liberalism.lua (in Social Policies -> Freedom). The Liberalism code provides +1 happiness for every two social policies. It is done via a no limit building that provides 1 global happiness. Let me know if this is too vague.

I thought the code was already hooked into that event? (Well, technically, hooked into an event that's hooked into CityConvertsReligion)
The CityConvertsReligion event that fraxis made fires when a city changes religion or changes follower count. The lua event you got from me listens to that but only fires when a city changes religion.

If you wanted to provide happiness per following city than you would want to use the lua event you got from me. If you want to provide happiness per follower you would want to use the fraxis event.
 
After taking a look at it, quick question: Why the heck did you not make your buildings invisible? :crazyeye:
It sounds sort of pretty easy enough; I'd just like to not see 60+ of the same building in my cities if the religion grows enough. :p That's really all I have against using no-limit buildings.

I'd like to change my intended UA a little: +1 happiness per four citizens if you're the first to found a religion, and a free pressure-increasing building into every city that fully converts to your religion even if you're not the first to found one. (That would increase religious pressure in surrounding cities, correct?)

The trouble is with the first clause... I need the LuaEvent that I created (if there are no errors in it) to detect if you're the first to found one, but I also need to hook the function into GameEvents.CityConvertsReligion... :confused: How does one do that?

Meanwhile, this is my stab at the second clause:
Code:
GameEvents.CityConvertsReligion.Add(
function(iPlayer, iReligion, iX, iY)
	
	local plot = Map.GetPlot(iX, iY);
	if not (plot:IsCity()) then
		return;
	end
	
	local city = plot:GetPlotCity();
	if (city:GetOwner() == iPlayer)
	and (iPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
		if (iPlayer:HasCreatedReligion()) then
			local iReligion = iPlayer:GetReligionCreatedByPlayer()
			if (city:IsHasReligion(iReligion)) then
				if (city:GetNumFollowers(iReligion) == city:GetPopulation()) then
					city:SetNumRealBuilding(GameInfoTypes.BUILDING_DUMMY_GEORGIA_PRESSURE, 1)
					-- else clause missing because building isn't intended to be removed
					end
				end
			end
		end
	end
 
Still have no idea how to do the first clause but this is my guess: You hook the function into GameEvents.CityConvertsReligion and then have a line saying:
Code:
local function LuaEvents.GeorgianCityConvertsReligionFirstTime;
That's probably not right, but it's the best I can come up with. Would it still allow me to use the firstConversion variable from the LuaEvent?

To figure out if you're the first to found a religion I'm assuming it's as easy as detecting when your holy city converts to its own religion, and when it does see if no one else has created a religion. Like so:
Code:
if (firstConversion) and (city:IsHolyCityForReligion(iReligion)) then
	if not (mPlayer:HasCreatedReligion()) then
Where mPlayer represents your opponent. But truthfully I have no idea how to define iPlayer's opponents. I opened a thread about it a while ago to find out and learned that it's "for iPlayer, pPlayer in pairs(Players) do", although since CSs can't found religions we might as well use the whole "for i = 0, GameDefines.MAX_MAJOR_CIVS -1, 1 do" command. Although using that I'm not sure how to create mPlayer. Should I add in "m > 0" there?

Finally, since Georgia's secondary bias is defense it might work better to give them a defensive bonus instead of a happiness bonus. Any ideas? (Sorry that I change my mind about UA ideas a lot...)
 
You can use "Game.GetNumReligionsFounded()" as an easy way to see if a player is first to a religion.

As for firstConversion, you'll only have access to that if the event you hook into provides that information. The lua events you got from me will have that information but the fraxis event will not.

If you're using the lua event that fires when a city converts religion, you can also use the second lua event that fires when a religion is founded.

If you want to give the civ a building when their cities follow their own religion (this could be extra defense, happiness or other building-related things) than you'll want to hook into the lua event you got from me that fires when a city adopts a religion. If the city belongs to the civ and the new religion is the civ's religion, give the city the building. (The building should also have neverCapture=true).
 
You can use "Game.GetNumReligionsFounded()" as an easy way to see if a player is first to a religion.
So something along the lines of "if (iPlayer:HasCreatedReligion()) and (Game.GetNumReligionsFounded() == 1) then"?
As for firstConversion, you'll only have access to that if the event you hook into provides that information. The lua events you got from me will have that information but the fraxis event will not.
Since that whole event is just used to detect founding a religion and the function you gave above is an easier way to see if you're the first to found a religion, why not use that?
If you're using the lua event that fires when a city converts religion, you can also use the second lua event that fires when a religion is founded.
That's what I was asking about earlier: How? You can hook into one event - in this case you said it should be GameEvents.CityConvertsReligion. Where in the coding does the other one - my LuaEvent base on yours - go?
If you want to give the civ a building when their cities follow their own religion (this could be extra defense, happiness or other building-related things) than you'll want to hook into the lua event you got from me that fires when a city adopts a religion. If the city belongs to the civ and the new religion is the civ's religion, give the city the building. (The building should also have neverCapture=true).
Specifically it should be when the city fully converts to the religion. As long as there are no errors in my function (again, yours works great but it has 11x+ more dummy buildings than I need), it would work fine too, wouldn't it? And to check if a city converts fully, I think it should be as easy as the line "if (city:GetNumFollowers(iReligion) == city:GetPopulation()) then".
 
The event you want to hook into depends on what you are trying to do. When you said you wanted to do something based on the number of followers, I said you would need to use the fraxis event (that fires when follower counts change in a city). If you want to give georgian cities a defense bonus when they are the georgian religion than you'll need to use the lua event I wrote that fires when a city converts religion. If you want to do something when Georgia founds a religion you can use the religionFoundedEvent I also have.

If you don't want to use the lua stuff I already have than it will require a bit more work on your part to replicate its functionality. If you want to give a building to every geogian city when it adopts the geogian religion without using any of my lua than you'll be hooking into "GameEvents.CityConvertsReligion" as you have in your code above. You'll need to test that the city is owned by georgia and that its religion is the one founded by georgia. If so, give the city the building.
 
Alright... now the hard part.
I've finally decided on a UA (I promise I won't change it unless it sounds unbalanced to other people or impossible) that will take a form like this:

Clause 1) If Georgia is the first civ to found a religion, it receives additional faith each turn equal to one half of the total number of that religion's followers.
Clause 2) After Georgia founds a religion, every city following that religion adopts it fully.

The probable facts:
  • Clause 1 will need to be hooked into GameEvents.CityConvertsReligion to detect when the total number of followers changes...
  • ...unless it also needs to be hooked into the LuaEvent to detect when Georgia founds a religion,
  • ...and after that happens we'll need to see if it's the only religion present. Which we can do with something like the line "if (iPlayer:HasCreatedReligion()) and (Game.GetNumReligionsFounded() == 1) then".
  • Possible other problem: Is it possible this function will have to hook into 3 events? CityConvertsReligion, the LuaEvent, and GameEvents.PlayerDoTurn to give faith each turn? Is it then possible to put an event within a function within an event within a function within an event?
    Like this pseudo-code:
    Code:
    GameEvents.CityConvertsReligion.Add(
    -- Get total followers
    -- move on to when religion is founded
    		LuaEvents.whatevertheheckIcalledit.Add(
    		-- see if iPlayer has founded a religion and it's the first one
    		-- if so, using # of followers:
    				GameEvents.PlayerDoTurn.Add(
    					-- Add faith per turn
    
    		-- ridiculous number of ends
    end)
  • Clause 2 is probably pretty easy to do; I assume we can just use city:AdoptReligionFully(iReligion), with the condition that city:GetReligiousMajority() returns iReligion. Like this:
    Spoiler :
    Code:
    GameEvents.CityConvertsReligion.Add(
    function(iPlayer, iReligion, iX, iY)
    
    	local plot = Map.GetPlot(iX, iY)
    	if not (plot:IsCity()) then
    		return;
    	end
    	
    	local city = plot:GetPlotCity();
    	if (city:GetOwner() == iPlayer) then
    		if (iPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
    			if (iPlayer:HasCreatedReligion()) then
    				local iReligion = iPlayer:GetReligionCreatedByPlayer()
    				if (city:GetReligiousMajority() == iReligion) then
    					city:AdoptReligionFully(iReligion)
    				end
    			else
    				return;
    			end
    		else
    			return;
    		end
    	end

What do you think? Can it be done easily with reasonable, non-absurd difficulty? Is it OP or UP or anything?
I was racking my brain last night trying to figure this out and finally settled on, as long as Georgia is a faith-based civ, it might as well have a faith-based UA! :crazyeye:
 
It not a problem to change what you want the UA to be. Once you've got the algorithm that gives Georgian cities an arbitrary building when they adopt the Georgian religion, changing that building from a defense bonus to +1 happiness is trivial.

For simplicity sake, I'm going to assume you'll be using my religion snippets. Once its working with the snippet we can go through the steps for removing them.

Clause 1) If Georgia is the first civ to found a religion, it receives additional faith each turn equal to one half of the total number of that religion's followers.
Hook into the ReligionFoundedEvent. Test to see if the founding player is Georgia and if the number of religions founded so far is 1. If both are true you know Georgia is the first to found a religion.

Implementing the bonus
Mark in some way that Georgia achieved their religion first. This could be a stored persistent value, a building added to the Georgian capital, whatever you're comfortable with.

Add a function to playerDoTurn. This function should test to see if the player whose turn it is is Georgia and if Georgia achieved religion first (by looking for however you marked it). If so, give the player the faith bonus.

Clause 2) After Georgia founds a religion, every city following that religion adopts it fully.
I'm not sure I understand what you intend here. When Georgia founds (say) Islam, the only city that will have any Islam followers will be <name of Georgian city where the great prophet was>. Did you mean you want to convert all cities Georgia owns to Islam when they found it?
 
Hook into the ReligionFoundedEvent. Test to see if the founding player is Georgia and if the number of religions founded so far is 1. If both are true you know Georgia is the first to found a religion.
So the LuaEvent that you (or I) made?
Implementing the bonus
Mark in some way that Georgia achieved their religion first. This could be a stored persistent value, a building added to the Georgian capital, whatever you're comfortable with.
A variable is what I assume you mean by "a stored persistent value"; I'm assuming I need to specifically not make it local. Should I not assign it a locality at all or should I make it global then?
Add a function to playerDoTurn. This function should test to see if the player whose turn it is is Georgia and if Georgia achieved religion first (by looking for however you marked it). If so, give the player the faith bonus.
Will CityConvertsReligion not be needed at all since the faith will be added at the beginning of the player's turn anyway, not when the number of followers changes?
I'm not sure I understand what you intend here. When Georgia founds (say) Islam, the only city that will have any Islam followers will be <name of Georgian city where the great prophet was>. Did you mean you want to convert all cities Georgia owns to Islam when they found it?
I meant something more along the lines of "when the majority of a Georgian city's religious followers is following Islam, make so that all of that city's followers/population follows Islam". This is based on what I assume City.AdoptReligionFully does, though I'm not sure whether it converts all of a city's followers or its entire population. Either way is fine with me.

Or it could deprecated for all I know.
 
ReligionFoundedEvent is a lua event you can get from my religion snippets.

As for persisting data, the wiki has some information on the process. If you're not comfortable with the process you could use a building to mark.

Will CityConvertsReligion not be needed at all since the faith will be added at the beginning of the player's turn anyway, not when the number of followers changes?
There are multiple ways you could implement the effect "give a player faith equal to 1/4th their follower count". One approach would be to hook into playerDoTurn, count how many followers their religion has and change the player's faith.

An alternative approach would be to give copies of a noLimit building that provided +1 faith. Updating the quantity as the follower count changes. This approach would require hooking into CityConvertsReligion (the fraxis event since it fires when follower counts change).

The second approach is probably a bit trickier but works more gracefully with the faith-per-turn interface.

As for using City.AdoptReligionFully, I've not used it myself but I've read other people saying it didn't work. I know convertPercentFollowers works so you could use that.
 
Assuming we're using your LuaEvent, this is my attempt at Clause 1:
Spoiler :
Code:
-- Hook into the LuaEvent to see if the global variable "foundedReligionFirst" is true or false

LuaEvents.CityAdoptsReligionEvent.Add(
function(iPlayer, iX, iY, iReligion)
	
	local plot = Map.GetPlot(iX, iY)
	if not (plot:IsCity()) then
		return;
	else
		local city = plot:GetCity()
		if (city:GetOwner() == iPlayer) then
			if (iPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
				if (iPlayer:HasCreatedReligion()) then
					local iReligion = iPlayer:GetReligionCreatedByPlayer()
					if (city:IsHolyCityForReligion(iReligion) and bFirstConversion) then
						foundedReligion = true
						if (foundedReligion) and (Game.GetNumReligionsFounded() == 1) then
							global foundedReligionFirst = true
						else
							global foundedReligionFirst = false
						end
					end
				end
			end
		end
	end
end)

-- Now with the variable let's see if Georgia deserves to get faith each turn

GameEvents.PlayerDoTurn.Add(
function(iPlayer, iReligion)
	
	local iPlayer = Players[iPlayer]
	if (iPlayer:HasCreatedReligion()) then
		local iReligion = iPlayer:GetReligionCreatedByPlayer()
		
		if (iPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
			if (foundedReligionFirst) then
				iPlayer:ChangeFaith((math.floor(Game.GetNumFollowers(iReligion)/4))
			else
				return;
			end
		end
	end
end)
That last line could probably be coded more easily, but it would require defining a bunch of new variables that I'll only use in that line anyway.

And hopefully that global variable works like it should. However, will it retain its data even after saving and reloading the way it's coded now, or should I add a few lines with ModData and SetValue and all that?

Lastly, for ConvertPercentFollowers - I'm assuming this function is used with cities - we'd probably set it to 100, correct?
 
The (untested) code below will let you provide a bonus if Georgia is the first to found a religion. You'll need to change the brown sections.
Code:
function GeorgiaFoundingBonus(founderID, iX, iY, eOldReligion, eNewReligion)
  player = Players[founderID];

  if(player:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA and Game.GetNumReligionsFounded() == 1 and [COLOR="Sienna"]have not already given bonus[/COLOR]) then
    [COLOR="Sienna"]give bonus...[/COLOR]
  end
end
LuaEvents.ReligionFoundedEvent.Add(GeorgiaFoundingBonus);

And hopefully that global variable works like it should. However, will it retain its data even after saving and reloading the way it's coded now, or should I add a few lines with ModData and SetValue and all that?
It will not be enough to just make a variable global. You'll need to do the extra steps to make the value be stored correctly between saves and loads.

Lastly, for ConvertPercentFollowers - I'm assuming this function is used with cities - we'd probably set it to 100, correct?
ConvertPercentFollowers(ReligionType arg0, ReligionType arg1, int arg2)

For example:
ConvertPercentFollowers(GameInfoTypes["RELIGION_PROTESTANTISM"], GameInfoTypes["RELIGION_CHRISTIANITY"], 40)
Converts 40% of the city's christian followers to protestantism followers.
 
I'd like to say that the lua/ui reference's entry on persisting data makes total sense to me, but that would be a lie. All I've picked up so far is that something along these lines should maybe probably be added in the code somewhere:
Code:
Modding.OpenUserData("AW_GEORGIA", "1")
ModData.SetValue("foundedReligionFirst", true)
(I love how clear and detailed the reference is about everything. :rolleyes:)
I'm 99.99999999999969% sure that those two lines are completely wrong. Nevertheless I'd really like to learn how to do this because less dummy buildings = better.

I actually wasn't able to find the ReligionFoundedEvent, assuming it's included in the G&K version of Race for Religion. But seeing as how I couldn't find it, it probably isn't. Is it in the BNW version, or...?
 
I actually wasn't able to find the ReligionFoundedEvent, assuming it's included in the G&K version of Race for Religion. But seeing as how I couldn't find it, it probably isn't. Is it in the BNW version, or...?
The G&K stuff is not the latest and greatest version. You can grab the latest and greatest version here.
 
*cringes* The workshop. :cringe:
I know this sounds like a very n00bish question to ask (although you should probably expect that from me after having dealt with me all this time in this thread), but where the heck do the files from subscribed mods go to on your computer? I'd like to see the coding (just to see out it works and all that) but I have no idea where to find them because, well, that's Steam for you.
 
...Documents\my games\Sid Meier's Civilization 5\MODS
 
...Documents\my games\Sid Meier's Civilization 5\MODS
For steam workshop items?
I'm not seeing anything along the lines of "Religion snippets" there...
 
Top Bottom