Post by cyberchocobo on Mar 16, 2024 22:16:42 GMT
Hello.
I am currently (in the very early stages of) working on my custom gameplay rebalance mod for Tyrian 2000. When planning what exactly I want to change, I quickly realized that there's a whole lot that I'd need to modify in the game engine itself, which would normally result in a completely separate OpenTyrian2000 fork just for this one mod. But wouldn't it be a lot more practical to un-hardcode'ify all this stuff and move it to more easily editable external config and data files to make everyone's job easier?
The most crucial thing I needed to modify in the game engine right off the bat was giving it ability to take each weapon's power drain values from the individual weapon levels. The vanilla game takes power drain value from WeaponPort structure (specific front/rear gun with pointer values to all 11 of its levels), which prevents implementing a proper drain increase with weapon upgrades, or in some cases even results in lower levels having bigger power drain per second than higher levels (Mega Pulse being probably the most egregious case). Thankfully the Weapon data structure (individual shot patterns for any weapon, including sidekicks) has an unused power drain field itself, so I made use of that instead. Here's my modified code (in shots.c). Relies on setting a single global variable to 0.
if(drainFromWeaponPort) { //===CC=== default Tyrian behavior
if (power < weaponPort[portNum].poweruse)
return MAX_PWEAPON;
power -= weaponPort[portNum].poweruse;
} else { //===CC=== get drain from Weapon instead of WeaponPort; for gameplay mods
if (power < weapon->drain)
return MAX_PWEAPON;
power -= weapon->drain;
}
My future modifications would involve replacing the following hardcoded stuff:
1. 1 Player Full Game starting loadouts (JE_initPlayerData function in mainint.c).
2. Enabling twiddles for all 19 existing ships in the data (JE_SFCodes function in mainint.c):
2. Enabling twiddles for all 19 existing ships in the data (JE_SFCodes function in mainint.c):
[...]
/*Get direction*/
if (playerNum_ == 2 && ship < 19) //===CC=== 15->19; see below
{
ship = 0;
}
if (ship < 19) //===CC=== 15->19; enables twiddles for Red Dragon, Gencore II, PeteZoomer and Rum Bottle
{
[...]
3. List of twiddles of individual ships (const JE_byte shipCombos[19][3] in varz.c), key combinations for executing these twiddles (const JE_byte keyboardCombos[26][8] in varz.c). Possibly also the actual effects, but I haven't analyzed what and how much would need to be changed yet.4. Difficulty level related stuff: score multipliers (const float score_multiplier[10] in mainint.c and enemyDat[eDatI].value manipulations in tyrian2.c), enemy rate of fire (enemy.eshotwait manipulations in tyrian2.c), enemy durability (enemyDat[eDatI].armor manipulations in tyrian2.c) and enemy aimed projectile speed (currently "aim += difficultyLevel - 2;" in tyrian2.c). All these calculations could probably be replaced with arrays of multipliers for each difficulty in order to make modifying them easier.
5. and additional more extensive stuff that would require more sophisticated code rewrites and would indeed require a separate source port, or at least huge blocks of new code inside if/else statements.
I am merely an amateur and don't know much about good coding/development practices. From how I imagine things to work, the solution to this would be creating extra (arrays of) global variables with default values corresponding to vanilla Tyrian 2000 behavior, and then implementing a new command line parameter for launching Tyrian exe to optionally supply the program with a config file with flags for enabling novel behavior and new data to overwrite the old hardcoded data. How sensible would that be? Would it be a welcome feature in the main OpenTyrian(2000) source port for sake of facilitating mod development, or should I just develop my mod on my independent branch of game engine?