Big Issues -- Hierarchy Behavior/SubRoutines

So, I’m new to Panda3D forums and python Programming. I’m not extremely new to programming (I’m a senior CS Major) but my problem is that I’m not the best at what I enjoy. So I was wondering if anyone here would be willing to help me with my problem.

I’m working on my Senor Project and I’m developing a game using the Panda3D that basis attacks depending on if the user answers a math question right. I’m calling my GUI for the menu’s during battle through my battleSystem file and I understand why it’s not working, I just can’t figure out how to solve my problem without rewritting my entire code.

Problem:
I have a flag set for when the player selects to attack it changes the flag and then another flag that when the player gets the right answer it does damage to the NPC. Yet, my code calls the flags before I can have the user set to attack or not and I don’t want this to happen. Does that make sense?
Here’s my battleSystem and GUI code.

 #=================================
 # Mathematics- Power of Numbers!
 # By J. Patterson 0->23
 #=================================
 # battleSys.py
 # A quick code for controlling
 # the battle system.
 #=================================
import random, sys, os, math
from Creatures import Creature
from gui import GUI
from direct.showbase.ShowBase import ShowBase

 
class battleSystem():
    def __init__(self):
        #Delaring the imports for the battle
        self.enemy = Creature()
        self.gui = GUI()
        self.enemySpeed = self.enemy.enemySpeed
        
        #Setting up player stats
        self.playerSpeed = 5
        self.playerHealth = 150
        
        #Setting  up attack or guarding situations for player
        self.playerAttack = False
        self.playerGuard = False
        
        #Setting up enemyies guard -- automatic to false
        self.enemyGuard = False
        self.countGuard = 0 # determines how many times enemy guards so it won't continously guard
        
        #Initilizing turn -- automatically players turn
        self.turn = 0
        
        #Flag to determine if battle is going or not
        self.battleFlag = False
        
        self.playerDamage = 0
        
    # calls when player attacks
    def playerAttacked(self):
        print "Reached playerAttack"
        self.playerAttack = True
        self.playerGuard = False
    
    # calls when player guards
    def playerGuards(self):
        print "Reached playerGuard"
        self.playerGuard = True
        self.playerAttack = False
        
    # The actual turn system, determined by speed 
    def turnStart(self):
        if (self.enemy.enemySpeed >= self.playerSpeed):
            self.turn = 1 # enemy's turn
            self.enemyBattleBehavior()
        else:
            self.turn = 0 # player's turn
            self.playerBattleBehavior()
        
    # Determines how the enemy behaves in battle (rough AI)
    def enemyBattleBehavior(self):
        # determines if enemy is dead
        print "Enemy Battle Behaviour"
        if(self.enemy.enemyHealth <= 0):
            #call battleWin
            self.battleWin()
        #decides if the enemy should guard or attack
        if (self.enemy.enemyHealth >= 50 or self.countGuard == 0):
            #indicates to attack
            # ## Play attack animation ## #
            
            # Subtract damage from players health
            if (self.playerGuard == False): # player is not guarding
                self.playerHealth = self.playerHealth - self.enemy.enemyDamage
            elif(self.playerGuard == True): # Player IS guarding, reduce damage by 1/4
                elf.playerHealth = (self.playerHealth - self.enemy.enemyDamage) * (1/4)
            #set guard to false incase it was true
            self.enemyGuard = False
            self.turn = 0
            self.countGuard = 0
        elif(self.enemy.enemyHealth < 50 and self.countGuard <= 3):
            # enemy should now guard
            self.enemyGuard = True
            self.turn = 0
            self.countGuard = self.countGuard + 1
        self.playerBattleBehavior()

    # Players acts in battle -- Opposite of enemyBattleBehavior
    def playerBattleBehavior(self):
        # Determine if player is still alive
        print "Enter player Phase"
        if (self.playerHealth <= 0):
            #call battleLoss
            self.battleLoss()
        self.setAttackorGuard()
        # If player attacks
        while(self.playerAttack is False):
            self.gui.setMenu()
            self.setAttackorGuard()
            if(self.playerAttack is True):
                print "Start Damage"
                #set player damage based on level of difficulty in GUI
                if(self.gui.playerDamage == 1):
                    self.playerDamage = 4
                elif(self.gui.playerDamage == 2):
                    self.playerDamage = 8
                elif(self.gui.playerDamage == 3):
                    self.playerDamage = 16
                self.playerAttack = True
            
            # Deducting damage from enemy health based of enemyGuard
            if(self.enemyGuard == False):
                self.enemy.enemyHealth = self.enemy.enemyHealth - self.playerDamage
            elif(self.enemyGuard == True):
                self.enemy.enemyHealth = (self.enemy.enemyHealth - self.playerDamage) * (1/4)
            self.turn = 1 # enemy's turn now
        self.enemyBattleBehavior() #To call enemy's move
            
    # To select which enemy is being used for the battle
    def characterSel(self, object):
        self.obj = object
        self.enemy.chooseMonster()
        self.enemy.lookAtPlayer(self.obj) # makes the enemy face the player
        
    #Determines when a battle occurs
    def randomBattle(self, object):
        self.battleRand = random.randrange(1,1000) # to get a decent percentage of battles to occur
        self.object = object #player
        if(self.battleRand <= 2):
            self.characterSel(self.object)
            self.battleFlag = True
            self.turnStart()
    
    # when a battle wins
    def battleWin(self):
        # destroys enemy model
        self.enemy.death()
        #turns of battleSystem
        self.battleFlag = False
        # call gui win
    
    # when a battle is lost
    def battleLoss(self):
        #destroy enemy model
        self.enemy.death()
        #turn of battleSystem
        self.battleFlag = False
        # call gui Lost
    def setAttackorGuard(self):
        print "reached AttackorGuard"
        if(self.gui.correct is True):
            self.playerAttacked()
        elif(self.gui.attack is False):
            self.playerGuards()
        else:
            print "this"
        
        

GUI:

#====
# GUI.py by J. Patterson 0->23
#====
# Gui is the Graphic User Interface, which incorporates
# the games HUD (Heads Up Display) and buttons. 
# This is what the user will be seeing. 
import random, os
from direct.gui.OnscreenText import OnscreenText
from direct.gui.DirectGui import *
from panda3d.core import *
from algebraIDatabase import algebraIDatabase
class GUI():
    def __init__(self):
        self.Database = algebraIDatabase() # sets up connection with the database
        
        #initializing the counts to keep track of where the user is having issues
        self.pemdasCount = 0 #no mistakes
        self.otherCount = 0 #no mistakes
        self.correct = " "
        self.attack = False
        
        # initialize button text and options
        self.os_text = " "
        self.textObject = OnscreenText(text = self.os_text, pos = (0.5, 0.85),
                                  scale = 0.07, fg = (1, 0.8, 0.8, 1), align=TextNode.ACenter, mayChange=1)
        # Creates the 3 buttons texts 
        self.rightAnswerText = "Right Answer"
        self.wrongAnswer1Text = "Wrong Answer 1"
        self.wrongAnswer2Text = "Wrong Answer 2"
        
        #for battle
        self.playerDamage = 0
        
    #intialize the menu for the button optsion
    def setMenu(self):
        #create the menu for the options
        self.menu = DirectOptionMenu(text="options", scale=0.1,items=["Attack", "Guard", "Help"],
                                initialitem=2,highlightColor=(0.65,0.65,0.5,1),frameColor=(0,0,1,1),command=self.itemSel,textMayChange=1)
        self.menu.set_pos(-1,-1,-0.8)
        self.menu.set(0)
    def startText(self):
        self.os_text2 = "Welcome to MatheMatics - Power of Numbers!" 
        self.os_text3 = """You are Pythagrius. The sole survivor of Algebraine.
                            Your homeland was destroyed by the evil King Proof.
                            Now, stranded on a deserted land, you must use your ancient power
                            of Algebra to defend off the waves of monster attacks. Do you have what it
                            takes to win this battle? 
                            Instructions:
                            W - Moves forward
                            A - Turns left
                            S - Turns Right
                            Q/E - Rotate Camera
                            During a battle sequence, press and hold the button to see more options,
                            choose option and release button.
                            Try not to die and have fun"""
        self.myDialogBox = OkDialog( text = self.os_text3, 
                                    command = self.destroy, fadeScreen = 1)
    def destroy(self,random):
        self.myDialogBox.cleanup()
        
    #when a button is selected
    def itemSel(self,arg):
        if(arg == "Attack"):
            # Bring in Select Level of difficulty
            # Hide old Menu and initilize new one
            self.menu.hide()
            self.attack = True
            self.menu2 = DirectOptionMenu(text="options", scale=0.1,items=["Category I", "Category II", "Category III"],
                                initialitem=2,highlightColor=(0.65,0.65,0.5,1),frameColor=(0,0.5,1,1),command=self.itemSel,textMayChange=1)
        elif(arg == "Guard"):
            # set Guard
            self.y = 1
            self.attack = False
        elif(arg == "Help"):
            #call help screen
            self.startText()
        elif(arg == "Category I"):
            #category 1 questions
            self.menu2.hide()
            self.menu3 = DirectOptionMenu(text="options", scale=0.1,items=["Category I: Level 1", "Category I: Level 2", "Category I: Level 3"],
                                initialitem=2,highlightColor=(0.65,0.65,0.5,1),frameColor=(0,0.5,1,1),command=self.itemSel,textMayChange=1)
        elif(arg == "Category II"):
            #category 2 questions
            self.menu2.hide()
            self.menu3 = DirectOptionMenu(text="options", scale=0.1,items=["Category II: Level 1", "Category II: Level 2", "Category II: Level 3"],
                                initialitem=2,highlightColor=(0.65,0.65,0.5,1),frameColor=(0,0.5,1,1),command=self.itemSel,textMayChange=1)
        elif(arg == "Category III"):
            #category 3 questions
            self.menu2.hide
            self.menu3 = DirectOptionMenu(text="options", scale=0.1,items=["Category III: Level 1", "Category III: Level 2", "Category III: Level 3"],
                                initialitem=2,highlightColor=(0.65,0.65,0.5,1),frameColor=(0,0.5,1,1),command=self.itemSel,textMayChange=1)
        elif(arg == "Category I: Level 1"):
            # call questions from category 1 level 1
            self.Database.CategoryI(1)
            # sets the onscreen text to the question
            self.os_text ="Solve for X: " + self.Database.questionString
            # applies the change 
            self.textObject.setText(self.os_text)
            #Calls the buttons with the answers
            self.rightAnswerText = self.Database.answerString
            self.wrongAnswer1Text = self.Database.wrongAnswer1String
            self.wrongAnswer2Text = self.Database.wrongAnswer2String
            #Call for buttons
            self.answerButtons()
            self.playerDamage = 1
            self.menu3.hide()
        elif(arg == "Category I: Level 2"):
            # call questions from category 1 level 2
            self.Database.CategoryI(2)
            self.playerDamage = 2
        elif(arg == "Category I: Level 3"):
            # call questions from category 1 level 3
            self.Database.CategoryI(3)
            self.playerDamage = 3
        elif(arg == "Category II: Level 1"):
            # call questions from category 2 level 1
            self.Database.CategoryII(1)
        elif(arg == "Category II: Level 2"):
            # call questions from category 2 level 2
            self.Database.CategoryII(2)
        elif(arg == "Category II: Level 3"):
            # call questions from category 2 level 3
            self.Database.CategoryII(3)
        elif(arg == "Category III: Level 1"):
            # call questions from category 3 level 1
            self.Database.CategoryIII(1)
        elif(arg == "Category III: Level 2"):
            # call questions from category 3 level 2
            self.Database.CategoryIII(2)
        elif(arg == "Category III: Level 3"):
            # call questions from category 3 level 3
            self.Database.CategoryIII(3)
    def answerButtons(self):
        # This is the 3 button choices for the answers
        # In order to randomize the button process
        # I'm using a random number generator and assigning the buttons based on that
        self.randomNumber = random.randint(1,3) # pics a number 1 - 3
        
        #Create the 3 Buttons
        self.rightAnswerButton = DirectButton(text = self.rightAnswerText, command = self.CorrectAnswer,
                                              scale = 0.1, pos = (-0.8,0, 0))
        self.wrongAnswer1Button = DirectButton(text = self.wrongAnswer1Text, command = self.wrongAnswer1,
                                              scale = 0.1, pos = (0,0,0))
        self.wrongAnswer2Button = DirectButton(text = self.wrongAnswer2Text, command = self.wrongAnswer2,
                                              scale = 0.1, pos = (.8, 0,0))
                                              
        #position the buttons based off of randomNumber
        if(self.randomNumber == 1): # set right answer to the left
            self.rightAnswerButton.set_pos = (-0.9, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (0, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (0.9, -0.8, 0)
        elif(self.randomNumber == 2): # set right answer to the right
            self.rightAnswerButton.set_pos = (0.9, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (0, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (-0.9, -0.9, 0)
        elif(self.randomNumber == 3): # set right answer to the center
            self.rightAnswerButton.set_pos = (0, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (-0.9, -0.9, 0)
            self.wrongAnswer2Button.set_pos = (0.9, -0.8, 0)
        #determine the question string -- to set for each button
        self.rightAnswerText = self.Database.questionString
        
    def CorrectAnswer(self):
        #when player gets it right
        self.correct = True
        self.buttonDestroy()
        
    def wrongAnswer1(self):
        #when player gets it wrong
        self.correct = False
        self.pemdasCount = self.pemdasCount + 1
        if(self.pemdasCount >= 9):
            #call pemdas text in GUI
            
            #reset
            self.pemdasCount = 0
        self.buttonDestroy()
    def wrongAnswer2(self):
        #when player gets it wrong
        self.correct = False
        self.otherCount = self.otherCount + 1
        if (self.otherCount >= 9):
            #call other text in GUI
            
            #reset
            self.otherCount = 0
        self.buttonDestroy()

    # destroys all menus at end of battle
    def destroyMenu(self):
        self.menu.destroy()
        self.menu2.destroy()
        self.menu3.destroy()
        
    def buttonDestroy(self):
        self.rightAnswerButton.destroy()
        self.wrongAnswer1Button.destroy()
        self.wrongAnswer2Button.destroy()

It’s not perfect or anywhere close to what I see on here, but I haven’t fully made it though all of the manual for panda and haven’t been able to put the time into learning like I should of :frowning:

—Update—

I had fixed my problem and finished it for the class. Thanks though.