I have a group that is about ready to start a new Dungeons and Dragons campaign. The last time we played was somewhere between 2 and 4 years ago. Since then, Wizards of the Coast has release the 4th edition of the system. In addition to that, they have released a character creator, which has made creating and leveling up characters super easy.
I downloaded the demo of the character creator and created a sample character. I then had a look at the file that was saved. I was amazed to see that it was saved in xml format. Nice plain text. Thank you wizards of the coast for making it accessible. Even better than that, within the xml, they provide links to their online compendium of rules. For instance, here is an xml node from the saved character file, which is of the new Dragonborn class.
<ruleselement name="Dragon Breath" type="Power" internal-id="ID_FMP_POWER_1448" url="http://www.wizards.com/dndinsider/compendium/power.aspx?id=1448" charelem="60bad78" legality="rules-legal"></ruleselement>
Using that URL, you can visit the compendium site and read about the power. That said, the compendium requires authentication of a paid account. I see the compendium as a great value. Wizards makes all the rules, feats, powers, etc. available in the compendium site and character creator even if you haven’t purchased the book. They have a lot of intellectual property in the compendium, and it makes sense to me that they get paid for the service.
When you view your character sheet in the character creator, there is a page or two of “power cards” at the end. I thought it would be interesting to print those on 4×6 cards, laminate them, and make them available to the players to make playing easier, especially since we have a few new players in our group for this session. The format of the cards from the character creator wasn’t quite right for me. First, because it contained character specific information, like bonuses at the current state of the character. I wanted the generic power cards that could be reused by different characters. With them laminated, they players could write the appropriate bonuses right on the cards in dry-erase marker, and update as we go.
My solution was to use the nice, open, dnd4e xml files saved by the character creator. I wrote a little jython script that uses the httpunit framework in java to login to the compendium and download the power pages. that way they don’t have any character specific information in them, and I can just open them in firefox and format them for my 4×6 cards that I can feed right through the printer.
the script took considerably longer than I hoped, partly because I haven’t done any jython/python in a few years, partly because of the compendium login session management. So, without further ado, here is the source.
from java.io import FileInputStream from javax.xml.transform.stream import StreamSource from javax.xml.transform.stream import StreamResult from javax.xml.parsers import DocumentBuilderFactory from com.meterware.httpunit import * from com.meterware.httpunit.cookies import CookieProperties import subprocess import codecs import os.path import sys email = "YOUR EMAIL ADDRESS HERE" pwd = "YOUR PASSWORD HERE" inputList = sys.argv; del inputList; nameList =  CookieProperties.setDomainMatchingStrict( 0 ); CookieProperties.setPathMatchingStrict( 0 ); wc = WebConversation(); def getPower( url, name ): if name not in nameList: print name+"..."; if not os.path.exists( name ): try: nameList.append( name ); request = GetMethodWebRequest( url ); response = wc.getResponse( request ); form = response.getFormWithID( "form1" ); if form is not None and "email" in form.getParameterNames(): print "logging in"; form.setParameter( "email", email ); form.setParameter( "password", pwd ); subButton = form.getSubmitButton( "InsiderSignin" ); response = form.submit(subButton); request = GetMethodWebRequest( url ); response = wc.getResponse( request ); else: print "not required to login"; outFile = codecs.open( name, "w", "utf-8" ); outFile.write( response.getText()); outFile.close(); except: nameList.remove( name ); print "ERROR: Unable to get "+name+" at "+url; for charname in inputList: print "Processing "+charname fname = "characters/%s.dnd4e" % charname input=None powerdir = "./characters/"+charname+"/powers" try: input=FileInputStream( fname ) except: print "unable to load %s" % fname continue try: print "making directory %s" %powerdir os.makedirs( powerdir ) except: print "uanble to make directory %s" % powerdir factory = DocumentBuilderFactory.newInstance() builder = factory.newDocumentBuilder() document = builder.parse(input) nodes = document.getElementsByTagName( "RulesElement" ) for i in range( nodes.getLength()): node = nodes.item(i) if node.getAttributes() is not None: typeattr = node.getAttributes().getNamedItem( "type" ) urlattr = node.getAttributes().getNamedItem( "url" ) nameattr = node.getAttributes().getNamedItem( "name" ) if typeattr.getNodeValue() == "Power" : if urlattr is not None and urlattr.getNodeValue() is not None: outName = powerdir+"/"+nameattr.getNodeValue()+".html"; getPower( urlattr.getNodeValue(), outName ); else: print "no attributes" input.close()
Ok, so this is not pretty jython code. I’m sure there are a hundred improvements that could be made to this code by someone that actually knows what they are doing in python. Here’s the batch script I use to launch the script
@echo off set LIBPATH=.\lib set JAR_PATH=%LIBPATH%\httpunit.jar;%LIBPATH%\js-1.6R5.jar;%LIBPATH%\nekohtml-0.9.5.jar;%LIBPATH%\xercesimpl-2.6.1.jar ..\jython2.5.1\bin\jython.bat -Dpython.path=%JAR_PATH% getpowers.py %*
Obviously, to run the script, you must have the above jar files, which are used to support httpunit. Also, you must have jython. Once you have that, you can modify the .bat script for your environment.
The getpowers.py script is expecting to have a directory named “characters” adjacent to it. Within that directory should be the dnd4e files for the characters. It would be awesome if the script would just grab all the .dnd4e files within the characters directory, but it doesn’t yet. That’s just the way it is. Part of the reason was so that I would be able to update only a single character at a time if I wanted to. In any case, I run it as follows:
jython.bat Fezzik Orlissa
where Fezzik and Orlissa are the names of the characters, and have corresponding Fezzik.dnd4e and Orlissa.dnd4e files in the characters directory.
The script will load the dnd4e file, find all the powers that have URLs, and download them. Fortunately, it will not download them if they already exist on the hard drive (we don’t want to abuse wizards’ servers) for that character.
I’ve debated whether to have it dump all the powers into the same directory or do it on a character by character basis. Right now I’ve got it on a character basis so that I know what I need to print for each character before we get started. I’ll probably modify it and just use the timestamp on the power file to know which ones to print once we get started.
Finally, to get the power file to display correctly, you must have the stylesheets within the appropriate directory so they can be read by your browser when you load the power html file. Wizards used different stylesheets for the view, and the print. The print stylesheet removes all the colors and whatnot. That’s easy enough to get around by simply saving the display stylesheet as both display and print.
I may be blogging about this earlier than I should. The script isn’t really great yet, but it’s functional for my needs, and I thought it might be a good start for anyone else looking to do the same thing.