Prof. Garfield

Deity
Supporter
Joined
Mar 6, 2004
Messages
4,363
Location
Ontario
This thread is meant to serve two related purposes. The first is to provide a general Q&A thread for Lua and related topics. The second is to provide a link index for questions and their answers, as well as other resources. I'll edit this post periodically to add links to the questions and answers. This way, there is a convenient place to see if a topic has been addressed.

Don't worry about if a question has been addressed elsewhere, feel free to ask it here anyway. If you know of questions and answers elsewhere on the forums, it would be helpful to post a link in this thread, and I'll add it to the Q&A List. Also, if a question asked here turns out to require substantial coding and/or discussion, please move it to its own thread, or the Lua Scripting Possibilities thread, and provide a link. As a rule of thumb, I'd say after ~6 posts, strongly consider if the discussion should be moved elsewhere.

Questions and Answers
How do I convert my existing scenario to Lua, and take advantage of build option restrictions?
How do I add a wonder to a city?
(Delayed Action Module) How can a delayed action use information that is only available when the action is first delayed? (Question, Answer)
How do I move a city?
How do I add or remove a river?
How do I stop certain ground units from being airlifted?
What is the difference between civ.createUnit, civlua.createUnit, and gen.createUnit, and how do I know which one to use?
How do you add/remove an improvement (or wonder) from a city be it either when a specific turn is reached or when a city is taken?
How do I make nested menus?
How do I make an event fire if a unit is destroyed on a specific tile? (Question, Answer)
How do I add/remove pollution from a tile?
If the River/Road/Railroad/Alpine movement multipliers are different, which one is chosen?
What happens if I use Lua to give a unit a non-integer movement allowance?
Is there a way to set (or increase/decrease) the number of unhappy citizens via some sort of function? Suggestion 1. Suggestion2.
How can I have 2 (or more) sets of conditions for building an item, where only one set of conditions has to be true?

Links to Scripts and Resources
How can I copy my scenario to a larger map?
Download the Lua Scenario Template.
 
Last edited:
Could you please provide some clarity in working around the globals situation with your template? I know you've done this in the past, but what I'm specifically trying to help Techumseh with is an event where units show up in or around a city at a delayed point in the future. The problem is "city" isn't recognized. I believe what I need to do is include a local definition of city within this code, however:

local city = civ.getCity() needs a key, and CityID isn't working, and I also want this event to happen for every city. Do you have advice on what to put here? I wonder if a list of these sort of things would be useful at some point as well.

Code:
local function createPartisansOnCityCapture(argTable)

local nearbyRecruitmentTiles = gen.nearbyOpenTilesForTribe({city.location.x,city.location.y,city.location.z},5,{0,1,2,3,4,5,6,7,9,11,12,13,14,15},object.pCommunists)
        gen.createUnit(object.uGuerrillaC, object.pCommunists, nearbyRecruitmentTiles, {count=3,randomize=true, veteran=false,scatter=true})
        civ.ui.text("Communists guerillas strengthen their position near "..city.name)
end
delayedAction.makeFunctionDelayable("createUnit",createPartisansOnCityCapture)
(Note this is just testing code and isn't the "correct" civ/units/etc. for the scenario)
 
Could you please provide some clarity in working around the globals situation with your template? I know you've done this in the past, but what I'm specifically trying to help Techumseh with is an event where units show up in or around a city at a delayed point in the future. The problem is "city" isn't recognized. I believe what I need to do is include a local definition of city within this code, however:

local city = civ.getCity() needs a key, and CityID isn't working, and I also want this event to happen for every city. Do you have advice on what to put here? I wonder if a list of these sort of things would be useful at some point as well.

Globals wouldn't help you here if they were available. What you have to do is pass the information through the "argument table." When you use delay.doInFuture, you can specify a table to be used as the argument for the delayed function. Since this table is being saved in the state table, it should only have strings and numbers keys and values. (Values can also be tables with string and number components.)

Here, we'll store the id of the tile that the city is on (just in case the city is destroyed later):
Code:
{cityTileId = gen.getTileId(city.location)}
Other options would be the x,y,z coordinates of the city tile, or the city's id number.

Your code would look something like this (untested):
Code:
local function createPartisansOnCityCapture(argTable)
    local cityLocation = gen.getTileFromId(argTable.cityTileId)
    local city = cityLocation.city
    local nearbyRecruitmentTiles = gen.nearbyOpenTilesForTribe(cityLocation,5,{0,1,2,3,4,5,6,7,9,11,12,13,14,15},object.pCommunists)
    gen.createUnit(object.uGuerrillaC, object.pCommunists, nearbyRecruitmentTiles, {count=3,randomize=true, veteran=false,scatter=true})
        civ.ui.text("Communists guerillas strengthen their position near "..city.name) -- if the city can be destroyed, city.name won't work
end
delayedAction.makeFunctionDelayable("createUnit",createPartisansOnCityCapture)

Code:
function discreteEvent.onCityTaken(city,defender)
    local futureTurn = civ.getTurn()+param.partisanDelay
    delay.doInFuture("createUnit",{cityTileId=gen.getTileId(city.location)},futureTurn,object.pCommunists.id)
end
 
Question (from a PM I received):

What is the difference between civ.createUnit, civlua.createUnit, and gen.createUnit, and how do I know which one to use?

Answer:

The civ.createUnit function is the function that actually tells the game to do something. This information is provided by the Lua Function Reference:

createUnit
civ.createUnit(unittype, tribe, tile) -> unit

Creates a unit of type `unittype`, owned by `tribe`, at the location given by `tile`.

civ.createUnit will create the unit no questions asked, unless it isn't provided a valid unittype, tribe, or tile. It doesn't care if you're trying to create a land unit on the ocean, or if the destination tile is occupied by another tribe. If you want to set the home city or veteran status, you must write lines for that. Want to make multiple units? You must write a loop. Don't want the unit to appear on another tribe's tile? You must write code to check if the tile is clear, and only create the unit if it is. Want the unit to randomly choose one of 4 tiles? Your code will have to select the tile first.

Using civ.createUnit is likely to require you to ask and answer a lot of questions in your code. That means thinking about details and debugging those details. civlua.createUnit and gen.createUnit both allow you to provide some extra information in the arguments, and then handle details behind the scenes.

@TheNamelessOne wrote civlua.createUnit to recreate the functionality and options of the Create Unit macro event. Ground units won't be created at sea, you can provide a list of tiles and the unit will be placed on the first valid one, etc. If you want this kind of functionality, civlua.createUnit does it more easily and reliably than civ.createUnit.

Here is the information from civlua.lua:
Code:
--[[
Create (a) unit(s) of type `unittype`, owned by tribe `tribe`. This is the Lua implementation of the CreateUnit action.
`locations` is a list of tile coordinates, like {{0, 0, 0}, {1, 1, 0}, ...}.
`options` is a table with any of the following keys:
- `count`, the number of units to create;
- `randomize`, randomize the list of locations;
- `inCapital`, create unit(s) in the tribe's capital city;
- `veteran`, sets the veteran flag on the created unit(s);
- `homeCity`, the home city for the unit(s).
--]]
local function createUnit(unittype, tribe, locations, options)

civlua.createUnit can more easily handle creating multiple units, or accounting for the fact that a desired tile might be occupied than can civ.createUnit. However, civ.createUnit will create a land unit on water, which civlua.createUnit won't do. (This came up in Over the Reich, when the photo recon plane sometimes tried to create a 'camera' on the ocean, and civlua.createUnit wouldn't do it.)

gen.createUnit is meant to replace civlua.createUnit. It has more options than than civlua.createUnit, and the locations argument now accepts a table of tileObjects (and even a single tile object), not just a table of coordinate triples. Here is the documentation for gen.createUnit:

Code:
gen.createUnit(unitType,tribe,locations,options) --> table of units Creates one or several units.
Meant to provide improve upon civlua.createUnit. Returns a table of units, indexed by integers starting at 1 (unless no units were created, in which case an empty table is returned, and a message printed to the console, but no error is generated). "unitType" is the unit type that will be created. "tribe" is the tribe that will own the unit(s). "locations" specifies where the unit will be created. If a table is provided, this is the order in which to try to place the units, unless a different option is specified in "options." "options" a table with various keys and values.
Valid Arguments:
Code:
unitType: unitTypeObject 
tribe: tribeObject 
locations: a tile object 
        a table of 3 elements (indexed by integers 1,2,3) corresponding to x,y,z coordinate
        a table of tile objects (indexed by integers)
        a table of coordinate triple tables (indexed by integers) 
options: a table with the following keys: 
    count = integer 
        the number of units to create nil means 1 
    randomize = bool or nil 
        if true, randomize the list of locations if false or nil, try to place at the tile with the smallest index in table first 
    scatter = bool or nil 
        if true, and if randomize is true, each unit is created on a random tile in the location table 
    inCapital = bool or nil 
        if true, attempt to place in the capital before other locations in case of multiple capitals, capitals are ranked with smallest city id first randomize/scatter applies to list of capitals if this is selected 
    veteran = bool or fraction in 0-1 or integer or nil 
        if true, make the created unis veteran 
        if a fraction in 0-1, each unit created has that chance of being veteran 
        if number >= 1, this many of the count are veteran (take floor) 
        nil or false means no veterans 
    homeCity = city or true or nil 
        if city, that city is the home city 
        if true, the game selects the home city (probably the same way a city is chosen if you create a unit by using the cheat menu) 
        if nil, no home city 
    overrideCanEnter = bool or nil 
        if true, unit will be placed even if unitType:canEnter(tile) returns false 
        false or nil means follow the restriction civ.canEnter appears to check if the terrain is impassible, or the unit can cross impassible 
    overrideDomain = bool or nil 
        if true, sea units can be created on land outside cities, and land units at sea 
        false or nil means units can only be created where they could travel naturally 
    overrideDefender = bool or nil 
        if true, unit can be placed on tiles with enemy units or cities 
        false or nil means the tile must have no enemy cities, and no enemy defender

So, how to choose between civ.createUnit, civlua.createUnit, and gen.createUnit? First, gen.createUnit will (I'm pretty sure) take any functioning example of civlua.createUnit and do the same thing. Since gen.createUnit has extra features, civlua.createUnit is obsolete for any purpose I can think of.

For choosing between civ.createUnit and gen.createUnit, default to gen.createUnit. However, if what you want to do will require you to go through the list of created units and change things about the created unit(s), it might make more sense to use civ.createUnit. If I'm creating rebels or reinforcements, I'd likely use gen.createUnit. If I'm making a capture the defeated unit mechanic, I'd be more inclined to use civ.createUnit, since I might want to mess with hitpoints or spent movement.
 
Question (from a PM I received):

How do you add/remove an improvement (or wonder) from a city be it either when a specific turn is reached or when a city is taken?

Answer:

Adding improvements to a city is done using the addImprovement function or method:

addImprovement
civ.addImprovement(city, improvement) -> void

Adds city improvement `improvement` to city `city`.
Code:
civ.addImprovement(object.lMyCityLocation.city,object.iSomeImprovement)

addImprovement
city:addImprovement(improvement) -> void

Alias for `civ.addImprovement(city, improvement)`.
Code:
object.cMyOtherCity:addImprovement(object.iDifferentImprovement)

Removing an improvement from a city is done with
removeImprovement
civ.removeImprovement(city, improvement) -> void

Removes city improvement `improvement` from city `city`.
Code:
civ.removeImprovement(object.cThirdCity,object.iImprovementToTake)

removeImprovement
city:removeImprovement(improvement) -> void

Alias for `civ.removeImprovement(city, improvement)`.
Code:
object.lFourthCityLocation.city:(object.iDoomedImprovement)

Adding and taking wonders is a bit different. In that case. Rather than changing the city object, you change the wonderObject:

city (get/set)
wonder.city -> city

Returns the city that has built the wonder, `nil` if not built yet or destroyed.
Code:
object.wWonderToAdd.city = object.cDestinationCity
Code:
object.wWonderToRemove.city = nil

The wonder can also be destroyed using
destroy
wonder:destroy() -> void

Alias for `civ.destroyWonder(wonder)`.

Code:
object.wDoomedWonder:destroy()

Taking an improvement (if it exists) from any city when the Germans capture it from the Russians looks like this (untested code):
Code:
local discreteEvents = require("discreteEventsRegistrar")
local param = require("parameters")
local object = require("object")
local text = require("text")
function discreteEvents.onCityTaken(city,defender)
    if city.owner == object.pGermans and 
        defender == object.object.pRussians and
        city:hasImprovement(object.iFactory) then
        local message = text.substitute("The %STRING1 have captured %STRING2, but the %STRING3 army destroyed the %STRING4 before they left.",
            {object.pGermans.name, city.name,object.pRussians.adjective, object.iFactory.name})
        city:removeImprovement(object.iFactory)
        text.simple(message,"War Minister")
    end
end

Taking away a wonder on a particular turn can be done like this (untested code):
Code:
function discreteEvents.onTurn(turn)
    if turn == param.lostWonderTurn then
        local message = "The "..object.wDoomedWonder.name.." in "..object.wDoomedWonder.city.name.." has crumbled to dust."
        object.wDoomedWonder.city = nil
        text.simple(message,"Domestic Adviser")
    end
end
 
Question (from a PM): How do I make nested menus? In particular, how can I make a menu option that allows me to change a previous selection?

Answer: There is no quick method for doing this. This has occurred to me, but I couldn't come up with a reasonable way to specify a nested menu. (I'm open to ideas if anyone has them.) text.menu can only generate one menu, but that menu can be multiple pages, and you can go back and forth.

To make a system of menus where you can go back to a previous menu, my preferred method is to make a recursive function (a function that makes calls to itself). In the attached code, which can be run (using load script) in any scenario that has access to the text module, I created a menu that lets you choose a unit type. Since there are a lot of unit types, you can choose to filter based on attack or defense values, then choose the range of those values, then select a unit, and finally confirm the unit selection. At each point, there are options to go back to an earlier menu to make a different choice.

In the code, I define the following function

Code:
local function chooseUnitType(menuType,info)
The menuType argument is a string, and that determines what kind of menu will be shown next. ("selectFilter" -- choose attack or defense, "statisticOptions" -- choose a range of values, "filteredOptions" -- select a unit type, "confirmChoice" -- confirm the choice, or make a change)

The info argument is a table that saves information from a previous menu in order to be used in the next one. This way, I pass things like whether the attack or defense is being used as the filter, the range of acceptable values, and the unit that was selected and must now be confirmed.

I'm happy to provide more explanation of the code if anyone wants it.

EDIT: I have added another even simpler nested menu which just lets you go between a couple menus.
 

Attachments

  • nestedMenuSample.lua.zip
    1.1 KB · Views: 23
  • simpleNestedMenu.lua.zip
    443 bytes · Views: 26
Last edited:
If the River/Road/Railroad/Alpine movement multipliers are different, which one is chosen?

The game first checks for a railroad connection between two tiles. If that exists, then the railroad multiplier is used.
Next, the alpine flag is checked for the moving unit. If that exists, then the alpine multiplier is used.
Third, the game checks for a road connection between the two tiles. If that exists, the road multiplier is used.
Finally, the game checks for a river connection, and if it exists, the river multiplier is used.

Note that the game uses the first valid multiplier in this process, even if a better multiplier could be found later in the process.
 
What happens if I use Lua to give a unit a non-integer movement allowance?
The unitType field unitType.move registers the movement allowance of a unit in "atomic" movement points. So, using standard game rules, the aggregate movement multiplier is 3, hence settlers have 3 atomic movement points, armor have 9, and fighters have 30. However, using Lua, we could, for example, set the settler unitType move field to 5, giving the settler 1 2/3 movement allowance. How does the game handle this?

If the unit is at full health, it gets exactly the movement allowance specified in the move field. So, our settler with 5 movement shows a 1 2/3 movement allowance.

However, if the unit is damaged, the game calculates a movement allowance that depends on its fraction of remaining hitpoints. This calculation always returns 'full' movement points, but it rounds up instead of down. This means that a slightly damaged settler will actually have its movement allowance bumped up to 2. In fact, for health of 16/20 to 19/20, the settler gets 2 movement points.

This is the code to mimic the game's calculation:
Code:
    local aggMult = totpp.movementMultipliers.aggregate
    local moveAllowance = (unit.hitpoints*unit.type.move)//unit.type.hitpoints -- // means divide and discard fraction part
    if moveAllowance % aggMult > 0 then  -- this section rounds up
        moveAllowance = moveAllowance - (moveAllowance % aggMult) + aggMult
    end
It turns out that there is potential for rounding up as long as unit.type.move is at least 2 atomic movement points above a full movement point. Consider a unitType.move = 8, totpp.movementMultipliers = 6, (so 1 2/6 mp), and hitpoints 19/20. Then
Code:
moveAllowance = (19*8)//20 = 152//20 = 7
moveAllowance % aggMult > 0 --> 7 % 6 > 0 --> 1 > 0 --> true
[/CODE]
so,
Code:
moveAllowance = 7 - 1 + 6 = 12

Hence, even though 1 2/6 "should" be "rounded down" to 1, it actually gets rounded up to 2 for 1 damage to a 20 hp unit.
 
Is there a way to set (or increase/decrease) the number of unhappy citizens via some sort of function? Real world example: lets say I'm building an Age of discovery type scenario with European powers but it also includes Native factions. Temple (renamed Church) and Cathedral are used for Europeans, but since there's no air units I want to somehow use SAM Missile Battery (renamed Temple) and SDI Defense (renamed Grand Temple), essentially making a mirror of Church/Cathedral for native factions.
 
Is there a way to set (or increase/decrease) the number of unhappy citizens via some sort of function? Real world example: lets say I'm building an Age of discovery type scenario with European powers but it also includes Native factions. Temple (renamed Church) and Cathedral are used for Europeans, but since there's no air units I want to somehow use SAM Missile Battery (renamed Temple) and SDI Defense (renamed Grand Temple), essentially making a mirror of Church/Cathedral for native factions.
You can change the default number of unhappy citizens (the first line of the happiness calculation) using civ.cosmic.sizeUnhappiness during the onCalculateCityYield event. Here is some example code to be placed in calculateCityYield.lua, in the Lua Scenario Template.

Code:
local changeRules = require("changeRules")
Code:
function cityYield.onCalculateCityYield(city,food,shields,trade)
    -- some code
    local defaultSizeUnhappiness = changeRules.authoritativeDefaultRules["civ.cosmic"].sizeUnhappiness
    if city:hasImprovement(gen.original.iSAMMissileBattery) then
        civ.cosmic.sizeUnhappiness = defaultSizeUnhappiness +2
    else
      civ.cosmic.sizeUnhappiness = defaultSizeUnhappiness
    end
    -- more code

The above code adds +2 content citizens on the first line of the happiness calculation if the city has a SAM Missile Battery in the city. This isn't exactly the same as a happiness improvement, but it may be adequate for your purposes.
 
Is there a way to set (or increase/decrease) the number of unhappy citizens via some sort of function? Real world example: lets say I'm building an Age of discovery type scenario with European powers but it also includes Native factions. Temple (renamed Church) and Cathedral are used for Europeans, but since there's no air units I want to somehow use SAM Missile Battery (renamed Temple) and SDI Defense (renamed Grand Temple), essentially making a mirror of Church/Cathedral for native factions.
Here's another option. The temple and cathedral depend on certain techs (ceremonial burial, mysticism, monotheism, theology) to make them work. You could have one or both of these buildings be some sort of generic always there building, that has no upkeep and can't be sold (change these in the rules.txt). Then give or take the techs to make them work based on the presence of a different building in the city.

Here's a proof of concept with the cathedral and monotheism

This can be anywhere, and gives all new cities a cathedral for free:
Code:
local discreteEvents = require("discreteEventsRegistrar")

discreteEvents.onCityFounded(function(city)
    city:addImprovement(gen.original.iCathedral)
end)

In calculateCityYield.lua
Code:
function cityYield.onCalculateCityYield(city,food,shields,trade)
    -- some code
    if city:hasImprovement(gen.original.iSAMMissileBattery) then
        city.owner:giveTech(gen.original.aMonotheism)
    else
        city.owner:takeTech(gen.original.aMonotheism)
    end
    -- more code

I guess if you want to be thorough, you could give/take some dummy tech as well, so the tech cost doesn't fluctuate based on the last city that was examined.
 
Here's another option. The temple and cathedral depend on certain techs (ceremonial burial, mysticism, monotheism, theology) to make them work. You could have one or both of these buildings be some sort of generic always there building, that has no upkeep and can't be sold (change these in the rules.txt). Then give or take the techs to make them work based on the presence of a different building in the city.

Here's a proof of concept with the cathedral and monotheism

This can be anywhere, and gives all new cities a cathedral for free:
Code:
local discreteEvents = require("discreteEventsRegistrar")

discreteEvents.onCityFounded(function(city)
    city:addImprovement(gen.original.iCathedral)
end)

In calculateCityYield.lua
Code:
function cityYield.onCalculateCityYield(city,food,shields,trade)
    -- some code
    if city:hasImprovement(gen.original.iSAMMissileBattery) then
        city.owner:giveTech(gen.original.aMonotheism)
    else
        city.owner:takeTech(gen.original.aMonotheism)
    end
    -- more code

I guess if you want to be thorough, you could give/take some dummy tech as well, so the tech cost doesn't fluctuate based on the last city that was examined.
Thank you, very interesting, but I like the first approach better.
 
@Prof. Garfield is it possible to make some sort of aggregate conditions inside canBuildSetting.lua? E.g. in The Age of Reformation scenario, even with the right advance, the Habsburg can't build Siege Mortars for as long as they own Antwerp which has Dutch Textile Industry wonder (acts as Water Mill improvement which supersedes Armor Factory which is necessary to produce Siege Mortar in the first place).
So... let's modify that to an aggregate condition to: Siege Mortar can be build if a city has Armour Factory improvement OR it has Manufacture improvement AND belongs to a civ that controls Dutch Textile Industry. Can this be done in canBuildSetting.lua alone or do I have to modify some part of LuaCore?
 
@Prof. Garfield is it possible to make some sort of aggregate conditions inside canBuildSetting.lua? E.g. in The Age of Reformation scenario, even with the right advance, the Habsburg can't build Siege Mortars for as long as they own Antwerp which has Dutch Textile Industry wonder (acts as Water Mill improvement which supersedes Armor Factory which is necessary to produce Siege Mortar in the first place).
So... let's modify that to an aggregate condition to: Siege Mortar can be build if a city has Armour Factory improvement OR it has Manufacture improvement AND belongs to a civ that controls Dutch Textile Industry. Can this be done in canBuildSetting.lua alone or do I have to modify some part of LuaCore?
If you want something to be built when one of two (or more) conditions is satisfied, you use addBuildConditions for each of them. In this case, the code would be something like this:
Code:
addBuildConditions(object.uSiegeMortar, {allImprovements = {object.iArmourFactory, }, })

addBuildConditions(object.uSiegeMortar, {allImprovements = {object.iManufacture, }, allWonders = {object.wDutchTextileIndustry, }, })

Another option would be to set overrideDefaultBuildFunction = true for the Armor Factory build condition instead, so that the Armor Factory can still be built by the tribe with the Water Mill. (You'd also have to add the prereq tech and the prereq building to the build conditions, since overrideDefaultBuildFunction ignores everything the game usually requires.)

If you want something to be built with either the standard requirements, or with some other requirement, you have to add an empty table of buildConditions
Code:
addBuildConditions(object.uSomeUnit,{})
addBuildConditions(object.uSomeUnit,otherConditions)

Ordinarily, not adding any build conditions defaults to the game's standard requirements, but once you add a condition, the "empty" condition must be added back.

In case you haven't seen it yet, here's a video where I show how to do a lot of different build conditions. I think the code generator does everything except custom functions.
 
If you want something to be built when one of two (or more) conditions is satisfied, you use addBuildConditions for each of them. In this case, the code would be something like this:
Code:
addBuildConditions(object.uSiegeMortar, {allImprovements = {object.iArmourFactory, }, })

addBuildConditions(object.uSiegeMortar, {allImprovements = {object.iManufacture, }, allWonders = {object.wDutchTextileIndustry, }, })

Another option would be to set overrideDefaultBuildFunction = true for the Armor Factory build condition instead, so that the Armor Factory can still be built by the tribe with the Water Mill. (You'd also have to add the prereq tech and the prereq building to the build conditions, since overrideDefaultBuildFunction ignores everything the game usually requires.)

If you want something to be built with either the standard requirements, or with some other requirement, you have to add an empty table of buildConditions
Code:
addBuildConditions(object.uSomeUnit,{})
addBuildConditions(object.uSomeUnit,otherConditions)

Ordinarily, not adding any build conditions defaults to the game's standard requirements, but once you add a condition, the "empty" condition must be added back.

In case you haven't seen it yet, here's a video where I show how to do a lot of different build conditions. I think the code generator does everything except custom functions.
Unfortunately, The Reformation ships with older version of LuaTemplate, which doesn't contain new functionality such as addBuildConditions or Can Build Code Generator. I tried copying new LuaTemplate over existing one, brute-force style, but the game throws errors. Then I tried adding at least some of new functionality in, by copying function by function. Again, error due to missing dependencies from LuaCore, etc. So, I'll try overrideDefaultBuildFunction = true. Where should I place that code? I mean, which file?
 
Unfortunately, The Reformation ships with older version of LuaTemplate, which doesn't contain new functionality such as addBuildConditions or Can Build Code Generator. I tried copying new LuaTemplate over existing one, brute-force style, but the game throws errors. Then I tried adding at least some of new functionality in, by copying function by function. Again, error due to missing dependencies from LuaCore, etc. So, I'll try overrideDefaultBuildFunction = true. Where should I place that code? I mean, which file?
overrideDefaultBuildFunction is a key that can be placed in any buildConditionTable, the same as allImprovements, or earliestTurn.

In the old system (and the new system, if you really want to do it that way), if you want to have multiple different build conditions, you can use the alternateParameters key.

The alternateParameters key must have a table as its value. In that table, you list all the extra buildConditionTables that you also want as an option.

Let me know if you need more explanations.
 
Is there a function to identify a player by the civ's internal ID and/or tribe colour? @Dadais' Expanded Mod has tribe-specific unique units à la Civ3, but the code parses the civ's string name, meaning customized tribe monikers will lose those units.

I'm thinking specifically with regard to tweaking the Extended Original game mode to allow a mirror Centauran space programme to land on Earth. As scripted, the Centauri Arrival events parse with "race=anybody", so a Centauran mission ends up on its homeworld. It's possible to duplicate the events discretely for each civ, but besides being tedious, this runs into the same problem where the trigger can't catch a custom name.
 
Is there a function to identify a player by the civ's internal ID and/or tribe colour? @Dadais' Expanded Mod has tribe-specific unique units à la Civ3, but the code parses the civ's string name, meaning customized tribe monikers will lose those units.

I'm thinking specifically with regard to tweaking the Extended Original game mode to allow a mirror Centauran space programme to land on Earth. As scripted, the Centauri Arrival events parse with "race=anybody", so a Centauran mission ends up on its homeworld. It's possible to duplicate the events discretely for each civ, but besides being tedious, this runs into the same problem where the trigger can't catch a custom name.
If I understand what you're asking, you can check the ID number of the tribe that arrives at Centauri by using tribe.id, and then checking if that ID is 7 or not. Like this:
Code:
civ.scen.onCentauriArrival(function (tribe)
    if tribe.id == 7 then
        -- place units for the `tribe` on map 0
        

    else
        --place units for the `tribe` on map 1

    
    end
end)

If you really want to get fancy, you could check what map all that tribe's units are on, and then place the units on the other map.

In case you haven't noticed, I've started a new series of lessons for teaching Lua to program events.
 
Top Bottom