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

Hi everybody:

I want to add xml tags that work through Lua as the title said. However, I want to do it by inserting tables instead of columns to fulfill my goal. The reason is that I find adding tables is more modular then adding columns, and thus it's easier to be used as mod components. Below is my lua code and XML code, I'm now at work so I cannot try it. Could anybody look at it to tell me if I made any mistakes?

Thank you!

Edit: Sorry that I don't know why but the format of the code became a mess when I put it the spoiler

XML:

Spoiler :

<GameData>
<Table name="Building_PrereqPolicy">
<Column name="BuildingType" type="text" reference="Buildings(Type)"/>
<Column name="PolicyType" type="text" reference="Policies(Type)"/>
</Table>

<Building_PrereqPolicy>
<Row>
<BuildingType>BUILDING_MONUMENT</BuildingType>
<PolicyType>POLICY_PIETY</PolicyType>
</Row>
</Building_PrereqPolicy>

</GameData>



Lua:

Spoiler :

function BuildingPrereqPolicy(iPlayer, buildingTypeID)
local buildingType = GameInfo.Buildings[buildingTypeID].Type;
local prereqPolicy = GameInfo.Building_PrereqPolicy[buildingType].PolicyType;
local player = Players[iPlayer];

if prereqPolicy then
local policyID = GameInfo.Policies[PrereqPolicy].ID
if not player:HasPolicy(policyID) then
return false
end
end
return true

end



GameEvents.PlayerCanConstruct.Add( BuildingPrereqPolicy );

 
Use [CODE]code[/CODE] tags around your code.

Since I've been doing 99% SQL rather than XML modding, I can't say for sure if the XML is correct. I think it is.

But...

There are really two kinds of tables in Civ5. You have tables with ID and Type columns, where Type is always unique (not just unique in the table but across the whole game so that GameInfoTypes["<typeString>"] always evaluates to a single integer). Then you have "subtables" that don't have ID or Type or any other unique row identifier. Your's follows the format for a subtable.

The syntax "GameInfo.Buildings[<Type or ID>]" to get an entire table row only works for the former table type with ID and Type columns. It can't work for a subtable because the buildingType (or <whatever>Type) is usually not unique within the table.

However, you can iterate over both kinds of table, including tables that you created. Works like this:
Code:
for row in GameInfo.Building_PrereqPolicy() do
	local buildingType = row.BuildingType
	local policyType = row.PolicyType

	<some logic here>

end

For subtables, you will always have to iterate over them. But really, the point of subtables is to allow you to assign >1 prereq policy for each building. That logically demands an iteration since you may have a "many to many" rather than a "one to one" relationship.

Edit:
On the argument that tables are more modular than columns, I would disagree. Both are completely modular as long as the name is safe.
 
Thank you for your help Pazyryk!

Seems that I don't quite get the point of using the second type of table. Below is my new code but it doesn't work. The biggest trouble I have is: I don't know how to link the viarant buildingTypeID to the buildingType in Building_FreeCulture. :sad:

Code:
function BuildingPrereqPolicy(iPlayer, buildingTypeID)
	
	local player = Players[iPlayer];

	for row in GameInfo.Building_FreeCulture() do
		local buildingType = row.BuildingType;
		local policyType = row.PolicyType;
		if buildingType == GameInfo.Buildings[buildingTypeID].Type then
					
				local policyID = GameInfo.Policies[policyType].ID
				if not player:HasPolicy(policyID) then
					return false
				end
		end
		return true
	end
end



GameEvents.PlayerCanConstruct.Add( BuildingPrereqPolicy );
 
I can't tell what you are trying to do there. It looks very much like you are trying to do a simple policy prereq test, but then why would you be iterating over a table called Building_FreeCulture?
 
I can't tell what you are trying to do there. It looks very much like you are trying to do a simple policy prereq test, but then why would you be iterating over a table called Building_FreeCulture?

'cause I was looking at the freeculture mod to get some ideas of using the new table:goodjob:

After some failure, I make a code that works. If you would like to take a look at it to see if there's some potential problems:

Code:
function BuildingPrereqPolicy(iPlayer, buildingTypeID)
	
	local player = Players[iPlayer];

	for row in GameInfo.Building_PrereqPolicy() do
		local buildingType = row.BuildingType;
		local policyType = row.PolicyType;
		local buildingID = GameInfo.Buildings[buildingType].ID;
		if buildingID == buildingTypeID then
					
				local policyID = GameInfo.Policies[policyType].ID;
				if not player:HasPolicy(policyID) then
					return false
				end
				return true
		end
		return true
	end
end



GameEvents.PlayerCanConstruct.Add( BuildingPrereqPolicy );
 
Can you please tell me where I'm going wrong. I'm trying to make a mod that adds an abbey building, which becomes available when the piety policy is acquired. Currently the abbey building appears in game, but is available right from the start without any policies being acquired.

Here is the code from my modbuddy:-

SQL:-
Spoiler :
t6frll.jpg


Lua:-
Spoiler :
24ysaoo.jpg


XML:-

Spoiler :
zwfbmc.jpg


Actions:-

Spoiler :
35c5160.jpg


I am using Gods & Kings version 1.0.1.705.

Thanks in advance.
 
Thanks for the response. I have made small mods before, but never anything with Lua.

I have tried the following in the contents which still didn't work:-

Spoiler :
nfs65k.jpg


I'm guessing the type is wrong but I'm not sure.
 
The problem understanding quotes in SQL is that the language tries so hard to interpret what it's given from context. So you can often use quotes when you shouldn't or not use them when you should or use the wrong kind. The one danger is using double quotes for table data (causes parser to attempt to treat something as a table or column name rather than a string literal, if it can).

I've been using single quotes when creating tables or columns because I think the text is treated as a string literal at this stage. But that might be a mistake on my part. Apparently CREATE TABLE and ALTER TABLE can take table and column names without any quote.
 
Yes that did it! Big thanks to PawelS, FramedArchitect and of course Pazyryk. If anyone wants to create a similar mod, just add the code like I have done in my images, but remove the ' ' from the sql.

Ideally I would like for the new abbey building to be purchased with faith. However when experimenting setting the cost to -1 and the faithcost to 200 like the other faith buildings, the abbey also becomes available to cities that have a majority religion, with or without piety adopted. I'm guessing there is not much that can be done about this, but I would appreciate any thoughts on the matter.
 
Is it possible to check a property of the city in question with PlayerCanConstruct or a similar function?

I see how I would go about checking if the player is in an era or has a policy or has met 3 other players or whatever, but what if I want a building to require at least 5 population in the city before you can build it? Just not possible in lua, or am I missing something?

EDIT: Derp, there's this exact example on page 3. Trying it now. Will report back if I can't get it working.

EDIT2: Working. CityCanConstruct is not documented in the OP, which purports to have a complete list of the functions added (granted, added in a specific patch and I don't know if this was added at a different time), which is a bit misleading - it may be worth noting its existence with an edit to the OP.
 
@Drawmeus, you should bookmark the civfanatics modding wiki. It has all of the existing GameEvents. (I'll update the OP.)

I have it bookmarked, I apparently just missed that event. My bad!

Also, thanks for the response. I appreciate the help even if it mostly turned out to be my reading comprehension at fault this time.
 
I think I can make trait pieces using this method. Create the trait piece as a boolean. Check for truth with Lua, then do my stuff that I want the trait to do.

If I want to give the trait piece to a Leader, just do <TraitPiece>true</TraitPiece>

Right?
 
Using the examples in this thread my mod has evolved into a full blown Piety mod. It is nearly finished and ready for publishing, but I have found a slight problem.

In my mod the Piety tree now has a policy called Monasticism, which once chosen allows you to build Monasteries. However if you then select a policy from the Rationalism tree the Monastery is still available to be built, despite the rest of the Piety tree being inactive. The way I think it should work is that any Monasteries already built should still give their bonuses, but any new Monasteries should not be available to build, unless the Piety tree is reactivated.

Is there a way to modify the code to do this?

Thanks in advance, and for making my mod possible in the first place.
 
You'll need to use a lua hook into GameEvents:CityCanConstruct, then check Player:HasPolicy(GameInfoTypes.POLICY_RATIONALISM). If they have Rationalism, return false, otherwise return true.

I *THINK* this should work with Policy braches, as well as individual policies.
 
Back
Top Bottom