DN's D&D4e Character Sheet Framework

Framework(s) for D&D 4e, including Veggiesama's.

Moderators: dorpond, trevor, Azhrei, giliath, Gamerdude, jay, Mr.Ice

psychopez
Kobold
Posts: 6
Joined: Tue Jun 29, 2010 12:41 pm

Re: DN's D&D4e Character Sheet Framework

Post by psychopez »

Hmm, let me take a look at it this weekend...

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

That would be...
AWESOME!!
Thanks in advance for any and all work you can do on this.
I am a special snowflake!

psychopez
Kobold
Posts: 6
Joined: Tue Jun 29, 2010 12:41 pm

Re: DN's D&D4e Character Sheet Framework

Post by psychopez »

First, introduction. I'm Mike aka PsychoPez. Been using MapTool for year and a half now, and DN for a year, both as a DM and a player. Been looking for an excuse to get into the guts of MapTool for some time, and this is as good an excuse as any.

So, things I've done in the past: wrote a iplay4e->WotC VT parser that worked with the exception of various server side values WotC added to the end VT char file, making a 3rd party translator all but impossible. But good learning experience.

Things I've not done in the past: MapTool dev, DN dev, JSON. So here's hoping today's learning experience is a bit more productive then the last...

Here's my very dirty, rough code so far. Next step is to do the grunt work of adding the obvious transforms where they belong, STR, STR mod, lvl, the 'first page' stuff, so if any of you experienced DN/MT devs want to provide feedback/comment to this new guy you can. I think adding the loops for stuffing the JSON into powers should be straight forward, the logic for determining unarmed/implement/weapon can be addressed after I get that done. :)

The issue I can plainly see now is this rptools hash table. I wash hoping to be able to do all of this outside of maptool, or as much as possible. Those hash table tags tell me there's some sort of maptool calls creating the hash, which tells me that this will have to be done inside of maptool someway, similar to the copy and paste from the Monster PDFs work. Might need some links to documention for that part, but I can worry about that later.

TL;DR, at the very least I should be able to get an xsl that transform all the data correctly for DN PCs (And if I get really ambitious, .monster files for NPCs that reads the monster xml directly). Uncertain about the hash tables, but I assume yinz guys are a friendly bunch that can answer my n00b questions and point me in the right direction.
Attachments
dnd4eToDN.zip
Zip of the files using to create the dnd4eToDN.xsl
(84.48 KiB) Downloaded 70 times

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

Psychopez, there is already an NPC converter done by TravisT.
http://forums.rptools.net/viewtopic.php?f=8&t=16137
Welcome to the DN world. I'm just the Head cheerleader, so I can offer no coding help, but I will applaud your every move.
I am a special snowflake!

psychopez
Kobold
Posts: 6
Joined: Tue Jun 29, 2010 12:41 pm

Re: DN's D&D4e Character Sheet Framework

Post by psychopez »

PinkRose wrote:Psychopez, there is already an NPC converter done by TravisT.
http://forums.rptools.net/viewtopic.php?f=8&t=16137
Welcome to the DN world. I'm just the Head cheerleader, so I can offer no coding help, but I will applaud your every move.


Yep, I know and use that all the time.

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

Ok. So your post confuses me then.
(And if I get really ambitious, .monster files for NPCs that reads the monster xml directly).
Is that the same thing? Or different?
And what is that file you posted and how is it used?
I am a special snowflake!

psychopez
Kobold
Posts: 6
Joined: Tue Jun 29, 2010 12:41 pm

Re: DN's D&D4e Character Sheet Framework

Post by psychopez »

PinkRose wrote:Ok. So your post confuses me then.
(And if I get really ambitious, .monster files for NPCs that reads the monster xml directly).
Is that the same thing? Or different?
And what is that file you posted and how is it used?


The current NPC parser requires a copy and paste from a pdf file. I'd like to, if I get the PC parser going simply by using the dnd4e file and feeding it somewhere, to do the same with a monster builder file. I like to think big...

RE: File, I hate it when people post on a forum that they'll do something, then never do it, which is easy because who cares, it's the interent. That's was just me saying, "Yep, I'm working on this, here's my minimial progress, but it's a start".

All questions can usually be answered by the first 6 letters of my forum name. :)

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

Well, I guess it would be ok to make this framework and my hobby better and easier.
I'll allow it.
I am a special snowflake!

jffdougan
Cave Troll
Posts: 55
Joined: Mon Jan 04, 2010 1:50 pm
Location: Central IL

Re: DN's D&D4e Character Sheet Framework

Post by jffdougan »

Not sure whether this counts as a bug or not, but something that cropped up the last time I got to play:

Trying to cut and then paste a token from one map in a campaign to another always dropped my remaining surges to 1. Copy and paste worked just fine, though.

Bizarre, and something I thought would be worth mentioning.
LFR Characters:

Tiernan, Vestige'lock 9
[spoiler=Tiernan's adventure wishlist]CORE 1-12 (H3), AGLA 2-1 (H3)[/spoiler]
Calisto, Arcas, Ganymede, & Thalia, Half-elf Sentinel Druid 2 and wall of fur
Knossos, Minotaur Lifespirit Warden 1

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

Wow. I cut and paste all the time with no loss of Healing Surges.
I don't even understand how that's possible if you cut and paste.
I am a special snowflake!

mojoflow
Kobold
Posts: 4
Joined: Thu Jun 30, 2011 1:03 pm

Re: DN's D&D4e Character Sheet Framework

Post by mojoflow »

I am trying to figure out how to get a character sheet (dnd4e) into a PC token using the DN framework, using the above scripts, and I am having some problems.

I am basically missing some steps I think due to not understanding how all the pieces fit together, I think.

Can anyone help me out with this, or point me at a thread that details it a bit more for a newbie?

Cheers!

User avatar
MadJoker
Cave Troll
Posts: 55
Joined: Sat Mar 28, 2009 3:43 pm

Re: DN's D&D4e Character Sheet Framework

Post by MadJoker »

Hi, I'm not sure if this is known, but I noticed that for powers the icon that represents the sustain action is missing, even though I have set a sustain action. After looking through the code I found out why that is. For finding the appropriate symbol you have a list of action types on Lib:Information, called "PowerActions".

Code: Select all

{"No Action":1,"Standard Action":5,"Move Action":4,"Minor Action":3,"Free Action":2,"Immediate Interrupt":7,"Immediate Reaction":7,"Opportunity Action":6,"First Bloodied":8,"Reduced to 0 HP":8}


However, for sustain actions you only use a short version, i.e. Standard, Minor, etc. Just replace the PowerEntry macro on Lib:Sheet with this

[spoiler=Fix for missing sustain icon]

Code: Select all

<!-- Power Entry -->
[H: setProperty("DNA_MacroTempStorage" + getPlayerName(), "")]
[H, forEach(DNT_Variable, "InfoWindowType, Slot, StorageGroup, GroupSlot, ColorType, SpecialType"): set("DNT_" + DNT_Variable, json.get(macro.args, DNT_Variable))]

[H, if(DNT_Slot == "New"), CODE:{[H: DNT_Entry = '{}']};{[H: DNT_Entry = getProperty(DNT_storageGroup + DNT_slot)]}]

[H: DNT_PowerKeywords = getLibProperty("PowerKeywords", "Lib:Information")]
[H: DNT_PowerActions = getLibProperty("PowerActions", "Lib:Information")]
[H: DNT_PowerRanges = getLibProperty("PowerRanges", "Lib:Information")]
[H: DNT_PowerUsage = getLibProperty("PowerUsage", "Lib:Information")]

[H: DNT_EntryUsage = json.get(DNT_Entry, "UsageType")]

[H: DNT_TitleColor = FindColor("Power", DNT_EntryUsage, 1)]
[H: DNT_TitleFont = FindColor("Power", DNT_EntryUsage, 2)]

[H: DNT_ReplaceList = "Flavor, Effect, Sustain, Special"]

<head>
   <meta name="input" content = "true">
   <title>Power Entry</title>
</head>
<body>
<form method="json" name="Edit Power" action="[R: macroLinkText('[email protected]:Sheet', 'none', '', currentToken())]">

<table width="100%" border="0" cellpadding="3" bgcolor="[R: DNT_titleColor]" nowrap="nowrap">
   <tr>
      <td><span style="color:[R: DNT_titleFont]"><b>Name:</b></span></td>
      <td><input type="text" name="Name" size="75" value="[R: json.get(DNT_Entry, 'Name')]"></input></td>
      <td><span style="color:[R: DNT_titleFont]">Tracking Power:</td>
      <td><select name="Tracker">
            <option value=""></option>      
[R, forEach(DNT_Tracker, getProperty("DNA_PowerIndex"), ""), CODE:
   {
      <option value='[R: DNT_Tracker]' [R: if(json.get(DNT_Entry, 'Tracker') == DNT_Tracker, "Selected", "")]>[R: json.get(getProperty("DNA_Power" + DNT_Tracker), "Name")]</option>
   }
]   
      </select></td>      
      <td><span style="color:[R: DNT_titleFont]">Delete?</span></td>
      <td><input type="checkbox" name="DeleteEntry" value="1"></input></td>
   </tr>
</table>
<table border="0" width="100%" cellpadding="3" bgcolor="B3AF94">
   <tr>
      <td colspan="6"><textarea rows="2" cols="100" name="Flavor">[R: ConvertHTML(json.get(DNT_Entry, "Flavor"))]</textarea></td>
   </tr>
</table>

<table border="0" width="100%" cellpadding="3" bgcolor="DBD9C0" nowrap="nowrap">
   <tr>
      <td><b>Type:</b></td>
      <td><select name="UsageType">
[R, forEach(DNT_usageType, json.fields(DNT_PowerUsage), ""), CODE:
   {
      <option value="[R: DNT_usageType]" [R: if(json.get(DNT_Entry, "UsageType") == DNT_UsageType, "selected", "")]>[R: DNT_UsageType]</option>
   }
]
      </select></td>      
      <td width="10"></td>
      <td>Uses:</td>
      <td><input type="text" name="Uses" value="[r: json.get(DNT_Entry, 'Uses')]" size="15"></input></td>
      <td width="10"></td>
      <td>Recharge:</td>
      <td><input type="text" name="Recharge" value="[R: json.get(DNT_Entry, 'Recharge')]" size="55"></input></td>
      <td width="10"></td>
      <td>Output Keywords:</td>
      <td><input type="checkbox" name="ShowKeywords" value="1" [R: if(json.get(DNT_Entry, "ShowKeywords") == 1, "Checked", "")]></input></td>
   </tr>
</table>
<table border="0" width="100%" cellpadding="3" bgcolor="DBD9C0">
   <tr>
[H: DNT_CellCount = 0]
[H: DNT_EndKeyword = json.get(DNT_PowerKeywords, json.length(DNT_PowerKeywords)-1)]

[R, forEach(DNT_Group, DNT_PowerKeywords, ""), code:
   {
      <td width="1" align="right"><input type="checkbox" name="Keyword[R: DNT_Group]" value="1" [R: if(json.contains(DNT_Entry, 'Keyword'+ DNT_Group) == 1, 'checked="checked"', "")]></input></td>
      <td align="left">[R: if(DNT_Group == "Implement" || DNT_Group == "Preparable" || DNT_Group == "Augmentable" || DNT_Group == "Reliable", "<b>", "")][R: DNT_Group]</b></td>
      [R: if(DNT_CellCount == 6 && DNT_Group != DNT_EndKeyword , "</tr><tr>", "")]
      [H: DNT_CellCount = if(DNT_CellCount == 6, 0, DNT_CellCount+1)]
   }
]
</table>
<table border="0" width="100%" cellpadding="0" bgcolor="DBD9C0">
<table border="0" cellpadding="3">
   <tr>
      <td>Action:</td>
      <td><select name="Action">
[R, forEach(DNT_Group, DNT_PowerActions, ""), CODE:
   {
         <option value="[R: DNT_Group]" [r: if(json.get(DNT_Entry, "Action") == DNT_Group, "selected", "")]>[R: DNT_Group]</option>
   }
]
      </select></td>
      <td width="10"></td>   
      <td>Range:</td>
      <td><select name="Range">
         <option value=""></option>
[R, forEach(DNT_Group, DNT_PowerRanges, ""), CODE:
   {
            <option value="[R: DNT_Group]" [R: if(json.get(DNT_Entry, "Range") == DNT_Group, "selected", "")]>[R: DNT_Group]</option>
   }
]
      </select></td>
      <td>Distance:</td>
      <td><input type="text" name="Distance" value="[R: json.get(DNT_Entry, 'Distance')]" size="5"></input></td>
      <td>Area:</td>
      <td><select name="AreaType">
         <option value=""></option>
         <option value="Burst" [R: if(json.get(DNT_Entry, "AreaType") == "Burst", "Selected", "")]>Burst</option>
         <option value="Blast" [R: if(json.get(DNT_Entry, "AreaType") == "Blast", "Selected", "")]>Blast</option>
         <option value="Wall" [R: if(json.get(DNT_Entry, "AreaType") == "Wall", "Selected", "")]>Wall</option>
      </select></td>
      <td>Size:</td>
      <td><input type="text" name="AreaSize" value="[R: json.get(DNT_Entry, 'AreaSize')]" size="5"></input></td>
   </tr>
</table>
<table border="0" cellpadding="3">
   <tr>
      <td>Requirements:</td>
      <td><input type="text" name="Requirements" value="[R: json.get(DNT_Entry, 'Requirements')]" size="100"></input>
      <td>List:</td>
      <td><input type="checkbox" name="ShowReqs" value="1" [R: if(json.get(DNT_Entry, "ShowReqs") == 1, "checked", "")]></input></td>
   </tr>
</table>
<table border="0" cellpadding="3">
   <tr>
      <td>Trigger:</td>
      <td><input type="text" name="Trigger" value="[R: json.get(DNT_Entry, 'Trigger')]" size="100"></input>
      <td>List:</td>
      <td><input type="checkbox" name="ShowTrigger" value="1" [R: if(json.get(DNT_Entry, "ShowTrigger") == 1, "checked", "")]></input></td>
   </tr>
</table>   
<table border="0" cellpadding="3" nowrap="nowrap">
   <tr>
      <td>Targets:</td>
      <td><input type="text" name="Targets" value="[R: json.get(DNT_Entry, 'Targets')]" size="100"></input>
</table>
</table>
<table border="0" width="100%" cellpadding="0" bgcolor="B3AF94" nowrap="nowrap">
<table border="0" cellpadding="3">
   <tr>
      <td><b>Number of Attack and Damage Routines:</b></td>
      <td><input type="text" name="AttackRoutines" value="[R: json.get(DNT_Entry, 'AttackRoutines')]" size="5"></input></td>
      <td width="10"></td>
      <td>Basic Attack</td>
      <td><input type="checkbox" name="IsBasic" value="1" [R: if(json.get(DNT_Entry, "IsBasic") == 1, "checked", "")]></input></td>
      <td width="10"></td>
      <td>Non-Attack/Conditions Only:</td>
      <td><input type="checkbox" name="HasConditions" value="1" [R: if(json.get(DNT_Entry, "HasConditions") == 1, "checked", "")]></input></td>
   </tr>
</table>
</table>
<table border="0" width="100%" cellpadding="3" bgcolor="DBD9C0">
   <tr>
      <td valign="top">Effect:</td>
      <td colspan="2"><textarea rows="3" cols="100" name="Effect">[R: ConvertHTML(json.get(DNT_Entry, "Effect"))]</textarea></td>
      <td valign="top">Output:</td>
      <td valign="top"><input type="checkbox" name="ShowEffect" value="1" [R: if(json.get(DNT_Entry, "ShowEffect") == 1, "checked", "")]></input></td>
   </tr>
   <tr bgcolor="B3AF94">
      <td valign="top">Sustain:</td>
      <td valign="top"><select name="SustainAction">
         <option value=""></option>
         <option value="Standard Action" [R: if(json.get(DNT_Entry, "SustainAction") == "Standard Action", "selected", "")]>Standard</option>
         <option value="Move Action" [R: if(json.get(DNT_Entry, "SustainAction") == "Move Action", "selected", "")]>Move</option>
         <option value="Minor Action" [R: if(json.get(DNT_Entry, "SustainAction") == "Minor Action", "selected", "")]>Minor</option>
         <option value="Free Action" [R: if(json.get(DNT_Entry, "SustainAction") == "Free Action", "selected", "")]>Free</option>
      </td></select>
      <td><textarea rows="2" cols="100" name="Sustain">[R: ConvertHTML(json.get(DNT_Entry, "Sustain"))]</textarea></td>
      <td valign="top">Output:</td>
      <td valign="top"><input type="checkbox" name="ShowSustain" value="1" [R: if(json.get(DNT_Entry, "ShowSustain") == 1, "checked", "")]></input></td>      
   </tr>
   <tr>
      <td valign="top">Special:</td>
      <td colspan="2"><textarea rows="2" cols="100" name="Special">[R: ConvertHTML(json.get(DNT_Entry, "Special"))]</textarea></td>
      <td valign="top">Output:</td>
      <td valign="top"><input type="checkbox" name="ShowSpecial" value="1" [R: if(json.get(DNT_Entry, "ShowSpecial") == 1, "checked", "")]></input></td>
   </tr>
</table>
<table border="0" width="100%" cellpadding="3" bgcolor="B3AF94" nowrap="nowrap">
   <tr>
      <td>List Notes:</td>
      <td><input type="text" name="Notes" value="[R: json.get(DNT_Entry, 'Notes')]" size="100"></td>
   </tr>
   <tr>
      <td>Chat Output:</td>
      <td><input type="text" name="Short" value="[R: json.get(DNT_Entry, 'Short')]" size="100"></td>
   </tr>
</table>
<table border="0" width="100%" cellpadding="3" bgcolor="DBD9C0">
   <tr>
      <td align="center" colspan="2"><input id="SaveButton" type="submit" name="SaveEntry" value="Save"></input></td>
   </tr>
</table>
[R, forEach(DNT_Variable, "InfoWindowType, Slot, StorageGroup, GroupSlot, ColorType, SpecialType", ""), CODE:{<input  type="hidden" name="[R: DNT_Variable]" value="[R: eval('DNT_' + DNT_Variable)]"></input>}]
<input type="hidden" name="ReplaceList" value="[R: DNT_ReplaceList]"></input>
</body></form>
[/spoiler]

Note that you need to edit and resave the Power for this to take effect. The sustain action entry will be missing the first time you edit the power after this fix.

User avatar
MadJoker
Cave Troll
Posts: 55
Joined: Sat Mar 28, 2009 3:43 pm

Re: DN's D&D4e Character Sheet Framework

Post by MadJoker »

Sorry for the double post, but this is something entirely different, so I thought it was appropriate to make it a new post.

I am also experiencing the interface locking up/black screen problem. Recently I started to look into the MT code, so I thought maybe I can track down that bug. Well, I spent some time looking at logs, and adding some additional logging stuff, and I can at least tell you that the problem is not caused by your FW. The freezing happens sometimes when the Character Sheet gets updated. My investigation showed that the HTML code for the frame in such a case is completely and normally generated and is even correctly send to the frame. But then something goes wrong, that is not really clear. My guess is, that it is some internal Java bug, that cannot be fixed by anyone here.

For those interested what exactly is happening, all the HMTL frame macros are executed on the same thread as the GUI (by the so called Event Dispatch Thread, EDT), so that the content is fully updated before any repainting happens. If this was not the case the token would be modifiable before the macro finished executing, which leads to problems. Now, what happens is that the macro is invoked on the EDT. It runs, and executes correctly. However, after it finishes the EDT just stops executing any orders it has pending. Because the GUI runs on this, the interface locks up, but everything else runs still fine.

So, this is just so that you can stop worrying that there might be some elusive bug in you FW which is causing this.

User avatar
PinkRose
Dragon
Posts: 732
Joined: Sat Nov 15, 2008 2:28 pm
Location: The City of Roses, Oregon

Re: DN's D&D4e Character Sheet Framework

Post by PinkRose »

THANK YOU!
I've had this problem for awhile now and my players think I'm crazy. (Two seperate issues, not sure if they are related)
There has been no mention by anyone else on the Maptool or the FW forums, so i apprecitae someone else pointing this out and saying it isn't my fault.
I am a special snowflake!

User avatar
OggDude
Kobold
Posts: 4
Joined: Tue Sep 14, 2010 2:42 pm
Location: Bay Area, CA

Re: DN's D&D4e Character Sheet Framework

Post by OggDude »

OK, I have a feeling that this has been addressed before, even though I haven't been able to find it, but...

So far, this is the cleanest, most professional-looking 4e framework I've come across. I'd love to use it, but one thing has been bugging me about it:

It doesn't support resistances and vulnerabilities.

Yes, I know you can add them as text, but I'd like the actual numbers taken into account when doing attacks. In other words, when the damage window comes up, I'd like a dropdown to choose damage type (Normal, Fire, Frost, Necrotic, etc). I'd also like this dropdown to be auto-selected based on the damage type defined for a power. That is, if an attack does 10 Fire damage, when I click on the "damage" link, I'd like the dropdown to automatically have "Fire" selected. And, of course, when applying damage to the token, I'd like vulnerabilities and resistances to effect the final damage done.

I know this will hit in a lot of areas. Character sheets will need a base resist/vuln setting supporting any of the damage types. Powers will need to grant temporary resists and/or vulnerabilities (if they exist), as will magic items, if equipped. And, there will probably need to be a dialog for choosing variable resistances. Keyword immunity to powers should also be covered somewhere.

Not asking for much, am I? :D As I said, this is a great framework, and I love the ability to import monsters from the MM or modules. I'd like to be able to import characters from the CB, too, but maybe soon. But the lack of resistance or vulnerability support is being a peeve of mine for some reason. I think it's because I tend to forget about them when I play old school, so I'd like whatever VTT I'm using to apply them for me. In fact, the simple "framework" I've made for myself right now supports resistances and vulnerabilities in my "do damage" macro.

Onto some other things... the two arrow icons to the right of powers allow you to perform generic attacks and targeted attacks. The problem is that, even though it'll say that an attack is "against Bob the Barbarian", it still won't compare attacks to defenses and tell whether or not I hit. I once saw a "Miss!" when I was playing around with multiple attacks, or secondary attacks, or something like that, but when I have a normal, "single" attack and go to target a token, it doesn't tell me whether I hit or not. Maybe it's something I'm doing, I don't know.

Also, as a minor point, when it puts tokens into the initiative tracker, it doesn't seem to sort them. Is it supposed to do that? I know if I try adding a non-DNA token, it prevents the macro from clearing off them decimal points that you use for tied initiative, but even with all DNA tokens, and even with the macro doing a floor() on the initiative score, it's still not auto-sorting.

Anyway, about the only other thing I think would be very cool would be if you convert the "attack target" dialog into a frame so you can select secondary tokens as targets for attacks, a la Rumble's FW, rather than selecting a target token and clicking on the "damage" link in chat. That and have some sort of AOE targeting capability :)

Enough whining for now. Again, great FW!
OggDude
There's someone in my head, but it's not me

Post Reply

Return to “D&D 4e Frameworks”