[TOTPP] Lua Scenario Template

And is it also possible to set diplomatic relationships via LUA which won't change during the game?
I've a Christian Nations civ, which represents all the minor European Nations during the 16th century. They should only get into war with the Ottoman Empire. With all other major European Nations there should be a peace treaty during the complete game which can't be change.

At the moment, you can set it so that treaties can only be changed by event, by placing a line
Code:
diplomacy.setEventTreatiesOnly(eventTreatiesMsg)
where the argument is the message that you want shown when treaties are restored.

The way it works is that for every unit activation, the game looks at what the treaties "should" be for all players, and restores them. Using the diplomacy module's functions changes the expected treaties.
Code:
-- Provides Functionality related to diplomacy
--  diplomacy.warExists(tribe1,tribe2)-->bool
--  diplomacy.setWar(tribe1,tribe2)
--  diplomacy.clearWar(tribe1,tribe2)
--  diplomacy.contactExists(tribe1,tribe2)-->bool
--  diplomacy.setContact(tribe1,tribe2)
--  diplomacy.clearContact(tribe1,tribe2)
--  diplomacy.ceaseFireExists(tribe1,tribe2)-->bool
--  diplomacy.setCeaseFire(tribe1,tribe2)
--  diplomacy.clearCeaseFire(tribe1,tribe2)
--  diplomacy.peaceTreatyExists(tribe1,tribe2)-->bool
--  diplomacy.setPeaceTreaty(tribe1,tribe2)
--  diplomacy.clearPeaceTreaty(tribe1,tribe2)
--  diplomacy.allianceExists(tribe1,tribe2)-->bool
--  diplomacy.setAlliance(tribe1,tribe2)
--  diplomacy.clearAlliance(tribe1,tribe2)
--  diplomacy.hasEmbassyWith(ownerTribe,hostTribe) -->bool
--  diplomacy.setEmbassyWith(ownerTribe,hostTribe)
--  diplomacy.clearEmbassyWith(ownerTribe,hostTribe)
--  diplomacy.hasVendettaWith(angryTribe,offendingTribe)-->bool
--  diplomacy.setVendettaWith(angryTribe,offendingTribe)
--  diplomacy.clearVendettaWith(angryTribe,offendingTribe)

I should probably change this so that only some treaties are fixed while others are not.

I'm sure @Prof. Garfield can offer something better, but I am sure Lua allows different models of civ-relations, using humanonly and computeronly talkers.

Under the rules events, there is the negotiationSettings.lua file, which has this function
Code:
function negotiationSettings.negotiation(talker,listener)

Talker and listener are tribe objects. If this function returns true, the two tribes can talk to each other, and if false, they can't. At the moment, if false is returned, the talker can't see the listener in the list of tribes in the foreign minister report, which is slightly different than the regular behaviour (where you could check intelligence reports even if you couldn't talk).
 
Good to hear that LUA also allows editing relationships between the civs. May I ask you for an example code preventing the negotiations between two civs? I'm a completly newby writing scripts in LUA. My goal is to understand how they work.

I'm happy that I managed to set which city can build which unit. With your template it works very fine.
Now I'm trying to write my first events in LUA.
 
In the current version of the template, the negotiation bug that existed earlier should be fixed, so you can use the legacy events to set negotiations. If you want to write it in lua, open the LuaRulesEvents directory, and negotiationSettings.lua

In this example, the ottomans can't negotiate with anyone until they and their negotiation partner have the technology associated with aChiristianMuslimDiplomacy in the object file

Code:
local require("object")
function negotiationSettings.negotiation(talker,listener)
    if talker ~= object.tOttomans and listener ~= object.tOttomans then
        return true
    elseif talker:hasTech(object.aChiristianMuslimDiplomacy) and listener:hasTech(object.aChristianMuslimDiplomacy) then
        return true
    else 
        return false
    end
end

If the talker and listener are both not Ottomans, then they can talk. If one of them are the Ottomans, go to the elseif line, where both tribes are checked to have the diplomacy technology, and if they do, they can talk. If one tribe doesn't have it, we move to the else statement, and return false so they can't talk.

Scripting diplomacy is probably not the first thing I would start to learn Lua with. It is not especially difficult, but in most cases you'll have to check a lot of things. There are simpler and more interesting things to write with other events.
 
Many thanks for the code, Prof.Garfield :thumbsup:

You are right, I think I should start with the more or less standard events like city is conquered or unit is killed to understand the basics.
You wrote in some posts before that we shouldn't use the events.lua file and writing our events instead in the triggerEvents.lua file? So this file is my main file where I write all events I will use for the scenario?
 
You wrote in some posts before that we shouldn't use the events.lua file and writing our events instead in the triggerEvents.lua file? So this file is my main file where I write all events I will use for the scenario?

For stuff that doesn't fall under 'rules events', the triggerEvents.lua file is the 'basic' events file. If that file gets too big, you might eventually move the code into the files in the UniversalTriggerEvents directory.
 
I tried to create a simple event for conquering a city by the Habsburgians. Unfortunatelly it doesn't work, maybe it's because I made some stupid mistakes.
I copied a code from @JPetroski 's Boudicca scenario and changed it as followed:

Code:
if city == object.cHavanna and defender == object.tBarbarians and city.owner == object.tHabsburgian then
    gen.justOnce("Havanna conquered",function ()
    civ.ui.text("Havanna conquered by Spanish troops" )
    civlua.createUnit(object.uSpanishPikemen, object.tHabsburgian, {{27,115,0},}, {count=5,randomize=true, veteran=false})
    end)
end

The code is located in the triggerEvents.lua directly behind

Code:
function triggerEvents.onCityTaken(city,defender)
    context[getContext()]["onCityTaken"](city,defender)
    universal["onCityTaken"](city,defender)
    legacy.doCityTakenEvents(city,defender)
end

The game shows me the following error message:
upload_2021-3-28_19-9-44.png


What did I wrong?
 
I hope the file won't be too big. Is there a limit?

Not in terms of text. More in terms of organisation, in the sense that it might be hard to find your way around a single file with 10,000 lines of code and data. You are also limited to 200 local variables per function, and the file itself counts as a function being executed (we ran into this limit in OTR), so if you have lots of helper functions and data variables for those functions, you could run into 200 as we did for OTR. (You can get around this, by placing variables in tables, but it was too hard to find anything in OTR anyway by that point.)

The code is located in the triggerEvents.lua directly behind

It should be inside the function. In programming, a "function" is a series of instructions, and in lua, the keyword function is the beginning of those instructions, and there is an end that finishes them. What you want to try is this:
Code:
function triggerEvents.onCityTaken(city,defender)
   context[getContext()]["onCityTaken"](city,defender)
    universal["onCityTaken"](city,defender)
    legacy.doCityTakenEvents(city,defender)
    if city == object.cHavanna and defender == object.tBarbarians and city.owner == object.tHabsburgian then
        gen.justOnce("Havanna conquered",function ()
        civ.ui.text("Havanna conquered by Spanish troops" )
        civlua.createUnit(object.uSpanishPikemen, object.tHabsburgian, {{27,115,0},}, {count=5,randomize=true, veteran=false})
        end)
    end
end
 
Again many thanks Prof.Garfield.
It works and I also managed that the name of the conquered city will be renamed. For example, Tenochtitlan will be renamed to Mexico City after Spain conquered the city.
I've found the related code in @JPetroski 's Cold War scenario.

I thought I understood more and more the basics how the codes working together, but then I got unfortunatelly the next error message. I copied the code which triggers an event if a certain technology is researched and pasted it behind the function triggerEvent.onTurn.
Code:
function triggerEvents.onTurn(turn)
    context[getContext()]["onTurn"](turn)
    universal["onTurn"](turn)
    delay.doOnTurn(turn)
    legacy.onTurnEventsAndMaintenance(turn)
       
    --Colonization of Cuba
    if  turn >=1 and turn <=140 and civ.hasTech(object.tHabsburgian, civ.getTech(77)) and tribe == object.tHabsburgian then
        justOnce("Colonization of Cuba", function()
        civ.ui.text(func.splitlines("Cuba is colonized"))
         civlua.createUnit(object.uSpanishPikemen, object.tHabsburgian, {{30,116,0}}, {count=5, randomize=true, veteran=true})
    end)
    end
   
end

The game shows me the following error message when the tech 77 is researched:
upload_2021-3-28_22-27-25.png


So I copied the folowing code
Code:
local tribe = civ.getCurrentTribe()
just behind
Code:
legacy.onTurnEventsAndMaintenance(turn)

After researching the technology nothing happens. No error message but also no units appearing on the marked tile.
May I ask you for advice again?

I really have much to learn but it's amazing what LUA allows and I'm excited what will be available in future.
 
The onTurn event happens after player 7 has moved and before player 0 (the barbs) have moved for the next turn. I think that civ.getCurrentTribe() will always return tribe 7 during the onTurn event.

There is an afterProduction event that happens after all city production is computed and before units are moved (it requires an active unit to trigger the event). That event is player dependant, and so uses 'tribe' as one of the arguments.

Remove this line
Code:
local tribe = civ.getCurrentTribe()

If you want the event to take place at the start of the next turn after the Habsburgs get tech 77, remove the
Code:
and tribe == object.tHabsburgian

If you want it to occur during the next after production phase for the Habsburgs, move the check to the afterProuction function. If you want the event to occur in the after production phase of any tribe after the Habsburgs get the tech, move to the afterProduction event and remove the check for the tribe to be the Habsburgs.
 
I've deleted the lines you mentioned and copied the code into the afterProduction function and deleted it in the triggerEvents.onTurn. Now I get the following error message:
upload_2021-3-28_23-38-17.png


I'm just wondering why LUA has a problem with the justOnce value. The justOnce value is located in the generalLibrary and it is activated, at least I found it there. What could it be?
 
Just another little question :)
Is it possible to change the width of the text box via LUA? I would like to make it a little bit bigger.
upload_2021-3-29_20-15-13.png


Is it also possible to give the text a headline, in this case for example "Colonization of Cuba"?
 
Is it also possible to give the text a headline, in this case for example "Colonization of Cuba"?

If you use the text library,
Code:
local text = require("text")
then there is
Code:
text.simple(message,title)

Is it possible to change the width of the text box via LUA? I would like to make it a little bit bigger.

have a look at the dialog object
https://forums.civfanatics.com/threads/totpp-lua-function-reference.557527/#dialog

You create one by
Code:
dialog = civ.ui.createDialog()
 
Many thanks for the reply, Prof.Garfield:)

sorry for asking you again for a maybe simple LUA code but I can`t get it working.
This is what the LUA console writes:
upload_2021-3-29_21-28-52.png


And this is the code I'm currently using:
Code:
if  turn >=1 and turn <=140 and civ.hasTech(object.tHabsburgian, civ.getTech(77)) then
        gen.justOnce("Colonization of Cuba", function()
        dialog = civ.ui.createDialog()
            dialog.title = "Colonization of Cuba"
            dialog.width = 300
            dialog:addText(object.xColonizationCuba1)
        object.cHavanna.owner = object.tHabsburgian
        object.cHavanna.name = "Habana"
        object.cCamaguey.owner = object.tHabsburgian
        object.cMoron.owner = object.tHabsburgian
        object.cSantiagoCuba.name = "Santiago Cuba"
 
sorry for asking you again for a maybe simple LUA code but I can`t get it working.

I should have written
Code:
local dialog = civ.ui.createDialog()

When you first declare a variable, you need to use local. By default, if you use a variable name that hasn't been declared as a local, Lua assumes that you mean the corresponding key in the "Global" table. I've disabled this, since in practice it means that typos turn into bugs that are hard to diagnose.
 
Great, it works now. Your support is really appreciated :thumbsup:

I tried to split the string in two lines because the text is very long and added the value
Code:
\n
right behind the word where the split should appear.

This is the code where I'm using the split
Code:
dialog:addText(func.splitlines("The hope of new ressources and cheap Native labors led the Spanish conquistador Diego Velazquez de Cuellar to Cuba.\n He formed the first Spanish"

Indeed LUA splits the string but doesn't show me the text behind.
upload_2021-3-29_23-6-31.png


Did I forget to use a special symbol?
 
Did I forget to use a special symbol?
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.
 
A strange thought came to me while playing CIV2 today, (unlike most of my strange thoughts, this one is worth mentioning) is there any possibilities for Lua to influnce, clone or change the effects of Wonders? Or it purely a code thing?
 
A strange thought came to me while playing CIV2 today, (unlike most of my strange thoughts, this one is worth mentioning) is there any possibilities for Lua to influnce, clone or change the effects of Wonders? Or it purely a code thing?

The wonder effects are hard coded. However, you can have event effects that change based on the owner of the wonder. So, for example, you could use an onActivation event to mimic the effects of Magellan's expedition by increasing the movement allowance of unit types when the unit is activated by the owner of a wonder.
 
Back
Top Bottom