The short answer: It's a bit convoluted.
As far as I'm aware, the Player is the only person to ever buy plots with Gold (I have no way of knowing if the AI ever does so, but at least I've never seen them suddenly own 5 tiles to cut me off of resources.)
You can check my Holo mod's Lua; I handled this plot-buying-detection handler with my
CityInfoPlotUpdate() function. It is tied to
Events.SerialEventCityInfoDirty() which fires every time the player views the City Info screen and something changes in there. As part of its logic, it caches the Player's Gold reserves, as well as whether or not they've visited the "Purchase Plot" screen by tracking the interface mode:
Code:
if UI.GetInterfaceMode() == InterfaceModeTypes.INTERFACEMODE_PURCHASE_PLOT then
Afterward, it checks to see whether or not the Player's Gold reserves have dropped or not, which would be a decent indication that the Player just bought a plot.
However, this method is not foolproof, as it is possible for it to be 'tricked' by users entering the Plot Purchase screen, and then buying something else.
Having said all that, the function in the public release of Holo (v2 currently) is outdated, as that code was written before the latest patch introduced the
CityBoughtPlot GameEvent. I've since rewritten that code and function, although the basic logic hasn't changed very much for me. It is still pending testing in my Beta branch of development, though.
Either way, the core of the function is still the same; the only difference is that
CityBoughtPlot, even if broken, does the heavy lifting of actually detecting when a plot has been purchased for you. It doesn't know
which plot it is, though, which puts it in the same position as my current function, so it's simply a matter of migrating the logic over. The main benefit is that I would no longer have to track and cache the Player's Gold reserves and InterfaceMode changes.
My method also relies heavily on data persistence, because I find no completely reliable way to determine plot status from within the game itself. The method LeeS proposed is a very reasonable one which does not require the use of data persistence. However, the main problem I have with it is that (if
GetOwnershipDuration works the way I think it does) I can't think of any way it can distinguish between plots which you have already calculated or not.
Because you have no way of knowing which plot was just bought, you have to run a loop to scan all the plots around the City to find plots currently owned. The above method may return to you the newest plots (those with an ownership duration of zero, or something) but let's say that in one given turn, your City's borders expand naturally, claiming one tile, and then you go and
purchase another plot or two?
Even if you limit the function to firing when
bGold returned true, how would it work out which of the three new plots have had effects applied to them, and which ones haven't? At worst, one plot may have affects applied to it, or at least be counted three times.
With that said, in terms of logic, once you can persist the data about each plot, it's not entirely too difficult.
Basically, on
CityBoughtPlot, when
bGold returns true, run a plot scan around the City for all plots owned by the Player, and of interest to you. Once you have such plots, you check whether or not:
- The plot exists in the table persisted through game saves (for example, via TableSaverLoader)
- The plot has already been accounted for, for whatever functions you need to run
If they
do exist, then either do nothing, or whatever else with this "old" plot. If it is a new plot, then run your functions, and add an entry into the table stating that it has been accounted for. This additionally prevents plots which "overlap" other Cities from firing twice (once for each City.)
If you do anything normally-irreversible to the plot, you'll also want to set up a secondary function to scan this table every turn to prune it of plots which are no longer owned by the Player, or if the Player has lost control of this plot, and then to run functions to reverse any bonus.
Holo does this with Wheat plots, because her code directly modifies the plot's yields, and she needs to remember which plots to remove the yields for if she loses it for any reason.