PSA to modders - hard limit on unique districts?

anansethespider

Warlord
Joined
Oct 27, 2016
Messages
288
It would seem from my testing that you cannot have more than one unique replacement district for any base game district type. Whichever one is added to the database second can still be built, but buildings from that base district cannot be built inside.

Ie, I am playing with my mod that adds a unique commerce hub district to France. I load Sukitract's new Rama mod and it gets added to the database after my own mod. With both mods active, I can build Floating Markets but I cannot build any Commerce Hub buildings inside them.

It's late and i have no idea what to do about this problem, I'm just making everyone aware of it.
 
Make sure to check the logs for errors, especially the database. Might just be an error in your xml/sql before your DistrictReplaces or whatever that entry is, and it just doesn't load the rest of the file. Might be a conflict with the the other mod you're loading or something.
 
It is not. I am nearly certain the issue is exactly as I describe. I've been able to replicate it in two separate instances.
 
Yeah, I've tested this now and ... yeah .. that's how it works. I simply turned another unique district (Hansa) into a CivUniqueDistrictType that replaces Theater in the DistrictReplaces replaces table, in addition to retaining Acropolis as a unique replacement in the same table. I then gave a single civ the traits for each of Hansa and Acropolis and tested the outcome. Here are the findings:

(1) Based on my previous tests that involved building multiples of the same basic district type in one city, I expected that only one of the districts with the same buildings line up would be able to build any of the buildings from the common set. When duplicates of the same district type are built in one city, the first district built is given primacy over any subsequent iterations. The non-building-related functionality remains unchanged (adjacency bonuses, etc.) for all the instances of the same district, but all the buildings are nested in the one that was placed (not completed) first. This led me to believe that access to building is simply a matter of first-past-the-post.

(2) However, what I did not expect is how two unique district replacements of the same basic districts behaved in the same situation. One was indeed given primacy over the other (that was anticipated where one city is involved), but not the one I expected. By all accounts, and any way you assess it, Acropolis should have loaded first, ahead of Hansa. Acropolis is ahead in the Districts table, the DistrictReplaces table and in the order in which I attached the respective Traits to the test civilization. One would expect Acropolis to get primacy. A fortiori, if Acropolis is placed on the map ahead of the Hansa.

(3) However, it worked the other way around. No matter how I tried and the sequence I followed when constructing the districts, Hansa always clinched the buildings line up. Whether or not Acropolis was placed first on the map, the buildings became available under Hansa (as soon as Acropolis was placed on the map, or, if Hansa was placed first, then at that point).

(4) If indeed load order has anything to do with the primacy, then it would seem to work the other way. The district that comes later (by row number in a table) get the buildings. It would kind of makes sense from the standpoint of load order, as the later code should overwrite the earlier code, if at all possible, in the event of a conflict.

(5) Here is a way to test this in your set up (with two separate mods). Use the following in your mod's MODINFO:

Code:
    <Components>
        <UpdateDatabase id="SQL_Changes">
<!--The value of LoadOrder is intentionally set to a high integer of 10,100, to ensure that the SQL component loads after all other mod and DLC components.
    The Properties element may be removed altogether if this functionality is not desired. Conversely, the integer may be increased if the number of other mod
    and DLC components exceeds the value set below and the SQL component of this mod fails to load last of all.-->
            <Properties>
                <LoadOrder>10,100</LoadOrder>
            </Properties>
            <Items>
                <File>UniqueDistrictsPopReqModSQL.sql</File>
            </Items>
        </UpdateDatabase>
    </Components>

to force the component that inserts your mod's unique replacement for the Commercial Hub to load after all the other DLC and mod components are loaded (see here for a full explanation of the method from PlotinusRedux: LINK). If the pattern that you report repeats (i.e if all of a sudden Floating Markets get access to the buildings line up and your own mod's district loses it), then load order is the cause. If, however, nothing changes, then the root of the problem is elsewhere. Perhaps in the order in which the districts are placed into the tables.
 
As a practical matter, one solution is designing unique districts that don't actually replace base game districts. But for instance, in the above example, Siam could have a trait that makes them unable to build Commercial Hubs, and another trait that gives them Floating Markets as a separate unique district. It would require some tinkering around, but that's the best way I can imagine going beyond the number of generic districts in the game
 
That's right. The only other additional step you would need to do is to create a separate line up of identical Commercial Hub buildings for the non-replacing unique district. If BUILDING_BANK has PrereqDistrict COMMERCIAL_HUB, it can never be built in an entirely unrelated district, unique or not. AFAIK, the way the PrereqDistrict equivalence is achieved in XML is by making the district sharing identical building line-ups to appear in the same row in the DistrictReplaces table (much like BUILDING_BARRACKS and BUILDING_STABLE have equivalent prerequisite, modifier, etc. effects because they appear in the same row in the MutuallyExclusiveBuildings table). If you do not have Acropolis replace Theatre, for instance, Acropolis can't build the DISTRICT_THEATRE buildings, and so forth. So, one way to ensure that the unique district functions properly, notwithstanding the effect of any other mod, is to create a separate and unique building line up for it that duplicates the line up of the basic game district it replaces (but does now, because you would omit place the pair in the DistrictReplaces table).

The problem with the latter approach is that you would also have to duplicate all the Modifier, Requirement, Ability, etc. chains that are attached to the building line up of the basic game district. Add to that the possibility of other mods adding new interdependencies that you may wish to maintain applicable throughout the game's database for each instance of the game, and you have a real mess. It's would be either excruciatingly mind-numbing to code all the duplicate interdependencies or virtually impossible. You can certainly achieve some basic functionality, but to get it perfect is hard.

So, we need a second (or, rather, third) option. What we need is either a way to check (in SQL), at the conclusion of the load order of all components, what interdependency chains have been added to the database and then duplicate them. Duplicating itself is not that difficult. SQL can update everything at once with a few lines of code. But actually checking, and possibly creating the necessary additional tables, on the fly is more daunting (I haven't found a way to do so in SQL yet, thought my experience is limited).

The other approach is to do the same in LUA. Create a temporary LUA table that would note the necessary relations and then enforce them for the non-replacing unique district. Then save this table to be called up again on game reload. I've read that this type of functionality is limited in the current implementation of LUA in CIVI. Besides, there may be the unfortunate problem that this approach would have to mix-and-match IN SCRIPT (<GameplayScripts>) and IN CONTEXT (<UserInterface>), and we can't do that. I can identify the any new district added to map by ID# in LUA and then place an incomplete building in it, no problem (at least I think so, I haven't tried placing a building in any district other than DISTRICT_CITY_CENTER), but we have no way of linking this process to the UI commands (i.e. the mouse click tracker, etc.).

However, and let me give this try, perhaps the problem is tied to the UI implementation of Production Panels. If so, then the solution is far simpler. We simply have to remove the block that's preventing the building line up from appearing in the BuildList. However, again, if this process relies on Hash values and PARAM variables, I have no idea how to work with those. I've tried unsuccessfully. I simply don't know how to change the hash values.
 
As a practical matter, one solution is designing unique districts that don't actually replace base game districts. But for instance, in the above example, Siam could have a trait that makes them unable to build Commercial Hubs, and another trait that gives them Floating Markets as a separate unique district. It would require some tinkering around, but that's the best way I can imagine going beyond the number of generic districts in the game

I'm not an expert on modding, but would this not mean that, if I were to conquer a Siamese city with a Floating Market, the district were to disappear, instead of turning into a Commercial Hub? Or can that easily be fixed?
 
I'm not an expert on modding, but would this not mean that, if I were to conquer a Siamese city with a Floating Market, the district were to disappear, instead of turning into a Commercial Hub? Or can that easily be fixed?

You are correct, that would happen :(
 
Back
Top Bottom