Anyone know a way to detect when a barb camp has been destroyed?

Machiavelli24

Mod creator
Joined
May 9, 2012
Messages
818
Anyone know a good way to detect when a barbarian camp has been destroyed? I don't think using SerialEventImprovementDestroyed will work because it looks like the two arguments it has are the x and y of the improvement, which isn't enough information to determine if it is a barb camp or something like a goodie hut.

Using SerialEventUnitDestroyed wouldn't work because if the camp was empty when it was destroyed (say because the barbarian in the camp was killed by a ranged attack) then it wouldn't detect correctly.
 
First of all, most of the Serial Events (like SerialEventImprovementDestroyed) only trigger if the active player can SEE the improvement in question at the time it's destroyed. If the improvement is destroyed off in the fog of war, the trigger won't happen until the active player moves a unit to where he can now see that hex. Now, depending on exactly what you need it for, that might be fine. If you're trying to give some sort of extra benefit on the capture of a barbarian camp, then you'll have problems, but if you just want to give the active player an extra little message when he takes out a camp, it's just fine.

As to your other complaint, you can always use the X and Y value to find out what's on a hex. First you use a function (GetPlotFromXY? I can't check at the moment, but it's something like that) to get a Plot structure for the appropriate hex, and then use Plots:GetImprovementType() to find out what improvement is on the hex. The problem is that if the serial event triggers AFTER the improvement is destroyed, then this won't do you much good. It's far more useful if you're going the other direction, triggering when an improvement is created.

The simple fact is, though, there are no good options for MANY of the things we want. Most of the serial events have UI-related issues, and the GameEvents (which are much more reliable to use) are very limited in number, with only a couple dozen made so far. So in a lot of cases, you either have to do without, or find some less direct method. For instance, there's no event that triggers when a Building is completed in a city. Mods like the heavily used "Building Resources" mod component get around this by creating an array storing exactly which buildings are completed in each city, and then at the start of each turn, checking the new values against what was stored on the previous turn. If the two lists are different, then a new building must have been completed; if it's of a certain type, then you can trigger a new effect. It's not instantaneous, since it won't trigger until the start of the next turn, and there are major issues when loading an in-progress savegame, but it does work fairly well.

So you could, at the start of each turn, loop over every hex on the map, recording the number and positions of those containing barbarian camps. If one is missing at the start of the next turn, then just check to see whose unit (if any) is sitting on the hex in question. Chances are, it's whoever defeated the camp. Obviously this adds significant overhead (scanning the entire map), and it's abuseable (kill whatever unit DID clear the camp and then move onto that hex before the next check), but it's about as close as you'll get until we get full DLL access.
 
If you're trying to give some sort of extra benefit on the capture of a barbarian camp, then you'll have problems...
That is what I'm trying to do unfortunately.

you could, at the start of each turn, loop over every hex on the map, recording the number and positions of those containing barbarian camps.
If there is an event that fires at the end of each player or AI turn it would be possible to check each stored camp location. Any missing ones can correctly be attributed to the player that just finished their turn.

But I was reluctant to use such an approach because of its performance cost. If that is the only option I would rather do without.
 
If there is an event that fires at the end of each player or AI turn

Unfortunately, there isn't. There's a serial event that triggers at the end of YOUR turn, and a far superior GameEvent that triggers at the start of each player's turn (including the AI). So in theory you can mimic an end-of-turn event by using the start-of-turn event and subtracting 1 from the ID of the current player, to see whose turn just ended. Unfortunately, many of the variables get reset or recalculated at the end of each player's turn, so you can't always use this method, and there are a few other minor timing issues.

But I was reluctant to use such an approach because of its performance cost. If that is the only option I would rather do without.

Unfortunately, yes, there's no easy way to avoid doing a full map scan to do what you've described. When dealing with temporary Improvements you can usually use Player:GetImprovementCount to see how many copies of a given improvement are within a player's borders; I use this mechanism in my own Terraforming logic, to know whether it's worth scanning the map this turn. But for obvious reasons, that doesn't help you here.
 
Back
Top Bottom