Tuesday, January 17, 2017

Positive Progress

In keeping with the positive spirit of progress, here are a few more things I've accomplished on my RPG lately:

1) I think I've filled out one of my character's skill lists - with a full window of 16 skills - which is a big (albeit early) step toward conceptual completion (and it's pushing me toward completing the other characters' skill lists). I've also pulled off a neat little trick in the course of implementing some of those skills - using states, and a plugin to change the default Attack command that appears in battle. I'm aiming for some amount of variety across the seven playable characters in my game - I don't want them all to feel the same. I haven't worked out all the details yet - because they're narrative characters (like in FFIV) and not figureheads (like in FFI) - but I'm hoping to give the player some choice in the ultimate lineup of their final team.

This particular character is an archer, and I don't want to spoil all the surprises, but her fighting style is heavily influenced by the Ranger profession in Guild Wars. I've successfully implemented a couple of "stances", and a few "preparations" (e.g., poison arrow, fire arrow). Instead of one-off special attacks, these are technically states that can be applied to temporarily modify this character's regular attack for a limited number of turns. It's a fun way to fight, and it gives her a unique playing style that hasn't been duplicated by any other characters in my game so far.

2) As irreversibly enmeshed into the MV iteration of RPG Maker as I am now, I could still rant at length about the things that irritate me about it, mostly tied to its dedication to mobile gaming - which requires streaming resources, and often results in sloppy gameplay, with the tradeoff of having to live with either a lot of jerkiness or loading screens. Thankfully, the Preload Manager + WebAudioCache combination of plugins has solved (to an acceptable extent) the BGM Delay issue I was having; although there is still no (and will probably never be) a solution to the not-so-"instantaneous" map transfer delay problem that's been particularly hounding progress on my other game, Ascension.

But I was becoming frustrated with even the regular screen fade transitions, when I loaded up VX Ace, and having used MV exclusively for a long time, the consistency and reliability of the smooth transitions in the older program absolutely amazed me. After some testing, I discovered that out of the box, MV's post-transition screen fadeins are often jerky, while using the Preload Manager (which is mandatory for syncing the BGMs in your game) causes the transition to pause a little bit between maps while the game does its loady thing. But what's annoying is that the game doesn't actually pause, it just hangs for about half a second, and then, as if trying to catch up, completely skips the fadein more often than not.

Perhaps a casual player wouldn't even notice it, but as a developer and lead tester, it began to drive me crazy. Is it too much to ask for a program that doesn't look buggy when you play it? Anyway, I found a workaround, even if it meant redoing all the map transfers in my game. In case you're interested, all you have to do is give up on the fade that's built in to the Map Transfer event command. Use a manual Fadeout before the transfer, and a Fadein after, but stick a 30 frame Wait command between the transfer and the Fadein to give the game time to catch up, before it moves on to the fade. Give it a try. The result is consistent and reliable fades. As somebody with OCD, it makes me much happier.

3) In my game, I have two skills planned that are based on the Warp and Exit spells from the first Final Fantasy. The difference between them is that Warp will send you back one floor, while Exit will send you all the way to the start of the dungeon you're in. They're good "quick escape" skills, also useful as a way to transport the player out of a dungeon once it's completed, without having to backtrack all the way to the entrance, and in lieu of thematically-appropriate dungeon-end teleports (as encountered in some dungeons in Final Fantasy). And, in the spirit of Dragon Quest's inclusion of skills that are useful outside of battle, I also want them available as shortcuts for use in towns and potentially on the World Map as well.

The Exit skill was easy enough to implement, by storing map and location info in variables every time the player enters (or exits) a town or dungeon. The Warp skill was a little trickier, however, as it needs to trigger on each floor, and I also want the player to be able to "stack" warps to travel multiple floors (if they have the resource points) - so the game needs to remember where the player has been and in what order. And rather than allocating a specific number of variables, I figured it would be more versatile to resort to storing an array inside a game variable, like I did in the course of implementing my Wardrobe Manager - although it involves more trial and error since I have to access the contents of the variable using script calls. But it's working!

4) On the subject of clever implementations involving skills useful outside of battle (although these ones are directly related to battle), I've just completed another challenge. One of the foundational skills in my game is a skill called Hunt, which gives the player the ability to force a random encounter (provided one is possible on whatever tile the player is standing on). This may not sound like the funnest skill, but I intend for it to dovetail with my game's encounter system - I'm just not sure exactly how...yet. In any case, it can be used to save the ambitious player time and embarrassment walking around in circles, should they want to fight enemies to boost their characters' levels, or collect special item drops.

Anyway, I have a couple of other skills planned that are in that family, one of which is directly inspired by the Repel skill from Dragon Quest, which reduces the random encounter rate (in that game, primarily to avoid wasting time fighting enemies below your level). But the one I'm most excited about is the one I've just programmed, which is a "Bait" skill. In many Final Fantasys, there are certain rare enemy encounters - especially in late-game dungeons - that promise valuable rewards for the persistent adventurer. The prestige awarded by these encounters (going all the way back to WarMech, if not earlier) makes them alluring, but I've never been fond of having to play the odds.

To wit, the best player could walk up and down the bridge in Sky Castle, battle 60 troops of enemies, and not encounter WarMech once, all on account of bad luck. This might be justifiable in a multiplayer online game, where you have a sort of players' economy, but at a certain point you have to just throw your hands up and say, "come on, already!" That's why, although I think these encounters should still be earned (which is why the Bait skill will be a late-game acquisition), I think there should be a point where the game says, "ok, you've earned this." And that's where Bait comes in.

Bait works just like Hunt - by forcefully initiating a random encounter - but not before performing a tricky bit of code math. I already had to add in some new functions related to the game's back-end encounter variables for the Hunt skill, in order to determine when the Hunt skill should be able to be used. But for Bait, I went even further, by taking the list of applicable encounters on any given tile (as determined by the developer on the map properties) and reversing the probability "weights" of each troop, so that when you initiate the next encounter, the common enemies will become rare, and the rare enemies will become common. You'll have to excuse me if I think that's just brilliant! And it works! Hey, I'm pretty excited.

(Now, if I could just pick up the slack in the mapping department...)

Monday, January 2, 2017

On The Bright Side

You'll be pleased to hear that one of my New Year's resolutions is to get back into working on my RPG in earnest. I've been thinking about it a lot. The details of the final dungeon are beginning to form more clearly in my head (which is not to say that everything leading up to it is finished :-p), and it's one of the many things about my game that I'm very excited about. I've been studying some of the more sinister dungeons from Final Fantasy IV - namely the Towers of Zot and Bab-il - for inspiration (I love that the Tower of Bab-il is so tall, that not only does it connect the Underworld to the Overworld, but it actually consists of two major dungeons in the game - one going up from the bottom, and another coming down from the top!). FFVI may be my favorite Final Fantasy, but I've been drawing a lot of inspiration for my RPG from the games that preceded it; especially the first one (because it's always good to start with the basics), and the fourth - which has an appealing balance of simple mechanics and a good, dramatic storyline.

You know, when I started working with RPG Maker, I had thought that more people would be using the program as I assume it was primarily intended - to create Dragon Quest/Final Fantasy-style classic RPGs. I love those old games, and I regret that technology has pushed us forward into the 3-D, polygonal, massively multiplayer paradigm of modern RPGs. I'd rather Square release another SNES-era Final Fantasy - with a new story and characters (not one of those lame-o 3-D portable sequels) - than give us more of the innovation we've been getting since FFVII and onward, that increasingly pushes us away from that classic gameplay style. Now, if Square won't do it, I'd take an amateur substitution. Enter RPG Maker. But it seems to me that most serious developers (i.e., the ones who actually complete their games, and are any good) are interested in using the engine to develop unique gaming experiences (often not even in the RPG format, and with an original graphical style). I mean, in terms of creating original content, and building your brand and reputation as a game designer, this is the way to go. But what I really want to see is a fan community like, say, the one Doom has, which spends its time creating new content entirely in the style of the classics, for all the fans who liked the game just the way it was way back when, but would love to have new things to experience within that realm.

Ah well. If I ever finish my RPG (and I do hope I will), I'll be contributing to that at least. It's easy to get daunted by the task of single-handedly putting together a classic 2-D RPG, not to mention surmounting the many obstacles RPG Maker MV insists on throwing one's way. But I was surprised to remind myself of some of the things I've already accomplished. The Wardrobe Manager is pretty much complete, and working entirely as intended. It's a mainly superficial mod to the game - the ability to give your characters alternate outfits - but one that is nevertheless very important to me, because I think dressing your character up in alternate outfits (and picking the one you like best) is a lot of fun. I was having problems implementing it in VX Ace, if you recall, but I found a plugin for MV that basically single-handedly makes it possible, by using "placeholder" graphics that are replaced on the fly. It's ingenious! Of course, I still had to do a lot of work to get the manager running - including the clever usage of an in-game variable as a multidimensional array (accessed exclusively via script calls). But it's running!

I've done a little coding, too. Nothing on the level of last spring's Peep skill (which was a landmark for me), but in lieu of waiting for a plugin to be ported from VX Ace to MV, I found a far more complex alternative and reverse-engineered it to do just the thing I wanted it to do (which is allow for a conditional check before using items - so that, for example, the game won't let you use a Tent when you're not on the overworld map, or other designated spaces). I've also just completed a new modification to the encounter system, partially inspired by the Repel skill in the original Dragon Quest, which causes the random encounter rate to gradually reduce to zero as your characters level up to a point beyond the local average (determined by my usage of Region ID) - so that you're not constantly being hounded by weaklings (e.g., level 1 Slimes) that aren't even worth spending the time to squash under your boot. I'm still not 100% decided on all the details of how I want the encounter system in my game to run, but having this capability puts me one step closer to figuring it all out. :-)

Thursday, December 15, 2016

Modular Programming

Modular programming is like taking an algorithm, shattering it into a thousand pieces, and then burying each piece in a different location. Maybe it's more efficient. Maybe it's more versatile. I don't know. I imagine that it would make it harder for a hacker to copy/steal the code. But in RPG Maker's case, the user is intended to go in and fiddle with the code to make the program do what the user needs it to do, and this modular programming approach makes it extremely difficult to figure out how anything works. It's like a million tiny functions that look so simple, you can't imagine them accomplishing anything; but you know that together, somehow, they power a complex and robust program. But good luck finding the handful of grains in that sandbox that perform the behavior you wish to modify...

Sunday, May 8, 2016

Dragonfaith (MV) Alpha 2.0 - Greendale



My last release for Dragonfaith on RPG Maker MV contained little more than the prologue - which isn't much, but you gotta start somewhere. This release adds in the first town, which is fully explorable. I've renamed it "Greendale Village" in honor of my favorite album from one of my favorite bands, to give it a little more personality. The first town in my RPG is thematically inspired by many classic video games whose first stages are green, grassy stages (Super Mario Bros. 3 is one of the more prominent and memorable examples). The idea is to start the game off somewhere calm and unthreatening, before throwing the player into progressively more intimidating locales (e.g., forest, cave, mountain, desert, volcano, tundra). Greendale also represents the protagonist's hometown - a gentle, welcoming village to fight for and dream of returning to later on - and subtly introduces the player to a prominent theme of the game - the importance of nature and the conflict between living with it, and becoming victim to it. So, go ahead and explore!

I actually have a bit more of the game done already, but as I think I've explained before, getting the combat working is putting a hold on me releasing that just yet. I think I'm going to eventually have to just live with releasing parts of this game in a more and less unfinished capacity, just to get things moving along, because I'm not going to be able to fit all the pieces together neatly like a puzzle until I have the whole thing from start to finish at least storyboarded and constructed in some kind of outline format. I tell you, my OCD and perfectionism is wreaking havoc with my productivity on this project, but I'm trudging forward, however slowly at times. If you have the time and the inclination to check out this latest release, as always, let me know your impressions, if there are any bugs, and any comments or suggestions you might have. It's a work in progress, and there's always room for improvement.

Dragonfaith (MV) Alpha 2.0
Download (~130 MB): Windows | Mac

Sunday, April 3, 2016

Dragonfaith (MV) Alpha 1.0 - Prologue

Here is my first release of Dragonfaith for RPG Maker MV. To temper your expectations, it's pretty much just the prologue. But we gotta start somewhere, right? I actually have a bunch more stuff done already, but it's not presentable just yet. Actually, I'm finding that the limitations of the combat (which is one aspect I'm having considerable trouble with, given that the default numbers are so out of wack, and there's so much to account for that I'm not sure I'll even have a clear plan of attack until the skeleton of the game has been put together) is keeping me from putting more of the game together for release.

I just don't know how much sense it makes to give you demos of an increasingly greater portion of the game before I've added any real combat in. You'll already be bored of the locations and the story by the time I need you to test the combat balance, which is an important (and conceivably tedious) aspect of the testing process. On the other hand, it could be years (I don't want it to take that long, but I'm trying to be realistic here) before I even get some semblance of the combat working, assuming I devote my time and effort to the other stuff I feel needs to be in place first, and I'd really hate to go that long without showing you any of what I do accomplish (you'd be forgiven for thinking I've given up on the game, although that most certainly is not the case).

I'll either have to think of a non-standard way of showcasing those aspects of the game, or else just suck it up and live with the idea of releasing it in a very non-polished format (which is bound to drive my OCD and perfectionism bonkers, although we are dealing with early alphas here (as sad as it is to call them "early" given that the game has already been in development for two years - although that has everything to do with having to upgrade it to the newest version of RPG Maker released just at the end of last year)).

Anyhow, without further ado, here is the first release of Dragonfaith for RPG Maker MV:

Dragonfaith (MV) Alpha 1.0
Download (~130 MB): [check sidebar for newest release]

Friday, March 4, 2016

My First Serious Plugin - Peep Skill (MV)

(Download at bottom of post).

I'm happy to report that I've pretty much gotten the hang of scripting in RPG Maker MV. Doesn't mean that any problem that crops up will be easy to solve, or that I will be able to solve any and all problems I encounter (especially the more complex ones, although the fact that there is a nice community of even better scripters than I working on commonly desired features helps a lot), but it means my abilities to get what I want out of this program (and my confidence in being able to do so) are stronger than ever.

I'm fairly confident coding in JavaScript by now - which isn't to say that I know the language back and forth, but I know the basic syntax, and figuring out how to do specific things is as easy as typing a question into Google and surveying the answers. The hardest part remains diving into the - as I said - tens of thousands of lines of code that make up RPG Maker MV, and a) finding the code you need to modify to get the results you want and/or b) trying to understand not so much the JavaScript, but how the actual program RPG Maker has been designed to function.

On the other hand, I haven't had this much of an opportunity to program since I finished my schooling (the barrier of learning a foreign language is surprisingly intimidating, even if most of the logic behind computer programming is the same no matter what language you're using), and I had forgotten just how much fun it is to code (barring all those frustrating times that your code fails, and you assume you've screwed up the logic, when it so frequently ends up being nothing more than a parenthesis or a semicolon out of place). It's the thrill of problem-solving. Some people like to fix things with their hands. Computer programming is the same, except you're using your mind - and that's always been my strongest tool.

So over a couple of weeks I pretty much absorbed myself into programming, and worked out a nice little plugin that I'd like to offer up to the community. It started out with me trying to figure out how to create an enemy that mirrors the player's stats, no matter what they happen to be when the battle is initiated. I couldn't find a way to preload those stats into the enemy's properties in the database, so I opted to run an event at the start of the battle that reads the player's current stats and then feeds them into the enemy (to do this, I made all the enemy's base stats 1, and then added the player's stats minus 1 on top of them).

It was an adequate solution, but in the process of working on it, I wanted to have a nice way to read the enemy's stats in-game to make sure they were what I wanted (and expected) them to be. So I embarked on creating something of a skill akin to the Peep command in Final Fantasy IV (since, to my knowledge, RPG Maker comes with nothing like it by default). It's probably come up in other places (although that's the first one that came to my mind), but basically it's a skill you can use in battle to investigate an enemy's stats (HP, MP, etc.) as well as its strengths and weaknesses (e.g., strong against fire, weak against poison, immune to sleep).

So this plugin started out very basic and functional, but as I went along, I realized how well it presented itself to user customization, and I decided to use it as an opportunity to learn a lot of valuable techniques in scripting for MV - like proper aliasing, utilization of plugin parameters, as well as plugin commands (although I finally opted for notetag functionality over plugin commands, in order to bypass the extraneous step of having to call a common event). It started out as pretty much one big function that did everything I needed it to do, but then I decided to split it up and write it in the format of the rest of RPG Maker's code, which is very modular and method-based.

The end result is a fair-sized monster of a thing (by my standards, that is - it's tiny next to some of those professional-level plugins you can find). And even though I still consider myself to be a beginner - or beginner-intermediate, at best - scripter, it's something I'm pretty proud of. I can't claim that it will be compatible with any and all other plugins, but I don't anticipate it having any significant problems (most of it is contained within a brand new class that I've written). So, if you get a chance to try it out, please tell me how you like it, and if there are any bugs you encounter.

My plugin in action.

Now, let me briefly describe what my Peep Skill plugin can do. (The plugin itself is fully annotated, so you should be able to figure out how to work it just by reading the description at the top of the file, or through RPG Maker's Plugin Manager). After the plugin is installed, all you gotta do to use it is type <peep> alone or with arguments (see the file for details) in the note box of the skill or item that you want to execute the peep skill when used in battle. When you use it, if successful, it will display on screen a list of the target enemy's properties. You can fully customize which properties are displayed and in what order, choosing from the following options:

Enemy's Name
Current and Max HP and MP
Basic Parameters (Attack, Defense, Magic Attack, Magic Defense, Agility, Luck)
Current States applied (e.g., sleep, poison, mute)
Current Buffs (attack up, agility down, etc.)
Elemental and State strengths, weaknesses, and immunities (all according to the enemy's traits listed in the Database)
Enemy's worth in both experience and gold
Potential drops (with probabilities)

As I said, you can choose any or all of these to be displayed, and you can even format them by adding in blank lines. The plugin is designed to wrap lines that exceed the length of the text box (you have to input the max character limit if you're not using the default font and size). And all of the text prefixes and terminology is modifiable. Plus, you can add the tag <peep:no> to the note box of any enemies that you don't want the player to be able to read the stats of, and even customize the failure message that is displayed! All in all, I'd like to think it's a pretty robust plugin. It does have a few limitations (it only works on enemies, and not actors; it only works on one enemy at a time; and it only works in battle), but hopefully it will be useful for whatever your specific purposes are!

Download: Peep Skill Plugin (for use with RPG Maker MV)

Tuesday, February 16, 2016

Plugin: Terrain Battle Backs (MV)

The struggle to adapt my game to the latest version of RPG Maker continues, in spite of the frustrating limitations of developing a game inspired by classics that were designed for the desktop on a mobile platform.

You might remember my efforts at customizing the battle backgrounds automatically chosen based on terrain type on designated world maps in VX Ace, which I detailed in this post from two years ago (egads, has it really been that long?). That there isn't a built-in, user-friendly way to adjust these choices is one of those things in RPG Maker that amazes me.

Previously, I had opted to run a Parallel Process event on the world map to constantly check the tile ID (and thus, type of terrain) of the spot the player was standing on at any given time, in order to manually override the choice of battle background. It's a testament to how much has changed in the past couple of years that my first instinct this time around was to try and develop a scripted solution that modifies the way the backend code functions, instead.

So, I opened up the hood and jumped into the code. As a potentially relevant side note, MV is programmed in JavaScript. Trying to make sense of the tens of thousands of lines of code - and, particularly, trying to find the parts that do the stuff you want to modify - is no easy task. But I was able to track down the very function(s) that determine which battle background goes with which type of terrain. They are located (for reference) in rpg_sprites.js on lines 2530-2572. I'll copy them here:
Spriteset_Battle.prototype.terrainBattleback1Name = function(type) {
    switch (type) {
    case 24: case 25:
        return 'Wasteland';
    case 26: case 27:
        return 'DirtField';
    case 32: case 33:
        return 'Desert';
    case 34:
        return 'Lava1';
    case 35:
        return 'Lava2';
    case 40: case 41:
        return 'Snowfield';
    case 42:
        return 'Clouds';
    case 4: case 5:
        return 'PoisonSwamp';
    default:
        return null;
    }
};

Spriteset_Battle.prototype.terrainBattleback2Name = function(type) {
    switch (type) {
    case 20: case 21:
        return 'Forest';
    case 22: case 30: case 38:
        return 'Cliff';
    case 24: case 25: case 26: case 27:
        return 'Wasteland';
    case 32: case 33:
        return 'Desert';
    case 34: case 35:
        return 'Lava';
    case 40: case 41:
        return 'Snowfield';
    case 42:
        return 'Clouds';
    case 4: case 5:
        return 'PoisonSwamp';
    }
};
If you're not familiar with switch statements, they're basically extended conditionals, which check the value of a variable - each "case" basically tells the program "if this, then do that". The first thing you should note is that there are in fact two separate functions, corresponding to the two parts of the battle background - the bottom or ground section, and the top or wall section. This should be familiar to you if you've ever worked with the battle backgrounds, or looked at the associated image files that are named in these functions.

Another thing you might notice is the numbers that are being dealt with here. The function takes an argument (named "type") that, as you might guess, corresponds to the terrain-dependent tile ID, which is then evaluated in the switch statement. What's interesting is that these numbers are much smaller than the unwieldy tile IDs we dealt with before, which ran the gamut from 2048-4350. There's a rather obvious reason for this, that I must admit I discovered in an embarrassingly roundabout fashion. Those larger numbers are still relevant, as by using the Get Location Info event command, you'll find in-game that they haven't changed from VX Ace to MV. But for coding purposes, a little bit of math has been performed to make them more palatable. You can find that calculation in another function located on lines 5912-5915 of rpg_objects.js:
Game_Map.prototype.autotileType = function(x, y, z) {
    var tileId = this.tileId(x, y, z);
    return tileId >= 2048 ? Math.floor((tileId - 2048) / 48) : -1;
};
Basically, what this function does is take the tile ID corresponding to a location on the map determined by the x, y, and z (or layer level) coordinates, passed into the function as arguments. It then subtracts 2048 (since, I don't know why, but the IDs start at - and are thus offset by - a base value of 2048), and divides that number by 48. This makes sense because if you take the time to scrutinize, as I have, you'll find that there is a space of 48 numbers between each different type of terrain. These correspond to the various orientations of autotile placement which I have annotated in detail in my previous post for VX Ace.

But since choosing a battle background doesn't depend on whether you're standing on a "border" tile or a "center" tile (or what have you), you can essentially boil each set of 48 IDs down to a single terrain-dependent index. Which is exactly what the above calculation is doing (note also that if the tile ID doesn't fall into the expected range, the function returns a -1 instead, presumably for fallback purposes). Now, the thing that made me feel stupid for not realizing it sooner was the fact that, after you perform the calculation, what you're left with is nothing more than the placement index (starting at 0) of the tiles as they appear in the editor for the World_A tileset!

To illustrate, where we had this before:


We now have something much simpler (and more predictable!):


I'm not sure if this had crossed my mind before, but the indices (and the tile IDs they correspond to) are all unique. Meaning that, although they're stacked on either of two separate layers - so that a given tile can have both a Layer 1 ID and a Layer 2 ID - the numbers on either layer never overlap. So if you give me a number, I can tell you exactly what type of terrain it corresponds to without knowing whether it's a Layer 1 or a Layer 2 ID. Which, it turns out, is exactly what the functions with the long switch statements that I copied above are doing. So then, you might ask, are those functions evaluating Layer 1 or Layer 2 IDs? And how is that determined? Exploring the functions that call those two functions will answer those questions. You can find them in rpg_sprites.js at lines 2518-2528. Here they are:
Spriteset_Battle.prototype.normalBattleback1Name = function() {
    return (this.terrainBattleback1Name(this.autotileType(1)) ||
            this.terrainBattleback1Name(this.autotileType(0)) ||
            this.defaultBattleback1Name());
};

Spriteset_Battle.prototype.normalBattleback2Name = function() {
    return (this.terrainBattleback2Name(this.autotileType(1)) ||
            this.terrainBattleback2Name(this.autotileType(0)) ||
            this.defaultBattleback2Name());
};
As well as I can figure, these functions run when the game is trying to load a battle and determine which battle background to use. Again, you'll note that there are two separate functions, one for each half of the battle background. They each do essentially the same thing, however, which is to call the long switch functions we've already seen (hereafter referred to as "the terrainName function(s)") to determine which battle background to use based on the terrain corresponding to the index evaluated via the autotileType function (the one with the math that we examined above).

If you're paying attention, you'll note that here the function only takes a single argument, whereas before it took three. This is confusing, but the explanation for it is quite simple. The previous autotileType function belonged to the Game_Map class. But here, we're dealing with the Spriteset_Battle class, which has defined its own autotileType function. But before you throw your arms up in frustration, this local version of the function is nothing more than a shortcut to that other version, but with the x and y arguments already predetermined to be the player's x and y map coordinates. You can examine the function yourself. It is located in rpg_sprites.js at lines 2590-2592, which I will reproduce here:
Spriteset_Battle.prototype.autotileType = function(z) {
    return $gameMap.autotileType($gamePlayer.x, $gamePlayer.y, z);
};
So, returning to the normalBattlebackName functions (hereafter referred to as "the normalName function(s)"), when they call the terrainName functions, they're passing in an index corresponding to a tile ID at either the first or second layer, depending on whether the autotileType function is being passed a 0 or a 1 (note that since counters in programming usually start at 0, the 0 corresponds to Layer 1, and the 1 corresponds to Layer 2 - try not to get confused). There's something a little weird going on here, though, because each normalName function is trying to return the value of a call to the corresponding terrainName function (which would be the name of the battle background file associated with the given terrain), but it's tangled up in an OR operator ("||"). Let's take a closer look:
return (this.terrainBattleback1or2Name(this.autotileType(1)) ||
            this.terrainBattleback1or2Name(this.autotileType(0)) ||
            this.defaultBattleback1or2Name());
It took me a while to get a firm grasp on what exactly is going on here, even though it's largely intuitive. (Sometimes explicit instructions are helpful). For a detailed explanation of the behavior of JavaScript's OR operator, read this. Suffice to say, the operator responds not just to true/false evaluations, but also to the wishy-washy properties of truthiness/falsiness. Sounds messy, doesn't it?

I'm pretty confident, though, that what's going on in these normalName functions is that they're trying to call the corresponding terrainName function first with the Layer 2 ID (giving it precedence). If the tile the player is standing on has no Layer 2 ID (presumably resulting in a "falsey" value), then it calls the function instead using the Layer 1 ID. And then, if for some reason there's no Layer 1 ID either, it falls back to a default (calling a simple function that does nothing more than return the 'Grassland' battleback - whether top or bottom).

---------

Are you with me so far? Because here's where we get to start customizing things. Now that we know which indices correspond to which terrains (see the second image above), it would be a simple matter to just change the names of the battle backgrounds in those functions with the long switch statements, or even to add new cases to designate other battle backgrounds for terrains that the default function doesn't account for.

(Disclaimer: I don't advise changing the original JavaScript files that come packed in with the program. But if you copy the important functions into a new JavaScript file, and make your adjustments there, then you can add it in the same way you do with your other plugins (MV terminology for scripts), and add it to your game via the plugin manager. That way, if there are any problems in the future, you have the simple option of either turning off or getting rid of the plugin completely, and reverting to the game's default functionality).

But in the process of doing this, I hit a little snag, because I like to have a little bit more fine-tuned control over the choice of battle background depending not just on either the Layer 1 or Layer 2 ID, but in some cases the result of their combination. In different cases, the Layer 2 ID might take precedence, whereas in others, the Layer 1 ID will be more important. My way of dealing with this via the eventing solution I used in VX Ace was to simply handle both Layer IDs simultaneously and check them against each other. But the functions we're dealing with here only consider one ID at a time. So what to do?

I tried a few different ways to get around this limitation, but I ultimately decided to modify the function itself to actually take two arguments instead of just one - one for each of the first two Layer IDs. I checked through all the core scripts (Ctrl-F is your friend), to make sure I knew every place the terrainName functions were being called, so as to avoid any discrepancies in the code. And it turns out that the only time the functions come up is in those cases we've already explored here.

(Another disclaimer: if you use another plugin that attempts to use or modify these same functions, you may encounter problems. I'm only a beginner MV scripter right now, so I wouldn't know how to minimize that possibility, e.g. by aliasing or whatever. Feel free to add in some contingency code yourself if you know how to go about doing that).

So all I had to do was change the (type) part of the function to a (type1, type2), and then in the normalName functions where the terrainName functions are being called, replace the first part of the confusing OR evaluation (while preserving the default fallback), so as to call the terrainName function just once with both arguments - one that retrieves the autotileType for Layer 1, and one for Layer 2. This is what the modified functions look like:
Spriteset_Battle.prototype.normalBattleback1Name = function() {
    return (this.terrainBattleback1Name(this.autotileType(0),
            this.autotileType(1)) || this.defaultBattleback1Name());
};

Spriteset_Battle.prototype.normalBattleback2Name = function() {
    return (this.terrainBattleback2Name(this.autotileType(0),
            this.autotileType(1)) || this.defaultBattleback2Name());
};
All that was left then was to modify the terrainName functions, by manipulating the switch statement(s), and in my case, adding in a couple of extra if/else statements for better flow, to tie the proper battle backgrounds to the proper combination of terrains. Here's what I ended up with (although I may make some more fine-tuned adjustments in the future):
Spriteset_Battle.prototype.terrainBattleback1Name = function(type1, type2) {
    if (type2 === 29) {
        return 'Cobblestones2';
    } else if (type2 === 37) {
        return 'Cobblestones4';
    } else {
        switch (type1) {
        case 4: case 5:
            return 'PoisonSwamp';
        case 8:
            return 'Ship';
        case 10: case 40:
            return 'Snowfield';
        case 16: case 18:
            switch (type2) {
            case 17: case 19:
                return 'Meadow';
            case 20: case 21:
                return 'GrassMaze';
            default:
                return 'Grassland';
            }
        case 24: case 26:
            return 'Wasteland';
        case 32:
            if (type2 === 33) {
                return 'Desert';
            } else {
                return 'Sand';
            }
        case 34:
            if (type2 === 35) {
                return 'Lava2';
            } else {
                return 'Lava1';
            }
        case 42:
            return 'Clouds';
        default:
            return null;
        }
    }
};

Spriteset_Battle.prototype.terrainBattleback2Name = function(type1, type2) {
    if (type2 === 30 || type2 === 38 || type2 === 41 || type2 === 46) {
        return 'Cliff';
    } else if (type2 === 21 || type2 === 36 || type2 === 44) {
        return 'Forest1';
    } else {
        switch (type1) {
        case 4: case 5:
            return 'PoisonSwamp';
        case 8:
            return 'Bridge';
        case 10:
            return 'Snowfield';
        case 16: case 18:
            if (type2 === 20) {
                return 'GrassMaze';
            } else {
                return 'Grassland';
            }
        case 24: case 26:
            return 'Wasteland';
        case 32:
            if (type2 === 33) {
                return 'Desert';
            } else {
                return 'Sea';
            }
        case 34:
            return 'Lava';
        case 40:
            return 'Snowfield';
        case 42:
            return 'Clouds';
        }
    }
};
A couple of notes to help you understand what's going on here. In the first function, I used an overriding if statement to return the appropriate ground textures for map tiles that feature roads (indicated by a Layer 2 ID), no matter what Layer 1 terrain is involved (grass, desert, snow, etc.). The rest of the cases are pretty straightforward, except that I provided some alternatives such as a different lower background for plains (indicated by a Layer 1 ID) versus grassy plains (indicated by a Layer 2 ID), and a similar alternative for ashy wasteland versus cracked lavafield (the subtle difference between the Lava1 and Lava2 battle backgrounds).

In the second function, I've used another conditional to override the texture for any tiles that require the Cliff or Forest1 wall texture, since they tend to crop up over a number of different Layer 1 ID terrains. The rest of the switch statement is again pretty straightforward, although here you'll see that I've designated one of the two desert terrains as a "beach" (as opposed to a landlocked desert) by giving it the Sea wall texture instead of the usual Desert wall texture.

And that's pretty much it! Feel free to take these code snippets and play around with them to suit your purposes. I'd love to make a fully customizable plugin out of what I've done here, but I fear that the individual needs of each user will be so specific as to require a heavily personalized combination of conditionals. Come to think of it, that may be why the original programmers haven't already done it.

Just a few last notes. It should be mentioned that in these examples, I've replaced all of my MV image files with resized versions of the VX Ace graphics (because I like them better). So my filenames may not match yours (although many - but not all - of the battleback filenames have remained the same from VX Ace to MV). Make sure the names you use in your code match the filenames in your img/battlebacks folders (1 and 2), minus the file extensions.

On a related subject, if you want to change the default battle background for use while riding the ship, you'll find that in a separate pair of functions that are really simple to modify. Look for them in rpg_sprites.js at lines 2582-2588.

I don't know how or to what extent the solution I've come up with here will dovetail with an airship encounter system, as I haven't tackled that problem in the MV version of my game yet. But if I have anything to say about that in the future, you can be sure to find it here on this blog!