cookchar

Tkinter DnD Character Sheet v1.1

Oct 24th, 2017
96
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import tkinter as tk
  2. import tkinter.simpledialog as sdg
  3. import tkinter.messagebox as mbx
  4. import tkinter.font as tkf
  5. import tkinter.tix as tix
  6. import random as rnd
  7. import operator as op
  8. import os
  9.  
  10. #Charlie Cook's Dungeons & Dragons Character Sheet Program
  11. #Begun early June 2017
  12. #Last updated late October 2017
  13.  
  14. def updtSAVETHRW():
  15.     savingThrows[0] = mainStats[2] + bonusStats[2]
  16.     savingThrows[1] = mainStats[1] + bonusStats[1]
  17.     savingThrows[2] = mainStats[4] + bonusStats[4]
  18.  
  19. def levelUp():
  20.     experience[0] += 1
  21.     experience[1] -= experience[2]
  22.     if LEVLVar.get():
  23.         experience[2] = brackets5E[experience[0]]
  24.     else:
  25.         experience[2] = 100 + 10 * experience[0]
  26.     mbx.showinfo("Level Up!","Congratulations!\nYou are now Level " + str(experience[0]))
  27.  
  28. def refrSTAT():
  29.     LEVLLbl.config(text = "Level: " + str(experience[0]))
  30.     HPLbl.config(text = "HP:" + str(health[0]) + "/" + str(health[1]))
  31.     XPLbl.config(text = "XP:" + str(experience[1]) + "/" + str(experience[2]))
  32.  
  33.     STRLbl.config(text = "STR: " + str(mainStats[0]))
  34.     DEXLbl.config(text = "DEX: " + str(mainStats[1]))
  35.     CONLbl.config(text = "CON: " + str(mainStats[2]))
  36.     INTLbl.config(text = "INT: " + str(mainStats[3]))
  37.     WISLbl.config(text = "WIS: " + str(mainStats[4]))
  38.     CHALbl.config(text = "CHA: " + str(mainStats[5]))
  39.  
  40.     if bonusStats[0] > 0:
  41.         STRBLbl.config(text = "+" + str(bonusStats[0]))
  42.     else:
  43.         STRBLbl.config(text = str(bonusStats[0]))
  44.  
  45.     if bonusStats[1] > 0:
  46.         DEXBLbl.config(text = "+" + str(bonusStats[1]))
  47.     else:
  48.         DEXBLbl.config(text = str(bonusStats[1]))
  49.  
  50.     if bonusStats[2] > 0:
  51.         CONBLbl.config(text = "+" + str(bonusStats[2]))
  52.     else:
  53.         CONBLbl.config(text = str(bonusStats[2]))
  54.  
  55.     if bonusStats[3] > 0:
  56.         INTBLbl.config(text = "+" + str(bonusStats[3]))
  57.     else:
  58.         INTBLbl.config(text = str(bonusStats[3]))
  59.  
  60.     if bonusStats[4] > 0:
  61.         WISBLbl.config(text = "+" + str(bonusStats[4]))
  62.     else:
  63.         WISBLbl.config(text = str(bonusStats[4]))
  64.  
  65.     if bonusStats[5] > 0:
  66.         CHABLbl.config(text = "+" + str(bonusStats[5]))
  67.     else:
  68.         CHABLbl.config(text = str(bonusStats[5]))
  69.  
  70.     updtSAVETHRW()
  71.  
  72.     FORTLbl.config(text = "Fortitude: " + str(savingThrows[0]))
  73.     REFLLbl.config(text = "Reflex: " + str(savingThrows[1]))
  74.     WILLLbl.config(text = "Will: " + str(savingThrows[2]))
  75.  
  76. def HPUp():
  77.     if health[0] < health[1]:
  78.         health[0] += 1
  79.         refrSTAT()
  80.  
  81. def HPDown():
  82.     if health[0] > 0:
  83.         health[0] -= 1
  84.         refrSTAT()
  85.  
  86. def XPUp():
  87.     temp = sdg.askinteger("Add XP", "Enter how many experience points you've earned:")
  88.     if type(temp) == int:
  89.         experience[1] += temp
  90.  
  91.     while experience[1] > experience[2]:
  92.         levelUp()
  93.         refrSTAT()
  94.  
  95.     refrSTAT()
  96.  
  97. def ChangeXP():
  98.     if mbx.askokcancel("Warning!", "Changing the level up brackets may make things weird. Is it okay to continue?"):
  99.         if LEVLVar.get():
  100.             tempLvl = experience[0] - 1
  101.             tempXP = experience[1]
  102.             tempMXP = tempLvl * 10 + 100
  103.  
  104.             while tempLvl > 0:
  105.                 tempXP += tempMXP
  106.                 tempLvl -= 1
  107.                 tempMXP = tempLvl * 10 + 100
  108.  
  109.             print(tempXP)
  110.  
  111.             experience[1] = tempXP
  112.             experience[0] = 1
  113.             experience[2] = brackets5E[1]
  114.  
  115.             while experience[1] > experience[2]:
  116.                 levelUp()
  117.                 refrSTAT()
  118.         else:
  119.             tempLvl = experience[0] - 1
  120.             tempXP = experience[1]
  121.             tempMXP = brackets5E[tempLvl]
  122.  
  123.             while tempLvl > 0:
  124.                 tempXP += tempMXP
  125.                 tempLvl -= 1
  126.                 tempMXP = brackets5E[tempLvl]
  127.  
  128.             print(tempXP)
  129.  
  130.             experience[1] = tempXP
  131.             experience[0] = 1
  132.             experience[2] = 110
  133.  
  134.             while experience[1] > experience[2]:
  135.                 levelUp()
  136.                 refrSTAT()
  137.         refrSTAT()
  138.     else:
  139.         LEVLVar.set(not LEVLVar.get())
  140.  
  141. class editStatRoot(sdg.Dialog):
  142.     def body(self, master):
  143.         self.title("Edit Stats")
  144.         self.resizable(False, False)
  145.         self.choice = tk.IntVar()
  146.         self.choice.set(1)
  147.         tk.Label(master, text = "Choose a stat item to edit:", font = ftSmall).grid(row = 0)
  148.        
  149.         STR = tk.Radiobutton(master, text = "Strength", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  150.         DEX = tk.Radiobutton(master, text = "Dexterity", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  151.         CON = tk.Radiobutton(master, text = "Constitution", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  152.         INT = tk.Radiobutton(master, text = "Intelligence", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  153.         WIS = tk.Radiobutton(master, text = "Wisdom", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  154.         CHA = tk.Radiobutton(master, text = "Charisma", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  155.  
  156.         LEV = tk.Radiobutton(master, text = "Level", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  157.         XP = tk.Radiobutton(master, text = "Experience", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  158.         HPC = tk.Radiobutton(master, text = "Current Health", value = 9, variable = self.choice, cursor = "hand2", font = ftSmall)
  159.         HPM = tk.Radiobutton(master, text = "Maximum Health", value = 10, variable = self.choice, cursor = "hand2", font = ftSmall)
  160.  
  161.         STR.grid(row = 5, sticky = "w")
  162.         DEX.grid(row = 6, sticky = "w")
  163.         CON.grid(row = 7, sticky = "w")
  164.         INT.grid(row = 8, sticky = "w")
  165.         WIS.grid(row = 9, sticky = "w")
  166.         CHA.grid(row = 10, sticky = "w")
  167.  
  168.         LEV.grid(row = 1, sticky = "w")
  169.         XP.grid(row = 2, sticky = "w")
  170.         HPC.grid(row = 3, sticky = "w")
  171.         HPM.grid(row = 4, sticky = "w")
  172.  
  173.     def apply(self):
  174.         self.result = self.choice.get()
  175.  
  176. class editStatLeaf(sdg.Dialog):
  177.     def __init__(self, master = None, m = 0):
  178.         self.mode = m - 1
  179.         super().__init__(master)
  180.  
  181.     def body(self, master):
  182.         choices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
  183.         self.title("Edit " + choices[self.mode])
  184.         self.resizable(False, False)
  185.         tk.Label(master, text = "Enter your new " + choices[self.mode].lower() + ":", font = ftSmall).grid(row = 0)
  186.         tk.Label(master, text = "Enter your new " + choices[self.mode].lower() + " bonus:", font = ftSmall).grid(row = 2)
  187.         tk.Label(master, text = "Note: Blank/Unchanged fields\nwill result in no change", font = ftSmall).grid(row = 4)
  188.  
  189.         self.Value = tk.Entry(master, font = ftSmall)
  190.         self.Bonus = tk.Entry(master, font = ftSmall)
  191.  
  192.         self.Value.insert(0, mainStats[self.mode])
  193.         self.Bonus.insert(0, bonusStats[self.mode])
  194.  
  195.         self.Value.grid(row = 1)
  196.         self.Bonus.grid(row = 3)
  197.  
  198.     def apply(self):
  199.         try:
  200.             temp = []
  201.  
  202.             if len(self.Value.get()) > 0:
  203.                 temp.append(int(self.Value.get()))
  204.             else:
  205.                 temp.append("")
  206.  
  207.             if len(self.Bonus.get()) > 0:
  208.                 temp.append(int(self.Bonus.get()))
  209.             else:
  210.                 temp.append("")
  211.  
  212.             self.result = temp
  213.  
  214.         except:
  215.             mbx.showerror("Error","Invalid Input")
  216.             self.result = []
  217.  
  218. def editStat():
  219.     choice = editStatRoot(base).result
  220.  
  221.     if type(choice) == int:
  222.         if choice < 7:
  223.             temp = editStatLeaf(base, choice).result
  224.  
  225.         elif choice == 7:
  226.             temp = sdg.askinteger("Edit Level", "Enter your new level:", initialvalue = experience[0])
  227.             if type(temp) == int:
  228.                 experience[0] = temp
  229.                 experience[2] = 100 + 10 * experience[0]
  230.  
  231.         elif choice == 8:
  232.             temp = sdg.askinteger("Edit Experience", "Enter your new current experience points:", initialvalue = experience[1])
  233.             if type(temp) == int:
  234.                 experience[1] = temp
  235.                 while experience[1] > experience[2]:
  236.                     levelUp()
  237.  
  238.         elif choice == 9:
  239.             temp = health[1] + 1
  240.  
  241.             while temp > health[1]:
  242.                 temp = sdg.askinteger("Edit Health", "Enter your new current health:", initialvalue = health[0])
  243.                 if type(temp) != int:
  244.                     return
  245.                 elif temp > health[1]:
  246.                     mbx.showerror("Error", "You can't overcharge your health!")
  247.  
  248.             if type(temp) == int:
  249.                 health[0] = temp
  250.  
  251.         elif choice == 10:
  252.             temp = sdg.askinteger("Edit Health", "Enter your new maximum health:", initialvalue = health[1])
  253.             if type(temp) == int:
  254.                 health[1] = temp
  255.                 if health[0] > health[1]:
  256.                     health[0] = health[1]
  257.  
  258.         if type(temp) == list:
  259.             if type(temp[0]) == int:
  260.                 mainStats[choice - 1] = temp[0]
  261.  
  262.             if type(temp[1]) == int:
  263.                 bonusStats[choice - 1] = temp[1]
  264.  
  265.             refrSTAT()
  266.  
  267.         elif type(temp) == int:
  268.             refrSTAT()
  269.  
  270. def refrINFO():
  271.     NAMELbl.config(text = info[0])
  272.     CLSSLbl.config(text = info[1])
  273.     DETYLbl.config(text = info[2])
  274.     RACELbl.config(text = info[3])
  275.     GNDRLbl.config(text = info[4])
  276.     AYGELbl.config(text = "Age: " + str(info[5]))
  277.     HGHTLbl.config(text = str(info[6]) + " " + info[7])
  278.     WGHTLbl.config(text = str(info[8]) + " " + info[9])
  279.     HAIRLbl.config(text = "Hair: " + info[10])
  280.     EYESLbl.config(text = "Eyes: " + info[11])
  281.     MONYLbl.config(text = str(info[13]) + " " + info[12])
  282.  
  283. def changeMoney():
  284.     debit = sdg.askinteger("Change Money", "How much money to add/remove?")
  285.     if type(debit) == int:
  286.         info[13] += debit
  287.         refrINFO()
  288.  
  289. class editInfoRoot(sdg.Dialog):
  290.     def body(self, master):
  291.         self.title("Edit Info")
  292.         self.resizable(False, False)
  293.         self.choice = tk.IntVar()
  294.         self.choice.set(1)
  295.         tk.Label(master, text = "Choose an info item to edit:", font = ftSmall).grid(row = 0)
  296.        
  297.         Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  298.         Class = tk.Radiobutton(master, text = "Class", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  299.         Deity = tk.Radiobutton(master, text = "Deity", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  300.         Race = tk.Radiobutton(master, text = "Race", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  301.         Gender = tk.Radiobutton(master, text = "Gender", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  302.         Age = tk.Radiobutton(master, text = "Age", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  303.         Height = tk.Radiobutton(master, text = "Height", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  304.         Weight = tk.Radiobutton(master, text = "Weight", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  305.         HairColor = tk.Radiobutton(master, text = "Hair Color", value = 9, variable = self.choice, cursor = "hand2", font = ftSmall)
  306.         EyeColor = tk.Radiobutton(master, text = "Eye Color", value = 10, variable = self.choice, cursor = "hand2", font = ftSmall)
  307.         Currency = tk.Radiobutton(master, text = "Currency", value = 11, variable = self.choice, cursor = "hand2", font = ftSmall)
  308.  
  309.         Name.grid(row = 1, sticky = "w")
  310.         Class.grid(row = 2, sticky = "w")
  311.         Deity.grid(row = 3, sticky = "w")
  312.         Race.grid(row = 4, sticky = "w")
  313.         Gender.grid(row = 5, sticky = "w")
  314.         Age.grid(row = 6, sticky = "w")
  315.         Height.grid(row = 7, sticky = "w")
  316.         Weight.grid(row = 8, sticky = "w")
  317.         HairColor.grid(row = 9, sticky = "w")
  318.         EyeColor.grid(row = 10, sticky = "w")
  319.         Currency.grid(row = 11, sticky = "w")
  320.  
  321.     def apply(self):
  322.         self.result = self.choice.get()
  323.  
  324. class editWH(sdg.Dialog):
  325.     def __init__(self, master = None, m = 9):
  326.         self.mode = m - 7
  327.         super().__init__(master)
  328.  
  329.     def toggleUnit(self):
  330.         if self.ChangeUnit.get() == 1:
  331.             self.Unit.config(state = "normal")
  332.         else:
  333.             self.Unit.config(state = "disabled")
  334.  
  335.     def body(self, master):
  336.         choices = ["height", "weight"]
  337.         self.title("Edit " + choices[self.mode].title())
  338.         self.resizable(False, False)
  339.         self.ChangeUnit = tk.IntVar()
  340.         self.ChangeUnit.set(0)
  341.         tk.Label(master, text = "Enter your new " + choices[self.mode] + ":", font = ftSmall).grid(row = 0)
  342.  
  343.         self.Value = tk.Entry(master, font = ftSmall)
  344.         self.Unit = tk.Entry(master, font = ftSmall)
  345.  
  346.         if self.mode == 0:
  347.             self.Value.insert(0, info[6])
  348.             self.Unit.insert(0, info[7])
  349.         elif self.mode == 1:
  350.             self.Value.insert(0, info[8])
  351.             self.Unit.insert(0, info[9])
  352.  
  353.         self.Unit.config(state = "disabled")
  354.  
  355.         ChangeUnitChk = tk.Checkbutton(master, text = "Check to change unit", variable = self.ChangeUnit, command = self.toggleUnit, font = ftSmall)
  356.  
  357.         self.Value.grid(row = 1)
  358.         self.Unit.grid(row = 3)
  359.         ChangeUnitChk.grid(row = 2)
  360.  
  361.     def apply(self):
  362.         try:
  363.             self.result = [int(self.Value.get()), self.Unit.get(), self.ChangeUnit.get()]
  364.         except:
  365.             mbx.showerror("Error","Invalid Measurement")
  366.             self.result = []
  367.  
  368. def editInfo():
  369.     editInfoSelect(editInfoRoot(base).result)
  370.     refrINFO()
  371.  
  372. def editInfoSelect(choice):
  373.     if choice in range(1, 7) or choice in range(9, 12):
  374.         if choice < 8:
  375.             index = choice - 1
  376.         else:
  377.             index = choice + 1
  378.  
  379.         choices = ["", "name", "class", "deity", "race", "gender", "age", "", "", "hair color", "eye color", "currency"]
  380.        
  381.         if choice == 6:
  382.             temp = sdg.askinteger("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
  383.    
  384.             if type(temp) == int:
  385.                 info[index] = temp
  386.  
  387.         elif choice != 6:
  388.             temp = sdg.askstring("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
  389.    
  390.             if type(temp) == str:
  391.                 info[index] = temp
  392.  
  393.     elif choice in range(7, 9):
  394.         n = choice
  395.         if n < 8:
  396.             n -= 1
  397.  
  398.         temp = editWH(base, choice).result
  399.  
  400.         if type(temp) == list and len(temp) > 0:
  401.             info[n] = temp[0]
  402.             if temp[2] == 1:
  403.                 info[n + 1] = temp[1]
  404.  
  405. def refrINVT():
  406.     INVTTxt.delete(0, INVTTxt.size())
  407.  
  408.     tempWGHT = 0.0
  409.  
  410.     for item in inventory:
  411.  
  412.         tempWGHT += round(item[2] * item[3], 4)
  413.  
  414.         tempStr = ""
  415.         tempStr += item[0][:36]
  416.         if len(item[0]) > 36:
  417.             tempStr += "... "
  418.         else:
  419.             tempStr += (40 - len(item[0])) * " "
  420.  
  421.         tempStr += str(item[2])
  422.         tempStr += (8 - len(str(item[2]))) * " "
  423.         tempStr += str(item[3])
  424.         tempStr += (8 - len(str(item[3]))) * " "
  425.  
  426.         if item[4] != 0 and item[5]:
  427.             tempStr += "d" + str(item[4]) + " x" + str(item[5])
  428.             tempStr += (8 - len("d" + str(item[4]) + " x" + str(item[5]))) * " "
  429.         else:
  430.             tempStr += 8 * " "
  431.        
  432.         if item[7] != 0:
  433.             tempStr += str(item[6]) + "/" + str(item[7])
  434.             tempStr += (8 - len(str(item[6]) + "/" + str(item[7]))) * " "
  435.         else:
  436.             tempStr += 8 * " "
  437.  
  438.         if item[8]:
  439.             tempStr += "Yes"
  440.         else:
  441.             tempStr += "No"
  442.  
  443.         INVTTxt.insert("end", tempStr)
  444.  
  445.     INVTENCMLbl.config(text = "Encumberance: " + str(tempWGHT))
  446.  
  447. def newItem():
  448.     tempItem = []
  449.     tempStr = ""
  450.  
  451.     try:
  452.         while len(tempStr) == 0:
  453.             tempStr = sdg.askstring("New Item", "Enter the new item's name:")
  454.             if len(tempStr) == 0:
  455.                 mbx.showerror("Error", "You must name your item!")
  456.  
  457.         tempItem.append(tempStr)
  458.  
  459.         tempStr = sdg.askstring("New Item", "[Optional] Enter the new item's bonus(es):")
  460.         tempItem.append(tempStr)
  461.  
  462.         tempItem.append(sdg.askinteger("New Item", "Enter how many of the new item you have:"))
  463.         tempItem.append(sdg.askfloat("New Item", "Enter the weight of the item:"))
  464.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the type of dice the item uses:"))
  465.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the amount of dice rolls for the item:"))
  466.        
  467.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the maximum magical charges the item has:"))
  468.         tempInt = tempItem[6] + 1
  469.         while tempInt > tempItem[6]:
  470.             tempInt = sdg.askinteger("New Item", "[Optional] Enter the current magical charges the item has:")
  471.             if tempInt > tempItem[6]:
  472.                 mbx.showerror("Error", "You can't overcharge your item!")
  473.         tempItem.insert(6, tempInt)
  474.                
  475.         tempItem.append(mbx.askyesno("New Item", "Is the item equipped?"))
  476.  
  477.         inventory.append(tempItem)
  478.         refrINVT()
  479.  
  480.     except TypeError:
  481.         pass
  482.  
  483. class editItemRoot(sdg.Dialog):
  484.     def __init__(self, master = None, i = ""):
  485.         self.item = i
  486.         super().__init__(master)
  487.  
  488.     def body(self, master):
  489.         self.title("Edit " + self.item)
  490.         self.resizable(False, False)
  491.         self.choice = tk.IntVar()
  492.         self.choice.set(0)
  493.         tk.Label(master, text = "Choose an item attribute to edit:", font = ftSmall).grid(row = 0)
  494.  
  495.         Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  496.         Bonus = tk.Radiobutton(master, text = "Bonus(es)", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  497.         Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  498.         Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  499.         dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  500.         dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  501.         Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  502.         MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  503.         Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  504.  
  505.         Name.grid(row = 1, sticky = "w")
  506.         Bonus.grid(row = 2, sticky = "w")
  507.         Count.grid(row = 3, sticky = "w")
  508.         Weight.grid(row = 4, sticky = "w")
  509.         dType.grid(row = 5, sticky = "w")
  510.         dCount.grid(row = 6, sticky = "w")
  511.         Charges.grid(row = 7, sticky = "w")
  512.         MaxCharges.grid(row = 8, sticky = "w")
  513.         Equipped.grid(row = 9, sticky = "w")
  514.  
  515.     def apply(self):
  516.         self.result = self.choice.get()
  517.  
  518. def editItem():
  519.     try:
  520.         index = INVTTxt.curselection()[0]
  521.         item = inventory[index]
  522.         attr = editItemRoot(base, item[0]).result
  523.  
  524.         if type(attr) == int:
  525.             choices = ["Name", "Bonus(es)", "Count", "Weight", "Dice Type", "Dice Count", "Charges", "Max Charges", ""]
  526.             title = "Edit " + item[0]
  527.             prompt = "Enter the item's new " + choices[attr] + ":"
  528.  
  529.             if attr < 2:
  530.                 temp = sdg.askstring(title, prompt, initialvalue = item[attr])
  531.  
  532.                 if type(temp) == str and len(temp) > 0 and temp != item[attr]:
  533.                     inventory[index][attr] = temp
  534.  
  535.             elif attr < 6 and attr != 3:
  536.                 temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  537.  
  538.                 if type(temp) == int and temp != item[attr]:
  539.                     inventory[index][attr] = temp
  540.  
  541.             elif attr == 3:
  542.                 temp = sdg.askfloat(title, prompt, initialvalue = item[attr])
  543.  
  544.                 if type(temp) == float and temp != item[attr]:
  545.                     inventory[index][attr] = temp
  546.  
  547.             elif attr == 6:
  548.                 temp = item[7] + 1
  549.                 while type(temp) == int and temp > item[7]:
  550.                     temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  551.                    
  552.                     if type(temp) == int and temp > item[7]:
  553.                         mbx.showerror("Error", "You can't overcharge your item!")
  554.  
  555.                 if type(temp) == int and temp != item[attr]:
  556.                     inventory[index][attr] = temp
  557.  
  558.             elif attr == 7:
  559.                 temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  560.  
  561.                 if type(temp) == int and temp != item[attr]:
  562.                     if temp < item[6]:
  563.                         inventory[index][6] = temp
  564.  
  565.                     inventory[index][attr] = temp
  566.  
  567.             else:
  568.                 inventory[index][attr] =  not inventory[index][attr]
  569.  
  570.             refrINVT()
  571.  
  572.     except IndexError:
  573.         mbx.showerror("Error", "No item selected!")
  574.  
  575. def inspectItem():
  576.     try:
  577.         if len(inventory[INVTTxt.curselection()[0]][1]) > 0:
  578.             mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n" + inventory[INVTTxt.curselection()[0]][1])
  579.         else:
  580.             mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n[None]")
  581.  
  582.     except IndexError:
  583.         mbx.showerror("Error", "No item selected!")
  584.  
  585. def deleteItem():
  586.     try:
  587.         if mbx.askyesno("Delete Item: " + inventory[INVTTxt.curselection()[0]][0], "Are you sure you want to delete this item?"):
  588.             del inventory[INVTTxt.curselection()[0]]
  589.             refrINVT()
  590.  
  591.     except IndexError:
  592.         mbx.showerror("Error", "No item selected!")
  593.  
  594. class sortItemsRoot(sdg.Dialog):
  595.     def body(self, master):
  596.         self.title("Sort Items")
  597.         self.resizable(False, False)
  598.         self.choice = tk.IntVar()
  599.         self.order = tk.IntVar()
  600.         self.choice.set(0)
  601.         self.order.set(0)
  602.         tk.Label(master, text = "Choose an attribute to sort by:", font = ftSmall).grid(row = 0)
  603.         tk.Label(master, text = "Choose an order to sort by:", font = ftSmall).grid(row = 9)
  604.  
  605.         Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  606.         Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  607.         Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  608.         dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  609.         dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  610.         Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  611.         MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  612.         Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  613.         Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftSmall)
  614.         Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftSmall)
  615.  
  616.         Name.grid(row = 1, sticky = "w")
  617.         Count.grid(row = 2, sticky = "w")
  618.         Weight.grid(row = 3, sticky = "w")
  619.         dType.grid(row = 4, sticky = "w")
  620.         dCount.grid(row = 5, sticky = "w")
  621.         Charges.grid(row = 6, sticky = "w")
  622.         MaxCharges.grid(row = 7, sticky = "w")
  623.         Equipped.grid(row = 8, sticky = "w")
  624.         Ascending.grid(row = 10, sticky = "w")
  625.         Descending.grid(row = 11, sticky = "w")
  626.  
  627.     def apply(self):
  628.         self.result = [self.choice.get(), self.order.get()]
  629.  
  630. def sortItems():
  631.     choice = sortItemsRoot(base).result
  632.    
  633.     if type(choice) == list:
  634.         if choice[1] == 1:
  635.             order = True
  636.         else:
  637.             order = False
  638.  
  639.         inventory.sort(key = op.itemgetter(choice[0]), reverse = order)
  640.         refrINVT()
  641.  
  642. def rollDice(d):
  643.     def rollDiceWrap(dice = d):
  644.         if dice < 100:
  645.             DICELbl.config(text = str(rnd.randint(1, dice)) + " | d" + str(dice))
  646.         else:
  647.             DICELbl.config(text = str(rnd.randint(0, 100)) + " | d%")
  648.     return rollDiceWrap
  649.  
  650. def refrSKIL():
  651.     SKILTxt.delete(0, SKILTxt.size())
  652.     stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
  653.  
  654.     for sk in skills:
  655.         SKILTxt.insert("end", stats[sk[0]] + "|" + sk[1])
  656.  
  657. class skillStat(sdg.Dialog):
  658.     def __init__(self, master = None, m = "", sa = "", i = 0):
  659.         self.mode = m
  660.         self.skab = sa
  661.         self.index = i
  662.         super().__init__(master)
  663.  
  664.     def body(self, master):
  665.         self.resizable(False, False)
  666.         self.stat = tk.IntVar()
  667.  
  668.         if self.skab == "skill":
  669.             if self.mode == "edit":
  670.                 self.title("Edit " + skills[self.index][1])
  671.                 self.stat.set(skills[self.index][0])
  672.  
  673.             elif self.mode == "new":
  674.                 self.title("New Skill")
  675.                 self.stat.set(0)
  676.  
  677.         elif self.skab == "ability":
  678.             if self.mode == "edit":
  679.                 self.title("Edit " + abilities[self.index][1])
  680.                 self.stat.set(abilities[self.index][0])
  681.  
  682.             elif self.mode == "new":
  683.                 self.title("New Ability")
  684.                 self.stat.set(0)
  685.  
  686.  
  687.         PRMPLbl = tk.Label(master, font = ftSmall)
  688.         PRMPLbl.grid(row = 0)
  689.         if self.skab == "skill":
  690.             if self.mode == "edit":
  691.                 PRMPLbl.config(text = "[Optional] Choose a new stat for the skill:")
  692.             elif self.mode == "new":
  693.                 PRMPLbl.config(text = "Choose a stat for the skill:")
  694.         elif self.skab == "ability":
  695.             if self.mode == "edit":
  696.                 PRMPLbl.config(text = "[Optional] Choose a new stat for the ability:")
  697.             elif self.mode == "new":
  698.                 PRMPLbl.config(text = "Choose a stat for the ability:")
  699.  
  700.         STRBtn = tk.Radiobutton(master, text = "Strength", value = 0, variable = self.stat, font = ftSmall)
  701.         DEXBtn = tk.Radiobutton(master, text = "Dexterity", value = 1, variable = self.stat, font = ftSmall)
  702.         CONBtn = tk.Radiobutton(master, text = "Constitution", value = 2, variable = self.stat, font = ftSmall)
  703.         INTBtn = tk.Radiobutton(master, text = "Intelligence", value = 3, variable = self.stat, font = ftSmall)
  704.         WISBtn = tk.Radiobutton(master, text = "Wisdom", value = 4, variable = self.stat, font = ftSmall)
  705.         CHABtn = tk.Radiobutton(master, text = "Charisma", value = 5, variable = self.stat, font = ftSmall)
  706.        
  707.         STRBtn.grid(row = 1, sticky = "w")
  708.         DEXBtn.grid(row = 2, sticky = "w")
  709.         CONBtn.grid(row = 3, sticky = "w")
  710.         INTBtn.grid(row = 4, sticky = "w")
  711.         WISBtn.grid(row = 5, sticky = "w")
  712.         CHABtn.grid(row = 6, sticky = "w")
  713.  
  714.     def apply(self):
  715.         self.result = self.stat.get()
  716.  
  717. def newSkill():
  718.     tempStr = ""
  719.     while type(tempStr) == str and len(tempStr) < 1:
  720.         tempStr = sdg.askstring("New Skill", "Enter the new skill's name:")
  721.         if type(tempStr) == str and len(tempStr) < 1:
  722.             mbx.showerror("Error", "You must name this skill!")
  723.  
  724.     if type(tempStr) == str:
  725.         tempInt = skillStat(base, "new", "skill").result
  726.         if type(tempInt) == int:
  727.             skills.append([tempInt, tempStr])
  728.             refrSKIL()
  729.  
  730. def editSkill():
  731.     try:
  732.         index = SKILTxt.curselection()[0]
  733.         sk = skills[index]
  734.         tempStr = sdg.askstring("Edit " + sk[1], "[Optional] Enter the skill's new name:", initialvalue = sk[1])
  735.         if type(tempStr) == str:
  736.             if len(tempStr) > 0 and tempStr != sk[1]:
  737.                 skills[index][1] = tempStr
  738.            
  739.             tempInt = skillStat(base, "edit", "skill", index).result
  740.             if type(tempInt) == int and tempInt != sk[0]:
  741.                 skills[index][0] = tempInt
  742.  
  743.             refrSKIL()
  744.     except IndexError:
  745.         mbx.showerror("Error", "No skill selected!")
  746.  
  747. def deleteSkill():
  748.     try:
  749.         if mbx.askyesno("Delete " + skills[SKILTxt.curselection()[0]][1], "Are you sure you want to delete this skill?"):
  750.             del skills[SKILTxt.curselection()[0]]
  751.             refrSKIL()
  752.  
  753.     except IndexError:
  754.         mbx.showerror("Error", "No skill selected!")
  755.  
  756. class sortSkillsAbils(sdg.Dialog):
  757.     def __init__(self, master = None, sa = ""):
  758.         self.skab = sa
  759.         super().__init__(master)
  760.  
  761.     def body(self, master):
  762.         if self.skab == "skill":
  763.             self.title("Sort Skills")
  764.         elif self.skab == "ability":
  765.             self.title("Sort Abilities")
  766.         self.resizable(False, False)
  767.         self.choice = tk.IntVar()
  768.         self.order = tk.IntVar()
  769.         self.choice.set(0)
  770.         self.order.set(0)
  771.         tk.Label(master, text = "Choose an attribute to sort by:", font = ftSmall).grid(row = 0)
  772.         tk.Label(master, text = "Choose an order to sort by:", font = ftSmall).grid(row = 3)
  773.  
  774.         Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  775.         Stat = tk.Radiobutton(master, text = "Stat", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  776.         Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftSmall)
  777.         Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftSmall)
  778.  
  779.         Name.grid(row = 1, sticky = "w")
  780.         Stat.grid(row = 2, sticky = "w")
  781.         Ascending.grid(row = 4, sticky = "w")
  782.         Descending.grid(row = 5, sticky = "w")
  783.  
  784.     def apply(self):
  785.         self.result = [self.choice.get(), self.order.get()]
  786.  
  787. def sortSkills():
  788.     choice = sortSkillsAbils(base, "skill").result
  789.  
  790.     if type(choice) == list:
  791.         if choice[1] == 1:
  792.             order = True
  793.         else:
  794.             order = False
  795.  
  796.         skills.sort(key = op.itemgetter(choice[0]), reverse = order)
  797.         refrSKIL()
  798.  
  799. def refrABIL():
  800.     ABILTxt.delete(0, ABILTxt.size())
  801.     stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
  802.  
  803.     for ab in abilities:
  804.         ABILTxt.insert("end", stats[ab[0]] + "|" + ab[1])
  805.  
  806. def newAbility():
  807.     tempStrA = ""
  808.     while type(tempStrA) == str and len(tempStrA) < 1:
  809.         tempStrA = sdg.askstring("New Ability", "Enter the new ability's name:")
  810.        
  811.         if type(tempStrA) == str and len(tempStrA) < 1:
  812.             mbx.showerror("Error", "You must name this ability!")
  813.  
  814.     if type(tempStrA) == str:
  815.         tempInt = skillStat(base, "new", "ability").result
  816.        
  817.         if type(tempInt) == int:
  818.             tempStrB = sdg.askstring("New Ability", "Describe the new ability:")
  819.            
  820.             if type(tempStrB) == str:
  821.                 abilities.append([tempInt, tempStrA, tempStrB])
  822.                 refrABIL()
  823.  
  824. def editAbility():
  825.     try:
  826.         index = ABILTxt.curselection()[0]
  827.         ab = abilities[index]
  828.         tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Enter the ability's new name:", initialvalue = ab[1])
  829.         if type(tempStr) == str:
  830.             if len(tempStr) > 0 and tempStr != ab[1]:
  831.                 abilities[index][1] = tempStr
  832.            
  833.             tempInt = skillStat(base, "edit", "ability", index).result
  834.             if type(tempInt) == int:
  835.                 if tempInt != ab[0]:
  836.                     abilities[index][0] = tempInt
  837.  
  838.                 tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Describe the ability again:", initialvalue = ab[2])
  839.                 if type(tempStr) == str and len(tempStr) > 0 and tempStr != ab[2]:
  840.                     abilities[index][2] = tempStr
  841.  
  842.             refrABIL()
  843.     except IndexError:
  844.         mbx.showerror("Error", "No ability selected!")
  845.  
  846. def deleteAbility():
  847.     try:
  848.         if mbx.askyesno("Delete " + abilities[ABILTxt.curselection()[0]][1], "Are you sure you want to delete this ability?"):
  849.             del abilities[ABILTxt.curselection()[0]]
  850.             refrABIL()
  851.  
  852.     except IndexError:
  853.         mbx.showerror("Error", "No ability selected!")
  854.  
  855. def inspectAbility():
  856.     try:
  857.         if len(abilities[ABILTxt.curselection()[0]][2]) > 0:
  858.             mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n" + abilities[ABILTxt.curselection()[0]][2])
  859.         else:
  860.             mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n[None]")
  861.  
  862.     except IndexError:
  863.         mbx.showerror("Error", "No ability selected!")
  864.  
  865. def sortAbilities():
  866.     choice = sortSkillsAbils(base, "ability").result
  867.  
  868.     if type(choice) == list:
  869.         if choice[1] == 1:
  870.             order = True
  871.         else:
  872.             order = False
  873.  
  874.         abilities.sort(key = op.itemgetter(choice[0]), reverse = order)
  875.         refrABIL()
  876.  
  877. def exitOverride():
  878.     if mbx.askyesno("Warning! Data Loss Possibility Detected!", "Unsaved data will be lost if you quit.\nAre you sure you want to quit?"):
  879.         base.destroy()
  880.  
  881. def newCharacter():
  882.     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?"):
  883.         return
  884.  
  885.     tempInfo = []
  886.     tempHealth = []
  887.     tempExp = []
  888.     tempMStats = []
  889.     tempBStats = []
  890.     tempInt = 0
  891.     tempIntB = 0
  892.     tempStr = ""
  893.     tempCount = 0
  894.     infoChoices = ["name", "class", "deity", "race", "gender", "age", "height", "unit", "weight", "unit", "hair color", "eye color", "currency"]
  895.     statChoices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
  896.  
  897.     while len(tempInfo) < 14:
  898.         if tempCount < 5 or tempCount > 9:
  899.             tempStr = sdg.askstring("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  900.             if type(tempStr) == str:
  901.                 tempInfo.append(tempStr)
  902.             else:
  903.                 return
  904.  
  905.             if tempCount == 12:
  906.                 tempInt = sdg.askinteger("New Character: Info", "Enter how much currency you have:")
  907.                 if type(tempInt) == int:
  908.                     tempInfo.append(tempInt)
  909.                 else:
  910.                     return
  911.             else:
  912.                 tempCount += 1
  913.  
  914.         elif tempCount > 5 and tempCount < 10:
  915.             tempStr = sdg.askstring("New Character: Info", "Enter your unit of " + infoChoices[tempCount] + ":")
  916.             if type(tempStr) != str:
  917.                 return
  918.  
  919.             tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  920.             if type(tempInt) == int:
  921.                 tempInfo.append(tempInt)
  922.                 tempInfo.append(tempStr)
  923.                 tempCount += 2
  924.             else:
  925.                 return
  926.  
  927.         elif tempCount == 5:
  928.             tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  929.             if type(tempInt) == int:
  930.                 tempInfo.append(tempInt)
  931.                 tempCount += 1
  932.             else:
  933.                 return
  934.  
  935.     tempInt = sdg.askinteger("New Character: Health", "Enter your maximum health points:")
  936.     if type(tempInt) != int:
  937.         return
  938.  
  939.     tempIntB = tempInt + 1
  940.     while tempIntB > tempInt or tempIntB < 0:
  941.         tempIntB = sdg.askinteger("New Character: Health", "Enter your current health points:")
  942.         if type(tempIntB) != int:
  943.             return
  944.         elif tempIntB > tempInt:
  945.             mbx.showerror("Error", "You can't overcharge your health points!")
  946.         elif tempIntB < 0:
  947.             mbx.showerror("Error", "You can't undercharge your health points!")
  948.  
  949.     tempHealth.append(tempIntB)
  950.     tempHealth.append(tempInt)
  951.  
  952.     tempInt = sdg.askinteger("New Character: Experience", "Enter your level:")
  953.     if type(tempInt) != int:
  954.         return
  955.     tempExp.append(tempInt)
  956.  
  957.     tempInt = 100 + tempExp[0] * 10
  958.     tempIntB = abs(sdg.askinteger("New Character: Experience", "Enter your current experience points:"))
  959.     if type(tempIntB) != int:
  960.         return
  961.  
  962.     tempExp.append(tempIntB)
  963.     tempExp.append(tempInt)
  964.  
  965.     tempCount = 0
  966.  
  967.     while len(tempMStats) < 6 and len(tempBStats) < 6:
  968.         tempInt = sdg.askinteger("New Character: Stats", "Enter your " + statChoices[tempCount] + ":")
  969.         if type(tempInt) != int:
  970.             return
  971.  
  972.         tempIntB = sdg.askinteger("New Character: Stats", "Enter your " + statChoices[tempCount] + " Bonus:")
  973.         if type(tempIntB) == int:
  974.             tempMStats.append(tempInt)
  975.             tempBStats.append(tempIntB)
  976.             tempCount += 1
  977.         else:
  978.             return
  979.  
  980.     tempCount = 0
  981.  
  982.     for bit in tempInfo:
  983.         info[tempCount] = bit
  984.         tempCount += 1
  985.  
  986.     tempCount = 0
  987.  
  988.     for bit in tempHealth:
  989.         health[tempCount] = bit
  990.         tempCount += 1
  991.  
  992.     tempCount = 0
  993.  
  994.     for bit in tempExp:
  995.         experience[tempCount] = bit
  996.         tempCount += 1
  997.  
  998.     tempCount = 0
  999.  
  1000.     for bit in tempMStats:
  1001.         mainStats[tempCount] = bit
  1002.         tempCount += 1
  1003.  
  1004.     tempCount = 0
  1005.  
  1006.     for bit in tempBStats:
  1007.         bonusStats[tempCount] = bit
  1008.         tempCount += 1
  1009.  
  1010.     while len(skills) > 0:
  1011.         del skills[0]
  1012.  
  1013.     while len(abilities) > 0:
  1014.         del abilities[0]
  1015.  
  1016.     while len(inventory) > 0:
  1017.         del inventory[0]
  1018.  
  1019.     refrSTAT()
  1020.     refrINFO()
  1021.     refrSKIL()
  1022.     refrABIL()
  1023.     refrINVT()
  1024.  
  1025. def saveCharacter():
  1026.     fileName = sdg.askstring("Save Character", "Enter the name of the file to save to:")
  1027.     if type(fileName) != str:
  1028.         return
  1029.  
  1030.     fileName += ".dat"
  1031.  
  1032.     if os.path.isfile(fileName):
  1033.         if not mbx.askyesno("Warning! File Already Exists!", "Do you want to overwrite " + fileName + "?"):
  1034.             return
  1035.  
  1036.     saveFile = open(fileName, "w")
  1037.  
  1038.     dlm = " || "
  1039.     adlm = " |\n"
  1040.     nl = "\n\n"
  1041.  
  1042.     temp = 0
  1043.  
  1044.     for bit in info:
  1045.         saveFile.write(str(bit))
  1046.  
  1047.         if temp == 13:
  1048.             saveFile.write(nl)
  1049.         else:
  1050.             saveFile.write(dlm)
  1051.  
  1052.         temp += 1
  1053.  
  1054.     temp = 0
  1055.  
  1056.     for bit in health:
  1057.         saveFile.write(str(bit))
  1058.  
  1059.         if temp == 1:
  1060.             saveFile.write(nl)
  1061.         else:
  1062.             saveFile.write(dlm)
  1063.  
  1064.         temp += 1
  1065.  
  1066.     temp = 0
  1067.  
  1068.     for bit in experience:
  1069.         saveFile.write(str(bit))
  1070.  
  1071.         if temp == 2:
  1072.             saveFile.write(nl)
  1073.         else:
  1074.             saveFile.write(dlm)
  1075.  
  1076.         temp += 1
  1077.  
  1078.     temp = 0
  1079.  
  1080.     for bit in mainStats:
  1081.         saveFile.write(str(bit))
  1082.  
  1083.         if temp == 5:
  1084.             saveFile.write(nl)
  1085.         else:
  1086.             saveFile.write(dlm)
  1087.  
  1088.         temp += 1
  1089.  
  1090.     temp = 0
  1091.  
  1092.     for bit in bonusStats:
  1093.         saveFile.write(str(bit))
  1094.  
  1095.         if temp == 5:
  1096.             saveFile.write(nl)
  1097.         else:
  1098.             saveFile.write(dlm)
  1099.  
  1100.         temp += 1
  1101.  
  1102.     temp = 1
  1103.  
  1104.     for sk in skills:
  1105.         saveFile.write(str(sk[0]) + dlm + sk[1])
  1106.  
  1107.         if temp != len(skills):
  1108.             saveFile.write(adlm)
  1109.  
  1110.         temp += 1
  1111.  
  1112.     saveFile.write(nl)
  1113.  
  1114.     temp = 1
  1115.  
  1116.     for ab in abilities:
  1117.         saveFile.write(str(ab[0]) + dlm + ab[1] + dlm + ab[2])
  1118.  
  1119.         if temp != len(abilities):
  1120.             saveFile.write(adlm)
  1121.  
  1122.         temp += 1
  1123.  
  1124.     saveFile.write(nl)
  1125.  
  1126.     temp = 1
  1127.  
  1128.     for item in inventory:
  1129.         tempAux = 1
  1130.  
  1131.         for bit in item:
  1132.             saveFile.write(str(bit))
  1133.             if tempAux < 9:
  1134.                 saveFile.write(dlm)
  1135.  
  1136.             tempAux += 1
  1137.  
  1138.         if temp != len(inventory):
  1139.             saveFile.write(adlm)
  1140.  
  1141.         temp += 1
  1142.  
  1143.     saveFile.close()
  1144.  
  1145.     mbx.showinfo("Save Character", "Saved!\nCheck the working directory of this program for the file.")
  1146.  
  1147. def loadCharacter():
  1148.     loaded = False
  1149.  
  1150.     while not loaded:
  1151.         try:
  1152.             fileName = sdg.askstring("Load Character", "Enter the name of the file to load from:")
  1153.             if type(fileName) != str:
  1154.                 return
  1155.  
  1156.             fileName += ".dat"
  1157.             loadFile = open(fileName, "r")
  1158.             loaded = True
  1159.  
  1160.         except FileNotFoundError:
  1161.             mbx.showerror("Error", "File not found!")
  1162.  
  1163.     dlm = " || "
  1164.     adlm = " |\n"
  1165.     nl = "\n\n"
  1166.  
  1167.     contents = loadFile.read().split(nl)
  1168.  
  1169.     tempCountA = 0
  1170.  
  1171.     try:
  1172.         for bit in contents:
  1173.             tempList = []
  1174.  
  1175.             if adlm in bit:
  1176.                 tempList = bit.split(adlm)
  1177.                 tempCountB = 0
  1178.  
  1179.                 for item in tempList:
  1180.                     tempList[tempCountB] = item.split(dlm)
  1181.                     tempCountC = 0
  1182.  
  1183.                     for el in tempList[tempCountB]:
  1184.                         if el == "True":
  1185.                             tempList[tempCountB][tempCountC] = True
  1186.                         elif el == "False":
  1187.                             tempList[tempCountB][tempCountC] = False
  1188.                         else:
  1189.                             try:
  1190.                                 tempList[tempCountB][tempCountC] = int(el)
  1191.                
  1192.                             except ValueError:
  1193.                                 try:
  1194.                                     tempList[tempCountB][tempCountC] = float(el)
  1195.                                 except ValueError:
  1196.                                     pass
  1197.    
  1198.                         tempCountC += 1
  1199.    
  1200.                     tempCountB += 1
  1201.  
  1202.             elif dlm in bit:
  1203.                 tempList = bit.split(dlm)
  1204.                 tempCountB = 0
  1205.  
  1206.                 for el in tempList:
  1207.                     try:
  1208.                         tempList[tempCountB] = int(el)
  1209.                
  1210.                     except ValueError:
  1211.                         try:
  1212.                             tempList[tempCountB] = float(el)
  1213.                         except ValueError:
  1214.                             pass
  1215.        
  1216.                     tempCountB += 1
  1217.    
  1218.             contents[tempCountA] = tempList
  1219.  
  1220.             tempCountA += 1
  1221.  
  1222.     except:
  1223.         mbx.showerror("Error", "Unable to Load File!")
  1224.         return
  1225.  
  1226.     tempCount = 0
  1227.  
  1228.     for bit in contents[0]:
  1229.         info[tempCount] = bit
  1230.         tempCount += 1
  1231.  
  1232.     tempCount = 0
  1233.  
  1234.     for bit in contents[1]:
  1235.         health[tempCount] = bit
  1236.         tempCount += 1
  1237.  
  1238.     tempCount = 0
  1239.  
  1240.     for bit in contents[2]:
  1241.         experience[tempCount] = bit
  1242.         tempCount += 1
  1243.  
  1244.     tempCount = 0
  1245.  
  1246.     for bit in contents[3]:
  1247.         mainStats[tempCount] = bit
  1248.         tempCount += 1
  1249.  
  1250.     tempCount = 0
  1251.  
  1252.     for bit in contents[4]:
  1253.         bonusStats[tempCount] = bit
  1254.         tempCount += 1
  1255.  
  1256.     while len(skills) > 0:
  1257.         del skills[0]
  1258.  
  1259.     for bit in contents[5]:
  1260.         skills.append(bit)
  1261.  
  1262.     while len(abilities) > 0:
  1263.         del abilities[0]
  1264.  
  1265.     for bit in contents[6]:
  1266.         abilities.append(bit)
  1267.  
  1268.     while len(inventory) > 0:
  1269.         del inventory[0]
  1270.  
  1271.     for bit in contents[7]:
  1272.         inventory.append(bit)
  1273.  
  1274.     mbx.showinfo("Load Character", "Loaded!\nYour journey continues...")
  1275.     refrSTAT()
  1276.     refrINFO()
  1277.     refrINVT()
  1278.     refrSKIL()
  1279.     refrABIL()
  1280.  
  1281. mainStats = [0, 0, 0, 0, 0, 0]
  1282. bonusStats = [0, 0, 0, 0, 0, 0]
  1283. savingThrows = [0, 0, 0]
  1284. health = [0, 10]
  1285. experience = [1, 0, 110]
  1286. info = ["name", "class", "deity", "race", "gender", 18, 170, "cm", 70, "kg", "brown", "black", "currency", 0]
  1287. skills = []
  1288. abilities = []
  1289. inventory = []
  1290. brackets5E = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000]
  1291.  
  1292. base = tk.Tk()
  1293. base.protocol("WM_DELETE_WINDOW", exitOverride)
  1294.  
  1295. ftSmall = tkf.Font(family = "Consolas", size = 8)
  1296. ftNormal = tkf.Font(family = "Consolas", size = 10)
  1297. ftNormUnd = tkf.Font(family = "Consolas", size = 10, underline = 1)
  1298. ftLarge = tkf.Font(family = "Consolas", size = 12)
  1299. ftTitle = tkf.Font(family = "Consolas", size = 12, weight = "bold", slant = "italic")
  1300. ftBigTitle = tkf.Font(family = "Consolas", size = 16, weight = "bold", slant = "italic")
  1301. ftSubtitle = tkf.Font(family = "Consolas", size = 12, slant = "italic")
  1302. ftDice = tkf.Font(family = "Consolas", size = 12, weight = "bold")
  1303.  
  1304. STATPnl = tk.Frame(base, bd = 4, relief = "groove")
  1305. STATPnl.grid(row = 1, column = 0, rowspan = 2, padx = 4, pady = 4, sticky = "n")
  1306.  
  1307. STATTitl = tk.Label(STATPnl, text = "Stats", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1308. LEVLLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1309. LEVLVar = tk.BooleanVar()
  1310. LEVLVar.set(False)
  1311. LEVLChk = tk.Checkbutton(STATPnl, text = "5E", command = ChangeXP, variable = LEVLVar, font = ftNormal)
  1312. XPLbl = tk.Label(STATPnl, width = 16, relief = "ridge", font = ftNormal)
  1313. XPPlusBtn = tk.Button(STATPnl, text = "+", command = XPUp, cursor = "hand2", font = ftSmall)
  1314. HPLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1315. HPPLUSBtn = tk.Button(STATPnl, text = "+", command = HPUp, cursor = "hand2", font = ftSmall)
  1316. HPMINSBtn = tk.Button(STATPnl, text = "-", command = HPDown, cursor = "hand2", font = ftSmall)
  1317.  
  1318. STRLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1319. DEXLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1320. CONLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1321. INTLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1322. WISLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1323. CHALbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1324.  
  1325. STRBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1326. DEXBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1327. CONBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1328. INTBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1329. WISBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1330. CHABLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1331.  
  1332. FORTLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1333. REFLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1334. WILLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1335. STATEDITBtn = tk.Button(STATPnl, text = "Edit Stats", width = 10, command = editStat, cursor = "hand2", font = ftSmall)
  1336.  
  1337. STATTitl.grid(row = 0, columnspan = 3, pady = 2)
  1338. LEVLLbl.grid(row = 1, column = 0, columnspan = 3, pady = 2)
  1339. XPLbl.grid(row = 2, column = 0, columnspan = 2, pady = 2)
  1340. XPPlusBtn.grid(row = 2, column = 2)
  1341. HPLbl.grid(row = 3, column = 0, pady = 2)
  1342. HPPLUSBtn.grid(row = 3, column = 1)
  1343. HPMINSBtn.grid(row = 3, column = 2, padx = 4)
  1344.  
  1345. STRLbl.grid(row = 4, column = 0, padx = 4, pady = 2)
  1346. DEXLbl.grid(row = 5, column = 0, padx = 4, pady = 2)
  1347. CONLbl.grid(row = 6, column = 0, padx = 4, pady = 2)
  1348. INTLbl.grid(row = 7, column = 0, padx = 4, pady = 2)
  1349. WISLbl.grid(row = 8, column = 0, padx = 4, pady = 2)
  1350. CHALbl.grid(row = 9, column = 0, padx = 4, pady = 2)
  1351.  
  1352. STRBLbl.grid(row = 4, column = 1, columnspan = 2, padx = 4, pady = 2)
  1353. DEXBLbl.grid(row = 5, column = 1, columnspan = 2, padx = 4, pady = 2)
  1354. CONBLbl.grid(row = 6, column = 1, columnspan = 2, padx = 4, pady = 2)
  1355. INTBLbl.grid(row = 7, column = 1, columnspan = 2, padx = 4, pady = 2)
  1356. WISBLbl.grid(row = 8, column = 1, columnspan = 2, padx = 4, pady = 2)
  1357. CHABLbl.grid(row = 9, column = 1, columnspan = 2, padx = 4, pady = 2)
  1358.  
  1359. FORTLbl.grid(row = 10, columnspan = 3, padx = 4, pady = 2)
  1360. REFLLbl.grid(row = 11, columnspan = 3, padx = 4, pady = 2)
  1361. WILLLbl.grid(row = 12, columnspan = 3, padx = 4, pady = 2)
  1362. STATEDITBtn.grid(row = 13, column = 0, padx = 4, pady = 2)
  1363. LEVLChk.grid(row = 13, column = 1, columnspan = 2)
  1364.  
  1365. refrSTAT()
  1366.  
  1367. INFOPnl = tk.Frame(base, bd = 4, relief = "groove")
  1368. INFOPnl.grid(row = 1, column = 1, padx = 4, pady = 4, sticky = "nw")
  1369.  
  1370. INFOTitl = tk.Label(INFOPnl, text ="Information", width = 32, bd = 4, relief = "raised", font = ftTitle)
  1371. INFOTitl.grid(row = 0, columnspan = 4, pady = 2)
  1372.  
  1373. NAMELbl = tk.Label(INFOPnl, width = 48, bd = 4, relief = "ridge", font = ftLarge)
  1374. CLSSLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1375. DETYLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1376. RACELbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1377. GNDRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1378. AYGELbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1379. HGHTLbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1380. WGHTLbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1381. INFOEDITBtn = tk.Button(INFOPnl, text = "Edit Info", width = 8, command = editInfo, cursor = "hand2", font = ftSmall)
  1382. HAIRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1383. EYESLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1384. MONYLbl = tk.Label(INFOPnl, width = 32, relief = "ridge", font = ftLarge)
  1385. MONYCHNGBtn = tk.Button(INFOPnl, text = "Credit/Debit", width = 12, command = changeMoney, cursor = "hand2", font = ftSmall)
  1386.  
  1387. NAMELbl.grid(row = 1, columnspan = 4, pady = 4)
  1388. CLSSLbl.grid(row = 2, column = 0, columnspan = 2, pady = 4)
  1389. DETYLbl.grid(row = 3, column = 0, columnspan = 2, pady = 4)
  1390. RACELbl.grid(row = 2, column = 2, columnspan = 2, padx = 2)
  1391. GNDRLbl.grid(row = 3, column = 2, columnspan = 2, padx = 2)
  1392. AYGELbl.grid(row = 5, column = 0, pady = 4)
  1393. HGHTLbl.grid(row = 5, column = 1)
  1394. WGHTLbl.grid(row = 5, column = 2)
  1395. INFOEDITBtn.grid(row = 5, column = 3)
  1396. HAIRLbl.grid(row = 4, column = 0, columnspan = 2, pady = 4)
  1397. EYESLbl.grid(row = 4, column = 2, columnspan = 2)
  1398. MONYLbl.grid(row = 6, column = 0, columnspan = 3)
  1399. MONYCHNGBtn.grid(row = 6, column = 3, pady = 11)
  1400.  
  1401. refrINFO()
  1402.  
  1403. INVTPnl = tk.Frame(base, bd = 4, relief = "groove")
  1404. INVTPnl.grid(row = 2, column = 1, rowspan = 2, columnspan = 2, padx = 4, pady = 4, sticky = "w")
  1405.  
  1406. INVTTitl = tk.Label(INVTPnl, text = "Inventory", width = 24, bd = 4, relief = "raised", font = ftTitle)
  1407. INVTNEWWBtn = tk.Button(INVTPnl, text = "Create Item", width = 12, command = newItem, cursor = "hand2", font = ftSmall)
  1408. INVTEDITBtn = tk.Button(INVTPnl, text = "Edit Item", width = 12, command = editItem, cursor = "hand2", font = ftSmall)
  1409. INVTDELTBtn = tk.Button(INVTPnl, text = "Delete Item", width = 12, command = deleteItem, cursor = "hand2", font = ftSmall)
  1410. INVTINSPBtn = tk.Button(INVTPnl, text = "Inspect Item", width = 12, command = inspectItem, cursor = "hand2", font = ftSmall)
  1411. INVTSORTBtn = tk.Button(INVTPnl, text = "Sort Items", width = 12, command = sortItems, cursor = "hand2", font = ftSmall)
  1412. INVTLbl = tk.Label(INVTPnl, text = "Name\t\t\t\t\tCount\tWeight\tDice\tCharges\tEquipped", font = ftNormUnd)
  1413. INVTTxt = tk.Listbox(INVTPnl, height = 10, width = 80, cursor = "cross", font = ftNormal)
  1414. IVNTScr = tk.Scrollbar(INVTPnl, orient = "vertical", command = INVTTxt.yview)
  1415. INVTTxt.config(yscrollcommand = IVNTScr.set)
  1416. INVTENCMLbl = tk.Label(INVTPnl, text = "Encumberance:", width = 24, anchor = "w", relief = "ridge", font = ftNormal)
  1417.  
  1418. INVTTitl.grid(row = 0, column = 0, pady = 2)
  1419. INVTNEWWBtn.grid(row = 0, column = 1)
  1420. INVTEDITBtn.grid(row = 0, column = 2)
  1421. INVTDELTBtn.grid(row = 1, column = 2, columnspan = 2)
  1422. INVTINSPBtn.grid(row = 1, column = 1, columnspan = 2)
  1423. INVTSORTBtn.grid(row = 0, column = 3)
  1424. INVTLbl.grid(row = 2, columnspan = 4, sticky = "w")
  1425. INVTTxt.grid(row = 3, column = 0, columnspan = 4)
  1426. IVNTScr.grid(row = 2, column = 4, rowspan = 2, sticky = "ns")
  1427. INVTENCMLbl.grid(row = 4, columnspan = 5, pady = 4, sticky = "e")
  1428.  
  1429. refrINVT()
  1430.  
  1431. DICEPnl = tk.Frame(base, bd = 4, relief = "groove")
  1432. DICEPnl.grid(row = 3, column = 0, padx = 4, pady = 4, sticky = "s")
  1433.  
  1434. DICETitl = tk.Label(DICEPnl, text = "Dice", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1435. DICELbl = tk.Label(DICEPnl, text = "0 | d?", width = 8, relief = "groove", font = ftDice)
  1436. DICEd4Btn = tk.Button(DICEPnl, text = "d4", command = rollDice(4), cursor = "hand2", font = ftSmall)
  1437. DICEd6Btn = tk.Button(DICEPnl, text = "d6", command = rollDice(6), cursor = "hand2", font = ftSmall)
  1438. DICEd8Btn = tk.Button(DICEPnl, text = "d8", command = rollDice(8), cursor = "hand2", font = ftSmall)
  1439. DICEd10Btn = tk.Button(DICEPnl, text = "d10", command = rollDice(10), cursor = "hand2", font = ftSmall)
  1440. DICEd12Btn = tk.Button(DICEPnl, text = "d12", command = rollDice(12), cursor = "hand2", font = ftSmall)
  1441. DICEd20Btn = tk.Button(DICEPnl, text = "d20", command = rollDice(20), cursor = "hand2", font = ftSmall)
  1442. DICEd100Btn = tk.Button(DICEPnl, text = "d100", command = rollDice(100), cursor = "hand2", font = ftSmall)
  1443.  
  1444. DICETitl.grid(row = 0, column = 0, columnspan = 3, pady = 2)
  1445. DICELbl.grid(row = 1, column = 0, columnspan = 3, padx = 36, pady = 2)
  1446. DICEd4Btn.grid(row = 2, column = 0, pady = 2)
  1447. DICEd6Btn.grid(row = 2, column = 1, pady = 2)
  1448. DICEd8Btn.grid(row = 2, column = 2, pady = 2)
  1449. DICEd10Btn.grid(row = 3, column = 0, pady = 2)
  1450. DICEd12Btn.grid(row = 3, column = 1, pady = 2)
  1451. DICEd20Btn.grid(row = 3, column = 2, pady = 2)
  1452. DICEd100Btn.grid(row = 4, column = 1, pady = 2)
  1453.  
  1454. SKILPnl = tk.Frame(base, bd = 4, relief = "groove")
  1455. SKILPnl.grid(row = 2, column = 3, rowspan = 2, padx = 4, pady = 4, sticky = "n")
  1456.  
  1457. SKILTitl = tk.Label(SKILPnl, text = "Skills", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1458. SKILTxt = tk.Listbox(SKILPnl, height = 10, width = 32, cursor = "cross", font = ftNormal)
  1459. SKILScrV = tk.Scrollbar(SKILPnl, orient = "vertical", command = SKILTxt.yview)
  1460. SKILScrH = tk.Scrollbar(SKILPnl, orient = "horizontal", command = SKILTxt.xview)
  1461. SKILTxt.config(yscrollcommand = SKILScrV.set, xscrollcommand = SKILScrH.set)
  1462. SKILNEWWBtn = tk.Button(SKILPnl, text = "Create Skill", width = 12, command = newSkill, cursor = "hand2", font = ftSmall)
  1463. SKILEDITBtn = tk.Button(SKILPnl, text = "Edit Skill", width = 12, command = editSkill, cursor = "hand2", font = ftSmall)
  1464. SKILDELTBtn = tk.Button(SKILPnl, text = "Delete Skill", width = 12, command = deleteSkill, cursor = "hand2", font = ftSmall)
  1465. SKILSORTBtn = tk.Button(SKILPnl, text = "Sort Skills", width = 12, command = sortSkills, cursor = "hand2", font = ftSmall)
  1466.  
  1467. SKILTitl.grid(row = 0, columnspan = 3, pady = 2)
  1468. SKILTxt.grid(row = 3, column = 0, columnspan = 2)
  1469. SKILScrV.grid(row = 3, column = 2, rowspan = 2, sticky = "ns")
  1470. SKILScrH.grid(row = 4, column = 0, columnspan = 2, sticky = "we")
  1471. SKILNEWWBtn.grid(row = 1, column = 0, pady = 2)
  1472. SKILEDITBtn.grid(row = 1, column = 1)
  1473. SKILDELTBtn.grid(row = 2, column = 0, pady = 2)
  1474. SKILSORTBtn.grid(row = 2, column = 1)
  1475.  
  1476. refrSKIL()
  1477.  
  1478. ABILPnl = tk.Frame(base, bd = 4, relief = "groove")
  1479. ABILPnl.grid(row = 1, column = 2, columnspan = 2, padx = 4, pady = 4, sticky = "n")
  1480.  
  1481. ABILTitl = tk.Label(ABILPnl, text = "Abilities", width = 16, bd = 4, relief = "raised", font = ftTitle)
  1482. ABILTxt = tk.Listbox(ABILPnl, height = 10, width = 48, cursor = "cross", font = ftNormal)
  1483. ABILScrV = tk.Scrollbar(ABILPnl, orient = "vertical", command = ABILTxt.yview)
  1484. ABILScrH = tk.Scrollbar(ABILPnl, orient = "horizontal", command = ABILTxt.xview)
  1485. ABILTxt.config(yscrollcommand = ABILScrV.set, xscrollcommand = ABILScrH.set)
  1486. ABILNEWWBtn = tk.Button(ABILPnl, text = "Create Ability", width = 16, command = newAbility, cursor = "hand2", font = ftSmall)
  1487. ABILEDITBtn = tk.Button(ABILPnl, text = "Edit Ability", width = 16, command = editAbility, cursor = "hand2", font = ftSmall)
  1488. ABILDELTBtn = tk.Button(ABILPnl, text = "Delete Ability", width = 16, command = deleteAbility, cursor = "hand2", font = ftSmall)
  1489. ABILINSPBtn = tk.Button(ABILPnl, text = "Inspect Ability", width = 16, command = inspectAbility, cursor = "hand2", font = ftSmall)
  1490. ABILSORTBtn = tk.Button(ABILPnl, text = "Sort Abilities", width = 16, command = sortAbilities, cursor = "hand2", font = ftSmall)
  1491.  
  1492. ABILTitl.grid(row = 0, columnspan = 4)
  1493. ABILTxt.grid(row = 3, column = 0, columnspan = 3)
  1494. ABILScrV.grid(row = 3, column = 3, rowspan = 2, sticky = "ns")
  1495. ABILScrH.grid(row = 4, columnspan = 3, sticky = "we")
  1496. ABILNEWWBtn.grid(row = 1, column = 0, pady = 2)
  1497. ABILEDITBtn.grid(row = 1, column = 1)
  1498. ABILDELTBtn.grid(row = 2, column = 1, columnspan = 2, pady = 2)
  1499. ABILINSPBtn.grid(row = 2, column = 0, columnspan = 2)
  1500. ABILSORTBtn.grid(row = 1, column = 2, columnspan = 2, padx = 8)
  1501.  
  1502. MENUPnl = tk.Frame(base, bd = 4, relief = "groove")
  1503. MENUPnl.grid(row = 0, columnspan = 4, pady = 4)
  1504.  
  1505. MENUTitl = tk.Label(MENUPnl, text = "C²'s D&D Character Sheet", width = 64, bd = 4, relief = "raised", font = ftBigTitle)
  1506. MENUNEWWBtn = tk.Button(MENUPnl, text = "New Character", width = 16, command = newCharacter, cursor = "hand2", font = ftLarge)
  1507. MENUSAVEBtn = tk.Button(MENUPnl, text = "Save Character", width = 16, command = saveCharacter, cursor = "hand2", font = ftLarge)
  1508. MENULOADBtn = tk.Button(MENUPnl, text = "Load Character", width = 16, command = loadCharacter, cursor = "hand2", font = ftLarge)
  1509. MENUVERS = tk.Label(MENUPnl, text = "Version 1.1", width = 16, bd = 4, relief = "ridge", font = ftSubtitle)
  1510.  
  1511. MENUTitl.grid(row = 0, columnspan = 4, padx = 16, pady = 4)
  1512. MENUNEWWBtn.grid(row = 1, column = 0, pady = 4)
  1513. MENUSAVEBtn.grid(row = 1, column = 1)
  1514. MENULOADBtn.grid(row = 1, column = 2)
  1515. MENUVERS.grid(row = 1, column = 3)
  1516.  
  1517. base.title("DnD Character Sheet")
  1518. base.resizable(False, False)
  1519. base.mainloop()
RAW Paste Data