Advertisement
cookchar

DnD Character Sheet v1.2

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