Narrowness Of Game Engine Effects Is Becoming Frustrating, I Think It Bodes Ill For Future Modding

tman2000

Prince
Joined
Feb 11, 2025
Messages
480
I have a military unit that I want to work like a migrant. Well, you can assign it the resettle ability and it works! Which is cool, except I want this to only work in distant lands. Okay, you can specify an effect on a city if it's in distant lands. You can specify an effect for a unit ability. But the entire resettle ability is behind the curtain in the engine, so it's all or nothing.

I wanted specific resources to get a bonus yield. Easy right? No, because while the effect to do this is in the database, it's not implemented by any civ yet, so it doesn't actually do anything. You can adjust the yields of unassigned resources. You can adjust the yields of assigned resources. You can adjust all resource yields. You can update the database to permanently change a resource yield. You can't actually just modify the ResourceYields value dynamically in the middle of play. Since I can't make this simple modification, because the effect isn't implemented, I settled for lowering the yield bonus and having it just apply universally in distant lands, since the game engine does have a filter for cities whether they're in DL or not.

I want to have new cities found with a free building, I wanted one specific building, but even just any free building would do. Simon Bolivar can do that, except, no his effect can only tell the engine to do that when conquering a city.

I thought, maybe a unit instead of a building? There's an effect to add a unit after the city is conquered. There's a narrative event that adds a unit to a city. The best I can do is create a unit when a policy is researched, or you can spam slotting a policy in and out to get many units (ironically a bug that Spiffing Brit made a video about). There's no "listen for when a city is founded" effect because it hasn't been implemented in engine yet.

I had an idea to have missionary charges do something else, at least add some happiness or something. Well, the Majapahit missionary adds culture, and there's an entire game effect for it with selectable yields and amounts. Great! Problem is, the Peranda yield is culture, and while you can also implement a science yield, no other yields are implemented in engine and they don't work. Worse, Peranda is supposed to do +25 culture and that's the database value the game file loads in, but actually it will only give 20 culture, or if you do science, 20 science. The amount modifier doesn't actually change anything, and in fact the game text and civolopedia feature is not as advertised.

There's a visual updater which they use to recycle unit model assets for new civs. It takes "kind" values, but that's just a shell. It doesn't actually let you remap constructible models, just units.

If anyone has some workaround on any of these issues, I'd love to hear it just out of morbid curiosity at this point having worked a few hours trying to solve them. However, I'm mostly just expressing my frustration. I know you can't expect much with limited mod tools, but it's also that I encounter errors a lot of the time in the game files (in Bulgaria's files, one of the tags was autocompleted as "BUGANDA" instead of "BULGARIA", for example). It seems like every single unit civ abilities is hard coded into the engine, instead of just being scripted around simple and common game effects. Like, you could make city events: conquest, founding, new building. Just put a set of tags tied to listeners for all of that. Then add a set of tags for basic yield and value modifications. Then, when they make a new civ with a new ability, it's extremely easy to script.

This kind of simplicity would allow us to do a lot too. For instance, I want to make a civ that let's you "dock" an army commander on a friendly city-state and turn it into a city, but you can "undock" him and it reverts to city-state behavior. The game can already convert a city into a city-state when an independent power conquers it, so the basic value switching needed is there. It's just all behind the curtain.

I had a revelation that they're charging $30 for 4 civs, each with relatively minor gameplay modifications. While you are getting 2 leaders and a few building models, a LOT is reused. We even had an issue with unique unit models with GB and the revenge. So, if one civ adds in "only one city" and a new leader adds it "free building when you conquer", then they are also selling new modibility options as well, instead of them being available upfront.

Think about it, if we could dynamically alter these values, then how interesting could these new civs be? We would have already tried every recombination of features, and the devs would have to add more value into their product - like more complete and interesting narrative storylines, better unit models, or genuinely novel game mechanics. I mean, I'd be fine if the DLCs became little more than asset packs, new toys to play with.

If modibility is limited, then the value of new game effects in new DLC goes up. I have to say it.

Regardless, the bones of Civ 7 seem very weak to me. I don't understand all these half-implementations and how if they one day have a civ that gets +5 science on sugar dates, it will have a game effect that does that, maybe does +5 culture, and nothing else. The bare minimum, rushed implementation, behind the curtain so people can modify it.

Anyway, I hope to be corrected. I might be missing something here about how to implement game mechanics.
 
With all due respect, you're not really looking hard enough. More familiarity with the requirement/modifier system helps in figuring out how to do what you want to do. There are limitations, but there are also lots of things you can do if you get creative. I don't have solutions for everything you mentioned off the top of my head, but here's a few:

You want a free building on new cities? Find a civ (Normans) who already do that and copy them - you'll find there's a modifier you can attach to a Settler.
...because while the effect to do this is in the database, it's not implemented by any civ yet, so it doesn't actually do anything.
This doesn't follow. There are plenty of effects in Civ6 and Civ7 that weren't "demoed" but were perfectly functional.
I wanted specific resources to get a bonus yield.
Use REQUIREMENT_CITY_HAS_RESOURCE to check if a city has a specific resource type. If so, grant a yield to the city itself, not the resource.
There's no "listen for when a city is founded" effect because it hasn't been implemented in engine yet.
Untested, but try REQUIREMENT_CITY_HAS_BUILDING and checking for Palace or City Hall. Might need to specify your modifier runs once. Those are granted for free when a city is founded, so functionally it's the same as "when a city is founded".
But the entire resettle ability is behind the curtain in the engine, so it's all or nothing.
Untested, but try attaching a modifier to the unit or player units which toggles the ability when in distant lands (EFFECT_UNIT_ADJUST_ABILITY).
 
Untested, but try attaching a modifier to the unit or player units which toggles the ability when in distant lands (EFFECT_UNIT_ADJUST_ABILITY).
Thanks for all the tips, I was frustrated but am also looking for answers. Where did you find the above? Which civ uses it? EDIT: Oh, GP obviously, nevermind.

As for things like adding a happiness yield, I'm going to try adding a GP effect button to missionaries, and I'm hoping that I can make it contingent on having a tradition slotted, so that missionaries aren't affected for other players.
 
Last edited:
I'd say frustration is 'normal' in the sense that it happens to everyone. The question will be if you feel the satisfaction when you finish was worth it. It can also be satisfying to come up with something working within limitations.

My suggestion is if you are creating a new civ is to just get it done and polish it up, even if it's not everything you hoped for. Sometimes you can figure things out while you are not working on them.
 
Thanks for all the tips, I was frustrated but am also looking for answers. Where did you find the above? Which civ uses it? EDIT: Oh, GP obviously, nevermind.
Actually the adjust unit ability is a non implemented effect for an unused heal ability of the Khmer cavalry unit.

The great people handle conditional ability use behind the curtain of the engine
 
I'd say frustration is 'normal' in the sense that it happens to everyone. The question will be if you feel the satisfaction when you finish was worth it. It can also be satisfying to come up with something working within limitations.

My suggestion is if you are creating a new civ is to just get it done and polish it up, even if it's not everything you hoped for. Sometimes you can figure things out while you are not working on them.
Thanks. I’ve had to be creative but it is amazing how implementing a feature with an entirely different effect ends up mostly accomplishing the goal. I wanted missionary spreads to add things like science but you can only do it through first time conversions and religious spread is hidden in the engine. But I just repurposed the own-city civics with bonus city yields and it’s essentially the same thing, at least thematically and you’re doing similar effort for the effect.

I think I will be satisfied with the result for certain. After release I want to take time and fill out the narrative events, which should be fun in itself.
 
I'm glad you're finding some workarounds. You might be already doing these, but a few tips on how I navigate the modifier system:
  • Whenever I encounter an Effect or Requirement that I want to figure out how to use, the first thing I do is use Notepad++ Find in Files to search the various Civ7 modules/database folder for that tag. That gives me an immediate and quick demo on how it's implemented.
  • I use DB Browser for SQLite to poke around the debug databases. Some useful queries for joining some relevant tables together to get a better contextual understanding:
SQL:
SELECT GameEffects.Type,
    GameEffects.Description,
    GameEffectArguments.Name as ArgumentName,
    GameEffectArguments.Description as ArgumentDescription,
    GameEffectArguments.Required,
    GameEffectArguments.ArgumentType,
    GameEffectArguments.DefaultValue,
    GameEffectArguments.MinValue,
    GameEffectArguments.MaxValue,
    GameEffectArguments.DatabaseKind
FROM GameEffects
INNER JOIN GameEffectArguments ON GameEffects.Type = GameEffectArguments.Type;

SQL:
SELECT RequirementSets.RequirementSetId,
    RequirementSets.RequirementSetType,
    RequirementSetRequirements.RequirementId,
    Requirements.RequirementType,
    Requirements.Inverse,
    RequirementArguments.Name as ArgumentName,
    RequirementArguments.Value as ArgumentValue
FROM RequirementSets
INNER JOIN RequirementSetRequirements ON RequirementSets.RequirementSetId = RequirementSetRequirements.RequirementSetId
INNER JOIN Requirements ON Requirements.RequirementId = RequirementSetRequirements.RequirementId
INNER JOIN RequirementArguments ON RequirementArguments.RequirementId = Requirements.RequirementId;

SQL:
SELECT Modifiers.ModifierId,
    Modifiers.ModifierType,
    DynamicModifiers.EffectType,
    DynamicModifiers.CollectionType,
    Modifiers.Permanent,
    Modifiers.RunOnce,
    Modifiers.OwnerRequirementSetId,
    Modifiers.SubjectRequirementSetId,
    ModifierArguments.Name as ArgumentName,
    ModifierArguments.Type as ArgumentType,
    ModifierArguments.Value as ArgumentValue,
    ModifierArguments.Extra as ArgumentExtra
FROM Modifiers
INNER JOIN ModifierArguments ON Modifiers.ModifierId = ModifierArguments.ModifierId
INNER JOIN DynamicModifiers ON Modifiers.ModifierType = DynamicModifiers.ModifierType;
 
Last edited:
Oh, one more thing: when testing modifiers it is useful to set up some logging for GameEffects in AppOptions.txt:

Code:
;Game Effects logging level, 0 = Off, 1 = Minimal, 2 = Normal, 3 = Detailed, 4 = Diagnostic

Set it to 3 or 4 when testing to check where and when your modifiers are getting attached. This can be very helpful when trying to figure out which collection to use.
 
Oh, one more thing: when testing modifiers it is useful to set up some logging for GameEffects in AppOptions.txt:

Code:
;Game Effects logging level, 0 = Off, 1 = Minimal, 2 = Normal, 3 = Detailed, 4 = Diagnostic

Set it to 3 or 4 when testing to check where and when your modifiers are getting attached. This can be very helpful when trying to figure out which collection to use.
Thanks, this is helpful for knowing if the modifier has changed and the engine doesn't care.

I've found there's a lot of nuance with for instance how modifiers only trigger when a policy is first researched, so you have to save game before that to try out changes. Also, I believe that sometimes you have to turn off your mod, load, then turn it on again sometimes just because it will retain past modifications without introducing new ones. This leads to errors in culture tree nodes.
 
Use REQUIREMENT_CITY_HAS_RESOURCE to check if a city has a specific resource type. If so, grant a yield to the city itself, not the resource.
I don't believe this works as I don't believe the engine has implemented it. I think there are unused tags from abandoned features. Adjust ability also is from an abandoned feature and doesn't work.

My work around was to make the ability permanent and the units appear with each golden age celebration. It was working, but now they only appear for one celebration only. Working on it.

Would love if you could figure out how to give yield to plot or city for one type of resource. All I can do is give all distant lands resource plots a yield.
 
I don't believe this works as I don't believe the engine has implemented it. I think there are unused tags from abandoned features. Adjust ability also is from an abandoned feature and doesn't work.

My work around was to make the ability permanent and the units appear with each golden age celebration. It was working, but now they only appear for one celebration only. Working on it.

Would love if you could figure out how to give yield to plot or city for one type of resource. All I can do is give all distant lands resource plots a yield.
Adjust Ability? You can grant abilities, but you need to already have the unit being assigned the ability, it’s more like “activating” it.

Imago Mundi does adjust the scout ability but it’s very hardcoded I suspect.

I’m not sure what you want from the resource granting different yields, is the idea that some civ or leader has an ability where an improvement that has Dates on it would get bonus yields? I would’ve expected that to be doable, as it was doable in Civ VI.

I think you are maybe a bit conspiratorial as far as thinking this stuff is not exposed because it cuts into their revenue. The reason for the GameEffect system existing and being exposed to begin with is so a Game Designer on the Firaxis team doesn’t have to know C++ to make and test a new civ ability. In fact the last two years of civ VI content was done with seemingly no input from the C++ engine guys, they were just official Firaxis mods in a way.

Sure it would be nice for them if there was a huge fancy system of Event handling, and that was actually used in civ VI for Lua scripting, but not for the effect system. It would probably take a lot more headache to do that for the effect system, and might end up making the game slower, and performance is king over that level of customisation.
 
Adjust Ability? You can grant abilities, but you need to already have the unit being assigned the ability, it’s more like “activating” it.

Imago Mundi does adjust the scout ability but it’s very hardcoded I suspect.
It doesn't adjust the ability, it just adds sight to scout. Adjust sight is an effect that is hardcoded but at least can be applied universally. I wanted a lands version of Christopher Columbus's reveal map for a "John Smith" great person. What I did was create a unit that has a hidden icon and is unlocked from Future Tech and costs 299,999 gold. That unit has +15 sight, and so the great person can spawn it in the nearest city. I gave it movement zero. Best I could do there, but the adjust sight was useful.

I think adjust ability, while it would work as you said, hasn't actually been implemented. It is associated with a heal ability where the Khmer elephant cavalry get the ability when next to a river, but this was not implemented in the game. The ability is in the gameeffects file, but not applied to the unit. Adjust ability was meant to activate this heal ability. It doesn't appear to work.
I’m not sure what you want from the resource granting different yields, is the idea that some civ or leader has an ability where an improvement that has Dates on it would get bonus yields? I would’ve expected that to be doable, as it was doable in Civ VI.
Yesh, tea gives a bonus yield with an unlocked civic. However, my work around is to use the requirement created for "have X horses to unlock mongolia". I'm doing "have X tea" and then just applying the yield to the capital. Makes sense I suppose, almost works better thematically. But the "CITY_HAS_RESOURCE" doesn't seem to work, and if you look it up, it's not used. For instance, Carthage's resource based cavalry combat bonus is not taking a has_resource tag and connecting it to a give_combat_bonus effect. Instead there is a custom "carthage_cavalry_resource_bonus" effect. This is what I mean by they seem to be building out the entire game bespoke one feature at a time directly into the engine.
I think you are maybe a bit conspiratorial as far as thinking this stuff is not exposed because it cuts into their revenue. The reason for the GameEffect system existing and being exposed to begin with is so a Game Designer on the Firaxis team doesn’t have to know C++ to make and test a new civ ability. In fact the last two years of civ VI content was done with seemingly no input from the C++ engine guys, they were just official Firaxis mods in a way.
Is it really "conspiratorial". I think it's the C++ engine guys being task to update mundane game effects because whatever happened to the UI also sunk their scripting system. I think the latest civ updates like Carthage's effects or Bulgaria's send production to towns from pillage are literally hardcoded into the engine since they probably don't have a system nor a team around to do this level of game development.
 
I do agree that the resource system is far more hardcoded than I would like, at least on an assignment level. I’ve been looking into fixing the Coal bug before Firaxis did it for me, and couldn’t find a way to manually check for total resource count, including imports. VI also had that issue

For the Tea thing, have you tried a modifierType that’s like COLLECTION_CITY_PLOTS and EFFECT_ADJUST_PLOT_YIELD? You’d then need a requirement to check the plot had the right resource. Not at PC.l, but I’ll check how I did it in VI, think I used typeTags to assign the resource to a tag, then used REQUIREMENT_PLOT_RESOURCE_TAG_MATCHES
 
Last edited:
CITY_HAS_RESOURCE is just a way to test for factory resources in a city for the factory town project. I don't think it can be modified.

However, I did learn that you can set "REQUIREMENT_CITY_IS_DISTANT_LANDS" to homelands with inverse="true"
 
I do agree that the resource system is far more hardcoded than I would like, at least on an assignment level. I’ve been looking into fixing the Coal bug before Firaxis did it for me, and couldn’t find a way to manually check for total resource count, including imports. VI also had that issue

For the Tea thing, have you tried a modifierType that’s like COLLECTION_CITY_PLOTS and EFFECT_ADJUST_PLOT_YIELD? You’d then need a requirement to check the plot had the right resource. Not at PC.l, but I’ll check how I did it in VI, think I used typeTags to assign the resource to a tag, then used REQUIREMENT_PLOT_RESOURCE_TAG_MATCHES
TAG_MATCHES seems to not distinguish between different resources, but I'll give it another try. Earlier I wanted to do +5 gold per treasure resource plot yield, but since it couldn't discriminate I just set it to +2 for all resources in distant lands, since I can discriminate based on city location.

I found this: EFFECT_PLAYER_ADJUST_YIELD_PER_RESOURCE_TYPE and EFFECT_PLAYER_ADJUST_YIELD_PER_RESOURCE

The problem is these apply to slotted ("TYPE" works for empire) resources. Tea is a treasure resources, so I'm investigating if the yield applies once the treasure resource is acknowledged after shipbuilding is researched.
 
Nope, treasure resources are not allocated to their city so there's no way to assign yields to them.

I can't find what tags work with "RESOURCE_TAG_MATCHES", RESOURCECLASS nor RESOURCE seem to work.
 
You would have to set a tag. I would avoid anything that changes the resource, that will probably apply to the collected resource, not the tile. Got it to work here in a test case with Xerxes and Dates, but you could put it on a civicTree and Tea easily:


SQL:
INSERT INTO TraitModifiers(TraitType, ModifierId) VALUES
('TRAIT_LEADER_XERXES_ABILITY', 'MOD_BUFF_TEA');

INSERT INTO Modifiers(ModifierId, ModifierType, SubjectRequirementSetId) VALUES
('MOD_BUFF_TEA', 'MOD_BUFF_TEA_TYPE', 'PLOT_HAS_TEA_REQS');            --

INSERT INTO ModifierArguments(ModifierId, Name, Value) VALUES
('MOD_BUFF_TEA', 'YieldType', 'YIELD_FOOD'),
('MOD_BUFF_TEA', 'Amount','10');

INSERT INTO DynamicModifiers(ModifierType, CollectionType, EffectType) VALUES
('MOD_BUFF_TEA_TYPE', 'COLLECTION_PLAYER_PLOT_YIELDS', 'EFFECT_PLOT_ADJUST_YIELD');

INSERT INTO Types(Type, Kind) VALUES
('MOD_BUFF_TEA_TYPE', 'KIND_MODIFIER');

INSERT INTO RequirementSetRequirements(RequirementSetId, RequirementId) VALUES
('PLOT_HAS_TEA_REQS', 'PLOT_HAS_TEA');

INSERT INTO RequirementSets(RequirementSetId, RequirementSetType) VALUES
('PLOT_HAS_TEA_REQS','REQUIREMENTSET_TEST_ALL');

INSERT INTO Requirements(RequirementId, RequirementType) VALUES ('PLOT_HAS_TEA', 'REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES');

INSERT INTO RequirementArguments(RequirementId, Name, Value) VALUES ('PLOT_HAS_TEA', 'ResourceType', 'RESOURCE_DATES');

1743873520139.png
 
INSERT INTO Requirements(RequirementId, RequirementType) VALUES ('PLOT_HAS_TEA', 'REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES');
I didn't know REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES was in the database. Where did you find it?

I tried to make a "RESOURCE_NEW_TEA" like a Lapis Lazuli that was gifted by a civic. I couldn't get the yields to change so I tried updating the yield changes on RESOURCE_KAOLIN and the engine doesn't care what values are in the modifiers database, it must be assigning resource values in engine.

Anyway, thanks for solving this one for me! Maybe my last hurdle.

Last hurdle actually is solving how to get a golden age celebration modifier to trigger more than just once.
 
I didn't know REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES was in the database. Where did you find it?

I knew about it from Civ Vi, it’s how the Water Mill grants yields to Rice, Wheat and Maize.

I have a little python script to convert the database into a bunch of csv’s and search it for substrings, I just looked for any like REQUIREMENT_PLOT.

That’s how I found its use in Civ VI, I then used the same method to see if that REQUIREMENT_PLOT_RESOURCE_TYPE_MATCHES existed in VII. It was in Types and GameEffects, so I figured it was worth a try.

A lot of this stuff is just Firaxis not really having good documentation.

That last one sounds a little harder to figure out as the Golden Age stuff is new. I can have a look later
 
Got it to work here in a test case with Xerxes and Dates,
I implemented this and it was apply the yield boost to all tiles other than those with resources, so I inverted the tag and it now applies it to all resources.

EDIT: So I created an .sql file and copied and pasted your text and it does work now. I was trying to implement it via the .xml file before.

I honestly don't know why that was causing a bug. The only difference from the .sql code was maybe MOD_BUFF_TEA _TYPE wasn't being explicitly created.

If I had to guess the requirement wasn't in the database prior to the requirement check in the .xml code, so it defaulted to FALSE when it checked if "ResourceType" was tea for all actual resource tiles (since there was no previous reference), causing the non-resource tiles to pick up the yield adjustment.

Anyway, this might be why other features aren't working for me. You have to actually insert these checks into the database ahead of time. Which is weird because I'm using the game files as a model so I suppose they might be hard coding these default checks into the C++ engine rather than building out the database values for them every time.
 
Last edited:
Back
Top Bottom