Quick Modding Questions Thread

I did it and it still doesn't work.
Here's the modinfo:
Spoiler Modinfo :

<?xml version="1.0" encoding="utf-8"?>
<Mod id="4365a6cc-c4b9-4334-b448-97ed54b0a51e" version="1">
<Properties>
<Name>Alternate City Lists - Gathering Storm</Name>
<Description>A mod that changes city lists, adding cities, changing names into native names.</Description>
<Created>1588288179</Created>
<Teaser>A mod that changes city lists.</Teaser>
<Authors>Igor</Authors>
<CompatibleVersions>1.2,2.0</CompatibleVersions>
<LoadOrder>500</LoadOrder>
</Properties>
<Dependencies>
<Mod id="9786606e-c741-4c51-9833-88999c0c193f" title="Alternate City Lists" />
</Dependencies>
<References>
<Mod id="4873eb62-8ccc-4574-b784-dda455e74e68" title="Expansion: Gathering Storm" />
</References>
<FrontEndActions>
<UpdateText id="GSTextUpdate">
<File priority="500">Names.xml</File>
</UpdateText>
</FrontEndActions>
<InGameActions>
<UpdateDatabase id="DatabaseUpdate">
<File priority="500">Database GS.xml</File>
</UpdateDatabase>
<UpdateText id="CityListTextUpdate">
<File priority="500">City Lists GS.xml</File>
</UpdateText>
<UpdateText id="InGame Text">
<File priority="500">Names.xml</File>
</UpdateText>
</InGameActions>
<Files>
<File>City Lists GS.xml</File>
<File>Database GS.xml</File>
<File>Names.xml</File>
</Files>
</Mod>
LoadOrder has to be set as a Property of an Individual Action, not as a property of the overall mod.

At one time setting LoadOrder as a property of the overall mod worked, but Firaxis disabled this several patches ago.

File priority only affects the relative order a file loads from within the list in a single action, not as a relative order as compared to files from a different Action or Mod.
 
LoadOrder has to be set as a Property of an Individual Action, not as a property of the overall mod.

At one time setting LoadOrder as a property of the overall mod worked, but Firaxis disabled this several patches ago.

File priority only affects the relative order a file loads from within the list in a single action, not as a relative order as compared to files from a different Action or Mod.
So what should I write?
This?
<UpdateText id="CityListTextUpdate">
<LoadOrder="500">City Lists GS.xml</LoadOrder>
 
Code:
    <UpdateDatabase id="XML_Actions">
      <Properties>
        <LoadOrder>500</LoadOrder>
      </Properties>
      <File ………
You can also enter the LoadOrder and its value in modbuddy as a custom property of an action.
 
Code:
    <UpdateDatabase id="XML_Actions">
      <Properties>
        <LoadOrder>500</LoadOrder>
      </Properties>
      <File ………
You can also enter the LoadOrder and its value in modbuddy as a custom property of an action.
Thanks! Problem finally solved! Every time I try making even the smallest change to the game I curse whoever programmed the whole load order thing this way. I mean, shouldn't it be obvious that a mod has to load after the base game?!
 
Sorry for replacing post (got lost in other issues), but I'm having an issue that most likely has a simple solution but it is frustrating and I can't seem it figure it out.
I'm trying to change some default parameters for some improvements in the game.
One of these changes relates to the Chemamull. I'm trying to remove its Appeal restriction and have it gain Culture equal to 100% of the tiles Appeal, rather than 75%.
So I use the following syntax:
Code:
<Improvements>
       <Replace ImprovementType="IMPROVEMENT_CHEMAMULL" Name="LOC_IMPROVEMENT_CHEMAMULL_NAME" Description="LOC_IMPROVEMENT_CHEMAMULL_DESCRIPTION" Icon="ICON_IMPROVEMENT_CHEMAMULL" PlunderType="PLUNDER_FAITH" PlunderAmount="25" Buildable="true" PrereqCivic="CIVIC_CRAFTSMANSHIP" YieldFromAppeal="YIELD_CULTURE" YieldFromAppealPercent="100" TraitType="TRAIT_CIVILIZATION_IMPROVEMENT_CHEMAMULL"/>
</Improvements>
Suddenly, the improvement was no longer showing up as an option for builders to build (even though it was still showing up in the Civic Tree, as well as Mapuche descriptions). I realized that many, but not all, of the improvements I was trying to change were disappearing, including my Fort changes and Chateau changes. I also realized that those three were the only three I was using the "replace" syntax for. So, I decided to change it and try this instead:
Code:
<Improvements>
        <Delete ImprovementType="IMPROVEMENT_CHEMAMULL"/>
       <Row ImprovementType="IMPROVEMENT_CHEMAMULL" Name="LOC_IMPROVEMENT_CHEMAMULL_NAME" Description="LOC_IMPROVEMENT_CHEMAMULL_DESCRIPTION" Icon="ICON_IMPROVEMENT_CHEMAMULL" PlunderType="PLUNDER_FAITH" PlunderAmount="25" Buildable="true" PrereqCivic="CIVIC_CRAFTSMANSHIP" YieldFromAppeal="YIELD_CULTURE" YieldFromAppealPercent="100" TraitType="TRAIT_CIVILIZATION_IMPROVEMENT_CHEMAMULL"/>
</Improvements>
However, this was ALSO not working. I'm not sure what I'm doing wrong. My syntax for the other improvements seem to be working fine (though, they are using either "Row" commands or "Update" commands). I checked the "Database.Log" and it indicates nothing is wrong. It continues to read the file far after the failed improvement lines (usually if something is wrong with the mod, it fails to include anything after the error)... What the hell is going on???
 
Last edited:
Is there an accepted, 'correct' way to use special (non-English) characters within Localized Text?

Are there restrictions on which elements in the game can accept them? I am asking this because I thought that perhaps the fonts which render things in-game may restrict the use of special characters, if those characters don't exist in that font. Naturally, the game uses a few different fonts.

By way of example - I note that Sukritact's Icelandic civilization mod implements special characters; the two that I have witnessed working in-game for myself include cities and rivers. When I try to implement these in my mod, the characters are replaced by the ☒ symbol. Both his mod and mine appear to have these characters inserted in SQL files as explicit characters - not using character-codes etc.
 
Sorry for replacing post (got lost in other issues), but I'm having an issue that most likely has a simple solution but it is frustrating and I can't seem it figure it out.
I'm trying to change some default parameters for some improvements in the game.
One of these changes relates to the Chemamull. I'm trying to remove its Appeal restriction and have it gain Culture equal to 100% of the tiles Appeal, rather than 75%.
So I use the following syntax:
Code:
<Improvements>
       <Replace ImprovementType="IMPROVEMENT_CHEMAMULL" Name="LOC_IMPROVEMENT_CHEMAMULL_NAME" Description="LOC_IMPROVEMENT_CHEMAMULL_DESCRIPTION" Icon="ICON_IMPROVEMENT_CHEMAMULL" PlunderType="PLUNDER_FAITH" PlunderAmount="25" Buildable="true" PrereqCivic="CIVIC_CRAFTSMANSHIP" YieldFromAppeal="YIELD_CULTURE" YieldFromAppealPercent="100" TraitType="TRAIT_CIVILIZATION_IMPROVEMENT_CHEMAMULL"/>
</Improvements>
Suddenly, the improvement was no longer showing up as an option for builders to build (even though it was still showing up in the Civic Tree, as well as Mapuche descriptions). I realized that many, but not all, of the improvements I was trying to change were disappearing, including my Fort changes and Chateau changes. I also realized that those three were the only three I was using the "replace" syntax for. So, I decided to change it and try this instead:
Code:
<Improvements>
        <Delete ImprovementType="IMPROVEMENT_CHEMAMULL"/>
       <Row ImprovementType="IMPROVEMENT_CHEMAMULL" Name="LOC_IMPROVEMENT_CHEMAMULL_NAME" Description="LOC_IMPROVEMENT_CHEMAMULL_DESCRIPTION" Icon="ICON_IMPROVEMENT_CHEMAMULL" PlunderType="PLUNDER_FAITH" PlunderAmount="25" Buildable="true" PrereqCivic="CIVIC_CRAFTSMANSHIP" YieldFromAppeal="YIELD_CULTURE" YieldFromAppealPercent="100" TraitType="TRAIT_CIVILIZATION_IMPROVEMENT_CHEMAMULL"/>
</Improvements>
However, this was ALSO not working. I'm not sure what I'm doing wrong. My syntax for the other improvements seem to be working fine (though, they are using either "Row" commands or "Update" commands). I checked the "Database.Log" and it indicates nothing is wrong. It continues to read the file far after the failed improvement lines (usually if something is wrong with the mod, it fails to include anything after the error)... What the hell is going on???
Are you sure your code is loading after Rise and Fall ? Ie, are you sure your problem is not essentially the same as the issue IgorS was having ?

Without your actual mod (or at the very least the actual xml file involved from your mod as well as the modinfo file) to look at it will be difficult to do more than make the usual guesses as to what is wrong.
 
Are you sure your code is loading after Rise and Fall ? Ie, are you sure your problem is not essentially the same as the issue IgorS was having ?

Without your actual mod (or at the very least the actual xml file involved from your mod as well as the modinfo file) to look at it will be difficult to do more than make the usual guesses as to what is wrong.
I've set the LoadOrder to 1001. All of my LoadOrers are that high (not sure if thats an issue).
Also, other changes I'm making in the mod are working. So I know it is loading. It isn't working with any of the lines of syntax starting with "Replace" or "Delete".
For example, this is working:
Code:
<Improvement_YieldChanges>
        <Update>
            <Where ImprovementType="IMPROVEMENT_KURGAN" YieldType="YIELD_GOLD"/>
            <Set YieldChange="2"/>
        </Update>
</Improvement_YieldChanges>
But this is not:
Code:
<Improvements>
        <Delete ImprovementType="IMPROVEMENT_FORT"/>
        <Row ImprovementType="IMPROVEMENT_FORT" Name="LOC_IMPROVEMENT_FORT_NAME" Description="LOC_IMPROVEMENT_FORT_DESCRIPTION" Icon="ICON_IMPROVEMENT_FORT" PlunderType="NO_PLUNDER" Buildable="true" PrereqTech="TECH_SIEGE_TACTICS" CanBuildOutsideTerritory="true" DefenseModifier="4" GrantFortification="2" Housing="1" TilesRequired="2"/>
</Improvements>
If I change that last Fort code into a "Replace" (and remove the "Delete" of course), it also isn't working.
And just to be clear, by "not working", I mean it isn't appearing as an action for a Builder, despite still showing up in the Civic/Tech tree and in the Civs description.

Maybe it has something to do with the fact I'm altering the <Improvements> table? I'm trying to add Housing to the Fort, remove the river restriction from the Chateau, and remove the appeal restriction from the Chemamull. All of the information is in the <Improvements> table. Everything else I'm changing isn't on the <Improvements> table and is working fine.

Update: So, I tried the following "Update" syntax and it worked:
Code:
<Improvements>
        <Update>
            <Where ImprovementType="IMPROVEMENT_CHATEAU"/>
            <Set RequiresRiver="false"/>
        </Update>
</Improvements>
Unforunately, I do not know how to update a row within the <Improvements> table with new information. With the Chateau and Chemamull, I'm just changing existing data. However, I'm trying to give the Fort, Roman Fort, and Pa +0.5 Housing by adding [Housing="1" TilesRequired="2"] at the end of the line. I tried this and it didn't work:
Code:
<Improvements>
        <Row ImprovementType="IMPROVEMENT_FORT" Housing="1" TilesRequired="2"/>
</Improvements>
I'm assuming doing that just clashes with the existing "IMPROVEMENT_FORT" row in the table.

Update 2: So, I didn't realize you could just "Update" and "Set" information in a row that wasn't already present. Thus, I think I got almost everything figured out, because this has seemed to work:
Code:
<Improvements>
        <Update>
            <Where ImprovementType="IMPROVEMENT_CHATEAU"/>
            <Set SameAdjacentValid="false"/>
        </Update>
</Improvements>
Even though "SameAdjacentValid" isn't in the row, I suppose in the overall <Improvements> table, it exists, and thus can be used (yay I learned something). However, it seems as though the following modifier isn't working for me:
Code:
<ImprovementModifiers>
        <Row ImprovementType="IMPROVEMENT_CHATEAU" ModifierId="SM_CHATEAU_RIVERADJACENCY_CULTURE"/>
        <Row ImprovementType="IMPROVEMENT_CHATEAU" ModifierId="SM_CHATEAU_RIVERADJACENCY_HOUSING"/>
    </ImprovementModifiers>
    <Modifiers>
        <Row ModifierId="SM_CHATEAU_RIVERADJACENCY_CULTURE" ModifierType="MODIFIER_SINGLE_PLOT_ADJUST_PLOT_YIELDS" SubjectRequirementSetId="PLOT_ADJACENT_TO_RIVER_REQUIREMENTS"/>
        <Row ModifierId="SM_CHATEAU_RIVERADJACENCY_HOUSING" ModifierType="MODIFIER_SINGLE_CITY_ADJUST_IMPROVEMENT_HOUSING" SubjectRequirementSetId="PLOT_ADJACENT_TO_RIVER_REQUIREMENTS"/>
    </Modifiers>
    <ModifierArguments>
        <Row ModifierId="SM_CHATEAU_RIVERADJACENCY_CULTURE" Name="YieldType" Value="YIELD_CULTURE"/>
        <Row ModifierId="SM_CHATEAU_RIVERADJACENCY_CULTURE" Name="Amount" Value="1"/>
        <Row ModifierId="SM_CHATEAU_RIVERADJACENCY_HOUSING" Name="Amount" Value="1"/>
</ModifierArguments>
The culture bonus from being adjacent to a river IS working, but the housing isn't... not sure why... And just to be clear, the "SubjectRequirementSetId" of "PLOT_ADJACENT_TO_RIVER_REQUIREMENTS" is the one used by the Ziggurat.
 
Last edited:
As you've discovered in an <Update> you can "Set" any data for the existing row that is valid for that table, even if the original row is not using a particular column in the XML. The row is in fact using all of the columns for that table, but for data that is not needed the table's default settings of (generally) "false", "0", or "NULL" will be used by the game.

Housing adjustments that come from modifiers are not generally shown as an inherent effect of the plot or improvement, they are only reflected directly in the city, so you would need to examine the city's "growth" panel before and after building the improvement in order to determine whether the effect is being applied. The vexed question in the case of the Housing modifier as you are trying to set it up is whether or not the improvement will need to be adjacent to a river or whether the city will need to be adjacent to a river based on the modifier-type you are using.

In the case of MODIFIER_SINGLE_PLOT_ADJUST_PLOT_YIELDS it is clear that the improvement's plot needs to be river-adjacent.
 
As you've discovered in an <Update> you can "Set" any data for the existing row that is valid for that table, even if the original row is not using a particular column in the XML. The row is in fact using all of the columns for that table, but for data that is not needed the table's default settings of (generally) "false", "0", or "NULL" will be used by the game.

Housing adjustments that come from modifiers are not generally shown as an inherent effect of the plot or improvement, they are only reflected directly in the city, so you would need to examine the city's "growth" panel before and after building the improvement in order to determine whether the effect is being applied. The vexed question in the case of the Housing modifier as you are trying to set it up is whether or not the improvement will need to be adjacent to a river or whether the city will need to be adjacent to a river based on the modifier-type you are using.

In the case of MODIFIER_SINGLE_PLOT_ADJUST_PLOT_YIELDS it is clear that the improvement's plot needs to be river-adjacent.
I'm using the ModifierType "MODIFIER_SINGLE_CITY_ADJUST_IMPROVEMENT_HOUSING" from the Stepwell and the SubjectRequirementSetId "PLOT_ADJACENT_TO_RIVER_REQUIREMENTS" from the Ziggurat. I know that +X Culture is different than +X Housing as far as yields are concerned, so it wouldn't surprise me is the RequirementSet is more intended for normal yields than is something like housing. What would you suggest?

Also, has anyone else had a problem with the Alcazar and Monastery not being updated with the newer Gathering Storm stuff? For example, the Alcazar, as of Gather Storm, is supposed to gain Science base on 50% of the tiles appeal. In my games, that doesn't happen, nor does the tooltip or improvement description of the Alcazar update.
 
Last edited:
After having a closer look at the setup files (and well, now I think that civ5' AssignStartingPlots.lua file was not so complex after all...), I can confirm that the code is called after launching the game in the gameplay DLL.

But you can assign a random leader yourself from your own selection into your slot by adding some code in AdvancedSetup.lua in the OnStartButton() function using (for axample)
Code:
local playerConfig = PlayerConfigurations[0]
playerConfig:SetSlotStatus(SlotStatus.SS_TAKEN)
playerConfig:SetLeaderTypeName("LEADER_SALADIN")
playerConfig:SetLeaderName("LOC_LEADER_SALADIN_NAME")

Thanks for checking it out for me, I appreciate it.

How would your example code assign a random leader though?

I assume that since it's called on after launching the game then there's no way to create a mod with an lua script that will handle random leaders?
 
By writing your own function to do the random selection when you click the start button in the AdvancedSetup.lua file, and assigning your selection to the leader slots, YnAMP does that know with a leader ban list (which does not work as you want it, because it also apply the ban to the AI)

My function is a bit complex because I use TSL restriction too and want to prevent duplicates Leaders/Civilization so I override the whole randomization method, but to pick one random leaders from a restricted list (that you could query using SQL based on the ruleset in use) then leave the rest as they are, it doesn't have to be as complex.

edit part of the code, also handling CS, the list themselves (and some other variables/tables) are set in another part of the code, because I handle TSL before clicking start.
Code:
function OnStartButton()

    -- <<<<< YNAMP
  
    -- We can't have a nil Map Seed for the random selections
    if not MapConfiguration.GetValue("RANDOM_SEED") then
print(MapConfiguration.GetValue("RANDOM_SEED"), GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED"))
        local gameSeed = GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED")
        GameConfiguration.RegenerateSeeds()
        if gameSeed then
            GameConfiguration.SetValue("GAME_SYNC_RANDOM_SEED", gameSeed)
        end
print(MapConfiguration.GetValue("RANDOM_SEED"), GameConfiguration.GetValue("GAME_SYNC_RANDOM_SEED"))
    end
  
    -- hide the player section first to not show the mod selection for random slots
    Controls.PlayersSection:SetHide(true)
  
    -- output the last validation report to the log
    print(Controls.WindowTitle:GetToolTipString())
    ---[[
    local player_ids     = GameConfiguration.GetParticipatingPlayerIDs();
    local numPlayers     = #player_ids
    local numCS            = GameConfiguration.GetValue("CITY_STATE_COUNT")
    local newNumCS        = numCS
    local maxPlayer        = 62             -- max is 64 but 1 slot is required for barbarian and 1 slot for free cities
    local cityStateID    = 0             -- Player slots IDs start at 0, Human is 0, so we should start at 1, but start at 0 in case some mod (spectator ?) change that
    local maxCS         = maxPlayer - numPlayers
    local bSelectCS        = MapConfiguration.GetValue("SelectCityStates") ~= "RANDOM"
    local bBanListCS    = MapConfiguration.GetValue("SelectCityStates") == "EXCLUSION"
    local bBanLeaders    = MapConfiguration.GetValue("BanLeaders")
    local bOnlyTSL        = MapConfiguration.GetValue("OnlyLeadersWithTSL")
    local ruleset        = GameConfiguration.GetValue("RULESET")
    local playerDomain    = ruleset and RulesetPlayerDomain[ruleset] or "Players:StandardPlayers"
  
    local ruleset = GameConfiguration.GetValue("RULESET")
    print("Active Ruleset = ", ruleset)
    print("Player Domain = ", playerDomain)
  
    -- Limit number of players for R&F and GS
    print("------------------------------------------------------")
    print("YnAMP checking for number of players limit on Start...")
    print("num. players = ".. tostring(numPlayers) .. ", num. CS = ".. tostring(numCS), ", Selection type = ", MapConfiguration.GetValue("SelectCityStates"), ", Do selection =", bSelectCS)
    if (GameConfiguration.GetValue("RULESET") == "RULESET_EXPANSION_1" or GameConfiguration.GetValue("RULESET") == "RULESET_EXPANSION_2") and numPlayers + numCS > maxPlayer then
        newNumCS = maxCS
        print("new num. CS = ".. tostring(newNumCS))
        GameConfiguration.SetValue("CITY_STATE_COUNT", newNumCS)
    end
  
    if true then --bBanLeaders then -- I prefer the randomization of this function over the Core method (less duplicates when allowed, no duplicate when not), so make it default.
        print("------------------------------------------------------")
        print("Getting Leaders for Random slots...")
      
        local IsUsedCiv        = {}
        local IsUsedLeader     = {}
      
        -- Taken from SetupParameters:Parameter_FilterValues
        -- <<<
        local unique_leaders         = GameConfiguration.GetValue("NO_DUPLICATE_LEADERS");
        local unique_civilizations     = GameConfiguration.GetValue("NO_DUPLICATE_CIVILIZATIONS");

        local leaders_in_use;
        local civilizations_in_use;

        local InsertIntoDuplicateBucket = function(map, key, other_key)
            local bucketA = map[key];
            local bucketB = map[other_key];

            if(bucketA == nil and bucketB == nil) then
                bucketA = {key, other_key};
                map[key] = bucketA;
                map[other_key] = bucketA;

            elseif(bucketA == nil and bucketB ~= nil) then
                table.insert(bucketB, key);
                map[key] = bucketB;

            elseif(bucketA ~= nil and bucketB == nil) then
                table.insert(bucketA, other_key);
                map[other_key] = bucketA;
          
            elseif(bucketA ~= nil and bucketB ~= nil and bucketA ~= bucketB) then
                -- consolidate buckets
                -- if A is a dupe of B and B is a dupe of C, then A is a dupe of C.
                for i,v in ipairs(bucketB) do
                    table.insert(bucketA, v);
                    map[v] = bucketA;
                end

            elseif(bucketA == bucketB) then
                -- buckets are same, no need to do anything since they are already dupes of each other
            end
        end;

        local duplicate_civilizations;
        if(unique_civilizations) then
            duplicate_civilizations = {};
            for i, row in ipairs(CachedQuery("SELECT CivilizationType, OtherCivilizationType from DuplicateCivilizations where Domain = ?", playerDomain)) do
                InsertIntoDuplicateBucket(duplicate_civilizations, row.CivilizationType, row.OtherCivilizationType);
            end
        end

        local duplicate_leaders;
        if(unique_leaders) then
            duplicate_leaders = {};
            for i, row in ipairs(CachedQuery("SELECT LeaderType, OtherLeaderType from DuplicateLeaders where Domain = ?", playerDomain)) do
                InsertIntoDuplicateBucket(duplicate_leaders, row.LeaderType, row.OtherLeaderType);
            end
        end
        -->>>
      
        local function MarkUsedCiv(civilizationType)
            IsUsedCiv[civilizationType] = true
            local dupes = duplicate_civilizations and duplicate_civilizations[civilizationType]
            if(dupes) then
                for i,v in ipairs(dupes) do
                    IsUsedCiv[v] = true
                end
            end
        end
      
        local function MarkUsedLeader(leaderType)
            IsUsedLeader[leaderType] = true
            local dupes = duplicate_leaders and duplicate_leaders[leaderType]
            if(dupes) then
                for i,v in ipairs(dupes) do
                    IsUsedLeader[v] = true
                end
            end
        end
          
        -- Get Random slots and used leaders and Civs
        local randomSlots = {}
        for i, slotID in ipairs(player_ids) do
            local playerConfig = PlayerConfigurations[slotID];
            if playerConfig:GetSlotName() == "LOC_RANDOM_LEADER" then
                table.insert(randomSlots, slotID)
            else
                local civilizationType     = playerConfig:GetCivilizationTypeName()
                local leaderType         = playerConfig:GetLeaderTypeName()
                MarkUsedCiv(civilizationType)
                MarkUsedLeader(leaderType)
            end
        end
        print("Random Leaders Slots = ", #randomSlots)
      
        if #randomSlots > 0 then -- don't waste time if there are no random slots...
          
            local filteredRandomLeaderList = {}
            for leaderType, bValid in pairs(availableLeaderList) do
                bValid = bValid and #CachedQuery("SELECT LeaderType from Players WHERE Domain = ? AND LeaderType = ?", playerDomain, leaderType)>0
                if bValid then
                    table.insert(filteredRandomLeaderList, leaderType)
                end
            end
          
            local shuffledList     = GetShuffledCopyOfTable(filteredRandomLeaderList)
            local listIndex        = 1
      
            -- Helper to get the CivilizationType of a LeaderType
            local function GetPlayerCivilization(leaderType)
                for i, row in ipairs(CachedQuery("SELECT CivilizationType from Players where LeaderType = ? LIMIT 1", leaderType)) do
                    return row.CivilizationType
                end
            end
            --
            local function GetLeaderName(leaderType)
                for i, row in ipairs(CachedQuery("SELECT LeaderName from Players where LeaderType = ? LIMIT 1", leaderType)) do
                    return row.LeaderName
                end
            end
            --           
            local function GetNextLeaderType(bSecondLoop)
                local leaderType         = shuffledList[listIndex]
                local bNoDupeLeaders     = unique_leaders or (not bSecondLoop)         -- avoid duplicate leaders on first loop, even if allowed
                local bNoDupeCivs         = unique_civilizations or (not bSecondLoop) -- avoid duplicate civs on first loop, even if allowed
                while(leaderType) do
                    if not MapConfiguration.GetValue(leaderType) then -- this leaderType is not banned
                        if (not IsUsedLeader[leaderType]) or (not bNoDupeLeaders) then
                            local civilizationType = GetPlayerCivilization(leaderType)
                            if civilizationType then
                                if (not IsUsedCiv[civilizationType]) or (not bNoDupeCivs) then
                                    MarkUsedCiv(civilizationType)
                                    MarkUsedLeader(leaderType)
                                    listIndex     = listIndex + 1
                                    return leaderType
                                else
                                    --print(" - Can't use leader because of duplicate Civilization : ", leaderType, civilizationType)
                                end
                            else
                                --print(" - WARNING: can't find civilizationType for : ", leaderType)
                            end
                        else
                            --print(" - Can't use duplicate leader : ", leaderType)
                        end
                    else
                        --print(" - Can't use banned leader : ", leaderType)
                    end
                    listIndex     = listIndex + 1
                    leaderType     = shuffledList[listIndex]
                end
                if not bSecondLoop then -- in case duplicates are allowed
                    print(" - Can't find next leader, trying second loop")
                    shuffledList = GetShuffledCopyOfTable(shuffledList)
                    listIndex = 1
                    if not unique_leaders then
                        IsUsedLeader = {}
                    end
                    if not unique_civilizations then
                        IsUsedCiv = {}
                    end
                    return GetNextLeaderType(true)
                else
                    print(" - Can't find next leader after second loop")
                end
            end
          
            print("Setting random slots...")
            for i, slotID in ipairs(randomSlots) do
                local playerConfig     = PlayerConfigurations[slotID]
                local leaderType     = GetNextLeaderType()
                if leaderType then
                    print("- Placing ", leaderType, " in slot#", slotID)
                    playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
                    playerConfig:SetLeaderName(GetLeaderName(leaderType))
                    playerConfig:SetLeaderTypeName(leaderType)
                    playerConfig:SetMajorCiv()
                else
                    print("- No LeaderType available, clearing slot#", slotID)
                    playerConfig:SetLeaderTypeName(nil)
                    GameConfiguration.RemovePlayer(slotID)
                end
            end
        end
    end
  
    -- Get available player slots list for CS
    if (bSelectCS or bOnlyTSL) and (not ConfigYnAMP.IsDatabaseChanged) then
        print("------------------------------------------------------")
        print("Generate available slots list for CS...")
        local CityStatesSlotsList    = {}
        while(cityStateID < maxPlayer) do
            local playerConfig = PlayerConfigurations[cityStateID];
          
            -- If we've reached the end of the line, exit.
            if(playerConfig == nil) then
                print("playerConfig is nil at cityStateID#", cityStateID)
                --break;
            end

            -- Check for free slots to add to the CS list.
            if (playerConfig:GetSlotStatus() == SlotStatus.SS_CLOSED) then
                table.insert(CityStatesSlotsList, cityStateID)
            end

            -- Increment the AI, this assumes that either player config will hit nil
            -- or we'll reach a suitable slot.
            cityStateID = cityStateID + 1;
        end
      
        -- Get the City States list
        local query        = cityStatesQuery
        local results    = DB.ConfigurationQuery(query)
      
        if(results and #results > 0) then
      
            local filteredList     = {}
            local duplicate        = {}
            local mapName        = MapConfiguration.GetValue("MapName")
            for i, row in ipairs(results) do
                local leaderType     = row.ConfigurationId
                local bValid        = true
              
                if bBanListCS then -- first check if the selection list is in "exclusion" mode
                    if MapConfiguration.GetValue(leaderType) then -- true if this CS was checked
                        bValid = false
                    end
                end
              
                if bValid and bOnlyTSL then -- filter CS list by TSL
                    local args                = {}
                    args.leaderType            = leaderType
                    args.civilizationType    = LeadersCivilizations[leaderType]
                    args.mapName            = mapName
                    if not HasTSL(args) then--(leaderType, mapName, playerDomain, civilizationType)
                        bValid = false
                    end
                end
              
                if bValid and not duplicate[leaderType] then
                    duplicate[leaderType] = true
                    table.insert(filteredList, {ConfigurationId = leaderType, Name = row.Name})
                end
            end
      
            local bCapped            = MapConfiguration.GetValue("SelectCityStates") == "SELECTION" or MapConfiguration.GetValue("SelectCityStates") == "EXCLUSION"
            local bOnlySelection    = MapConfiguration.GetValue("SelectCityStates") == "ONLY_SELECTION"
            local cityStateSlots     = (bCapped and numCS) or maxCS
            local shuffledList         = GetShuffledCopyOfTable(filteredList)
            local randomList        = {}
            local slotListID        = 1
            print("------------------------------------------------------")
            print("YnAMP setting specific CS slots...")
            print("Trying to reserve slots for selected CS, available slots = "..tostring(#CityStatesSlotsList)..", maxCS = "..tostring(cityStateSlots).. ", bCapped = ", bCapped, " bOnlySelection = ", bOnlySelection)
            for i, row in ipairs(shuffledList) do
                --print(i)
                --for k, v in pairs(row) do print(k, v) end
                local leaderType = row.ConfigurationId
                local leaderName = row.Name
                if (not bBanListCS) and MapConfiguration.GetValue(leaderType) then -- true if this CS was checked and we're not in exclusion mode
                    if cityStateSlots > 0 then
                        local slotID = CityStatesSlotsList[slotListID]
                        if slotID then
                            print(" - Reserving player slot#"..tostring(slotID).." for ".. Locale.Lookup(leaderName) )
                            local playerConfig = PlayerConfigurations[slotID]
                            playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
                            playerConfig:SetLeaderName(leaderName)
                            playerConfig:SetLeaderTypeName(leaderType)
                            cityStateSlots    = cityStateSlots - 1
                            slotListID        = slotListID + 1
                        else
                            print(" - ERROR, No slots found for ".. Locale.Lookup(leaderName) .." at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) .." but calculated slots left = ".. tostring(cityStateSlots) )
                        end
                    else
                        print(" - Maximum #CS reached, can't set a slot for ".. Locale.Lookup(leaderName) .." at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )                 
                    end
                else -- add unselected CS to the random pool
                    table.insert(randomList, row)
                end
            end
            local placedCS    = slotListID - 1
            local newNumCS     = bOnlySelection and 0 or math.max(0, numCS - placedCS)
            print("Unused slots left = ", cityStateSlots )
            print("Setting Random CS to number of slots = ", newNumCS )
            --GameConfiguration.SetValue("CITY_STATE_COUNT", newNumCS)
            ---[[
            if newNumCS > 0 then
                local nextIndex    = 1
                for slotListID = slotListID, slotListID + newNumCS - 1 do --cityStateSlots do
                    local slotID         = CityStatesSlotsList[slotListID]
                    local playerConfig     = PlayerConfigurations[slotID]
                    if playerConfig then
                        -- get next entry in the random pool
                        local row    = randomList[nextIndex]
                        nextIndex    = nextIndex + 1
                        if row then
                            local leaderType = row.ConfigurationId
                            local leaderName = row.Name
                            print(" - Reserving player slot#"..tostring(slotID).." for ".. Locale.Lookup(leaderName) )
                            playerConfig:SetSlotStatus(SlotStatus.SS_COMPUTER)
                            playerConfig:SetLeaderName(leaderName)
                            playerConfig:SetLeaderTypeName(leaderType)
                        else
                            print(" - No more CS in Random pool, can't set a CS at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )
                        end
                    else
                        print(" - No more Slot available, can't set a CS at slotListID#"..tostring(slotListID).."/".. tostring(#CityStatesSlotsList) )
                    end
                end
            end
            --]]
        end
    elseif ConfigYnAMP.IsDatabaseChanged then
        print("------------------------------------------------------")
        print("Database Changed, skipping CS selection...")
    end
[...]

edit 2: and the shuffled function, adapted from a Firaxis version
Code:
function GetShuffledCopyOfTable(incoming_table)
    -- Designed to operate on tables with no gaps. Does not affect original table.
    local len = table.maxn(incoming_table);
    local copy = {};
    local shuffledVersion = {};
    local seed = MapConfiguration.GetValue("RANDOM_SEED") -- passing the same table will give the same result.
    print("Using Map Random seed for GetShuffledCopyOfTable :", seed )
    math.randomseed(seed)
    print("random first call = ", math.random(1,10))
    -- Make copy of table.
    for loop = 1, len do
        copy[loop] = incoming_table[loop];
    end
    -- One at a time, choose a random index from Copy to insert in to final table, then remove it from the copy.
    local left_to_do = table.maxn(copy);
    for loop = 1, len do
        local random_index = math.random(1,left_to_do)--1 + TerrainBuilder.GetRandomNumber(left_to_do, "Shuffling table entry - Lua");
        table.insert(shuffledVersion, copy[random_index]);
        table.remove(copy, random_index);
        left_to_do = left_to_do - 1;
    end
    return shuffledVersion
end
 
Last edited:
Can you tell me where in the XML files there is an info that Roman Legion can clear features?
I see it has CLASS_REGION, I see that it can build Roman Fort, but I can't find clear features ability anywhere.
Thanks for help
 
I believe clearing features is just something that comes along with having build charges.
 
The same is as I see with the Repair action? I just tested it with Maori Toa and apparently Toa can repair improvements he can't built. I just repaired a pillaged Camp improvement with Toa.

What about harvesting resource and planting woods? Cant find any place in XML/LUA files that adds this operations to Builder unit.
 
Last edited:
Yup, those too. What a unit can actually build is defined by an XML, but everything else that a builder can do seems to be baked into build charges. I wish this wasn't the case, it threw a wrench into my plans for a road builder unit.
 
Hi, got a very quick question that am hoping someone can help with.

I was trying to make a small mod just to rename the Giant Death Robot for aesthetic purposes but for some reason keep ending up with Spanish text appearing in game now.

I've created a file with the text for the unit name, unit description and tech descriptions for the future techs which give bonuses to the GDR and it all seems to load fine.

Except for some reason other text items that I havent changed are now appearing as spanish. For example the yield bonus to robotics (even though I havent changed any of the text for the robotics tech itself). Similarly the desription in cybernetics now shows the revised description with the new GDR name, but for some reason the tech is showing as "Cybernetica" (even though I didn't add a row to change the name, just the description) along with a few other (unchanged) future techs and some of the "history" entries for them showing in Spanish now.

Anyone got any ideas?
 
Last edited:
would need to see the code you are using in your mod or the alterations you are making to base game text files (if that's the way you are doing it) in order to have any real idea what has gone awry.
 
would need to see the code you are using in your mod or the alterations you are making to base game text files (if that's the way you are doing it) in order to have any real idea what has gone awry.

I used the mod buddy from the Civ VI tools and edited the "new unit" example as a base, just keeping the unit_text file and adding in the rows relating to the GDR. I figured that was better than just editing the game files especially if I started wanting to add more units or change other things.

Its names and descriptions that I havent changed which are showing as spanish. Eg the GDR description, LOC_UNIT_GIANT_DEATH_ROBOT_DESCRIPTION started showing as spanish in the tech tree view in game, so I added that as an exact copy and it now shows fine as below, but now the yield bonus in Robotics shows in spanish.


Code:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Default" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Default</Configuration>
    <Name>Rename GDR</Name>
    <Guid>e2a8a546-3481-444d-a33b-db941764fa73</Guid>
    <ProjectGuid>04774aa4-6605-4604-8ba6-941543e62f02</ProjectGuid>
    <ModVersion>2</ModVersion>
    <Teaser>Renames GDR</Teaser>
    <Description>Renames GDR unit to Titan.</Description>
    <AffectsSavedGames>true</AffectsSavedGames>
    <SupportsSinglePlayer>true</SupportsSinglePlayer>
    <SupportsMultiplayer>true</SupportsMultiplayer>
    <SupportsHotSeat>true</SupportsHotSeat>
    <CompatibleVersions>1.2,2.0</CompatibleVersions>
    <InGameActionData><![CDATA[
      <InGameActions>
        <UpdateText id="Text">
          <File>Rename_GDR_Text.xml</File>
        </UpdateText>
      </InGameActions>
      ]]></InGameActionData>
    <AssemblyName>Rename GDR</AssemblyName>
    <RootNamespace>Rename GDR</RootNamespace>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Default' ">
    <OutputPath>.</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Content Include="Rename_GDR_Text.xml" />
  </ItemGroup>
  <Import Project="$(MSBuildLocalExtensionPath)Civ6.targets" />
</Project>


<?xml version="1.0" encoding="utf-8"?>
<GameData>
  <EnglishText>
    <!-- Unit Name -->
    <Row Tag="LOC_UNIT_GIANT_DEATH_ROBOT_NAME">
      <Text>Titan</Text>
    </Row>
    <Row Tag="LOC_UNIT_GIANT_DEATH_ROBOT_DESCRIPTION">
      <Text>Information Era Super-Unit. Able to move and fight in water. Resistant to Weapons of Mass Destruction. Combat abilities can be upgraded by researching future technologies.</Text>
    </Row>
    <!-- Civilopedia -->
    <Row Tag="LOC_PEDIA_CONCEPTS_PAGE_DEDICATIONS_CHAPTER_CONTENT_PARA_13">
      <Text>Automaton Warfare: Gain +1 Era Score each time you kill a non-Barbarian unit with a Titan unit. If chosen at the start of a Golden Age, gain a Titan in your capital. Receive 3 [ICON_Resource_Uranium] Uranium per turn. [ICON_Resource_Uranium] Uranium mines accumulate +1 more resource per turn. Information and Future Era.</Text>
    </Row>
    <Row Tag="LOC_PEDIA_UNITS_PAGE_UNIT_GIANT_DEATH_ROBOT_CHAPTER_HISTORY_PARA_1">
      <Text>Almost no one calls them Gunnery Deployment Rigs, because pop culture anticipated the rise of the bipedal combat platform for more than fifty years prior to the first operational deployment of a GDR, and has given them dozens of evocative names: Mechs, walkers, Giant Death Robots, and so forth. There is something psychologically affecting about seeing one stride across the landscape—reassuring for friendly forces, and terrifying for enemies. There is a certain purity to the GDR, a recapitulation of the human form, as well as an improvement on it.</Text>
    </Row>
    <Row Tag="LOC_PEDIA_UNITS_PAGE_UNIT_GIANT_DEATH_ROBOT_CHAPTER_HISTORY_PARA_2">
      <Text>The Titan is not a stealthy weapon, but it is an effective one. The use of a roughly-human anatomy allows pilots a more intuitive grasp of the weapon and defensive systems, and allows motion feedback systems to tap into human locomotion to assist. Indeed, some people regard the locomotion controls of the GDR to be the most impressive advancement in the entire system.</Text>
    </Row>
    <!-- Technologies -->
    <Row Tag="LOC_TECH_ADVANCED_AI_DESCRIPTION">
      <Text>Unlocks Titan upgrade: Drone Air Defense[NEWLINE]+100 [ICON_AntiAir_Large] Anti-Air Strength.</Text>
    </Row>
    <Row Tag="LOC_TECH_ADVANCED_POWER_CELLS_DESCRIPTION" >
      <Text>CO2 emissions from units reduced by 50%. Unlocks Titan upgrade: Particle Beam Siege Cannon[NEWLINE]Ranged attacks against Cities and Encampments are 100% effective and gain +30 [ICON_Ranged] Ranged Strength.</Text>
    </Row>
    <Row Tag="LOC_TECH_CYBERNETICS_DESCRIPTION" >
      <Text>Unlocks Titan upgrade: Enhanced Mobility[NEWLINE]+3 [ICON_Movement] Movement. Can perform a Jump action to cross over mountain terrain.</Text>
    </Row>
    <Row Tag="LOC_TECH_SMART_MATERIALS_DESCRIPTION" >
      <Text>Unlocks Titan upgrade: Reinforced Armor Plating[NEWLINE]+10 [ICON_Strength] Combat Strength when defending against land and naval units.</Text>
    </Row>
  </EnglishText>
</GameData>
 
Back
Top Bottom