Guest Post – Making the Game part 10 – Overseas manufacturing

Previous Entry: Part 9

Welcome back to my blog series Making the Game, in which I talk about the process of creating my card and dice game, Chaos & Alchemy. This is an addendum to my previous post about manufacturing the game by guest blogger Jamey Stegmaier, the creator of a game called Viticulture that is currently on Kickstarter. Here’s Jamey.

-Michael the OnlineDM

Jamey Stegmaier – your friendly guest blogger today

Viticulture has a number of components, including: 

  • A box
  • 140 cards
  • A game board
  • A rulebook
  • Player mats
  • Wood tokens/meeples
  • Clear acrylic glass gems
  • Punchboard coin tokens

Unlike Chaos & Alchemy, I’m obtaining all of these components from the same source: Panda Games Manufacturing. Michael was doing a print-run of 125 games, and it’s great that he was able to piece everything together from manufacturers here in the U.S. It definitely saves on freight shipping.

But I wanted a manufacturer who could handle the whole process and keep costs low. I did not have success finding a manufacturer in the U.S. who meets those requirements, so I turned to a company that several other Kickstarter game creators had recommended to me.

Their recommendations could not have been more accurate. Panda is a pleasure to work with—specifically, Chris Matthew (chris@pandagm.com), who actually works out of Panda’s corporate office in Vancouver. Chris is highly communicative and is great at identifying little issues that you might overlook (like when your player mats are bigger than the box…oops). I wouldn’t recommend reaching out to him unless you know exactly what your components will be. 

Freight Shipping

The other factor you have to weigh when you consider Panda Games is that you have to pay for freight shipping across the Pacific. That will run you between $4k (half a shipping container) and $6k (a full container). They’ll ship door to door, which means that they can take care of customs and tariffs and all that (you’ll pay for it, but they’ll oversee the process). But you also need to have a destination for all those games (I’m still learning about what happens next if you use a storage and fulfillment center, so perhaps I’ll have to follow up with another post in the future). 

Cost

The high freight shipping cost means that you want to ship as many games as possible. The minimum order through Panda is 1500 copies of the game, hence the necessity for Kickstarter unless you have $20k sitting around collecting dust (and if that’s the case, you really should at least put that cash in a bank). If your game has similar components to mine, you can expect to save about a dollar if you increase your print run from 1500 to 2000, and then another dollar if you increase that to 3000 (which will fill a shipping container). Thus 3000 is kind of the sweet spot to maximize your per-unit price and your shipping costs. 

Viticulture box art by Beth Sobel – one of the Chaos & Alchemy artists!

Duration

You’re probably wondering about manufacturing time. From the minute you send your final files to Panda, there will be a bare minimum of 4 months before you receive your games, and that’s if everything goes perfectly. 3 months at Panda for manufacturing, 1 month for shipping. And that doesn’t include packing and shipping the individual recipients. I budgeted 6 months for Viticulture, but I hope to be faster than that. 

Customization

On Kickstarter, it’s common to offer different versions of the same game so people have a choice. For example, I offer the Viticulture base game for $39 and the game + expansion for $49. Panda can custom package your games based on those reward levels.

Components

I have a few notes about some of the components. 

Cards

You’ll want to keep a few numbers in mind if you have cards in your game so that you can maximize each sheet of cards, as it costs a fair amount to set a single sheet. Depending on the size of the cards you’re using, different numbers of cards can fit on a single sheet: 

•    57 x 87mm (bridge) – 54 cards/sheet
•    63 x 88m (blackjack) – 54 cards/sheet
•    59 x 91mm (euro) – 45 cards/sheet
•    44 x 67mm (mini) – 70 cards/sheet

I decided to go with the mini cards for Viticulture—they’re the same size as the cards in Settlers of Catan. They’re not big enough for a lot of text, but my cards don’t have much text.

Wood Tokens/Meeples

Panda can make pretty much any type of token if you send them an outline to use. You’ll have to pay extra for custom tokens, and even more with custom tokens with concavities, but anything else is fair game.

Punchboards

You’ve probably seen these in games: thick cardboard with corrugated coins to be poked out before you can play. The key with these is to include everything on a single punchboard and then have Panda include multiple copies per game if necessary. For example, in Viticulture, there are 108 coins. I can fit 36 per sheet, so I’m putting all of the various types of coins on one sheet (opposed to all silver coins on one sheet and all gold coins on the next). That way Panda only has to set one sheet of tokens.

Metal Coins

I wish I had known more about metal tokens before I started my campaign. Now I know better. I think these are a really cool addition to any game. They’ll cost you a bit, but it’s not extravagant, and at the very least you could offer them as a stretch goal on Kickstarter.

I think that’s pretty much it. I’m sure I’ll have more to share after this process is over—I’ve only really just begun. But I’ll share more in the future. In the meantime, if you want to stay in touch with Stonemaier Games, feel free to subscribe to our blog or Like us on Facebook. Or back Viticulture on Kickstarter to get updates throughout the manufacturing process—I intend to share the inside scoop with everyone there. Thanks!

 

This is Michael jumping back in here to say that I’m a backer of Viticulture; it’s definitely my kind of game. I highly recommend checking it out!

-Michael the OnlineDM

New maps from Tobold – Iron Keep from Reavers of Harkenwold

A few months ago, Tobold from Tobold’s Blog reached out to me for maps from Reavers of Harkenwold. I ran the adventure last year (review here) and had put up my own recreated maps for the adventure on my blog. (I later discovered that the official maps were available from the Wizards of the Coast web site for D&D Insider subscribers.)

Tobold made use of some of my maps, but he also took the time to create his own versions of the Iron Keep main tower maps using Campaign Cartographer. He was gracious enough to allow me to share his versions here as well. These maps, along with all of my other maps, can be found on my Map Library page. As you can see, his versions are a significant upgrade over what I had originally made!

Grand Tower 1st floor by Tobold

Grand Tower First Floor - My version

Grand Tower 2nd floor by Tobold

Grand Tower Second Floor - my version

Grand Tower 3rd floor by Tobold

Grand Tower Third Floor - my version

Thank you to Tobold for sharing these maps! And if anyone else wants me to share their maps on my site, please reach out to me at onlinedungeonmaster@gmail.com.

Five new maps from Josh Cayer

Online Dungeon Master is usually a one-man operation (that’s me), but I welcome guest posts and contributions. Today, I’m pleased to share some maps and MapTool files created by one of my readers, Josh Cayer. These maps have also been added to my Map Library.

Wizard Tower

The MapTool file can be downloaded here. Josh explains:

It is a combo puzzle/encounter….I have left the solution in place.  Just remove the Orbs from the map.
Upon entry, the illusionary wizard at the bottom of the map appears and tells the players they must place 8 orbs on the map.  The orbs cannot “see” each other horizontally or vertically.
Like I said, there are no orbs on the map at the start.  A new one can be obtained from any of the three bowls.  Only one orb can be in play at a time.  Once an orb is placed, it grows to fill the square, making it impassable.
Once an orb is placed, moving next to it results in a small amount of lightening damage.
A misplaced orb can be moved but there is lightening damage.
The beholders, if killed, continue to come back until all the orbs are placed.

Wizard Tower by Josh Cayer - Gridded

Wizard Tower by Josh Cayer - no grid

Valley map

I particularly like this one. The MapTool file is here.

Valley by Josh Cayer - Gridded

Valley by Josh Cayer - no grid

Cave complex

This is a gigantic map! I’ve done what I can to reproduce it from the MapTool file with good resolution, which means that it’s a big file.

Cave Complex (very large) by Josh Cayer - Gridded

Cave Complex (very large) by Josh Cayer - no grid

Ruined temple

The MapTool file for this one is here.

Ruined Temple by Josh Cayer - Gridded

Ruined Temple by Josh Cayer - no grid

Small ship with dock

The MapTool file is here.

Small ship and dock by Josh Cayer - gridded

Small ship and dock by Josh Cayer - no grid

Thank you so much to Josh Cayer for submitting these maps! I’ve already received some more maps from another cartographer, which I’ll be posting about soon. If you have maps you’d like to see hosted by the Online Dungeon Master, please send me an email at onlinedungeonmaster@gmail.com.

– Michael the OnlineDM

Guest Post from Paul Baalham: MapTool ongoing damage tracking macro

Editor’s note from OnlineDM: Today we are lucky to have another guest post, this one from Paul Baalham (@paulbaalham on Twitter; you can also find him at Daily Encounter).

Tracking ongoing damage and conditions with MapTool for 4E

As a DM that wants to use MapTool to handle all the boring stuff of D&D fights, to leave the players and me more tim for the fun stuff, I realised very early on that I wanted to create a system that would track ongoing damage and conditions so that we wouldn’t forget about the ongoing damage or that the slowed condition actually ended on the PC’s last turn. I managed to get the ongoing damage tracked quite easily so here is what I have done. Could it be improved? Almost certainly. If you can improve it then PLEASE let me know in the comments.

Campaign Properties

The code in this post require the following properties for the tokens that will be using it (i.e. players and monsters).

Acid:0
Cold:0
Fire:0
Force:0
Lightning:0
Necrotic:0
Poison:0
Psychic:0
Radiant:0
Thunder:0
Untyped:0
SEAcid:0
SECold:0
SEFire:0
SEForce:0
SELightning:0
SENecrotic:0
SEPoison:0
SEPsychic:0
SERadiant:0
SEThunder:0
SEUntyped:0
IsWarden:0

The SE variables are to help determine whether there is a Save Ends condition. I think there is probably a way of eliminating these, but I haven’t thought of a way yet (it works currently so I don’t want to break it!) The ISWarden may look out of place, but as Wardens can save against ongoing damage at the start of their turn, this variable helps in keeping track of the initiative.

The “Place Ongoing Damage” Button

I created a button for placing ongoing damage to tokens. This was situated on my Campaign macros window, but where you put it is up to you,

First of all, in the States section of the Campaign Properties the following states should be present:

Acid
Cold
Fire
Force
Lightning
Necrotic
Poison
Psychic
Radiant
Thunder
Untyped

Each one of these states should be in the Group called “Damage”.

This allows us to collect together all of the ongoing damage types like this:

[h: dmgList = getTokenStates(",","Damage")]

We then need to get a list of all of the tokens that are on the map:

[h: tokenList=getExposedTokenNames()]
[h: imgList = tokenList]
[h: Num = listCount(imgList)]

We need to create a list of token names and create a list of images to display.

[h,COUNT(Num),CODE:
{
  [h:tokenName=listGet(imgList,roll.count)]
  [h,token(tokenName): image=getTokenImage()]
  [h:imgList=listReplace(imgList,roll.count,tokenName+" "+image)]
}]

Next we display a pop up window that shows a list of targets (including images) as well as a list of the types of damage. Finally the value of the ongoing damage needs to be typed in by the DM.

[h:status=input(
"Target|"+imgList+"|Select Target|LIST|SELECT=0 ICON=TRUE ICONSIZE=30",
"damageType|"+dmgList+"|Select Type of Damage|LIST|SELECT=0 VALUE=STRING",
"amount| |Enter amount of damage"
)]
[h:abort(status)]

We now know the name of the target so we can switch the focus to that token:

[h:targetName = listGet(tokenList,Target)]
[h:switchToken(targetName)]

The following looks at what type of damage it was, sets the value of the appropriate variable and then creates a string to be dsiplayed at the end. This is the bit of code I think is the most likely that someone could improve upon.

[h,switch(damageType),code:
  case "Acid": {
    [h: Acid=amount]
    [h: SEAcid=1]
    [h: stringToShow= targetName+ " has ongoing Acid damage"]
  };
  case "Cold": {
    [h: Cold=amount]
    [h: SECold=1]
    [h: stringToShow= targetName+ " has ongoing Cold damage"]
  };
  case "Fire": {
    [h: Fire=amount]
    [h: SEFire=1]
    [h: stringToShow= targetName+ " has ongoing Fire damage"]
  };
  case "Force": {
    [h: Force=amount]
    [h: SEForce=1]
    [h: stringToShow= targetName+ " has ongoing Force damage"]
  };
  case "Lightning": {
    [h: Lightning=amount]
    [h: SELightning=1]
    [h: stringToShow= targetName+ " has ongoing Lightning damage"]
  };
  case "Thunder": {
    [h: Thunder=amount]
    [h: SEThunder=1]
    [h: stringToShow= targetName+ " has ongoing Thunder damage"]
  };
  case "Necrotic": {
    [h: Necrotic=amount]
    [h: SENecrotic=1]
    [h: stringToShow= targetName+ " has ongoing Necrotic damage"]
  };
  case "Psychic": {
    [h: Psychic=amount]
    [h: SEPsychic=1]
    [h: stringToShow= targetName+ " has ongoing Psychic damage"]
  };
  case "Poison": {
    [h: Poison=amount]
    [h: SEPoison=1]
    [h: stringToShow= targetName+ " has ongoing Poison damage"]
};
  case "Radiant": {
    [h: Radiant=amount]
    [h: SERadiant=1]
    [h: stringToShow= targetName+ " has ongoing Radiant damage"]
  };
  case "Untyped": {
    [h: Untyped=amount]
    [h: SEUntyped=1]
    [h: stringToShow= targetName+ " has ongoing damage (untyped)"]
  }
]

Almost finished! We need to put the damage on the token.

[h:Condition=damageType]
[h:setState(Condition,1)]

And finally show the string that we formatted earlier that tells everyone who has been tagged with ongoing damage, the type and how much.

[r: stringToShow]

Now we have a way of placing the ongoing damage on a token, we need a way of automating the subtraction of the damage from tokens at the start of their turn and reminding them to save at the end of their turn.

The “Next Initiative” Button

I created a button that I placed on the Campaign group called Next Initiative which passes the initiative to the next person on the list. But before it does this it checks to see if the current token has any save ends conditions on it (I have only pasted the ongoing damage here as conditions will be in another post).

First of all, we need to determine who the current token is and switch the focus to that token:

[h: id = getInitiativeToken()]
[h: switchToken(id)]
[h: targetname=getName(id)]

Next we need to see if the token has ongoing damage it needs to save against. It will then ask if the token has saved against it. The DM will see a popup window asking if the player saved against the condition. The player should still be able to roll for the save while the pop up is on the DM’s screen.

[h:saveList=""]
[h,if(SEAcid), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Acid damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEAcid=0]
    [h:Acid=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Acid damage! :D"]
    [h:state.Acid=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Acid damage! :("]
  }]
}]

[h,if(SECold), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Cold damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SECold=0]
    [h:Cold=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Cold damage! :D"]
    [h:state.Cold=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Cold damage! :("]
  }]
}]
[h,if(SEFire), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Fire damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEFire=0]
    [h:Fire=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Fire damage! :D"]
    [h:state.Fire=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Fire damage! :("]
  }]
}]
[h,if(SEForce), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Force damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEForce=0]
    [h:Force=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Force damage! :D"]
    [h:state.Force=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Force damage! :("]
  }]
}]
[h,if(SELightning), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Lightning damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SELightning=0]
    [h:Lightning=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Lightning damage! :D"]
    [h:state.Lightning=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Lightning damage! :("]
  }]
}]
[h,if(SENecrotic), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Necrotic damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SENecrotic=0]
    [h:Necrotic=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Necrotic damage! :D"]
    [h:state.Necrotic=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Necrotic damage! :("]
  }]
}]
[h,if(SEPoison), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Poison damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEPoison=0]
    [h:Poison=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Poison damage! :D"]
    [h:state.Poison=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Poison damage! :("]
  }]
}]
[h,if(SEPsychic), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Psychic damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEPsychic=0]
    [h:Psychic=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Psychic damage! :D"]
    [h:state.Psychic=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Psychic damage! :("]
  }]
}]
[h,if(SERadiant), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Radiant damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SERadiant=0]
    [h:Radiant=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Radiant damage! :D"]
    [h:state.Radiant=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Radiant damage! :("]
  }]
}]
[h,if(SEThunder), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Thunder damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEThunder=0]
    [h:Thunder=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Thunder damage! :D"]
    [h:state.Thunder=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Thunder damage! :("]
  }]
}]
[h,if(SEUntyped), code: {
  [h:stringToShow="Did " + targetname + " Save against ongoing Untyped damage? (1=yes, 0=no)"]
  [h:status=input("hasSaved|0|"+stringToShow)]
  [h:abort(status)]
  [h,if(hasSaved), code: {
    [h:SEUntyped=0]
    [h:Untyped=0]
    [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Untyped damage! :D"]
    [h:state.Untyped=0]
  };
  {
    [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Untyped damage! :("]
  }]
}]

[h:stringToList(saveList, " ")]
[h:number=listCount(saveList)]
[r,if(number>0),code:{
  [r,foreach(var,saveList),code:{
    [r:var]
    <br>
  }]
}]
<br>

Pass the initiative onto the next token.

[h: nextInitiative()]

And here is where it starts to get a bit messy. My wife plays a Warden in the game. Wardens get to save against conditions at the START of their turn.

Get the token that now has initiative and switch the focus to them.

[h: id = getInitiativeToken()]
[h: switchToken(id)]

If they are a Warden then repeat the code from up above:

[h,if(isWarden==1),code: {
  [h:saveList=""]
  [h,if(SEAcid), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Acid damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEAcid=0]
      [h:Acid=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Acid damage! :D"]
      [h:state.Acid=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Acid damage! :("]
    }]
  }]
  [h,if(SECold), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Cold damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SECold=0]
      [h:Cold=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Cold damage! :D"]
      [h:state.Cold=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Cold damage! :("]
    }]
  }]
  [h,if(SEFire), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Fire damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEFire=0]
      [h:Fire=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Fire damage! :D"]
      [h:state.Fire=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Fire damage! :("]
    }]
  }]
  [h,if(SEForce), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Force damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEForce=0]
      [h:Force=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Force damage! :D"]
      [h:state.Force=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Force damage! :("]
    }]
  }]
  [h,if(SELightning), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Lightning damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SELightning=0]
      [h:Lightning=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Lightning damage! :D"]
      [h:state.Lightning=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Lightning damage! :("]
    }]
  }]
  [h,if(SENecrotic), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Necrotic damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SENecrotic=0]
      [h:Necrotic=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Necrotic damage! :D"]
      [h:state.Necrotic=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Necrotic damage! :("]
    }]
  }]
  [h,if(SEPoison), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Poison damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEPoison=0]
      [h:Poison=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Poison damage! :D"]
      [h:state.Poison=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Poison damage! :("]
    }]
  }]
  [h,if(SEPsychic), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Psychic damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEPsychic=0]
      [h:Psychic=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Psychic damage! :D"]
      [h:state.Psychic=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Psychic damage! :("]
    }]
  }]
  [h,if(SERadiant), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Radiant damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SERadiant=0]
      [h:Radiant=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Radiant damage! :D"]
      [h:state.Radiant=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Radiant damage! :("]
    }]
  }]
  [h,if(SEThunder), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Thunder damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEThunder=0]
      [h:Thunder=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Thunder damage! :D"]
      [h:state.Thunder=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Thunder damage! :("]
    }]
  }]
  [h,if(SEUntyped), code: {
    [h:stringToShow="Did " + targetname + " Save against ongoing Untyped damage? (1=yes, 0=no)"]
    [h:status=input("hasSaved|0|"+stringToShow)]
    [h:abort(status)]
    [h,if(hasSaved), code: {
      [h:SEUntyped=0]
      [h:Untyped=0]
      [h:saveList=saveList+" ,"+targetname + " has saved against the ongoing Untyped damage! :D"]
      [h:state.Untyped=0]
    };
    {
      [h:saveList=saveList+" ,"+targetname + " did not save against the ongoing Untyped damage! :("]
    }]
  }]
}]

[h:stringToList(saveList, " ")]
[h:number=listCount(saveList)]
[r,if(number>0),code:{
  [r,foreach(var,saveList),code:{
    [r:var]
    <br>
  }]
}]

Next. we display the name of who has initiative and display the current conditions effecting them.

[r: getName(id) + " has Initiative"]
[r:strlist = "and currently has"]

The next line just sees whether there is any ongoing damage at all (this could probably be used further up, but I haven’t done this yet).

[h:OD=Acid+Cold+Fire+Force+Lightning+Necrotic+Poison+Psychic+Radiant+Thunder+Untyped]

If there is ongoing damage then cycle through the damage types and subtract the value from the token’s HP.

[h,if(OD>0),code:{
  [h,if(Acid>0):strlist=strlist+" ,"+ string(Acid)+" Acid damage"]
  [h,if(Cold>0):strlist=strlist+" ,"+ string(Cold)+" Cold damage"]
  [h,if(Fire>0):strlist=strlist+" ,"+ string(Fire)+" Fire damage"]
  [h,if(Force>0):strlist=strlist+" ,"+ string(Force)+" Force damage"]
  [h,if(Lightning>0):strlist=strlist+" ,"+ string(Lightning)+" Lightning damage"]
  [h,if(Necrotic>0):strlist=strlist+" ,"+ string(Necrotic)+" Necrotic damage"]
  [h,if(Poison>0):strlist=strlist + " ," + string(Poison)+" Poison damage"]
  [h,if(Psychic>0):strlist=strlist+" ,"+ string(Psychic)+" Psychic damage"]
  [h,if(Radiant>0):strlist=strlist+" ,"+ string(Radiant)+" Radiant damage"]
  [h,if(Thunder>0):strlist=strlist+" ,"+ string(Thunder)+" Thunder damage"]
  [h,if(Untyped>0):strlist=strlist+" ,"+ string(Untyped)+" Untyped damage"]
  [h:HP=HP-Cold]
  [h:HP=HP-Fire]
  [h:HP=HP-Force]
  [h:HP=HP-Lightning]
  [h:HP=HP-Necrotic]
  [h:HP=HP-Poison]
  [h:HP=HP-Psychic]
  [h:HP=HP-Radiant]
  [h:HP=HP-Thunder]
  [h:HP=HP-Untyped]
  [h:strlist=strlist + ", and now has " + HP + " HP"]
  [state.Dying = 1 - max(0,min(1,HP))]
  [state.Bloodied = 1 - max(0, min(1,HP - Bloodied))]
  [setBar("Health", HP/MaxHP)]
}]

Finally display the ongoing damages that the token is suffering from.

[h:stringToList(strlist, " ")]
[h:number=listCount(strlist)]
[r,if(number>1),code:{
  [r,foreach(var,strlist),code:{
    [r:var]
    <br>
  }]
}]

I hope someone finds this useful. I am not a software programmer by trade (although I do have to occasionally write code), so I am sure this code could be improved. It would be awesome if someone took this and made it better and allowed OnlineDM to post it on his site.

Guest post from @blindgeekuk: Becoming One of the Community

Editor’s note: My post on my feelings about my place (or lack thereof) in the online RPG community from Wednesday sparked a fair amount of discussion, most of which made me feel better! As part of that discussion, Adam Page (@blindgeekuk on Twitter and a contributor to Daily Encounter) asked if he could put up a guest post here on Online Dungeon Master talking about his feelings regarding the online RPG community. I was pleased that he asked. His post follows.

Becoming One of The Community

I wanted to write this post to tie it into OnlineDM’s comments from Wednesday, touch on my experiences, and emphasise why an existing member of the D&D community, like @ThadeousC getting the job at WotC is not only important, but is crucial.

I’ve been a gamer for 20 years. I was writing my own 2e and SLA Industries stuff before I knew that mailing lists and BBS hosted fan books existed for these games. It was only when I got a data connection for my cheap nokia phone, that let me dial up to the internet at a staggering 9.6 kbps that I was enlightened.

I only recently got involved in the D&D 4e community, but for most of the 00’s was a major figure in the SLA industries fan scene, publishing, at my last count, about 600 pieces of material for that game, and helping to form Team8, a group of UK rpg’ers that support the hobby. At the time, that community was effectively lead by a couple of well known names, and the goal of Team8 was to publish material without the stigma of a name attached to it… everything would be anonymous… The theory lasted 1 issue of our fanzine, before the names stepped in again to promote it and take control of the group. I left/was forced out, and to be honest, it was one of the best moves I made, because it showed me that I wasn’t after the glory or recognition, I just wanted to support my favourite game.

Having missed most of 3e, and the rumours of 4e, I checked it out when it hit the torrent site’s and I loved it, and have picked up pretty much everything since, spending several thousand dollars on minis and books in the 3 years i’ve been DM’ing. I reformed my old 2e group, I started up a roleplaying group at my FLGS because there was nothing for gamers there, and I heavily promoted that. In order to do so, I built a website…

And suddenly, unbeknownst to me, I was part of the community, people would google stuff and end up at my site, which I had intended just to be for my local players. When the rumours about Dark Sun started to hit, I collected them, and people like @Alphastream linked to them. I posted some rough ideas for content on there as well.

But it was the Encounters program, with it’s Twitter buffs that was the final transition. I’d checked out @wilw’s timeline a few times, and watched #gencon tweets flood in each year, but Encounters convinced me to create an account, and follow a few well known uk tweeters like @symatt and @greywulf. From there, the #ff system gained me followers, AND people to follow, and Twitter is all about the interaction with these people. I was starting to tweet to people whose blogs I read, and they were tweeting back… I was becoming one of their community.

After a year of this, I suffered a serious case of depression, and I decided to stop tweeting as me, and tried an experiment: was quantity, or quality a factor in getting recognised in the community, and how quickly could someone get accepted as being a contributing member of the community. I created a fake persona, twitter account, email, wordpress blog, and started filling it with content, from themes, to mundane descriptions to encounter summaries. I was surprised by the response. While it wasn’t the amazing ‘welcome to the community’ I was hoping for, some content did get discussed by people that most of us consider to be important tweeters (e.g @ChrisSSims).

I ended the blog early, scared of the implications if people found out, and because @SarahDarkmagic gave me a perfect opportunity. She had finally gotten the recognition she deserves with Lost City, and articles in Dragon, and she was discussing how she had become accepted into the community by basically introducing herself to people. My fake persona, and the real me grilled her on this, and we came to the summary that to be acknowledged in the community you need to:

“you have to write a regular schedule of good quality material, which shows attention to detail and a clear understanding of the game world/rules, it needs to show your passion for the game, you have to promote yourself in various places including twitter, the forums (enworld and wotc) and be heard on podcasts, and you need to build relationships with other bloggers by guest posting for them”

I closed down the persona, and started up my own blog, again, posting content until another bout of depression saw me slim down my online presence. However, prior to that, I was spotted doing stuff with Hirst Arts bricks by @mikemearls, opening up the chance to make the 3d version of Lair Assault.

Since closing down my own blog, I’ve taken that summary to heart. I’m posting here, there, and everywhere. While I don’t want the massive recognition, or to be named as one of the top ten D&D twitter people, I’d like to know that what I write is read and appreciated, and if anything, that’s something we fail in as a community, thanking each other and praising each other on a good blog post.

So yeah, thats my summary of how I became a member of the D&D community.

OnlineDM’s comments about not feeling part of the community mirror my own feelings until very recently. To me, there seems to be 3 levels in the community. You have your big names: @NewbieDM, @SlyFlourish, @SarahDarkmagic, people whose opinions are listened to and who are respected. Then there’s a middle tier, full of people who post regularly, but who don’t get the recognition they deserve: @ObsidianCrane, @PaulBaalham, @WastexGames. Finally, there is an outer tier, which is where many like OnlineDM feel they are. In this tier, you post but people never seem to respond, you tweet replies at people and never get re-tweeted etc. To me, it is important that people in here are supported, because there are a lot more of them than there are big names, and often, it’s these people who have the best content, but it’s just never seen…

At the start, I mentioned that I think a member of our community, like @thadeousc being WotC’s new social/community manager is important… There are lots of reasons why someone who understands twitter should get the job, but Thad is a known member of the community, and trusted by us all. If it came down to a situation that the community had reacted to, such as the announcement of Essentials, him saying ‘Trust me about this’ in a tweet would probably calm most of the raving fans down.

WotC have acknowledged that they lost touch with the fan base, that they have failed to communicate with us properly, and I think that reaching out to the community and hiring someone from there, who knows how we perceive things, and has the contacts amongst the twitterverse and blogosphere is the right thing to do.