[TOTPP] Lua Scenario Template

Is it too possible to forbid another tribes building certain improvements?
Currently it only works when I'm using the codes for my own tribe. If I add any AI tribe, all buildings available again for all tribes.

LUA itself doesn't show me any error. The consule says that everything is alright.

Can you please post the exact code you've tried? I did a quick test and for my setup it seems to be working. My validation code doesn't catch everything.
 
I used for my own test these two codes:
Code:
improvementBuild[object.iTemple.id] = {forbiddenTribes=object.tHabsburgians}

Code:
improvementBuild[object.iTemple.id] = {forbiddenTribes={[object.tHabsburgians.id]=true}}

Equal which code I use, it doesn't work if I add a second or more tribes.
If I only use it for my own tribe, it works without any problems.
 
This worked for me in the version of the scenario that I have (after setting the prereq for the temple to nil).
Code:
improvementBuild[object.iTemple.id] = {forbiddenTribes={[object.tHabsburgians.id]=true,[object.tFrench.id]=true}}

EDIT: This worked too:
Code:
improvementBuild[object.iTemple.id] = {forbiddenTribes={object.tHabsburgians,object.tFrench}}
 
Hello Prof.Garfield,

unfortunatelly I've a little problem with the diplomacy functions when I'm using LUA. Because I had to rerange all of the units I started again designing the scenario from an empty map.
I'm now setting the diplomacy rules but they don't work for some reason anymore. Within LUA in the diplomacySettings.LUA I'm currently using the following codes:
Code:
diplomacy.setEventTreatiesOnly()

--Habsburgians can negotiate to:
diplomacy.alwaysEnableTreatyChanges(object.tHabsburgians,object.tEnglish)
diplomacy.alwaysEnableTreatyChanges(object.tHabsburgians,object.tFrench)
diplomacy.alwaysEnableTreatyChanges(object.tHabsburgians,object.tProtestants)
diplomacy.alwaysEnableTreatyChanges(object.tHabsburgians,object.tOttomans)
--All other can negotiate to:
diplomacy.alwaysEnableTreatyChanges(object.tFrench,object.tEnglish)
diplomacy.alwaysEnableTreatyChanges(object.tProtestants,object.tEnglish)
diplomacy.alwaysEnableTreatyChanges(object.tFrench,object.tProtestants)
diplomacy.alwaysEnableTreatyChanges(object.tOttomans,object.tEnglish)
diplomacy.alwaysEnableTreatyChanges(object.tOttomans,object.tFrench)
diplomacy.alwaysEnableTreatyChanges(object.tOttomans,object.tProtestants)

Diplomacy should be disabled to ensure that no one can talk with the Neutrals but it should be available for the other civs.
In game I set the diplomacy treaties via cheat menu. Without LUA they are all set, when I copy the LUA files into the scenario folder, all settings are cleared.

Using LUA for diplomacy setting too doesn't work. Should I send you the new files for checking?
 
unfortunatelly I've a little problem with the diplomacy functions when I'm using LUA. Because I had to rerange all of the units I started again designing the scenario from an empty map.

If you only need to delete the units (and nothing else), you can preserve the rest of your work by using a console command to delete the units:
Code:
for unit in civ.iterateUnits() do civ.deleteUnit(unit) end
I've done this a lot to test the between turn events (although now you can use console.onTurn() in the console).

I'm now setting the diplomacy rules but they don't work for some reason anymore. Within LUA in the diplomacySettings.LUA I'm currently using the following codes:

Diplomacy should be disabled to ensure that no one can talk with the Neutrals but it should be available for the other civs.
In game I set the diplomacy treaties via cheat menu. Without LUA they are all set, when I copy the LUA files into the scenario folder, all settings are cleared.

Using LUA for diplomacy setting too doesn't work. Should I send you the new files for checking?

Try this:
1. Comment out diplomacy.setEventTreatiesOnly() (and save the file)
2. Load your game, change some treaties with cheat mode.
3. Activate a unit (the table that stores the treaty information is updated when a unit is activated).
4. Save the game.
5. Uncomment diplomacy.setEventTreatiesOnly()
6. Load the scenario again.

If this doesn't work, send me the files, and the diplomacy that you want to start the scenario with.
 
I didn't know that you added a code for deleting units automatically. Good to know for future projects :)

Your instructions for the diplomacy settings seems to be working, many thanks.
 
I've uploaded the "traits" module. Traits.lua goes in LuaCore, and setTraits.lua is suggested to go in Lua Parameter Files. makeSetTraits.lua can go in the Scripts folder if you have one, but it doesn't really matter where it goes, if you even want to use it. One of your files must have a line
Code:
local setTraits = require("setTraits)
.
It doesn't matter which one, except it can't be one that is required by setTraits.lua (by default, this excludes object.lua). The require line only runs the script, it doesn't provide any information directly.

The purpose of the traits module is to give different objects "traits", or qualities, that can be checked later. Basically, a trait can be thought of as the name of a list, and the trait module allows you to check if an object is in that list.

To assign traits to an object, use
Code:
local traits = require("traits")
traits.allowedTraits("myTrait1","mySecondTrait",{"myThirdTrait","a fourth trait"}) -- can have any number of arguments, each of which is a string or table of strings
traits.assign(object.uMyUnitType,"mySecondTrait",{"myThirdTrait","myTrait1"}) -- can have any number of arguments, each of which (other than the first) is a string or table of strings
traits.assign(object.iMyImprovement,{"a fourth trait"})
traits.conditionalTrait(object.uMyOtherUnitType,"mySecondTrait",function () if civ.getTurn() >= 30 then return true else return false end) -- assigns only 1 trait at a time, third argument is function of form function() --> bool; item has trait if function returns true at time of check.

Check if something has a trait with these functions
Code:
trait.hasTrait(object.uMyUnitType,"mySecondTrait")
trait.hasAllTraits(object.uMyOtherUnitType,"myThirdTrait","a fourth trait") -- can have any number of arguments, each of which (other than the first) is a string or table of strings
trait.hasAnyTrait(object.uMyOtherUnitType,{"myThirdTrait","a fourth trait"}) -- can have any number of arguments, each of which (other than the first) is a string or table of strings

I'll document this stuff soon.
 

Attachments

Just a small question:
I'm using the code
Code:
    local tribe = object.tHabsburgians
        tribe.money = tribe.money + 250
which giving Spain 250 Thaler if they conquer a certain city.

Is it possible to set the "object.t..." neutral, so that the actual tribe who conquers the city will get the 250 Thaler?
 
Is it possible to set the "object.t..." neutral, so that the actual tribe who conquers the city will get the 250 Thaler?

In the cityTaken.onCityTaken function that you would put this event in (or the equivalent function in triggerEvents.lua)
Code:
function cityTaken.onCityTaken(city,defender)
city.owner gives you the tribe that just conquered the city
Code:
function cityTaken.onCityTaken(city,defender)
    if someConditionCheckFn(city,defender) then
        city.owner.money = city.owner.money+250
    end
end
 
I'm having a little trouble using gen.nearbyUnoccupiedTiles. Ideally I'd like to use it for a resistance mechanism so I can have truly random placement of partisans but I was testing it on a cityTaken method. Object.lParis is defined correctely... However this:

Code:
if city == object.cParis then 
local randomTile = gen.nearbyUnoccupiedTiles(object.lParis,4,{0,1,2,3,4,5,6,7,8,9,11,12,13,14,15})
civlua.createUnit(object.uPartisans, object.tUSSR, {{randomTile.x,randomTile.y,randomTile.z}}, {count=10,randomize=true, veteran=false})
civ.ui.text("this is a test to see if the resistance mechanism is working for creating partisans")
end

Produces this error:

Code:
...f Time\Scenario\Hinge of Fate\LuaCore\civluaModified.lua:116: bad argument #1 to 'getTile' (number expected, got no value)
stack traceback:
    [C]: in function 'civ.getTile'
    ...f Time\Scenario\Hinge of Fate\LuaCore\civluaModified.lua:116: in function <...f Time\Scenario\Hinge of Fate\LuaCore\civluaModified.lua:114>
    (...tail calls...)
    ...f Time\Scenario\Hinge of Fate\LuaCore\civluaModified.lua:137: in function 'civluaModified.createUnit'
    ...e\Scenario\Hinge of Fate\LuaTriggerEvents\resistance.lua:161: in function 'resistance.onCityTaken'
    ...cenario\Hinge of Fate\LuaTriggerEvents\triggerEvents.lua:2996: in function 'triggerEvents.onCityTaken'
    D:\Test of Time\Scenario\Hinge of Fate\events.lua:337: in function <D:\Test of Time\Scenario\Hinge of Fate\events.lua:333>

I also tried replacing object.lParis with {84,84,0} but this also didn't work. What is the correct format for this please?
 
Code:
local randomTile = gen.nearbyUnoccupiedTiles(object.lParis,4,{0,1,2,3,4,5,6,7,8,9,11,12,13,14,15})
Looks like you should be using gen.getRandomNearbyUnoccupiedTile(tile,distance,allowedTiles) because gen.nearbyUnoccupiedTiles produces a table of tile objects. Hence
Code:
{randomTile.x,randomTile.y,randomTile.z}
is currently evaluated to
Code:
{nil,nil,nil}
since randomTile only has values for integer keys.

You might also want to use gen.createUnit instead of civlua.createUnit, since it gives you a couple extra options, and accepts tables of tiles for locations if you need that.
 
I ended up using the nearbyOpenTilesForTribe - I had to go use the template/Boudicca to figure it out (so I guess it works since it's been long enough I forgot about it)!. You're right that the gen.createUnit is important here because of the scatter function. This is really going to make this scenario have greater replayability for sure.

Code:
if city == object.cParis then 
local nearbyRecruitmentTiles = gen.nearbyOpenTilesForTribe(object.lParis,4,{0,1,2,3,4,5,6,7,8,9,11,12,13,14,15},object.tUSSR)
gen.createUnit(object.uPartisans, object.tUSSR, nearbyRecruitmentTiles, {count=10,randomize=true, veteran=false,scatter=true})
civ.ui.text("this is a test to see if the resistance mechanism is working for creating partisans")
end
 
In the cityTaken.onCityTaken function that you would put this event in (or the equivalent function in triggerEvents.lua)
Code:
function cityTaken.onCityTaken(city,defender)
city.owner gives you the tribe that just conquered the city
Code:
function cityTaken.onCityTaken(city,defender)
    if someConditionCheckFn(city,defender) then
        city.owner.money = city.owner.money+250
    end
end

Many thanks Prof.Garfield.

It works now:thumbsup:
 
Hello @Prof. Garfield,

I still remember, that you mentioned a script, which automatically fills the object.lua file with all the parameters from the rules.txt file. Does such a script exist and if so, how does it work?
I've currently updated a rules.txt file and would like to put everything into the object.lua file without writing everything again, if possible.
 
Hello @Prof. Garfield,

I still remember, that you mentioned a script, which automatically fills the object.lua file with all the parameters from the rules.txt file. Does such a script exist and if so, how does it work?
I've currently updated a rules.txt file and would like to put everything into the object.lua file without writing everything again, if possible.

Look here:

https://profgarfield.github.io/TheLuaScenarioTemplate.html#building-the-objectlua-file

I think earlier versions of the template had the makeObject.lua file in the LuaCore folder instead, though it may be worth downloading and using the latest version anyway.
 
Look here:

https://profgarfield.github.io/TheLuaScenarioTemplate.html#building-the-objectlua-file

I think earlier versions of the template had the makeObject.lua file in the LuaCore folder instead, though it may be worth downloading and using the latest version anyway.

Many thanks @Prof. Garfield. I've downloaded your latest template and everything worked fine.
Just one question. In the object.lua I have now two lists of cities. One with prefix 'l', the another with prefix 'c'. Which one can I use for the trigger events?
 
Many thanks @Prof. Garfield. I've downloaded your latest template and everything worked fine.
Just one question. In the object.lua I have now two lists of cities. One with prefix 'l', the another with prefix 'c'. Which one can I use for the trigger events?

The prefix 'l' ("location") means that the object is the tile under the city, while the 'c' prefix is for the actual city object. Only use the object.cSomeCity version if cities can't be destroyed in your scenario (there is an "if false then" line that must be changed to "if true then" in object.lua so the city objects are actually created). If cities can be destroyed, use object.lSomeCity.city to get the city (and, of course, make an appropriate check to be sure the city still exists).
 
@Prof. Garfield, I would like to ask you another question.

I'm using an event which should take away 10% of the players treasury for ten turns. Currently I'm using the following code for decreasing the treasury:
Code:
object.pSpanishHabsburgEmpire.money = math.floor(.9*object.pSpanishHabsburgEmpire.money)

Unfortunatelly the game tooks around 34% of the treasury away the first turn, around 10% the second turn, around 43% the third turn and so on. What parameter do I have to use for a fix 10% or 15% decrease every turn?
I've set the Taxes that I have an income of 31 gold and total cost of 28 gold, so that I have more or less 0 income for the test.
 
Back
Top Bottom