Mar 24, 2024


So yesterday (3/24) I spent some time implementing a move called Cat Breath (RIP to in inspiration Lucy up the street) that will work like a normal attack, but has a significantly increased chance at a critical hit; however, it will also delay your next turn.  I also worked a bit on trying to implement turn order.  When I say turn order, I don't mean based on the graceful stat (ie agility).  The way I'm going to implement skills (and items if I decide to have items) is to have skills essentially make you lose a turn (or more than one turn).  It almost certainly would be easier to do a straight magic point system, but I figured this would be a nice spin on things and if I can nail the battle system and damage calculations, this could add a bit of strategy to the encounters.  Right now, I think it's working with the 2 skills I have (dusty's chirp -- healing -- and cat breath), but I haven't tested extensively because the damage calculations and/or stats for both player and enemy are just way off.  Best I can tell by testing my 'great porkachew' encounters, it seems like this works.  I'll leave it for now and go back to this at a later date.  

To determine the roll for critical hits, I normally have two damage multipliers that are a random value between 1 and 4.  If both fields roll a 4, you score a critical that is double the typical damage.  For cat breath, you essentially have a 50% chance at a crit.  I roll the first multiplier to a random value of 1 or 2.  So I'm only looking for a 2 to get a crit.  Big difference in frequency, but is it worth the risk on stronger enemies (ie bosses)!?  

To implement losing/delaying your turn, I created variables for both the player and the enemy called turnOrder.  Since battles are menu driven, I leverage the menu selection to drive most of the logic in my flows.  I have multiple scripts throughout the battle flow.  It's hands down the most complex system I have and probably will remain the most complex.  Generally speaking, the flow goes like this:

  1. Walk around (or when I have boss battles interact/trigger something) and a battle is triggered
  2. This will call the "toBattle" script which:
    1. stores the player's X,Y position on the scene
    2. reset the following variables back to 0
      1. randomEncounter (admittedly don't remember if I use this off-hand.  i need to investigate)
      2. stepCounter
      3. turnOrderPlayer 
      4. turnOrderEnemy
      5. save the current scene to the stack
      6. call the "battleUI" scene
  3. The battleUI scene is triggered which
    1. Calls the enemyNameDisplay_battleUI script
      1. uses my 'nextEnemyNumber' and 'nextEnemyType' variables to trigger the enemy encounters.  
        1. each scene that should have battles will have a range of random numbers for these two values.  
        2. these numbers will drive the enemies seen.  The enemyNameDisplay_battleUI script will take the value for number and type and essentially display the corresponding sprite and use the corresponding stat values for whatever I've defined to match those.
        3. Example:  
    2. Once the enemy is identified and displayed, the battleUI scene calls the battleMenu script
  4. The battleMenu script is where the flow starts to get complicated.  The first thing I do is look at the turn order (delayed enemy turns or skills not implemented and that's going to be a long time if I ever do.  I might just do custom scripts for bosses to have skills).
    1. If the playerTurnOrder variable is >= 0, they get to choose the menu interaction.  If it's less than 0, they are met with dialog that the player looks around and doesn't know what to do and then the enemy moves.
    2. For player turns, they get the standard menu for fight magic item run (bork command treats disappyr)
      1. A bork choice is pretty simple.  It sees a menu value of 1 and calls a script to generate damage.  This script takes the players strength (bork) and the enemy's floof (defense) in to account, rolls for the crit (see above), and then does some math to determine the value.   It then calls the 'battleMenuText' script.
      2. A command choice is a bit more complicated.  We'll have two kinds of commands.  combat commands (cat breath) and non-combat commands.  I created a variable to identify the difference between this.  For combat commands, it follows the same flow as 4.b.i above and goes to the damageGenerated script.  For non-combat commands like Dusty's chirp which is healing, it goes to the 'nonCombatChoice' script.  It's admittedly similar to damageGenerated, but I wanted to keep them as separate flows.  It essentially does the same thing, but does a calc for amount healed.  The amountToBeHealed variable is set to the sum of the player's level and the value of heal amount multiplier (currently set to random value of 1-10.  almost certainly will need modified). With the value set, this also calls the battleMenuText script.
      3. Note:  nonCombat will eventually be getting something to make it harder for the enemy to hit the player.  I have to think on how to implement that, but it's one of the commands I'd like to implement at some point.
  5. The battleMenuText script is ultimately what manages the logic to display message text for the user.  I tried to manage the order flow and HP updates separately, but for whatever reason I kept messing up the flow, so everything now lives here and it's a nightmare.
    1. This script starts off looking at the player HPs to make sure they're not dead.
    2. It then moves on to check who is faster -- player or enemy
      1. If the player is faster, it moves on to check if the attack is a non-combat or combat type move.
        1. For combat moves, there's a check to see if it's cat breath in which case it calls out the move used in dialog and manages text to indicate a crit or not.  If it's a normal attack the normal 'you've attacked' dialog occurs along with the crit messaging if that happens.
      2. After the move dialog happens, the damange dealt is decremented from the enemy and a HP check for them is applied to determine if they're dead.  If they are, the post battle update happens which manages XP gains and calls the level up script if necessary.
      3. If the enemy is not dead, they get their damage rolls and decrement their damange value from the player's current HP.  
  6. If the player chose a non-combat move, the non-combat results are applied and then the enemy applies their damage.
  7. If the enemy is faster, the same things in 5 and 6 happen, but just that enemy goes first.
  8. When all of these battleMessageText actions are done, if both the enemy and player are still alive (HP > 0), we go back to the original 'battleMenu' script and start this all over again.
  9. The screenshot below makes that script look so small and basic.  Trust me when I say that's not the case.


Whew!  That was so much text!  I didn't plan on giving this long and detailed of an update!  I just started typing and one thought led tot he next.  It's nice to see the flow laid out though.  I should create a workflow diagram at some point.  

My code has gotten really messy.  I tried creating a script, but no matter where I put it, it felt like it was never functioning correctly.  So I ended up building nested if statements in to the battle flow.  It sucks and will make maintaining things moving forward a nightmare.  I probably should focus on refactoring the entire codebase while it's small.  Perhaps I will at some point over the coming weeks.  I'm far from a professional developer and in fact my day job is 'product owner', so i'm even at a loss for how to best parse this all out in to scripts.  But code cleanliness isn't exactly a good or flashy update, so I'll leave it at that.  It is on my list of 'some day maybe' items.

Files

Tower-of-Meowgic.gb 128 kB
Mar 25, 2024
Tower-of-Meowgic.zip Play in browser
Mar 25, 2024

Get Tower of Meowgic

Leave a comment

Log in with itch.io to leave a comment.