But as a programmer, I have to ask: How the hell something that deals with iterating over plots breaks unit abilities? How?
I can't remember exactly what DarkScythe managed to find out, but at the very least, if you have two lua files with "PlotIterators" anywhere in the filename, they'll overwrite each other.
There are, unfortunately, multiple issues involved here, but
most of the fault lies with Firaxis.
To start off, Firaxis gives us, instead of Lua's own file-inclusion methods (I
think they're disabled, but I never double-checked this,) Firaxis has us use their own method called
include().
When we call
include(), it writes whatever is in that file into the context that it was called in, since each mod's Lua scripts are in their own context.
This works in tandem with Firaxis' VFS system, which seems to overwrite files if they are of the same name. This in itself is not strange -- if you dropped two files called
test.txt into the same folder in Windows, Windows would ask if you wanted to overwrite the previous file. VFS does not automatically rename files on-the-fly to avoid such conflicts. As such, effectively only one copy of any particular filename will be able to exist in VFS at any given time. (I am making some assumptions here, as I've not delved deeply into the technical details of how VFS is implemented. If I have made any mistakes here, do let me know.)
However, if you look at it this way, the author of RAS actually
did try to avoid conflict, by renaming his PlotIterators file. Following his edits of whoward's original code, he saved the file as
GTAS_PlotIterators.lua which is different from
PlotIterators.lua -- the latter being a sort of default name that everyone who uses whoward's code without modification tends to use. This
should mean that
in theory both versions exist in VFS at the same time.
So, what's the problem?
include()!
Some people may notice that, for example,
include(PlotIterators) and
include(PlotIterators.lua) will both work fine. (Let's set aside conflicts for the time being.) This is because of the way Firaxis designed their
include() to work.
It doesn't search for an exact filename match!
It searches for a partial match using
string.find() -- that's why those two different includes work to pull up the same file.
PlotIterators.lua contains the phrase
PlotIterators and becomes a valid match for
include() to use.
I first
ran into this problem with a conflict with
TableSaverLoader and one of ViceVirtuoso's Civs running an older version of TSL than my mod. As
whoward responded here, it's intentional on Firaxis' part. This was the reason that Pazyryk changed the filename of TableSaverLoader to include the version number after my report of the issue.
In this particular case,
GTAS_PlotIterators.lua contains the phrase
PlotIterators.lua and becomes a valid match for what the game assumes we're looking for, and writes that code instead of our
original PlotIterators.lua!
Of course, not all the blame is on Firaxis -- If this was all that was happening, it
should still be fine. However, recall
why the file was renamed in the first place -- RAS' author modified it!
Most of our Civs who run into such conflicts rely on one major function --
PlotAreaSpiralIterator() which RAS' author has modified.
Again, though, he
tried to avoid conflict by renaming his modified function
GTAS_PlotAreaSpiralIterator(). Unfortunately, this is also exactly why it broke everything. In doing so, he essentially
removed the stock PlotAreaSpiralIterator() function.
Unfortunately, since
include() decided to use his version of the file, whenever our mods attempt to use
PlotAreaSpiraliterator() they fail,
because it doesn't exist!
For the time being, our solution is to completely rename our PlotIterators files to avoid such conflicts in the first place, but at the expense of having multiple versions of the
exact same file in VFS. Alternatively, as I've seen ViceVirtuoso do with his last update to his Civs, he can attempt to
re-replace
GTAS_PlotIterators.lua with a version that contains the
original PlotAreaSpiralIterator() function alongside RAS' modified one. They have different function names, so they have no problem existing together in this way.
However, I'm not entirely sure this would be a solution that works 100% of the time, as I
believe it relies on mod loading order to ensure that RAS' version gets replaced. I suppose one can set RAS to be a referenced mod, but I am not sure.
Anyway, lengthy explanation, but that's what's happening behind-the-scenes, and the headaches that we have to deal with so people can simply enjoy playing with our mods.
Hope that helped.