[TOTPP] Prof. Garfield's Lua Code Thread

That change did the trick! And I was able to adapt it to a few other pieces of code. Tinkered a bit -- always fun when things work. Thank you!

I've tried and tried though, and just cannot seem to get the onCanBuild functions to work again. The population/limit ones work just fine, but the improvement prerequisite ones are stubborn. I tried finding an older events.lua file to see where that change could've happened, but no luck.

The other, albeit minor, issue I'm having is those wonders continue to show up in the build menu even when built.
 
I've tried and tried though, and just cannot seem to get the onCanBuild functions to work again. The population/limit ones work just fine, but the improvement prerequisite ones are stubborn. I tried finding an older events.lua file to see where that change could've happened, but no luck.
Here's an example I found with light cavalry:
Code:
local function inBuildMenu(defaultBuildFunction,city,item,tribe)
-- some code
if civ.isUnitType(item) then
    if item == unitAliases.LightCavalry then
        if not defaultBuildFunction(city,item) then
            return false
        else
            return countUnits(unitAliases.LightCavalry,city.owner) <= findNativePopulation(city.owner)/4
        end
    end
end
-- more code
    if civ.isUnitType(item) then
        if item == unitAliases.LightCavalry or item == unitAliases.HeavyCavalry then
            return civ.hasImprovement(city,improvementAliases.Barracks) and defaultBuildFunction(city,item)
        end
    end
-- even more code
end
When the code is applied for light cavalry, the code stops at one of these return lines:
Code:
            return false
        else
            return countUnits(unitAliases.LightCavalry,city.owner) <= findNativePopulation(city.owner)/4
Therefore, the code never reaches this check
Code:
    if civ.isUnitType(item) then
        if item == unitAliases.LightCavalry or item == unitAliases.HeavyCavalry then
            return civ.hasImprovement(city,improvementAliases.Barracks) and defaultBuildFunction(city,item)
        end
    end
Hence, this condition is irrelevant.

The other, albeit minor, issue I'm having is those wonders continue to show up in the build menu even when built.
You will either have to add back in the defaultBuildFunction check (and figure out why your rules didn't let you build the wonders), or you will have to check the wonder.city and wonder.destroyed fields and return true only if they are nil and false respectively.
 
I see! I'll need to parse these apart and otherwise adjust. So much time spent parsing thru, and it was under my nose the whole time! Thanks Prof.
 
Hi @Prof. Garfield ~ I have two questions coming up, and was wondering if you had some advice.

The first is an event which is as follows. I am trying to register "+10 turns after X event," -- if the player can't do something within 10 turns, they "lose" the mission, else if they can, they succeed. I've tried flags, to no avail. Not sure how to implement this. Here is my code thus far (everything works fine, other than the 10 turn time limit).

Spoiler :
Code:
discreteEvents.onCityProcessingComplete(function (turn, tribe)
if tribe:hasTech(techAliases.DivinedPower) then
        gen.justOnce("DivinedPowerReceivedBy"..tostring(tribe.id),function()
                    local rebellionChoiceList = {}
                    local index = 1
                    local rebelCity = nil
                    for city in civ.iterateCities() do
                        if city.owner == tribe then
                            rebellionChoiceList[index] = city.id
                            index = index + 1
                        end
                    end
                    if index > 1 then
                    local rebellionChoice = rebellionChoiceList[math.random(1,index-1)]
                    rebelCity = civ.getCity(rebellionChoice)
                    end
                    if civ.isCity(rebelCity) then
                    civ.captureCity(rebelCity,civ.getTribe(0))
                    local rebelTile = rebelCity.location
                    gen.createUnit(unitAliases.Rebel1,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    gen.createUnit(unitAliases.Rebel2,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    gen.createUnit(unitAliases.Rebel3,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})   
                        for unit in civ.iterateUnits() do
                            if unit.owner == civ.getCurrentTribe() and unit.location == rebelTile then
                                gen.killUnit(unit)
                            end
                        end
                        --try flags
                        if rebelCity.owner == civ.getCurrentTribe() and turn == turn+10 then
                        civ.ui.text("hey")
                        gen.setWeLoveTheKing(index)
                        elseif rebelCity.owner == civ.getTribe(0) and turn == turn+10 then
                        civ.ui.text("You have failed to retake "..rebelCity.name.."! Your people believe you to be but a petty human. More rebellion near "..rebelCity.name.." is expected.")
                    gen.createUnit(unitAliases.Rebel1,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    gen.createUnit(unitAliases.Rebel2,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    gen.createUnit(unitAliases.Rebel3,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})   
                        --try flags
                        end
                    end
                    if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "Power Divined by the Gods"
                dialog.width = 500
        local multiLineText = "You have claimed that your leadership is one of divine presence and that the gods are on your side. Some of your people, however, question these claims.\n^\n^Rebels have taken over "..rebelCity.name.." in protest!\n^\n^You must retake "..rebelCity.name.." in the next few years to prove your status as a divined leader.\n^\n^Mission: Retake "..rebelCity.name.." within 10 turns."
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
        end
    end)
    end
end)

The next is this darn fortress code again. This is working great -- when I load saved games. When I start a new game, it has stopped working. Any idea why this may be? Imagine this code, but repeated for several different techs.

EDIT: Come to think of it, this is happening with a few features (not working in new game, working in saved game).

Spoiler :
Code:
local FortLayout = civ.ui.loadImage("Images/fortlayout.bmp")
discreteEvents.onCityProcessingComplete(function (turn, tribe)
    gen.justOnce("EngineeringFortress"..tostring(tribe.id),function()
    if tribe:hasTech(techAliases.Engineering) then
        local chosenCity = nil
                if tribe.isHuman then
                        local menuTable = {}
                        local offset = 3
                        for city in civ.iterateCities() do
                            if city.owner == civ.getCurrentTribe() then
                                menuTable[offset+city.id] = city.name
                            end
                        end
                        local fortChoice = text.menu(menuTable,"We have the materials and expertise for a new fortress. Select a city.","A New Fortress")
                        if fortChoice >= offset then
                            chosenCity = civ.getCity(fortChoice-offset)
                        end
                else
                    local aiChoiceList = {}
                    local index = 1
                    for city in civ.iterateCities() do
                        if city.owner == tribe then
                            aiChoiceList[index] = city.id
                            index = index + 1
                        end
                    end
                    if index > 1 then
                    local aiChoice = aiChoiceList[math.random(1,index-1)]
                    chosenCity = civ.getCity(aiChoice)
                    end
                end
                if civ.isCity(chosenCity) then
                        local tileList = gen.cityRadiusTiles(chosenCity)
                        tileList[21] = nil
                        gen.makeArrayOneToN(tileList)
                        local choice = nil
                    if tribe.isHuman then
                            local dialog = civ.ui.createDialog()
                            dialog.title = "Select a Location"
                            dialog.width = 375
                            dialog:addImage(FortLayout)
                            local multiLineText = "A new fortress will be constructed near " ..chosenCity.name..".\n^Where should we construct our fortress?\n^Fortresses cannot be built on the sea."
                            text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Northeast, adjacent to city (1)", 1)
                    dialog:addOption("East, adjacent to city (2)", 2)
                    dialog:addOption("Southeast, adjacent to city (3)", 3)
                    dialog:addOption("South, adjacent to city (4)", 4)
                    dialog:addOption("Southwest, adjacent to city (5)", 5)
                    dialog:addOption("West, adjacent to city (6)", 6)
                    dialog:addOption("Northwest, adjacent to city (7)", 7)
                    dialog:addOption("North, adjacent to city (8)", 8)
                    dialog:addOption("Northeast (9)", 9)
                    dialog:addOption("Southeast (10)", 10)
                    dialog:addOption("Southwest (11)", 11)
                    dialog:addOption("Northwest (12)", 12)
                    dialog:addOption("North, slight east (13)", 13)
                    dialog:addOption("East, slight north (14)", 14)
                    dialog:addOption("East, slight south (15)", 15)
                    dialog:addOption("South, slight east (16)", 16)
                    dialog:addOption("South, slight west (17)", 17)
                    dialog:addOption("East, slight south (18)", 18)
                    dialog:addOption("East, slight north (19)", 19)
                    dialog:addOption("North, slight west (20)", 20)
                    choice = dialog:show()
                    else
                        choice = math.random(9,20)
                    end
            if choice == 1 then
                local fortTile = tileList[1]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end
        elseif choice == 2 then
                local fortTile = tileList[2]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end
        elseif choice == 3 then
                local fortTile = tileList[3]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end
        elseif choice == 4 then
                local fortTile = tileList[4]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end
        elseif choice == 5 then
                local fortTile = tileList[5]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end           
        elseif choice == 6 then
                local fortTile = tileList[6]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end           
        elseif choice == 7 then
                local fortTile = tileList[7]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end           
        elseif choice == 8 then
                local fortTile = tileList[8]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end       
        elseif choice == 9 then
                local fortTile = tileList[9]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end       
        elseif choice == 10 then
                local fortTile = tileList[10]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end       
        elseif choice == 11 then
                local fortTile = tileList[11]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end       
        elseif choice == 12 then
                local fortTile = tileList[12]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end               
        elseif choice == 13 then
                local fortTile = tileList[13]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end   
        elseif choice == 14 then
                local fortTile = tileList[14]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end               
        elseif choice == 15 then
                local fortTile = tileList[15]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end           
        elseif choice == 16 then
                local fortTile = tileList[16]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end               
        elseif choice == 17 then
                local fortTile = tileList[17]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end   
        elseif choice == 18 then
                local fortTile = tileList[18]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end           
        elseif choice == 19 then
                local fortTile = tileList[19]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end       
        elseif choice == 20 then
                local fortTile = tileList[20]
                        if fortTile.terrainType == 10 then
                            if tribe.isHuman then
                            civ.ui.text("Unfortunate news! Storms and floodwaters have thwarted our attempt to construct a fort. Salvaged materials have been sent to the capital.")
                            gen.createUnit(unitAliases.Materials1,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                            else
                                addShieldsToNearestCity(chosenCity,civ.getCurrentTribe(),50)
                            end
                        else
                            gen.placeFortress(fortTile)
                        end               
            end
                end
        end
    end)
end)

Any insight would be much appreciated!
 
Last edited:
The second one was a silly and small mistake of inversing the "justonce" and "tribe:hasTech" lines. All fixed now! The first one I am still having trouble with. Can't seem to mark the # of turns in the same way I could for other flags.
 
Meant to do this yesterday, but it slipped my mind. I think this (untested) code will do what you want, but you'll need to fill in details, and double check.
Code:
local counter   = require("counter")
local delayedAction = require("delayedAction")
local flag = require("flag")
Code:
for i=0,7 do
    flag.define("DivinedPowerEventOngoing"..i,false)
end
for i=0,7 do
    counter.define("DivinedPowerCityLocationID"..i,-1)
end
local function divinedPowerFailureEvent(argTable)
    local tribeID = argTable.tribeID
    local rebelCity = gen.getTileFromID(counter.value("DivinedPowerCityLocationID"..tribeID)).city
    if not rebelCity then
        -- this happens if the city is destroyed
        return
    end
    if not flag.value("DivinedPowerEventOngoing"..tribeID) then
        civ.ui.text("hey")
        gen.setWeLoveTheKing(rebelCity)
        return
    end
    local rebelTile = rebelCity.location
    civ.ui.text("You have failed to retake "..rebelCity.name.."! Your people believe you to be but a petty human. More rebellion near "..rebelCity.name.." is expected.")
    gen.createUnit(unitAliases.Rebel1,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
    gen.createUnit(unitAliases.Rebel2,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
    gen.createUnit(unitAliases.Rebel3,civ.getTribe(0),rebelTile,{count = 2, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
end
delayedAction.makeFunctionDelayable("divinedPowerFailureCheck",divinedPowerFailureEvent)
discreteEvents.onCityProcessingComplete(function (turn, tribe)
    if tribe:hasTech(techAliases.DivinedPower) then
        gen.justOnce("DivinedPowerReceivedBy"..tostring(tribe.id),function()
            local rebellionChoiceList = {}
            local index = 1
            local rebelCity = nil
            for city in civ.iterateCities() do
                if city.owner == tribe then
                    rebellionChoiceList[index] = city.id
                    index = index + 1
                end
            end
            if index > 1 then
                local rebellionChoice = rebellionChoiceList[math.random(1,index-1)]
                rebelCity = civ.getCity(rebellionChoice)
                counter.setValue("DivinedPowerCityLocationID"..tribe.id,gen.getTileID(rebelCity.location))
                flag.setTrue("DivinedPowerEventOngoing"..tribe.id)
                delayedAction.doInFuture("divinedPowerFailureCheck",{tribeID = tribe.id},turn+10)
                -- do other rebellion setup
            end
        end)
    end
end)
discreteEvents.onCityTaken(function (city, defender)
    local tribeID = city.owner.id
    if not flag.value("DivinedPowerEventOngoing"..tribeID) or defender.id == 0 then
        return
    end
    local rebelCity = gen.getTileFromID(counter.value("DivinedPowerCityLocationID"..tribeID)).city
    if city == rebelCity then
        flag.setFalse("DivinedPowerEventOngoing"..tribeID)
        civ.ui.text("You have retaken "..city.name.."! Your people believe you to be a god. More rebellion near "..city.name.." is unlikely.")
    end
end)
discreteEvents.onCityDestroyed(function(city)
    local tribeID = civ.getCurrentTribe().id
    if not flag.value("DivinedPowerEventOngoing"..tribeID) or city.owner.id ~= 0 then
        return
    end
    local rebelCity = gen.getTileFromID(counter.value("DivinedPowerCityLocationID"..tribeID)).city
    if city == rebelCity then
        flag.setFalse("DivinedPowerEventOngoing"..tribeID)
        civ.ui.text("You have destroyed "..city.name.."! Your people believe you to be a god. More rebellion near "..city.name.." is unlikely.")
    end
end)
 
Thank you Prof.! I tried this out. It is telling me that the line:
"delayedAction.doInFuture("divinedPowerFailureCheck",{tribeID = tribe.id},turn+10)"

requires "numbers for tribeID and turn," as it says, in the console. Any ideas?
 
Try changing the line

Code:
delayedAction.doInFuture("divinedPowerFailureCheck",{tribeID = tribe.id},turn+10)
to
Code:
delayedAction.doInFuture("divinedPowerFailureCheck",{tribeID = tribe.id},turn+10,tribe.id)
 
Thank you! Will give this a shot first thing tomorrow. This is coming together!
 
I'm getting a console error: "too many local variables (limit is 200)." Does this mean my events.lua has too much in it?
 
I'm getting a console error: "too many local variables (limit is 200)." Does this mean my events.lua has too much in it?
Yes, in a way. In Lua, every function can have up to 200 local variables, and the overall file counts as a "function" for this purpose. So, you don't have to worry about the local variables within functions.

The easiest way to fix this is to make a table, and assign values to that table instead of local variables. This was the original reason to have tables like unitAliases. Alternatively, you can spread out your events into multiple files.
 
Good incentive! I separated some out this morning, and things are running smoothly.

The event above works in the negative, but not the positive. If the city is not retaken, everything goes well. If it is retaken within 10 turns, nothing happens -- no console error. If the city is retaken within 10 turns, I want the city to have a we love the king day and a message to come up... perhaps some other bits I could add in later.

I tried adding the discreteEvents registrar to the onCityProcessingComplete.lua file (this is where this event is now stored), and then added the onCityTaken discreteEvent to that file, but I don't think things are linking up that way. Also tried leaving just that piece in the main events.lua file, but that also did not work. Any thoughts?
 
The event above works in the negative, but not the positive. If the city is not retaken, everything goes well. If it is retaken within 10 turns, nothing happens -- no console error. If the city is retaken within 10 turns, I want the city to have a we love the king day and a message to come up... perhaps some other bits I could add in later.

I tried adding the discreteEvents registrar to the onCityProcessingComplete.lua file (this is where this event is now stored), and then added the onCityTaken discreteEvent to that file, but I don't think things are linking up that way. Also tried leaving just that piece in the main events.lua file, but that also did not work. Any thoughts?

In the onCityTaken code, this if statement should be changed
Code:
    if not flag.value("DivinedPowerEventOngoing"..tribeID) or defender.id == 0 then
        return
    end
It should be
Code:
    if not flag.value("DivinedPowerEventOngoing"..tribeID) or defender.id ~= 0 then
I assumed that the event should fail if the rebellious city was captured by another tribe, then retaken, which is why the defender should be the barbarian tribe. You may need to change that.

Of course, you'll also have to add the gen.setWeLoveTheKing call (as well as some other stuff; I didn't copy all the event setup).

Note: If you're not sure if an event is happening at all, a good strategy is to place print or civ.ui.text calls early in the event, and see if they happen.

Good incentive! I separated some out this morning, and things are running smoothly.
When I was looking for a way to increase the allowed number of local variables in a file, I ran across some advice which pointed out that if you're running into this limit, you're probably doing too much within the file (or function, I suppose) anyway. That was certainly true of the OTR events.
 
This is working like a charm, thanks Prof.! I got rid of the we love the king reward, since it gets canceled the next turn anyway. Decided to award a high powered military unit instead.

Well, this is good. It has prompted me to actually follow through with separating the files. And this makes things a lot easier to find, anyway.
 
Quick question, that may not have such a quick answer.

In my onUnitKilled function, I have an effect happening when an Envoy is killed. With this, there is "loser, winner" properties. Yet I'd like to set a flag to true when the Envoy is killed -- but specifically for that tribe's envoy, so that, later, in a discreteEvent.onTribeTurnBegin, it generates that killed unit in the capital.

When generating the unit within the onUnitKilled function, it generates immediately after death -- thereby making an attack on a capital city, if the unit is in that city, a futile effort.

So I'm trying to make a flag for that dead unit, but in the discreteEvent.onTribeTurnBegin, I can't identify the "loser" of the unit for the flag set to true. Is there someway to link that discreteEvent to the "loser" in the function of onUnitKilled?
 
In my onUnitKilled function, I have an effect happening when an Envoy is killed. With this, there is "loser, winner" properties. Yet I'd like to set a flag to true when the Envoy is killed -- but specifically for that tribe's envoy, so that, later, in a discreteEvent.onTribeTurnBegin, it generates that killed unit in the capital.

When generating the unit within the onUnitKilled function, it generates immediately after death -- thereby making an attack on a capital city, if the unit is in that city, a futile effort.

So I'm trying to make a flag for that dead unit, but in the discreteEvent.onTribeTurnBegin, I can't identify the "loser" of the unit for the flag set to true. Is there someway to link that discreteEvent to the "loser" in the function of onUnitKilled?
One way is to define a separate flag for each tribe, like I did for your rebellion code
Code:
for i=0,7 do
    flag.define("DivinedPowerEventOngoing"..i,false)
end
You can then use the tribeID to choose between the specific flags.

Alternatively, and probably more appropriately, you can use the tribeData module to define an appropriate flag for each tribe
Code:
local tribeData = require("tribeData")
tribeData.defineFlag("envoyKilled",false)

discreteEvents.onTribeTurnBegin(function (turn, tribe)
    if tribeData.flagGetValue(tribe,"envoyKilled") then
        -- create envoy
        tribeData.flagSetFalse(tribe,"envoyKilled")
    end
end)

discreteEvents.onUnitKilled(function (loser, winner, aggressor, victim, loserLocation, winnerVetStatus, loserVetStatus)
    if loser.type == object.uEnvoy then
        tribeData.flagSetValue(loser.owner,"envoyKilled",true)
    end
end)
 
Hi Prof., thanks for this. Console is telling me, "first argument is not a tribe." Any idea what this could mean?
 
Hi Prof., thanks for this. Console is telling me, "first argument is not a tribe." Any idea what this could mean?
From the code I provided, I can't see why you would get that error. I'll need to see the actual error message and the lines of code referenced. (That is, the lines in the file your working on, not the "chain" of errors.)
 
Here you go! All below in the spoiler.

Spoiler :
Code:
local tribeData = require("tribeData")
tribeData.defineFlag("envoyKilled",false)

discreteEvents.onTribeTurnBegin(function (tribe,turn)
    if tribeData.flagGetValue(tribe,"envoyKilled") then
        gen.createUnit(unitAliases.TribalEnvoy,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        tribeData.flagSetFalse(tribe,"envoyKilled")
    end
end)

discreteEvents.onUnitKilled(function (loser,winner,aggressor,victim,loserLocation,winnerVetStatus,loserVetStatus)
    if loser.type == unitAliases.TribalEnvoy then
        tribeData.flagSetValue(loser.owner,"envoyKilled",true)
    end
end)


ERROR MESSAGE


Global variables are disabled
Enter console.commands() to see a list of keys in the console table.  Some give access to functions in modules, others will run event code.
...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 7
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 8
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 8
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 8
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 8
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe.  Received: 8
stack traceback:
    [C]: in function 'error'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: in upvalue 'standardChecks'
    ...cient ToT With Lua\Original\LuaCore\supplementalData.lua:439: in function 'tribeData.flagGetValue'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:3647: in field '?'
    ...oT With Lua\Original\LuaCore\discreteEventsRegistrar.lua:252: in field 'performOnTribeTurnBegin'
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:919: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>
 
Code:
discreteEvents.onTribeTurnBegin(function (tribe,turn)
should be
Code:
discreteEvents.onTribeTurnBegin(function (turn,tribe)
The order matters. The function parameter names turn and tribe are only there for us, Lua doesn't pay them any attention. When the function registered by discreteEvents.onTribeTurnBegin is called, it will be given a number as the first argument/parameter, and the tribe as the second.

Here's a clue:
...cient ToT With Lua\Original\LuaCore\supplementalData.lua:428: tribeData.flagGetValue: first argument is not a tribe. Received: 7

Not only is the first argument not a tribe, which it is supposed to be, the error actually tells us what the value is: 7, a number. This means that the first argument is the number 7, so the variable 'tribe' has been assigned the number 7 at some point.

This said, I understand that it can be a bit confusing, since the error was actually triggered in a LuaCore file.
 
Top Bottom