Quick Modding Questions Thread

I've not looked closely at that part of the code yet, but I think the code to assign a civ to a random slot is called after launching the game in the gameplay DLL.

I plan to have a "leader ban" option in YnAMP at some point, I'll try to do a workaround by doing the random selection before launching the game and manually assign my mod selection to the random slots then launch the game.
 
Does "< 5" include 5, or would it be numbers up to 4?

e.g.
Code:
function GeneratePlotTypes()
    local mapType = TerrainBuilder.GetRandomNumber(10, "Random World Age - Lua");
    if(mapType < 5) then
        -- Fractal Map
        return FractalGenerator();
    elseif(mapType < 8) then
        -- Island Map
        return IslandPlates();
    else
        -- Continent Map
        return Continents ();
    end
end
Is that:

40% chance of Fractal
30% chance of lsland Plates
30% chance of Continents

Or:

50% chance of Fractal
30% chance of lsland Plates
20% chance of Continents
 
it's "<= 5" that would include 5.
 
Hey, I didn't see anyone else reply, but LeeS recently gave me some tips. Basically, You shouldn't need to use DynamicModifiers *unless* there is an effect that does not already have an associated Modifier. Example:

MODIFIER_PLAYER_UNIT_ADJUST_GREAT_PEOPLE_POINTS_PER_KILL (<-- this is a ModifierType, not a ModifierId) already points at EFFECT_ADJUST_GREAT_PEOPLE_POINTS_PER_KILL (this association can be found in the Modifiers.xml). However, if the modifier didn't exist, but the effect was valid, you would need to create your own ModifierType, and insert into the DynamicModifier table to create it. This is also where what the ModifierType effects is set (such as COLLECTION_OWNER effects all valid targets belonging to the 'owner' of the ability/trait)

So, your ModifierId is what you create to reference your unique usage of a modifier, and is associated to a trait or ability

That ModifierId then need to be connected to a valid ModifierType, which is done here:

Code:
INSERT INTO    Modifiers
        (ModifierId,                                        ModifierType,                                                OwnerRequirementSetId,                SubjectRequirementSetId,            RunOnce,    Permanent    )
VALUES
        ('MODIFIER_ZAG_SUMETAL_UA_GPM_POINTS',                'MODIFIER_PLAYER_UNITS_GRANT_ABILITY',                        NULL,                                NULL,                                0,            1            ),
        ('MODIFIER_ZAG_SUMETAL_UA_GPM_POINTS_ABILITY',        'MODIFIER_PLAYER_UNIT_ADJUST_GREAT_PEOPLE_POINTS_PER_KILL',    NULL,                                NULL,                                0,            1            );

and now that you've called up the modifier type, you need to feed it arguments, with the arguments being based on the effect being called upon through the ModifierType.

Code:
INSERT INTO    ModifierArguments
        (ModifierId,                                        Name,                        Value                            )
VALUES
        ('MODIFIER_ZAG_SUMETAL_UA_GPM_POINTS',                'AbilityType',                'ABILITY_ZAG_SUMETAL_UA_GPM_POINTS'    ),
        ('MODIFIER_ZAG_SUMETAL_UA_GPM_POINTS_ABILITY',        'GreatPersonClassType',        'GREAT_PERSON_CLASS_MUSICIAN'        ),
        ('MODIFIER_ZAG_SUMETAL_UA_GPM_POINTS_ABILITY',        'Amount',                    1        );

This spreadsheet is great at finding effects, but then you need to try and find the right modifier to call on. Not to difficult usually.

Thanks, I still don't really understand much about these, but I think I'm just gonna have to probably give it my best shot or something and hope it works out. If not, I'll just drop this project.
So, now I need to find the requirement. I think "REQUIREMENT_OPPONENT_UNIT_TYPE" is the one I want.
How do I explain this? I need to unit to do damage against all melee, ranged and anti-cavalry units. So I'm guessing I need three modifiers here, each for the 3 classes. The only problem is that I'm not sure if "UNIT_TYPE" refers to melee, ranged, anti-cavalry, etc. or something else entirely.

Just for reference, this is where I am at in the template.
INSERT INTO Modifiers
(ModifierId, ModifierType, OwnerRequirementSetId, SubjectRequirementSetId, Permanent, RunOnce )
VALUES ('MODIFIER_PENC_MINAMOTO_UU_ADJUST_STRENGTH_AGAINST_UNITS', 'MODTYPE_PENC_MINAMOTO_UU_ADJUST_STRENGTH_AGAINST_UNITS', NULL, 'REQSET_PENC_MINAMOTO_UU_UNIT_', 0, 0 ); -- This one has a ReqSetID which means that it identifies for this modifier to run - it needs a requirement.​
 
Last edited:
Thanks, I still don't really understand much about these, but I think I'm just gonna have to probably give it my best shot or something and hope it works out. If not, I'll just drop this project.
So, now I need to find the requirement. I think "REQUIREMENT_OPPONENT_UNIT_TYPE" is the one I want.
How do I explain this? I need to unit to do damage against all melee, ranged and anti-cavalry units. So I'm guessing I need three modifiers here, each for the 3 classes. The only problem is that I'm not sure if "UNIT_TYPE" refers to melee, ranged, anti-cavalry, etc. or something else entirely.

Just for reference, this is where I am at in the template.
INSERT INTO Modifiers
(ModifierId, ModifierType, OwnerRequirementSetId, SubjectRequirementSetId, Permanent, RunOnce )
VALUES ('MODIFIER_PENC_MINAMOTO_UU_ADJUST_STRENGTH_AGAINST_UNITS', 'MODTYPE_PENC_MINAMOTO_UU_ADJUST_STRENGTH_AGAINST_UNITS', NULL, 'REQSET_PENC_MINAMOTO_UU_UNIT_', 0, 0 ); -- This one has a ReqSetID which means that it identifies for this modifier to run - it needs a requirement.​
The sort of REQUIREMENT you use depends on exactly on what you want to accomplish. There are three main methods for requiring a Unit "Match": UnitType, Unit "CLASS" Tag, and Unit Promotion Class. Here are examples of all three methods so far as the arguments needed, taken from the game's database:

Promotion Class (ie, PROMOTION_CLASS_MELEE)
Requirements:
RequirementId | RequirementType
REQUIREMENT_UNIT_IS_MELEE | REQUIREMENT_UNIT_PROMOTION_CLASS_MATCHES
RequirementArguments:
RequirementId | Name | Value
REQUIREMENT_UNIT_IS_MELEE | UnitPromotionClass | PROMOTION_CLASS_MELEE

Unit Class Tag (ie, CLASS_HETAIROI)
Requirements:
RequirementId | RequirementType
REQUIREMENT_UNIT_IS_HETAIROI | REQUIREMENT_UNIT_TAG_MATCHES
RequirementArguments:
RequirementId | Name | Value
REQUIREMENT_UNIT_IS_HETAIROI | Tag | CLASS_HETAIROI

UnitType (ie, UNIT_SUBMARINE)
Requirements:
RequirementId | RequirementType
REQUIREMENT_UNIT_IS_SUBMARINE | REQUIREMENT_UNIT_TYPE_MATCHES
RequirementArguments:
RequirementId | Name | Value
REQUIREMENT_UNIT_IS_SUBMARINE | UnitType | UNIT_SUBMARINE
 
How do i generate .modinfo file in modbuddy?
I've created empty project, removed xml file, added my sql scripts, set up all project properties (loading my sql scripts). Build a solution and still got just .civ6proj file, I need .modinfo file to be able upload mod to steam workshop.
Thanks.

Edit: For context I'm not windows user. So I created my mod based on existing, just by editing their .modinfo. Now I have mode ready for release, so I want upload it using Steam Uploader on my virtual machine with windows.
 
Last edited:
When you build the solution, IIRC, it places the mod (and the .modinfo) in the Mods folder (\Documents\my games\Sid Meier's Civilization VI\Mods)
 
How do i generate .modinfo file in modbuddy?
I've created empty project, removed xml file, added my sql scripts, set up all project properties (loading my sql scripts). Build a solution and still got just .civ6proj file, I need .modinfo file to be able upload mod to steam workshop.
Thanks.

Edit: For context I'm not windows user. So I created my mod based on existing, just by editing their .modinfo. Now I have mode ready for release, so I want upload it using Steam Uploader on my virtual machine with windows.
When you build the solution, IIRC, it places the mod (and the .modinfo) in the Mods folder (\Documents\my games\Sid Meier's Civilization VI\Mods)
Correct. The modinfo file is only generated into the playable version of the mod whenever "Build" or "Build Solution" is conducted. It is never added anywhere in the Modbuddy Project. The two "Build" functions in Modbuddy take the information in the modbuddy project and package it into a usable mod -- part of this process is generating a new folder in the Mods folder @Gedemon mentioned, and also creating all the needed files within this folder that the game needs to execute the mod. The modinfo file is one of these necessary files, and is generated as part of the Build process. The modinfo file is the "control" file for the mod, specifying to the game what the game should do with the various files contained within the newly-created folder.

But this is the behavior on Windows machines, so I have no idea if Mac or Linux users will get different behavior even if they use a Windows emulator program.
 
Last edited:
Hey everyone,

Got a few questions, sorry if this is the wrong place. I think there are some mods on the steam workshop that do some or all of these things but they seem out of date (I want something that works for all expansions), and I'm curious to try doing some modding myself (I'm relatively familiar with basic programming).

1. How do I change the Eureka/Inspiration boost? I think I want to reduce it more to the 10-15% range.
2. How do I change the production and research cost multiplier for technology/civics for the different game speeds? I want to have marathon speed technology/civic research with epic-ish level production. I think there are some mods that do this (like Historic Speed mod: https://steamcommunity.com/sharedfiles/filedetails/?id=890528355 ), but I'm just curious how hard it is to modify these values.
 
Clean modding is more complicated but as for the location of these values

Base / Assets / Gameplay / Data / GameSpeeds.xml -> There is some CostMultiplier element there
... / Technologies.xml or Civics.xml -> They have Boosts element containing boost definitions, there is the number which presumably expresses the percentage. Note this is likely overriden by RF, GS or both, given that the original 50% has changed since
 
The cost multiplier values in GameSpeeds applies to everything. There is no individual modifier for Research.

If you can understand SQL, this code makes all Boosts for Technologies and Civics give a 30% Boost.
Code:
UPDATE Boosts SET Boost= 30 WHERE TechnologyType IS NOT NULL;
UPDATE Boosts SET Boost= 30 WHERE CivicType IS NOT NULL;
The issue is that the InGame UpdateDatabase Action needs a LoadOrder setting of around 300 to ensure that the SQL file is implemented after Rise and Fall and Gathering Storm make their alterations to the game's database.

A similar approach also can work for costs of technologies, such as
Code:
UPDATE Technologies SET Cost = Cost * 1.35;
The real problem comes in with the special late-game "Future" techs added by Gathering Storm. They don't play as nicely so far as where they end up getting placed in the Tech Tree based on the "cost" value.
 
@Jeppetto @LeeS thanks for the information. Is there a good tutorial anywhere about how to make a mod that changes some of these values? I'll just focus on reducing the boosts for now.
 
If only someone were working on a Modding Guide for Civ 6 that while still a WIP already has an example of how to make a simple mod using Modbuddy.

If only there were a link to such a thing in a signature or something. :ninja: :mischief: :ninja:
 
Thank you kindly, I'll see myself out...

In general, are there any good mods that fix the pacing issues with CIV 6, that still work properly after the fall 2019 patch? It's fine if they're more ambitious conversion mods too. I don't know, I want to like Civ 6 but it just seems to have so many issues, I find myself going back to Civ V or even Civ 3 with Rise and Rule running, which always had a special place in my heart for its dense tech tree.
 
I don't know the list, but there are things that, even when changed while the game is not running, won't affect the savefile, so I have serious doubts there is anything updated while the game is running.
 
Where in the LUA scripts is the function that assigns a leader/civ to the human player (in single player) when the player selects "random" as their option for leader?

Asking because I want to modify that function to pass a query to the leaders table that passes over certain leaders that I never want to play (if I select random leaders)
I want to make sure that for the AI players with "random" selected for their leader that they can still get every leader in the leaders table, but only if the human selects random do I want to make that change ...

I'm not entirely comfortable reading/writing LUA, but I'm pretty sure what I'm looking for will be in one of those setup LUA files so that's why I've targeted that. If anyone with better understanding of how the game selects leaders when "random" is the option knows where that's done, then yeah, I'll defer to your knowledge.

Spoiler :
I've especially been looking at PlayerSetupLogic.lua at line 316 (text colors added for reference):

function GetPlayerInfo(domain, leader_type)
if(leader_type ~= "RANDOM") then
local info_query = "SELECT CivilizationIcon, LeaderIcon, LeaderName, CivilizationName, LeaderAbilityName, LeaderAbilityDescription, LeaderAbilityIcon, CivilizationAbilityName, CivilizationAbilityDescription, CivilizationAbilityIcon, Portrait, PortraitBackground, PlayerColor from Players where Domain = ? and LeaderType = ? LIMIT 1";
local item_query = "SELECT Name, Description, Icon from PlayerItems where Domain = ? and LeaderType = ? ORDER BY SortIndex";
local info_results = CachedQuery(info_query, domain, leader_type);
local item_results = CachedQuery(item_query, domain, leader_type);


That info_query seems to me to be what's grabbing the civ/leader ... but I don't know the usage of "?" in the queries ... and further down I don't know how "CachedQuery" works ...
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")
 
Can I modify game data while game is running? How should I do that?
You can swap back and forth between the game and for example an SQL fie and make edits to it, but none of these edits will be implemented within the game's database until you save and then reload that saved game. Game Data that is in the database is locked for the duration of that session of a game. You have to exit the game you are playing and at least return to the main menu and then reload before any alterations can be made to the game's database.

Certain types of game data should never be altered once a game is started, however. You should not add for example a new unit to the game once you have started a game because this can cause desynch issues between the ID #'s assigned to the units in the database when the game was saved, and the new set of ID #'s and etcetera when the saved game is reloaded with an altered database. This sort of thing is also the root cause of why updates to mods can often make a saved game unrecoverable -- the process of updating the mod can cause a user's list of mods to load in a different order than when the game was first created, and now the assignments of row #s and Id #'s is different simply because the total set of mods currently being run load in a different order. The basic rule here is that you should never add or remove anything that must be registered within gametable <Types>, and you should never alter the order mods load when they are adding new elements or adjusting elements of the game that must be registered in table <Types>.

Unfortunately Steam don't pay any attention whatever to this rule. Firaxis does not control how mod updates are handled for a user -- Steam does.

Lua User Interface files and "context" XML files can be edited in realtime and the changes will be reflected in the correct UI panel or poop up. But this is not gameplay data, this is display code for the interface between the human user and the game.
 
Top Bottom