Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- import tkinter.simpledialog as sdg
- import tkinter.messagebox as mbx
- import tkinter.font as tkf
- import tkinter.tix as tix
- import random as rnd
- import operator as op
- import os
- #Charlie Cook's Dungeons & Dragons Character Sheet Program
- #Begun early June 2017
- #Last updated mid January 2018
- #Gets the DEX, STR, and INT scores to set the Reflex, Fortitude, and Will saving throw scores
- #Now accommodates for when Ability Scores are changed between base and racial/class bonus mode
- #Scores are indexed as follows: STR=0, DEX=1, CON=2, INT=3, WIS=4, CHA=5
- def updtSAVETHRW(regularMode = True, altMS = [], alsBS = []):
- if regularMode:
- savingThrows[0] = mainStats[2] + bonusStats[2]
- savingThrows[1] = mainStats[1] + bonusStats[1]
- savingThrows[2] = mainStats[4] + bonusStats[4]
- else:
- savingThrows[0] = altMS[2] + alsBS[2]
- savingThrows[1] = altMS[1] + alsBS[1]
- savingThrows[2] = altMS[4] + alsBS[4]
- #Increments the level of the player and checks to see if 5E players are overleveled
- #The level, current XP, and required XP are recorded in the experience list in the afore-noted order
- def levelUp():
- showMessage = True
- experience[0] += 1 #Increment the player's level
- if LEVLVar.get(): #If the player is using the 5E brackets
- if experience[0] == 20: #If the player has reached level 20, the maximum allowed in 5E
- mbx.showinfo("Level Up!", "You have reached the maximum level allowed in 5E! Well played!")
- experience[2] = 999999 #Theoretically, no 5E player should reach such ridiculous XP
- elif experience[0] > 20: #If they do, be snide to them because they must be cheating
- mbx.showinfo("Level Up?", "You really should make a new character by now, 5E isn't meant to work with this much XP. To prevent errors, your current XP will be modulated to a six-digit number.")
- experience[1] = experience[1] % 999999
- experience[0] -= 1
- showMessage = False
- else: #If the player can still level up in the future, set the required XP to the proper amount
- experience[2] = brackets5E[experience[0]]
- else: #See prior comment
- experience[2] += 100 + 10 * experience[0]
- if showMessage:
- mbx.showinfo("Level Up!","Congratulations!\nYou are now Level " + str(experience[0]))
- #Refreshes the information in the Stats frame
- #Now accommodates for when Ability Scores are changed between base and racial/class bonus mode
- #Scores are indexed as follows: STR=0, DEX=1, CON=2, INT=3, WIS=4, CHA=5
- def refrSTAT(regularMode = True, altMS = [], altBS = []):
- LEVLLbl.config(text = "Level: " + str(experience[0]))
- HPLbl.config(text = "HP:" + str(health[0]) + "/" + str(health[1]))
- XPLbl.config(text = "XP:" + str(experience[1]) + "/" + str(experience[2]))
- #The below strings are evaluated to their python list objects via the eval() function.
- #This allows for the block of code that updates the scores to not be written twice.
- #Since a situation like this needs an if-else block, it's only worth it if the main code block
- #Is longer than the lines needed to assign the names of the strings to be eval'd
- if regularMode:
- mainStr = "mainStats"
- bonusStr = "bonusStats"
- updtSAVETHRW()
- else:
- mainStr = "altMS"
- bonusStr = "altBS"
- updtSAVETHRW(False, altMS, altBS)
- STRLbl.config(text = "STR: " + str(eval(mainStr)[0]))
- DEXLbl.config(text = "DEX: " + str(eval(mainStr)[1]))
- CONLbl.config(text = "CON: " + str(eval(mainStr)[2]))
- INTLbl.config(text = "INT: " + str(eval(mainStr)[3]))
- WISLbl.config(text = "WIS: " + str(eval(mainStr)[4]))
- CHALbl.config(text = "CHA: " + str(eval(mainStr)[5]))
- if bonusStats[0] > 0:
- STRBLbl.config(text = "+" + str(eval(bonusStr)[0]))
- else:
- STRBLbl.config(text = str(eval(bonusStr)[0]))
- if bonusStats[1] > 0:
- DEXBLbl.config(text = "+" + str(eval(bonusStr)[1]))
- else:
- DEXBLbl.config(text = str(eval(bonusStr)[1]))
- if bonusStats[2] > 0:
- CONBLbl.config(text = "+" + str(eval(bonusStr)[2]))
- else:
- CONBLbl.config(text = str(eval(bonusStr)[2]))
- if bonusStats[3] > 0:
- INTBLbl.config(text = "+" + str(eval(bonusStr)[3]))
- else:
- INTBLbl.config(text = str(eval(bonusStr)[3]))
- if bonusStats[4] > 0:
- WISBLbl.config(text = "+" + str(eval(bonusStr)[4]))
- else:
- WISBLbl.config(text = str(eval(bonusStr)[4]))
- if bonusStats[5] > 0:
- CHABLbl.config(text = "+" + str(eval(bonusStr)[5]))
- else:
- CHABLbl.config(text = str(eval(bonusStr)[5]))
- FORTLbl.config(text = "Fortitude: " + str(savingThrows[0]))
- REFLLbl.config(text = "Reflex: " + str(savingThrows[1]))
- WILLLbl.config(text = "Will: " + str(savingThrows[2]))
- #Increments the current HP if possible
- def HPUp():
- if health[0] < health[1]: #If the current health is less than the max
- health[0] += 1 #Increment it
- if SKILSCORVar.get(): #See the changeScores() function for more information on this block
- changeScores()
- else:
- refrSTAT()
- #Decrements the current HP if possible
- def HPDown():
- if health[0] > -10: #If the player won't die by losing health
- health[0] -= 1 #Decrement it
- if SKILSCORVar.get(): #See the changeScores() function for more information on this block
- changeScores()
- else:
- refrSTAT()
- #Increments the current XP and levels up if necessary
- def XPUp():
- temp = sdg.askinteger("Add XP", "Enter how many experience points you've earned:")
- if type(temp) == int:
- experience[1] += temp
- while experience[1] >= experience[2]: #While the current XP exceeds the required XP
- levelUp()
- if SKILSCORVar.get(): #See the changeScores() function for more information on this block
- changeScores()
- else:
- refrSTAT()
- if SKILSCORVar.get():
- changeScores()
- else:
- refrSTAT()
- #Changes the leveling requirements between 5E and the 100 + 10 * Current Level formula and re-levels the player
- def ChangeXP():
- if mbx.askokcancel("Warning!", "Changing the level up brackets may make things weird. Is it okay to continue?"):
- if LEVLVar.get(): #Switching to 5E
- experience[0] = 1
- experience[2] = brackets5E[1]
- else: #Switching to C^2's homebrew method
- experience[0] = 1
- experience[2] = 110
- while experience[1] >= experience[2]: #See comment in XPUp()
- levelUp()
- if SKILSCORVar.get(): #See the changeScores() function for more information on this block
- changeScores()
- else:
- refrSTAT()
- if SKILSCORVar.get():
- changeScores()
- else:
- refrSTAT()
- #The below else condition is present because the checkbox that invokes this function
- #will change regardless of the yes or no in the above message box, thus it must be reset if no is selected
- else:
- LEVLVar.set(not LEVLVar.get())
- #Root dialog for editing stats
- class editStatRoot(sdg.Dialog):
- def body(self, master):
- self.title("Edit Stats")
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.choice.set(1)
- tk.Label(master, text = "Choose a stat item to edit:", font = ftNormal).grid(row = 0)
- STR = tk.Radiobutton(master, text = "Strength", value = 1, variable = self.choice, cursor = "hand2", font = ftNormal)
- DEX = tk.Radiobutton(master, text = "Dexterity", value = 2, variable = self.choice, cursor = "hand2", font = ftNormal)
- CON = tk.Radiobutton(master, text = "Constitution", value = 3, variable = self.choice, cursor = "hand2", font = ftNormal)
- INT = tk.Radiobutton(master, text = "Intelligence", value = 4, variable = self.choice, cursor = "hand2", font = ftNormal)
- WIS = tk.Radiobutton(master, text = "Wisdom", value = 5, variable = self.choice, cursor = "hand2", font = ftNormal)
- CHA = tk.Radiobutton(master, text = "Charisma", value = 6, variable = self.choice, cursor = "hand2", font = ftNormal)
- LEV = tk.Radiobutton(master, text = "Level", value = 7, variable = self.choice, cursor = "hand2", font = ftNormal)
- XP = tk.Radiobutton(master, text = "Experience", value = 8, variable = self.choice, cursor = "hand2", font = ftNormal)
- HPC = tk.Radiobutton(master, text = "Current Health", value = 9, variable = self.choice, cursor = "hand2", font = ftNormal)
- HPM = tk.Radiobutton(master, text = "Maximum Health", value = 10, variable = self.choice, cursor = "hand2", font = ftNormal)
- ALL = tk.Radiobutton(master, text = "Ability Re-roll", value = 11, variable = self.choice, cursor = "hand2", font = ftNormal)
- STR.grid(row = 6, sticky = "w")
- DEX.grid(row = 7, sticky = "w")
- CON.grid(row = 8, sticky = "w")
- INT.grid(row = 9, sticky = "w")
- WIS.grid(row = 10, sticky = "w")
- CHA.grid(row = 11, sticky = "w")
- LEV.grid(row = 1, sticky = "w")
- XP.grid(row = 2, sticky = "w")
- HPC.grid(row = 3, sticky = "w")
- HPM.grid(row = 4, sticky = "w")
- ALL.grid(row = 5, sticky = "w")
- def apply(self):
- self.result = self.choice.get()
- #Edits attributes, health, level, and XP
- def editStat():
- choice = editStatRoot(base).result
- if type(choice) == int: #If the user didn't hit Cancel in the root dialog
- choices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
- if choice < 7: #If the user wants to edit an Ability Score
- temp = []
- try:
- temp.append(sdg.askinteger("Edit " + choices[choice - 1], "Enter your new " + choices[choice - 1] + ":"))
- temp.append((temp[0] - 10) // 2)
- except TypeError:
- temp = None
- elif choice == 7:
- temp = sdg.askinteger("Edit Level", "[Warning! This will change your XP!]\nEnter your new level:", initialvalue = experience[0])
- if type(temp) == int and temp > 0:
- experience[0] = temp
- if LEVLVar.get():
- if experience[0] > 20:
- mbx.showinfo("Warning!", "When using the 5E level up brackets, you cannot have a level greater than 20. To prevent errors, your entered level will now be modulated to a number from 1 to 20.")
- experience[0] = experience[0] % 20
- if experience[0] == 20:
- experience[2] = 999999
- else:
- experience[2] = brackets5E[experience[0]]
- experience[1] = brackets5E[experience[0] - 1]
- else:
- experience[2] = 0
- for i in range(1, experience[0] + 1):
- experience[2] += 100 + 10 * i
- experience[1] = experience[2] - (100 + 10 * experience[0])
- elif type(temp) == int and temp <= 0:
- mbx.showerror("Error", "You can't have a negative level!")
- elif choice == 8:
- temp = sdg.askinteger("Edit Experience", "[Warning! This will change your level!]\nEnter your new current experience points:", initialvalue = experience[1])
- if type(temp) == int and temp >= 0:
- experience[1] = temp
- experience[0] = 1
- if LEVLVar.get():
- experience[2] = 300
- else:
- experience[2] = 110
- while experience[1] >= experience[2]:
- levelUp()
- if SKILSCORVar.get():
- changeScores()
- else:
- refrSTAT()
- elif type(temp) == int and temp < 0:
- mbx.showerror("Error", "You can't have negative experience points!")
- elif choice == 9:
- temp = health[1] + 1
- while temp > health[1]:
- temp = sdg.askinteger("Edit Health", "Enter your new current health:", initialvalue = health[0])
- if type(temp) != int:
- return
- elif temp > health[1]:
- mbx.showerror("Error", "You can't overcharge your health!")
- if type(temp) == int and temp >= -10:
- health[0] = temp
- elif type(temp) == int and temp < -10:
- mbx.showerror("Error", "You can't have your health drop below -10, you'd be dead then!")
- elif choice == 10:
- temp = sdg.askinteger("Edit Health", "Enter your new maximum health:", initialvalue = health[1])
- if type(temp) == int and temp > 0:
- health[1] = temp
- if health[0] > health[1]:
- health[0] = health[1]
- elif type(temp) == int and temp <= 0:
- mbx.showerror("Error", "You can't have a negative maximum health!")
- elif choice == 11:
- tempMStats = []
- tempBStats = []
- tempStr = ""
- temp = newCharacterStatRoot(base).result
- if type(temp) != int:
- return
- if temp == 0:
- tempStr = pointBuyRoot(base).result
- elif temp == 1:
- tempStr = diceRollStatsRoot(base).result
- if type(tempStr) != str:
- return
- if temp in (0, 1):
- for s in tempStr.split()[0].split('|'):
- tempMStats.append(int(s))
- for s in tempStr.split()[1].split('|'):
- tempBStats.append(int(s))
- elif temp == 2:
- tempCount = 0
- while len(tempMStats) < 6 and len(tempBStats) < 6:
- temp = sdg.askinteger("New Character: Manual Stats", "Enter your " + choices[tempCount] + ":")
- if type(temp) != int:
- return
- tempMStats.append(temp)
- tempBStats.append((temp - 10) // 2)
- tempCount += 1
- tempCount = 0
- for bit in tempMStats:
- mainStats[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in tempBStats:
- bonusStats[tempCount] = bit
- tempCount += 1
- if type(temp) == list:
- if type(temp[0]) == int:
- mainStats[choice - 1] = temp[0]
- if type(temp[1]) == int:
- bonusStats[choice - 1] = temp[1]
- if type(temp) in (int, list):
- if SKILSCORVar.get():
- changeScores()
- else:
- refrSTAT()
- #Refreshes the information frame
- def refrINFO():
- NAMELbl.config(text = info[0])
- CLSSLbl.config(text = "Class: " + info[1])
- DETYLbl.config(text = "Deity: " + info[2])
- RACELbl.config(text = "Race: " + info[3])
- GNDRLbl.config(text = "Gender: " + info[4])
- AYGELbl.config(text = "Age: " + str(info[5]))
- HGHTLbl.config(text = str(info[6]) + " " + info[7])
- WGHTLbl.config(text = str(info[8]) + " " + info[9])
- HAIRLbl.config(text = "Hair: " + info[10])
- EYESLbl.config(text = "Eyes: " + info[11])
- MONYLbl.config(text = str(info[13]) + " " + info[12])
- #Changes the amount of money
- def changeMoney(): #Money is kept as an integer to prevent floating-point-arithmetic errors
- debit = sdg.askinteger("Change Money", "How much money to add/remove?")
- if type(debit) == int:
- info[13] += debit
- refrINFO()
- #Root dialog for editing information
- class editInfoRoot(sdg.Dialog):
- def body(self, master):
- self.title("Edit Info")
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.choice.set(1)
- tk.Label(master, text = "Choose an info item to edit:", font = ftNormal).grid(row = 0)
- Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftNormal)
- Class = tk.Radiobutton(master, text = "Class", value = 2, variable = self.choice, cursor = "hand2", font = ftNormal)
- Deity = tk.Radiobutton(master, text = "Deity", value = 3, variable = self.choice, cursor = "hand2", font = ftNormal)
- Race = tk.Radiobutton(master, text = "Race", value = 4, variable = self.choice, cursor = "hand2", font = ftNormal)
- Gender = tk.Radiobutton(master, text = "Gender", value = 5, variable = self.choice, cursor = "hand2", font = ftNormal)
- Age = tk.Radiobutton(master, text = "Age", value = 6, variable = self.choice, cursor = "hand2", font = ftNormal)
- Height = tk.Radiobutton(master, text = "Height", value = 7, variable = self.choice, cursor = "hand2", font = ftNormal)
- Weight = tk.Radiobutton(master, text = "Weight", value = 8, variable = self.choice, cursor = "hand2", font = ftNormal)
- HairColor = tk.Radiobutton(master, text = "Hair Color", value = 9, variable = self.choice, cursor = "hand2", font = ftNormal)
- EyeColor = tk.Radiobutton(master, text = "Eye Color", value = 10, variable = self.choice, cursor = "hand2", font = ftNormal)
- Currency = tk.Radiobutton(master, text = "Currency", value = 11, variable = self.choice, cursor = "hand2", font = ftNormal)
- Name.grid(row = 1, sticky = "w")
- Class.grid(row = 2, sticky = "w")
- Deity.grid(row = 3, sticky = "w")
- Race.grid(row = 4, sticky = "w")
- Gender.grid(row = 5, sticky = "w")
- Age.grid(row = 6, sticky = "w")
- Height.grid(row = 7, sticky = "w")
- Weight.grid(row = 8, sticky = "w")
- HairColor.grid(row = 9, sticky = "w")
- EyeColor.grid(row = 10, sticky = "w")
- Currency.grid(row = 11, sticky = "w")
- def apply(self):
- self.result = self.choice.get()
- #Dialog for editing height and/or weight
- class editWH(sdg.Dialog):
- def __init__(self, master = None, m = 9):
- self.mode = m - 7
- super().__init__(master)
- def toggleUnit(self):
- if self.ChangeUnit.get() == 1:
- self.Unit.config(state = "normal")
- else:
- self.Unit.config(state = "disabled")
- def body(self, master):
- choices = ["height", "weight"]
- self.title("Edit " + choices[self.mode].title())
- self.resizable(False, False)
- self.ChangeUnit = tk.IntVar()
- self.ChangeUnit.set(0)
- tk.Label(master, text = "Enter your new " + choices[self.mode] + ":", font = ftNormal).grid(row = 0)
- self.Value = tk.Entry(master, font = ftNormal)
- self.Unit = tk.Entry(master, font = ftNormal)
- if self.mode == 0:
- self.Value.insert(0, info[6])
- self.Unit.insert(0, info[7])
- elif self.mode == 1:
- self.Value.insert(0, info[8])
- self.Unit.insert(0, info[9])
- self.Unit.config(state = "disabled")
- ChangeUnitChk = tk.Checkbutton(master, text = "Check to change unit", variable = self.ChangeUnit, command = self.toggleUnit, font = ftNormal)
- self.Value.grid(row = 1)
- self.Unit.grid(row = 3)
- ChangeUnitChk.grid(row = 2)
- def apply(self):
- try:
- self.result = [int(self.Value.get()), self.Unit.get(), self.ChangeUnit.get()]
- except:
- mbx.showerror("Error","Invalid Measurement")
- self.result = []
- #Wrapper function (?) for editing information
- def editInfo():
- editInfoSelect(editInfoRoot(base).result)
- refrINFO()
- #Function for editing information
- def editInfoSelect(choice):
- if choice in range(1, 7) or choice in range(9, 12):
- if choice < 8:
- index = choice - 1
- else:
- index = choice + 1
- choices = ["", "name", "class", "deity", "race", "gender", "age", "", "", "hair color", "eye color", "currency"]
- if choice == 6:
- temp = sdg.askinteger("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
- if type(temp) == int:
- info[index] = temp
- elif choice != 6:
- temp = sdg.askstring("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
- if type(temp) == str:
- info[index] = temp
- elif choice in range(7, 9):
- n = choice
- if n < 8:
- n -= 1
- temp = editWH(base, choice).result
- if type(temp) == list and len(temp) > 0:
- info[n] = temp[0]
- if temp[2] == 1:
- info[n + 1] = temp[1]
- #Refreshes the inventory frame
- def refrINVT():
- INVTTxt.delete(0, INVTTxt.size())
- tempWGHT = 0.0
- for item in inventory:
- tempWGHT += round(item[2] * item[3], 4)
- tempStr = ""
- tempStr += item[0][:36]
- if len(item[0]) > 36:
- tempStr += "... "
- else:
- tempStr += (40 - len(item[0])) * " "
- tempStr += str(item[2])
- tempStr += (8 - len(str(item[2]))) * " "
- tempStr += str(item[3])
- tempStr += (8 - len(str(item[3]))) * " "
- if item[4] != 0 and item[5]:
- tempStr += "d" + str(item[4]) + " x" + str(item[5])
- tempStr += (8 - len("d" + str(item[4]) + " x" + str(item[5]))) * " "
- else:
- tempStr += 8 * " "
- if item[7] != 0:
- tempStr += str(item[6]) + "/" + str(item[7])
- tempStr += (8 - len(str(item[6]) + "/" + str(item[7]))) * " "
- else:
- tempStr += 8 * " "
- if item[8]:
- tempStr += "Yes"
- else:
- tempStr += "No"
- INVTTxt.insert("end", tempStr)
- INVTENCMLbl.config(text = "Encumberance: " + str(tempWGHT))
- #Creates a new item
- def newItem():
- tempItem = []
- tempStr = ""
- try:
- while len(tempStr) == 0:
- tempStr = sdg.askstring("New Item", "Enter the new item's name:")
- if len(tempStr) == 0:
- mbx.showerror("Error", "You must name your item!")
- tempItem.append(tempStr)
- tempItem.append(sdg.askstring("New Item", "[Optional] Enter the new item's bonus(es) or description:"))
- if None in tempItem:
- return
- tempItem.append(sdg.askinteger("New Item", "Enter how many of the new item you have:", initialvalue = 1))
- if None in tempItem:
- return
- tempItem.append(sdg.askfloat("New Item", "Enter the weight of the item:", initialvalue = 0.0))
- if None in tempItem:
- return
- tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the type of dice the item uses:", initialvalue = 0))
- if None in tempItem:
- return
- tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the amount of dice rolls for the item:", initialvalue = 0))
- if None in tempItem:
- return
- tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the maximum magical charges the item has:", initialvalue = 0))
- if None in tempItem:
- return
- tempInt = tempItem[6] + 1
- while tempInt > tempItem[6]:
- tempInt = sdg.askinteger("New Item", "[Optional] Enter the current magical charges the item has:", initialvalue = 0)
- if tempInt > tempItem[6]:
- mbx.showerror("Error", "You can't overcharge your item!")
- tempItem.insert(6, tempInt)
- tempItem.append(mbx.askyesno("New Item", "Is the item equipped?"))
- inventory.append(tempItem)
- refrINVT()
- except TypeError:
- pass
- #Root dialog for editing items
- class editItemRoot(sdg.Dialog):
- def __init__(self, master = None, i = ""):
- self.item = i
- super().__init__(master)
- def body(self, master):
- self.title("Edit " + self.item)
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.choice.set(0)
- tk.Label(master, text = "Choose an item attribute to edit:", font = ftNormal).grid(row = 0)
- Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftNormal)
- Bonus = tk.Radiobutton(master, text = "Bonus(es)", value = 1, variable = self.choice, cursor = "hand2", font = ftNormal)
- Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftNormal)
- Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftNormal)
- dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftNormal)
- dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftNormal)
- Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftNormal)
- MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftNormal)
- Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftNormal)
- Name.grid(row = 1, sticky = "w")
- Bonus.grid(row = 2, sticky = "w")
- Count.grid(row = 3, sticky = "w")
- Weight.grid(row = 4, sticky = "w")
- dType.grid(row = 5, sticky = "w")
- dCount.grid(row = 6, sticky = "w")
- Charges.grid(row = 7, sticky = "w")
- MaxCharges.grid(row = 8, sticky = "w")
- Equipped.grid(row = 9, sticky = "w")
- def apply(self):
- self.result = self.choice.get()
- #Changes edited item attributes
- def editItem():
- try:
- index = INVTTxt.curselection()[0]
- item = inventory[index]
- attr = editItemRoot(base, item[0]).result
- if type(attr) == int:
- choices = ["Name", "Bonus(es)", "Count", "Weight", "Dice Type", "Dice Count", "Charges", "Max Charges", ""]
- title = "Edit " + item[0]
- prompt = "Enter the item's new " + choices[attr] + ":"
- if attr < 2:
- temp = sdg.askstring(title, prompt, initialvalue = item[attr])
- if type(temp) == str and len(temp) > 0 and temp != item[attr]:
- inventory[index][attr] = temp
- elif attr < 6 and attr != 3:
- temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
- if type(temp) == int and temp != item[attr]:
- inventory[index][attr] = temp
- elif attr == 3:
- temp = sdg.askfloat(title, prompt, initialvalue = item[attr])
- if type(temp) == float and temp != item[attr]:
- inventory[index][attr] = temp
- elif attr == 6:
- temp = item[7] + 1
- while type(temp) == int and temp > item[7]:
- temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
- if type(temp) == int and temp > item[7]:
- mbx.showerror("Error", "You can't overcharge your item!")
- if type(temp) == int and temp != item[attr]:
- inventory[index][attr] = temp
- elif attr == 7:
- temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
- if type(temp) == int and temp != item[attr]:
- if temp < item[6]:
- inventory[index][6] = temp
- inventory[index][attr] = temp
- else:
- inventory[index][attr] = not inventory[index][attr]
- refrINVT()
- except IndexError:
- mbx.showerror("Error", "No item selected!")
- #Shows an item's bonus(es) or description
- def inspectItem():
- try:
- if len(inventory[INVTTxt.curselection()[0]][1]) > 0:
- mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n" + inventory[INVTTxt.curselection()[0]][1])
- else:
- mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n[None]")
- except IndexError:
- mbx.showerror("Error", "No item selected!")
- #Deletes an item
- def deleteItem():
- try:
- if mbx.askyesno("Delete Item: " + inventory[INVTTxt.curselection()[0]][0], "Are you sure you want to delete this item?"):
- del inventory[INVTTxt.curselection()[0]]
- refrINVT()
- except IndexError:
- mbx.showerror("Error", "No item selected!")
- #Root dialog for sorting items
- class sortItemsRoot(sdg.Dialog):
- def body(self, master):
- self.title("Sort Items")
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.order = tk.IntVar()
- self.choice.set(0)
- self.order.set(0)
- tk.Label(master, text = "Choose an attribute to sort by:", font = ftNormal).grid(row = 0)
- tk.Label(master, text = "Choose an order to sort by:", font = ftNormal).grid(row = 9)
- Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftNormal)
- Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftNormal)
- Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftNormal)
- dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftNormal)
- dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftNormal)
- Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftNormal)
- MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftNormal)
- Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftNormal)
- Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftNormal)
- Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftNormal)
- Name.grid(row = 1, sticky = "w")
- Count.grid(row = 2, sticky = "w")
- Weight.grid(row = 3, sticky = "w")
- dType.grid(row = 4, sticky = "w")
- dCount.grid(row = 5, sticky = "w")
- Charges.grid(row = 6, sticky = "w")
- MaxCharges.grid(row = 7, sticky = "w")
- Equipped.grid(row = 8, sticky = "w")
- Ascending.grid(row = 10, sticky = "w")
- Descending.grid(row = 11, sticky = "w")
- def apply(self):
- self.result = [self.choice.get(), self.order.get()]
- #Sorts inventory by various attributes
- def sortItems():
- choice = sortItemsRoot(base).result
- if type(choice) == list:
- if choice[1] == 1:
- order = True
- else:
- order = False
- inventory.sort(key = op.itemgetter(choice[0]), reverse = order)
- refrINVT()
- #Rolls virtual dice of various types
- def rollDice(d):
- def rollDiceWrap(dice = d):
- if dice == 0:
- DICELbl.config(text = "0 | d?")
- elif dice == 2:
- if rnd.randint(0,1):
- DICELbl.config(text = "Heads | Coin")
- else:
- DICELbl.config(text = "Tails | Coin")
- elif dice < 100:
- DICELbl.config(text = str(rnd.randint(1, dice)) + " | d" + str(dice))
- else:
- DICELbl.config(text = str(rnd.randint(0, 100)) + " | d%")
- return rollDiceWrap
- #Refreshes the skills frame
- def refrSKIL():
- SKILTxt.delete(0, SKILTxt.size())
- stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
- for sk in skills:
- SKILTxt.insert("end", stats[sk[0]] + "|" + sk[1])
- #Dialog for selecting the attribute stat associated with a skill or ability
- class skillStat(sdg.Dialog):
- def __init__(self, master = None, m = "", sa = "", i = 0):
- self.mode = m
- self.skab = sa
- self.index = i
- super().__init__(master)
- def body(self, master):
- self.resizable(False, False)
- self.stat = tk.IntVar()
- if self.skab == "skill":
- if self.mode == "edit":
- self.title("Edit " + skills[self.index][1])
- self.stat.set(skills[self.index][0])
- elif self.mode == "new":
- self.title("New Skill")
- self.stat.set(0)
- elif self.skab == "ability":
- if self.mode == "edit":
- self.title("Edit " + abilities[self.index][1])
- self.stat.set(abilities[self.index][0])
- elif self.mode == "new":
- self.title("New Ability")
- self.stat.set(0)
- PRMPLbl = tk.Label(master, font = ftSmall)
- PRMPLbl.grid(row = 0)
- if self.skab == "skill":
- if self.mode == "edit":
- PRMPLbl.config(text = "[Optional] Choose a new stat for the skill:")
- elif self.mode == "new":
- PRMPLbl.config(text = "Choose a stat for the skill:")
- elif self.skab == "ability":
- if self.mode == "edit":
- PRMPLbl.config(text = "[Optional] Choose a new stat for the ability:")
- elif self.mode == "new":
- PRMPLbl.config(text = "Choose a stat for the ability:")
- STRBtn = tk.Radiobutton(master, text = "Strength", value = 0, variable = self.stat, font = ftNormal)
- DEXBtn = tk.Radiobutton(master, text = "Dexterity", value = 1, variable = self.stat, font = ftNormal)
- CONBtn = tk.Radiobutton(master, text = "Constitution", value = 2, variable = self.stat, font = ftNormal)
- INTBtn = tk.Radiobutton(master, text = "Intelligence", value = 3, variable = self.stat, font = ftNormal)
- WISBtn = tk.Radiobutton(master, text = "Wisdom", value = 4, variable = self.stat, font = ftNormal)
- CHABtn = tk.Radiobutton(master, text = "Charisma", value = 5, variable = self.stat, font = ftNormal)
- STRBtn.grid(row = 1, sticky = "w")
- DEXBtn.grid(row = 2, sticky = "w")
- CONBtn.grid(row = 3, sticky = "w")
- INTBtn.grid(row = 4, sticky = "w")
- WISBtn.grid(row = 5, sticky = "w")
- CHABtn.grid(row = 6, sticky = "w")
- def apply(self):
- self.result = self.stat.get()
- #Creates a new skill
- def newSkill():
- tempStr = ""
- while type(tempStr) == str and len(tempStr) < 1:
- tempStr = sdg.askstring("New Skill", "Enter the new skill's name:")
- if type(tempStr) == str and len(tempStr) < 1:
- mbx.showerror("Error", "You must name this skill!")
- if type(tempStr) == str:
- tempInt = skillStat(base, "new", "skill").result
- if type(tempInt) == int:
- skills.append([tempInt, tempStr])
- refrSKIL()
- if SKILSCORVar.get():
- changeScores()
- #Edits a skill
- def editSkill():
- try:
- index = SKILTxt.curselection()[0]
- sk = skills[index]
- tempStr = sdg.askstring("Edit " + sk[1], "[Optional] Enter the skill's new name:", initialvalue = sk[1])
- if type(tempStr) == str:
- if len(tempStr) > 0 and tempStr != sk[1]:
- skills[index][1] = tempStr
- tempInt = skillStat(base, "edit", "skill", index).result
- if type(tempInt) == int and tempInt != sk[0]:
- skills[index][0] = tempInt
- refrSKIL()
- if SKILSCORVar.get():
- changeScores()
- except IndexError:
- mbx.showerror("Error", "No skill selected!")
- #Deletes a skill
- def deleteSkill():
- try:
- if mbx.askyesno("Delete " + skills[SKILTxt.curselection()[0]][1], "Are you sure you want to delete this skill?"):
- del skills[SKILTxt.curselection()[0]]
- refrSKIL()
- if SKILSCORVar.get():
- changeScores()
- except IndexError:
- mbx.showerror("Error", "No skill selected!")
- #Dialog for skills and/or abilities
- class sortSkillsAbils(sdg.Dialog):
- def __init__(self, master = None, sa = ""):
- self.skab = sa
- super().__init__(master)
- def body(self, master):
- if self.skab == "skill":
- self.title("Sort Skills")
- elif self.skab == "ability":
- self.title("Sort Abilities")
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.order = tk.IntVar()
- self.choice.set(0)
- self.order.set(0)
- tk.Label(master, text = "Choose an attribute to sort by:", font = ftNormal).grid(row = 0)
- tk.Label(master, text = "Choose an order to sort by:", font = ftNormal).grid(row = 3)
- Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftNormal)
- Stat = tk.Radiobutton(master, text = "Stat", value = 0, variable = self.choice, cursor = "hand2", font = ftNormal)
- Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftNormal)
- Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftNormal)
- Name.grid(row = 1, sticky = "w")
- Stat.grid(row = 2, sticky = "w")
- Ascending.grid(row = 4, sticky = "w")
- Descending.grid(row = 5, sticky = "w")
- def apply(self):
- self.result = [self.choice.get(), self.order.get()]
- #Sorts skills by name or attribute stat
- def sortSkills():
- choice = sortSkillsAbils(base, "skill").result
- if type(choice) == list:
- if choice[1] == 1:
- order = True
- else:
- order = False
- skills.sort(key = op.itemgetter(choice[0]), reverse = order)
- refrSKIL()
- #Toggles between including racial/class ability score bonuses into the Stats display
- def changeScores():
- if SKILSCORVar.get():
- newScores = []
- for i in range(len(mainStats)):
- newScores.append(mainStats[i])
- for sk in skills:
- if sk[1][0] in "+-":
- try:
- if sk[1][0] == '+':
- newScores[sk[0]] += int(sk[1][1:].split()[0])
- else:
- newScores[sk[0]] += int(sk[1][0:].split()[0])
- except ValueError:
- pass
- newMods = [0, 0, 0, 0, 0, 0]
- for i in range(len(newScores)):
- newMods[i] = (newScores[i] - 10) // 2
- refrSTAT(False, newScores, newMods)
- else:
- refrSTAT()
- #Shows the information box regarding the above functionality
- def showPrefixInfo():
- mbx.showinfo("Skills: Apply Prefixes", "When checked, all skills whose name have a leading +/- character \
- followed by an integer then a space will be compiled and added to your base Ability Scores without changing said scores. \
- This is useful for adding temporary skill entries to act as buffs from equipment or spells.")
- #Refreshes the abilities frame
- def refrABIL():
- ABILTxt.delete(0, ABILTxt.size())
- stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
- for ab in abilities:
- ABILTxt.insert("end", stats[ab[0]] + "|" + ab[1])
- #Creates a new ability
- def newAbility():
- tempStrA = ""
- while type(tempStrA) == str and len(tempStrA) < 1:
- tempStrA = sdg.askstring("New Ability", "Enter the new ability's name:")
- if type(tempStrA) == str and len(tempStrA) < 1:
- mbx.showerror("Error", "You must name this ability!")
- if type(tempStrA) == str:
- tempInt = skillStat(base, "new", "ability").result
- if type(tempInt) == int:
- tempStrB = sdg.askstring("New Ability", "Describe the new ability:")
- if type(tempStrB) == str:
- abilities.append([tempInt, tempStrA, tempStrB])
- refrABIL()
- #Edits an ability
- def editAbility():
- try:
- index = ABILTxt.curselection()[0]
- ab = abilities[index]
- tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Enter the ability's new name:", initialvalue = ab[1])
- if type(tempStr) == str:
- if len(tempStr) > 0 and tempStr != ab[1]:
- abilities[index][1] = tempStr
- tempInt = skillStat(base, "edit", "ability", index).result
- if type(tempInt) == int:
- if tempInt != ab[0]:
- abilities[index][0] = tempInt
- tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Describe the ability again:", initialvalue = ab[2])
- if type(tempStr) == str and len(tempStr) > 0 and tempStr != ab[2]:
- abilities[index][2] = tempStr
- refrABIL()
- except IndexError:
- mbx.showerror("Error", "No ability selected!")
- #Deletes an ability
- def deleteAbility():
- try:
- if mbx.askyesno("Delete " + abilities[ABILTxt.curselection()[0]][1], "Are you sure you want to delete this ability?"):
- del abilities[ABILTxt.curselection()[0]]
- refrABIL()
- except IndexError:
- mbx.showerror("Error", "No ability selected!")
- #Shows an ability's description
- def inspectAbility():
- try:
- if len(abilities[ABILTxt.curselection()[0]][2]) > 0:
- mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n" + abilities[ABILTxt.curselection()[0]][2])
- else:
- mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n[None]")
- except IndexError:
- mbx.showerror("Error", "No ability selected!")
- #Sorts abilities by name or attribute stat
- def sortAbilities():
- choice = sortSkillsAbils(base, "ability").result
- if type(choice) == list:
- if choice[1] == 1:
- order = True
- else:
- order = False
- abilities.sort(key = op.itemgetter(choice[0]), reverse = order)
- refrABIL()
- #Prevents the program from exiting on one click
- def exitOverride():
- if mbx.askyesno("Warning! Data Loss Possibility Detected!", "Unsaved data will be lost if you quit. Are you sure you want to quit?"):
- base.destroy()
- #Dialog for choosing a method to set main stats
- class newCharacterStatRoot(sdg.Dialog):
- def body(self, master):
- self.title("New Character: Stats")
- self.resizable(False, False)
- self.choice = tk.IntVar()
- self.choice.set(0)
- tk.Label(master, text = "It is now time to set your ability scores / main stats.\nChoose a method below:", font = ftNormal).grid(row = 0)
- PB = tk.Radiobutton(master, text = "5E Point-Buy", value = 0, variable = self.choice, cursor = "hand2", font = ftNormal)
- DR = tk.Radiobutton(master, text = "Dice Rolls", value = 1, variable = self.choice, cursor = "hand2", font = ftNormal)
- MAN = tk.Radiobutton(master, text = "Manual Entry", value = 2, variable = self.choice, cursor = "hand2", font = ftNormal)
- PB.grid(row = 1, sticky = "w")
- DR.grid(row = 2, sticky = "w")
- MAN.grid(row = 3, sticky = "w")
- def apply(self):
- self.result = self.choice.get()
- #Dialog for a point-buy calculator
- class pointBuyRoot(sdg.Dialog):
- def body(self, master):
- self.title("New Character: Point-Buy Stats")
- self.resizable(False, False)
- self.STR = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.DEX = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.CON = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.INT = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.WIS = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.CHA = tk.Scale(master, from_ = 8, to = 15, orient = "horizontal", command = self.calculatePoints, font = ftNormal)
- self.bSTRVar = tk.IntVar()
- self.bDEXVar = tk.IntVar()
- self.bCONVar = tk.IntVar()
- self.bINTVar = tk.IntVar()
- self.bWISVar = tk.IntVar()
- self.bCHAVar = tk.IntVar()
- self.bSTRVar.set(-1)
- self.bDEXVar.set(-1)
- self.bCONVar.set(-1)
- self.bINTVar.set(-1)
- self.bWISVar.set(-1)
- self.bCHAVar.set(-1)
- bSTR = tk.Label(master, textvariable = self.bSTRVar, width = 2, relief = "ridge", font = ftNormal)
- bDEX = tk.Label(master, textvariable = self.bDEXVar, width = 2, relief = "ridge", font = ftNormal)
- bCON = tk.Label(master, textvariable = self.bCONVar, width = 2, relief = "ridge", font = ftNormal)
- bINT = tk.Label(master, textvariable = self.bINTVar, width = 2, relief = "ridge", font = ftNormal)
- bWIS = tk.Label(master, textvariable = self.bWISVar, width = 2, relief = "ridge", font = ftNormal)
- bCHA = tk.Label(master, textvariable = self.bCHAVar, width = 2, relief = "ridge", font = ftNormal)
- bSTR.grid(row = 2, column = 2, sticky = "s")
- bDEX.grid(row = 3, column = 2, sticky = "s")
- bCON.grid(row = 4, column = 2, sticky = "s")
- bINT.grid(row = 5, column = 2, sticky = "s")
- bWIS.grid(row = 6, column = 2, sticky = "s")
- bCHA.grid(row = 7, column = 2, sticky = "s")
- self.currentPoints = tk.IntVar()
- self.currentPoints.set(0)
- tk.Label(master, text = "Point Total:", font = ftLarge).grid(row = 0, column = 0, columnspan = 2)
- tk.Label(master, textvariable = self.currentPoints, relief = "ridge", width = 2, font = ftLarge).grid(row = 0, column = 1, sticky = "e")
- tk.Label(master, text = "/27", font = ftLarge).grid(row = 0, column = 2)
- tk.Label(master, text = "Attribute", font = ftSmall).grid(row = 1, column = 0)
- tk.Label(master, text = "Value", font = ftSmall).grid(row = 1, column = 1)
- tk.Label(master, text = "Modifier", font = ftSmall).grid(row = 1, column = 2)
- tk.Label(master, text = "Strength", width = 16, font = ftNormal).grid(row = 2, column = 0, sticky = "s")
- tk.Label(master, text = "Dexterity", width = 16, font = ftNormal).grid(row = 3, column = 0, sticky = "s")
- tk.Label(master, text = "Constitution", width = 16, font = ftNormal).grid(row = 4, column = 0, sticky = "s")
- tk.Label(master, text = "Intelligence", width = 16, font = ftNormal).grid(row = 5, column = 0, sticky = "s")
- tk.Label(master, text = "Wisdom", width = 16, font = ftNormal).grid(row = 6, column = 0, sticky = "s")
- tk.Label(master, text = "Charisma", width = 16, font = ftNormal).grid(row = 7, column = 0, sticky = "s")
- self.STR.grid(row = 2, column = 1)
- self.DEX.grid(row = 3, column = 1)
- self.CON.grid(row = 4, column = 1)
- self.INT.grid(row = 5, column = 1)
- self.WIS.grid(row = 6, column = 1)
- self.CHA.grid(row = 7, column = 1)
- def validate(self):
- if self.currentPoints.get() == 27 and mbx.askyesno("Confirmation", "Are you sure you want these values for your main stats?"):
- return 1
- elif self.currentPoints.get() != 27:
- mbx.showerror("Error", "You need to have a Point Total of 27 to have valid values!")
- return 0
- else:
- return 0
- def apply(self):
- resultString = ""
- resultString += str(self.STR.get()) + "|"
- resultString += str(self.DEX.get()) + "|"
- resultString += str(self.CON.get()) + "|"
- resultString += str(self.INT.get()) + "|"
- resultString += str(self.WIS.get()) + "|"
- resultString += str(self.CHA.get()) + "\n"
- resultString += str(self.bSTRVar.get()) + "|"
- resultString += str(self.bDEXVar.get()) + "|"
- resultString += str(self.bCONVar.get()) + "|"
- resultString += str(self.bINTVar.get()) + "|"
- resultString += str(self.bWISVar.get()) + "|"
- resultString += str(self.bCHAVar.get())
- self.result = resultString
- def calculatePoints(self, changedSlider):
- self.bSTRVar.set((self.STR.get() - 10) // 2)
- self.bDEXVar.set((self.DEX.get() - 10) // 2)
- self.bCONVar.set((self.CON.get() - 10) // 2)
- self.bINTVar.set((self.INT.get() - 10) // 2)
- self.bWISVar.set((self.WIS.get() - 10) // 2)
- self.bCHAVar.set((self.CHA.get() - 10) // 2)
- currentScores = []
- currentScores.append(self.STR.get())
- currentScores.append(self.DEX.get())
- currentScores.append(self.CON.get())
- currentScores.append(self.INT.get())
- currentScores.append(self.WIS.get())
- currentScores.append(self.CHA.get())
- pointsUsed = 0
- for score in currentScores:
- if score < 14:
- pointsUsed += score - 8
- elif score == 14:
- pointsUsed += 7
- elif score == 15:
- pointsUsed += 9
- self.currentPoints.set(pointsUsed)
- #Dialog for a dice-roll stat selector
- class diceRollStatsRoot(sdg.Dialog):
- def body(self, master):
- self.title("New Character: Dice Roll Stats")
- self.resizable(False, False)
- self.letters = ('A', 'B', 'C', 'D', 'E', 'F')
- self.stats = ('STR', 'CHA', 'WIS', 'INT', 'CON', 'DEX')
- self.rolled = False
- self.rolls = [0, 0, 0, 0, 0, 0]
- #self.rollsVar = tk.StringVar()
- #self.rollsVar.set("Press \"Roll\" to begin!")
- tk.Label(master, text = "You can swap values between attributes below.\nIn the \"six 4d6\" roll mode,\nthe lowest roll of each batch is not counted.", font = ftSmall).grid(row = 0, columnspan = 3)
- #rollsLbl = tk.Label(master, textvariable = self.rollsVar, width = 36, relief = "ridge", font = ftNormal)
- #rollsLbl.grid(row = 1, column = 0, columnspan = 2)
- self.swapOne = tk.Spinbox(master, width = 4, values = self.stats, wrap = True, font = ftNormal)
- self.swapTwo = tk.Spinbox(master, width = 4, values = self.stats, wrap = True, font = ftNormal)
- self.rollMode = tk.Spinbox(master, width = 8, values = ("six 1d20", "six 4d6"), wrap = True, font = ftNormal)
- self.swapOne.grid(row = 1, column = 0)
- self.swapTwo.grid(row = 1, column = 1)
- self.rollMode.grid(row = 2, column = 1)
- tk.Button(master, text = "Swap", command = self.swap, cursor = "hand2", font = ftNormal).grid(row = 1, column = 2)
- tk.Label(master, text = "Roll Mode", font = ftNormal).grid(row = 2, column = 0)
- tk.Button(master, text = "Roll", command = self.rollStats, cursor = "hand2", font = ftNormal).grid(row = 2, column = 2)
- tk.Label(master, text = "Attribute", font = ftSmall).grid(row = 3, column = 0)
- tk.Label(master, text = "Value", font = ftSmall).grid(row = 3, column = 1)
- tk.Label(master, text = "Modifier", font = ftSmall).grid(row = 3, column = 2)
- tk.Label(master, text = "Strength", font = ftNormal).grid(row = 4, column = 0)
- tk.Label(master, text = "Dexterity", font = ftNormal).grid(row = 5, column = 0)
- tk.Label(master, text = "Constitution", font = ftNormal).grid(row = 6, column = 0)
- tk.Label(master, text = "Intelligence", font = ftNormal).grid(row = 7, column = 0)
- tk.Label(master, text = "Wisdom", font = ftNormal).grid(row = 8, column = 0)
- tk.Label(master, text = "Charisma", font = ftNormal).grid(row = 9, column = 0)
- self.STR = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.DEX = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.CON = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.INT = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.WIS = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.CHA = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bSTR = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bDEX = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bCON = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bINT = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bWIS = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.bCHA = tk.Label(master, text = "?", width = 4, relief = "ridge", font = ftNormal)
- self.STR.grid(row = 4, column = 1)
- self.DEX.grid(row = 5, column = 1)
- self.CON.grid(row = 6, column = 1)
- self.INT.grid(row = 7, column = 1)
- self.WIS.grid(row = 8, column = 1)
- self.CHA.grid(row = 9, column = 1)
- self.bSTR.grid(row = 4, column = 2)
- self.bDEX.grid(row = 5, column = 2)
- self.bCON.grid(row = 6, column = 2)
- self.bINT.grid(row = 7, column = 2)
- self.bWIS.grid(row = 8, column = 2)
- self.bCHA.grid(row = 9, column = 2)
- def validate(self):
- if not self.rolled:
- mbx.showerror("Error", "You must roll at least once!")
- return 0
- elif not mbx.askyesno("Confirmation", "Are you sure you want these values for your main stats?"):
- return 0
- return 1
- def apply(self):
- resultString = ""
- resultString += self.STR["text"] + "|"
- resultString += self.DEX["text"] + "|"
- resultString += self.CON["text"] + "|"
- resultString += self.INT["text"] + "|"
- resultString += self.WIS["text"] + "|"
- resultString += self.CHA["text"] + "\n"
- resultString += self.bSTR["text"] + "|"
- resultString += self.bDEX["text"] + "|"
- resultString += self.bCON["text"] + "|"
- resultString += self.bINT["text"] + "|"
- resultString += self.bWIS["text"] + "|"
- resultString += self.bCHA["text"]
- self.result = resultString
- def setValues(self, master, tempStats):
- self.STR.config(text = str(tempStats[0]))
- self.DEX.config(text = str(tempStats[1]))
- self.CON.config(text = str(tempStats[2]))
- self.INT.config(text = str(tempStats[3]))
- self.WIS.config(text = str(tempStats[4]))
- self.CHA.config(text = str(tempStats[5]))
- self.bSTR.config(text = str((int(tempStats[0]) - 10) // 2))
- self.bDEX.config(text = str((int(tempStats[1]) - 10) // 2))
- self.bCON.config(text = str((int(tempStats[2]) - 10) // 2))
- self.bINT.config(text = str((int(tempStats[3]) - 10) // 2))
- self.bWIS.config(text = str((int(tempStats[4]) - 10) // 2))
- self.bCHA.config(text = str((int(tempStats[5]) - 10) // 2))
- def swap(self):
- if not self.rolled:
- mbx.showerror("Error", "You must roll at least once!")
- return
- tempStats = []
- localStats = ('STR', 'DEX', 'CON', 'INT', 'WIS', 'CHA')
- statA = localStats.index(self.swapOne.get())
- statB = localStats.index(self.swapTwo.get())
- if statA == statB:
- mbx.showerror("Error", "You can't swap a value with itself!")
- return
- tempStats.append(self.STR["text"])
- tempStats.append(self.DEX["text"])
- tempStats.append(self.CON["text"])
- tempStats.append(self.INT["text"])
- tempStats.append(self.WIS["text"])
- tempStats.append(self.CHA["text"])
- temp = tempStats[statA]
- tempStats[statA] = tempStats[statB]
- tempStats[statB] = temp
- self.setValues(self, tempStats)
- def rollStats(self):
- tempStats = [0, 0, 0, 0, 0, 0]
- tempRolls = []
- tempStr = ""
- if self.rollMode.get() == "six 1d20":
- for i in range(len(tempStats)):
- tempStats[i] = rnd.randint(1, 20)
- else:
- for i in range(len(tempStats)):
- for n in range(4):
- tempRolls.append(rnd.randint(1,6))
- tempRolls.remove(min(tempRolls))
- tempStats[i] = sum(tempRolls)
- tempRolls = []
- self.setValues(self, tempStats)
- self.rolled = True
- #Guides the player through character creation
- def newCharacter():
- if not mbx.askyesno("Warning! Data Loss Possibility Detected!", "Making a new character will erase all current data\nAre you sure you want to continue?"):
- return
- tempInfo = []
- tempHealth = []
- tempExp = []
- tempMStats = []
- tempBStats = []
- tempInt = 0
- tempIntB = 0
- tempStr = ""
- tempCount = 0
- infoChoices = ["name", "class", "deity", "race", "gender", "age", "height", "unit", "weight", "unit", "hair color", "eye color", "currency"]
- statChoices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
- while len(tempInfo) < 14:
- if tempCount < 5 or tempCount > 9:
- tempStr = sdg.askstring("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
- if type(tempStr) == str:
- tempInfo.append(tempStr)
- else:
- return
- if tempCount == 12:
- tempInt = sdg.askinteger("New Character: Info", "Enter how much currency you have:")
- if type(tempInt) == int:
- tempInfo.append(tempInt)
- else:
- return
- else:
- tempCount += 1
- elif tempCount > 5 and tempCount < 10:
- tempStr = sdg.askstring("New Character: Info", "Enter your unit of " + infoChoices[tempCount] + ":")
- if type(tempStr) != str:
- return
- tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
- if type(tempInt) == int:
- tempInfo.append(tempInt)
- tempInfo.append(tempStr)
- tempCount += 2
- else:
- return
- elif tempCount == 5:
- tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
- if type(tempInt) == int:
- tempInfo.append(tempInt)
- tempCount += 1
- else:
- return
- tempInt = sdg.askinteger("New Character: Health", "Enter your initial maximum health points:")
- if type(tempInt) != int:
- return
- tempHealth.append(tempInt)
- tempHealth.append(tempInt)
- tempExp.append(1)
- tempExp.append(0)
- if LEVLVar.get():
- tempExp.append(300)
- else:
- tempExp.append(110)
- tempInt = newCharacterStatRoot(base).result
- if type(tempInt) != int:
- return
- if tempInt == 0:
- tempStr = pointBuyRoot(base).result
- elif tempInt == 1:
- tempStr = diceRollStatsRoot(base).result
- if type(tempStr) != str:
- return
- if tempInt in (0, 1):
- for s in tempStr.split()[0].split('|'):
- tempMStats.append(int(s))
- for s in tempStr.split()[1].split('|'):
- tempBStats.append(int(s))
- elif tempInt == 2:
- tempCount = 0
- while len(tempMStats) < 6 and len(tempBStats) < 6:
- tempInt = sdg.askinteger("New Character: Manual Stats", "Enter your " + statChoices[tempCount] + ":")
- if type(tempInt) != int:
- return
- tempIntB = (tempInt - 10) // 2
- tempMStats.append(tempInt)
- tempBStats.append(tempIntB)
- tempCount += 1
- tempCount = 0
- for bit in tempInfo:
- info[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in tempHealth:
- health[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in tempExp:
- experience[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in tempMStats:
- mainStats[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in tempBStats:
- bonusStats[tempCount] = bit
- tempCount += 1
- while len(skills) > 0:
- del skills[0]
- while len(abilities) > 0:
- del abilities[0]
- while len(inventory) > 0:
- del inventory[0]
- refrSTAT()
- refrINFO()
- refrSKIL()
- refrABIL()
- refrINVT()
- mbx.showinfo("New Character: Complete", "Done! Your character's main information and stats are ready. You might want to add some abilities or skills for additional bits of information, such as racial bonuses, character backstory, or starting abilities. Good luck, adventurer!")
- #Saves the current character to a .dat file
- def saveCharacter():
- fileName = sdg.askstring("Save Character", "[Files are saved to the directory\nwhere this program is run]\nEnter the name of the file to save to:")
- if type(fileName) != str:
- return
- fileName += ".dat"
- if os.path.isfile(fileName):
- if not mbx.askyesno("Warning! File Already Exists!", "Do you want to overwrite " + fileName + "?"):
- return
- saveFile = open(fileName, "w")
- dlm = " || "
- adlm = " |\n"
- nl = "\n\n"
- temp = 0
- for bit in info:
- saveFile.write(str(bit))
- if temp == 13:
- saveFile.write(nl)
- else:
- saveFile.write(dlm)
- temp += 1
- temp = 0
- for bit in health:
- saveFile.write(str(bit))
- if temp == 1:
- saveFile.write(nl)
- else:
- saveFile.write(dlm)
- temp += 1
- temp = 0
- for bit in experience:
- saveFile.write(str(bit))
- if temp == 2:
- saveFile.write(nl)
- else:
- saveFile.write(dlm)
- temp += 1
- temp = 0
- for bit in mainStats:
- saveFile.write(str(bit))
- if temp == 5:
- saveFile.write(nl)
- else:
- saveFile.write(dlm)
- temp += 1
- temp = 0
- for bit in bonusStats:
- saveFile.write(str(bit))
- if temp == 5:
- saveFile.write(nl)
- else:
- saveFile.write(dlm)
- temp += 1
- temp = 1
- for sk in skills:
- saveFile.write(str(sk[0]) + dlm + sk[1])
- if temp != len(skills):
- saveFile.write(adlm)
- temp += 1
- saveFile.write(nl)
- temp = 1
- for ab in abilities:
- saveFile.write(str(ab[0]) + dlm + ab[1] + dlm + ab[2])
- if temp != len(abilities):
- saveFile.write(adlm)
- temp += 1
- saveFile.write(nl)
- temp = 1
- for item in inventory:
- tempAux = 1
- for bit in item:
- saveFile.write(str(bit))
- if tempAux < 9:
- saveFile.write(dlm)
- tempAux += 1
- if temp != len(inventory):
- saveFile.write(adlm)
- temp += 1
- saveFile.close()
- mbx.showinfo("Save Character", "Saved!\nCheck the working directory of this program for the file.")
- #Loads a character from a .dat file
- def loadCharacter():
- loaded = False
- while not loaded:
- try:
- fileName = sdg.askstring("Load Character", "[Files are loaded from the directory\nwhere this program is run]\nEnter the name of the file to load from:")
- if type(fileName) != str:
- return
- fileName += ".dat"
- loadFile = open(fileName, "r")
- loaded = True
- except FileNotFoundError:
- mbx.showerror("Error", "File not found!")
- if mbx.askyesno("Leveling Standard", "Do you want to use the 5E Experience Point brackets instead of C^2's Experience Formula?"):
- LEVLVar.set(True)
- else:
- LEVLVar.set(False)
- dlm = " || "
- adlm = " |\n"
- nl = "\n\n"
- contents = loadFile.read().split(nl)
- tempCountA = 0
- try:
- for bit in contents:
- tempList = []
- if adlm in bit:
- tempList = bit.split(adlm)
- tempCountB = 0
- for item in tempList:
- tempList[tempCountB] = item.split(dlm)
- tempCountC = 0
- for el in tempList[tempCountB]:
- if el == "True":
- tempList[tempCountB][tempCountC] = True
- elif el == "False":
- tempList[tempCountB][tempCountC] = False
- else:
- try:
- tempList[tempCountB][tempCountC] = int(el)
- except ValueError:
- try:
- tempList[tempCountB][tempCountC] = float(el)
- except ValueError:
- pass
- tempCountC += 1
- tempCountB += 1
- elif dlm in bit:
- tempList = bit.split(dlm)
- tempCountB = 0
- for el in tempList:
- try:
- tempList[tempCountB] = int(el)
- except ValueError:
- try:
- tempList[tempCountB] = float(el)
- except ValueError:
- pass
- tempCountB += 1
- contents[tempCountA] = tempList
- tempCountA += 1
- except:
- mbx.showerror("Error", "Unable to Load File!")
- return
- tempCount = 0
- for bit in contents[0]:
- info[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in contents[1]:
- health[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in contents[2]:
- experience[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in contents[3]:
- mainStats[tempCount] = bit
- tempCount += 1
- tempCount = 0
- for bit in contents[4]:
- bonusStats[tempCount] = bit
- tempCount += 1
- while len(skills) > 0:
- del skills[0]
- if len(contents[5]) > 0:
- if type(contents[5][0]) is list:
- for bit in contents[5]:
- skills.append(bit)
- else:
- skills.append(contents[5])
- while len(abilities) > 0:
- del abilities[0]
- if len(contents[6]) > 0:
- if type(contents[6][0]) is list:
- for bit in contents[6]:
- abilities.append(bit)
- else:
- abilities.append(contents[6])
- while len(inventory) > 0:
- del inventory[0]
- if len(contents[7]) > 0:
- if type(contents[7][0]) is list:
- for bit in contents[7]:
- inventory.append(bit)
- else:
- inventory.append(contents[7])
- mbx.showinfo("Load Character", "Loaded!\nYour journey continues...")
- refrSTAT()
- refrINFO()
- refrINVT()
- refrSKIL()
- refrABIL()
- #Lists for main program data
- mainStats = [10, 10, 10, 10, 10, 10]
- bonusStats = [0, 0, 0, 0, 0, 0]
- savingThrows = [0, 0, 0]
- health = [0, 10]
- experience = [1, 0, 300]
- info = ["name", "class", "deity", "race", "gender", 18, 170, "cm", 70, "kg", "brown", "black", "currency", 0]
- skills = []
- abilities = []
- inventory = []
- brackets5E = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000]
- #Creation of base tk window
- base = tk.Tk()
- base.protocol("WM_DELETE_WINDOW", exitOverride)
- #Declaration of fonts
- ftSmall = tkf.Font(family = "Consolas", size = 8)
- ftNormal = tkf.Font(family = "Consolas", size = 10)
- ftNormUnd = tkf.Font(family = "Consolas", size = 10, underline = 1)
- ftLarge = tkf.Font(family = "Consolas", size = 12)
- ftTitle = tkf.Font(family = "Consolas", size = 12, weight = "bold", slant = "italic")
- ftBigTitle = tkf.Font(family = "Consolas", size = 16, weight = "bold", slant = "italic")
- ftName = tkf.Font(family = "Consolas", size = 16, weight = "bold")
- ftSubtitle = tkf.Font(family = "Consolas", size = 12, slant = "italic")
- ftDice = tkf.Font(family = "Consolas", size = 12, weight = "bold")
- #Frame for stats
- STATPnl = tk.Frame(base, bd = 4, relief = "groove")
- STATPnl.grid(row = 1, column = 0, rowspan = 2, padx = 8, sticky = "n")
- #Stats labels and buttons
- STATTitl = tk.Label(STATPnl, text = "Stats", width = 8, bd = 4, relief = "raised", font = ftTitle)
- LEVLLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- LEVLVar = tk.BooleanVar()
- LEVLVar.set(True)
- LEVLChk = tk.Checkbutton(STATPnl, text = "5E XP", command = ChangeXP, variable = LEVLVar, font = ftNormal)
- XPLbl = tk.Label(STATPnl, width = 16, relief = "ridge", font = ftLarge, anchor = "w")
- XPPlusBtn = tk.Button(STATPnl, text = "+", command = XPUp, cursor = "hand2", font = ftNormal)
- HPLbl = tk.Label(STATPnl, width = 12, relief = "ridge", font = ftLarge, anchor = "w")
- HPPLUSBtn = tk.Button(STATPnl, text = "+", command = HPUp, cursor = "hand2", font = ftNormal)
- HPMINSBtn = tk.Button(STATPnl, text = "-", command = HPDown, cursor = "hand2", font = ftNormal)
- STRLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- DEXLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- CONLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- INTLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- WISLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- CHALbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
- STRBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- DEXBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- CONBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- INTBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- WISBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- CHABLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftLarge)
- FORTLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
- REFLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
- WILLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
- STATEDITBtn = tk.Button(STATPnl, text = "Edit Stats", width = 10, command = editStat, cursor = "hand2", font = ftSmall)
- #Grid assignments of stats elements
- STATTitl.grid(row = 0, columnspan = 3, pady = 4)
- LEVLLbl.grid(row = 1, column = 0, columnspan = 3, pady = 2)
- XPLbl.grid(row = 2, column = 0, columnspan = 2, padx = 4, pady = 2, sticky = "W")
- XPPlusBtn.grid(row = 2, column = 2)
- HPLbl.grid(row = 3, column = 0, padx = 4, pady = 2, sticky = "W")
- HPPLUSBtn.grid(row = 3, column = 1, padx = 2)
- HPMINSBtn.grid(row = 3, column = 2, padx = 2)
- STRLbl.grid(row = 4, column = 0, padx = 4, pady = 2, sticky = "E")
- DEXLbl.grid(row = 5, column = 0, padx = 4, pady = 2, sticky = "E")
- CONLbl.grid(row = 6, column = 0, padx = 4, pady = 2, sticky = "E")
- INTLbl.grid(row = 7, column = 0, padx = 4, pady = 2, sticky = "E")
- WISLbl.grid(row = 8, column = 0, padx = 4, pady = 2, sticky = "E")
- CHALbl.grid(row = 9, column = 0, padx = 4, pady = 2, sticky = "E")
- STRBLbl.grid(row = 4, column = 1, columnspan = 2, padx = 4, pady = 2)
- DEXBLbl.grid(row = 5, column = 1, columnspan = 2, padx = 4, pady = 2)
- CONBLbl.grid(row = 6, column = 1, columnspan = 2, padx = 4, pady = 2)
- INTBLbl.grid(row = 7, column = 1, columnspan = 2, padx = 4, pady = 2)
- WISBLbl.grid(row = 8, column = 1, columnspan = 2, padx = 4, pady = 2)
- CHABLbl.grid(row = 9, column = 1, columnspan = 2, padx = 4, pady = 2)
- FORTLbl.grid(row = 10, columnspan = 3, padx = 4, pady = 2)
- REFLLbl.grid(row = 11, columnspan = 3, padx = 4, pady = 2)
- WILLLbl.grid(row = 12, columnspan = 3, padx = 4, pady = 2)
- STATEDITBtn.grid(row = 13, column = 0, padx = 4, pady = 2)
- LEVLChk.grid(row = 13, column = 1, columnspan = 2)
- refrSTAT()
- #Frame for information
- INFOPnl = tk.Frame(base, bd = 4, relief = "groove")
- INFOPnl.grid(row = 1, column = 1, sticky = "nw")
- #Information labels and buttons
- INFOTitl = tk.Label(INFOPnl, text ="Information", width = 32, bd = 4, relief = "raised", font = ftTitle)
- INFOTitl.grid(row = 0, columnspan = 6, pady = 4)
- NAMELbl = tk.Label(INFOPnl, width = 36, bd = 4, relief = "ridge", font = ftName)
- CLSSLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- DETYLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- RACELbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- GNDRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- AYGELbl = tk.Label(INFOPnl, width = 10, relief = "ridge", font = ftLarge)
- HGHTLbl = tk.Label(INFOPnl, width = 10, relief = "ridge", font = ftLarge)
- WGHTLbl = tk.Label(INFOPnl, width = 10, relief = "ridge", font = ftLarge)
- INFOEDITBtn = tk.Button(INFOPnl, text = "Edit Info", width = 12, command = editInfo, cursor = "hand2", font = ftSmall)
- HAIRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- EYESLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
- MONYLbl = tk.Label(INFOPnl, width = 32, relief = "ridge", font = ftLarge)
- MONYCHNGBtn = tk.Button(INFOPnl, text = "Credit/Debit", width = 12, command = changeMoney, cursor = "hand2", font = ftSmall)
- #Grid assignments of information elements
- NAMELbl.grid(row = 1, columnspan = 4, padx = 16, pady = 4)
- CLSSLbl.grid(row = 2, column = 0, columnspan = 2, pady = 4)
- RACELbl.grid(row = 2, column = 2, columnspan = 2, padx = 6)
- DETYLbl.grid(row = 3, column = 0, columnspan = 2, pady = 4)
- GNDRLbl.grid(row = 3, column = 2, columnspan = 2, padx = 6)
- HAIRLbl.grid(row = 4, column = 0, columnspan = 2, pady = 4)
- EYESLbl.grid(row = 4, column = 2, columnspan = 2, padx = 6)
- AYGELbl.grid(row = 5, column = 0, pady = 4)
- HGHTLbl.grid(row = 5, column = 1)
- WGHTLbl.grid(row = 5, column = 2)
- INFOEDITBtn.grid(row = 5, column = 3)
- MONYLbl.grid(row = 6, column = 0, columnspan = 3)
- MONYCHNGBtn.grid(row = 6, column = 3, pady = 11)
- refrINFO()
- #Frame for inventory
- INVTPnl = tk.Frame(base, bd = 4, relief = "groove")
- INVTPnl.grid(row = 2, column = 1, rowspan = 2, columnspan = 2, pady = 8, sticky = "w")
- #Inventory elements
- INVTTitl = tk.Label(INVTPnl, text = "Inventory", width = 24, bd = 4, relief = "raised", font = ftTitle)
- INVTNEWWBtn = tk.Button(INVTPnl, text = "Create Item", width = 12, command = newItem, cursor = "hand2", font = ftSmall)
- INVTEDITBtn = tk.Button(INVTPnl, text = "Edit Item", width = 12, command = editItem, cursor = "hand2", font = ftSmall)
- INVTDELTBtn = tk.Button(INVTPnl, text = "Delete Item", width = 12, command = deleteItem, cursor = "hand2", font = ftSmall)
- INVTINSPBtn = tk.Button(INVTPnl, text = "Inspect Item", width = 12, command = inspectItem, cursor = "hand2", font = ftSmall)
- INVTSORTBtn = tk.Button(INVTPnl, text = "Sort Items", width = 12, command = sortItems, cursor = "hand2", font = ftSmall)
- INVTLbl = tk.Label(INVTPnl, text = "Name\t\t\t\t\tCount\tWeight\tDice\tCharges\tEquipped", font = ftNormUnd)
- INVTTxt = tk.Listbox(INVTPnl, height = 11, width = 80, cursor = "cross", font = ftNormal)
- IVNTScr = tk.Scrollbar(INVTPnl, orient = "vertical", command = INVTTxt.yview)
- INVTTxt.config(yscrollcommand = IVNTScr.set)
- INVTENCMLbl = tk.Label(INVTPnl, text = "Encumberance:", width = 24, anchor = "w", relief = "ridge", font = ftNormal)
- #Grid assignments of inventory elements
- INVTTitl.grid(row = 0, column = 0, pady = 4)
- INVTNEWWBtn.grid(row = 0, column = 1)
- INVTEDITBtn.grid(row = 0, column = 2)
- INVTDELTBtn.grid(row = 1, column = 2, columnspan = 2)
- INVTINSPBtn.grid(row = 1, column = 1, columnspan = 2)
- INVTSORTBtn.grid(row = 0, column = 3)
- INVTLbl.grid(row = 2, columnspan = 4, sticky = "w")
- INVTTxt.grid(row = 3, column = 0, columnspan = 4)
- IVNTScr.grid(row = 2, column = 4, rowspan = 2, sticky = "ns")
- INVTENCMLbl.grid(row = 4, columnspan = 5, pady = 2, sticky = "e")
- refrINVT()
- #Frame for dice
- DICEPnl = tk.Frame(base, bd = 4, relief = "groove")
- DICEPnl.grid(row = 3, column = 0, padx = 8, pady = 8, sticky = "w")
- #Dice labels and buttons
- DICETitl = tk.Label(DICEPnl, text = "Dice", width = 8, bd = 4, relief = "raised", font = ftTitle)
- DICELbl = tk.Label(DICEPnl, width = 13, text = "0 | d?", relief = "groove", font = ftDice)
- DICEd2Btn = tk.Button(DICEPnl, width = 4, text = "Coin", command = rollDice(2), cursor = "hand2", font = ftNormal)
- DICEd4Btn = tk.Button(DICEPnl, width = 4, text = "d4", command = rollDice(4), cursor = "hand2", font = ftNormal)
- DICEd6Btn = tk.Button(DICEPnl, width = 4, text = "d6", command = rollDice(6), cursor = "hand2", font = ftNormal)
- DICEd8Btn = tk.Button(DICEPnl, width = 4, text = "d8", command = rollDice(8), cursor = "hand2", font = ftNormal)
- DICEd10Btn = tk.Button(DICEPnl, width = 4, text = "d10", command = rollDice(10), cursor = "hand2", font = ftNormal)
- DICEd12Btn = tk.Button(DICEPnl, width = 4, text = "d12", command = rollDice(12), cursor = "hand2", font = ftNormal)
- DICEd20Btn = tk.Button(DICEPnl, width = 4, text = "d20", command = rollDice(20), cursor = "hand2", font = ftNormal)
- DICEd100Btn = tk.Button(DICEPnl, width = 4, text = "d100", command = rollDice(100), cursor = "hand2", font = ftNormal)
- DICERstBtn = tk.Button(DICEPnl, width = 4, text = "Reset", command = rollDice(0), cursor = "hand2", font = ftNormal)
- #Grid assignments of dice elements
- DICETitl.grid(row = 0, column = 0, columnspan = 3, pady = 4)
- DICELbl.grid(row = 1, column = 0, columnspan = 3, padx = 32, pady = 4)
- DICEd2Btn.grid(row = 2, column = 0, pady = 2)
- DICEd4Btn.grid(row = 2, column = 1)
- DICEd6Btn.grid(row = 2, column = 2)
- DICEd8Btn.grid(row = 3, column = 0, pady = 2)
- DICEd10Btn.grid(row = 3, column = 1)
- DICEd12Btn.grid(row = 3, column = 2)
- DICERstBtn.grid(row = 4, column = 0, pady = 2)
- DICEd20Btn.grid(row = 4, column = 1)
- DICEd100Btn.grid(row = 4, column = 2)
- #Panel for skills
- SKILPnl = tk.Frame(base, bd = 4, relief = "groove")
- SKILPnl.grid(row = 2, column = 3, rowspan = 2, padx = 8, pady = 8, sticky = "ne")
- #Skill elements
- SKILTitl = tk.Label(SKILPnl, text = "Skills", width = 8, bd = 4, relief = "raised", font = ftTitle)
- SKILTxt = tk.Listbox(SKILPnl, height = 9, width = 32, cursor = "cross", font = ftNormal)
- SKILScrV = tk.Scrollbar(SKILPnl, orient = "vertical", command = SKILTxt.yview)
- SKILScrH = tk.Scrollbar(SKILPnl, orient = "horizontal", command = SKILTxt.xview)
- SKILTxt.config(yscrollcommand = SKILScrV.set, xscrollcommand = SKILScrH.set)
- SKILNEWWBtn = tk.Button(SKILPnl, text = "Create Skill", width = 12, command = newSkill, cursor = "hand2", font = ftSmall)
- SKILEDITBtn = tk.Button(SKILPnl, text = "Edit Skill", width = 12, command = editSkill, cursor = "hand2", font = ftSmall)
- SKILDELTBtn = tk.Button(SKILPnl, text = "Delete Skill", width = 12, command = deleteSkill, cursor = "hand2", font = ftSmall)
- SKILSORTBtn = tk.Button(SKILPnl, text = "Sort Skills", width = 12, command = sortSkills, cursor = "hand2", font = ftSmall)
- SKILSCORVar = tk.BooleanVar()
- SKILSCORVar.set(False)
- SKILSCORSwt = tk.Checkbutton(SKILPnl, text = "Apply +/- Skills To Stats", command = changeScores, variable = SKILSCORVar, font = ftSmall)
- SKILSCORBtn = tk.Button(SKILPnl, text = "?", command = showPrefixInfo, cursor = "hand2", font = ftSmall)
- #Grid assignments of skill elements
- SKILTitl.grid(row = 0, columnspan = 3, pady = 4)
- SKILTxt.grid(row = 4, column = 0, columnspan = 2)
- SKILScrV.grid(row = 4, column = 2, rowspan = 2, sticky = "ns")
- SKILScrH.grid(row = 5, column = 0, columnspan = 2, pady = 2, sticky = "we")
- SKILNEWWBtn.grid(row = 1, column = 0)
- SKILEDITBtn.grid(row = 1, column = 1)
- SKILDELTBtn.grid(row = 2, column = 0)
- SKILSORTBtn.grid(row = 2, column = 1)
- SKILSCORSwt.grid(row = 3, column = 0, columnspan = 2, padx = 8, sticky = "w")
- SKILSCORBtn.grid(row = 3, column = 1, padx = 8, sticky = "e")
- refrSKIL()
- #Frame for abilities
- ABILPnl = tk.Frame(base, bd = 4, relief = "groove")
- ABILPnl.grid(row = 1, column = 2, columnspan = 2, padx = 8, sticky = "n")
- #Ability elements
- ABILTitl = tk.Label(ABILPnl, text = "Abilities", width = 16, bd = 4, relief = "raised", font = ftTitle)
- ABILTxt = tk.Listbox(ABILPnl, height = 10, width = 48, cursor = "cross", font = ftNormal)
- ABILScrV = tk.Scrollbar(ABILPnl, orient = "vertical", command = ABILTxt.yview)
- ABILScrH = tk.Scrollbar(ABILPnl, orient = "horizontal", command = ABILTxt.xview)
- ABILTxt.config(yscrollcommand = ABILScrV.set, xscrollcommand = ABILScrH.set)
- ABILNEWWBtn = tk.Button(ABILPnl, text = "Create Ability", width = 16, command = newAbility, cursor = "hand2", font = ftSmall)
- ABILEDITBtn = tk.Button(ABILPnl, text = "Edit Ability", width = 16, command = editAbility, cursor = "hand2", font = ftSmall)
- ABILDELTBtn = tk.Button(ABILPnl, text = "Delete Ability", width = 16, command = deleteAbility, cursor = "hand2", font = ftSmall)
- ABILINSPBtn = tk.Button(ABILPnl, text = "Inspect Ability", width = 16, command = inspectAbility, cursor = "hand2", font = ftSmall)
- ABILSORTBtn = tk.Button(ABILPnl, text = "Sort Abilities", width = 16, command = sortAbilities, cursor = "hand2", font = ftSmall)
- #Grid assignments of ability elements
- ABILTitl.grid(row = 0, columnspan = 4, pady = 4)
- ABILTxt.grid(row = 3, column = 0, columnspan = 3)
- ABILScrV.grid(row = 3, column = 3, rowspan = 2, sticky = "ns")
- ABILScrH.grid(row = 4, columnspan = 3, sticky = "we")
- ABILNEWWBtn.grid(row = 1, column = 0, sticky = "e")
- ABILEDITBtn.grid(row = 1, column = 1, sticky = "e")
- ABILSORTBtn.grid(row = 1, column = 2, sticky = "e")
- ABILINSPBtn.grid(row = 2, column = 0, columnspan = 2)
- ABILDELTBtn.grid(row = 2, column = 1, columnspan = 2)
- #Frame for menu
- MENUPnl = tk.Frame(base, bd = 4, relief = "groove")
- MENUPnl.grid(row = 0, columnspan = 4, pady = 8)
- #Menu labels and buttons
- MENUTitl = tk.Label(MENUPnl, text = "C²'s D&D Character Sheet", width = 64, bd = 4, relief = "raised", font = ftBigTitle)
- MENUNEWWBtn = tk.Button(MENUPnl, text = "New Character", width = 16, command = newCharacter, cursor = "hand2", font = ftLarge)
- MENUSAVEBtn = tk.Button(MENUPnl, text = "Save Character", width = 16, command = saveCharacter, cursor = "hand2", font = ftLarge)
- MENULOADBtn = tk.Button(MENUPnl, text = "Load Character", width = 16, command = loadCharacter, cursor = "hand2", font = ftLarge)
- MENUVERS = tk.Label(MENUPnl, text = "Version 1.2.4", width = 16, bd = 4, relief = "ridge", font = ftSubtitle)
- #Grid assignments of menu elements
- MENUTitl.grid(row = 0, columnspan = 4, padx = 16, pady = 4)
- MENUNEWWBtn.grid(row = 1, column = 0, pady = 4)
- MENUSAVEBtn.grid(row = 1, column = 1)
- MENULOADBtn.grid(row = 1, column = 2)
- MENUVERS.grid(row = 1, column = 3)
- #Initialization of main window and final settings
- base.title("DnD Character Sheet")
- base.resizable(False, False)
- base.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment