Thank you Wizards of the Coast

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="" 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 import FileInputStream
from import StreamSource
from 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


inputList = sys.argv;
del inputList[0];

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 ):
                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 );
                    print "not required to login";
                outFile = name, "w", "utf-8" );
                outFile.write( response.getText());
                nameList.remove( name );
                print "ERROR: Unable to get "+name+" at "+url;

for charname in inputList:
    print "Processing "+charname
    fname = "characters/%s.dnd4e" % charname
    powerdir = "./characters/"+charname+"/powers"
        input=FileInputStream( fname )
        print "unable to load %s" % fname

        print "making directory %s" %powerdir
        os.makedirs( powerdir )
        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 );
            print "no attributes"

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% %*

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 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.

Here’s a picture of the cards I printed.
DnD Power Cards

One thought on “Thank you Wizards of the Coast

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s