Mountains, Districts, Improvements, Wonders, Coasts - Using LUA & XML to Work Around the Limitations

Gleb Bazov

Warlord
Joined
Feb 13, 2017
Messages
176
I remember several postings on here regarding mountain plots in Civ VI and whether it is possible to place districts and improvements on them. There was also (a successfully resolved) discussion about enabling movement on mountain tiles for helicopters, scouts, builders, and settlers, and restricting it for all other unit types.

I am posting this here to share my implementation of several workarounds that enable all this functionality in case anyone else is still searching for solutions. If you are interested in getting the code for any of the below, let me know. It's the requests by others that triggered my own attempts. I have a few ideas, but no immediate time or plans to fully develop the applications. Here is a short list of methods:

(a) mountain movement for specified units;
(b) mountains as workable city plots;
(c) placement of districts and improvements on mountains; and,
(d) restricting wonders to coastal tiles.​

(1) XML - Mountain Movement for Helicopters, Scouts, Builders, Settlers, but not Others
Mountain Usability as City Plots


Following Issau's proposal, I've implemented XML code that allows for the following:

(1) helicopters, scouts, builder, and settlers, archaeologists etc. to move onto mountains;
(2) settlers to build cities on mountains; and,
(3) builders to plant forests on mountains.
As well, mountains can easily be made into workable tiles, with customizable yields. Using XML, they can be made subject to a variety of modifiers that change yields (such as making Petra apply to mountain tiles, for example), and so forth. The mountains do not use any of their other functionality, such as being available for adjacency bonī, etc.

An interesting idea is to have city Projects that affect mountains (or other terrain types). For instance, Projects can be coded with modifiers that act as "public works" that improve the usability of mountains (or desert, etc.) each time they are completed. For instance:

(1) a Project that acts as a "gold rush" or a mining cosortium's development of mountains. With each completion, mountain plots (of a give type, or any) would gain, say, 1 point of production; or,

(2) a Project that acts as "desert irrigation", for example, that improves the quality of desert tiles.

Such Projects can be one-off or recurrent. A "gold rush" type project can, also, be made to interact with LUA to activate greater yields only while a city is actually building the project, but otherwise remain dormant. (This can be done by listening in LUA for whether a specific Modifier is active, and triggering the effect only during that period).​

Mountains cannot be made available for building improvements using XML. However, they can be made to host features and resources (although you wouldn't be able to improve such resources or features, anything that's hosted on the mountain will still trigger an adjacency bonus).

This XML code precludes any units other than those defined from moving onto the mountains (so you won't have cavalry running up the mountains, for example). I had some trouble with ensuring that GPs are able to move onto the mountains, but I think I've gotten it mostly right and it just needs some further debugging.

Here is a catch, if a unit not permitted to move onto mountains is built/appears in a city built on a mountain, it will disappear. The same will happen to GPs. However, the units that have the mountain movement ability do just fine.

(2) LUA - Making Mountains Host Districts & Improvements

Buildings (Wonders) can already be placed directly on mountains using XML code. This part is very easy. You just need to include TERRAIN_MOUNTAIN_X among the terrains on which a specific wonder can be placed.

More recently, I've applied some of the WorldBuilder LUA functions to place districts and improvements on mountains. I recall someone on here making a mod that had a unique building - a neighbourhood - that could only be built on mountains. This is possible, although not especially elegant.

Because we can't directly intermix InScript and InContext (UI) LUA environments, there needs to be a trigger that the InScript LUA will recognize to effect the function. For my tests, I've used the placement of a feature (forest) or an improvement to trigger district and improvement placement on mountains.

Because features (forests) can be placed on mountains (after XML adjustments) without limitation, the easiest is the following process:

(1) a builder (or another unit created for the purpose -- District Builder) places a forest on a mountain;
(2) LUA detects this, and does the following:

(i) gets the Plot on which the new feature was placed;
(ii) momentarily replaces the Plot terrain with another terrain (e.g. hills);
(iii) (optionally--removes the forest from the Plot);
(iii) places the district on the Plot; and,
(iv) restores the mountain terrain on the Plot.
The district can be placed with any degree of completion (from 1% to 100%), and the city can then continue building the district. By default, the city would have to be manually made to continue building the district, but, AFAIK, there is also LUA code to place the new district into the city's build queue, so that's fixable.

Alternatively, the district can be placed complete, with the appropriate amount subtracted from the player's treasury. If the player's treasure does not contain enough gold, the process could be aborted, with no district placed. There may also be a way to force a UI notification to appear for the player, informing of the failure, by feeding a value to a separate LUA InContext (UI) file.

(3) another approach would be to have a builder place a special improvement (e.g. IMPROVEMENT_DISTRICT) next to a mountain plot, and the district would appear on the mountain using the same process. In case there are several mountain plots adjacent, a plot iterator function can be used to detect all of them and then place the district only on one of them. There is no way to have the player choose among several plots in the InScript context. UI would need to generate that value. However, the conditions can be restricted so that districts can only be placed on solitary mountains.

This approach avoids having to enable builders to move onto mountains. To make it more interesting, a special unit that costs as much as a district can be created, with one charge and able to build only one improvement -- IMPROVEMENT_DISTRICT_X -- and that improvement can restricted to plots next to a mountain.

(4) Improvements DO NOT require the additional step of converting a mountain into a hill and then back. WorldBuilder functions can place an improvement directly onto the mountain during the game. The very same approaches can be used -- triggering it with a forest on a mountain or with an improvement next to the mountain. So, that's a bit more elegant.

(5) Firaxis apparently anticipated things being placed on top of the mountains, and the graphics adapt accordingly. The mountain flattens (but not completely, it can still be seen underneath) and the graphic of the district or improvement is placed appropriately.
(3) Restricting Wonders to Coast Tiles

I've been trying (so far unsuccessfully) to find a way to create the condition for a particular wonder to require a coastal tile. This is apparently impossible using XML. However, XML can help us in combination with LUA.

I have not attempted, let alone tested this, but here is a possibility. The TutorialUIRoot.lua listens for the initialization of the Building Placement Interface Mode. If TutorialUIRoot can do this (and I've been able to replicate a lot of those methods in the InScript context), then this may be a possibility in LUA:

(1) detect the activation of the Building Placement Interface Mode;
(2) check whether the specified Wonder is being placed;
(3) if yes, then place invisible dummy resources on coastal water tiles of the city (only in plots where there is no resource already);
The rest of the process is done in XML. The Wonder is restricted to require an adjacent resource -- either any sea resource or the dummy resource. Ergo, the Wonder can only be placed on coastal tiles of that city.

Once the Wonder has been placed (a listener can check this), all the dummy resources can be removed.

Alternatively, a dummy resource can be placed on all coastal tiles of all player's cities upon that player reaching the prerequisite technology for the Wonder, provided the Wonder has not been built, and then removed after the Wonder is built.

In a further alternative, a dummy resource can be placed on all coastal tiles at the time the map is generated, after all the others features or resources have been placed. This would then act as a limiter for the Wonder placement.

Anyways, sorry for the block of text, but if anyone is interested in any of the above applications, let me know. Some of it I'll need to polish up first, and (3) I haven't tried yet, but I'll be happy to share.

GB
 
Last edited:
Top Bottom