Quick Modding Questions Thread

How can I get the civilization Type of a player with lua (to compare it with a civilizationType in a Database Table)? and The TerrainType/FeatureType that a Unit stands On or moved to?
 
Code:
if (PlayerConfigurations[iPlayer]:GetCivilizationTypeName() == "CIVILIZATION_ROME") then
For Terrain and Features
Code:
if (pPlot:GetTerrainType() == iTerrainIndex) then

		local iResourceType = pPlot:GetResourceType()
		local iImprovementType = pPlot:GetImprovementType()
		local iFeatureType = pPlot:GetFeatureType()
		local iRouteType = pPlot:GetRouteType()
These are Index numbers from their respective database tables. To translate into something like TERRAIN_GRASS:
Code:
local tTerrainData = GameInfo.Terrains[pPlot:GetTerrainType()]
local sTerrainType = ((tTerrainData  ~= nil) and tTerrainData.TerrainType or "NONE_VALID")
While it should not be possible to get an invalid TerrainType in the example, I prefer to belts and suspender my code because there are quite a lot of cases where what one "gets" is garbage in terms of pulling any associated data from a Database table, and then what you will get is an lua runtime error for attempting to index a nil value.
 
Code:
if (PlayerConfigurations[iPlayer]:GetCivilizationTypeName() == "CIVILIZATION_ROME") then
For Terrain and Features
Code:
if (pPlot:GetTerrainType() == iTerrainIndex) then

local iResourceType = pPlot:GetResourceType()
local iImprovementType = pPlot:GetImprovementType()
local iFeatureType = pPlot:GetFeatureType()
local iRouteType = pPlot:GetRouteType()
These are Index numbers from their respective database tables. To translate into something like TERRAIN_GRASS:
Code:
local tTerrainData = GameInfo.Terrains[pPlot:GetTerrainType()]
local sTerrainType = ((tTerrainData ~= nil) and tTerrainData.TerrainType or "NONE_VALID")
While it should not be possible to get an invalid TerrainType in the example, I prefer to belts and suspender my code because there are quite a lot of cases where what one "gets" is garbage in terms of pulling any associated data from a Database table, and then what you will get is an lua runtime error for attempting to index a nil value.

Thanks for the Infos!

Is there some example to get the current plot of a Unit (plot he stands on or moved to)?
 
Is there a way to apply a list of modifier on all tiles following a requirement on the map at the beginning of the game ?

I thougt about asking for help to do something a bit in the way of how disasters act on the map , because they basically modify yields outside of city limits for the entire game for everyone ( applying modifers )

I would love an example and help to build something like that. could open a lot of interesting modding possibilities :D ( lua or whatever way you guys are aware of )

Thanks :)
 
Thanks for the Infos!

Is there some example to get the current plot of a Unit (plot he stands on or moved to)?
Code:
local pPlot = Map.GetPlot(   pUnit:GetX(), pUnit:GetY()  )
Civ6 is a little wonky in that it often lacks direct methods like a Unit:GetPlot() as Civ5 had.
 
In modifier arguments I see some modifiers using multiple values in the value column separate by commas, however when trying to make a modifer that affects every building, but this code will not work. Is there anyway I can do this without making 50 different modifiers?
Code:
INSERT INTO DynamicModifiers
            (ModifierType,  CollectionType, EffectType)
VALUES      ('OAT_MODIFIER_ALL_CITIES_ADJUST_BUILDING_PURCHASE_COST',  'COLLECTION_ALL_CITIES',  'EFFECT_ADJUST_BUILDING_PURCHASE_COST' );
INSERT INTO Modifiers
            (ModifierId,                                        ModifierType,                              RunOnce, Permanent,  SubjectRequirementSetId)
VALUES      ('OAT_BUILDINGS_COST_ADJUSTMENT',    'OAT_MODIFIER_ALL_CITIES_ADJUST_BUILDING_PURCHASE_COST',     0,       0, NULL);
INSERT INTO ModifierArguments
            (ModifierId,                        Name,           Type,                   Value)
VALUES      ('OAT_BUILDINGS_COST_ADJUSTMENT',    'BuildingType',    'ARGTYPE_IDENTITY',   'BUILDING_MONUMENT,BUILDING_BARRACKS,BUILDING_GRANARY,BUILDING_LIBRARY,BUILDING_SHRINE, AND 50 OTHER BUILDINGS'),
            ('OAT_BUILDINGS_COST_ADJUSTMENT',    'Amount',       'ARGTYPE_IDENTITY',   '50');

However, it works if I put one building as the value.
 
In order to get it to work you would have to fill in the "Amount" values for each building as well.
Code:
('OAT_BUILDINGS_COST_ADJUSTMENT',    'Amount',       'ARGTYPE_IDENTITY',   '50,50,50,50,50 and so on');
That is, assuming the game will allow such a long string to be entered into the game's database like you have for the 'BuildingType' row. I'm not sure what the text string length limit is in the database for a single field.
 
Can someone give me an overview of "LuaEvents"?

I understand how lua "Events" and "GameEvents" work, which are all listed here. And I understand how to pass operations back and forth between UI and Gameplay scripts. But I haven't found a concise explanation for what LuaEvents are and when they should be used. Nor a comprehensive list of LuaEvents comparable to Events/GameEvents.

For example, the base file for Options.lua at line 2056 it has:

Code:
Events.OptionChangeRequiresResolutionAck.Add(OnOptionChangeRequiresResolutionAck);

LuaEvents.PBCNotifyRemind_ShowOptions.Add(OnPBCNotifyRemind_ShowOptions);

A use of Events followed by LuaEvents... what's the difference?

Kind regards,
DB

"Events" are called from gamecore, ie from the game's exe (or dll) at specific time in the code.

There is no list for "LuaEvents" as they are created and called in Lua, ie you add functions to your LuaEvents using the syntax
Code:
LuaEvents.MyEvent.Add(MyFunction)

then when you want to call those functions you use
Code:
LuaEvents.MyEvent(MyParameters)

You don't define it before using it, it's handled by the LuaEvents table.

"GameEvents" are a bit of both, some are called from gamecore, but you can also add your own in a similar way to LuaEvents.
 
In order to get it to work you would have to fill in the "Amount" values for each building as well.
Code:
('OAT_BUILDINGS_COST_ADJUSTMENT',    'Amount',       'ARGTYPE_IDENTITY',   '50,50,50,50,50 and so on');
That is, assuming the game will allow such a long string to be entered into the game's database like you have for the 'BuildingType' row. I'm not sure what the text string length limit is in the database for a single field.
Tried it with only a few like this
Code:
INSERT INTO ModifierArguments
            (ModifierId,                        Name,           Type,                    Value)
VALUES      ('OAT_BUILDINGS_COST_ADJUSTMENT',    'BuildingType',    'ARGTYPE_IDENTITY',   'BUILDING_MONUMENT,BUILDING_ARENA,BUILDING_LIGHTHOUSE'),
            ('OAT_BUILDINGS_COST_ADJUSTMENT',    'Amount',       'ARGTYPE_IDENTITY',   '50,50,50');
Didn't work. but this does work
Code:
INSERT INTO ModifierArguments
            (ModifierId,                        Name,           Type,                    Value)
VALUES      ('OAT_BUILDINGS_COST_ADJUSTMENT',    'BuildingType',    'ARGTYPE_IDENTITY',   'BUILDING_MONUMENT'),
            ('OAT_BUILDINGS_COST_ADJUSTMENT',    'Amount',       'ARGTYPE_IDENTITY',   '50');

So if this isn't going to work is there anyway I can lower the cost of purchasing buildings from 4x the production cost to 2x, without making 50+ modifiers like the one above?
 
Try using xml. But I have only seen few Columns that could hold many entries. Or try those columns first, just to be sure that it's possible. And have a look at the Game's files that make use of them.
 
ModifierArguments and RequirementArguments both allow multiple entries as text strings in both XML and SQL for Column "Value". Pulled directly from the pertinent table (running the game under Vanilla in this example) in the DebugGameplay.sqlite file:
Code:
"ModifierArguments"
ModifierId	Name	Type	Value
MINOR_CIV_PRODUCTION_WALLS	BuildingType	ARGTYPE_IDENTITY	BUILDING_WALLS,BUILDING_CASTLE,BUILDING_STAR_FORT
MINOR_CIV_PRODUCTION_WALLS	Amount	ARGTYPE_IDENTITY	200
TRAIT_LEADER_NEARBY_CITIES_GAIN_YIELDS	YieldType	ARGTYPE_IDENTITY	YIELD_PRODUCTION, YIELD_FOOD, YIELD_SCIENCE, YIELD_CULTURE, YIELD_GOLD, YIELD_FAITH
TRAIT_LEADER_NEARBY_CITIES_GAIN_YIELDS	Amount	ARGTYPE_IDENTITY	10, 10, 10, 10, 10, 10
TRAIT_LEADER_NEARBY_CITIES_LOSE_YIELDS	YieldType	ARGTYPE_IDENTITY	YIELD_PRODUCTION, YIELD_FOOD, YIELD_SCIENCE, YIELD_CULTURE, YIELD_GOLD, YIELD_FAITH
TRAIT_LEADER_NEARBY_CITIES_LOSE_YIELDS	Amount	ARGTYPE_IDENTITY	-15, -15, -15, -15, -15, -15
And one I added to the game as an experiment in the GameModifiers effects on plot yields
Code:
"ModifierArguments"
RIVER_ADDYIELDS_MODIFIER	Amount	ARGTYPE_IDENTITY	2,1
RIVER_ADDYIELDS_MODIFIER	YieldType	ARGTYPE_IDENTITY	YIELD_FOOD,YIELD_GOLD
I think the issue may be with the Collection or the Effect being used.

"Modifiers"
Code:
ModifierId	ModifierType
MINOR_CIV_PRODUCTION_WALLS	MODIFIER_PLAYER_CITIES_ADJUST_BUILDING_PRODUCTION
"ModifierArguments"
Code:
ModifierId	Name	Type	Value
MINOR_CIV_PRODUCTION_WALLS	Amount	ARGTYPE_IDENTITY	200
MINOR_CIV_PRODUCTION_WALLS	BuildingType	ARGTYPE_IDENTITY	BUILDING_WALLS,BUILDING_CASTLE,BUILDING_STAR_FORT
Note that in this case I was incorrect and only one "Amount" value is needed.

And the EffectType being used as defined in table "DynamicModifiers"
Code:
ModifierType	CollectionType	EffectType
MODIFIER_PLAYER_CITIES_ADJUST_BUILDING_PRODUCTION	COLLECTION_PLAYER_CITIES	EFFECT_ADJUST_BUILDING_PRODUCTION
Which is an entirely different effect and collection from what @Oathkeeper Oblivion is attempting

Unfortunately for the desired EffectType (EFFECT_ADJUST_BUILDING_PURCHASE_COST) I am not finding any cases where more than one BuildingType is specified in the ModifierArguments "Value" column. So this may be a case where the game's controlling DLL is not coded to accept more than one Value per row in table ModifierArguments for that EffectType.

Using XML or SQL doesn't matter so long as in SQL the entire set of "Values" is entered as one text-string
Code:
INSERT OR REPLACE INTO GameModifiers (ModifierId)
	VALUES ('RIVER_ADDYIELDS');

INSERT OR REPLACE INTO Modifiers (ModifierId, ModifierType)
	VALUES	('RIVER_ADDYIELDS', 'MODIFIER_ALL_CITIES_ATTACH_MODIFIER');

INSERT OR REPLACE INTO Modifiers (ModifierId, ModifierType,SubjectRequirementSetId)
	VALUES	('RIVER_ADDYIELDS_MODIFIER', 'MODIFIER_CITY_PLOT_YIELDS_ADJUST_PLOT_YIELD', 'PLOT_ADJACENT_TO_RIVER_REQUIREMENTS');

INSERT OR REPLACE INTO ModifierArguments (ModifierId, Name, Value)
	VALUES	('RIVER_ADDYIELDS', 		'ModifierId',	'RIVER_ADDYIELDS_MODIFIER'),
		('RIVER_ADDYIELDS_MODIFIER',	'Amount',	'2,1'),
		('RIVER_ADDYIELDS_MODIFIER',	'YieldType',	'YIELD_FOOD,YIELD_GOLD');
 
Try using xml. But I have only seen few Columns that could hold many entries. Or try those columns first, just to be sure that it's possible. And have a look at the Game's files that make use of them.
I've actually used it with BuildingType in another modifier with another effect and it worked fine. So I don't understand :/
I'll give xml a shot

edit: just saw Lee's reply. Makes a lot of sense, seems I'm out of luck
 
Is there anyway I can do this without making 50 different modifiers?

I've made similar modifiers. Here's how I would do it:

Code:
INSERT OR IGNORE INTO Types (Type, Kind) 
VALUES ('DM_ADJUST_BUILDING_PURCHASE_COST', 'KIND_MODIFIER') ;

INSERT OR IGNORE INTO DynamicModifiers (ModifierType,  CollectionType, EffectType) 
VALUES ('DM_ADJUST_BUILDING_PURCHASE_COST',  'COLLECTION_ALL_CITIES',  'EFFECT_ADJUST_BUILDING_PURCHASE_COST') ;

INSERT OR IGNORE INTO Modifiers(ModifierId, ModifierType)
SELECT 'MOD_ADJUST_' || BuildingType || '_PURCHASE_COST', 'DM_ADJUST_BUILDING_PURCHASE_COST' FROM Buildings WHERE IsWonder = 0 ;

INSERT OR IGNORE INTO ModifierArguments(ModifierId, Name, Value)
SELECT 'MOD_ADJUST_' || BuildingType || '_PURCHASE_COST', 'BuildingType', BuildingType FROM Buildings WHERE IsWonder = 0 ;

INSERT OR IGNORE INTO ModifierArguments(ModifierId, Name, Value)
SELECT 'MOD_ADJUST_' || BuildingType || '_PURCHASE_COST', 'Amount', 50 FROM Buildings WHERE IsWonder = 0 ;

You can use a Select command for the values of an Insert command... and grab any list in the database that way. The Select command I provided is essentially all the buildings where IsWonder is 0.

The || operator is for string concatenation in SQLite.

The end result of this query is 50ish modifiers, one for each of the 50ish buildings... one that makes monuments cheaper, another for granaries, etc. Of course, you still need to attach the modifiers somewhere. Just having them created doesn't do anything. I'm guessing GameModifiers?

Kind regards,
DB
 
Hi folks, I'm hoping someone can help me figure out why my mod build isn't working properly. When I build the mod in ModBuddy, the .dep file isn't created. I'm sure I've done everything correctly, but my icons aren't working, presumably due to the lack of a .dep file being created. If anyone has the time to take a look at this mod and can tell me what's wrong, I'd really appreciate it! Thanks!

Edit:
Turns out the issue is that ModBuddy needs *any* ArtDef at all to be present in order to generate the dep file. It's working now.
 

Attachments

Last edited:
I'm modding the civic tree, and I have civics in the same era arranging themselves in the wrong order? More expensive ones move themselves to the left of the less expensive ones? picture for what I'm talking about
https://i.imgur.com/Mr1XSD7.png
Also note that Early Empire does not require Political Philosophy.
This is happening in multiple areas of my civic tree. Why are they displaying this way?
 
without the actual code you are using to look at it is impossible to give a meaningful answer.
of course.
I have removed most of the civics, the ones that remain I reorganized them on the tree. Here's the code for the actual costs and tree position, and all of the more expensive ones in each era are NOT appearing to the right of the cheaper ones. I'm not sure why
Code:
UPDATE Civics SET Cost= 10, EraType= 'ERA_ANCIENT', UITreeRow= -1 WHERE CivicType= 'CIVIC_CODE_OF_LAWS';
UPDATE Civics SET Cost= 10, EraType= 'ERA_ANCIENT', UITreeRow= -3 WHERE CivicType= 'CIVIC_CRAFTSMANSHIP';
UPDATE Civics SET Cost= 10, EraType= 'ERA_ANCIENT', UITreeRow= 2 WHERE CivicType= 'CIVIC_FOREIGN_TRADE';
UPDATE Civics SET Cost= 20, EraType= 'ERA_ANCIENT', UITreeRow= 0 WHERE CivicType= 'CIVIC_THEOLOGY';
UPDATE Civics SET Cost= 21, EraType= 'ERA_ANCIENT', UITreeRow= -3 WHERE CivicType= 'CIVIC_MILITARY_TRADITION';
UPDATE Civics SET Cost= 21, EraType= 'ERA_ANCIENT', UITreeRow= -1 WHERE CivicType= 'CIVIC_EARLY_EMPIRE';
UPDATE Civics SET Cost= 21, EraType= 'ERA_ANCIENT', UITreeRow= 2 WHERE CivicType= 'CIVIC_MYSTICISM';
UPDATE Civics SET Cost= 60, EraType= 'ERA_ANCIENT', UITreeRow= 0 WHERE CivicType= 'CIVIC_POLITICAL_PHILOSOPHY';

UPDATE Civics SET Cost= 45, EraType= 'ERA_CLASSICAL', UITreeRow= -3 WHERE CivicType= 'CIVIC_MILITARY_TRAINING';
UPDATE Civics SET Cost= 45, EraType= 'ERA_CLASSICAL', UITreeRow= -1 WHERE CivicType= 'CIVIC_STATE_WORKFORCE';
UPDATE Civics SET Cost= 45, EraType= 'ERA_CLASSICAL', UITreeRow= 2 WHERE CivicType= 'CIVIC_DRAMA_POETRY';
UPDATE Civics SET Cost= 120, EraType= 'ERA_CLASSICAL', UITreeRow= 0 WHERE CivicType= 'CIVIC_CIVIL_SERVICE';

UPDATE Civics SET Cost= 100, EraType= 'ERA_MEDIEVAL', UITreeRow= -3 WHERE CivicType= 'CIVIC_DEFENSIVE_TACTICS';
UPDATE Civics SET Cost= 100, EraType= 'ERA_MEDIEVAL', UITreeRow= -1 WHERE CivicType= 'CIVIC_NAVAL_TRADITION';
UPDATE Civics SET Cost= 100, EraType= 'ERA_MEDIEVAL', UITreeRow= 2 WHERE CivicType= 'CIVIC_RECORDED_HISTORY';
UPDATE Civics SET Cost= 250, EraType= 'ERA_MEDIEVAL', UITreeRow= 0 WHERE CivicType= 'CIVIC_HUMANISM';

UPDATE Civics SET Cost= 200, EraType= 'ERA_RENAISSANCE', UITreeRow= -3 WHERE CivicType= 'CIVIC_FEUDALISM';
UPDATE Civics SET Cost= 200, EraType= 'ERA_RENAISSANCE', UITreeRow= -1 WHERE CivicType= 'CIVIC_EXPLORATION';
UPDATE Civics SET Cost= 200, EraType= 'ERA_RENAISSANCE', UITreeRow= 2 WHERE CivicType= 'CIVIC_DIVINE_RIGHT';
UPDATE Civics SET Cost= 600, EraType= 'ERA_RENAISSANCE', UITreeRow= 0 WHERE CivicType= 'CIVIC_NATURAL_HISTORY';
 
First you need to have all the Cost values for Ancient Era Civics less than the lowest cost value of any Civic in the Classical Era, and so on for each respective pair of eras. Otherwise this borks the code in the lua file that assigns the positions in the display.

Second you need to ensure that the CivicPrereqs table is properly constructed after your changes and does not have logical conflicts with the costs and positioning on the tree you are aiming after.
 
Back
Top Bottom