alternatives to InGame.xml

Joined
Jul 31, 2002
Messages
705
edit: see post #4 for solutions


has anyone tried including lua context lines in the other context xml files?

for example, civ5\assets\UI\InGame\LeaderHead\DiscussLeader.xml, a really small file that seems to deal with the first diplo discussion window (discuss, trade, exit, etc), and putting a luacontext line there loads up a lua file just fine, as opposed to ingame, after looking at it some more, seems to have some important stuff in that could get updated or modified

also anyone know any other mod action controls asides from onmodactivated / updatedatabase? i noticed packaged lua files are automatically included in the main state IncludeFileList table; halfway there from being loaded up as a state for the game, so there's got to be an easier way to have them load outside of the xml <Context>.

sql doesnt seem to work here, and i have no idea where context even gets loaded. just about each vanilla lua file has one, but replicating that with unique named files doesnt seem to do the trick
 
There's a super-global by the name of ContextPtr. It keeps track of which built-in lua file is being executed and links it to an xml file by the same name, operating on LuaContexts and generating instances according to the xml. If you want to change that default behavior, then you'll likely need to rewrite the ContextPtr class. That could requires access to the DLLs, I don't know.
 
that's what im trying now, the ContextPtr:LoadNewContext(luafile). i noticed the info addict mod was loading a lua file via an entrypoint, which is then caught by vanilla files using Modding.GetActivatedModEntryPoints and then loaded into the ContextPtr

via the console i can use ContextPtr to add as much as i want, but using the entrypoint it looks like I'm limited to one lua file per mod
 
many crashes and tests later i finally found a working method :D:D:D

edit: after testing and working out a somewhat convoluted process, i ran across robk's awesome Info Addict that also has been using entrypoints for lua, but without any of the problems i kept running into! if only i had looked at it earlier i would of probably saved myself a lot of headache :cry:

Howto:

instead of using a civ5 context file, like InGame.xml/DiscussLeader.xml/etc (which overrides the vanilla one, which can be updated by firaxis, and which requires merging with other mods using the same file), you just have to use one of the known available EntryPointMethods

In modbuddy:

  • put all your lua files requiring loading into a lua folder of your mod (./lua/)
  • right click your project and go to properties then the contents tab
  • for Type (the entry point) enter either "InGameUIAddin", "CityViewUIAddin" or "DiplomacyUIAddin" (without the quotes and any of them works as they all do the same thing)
  • for name and description enter whatever you want
  • for filename enter your lua filename

once packaged, the modinfo file will have something like this:

Code:
  <EntryPoints>
    <EntryPoint type="DiplomacyUIAddin" file="icsai.lua">
      <Name>ICSing AI</Name>
      <Description>ICSing AI</Description>
    </EntryPoint>
  </EntryPoints>

Then you're set! You can activate all the mods that use this without having to worry about merging the xml context file


Notes:

Since the lua is no longer being loaded out of lua context files (they load just a little bit after) the event SequenceGameInitComplete doesn't seem possible to catch anymore. If more than one lua file has a function set to start on this event, civ5 will crash. there's nothing as to why in the logs and it's possible more that one event is affected like this (although I run a lot of them and gameinit is it so far)

A good use for that event was to catch a newly started or loaded game and set up variables, load data, etc. This can still be done by just adding the script elements to the "top level" part of the logic

For example if I wanted to replicate game starts I'd write something like this:

Code:
-- first let the game read in objects
local a = 0;

function init ()
    print( "Hello World!" );
end

-- now that those are processed, the script can use those 
if ( a == 0 ) then
    init();
end



More info:

To see how "InGameUIAddin", "CityViewUIAddin" and "DiplomacyUIAddin" are treated by the vanilla game refer to InGame.lua, CityView.lua and LeaderHeadRoot.lua. They use the Modding class functions to get your file and load it up with

ContextPtr:LoadNewContext(filename)

you can also use this function manually to add new lua states via the console,or use it in scripts but from my experience (probably because the init events) it crashes often at game loading


this alternative to using the vanilla context xml just keeps on getting better :)

it would be nice if eventually we can load up custom lua files and have them treated as vanilla ones, so real time changes are immediately reflected in game. theres 2 globals with file lists and game paths that almost seemed to offer hints for that:

IncludeFileList table and the package.path string, but so far nothing has come out of those

there is however a "Custom" entry point method from CustomMod.lua:

Enter "Custom" in modbuddy for the entrypoint type, then when you setup a game you chose "Custom Game", and what happens next is all the preloaded context is seemingly cleared out of memory and only your lua files are left, loaded right there and then. although without supporting menu scripts and such there isn't much you can do except exit the game :)
 
I'll need a little time to digest all of this, but just off the cuff, won't execution order be an issue? The LuaContext entries in the InGame.xml determine the order lua files are executed. Anything added as a UIAddin, instead of as a LuaContext, is executed last and their order is determined by the order they appear in the modinfo file. Correct?
 
no the UIAddin method is just a custom name (custom method) the devs put in

its loaded as context. they do load in order of appearance, but every lua is independant anyway
 
I'm not sure what you mean, but if you look in the InGame.lua file you'll find this at the very bottom.

Spoiler :
Code:
---------------------------------------------------------------------------------------
-- Support for Modded Add-in UI's
---------------------------------------------------------------------------------------
g_uiAddins = {};
for addin in Modding.GetActivatedModEntryPoints("InGameUIAddin") do
	local addinFile = addin.File;
	
	-- Get the absolute path and filename without extension.
	local extension = Path.GetExtension(addinFile);
	local path = string.sub(addinFile, 1, #addinFile - #extension);
	
	table.insert(g_uiAddins, ContextPtr:LoadNewContext(path));
end
Maybe I've been reading this wrong but I thought this meant they get executed last and all of my tests have supported that assumption.

I must be misunderstanding something.
 
Oh I see. You assume order of lua contexts don't matter. Currently I guess that's true. But not for long. I'll be releasing a lua very soon that allows all lua states/contexts to share the same globals in real time. Thus execution order becomes very important.

With luck, I'll post it tonight and put a link here for consideration.
 
no im not assuming anything :)

the order is always top to bottom when it reads in xml and lua, not to be confused with the method the game applies order of importance to loading a mod

did you figure out where the other lua tables are stored in _G?
 
top to bottom as in first line then second line, and so on. making a custom <context></context> xml with a simple print warning in the luas shows the order

_G is supposed to be the lua top level namespace/global, everything else is under it
 
Okay, that's what I thought. I wonder if it's possible to alter the order within the lua. In any event, here is my shared globals file. You can find 2 demonstration mods in the in-game mod screen by the names Share Test (1 of 2) -- Demo and Share Test (2 of 2) -- Demo. They are intended to be run concurrently and demonstrate a shared object reference and a shared function reference via lua console output. I have a thread for it here: http://forums.civfanatics.com/showthread.php?t=398814

My concern is that ShareData.lua needs to be run before all others so that the LuaEvents exist before all others execute. This requires I use InGame.xml.
 
This game has a horrible lack of load order flexibility. :badcomp:

Great solution to one merging problem, got it working flawlessly. Is there a way to apply this to the merging issue of NotificationPanel.xml?
 
yes, throw some context XML into a xml sub directory, make sure it has the same name

ie, test.lua and test.xml

and the game will read in the context file. it seems to work as intended: i had a <luacontext> entry and the game loaded the extra lua file, so I'm sure you can add in <instance> objects and the like
 
Nice work, fully digested now. :)

At first, because you said you can only add one entry point this way, I took that to mean you were limited to a single lua and single xml. But now I see there is in fact no limit to contexts and sub contexts. As example, and to help others as slow as I to digest this, I created the following chain. Just add Test.lua as an InGameUIAddin under the content tab in ModBuddy.

Test.lua
Spoiler :
Code:
print( "Test.lua" );

Test.xml
Spoiler :
Code:
<?xml version="1.0" encoding="utf-8"?>
<Context Name="Test" >
	<LuaContext FileName="Component" ID="Component" Hidden="True" />
</Context>

Component.lua
Spoiler :
Code:
print( "Component.lua" );

function exec()
	print( "exec()" );
end
Events.ActivePlayerTurnStart.Add( exec );

Component.xml
Spoiler :
Code:
<?xml version="1.0" encoding="utf-8"?>
<Context Name="Component" >
	<LuaContext FileName="SubComponent" ID="SubComponent" Hidden="True" />
</Context>

SubComponent.lua
Spoiler :
Code:
print( "SubComponent.lua" );

function exec_sub()
	print( "exec_sub()" );
end
Events.ActivePlayerTurnStart.Add( exec_sub );

Output: (after first turn taken)
Spoiler :
Code:
SubComponent: SubComponent.lua
Component: Component.lua
Test: Test.lua
SubComponent: exec_sub()
Component: exec()

If the modding community can manage to set a standard base mod lua context, then we could all mod that file instead of InGame. It still requires some merging, but at least we would be safer from Civ updates. Maybe the base lua file could be used to control execution order of sub contexts? That could provide a great deal more modular control of components.
 
Hmm... I must of misunderstood you about single entry point all together. I just tested this with two entry points and they both work, both chained. Both InGameUIAddins.

Any news on using Associations in ModdBuddy? It could completely resolve the issue of execution order in light of this. Specifically, SaveUtils needs to add ShareData to the references list, but it's all disabled.
 
it seems like no limit. at first i had it add lua located in the root directory and this caused crashes, and also when some lua had the gamesequenceinit event it would cause more crashes. switching it around though doesnt crash and that's a good thing

no idea on associations can't get those fields edited in modbuddy. maybe if there was some examples from firaxis
 
I think it's intentionality disabled, but maybe I'm wrong.

To be clear, the problem I have with adding everything as an InGameUIAddin is the only means for controlling execution order is the order the entry points appear in the modinfo. That's fine when running one mod or making a composite mod, but when running two separate InGameUIAddin mods, execution order becomes inconsistent and unpredictable. I've watched as such files will load and execute in one order one time and in another order the next. But if I could add ShareData to the references list, then adding everything as UIAddins would work just fine.
 
Top Bottom