Retrieving Data

daviiadams

Prince
Joined
Jul 7, 2011
Messages
369
Location
London
Is it possible to retieve any data through Lua (even if it's inserted via SQL for a mod), or can you only return results that the game itself is compiling?

Say I add something that accumilates via buildings - like culture, gold, or tech progress does - but isn't in the vanilla game, can I retrieve the sum of that entity being produced each turn?

I'm working on something and can do everything but retrieve/display the data, but wonder if I'm wasting time if I can't tell the game to add it up?
 
If you add a table (or table column to existing table) as an OnModActivated, then you can get these values exactly as you do for base tables. That is:

for indexed table:
local value = GameInfo[MyTable][ID# or Type string][column]
local row = GameInfo[MyTable][ID# or Type string]

for non-indexed table you can get each row from an iterator function:
for row in GameInfo[MyTable]() do...

Variables in Lua hold their value (at the level defined) until you change it or exit the game. So if you set "local countThis = 0" in a Lua file, then that number can be modified by functions in that file and these values will be stable and maintained over turns. If you want that value to be "saved" and reloaded on game exit/reload, then you will need to use either SaveUtils or my own TableSaverLoader.
 
If you add a table (or table column to existing table) as an OnModActivated, then you can get these values exactly as you do for base tables. That is:

for indexed table:
local value = GameInfo[MyTable][ID# or Type string][column]
local row = GameInfo[MyTable][ID# or Type string]

for non-indexed table you can get each row from an iterator function:
for row in GameInfo[MyTable]() do...

Variables in Lua hold their value (at the level defined) until you change it or exit the game. So if you set "local countThis = 0" in a Lua file, then that number can be modified by functions in that file and these values will be stable and maintained over turns. If you want that value to be "saved" and reloaded on game exit/reload, then you will need to use either SaveUtils or my own TableSaverLoader.

I have to admit that Lua looks like complete gibberish to me and have thus far been reliant on taking existing code and slipping in my bits as necessary :blush:

I take it that if I'm inserting a row into an existing table that becomes:

GameInfo.Buildings[MyRow]()

?
 
One thing to know in Lua is that these 4 are equivalent:

GameInfo.Buildings.BUILDING_TEMPLE.Cost
GameInfo["Buildings"].BUILDING_TEMPLE.Cost
GameInfo["Buildings"]["BUILDING_TEMPLE"]["Cost"]
local mytable = "Buildings"
GameInfo[mytable].BUILDING_TEMPLE.Cost

All of these evaluate to a single value, the Cost of the temple building. Lua is weird in that you can have integers or text (or almost anything) as keys to tables, and GameInfo lets you use either the Type field ("BUILDING_TEMPLE") or the ID (an integer) in that second index position. So, let's say the ID for temple is 17 (I just made that up). You could then get the same value with:

GameInfo.Buildings[17].Cost
Note that GameInfo.Buildings.17.Cost is not correct because it is really shorthand for GameInfo.Buildings["17"].Cost

I could also get the whole table for Temple like this:

local temple = GameInfo.Buildings.BUILDING_TEMPLE

temple is now a table; we can get the Cost of temple now using temple.Cost

Putting "()" after something makes Lua try to interpret it as a function. This won't work unless someone has set it up to work as a function (using metatables, but you don't need to worry about how to do that). Firaxus has made GameInfo work so that GameInfo.Buildings() acts as an iterator function. You can do this on any table added by Firaxis or you (as an OnModActivated table). Basically, you are only ever going to see this as part of a "for" loop when you want to iterate through a table and get each row to process in your loop.

So all of my answers above are about getting values from tables with Lua (your OP).

But now you are asking about adding values to Database tables via Lua. You definitely should not be trying to change tables like Buildings (or any new tables that you add by OnModActivated) using Lua. It's not a stupid question -- I was asking the same thing 9 months ago -- but it is a totally misguided question. Those tables added via XML or SQL are "fixed" and define what Buildings are in a sort of immutable way. Don't even think of trying to change the DB values (once a game is running). Now, there are many Lua functions that can change things on the fly during game session, and these are the object functions you find at the wiki for units, plots, and so on. You can change a lot this way but not everything. In general, your code will need to "remember" your adjustment from the initial table value, and apply that value during game init as the game is loaded (or else apply it each turn based on some info that you can calculate from Lua). The advanced mods do this kind of thing all the time, but it takes a bit of effort to learn how. But just forget about changing the actual DB value during a game by Lua -- it doesn't work that way.
 
One thing to know in Lua is that these 4 are equivalent:

GameInfo.Buildings.BUILDING_TEMPLE.Cost
GameInfo["Buildings"].BUILDING_TEMPLE.Cost
GameInfo["Buildings"]["BUILDING_TEMPLE"]["Cost"]
local mytable = "Buildings"
GameInfo[mytable].BUILDING_TEMPLE.Cost

All of these evaluate to a single value, the Cost of the temple building. Lua is weird in that you can have integers or text (or almost anything) as keys to tables, and GameInfo lets you use either the Type field ("BUILDING_TEMPLE") or the ID (an integer) in that second index position. So, let's say the ID for temple is 17 (I just made that up). You could then get the same value with:

GameInfo.Buildings[17].Cost
Note that GameInfo.Buildings.17.Cost is not correct because it is really shorthand for GameInfo.Buildings["17"].Cost

I could also get the whole table for Temple like this:

local temple = GameInfo.Buildings.BUILDING_TEMPLE

temple is now a table; we can get the Cost of temple now using temple.Cost

Putting "()" after something makes Lua try to interpret it as a function. This won't work unless someone has set it up to work as a function (using metatables, but you don't need to worry about how to do that). Firaxus has made GameInfo work so that GameInfo.Buildings() acts as an iterator function. You can do this on any table added by Firaxis or you (as an OnModActivated table). Basically, you are only ever going to see this as part of a "for" loop when you want to iterate through a table and get each row to process in your loop.

So all of my answers above are about getting values from tables with Lua (your OP).

But now you are asking about adding values to Database tables via Lua. You definitely should not be trying to change tables like Buildings (or any new tables that you add by OnModActivated) using Lua. It's not a stupid question -- I was asking the same thing 9 months ago -- but it is a totally misguided question. Those tables added via XML or SQL are "fixed" and define what Buildings are in a sort of immutable way. Don't even think of trying to change the DB values. Now, there are many Lua functions that can change things on the fly during game session, and these are the object functions you find at the wiki for units, plots, and so on. You can change a lot this way but not everything. In general, your code will need to "remember" your adjustment from the initial table value, and apply that value during game init as the game is loaded (or else apply it each turn based on some info that you can calculate from Lua). The advanced mods do this kind of thing all the time, but it takes a bit of effort to learn how. But just forget about changing the actual DB value during a game by Lua -- it doesn't work that way.

I should've said in the OP that this would be for unique buildings involved in the mod and not the vanilla game, though I'm guessing that wouldn't change the outcome(?)

In fact, I think I've made a pig's ear of asking the question - the insert would actually be a column, with a default of zero and the unique buildings their individual values.

What I was looking to do, was to add an attribute called "Reform" and have the game tally up the sum amount of Reform produced by the player each turn.

So, I setup the SQL with the mod to insert a column into the Buildings table as mentioned above and amended my unique buildings to have values associated so they didn't default to zero.

Then, obviously, I was trying to figure out how to retrieve the total amount each turn, using the maintenance/culture/tech progress/food etc standards that are already there in Lua...which is the part where everything starts to become difficult with my total lack of Lua expertise.

From what you've said, I get the feeling that I could retrieve the Reform value of a single building, but not the sum total of Reform across a number of buildings the player has built(?)

Or have I completely missed the point? :blush:
 
If you introduce a new column in Buildings with some value (for each building), you can retrieve it, sum it, multiply it, exponent it, factorize it, do a Fourier transform, make an end of the world prediction from it ... you just can't change it.

Maybe this is what you need:

Code:
local totalReform = 0
for city in Cities[iPlayer] do
	for building in GameInfo.Buildings() do
		if building.Reform and city:IsHasBuilding(building.ID) then
			totalReform = totalReform + building.Reform 
		end
	end
end

Note: This code will run a tiny bit faster if you leave default for reform as NULL rather than zero.

Check my functions with the Wiki. I can never remember whether it is city:IsHasBuilding or city:HasBuilding...
 
If you introduce a new column in Buildings with some value (for each building), you can retrieve it, sum it, multiply it, exponent it, factorize it, do a Fourier transform, make an end of the world prediction from it ... you just can't change it.

Maybe this is what you need:

Code:
local totalReform = 0
for city in Cities[iPlayer] do
	for building in GameInfo.Buildings() do
		if building.Reform and city:IsHasBuilding(building.ID) then
			totalReform = totalReform + building.Reform 
		end
	end
end

Note: This code will run a tiny bit faster if you leave default for reform as NULL rather than zero.

Check my functions with the Wiki. I can never remember whether it is city:IsHasBuilding or city:HasBuilding...

Thanks for your help on this. I keep saying that I will sit down and learn this stuff properly, but find it hard going.

Will make the change to NULL and give it a go :)
 
Will make the change to NULL and give it a go :)

Double check in example files to see if NULL is the right entry for XML. That's the right thing for SQL (NULL without quotes) but I've largely forgotten how to add/modify tables in XML. In Lua this becomes nil.
 
Double check in example files to see if NULL is the right entry for XML. That's the right thing for SQL (NULL without quotes) but I've largely forgotten how to add/modify tables in XML. In Lua this becomes nil.

This appears to be the general case in the xml columns, in Buildings at least:

Type > integer > integer

Type > boolean > false

Type > text > NULL

Have left default as zero on that score.

Program appears happy with the code you suggested, not reporting any errors, but not having any luck finding out if it's working.

print(totalReform) doesn't show anything, but I'm only guessing that to be one way to show the result, in Tuner anyway.

?
 
Back
Top Bottom