Modding with religion and happiness

It won't download until you subscribe to the mod and start up civ 5 and go to the mods menu. It may also be in ...Documents\my games\Sid Meier's Civilization 5\MODS\mods.
 
It won't download until you subscribe to the mod and start up civ 5 and go to the mods menu. It may also be in ...Documents\my games\Sid Meier's Civilization 5\MODS\mods.
Ahhh. I see.

This event needs no dummy buildings? Nice! :goodjob:
Then the code to make the global variable should be this simple:
Code:
LuaEvents.ReligionFoundedEvent.Add(
function (founderID, iX, iY, eOldReligion, eNewReligion)
	player = Players[founderID]
	if (player:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
		if (Game.GetNumReligionsFounded() == 1) then
			if (foundedReligionFirst == nil) then
				global foundedReligionFirst = true
			end
		else
			global foundedReligionFirst = false
		end
	end
end)
And then the other half - where the bonus actually is given each turn - is the latter half of the coding in post #14 I whipped up, and that should work as long as the two codes are in the same file and I include the ReligionFounded snippet in my mod, right?

And if that's all working correctly, then there's just one last thing to do: learning how to do persistent data.

Crossing my fingers that I can finish Georgia up soon!
(Seriously - if the original UA worked like it was supposed to, Georgia would have been released some 7 months ago. :p)
 
While the ReligionFoundedEvent doesn't use any additional dummy buildings of its own, it will not work correctly unless you are also using LuaEvents.CityAdoptsReligionEvent (the one which has all the dummy buildings for every religion).

As for providing the benefit, if you want to make things much easier on yourself (and want to get around having to use any dummy buildings) use a bonus that can be implemented with a single building. Something like +4 Happiness, +1 Happiness from every Temple, +5 Faith, +25% Great People, etc.
-------------
Very minor code organization note:
Code:
if(X and Y) then
  ...do stuff...
end
Code:
if(X) then
  if(Y) then
    ...do stuff...
  end
end
Both are the same, but in general the first is preferred for being cleaner and easier to read (it requires less nesting).
 
While the ReligionFoundedEvent doesn't use any additional dummy buildings of its own, it will not work correctly unless you are also using LuaEvents.CityAdoptsReligionEvent (the one which has all the dummy buildings for every religion).
Dang. I didn't see that it hooks into LuaEvents.CityAdoptsReligionEvent.
In theory, could I take your LuaEvent.ReligionFoundedEvent and hook into my LuaEvent (based on yours) instead and still have it function?

A while ago you said my LuaEvent needed "a bit more work on your [my] part to replace its [your LuaEvent's] functionality". From what I can tell simply from looking at the code for your event, it seems to be defining eOldReligion and eNewReligion and the initialization check at the end, as well as removing buildings for some reason I'm still trying to grasp (lines 41 - 47). Can you think of anything else it needs?

(Again - purpose behind this is really just less dummy buildings = better. And the purpose behind that is just that you can't make dummy buildings invisible in G&K as easily as in BNW.)
As for providing the benefit, if you want to make things much easier on yourself (and want to get around having to use any dummy buildings) use a bonus that can be implemented with a single building. Something like +4 Happiness, +1 Happiness from every Temple, +5 Faith, +25% Great People, etc.
I typically do that (Inuit UA dummy building as an example) except when the conditions for adding the dummy buildings don't match, which is almost all the time anyway.
 
From what I can tell simply from looking at the code for your event, it seems to be defining eOldReligion and eNewReligion and the initialization check at the end, as well as removing buildings for some reason I'm still trying to grasp (lines 41 - 47).
The code in question:
Code:
	-- If a city has no religious majority, eNewReligion will be -1
	if(eNewReligion < 1) then
		-- Case 1) no majority religion
		-- Remove any buildings marking what the old religion the city is (TODO: this check should be happening every turn to avoid having incorrect state for a few turns)
		for row in GameInfo.Religions() do
			local temp = "BUILDING_" .. row.Type;

			if (city:IsHasBuilding(GameInfoTypes[temp])) then
				city:SetNumRealBuilding(GameInfoTypes[temp], 0); -- Remove the building
			end
		end
		-- Do not continue because the city has no majority religion
		return;
	else
The critical line is the "eNewReligion < 1". This means that while the city has gained a follower of some religion it does not currently have a majority religion. The buildings are removed because they are suppose to be in sync with the majority religion of the city. If this code wasn't here than when this city later actually adopted a religion its oldReligion information could be incorrect.
 
So I need to add that in I'm guessing?

As for this:
Spoiler :
Code:
	-- Only way to get here is if: eNewReligion >= 1 and city does not have newReligionBuilding
	-- Case 2.B) majority religion and city has changed religion
	local eOldReligion = 0;
	-- Find any buildings marking what the old religion the city is
	for row in GameInfo.Religions() do
		local religionMarkingBuilding = "BUILDING_" .. row.Type;
		-- Skip the current local majority religion (eNewReligion) but remove all other religion marking buildings
		if (row.ID ~= eNewReligion and city:IsHasBuilding(GameInfoTypes[religionMarkingBuilding])) then
			city:SetNumRealBuilding(GameInfoTypes[religionMarkingBuilding], 0);

			-- Possible error check.  Just because there is a building marking for the old religion doesn't mean the city has been that religion recently.
			--    For example, if the city was hit by an Inquisitor the building marking old religion wouldn't be removed.
			--    For now, better to have old religion sometimes be the most recent religion than risk adding bugs with extra checks.
			--if(city:GetNumFollowers(row.ID) > 0 or city:GetPopulation() == 1) then
				
			-- Found the old religion of the city
			eOldReligion = row.ID;
			--end
		end
	end

	-- Is this the first time the city has adopted the majorityReligion
	local hasBeenReligionBuilding = "BUILDING_HAS_BEEN_" .. GameInfo.Religions[eNewReligion].Type;
In my case I need to make hasBeenReligionBuilding and religionMarkingBuilding refer to BUILDING_GEORGIA_DUMMY_HAS_BEEN_RELIGION and BUILDING_GEORGIA_DUMMY_IS_RELIGION, respectively. However, I'm guessing I'm still going to need the line "for row in GameInfo.Religions() do" for the row.ID stuff. It results in this:
Spoiler :
Code:
	-- Only way to get here is if: eNewReligion >= 1 and city does not have newReligionBuilding
	-- Case 2.B) majority religion and city has changed religion
	local eOldReligion = 0;
	-- Find any buildings marking what the old religion the city is
	for row in GameInfo.Religions() do
		local religionMarkingBuilding = GameInfoTypes.BUILDING_GEORGIA_DUMMY_IS_RELIGION
		-- Skip the current local majority religion (eNewReligion) but remove all other religion marking buildings
		if (row.ID ~= eNewReligion and city:IsHasBuilding(GameInfoTypes[religionMarkingBuilding])) then
			city:SetNumRealBuilding(GameInfoTypes[religionMarkingBuilding], 0);

			-- Possible error check.  Just because there is a building marking for the old religion doesn't mean the city has been that religion recently.
			--    For example, if the city was hit by an Inquisitor the building marking old religion wouldn't be removed.
			--    For now, better to have old religion sometimes be the most recent religion than risk adding bugs with extra checks.
			--if(city:GetNumFollowers(row.ID) > 0 or city:GetPopulation() == 1) then
				
			-- Found the old religion of the city
			eOldReligion = row.ID;
			--end
		end
	end

	-- Is this the first time the city has adopted the majorityReligion
	local hasBeenReligionBuilding = GameInfoTypes.BUILDING_GEORGIA_DUMMY_HAS_BEEN_RELIGION
The line that worries me is:
Code:
if (row.ID ~= eNewReligion and city:IsHasBuilding(GameInfoTypes[religionMarkingBuilding])) then
Because the dummy buildings no longer use row.Type, is this line still functional?

Unless I have this all wrong - would this code require me to create an additional two dummy buildings in order to satisfy the religion that a Georgian city used to be?
 
I would recommend you get everything working first (using my events are necessary) before worrying about removing my religion snippets.
---------------------
If you are willing to go with an effect that can be done with a single building, the below code is all you need. It won't require any of my religion snippets or their associated dummy buildings for the religions.
Code:
function GeorgiaFoundingBonus(founderID, iX, iY, eOldReligion, eNewReligion)
  player = Players[founderID];
  city = Game.GetHolyCityForReligion(eNewReligion, -1);

  if(player:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA and Game.GetNumReligionsFounded() == 1 and not city:IsHasBuilding(GameInfoTypes["BUILDING_GEORGIA_FOUNDING_BONUS"])) then
    city:SetNumRealBuilding(GameInfoTypes["BUILDING_GEORGIA_FOUNDING_BONUS"], 1);
  end
end
LuaEvents.ReligionFoundedEvent.Add(GeorgiaFoundingBonus);
 
Alright, I used your religion snippets and after trial and error to fix many errors I can confirm that it works. The dummy building is added to the holy city upon founding the religion. (NOTE: I used a different name for the dummy building)

However, the reward for founding a religion first is not something that can be done with a building. (1 :c5faith: per 4 followers each turn). So I tried adding this directly after your code:
Code:
GameEvents.PlayerDoTurn.Add(
function(iPlayer)
	local iPlayer = Players[iPlayer]
	if (iPlayer:HasCreatedReligion()) then
		iReligion = iPlayer:GetReligionCreatedByPlayer()
		if Game.GetHolyCityForReligion(iReligion):IsHasBuilding(GameInfoTypes.BUILDING_GEORGIA_DUMMY_RELIGION_FIRST) then
			iPlayer:ChangeFaith(math.floor(Game.GetNumFollowers(iReligion)/4))
		end
	else
		return;
	end
end)
No effect and no lua.log errors. It may, however, have something to do with the fact that I started on medieval era and set the classical-era medieval UB to give +300 :c5faith: and cost 1 :c5production: so that I can found and see the effects of founding a religion by turn 2; thus no city actually got above a population of 1.

I still haven't tested the "fully converting to cities" thing yet.

So now that we know it (at least partially) works with your snippets we're back to where we were before: removing unnecessary dummy buildings. I'll test out my version of your code later and see how many errors it returns.

Finally, in the code you posted above, the effect of the dummy building is therefore just to be used for persistent data, I realized. So that part can really be replaced with a global variable once I figure out how to do real persistent data, correct?
 
You sure? You seem to be trying to accomplish the effect of faith per pop in a very different way. Just as an example, you tried faith for <Building_YieldChangesPerPop>, whereas I'm actually taking the total number of religious followers for a religion, dividing it by 4 and adding whatever number that results in to the player's faith each turn.

I don't know if that's what Pouakai tried doing though. :p I haven't seen the code in question.

However, if that is indeed still a problem, I guess I'll have to switch around the UA again. Recall that I really didn't want to (see post #10) - but also, recall my exact words:
AgressiveWimp said:
I've finally decided on a UA (I promise I won't change it unless it sounds unbalanced to other people or [is] impossible) that will take a form like this:
New UA (just switching around the effects): If you found a religion first, all your cities which have that religion as their majority religion convert all religious followers in that city to their majority religion/adopt it fully. After founding a religion all of your cities following that religion gain a defence bonus. +2 (or 25%) :c5faith: in cities adjacent to mountains.

Again, as Machiavelli24 pointed out, dummy building effects can easily be changed.

--------------------------------------------------------------------------------------------------

You know, last night I realized: If the CityAdoptsReligion event uses dummy buildings just to mark a city's past and current religions and other than that they have no real effect, couldn't they easily be swapped out for global variables? Of course, once again I'd have to learn to code persistent data - you know what? I'll make a thread about that right now!
 
As bane noted, Culture and Faith are a bit unusual as yields go. Some things that work for Food/Gold/Production/Science won't work for Culture or Faith. However, AgressiveWimp is not giving the faith via a building with per pop yields but by changing the player's faith directly.
------------
If the CityAdoptsReligion event uses dummy buildings just to mark a city's past and current religions and other than that they have no real effect, couldn't they easily be swapped out for global variables?
Yes they could. I decided to implement them as buildings because it let me (and others) have things that boost buildings (like beliefs or social policies) buff specific religious marking buildings. For example, I could do things like the belief "Religious Diversity: +1 Science per religion this city has followed" by having the belief provide +1 Science from every "HAS_BEEN" religion marking building.

It was not a costless design choice, so I can understand the appeal of using persistent data instead.
 
Yes they could. I decided to implement them as buildings because it let me (and others) have things that boost buildings (like beliefs or social policies) buff specific religious marking buildings. For example, I could do things like the belief "Religious Diversity: +1 Science per religion this city has followed" by having the belief provide +1 Science from every "HAS_BEEN" religion marking building.

It was not a costless design choice, so I can understand the appeal of using persistent data instead.
Yes! I actually got one right! :w00t:

Now to figure out how to implement it:

This is your code, with the sections dealing with defining, adding, and subtracting dummy buildings highlighted in blue and bolded, because they're what probably need to be replaced:
Spoiler :
Code:
function CallCityAdoptsReligionEvent(iOwner, eReligion, iX, iY)
	local plot = Map.GetPlot(iX, iY);
	-- Error check, if this isn't a city don't continue
	if(not plot:IsCity()) then
		return;
	end

	local city = plot:GetPlotCity();
	local eNewReligion = city:GetReligiousMajority();
	local newReligionBuilding = nil;

	-- If a city has no religious majority, eNewReligion will be -1
	if(eNewReligion < 1) then
		-- Case 1) no majority religion
		-- Remove any buildings marking what the old religion the city is (TODO: this check should be happening every turn to avoid having incorrect state for a few turns)
		for row in GameInfo.Religions() do
			[B][COLOR="Blue"]local temp = "BUILDING_" .. row.Type;

			if (city:IsHasBuilding(GameInfoTypes[temp])) then
				city:SetNumRealBuilding(GameInfoTypes[temp], 0); -- Remove the building[/COLOR][/B]			end
		end
		-- Do not continue because the city has no majority religion
		return;
	else
		-- Case 2.A) majority religion but city hasn't changed religion
		[COLOR="blue"][B]newReligionBuilding = "BUILDING_" .. GameInfo.Religions[/B][/COLOR][eNewReligion].Type;
		[B][COLOR="blue"]if(city:IsHasBuilding(GameInfoTypes[newReligionBuilding])) then[/COLOR][/B]
			-- The city has not changed religion, don't continue
			return;
		end
	end

	-- Only way to get here is if: eNewReligion >= 1 and city does not have newReligionBuilding
	-- Case 2.B) majority religion and city has changed religion
	local eOldReligion = 0;
	-- Find any buildings marking what the old religion the city is
	for row in GameInfo.Religions() do
		[B][COLOR="blue"]local religionMarkingBuilding = "BUILDING_" .. row.Type;[/COLOR][/B]
		-- Skip the current local majority religion (eNewReligion) but remove all other religion marking buildings
		[B][COLOR="blue"]if (row.ID ~= eNewReligion and city:IsHasBuilding(GameInfoTypes[religionMarkingBuilding])) then
			city:SetNumRealBuilding(GameInfoTypes[religionMarkingBuilding], 0);[/COLOR][/B]
			-- Possible error check.  Just because there is a building marking for the old religion doesn't mean the city has been that religion recently.
			--    For example, if the city was hit by an Inquisitor the building marking old religion wouldn't be removed.
			--    For now, better to have old religion sometimes be the most recent religion than risk adding bugs with extra checks.
			--if(city:GetNumFollowers(row.ID) > 0 or city:GetPopulation() == 1) then
				
			-- Found the old religion of the city
			eOldReligion = row.ID;
			--end
		end
	end

	-- Is this the first time the city has adopted the majorityReligion
	[B][COLOR="blue"]local hasBeenReligionBuilding = "BUILDING_HAS_BEEN_" .. [/COLOR][/B]GameInfo.Religions[eNewReligion].Type;
	local bFirstConversion = false;

	[B][COLOR="blue"]if(not city:IsHasBuilding(GameInfoTypes[hasBeenReligionBuilding])) then[/COLOR][/B]		bFirstConversion = true;
	end

	-- Update religion building state
	[B][COLOR="blue"]city:SetNumRealBuilding(GameInfoTypes[newReligionBuilding], 1);
	city:SetNumRealBuilding(GameInfoTypes[hasBeenReligionBuilding], 1);[/COLOR][/B]

	-- Call the lua event
	--print("Calling CityAdoptsReligionEvent(iOwner: " .. tostring(iOwner) .. " iX: " .. tostring(iX) .. " iY: " .. tostring(iY) .. " eOldReligion: " .. tostring(eOldReligion) .. " eNewReligion: " .. tostring(eNewReligion) .. " bFirstConversion: " .. tostring(bFirstConversion) .. ")");
	LuaEvents.CityAdoptsReligionEvent(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion);
end

--------------
-- Initialization check.  Ensures this code isn't loaded twice
--------------
local retVal = {};
LuaEvents.CityAdoptsReligionEvent_IsInitialized(retVal);

-- If retVal isn't changed, no other mod has initialized this code.
if (retVal.isInitialized == nil) then
	LuaEvents.CityAdoptsReligionEvent_IsInitialized.Add(function (retVal) retVal.isInitialized = true; end);
	-- Initialize the code
	GameEvents.CityConvertsReligion.Add(CallCityAdoptsReligionEvent);
end
Let's begin with: I don't suppose it would be syntaxically (it's a word as far as I'm concerned) correct to do this:
Code:
newReligion = GameInfo.Religions[eNewReligion].Type;
rather than this?
Code:
newReligionBuilding = "BUILDING_" .. GameInfo.Religions[eNewReligion].Type;

And then instead of adding or removing and adding dummy buildings, we could simply set a variable to either true or false - or at least, it sounds simple in theory. But you know what they (I?) say: In theory there ought to be no difference between practice and theory. In practice, there is. :p

I'll take a closer look at it and try to replace buildings with variables. On a closer look it seems harder than it sounds.
 
Alright: This is my first attempt at replacing all dummy buildings with variables. It's probably horribly coded but it's a start. I basically your coding with every dummy build replaced with my random guess as to whether to assign it the value of true, false or nil.
Spoiler :
Code:
function CallCityAdoptsReligionEvent(iOwner, eReligion, iX, iY)
	local plot = Map.GetPlot(iX, iY);
	-- Error check, if this isn't a city don't continue
	if(not plot:IsCity()) then
		return;
	end

	local city = plot:GetPlotCity();
	local eNewReligion = city:GetReligiousMajority();
	local newReligionBuilding = nil;

	-- If a city has no religious majority, eNewReligion will be -1
	if(eNewReligion < 1) then
		-- Case 1) no majority religion
		-- Remove any buildings marking what the old religion the city is (TODO: this check should be happening every turn to avoid having incorrect state for a few turns)
		for row in GameInfo.Religions() do
			local temp = nil;

			if (temp) then
				temp = false; -- Remove the building
			end
		end
		-- Do not continue because the city has no majority religion
		return;
	else
		-- Case 2.A) majority religion but city hasn't changed religion
		newReligion = true;
		if(newReligion) then
			-- The city has not changed religion, don't continue
			return;
		end
	end

	-- Only way to get here is if: eNewReligion >= 1 and city does not have newReligionBuilding
	-- Case 2.B) majority religion and city has changed religion
	local eOldReligion = 0;
	-- Find any buildings marking what the old religion the city is
	for row in GameInfo.Religions() do
		local is_religion = nil;
		-- Skip the current local majority religion (eNewReligion) but remove all other religion marking buildings
		if (row.ID ~= eNewReligion and is_newReligion) then
			is_newReligion = false;

			-- Possible error check.  Just because there is a building marking for the old religion doesn't mean the city has been that religion recently.
			--    For example, if the city was hit by an Inquisitor the building marking old religion wouldn't be removed.
			--    For now, better to have old religion sometimes be the most recent religion than risk adding bugs with extra checks.
			--if(city:GetNumFollowers(row.ID) > 0 or city:GetPopulation() == 1) then
				
			-- Found the old religion of the city
			eOldReligion = row.ID;
			--end
		end
	end

	-- Is this the first time the city has adopted the majorityReligion
	local hasBeen_newReligion = true;
	local bFirstConversion = false;

	if(not hasBeen_newReligion) then
		bFirstConversion = true;
	end

	-- Update religion building state
	is_newReligion = true;
	hasBeen_newReligion = true;

	-- Call the lua event
	--print("Calling CityAdoptsReligionEvent(iOwner: " .. tostring(iOwner) .. " iX: " .. tostring(iX) .. " iY: " .. tostring(iY) .. " eOldReligion: " .. tostring(eOldReligion) .. " eNewReligion: " .. tostring(eNewReligion) .. " bFirstConversion: " .. tostring(bFirstConversion) .. ")");
	LuaEvents.CityAdoptsReligionEvent(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion);
end

--------------
-- Initialization check.  Ensures this code isn't loaded twice
--------------
local retVal = {};
LuaEvents.CityAdoptsReligionEvent_IsInitialized(retVal);

-- If retVal isn't changed, no other mod has initialized this code.
if (retVal.isInitialized == nil) then
	LuaEvents.CityAdoptsReligionEvent_IsInitialized.Add(function (retVal) retVal.isInitialized = true; end);
	-- Initialize the code
	GameEvents.CityConvertsReligion.Add(CallCityAdoptsReligionEvent);
end
 
Any guesses as to the code's functionality? I haven't tested it yet but I'm guessing the lua.log will be full of errors and nothing will work correctly, but there's always a chance.

Just guessing what to set each variable to sounds like a truly awful way to replace buildings with variables. Should I set them all to nil? Or true? Maybe false? Any ideas?
 
Well, I tested out my coding, and I can confirm that it does not work. What a shock there. :p
The building didn't show up and the logs yield no errors. Does anybody have any idea what these variables should be set to? Anyone? I certainly don't...
 
Back
Top Bottom