[TOTPP] Lua Scenario Template

A quick test with both cheat mode and Lua Console shows that taking communism away from a tribe removes the cathedral penalty for that tribe.
Awesome! Thanks, Prof!
 
The template has been updated. The functions in the General Library are now all documented, so the tooltip will be informative if you use Visual Studio Code (or some other text editor that has a Lua Language Server extension). The only functionality that is changed is
Code:
gen.unitTypeOnTile(tile,unitTypeTable,excludeFromCheck)
Which now lets you exclude a unit or units from the check. This came up when I was helping someone with an onEnterTile event, which depended on whether there was already a unit of that type on the tile, and I couldn't use gen.unitTypeOnTile for a couple of line solution.
 
I've been working on the "custom cosmic" module for the past few days. The module lets you customise a large number of ephemeral game values based on which unit is active or which city is being processed. Noteworthy is that the movement multipliers can be changed on a per-unit basis, and the functionality exists to set all air and sea multipliers to 1, to enable larger movement allowances.

I've finished the unit section, and now am working on the city section.

Documentation for unit cosmic settings:
Spoiler :

Code:
-- if both of these are used, both modify movement
    atomicMovementBonus = nilIntFn,
    -- atomicMovementBonus = nil|int or function(unit)-->nil|Int
    -- Bonus movement points (compared to authoritativeDefaultRules)
    -- Positive means add, negative means subtract
    -- nil means no change
    -- if function, the returned value of function(unit) is used.
    movementBonus = nilNumFn,
    -- movementBonus = nil|num or function(unit)-->nil|num
    -- Bonus movement points (compared to authoritativeDefaultRules)
    -- whole movement points, positive means add, negative means subtract
    -- nil means no change
    -- if function, the returned value of function(unit) is used.

-- only one of these two items is permissible.  If both exist,
-- atomicCustomMovement is used
    -- if this and the movementBonus both exist, the movementBonus is
    -- added to this instead of the authoritativeDefaultRules
    -- if both are nil, refer to the authoritativeDefaultRules
    atomicCustomMovement = nilPosIntFn,
    -- atomicCustomMovement nil|int>=0 or function(unit)-->nil|int>=0
    -- Unit type will have this amount of atomic movement points,
    -- regardless of the authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.
    customMovement = nilPosNumFn,
    -- customMovement = nil|num>=0 or function(unit)--> nil|num>=0
    -- Unit type will have this amount of movement points, regardless
    -- of the authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.

-- if both of these are used, the larger one is used
    atomicMinMove = nilPosIntFn,
    -- atomicMinMove = nil|int or function(unit)-->nil|int
    -- Ensures a damaged land or sea unit will still be able
    -- to move this many atomic movement points
    -- (unless that would require setting it's unit type's atomic movement
    -- beyond 255, which can't be overcome.  If this is a problem,
    -- consider changing movement multipliers for the unit to have
    -- a lower aggregate value)
    -- nil means no minimum movement
    -- does not increase movement beyond the unit's movement allowance
    -- since a damaged unit can't have a fractional movement allowance,
    -- the effective atomicMinMove is reduced to the next lowest full
    -- movement point.
    minMove = nilPosNumFn,
    -- minMove = nil|num or function(unit)-->nil|num
    -- Ensures a damaged land or sea unit will still be able
    -- to move this many movement points
    -- (unless that would require setting it's unit type's atomic movement
    -- beyond 255, which can't be overcome.  If this is a problem,
    -- consider changing movement multipliers for the unit to have
    -- a lower aggregate value)
    -- nil means no minimum movement
    -- does not increase movement beyond the unit's movement allowance

    roadMultiplier = mMultFn,
    -- roadMultiplier = nil or int>=-1 or function(unit)-->nil int>=-1
    -- The road multiplier for the unit type
    -- nil means refer first to the defaultMovementMultipliers, then to authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.

    railroadMultiplier = mMultFn,
    -- railroadMultiplier = nil or int>=-1 or function(unit)-->nil int>=-1
    -- The railroad multiplier for this unit type
    -- nil means refer first to the defaultMovementMultipliers, then to authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.

    alpineMultiplier = mMultFn,
    -- alpineMultiplier = nil or int>=-1 or function(unit)-->nil int>=-1
    -- The alpine multiplier for this unit type
    -- nil means refer first to the defaultMovementMultipliers, then to authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.

    riverMultiplier = mMultFn,
    -- riverMultiplier = nil or int>=-1 or function(unit)-->nil int>=-1
    -- The river multiplier for this unit type
    -- nil means refer first to the defaultMovementMultipliers, then to authoritativeDefaultRules
    -- if function, the returned value of function(unit) is used.

    isImpassable = baseTerrainKeyTableImpassableSpec,
    -- isImpassable[baseTerrainObject/ID] = nil or boolean or function(unit)-->nil or boolean
    -- if true, the baseTerrain is impassable for the unit type
    -- if false, the baseTerrain is not impassable for the unit type
    -- if nil, refer to the authoritativeDefaultRules
    -- note, ID is the id generated by gen.getBaseTerrainID,
    -- but you can just use the baseTerrain object.
    -- if function, the returned value of function(unit) is used.


    moveCost = baseTerrainKeyTableMoveCostSpec,
    -- moveCost[baseTerrainObject/ID] = nil or positiveInteger or function(unit)-->nil or positiveInteger
    -- if integer, this is the (full movement point) movement cost of the base terrain
    -- if nil, refer to the authoritativeDefaultRules
    -- note, ID is the id generated by gen.getBaseTerrainID
    -- if function, the returned value of function(unit) is used.

    cosmic = customCosmicUnitTypeCosmicSettingsSpec,
    -- cosmic[cosmicKey] = positiveInteger or nil or function(unit)-->posInt or nil
    -- if nil, use the value in the authoritativeDefaultRules instead
    -- possible values for cosmicKey:
    -- "paradropRange"
    -- "triremeLost"
    -- "transformBase"
    -- if function, the returned value of function(unit) is used.

    flags = customCosmicUnitTypeFlagSettingsSpec,
    -- flags[flagKey] = nil or boolean or function(unit)-->nil or boolean
    -- if true, the unit has the flag corresponding to the flagKey
    -- if false, the unit does not have the flag corresponding to flagKey
    -- if nil, flags from the authoritativeDefaultRules are used
    -- possible values for flagKey:
    -- "canCrossImpassableTerrain"
    -- "canFoundCities"
    -- "canImproveTiles" (no effect if not settler)
    -- "seeTwoSpaces"
    -- "ignoreZOC"
    -- "amphibious"
    -- "coastal"
    -- "ignoreWalls"
    -- "carryAir"
    -- "paradrop"
    -- "alpine"
    -- "destroyedAfterAttacking"
    -- "spotSubmarines"
    -- if function, the returned value of function(unit) is used.

    condition = unitSpecCondition,
    -- condition = nil|tribeObject|traitString|function(unit)-->boolean or
    --          table of tribeObject|traitString
    -- if nil, this unit type customisation applies to all units
    -- of the relevant type(s).
    -- if tribeObject, this customisation can only apply to units
    -- owned by that tribe (as long as the unit is also of
    -- the relevant type)
    -- if traitString, this customisation applies to tribes which
    -- have the trait
    -- if table of tribeObject|traitString, this applies to any
    -- tribe or traitString in the table
    -- if function(unit) --> boolean, then this customisation
    -- applies to units of the relevant type(s) which also make this function
    -- return true
    -- Only one customisation can apply to any unit.  The priority
    -- key is used to tie break.

    priority = posNum,
    -- priority = nil or number>=0
    -- If multiple customisations can apply to a unit, this value chooses
    -- among them, with higher priority taking precedence.
    -- If the unit is eligible for two customisations of the same priority,
    -- an error may be generated, and will certainly be generated if they
    -- are of the highest priority

    customisationName = {["string"]=true},
    -- A name to be used during certain kinds of error and debugging messages
    -- nil will give "Unnamed UnitType Customisation"


Documentation for city cosmic settings:
Spoiler :

Code:
    communismPalaceDistance = nilPosIntFn,
    -- communismPalaceDistance = nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.communismPalaceDistance
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    communismPalaceDistanceModifier = nilIntFn,
    -- communismPalaceDistanceModifier = nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.communismPalaceDistance
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    foodEaten = nilPosIntFn,
    -- foodEaten = nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.foodEaten
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    foodEatenModifier = nilIntFn,
    -- foodEatenModifier = nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.foodEaten
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    foodRows= nilPosIntFn,
    -- foodRows= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.foodRows
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    foodRowsModifier = nilIntFn,
    -- foodRowsModifier = nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.foodRows
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    prodChangePenalty= nilPosIntFn,
    -- prodChangePenalty= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.prodChangePenalty
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    prodChangePenaltyModifier= nilIntFn,
    -- prodChangePenaltyModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.prodChangePenalty
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    riotFactor= nilPosIntFn,
    -- riotFactor= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.riotFactor
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    riotFactorModifier = nilIntFn,
    -- riotFactorModifier = nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.riotFactor
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    scienceLostFundamentalism= nilPosIntFn,
    -- scienceLostFundamentalism= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.scienceLostFundamentalism
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    scienceLostFundamentalismModifier= nilIntFn,
    -- scienceLostFundamentalismModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.scienceLostFundamentalism
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    scienceRateFundamentalism= nilPosIntFn,
    -- scienceRateFundamentalism= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.scienceRateFundamentalism
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    scienceRateFundamentalismModifier= nilIntFn,
    -- scienceRateFundamentalismModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.scienceRateFundamentalism
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    settlersEatHigh= nilPosIntFn,
    -- settlersEatHigh= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.settlersEatHigh
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    settlersEatHighModifier= nilIntFn,
    -- settlersEatHighModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.settlersEatHigh
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    settlersEatLow= nilPosIntFn,
    -- settlersEatLow= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.settlersEatLow
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    settlersEatLowModifier= nilIntFn,
    -- settlersEatLowModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.settlersEatLow
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    shieldRows= nilPosIntFn,
    -- shieldRows= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.shieldRows
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    shieldRowsModifier= nilIntFn,
    -- shieldRowsModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.shieldRows
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    sizeAquaduct= nilPosIntFn,
    -- sizeAquaduct= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.sizeAquaduct
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    sizeAquaductModifier= nilIntFn,
    -- sizeAquaductModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.sizeAquaduct
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    sizeSewer= nilPosIntFn,
    -- sizeSewer= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.sizeSewer
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    sizeSewerModifier= nilIntFn,
    -- sizeSewerModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.sizeSewer
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    sizeUnhappiness= nilPosIntFn,
    -- sizeUnhappiness= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.sizeUnhappiness
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    sizeUnhappinessModifier= nilIntFn,
    -- sizeUnhappinessModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.sizeUnhappiness
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    supportCommunism= nilPosIntFn,
    -- supportCommunism= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.supportCommunism
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    supportCommunismModifier= nilIntFn,
    -- supportCommunismModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.supportCommunism
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    supportFundamentalism= nilPosIntFn,
    -- supportFundamentalism= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.supportFundamentalism
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    supportFundamentalismModifier= nilIntFn,
    -- supportFundamentalismModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.supportFundamentalism
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    supportMonarchy= nilPosIntFn,
    -- supportMonarchy= nil|int>=0 or function(city) --> nil|int>=0
    -- Specifies the base value to be used for civ.cosmic.supportMonarchy
    -- If nil, the value from the authoritativeDefaultRules is used.
    -- If function, use the returned value when given the city as the argument.
    supportMonarchyModifier= nilIntFn,
    -- supportMonarchyModifier= nil|int or function(city) --> nil|int
    -- Add this to the base value to be used for
    -- civ.cosmic.supportMonarchy
    -- If nil, add 0.  Note, a negative number here will not reduce the
    -- base value below 0.
    -- If function, use the returned value when given the city as the argument.
    customisationName = {["string"]=true},
    -- A name to be used during certain kinds of error and debugging messages
    -- nil will give "Unnamed City Customisation"
    condition = citySpecCondition,
    -- condition = nil|tribeObject|traitString|function(city)-->boolean or
    --          table of tribeObject|traitString
    -- if nil, this customisation applies to all cities (unless a higher
    -- priority customisation also applies)
    -- if tribeObject, this customisation applies to cities owned by
    -- the tribe
    -- if traitString, this customisation applies to tribes which have the
    -- trait
    -- if table of tribeObject|traitString, this applies to any tribe or
    -- traitString in the table
    -- if function(city) --> boolean, then this customisation applies to
    -- cities which make this function return true
    -- only one customisation can apply to any city.  The priority key
    -- is used to tie break.
    priority = posNum,
    -- priority - nil or number >= 0
    -- If multiple customisations can apply to a city, this value chooses
    -- among them, with higher priority taking precedence.
    -- If the city is eligible for two customisations of the same priority,
    -- an error may be generated, and will certainly be generated if they
    -- are of the highest priority.

    -- [unitTypeObject] = {
    --          cost = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base cost (in shield rows) for the city
    --              If nil, refer to authoritativeDefaultRules
    --              If function, use result after evaluating function(city)
    --          costModifier = nil|int or function(city)-->nil|int
    --              Add this to the base cost, but cost won't be less than 0
    --              If nil, use 0
    --              If function, use result after evaluating function(city)
    --          freeSupportUnderFundamentalism = nil|boolean or function(city)-->nil|boolean
    --              If true, unitType has the freeSupportUnderFundamentalism
    --              for this city.  If false, it does not.
    --              If nil, refer to the authoritativeDefaultRules
    --          requiresFoodSupport = nil|boolean or function(city)-->nil|boolean
    --              If true, the city must pay food support for this unitType.
    --              If false, it does not. (Setting this to true makes both
    --              settler and non-settler unit types require food.)
    --              If nil, refer to the authoritativeDefaultRules
    --          }

    -- [improvementObject] = {
    --          cost = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base cost (in shield rows) for the city
    --              If nil, refer to authoritativeDefaultRules
    --              If function, use result after evaluating function(city)
    --          costModifier = nil|int or function(city)-->nil|int
    --              Add this to the base cost, but cost won't be less than 0
    --              If nil, use 0
    --              If function, use result after evaluating function(city)
    --          cantSell = nil|boolean or function(city)-->nil|boolean
    --              If true, the city can't sell the improvement, if false,
    --              it can.
    --              If nil, refer to the authoritativeDefaultRules
    --          upkeep = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base upkeep (gold per turn) this improvement
    --              in this city.
    --              If nil, refer to authoritativeDefaultRules
    --              If function, use result after evaluating function(city)
    --          upkeepModifier = nil|int or function(city)-->nil|int
    --              Add this to the base upkeep, but upkeep won't be less than 0
    --              If nil, use 0
    --              If function, use result after evaluating function(city)
    --          onCapture = nil|0|1|2|3 or function(city)-->nil|0|1|2|3
    --         
    -- [wonderObject] = {
    --          cost = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base cost (in shield rows) for the city
    --              If nil, refer to authoritativeDefaultRules
    --              If function, use result after evaluating function(city)
    --          costModifier = nil|int or function(city)-->nil|int
    --              Add this to the base cost, but cost won't be less than 0
    --              If nil, use 0
    --              If function, use result after evaluating function(city)
    --          }
    --             
    -- [baseTerrainObject] = {
    --          irrigateBonus = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base value of the irrigation bonus for the
    --              city and baseTerrain.
    --              If nil, refer to the authoritativeDefaultRules,
    --              If function, use the result of function(city),
    --          irrigateBonusModifier = nil|int or function(city)-->nil|int
    --              Add this to the base irrigation bonus, but results less
    --              than 0 will be set to 0.
    --              If nil, use 0.
    --              If function, use result after evaluating function(city)
    --          mineBonus = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base value of the mining bonus for the
    --              city and baseTerrain.
    --              If nil, refer to the authoritativeDefaultRules,
    --              If function, use the result of function(city),
    --          mineBonusModifier = nil|int or function(city)-->nil|int
    --              Add this to the base mining bonus, but results less
    --              than 0 will be set to 0.
    --              If nil, use 0.
    --              If function, use result after evaluating function(city)
    --          roadTrade = nil|boolean or function(city)-->nil|boolean
    --              If true, for this city and baseTerrain, the road trade
    --              bonus is applied.  If false, it is not.
    --              If nil, refer to the authoritativeDefaultRules

    -- [terrainObject] = {
    --          food = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base value for the food produced for this
    --              city by this terrain type.
    --              If nil, refer to the authoritativeDefaultRules
    --              If function, use the result of function(city)
    --          foodModifier = nil|int or function(city)-->nil|int
    --              Add this to the base food production value, but
    --              if the result is less than 0, it will be raised to 0.
    --              If nil, use 0.
    --              If function, use the result of function(city)
    --          shields = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base value for the shields produced for this
    --              city by this terrain type.
    --              If nil, refer to the authoritativeDefaultRules
    --              If function, use the result of function(city)
    --          shieldsModifier = nil|int or function(city)-->nil|int
    --              Add this to the base shield production value, but
    --              if the result is less than 0, it will be raised to 0.
    --              If nil, use 0.
    --              If function, use the result of function(city)
    --          trade = nil|int>=0 or function(city)-->nil|int>=0
    --              Sets the base value for the trade produced for this
    --              city by this terrain type.
    --              If nil, refer to the authoritativeDefaultRules
    --              If function, use the result of function(city)
    --          tradeModifier = nil|int or function(city)-->nil|int
    --              Add this to the base trade production value, but
    --              if the result is less than 0, it will be raised to 0.
    --              If nil, use 0.
    --              If function, use the result of function(city)
 
Custom Cosmic is finally finished, and the repository has been updated.

The customCosmicsSettings file (which has documentation) can be seen in your browser here.

As always, let me know if you run into any bugs or need more explanations on how to use this module.
 
Last edited:
Lately, I've been re-creating profgarfield.github.io, which is the website I use to document template stuff. Much of it is automated, both using my own code and Jekyll markdown. I've updated the template repository, but nearly all the changes are either minor (if I noticed something wasn't quite right) or simply changes to automate some documentation. For example, there are comments of the form "---&autoDoc", which allows my website building code to pull examples directly from the template, in the event that the code changes in the future.

Only fix of note is that the final order given event now gives a 'final order' to sleeping and fortified units at the end of the player's turn.
 
Added a "configuration" module to the template.

Basically, the player can press 0 to open a menu to change settings, and the scenario designer can use configuration.getSettingValue to find out what the setting is. Each player can have their own settings. By default, there is a setting to change how many lines the text boxes have for functions like text.menu and text.simple, before these functions split messages into multiple boxes.

For example, you may want to have a popup showing the strength of units when combat starts, but the player might find that distracting after a while. With this module, you can write a menu option to hide or show combat statistics.
 
Added the landAirCargo module, which allows land and air units to "carry" other units as cargo. Basically, an onEnterTile event "drags" the cargo along with the carrier. MechanicsFiles\cargoSettings.lua is where you define settings for cargo and transport. Sea transport still uses navySettings.lua. As usual, report potential bugs when discovered, and ask for help if necessary.

From a player perspective, the module works like this: If a transport unit can carry cargo, it will carry with it any sleeping units that are on the same tile (up to the transport's capacity), as long as the units can be carried by the transport, and can be loaded onto the transport unit on that tile. When a player opens a city screen, all units in that city are unloaded from any transport units that might be carrying them. This also happens at the end of the player's turn. Activating a unit will either unload it, or the activation will fail if it can't unload on that tile.

To facilitate this new module, I added the execution point City Window Opened. I also changed the Activate Unit execution point so that if a function returns true (or a function, which can do something else to the unit), the activation is cancelled, and any other activation code is not run. This could be useful when you decide to kill a unit during activation, for example.

I fixed some bugs that were reported to me, including:

Units failing to be killed with their transport at sea. Aircraft carriers expelling air units from port if they can't be carried. Promotions of "munition generators" when the unit in combat wasn't a munition, and the promoted unit didn't generate it (actually a mistake in munitions.lua). The authoritativeDefaultRules of the changeRules.lua module didn't read the COSMIC2 rules, and just used defaults. Changing the leader names in leaderBonusSettings.lua caused errors.

The Legacy Event Engine no should no longer display a warning message about having a pre-2020 version of the Engine. By now, the message is only triggered because the game has never been saved with the Legacy Event Engine enabled, and not because an update could scramble state table data.

Updating your scenario can be done by adding the attached file to your scripts folder (replacing the existing file). Then press CTRL+SHIFT+F4, and choose the "Run update helper" option. Updated files will be printed in the console, along with a warning if you changed the "fileModified" variable at the top of the file in your version. You can then copy over new files from the most recent template download.
 

Attachments

  • updateInfo.lua.zip
    1.7 KB · Views: 10
his also happens at the end of the player's turn. Activating a unit will either unload it, or the activation will fail if it can't unload on that tile.

Does this mean that you have to put the cargo back on every turn though or am I misreading you? I suppose the advantage of your method over SorFox's is that you don't need to find a place to tuck the units away, but I'm not sure I'd want to have to keep loading them each turn - though I may have completely misread.
 
Does this mean that you have to put the cargo back on every turn though or am I misreading you? I suppose the advantage of your method over SorFox's is that you don't need to find a place to tuck the units away, but I'm not sure I'd want to have to keep loading them each turn - though I may have completely misread.
Your transport is unloaded at the end of a turn only if it is in a city. I wanted units to unload from a transport if the city window was opened, since otherwise the city menu could be used to interfere with how the code keeps track of what is being carried, and it seemed natural to unload everything at the end of the turn as well, because you couldn't load again at that point. I think part of my reasoning was also that I didn't want units inside a city to be destroyed with their transport, or to suffer a combat penalty on the defence.

I made sure the transport could pass through a city without automatically unloading, since that could get annoying.
 
Quick update to the template, making a bugfix to landAirCargo.lua and events.lua.

The previous version of landAirCargo.lua caused a bug to clear goto orders, which @tootall_2012 brought to my attention.

It turns out that checking (not even changing) the field unit.carriedBy during the onActivateUnit execution point for the unit causes the unit's goto order to be cancelled. This doesn't happen for other units (at least not when I test in the Lua Console). However, I used the unitData module to add a flag to tell whether the unit is actually being carried or not. Once I figured out the problem, the fix was not that hard. I had anticipated not being able to use the carriedBy field at all, so I wrote functions to interact with the field, so that I could change how lua kept track of cargo to a flag and counter system if necessary.

During this investigation, I discovered that a unit moving with goto orders along a (infinite movement) railroad doesn't trigger the onActivateUnit event for every tile, just the one it stops on.
 
There is an important bug fix for the general library, for any scenario where tiles can be improved with farmland. The explanation can be found here.

Before you replace generalLibrary.lua (in LuaCore folder) with this updated version, save a backup of your old version. This version of the General Library may cause an error when loading a game in older versions of the template. If that happens to you, PM me your verison of the General Library and I'll make the fix.
 

Attachments

  • generalLibrary.lua-farmland-fix.zip
    68.8 KB · Views: 8
Funny... I just noticed this today (I hadn't gotten this far in playtesting my mod). Many thanks for the fix, Prof.! I'll give it a shot this weekend.
 
I pushed a couple bug fixes. Of note is a bug where rules_lst.txt won't promote a unit into a new unit unless the promotion chance is 100%. This was because of an integer division when changing from a percent to a fraction (100//100-->1, but 90//100-->0).

This file is for rules.lua, which goes in the LuaCore. This is different from rules.txt or rules_lst.txt.
 

Attachments

  • rules.lua-fix-sept-17.zip
    8.2 KB · Views: 7
I uploaded a fix to events.lua. The onCityProcessed event would only work once in a game. If anyone using an old version of the template needs the event fixed, upload your events.lua file, and I'll make the switch. I doubt anyone needs the fix, since this bug is hard to miss if you play more than one turn. (Unfortunately, it exists because I only tested for one turn...)
 
The template has been updated.

I have added more "supplementalData" modules. There are now modules to easily associate data with unitTypes, improvements, wonders, terrains, baseTerrains, and technologies. I don't know of specific reasons to want to do this, but the supplementalData module (which was already used to create unitData, cityData, tileData, and tribeData) made building these modules easy, so I figure the extra modules won't do any harm and will be available if the need arises.

More notably, I added a "data" module, which provides the same mechanics as the other "supplementalData" modules, except that this one doesn't require specifying an item. At the moment, it is just an alternative to the existing flag and counter modules. However, I'm considering removing the flag and counter modules in a future update and change the modules that rely on flags and counters to rely on the new data module version. That way, all the flags, counters, and phrases will work with similar commands.

I have updated the legacy event engine and builder with some more helpful error messages for some errors.

Events.lua now checks for duplicate files in the main scenario folder, and in LuaCore, EventsFiles, LuaParameterFiles, and MechanicsFiles. This way, accidentally having duplicate files won't result in the wrong one being required (which is a very frustrating bug to diagnose).
 
Hi @Prof. Garfield , I'm getting some errors with the new template. First was duplicate files, so I deleted a few duplicates (onUseNukes, combatSettings.lua [both in base folder and in Mechanics] and legacyEvents.txt. Now getting this message:
Spoiler :
Code:
Global variables are disabled
...Desktop\Empires of Dust\Original\LuaCore\changeRules.lua:1141: attempt to perform arithmetic on a nil value (field '?')
stack traceback:
    ...Desktop\Empires of Dust\Original\LuaCore\changeRules.lua:1141: in local 'newItemFn'
    ...Desktop\Empires of Dust\Original\LuaCore\changeRules.lua:1210: in local 'createAuthoritativeDefaultRulesSubtable'
    ...Desktop\Empires of Dust\Original\LuaCore\changeRules.lua:1397: in main chunk
    [C]: in function 'require'
    ...s of Dust\Original\MechanicsFiles\calculateCityYield.lua:17: in main chunk
    [C]: in function 'require'
    ...dministrator\Desktop\Empires of Dust\Original\events.lua:231: in main chunk
 
Hi @Prof. Garfield , I'm getting some errors with the new template. First was duplicate files, so I deleted a few duplicates (onUseNukes, combatSettings.lua [both in base folder and in Mechanics] and legacyEvents.txt. Now getting this message:
Can you please post the COSMIC2 section of your rules?
 
Here you are!
Code:
@COSMIC2
TradeGoldMultiplier, 100
TradeScienceMultiplier, 0
ImpassableAir, 1
TerrainDefenseForAir, 0
CityPopulationLossAttack, 1
CityPopulationLossCapture, 1
UnitShieldColor, 28
NoStackKills, 1
EventHeapSize, 106480, 1
NumberOfTerrainTypes, 16
NoIncrementalRushBuy, 1
MovementMultipliers, 1, 2
RoadMultiplier, 1, 6
RailroadMultiplier, 1, 4
RiverMultiplier, 1, 6
AlpineMultiplier, 1, 3
ProductionCarryOver,0
NumberOfUnitTypes, 128
AICapitalizationLimit, 1200
PlayableTribes, 0b00000010
PlayableDifficulties, 0b000000
NumberOfTechs, 121
 
@ThichN

How many maps does this scenario/mod have? If more than 1, you need a NumberOfTerrainTypes for each one.
 
Top Bottom