how do trees avoid rivers?

davidlallen

Deity
Joined
Apr 28, 2008
Messages
4,743
Location
California
In my post-apocalyptic mod, there are city ruins which I have implemented as "features". Geomodder has been helping me out by creating a new nif file which has a better mixture of ruined buildings; see this post and around there in the thread.

In the screenshots, you can see that the ruined buildings appear right on top of rivers and roads. But, the forest feature is "smarter" somehow -- trees never appear on top of rivers or roads.

Does anybody know what part of the code arranges to have trees deleted when river or road appears there? We would like to clone / borrow this code for ruins as well.
 
Can you give me a little more information? For example, in vanilla BTS, with a bunch of rivers and forests, there are never any trees in the rivers. If this is done by the L-system, can you show me where? For example, is there something I could change to *remove* this behavior and have trees growing in rivers? This by itself is not useful, but if I am sure I understand how it works, then I can apply that to my ruins.
 
Hrm... I tried to look up more information for you and it seems that only improvements utilize the LSystem. Routes and Features are handled semi-seperately. Each entry in the LSystem has a field for "<Attribute Class="Scalar">bCutTrees:1</Attribute>" which would sure seem to be tied into the current issue, but I find nothing matching this in the DLL.

So I guess I am going to have to amend my assumption and instead state that it is controlled via "Resources/Themes/Civ4/Civ4Theme_Tree.thm"

Thus far I am very hazy on theme files at best, and I can barely tell enough about this one to convince myself that it IS for controlling forests. I cannot see just yet precisely how it is linked in to anything else to tell you how to manipulate attachment elsewhere. Best guess would be rename the file and load the game, see if you get an error. If so, hopefully it points you to the connection point. If not, load a game and see if you managed to break the ability of trees to be "smart" or not.

EDIT: Was curious so I toyed with changing this myself. No errors, and no change in tree behavior. So once again stumped.
 
Er, I *highly* doubt that the theme files are related to display of forests. I cannot tell offhand what the syntax in the theme file means. But, by the names of the other files in the themes directory, I believe that these have to do with nuts and bolts of gui elements like sliders and spinboxes. Inside Civ4Theme_Tree.thm, the only file reference is to Civ4/tree_icons.tga, which has inside it the little "+" and "-" icons you would use to open up levels of directory tree in a file explorer. I think that is the kind of tree it deals with, not the kind in a forest.

Are there any other types of files which might be related to not drawing trees on top of rivers?
 
Wacky partial guess based on no information: how about Assets/XML/Art/CIV4RiverModelInfos.xml giving a BorderFile like Assets/Art/Terrain/Routes/Rivers/xxx.dds. These dds files have a transparency layer which might correspond to the river course. Maybe forests get laid down first, and then rivers are selected. For each river which is selected, the related dds transparency layer is used to find where trees must be chopped.

Looking in BTS/CvGameCoreDll/*.h, I can see get/setBorderFile, but as far as I can tell it's never used for anything. I haven't spent much time (hardly any time) inside the SDK; but I can't find any trails to confirm or deny this theory. Anybody?

What I'm looking for is to have my feature nif file fill the square except for rivers and roads.
 
Yeah, I forgot to actually look at those icons first, and I figured it was a stretch when I peeked in there, but led myself on pretty well :)

Peeking at RiverModelInfos (and Route while I am at it), it seems to just be the definitions for the rivers themselves.

Maybe approaching from the opposite tack might prove useful? Find the NIFs for the forests and replace those with your Ruins, see where/what you have to modify to get them in by that method, and attempt to clone it at some point with a re-definition?


EDIT: This looks more promising:

Assets\XML\Terrain\CIV4FeatureInfos.xml - Contains pathways to the NIFs for the trees themselves. Refers to them as Symbols.

XML\Terrain\CIV4SymbolMeshPaths.xml - Contains entries for many things which would have to interact with other things. But I cannot seem to find the NIFs mentioned, even in the PAK.

EDIT2: Seems that Symbol was the key. It is still used to just mean "icon" as well in the DLL, but there are numerous locations where it is talking about features/routes/rivers and the map. Mostly in the CvDLLSymbolIFaceBase.h, but also in a few other CvDLL____.h files and in CvPlot.
 
Assets\XML\Terrain\CIV4FeatureInfos.xml - Contains pathways to the NIFs for the trees themselves. Refers to them as Symbols.

We got to this point in the original thread. For each feature, there are 15 nifs, which represent all the different combinations of corners: N, S, E, W, NS, NE, NW, SE, SW, EW, NSE, NSW, NEW, SEW, NSEW. There is going to be some code for figuring out which nif to use, based on which corners touch other plots of the same terrain. That is an interesting problem too, I'd like to make the new feature have rounded edges like forest does.

XML\Terrain\CIV4SymbolMeshPaths.xml - Contains entries for many things which would have to interact with other things. But I cannot seem to find the NIFs mentioned, even in the PAK.

This is a mystery. It is suspicious that there are 9 identical entries, for example for oasis or fallout. The index must be in some other place, maybe a C-level enum. Searching for "MeshPath" or "SymbolMesh" in the *.h, *.cpp doesn't find anything, so I don't know how to proceed on that.

EDIT2: Seems that Symbol was the key. It is still used to just mean "icon" as well in the DLL, but there are numerous locations where it is talking about features/routes/rivers and the map. Mostly in the CvDLLSymbolIFaceBase.h, but also in a few other CvDLL____.h files and in CvPlot.

Hm, I'll look into that tomorrow.
 
Well, CvPlot::updateRiverSymbol() is starting to look promising:

//force tree cuts for adjacent plots
[...]
ForceTreeOffsets(pAdjacentPlot->getX(), pAdjacentPlot->getY());

But then I stall again because ForceTreeOffsets isn't defined anywhere I can see. If ForceTreeOffsets only deals with trees and isn't programmable, we may be stuck. I'm not good enough with nif to create the 15 nif files needed to replace trees. If I could, or somebody could, maybe we could make the feature as a FeatureVariety of the trees?
 
Code:
gDLL->getEngineIFace()->ForceTreeOffsets(pAdjacentPlot->getX(), pAdjacentPlot->getY());

You left out the "gDLL->blah" part in your post above. I think, and an accual SDK elite can correct me if I'm wrong, that gDLL->getEngineIFace() is returning the exe object and calling ForceTreeOffsets from that.



And glad to see you are looking into the SDK davidlallen. I think you will be able to do alot of the stuff your asking about over the last few weeks, once you get the basics down. :goodjob:
 
You left out the "gDLL->blah" part in your post above. I think, and an accual SDK elite can correct me if I'm wrong, that gDLL->getEngineIFace() is returning the exe object and calling ForceTreeOffsets from that.

It is true that I trimmed out the bits which did not seem relevant. But the point is, I can't see any way to figure out what ForceTreeOffsets does or how to make it work on my new feature also.

And glad to see you are looking into the SDK davidlallen. I think you will be able to do alot of the stuff your asking about over the last few weeks, once you get the basics down. :goodjob:

Thanks for the encouragement. Note that I still have no interest in *compiling* the SDK, that is the hard part. Reading the code is easy.
 
Yeah, at that point it goes into the EXE and there is nothing which we can do. But if you expose that function call to python then you could play with applying it when YOU want to do so. See what happens when you apply it to some tiles with rivers and your new graphic (though I am reasonably certain that you NEED to have the NIF split up into multiple parts because it is actually placing numerous Forest NIFs to accomplish the look of each tile).


Other promising functions are the ones which call on updateRiverSymbol, most notably at the moment would be setNOfRiver & setWOfRiver. Both of those are called during ::doRiver, but that seems less useful than shortcutting straight to the functions to see what can happen.
 
This mystery function ForceTreeOffsets must make some decision about which features to modify. Evidently it modifies only the forest and jungle feature. Is that because it modifies all features which have the 15-nif variants? Or is there some flag which we can't spot immediately to tell it what to do? Or are the names "FOREST" and "JUNGLE" hardcoded into it?

We know from experimentation that a feature with a single nif (our city ruins feature) does not have this function applied, or at any rate it is not having any effect. So we see ruined buildings on top of the river. What we are trying to figure out is what we can do differently, so that ForceTreeOffsets will remove the buildings on top of the river. It would be some amount of work to create the 15 correct nif variants and make sure the game is using them right; so before trying that I'd like to know if that is enough.

Can anybody give us more insight into what is actually happening to remove the trees on top of rivers?
 
I believe its hard coded. Just as road and river intersections are hard coded (placing bridges, etc), and forests and jungles account for roads passing through them.

I would not assume that making 15 variations would account for either road placement or river placement.
 
It is definitely NOT hardcoded. I just went into my FeatureInfos and copied all the data for Forest into a second field, renamed it to Forest2 (different enough a program can't link them, even if minor) and bumped it up to provide 100 Commerce so I could tell the difference between them. End result was that it translated the forest into 3 different versions for me (Normal, Arctic and whatever the other thing is, looks also normal), and they still reacted properly to rivers and roads.

I would say it is worthwhile to get someone to cut up the NIFs you are using and try placing some in the position of the Jungle Nifs. Worst case scenario you completely replace Jungles and just do without them in the Post-Apocalyse, mildly appropriate anyway. Best case scenario, you see that it looks horrible and doing any further work is pointless ;) But maybe something will finally give us an error and point at a new location to investigate.

Could it be tied to the Tile Art Type?
 
Ok, so the 3 types of Forests appeared because of 3 cases of <FeatureVariety> setups.

The multiple NIFs are all listed in each Variety as Feature Art Pieces.

Deleting 2 of the 3 Varieties caused no Issue.

Deleting all but 1 of the Art Pieces resulted in a very small clump of trees in the middle of the tile which still reacted to road placement.

I changed out the TileArtType to be NONE, and on a lark I changed FfH's Ancient Forests to be defined as TREES in this field. End result: My new trees quit reacting to roads, and the Ancient forsts started doing so. It would appear your answer may be as simple as creating 15 (or however many you want to fill the tile) NIFs and calling them TileArtType TREES.



I am curious what the FeatureDummyNodes are used for....


Anyway, things are loaded via CvInfos.cpp: CvArtInfoFeature::read. Lots of very non-standard lines of code in here, so I am pretty sure this is where things get linked up in the EXE or wherever it is being handled.


EDIT: New test: I placed 15 copies of the same NIF for the Ancient Forests using the connection schemes from normal Forests to see how it looked in game. I am suspecting that it will fill in the tile more and react to roads/rivers properly, while not looking like an empty parkinglot. End result is what I wanted: The tile is filled with the trees, reacts to rivers, Mountains and Roads properly. So your answer is pure XML if you want it.
 
Awesome! It seems that you made two changes, and then the proper cutting happened. First, you used something which already had the 15 nifs. Second, you changed the TileArtType to TILE_ART_TYPE_TREES. I cannot experiment for another 6 hours or so; but what happens if you apply TILE_ART_TYPE_TREES to something which does not have 15 nifs? These are two separable aspects of display. I'd *like* to have 15 good nifs, but I don't. So if the tree cutting happens for anything with TILE_ART_TYPE_TREES, then I can get by with one nif.

There is a specific nif to try, if you want, in the original thread which spawned this. All the files should be there in the rar. Does your magic work on that?
 
The 15 NIFs isn't so much to use seperate NIFs, I used the same one for everything. It is for the Connection types. Not having those means your NIF will only be placed dead center in the tile. Having all 15 means you will fill the entire tile if allowed to do so.

So all that you NEED is to define TILE_ART_TYPE_TREES, but that gives you a boring, nearly empty tile with just a single non-connected NIF. Make it that same NIF with 15 Connections (might get away with fewer, haven't tested that) and you get a much nicer effect (and if the tile has no road/river, it looks just like it would the normal way)

EDIT: Tried it out real quickly, and having all 15 fields with that NIF caused my system to slow down considerably, and they were appearing beneath my terrain. So just subbing them in for the Forests I was using doesn't work so well :)

I did try things out again with a single NIF definition this time, and it seems that just listing <Connections>NW NE SE SW</Connections> fills the tile nicely enough, so no need for a full 15 NIFs. I kinda figured as much, but wanted to change as little as possible in initial tests :)

Mildly curious why Ice defines 3 NIFs per connection type. A tad bizzare.
 
Great find Xienwolf (and very good news on the ancient forests as well)!
 
Ewww... I take back my comment about just using NW NE SW SE and being covered. It splashes the feature out along the neighbor tiles. when you do that (did it with Scrubs and it was very obviously just 4 copies of the same NIF centered on each corner)


Now that I am looking at individual tiles instead of huge chunks it seems even with the full 15 entries (and a 16th with no connections listed) it is doing the same thing. So need a smaller NIF file. But I really want to know why a normal forest doesn't overflow the tile the same way....

Seems like using no connections listed on Scrubs resulted in the same 4 way duplication of the original NIF on a blank tile.


Oh, and there are 3 NIFs listed per entry on Ice because it uses Half_tilting instead of Trees. The options for the field are:

TILE_ART_TYPE_NONE = -1,
TILE_ART_TYPE_TREES,
TILE_ART_TYPE_HALF_TILING,
TILE_ART_TYPE_PLOT_TILING,
NUM_TILE_ART_TYPES


I would suspect the reason the Forests remain in the tile is that each of those 15 NIFs are set up to work only in the appropriate corner to keep it in the tile. So if you cut your city Nif into 4 pieces, place each of them off-center, and assign the proper connections, you should be good.


No luck on figuring out what the bGenerateRotations field does.

FeatureDummy node holds a Tag and a Name, and nothing in plain BtS uses it.... maybe a Final Frontier thing? Yup, used for Orbit rings in Final Frontier. Might be nifty for the Ring of Carcer in FfH, but not going to get into playing with those just yet. Need to do some work again at actual "they pay me" work. ;)
 
Back
Top Bottom