Hmm, that's an interesting idea. The two thoughts that jump to the front of my mind are, "that would be a distraction from progressing on the game" and "that would be a way to make it more immediately useful to a wider audience". Assuming I'm interpreting the idea as you meant it, in both cases.
Which, in terms of my understanding, is the CivAssist Mode would be used for the
existing Conquests, as last updated to 1.22 in 2004, not for assisting with any future C7 games (well, at least, not in 2021, maybe in the future). And displaying individual FLC frames would be a purpose-specific utility.
I suppose it comes down to if it's an easy thing to do and there's motivation for it, and a fairly certain audience (e.g. the type of "I'd really like this CAII thing but CAII doesn't work for me on Win10" message I've received occasionally over the years), why not? But we don't want to spend so much time on it that a year from now we look at the project and find, "it's a nice replacement for 2/3 of the functionality of CAII, and works well on Windows 10, but there's no gameplay yet." At least, not with our current goals. If we've got some gameplay but it's not ready for prime time, but there's also a couple dozen people using it because it replaces the most critical 25% of CAII, that could be a net benefit.
-----------
I never did fully figure out which overlay goes where. I got kinda close for mountains, but there's about 10% of the time that the game uses a different one than my editor. With forests and jungles, I gave up after spending far too much time on that and realizing it really wasn't
that important in an editor, compared to all the other things that could be worked on.
If the goal is just a proof of concept for layered tile maps or drawing overlays, I'd probably go with mines or something that will be consistent tile to tile.
But if you prefer mountain, here's my code from the editor for figuring out which mountain to draw. It always chooses the most "logical" one based on which sides of the mountains border other mountains, and thus should have elevated terrain; as mentioned, sometimes Civ doesn't choose the most "logical" one, but most of the time it does.
It returns an index into the art file, and as you can see, evaluates all the directly neighboring tiles. The null checks are in case the tile being evaluated is at the edge of a map.
Code:
private int getMountainIndex(int xIndex, int yIndex) {
//TODO: This can probably be combined with getIrrigationIndex with the help of functional operations
int mtnIndex = 0;
//check for nulls first.
//This would be nice and easy with Groovy's nullsafe dot operator
//Unfortunately Civ seems to only use this as an occasionally way to do things
//At first it appeared Snow Mtns didn't count hills as neighbors, but that didn't solve it either
//Annoying Mountains.biq illustrates the madness of deciding which mtn is which
TILE center = getTile(xIndex, yIndex);
TILE northEast = center.neighbor(MapDirection.NORTHEAST);
TILE southEast = center.neighbor(MapDirection.SOUTHEAST);
TILE southWest = center.neighbor(MapDirection.SOUTHWEST);
TILE northWest = center.neighbor(MapDirection.NORTHWEST);
if (northEast == null)
;
else if(northEast.getRealTerrain() == TERR.MOUNTAIN || northEast.getRealTerrain() == TERR.HILLS || northEast.getRealTerrain() == TERR.VOLCANO)
mtnIndex+=2; //Northeast
if (southWest == null)
;
else if(southWest.getRealTerrain() == TERR.MOUNTAIN || southWest.getRealTerrain() == TERR.HILLS || southWest.getRealTerrain() == TERR.VOLCANO)
mtnIndex+=4; //Southwest
if (southEast == null)
;
else if(southEast.getRealTerrain() == TERR.MOUNTAIN || southEast.getRealTerrain() == TERR.HILLS || southEast.getRealTerrain() == TERR.VOLCANO)
mtnIndex+=8;
if (northWest == null)
;
else if(northWest.getRealTerrain() == TERR.MOUNTAIN || northWest.getRealTerrain() == TERR.HILLS || northWest.getRealTerrain() == TERR.VOLCANO)
mtnIndex++;
return mtnIndex;
}
This integer is then used in my drawHillyTerrain method. I do not suggest following the same approach of bitmapping the graphics now that we have nodes and an actual game engine, just including it for context. Although it does remind us that the hills and mountains both have greater height than the base terrain, so that has to be accounted for.
Code:
private void drawHillyTerrain(TILE tile, int defaultXPosition, int defaultYPosition, Graphics canvas) {
final int HILLS_Y_POS = defaultYPosition - 12;
final int MOUNTAINS_Y_POS = defaultYPosition - 24;
if (tile.getRealTerrain() == TERR.MOUNTAIN || tile.getRealTerrain() == TERR.HILLS || tile.getRealTerrain() == TERR.VOLCANO) {
int graphicsIndex = getMountainIndex(tile.xPos, tile.yPos); // THIS LINE CALLS THE METHOD QUOTED ABOVE. <---------------------- LOOK HERE
int forestJungleCheck = useForestOrJungleHillVariant(tile);
if (tile.getRealTerrain() == TERR.HILLS) {
if (tile.isLandmark()) {
canvas.drawImage(assets.lmHillGraphics[graphicsIndex], defaultXPosition, HILLS_Y_POS, null);
}
else {
if (forestJungleCheck == TERR.FOREST) {
canvas.drawImage(assets.forestHillGraphics[graphicsIndex], defaultXPosition, HILLS_Y_POS, null);
}
else if (forestJungleCheck == TERR.JUNGLE) {
canvas.drawImage(assets.jungleHillGraphics[graphicsIndex], defaultXPosition, HILLS_Y_POS, null);
}
else {
canvas.drawImage(assets.hillGraphics[graphicsIndex], defaultXPosition, HILLS_Y_POS, null);
}
}
}
As for what e.g. forestHillGraphics looks like, the PCX is chopped up into an array with this method:
Code:
private BufferedImage[] importGraphics(String fileName, int xDim, int yDim, int heightEach, int heightOffset)
{
String mtnName = null;
try{
mtnName = utils.findFile(fileName, "Art" + fileSlash + "Terrain" + fileSlash, biq);
}
catch(FileNotFoundException e){
logger.error("Could not find " + fileName + "; civInstallDir = " + settings.civInstallDir, e);
JOptionPane.showMessageDialog(null, "Could not find " + fileName + ". The civ install dir (" + settings.civInstallDir + ") being incorrect may cause this problem. This can be changed by clicking on the Settings button.\nError: " + e.getMessage());
return null;
}
Civ3PCXFilter mtns = new Civ3PCXFilter(mtnName);
mtns.readFile();
mtns.parse();
mtns.createBufferedImage();
BufferedImage[]mountainGraphics = new BufferedImage[xDim * yDim];
//j is rows of PCX files
for (int j = 0; j < 4; j++)
{
//k is columns of PCX files
for (int k = 0; k < 4; k++)
{
mountainGraphics[j*4 + k] = mtns.getBufferedImage().getSubimage(k*128, j*heightEach + heightOffset, 128, heightEach);
}
}
return mountainGraphics;
}
So for example (the unused last parameter defaulting to zero)
Code:
BufferedImage[]jungleHillGraphics = importGraphics("hill jungle.pcx", 4, 4, 72);
I haven't looked at the map code in enough detail to know how you've been dividing up those graphics yet, but since that's working you probably already have a good solution in that area.