Is there a Event/GameEvent for this?

AW Arcaeca

Deus Vult
Joined
Mar 10, 2013
Messages
2,984
Location
Operation Padlock ground zero
Quite simply, I just need to know if there is a lua event or gamevent that triggers when a religion is founded. Wasn't able to find one on the UI reference. :sad:
I'm hoping if there is, I can use in a simple lua code to give a player a dummy building upon founding a religion.
 
I have some lua code that fires a lua event when a city adopts a religion. It would be pretty easy to extended it to identify when a Religion is founded by seeing if the holy city for religion 'Blah' is adopting 'Blah' for the first time. And if those conditions are met to fire off a "religion founded" lua event that you could hook into.

I intend to write that extension soon but I don't have it right now.
 
I have some lua code that fires a lua event when a city adopts a religion. It would be pretty easy to extended it to identify when a Religion is founded by seeing if the holy city for religion 'Blah' is adopting 'Blah' for the first time. And if those conditions are met to fire off a "religion founded" lua event that you could hook into.

I intend to write that extension soon but I don't have it right now.
Sounds good, but I'm not sure how to do the whole "first time" part in "city is adopting blah for the first time".
I assume I'll have to use GameEvents.CityConvertsReligion.Add for this...
I made something of a template for how I can make the code work, obviously it won't be fully functional as it is, but does it look okay so far?
Code:
GameEvents.CityConvertsReligion.Add(
funtion(playerID)
	local pPlayer = Players[playerID]
	if (pPlayer:IsAlive()) then
		if (pPlayer:HasCreatedReligion()) then
			local pReligion = pPlayer:GetReligionCreatedByPlayer()
			local pHolyCity = Game.GetHolyCityForReligion(pReligion, pPlayer)
			pHolyCity:SetNumRealBuilding(GameInfoTypes.BUILDING_DUMMY, 1)
		end
	end
end)
 
You can find the code you'll need in my Race for Religion mod. In the "Race for Religion (BNW)\Shared\CityAdoptsReligionEvent" directory there will be two files (a lua file and a sql file). You'll need both of them.

The Lua event those files will create for you is:

LuaEvents.CityAdoptsReligionEvent(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
  • iOwner: The ID of the player who owns the city
  • iX, iY: The location of the city, use Map.GetPlot(iX, iY) to get the plot object
  • eOldReligion: The ID of the religion the city use to be. If the city was not previously a founded religion (due to the city having a Pantheon or no Pantheon) eOldReligion will be 0.
  • eNewReligion: The ID of the religion the city is now. Will always be 1 or greater because the 0 ID is for "Pantheon religions".
  • bFirstConversion: A boolean that will be true if this is the first time the city has become eNewReligion, false otherwise.
 
Great, thanks!
So I need City.CallCityAdoptsReligionEvent then?
(I'm using the G&K version of your mod BTW, as this is a mod for G&K.)

Looking through the code, I'm not sure quite how to use this new function or what call hook to use. It appears you're using dummy buildings of some kind...? I'm a little confused, but here's what I managed to code:
Code:
GameEvents.CityConvertsReligion.Add(
function(playerID)
	local pPlayer = Players[playerID]
	if (pPlayer:IsAlive()) then
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_NEWCIV) then
			if (pPlayer:HasCreatedReligion()) then
				local pReligion = pPlayer:GetReligionCreatedByPlayer()
				local pHolyCity = Game.GetHolyCityForReligion(pReligion)
				local pHCX = pHolyCity:GetX()
				local pCHY = pHolyCity:GetY()
				if LuaEvents.CityAdoptsReligionEvent(pPlayer, pHCX, pCHY, -1, pReligion, true)
					pHolyCity:SetNumRealBuilding(GameInfoTypes.BUILDING_DUMMY)
				end
			end
		end
	end
end)
I just kind of assumed that I still need to use the GameEvents.CityConvertsReligion.Add hook, I might (and probably am) be wrong about that.
I used -1 as eOldReligion (again, probably not correct) because wouldn't that mean that city didn't have a religion to begin with?
 
The CityAdoptsReligion event didn't change between G&K and BNW so it shouldn't matter if you get the code from the BNW or G&K version of Race for Religion. However, I would recommend using the BNW version since that is most likely to be the latest and greatest version.

You should use LuaEvents.CityAdoptsReligionEvent and not worry about the built in GameEvents.CityConvertsReligion event. GameEvents.CityConvertsReligion does not do what its name implies, it would be more accurate to call it "CityFollowerCountHasChanged". Conceptually the lua event I wrote sits on top of the existing GameEvents.CityConvertsReligion and does some logic to filter when a city has actually changed religion. If all your code needs to know is when a city has adopted a religion than you hook into LuaEvents.CityAdoptsReligionEvent and let it do the heavy lifting.

The code you'll want to write will be something like:
Code:
function ReligionFounded(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
  local city = Map.GetPlot(iX, iY):GetPlotCity();

  if(bFirstConversion and city:IsHolyCityForReligion(eNewReligion)) then
    -- do stuff...
  end
end
LuaEvents.CityAdoptsReligionEvent.Add(ReligionFounded)
 
:confused: So then because I'm using that hook I don't need to define the variables myself?
Yes, all I need to do is make so that when the player of this new civilization founds a religion, a dummy building is placed in the holy city.

So is this anywhere near close? I feel like every time I'm getting further away from the correct coding...
Code:
LuaEvents.CityAdoptsReligion.Add(
function(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
	local pPlayer = Players[playerID]
	if (pPlayer:IsAlive()) then
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_NEWCIV) then
			local city = Map.GetPlot(iX, iY):GetPlotCity()
			if (bFirstConverion) and (city:IsHolyCityForReligion(eNewReligion)) then
				city:SetNumRealBuilding(GameInfoTypes.BUILDING_DUMMY, 1)
			end
		end
	end
end)
 
The code you have there is pretty much what you want. The only change you need to make is the line:

local pPlayer = Players[playerID]

should be:

local pPlayer = Players[iOwner]

While it isn't an error, you don't need to test if the player is alive, since the player iOwner points to has at least one city.
 
Okay... something isn't right here....
The game works fine, but the dummy building doesn't show up. It shows up in the civilopedia but not with the icon I set it to. (I mighted have forgot to set UpdateDatabase entries for the icon atlases, but its not too important right now) What the civilopedia does show are all these "Judaism" and "Sikhism", etc. buildings - I assume that's the result of the lua I "borrowed" from your mod? (Don't worry, I'll give you credit). Also, neither the database.log not the lua.log shows any errors.

So, questions:

1) My lua (after changing CIVILOPEDIA_NEWCIV and BUILDING_DUMMY to what they should be) is set to InGameUIAddin, while your lua is set to VFS=false. I assumed it wen under the "Does this file contain methods used by other Lua files and is included into those other Lua files?" category from this thread; was that the correct way to load it?

2) Any idea why these aren't showing up in the logs?

3) Is there any way of making your dummy buildings named after religions to not show up in the civilopedia, and thus, truly invisible?

4) Any visible problems with the code?

5) Would the attached mod help? ;) (It's about 15MB so I have to attach a link to dropbox instead:
http://dl.dropboxusercontent.com/s/236wfvibai6kk8d/AW%27s%20Kingdom%20of%20Georgia%20Mod%20%28v%201%29.zip?dl=1&token_hash=AAHmibKuaA4eYl4lYA3gGbdadJVmTB5CpIoC19-FZqYjQA)

Meanwhile, I'll also be looking through trying to deal with other "minor" issues. Thanks in advance!
(and FYI the relevant path files are:
my lua: LUA/GeorgiaTrait-Dummy.lua
your lua: Imported/LUA/CityAdoptsReligionEvent.lua
dummy building: GameInfo/GeorgianTraitXML.xml)
 
The event code does create some "blank" buildings named after each of the religions. The internal workings of the code need them but everyone else can ignore them as they have no game play effect.

Are you seeing the blank buildings only in the civilopedia? They should be showing up in cities as well (once cities have been a religion). I would need to take a look at the mod you provided to confirm but one quick thing to try is to throw some print statements in the chunk of code you wrote and see if the luaEvent is even firing.

The lua file you got from me should be InGameUIAddIn with VFS=false, while the SQL is OnModActivated -> UpdateDatabase.

As for hiding the blank buildings, the approach linked by JFD is the best (or least bad) way to do it. Alternative methods require rewriting a chunk of the UI which is probably outside the scope of what you want to do with a custom civilization mod.
 
Okay, so changed VFS=true to false and added an InGameUIAddin entry for your lua, and the dummy buildings showed up (haven't yet made them invisible in the civilopedia) but my own dummy still doesn't show up.

There is a print statement in my code, and it shows up in the lua.log, so at least the lua is loading correctly - but the statement is outside of any function, so whether or not the actual coding that follows is firing I'm not sure. The lua.log shows no syntax errors however.

So if this is your SQL:
Spoiler :
Code:
-- Add the current religion building type
INSERT INTO Buildings(Type, BuildingClass, Description, NukeImmune, ConquestProb, Cost)
SELECT 'BUILDING_'||Type as Type, 'BUILDINGCLASS_'||Type as BuildingClass, Description as Description, 'true' as NukeImmune, '100' as ConquestProb, '-1' as Cost
FROM Religions;

-- Add the current religion building classes
INSERT INTO BuildingClasses(Type, DefaultBuilding, Description)
SELECT 'BUILDINGCLASS_'||Type as Type, 'BUILDING_'||Type as DefaultBuilding, Description as Description

FROM Religions;

-- Add the has-ever-been religion building type
INSERT INTO Buildings(Type, BuildingClass, Description, NukeImmune, ConquestProb, Cost)
SELECT 'BUILDING_HAS_BEEN_'||Type as Type, 'BUILDINGCLASS_'||Type as BuildingClass, Description as Description, 'true' as NukeImmune, '100' as ConquestProb, '-1' as Cost

FROM Religions;

-- Add the has-ever-been religion building classes
INSERT INTO BuildingClasses(Type, DefaultBuilding, Description)
SELECT 'BUILDINGCLASS_HAS_BEEN_'||Type as Type, 'BUILDING_HAS_BEEN_'||Type as DefaultBuilding, Description as Description
FROM Religions;
then to make the buildings invisible I would change it to this?
Spoiler :
Code:
-- Add the current religion building type
INSERT INTO Buildings(Type, BuildingClass, Description, NukeImmune, ConquestProb, Cost, [B][COLOR="blue"]FaithCost, PrereqTech[/COLOR][/B])
SELECT 'BUILDING_'||Type as Type, 'BUILDINGCLASS_'||Type as BuildingClass, Description as Description, 'true' as NukeImmune, '100' as ConquestProb, '-1' as Cost, [COLOR="blue"][B]'-1' as FaithCost, '' as PrereqTech[/B][/COLOR]FROM Religions;

-- Add the current religion building classes
INSERT INTO BuildingClasses(Type, DefaultBuilding, Description)
SELECT 'BUILDINGCLASS_'||Type as Type, 'BUILDING_'||Type as DefaultBuilding, Description as Description
FROM Religions;

-- Add the has-ever-been religion building type
INSERT INTO Buildings(Type, BuildingClass, Description, NukeImmune, ConquestProb, Cost, [COLOR="blue"][B]FaithCost, PrereqTech[/B][/COLOR])
SELECT 'BUILDING_HAS_BEEN_'||Type as Type, 'BUILDINGCLASS_'||Type as BuildingClass, Description as Description, 'true' as NukeImmune, '100' as ConquestProb, '-1' as Cost, [B][COLOR="Blue"]'-1' as FaithCost, '' as PrereqTech[/COLOR][/B]FROM Religions;

-- Add the has-ever-been religion building classes
INSERT INTO BuildingClasses(Type, DefaultBuilding, Description)
SELECT 'BUILDINGCLASS_HAS_BEEN_'||Type as Type, 'BUILDING_HAS_BEEN_'||Type as DefaultBuilding, Description as Description
FROM Religions;
or is the PrereqTech part unnecessary since the default is null?
(Sorry, I almost never use SQL)
(And also for whatever reason the forum is deciding to place the FROM statement a line before it should)

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

EDIT: Okay, so I added a print statement inside the function and that statement doesn't show up in the log. Thus, the code doesn't fire. :(
Just as a note, this is what it currently is:
Spoiler :
Code:
-- GeorgiaTrait-Dummy
-- Author: AW, with the help of Machiavelli24
-- DateCreated: 1/28/2014 4:39:37 PM
--------------------------------------------------------------
print('Georgian lua loaded.')
LuaEvents.CityAdoptsReligion.Add(
function(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
	print('So the hook fires, huh? Thats good...')
	local pPlayer = Players[iOwner]
	if (pPlayer:IsAlive()) then
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
			local city = Map.GetPlot(iX, iY):GetPlotCity()
			if (bFirstConverion) and (city:IsHolyCityForReligion(eNewReligion)) then
				city:SetNumRealBuilding(GameInfoTypes.BUILDING_GEORGIA_DUMMY, 1)
			end
		end
	end
end)

EDIT2: Oops, I forgot the word "Events" in the hook. I'll add that in and try it again.
EDIT3: Okay, so corrected the hook, and now the code activates - somewhat. at least the print statements show up in the log:
Code:
[41967.014] CityAdoptsReligionEvent: Calling CityAdoptsReligionEvent(iOwner: 0 iX: 85 iY: 21 eOldReligion: 0 eNewReligion: 2 bFirstConversion: true)
[41967.014] CityAdoptsReligionEvent: So the hook fires, huh? Thats good...
But the dummy still doesn't show up. I don't understand why.
 
Since the 'So the hook fires...' line is getting printed you know the problem is somewhere in the red section:

Code:
print('Georgian lua loaded.')
LuaEvents.CityAdoptsReligion.Add(
function(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
	print('So the hook fires, huh? Thats good...')
	[COLOR="Red"]local pPlayer = Players[iOwner]
	if (pPlayer:IsAlive()) then
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
			local city = Map.GetPlot(iX, iY):GetPlotCity()
			if (bFirstConverion) and (city:IsHolyCityForReligion(eNewReligion)) then
				city:SetNumRealBuilding(GameInfoTypes.BUILDING_GEORGIA_DUMMY, 1)
			end
		end
	end[/COLOR]
end)

I don't see any obvious syntax error but if you add a few more print statements in, or temporarily comment out some of the lines, you should be able to narrow down which line is not acting as you expect.
 
If that's all the code, bFirstConverion is undefined (nil) so will be false, so the innermost if condition will never evaluate to true, so the SetNumRealBuilding() will never execute
 
bFirstConversion is defined in the code Machiavelli24 gave me, which goes like this:
Spoiler :
Code:
-- CityAdoptReligionEvent
-- Author: Machiavelli
-- DateCreated: 8/20/2012 10:02:01 AM
--------------------------------------------------------------
-- Purpose:
-- LuaEvents.CityAdoptsReligionEvent(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
-- Will be called whenever any city (human or ai) adopts or changes to a religion.  It is not called
-- when a Pantheon is adopted.  Nor is it called when an Inquisitor cleans a city.
--
-- Known limitations:
-- When an Inquisitor cleans a city the religion building marking that city remains even though
-- the city is no longer that religion.  The religion building won't be removed until this
-- function is called again, and if the city has at least 1 follower of the old religion when
-- that happens (due to natural pressure or a missionary) the CityAdoptsReligionEvent won't fire.
--
-- iOwner: The ID of the player who owns the city
-- iX, iY: The location of the city, use Map.GetPlot(iX, iY) to get the plot object
-- eOldReligion: The ID of the religion the city use to be.  If the city was not previously a
--       founded religion (due to the city having a Pantheon or no Pantheon) eOldReligion will
--       be 0.
-- eNewReligion: The ID of the religion the city is now.  Will always be 1 or greater because
--       the 0 ID is for "Pantheon religions".
-- bFirstConversion: A boolean that will be true if this is the first time the city has become
--       eNewReligion, false otherwise.
--------------------------------------------------------------
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
		-- 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
		newReligionBuilding = "BUILDING_" .. GameInfo.Religions[eNewReligion].Type;
		if(city:IsHasBuilding(GameInfoTypes[newReligionBuilding])) 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
	local eOldReligion = 0;
	-- Find any buildings marking what the old religion the city is
	for row in GameInfo.Religions() do
		local temp = "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[temp])) then
			city:SetNumRealBuilding(GameInfoTypes[temp], 0);

			if(city:GetNumFollowers(row.ID) > 0 or city:GetPopulation() == 1) then
				-- Possible error check, if this is the second religion marking building found, could cause issues.
				-- 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;
	local bFirstConversion = false;

	if(not city:IsHasBuilding(GameInfoTypes[hasBeenReligionBuilding])) then
		bFirstConversion = true;
	end

	-- Update religion building state
	city:SetNumRealBuilding(GameInfoTypes[newReligionBuilding], 1);
	city:SetNumRealBuilding(GameInfoTypes[hasBeenReligionBuilding], 1);

	-- 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
GameEvents.CityConvertsReligion.Add(CallCityAdoptsReligionEvent);
If I were to guess, I'd say the problem with my code lies in this line:
Code:
local city = Map.GetPlot(iX, iY):GetPlotCity()
But then again, I can't get this lua to work, so what do I know? :p
 
Well, it seems whoward69 was right. I added a print statement after every line of coding too see which one it stopped on and therefore is the line with the error, and it is indeed this line:
Code:
if (bFirstConverion) and (city:IsHolyCityForReligion(eNewReligion)) then
Specifically this is what the code looks like with all the print statements:
Spoiler :
Code:
print('Georgian lua loaded.')
LuaEvents.CityAdoptsReligionEvent.Add(
function(iOwner, iX, iY, eOldReligion, eNewReligion, bFirstConversion)
	print('So the hook fires, huh? Thats good...')
	local pPlayer = Players[iOwner]
	print('pPlayer is looking good...')
	if (pPlayer:IsAlive()) then
		print('Alive. Check.')
		if (pPlayer:GetCivilizationType() == GameInfoTypes.CIVILIZATION_GEORGIA) then
			print('Get that civilization! Is it Georgia? It is!')
			local city = Map.GetPlot(iX, iY):GetPlotCity()
			print('Got to know where that city is!')
			if (bFirstConverion) and (city:IsHolyCityForReligion(eNewReligion)) then
				print('First Conversion? You bet!')
				city:SetNumRealBuilding(GameInfoTypes.BUILDING_GEORGIA_DUMMY, 1)
				print('Anndd.... Building Added!')
			end
		end
	end
end)
And this is relevant part the lua.log:
Spoiler :
Code:
...
[COLOR="Green"][B][37296.032] GeorgiaTrait-Dummy: Georgian lua loaded.[/B][/COLOR]
[37296.625] AdvisorInfoPopup: Closing Advisor Info
[37296.625] Demographics: Dequeuing demographics
[37296.625] Demographics: Dequeuing demographics
[37324.721] CivilopediaScreen: SetSelectedCategory(4)
[37324.721] CivilopediaScreen: CivilopediaCategory[CategoryUnits].DisplayList
[37324.814] CivilopediaScreen: CivilopediaCategory[CategoryUnits].SelectArticle
[37324.814] CivilopediaScreen: SetSelectedCategory(4)
[37324.861] CivilopediaScreen: CivilopediaCategory[CategoryUnits].SelectArticle
[37330.384] TechPopup: stealingTechTargetPlayerID: -1
[37330.384] TechPopup: iValue: 0
[37349.088] TurnProcessing: Hiding TurnProcessing
[B][COLOR="green"][37368.931] CityAdoptsReligionEvent: Calling CityAdoptsReligionEvent(iOwner: 0 iX: 38 iY: 45 eOldReligion: 0 eNewReligion: 2 bFirstConversion: true)
[37368.931] CityAdoptsReligionEvent: So the hook fires, huh? Thats good...
[37368.931] CityAdoptsReligionEvent: pPlayer is looking good...
[37368.931] CityAdoptsReligionEvent: Alive. Check.
[37368.931] CityAdoptsReligionEvent: Get that civilization! Is it Georgia? It is!
[37368.931] CityAdoptsReligionEvent: Got to know where that city is![/COLOR][/B]
...
So I note that I seem to have mispelled bFirstConversion , but do I also need to change bFirstConversion to bFirstConversion=true, or something like that?
 
:mad:
So I finally, after some trial and error, got the dummy building to show up...
The purpose of the dummy building is to give 3 free missionaries, but they spawn without having any religion to spread, which kind of defeats the purpose...

So, new questions:
1) Why is it doing this, and how can I make the missionaries actually have religion?
2) How can I stop the religion dummy buildings from appearing in the civilopedia (as in, was my SQL correct?), and preferably also in the city screen, without using BNW-requiring methods?
 
Top Bottom