I developed this project as a game exploring multiple complex game development aspects using AIE's bootstrap. The project makes heavy use of fmod for dynamic music playing, and IMGUI for its interface, but its main goal is its automated combat cycle, which is developed and tweaked by players through the use .lua scripts, along with other features found in RPGs like speed calculation, progression, particles and music, implemented through fmod, which changes dynamically as the player gets closer to victory or defeat.
All art and music used in this project was downloaded from opengameart.
In this game, players begin play by scripting out orders for their dark knight, telling it when to use its abilities to generate resources and attack its foes, then generating their script and watching the Knight fight with no further input until the battle ends. < br/>
The four enemy types are scripted in the same manner, and work cooperatively to fight the warrior.
For example, berserkers will use a suicidal charge to kill the player, and will then be revived by the healer.
Other characters have taunts, shields, which can impede the player's progress.
The player has abilities that counter these attacks, like Knightfall, which damages both a target and their protector if they're shielded, but they must script their knight beforehand if they wish to exploit it.
The creation of the lua script works in a fashion similar to writing an .xml save file. Simple variables are taken from IMGUI and then stored as C++ variables. When a write function is called, those variables are then printed to the text file.
As an example. When the lua file writes a function for selecting a target, it'll write the start of the function, "Target = FindTarget(", input two integers taken from C++, findHealth and FindHighLow, and then close the function with a ")".
An in-depth example: Checking if conditions are true.
In this example a warrior is checking if it's health is below 30 for the purposes of deciding if it should use its kamikaze attack.
result = CheckCondition(2, 0, 0, 3, 1).
- The first variable is deciding what variable we'll be checking from a pre-determined list. 0 is the player's health, 1 is their souls, 2 is an enemy's health.
- The second variable is a continuation of the first, determining who to check. 0 only has the unit check itself. 1 has the unit check the player. 2 has the unit check any enemy.
- The third is a boolean for less or greater than. A 1 would indicate true, asking if greater than.
- The fourth is the number the number the function will compare itself to. For simplicity's sake, since health is out of 100, it's multiplied by 10 before checking.
- The fifth variable is used to specify if any checks involving "Me" Or "This", are the player or the enemy currently taking its turn.
If this function were to return 'nil', the condition fails, and the enemy tries another attack. if the ability succeeded, the game would return a 2, telling the function to end.
The function is just like one that could be created by the player, and would be generated in an iteration of a for loop that looks like this:
oss << "result = CheckCondition("; This starts the function.
oss << player->AbilityChosen[i] << ", "; At This point we need it to know if we can afford the ability.
oss << player->condition[ind] << ", "; Health, souls, enemies alive, etc.
oss << player->conditionOperator[ind] << ", "; Greater or less than.
oss << player->numberComparing[ind] << ", 5)\n";
Dynamic Music
For the dynamic music system, it's actually quite simple. A function plays at the end of every turn, and it begins by summing the average Life Force of each enemy (Health and Souls, since they'll die at 0 souls or health), then dividing by the number of surviving opponents. Dead enemies are not included, but the score receives a penalty for each dead enemy. This number is then compared to the player's remaining health. If the % difference is large enough, the game will determine a side is winning, although it takes a much larger % to change to one state than it does to maintain it, to prevent the system from swapping tracks every time a player or enemy is hurt.
As for the music itself, it has been edited into having multiple fade-outs. If the music is ready to be changed, instead of continuing after a fade, the music will fade out completely and be replaced with the fade in of another song.