--
-- Scouting XP cache helpers
--
local modDB = Modding.OpenSaveData() -- using database causes a small lag everytime a recon discovers a tile first... we use databse only to not loose scoutingXP when loading a savegame...
local cachedScoutingXp = {}
[B]local updateneeded = 0[/B]
function GetKey(iPlayer, iUnit)
return string.format("SCOUTING_XP_%i_%i", iPlayer, iUnit)
end
function GetScoutingXp(iPlayer, iUnit)
if (cachedScoutingXp[iPlayer] == nil) then
cachedScoutingXp[iPlayer] = {}
end
if (cachedScoutingXp[iPlayer][iUnit] == nil) then
cachedScoutingXp[iPlayer][iUnit] = (modDB.GetValue(GetKey(iPlayer, iUnit)) or 0)
end
return cachedScoutingXp[iPlayer][iUnit]
end
function SetScoutingXp(iPlayer, iUnit, iXp, bCommit)
cachedScoutingXp[iPlayer][iUnit] = iXp
if (bCommit [B]and updateneeded==1[/B]) then
-- Calls to modDB are expensive,
-- so we save them all up to the movement onto the tile
-- as opposed to when every tile is revealed
modDB.SetValue(GetKey(iPlayer, iUnit), iXp)
[B]updateneeded = 0[/B]
end
end
function ChangeScoutingXp(iPlayer, iUnit, iXp)
[B]updateneeded = 1[/B]
SetScoutingXp(iPlayer, iUnit, GetScoutingXp(iPlayer, iUnit) + iXp, false)
end
function UpdateScoutingXp(iPlayer, iUnit)
local iScoutingXp = GetScoutingXp(iPlayer, iUnit)
if (iScoutingXp >= iScoutingXpAccumulated) then
local pUnit = Players[iPlayer]:GetUnitByID(iUnit)
local iRealXp = math.floor(iScoutingXp / iScoutingXpDivisor)
pUnit:ChangeExperience(math.max(0, math.min(iRealXp, iScoutingXpLimit - pUnit:GetExperience())))
if (pUnit:GetExperience() >= iScoutingXpLimit) then
pUnit:SetHasPromotion(iXpForScoutingPromotion, false)
iScoutingXp = 0
else
iScoutingXp = iScoutingXp - (iRealXp * iScoutingXpDivisor)
end
[B]updateneeded = 1[/B]
end
SetScoutingXp(iPlayer, iUnit, iScoutingXp, true)
end
function OnUnitSetXY(iPlayer, iUnit, iX, iY)
if (iPlayer >= 0 and iPlayer <= iMaxMajor) then
if (Players[iPlayer]:GetUnitByID(iUnit):IsHasPromotion(iXpForScoutingPromotion)) then
UpdateScoutingXp(iPlayer, iUnit)
end
end
end
GameEvents.UnitSetXY.Add(OnUnitSetXY)
function OnUnitPrekill(iPlayer, iUnit, _, _, _, bDelay, _)
if (not bDelay and GetScoutingXp(iPlayer, iUnit) ~= 0) then
[B]updateneeded = 1[/B]
SetScoutingXp(iPlayer, iUnit, 0, true)
end
end
GameEvents.UnitPrekill.Add(OnUnitPrekill)
--
-- Tile reveal event handlers
--
function OnTileRevealed(iPlotX, iPlotY, iTeam, iFromTeam, bFirst, iPlayer, iUnit)
if (bFirst and iPlayer >= 0 and iPlayer <= iMaxMajor) then
if (Players[iPlayer]:GetUnitByID(iUnit):IsHasPromotion(iXpForScoutingPromotion)) then
local pPlot = Map.GetPlot(iPlotX, iPlotY)
-- Only land or lakes, but not NWs (as they are handled below)
if (((not pPlot:IsWater()) or pPlot:IsLake()) and (not pPlot:IsNaturalWonder())) then
ChangeScoutingXp(iPlayer, iUnit, iScoutingXpForTile)
end
end
end
end
GameEvents.TileRevealed.Add(OnTileRevealed)
function OnNaturalWonderDiscovered(iTeam, iFeature, iX, iY, bFirst, iPlayer, iUnit)
if (bFirst and iPlayer >= 0 and iPlayer <= iMaxMajor) then
if (Players[iPlayer]:GetUnitByID(iUnit):IsHasPromotion(iXpForScoutingPromotion)) then
ChangeScoutingXp(iPlayer, iUnit, iScoutingXpForNW)
end
end
end
GameEvents.NaturalWonderDiscovered.Add(OnNaturalWonderDiscovered)