[TOTPP] Prof. Garfield's Lua Code Thread

OK, so I've gone through every line of code, removed my entire added code in events.lua, and even then, I get this issue:

- All barbarian units, when attacking cities, do not deal or take damage
- They do deal and take damage outside of cities, as normal
- They can be attacked and damaged from cities (when the attack is launched from a city)
- All barb units are effected, making me think this is something to do with a tribe setting somewhere

When events.lua runs, is it editing lua files elsewhere in the template? I went through the files, but couldn't make out if anything would be amiss in there. The code was working perfectly fine in a previous savegame -- and still does! The barbs can attack cities in that savegame. I feel like I am missing something very obvious.

Removing the events.lua file corrects the issue, but then, well, no lua. Happy to post the file, if it might help solve this.
 
OK, so I've gone through every line of code, removed my entire added code in events.lua, and even then, I get this issue:

- All barbarian units, when attacking cities, do not deal or take damage
- They do deal and take damage outside of cities, as normal
- They can be attacked and damaged from cities (when the attack is launched from a city)
- All barb units are effected, making me think this is something to do with a tribe setting somewhere

When events.lua runs, is it editing lua files elsewhere in the template? I went through the files, but couldn't make out if anything would be amiss in there. The code was working perfectly fine in a previous savegame -- and still does! The barbs can attack cities in that savegame. I feel like I am missing something very obvious.

Removing the events.lua file corrects the issue, but then, well, no lua. Happy to post the file, if it might help solve this.

Yes, I will need your events.lua file to diagnose this. The template is actually designed so that you shouldn't have to change events.lua, but, since I haven't released an updated how-to guide, I can't fault you for not realising this.

The events.lua file is the starting point for all events. All the files in the template are ultimately run by events.lua, either directly using require, or by being run by a require line in another file.
 
Aha! That makes sense. I also kind of dove headfirst into all of this without even considering that those files were there to provide better organization. Thanks Prof. Here is my attached file. Apologies if the way I organized stuff is somewhat archaic.
 
OK, so I've gone through every line of code, removed my entire added code in events.lua, and even then, I get this issue:
I misread this, thinking that removing your added code resolved the problem. Since the problem persists, it could be my code.

Have you established an embassy with the barb tribe or investigated a city?

Does doing this trigger your barbarian issue?

Have you been using the diplomacy module to change treaties or forbid them from changing?

How many rounds of combat take place? Does combat stop immediately, or does it go on forever making you force quit the game?

My current hypothesis is that the weird barbarian 'diplomacy' is interacting with my code which prevents tribes not at war from starting wars by having 0 rounds of combat to 'cancel' the attack.

In events.lua, try replacing this code (line 996 in the file you sent me)

Code:
civ.scen.onInitiateCombat( function(attacker,defender,attackerDie,attackerPower,defenderDie,defenderPower,isSneakAttack)
    diplomacy.checkTreaties()

    aggressorLocation = attacker.location
    aggressorVetStatus = attacker.veteran
    aggressor = attacker
    victimVetStatus = defender.veteran
    victim = defender
    if diplomacy.contactExists(attacker.owner,defender.owner) and not diplomacy.warExists(attacker.owner,defender.owner) then
        return coroutine.create(function() end)
    end
    return combatSettings.onInitiateCombatMakeCoroutine(attacker,defender,attackerDie,attackerPower,defenderDie,defenderPower,isSneakAttack)
end)
With this code:
Code:
civ.scen.onInitiateCombat( function(attacker,defender,attackerDie,attackerPower,defenderDie,defenderPower,isSneakAttack)
    diplomacy.checkTreaties()

    aggressorLocation = attacker.location
    aggressorVetStatus = attacker.veteran
    aggressor = attacker
    victimVetStatus = defender.veteran
    victim = defender
    if diplomacy.contactExists(attacker.owner,defender.owner) and not diplomacy.warExists(attacker.owner,defender.owner) and attacker.owner.id ~= 0 and defender.owner.id ~= 0 then
        return coroutine.create(function() end)
    end
    return combatSettings.onInitiateCombatMakeCoroutine(attacker,defender,attackerDie,attackerPower,defenderDie,defenderPower,isSneakAttack)
end)
These lines are the only changed lines:
Code:
    if diplomacy.contactExists(attacker.owner,defender.owner) and not diplomacy.warExists(attacker.owner,defender.owner) and attacker.owner.id ~= 0 and defender.owner.id ~= 0 then
        return coroutine.create(function() end)
    end
 
Thanks for looking into this!

I'm on a brand new map -- no dip contact, investigating cities, etc. I also haven't played with the diplomacy module. Where is that located? Should I look into it?

How many rounds of combat take place? Does combat stop immediately, or does it go on forever making you force quit the game?

This is the good news: the barbarian attacks with its # of attacks allocated (example: 2 for cavalry), and then that's it. No damage taken/received, though -- and only in cities, strangely.

Oh, it also happens when barbarians attack AI cities, too!

In events.lua, try replacing this code (line 996 in the file you sent me)

Done! But the issue persists. :(
Hmm, maybe I'll try replacing the Lua Template with a fresh one? Could this help?
 
I also haven't played with the diplomacy module. Where is that located? Should I look into it?
Don't bother. I intend to change that module to make it more straightforward to use. That's my next project after getting land/sea transport to work (which I'm in the middle of).
This is the good news: the barbarian attacks with its # of attacks allocated (example: 2 for cavalry), and then that's it. No damage taken/received, though -- and only in cities, strangely.

Oh, it also happens when barbarians attack AI cities, too!
What other modules have you been using? It looks like what we have here is "combat" which is being cancelled before any rounds of combat take place. In the default version of MechanicsFiles\combatSettings.lua, this happens when an attacker is calculated to have 0 strength against an opponent. Have you, for example, registered any combat mechanics in MechanicsFiles\registerCombatModifiers.lua? Or, generated a rules_lst.txt file and changed combat prowess there?
 
I haven't used any modules, only edited the events.lua file. I also did not generate a rules_lst.txt file. I did edit my rules.txt file after applying Lua edits, but I've been doing this throughout with no issues.

Specifically, for rules.txt, I added a terrain type after applying Lua changes. I had an older rules.txt, and tried it just in case, but it also presents the same issue.

Attaching the 2 files you mentioned, plus the modified events.lua since your edit above, in case it helps diagnose!
 
Please replace the existing files in your directory by the two files attached here.

Once you've done so, run the tests again. I've added two text boxes, "Zero turn fight because of ATTACK POWER", and "Zero turn fight because of DIPLOMACY". Let me know if either of these text boxes show up when you experience your issue. If neither box does, then please PM me your entire folder, so I can re-create the situation on my machine.
 

Attachments

Prof! "Zero turn fight because of ATTACK POWER" showed up!
OK, I think I have the answer.
Barbarian attacker vs. All of the following adjustments apply only when the attacking unit belongs to tribe 0, the barbarians.
  1. Human defender. If the defender belongs to a tribe controlled by a human player, the barbarian attacker receives an adjustment based on the game's difficulty level. The adjustment may be less than 1 (i.e. a penalty), equal to 1 (no effect), or greater than 1 (i.e. a bonus) depending on that value. The adjustments are: Chieftain x0.25, Warlord x0.5, Prince x0.75, King x1, Emperor x1.25, Deity x1.5. Documented in (3)(n), although the implication there is that this adjustment is applied regardless of the tribe of the defender, when in fact it is only applied when the defender belongs to a human player.
  2. AI defender. If the defender belongs to a tribe controlled by an AI player, the barbarian attacker receives a x0.5 adjustment (penalty). Not previously documented, but correctly noted in a separate thread.
  3. Defender's only city. If the defender is located in the only city belonging to the defender's tribe, the barbarian attacker receives a x0 adjustment (full penalty) -- in other words, its attack strength is set to 0, rendering all other adjustments irrelevant. Not previously documented, but essentially noted correctly in a separate thread.
  4. Defender's capital city. If the defender is located in a city with the Palace improvement, but this is not the defender's only city, the barbarian attacker receives a x0.5 adjustment (penalty). Not previously documented; noted as an adjustment in a separate thread but with an incorrect formula.
  5. Defender with Great Wall. If the defender's tribe controls the Great Wall wonder and it has not expired, the attacker receives a x0.5 adjustment (penalty). Not previously documented in the Combat Guide, but understood in a general sense due to the description of the Great Wall wonder, which says, "Combat strength doubled against barbarians." Technically the attack strength is halved, rather than the defense strength being doubled.
Barbarian attack power is reduced to 0 if the unit is attacking a tribe's only city. So, combatSettings.lua runs the standard combat calculation and returns an attack value of 0. However, my added code interprets 0 attack as "can't attack this thing, so cancel attack", which makes sense in most contexts.

In the attached file, I've changed the 0 attack power check so that it doesn't cancel the attacks of barbarian units.
 

Attachments

This works! :worship: Wow, good info there from Knighttime, too. I had no idea. This explains tidily why saved games were operating fine. Since barbarians in my mod's early game are pretty important, I'm glad it could be resolved! I may also put in a safeguard, as in the event that generates barbs does not activate until 20 turns in or something.

Thanks Prof., for your expertise and time in solving this and other issues. Very generous of you. Much appreciated!
 
Since barbarians in my mod's early game are pretty important, I'm glad it could be resolved! I may also put in a safeguard, as in the event that generates barbs does not activate until 20 turns in or something.
If you want barbarians to be able to threaten even a single city, you can make this change in combatSettings.lua:
Code:
local function computeCombatStatistics(attacker, defender, isSneakAttack)
    
    local combatModifierOverride = {aCustomMult=1,dCustomMult=1}
Code:
local function computeCombatStatistics(attacker, defender, isSneakAttack)
    
    local combatModifierOverride = {aCustomMult=1,dCustomMult=1,aBarbarianAttackerVsDefendersOnlyCity=1}
 
Thanks Prof.
At some stage soon I'll post screenshots, to show progress on what it is I'm working on!

I've been tinkering with the gen.createUnit code, and have run into some issues; the console says I am missing a ')' or that there is an unexpected symbol. Making sure I am on the right track here. This is just a test. Ideally, I'd like to somehow specify that "whatever tribe researches the tech first" gets the "General" inCapital.

I also cannot figure out how to create a line break in the dialog. Is it ^^, as was previously mentioned, or is that just for ui.text?

Code:
local GreatGeneral = civ.ui.loadImage("Images/greatgeneral1.bmp")
discreteEvents.onCityProcessingComplete(function (turn, tribe)
    if tribe:hasTech(techAliases.Tributaries) then
        gen.justOnce("someTechReceivedBy"..tostring(tribe.id),function()
        function gen.createUnit(unitAliases.GutianRiders,civ.getTribe(3),{0,0},count = nil, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false)
        local dialog = civ.ui.createDialog()
                dialog.title = "A legendary figure appears..."
                dialog.width = 350
                dialog:addImage(GreatGeneral)
                local multiLineText = "Rumor has it that a great general has won many battles. (A civilization has researched Tributaries.) 'War is the father and king of all: some he has made gods, and some men; some slaves and some free.' - Heraclitus"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                dialog:show()
                end
        end)
    end
end)
 
Code:
function gen.createUnit(unitAliases.GutianRiders,civ.getTribe(3),{0,0},count = nil, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false)
should be
Code:
gen.createUnit(unitAliases.GutianRiders,civ.getTribe(3),{0,0},{count = 1, randomize = false, scatter = false, inCapital = true, veteran = true, homeCity = nil, overrideCanEnter = false, overrideDomain = false, overrideDefender = false})
Also, at the moment, this event runs every time a tribe discovers Tributaries, but each time it creates a unit for tribe 3. If you want this to only happen once, regardless of who discovers Tributaries, then change this line
Code:
gen.justOnce("someTechReceivedBy"..tostring(tribe.id),function()
to
Code:
gen.justOnce("TributariesResearched",function()
If you only want this to happen when tribe 3 researches the tech, make the same change above, and also change the line
Code:
if tribe:hasTech(techAliases.Tributaries) then
to
Code:
if civ.getTribe(3):hasTech(techAliases.Tributaries) then
 
I also cannot figure out how to create a line break in the dialog. Is it ^^, as was previously mentioned, or is that just for ui.text?
If you're using something like text.simple, then you need to insert the newline character ("\n") directly before it. Something like
Code:
text.simple("This line is left aligned\n^^This line is centred\n^This line is\n left aligned")
This will be 3 lines of text.
 
Wonderful, thanks Prof.! All this works and I was able to piece together some operational, related code.

Here is an image, by the way! Really enjoying this.

Spoiler :
tributaries.png


So, new question, then...

At the moment, I successfully made a dialog with 7 options, 6 of which will reduce the amount of money one has.
But how do I prevent this option from being shown / prevent it from "going through" if the player or AI does not have enough money for the cost?

I also wanted to add another option that says, "Threaten them!" and then gives a 50/50 chance of a "free unit" or a "hostile unit" ... I know how to add the chance with math.random, for it to do one thing vs do nothing, but don't know how to have it choose between 2 things randomly with a 50/50 chance. If that makes sense.

Also, you mentioned threshold tables before to cycle through a random selection of units. I'd like to learn more about those. Do you have resources you could point to or did you explain this elsewhere you could link to?

Here is my code...

Spoiler :
Code:
local function doWhenUnitKilled(loser,winner)
    if loser.type == unitAliases.Village then
        local choice = nil
        if winner.owner.isHuman then
            local dialog = civ.ui.createDialog()
                dialog.title = "Hire Mercenaries"
                dialog.width = 500
                dialog:addImage(BarbarianCapture)
            local multiLineText= "Which mercenaries would you like to hire?"
                text.addMultiLineTextToDialog(multiLineText,dialog)
                    dialog:addOption("Gutians (100 gold pieces)", 1)
                    dialog:addOption("Nabateans (150 gold pieces)", 2)
                    dialog:addOption("Galatians (250 gold pieces)", 3)
                    dialog:addOption("Sarmatians (350 gold pieces)", 4)
                    dialog:addOption("Numidians (500 gold pieces)", 5)
                    dialog:addOption("Gauls (500 gold pieces)", 6)
                    dialog:addOption("Do nothing (clears this village for now)", 7)
                choice = dialog:show()
            else
                choice = math.random(1,2,3,4,5,6,7)
            end
                if choice == 1 then
                    local newGutianRiders = civ.createUnit(unitAliases.GutianRiders, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -100)
                elseif choice == 2 then
                    local newNabateanCamels = civ.createUnit(unitAliases.NabateanCamels, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -150)
                elseif choice == 3 then
                    local newGalatianInfantry = civ.createUnit(unitAliases.GalatianInfantry, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -250)
                elseif choice == 4 then
                    local newSarmatianRiders = civ.createUnit(unitAliases.SarmatianRiders, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -350)
                elseif choice == 5 then
                    local newNumidianCavalry = civ.createUnit(unitAliases.NumidianCavalry, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -500)
                elseif choice == 6 then
                    local newGallicRaiders = civ.createUnit(unitAliases.GallicRaiders, winner.owner, winner.location)
                        winner.owner.money = math.max(winner.owner.money -500)
                elseif choice == 7 then
                    civ.ui.text("Mercenaries from this tribe may return in the future.")
                end
        end
end
 
Also, you mentioned threshold tables before to cycle through a random selection of units. I'd like to learn more about those. Do you have resources you could point to or did you explain this elsewhere you could link to?

Here is my code...

Here is what I said elsewhere:

You could use a threshold table to determine relative quantities.

Something like this:
Code:
local quantityChanceThresholdTable = gen.makeThresholdTable({
    [0.85] = 6, -- 15%
    [0.75] = 3, -- 10%
    [0.5] = 2, -- 25%
    [0.3] = 1, -- 20%
    [0] = 0, -- 30
})
local function getQuantity()
    return quantityChanceThresholdTable[math.random()]
end
Basically, a regular table only returns a (non-nil) value when the key you put into it is already in the table. The threshold table works by finding the largest index which is less than the submitted key. This can be used to choose between options randomly like shown above.

At the moment, I successfully made a dialog with 7 options, 6 of which will reduce the amount of money one has.
But how do I prevent this option from being shown / prevent it from "going through" if the player or AI does not have enough money for the cost?
Here is one way to do it (untested code). You'll have to fill in the rest of the optionsTable for this to work properly. Make sure you have an option for every index between 1 and 7, otherwise there could be a crash or an infinite loop.
Code:
local optionsTable = {}
optionsTable[1] = {
    text = "Gutians (100 gold pieces)",
    cost = 100,
    unitType = unitAliases.GutianRiders,
}
optionsTable[2] = {
    text = "Nabateans (150 gold pieces)",
    cost = 150,
    unitType = unitAliases.NabateanCamels,
}

optionsTable[7] = {
    text = "Do nothing (clears this village for now)",
    cost = 0,
    unitType = nil,
    specialEffect = function(loser,winner)
        if winner.owner.isHuman then
            civ.ui.text("Mercenaries from this tribe may return in the future.")
        end
    end,
}
optionsTable[8] = {
    text = "Threaten them",
    cost = 0,
    unitType = nil,
    specialEffect = function(loser,winner)
        if math.random() < 0.6 then
            -- do something with 60% chance           
        else
            -- do something else with remaining 40% chance

        end
    end,
}
local function doWhenUnitKilled(loser,winner)
    if loser.type == unitAliases.Village then
        local choice = nil
        if winner.owner.isHuman then
            local dialog = civ.ui.createDialog()
                dialog.title = "Hire Mercenaries"
                dialog.width = 500
                dialog:addImage(BarbarianCapture)
            local multiLineText= "Which mercenaries would you like to hire?"
            text.addMultiLineTextToDialog(multiLineText,dialog)
            for choiceID,choiceInfo in pairs(optionsTable) do
                if winner.owner.money >= choiceInfo.cost then
                    dialog:addOption(choiceInfo.text,choiceID)
                end
            end
            choice = dialog:show()
        else
            repeat
                choice = math.random(1,#optionsTable)
            until winner.owner.money >= optionsTable[choice].cost
        end
        local choiceInfo = optionsTable[choice]
        if choiceInfo and choiceInfo.unitType then
            civ.createUnit(choiceInfo.unitType,winner.owner,winner.location)
            winner.owner.money = winner.owner.money - choiceInfo.cost
        else
            if choiceInfo and choiceInfo.specialEffect then
                choiceInfo.specialEffect(loser,winner)
            end
            if winner.owner.isHuman then
                civ.ui.text("Mercenaries from this tribe may return in the future.")
            end
        end
    end
end
The code gathers information from the optionsTable (which is a table of tables). This way, we don't have to repeat similar code over and over.
Here, for each option in the optionsTable, the game checks if the winner has enough money, and, if so, creates the option.
Code:
                if winner.owner.money >= choiceInfo.cost then
                    dialog:addOption(choiceInfo.text,choiceID)
                end
Here, rather than filtering choices and forcing a single choice among affordable options, I just let the game keep making choices until it chooses one that it can afford.
Code:
            repeat
                choice = math.random(1,#optionsTable)
            until winner.owner.money >= optionsTable[choice].cost
Here, I separate the choice into two cases. The first case is that the choice has a unitType specified in the option, in which case that unit is created. Otherwise, the specialEffect function is run (if it exists).
Code:
        local choiceInfo = optionsTable[choice]
        if choiceInfo and choiceInfo.unitType then
            civ.createUnit(choiceInfo.unitType,winner.owner,winner.location)
            winner.owner.money = winner.owner.money - choiceInfo.cost
        else
            if choiceInfo and choiceInfo.specialEffect then
                choiceInfo.specialEffect(loser,winner)
            end
        end

Note:
Code:
choice = math.random(1,2,3,4,5,6,7)
is the incorrect way to use math.random. math.random() returns a number between 0 and 1. math.random(n) returns an integer between 1 and n (inclusive). math.random(m,n) returns an integer between m and n (inclusive). So, your code would just choose an integer between 1 and 2. You should have written math.random(1,7)

I also wanted to add another option that says, "Threaten them!" and then gives a 50/50 chance of a "free unit" or a "hostile unit" ... I know how to add the chance with math.random, for it to do one thing vs do nothing, but don't know how to have it choose between 2 things randomly with a 50/50 chance. If that makes sense.
You can just use an 'else' statement. I didn't do anything here, but the first option has a 60% chance of happening, and the second has 40%. Changing the number changes the odds.
Code:
optionsTable[8] = {
    text = "Threaten them",
    cost = 0,
    unitType = nil,
    specialEffect = function(loser,winner)
        if math.random() < 0.6 then
            -- do something with 60% chance           
        else
            -- do something else with remaining 40% chance

        end
    end,
}

Let me know if you need more help.
 
OK, first of all. Excellent explanation. Very clear, so much so that I went through and made memo of areas I'd like to see similar tables. What a useful piece of code there.

Second of all... just amazing effect and no issues whatsoever. I wrote out the code, as I like to do as it imprints into my memory better than copy/paste, so I had a few typos. Once I ironed those out, thanks to the handy console, I was good to go.

Here is some visual essay fun:
Spoiler :
1.png

Starting off here with 0 gold, and the tribal envoy unit (bottom right) about to "attack" a village.

2.png

System correctly understands my coffers having 0 gold, so I am presented with only these 2 options.

3.png

I take the "threaten them" risk/reward, and got a Gallic Warhorse! (going to do something about that... kind of too strong a unit for this early game)

5.png

OK, let's go back in time. I cheated to give myself 1000 gold coins. Now all options appear!

6.png

I chose Gauls and received some raiders.



Thank you, Prof. This is really cool.

Next, I'm going to try merging a couple of the lessons you've taught me here to see if I can adjust the options based on tech the player has...
 
By the way, I should also mention the above works great with the AI!

I decided to take a break from menu dialogs and to make sure my generals are giving the attack or defense bonuses where due. To do this, I adapted code from Tootall's Napoleon scenario. There are no errors coming up in-game or console, but I do not think the attack bonus is being given. I've made sure domains are set to 0 for both the general and the attacking units. This is a tough one to test, though, due to Civ's battle equation. How does this piece of code look?

Spoiler :
Code:
local onActivateUnitFunction = function (unit, source)
    for i = 0, civ.cosmic.numberOfUnitTypes - 1 do
        civ.getUnitType(i).attack = baseUnitAttack[i]
    end
    local basetype = unit.type
    local oldAttackValue = basetype.attack
    local attackFactor = 0.0
    local position = unit.location
    if position.z == 0 then
        for stackMember in position.units do
            if stackMember.id ~= unit.id then
                if stackMember.type == unitAliases.General1T
                   then
                        attackFactor = math.max(attackFactor, 0.4)
                end
            end
        end
    end
end
 
By the way, I should also mention the above works great with the AI!

I decided to take a break from menu dialogs and to make sure my generals are giving the attack or defense bonuses where due. To do this, I adapted code from Tootall's Napoleon scenario. There are no errors coming up in-game or console, but I do not think the attack bonus is being given. I've made sure domains are set to 0 for both the general and the attacking units. This is a tough one to test, though, due to Civ's battle equation. How does this piece of code look?

Spoiler :
Code:
local onActivateUnitFunction = function (unit, source)
    for i = 0, civ.cosmic.numberOfUnitTypes - 1 do
        civ.getUnitType(i).attack = baseUnitAttack[i]
    end
    local basetype = unit.type
    local oldAttackValue = basetype.attack
    local attackFactor = 0.0
    local position = unit.location
    if position.z == 0 then
        for stackMember in position.units do
            if stackMember.id ~= unit.id then
                if stackMember.type == unitAliases.General1T
                   then
                        attackFactor = math.max(attackFactor, 0.4)
                end
            end
        end
    end
end
In MechanicsFiles\combatSettings.lua, there is a line (approx 272)
Code:
    --civ.ui.text("Attacker: "..tostring(calculatedAttackerStrength/8).." FP:"..calculatedAttackerFirepower.." Defender: "..tostring(calculatedDefenderStrength/8).." FP:"..calculatedDefenderFirepower)
Which, when uncommented, will show the combat power before combat.

You don't seem to assign a new attack value anywhere in this code. This method of doing things will also conflict with the customCosmic module, and possibly won't work at all because of it.

However, the modern template has alternate ways of doing this. Look in MechanicsFiles\registerCombatModifiers.lua or MechanicsFiles\leaderBonusSettings.lua in order to assign combat bonuses or leader bonuses.

If you press CTRL+SHIFT+F4, you can open the scripts menu, which will let you generate a file setTraits.lua. You'll first need to use the appropriate script to generate object.lua, which is the "modern" version of unitAliases/techAliases/tribeAliases tables. You can still keep the unitAliases table around, to avoid re-writing any code you already have.

Traits let you assign civ items to groups, so they can be later referred to by a string. The above modules rely on traits for group assignments and conditions.

There are commented out examples at the bottom of the settings files, which I used for testing. Note that they reference units using gen.original.uSomeUnit, but you'll want to use object.uSomeUnit instead. Remember to require the object module with local object=require("object"). Let me know if you need help.
 
Back
Top Bottom