[TOTPP] Lua Scenario Template

Now that is a nice idea...!
Making a wonder-holder have boosts to unit stats is indeed food for thought. :)
 
Yes, with Lua you can add effects to any wonder, up to the limits of what Lua can do. So for example, you couldn't directly add the effect of "acts like a Library in every city" because there isn't a command or function for that. But you could have the event actually give a Library to every city (that didn't have one already) and then also, each turn, reimburse you for the maintenance cost of each Library you have.

In order to remove the native effects of a wonder, you simply need to expire it. If you're placing wonders at the beginning of a scenario, you just need to reserve one tech for "Wonder expiration" and give it to all tribes. If you want a wonder to be buildable within the game, you probably can't expire it in advance because (I suspect) that greatly reduces AI interest in building it. So you'd need to reserve a separate tech for each wonder that you want to expire, and then hand out that tech to all tribes immediately after the wonder is built. Of course any event-based effects you add could simply ignore the fact that the wonder is expired, and look solely at which tribe owns it.

Medieval Millennium contains a couple instances of this, because I wanted to include all 28 wonders in the game but wanted to reduce the power of some of them. So I expire the wonder upon construction and then handle all of its new (replacement) effects with events.
 
You need to write \n^, however if you're creating the dialog box manually, I think it will only add the first line. The text module has the following function to overcome that (and you don't have to use func.splitlines).
Code:
--  text.addMultiLineTextToDialog(text,dialogObject) --> void

You can add text to the archive to be reviewed later with
Code:
--  text.addToArchive(tribe or TribeID,messageBody,messageTitle,archiveTitle)-->void
and
Code:
--  text.displayNextOpportunity(tribe or tableOfTribes,messageBody,messageTitle="",
--              archiveTitle=nil, broadcast=nil)

can display and archive in one line (though you would lose manual control over width, unless I update the module), as well as save a message for a particular player's turn.

I played a little bit around with the codes you mentioned but I see that my programming skills are very limited. Whatever I made or wrote, I always got an error on the LUA console.
At least, this is just a visual issue and not really important. So I will try to solve it when the scenario is nearly ready.

I'm happy that I'm able to create easy events like city taken, give technology and on specific turn xx should happen yy with LUA. For me a big step forward. Currently I'm trying to understand how the flags, which I also used in the old macro world, are working in LUA.
 
If you want to send me a file where you tried to use one of those functions, I can give you an example of what actually should have been done.

I'm happy that I'm able to create easy events like city taken, give technology and on specific turn xx should happen yy with LUA. For me a big step forward. Currently I'm trying to understand how the flags, which I also used in the old macro world, are working in LUA.

Flags in lua are different from flags in the macro system. They're just a way to store true or false in the 'state' table, without worrying about the details. Unlike macro system flags, they keep their current value until you change it.

In your object file (doesn't have to be there, but it is convenient), add lines for each of the flags you want

Code:
flag.define("FlagOne",true) -- FlagOne is true by default
flag.define("FlagTwo",false)-- FlagTwo is false by default
You use flags with the commands
Code:
flag.value("FlagName") -- returns the current value (true or false) of the flag
flag.setTrue("FlagName") -- sets the value of the flag to true
flag.setFalse("FlagName") -- sets the value of the flag to false
flag.toggle("FlagName") -- changes the flag from true to false, or false to true

Remember to have the line
local flag = require("flag")
in any file where you use flags.
 
Many thanks Prof. Garfield :thumbsup:
attached are the triggerEvent file, on line 172 you will find the code for the dialog options I tried to use.

This is the error message the game shows me, when I load the savegame:
upload_2021-3-31_21-49-48.png


If I'm right the game expects a command after 'do'. I thought 'dialog:addText' in the next line would be the command.
 

Attachments

If you want to send me a file where you tried to use one of those functions, I can give you an example of what actually should have been done.



Flags in lua are different from flags in the macro system. They're just a way to store true or false in the 'state' table, without worrying about the details. Unlike macro system flags, they keep their current value until you change it.

In your object file (doesn't have to be there, but it is convenient), add lines for each of the flags you want

Code:
flag.define("FlagOne",true) -- FlagOne is true by default
flag.define("FlagTwo",false)-- FlagTwo is false by default
You use flags with the commands
Code:
flag.value("FlagName") -- returns the current value (true or false) of the flag
flag.setTrue("FlagName") -- sets the value of the flag to true
flag.setFalse("FlagName") -- sets the value of the flag to false
flag.toggle("FlagName") -- changes the flag from true to false, or false to true

Remember to have the line
local flag = require("flag")
in any file where you use flags.

Many thanks for the codes. Good to know that the flags in LUA are different from those in the macro system.
I think I understand a little bit how they are working, at least I hope so.:)
 
This is what you have:

Code:
        local dialog = civ.ui.createDialog()
            dialog.title = "Colonization of Cuba"
            dialog.width = 800
            local function addMultiLineTextToDialog()
                local lineTable = {func.splitlines(text)}
                    for i=1,i=2,i=3#lineTable do
                        dialog:addText("The hope of new ressources and cheap Native labors led the Spanish conquistador Diego Velazquez de Cuellar to Cuba. He formed the first Spanish settlement on the caribbean island and got orders from the Spanish crown to conquer Cuba.", 1)
                        dialog:addText("The prolonged guerilla campaign of the local population didn't prevent the invasion, in only three years the Spanish troops gained complete control of Cuba. Hatuy and other local chieftains were captured and burnt alive.", 2)
                        dialog:addText("Diego Velazquez became first governor of Cuba. Under his rule the Spanish established sugar and tobacco as Cuba's primary products, and the island soon supplanted Hispaniola as the prime Spanish base in the Caribbean.", 3)
                    end
            end
            dialog:show()

It should be replaced with this (not tested, but I'm pretty sure it is correct)

Code:
        local dialog = civ.ui.createDialog()
        dialog.title = "Colonization of Cuba"
        dialog.width = 800
        local multiLineText = "The hope of new ressources and cheap Native labors led the Spanish conquistador Diego Velazquez de Cuellar to Cuba. He formed the first Spanish settlement on the caribbean island and got orders from the Spanish crown to conquer Cuba.\n^The prolonged guerilla campaign of the local population didn't prevent the invasion, in only three years the Spanish troops gained complete control of Cuba. Hatuy and other local chieftains were captured and burnt alive.\n^Diego Velazquez became first governor of Cuba. Under his rule the Spanish established sugar and tobacco as Cuba's primary products, and the island soon supplanted Hispaniola as the prime Spanish base in the Caribbean."
        text.addMultiLineTextToDialog(multiLineText,dialog)
        dialog:show()

If I reference a function in a module like text or the generalLibrary, all you have to do is write the function name (in this case text.addMultiLineTextToDialog) and replace the items in the parentheses with the corresponding values from your code (in this case 'text' and 'dialogObject' are replaced by 'multiLineText' and 'dialog', since those are the names given in this code).
 
I have a stupid question. What does "disabling the global" do, and is there any way to selectively reintroduce it? I had @SorFox 's transportation module working pre-template, but as it uses globals it no longer functions. I'm wondering if there is a way to make it compatible with the module. If not, I might as well rework some of the units in a scenario I'm building.
 
I have a stupid question. What does "disabling the global" do, and is there any way to selectively reintroduce it? I had @SorFox 's transportation module working pre-template, but as it uses globals it no longer functions. I'm wondering if there is a way to make it compatible with the module. If not, I might as well rework some of the units in a scenario I'm building.

in events.lua, there is this line:

Code:
-- noGlobal prevents new global variables from being created
-- or accessed; this should make typos easier to discover
gen.noGlobal()

comment out gen.noGlobal() and you can have global variables.

You can fix the module by finding the first instance of each variable, and writing local before it. If the first instance is in an If statement or something, you might need a
Code:
local myFormerlyGlobalVariable = nil
outside of the if statement.

The no globals error will give you the name of the variable in question.
 
Hi,

Your polygon script does not have the third (map) set of coordinates. I have a scenario with multiple maps. I assume I will not break anything by manually entering the map coordinates on these, so long as they are all there, but I wanted to check with you first.

local britainPolygonCoordinates = {{87,67},{82,72},{54,74},{54,62},{60,50},{60,26},{75,9},{86,20},{87,39},}

As an aside, I think something you may wish to include in the template download is the script you use for populating (roughly) the object file. Or, perhaps there would be value in a "quick scripts package" with some little helper functions for design? Anything that can save a few hours work should help people churn out scenarios to play.
 
Hi,

Your polygon script does not have the third (map) set of coordinates. I have a scenario with multiple maps. I assume I will not break anything by manually entering the map coordinates on these, so long as they are all there, but I wanted to check with you first.

local britainPolygonCoordinates = {{87,67},{82,72},{54,74},{54,62},{60,50},{60,26},{75,9},{86,20},{87,39},}

--#gen.inPolygon(tile,tableOfCoordinates)-->bool
-- the table of coordinates defines the corners of the
-- polygon. Returns true if the tile is within the
-- polygon defined by the table of coordinates, and
-- false otherwise. Checking that the map is correct
-- must be done separately
-- the entry:
-- tableOfCoordinates.doesNotCrossThisX
-- sets an x coordinate that the polygon does not
-- cross. If absent, 0 is used,
-- meaning the polygon shouldn't cross the date line

You'll have to make a separate check for the map. Making the polygon yourself is perfectly fine, assuming the coordinates are valid.

As an aside, I think something you may wish to include in the template download is the script you use for populating (roughly) the object file. Or, perhaps there would be value in a "quick scripts package" with some little helper functions for design? Anything that can save a few hours work should help people churn out scenarios to play.

I didn't actually have a script for that. It just so happens that the text editor I use (VIM) makes that job fairly easy. Now that I think about it, I may actually have an easy way to make the object file.
 
As an aside, I think something you may wish to include in the template download is the script you use for populating (roughly) the object file. Or, perhaps there would be value in a "quick scripts package" with some little helper functions for design? Anything that can save a few hours work should help people churn out scenarios to play.

This script will create a new object file in your main test of time directory (was easiest to put it there). The file name starts with the operating system time, so nothing should be overwritten.

The file it produces looks good, but I didn't have anything to easily test it with. If someone wants to test it on a new scenario before I can get to it, that would be appreciated.

EDIT: deleted makeObject.lua.zip, since I reuploaded a modified version a couple posts down.
 
Last edited:
This is what you have:

Code:
        local dialog = civ.ui.createDialog()
            dialog.title = "Colonization of Cuba"
            dialog.width = 800
            local function addMultiLineTextToDialog()
                local lineTable = {func.splitlines(text)}
                    for i=1,i=2,i=3#lineTable do
                        dialog:addText("The hope of new ressources and cheap Native labors led the Spanish conquistador Diego Velazquez de Cuellar to Cuba. He formed the first Spanish settlement on the caribbean island and got orders from the Spanish crown to conquer Cuba.", 1)
                        dialog:addText("The prolonged guerilla campaign of the local population didn't prevent the invasion, in only three years the Spanish troops gained complete control of Cuba. Hatuy and other local chieftains were captured and burnt alive.", 2)
                        dialog:addText("Diego Velazquez became first governor of Cuba. Under his rule the Spanish established sugar and tobacco as Cuba's primary products, and the island soon supplanted Hispaniola as the prime Spanish base in the Caribbean.", 3)
                    end
            end
            dialog:show()

It should be replaced with this (not tested, but I'm pretty sure it is correct)

Code:
        local dialog = civ.ui.createDialog()
        dialog.title = "Colonization of Cuba"
        dialog.width = 800
        local multiLineText = "The hope of new ressources and cheap Native labors led the Spanish conquistador Diego Velazquez de Cuellar to Cuba. He formed the first Spanish settlement on the caribbean island and got orders from the Spanish crown to conquer Cuba.\n^The prolonged guerilla campaign of the local population didn't prevent the invasion, in only three years the Spanish troops gained complete control of Cuba. Hatuy and other local chieftains were captured and burnt alive.\n^Diego Velazquez became first governor of Cuba. Under his rule the Spanish established sugar and tobacco as Cuba's primary products, and the island soon supplanted Hispaniola as the prime Spanish base in the Caribbean."
        text.addMultiLineTextToDialog(multiLineText,dialog)
        dialog:show()

If I reference a function in a module like text or the generalLibrary, all you have to do is write the function name (in this case text.addMultiLineTextToDialog) and replace the items in the parentheses with the corresponding values from your code (in this case 'text' and 'dialogObject' are replaced by 'multiLineText' and 'dialog', since those are the names given in this code).

Again many thanks for your help.:thumbsup:
So I only had to add the function name and replaced the items in the parentheses with the names I'm using in my code. That's easy to understand. The more I play around with the LUA codes, the more I understand at least the basics of it.

The text splitting works but it looks a little bit funny in game. First I thought I have to change the width of the text box, but equal which parameter I use, nothing have an effect. I'm afraid it's a bug within the game itself.
upload_2021-4-1_16-37-3.png
 
The text splitting works but it looks a little bit funny in game. First I thought I have to change the width of the text box, but equal which parameter I use, nothing have an effect. I'm afraid it's a bug within the game itself.

Try putting a few extra newline (\n) characters in your text. Without the ^, it shouldn't display as a new line, but I think it will help the game display the text properly.
 
A couple tweaks added (still haven't tested on a new scenario). Now, if there would be duplicate entries in the object table, an underscore is added to the entry until the new entry is distinct. By looking for underscores, the designer can change the name to whatever he or she wants. I also changed the 'tribe' prefix to 'p' for "player", since we're probably going to need 't' for terrain, and I couldn't think of a good alternate letter.

EDIT: Again removed attachment due to code error. Good version below.
 
Last edited:
This script will create a new object file in your main test of time directory (was easiest to put it there). The file name starts with the operating system time, so nothing should be overwritten.

The file it produces looks good, but I didn't have anything to easily test it with. If someone wants to test it on a new scenario before I can get to it, that would be appreciated.

I tested this and got the following error:

Code:
D:\Test of Time\Scenario\Italy\LuaCore\generalLibrary.lua:2768: The Global table can't accept values for indices that don't already exist.  Key value is: file
stack traceback:
    [C]: in function 'error'
    D:\Test of Time\Scenario\Italy\LuaCore\generalLibrary.lua:2768: in metamethod '__newindex'
    D:\Test of Time\makeObject.lua:15: in main chunk

The object file that is produced is a 0kb file with nothing in it. Any ideas?
 
I made 'file' a local this time. I'm not sure why I didn't catch it. 'Row' was caught and fixed, so I wonder how come file didn't get caught for me.
 

Attachments

Not only did it work, it worked like a charm. There were significant "special characters" in the rules file that this just cut through. This is definitely worth an add to the template (and my updating the designer readme) when there's time. Thanks!
 
Back
Top Bottom