Lua not accessing modded database?

Thalassicus

Bytes and Nibblers
Joined
Nov 9, 2005
Messages
11,057
Location
Texas
In a sql file I have:

Code:
ALTER TABLE Worlds ADD ResourceMod integer default 100;
UPDATE Worlds SET ResourceMod = 100;

This column shows up correctly when I check Civ5DebugDatabase.db after loading my mod. However, this statement in AssignStartingPlots.lua:

Code:
print("ResourceMod = " .. tostring(GameInfo.Worlds.WORLDSIZE_DUEL.ResourceMod))

gives the error:

Code:
Cannot find key - ResourceMod

What might be wrong?
 
This is a really baffling problem. :hammer2:

My InfoTooltipInclude and CEAI_Events lua files were spitting out similar errors. On a hunch, I deleted civ's cache folder and restarted the game. InfoTooltipInclude no longer errors! But CEAI_Events still does. I can't find a consistent pattern. The database shows everything correctly in SQLiteSpy. The files just can't access it for some weird reason. These files worked perfectly before BNW. It's very puzzling!

I'm starting to think it's a problem with the way BNW caches data...
 
Hmm... thinking about this more. :think:

My ModTools.lua initializes some variables, then includes my other tool libraries:

Code:
-- ModTools.lua

print("ModTools.lua")

if not Cep then
    Cep = {}
end
for row in GameInfo.Cep() do
    Cep[row.Type] = row.Value
end

include("MT_LuaEvents.lua")

I include this in core files I override like InfoTooltipInclude so I can use my tools.

Code:
-- InfoTooltipInclude.lua
-- Help text for Info Objects (Units, Buildings, etc.)

include("ModTools.lua")

However, I discovered a few years ago the game includes files at a point when it can't actually execute lua statements.

Code:
Runtime Error: ModTools.lua:11: attempt to call global 'print' (a nil value)
Runtime Error: ModTools.lua:16: attempt to index global 'GameInfo' (a nil value)

I therefore added a check to my files to wait until everything works before including it.

Code:
-- ModTools.lua

if Game == nil then
    return
end

print("ModTools.lua")

This solution worked until BNW. It appears this does not always work anymore. With the "return" present, if the file is in the game cache, the file cannot access the sqlite database. This happens if I reload or regenerate a map without exiting to the main menu. If I remove the "return" the old problem appears, and it states all lua tables are nil. My other files included later as content with InGameUIAddin work okay. It's only when I need to override a vanilla file with "include in VFS=true" that I encounter the problem.

If you override core lua files like InfoTooltipInclude, how do you initialize data? I'm stumped. :think:
 
I think I just figured out what's going on. The game must cache these lua files before it loads the database, when we first click "next" on the mods screen. It's the only explanation that makes sense. I don't know why I didn't see it before... it seems obvious now. I had assumed the order always goes database->lua... but when we include files in the VFS, it must load those before the database.

The question is, then, how to access the database in files that load before the database... :think:
 
I think I just figured out what's going on. The game must cache these lua files before it loads the database, when we first click "next" on the mods screen. It's the only explanation that makes sense. I don't know why I didn't see it before... it seems obvious now. I had assumed the order always goes database->lua... but when we include files in the VFS, it must load those before the database.

The question is, then, how to access the database in files that load before the database... :think:

I don't understand. I access the database with my LUA files all the time.

-bbutttt-, and a big exception here, my LUA files are popups, so they are run, but contained in functions that are called after the game has loaded.
 
I'm starting to figure it out. If a lua file is loaded into the VFS, that happens before it connects to the database. I encountered this problem a year ago. My solution at the time was something like this at the top of each file:

if not Game then
return
end

This worked for me in the past. The game appears to load VFS files at the Mods menu before it loads the database. It then loads the file a second time later when we actually start a game. I think that second time no longer occurs... so the only time the VFS file loads is before we can access the database.

It's also connected to the cache somehow. My file often works the first time I start a game... but if I exit and start a new one, or reload, the second time fails with error messages.


Edit:

It appears this might be a problem with building projects in ModBuddy after BNW. I noticed ModBuddy project building fails a lot more often in BWN. It often complains it can't access the files it needs to copy into the Mods folder. Even if it does build the project, any VFS-included files can't access the database afterwards. If I restart the game, or simply edit the files in-place in the Mods folder instead of building them from ModBuddy, the problems don't seem to happen.
 
It appears this is a problem with building projects in ModBuddy after BNW. I noticed ModBuddy project building fails a lot more often in BWN. It often complains it can't access the files it needs to copy into the Mods folder. Even if it does build the project, any VFS-included files can't access the database afterwards. If I restart the game, or simply edit the files in-place in the Mods folder instead of building them from ModBuddy, the problems don't seem to happen.

This problem only occurs if the mod is currently active. To solve it, I just go to the main menu and build, and everything works fine.
 
I noticed the same thing, but then ran into this lua file problem. It seems like even going to the main menu doesn't completely solve the issue... BNW handles the database differently. I noticed it does the freezup "configuring game data" both on entering and exiting games now, unlike pre-BNW. Something changed that's breaking VFS files.
 
I figured it out! :dance:

There's two separate problems. The first problem is rebuilding a project in ModBuddy can mess up files we override by including in the virtual file system (VFS = true). Restarting the game or working directly in the Mods folder seem like good workarounds.

The second problem is VFS lua files set their GameInfo table before the program reads database tables used on the "modding game setup" screen. I created a simple project to test this.

Mod - General.sql
Code:
UPDATE Defines       SET Value             = 1 WHERE Name = 'MIN_CITY_RANGE';
UPDATE Units         SET Combat            = 1 WHERE Type = 'UNIT_WARRIOR';
UPDATE Worlds        SET NumNaturalWonders = 9 WHERE Type = 'WORLDSIZE_DUEL';
UPDATE HandicapInfos SET BarbCampGold      = 9 WHERE Type = 'HANDICAP_PRINCE';

Copy of InfoTooltipInclude.lua added to the mod, and (included in VFS):
Code:
-- UNIT
function GetHelpTextForUnit(iUnitID, bIncludeRequirementsInfo)
    print("MIN_CITY_RANGE    = " .. GameDefines.MIN_CITY_RANGE)
    print("Warrior Combat    = " .. GameInfo.Units.UNIT_WARRIOR.Combat)
    print("NumNaturalWonders = " .. GameInfo.Worlds.WORLDSIZE_DUEL.NumNaturalWonders)
    print("BarbCampGold      = " .. GameInfo.HandicapInfos.HANDICAP_PRINCE.BarbCampGold)

Lua.log report:

Code:
[174272.944] TechTree: MIN_CITY_RANGE    = 1
[174272.944] TechTree: Warrior Combat    = 1
[174272.944] TechTree: NumNaturalWonders = 2
[174272.944] TechTree: BarbCampGold      = 25

The tables I've found that do not work are Worlds, HandicapInfos, and GameSpeeds. These are all used for the game setup screen. A possible workaround is to hardcode a lua table with desired values, instead of reading in values from the database. I'm going to try this next.
 
Thanks for the explanation.

Here my solution to load the HandicapInfos database at the beginning of the game:
(can be done for others tables)

put this code near the beginning of your lua files than use your database.
Code:
local DB_HandicapInfos = {};
if Game then
	for realHandicap in DB.Query("SELECT * FROM HandicapInfos") do
		DB_HandicapInfos[realHandicap["ID"]] = {};
		for key,val in pairs(realHandicap) do 
			DB_HandicapInfos[realHandicap["ID"]][key] = val;
		end
	end
end

and now use DB_HandicapInfos[player:GetHandicapType()]
instead of GameInfo.HandicapInfos[player:GetHandicapType()]
 
Top Bottom