Best way to limit lua code copied in multiple mods to only execute once?

Machiavelli24

Mod creator
Joined
May 9, 2012
Messages
818
I have some lua code that I want to be able to copy into multiple different mods. However, I only want the code to execute once even when multiple mods containing the code are active.

For example, say I have a lua function (EveryTurnThing) that is added to GameEvents.PlayerDoTurn. Mod A contains EveryTurnThing.lua and Mod B also contains EveryTurnThing.lua. If an end-user is playing with both Mod A and Mod B than EveryTurnThing will fire twice ever GameEvents.PlayerDoTurn. I want to make it fire only once.

Things I've tried that didn't work
1) Only adding if GameEvents.PlayerDoTurn.Count(EveryTurnThing) is 0.
2) Doing GameEvents.PlayerDoTurn.Remove(EveryTurnThing) before adding.
3) Setting VFS to true (the files are still loaded multiple times even if they all overwrite eachother)
4) Creating an "IsInitialized" variable in the database (using InsertOrAbort) and then updating the value with DB.Query("UPDATE stuff...). The Query didn't change the value even though I put it in an empty for loop.
 
1, 2 and 3 won't work - the code will be executed by each mod as the Lua contexts are sandboxed from each other.

4 will work, but you'll need to use the Modding.OpenSaveData() database, not the core game one, and somehow remember (usually via the mod guids) which mod has the code running after a game save/load.

The other option is to use a "broadcast" approach using LuaEvents.

Broadcast a LuaEvent
If you get a reply, do nothing
If you don't get a reply, install a listener on the broadcast event that sends a reply (this is what stops other copies of the code from running) and also install your PlayerDoTurn listener
 
If I understand the broadcast approach right, it would be something like:

Code:
function IsInitialized()
    return true;
end

if(LuaEvents.MyPerTurnFunc_Initialized() == nil) then
    LuaEvents.MyPerTurnFunc_Initialized.Add(IsInitialized);

    <put lua code here, including GameEvents.PlayerDoTurn.Add(stuff)>
end
 
With respect to the broadcast approach. Given that each mod is sandboxed how do I send/detect the reply? I can see the println but I can't seem to change a variable via side effects or grab the return value.

Code:
function IsInitialized()
	[COLOR="DarkOrange"]-- Send message[/COLOR]
	print("Is initialized Mod A fired");
end

LuaEvents.MyEvent_IsInitialized();
if([COLOR="DarkOrange"]-- Detect message[/COLOR]) then
	LuaEvents.MyEvent_IsInitialized.Add(IsInitialized);
	LuaEvents.MyEvent.Add(MyCode);
end
 
The MapModData table is available from different mods, isn't it? I use it to communicate between Lua states (but everything I do is in one big mod). But aren't different mods just different states as far as Lua is concerned?
 
Pass a table in the event call, put the return value into it, then check for the key being in the table

Code:
-- Broadcast to see if anybody else is running this code
local retVal = {}
LuaEvent.IsThisAlreadyRunning(retVal)


if (!retVal.imHere) then
  -- We are the first, so make sure we now reply
  LuaEvent.IsThisAlreadyRunning.Add(function (retVal) retVal.imHere = true; end)

  -- Do your own stuff
end
 
Back
Top Bottom