Welcome to Update 5 of the Dicecord project. This week I was able to complete all my goals and have closed in on a release candidate. The sheet is now implemented into Dicecord, which now opens on a blank character. A sample is shown below:
In addition, I have used a tab system to switch between sheet and inventory, changed the mana section to incorporate mana stored in enchanted items and added a “notes” tab for users to take down notes about the game that the character is involved in. Finally, I renamed the Dicecord.py version that does not display a character sheet to “Dicecord-Lite.py” and will release this as a standalone app too. As always, the latest code can be found here on my github repo.
QT Tab Widget
The sheetUI object now uses a QTTabwidget as its central widget. This allows for multiple UI objects to be stored as tabbed pages, cutting down on window spam. For the release candidate this shows the main character sheet, the inventory and a general notes page. For gamelines like werewolf and demon I can use this to store stats for alternate forms.
Inventory Sheet – General
The inventory sheet is the 2nd tab and contains a mix of actual inventory and other forms of character assets/knowledge. Most of these are like the Obsessions, etc from the character sheet: labels with hover text that explain what they are. I also have more complex widget forms that will show important attributes of the asset and calculate relevant dicepools. The weapons item is a basically the same as the hover label widgets only it has multiple fields.
Inventory Sheet – Rotes and Praxes
Rotes and Praxes are ways that a mage locks in knowledge to cast an improvised spell. In the case of a praxis they use their normal spell casting pool but the spell had additional effects, while for rotes the mage incorporates a specific skill’s rating into the case pool. In addition, if they are using a skill with a rote specialty their pool is one larger.
The Rotes and Praxes widgets in the inventory will calculate the pool based on your current stats, and will update that pool if the underlying stats are changed.
Inventory Sheet – Enchanted Items
Enchanted items are a type of item that has a spell locked into it. These take the form of imbued items (mundane items that a mage puts a spell in) and Artifacts (legendary items taken from the supernal realms of magic). They both share the concept of an item that casts a spell, but the dicepools used to cast the spells are different for each case. The widget allows a player to enter in the name of the object, give a tooltip explaining its effects and calculates the dicepool for using it. One notable difference is that for imbued items you are locked into using the pool given, but for artifacts a player can choose between using their own stats or stats generated by the item. To keep the widget simple, I incorporated a tooltip for artifacts that show the calculation for the pool so players can easily identify if its worth substituting their own stats.
In addition to casting spells, these items serves as storage for mana, but each have different rules for the amount of mana they store and when it an be accessed. In order to properly display this I decided to link this widget to the mana widget on the character sheet. Now that widget will display a row for each artifact/imbued item, allowing a user to track how much mana is in each object.
One downside of this approach is that the main sheet object won’t redraw when content is added to it from another tab. This results in the mana widget not resizing when each new object is added. For now, as a workaround a user can export they character sheet and re-import it to have it resized.
XML Saving and Importing
I decided to save character details as XML files. Originally I was just going to do a text file, but I felt that stats that take the form of lists or dictionaries would be difficult to implement with this method. For the save action, it goes over the character.stats object and creates appropriate leafs for each stat. For reading, it looks for specific leafs and then parses them into the stats dictionary object. It will then use a class method to generate a character using that stats object as an input.
The general save/open methods were implemented into the character object itself. In the Dicecord object, I implemented methods to allow for saving, saving as and discarding changes made to a character. The app will also detect changes on quit and offer to save the details if anything has been changed.
I had some extra time so I decided to implement a notes tab to the character sheet. Right now it is just a window that you enter text in. This is saved as its own attribute in the character object rather than part of the overall stats attribute. In addition, this will be saved along with the character details.
Later on I plan to have a project dedicated to implement rich text formatting to the notes object, effectively building a word processor of sorts.
General Code Cleanup
I decided to make my code a bit cleaner by moving the inventory, sheet UI and basic UI building blocks to their own .py files. This way it should be easier to read the code as each file contains the main widgets shown in their tab. In addition, I changed how edit mode works to pretty much everything that requires XP to change is locked behind edit mode. This means that modifiers, health, damage, willpower spending, xp, beats, weapons and active spells can be edited at all times but everything else can only be changed in edit mode.
Plans for Next Week
I now have what I consider the feature complete version of Dicecord 1.0. This is a full Mage character sheet along with the Discord connected diceroller. My current plan is to gather feedback from my gaming group for any minor changes, put together an installer, write a read me and generally get the app ready for public distribution.