• We need to know your opinion about our social media accounts! Tell us here if you follow us on social media and what we could improve.

[TOTPP] Prof. Garfield's Lua Code Thread

Thank you! I'll give it a shot.

I'm also trying to set default zoom level to the furthest zoomed in. I can get to the ToTPP config menu in game, but it doesn't seem to save the option. When I start a new game, it loads at 0, even though I have it set to "8." Any ideas on why this might be?
 
There was a time when my unit retirement turns were working, but now they are not. Any idea why? Here is relevant code:

Spoiler :
Code:
unitData.defineCounter("unitRetirementTurn",10000)
unitData.defineCounter("lf1RetirementTurn",10000)
unitData.defineCounter("lf2RetirementTurn",10000)
unitData.defineCounter("lf3RetirementTurn",10000)
unitData.defineCounter("lf4RetirementTurn",10000)
unitData.defineCounter("g1RetirementTurn",10000)
unitData.defineCounter("g2RetirementTurn",10000)
unitData.defineCounter("g3RetirementTurn",10000)
unitData.defineCounter("g4RetirementTurn",10000)
unitData.defineCounter("gladiatorRetirementTurn",10000)
unitData.defineCounter("eruptionRetirementTurn",10000)
unitData.defineCounter("heroRetirementTurn",10000)


discreteEvents.onCityProcessingComplete(function (turn, tribe)
        if turn == 120 then
        gen.justOnce("EpicPoetryReceivedBy"..tostring(tribe.id),function()
        local createdUnits = gen.createUnit(unitAliases.Hero,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        if createdUnits[1] then
            unitData.counterSetValue(createdUnits[1],"heroRetirementTurn",civ.getTurn()+20)
        end
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "A Legendary Hero"
                dialog.width = 500
                dialog:addImage(EpicPoetry)
                local multiLineText = "A legendary figure has emerged amongst your people! This hero is\n^devoted to the ideals of your kingdom, yet seeks splendor and glory in\n^far away lands. When this hero's life comes to an end, you are certain\n^many epics will be written of their exploits.\n^\n^^'Be strong, saith my heart;\n^^I am a soldier;\n^^I have seen worse sights than this.'\n^\n^- Homer, The Iliad\n^\n^A Hero unit has been placed in your capital city. This only happens once.\n^Heroes have only 20 turns before they retire. For a full\n^list of what Heroes can do, see the Civliopedia or Readme."
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
                civ.playSound("Druman.wav")
            local createdUnits2 = gen.createUnit(unitAliases.Siren,civ.getTribe(0),mythTileOcean1,{count = 1, randomize = false, scatter = false, inCapital = false, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
            if createdUnits2[1] then
                unitData.counterSetValue(createdUnits2[1],"heroRetirementTurn",civ.getTurn()+20)
            end
            local createdUnits3 = gen.createUnit(unitAliases.Charybdis,civ.getTribe(0),mythTileOcean2,{count = 1, randomize = false, scatter = false, inCapital = false, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
            if createdUnits3[1] then
                unitData.counterSetValue(createdUnits3[1],"heroRetirementTurn",civ.getTurn()+20)
            end
            local createdUnits4 = gen.createUnit(unitAliases.Minotaur,civ.getTribe(0),mythTileMountain,{count = 1, randomize = false, scatter = false, inCapital = false, veteran = false, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
            if createdUnits4[1] then
                unitData.counterSetValue(createdUnits4[1],"heroRetirementTurn",civ.getTurn()+20)
            end
        end
    for unit in civ.iterateUnits() do
        if unit.owner == tribe and unitData.counterGetValue(unit,"heroRetirementTurn") <= turn then
            gen.killUnit(unit)
        end
    end
    end)
    end
-- Volcano
        if math.random() < 0.008 and (civ.getCurrentTribe() == civ.getTribe(0) and turn ~= 1) then
                local dialog = civ.ui.createDialog()
                dialog.title = "Volcanic Eruption!"
                dialog.width = 500
                dialog:addImage(VolcanoImage)
                local multiLineText = "Rumor has it that a volcano has violently erupted somewhere in the known world.\n^\n^^'The cloud sank down soon afterwards and covered the sea.\n^^I turned around and saw a thick black cloud advancing over the land like a flood.\n^^The darkness spread over us.\n^^But it was not the darkness of a cloudy night,\n^^but was as if the lamps had been put out in a closed room.'\n^\n^- Pliny the Younger"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
                civ.playSound("Volcano.wav")
                local placeEruption = getRandomVolcano()
                local createEruption = gen.createUnit(unitAliases.Eruption,civ.getTribe(0),placeEruption,{count = 1, randomize = true, scatter = true, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                for _,createdUnit in pairs(createEruption) do
                    unitData.counterSetValue(createdUnit,"eruptionRetirementTurn",civ.getTurn()+2)
        end
    for unit in civ.iterateUnits() do
        if unit.owner == tribe and unitData.counterGetValue(unit,"eruptionRetirementTurn") <= turn then
            gen.killUnit(unit)
                end
            end
    end
end)
 
There was a time when my unit retirement turns were working, but now they are not. Any idea why? Here is relevant code:
You have 2 loops that retire units. Both these loops are inside if statements. So, you'll only get retirements on turn 120 (if the tribe has epic poetry), or during a turn with a volcano eruption. You can delete one of these loops entirely, and move the other out of the if statements so that it is run every turn.
 
Thanks Prof. I'm having a difficult time with retirements across the board. It's strange as they worked well before. I wonder if I moved something to the wrong place. I've tried rearranging as you suggested, but no luck (how can I identify createdUnit, for example, outside of the if statement?). Here is some more code:

Spoiler :
Code:
local GreatGeneral = civ.ui.loadImage("Images/greatgeneral1.bmp")
discreteEvents.onCityProcessingComplete(function (turn, tribe)
    if tribe:hasTech(techAliases.Tributaries) then
        gen.justOnce("TributariesResearched",function()
        local choice = nil
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "A legendary figure appears..."
                dialog.width = 500
                dialog:addImage(GreatGeneral)
                local multiLineText = "Your civilization is the first in the known world to make use of Tributaries.\n^ \n^Your most talented general comes to your throne room carrying word\n^of a dozen new tribal pledges.\n^ \n^^'War is the father and king of all:\n^^some he has made gods, and some men;\n^^some slaves and some free.'\n^ \n^- Heraclitus\n^ \n^Generals are a special leader unit. Select a type:"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Protector", 1)
                    dialog:addOption("Tyrant", 2)
                 choice = dialog:show()
                else
                 choice = math.random(1,2)    
                end
            if choice == 1 then
                if tribe.isHuman then
                local createdUnit = gen.createUnit(unitAliases.General1P,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                        if createdUnit[1] then
                            unitData.counterSetValue(createdUnit[1],"unitRetirementTurn",civ.getTurn()+specialMilitaryLifeTable[math.random()])
                        end
                else
                local createdUnitAI = gen.createUnit(unitAliases.General1P,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                        if createdUnitAI[1] then
                            unitData.counterSetValue(createdUnitAI[1],"unitRetirementTurn",civ.getTurn()+specialMilitaryLifeTable[math.random()])
                        end
                civ.ui.text("Rumor has it that a great general has unified many tribes in nearby lands.")
                end
            elseif choice == 2 then
                if tribe.isHuman then
                local createdUnit2 = gen.createUnit(unitAliases.General1T,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    if createdUnit2[1] then
                        unitData.counterSetValue(createdUnit2[1],"unitRetirementTurn",civ.getTurn()+specialMilitaryLifeTable[math.random()])
                    end
                else
                local createdUnitAI2 = gen.createUnit(unitAliases.General1T,civ.getCurrentTribe(),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                    if createdUnitAI2[1] then
                        unitData.counterSetValue(createdUnitAI2[1],"unitRetirementTurn",civ.getTurn()+specialMilitaryLifeTable[math.random()])
                    end
                civ.ui.text("Rumor has it that a great general has unified many tribes in nearby lands.")
                end
            end
                for unit in civ.iterateUnits() do
                    if unit.owner == tribe and unitData.counterGetValue(unit,"unitRetirementTurn") <= turn then
                        gen.killUnit(unit)
                        if unit.owner.isHuman then
                        civ.ui.text("After years of service, your Great General has retired.")
                        end
                    end
                end
        end)
    end
end)
 
Thanks Prof. I'm having a difficult time with retirements across the board. It's strange as they worked well before. I wonder if I moved something to the wrong place. I've tried rearranging as you suggested, but no luck (how can I identify createdUnit, for example, outside of the if statement?). Here is some more code:
The code to actually retire units is separate from the code to create them and set the retirement counter.
This is the loop to retire units, and you've placed it inside the justOnce block of code.
Code:
                for unit in civ.iterateUnits() do
                    if unit.owner == tribe and unitData.counterGetValue(unit,"unitRetirementTurn") <= turn then
                        gen.killUnit(unit)
                        if unit.owner.isHuman then
                        civ.ui.text("After years of service, your Great General has retired.")
                        end
                    end
                end
You need to check this every turn, for every tribe. It can be its own discrete event if you want.
 
Long time, no see!
I am getting this error in a new game of my mod, but I have played thru several test games without this error and have not edited code.
Any ideas what could be happening?

Spoiler :
Code:
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Argos, true
Ephesus, true
Corinth, true
Athens, true
Populonia, true
Vulci, true
Caere, true
Arretium, true
Volsinii, true
Veii, true
Tarquinii, true
Argos, true
Ephesus, true
Corinth, false
Populonia, false
Arsacia, true
Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
Arsacia, true
Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
Arsacia, true
Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
Arsacia, true
Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

Arshak, true
Tarchna, true
Susa, true
Ctesiphon, true
Ecbatana, true
...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>

...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: attempt to index a nil value
stack traceback:
    ...strator\Desktop\Ancient ToT With Lua\Original\events.lua:925: in function <...strator\Desktop\Ancient ToT With Lua\Original\events.lua:912>
 
I'm guessing a city got destroyed, and that is triggering the bug in the code. Around line 925 in events.lua, you should find this code:
Code:
    for cityID,_ in pairs(state.processedCities) do
        if civ.getCity(cityID).owner == tribe then
            state.processedCities[cityID] = false
        end
    end
Try replacing it with this (untested code):
Code:
    for cityID,_ in pairs(state.processedCities) do
        if not civ.getCity(cityID) then
            state.processedCities[cityID] = nil
        elseif civ.getCity(cityID).owner == tribe then
            state.processedCities[cityID] = false
        end
    end
 
Thank you -- I'll give it a go. I have "city destruction" turned off in the mod... is there a loophole to this?
 
Thank you -- I'll give it a go. I have "city destruction" turned off in the mod... is there a loophole to this?
I presume you're not using civ.deleteCity or civ.killTribe somewhere. Maybe a city starved to death. Or, maybe a city was disbanded by building a settler. I can't think of anything else.
 
Potentially silly question. I know how to relocate a city and how to change owner of a city using Lua. However, is it possible to place a city from scratch, no settler required? What would this entail?

How about renaming a city with Lua?
 
Potentially silly question. I know how to relocate a city and how to change owner of a city using Lua. However, is it possible to place a city from scratch, no settler required? What would this entail?

How about renaming a city with Lua?

createCity
civ.createCity(tribe, tile) -> city

Creates a city owned by `tribe` at the location given by `tile`. Returns `nil` if a city could not be created.

name (get/set)
city.name -> string

Returns the city's name.
 
Thank you. I don't know how I missed those in the Lua Library.

My next question: I am working on a scenario that has 1 map, but would like to add another map. When I try the "import" feature of ToT, the game crashes. The 2nd map I want to add it the same size as the first. Is there a way to hard-code a second map into the scenario? Or do I need to go back to scratch and start a new game with multiple maps? Has anyone else experienced this issue of the game crashing when importing a 2nd map?
 
Thank you. I don't know how I missed those in the Lua Library.

My next question: I am working on a scenario that has 1 map, but would like to add another map. When I try the "import" feature of ToT, the game crashes. The 2nd map I want to add it the same size as the first. Is there a way to hard-code a second map into the scenario? Or do I need to go back to scratch and start a new game with multiple maps? Has anyone else experienced this issue of the game crashing when importing a 2nd map?
I don't know anything about importing maps. @JPetroski has made scenarios with multiple maps, so he can probably help.
 
I have always started a new scenario build to add maps, but the good news at least is you should be able to use Lua to kind of "copy" the placement of everything in one scenario in a "new" scenario.

If you need help setting up multiple maps for a fresh start, let me know. Probably in a different thread though.
 
I have always started a new scenario build to add maps, but the good news at least is you should be able to use Lua to kind of "copy" the placement of everything in one scenario in a "new" scenario.

If you need help setting up multiple maps for a fresh start, let me know. Probably in a different thread though.
Wow, interesting. Thank you for this. OK, I'll keep you posted! Hope to post about my new project in the coming days, but I'd like to have it at a somewhat workable state before then. The last project taught me a lot!
 
Top Bottom