View Full Version : Adding xml tags that work through Lua (eg, policy-dependent units & buildings)
Pazyryk Dec 19, 2011, 08:21 PM Let's say you want a simple policy prerequisite to build a building (there isn't one in the base game).
You can add columns to existing core tables via SQL. Here's the code you need in an SQL file:
ALTER TABLE Buildings ADD COLUMN 'PrereqPolicy' TEXT DEFAULT NULL;
SQL is added exactly as you add XML files (as an OnModActivated). Just make sure that the above file runs before your XML where you are using the new "PrereqPolicy" tag.
Now you need to add some Lua code to tell the dll what to do with this new table column:
GameEvents.PlayerCanConstruct.Add(
function(iPlayer, buildingTypeID)
local prereqPolicy = GameInfo.Buildings[buildingTypeID].PrereqPolicy
if prereqPolicy then
local player = Players[iPlayer]
local policyID = GameInfo.Policies[prereqPolicy].ID
if not player:HasPolicy(policyID) then
return false
end
end
return true
end)
That's it! You can now use this new tag to make any building construction dependent on having any particular policy, just like you use any other xml tag.
Following the example above, you should be able to add PolicyPrereq tags to Units and Techs in a similar way using these GameEvents:
GameEvents.PlayerCanTrain.Add(function(iPlayer, unitTypeID) ... end)
GameEvents.PlayerCanResearch.Add(function(iPlayer, techTypeID) ... end)
One suggestion: I actually add the above tag as "PrereqPolicy_paz". This is so that there are no problems down the road if the developers add a tag with this exact name (or perhaps a dll modder, once that is possible).
Also note that the above prereq will not be added to the pedia. You'll have to do that yourself. Otherwise, there will be no indication in the game why the building cannot be built.
************************************************** ************
Added 12/29
OK, let's say you want to run a conditional test of your own using a tag "LuaReq". Some of you may remember many such tags in FFH (and mods thereof). They are extremely powerful because you can write short Lua functions to create whatever condition you want.
As above, you add another column to Buildings like this:
ALTER TABLE Buildings ADD COLUMN 'LuaReq' TEXT DEFAULT NULL;
Now let's make a Monument conditional on something, say turn > 5 (you can do this in XML of course, but I do everything in SQL so it's much easier for me this way):
UPDATE Buildings SET LuaReq='Game.GetGameTurn() > 5' WHERE Type='BUILDING_MONUMENT';
That works, but it's pretty limited. What you really want to do is this:
UPDATE Buildings SET LuaReq='RunUserTestFunction()' WHERE Type='BUILDING_MONUMENT';
If RunUserTestFunction() returns true, then Monument can be built. If it reuturns false, then Monument cannot be built. (Example code below returns true when turn is > 5 and iPlayer == 0.) The code to make this all work for Buildings is below (adds both LuaReq and PrereqPolicy). The only thing you need to do is supply your own Lua condition test functions and call the compile function during game init (the very last line below). If you want to add LuaReq to other tables, hopefully you can use this as skeleton code to do it (be sure to add any Lua callback tags to the two tables on lines 2 and 3).
--add any tags and their tables to the two tables below in matching pairs (only for tags that "call" a Lua function)
local luaCallbackTable = { "Buildings"}
local luaCallbackTag = { "LuaReq"}
---------------------------------------------------------------
-- Compile Lua callback text (run once at game init)
---------------------------------------------------------------
local bLuaCallbacksCompiled = false
local LuaCallback = {} --will hold all lua functions (as function values) keyed by function text exactly as it appears in table
args = {} --loadstring always compiles in global environment, so use this global to hold arguments for function call
function CompileTableLuaCallbacks()
-- this must run after functions defined!
print("Compiling table Lua callbacks...")
for i, callbackTable in ipairs(luaCallbackTable) do
local callbackTag = luaCallbackTag[i]
for item in GameInfo[callbackTable]() do
local functText = item[callbackTag]
if functText and not LuaCallback[functText] then
print("Table "..callbackTable..", tag "..callbackTag..", function "..functText)
local funct = assert(loadstring("return "..functText))
LuaCallback[functText] = funct
end
end
end
bLuaCallbacksCompiled = true
end
---------------------------------------------------------------
-- Functions for new tags added to tables (including Lua callbacks)
---------------------------------------------------------------
-- Building requirements
GameEvents.PlayerCanConstruct.Add(
function(iPlayer, buildingTypeID)
local player = Players[iPlayer]
local building = GameInfo.Buildings[buildingTypeID]
local prereqPolicy = building.PrereqPolicy
if prereqPolicy then
local policyID = GameInfo.Policies[prereqPolicy].ID
if not player:HasPolicy(policyID) then
return false
end
end
local functText = building.LuaReq
if functText and bLuaCallbacksCompiled then
local funct = LuaCallback[functText]
args.iPlayer = iPlayer
args.buildingTypeID = buildingTypeID
if not funct() then --!!! that was the function call, so make sure args holds whatever you need !!!
return false
end
end
--add any additional restrictions to buildings here
return true
end)
---------------------------------------------------------------
-- An example user defined function (can be in another file but must be same state)
-- Note that any arguments must be passed through a global (I use args here)
---------------------------------------------------------------
function RunUserTestFunction()
print("called RunUserTestFunction")
iPlayer = args.iPlayer
buildingTypeID = args.buildingTypeID
print(iPlayer)
print(buildingTypeID)
if Game.GetGameTurn() > 5 and iPlayer == 0 then
return true
end
return false
end
---------------------------------------------------------------
-- !!! Important !!! Put this somewhere in your program where it runs
-- at game init (after all functions above have been defined)
---------------------------------------------------------------
CompileTableLuaCallbacks()
Edit: One correction, you should (in theory) be able to add an argument to a LuaReq function call. Just be aware that it will be compiled in a global environment. So ReqTurn(5) should work and ReqTurn(g) should work if g is a global, but ReqTurn(x) won't work if x is local. Of course, if the value you want is in a global, you can get it from within the function anyway (that's how I use args above) so I'm not sure if that will be useful. But the ability to supply a hard value would certainly be useful. For example, you could have many buildings call the same ReqTurn function, but each has a different turn requirement. Or you could require different gold levels in treasury. Or different total culture. Or... The possibilities are really endless. (I haven't actually tested this yet.)
************************************************** ************
There were a bunch of "Can" game events added in patch 1.0.1.332. Here's the whole list:
(Lua) Added GameEvents.CityCanBuyAnyPlot(ownerID, cityID) (TestAll)
(Lua) Added GameEvents.CityCanBuyPlot(ownerID, cityID, plotX, plotY) (TestAll)
(Lua) Added GameEvents.CityCanCreate(ownerID, cityID, projectTypeID); (TestAll)
(Lua) Added GameEvents.CityCanMaintain(ownerID, cityID, processTypeID); (TestAll)
(Lua) Added GameEvents.CityCanPrepare(ownerID, cityID, specialistTypeID); (TestAll)
(Lua) Added GameEvents.CityCanTrain(ownerID, cityID, unitTypeID); (TestAll)
(Lua) Added GameEvents.PlayerAdoptPolicy(playerID, policyTypeID); (Hook)
(Lua) Added GameEvents.PlayerAdoptPolicyBranch(playerID, policyBranchTypeID); (Hook)
(Lua) Added GameEvents.PlayerCanAdoptPolicy(playerID, policyTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanAdoptPolicyBranch(playerID, policyBranchTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanConstruct(playerID, buildingTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanCreate(playerID, projectTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanEverReseearch(playerID, techtypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanMaintain(playerID, processTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanPrepare(playerID, specialistTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanResearch(playerID, techTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanTrain(playerID, unitTypeID); (TestAll)
(Lua) Added GameEvents.TeamSetHasTech(teamID, techID); (Hook)
************************************************** ************
Edit 11/2012: Thanks to DonQuiche, we now have a complete wiki (http://modiki.civfanatics.com/index.php/Lua_and_UI_Reference) listing all of the GameEvents. (A few errors here and there, but on the whole it is an awesome resource...)
Sneaks Dec 22, 2011, 09:29 AM This is certainly a helpful little snippet. But seriously, give us some sneak peaks into what you are working on. I am practically jumping out of my seat after seeing all your code.
Pazyryk Dec 29, 2011, 01:25 AM Here's a teaser from the 1st line of my mod's description: "You begin knowing only that you are a small tribe, belonging to one of three races, without name, leader or history." I still have about 10 items on the checklist before alpha release, and each is a full day of work. Perhaps 4 - 8 weeks away.
Back on thread topic: I've also figured out a simple generic way to add "LuaReq" as a table column. So you add something like "ReqLuaExample()" as LuaReq for a building. The building can only be built if your function ReqLuaExample() returns a true value. I'll post this in the next couple days.
Pazyryk Dec 29, 2011, 09:35 PM Added code for a new LuaReq tag to the original post. This allows you to specify any Lua function (that you supply) that must return true for a building to be buildable.
Pouakai Dec 29, 2011, 11:33 PM Awesome work right here, free to use I suppose?
Also, you wouldn't happen to know where I can find a tutorial on adding new tables, would you?
Moriboe Dec 30, 2011, 06:41 AM This example code sure helped me a lot, thanks! :)
I added building and unit restrictions based on the current state of world diplomacy, to create an alternative path to diplomatic victories (rather than buying everyone out). If interested, check here (http://forums.civfanatics.com/showpost.php?p=11156034&postcount=57).
Pazyryk Dec 30, 2011, 09:12 AM Awesome work right here, free to use I suppose?
Yes, of course.
Also, you wouldn't happen to know where I can find a tutorial on adding new tables, would you?
No. I'll probably write a general SQL tutorial at some point that includes table creation (I don't do any of this in xml so I've forgotten how). I'll edit this post later with an example when I have access.
Moriboe Dec 31, 2011, 05:45 AM @Pouakai: with some examples available, adding new tables in XML is pretty straightforward. You can look for instance at the one I posted in the "culture per population" topic, then look at CIV5Buildings.xml. You will see it's the same thing really.
Pouakai Dec 31, 2011, 11:00 AM Thanks. My main concern is the lua telling it what to do.
xxhe Jan 31, 2012, 03:32 PM Thank you Paz. Very good example! I have a further question here: how to make this policy requirement shown in tooltips (such as the one in techtree when our pointer hang over the buiding)?
Pazyryk Feb 01, 2012, 02:25 PM Thank you Paz. Very good example! I have a further question here: how to make this policy requirement shown in tooltips (such as the one in techtree when our pointer hang over the buiding)?
Some of these you can do by modifying "Help" fields in the existing xml files. But others are generated "on the fly" within the UI Lua files. I haven't done a lot of this yet so you're going to have to figure it out on a case-by-case basis.
Nutty Feb 03, 2012, 05:27 PM Hi Pazyryk, is there a check for something like "player:HasEra(eraID)"?
Pazyryk Feb 05, 2012, 12:12 PM There is a player:GetCurrentEra() at the wiki (http://wiki.2kgames.com/civ5/index.php/Lua_Game_Objects/Player). I would assume that it returns current era ID as an integer, but I haven't used it.
Nutty Feb 06, 2012, 05:25 PM There is a player:GetCurrentEra() at the wiki (http://wiki.2kgames.com/civ5/index.php/Lua_Game_Objects/Player). I would assume that it returns current era ID as an integer, but I haven't used it.
You're right, it returns 0-6.
What content type do you publish this lua as?
EDIT:
If it's not obvious what I'm trying to do... Your post above got me thinking I could replicate, in LUA, the variation by era of units (like workers and great people). But it could also be useful to, e.g., simply obsolete a unit/building by era rather than a specific tech. I imagine you could do some interesting things with tech subtrees that don't have prerequisites as such.
But... I'm no good with LUA modding, and this isn't working:
SQL:
ALTER TABLE Units ADD COLUMN 'UnitArtInfoEraVariationStartEra_RED' TEXT DEFAULT NULL;
ALTER TABLE Units ADD COLUMN 'UnitArtInfoEraVariationStopEra_RED' TEXT DEFAULT NULL;
-- Spanish knight
INSERT INTO "Units" ('Type', 'Description', 'Civilopedia', 'Strategy', 'Help', 'Requirements', 'Combat', 'RangedCombat', 'Cost', 'Moves', 'Immobile', 'Range', 'BaseSightRange', 'Class', 'Special', 'Capture', 'CombatClass', 'Domain', 'CivilianAttackPriority', 'DefaultUnitAI', 'Food', 'NoBadGoodies', 'RivalTerritory', 'MilitarySupport', 'MilitaryProduction', 'Pillage', 'Found', 'FoundAbroad', 'CultureBombRadius', 'GoldenAgeTurns', 'IgnoreBuildingDefense', 'PrereqResources', 'Mechanized', 'Suicide', 'CaptureWhileEmbarked', 'PrereqTech', 'ObsoleteTech', 'GoodyHutUpgradeUnitClass', 'HurryCostModifier', 'AdvancedStartCost', 'MinAreaSize', 'AirUnitCap', 'NukeDamageLevel', 'WorkRate', 'NumFreeTechs', 'RushBuilding', 'BaseHurry', 'HurryMultiplier', 'BaseGold', 'NumGoldPerEra', 'SpreadReligion', 'IsReligious', 'CombatLimit', 'RangeAttackOnlyInDomain', 'RangeAttackIgnoreLOS', 'RangedCombatLimit', 'XPValueAttack', 'XPValueDefense', 'SpecialCargo', 'DomainCargo', 'Conscription', 'ExtraMaintenanceCost', 'NoMaintenance', 'Unhappiness', 'UnitArtInfo', 'UnitArtInfoCulturalVariation', 'UnitArtInfoEraVariation', 'ProjectPrereq', 'SpaceshipProject', 'LeaderPromotion', 'LeaderExperience', 'DontShowYields', 'ShowInPedia', 'MoveRate', 'UnitFlagIconOffset', 'PortraitIndex', 'IconAtlas', 'UnitFlagAtlas', 'UnitArtInfoEraVariationStartEra_RED', 'UnitArtInfoEraVariationStopEra_RED')
SELECT ("UNIT_SPANISH_KNIGHT"), ("TXT_KEY_UNIT_SPANISH_KNIGHT"), "Civilopedia", "Strategy", "Help", "Requirements", "Combat", "RangedCombat", "Cost", "Moves", "Immobile", "Range", "BaseSightRange", "Class", "Special", "Capture", "CombatClass", "Domain", "CivilianAttackPriority", "DefaultUnitAI", "Food", "NoBadGoodies", "RivalTerritory", "MilitarySupport", "MilitaryProduction", "Pillage", "Found", "FoundAbroad", "CultureBombRadius", "GoldenAgeTurns", "IgnoreBuildingDefense", "PrereqResources", "Mechanized", "Suicide", "CaptureWhileEmbarked", "PrereqTech", "ObsoleteTech", "GoodyHutUpgradeUnitClass", "HurryCostModifier", "AdvancedStartCost", "MinAreaSize", "AirUnitCap", "NukeDamageLevel", "WorkRate", "NumFreeTechs", "RushBuilding", "BaseHurry", "HurryMultiplier", "BaseGold", "NumGoldPerEra", "SpreadReligion", "IsReligious", "CombatLimit", "RangeAttackOnlyInDomain", "RangeAttackIgnoreLOS", "RangedCombatLimit", "XPValueAttack", "XPValueDefense", "SpecialCargo", "DomainCargo", "Conscription", "ExtraMaintenanceCost", "NoMaintenance", "Unhappiness",
("ART_DEF_UNIT_U_SPANISH_KNIGHT"), "UnitArtInfoCulturalVariation", "UnitArtInfoEraVariation", "ProjectPrereq", "SpaceshipProject", "LeaderPromotion", "LeaderExperience", "DontShowYields", "ShowInPedia", "MoveRate", "UnitFlagIconOffset", "PortraitIndex", "IconAtlas", "UnitFlagAtlas", NULL, 5
FROM "Units" WHERE (Type = "UNIT_KNIGHT");
INSERT INTO "Language_en_US" ( 'Tag', 'Text' )
VALUES ( 'TXT_KEY_UNIT_SPANISH_KNIGHT', 'Knight Spain' );
INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
SELECT ("UNIT_SPANISH_KNIGHT"), "UnitAIType"
FROM "Unit_AITypes" WHERE (UnitType = "UNIT_KNIGHT");
INSERT INTO "Unit_ClassUpgrades" ('UnitType', 'UnitClassType')
SELECT ("UNIT_SPANISH_KNIGHT"), "UnitClassType"
FROM "Unit_ClassUpgrades" WHERE (UnitType = "UNIT_KNIGHT");
INSERT INTO "Civilization_UnitClassOverrides" ( 'CivilizationType', 'UnitClassType', 'UnitType' )
VALUES ( 'CIVILIZATION_SPAIN', 'UNITCLASS_KNIGHT', 'UNIT_SPANISH_KNIGHT' );
INSERT INTO "Unit_Flavors" ('UnitType', 'FlavorType', 'Flavor')
SELECT ("UNIT_SPANISH_KNIGHT"), "FlavorType", "Flavor"
FROM "Unit_Flavors" WHERE (UnitType = "UNIT_KNIGHT");
INSERT INTO "Unit_FreePromotions" ('UnitType', 'PromotionType')
SELECT ("UNIT_SPANISH_KNIGHT"), "PromotionType"
FROM "Unit_FreePromotions" WHERE (UnitType = "UNIT_KNIGHT");
INSERT INTO "Unit_ResourceQuantityRequirements" ('UnitType', 'ResourceType', 'Cost')
SELECT ("UNIT_SPANISH_KNIGHT"), "ResourceType", "Cost"
FROM "Unit_ResourceQuantityRequirements" WHERE (UnitType = "UNIT_KNIGHT");
LUA:
GameEvents.PlayerCanTrain.Add(
function(iPlayer, unitTypeID)
local player = Players[iPlayer]
local eraID = player:GetCurrentEra()
local eraStop = GameInfo.Units[unitTypeID].UnitArtInfoEraVariationStopEra_RED
local eraStart = GameInfo.Units[unitTypeID].UnitArtInfoEraVariationStartEra_RED
if eraStop then
if eraID >= eraStop then return false
end
end
if eraStart then
if eraID < eraStart then return false
end
end
return true
end)
Pazyryk Feb 09, 2012, 08:58 AM For SQL, some aesthetic issues with quotes (not fatal but ugly and confusing):
Don't use double quotes. That's advice from the SQLite documentation itself.
Change this: INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
To this: INSERT INTO Unit_AITypes (UnitType, UnitAIType)
--you don't need any quotes for Tables and Columns that already have been defined.
To be honest, I don't really understand what you are doing with this:
INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
SELECT ("UNIT_SPANISH_KNIGHT"), "UnitAIType"
FROM "Unit_AITypes" WHERE (UnitType = "UNIT_KNIGHT");
But then, I never use very complicated SQL statements like this, so I might not understand something very basic. I've been able to add all of my game elements with a simple repetitive syntax (http://forums.civfanatics.com/showthread.php?t=437370)that allows many (100s) of rows per INSERT statement. I'm actually fairly ignorant when it comes to more advanced SQL logic (I haven't needed it), which is I guess what you are doing here.
I don't see any errors in the Lua. In fact, I'm pretty sure it has no errors. When I run into this situation, the first question I always ask is: Did my changes/additions get into the DB correctly? You should be looking at the DB everytime you alter it (with SQlite Manager (https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/)), or else you will be wasting time troubleshooting something that is perfectly correct.
What content type do you publish this lua as?
I don't understand this part of your question. Do you mean: how do I add a Lua file?
Nutty Feb 09, 2012, 04:55 PM For SQL, some aesthetic issues with quotes (not fatal but ugly and confusing):
The quotes are from Gedemon's R.E.D. modpack. It works, so I have not played with them.
To be honest, I don't really understand what you are doing with this:
INSERT INTO "Unit_AITypes" ('UnitType', 'UnitAIType')
SELECT ("UNIT_SPANISH_KNIGHT"), "UnitAIType"
FROM "Unit_AITypes" WHERE (UnitType = "UNIT_KNIGHT");
Again, from Gedemon. It's the same thing for most of the entries. I'm making a copy of the rows where UNIT_KNIGHT is the UnitType, and changing it to UNIT_SPANISH_KNIGHT instead. So in this case, UNIT_SPANISH_KNIGHT gets 2 rows for 2 UnitAITypes, just like UNIT_KNIGHT does, one for UNITAI_DEFENSE and one for UNITAI_FAST_ATTACK.
The unit is my own with some art I've been playing with, but the SQL entries are a copy-paste job. The unit itself works fine. The only thing I added to the SQL that was at all different from my usual setup was the first 2 lines, and the references to them in the add to the Units table. The columns are added successfully, and the entries for those columns are added successfully.
I don't see any errors in the Lua. In fact, I'm pretty sure it has no errors.
Thanks for taking a look... it's certainly simple enough, and I can't see why it wouldn't be working. To the extent I can bend FireTuner to my will, it looks like everything is working. But I can still train a unit before the 'UnitArtInfoEraVariationStartEra_RED' and after the 'UnitArtInfoEraVariationStopEra_RED'.
I don't understand this part of your question. Do you mean: how do I add a Lua file?
The question was basically whether this is using content type "InGameUIAddin."
I know the state of LUA modding has changed since Kael's guide came out. My understanding is no one makes changes to InGame.lua or InGame.xml anymore. Is this incorrect? I've hardly used LUA, and never in CiV, so I'll go take a look at some tutorials and/or recent prior art.
Thanks again, Pazyryk!
Pazyryk Feb 09, 2012, 07:31 PM Again, from Gedemon. It's the same thing for most of the entries. I'm making a copy of the rows where UNIT_KNIGHT is the UnitType, and changing it to UNIT_SPANISH_KNIGHT instead. So in this case, UNIT_SPANISH_KNIGHT gets 2 rows for 2 UnitAITypes, just like UNIT_KNIGHT does, one for UNITAI_DEFENSE and one for UNITAI_FAST_ATTACK.
I see. I tend to delete everything and re-add. It's just easier for me to keep it straight in my head that way.
Thanks for taking a look... it's certainly simple enough, and I can't see why it wouldn't be working. To the extent I can bend FireTuner to my will, it looks like everything is working. But I can still train a unit before the 'UnitArtInfoEraVariationStartEra_RED' and after the 'UnitArtInfoEraVariationStopEra_RED'.
Put a print statement in there so you know exactly what values Lua sees when it is called, or if it is being called at all.
The question was basically whether this is using content type "InGameUIAddin."
EaMain.lua is added as "InGameUIAddin", yes, with VFS=false. Then I have EaInit.lua, EaFunctions.lua, EaAI.lua, etc., all of which are included by "include" statements in EaMain.lua and have VFS=true.
No need anymore to worry about InGame.lua/InGame.xml.
Catalonia Feb 10, 2012, 07:26 AM And can I do it in a XML file?
Pazyryk Feb 10, 2012, 08:05 AM I don't know if you can add a column in XML or not. Maybe someone else has an answer.
(I gave up XML modding a while ago. Too hard for me.;))
Nutty Feb 10, 2012, 06:30 PM I see. I tend to delete everything and re-add. It's just easier for me to keep it straight in my head that way.
Sure, but if Firaxis patches something in that table, that way the mod may just upgrade gracefully.
Put a print statement in there so you know exactly what values Lua sees when it is called, or if it is being called at all.
Well, yeah, if you want to get technical about it. :hammer2: I have no idea why, but the LUA wasn't being executed. I set up a brand new mod, with almost the exact same setup, and suddenly it works. Very odd. :wallbash: Regardless...
It works! :woohoo: The only issue I had was that the numbers in the new columns were being stored as strings (though I had no quotes surrounding them), and comparison operators like greater/less than don't coerce strings to equivalent numbers. So, tonumber() function to the rescue, and the darn thing works.
Now. On to world domination! :mwaha:
:nono: (smily overload!)
:thanx:
Pazyryk Feb 11, 2012, 08:16 AM This line:
ALTER TABLE Units ADD COLUMN 'UnitArtInfoEraVariationStartEra_RED' TEXT DEFAULT NULL;
tells SQlite that that column has "text" affinity. Use INTEGER instead.
Pouakai Feb 11, 2012, 12:29 PM So, could this work to have units require a building in a city?
Pazyryk Feb 11, 2012, 03:06 PM There's already a Unit_BuildingClassRequireds table. Doesn't that work?
But yes, you could using GameEvents.CityCanTrain(ownerID, cityID, unitTypeID).
Pouakai Feb 11, 2012, 03:10 PM Oh, my mistake :blush:
It isn't used ingame, and I haven't checked the XML yet. Sorry!
killmeplease Feb 13, 2012, 09:31 PM is there a PlayerCanGetPolicy event?
id like to add tech prereqs to policies
also, are those lua fields added from .sql files or from the lua code somehow?
is it possible to change the game DB from lua?
Pazyryk Feb 14, 2012, 07:53 AM is there a PlayerCanGetPolicy event?
id like to add tech prereqs to policies
I believe this one is already in the policies xml file. I think it works but gives no help text to tell you why you can't adopt.
In any case, there is also a PlayerCanAdoptPolicy if you want to make it conditional on anything else. Here are the the list of added GameEvents (from patch 1.0.1.332) that are not in the wiki:
(Lua) Added GameEvents.CityCanBuyAnyPlot(ownerID, cityID) (TestAll)
(Lua) Added GameEvents.CityCanBuyPlot(ownerID, cityID, plotX, plotY) (TestAll)
(Lua) Added GameEvents.CityCanCreate(ownerID, cityID, projectTypeID); (TestAll)
(Lua) Added GameEvents.CityCanMaintain(ownerID, cityID, processTypeID); (TestAll)
(Lua) Added GameEvents.CityCanPrepare(ownerID, cityID, specialistTypeID); (TestAll)
(Lua) Added GameEvents.CityCanTrain(ownerID, cityID, unitTypeID); (TestAll)
(Lua) Added GameEvents.PlayerAdoptPolicy(playerID, policyTypeID); (Hook)
(Lua) Added GameEvents.PlayerAdoptPolicyBranch(playerID, policyBranchTypeID); (Hook)
(Lua) Added GameEvents.PlayerCanAdoptPolicy(playerID, policyTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanAdoptPolicyBranch(playerID, policyBranchTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanConstruct(playerID, buildingTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanCreate(playerID, projectTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanEverReseearch(playerID, techtypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanMaintain(playerID, processTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanPrepare(playerID, specialistTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanResearch(playerID, techTypeID); (TestAll)
(Lua) Added GameEvents.PlayerCanTrain(playerID, unitTypeID); (TestAll)
(Lua) Added GameEvents.TeamSetHasTech(teamID, techID); (Hook)
also, are those lua fields added from .sql files or from the lua code somehow?
is it possible to change the game DB from lua?All changes to DebugDatabase (odd name but that is the one used by the game) should be done as OnModActivated changes, either by SQL directly or XML (which is translated to SQL). Don't even think about changing this DB in game. Values like combat str, etc., need to be changed in game via Lua functions listed at the wiki, and if that doesn't exist then you can't really change it.
There is another DB that you can alter in-game via Lua (or really SQL commands embedded in Lua). This is SavedGameDB. You can add tables, change values, etc., but these only interact with your own Lua. The game engine doesn't need SavedGameDB at all. This is where my TableSaverLoader mod component saves/restores your Lua tables on game exit/reload.
killmeplease Feb 15, 2012, 03:00 AM thanks for the events list, i've added them to modiki along with your example for PlayerCanConstruct.
Don't even think about changing this DB in game.
what it will lead to?
Gedemon Feb 15, 2012, 04:15 AM what it will lead to?
nothing, that's the problem.
Nefliqus Feb 15, 2012, 06:54 AM Questions:
1) Do you have any ready mod with added xml tags through Lua?
2) Does OnModActivated event is activated only in SP or also in MultiPlayer mode?
Pazyryk Feb 15, 2012, 09:01 AM nothing, that's the problem.
If you think about the underlying C++ code, it would be surprising if it did. It's going to be a lot slower to reference a DB every time you need a value rather than holding it internally. So slow as to be unplayable, I would imagine.
However, I could imagine it will be possible to build dll functions that update internal values from the DB on some command. That would be a large effort and one can't expect the developers to do it for no reason. But it should be possible when we have the dll.
Questions:
1) Do you have any ready mod with added xml tags through Lua?
2) Does OnModActivated event is activated only in SP or also in MultiPlayer mode?
1. You'll have to wait for my mods release, hopefully in April.
2. I don't know anything about multiplayer (I thought that was not modable, yet...).
killmeplease Feb 15, 2012, 08:50 PM so evidently dll instantiates db entries in c++ objects and wokrs with them then to increase performance, not reading from db each time some value is requested
Ahhuatl Jun 20, 2012, 08:37 PM Okay, I'm making my first mod and all of this coding stuff is foreign to me. This seems like the appropriate area to ask my question and beg for help. I'm making a unique belief to add to a religion in Gods and Kings but there doesn't seem to be an ingame tag that will do what I need to do. Is the guide you've made how I'd go about creating this tag? I'm actually trying to create three unique tags:
1 - A golden age will occur every x number of turns.
2 - EXP earned doubles when at war with a city state that follows your religion
3 - Every time one of your unit dies in enemy territory, it acts a mini-missionary exerting x amount of faith.
Is this technically possible?
Pazyryk Jun 21, 2012, 12:57 AM Just remember that the XML tag doesn't do anything by itself. Something has to read it and do something. For existing tags, that would be the dll. For added tags, it has to be Lua code. All 3 of your items could be programmed in Lua, but these are pretty difficult. You would have to learn Lua to do this.
Ahhuatl Jun 23, 2012, 03:16 AM All right, well this was my best shot at #1 but it didn't work:
GameEvents.GoldenAge.Add
function(iPlayer, beliefType)
local XiuhAge = GameInfo.Beliefs[beliefType].XiuhAge
local pPlayer = Players[iPlayer];
if pPlayer:GetBeliefType(Belief.Founder) == local GameInfo.Beliefs['BELIEF_XIUHMOLPILLI'] then
if XiuhAge = true and (Game.GetGameTurn() = 55 or 110 or 165 or 220 or 275 or 330 or 385 or 440 or 495') then return true
break
break
end)
If I had to guess as to why, I'd say its because GameEvents.GoldenAge was just a wild guess. I for the life of me couldn't find the object that actually started GoldenAges - but what do I know? Maybe you can see some flaw that I can't. I'd appreciate any help you can offer...
Pazyryk Jun 23, 2012, 11:20 PM There is no game event for golden ages, as far as I recall. I suspect it would be a player function -- you should be looking for this stuff in the wiki (http://wiki.2kgames.com/civ5/index.php/Lua_Game_Objects). What you should do is figure out how to trigger a golden age with a single command in the fire tuner. I haven't done this but I think you will find a way. Worry about XML tags later, after you have your function working and you can trigger it from the tuner. (Folks will help on the main forum with Lua if you post some code and what you are trying to do.)
whoward69 Jun 24, 2012, 07:25 AM If I had to guess as to why, I'd say its because GameEvents.GoldenAge was just a wild guess.
As is
if pPlayer:GetBeliefType(Belief.Founder) == local GameInfo.Beliefs['BELIEF_XIUHMOLPILLI'] then
if XiuhAge = true and
(Game.GetGameTurn() = 55 or 110 or 165 or 220 or 275 or 330 or 385 or 440 or 495') then
return true
break
break
Before venturing into the Wiki, you may want to start with the Lua Tutorials (http://lua-users.org/wiki/TutorialDirectory)
Ahhuatl Jun 27, 2012, 11:13 PM Well, here is my latest unsuccessful attempt:
Player.ChangeGoldenAgeTurns.Add(
function(pPlayer, iChange)
local Player = Players[pPlayer]
if pPlayer:GetBeliefType(Belief.Founder) == local GameInfo.Beliefs['BELIEF_XIUHMOLPILLI'] then
if XiuhAge = true
return "10"
break
break
end)
Pazyryk Jun 28, 2012, 11:58 AM That code looks really random. I hate to sound mean, but there is not a single line it that is proper syntax or makes any sense, except maybe the last line "end)". You can't just make stuff up and expect it to work. Follow link above to a Lua tutorial.
In any case, you don't need an xml tag for this. The logic you need is to check for a belief and then do something. So don't try to follow my example in the OP. You first need to learn how to do something in Lua. Start with something simple like a print statement. (I'm not being sarcastic. If you can't print something and see it in Fire Tuner, there is no way that you can mod Lua.)
JFD Jun 29, 2012, 11:59 PM Is there any way to make a building require two Policies?
Hulfgar Jul 06, 2012, 03:47 PM Pazyryk would it be possible to add a terrain feature (such as forest) as prereq for a building using your method ?
And if yes could you provide the lua code please ? :)
thadian Jul 25, 2012, 07:30 PM 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:
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:
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.
Pazyryk Jul 26, 2012, 10:09 AM @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() (http://forums.civfanatics.com/showthread.php?t=464067) 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 block when pasting code on the forum. Just a couple mistakes I see:
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.)
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:
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:
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.)
thadian Jul 26, 2012, 11:07 AM 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
Hulfgar Jul 26, 2012, 01:37 PM hello Pazyryk thanks for the answer :)
FramedArchitect Aug 03, 2012, 01:17 PM Deleted
PawelS Aug 03, 2012, 02:43 PM 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.)
FramedArchitect Aug 03, 2012, 04:26 PM Deleted
Pazyryk Aug 03, 2012, 04:49 PM I didn't know that GameEvent existed. It's not in the G&K API thread (http://forums.civfanatics.com/showthread.php?t=465247). How did you find it?
canEverResearch needs to be capitalized (the wiki has a lot of these in lower case for some reason).
FramedArchitect Aug 03, 2012, 05:10 PM I didn't know that GameEvent existed. It's not in the G&K API thread (http://forums.civfanatics.com/showthread.php?t=465247). How did you find it?
canEverResearch needs to be capitalized (the wiki has a lot of these in lower case for some reason).
I think I found it here, http://forums.civfanatics.com/showthread.php?p=11588540
But looking now it's listed under "players" -- does that make a difference?
Pazyryk Aug 03, 2012, 05:52 PM 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.
FramedArchitect Aug 04, 2012, 01:18 PM Deleted
Pazyryk Aug 04, 2012, 04:53 PM 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:for i, beliefID in ipairs(Game.GetBeliefsInReligion(eReligion)) do
print beliefID
endThis 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.
FramedArchitect Aug 20, 2012, 10:02 AM Deleted
Pazyryk Aug 20, 2012, 03:44 PM 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).
FramedArchitect Aug 25, 2012, 10:15 PM Deleted
Pazyryk Aug 27, 2012, 06:52 PM for an OrPrereqPolicy column:
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.
Ethidum Aug 29, 2012, 07:51 AM 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
FramedArchitect Aug 30, 2012, 07:08 PM Deleted
FramedArchitect Aug 30, 2012, 07:25 PM Deleted
Pazyryk Aug 31, 2012, 02:48 PM 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:
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.
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).
xxhe Sep 04, 2012, 12:41 PM 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:
<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:
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 );
Pazyryk Sep 04, 2012, 03:24 PM Use 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: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.
xxhe Sep 04, 2012, 08:13 PM 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:
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 );
Pazyryk Sep 05, 2012, 04:44 PM 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?
xxhe Sep 05, 2012, 05:09 PM 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:
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 );
FramedArchitect Sep 26, 2012, 05:03 PM Deleted
espence Oct 30, 2012, 01:24 PM 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:-
http://i50.tinypic.com/t6frll.jpg
Lua:-
http://i50.tinypic.com/24ysaoo.jpg
XML:-
http://i48.tinypic.com/zwfbmc.jpg
Actions:-
http://i49.tinypic.com/35c5160.jpg
I am using Gods & Kings version 1.0.1.705.
Thanks in advance.
PawelS Oct 30, 2012, 01:37 PM Did you add your Lua file to Content?
espence Oct 30, 2012, 03:24 PM 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:-
http://i50.tinypic.com/nfs65k.jpg
I'm guessing the type is wrong but I'm not sure.
FramedArchitect Oct 31, 2012, 12:51 PM Deleted
Pazyryk Nov 01, 2012, 08:17 AM 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.
espence Nov 02, 2012, 07:30 AM 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.
Drawmeus Nov 15, 2012, 06:39 PM 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.
Pazyryk Nov 16, 2012, 07:08 AM @Drawmeus, you should bookmark the civfanatics modding wiki (http://modiki.civfanatics.com/index.php/Lua_and_UI_Reference). It has all of the existing GameEvents. (I'll update the OP.)
Drawmeus Nov 16, 2012, 08:00 AM @Drawmeus, you should bookmark the civfanatics modding wiki (http://modiki.civfanatics.com/index.php/Lua_and_UI_Reference). 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.
Irkalla Nov 25, 2012, 02:10 AM 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?
FramedArchitect Dec 06, 2012, 09:03 PM Deleted
espence Jan 28, 2013, 04:53 PM 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.
keirathi Jan 28, 2013, 05:10 PM 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.
FramedArchitect Jan 28, 2013, 07:03 PM Deleted
espence Jan 30, 2013, 10:47 AM Thanks again FramedArchitect, this works perfectly. I have now uploaded my mod. If anyone wants to check it out you can download it here (http://forums.civfanatics.com/showthread.php?t=487236).
FramedArchitect Feb 03, 2013, 10:04 AM Thanks again FramedArchitect, this works perfectly. I have now uploaded my mod. If anyone wants to check it out you can download it here (http://forums.civfanatics.com/showthread.php?t=487236).
Sure no problem. Glad it worked out. I so rarely choose piety branch, maybe this will make it seem worthwhile!
|
|