Adding xml tags that work through Lua (eg, policy-dependent units & buildings)

Sorry to bring up an older thread but i had a question about making units and buildings available by era instead of tech.

do i need one LUA file with this:

Spoiler :

GameEvents.PlayerCanConstruct.Add(function(iPlayer , buildingTypeID)
local prereqEra = GameInfo.Buildings[buildingTypeID].PrereqEra
local playerEra = player:GetCurrentEra();
if playerEra >= prereqEra then
return false;
end
end
return true
end)


or one for each building? Where in the XML do i reference the era?

Do i need to make an SQL with this:

Spoiler :

ALTER TABLE Buildings ADD COLUMN 'PrereqPolicy' TEXT DEFAULT NULL;


and how do i make said SQL run before the xml? Sorry if this is all old news, ive never seen SQL or LUA and i never realized how complex something so seemingly simple as adding a unit/building by era could be.
 
@Hulfgar,

You're going to have to write your own function to check for features (or whatever) around the city. My little Lua function PlotToRadiusIterator() might be helpful. The function just needs to return true to allow, false to disallow. One caution: These prereq functions get called a lot (many times per turn per player). So that might be an issue here.

@thadian

Use [CODE]code block[/CODE] when pasting code on the forum. Just a couple mistakes I see:
  1. GameInfo.Buildings[buildingTypeID].PrereqEra is going to return text (assuming you put text into that table field) but you are treating it as an integer. (I believe that player:GetCurrentEra() returns integer, but I'm not 100% sure.)
  2. Your SQL line refers to PrereqPolicy when it should be prereqEra

You make the SQL run before your XML by making sure it is higher up in the Actions tab (under your mod properties). Just hit the up/down buttons to reorder. Alternatively, you can just do the table additions in the SQL file after you have added the column (that's what I do).

Now that you've added a column to the table, you also need to put something in there (using SQL or XML). Sorry if this is obvious, but I didn't see it in your post.

@JFD

Yes, you just need to add two columns to the Buildings table:

Code:
ALTER TABLE Buildings ADD COLUMN 'PrereqPolicy' TEXT DEFAULT NULL;
ALTER TABLE Buildings ADD COLUMN 'AndPrereqPolicy' TEXT DEFAULT NULL;

Then alter Lua slightly to test for the new AndPrereqPolicy column:

Code:
GameEvents.PlayerCanConstruct.Add(
function(iPlayer, buildingTypeID)
	local building = GameInfo.Buildings[buildingTypeID]
	local prereqPolicy = building.PrereqPolicy
	if prereqPolicy then
		local player = Players[iPlayer]
		local policyID = GameInfo.Policies[prereqPolicy].ID
		if not player:HasPolicy(policyID) then
			return false
		end
		local andPrereqPolicy = building.AndPrereqPolicy
		if andPrereqPolicy then
			local andPolicyID = GameInfo.Policies[andPrereqPolicy].ID
			if not player:HasPolicy(andPolicyID) then
				return false
			end
		end
	end
	return true
end)

Then, of course, you have to add something to that 2nd column. (Note that the way I wrote it, AndPrereqPolicy is only checked if the building has a PrereqPolicy.)
 
this will take a little bit to absorb and redo, thanks for the tip!

Nothing is obvious to me, ive never used LUA for anything, just xml. so this is a whole new venture into a deep cave, with a treasure chest at the end - right now, im in the boss room working on the hard part XD
 
Your SQL code should have ; at the end :)

(I'm not a Lua expert so I can't tell you if your Lua code is good or not.)
 
Yes, that's a totally different animal. If it was a GameEvent, then it would work as you are trying to use it. But it's not. I don't have a complete list of GameEvents so I don't know if there is one that does what you want. (I'm sure there is a way to get all GameEvents, but I don't know it.)

But it's really a player method, which has to be used on a player object. Most likely player:CanCreatePantheon() just returns true or false.

There are only a couple new religion GameEvents. I don't know what they do but I found them in the Medieval scenario, so that is where you would have to look to see how they work.
 
I searched for HasCreatedPantheon in the Expansion folder and it appears about 10 times, nowhere with an argument. You really need to use a decent search program (Windows Grep or somesuch) to see how these are used by the developers. (Download and search some of the larger mods too, but they may not have much religious stuff yet.) That's how I learn. I suspect that player:HasCreatedPantheon() just returns a true/false telling you whether or not the player has created a pantheon.

Keep in mind that beliefs are associated with religions (even the pantheon belief gets "absorbed" as part of a religion if the civ founds one). The function you need to get beliefs in a religion is GetBeliefsInReligion. It's used as an iterator like this:
Code:
for i, beliefID in ipairs(Game.GetBeliefsInReligion(eReligion)) do
	print beliefID
end
This will print all beliefs (by ID) currently associated with eReligion, including the pantheon, founder, follower and enhancers. If eReligion has not been founded yet, it will crash the game (I know). It's not clear from your post what religion you want (the one founded by the player? any in any cities? dominant religion?).

I don't know how to test the belief associated with a pantheon that has not yet become a religion.
 
Great example above for the thread topic.

I've found that religion modding is kind of all or nothing. You can disable the existing system (by putting faith reqs out of reach) and then build your own entirely via Lua, where you Lua code each step (establishing pantheons & religions, enhancing religions, etc). However, doing something simple like limiting which pantheon is picked using the existing system may be impossible (you could do it for human with UI modding, but that would affect the AI).
 
for an OrPrereqPolicy column:

Code:
GameEvents.PlayerCanConstruct.Add(
function(iPlayer, buildingTypeID)
	local building = GameInfo.Buildings[buildingTypeID]
	local prereqPolicy = building.PrereqPolicy
	if prereqPolicy then
		local player = Players[iPlayer]
		local policyID = GameInfo.Policies[prereqPolicy].ID
		if not player:HasPolicy(policyID) then
			local orPolicy = building.OrPrereqPolicy
			if orPolicy then
				local orPolicyID = GameInfo.Policies[orPolicy].ID
				if not player:HasPolicy(policyID) then
					return false
				end
			else
				return false
			end
		end
		local andPrereqPolicy = building.AndPrereqPolicy
		if andPrereqPolicy then
			local andPolicyID = GameInfo.Policies[andPrereqPolicy].ID
			if not player:HasPolicy(andPolicyID) then
				return false
			end
		end
	end
	return true
end)

I wrote these assuming that you would always have something in PrereqPolicy if you used the additional AndPrereqPolicy or the OrPrereqPolicy.
 
Hey all - really useful thread you have going here! I'm trying to make certain techs dependent on resources or terrain, but I'm struggling to figure out how to make the right tests. I was hoping to find a "player.HasResource" sort of thing, but I'm coming up empty. Just to clarify, I don't want to use any of the resource in making the tech, just to check that the player has access to it. Does anyone know what test i can use?

Also, I'm using playerCanResearch(), but i see there's also playerCanEverResearch - what's the difference?

Bula Vinaka,

E
 
The scripts work nicely in game. However, when trying to load a save game that had used these scripts there is always a Runtime Error (DX11). For reference, I set the lua file as import into VFS and loaded it as an InGameUIAddIn.

Any suggestion on incorporating these scripts in such a way as to add save capability?

You should not have both InGameUIAddIn and VFS=true for the same file. I don't know if this is causing the error you are seeing -- but it is likely to cause some kind of error. (When I did the same exact thing, I saw multiple Lua states in the fire tuner that were all called "EaMain".)

If you have one lua file called "MyModMain.lua", then add it as an InGameUIAddIn and leave VFS=false. You can then add additional lua files (my mod has 15 or so) using include statements at the top of your MyModMain.lua:

include("anotherFile.lua")
include("yetAnotherFile.lua")

For these additional files, set VFS=true.

The basic thumbrule is that a file only needs to be "added" to the mod once; and think of VFS=true, InGameUIAddIn and OnModActivated as three different ways to add a file. Sometimes it doesn't matter if you violate this. Other times it can cause weird issues.

Two words of warning:
  1. The include statement allows a partial string match to the file name, which is a pretty stupid thing if you ask me because it can only cause problems. That's why you don't have to have the ".lua" extension. However, I include the extension so that "EaAI.lua" and "EaAI_units.lua" will be recognized as different files.
  2. It's perfectly natural to have a lua file that is included from different states. For example, you might have a Utilities.lua that is included from your MyModMain.lua and also from some of the base UI lua files (which are separate states). You can do that just fine, but be careful to never include any context references in these files that are "multiply-included" (context is a UI thing; see whoward69's tutorial). This is not a problem at all for files that exist in only one state (e.g., included only from your MyModMain.lua file).
 
Top Bottom