[TOTPP] Prof. Garfield's Lua Code Thread

Aha! This is a great resource for all. The government modifier is especially interesting to me! Thank you for posting this.

Prof., I've tried a few different combinations of code -- including trying to frankenstein a few pieces of different code -- but can't seem to adjust this to the way I want it. Here it is now. The main issue is that I am seeing (and being asked to choose) for the computer from their lists of cities. I've tried a "if tribe.isHuman then" line, and given the AI a random choice, but it messes with the code. Also, I cannot figure out how to eliminate the first option if the tribe does not have 500 gold. Do you have any advice for me here?

The plus side it does indeed add the improvement to the city chosen!

Spoiler :
Code:
-- The First Olympics

local OlympicGames = civ.ui.loadImage("Images/olympicgames.bmp")
discreteEvents.onCityProcessingComplete(function (turn, tribe)
if turn == 205 then
        local choice = nil
        if tribe.isHuman then
            local dialog = civ.ui.createDialog()
                dialog.title = "The First Olympic Games"
                dialog.width = 500
                dialog:addImage(OlympicGames)
            local multiLineText = "Insert Olympic Text"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Of course! We should show the world our prowess. (500 gold, a city receives Athletic Arena)", 1)
                    dialog:addOption("This is a waste of resources! We need more labor. (receive 2 Laborers)", 2)
                choice = dialog:show()
            else
                choice = math.random(1,2)
            end
                if choice == 1 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 olympicChoice = text.menu(menuTable,"Choose a City.","Menut Title")
                        local chosenCity = nil
                    if olympicChoice >= offset then
                        chosenCity = civ.getCity(olympicChoice-offset)
                    end
                    civ.addImprovement(chosenCity,improvementAliases.Improvement16)
                elseif choice == 2 then
                    gen.createUnit(unitAliases.Laborers,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                end
            end
        end)
 
Prof., I've tried a few different combinations of code -- including trying to frankenstein a few pieces of different code -- but can't seem to adjust this to the way I want it. Here it is now. The main issue is that I am seeing (and being asked to choose) for the computer from their lists of cities. I've tried a "if tribe.isHuman then" line, and given the AI a random choice, but it messes with the code. Also, I cannot figure out how to eliminate the first option if the tribe does not have 500 gold. Do you have any advice for me here?
Have a look at this code. I think it addresses your issues. Let me know if you have more questions.

Code:
if turn == 205 then
    local choice = nil
    if tribe.isHuman then
        local dialog = civ.ui.createDialog()
        dialog.title = "The First Olympic Games"
        dialog.width = 500
        dialog:addImage(OlympicGames)
        local multiLineText = "Insert Olympic Text"
        text.addMultiLineTextToDialog(multiLineText,dialog)
        if tribe.money >= 500 then
            dialog:addOption("Of course! We should show the world our prowess. (500 gold, a city receives Athletic Arena)", 1)
        end
        dialog:addOption("This is a waste of resources! We need more labor. (receive 2 Laborers)", 2)
        choice = dialog:show()
    else
        choice = math.random(1,2)
    end
    if choice == 1 then
        local chosenCity = nil
        if tribe.isHuman then
            local menuTable = {}
            local offset = 3
            for city in civ.iterateCities() do
                if city.owner == tribe then
                    menuTable[offset+city.id] = city.name
                end
            end
            local olympicChoice = text.menu(menuTable,"Choose a City.","Menut Title")
            if olympicChoice >= offset then
                chosenCity = civ.getCity(olympicChoice-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
            local aiChoice = aiChoiceList[math.random(1,index-1)]
            chosenCity = civ.getCity(aiChoice)
        end
        civ.addImprovement(chosenCity,improvementAliases.Improvement16)
        tribe.money = math.max(0,tribe.money - 500)
    elseif choice == 2 then
        gen.createUnit(unitAliases.Laborers,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
    end
end

Note, the AI can still choose option 1 even if it doesn't have 500 gold. My solution was just to set its treasury to 0 in that case. Alternatively, you could only make the human player pay for the privilege. Or, an if statement could change the AI's "choice" to 2 if it doesn't have the money.
 
Works extremely well, Prof, thank you! The improvement is getting built by the AI, and no menus to cycle through for the AI cities. This is great.

The only issue I am having is an error -- even though the code executes without an issue -- the error in the console says: "bad argument #1 to random (interval is empty)" -- seems to be reacting to the "math.random" piece.

Edit: I also noticed that the player, as well, can choose option 1 even if they don't have the money. Would I add a "if tribe.money >= olympicChoice then" line to solve this?
 
Last edited:
The only issue I am having is an error -- even though the code executes without an issue -- the error in the console says: "bad argument #1 to random (interval is empty)" -- seems to be reacting to the "math.random" piece.
Did you happen to be testing on a tribe that has no cities (or no valid cities, if you were doing some other kind of filtering)?

Code:
            if index > 1 then
                local aiChoice = aiChoiceList[math.random(1,index-1)]
                chosenCity = civ.getCity(aiChoice)
            end
        end
        if civ.isCity(chosenCity) then
            civ.addImprovement(chosenCity,improvementAliases.Improvement16)
            tribe.money = math.max(0,tribe.money - 500)
        else
            gen.createUnit(unitAliases.Laborers,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        end
Edit: I also noticed that the player, as well, can choose option 1 even if they don't have the money. Would I add a "if tribe.money >= olympicChoice then" line to solve this?
I did mention that:
Note, the AI can still choose option 1 even if it doesn't have 500 gold. My solution was just to set its treasury to 0 in that case. Alternatively, you could only make the human player pay for the privilege. Or, an if statement could change the AI's "choice" to 2 if it doesn't have the money.
My last option would look something like this:
Code:
    else
        choice = math.random(1,2)
        if tribe.money < 500 then
            choice = 1
        end
    end
 
That fix worked like a charm, Prof.! Thank you.

Also, for the 500 gold issue -- I'm OK with the AI getting the improvement regardless, but more want the player to have the money (I'm giving the AI a huge leg up in this mod, because, well, they need it ;)). At this point, the player can get the improvement even if they don't have the money.

My idea for a fix, and let me know if I'm off base, is to make an optionsTable, with this as a "special effect," and have a choiceInfo piece w/costs, similar to how you constructed the mercenary table. Or is this convoluted?
 
Also, for the 500 gold issue -- I'm OK with the AI getting the improvement regardless, but more want the player to have the money (I'm giving the AI a huge leg up in this mod, because, well, they need it ;)). At this point, the player can get the improvement even if they don't have the money.
The code I provided should do that:
Code:
        if tribe.money >= 500 then
            dialog:addOption("Of course! We should show the world our prowess. (500 gold, a city receives Athletic Arena)", 1)
        end
My idea for a fix, and let me know if I'm off base, is to make an optionsTable, with this as a "special effect," and have a choiceInfo piece w/costs, similar to how you constructed the mercenary table. Or is this convoluted?
I don't understand what you mean by this.
 
I am attempting to create a game-wide message whenever a nuclear weapon is used. I noticed the onUseNuclearWeapon function, and have tried implementing it. My results are either: I can bring up the dialog, but the nuke disappears/doesn't do anything; the nuke does something, but the message only appears if it is the player city. Would you be willing to give some more info on how this function is used?

The other function is the one that makes the AI obey the rules of ranged air units. I'm finding that even when I turn it to "true" for AI, they still do not obey the rules. So I think there is something foundational that I am missing in implementing these codes.

Thanks in advance Prof.! This mod could not be possible without you!
 
I am attempting to create a game-wide message whenever a nuclear weapon is used. I noticed the onUseNuclearWeapon function, and have tried implementing it. My results are either: I can bring up the dialog, but the nuke disappears/doesn't do anything; the nuke does something, but the message only appears if it is the player city. Would you be willing to give some more info on how this function is used?
If the function returns true, then the attack proceeds. If it returns false, the attack is cancelled. My guess is that you removed the return line, which is interpreted as a nil return, which is falsey. Try something like this in EventsFiles\onUseNuclearWeapons.lua

Code:
---Add any events to happen with a nuclear strike, or  
---return false to abort the strike.  Events.lua already
---kills (and performs related events) for units in the
---blast radius 
---@param unit unitObject The weapon (or spy) that is making the nuclear attack.
---@param tile tileObject The location of the attack.
---@return boolean If true, attack proceeds, if false, it is aborted.
function register.onUseNuclearWeapon(unit,tile)
    if tile.city then
        civ.ui.text("Nuclear attack on "..tile.city.name..".")
    else
        civ.ui.text("Nuclear attack at ("..tostring(tile.x)..","..tostring(tile.y)..").")
    end

    local proceedWithAttack = true
    return proceedWithAttack
end

The other function is the one that makes the AI obey the rules of ranged air units. I'm finding that even when I turn it to "true" for AI, they still do not obey the rules. So I think there is something foundational that I am missing in implementing these codes.
I didn't write anything to make the AI air units obey range limitations. I'm pretty sure that in Test of Time they already do.

If you're talking about obeying land and sea ranges, you must explicitly activate that in simpleSettings.lua. I strongly suspect that making the AI obey the limitations will just result in units dying, since the AI won't know that they must be returned to a city periodically.
 
Worked perfectly, Prof., thank you.

I've been bug-hunting all morning, and was wondering if you'd be able to help me find the fault here. Here is some code, which generates a Hero for each tribe when they research Epic Poetry respectively. This works excellently. The Hero generates, and "retires" after 15 turns.

However, when the human player obtains Epic Poetry, I also want a Siren and Charybdis to appear. They are doing so without any error -- and it looks and feels great in-game. However, they do not retire after the 15 turns.

I've then added a test code in there, too, to try to replicate what the Hero does, but with "PirateBireme." This sometimes works, sometimes does not -- no error in console. But when it does work, 6-12 of the Biremes are generated (in random ocean tile, which is great), and then disappear after just 1 turn.

(Note that I've defined the local "tile" functions elsewhere in the code.)

Spoiler :
Code:
unitData.defineCounter("unitRetirementTurn",10000)
local seaPeopleTile1 = getRandomOceanTile()
local seaPeopleTile2 = getRandomOceanTile()
local mythTileOcean1 = getRandomOceanTile()
local mythTileOcean2 = getRandomOceanTile()
local mythTileMountain = getRandomMountainTile()
local disasterTileTemperate = getRandomTemperateTile()
local RegionalUnity = civ.ui.loadImage("Images/regionalunity.bmp")
local EpicPoetry = civ.ui.loadImage("Images/epicpoetry.bmp")
local Literacy = civ.ui.loadImage("Images/literature1.bmp")
discreteEvents.onCityProcessingComplete(function (turn, tribe)
    if tribe:hasTech(techAliases.RegionalUnity) then
        gen.justOnce("SharedBeliefsReceivedBy"..tostring(tribe.id),function()
        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})
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "An Envoy for the Tribes"
                dialog.width = 500
                dialog:addImage(RegionalUnity)
                local multiLineText = "With the development of local faiths and belief systems, your civilization is now\n^prepared to negotiate with the various tribes that inhabit these lands.\n^\n^An Envoy to the tribes has been placed in your capital city. Perhaps you have noticed\n^villages springing up in areas you have already explored. Move the Envoy unit into\n^those tiles to negotiate with a tribe or hire out its services.\n^\n^Note: You will only ever have one Tribal Envoy at any given time. If the unit is\n^killed by barbarians or other civilizations, a new one will generate in your capital city.\n^\n^For more information on Tribal Envoys and tribes, see the Readme file."
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
                end
        end)
    end
    if tribe:hasTech(techAliases.Literacy) then
        gen.justOnce("LiteracyReceivedBy"..tostring(tribe.id),function()
        local choice = nil
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "Early Literature"
                dialog.width = 500
                dialog:addImage(Literacy)
                local multiLineText = "Tales of faith in the gods, legendary accomplishments, and\n^funerary rites have begun to circulate around the known world.\n^\n^^'What you seek you shall never find.\n^^For when the Gods made man,\n^^They kept immortality to themselves.'\n^\n^- The Epic of Gilgamesh\n^\n^Select your people's work of early literature:"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Epic of Gilgamesh (2 woodsmen)", 1)
                    dialog:addOption("Book of the Dead (3 laborers)", 2)
                    dialog:addOption("Tulukti-Ninurta Epic (5 Kassite Chariots)", 3)
                    dialog:addOption("Chronicle of Early Kings (2 settlers)", 4)
                    dialog:addOption("Code of the Nesilim (2 messengers)", 5)
                choice = dialog:show()
            else
                choice = math.random(1,5)
            end
                if choice == 1 then
                gen.createUnit(unitAliases.Ranger,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                elseif choice == 2 then
                gen.createUnit(unitAliases.Laborers,civ.getCurrentTribe(),{0,0},{count = 3, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                elseif choice == 3 then
                gen.createUnit(unitAliases.KassiteChariot,civ.getCurrentTribe(),{0,0},{count = 5, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                elseif choice == 4 then
                gen.createUnit(unitAliases.Settlers,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
                elseif choice == 5 then
                gen.createUnit(unitAliases.Envoy,civ.getCurrentTribe(),{0,0},{count = 2, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
            end
        end)
    end
        if tribe:hasTech(techAliases.EpicPoetry) 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],"unitRetirementTurn",civ.getTurn()+15)
        end
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "Heroes of Epic Poetry"
                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 15 turns before they vanish permanently. For a full\n^list of what Heroes can do, see the Civliopedia or Readme."
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
            local createdUnits2 = civ.createUnit(unitAliases.Siren,civ.getTribe(0),mythTileOcean1)
            civ.createUnit(unitAliases.Charybdis,civ.getTribe(0),mythTileOcean2)
            if createdUnits2[1] then
            unitData.counterSetValue(createdUnits2[1],"unitRetirementTurn",civ.getTurn()+15)
        end
        end
    end)
        if turn == 3 then
        local createdUnits3 = gen.createUnit(unitAliases.PirateBireme,civ.getTribe(0),seaPeopleTile1,{count = 3, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        if createdUnits3[1] then
            unitData.counterSetValue(createdUnits3[1],"unitRetirementTurn",civ.getTurn()+15)
        end
        if tribe.isHuman then
        civ.ui.text("Test")
        end
        end
    end
    for unit in civ.iterateUnits() do
        if unit.owner == tribe and unitData.counterGetValue(unit,"unitRetirementTurn") <= turn then
            gen.killUnit(unit)
        end
    end
end)
 
However, when the human player obtains Epic Poetry, I also want a Siren and Charybdis to appear. They are doing so without any error -- and it looks and feels great in-game. However, they do not retire after the 15 turns.
Code:
            local createdUnits2 = civ.createUnit(unitAliases.Siren,civ.getTribe(0),mythTileOcean1)
            civ.createUnit(unitAliases.Charybdis,civ.getTribe(0),mythTileOcean2)
            if createdUnits2[1] then
            unitData.counterSetValue(createdUnits2[1],"unitRetirementTurn",civ.getTurn()+15)
        end
civ.createUnit generates a unitObject, not a table of unitObjects, so createdUnits2 is actually the siren unit, and createdUnits[1] is nil, since a unitObject doesn't have a value for key 1. Similarly, the Charybdis isn't even assigned to a variable.

I've then added a test code in there, too, to try to replicate what the Hero does, but with "PirateBireme." This sometimes works, sometimes does not -- no error in console. But when it does work, 6-12 of the Biremes are generated (in random ocean tile, which is great), and then disappear after just 1 turn.
I think the standard rules.txt file has a setting to stop barbarian units from disappearing. (They sometimes do as part of normal gameplay, I presume if they're too far from anything to attack.)
Code:
        local createdUnits3 = gen.createUnit(unitAliases.PirateBireme,civ.getTribe(0),seaPeopleTile1,{count = 3, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        if createdUnits3[1] then
            unitData.counterSetValue(createdUnits3[1],"unitRetirementTurn",civ.getTurn()+15)
        end
Note that here you've created several pirate briremes, but you're only assigning a retirement turn to the first one. You should be using code like this
Code:
for _,createdUnit in pairs(createdUnits3) do
    unitData.counterSetValue(createdUnit,"unitRetirementTurn",civ.getTurn()+15)
end
 
Aha, yes, rules.txt does have that! That issue is solved. Also, the units are retiring when they're supposed to.

The only issue I'm still having is that, for some reason, a ton of the pirates are generating -- instead of the just 3.
 
The only issue I'm still having is that, for some reason, a ton of the pirates are generating -- instead of the just 3.
Your event is creating pirates after city processing is complete for each tribe. You should check that the tribe is the barbarian tribe before running that section of code.
 
Hello! Today I have two queries.

The first is using the coverTile function. This works great with pre-defined maps. Is there a way to make the tileObject categories on the map? What I mean is, I am trying to make it so that at a certain turn, the map is covered -- with the exception of Ocean tiles and City Radius tiles (of the currentTribe). tileObject is coordinates, but any way to make it a terrainType, or everything excluding city radii?

The second is about quantifying reputation. I noticed there is not much written about reputation (or did I miss something?). Can this also be increased as w/food, production, money, science? Is there a function out there for it? (I've seen the Diplomacy functions, but nothing to just increase the quantity of reputation points, which has similar effect to, say, Eiffel Tower.)
 
The first is using the coverTile function. This works great with pre-defined maps. Is there a way to make the tileObject categories on the map? What I mean is, I am trying to make it so that at a certain turn, the map is covered -- with the exception of Ocean tiles and City Radius tiles (of the currentTribe). tileObject is coordinates, but any way to make it a terrainType, or everything excluding city radii?
The tile argument can be a tile object as well, not just a coordinate triple (the way you wrote the question suggests you might not have realized that).

I think what you want is to do a loop over tiles
Code:
for tile in civlua.iterateTiles() do
    if tile.baseTerrain.type ~= 10 then
        for tribe in civlua.iterateTribes() do
            gen.coverTile(tile,tribe)
To check if the tile is in a city radius, you'd do something like
Code:
function isInCityRadius(tile,tribe)
    for _,nearbyTile in pairs(gen.cityRadiusTiles(tile)) do
        if tile.city and tile.city.owner == tribe then
            return true
        end
    end
    return false
end
This could end up being slow, depending on how large the map is, and the amount of it that is not ocean. You may wish to warn the player that it will take some time. If it is too slow even for a one off event, let me know and I can give some thought to speeding up the checks. One way would be to loop through the cities, and record the tiles within the city radius in a table (with gen.getTileID(tile) as the key), and then check that table for whether the tile is in a radius or not.

The second is about quantifying reputation. I noticed there is not much written about reputation (or did I miss something?). Can this also be increased as w/food, production, money, science? Is there a function out there for it? (I've seen the Diplomacy functions, but nothing to just increase the quantity of reputation points, which has similar effect to, say, Eiffel Tower.)
Here's some documentation of the tribe object. Since you can set these values, you can change them if desired. I don't know what these values mean exactly.

attitude (get/set)
tribe.attitude[otherTribe] -> integer

Returns the tribe's attitude to `otherTribe`.

betrayals (get/set)
tribe.betrayals -> integer

Returns the number of times the tribe has betrayed another tribe.

reputation (get/set)
tribe.reputation[otherTribe] -> integer

Returns the tribe's reputation with `otherTribe`.
 
The cover tiles part worked really well! Thank you! I can report that on a medium-sized map, it happened in an instant -- no lag whatsoever. Perhaps on a custom-made mega map, though, it would stutter or take longer. What a great feature. For my purposes, too, what is interesting is that when the tiles are covered, the cities no longer register them in radius until they are "re-discovered." This leads to effects that are highly desirable for my purposes!

Aha, I now see that in the lua function thread, too (about attitude). I could then specify "otherTribe" to be conditional on something else. E.g., could "otherTribe" be loser.owner, for example? Any tribe object?

My main goal right now is for a dialog to pop up when a "nuke" is used, which would give the player (or AI, if the player is the victim -- but I need this dialog to pop up for all civs except the "victim" in their next turns), 3 choices: send money, send labor, or do nothing -- for the city.tile.owner victim. So, in the onUseNuclearWeapons file, I've tried editing the civ.ui.text to a text dialog that is more complicated, but it doesn't seem to recognize those functions in that file.

Any ideas for how to streamline this or put this event elsewhere? Or is it a matter of copying those functions I wish to use into the onUseNuclearWeapons.lua file?
 
My main goal right now is for a dialog to pop up when a "nuke" is used, which would give the player (or AI, if the player is the victim -- but I need this dialog to pop up for all civs except the "victim" in their next turns), 3 choices: send money, send labor, or do nothing -- for the city.tile.owner victim. So, in the onUseNuclearWeapons file, I've tried editing the civ.ui.text to a text dialog that is more complicated, but it doesn't seem to recognize those functions in that file.

Any ideas for how to streamline this or put this event elsewhere? Or is it a matter of copying those functions I wish to use into the onUseNuclearWeapons.lua file?
It might be easiest to use the delayedAction module. Write (and register) a function as if the event could be executed immediately, then rely on the delayedAction module to postpone it to the player's next turn. The function you register takes a table as an argument, and specifying an argumentTable is part of setting up the delayed event. Let me know if you need more guidance.

Code:
-- A module for specifying an action which might have to wait until
-- a different player's turn, (or, a turn at some point in the future)
-- 
-- Functions that can be delayed will be provided to this module in
-- a table indexed by strings
-- These functions will take a table as their argument.
-- The keys to the argument table must be strings or numbers,
-- and the values must be strings, numbers, or tables
-- (and each table must only have strings, numbers, and tables)
--
-- usage:
-- delay = require("delayedAction")
--
--  To enable a function to be delayed
-- delay.makeFunctionDelayable(functionNameString,function)
--
-- To delay a function use one of these two functions
--  delay.doInFuture(functionNameString,argumentTable,turn,tribeID=-1)
--      performs an action specified by the functionNameString
--      and the argumentTable, on the turn specified
--      happens after production of the tribe associated with tribeID,
--      or onTurn, if submitted tribeID is -1
--
-- delay.doNextOpportunity(functionNameString,argumentTable={},tribeOrTribeID=-1)
--      performs a delayed action the next time a tribe is active, or immediately
--      if the tribe is the currently active tribe.  If no tribe is specified,
--      or the tribeID specified is -1,
--      the action will be performed with the onTurn actions for the next turn
--      if no argumentTable is specified, an empty table is generated
Any ideas for how to streamline this or put this event elsewhere? Or is it a matter of copying those functions I wish to use into the onUseNuclearWeapons.lua file?
Based on the documentation, you could register a delayed action function in any file that you like, and then just call delay.doNextOpportunity from the onUseNuclearWeapons.lua file.

Aha, I now see that in the lua function thread, too (about attitude). I could then specify "otherTribe" to be conditional on something else. E.g., could "otherTribe" be loser.owner, for example? Any tribe object?
Yes, any tribeObject can be used for otherTribe.
 
Very interesting! I gave it a shot, but I think the 2nd paragraph in the explanation above has me confused. (about the functions taking a table as their argument)
Here is what I cobbled together:
Spoiler :
Code:
function register.onUseNuclearWeapon(unit,tile)
    if tile.city then
        do delay.doNextOpportunity(functionNameString,argumentTable={},tribeOrTribeID=-1)
        local tribe = civ.getCurrentTribe()
        if tribe.isHuman then
        local dialog = civ.ui.createDialog()
                dialog.title = "A Terrible Disaster"
                dialog.width = 500
                local multiLineText = "Our people continue to hear stories of victims from"..tile.city.name..". What should we do?"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Send their leader gold! We should help those in need. (-300 gold; +reputation with victim)", 1)
                    dialog:addOption("This is most concerning. Let us join their rebuilding efforts! (-1000 gold; +reputation with all civs; +Laborers in victim city)", 2)
                    dialog:addOption("We have our own problems during these dark times. (+Migrants in victim city)", 3)
                choice = dialog:show()
        else
            choice = math.random(1,3)
            if tribe.money < 300 then
                choice = 3
            end
end
        if choice == 1 then
                tile.city.owner.money = tile.city.owner.money +1000
        elseif choice == 2 then
                civ.createUnit(unitAliases.Laborers,tile.city.owner,tile.city.location)
        elseif choice == 3 then
                gen.createUnit(unitAliases.Migrants,tile.city.owner,tile.city.location,{count = 5, randomize = false, scatter = false, inCapital = false, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
        end
end
        local proceedWithAttack = true
        return proceedWithAttack
    end
end
 
Here's a simple example
Code:
local function nukeMessage(argTable)
    civ.ui.text("Nuclear attack at "..argTable.cityName.."!")
end
delayedAction.makeFunctionDelayable("sampleDelayedFunction",nukeMessage)

function register.onUseNuclearWeapon(unit,tile)
    if tile.city then
        for tribeID = 1,7 do
            if unit.owner.id ~= tribeID then
                delayedAction.doNextOpportunity("sampleDelayedFunction",{cityName = tile.city.name},tribeID)
            end
        end
    end
    return true
end
 
Top Bottom