[BNW] [CP] This Lua isn't firing

HorseshoeHermit

20% accurate as usual, Morty
Joined
Apr 5, 2013
Messages
1,473
Location
Canada
Arright, after troubleshooting to close way more parentheses than I care to admit to, I've still got issues with this lua. The file itself is finally grammatically valid, but when the borders expand I don't get the bonus I'm looking for. I can make it give me Floating Gardens, but not the buildings I defined.

Also, the logs on one of the tests said that Player:ChangeYieldStored is not defined. I know this function runs in the game, that's where I got it from.

I've concocted quite an algorithm for your inspection, but hopefully my beautiful sectioning and InformativeFunctionNames make analysis totally painless.

The mod requires v.88 of the Community Patch (June 22 should be good enough).

edit: Lua log shows no evidence of anything happening at the appropriate time. My file's name doesn't appear.​
 

Attachments

Last edited:
So what I'm trying to do is trigger when the civ's borders first encompass a tile of Atoll, Ice, Jungle, Marsh, Oasis, and Snow, after adopting the Merchant Navy policy.

Code:
-- Cartography1
-- Author: Jason
-- DateCreated: 7/8/2017 2:49:19 AM
--------------------------------------------------------------

--------------------------------------------------------------
-- Config
--------------------------------------------------------------
local iCartographyPolicyID = GameInfoTypes.POLICY_MERCHANT_NAVY

--Cartography triggers on Jungle, Marsh, Oasis, Snow, Ice, and Atoll
local atoll, ice, jungle, marsh, oasis = GameInfoTypes.FEATURE_ATOLL, GameInfoTypes.FEATURE_ICE, GameInfoTypes.FEATURE_JUNGLE, GameInfoTypes.FEATURE_MARSH, GameInfoTypes.FEATURE_OASIS
local snow = GameInfoTypes.TERRAIN_SNOW

local speedPercent
do
   if Game.GetGameSpeedType() == 0 then speedPercent = 300 end
   if Game.GetGameSpeedType() == 1 then speedPercent = 150 end
   if Game.GetGameSpeedType() == 2 then speedPercent = 100 end
   if Game.GetGameSpeedType() == 3 then speedPercent = 66 end
end

local yieldGAP = math.floor((50 * speedPercent) / 100)
local yieldBeaker = math.floor( (50 * speedPercent) / 100)
local szYieldsMessage = "+"..yieldBeaker.." [ICON_RESEARCH], +"..yieldGAP.." [ICON_GOLDEN_AGE] from Cartography"

local diversePlots = {"ATOLL", "ICE", "JUNGLE", "MARSH", "OASIS"} --SNOW is Terrain
--------------------------------------------------------------
-- Memory
--------------------------------------------------------------
function GiveCapitalPersistence(buildingType, pPlayer)
   if (pPlayer:IsEverAlive() and pPlayer:GetCapitalCity())
   then
       if pPlayer:GetCapitalCity():HasBuilding(buildingType)
       then  
           function OnCapitalChanged(reorganizingPlayerID, newCapitalID, oldCapitalID)
               if reorganizingPlayerID ~= pPlayer:GetID() then return end
               Players[reorganizingPlayerID]:GetCityByID(newCapitalID):SetNumFreeBuilding(buildingType, 1)
               if (oldCapitalID ~= -1)
               then
                   local pOldCapital = Players[reorganizingPlayerID]:GetCityByID(oldCapitalID)
                   if (pOldCapital:GetOwner() == reorganizingPlayerID) --GetOwner() returns: PlayerID
                   then
                       pOldCapital:SetNumFreeBuilding(buildingType, 0)
                   end
               end
           end
           GameEvents.CapitalChanged.Add(OnCapitalChanged)
       end
   end
end
for _, pLoopPlayer in pairs(Players) do
   for _, v in ipairs(diversePlots) do
       GiveCapitalPersistence(GameInfo.Buildings["BUILDING_CARTOGRAPHY_"..v].ID, pLoopPlayer)
   end
   GiveCapitalPersistence(GameInfo.Buildings["BUILDING_CARTOGRAPHY_SNOW"].ID, pLoopPlayer)
end

--------------------------------------------------------------
-- Util
--------------------------------------------------------------
function GiveRewardAndPersistence(receivingPlayerID, buildingType)
   local receivingPlayer = Players[receivingPlayerID]
   if receivingPlayer:IsEverAlive()
   then
       local capitalCity = receivingPlayer:GetCapitalCity()  -- player->city
       capitalCity:SetNumFreeBuilding(buildingType, 1)
       receivingPlayer:ChangeYieldStored(GameInfoTypes.YIELD_GOLDEN_AGE_POINTS, yieldGAP)
       receivingPlayer:ChangeYieldStored(GameInfoTypes.YIELD_SCIENCE, yieldBeaker)
      
       receivingPlayer:AddMessage(szYieldsMessage)

       GiveCapitalPersistence(buildingType, receivingPlayer)
   end
end

--------------------------------------------------------------
-- POLICY_CARTOGRAPHY bonus triggers
--------------------------------------------------------------
local cartographyAward = {}
for i, v in ipairs(diversePlots) do
   cartographyAward[i] = function (iPlotX, iPlotY, iOwner, iOldOwner)
           if (Players[iOwner]:HasPolicy(iCartographyPolicyID))
           then
               if Players[iOwner]:GetCapitalCity():HasBuilding(GameInfo.Buildings["BUILDING_CARTOGRAPHY_"..v].ID) then return
               else
                   local newPlot = Map.GetPlot(iPlotX, iPlotY)
                   if (newPlot:GetFeatureType() == GameInfoTypes["FEATURE_"..v])
                   then
                       GiveRewardAndPersistence(iOwner, GameInfo.Buildings["BUILDING_CARTOGRAPHY_"..v].ID)
                   end
               end  
           end
   end --anonymous TileOwnershipChanged listener
end
cartographyAward[6] = function(iPlotX, iPlotY, iOwner, iOldOwner)
       if (Players[iOwner]:HasPolicy(iCartographyPolicyID))
       then
           if Players[iOwner]:GetCapitalCity():HasBuilding(GameInfo.Buildings["BUILDING_CARTOGRAPHY_SNOW"].ID) then return
           else
               local newPlot = Map.GetPlot(iPlotX, iPlotY)
               if (newPlot:GetTerrainType() == GameInfoTypes["TERRAIN_SNOW"])
               then
                   GiveRewardAndPersistence(iOwner, GameInfo.Buildings["BUILDING_CARTOGRAPHY_SNOW"].ID)
               end
           end  
       end
end --anonymous TileOwnershipChanged listener
GameEvents.TileOwnershipChanged.Add(cartographyAward[1])
GameEvents.TileOwnershipChanged.Add(cartographyAward[2])
GameEvents.TileOwnershipChanged.Add(cartographyAward[3])
GameEvents.TileOwnershipChanged.Add(cartographyAward[4])
GameEvents.TileOwnershipChanged.Add(cartographyAward[5])
GameEvents.TileOwnershipChanged.Add(cartographyAward[6])

--------------------------------------------------------------
-- OnPlayerAdoptPolicy POLICY_CARTOGRAPHY
--------------------------------------------------------------
function GiveCartographyBonus(adopterID, policyID)
   if (policyID == iCartographyPolicyID)
   then
       local hasAtoll, hasIce, hasJungle, hasMarsh, hasOasis, hasSnow = false, false, false, false, false, false
       for iPlotID = 0, Map.GetNumPlots()-1, 1 do
           local loopPlot = Map.GetPlotByIndex(iPlotID)
           if loopPlot:GetOwner() == adopterID
           then
               hasAtoll = hasAtoll or (loopPlot:GetFeatureType() == atoll)
               hasIce = hasIce or (loopPlot:GetFeatureType() == ice)
               hasJungle = hasJungle or (loopPlot:GetFeatureType() == jungle)
               hasMarsh = hasMarsh or (loopPlot:GetFeatureType() == marsh)
               hasOasis = hasOasis or (loopPlot:GetFeatureType() == oasis)
               hasSnow = hasSnow or (loopPlot:GetTerrainType() == snow)
               if hasAtoll and hasIce and hasJungle and hasMarsh and hasOasis and hasSnow
               then
                   break
               end
           end
       end

       if hasAtoll then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_ATOLL.ID)
       end
       if hasIce then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_ICE.ID)
       end
       if hasJungle then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_JUNGLE.ID)
       end
       if hasMarsh then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_MARSH.ID)
       end
       if hasOasis then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_OASIS.ID)
       end
       if hasSnow then GiveRewardAndPersistence(adopterID, GameInfo.Buildings.BUILDING_CARTOGRAPHY_SNOW.ID)
       end
       -- then rely on the OnTileOwnershipChanged listener
   end
end
GameEvents.PlayerAdoptPolicy.Add(GiveCartographyBonus)

When the lua loads it creates an event OnCapitalChanged that gives the sentinel buildings to the player's new capital every time it changes, for every player. Then it creates the TileOwnershipChange listener that applies the effect of the policy by giving yields and putting a sentinel building in the capital to remember that it happened.
A trigger is created for PlayerAdoptPolicy that applies the bonuses if the terrains are already inside the empire when Merchant Navy is adopted.

I'm 99% sure the shortcoming is due to some unexpected thing with lua tables, scoping, or closure. I can't glean anything from the lua manual, though.
 
Why not post this in the CPP thread?

Did you enable the TileOwnershipChange listener in CustomModOptions?

If so, I would have thought this would have been much easier to accomplish since basically...
  1. Use Lua with the Event system to apply the yields and maintain memory elements persisting through save games.
  2. Use the Event System to also grant you yields that can scale upon era and game speed(or not if you want).

But this is CP, not CBP so... let me see if I get this straight before diagnosing the issue.

  1. Player unlocks Merchant Navy and is checked through PlayerAdoptPolicy which checks all of the player's tile for any discovered features to apply memory building and yield.
  2. Player is checked whether Merchant Navy is unlocked and when unlocking a new tile and tile is checked through TileOwnershipChanged.
  3. TileOwnershipChanged checks whether or not they have the memory building and the specific feature discovered.
    1. If have memory building, end.
    2. If not, apply memory building and yield, end.

Is that right? I'm very illiterate as well so I don't know what your main problem is.
 
I avoided the Event System from CP because I thought it would force me to scale with era. I also find the sanitary conditions of that code to be lacking.
I didn't post in the CPP forum because... I thought the mission of that forum was just for CP bugs or CBP development.

You've understood my design. The problem is that nothing is happening - the lua log doesn't note any errors or any occurrences at all.
There was a point during my testing when I was able to get an Aztec Floating Gardens when I adopted the policy, but I traced that to be because I was passing GameInfo.Buildings.BUILDING_CARTOGRAPHY_ATOLL and not the ID attribute.
 
I avoided the Event System from CP because I thought it would force me to scale with era. I also find the sanitary conditions of that code to be lacking.
I didn't post in the CPP forum because... I thought the mission of that forum was just for CP bugs or CBP development.

You've understood my design. The problem is that nothing is happening - the lua log doesn't note any errors or any occurrences at all.
There was a point during my testing when I was able to get an Aztec Floating Gardens when I adopted the policy, but I traced that to be because I was passing GameInfo.Buildings.BUILDING_CARTOGRAPHY_ATOLL and not the ID attribute.
Like I said did you enable CustomModOptions of the TileOwnershipChanged listener?

Otherwise do print statements on every command and when the console stops printing out that is where it broke somewhere. I'm sure every Lua manual taught about how print statements are essentially debug statement for all Lua coders beginners and pros.
 
I didn't enable those two Events. :blush: retesting now.
I got the building to appear. Now I need to find a way to give the yields.

I don't want era-scaling; that would make the boosts too hard to balance and also encourage playing counter to the redesign's intent.

I can't remember where I saw the ChangeYieldStored function, but lualog reports there is no such thing. It isn't an API extension listed for CPP. I have a function to change golden age progress, but not one to award science.
 
Last edited:
I didn't enable those two Events. :blush: retesting now.
I got the building to appear. Now I need to find a way to give the yields.

I don't want era-scaling; that would make the boosts too hard to balance and also encourage playing counter to the redesign's intent.

I can't remember where I saw the ChangeYieldStored function, but lualog reports there is no such thing. It isn't an API extension listed for CPP. I have a function to change golden age progress, but not one to award science.
look at e&d
 
Yay! And now that I've got the notification working too, this mod is now feature-complete.

All I need to do is balance the tech boost for all game settings.
 
Back
Top Bottom