<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity=60)';}
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox where print preview displays the noscript content */
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

Also see [[AdvancedOptions]]
An Entry from the Journal of Eberweiss, Eladrin Demonwrecker
//-Expedition to the Demonweb Pits//

[[Sigil]], the City of doors, is the richest, most important crossroads town in the multiverse. It is ruled by an absolute despot - an autocrat called the [[Lady of Pain]] who says nothing and answers to no one. Her servants, the engineers and craftsfolk called the [[dabus]], do not speak either, but at least they communicate through illusions and visual riddles. Despite their strangeness, these creatures keep the city functioning and - for the most part - safe.

Cross the Lady, however, and you might just wind up in one of the mazes - the special pocket dimensions she creates that take years to escape from. Cross the dabus, and you are one step closer to crossing the Lady.

Sigil has only a few basic laws. Archons, devils, and other warring planar beings are forbidden to bring their conflicts here. Furthermore, the dabus immediately exile anyone caught damaging the city itself. And finally, recruitment for any kind of faction is forbidden. If you're a member of an organization, a philosopher's club, or a gentleman's society, keep it to yourself.

When you visit, remember that Sigil is the big time. You could be the greatest hero of whatever backwater plane you come from, but the greatest heroes of a great many planes gather here - and most are better than you. Sigil is the river born from a thousand streams, so it's best not to come here with an attitude.

You can get anywhere from Sigil - that's why it's called the City of Doors. But do some checking before you go jaunting off anywhere. Just because you can hop through a door to anywhere else in the multiverse doesn't mean that you should. A little time spent in the [[Library of the Lady]] can save you from painful, embarrassing, and costly mistakes that leave you weeks or months away from civilization. So be prepared when you travel. Get advice from the locals first. And yes, I do mean you should ask devils for the details before visiting the Nine Hells.

Oh, and don't drink the water. It's mostly recycled liquid waste that the dabus filter through their metropolitan aquamancy. It took years to learn that the dabus sell this nasty stuff to fund their repairs. Stick to beer, ale, or spirits.
New admissions are open to all intelligent humanoid races. The application process itself not public. Generally, a representative of the Planarversity visits the applicant. Often, the representative interviews the applicant in private, though an interview is not always required. Sometimes, there is a test of knowledge or skill. Requests to clarify the admission process are not answered, and all decisions are final for that academic year. Requests to apply in following years are usually unanswered.

Slightly less than half of all new students did not seek out the Planarversity. Representatives of the school constantly scout for new students, following a list of criteria known only to school officials. New classes rarely show any similarity from year to year. Only after deciding to approve on admission do they approach the candidate. Most do not refuse the call to the Planarversity. Financial aid and scholarships exists in various forms.

A very small number of full academic scholarships are handed out annually via open [[double-elimination|http://en.wikipedia.org/wiki/Double-elimination_tournament]] combat tournaments. [[Mercy]] is an example of one of this year's winners. //Tournament brackets are broken up by level: 1, 2, and 3. Applicants beyond level 3 are not allowed to enter the tournament.//

''//Please talk to the GM to determine how your PC enrolled into the Planarversity.//''

<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// 
College advisers are assigned to every new student to help guide the student through their undergraduate years at the Planarversity. Any questions or concerns regarding the school should be first directed toward one's college adviser.

Upperclassmen generally make up the college adviser pool, which is solely made up of volunteers. Most take on only one or two advisees, but some take a more active roll and advise a large number or undergraduates. Occasionally, faculty volunteer to become advisers. 

[img[Akioh the Autumn Lord|http://farm3.static.flickr.com/2462/3640477167_09ba87010f_o.jpg]]

Akioh the Autumn Lord is the first and sole Preceptor of the [[Shadowfell Planarversity]]. The campus lies on his protected demesne in the [[Shadowfell]]. He is rumored to have been the lover of both the third chancellor of the Planarversity, [[Arcueid Tenjou]], and the current chancellor of the Planarversity, [[Etuan Himemiya]]. He also serves as Captain of 1st Company, [[Order of the Rose]]. Akioh wields the legendary artifact known as the [[Godsword]].
|''Description:''|Inline annotations for tiddler text.|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|

*{{{((text to annotate(annotation goes here)}}}
* To include the text being annotated, in the popup as a title, put {{{^}}} as the first letter of the annotation text.
** {{{((text to annotate(^annotation goes here)}}}

Mouse over, the text below:
* ((banana(the best fruit in the world)))
* ((banana(^ the best fruit in the world)))

// /%
var _2=this.lookaheadRegExp.exec(w.source);
var _3=createTiddlyElement(w.output,"span",null,"annosub",_2[1]);
setStylesheet(".anno{position:absolute;border:2px solid #000;background-color:#DFDFFF; color:#000;padding:0.5em;max-width:15em;width:expression(document.body.clientWidth > (255/12) *parseInt(document.body.currentStyle.fontSize)?'15em':'auto' );}\n"+".anno h1, .anno h2{margin-top:0;color:#000;}\n"+".annosub{background:#ccc;}\n"+".annosubover{z-index:25; background-color:#DFDFFF;cursor:help;}\n","AnnotationStyles");

// %/
<tabs Character>
<tab Background>
!Aradun Mistwalker
//Moon Elf, 5'10" 185 lbs. 22 yrs. (appearance), pale skin, forest green eyes with gold flecks, tousled golden hair//
[img[Aradun Mistwalker|http://farm4.static.flickr.com/3107/3640512441_f7f475b036_o.jpg]]
<tab Stats>
Aradun Mistwalker, level 1
Moon Elf Paladin
Build: Avenging Paladin

Str 16, Con 10, Dex 13, Int 8, Wis 15, Cha 16.

Str 16, Con 10, Dex 11, Int 8, Wis 13, Cha 16.

AC: 19 Fort: 14 Reflex: 12 Will: 14
HP: 25 Surges: 10 Surge Value: 6

Religion +4, Insight +7, Intimidate +8, Endurance +5

Acrobatics -1, Arcana -1, Bluff +3, Diplomacy +3, Dungeoneering +2, Heal +2, History -1, Nature +4, Perception +4, Stealth -1, Streetwise +3, Thievery -1, Athletics +1

Level 1: Wild Elf Luck

Paladin at-will 1: Holy Strike
Paladin at-will 1: Enfeebling Strike
Paladin encounter 1: Piercing Smite
Paladin daily 1: Radiant Delirium

Adventurer's Kit, Vanguard Longspear +1, Verve Plate Armor +1
//(~ar-koo-AID ~TEN-joe)//


Arcueid Tenjou was the third chancellor of the Planarversity. She founded the [[Shadowfell Planarversity]] in 1466 DR, as well as the [[Order of the Rose]] in the same year.

Of note, she was an Feywild-born eladrin paladin, a dhampyr, close friends with [[the current chancellor|Etuan Himemiya]], and reportedly the lover of [[Akioh the Autumn Lord]].

She died defending the Shadowfell Planarversity from a massive undead invasion in 1470 DR.

Each year, The [[Planarversity]] holds series of combat arena tournaments, each serving different purposes. One is held each year as a form of admission application process. Some colleges hold tournaments as academic finals. And other tournaments are held purely for sport, as competition between the different colleges and campuses. The most widely held type of arena tournament is the 5v5 double elimination. Teams of five students are pitted up against similar teams, or against arena monsters, in a double elimination ladder. Arena tourneys are highly codified, and all safety precautions are taken, so there is almost never any loss of life.

| !Sample Bracket | !Event | !Typical 1st Place Prize | !Typical Monster Encounter | !Typical Map |h
|5v5 Level 1|admission tourney| 200gp | 2 [[Needlefang Drake Swarm (lvl 1)|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2155]], 3 [[Spiretop Drake|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=430]] | [[The Cage]] |
|5v5 Level 2|admission tourney| 290gp | 2 [[Hive Warrior|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2798]], 2 [[Hive Soldier|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2799]], 3 [[Hive Worker|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2797]] | [[The Cage]] |
|5v5 Level 3|admission tourney| 380gp | 2 [[Zairtail Firetongue|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1020]], 2 [[Zairtail Gazer|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1021]], 2 [[Zairtail Swarm|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1019]] | [[The Labyrinth]] |
|5v5 Level 5|first year mid-term tourney| Level 6 Magic Item and 500gp | 3 [[Deathjump Spider|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=134]], 2 [[Otyugh (lvl 5)|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1263]] | [[Lord of the Pit]] |
|5v5 Level 10|first year finals tourney| Level 11 Magic Item and 2500gp | 1 [[Foulspawn Hulk (lvl 11)|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2408]], 2 [[Foulspawn Grue (lvl 10)|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=2410]], 3 [[Foulspawn Mangler|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=658]] | [[Lord of the Pit]]|

*Teams must be formed by a team captain, and a team name must be given during registration.
*Each team must consist of members of the same or lower level as the bracket.
*An individual may only belong to a single arena team.
*//Competitors must be a race from the //PHB//, //~PHB2//, or //FRPG//. Monsters are part of monster encounters.//
*//Planarversity admissions through arena tournament accept ~PCs only from levels 1 through 3.//
*All participants, including the PC's and NPC's, are expressly limited to bringing into the arena nothing more than items following the rules below:
**3 magic items, of a level no more than the participant's level+3
**Non-magical, non-consumable items they can carry, equivalent to no more than 100 gold.
*//NPC teams may or may not follow these creation rules. When the do not, they follow the standard encounter rules.//

''Tournament Rules''
*//Each team will face three other teams per day, including at least one monster encounter and one PC team, in random order. Plan daily power and healing surge usage accordingly.//
*Time for a short rest follows every match. No extended rests between matches are possible. 
*Teams must provide for their own healing during and between matches.
*Unconscious or dead members unable to begin the next match are removed from the team and the remaining team members may continue the tournament short of five members, or voluntarily forfeit the tournament.

*//Each contestant starts each match with one action point total.  Only one action point may be spent per match.//
*A contestant may leave a match in progress in only two ways.
**A contestant who steps out of bounds, leaving the designated arena area, for at least three rounds is removed from the match.
**A contestant who remains unconscious for at least three rounds is removed from the match.
*Tournament officials teleport unconscious/dying contestants from the map and stabilize them. //Contestants are stabilized and may spend a healing surge. If a contestant has no remaining healing surges, the contestant is sent to the infirmary and forfeits the tournament.//
*A team with no contestants remaining in the match loses the match.
*The team with the least members left at the end of 30 rounds into a match is declared the loser of the match. In the case of a tied number of remaining members, the team that most recently lost a member is declared the loser of the match. In case of no members lost on either side, the team that spent the most number of healing surges is declared the loser of the match.

''Arenas (with maps)''
#[[The Cage]]
#[[Lord of the Pit]]
#[[The Labyrinth]]
# ''The Islands'' - 10x30
#*two 6x6 islands with no cover
#*swamp (scattered cover, difficult terrain) in the middle
#*nighttime (low light)
# ''The Highway'' - 15x10
#*a 3x10 road runs through the middle
#*water (difficult terrain) on both sides with limited cover
#*independent monsters in the water
# ''The Caves'' - 10x20
#*asymmetric map with two small starting areas
#*two large central areas, connected by three paths
#*featuring extensive cover/superior cover/concealment/superior concealment/traps
# ''The Keep'' - 14x14x10
#*one team starts in the keep
#*one team starts outside
#*assault is at night (full darkness), keep illuminated by scattered torches and central bonfire
#*keep is on an island surrounded by forest(cover), natural moat formed by river (difficult terrain), and 15' brick wall
#*an east-west road runs through the keep, bridging the river
#*2 open keep entrances with gates that start open
#*keep has main floor, parapets, two towers
<tabs Character>
<tab Background>
!Arkadio Durothil
//Sun Elf, 6'2", 180 lbs., 17 yrs. (appearance), bronze skin, shoulder length golden hair, golden eyes//
//(~Ar-KAY-dee-oh ~DUR-oh-thil)//


[[House Durothil|http://forgottenrealms.wikia.com/wiki/Durothil]] is the oldest noble [[sun elf|http://forgottenrealms.wikia.com/wiki/Sun_elf]] house on [[Faerûn|http://forgottenrealms.wikia.com/wiki/Faerûn]]. If the House were the tallest tree in [[Evermeet|http://forgottenrealms.wikia.com/wiki/Evermeet]], Arkadio would be the smallest sappling under its shadow. Indeed, he is a direct descendant of [[Prince Durothil|http://forgottenrealms.wikia.com/wiki/Durothil_(prince)]] - he is the youngest grandson of [[Selsharra Durothil|http://forgottenrealms.wikia.com/wiki/Selsharra_Durothil]], matron of the clan, and comes from a long line of statesmen, archmages, and warriors. No wonder he decided to throw it all away and run. Well, not all of it. Gold makes for a wonderful travel companion for a dilettante, after all.

Though still in his youth by elven standards, Arkadio had already spent years traveling across the realms, even dabbling in the courts of the [[Feywild|http://forgottenrealms.wikia.com/wiki/Feywild]]. His naturally good looks and the Durothil name opened many doors. Unfortunately, the name always came before him. Arkadio had drunken enough elven wine to become well aware of the painful truth that all the elven courts and women and songs were the same, more or less.

He spent a significant amount of time following the [[Golden Way|http://forgottenrealms.wikia.com/wiki/Golden_Way]], the trade route in far eastern [[Kara-Tur|http://forgottenrealms.wikia.com/wiki/Kara-Tur]], where few had ever seen an elf, let alone heard of his illustrious clan. He had even managed to become tavern fluent in the oriental [[Shou]] tongue, before his coinpurse began to hang lightly. On his return west, crossing the [[Hordelands|http://forgottenrealms.wikia.com/wiki/Hordelands]], he encountered the utterly enthralling [[Cheren of Khaghun]], princess of a dead clan. The encounter changed the course of his otherwise wandering life. Using every wit, wile, and gold coin in his purse, he rescued her from certain doom and ensured her safe passage back to his school in the distant west, [[Waterdeep Planarversity]]. She seemed enthralled with the idea.

If only he had actually attended the Planarversity... A few of his sisters had attended the school, an uncle at the [[Feywild Planarversity]]... he could make it happen... The road was far, and time and fortune were his dear, dear friends. In his travels, he discovered he had a knack for languages, people, and song. Attending a college to do more of the same, but on a far grander scale? It didn't sound overly painful.

The Durothil name -- and its deep contributions to the school - opened the door for both him and Princess Cheren. Of course he made no mention of a beautiful and tragic human princess to his family. That would only complicate things. Dread anything besmirch the Durothil name, no no... The matron seemed relieved that he finally decided to make something of himself. Arkadio, on the other hand... Waterdeep wine is such swill, after all.

<tab Stats>
Arkadio Durothil, level 1
Sun Elf Bard
Build: Cunning Bard
Bardic Virtue: Virtue of Cunning

Str 10, Con 14, Dex 12, Int 15, Wis 10, Cha 17.

Str 10, Con 14, Dex 10, Int 13, Wis 10, Cha 17.

AC: 17 Fort: 12 Reflex: 13 Will: 15
HP: 26 Surges: 9 Surge Value: 6

Thievery +6, Arcana +9, Streetwise +8, Insight +5, Bluff +8, Perception +5

Acrobatics +2, Diplomacy +4, Dungeoneering +1, Endurance +3, Heal +1, History +5, Intimidate +4, Nature +1, Religion +3, Stealth +2, Athletics +1

Bard: Ritual Caster
Level 1: Linguist

Bard at-will 1: Misdirected Mark
Bard at-will 1: Vicious Mockery
Bard encounter 1: Thunder's Calling
Bard daily 1: Echoing Roar

Ritual Book, Longsword, Adventurer's Kit, Lyre, Thunder Wand +1, Eladrin Chainmail +1
Comprehend Language, Glib Limerick

<tabs Character>
<tab Background>
!Aya Solice
//5'6", 110 lbs., 18 yrs. (appearance), golden skin, amber eyes, long golden locks//
//(~EYE-uh so-LISS)//
[img[Aya and Maya Solice|http://farm4.static.flickr.com/3662/3640468345_a3db6837ba_o.jpg]]

Aya and Maya Solice are identical twins, the only offspring of Esperifiel Solice and Lady Amberliss, a duchess of Feywild. 
Socialites known for being almost out of control and self-centered - and the most attractive girls in the entire school.
They don't act like snobs. They //know// they're better than everyone else. They don't need to flaunt it.
They keep no confidence other than their own. They are each other's best friends.
Aya acts as the "older" twin and does most of their talking.
They are inseparable, except when a boy is involved.
They are currently crushing on Tarsith of Solace, who is currently only a friend.
They are very competitive and do not accept losing as an option, and are willing to go to great lengths to win.
They are highly defensive of their dead father and will never forget or forgive a slight against him.
<tab Stats>
Aya Solice level 1
Eladrin, Rogue
Build: Aerialist Rogue
Rogue Tactics: Artful Dodger

Str 11, Con 10, Dex 20, Int 12, Wis 8, Cha 14.

Str 11, Con 10, Dex 18, Int 10, Wis 8, Cha 14.

AC: 18 Fort: 11 Reflex: 18 Will: 14
HP: 22 Surges: 6 Surge Value: 5

Perception +4, Stealth +10, Thievery +10, Bluff +7, Insight +4, Acrobatics +10, Athletics +7

Arcana +3, Diplomacy +2, Dungeoneering -1, Endurance, Heal -1, History +3, Intimidate +2, Nature -1, Religion +1, Streetwise +2

Level 1: Improved Initiative

Rogue at-will 1: Sly Flourish
Rogue at-will 1: Deft Strike
Rogue daily 1: Handspring Assault
Rogue encounter 1: Fox's Gambit

Dagger, Shuriken, Battle Harness Leather Armor +1, Gloaming Shroud +1, Lifedrinker Dagger +1

Plumes and Parchments begins at level 1, using a modified player character creation system. Players may play one of the [[Premade Characters]] or create their own character. Premade characters come with several starting magic items that give them an advantage versus standard starting characters. ''All characters, premade or player made, are level one with standard 22-point customized ability scores.''

All player characters must follow these guidelines:
#Race must be from the //Player's Handbook// or //Player's Handbook 2//
#''Good'', ''Lawful Good'', or ''Unaligned'' alignment
#Speak ''Common'' or ''Elven''
#Begin the campaign enrolled as a first year freshman undergraduate at [[Waterdeep Planarversity]]
#All official Dungeons &amp; Dragons rules sources (e.g. //Player's Handbook//, //Player's Handbook 2//, //Arcane Power//, //Dungeon// magazine, //Dragon// magazine) may be used, but are subject to final approval by the DM.

''The [[Character Builder|http://www.wizards.com/default.asp?x=dnd/insider/characterbuilder]] is highly recommended for character creation.''

The year is 1479 Dale Reckoning, The Year of the Ageless One. Ten years have passed since the death of [[Esperifiel Solice]], founder of the Planarversity, and nearly a century has passed since the Spellplague. Midsummer in Winterdeep has passed, and the new fire blossom saplings have begun to sprout in the [[Forest of Knowledge]] at the Central Campus, marking the beginning of a new and exciting year at the [[Planarversity]].

''Enroll now! [[Planarversity Matriculation|Matriculation]] and [[Planarversity Orientation|Orientation]].''

*[[Feywild Planarversity]]
*[[Shadowfell Planarversity]]
*[[Sigil Planarversity]]
*[[Waterdeep Planarversity]]

The Planarversity is ultimately lead by a Chancellor, elected by the Planarversity Elders, a council of Planarversity [[Founders]] and past chancellors, to run the daily business of the school. Chancellors serve until they decide to retire or until the founders elect a new chancellor.

!!Planarversity Chancellors
#[[Esperifiel Solice]] - 1396 DR to 1445 DR
#[[Erenthielle the Gray]] - 1445 DR to 1461 DR
#[[Arcueid Tenjou]] - 1461 DR to 1470 DR
#[[Elros Silvershield III]] - 1470 DR to 1479 DR
#[[Etuan Himemiya]] - 1479 DR (current)
<tabs Character>
<tab Background>
!Cheren of Khaghun
//Human, 5'9", 110 lbs., 17 yrs., dark tan complexion, mid-back straight black hair, brown oriental eyes//
//(~CHE-ren of ~KA-goon)//


Cheren is the last surviving member of the Khaghun, an ancient and nomadic tribe from the Eastern [[Hordelands|http://forgottenrealms.wikia.com/wiki/Hordelands]] of [[Abeir-Toril|http://forgottenrealms.wikia.com/wiki/Abeir-Toril]]. She is the late Khaghun khan's daughter and the reason why her tribe is nothing more than a whisper on the winds of the steppes of her distant homeland.

Cheren's mother was a runaway noble from [[Shou Lung|http://forgottenrealms.wikia.com/wiki/Shou_Lung]], and she inherited her mother's beauty and her father's strength, with jet black hair, long powerful legs, and a smokey, restless fire in her eyes. She grew up tall and proud, becoming a beauty unsurpassed -- a dangerous beauty that captured the attention of the son of a powerful [[Tuigan|http://forgottenrealms.wikia.com/wiki/Tuigan]] khan.

He would buy Cheren from her father and make her one of his brides, but she refused in pride. Never would she marry a weak and evil man. Her father turned down the young khanzadeh, and in response, the suitor gathered up an army of his father's men, destroyed her tribe, executed her father before her eyes, and left her to die among the remains of her people.

Cheren refused to die, would not die, would not let the carrion birds defile the bodies of her family. She had brought tremendous shame and sorrow upon her ancestors, and would not add to that shame by dying in vengeance, forever extinguishing the flame of her people.

Cheren is tall woman who wishes to stand taller, to stand for and avenge her people through living. She has made her way to [[Waterdeep Planarversity]] through incredible fortune and chance, with the help of [[Arkadio Durothil]], an eladrin bard who also attends Waterdeep Planarversity. She sees the school and the opportunities it offers as the greatest possibility for her to save her people. Through her, the songs and stories of her people will survive. The name Cheren means long life - a painful truth for the princess of a nearly dead race, but one full of hope.
<tab Stats>
Cheren of Khaghan, level 1
Human Ranger
Build: Archer Ranger
Fighting Style: Archer Fighting Style

Str 12, Con 12, Dex 18, Int 12, Wis 10, Cha 14.

Str 12, Con 12, Dex 16, Int 12, Wis 10, Cha 14.

AC: 17 Fort: 14 Reflex: 17 Will: 14
HP: 24 Surges: 7 Surge Value: 6

Perception +5, Nature +5, Endurance +5, Acrobatics +8, Athletics +5, Heal +5, Diplomacy +7

Arcana +1, Bluff +2, Dungeoneering, History +1, Insight, Intimidate +2, Religion +1, Stealth +3, Streetwise +2, Thievery +3

Human: Weapon Proficiency (Greatbow)
Level 1: Bardic Dilettante

Ranger at-will 1: Twin Strike
Ranger at-will 1: Careful Attack
Human: Nimble Strike
Ranger encounter 1: Fox's Cunning
Ranger daily 1: Hunter's Bear Trap

Hide Armor, Scimitar (2), Distance Greatbow +1, Cloak of Distortion +1
|Description:|Closes the tiddler if you click new tiddler then cancel. Default behaviour is to leave it open|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|

	handler_mptw_orig_closeUnsaved: config.commands.cancelTiddler.handler,

	handler: function(event,src,title) {
		if (!store.tiddlerExists(title) && !store.isShadowTiddler(title))
	 	return false;



Students are required to adhere to the Planarversity Code of Conduct at all times. As their studies may send them to locations with different sets of rules, students are advised to adhere to local laws and customs when possible. However, Planarversity laws supersede any and all other laws and customs.

Planarversity laws are protected and enforced by the [[Order of the Rose]], the standing policing force of the Planarversity.

!!Laws of Note
*[[School uniforms]] must be worn while on campus during school hours.
*Planarversity staff and students are strongly advised to maintain a neutral stance while studying in the field and keep a distance from local/regional politics.
*Though decidedly unaligned, the Planarversity has taken sides, more often than not, in support of Good or Lawful Good factions -- for purely pragmatic reasons. Such administrations are generally more favorable to scholarly pursuits.
*Duels between Planarversity students is regulated within the Planarversity [[Code of Dueling]], and violators shall be subject to academic probation or possible expulsion.
*Material theft from the Planarversity and/or its members is punishable by expulsion immediately following equivalent reimbursement of all properties if possible.
*Knowledge theft from the Planarversity and/or its members is punishable by expulsion immediately following a memory extraction of all stolen knowledge. Collateral memory loss is a common and acceptable consequence.
*Non-sanctioned violence against another student or faculty member leading to death is punishable by expulsion immediately following reimbursement of all material fees required to return any persons back to life and memory extraction of all Planarversity knowledge.
*Violations of local cultural laws or customs which cause a significant negative impact upon the Planarversity will result in permanent barring of access to the culture. Repeated violations shall result in expulsion or transfer to cultural auhorities.
*Divine intervention which interrupts with the regular functions of the Planarversity is prohibited. Violators shall be subject to expulsion, and gods will be barred from access to worshippers on school grounds.
*Divine proselytizing is prohibited on school grounds.
*Necromancy on school grounds is expressly prohibited without explicit permission from school administration. Violators shall be subject to expulsion.
The Planarversity has seven colleges, each specializing in areas of expertise. Classes for each college tend to center around certain campuses, but exceptions are common, especially at the undergraduate level. Below are the seven colleges and examples of their curriculum.

#The [[College of Cultural Studies]] (CCS) – Feywild
#*Bardic Arts
#*The Empires of ~Abeir-Toril
#The [[College of Natural Studies]] (CNS) – Waterdeep
#*Animal Husbandry
#The [[College of Cosmology]] (CC) – Waterdeep
#The [[College of Martial Science]] (CMS) – Shadowfell
#*Strategy and Tactics
#The [[Academy of Magic]] (Solice College or Solice) – Sigil
#*Ritual Magics
#*Sorcerer Arts
#*Warlock Arts
#*Wizard Arts
#The [[College of Divine and Primal Studies]] (DPS) – Sigil
#*Cleric Arts
#*Druid Arts
#*Paladin Arts
#*Shaman Arts
#*The Lower Planes
#The [[Graduate School of Planar Studies]] (SPS or Espers) – Sigil
#*Advanced Studies of the Far Realms
#*Denizens of the Feywilde
#*Threats in the Elemental Chaos
#*Topography of the Astral Sea
#*Undead of Shadowfell
Background: #fff
Foreground: #000
PrimaryPale: #FFE392
PrimaryLight: #FF7005
PrimaryMid: #C81700
PrimaryDark: #710000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
''//[[Details on the Forgotten Realms Calendar|http://dnd.steinhour.net/Forgotten_Realms_campaign/Forgotten_Realms/DnD_FR_calendar.html]]//''
//[[Forgotten Realms Calendar Tool|http://www.wizards.com/default.asp?x=dnd/frx/20050525x]]//

''Year of the Ageless One, 1479 DR''
*15 Marpenoth - Highharvesttide quarter of the 85th class of [[Waterdeep Planarversity]] begins. (New Moon) ''//BEGINNING DAY OF CAMPAIGN//''
*20 Nightal - Highharvesttide quarter at Waterdeep Planarversity ends. (Winter Solstice)

''Year of Deep Water Drifting, 1480 DR''
*16 Hammer - Midwinter quarter at Waterdeep Planarversity begins. (New Moon)
[[Plumes & Parchments]][[Recent Updates]]
The Door of Rooms can be found at the [[Planarversity Central Spire]] in [[Sigil]]. It is an ancient magical door crafted by dwarven smiths long dead and forgotten, made of mithril and covered from top to bottom in powerful runes. The door floats in the middle of a large room at the lowest basement of the spire, hanging in mid-air and surrounded by a soft blue glow when not in use. When the door is activated and a portal opens, the color and intensity of the glow changes, depending upon the portal's destination. Portals stay open for a variable amount of time, generally between ten seconds to one minute, depending upon the destination.

The door is known to hold portals connecting to each Planarversity campus. Depending on how one opens the door and steps through the door determines one's destination. Portals always open to special rooms on the other side that contain matching portals back to the Spire. Misuse usually has no permanent repercussions, though terrible accidents have occurred in the past. Students late for their classes have stepped through without the proper number of knocks or forgetting the proper phrases and have disappeared forever.

The door is guarded by a large contingent of [[portal guardians]].

Elerrielle Solice, born 1434 DR, is the human granddaughter of [[Esperifiel Solice]] and daughter of [[Grazielle Solice]]. She serves as the current Preceptor of [[Waterdeep Planarversity]]. She graduated from the Planarversity [[Academy of Magic]] in 1440 DR and the [[Graduate School of Planar Studies]] in 1444 DR. She is the guardian of [[Nar'talas]], adopted daughter of Esperifiel Solice.
<tabs Character>
<tab Background>
!Elisi Freep
//~Half-Elf, 5'6", 120 lbs., 20 yrs., golden blonde hair, amber eyes//
//(~ELZ-y FREEP)//
<tab Stats>
Elisi Freep, level 1
~Half-Elf, Cleric
Build: Devoted Cleric
Pact Initiate: Pact Initiate (fey pact)

Str 13, Con 11, Dex 10, Int 10, Wis 16, Cha 18.

Str 13, Con 9, Dex 10, Int 10, Wis 16, Cha 16.

AC: 16 Fort: 12 Reflex: 11 Will: 17
HP: 23 Surges: 7 Surge Value: 5

Religion +5, Insight +10, Diplomacy +11, Streetwise +10, Bluff +9

Acrobatics -1, Arcana, Dungeoneering +3, Endurance -1, Heal +3, History, Intimidate +4, Nature +3, Perception +3, Stealth -1, Thievery, Athletics

Cleric: Ritual Caster
Level 1: Pact Initiate

Cleric at-will 1: Gaze of Defiance
Cleric at-will 1: Sacred Flame
Cleric daily 1: Beacon of Hope
Cleric encounter 1: Cause Fear
Dilettante: Burning Spray

Ritual Book, Chainmail, Adventurer's Kit, Symbol of Hope +1, Cloak of the Walking Wounded +1, Mace
Gentle Repose, Brew Potion

Lord Elros Silvershield III was the fourth chancellor of the [[Planarversity]], and the first chancellor to have graduated from the Planarversity — he graduated in 1444 DR from the [[College of Martial Science]]. He served as chancellor from 1470 DR to 1479 DR before passing away from natural causes.

Lord Silvershield hailed from the Forgotten Realms, the eldest son from a long line of human nobles from Baldur's Gate. He was a duke, a battle hardened knight of several campaigns, and a charasmatic leader well before he took up the chancellorship. He joined the Planarversity late in life after having passed his hereditary lands to his son. Under his direction, the Planarversity experienced its largest period of growth. 

Erenthielle the Gray was a human archmage, co-founder of the [[Planarversity]], and the second Chancellor of the Planarversity, serving from 1445 DR to 1461 DR, before disappearing mysteriously. All attempts to discover what became of her proved fruitless, and she is presumed to have perished in a magical acciddent.

Little is known of her past, beyond the facts that she was a native Waterdhavian, and she was the first apprentice of [[Esperifiel Solice]].

She was the mother to the eldest daughter of Esperifiel Solice, the half-elf [[Grazielle Solice]].
//(es-pair-ee-FYELL so-LISS)//

Lord Esperifiel Solice, Archmage of [[Evermeet|http://forgottenrealms.wikia.com/wiki/Evermeet]], High Captain of the Elven Navy in [[Realmspeace|http://forgottenrealms.wikia.com/wiki/Realmspace]], Baron of [[Feywild|http://forgottenrealms.wikia.com/wiki/Feywild]], founder of the [[Planarversity]].

His grasp of the [[Weave|http://forgottenrealms.wikia.com/wiki/Weave]] and of elven [[High Magic|http://forgottenrealms.wikia.com/wiki/High_Magic]] was legendary -- he was capable of casting High Magic without the need of a circle of mages. Notably, there was none superior in the Realms when it came to the art of transmutation, the ability to turn one thing into another, or the art of necromancy, the ability to control life and death, surpassing even the legendary Szass Tam, lich king of Thay. He had once fought Lolth herself and lived. It was widely rumored Solice had perfected the ability to be in several places at once, though none could ever confirm as such.

Solice was the last surviving member of a noble Sun Elf house. He became one of the most senior elven archmages of the Realms following the assault on Evermeet lead by [[Kymil Mimesin|http://forgottenrealms.wikia.com/wiki/Kymil_Nimesin]] in [[1371 DR|http://forgottenrealms.wikia.com/wiki/1371_DR]], which decimated the elves and hastened their diaspora from the isle.

Solice spent the years after the defeat of Nimesin traveling across the Realms and the planes as an adventurer. Solice quickly amassed a large fortune which included spelljamming vessels and vast estates across the Sword Coast. He used the fortune to found the Solice Academy of Waterdeep in [[1374 DR|http://forgottenrealms.wikia.com/wiki/1374_DR]] as a private school devoted to the advancement of magic.

The death of Mystra in [[1385 DR|http://forgottenrealms.wikia.com/wiki/1385_DR]] gravely affected the academy. The campus was heavily damaged, and a large number of students and professors died or disappeared forever. Solice survived the disaster relatively unaffected, though the academy was forced to close. In 1396 DR, Solice returned to the Realms with new allies, new resources, and daughter [[Grazielle|Grazielle Solice]] to found the Planarversity and the Realms campus at his estate in Waterdeep.

Solice was the first chancellor of the Planarversity, holding the seat until [[1445 DR|http://forgottenrealms.wikia.com/wiki/1445_DR]]. During his tenure, he built campuses at Waterdeep, Sigil, and Feywild. He retired from the position to pursue personal matters, passing the mantle of chancellorship to the human archmage and former apprentice, [[Erenthielle the Gray]].

Unlike most Sun Elves, Solice was prolific. Though he never married, he was rumored to have sired seven sons and seven daughters, including elves, half-elves, and if it is to be believed, even a dragonborn. A few of of his sons, daughters, and grandchildren have attended the Planarversity. His twins [[Aya Solice]] and [[Maya Solice]] are newly enrolled at Waterdeep Planarversity.

In [[1469 DR|http://forgottenrealms.wikia.com/wiki/1469_DR]], defending a sudden attack on [[Feywild Planarversity]] by the chosen of a long forgotten elder god from the [[Far Realms]], Solice thwarted the assault, then descended into Far Realms to counterattack. All contact was lost, and he has not been heard from since via all means, divine and magical. All attempts to locate him have failed. He has since been presumed deceased.
//(~EH-tsu-on he-meh-~MEE-uh)//


Etuan Himemiya is the fifth and current Chancellor of the [[Planarversity]]. She is a human warlock from distant island nation of [[Kozakura|http://forgottenrealms.wikia.com/wiki/Kozakura]] in the oriental [[Kara-Tur|http://forgottenrealms.wikia.com/wiki/Kara-Tur]], and though she appears to be in her early twenties, her age is a true mystery - she was a close childhood friend of the third chancellor, [[Arcueid Tenjou]], who was both eladrin and dhampyr.

She is rumored to have been romantically attached to the Preceptor of [[Shadowfell Planarversity]], [[Akioh the Autumn Lord]], though does not appear to have such a relationship at present time.

Himemiya is a petite and dark skinned woman of little words, at least in public. She frequents all the campuses and sits in on classes on a regular basis. New students often make the grave error in mistaking her for a fellow student.
The seeds of magical fire blossom trees are known as everburning seeds. The trees are found exclusively in the [[Forest of Knowledge]]. The seeds are the holy symbol of the demigod [[Solace]].

Once a year, fire blossom trees in the Forest of Knowledge flower, becoming covered in hot glowing white five-petaled flowers that steadily shift from white to pink to red over the course of a month. The flowers catch flame and take to the wind. The burning embers that land are everburning seeds. A few seeds that land in the Forest of Knowledge germinate to form new fire blossom trees.

Everburning seeds planted outside the Forest of Knowledge grow fire blossom trees that bloom, but the trees do not give off heat and the flowers do not catch flame and will never produce everburning seeds.

Despite the name, the magical flames of everburning seeds cannot ignite anything they touch. The seeds feel warm to the touch and give off flickering light equivalent to a torch. 
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|

window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
	var tag = this.getAttribute("tag");
	var title = this.getAttribute("tiddler");
	// Thanks Saq, you're a genius :)
	var popup = Popup.stack[Popup.stack.length-1].popup;
	wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
	return false;


!!Notable Faculty
[[Elerrielle Solice]]
[[Li Po]]

Like the [[Shadowfell]], the Feywild is a plane parallel to the world and is the land of faeries and all things fey. It is the motherland of all elvenkind.

Of note, one of the founders of the Planarversity is the [[Matron of Mysteries]], a Gloaming Archfey who presides over the Feywild campus of the Planarversity.

[[Feywild Planarversity]] is home to the Planarversity [[College of Cultural Studies]].

As its name implies, Feywild Planarversity is the campus of the Planarversity in the [[Feywild]], specializing in the study of all things Fey.

The Feywild Planarversity is overseen by the [[Matron of Mysteries]], a benevolent gloaming archfey and co-founder of the Planarversity.

Ten years prior, the Feywild Planarversity campus survived a devastating attack by the avatar of an elder god from the Far Realms. Planarversity founder Esperifiel Solice fended off the god in single combat, but was lost after the battle. Most of the damage to the campus from the battle has been repaired, and a memorial has been recently erected to remember the tragic event and the loss of the school's founder.
The Fire Blossom Festival takes place annually in the [[Forest of Knowledge]] at [[Sigil Planarversity]], beginning when the fire blossom trees bloom and lasting approximately a month, until the last [[everburning seed|Everburning Seeds]] takes to the wind.

Over the course of the month, priests of [[Solace]] and the greater Planarversity populace host large parties in the Forest of Knowledge. Common activities include grand feasts, tournaments of skill and knowledge, graduation parties, even marriage ceremonies. Many Planarversity students have discovered their greatest loves while reminiscing the year's past events at a drunken blossom watching party. </p><p>People from all Planarversity campuses and their guests come to the festival, and an unofficial tradition of rivalry between the campuses has been established, each trying to throw the grandest party. Recent memorable parties have even drawn the attention of dragons, angels, and a few gods in disguise.
|Created by|SaqImtiaz|
Resize tiddler text on the fly. The text size is remembered between sessions by use of a cookie.
You can customize the maximum and minimum allowed sizes.
(only affects tiddler content text, not any other text)

Also, you can load a TW file with a font-size specified in the url.
Eg: http://tw.lewcid.org/#font:110

Try using the font-size buttons in the sidebar, or in the MainMenu above.

Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.
Then put {{{<<fontSize "font-size:">>}}} in your SideBarOptions tiddler, or anywhere else that you might like.

{{{<<fontSize>>}}} results in <<fontSize>>
{{{<<fontSize font-size: >>}}} results in <<fontSize font-size:>>

The buttons and prefix text are wrapped in a span with class fontResizer, for easy css styling.
To change the default font-size, and the maximum and minimum font-size allowed, edit the config.fontSize.settings section of the code below.

This plugin assumes that the initial font-size is 100% and then increases or decreases the size by 10%. This stepsize of 10% can also be customized.

*27-07-06, version 1.0 : prevented double clicks from triggering editing of containing tiddler.
*25-07-06,  version 0.9



//configuration settings
config.fontSize.settings =
            defaultSize : 100,  // all sizes in %
            maxSize : 200,
            minSize : 40,
            stepSize : 10

//startup code
var fontSettings = config.fontSize.settings;

if (!config.options.txtFontSize)
            {config.options.txtFontSize = fontSettings.defaultSize;
setStylesheet(".tiddler .viewer {font-size:"+config.options.txtFontSize+"%;}\n","fontResizerStyles");
setStylesheet("#contentWrapper .fontResizer .button {display:inline;font-size:105%; font-weight:bold; margin:0 1px; padding: 0 3px; text-align:center !important;}\n .fontResizer {margin:0 0.5em;}","fontResizerButtonStyles");

config.macros.fontSize.handler = function (place,macroName,params,wikifier,paramString,tiddler)

               var sp = createTiddlyElement(place,"span",null,"fontResizer");
               if (params[0])
               createTiddlyButton(sp,"+","increase font-size",this.incFont);
               createTiddlyButton(sp,"=","reset font-size",this.resetFont);
               createTiddlyButton(sp,"–","decrease font-size",this.decFont);

config.macros.fontSize.onDblClick = function (e)
             if (!e) var e = window.event;
             e.cancelBubble = true;
             if (e.stopPropagation) e.stopPropagation();
             return false;

config.macros.fontSize.setFont = function ()
               setStylesheet(".tiddler .viewer {font-size:"+config.options.txtFontSize+"%;}\n","fontResizerStyles");

               if (config.options.txtFontSize < fontSettings.maxSize)
                  config.options.txtFontSize = (config.options.txtFontSize*1)+fontSettings.stepSize;


               if (config.options.txtFontSize > fontSettings.minSize)
                  config.options.txtFontSize = (config.options.txtFontSize*1) - fontSettings.stepSize;



config.paramifiers.font =
               onstart: function(v)
                   config.options.txtFontSize = v;

The Forest of Knowledge surrounds the Central Campus of [[Sigil Planarversity]]. It is home to the largest Planarversity library at the eastern end of the forest, and the largest shrine to [[Solace]], Demigod of Growth and Learning, at the western. The campus sits at the northern end of the Forest, and the [[River of Remembrance]] bifurcates the forest, beginning from natural hot springs surrounding the campus and flowing southward through the forest and into the [[Astral Sea]].

The forest surrounds the Central Campus and is populated with fire blossom trees. They grow from [[everburning seeds|Everburning Seeds]], the holy symbol of Solace. The trees glow, giving off light from their leaves, following a cycle of darkness and light, corresponding to a regular 24-hour day. At their brightest, they give off the equivalent light of a sunny day. At their dimmest, they give off the equivalent of a full moon. The trunks and branches trees also give off heat, enough to keep the campus warm year-round: a cool summer day at their brightest, and a warm summer night at their dimmest. Fluctuations in light and heat among the forest are the cause of a constant warm breeze across the campus. The forest does not experience seasonal weather. //Temperatures range from 60F-80F each day, year round.//

Spread across the forest is the vast outdoor library of the Planarversity. The books come from all across the planes, though the two largest sources are the Realms and the school itself. In the field of planar studies, the collection is second to none.

The fire blossom trees keep the air dry for the books, provide ample lighting, and despite their fiery nature, never burn anything except themselves. The planar nature of the campus also precludes any chance of precipitation or fog.

When fire blossom trees first sprout from the soil, they glow like faint fireflies. As they mature, the light from the trees brightens and takes on a reddish hue. Once a year, the tall trees blossom, covered in hot glowing white five-petaled flowers that steadily shift from white to pink to red over the course of a month.

The heat from the petals increases the surrounding campus to an almost summer-like heat. During the month-long bloom, classes across all Planarversity campuses are closed, overtaken by the [[Fire Blossom Festival]], open to all Planarversity students across all campuses.

In the final days of the festival, the blossoms catch fire, burning for days. The largest, most blossom-laden trees completely catch aflame. At the end of the festival, the trees are dotted with all that remains of the blossoms: tiny everburning seeds. The seeds take to the wind, and a few take root each year to grow new fire blossom trees. The end of the academic year is traditionally marked as the last seed has taken to the wind, and the new academic year begins when the first new fire blossom saplings appear, a few months later.
*[[Esperifiel Solice]], founder of the Solice Academy and the Planarversity.
*[[Erenthielle the Gray]], second Chancellor of the Planarversity.
*[[Matron of Mysteries]], archfey Preceptor of the [[Feywild Planarversity]].
*[[Solace]], Demigod of Growth and Learning.
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>

See also [[WelcomeToTiddlyspot]].

//(~grat-see-EL ~so-LISS)//

[img[Grazielle Solice|http://farm3.static.flickr.com/2453/3640483431_0d32d40c90_o.jpg]]

Grazielle Solice, born 1392 DR, was the half-elven daughter of [[Esperifiel Solice]] and [[Erenthielle the Gray]]. Her human daughter is [[Elerrielle Solice]], the current Preceptor of [[Waterdeep Planarversity]].
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}

window.hideWhenLastTest = false;

window.removeElementWhen = function(test,place) {
	window.hideWhenLastTest = test;
	if (test) {


	hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( eval(paramString), place);

	showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !eval(paramString), place);

	hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);

	showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);

	hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAny(params), place);

	showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAny(params), place);

	hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);

	showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);

	hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);

	showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);

	hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title == params[0], place);

	showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title != params[0], place);

	'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !window.hideWhenLastTest, place);



*''Absentees'' - If a PC is a regular member of the party and is in a continuing series of encounters, such as in the middle of a dungeon, and the player must leave the game sesson early or cannot make it to the next gaming session, for the sake of continuity, the PC is played as an NPC by the GM until the player can return, receiving no XP or treasure while an NPC.
*''Action Points'' - An action point may be spent by a Player Character (PC) as a free action to reroll one roll he just made, instead of taking an extra action. The second roll must be used, even if it is lower than the first roll. A PC may only spend one action point per encounter. A PC may also only gain one action point per encounter.
*''Cooperation''- Using Cooperation to aid another PC on a skill check may only be used by a PC trained in the skill.
*''Crime and Punishment'' - A PC being caught and convicted of a serious crime such as murder, resulting in long-term imprisonment or execution, will be treated as the equivalent of PC death and the player will be forced to retire the PC.
*''Death'' - In the event of a PC's death, the player may play another PC enrolled in the same year of education at the Planarversity
*''Hit Points'' - Hit Points gained each level are max hit die every level, no rolling. //e.g. Barbarians gain 12 HP. They don't roll a d12.//
*''Friendly Fire'' - All damage done by one PC to another PC is non-lethal concussion damage. Receiving additional damage from non-PC sources can still result in death.
*''Pop Quizes'' - Short quizes will be given to players each game session, covering in-game topics and events. Doing well on the quizes will be rewarded with bonus action points, bonuses to rolls, and other significant rewards for their PC's
*''Taking Ten'' - Any time a PC were to make an out-of-combat skill check or an at-will or basic attack roll, he may count the roll as an automatic 10 instead of actually making the roll.
Student housing is included into the Planarversity enrollment fees, and all undergraduates are required to stay at student housing while not in the field or on studies abroad. Graduate students are not required to stay at student housing.

Undergraduate housing exists in various forms, depending upon the campus:
*Residence hall open dormitories
*Double occupancy rooms
*4-person double room suites

Housing is coed by floor or by building. All rooms are same-sex.

//At Waterdeep Planarversity, undergraduate housing is residence hall occupancy, with men and women in separate buildings. Curfew for the halls is midnight.//
|Author|Eric Shulman|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|Overrides|'image' formatter|
|Description|adds support for resizing images|
This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
The extended image syntax is:
where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between """{{""" and """}}""". Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
[<img(21% ,+)[images/meow.gif]]
[<img(13%+, )[images/meow.gif]]
[<img( 8%+, )[images/meow.gif]]
[<img( 5% , )[images/meow.gif]]
[<img( 3% , )[images/meow.gif]]
[<img( 2% , )[images/meow.gif]]
[img(  1%+,+)[images/meow.gif]]
2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
2009.02.22 [1.2.0] added stretchable images
2008.01.19 [1.1.0] added evaluated width/height values
2008.01.18 [1.0.1] regexp for "(width,height)" now passes all CSS values to browser for validation
2008.01.17 [1.0.0] initial release
version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 1, date: new Date(2009,2,24)};
var f=config.formatters[config.formatters.findByField("name","image")];
f.handler=function(w) {
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var floatLeft=lookaheadMatch[1];
		var floatRight=lookaheadMatch[2];
		var width=lookaheadMatch[3];
		var height=lookaheadMatch[4];
		var tooltip=lookaheadMatch[5];
		var src=lookaheadMatch[6];
		var link=lookaheadMatch[7];

		// Simple bracketted link
		var e = w.output;
		if(link) { // LINKED IMAGE
			if (config.formatterHelpers.isExternalLink(link)) {
				if (config.macros.attach && config.macros.attach.isAttachment(link)) {
					// see [[AttachFilePluginFormatters]]
					e = createExternalLink(w.output,link);
					e.title = config.macros.attach.linkTooltip + link;
				} else
					e = createExternalLink(w.output,link);
			} else 
				e = createTiddlyLink(w.output,link,false,null,w.isStatic);

		var img = createTiddlyElement(e,"img");
		if(floatLeft) img.align="left"; else if(floatRight) img.align="right";
		if(width||height) {
			var x=width.trim(); var y=height.trim();
			var stretchW=(x.substr(x.length-1,1)=='+'); if (stretchW) x=x.substr(0,x.length-1);
			var stretchH=(y.substr(y.length-1,1)=='+'); if (stretchH) y=y.substr(0,y.length-1);
			if (x.substr(0,2)=="{{")
				{ try{x=eval(x.substr(2,x.length-4))} catch(e){displayMessage(e.description||e.toString())} }
			if (y.substr(0,2)=="{{")
				{ try{y=eval(y.substr(2,y.length-4))} catch(e){displayMessage(e.description||e.toString())} }
			img.style.width=x.trim(); img.style.height=y.trim();
		if(tooltip) img.title = tooltip;

		if (config.macros.attach && config.macros.attach.isAttachment(src))
			src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
		else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
			if (config.browser.isIE || config.browser.isSafari) {
					return false;
			} else
		w.nextMatch = this.lookaheadRegExp.lastIndex;

config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
	e.title=((stretchW||stretchH)?'DRAG=stretch/shrink, ':'')
		+'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size';
	e.statusMsg='width=%0, height=%1';
	e.onmousedown=function(ev) { var ev=ev||window.event;
		return false;
	e.onmousemove=function(ev) { var ev=ev||window.event;
		if (this.sizing) {
			var s=this.style;
			var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
			var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
			var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
			var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
			if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
			if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
			clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
		return false;
	e.onmouseup=function(ev) { var ev=ev||window.event;
		if (ev.shiftKey) { this.style.width=this.style.height=''; }
		if (ev.ctrlKey)  { this.style.width=this.originalW; this.style.height=this.originalH; }
		return false;
	e.onmouseout=function(ev) { var ev=ev||window.event;
		return false;
config.formatters.unshift( {
	name: "inlinetabs",
	match: "\\<tabs",
        lookaheadRegExp: /(?:<tabs (.*)>\n)((?:.|\n)*?)(?:\n<\/tabs>)/mg,
	handler: function(w)
	    this.lookaheadRegExp.lastIndex = w.matchStart;
	    var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
	    if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
             var cookie = lookaheadMatch[1];
  	         var wrapper = createTiddlyElement(null,"div",null,cookie);
	         var tabset = createTiddlyElement(wrapper,"div",null,"tabset");
             var validTab = false;
             var firstTab = '';
             var tabregexp = /(?:<tab (.*)>)(?:(?:\n)?)((?:.|\n)*?)(?:<\/tab>)/mg;
             while((m = tabregexp.exec(lookaheadMatch[2])) != null)
		         if (firstTab == '') firstTab = m[1];
		         var tab = createTiddlyButton(tabset,m[1],m[1],story.onClickInlineTab,"tab tabUnselected");
		         tab.title = m[1];
		         if(config.options[cookie] == m[1])
                     validTab = true;
                 config.options[cookie] = firstTab;
             w.nextMatch = this.lookaheadRegExp.lastIndex;

Story.prototype.switchInlineTab = function(tabset,tab)
    var cookie = tabset.getAttribute("cookie");
    var theTab = null
    var nodes = tabset.childNodes;
    for(var t=0; t<nodes.length; t++)
    if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
        theTab = nodes[t];
        theTab.className = "tab tabSelected";
        nodes[t].className = "tab tabUnselected"
		if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
		var tabContent = createTiddlyElement(null,"div",null,"tabContents");
			config.options[cookie] = tab;
Story.prototype.onClickInlineTab = function(e)
    return false;
<tabs Character>
<tab Background>
//~Shadar-Kai, 5'10", 140 lbs., 20 yrs., alabaster white skin, shaved skull with skull tattoo, jade green eyes, green lipstick/eye shadow, extensive body piercings//

Daughter of shadar-kai adventurers, grew up in Sigil.
Wild flirt, quick temper, loud, assertive, no fear, extremely protective of friends and those in her charge, convincing and charismatic.
Beautiful, but scary.
Obsessed with anything new.

<tab Stats>
Ino, level 1
Shadar-kai Warlord
Build: Bravura Warlord
Commanding Presence: Bravura Presence

Str 16, Con 13, Dex 12, Int 15, Wis 8, Cha 15.

Str 16, Con 13, Dex 10, Int 13, Wis 8, Cha 15.

AC: 18 Fort: 15 Reflex: 12 Will: 13
HP: 25 Surges: 8 Surge Value: 6

Athletics +8, Heal +4, Endurance +6, Intimidate +7

Acrobatics +3, Arcana +2, Bluff +2, Diplomacy +2, Dungeoneering -1, History +2, Insight -1, Nature -1, Perception -1, Religion +2, Stealth +3, Streetwise +2, Thievery +1

Level 1: Armor Proficiency (Scale)

Warlord at-will 1: Commander's Strike
Warlord at-will 1: Rousing Assault
Warlord daily 1: Lead the Attack
Warlord encounter 1: Luring Focus

Verve Scale Armor +1, Vanguard Greatsword +1
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
* Change the timeFormat and dateFormat below to suit your preference.
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.

config.InstantTimestamp = {

	// adjust to suit
	timeFormat: 'DD/0MM/YY 0hh:0mm',
	dateFormat: 'DD/0MM/YY',

	translations: [
		[/^!ts?$/img,  "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
		[/^!ds?$/img,  "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],

		// thanks Adapted Cat

	excludeTags: [

	excludeTiddlers: [
		// more?


TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {

	tags = tags ? tags : []; // just in case tags is null
	tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
	var conf = config.InstantTimestamp;

	if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {

		var now = new Date();
		var trans = conf.translations;
		for (var i=0;i<trans.length;i++) {
			newBody = newBody.replace(trans[i][0], eval(trans[i][1]));

	// TODO: use apply() instead of naming all args?
	return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);

// you can override these in StyleSheet 
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");


<tabs Character>
<tab Background>
!Jarl Beornson
//~Half-Elf, 5'9", 185 lbs., 19 yrs. (appearance), pale skin, shoulder-length blonde hair, blue-gray eyes//
//(YARL ~BAY-orn-sun)//

"Only fools and women stand between a man and his son," his father would say, before beating his mother, then beating him. He remembers the day he killed his first reindeer. His aim was off, and he chased it for two hours across the tundra before it bled to death. He brought it home, and his father beat him.

He killed a boy in his sixteenth year. There were five, two with knives. The tallest stood before him, four hands taller, slower. He broke the arm of the one behind him, kicked the knife away, and shoved him into the boy with the other knife. He reached in his pockets and smashed his head into the face of the tallest boy, who screamed from a broken nose. He grabbed a rock in each hand from his pockets and slammed them again and again against the boy's head like clams against the rocks, crunching bone beneath his fists, until the kicks to his head brought in blackness.

The first time he truly tried to kill his father, his father broke his left shoulder. It healed in two months, and then he tried again. His father broke his left shoulder again. He spit on him. "The day my son can beat me is the day I deserve to die. You are weak. You are no son of mine."

By the next summer he finally became a man. He had grown later than the others. He was smaller than the rest, but quick and sturdy. It only takes an axe to fell a pine. A bear attacks from a crouch.

He did not wait for his father to step off the boat before he threw the harpoon, meant for whales. Men jumped out of their seats to avoid the harpoon. His father dove into the water. He ran to meet his father at the waves. Surprised, the men watched on from the boat bobbing in the shallows.

"I should have killed you when you were born!" his father yelled. And then he felt the burn of the thrown dagger buried in his left shoulder. Out of surprise more than pain, he lowered his axe for a moment, long enough for his father to charge toward him from the waves, greataxe held high in the harsh winter sky.

He dropped his axe and picked up the nearest spear he had buried in the sand and knelt down, burying the butt of the spear deep into the sand and gripping firmly. He felt the wild swipe of his father's axe bury into his shoulder, and then was knocked down under the weight of his father.

He shoved his father off. The spear breached clear through his father's bear hide vest, piercing his spine and coming out through his back. His father's eyes and mouth were wide open, staring at him with rage. He pulled the dagger from his shoulder, bent down, and slit his father's throat like a drowning fish.

He and his mother left. She took him to her people. There was no place for him there. He had killed his father, but he would always be his father's son. His father's people were the sworn enemy. Plans were made for him. His mother sent him off, far away.

"You are a man now, Jarl. Leave the tragedy of your past and make your own future, my son." She had returned home. He had left his. She had sent him to this school. He loved his mother, but his mother never understood. You can change a man as soon as you can tame a wolf.
<tab Stats>
Jarl Beornson, level 1
~Half-Elf, Barbarian
Build: Rageblood Barbarian
Feral Might: Rageblood Vigor
Birth – Among Another Race: Among Another Race (Human)

Str 16, Con 18, Dex 13, Int 11, Wis 10, Cha 10.

Str 16, Con 16, Dex 13, Int 11, Wis 10, Cha 8.

AC: 15 Fort: 17 Reflex: 13 Will: 11
HP: 33 Surges: 12 Surge Value: 8

Nature +5, Athletics +7, Endurance +8

Acrobatics, Arcana, Bluff, Diplomacy +2, Dungeoneering, Heal, History, Insight +2, Intimidate, Perception, Religion, Stealth, Streetwise, Thievery

Level 1: Stubborn Survivor

Barbarian at-will 1: Howling Strike
Barbarian at-will 1: Recuperating Strike
Half-Elf: Brash Strike
Barbarian encounter 1: Avalanche Strike
Barbarian daily 1: Bloodhunt Rage

Battlecrazed Greataxe +1, Hide Armor, Adventurer's Kit, Amulet of Physical Resolve +1

|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1 ($Rev: 2320 $)|
|Date:|$Date: 2007-06-18 22:37:46 +1000 (Mon, 18 Jun 2007) $|
|Author:|Simon Baird|
You end up with just backup one per year, per month, per weekday, per hour, minute, and second.  So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
Works in IE and Firefox only.  Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.

var MINS  = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS  = 24 * HOURS;

if (!config.lessBackups) {
	config.lessBackups = {
		// comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
		modes: [
			["YYYY",  365*DAYS], // one per year for ever
			["MMM",   31*DAYS],  // one per month
			["ddd",   7*DAYS],   // one per weekday
			//["d0DD",  1*DAYS],   // one per day of month
			["h0hh",  24*HOURS], // one per hour
			["m0mm",  1*HOURS],  // one per minute
			["s0ss",  1*MINS],   // one per second
			["latest",0]         // always keep last version. (leave this).

window.getSpecialBackupPath = function(backupPath) {

	var now = new Date();

	var modes = config.lessBackups.modes;

	for (var i=0;i<modes.length;i++) {

		// the filename we will try
		var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,

		// open the file
		try {
			if (config.browser.isIE) {
				var fsobject = new ActiveXObject("Scripting.FileSystemObject")
				var fileExists  = fsobject.FileExists(specialBackupPath);
				if (fileExists) {
					var fileObject = fsobject.GetFile(specialBackupPath);
					var modDate = new Date(fileObject.DateLastModified).valueOf();
			else {
				var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
				var fileExists = file.exists();
				if (fileExists) {
					var modDate = file.lastModifiedTime;
		catch(e) {
			// give up
			return backupPath;

		// expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
		// June file on disk that's more than an month old then it must be stale so overwrite
		// note that "latest" should be always written because the expiration period is zero (see above)
		var expiry = new Date(modDate + modes[i][1]);
		if (!fileExists || now > expiry)
			return specialBackupPath;

// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
	return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));


<tabs Character>
<tab Background>
//Human, 16 yrs., 5', 90 lbs., tan skin, short red hair, oriental brown eyes//
//(LEE PING)//

Any conversation at the Planarversity always begins with the offhanded remark that Ping seems nothing like her dear father, [[Li Po]], the Waterdeep Planarversity professor. Yes, he's my father. I'm adopted, she says.

As her father tells it, he was out drinking one night, mourning the tragic death of his fiancée, who had died in a midsummer fire. Twin harvest moons shined full and bright, one high in the bright sky and one below upon the river shore. The din of cicadas and the honey sweet smell of hydrangeas dripped along in the warm night air, and Li Po drank, drank and wept, till he could not tell whether his tears had soaked the land or the sky, in sympathy, began to rain.

The moon shimmered and wept for him, he saw. Don't cry, he said to the watery moon. I weep enough for all of us. He reached out to comfort the moon, and fell into the cold river. He would have resigned himself to drowning, he'd say, if it weren't for the crying. He rose to the surface. Hush hush, moon. Tears and wine do not belong together, for wine is sweet and tears are bitter. But it was not the moon that was crying. It was but the tiniest flower upon the water, crying in loneliness. Moved by the compassionate spirit of Kwan Ying, Li Po pressed the beautiful flower to his chest, and the blessed flower transformed into a beautiful baby girl with red hair like fire and eyes as bright as moons. And that girl grew up to be his beautiful daughter, Ping.

Usually at that point in the story, Ping walks away, red faced and teary eyed. Her father talks too much when he's drunk.

Ping grew up following her drunken father, who called the road more of a home than any place with four walls. Five years in the same place was a miracle. Maybe her father missed his youth in the old country, watching her years run away like old tattered dresses. Not that she grew much. She was still a kitten compared to the old snoring bear. But the land was sweet, and the spirits kind to her and her father. She helped him tend the land, tilling the soil and raising the plants. She didn't have his divine gift in the kitchen, and left those daily miracles up to him.

Even snow must one day melt and taste the salty sea, her father had been saying. He didn't mean the literal sea, which was only a few hours jaunt to the west. He meant schooling. Not school among the spirits of the land, or home with her father. School among other children her age. And then the road, like her father, like her youth. She felt the fire inside her still, simmering, bubbling at her toes. No need to rush. A journey begins with the first step.
<tab Stats>
Li Ping, level 1
Human Shaman
Build: Bear (Panda) Shaman
Companion Spirit: Protector Spirit

Str 8, Con 16, Dex 10, Int 13, Wis 18, Cha 11.

Str 8, Con 16, Dex 10, Int 13, Wis 16, Cha 11.

AC: 12 Fort: 15 Reflex: 12 Will: 16
HP: 28 Surges: 10 Surge Value: 7

Endurance +8, Nature +9, Insight +9, Religion +8, Heal +9

Acrobatics, Arcana +1, Bluff, Diplomacy, Dungeoneering +4, History +1, Intimidate, Perception +4, Stealth, Streetwise, Thievery, Athletics -1

Human: Melee Training (Wisdom)
Level 1: Human Perseverance

Shaman at-will 1: Wrath of Winter
Bonus ~At-Will Power: Stalker's Strike
Shaman daily 1: Spirit of the Healing Flood
Shaman encounter 1: Thunder Bear's Warding

Adventurer's Kit, Totem, Lifedrinker Scythe +1, Bloodthread Cloth Armor (Basic Clothing) +1
//(LEE POH)//

Li Po is a priestly monk of [[Tafan]], the Shou Lung God of Cookery. The old Shou also is an associate professor at [[Waterdeep Planarversity]] and has taught several courses for the past five winters, including //The Cuisine of ~Kara-Tur//, //An Introduction to Shou Lung//, //Essential Horticulture//, and //Basic Brewing//. His classes are very nonstandard, having obtained special permission to hold all his classes at his farm, roughly an hour's walk beyond the South Gate of Waterdeep. His adopted daughter [[Ping|Li Ping]] is a new undergraduate this year at Waterdeep Planarversity.

|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Date:''|mar 17, 2007|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 return bidix.core.loadRemoteFile(url,callback,params);

[img[Lord of the Pit|http://farm4.static.flickr.com/3607/3633364947_5240f9eee5.jpg][http://www.flickr.com/photos/perci/3633364947/]]
*symmetric inside map with four gates
*teams split into two random groups - one team exits N and S, one team exits W and E
*steep descent (difficult terrain) into center 2x2 pit
*2x2 magical zone enshrouded in shadows. Anyone in the zone at the beginning of his turn benefits from concealment, +1 to all saves, +1 to all attacks, and regeneration 5.
MPTW is a distribution or edition of [[TiddlyWiki|http://tiddlywiki.com]] that includes a standard ~TiddlyWiki core packaged with some plugins designed to improve usability and provide a better way to organise your information. For more information see http://mptw.tiddlyspot.com/.
[[Plumes & Parchments]] [[Beginning the Campaign]] [[The Planarversity|Planarversity]]					<<fontSize>><<toggleSideBar>>
New undergraduate students must first choose their [[college]]. Note that the Graduate School of Planar Studies is not open to undergratuate enrollment.

The majority of a student's studies will fall within the coursework offered at their college. However, interdisciplinary studies outside of their college are commonly available to undergraduates.

Students will be assigned to a primary campus for [[orientation]] and campus [[housing]] for the first year. First quarter [[tuition]] will also be collected, and any financial aid issues for the year will be resolved. 

''//For the purposes of the campaign, all students will be assigned to [[Waterdeep Planarversity]].//''

The Matron of Mysteries, sometimes affectionately called "Mom" by the undergraduates of the [[Feywild]] campus, is a co-founder of the [[Planarversity]] and the Preceptor of [[Feywild Planarversity]].

Mom is a Gloaming Archfey who appears as an attractive middle-aged eladrin noblewoman. She takes great pride in her charges, but woe to the undergraduate who catches the attention of Mom. Interesting things have been known to happen… Her wrath has been thwarted a few times in the past with bribes of chocolate.
<tabs Character>
<tab Background>
!Maya Solice
//5'6", 110 lbs., golden skin, amber eyes, long golden locks//
//(~MY-uh so-LISS)//
[img[Aya and Maya Solice|http://farm4.static.flickr.com/3662/3640468345_a3db6837ba_o.jpg]]

Aya and Maya Solice are identical twins, the only offspring of Esperifiel Solice and Lady Amberliss, a duchess of Feywild. 
Socialites known for being almost out of control and self-centered - and the most attractive girls in the entire school.
They don't act like snobs. They //know// they're better than everyone else. They don't need to flaunt it.
They keep no confidence other than their own. They are each other's best friends.
Aya acts as the "older" twin and does most of their talking.
They are inseparable, except when a boy is involved.
They are currently crushing on Tarsith of Solace, who is currently only a friend.
They are very competitive and do not accept losing as an option, and are willing to go to great lengths to win.
They are highly defensive of their dead father and will never forget or forgive a slight against him.
<tab Stats>
Maya Solice, level 1
Eladrin Rogue
Build: Trickster Rogue
Rogue Tactics: Artful Dodger

Str 11, Con 10, Dex 20, Int 12, Wis 8, Cha 14.

Str 11, Con 10, Dex 18, Int 10, Wis 8, Cha 14.

AC: 18 Fort: 11 Reflex: 18 Will: 14
HP: 22 Surges: 6 Surge Value: 5

Athletics +7, Stealth +10, Thievery +10, Insight +4, Perception +4, Bluff +7, Acrobatics +10

Arcana +3, Diplomacy +2, Dungeoneering -1, Endurance, Heal -1, History +3, Intimidate +2, Nature -1, Religion +1, Streetwise +2

Level 1: Backstabber

Rogue at-will 1: Sly Flourish
Rogue at-will 1: Riposte Strike
Rogue daily 1: Blinding Barrage
Rogue encounter 1: Dazing Strike

Dagger, Lifedrinker Dagger +1, Leather Armor of Exploits +1, Gloaming Shroud +1
<tabs Character>
<tab Background>
//Tiefling, 5'2", 90 lbs., 13 yrs. old, black skin, long reptilian tail, black A-line bob haircut, black snake-like eyes//

Each year Waterdeep Planarversity holds a tournament for prospective students from all over the Realms. Hundreds come in hopes of winning a handful of scholarships to the prestigious school. The tournament is unlike the Planarversity's standard admission process. This double-elimination tournament pits applicants against each other in a test of martial and arcane prowess.

Usually, contestants don't die. Mercy left her opponents with life-threatening burns that required immediate attention from tournament officials. She won her individual and team brackets, scoring one of the coveted full academic scholarships. She came to the tournament knowing she would. She had always known she was destined for something greater.

Mercy resembles and is named after her mother, a tiefling sorceress who died in childbirth. She has long contemplated her name, which she often thinks is life's first cruel joke on her. Growing up in the crowded slums of Waterdeep, she was never shown any mercy from the gangs of children who bullied and beat her for her cursed tiefling blood. It was during one of those cruel childhood lessons that Mercy's sorcerous powers blossomed for the first time. The only mercy she showed her enemies was a quick death.

Mercy's control over her powers have grown steadily in the past few years, but not quick enough to her liking. She sees the Planarversity as the perfect training ground to improve her abilities above and beyond what she could possibly accomplish on her own. Only in her early teens, Mercy is much younger than the average freshman. What she lacks in experience, she has made up for in determination.

Mercy counts [[Tarsith of Solace]] as her only friend at the school, whom she looks up to like an older brother. Like him, she stands out for her looks, but Tarsith does not judge her by her blood. When he is around, he quells her steadily simmering anger.
<tab Stats>
Mercy, level 1
Tiefling Sorcerer
Build: Storm Sorcerer
Spell Source: Storm Magic

Str 10, Con 10, Dex 17, Int 13, Wis 8, Cha 18.

Str 10, Con 10, Dex 17, Int 11, Wis 8, Cha 16.

AC: 13 Fort: 10 Reflex: 13 Will: 16
HP: 22 Surges: 6 Surge Value: 5

Arcana +6, Streetwise +9, Intimidate +9, Bluff +11

Acrobatics +3, Diplomacy +4, Dungeoneering -1, Endurance, Heal -1, History +1, Insight -1, Nature -1, Perception -1, Religion +1, Stealth +5, Thievery +3, Athletics

Level 1: Hellfire Blood

Sorcerer at-will 1: Storm Walk
Sorcerer at-will 1: Lightning Strike
Sorcerer encounter 1: Whirlwind
Sorcerer daily 1: Howling Tempest

Spellbook, Cloth Armor (Basic Clothing), Adventurer's Kit, Flaming Quarterstaff +1, Hedge Wizard's Gloves (heroic tier)
<tabs Character>
<tab Background>
!Mika Sevens
//Human, 5'8", 105 lbs., 21 yrs., tan skin, very long black hair, brown oriental eyes//
[img[Mika Sevens|http://farm3.static.flickr.com/2479/3641312230_302a503a61_o.jpg]]
<tab Stats>
Mika Sevens, level 1
Human Wizard
Build: Control Wizard
Arcane Implement Mastery: Orb of Imposition

Str 8, Con 12, Dex 10, Int 18, Wis 16, Cha 12.

Str 8, Con 12, Dex 10, Int 16, Wis 16, Cha 12.

AC: 15 Fort: 12 Reflex: 15 Will: 16
HP: 28 Surges: 7 Surge Value: 7

Nature +8, Arcana +9, Dungeoneering +8, History +9, Insight +8

Acrobatics, Bluff +1, Diplomacy +1, Endurance +1, Heal +3, Intimidate +1, Perception +3, Religion +4, Stealth, Streetwise +1, Thievery, Athletics -1

Wizard: Ritual Caster
Human: Arcane Familiar
Level 1: Expanded Spellbook

Wizard at-will 1: Thunderwave
Wizard at-will 1: Storm Pillar
Wizard encounter 1: Orbmaster's Incendiary Detonation
Wizard daily 1: Sleep
Wizard daily 1 Spellbook: Horrid Whispers
Wizard daily 1 Spellbook: Flaming Sphere
Human: Scorching Burst

Spellbook, Adventurer's Kit, Orb of Unlucky Exchanges +1, Robe of Contingency Cloth Armor (Basic Clothing) +1
Name: MptwBlack
Background: #000
Foreground: #fff
PrimaryPale: #333
PrimaryLight: #555
PrimaryMid: #888
PrimaryDark: #aaa
SecondaryPale: #111
SecondaryLight: #222
SecondaryMid: #555
SecondaryDark: #888
TertiaryPale: #222
TertiaryLight: #666
TertiaryMid: #888
TertiaryDark: #aaa
Error: #300

This is in progress. Help appreciated.

Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Description:|Miscellaneous tweaks used by MPTW|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
!!Note: instead of editing this you should put overrides in MptwUserConfigPlugin
var originalReadOnly = readOnly;
var originalShowBackstage = showBackstage;

config.options.chkHttpReadOnly = false; 		// means web visitors can experiment with your site by clicking edit
readOnly = false;								// needed because the above doesn't work any more post 2.1 (??)
showBackstage = true;							// show backstage for same reason

config.options.chkInsertTabs = true;    		// tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = "";			// don't need message when a tiddler doesn't exist
config.views.editor.defaultText = "";			// don't need message when creating a new tiddler 

config.options.chkSaveBackups = true;			// do save backups
config.options.txtBackupFolder = 'twbackup';	// put backups in a backups folder

config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file

config.mptwVersion = "2.5.3";


if (config.options.txtTheme == '')
	config.options.txtTheme = 'MptwTheme';

// add to default GettingStarted
config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]].";

// add select theme and palette controls in default OptionsPanel
config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see AdvancedOptions)/, "{{select{<<selectTheme>>\n<<selectPalette>>}}}$1");

// these are used by ViewTemplate
config.mptwDateFormat = 'DD/MM/YY';
config.mptwJournalFormat = 'Journal DD/MM/YY';

Name: MptwGreen
Background: #fff
Foreground: #000
PrimaryPale: #9b9
PrimaryLight: #385
PrimaryMid: #031
PrimaryDark: #020
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

Name: MptwRed
Background: #fff
Foreground: #000
PrimaryPale: #eaa
PrimaryLight: #c55
PrimaryMid: #711
PrimaryDark: #500
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Description|Mptw Theme with some rounded corners (Firefox only)|



{ -moz-border-radius: 1em; }

.tab {
	-moz-border-radius-topleft: 0.5em;
	-moz-border-radius-topright: 0.5em;
#topMenu {
	-moz-border-radius-bottomleft: 2em;
	-moz-border-radius-bottomright: 2em;


Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles|
Name: MptwTeal
Background: #fff
Foreground: #000
PrimaryPale: #B5D1DF
PrimaryLight: #618FA9
PrimaryMid: #1a3844
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #f8f8f8
TertiaryLight: #bbb
TertiaryMid: #999
TertiaryDark: #888
Error: #f88
|Description|Mptw Theme including custom PageLayout|

http://mptw.tiddlyspot.com/#MptwTheme ($Rev: 1829 $)

<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
	<div class='headerShadow'>
		<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
		<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
	<div class='headerForeground'>
		<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
		<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<!-- horizontal MainMenu -->
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<!-- original MainMenu menu -->
<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->
<div id='sidebar'>
	<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
	<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>


<div class="tagglyTagged" macro="tags"></div>

<div class='titleContainer'>
	<span class='title' macro='view title'></span>
	<span macro="miniTag"></span>

<div class='subtitle'>
	(updated <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>
	by <span macro='view modifier link'></span>)
	(<span macro='message views.wikified.createdPrompt'></span>
	<span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>)

<div macro="showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')">
	<div class='viewer'><pre macro='view text'></pre></div>
<div macro="else">
	<div class='viewer' macro='view text wikified'></div>

<div class="tagglyTagging" macro="tagglyTagging"></div>


<div class='toolbar'>
	<span macro="showWhenTagged systemConfig">
		<span macro="toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'"></span>
	<span macro="showWhenTagged systemTheme"><span macro="applyTheme"></span></span>
	<span macro="showWhenTagged systemPalette"><span macro="applyPalette"></span></span>
	<span macro="showWhen tiddler.tags.contains('css') || tiddler.title == 'StyleSheet'"><span macro="refreshAll"></span></span>
	<span style="padding:1em;"></span>
	<span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump'></span> <span macro='newHere label:"new here"'></span>
	<span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:"MM/0DD/YY"}}'></span>

<div class="toolbar" macro="toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler"></div>
<div class="title" macro="view title"></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div macro='annotations'></div>
<div class="editLabel">Content</div><div class="editor" macro="edit text"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<div class='editor' macro='edit alias'></div><div class='editorFooter'><span macro='message abegoTiddlerAlias.lingo.aliasPrompt'></span></div>


/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
	background: [[ColorPalette::TertiaryLight]];

/* sexy colours and font for the header */
.headerForeground {
	color: [[ColorPalette::PrimaryPale]];
.headerShadow, .headerShadow a {
	color: [[ColorPalette::PrimaryMid]];

/* separate the top menu parts */
.headerForeground, .headerShadow {
	padding: 1em 1em 0;

.headerForeground, .headerShadow {
	font-family: 'Trebuchet MS' sans-serif;
.headerForeground .siteSubtitle {
	color: [[ColorPalette::PrimaryLight]];
.headerShadow .siteSubtitle {
	color: [[ColorPalette::PrimaryMid]];

/* make shadow go and down right instead of up and left */
.headerShadow {
	left: 1px;
	top: 1px;

/* prefer monospace for editing */
.editor textarea, .editor input {
	font-family: 'Consolas' monospace;

/* sexy tiddler titles */
.title {
	font-size: 250%;
	color: [[ColorPalette::PrimaryLight]];
	font-family: 'Trebuchet MS' sans-serif;

/* more subtle tiddler subtitle */
.subtitle {
	font-size: 90%;
	color: [[ColorPalette::TertiaryMid]];
.subtitle .tiddlyLink {
	color: [[ColorPalette::TertiaryMid]];

/* a little bit of extra whitespace */
.viewer {

/* don't want any background color for headings */
h1,h2,h3,h4,h5,h6 {
	background-color: transparent;
	color: [[ColorPalette::Foreground]];

/* give tiddlers 3d style border and explicit background */
.tiddler {
	background: [[ColorPalette::Background]];
	border-right: 2px [[ColorPalette::TertiaryMid]] solid;
	border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;
	margin-bottom: 1em;
	padding:1em 2em 2em 1.5em;

/* make options slider look nicer */
#sidebarOptions .sliderPanel {
	border:solid 1px [[ColorPalette::PrimaryLight]];

/* the borders look wrong with the body background */
#sidebar .button {
	border-style: none;

/* this means you can put line breaks in SidebarOptions for readability */
#sidebarOptions br {
/* undo the above in OptionsPanel */
#sidebarOptions .sliderPanel br {

/* horizontal main menu stuff */
#displayArea {
	margin: 1em 15.7em 0em 1em; /* use the freed up space */
#topMenu br {
	display: none;
#topMenu {
	background: [[ColorPalette::PrimaryMid]];
#topMenu {
#topMenu .button, #topMenu .tiddlyLink, #topMenu a {
	margin-left: 0.5em;
	margin-right: 0.5em;
	padding-left: 3px;
	padding-right: 3px;
	color: [[ColorPalette::PrimaryPale]];
	font-size: 115%;
#topMenu .button:hover, #topMenu .tiddlyLink:hover {
	background: [[ColorPalette::PrimaryDark]];

/* make 2.2 act like 2.1 with the invisible buttons */
.toolbar {
.selected .toolbar {

/* experimental. this is a little borked in IE7 with the button 
 * borders but worth it I think for the extra screen realestate */
.toolbar { float:right; }

/* fix for TaggerPlugin. from sb56637. improved by FND */
.popup li .tagger a {

/* makes theme selector look a little better */
#sidebarOptions .sliderPanel .select .button {
#sidebarOptions .sliderPanel .select br {

/* make it print a little cleaner */
@media print {
	#topMenu {
		display: none ! important;
	/* not sure if we need all the importants */
	.tiddler {
		border-style: none ! important;
		margin:0px ! important;
		padding:0px ! important;
		padding-bottom:2em ! important;
	.tagglyTagging .button, .tagglyTagging .hidebutton {
		display: none ! important;
	.headerShadow {
		visibility: hidden ! important;
	.tagglyTagged .quickopentag, .tagged .quickopentag {
		border-style: none ! important;
	.quickopentag a.button, .miniTag {
		display: none ! important;

/* get user styles specified in StyleSheet */


|Description|Mptw Theme with a reduced header to increase useful space|


<!-- horizontal MainMenu -->
<div id='topMenu' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span refresh='content' tiddler='SiteTitle' style="padding-left:1em;font-weight:bold;"></span>:
<span refresh='content' tiddler='MainMenu'></span>
<div id='sidebar'>
	<div id='sidebarOptions'>
		<div refresh='content' tiddler='SideBarOptions'></div>
		<div style="margin-left:0.1em;"
			macro='slider chkTabSliderPanel SideBarTabs {{"tabs \u00bb"}} "Show Timeline, All, Tags, etc"'></div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>

For upgrading. See [[ImportTiddlers]].
URL: http://mptw.tiddlyspot.com/upgrade.html
|Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW|
See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last.

// example: set your preferred date format
//config.mptwDateFormat = 'MM/0DD/YY';
//config.mptwJournalFormat = 'Journal MM/0DD/YY';

// example: set the theme you want to start with
//config.options.txtTheme = 'MptwRoundTheme';

// example: switch off autosave, switch on backups and set a backup folder
//config.options.chkSaveBackups = true;
//config.options.chkAutoSave = false;
//config.options.txtBackupFolder = 'backups';

// uncomment to disable 'new means new' functionality for the new journal macro
//config.newMeansNewForJournalsToo = false;


Mystra was the last Goddess of Magic, who mysteriously and dramatically died in The Year of Blue Fire, [[1385 DR|http://forgottenrealms.wikia.com/wiki/1385_DR]]. Her death shook the very foundations of all the known worlds. Magic has never been the same since her death. She took over the domain of magic in [[-339 DR|http://forgottenrealms.wikia.com/wiki/-339_DR]], when [[Mystryl|http://forgottenrealms.wikia.com/wiki/Mystryl]], the first goddess of magic and time, died during the fall of the great magical human empire of Netheril.
<tabs Character>
<tab Background>
//Warforged, 4'9", 220 lbs. (80 lbs. appearance), 16 yrs. (appearance), white magical leather and mithril "flesh" bodysuit, human-looking head with pale skin, bright red eyes, short blue hair//
Many decades ago, an unheard of astrological event scarred the land of Feywild. A giant tear in the fabric of the sky appeared one night, shedding a blinding blue light as bright as the sun. From the tear, a flaming comet shot forth, crashing into the earth with such force, ancient majestic trees were bent low like blades of grass. The eladrin archmage [[Esperifiel Solice]] investigated the impact site at the behest of the Seelie Court of Feywild and at the bottom of a mile-long trench of pure arcane fire, discovered the nearly destroyed remains of a once living construct. He had never seen one, but had read of them in his studies, golems with souls, native to a distant magical plane and called warforged by their creators.

Solice had mastered several spheres of magic, and one of his specialties was in the creations of constructs. He had created permanent autonomous constructs before in the past, but never one which housed an eternal soul. Much of the warforged had been destroyed, and he had no template to follow. Borrowing from his experience with creating golems and other magical constructs, and with a natural gift of creativity, he reconstructed the warforged and coaxed back into her form a spark of life. To his great dismay, he discovered he had not brought her back to life, but in fact, gave her new life. She returned as a blank slate, a bright eyed child birthed into the world with no memory of her past.

Solice took her to his home, naming her Nar'talas, which means stone soul in the elven tongue. He noted she had retained an amazing will to live, as well as immeasurable magical potential. He raised her as his own child, teaching her when he could, and leaving her under the care of trusted friends at the Planarversity when he could not. He spent more time with Nar'talas than his own children. She needed him more, he would say in his defense.

Nar'talas did not understand when Solice passed away ten years ago. It took years, and during those years, she raged, still emotionally and mentally a child. Her magic flared into existence. In order to protect her as well as those around her, [[Elerrielle Solice]] took guardianship of Nar'talas, but she never was the same again. Her fiery demeanor had turned cold and distant. The once outgoing girl always asking questions turned inward, rarely speaking to anyone she didn't know.

In age, she is the chancellor's senior, though Nar'talas still behaves like an adolescent child. [[Elerrielle|Elerrielle Solice]] has enrolled Nar'talas into [[Waterdeep Planarversity]] this year, hoping that the experience will help Nar'talas gain better control of her sorceress abilities, grow up and move past the death of her father, Elerrielle's grandfather.

<tab Stats>
Nar'talas, level 1
Warforged Sorcerer
Build: Dragon Sorcerer
Spell Source: Dragon Magic
Dragon Soul: Dragon Soul Fire

Str 18, Con 13, Dex 10, Int 10, Wis 8, Cha 17.

Str 16, Con 11, Dex 10, Int 10, Wis 8, Cha 17.

AC: 17 Fort: 16 Reflex: 12 Will: 18
HP: 25 Surges: 7 Surge Value: 6

Arcana +7, Endurance +8, Intimidate +10, Athletics +9

Acrobatics, Bluff +3, Diplomacy +3, Dungeoneering -1, Heal -1, History, Insight -1, Nature -1, Perception -1, Religion, Stealth, Streetwise +3, Thievery

Level 1: Armor Proficiency (Leather)

Sorcerer at-will 1: Acid Orb
Sorcerer at-will 1: Burning Spray
Sorcerer daily 1: Lightning Breath
Sorcerer encounter 1: Tempest Breath

Defensive Staff +1, Battle Harness Leather Armor +1, Amulet of Resolution +1
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
merge(config.macros, {
	newHere: {
		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
	newJournalHere: {
		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);


|Description:|If 'New Tiddler' already exists then create 'New Tiddler (1)' and so on|
|Version:|1.1.1 ($Rev: 2263 $)|
|Date:|$Date: 2007-06-13 04:22:32 +1000 (Wed, 13 Jun 2007) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
!!Note: I think this should be in the core

// change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin
if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true;

String.prototype.getNextFreeName = function() {
       var numberRegExp = / \(([0-9]+)\)$/;
       var match = numberRegExp.exec(this);
       if (match) {
               var num = parseInt(match[1]) + 1;
               return this.replace(numberRegExp," ("+num+")");
       else {
               return this + " (1)";

config.macros.newTiddler.checkForUnsaved = function(newName) {
	var r = false;
	story.forEachTiddler(function(title,element) {
		if (title == newName)
			r = true;
	return r;

config.macros.newTiddler.getName = function(newName) {
       while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName))
               newName = newName.getNextFreeName();
       return newName;

config.macros.newTiddler.onClickNewTiddler = function()
	var title = this.getAttribute("newTitle");
	if(this.getAttribute("isJournal") == "true") {
		title = new Date().formatString(title.trim());

	// ---- these three lines should be the only difference between this and the core onClickNewTiddler
	if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true")
		title = config.macros.newTiddler.getName(title);

	var params = this.getAttribute("params");
	var tags = params ? params.split("|") : [];
	var focus = this.getAttribute("newFocus");
	var template = this.getAttribute("newTemplate");
	var customFields = this.getAttribute("customFields");
	if(!customFields && !store.isShadowTiddler(title))
		customFields = String.encodeHashMap(config.defaultCustomFields);
	var tiddlerElem = story.getTiddler(title);
	var text = this.getAttribute("newText");
	if(typeof text == "string")
		story.getTiddlerField(title,"text").value = text.format([title]);
	for(var t=0;t<tags.length;t++)
	return false;


<tabs Character>
<tab Background>
//Human, 5'11", 195 lbs., 20 yrs., tan complexion, shaggy medium length black hair, pale green eyes//


"The Seablades go back to the dreaded pirate Peregrin Seablade, scourge of the Sword Coast, may the [[Bitch Queen|http://forgottenrealms.wikia.com/wiki/Umberlee]] spare his god forsaken soul. Once a pirate, always a pirate," the old man would try to say every time he came back from the sea, but years of grog and a few too many belaying pins to the head and it always sounded more like, "Once a pie rat, aways a pie rat." His father was a pirate, as his father was before him, and his father before that, or so his father would claim in his drunken stupor, belching cheap rum and undirected bile. Nico always waited for lesson time to nip a coin or two from his stumbling father. Such a giver.

Sure, Percival "the Peregrin" Seablade was legend. That was a hundred years ago. If they were blood, then why did he and his father live like dogs and not pirate kings? The Peregrin sacked the Jewel of the North, sunk half the Elven Armada, and even robbed the goddess [[Sune Firehair|http://forgottenrealms.wikia.com/wiki/Sune]], when she walked Faerûn, of the jewels off her neck! A god's fortune, and what remained for Nico, generations after? Not a fly's fart. Where was the Seablade's damned horde hidden? Surely the old man must know. Every time he asked, he earned a backhand, or worse.

The old man set sail half the year, getting his and leaving Nico to fend for himself, through thuggery and shady stuffs. Nico was strongest, if not fastest. He had [[Tymora|http://forgottenrealms.wikia.com/wiki/Tymora]]'s luck and his father's cheap left hook. In the end, all that matters is who is standing up and who is lying face down. He got by without killing anyone who didn't deserve it, but he'd be no rat afloat on a boat of cheese.

Rumor had it, the Peregrin had run afoul of gods and dark magic, and his ghost yet sailed the Sword Coast, seeking to reclaim his greatest booty, worth more than the [[twelve kings of gold|Twelve Kings of Gold]]. And what was that? An emerald the size of your fist that granted wishes, some said. Nico found that stupid. If he'd a gem that granted wishes, the Peregrin would never have died in the first place. Flies and bogwater. Whatever it was, it was worth dying for. More importantly, it was worth living for, even into undeath. Nico would find the truth, no matter what people said. Life in Luskan was worth its weight in rusted nails. Nico was due his. Get out and find his fortune.

What does a pirate's life get you? Rotten whores, rum drunk or swimming with Umberlee. It didn't amount to a dry spit. His father's coins waxed and waned like the face of [[Selûne|http://forgottenrealms.wikia.com/wiki/Selûne]], leaving Nico only with her tears, and when Umberlee finally took the old man into her wet bosom, the share left to Nico was enough not to starve, and not enough to end up face up in the river Mirar. Nico would have taken up the family business, but "an old family friend" showed up and gave him an offer to head to Waterdeep -- to go to school. By mother's dog! But she gave good coin up front, and food, and clothes, and when they made town, she handed him twin ancient blades and said, "These swords belonged to your great grandfather, Percival Seablade." Flies and bogwater! But Nico would get his, and some.
<tab Stats>
Nico Seablade, level 1
Human Fighter
Build: Tempest Fighter
Fighter Talents: Tempest Technique

Str 18, Con 16, Dex 13, Int 10, Wis 10, Cha 9.

Str 16, Con 16, Dex 13, Int 10, Wis 10, Cha 9.

AC: 17 Fort: 17 Reflex: 13 Will: 11
HP: 31 Surges: 12 Surge Value: 7

Athletics +8, Endurance +7, Streetwise +4, Intimidate +4, Stealth +6

Acrobatics, Arcana, Bluff -1, Diplomacy -1, Dungeoneering, Heal, History, Insight, Nature, Perception, Religion, Thievery +1

Human: Two-Weapon Fighting
Level 1: Ruthless Efficiency

Fighter at-will 1: Dual Strike
Fighter at-will 1: Crushing Surge
Bonus At-Will Power: Footwork Lure
Fighter daily 1: Tempest Dance
Fighter encounter 1: Funneling Flurry

Chainmail, Luckblade Short sword +1, Staggering Longsword +1

//Lord Detourvel never wanted to kill his wife. She had been cheating on him for years, he knew, but truth be told, he loved her and couldn't imagine spending the rest of his days alone. He pretended not to know. It was better for everyone.

When those upstarts, the Goadwrights, alluded to the lascivious nature of Lady Detourvel's indiscretions, he was forced to play his hand. He would have to confront his wife and reach the inevitable conclusions that would unravel everything important to him. He would not let that happen now. He was not a young man anymore.

He was away, visiting his distant relatives, when the men he had hired took care of the issue. They made it look like a break in. He did not even have the opportunity to mourn. He returned to a house of the dead. The servants had fled or were slain, drained of their blood. He found his wife in the cellar with yet another plaything - she was devouring the poor girl. His ever faithful wife had returned to him from the grave.


Cruelly murdered for betraying her husband, Lady Detourvel returned as a pale reaver lord and keeps her husband alive, slowly driving him mad. The cuckold served his purpose while she lived, and he would do the same for her in death. She brings home her prey - the young noblewomen of the city - and disposes of the corpses in the cellar. The family's rage drake originally was purchased to keep out the sewyrms. Now the drake grows fat off a different kind of vermin.//


1 [[Pale Reaver Lord|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1987]] //(Open Grave 176)//
1 [[Human Noble|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=3012]] //(MM2 148)//
1 [[Rage Drake|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=381]] //(MM 92)//
6 [[Carcass Eater|http://www.wizards.com/dndinsider/compendium/monster.aspx?id=1878]] //(Open Grave 196)//

[img[http://farm4.static.flickr.com/3393/3658910405_ecebb4f414_o.jpg]] [img[http://farm4.static.flickr.com/3337/3658910423_3824460036_o.jpg]]
[img[http://farm4.static.flickr.com/3352/3659707166_4367330afc_o.jpg]] [img[http://farm3.static.flickr.com/2443/3658910465_6a150ebde4_o.jpg]]


Read the following:

//You all stumble down the street on the way back from a night of drunken revelry. It's not often you're in the noble district, but one rarely argues when someone else is buying the drinks. You take a short cut and turn down an alleyway to head back to your lodgings when when two well-dressed women running hand in hand fly past your group, reeking of perfume and alcohol. One is definitely Taris Liphon, a famous debutante known to run the party circuit. The other one sends shivers down your spine as she flies past - something about her long flowing white hair.

Taris trips and begins to laugh. The other one drags the giddy girl back to her feet. In the glow of tonight's full moon, you notice them standing over what must be an open manhole. Surprisingly, Taris gathers up her red gown and begins to descend down into the city sewers. The other woman glares back at you - and then disappears!

You hear splashes below, then a scream. It's too early to bed down anyway. You descend and give chase. Ahead, the echoing sounds of laughter and splashing water reverberates off the curved stone walls. After a few minutes of pursuit, the sounds stops. You turn a corner to find bright light streaming through where thick metal doors have been left ajar, and step into the light.//

Place the party at the southern stairs - any of the squares between E19 to H19 to H20 to E20 - then read:

//Stabbing light from a lamp far across the way illuminates a long hall. Dark, wet patches stain the cobblestone steps beneath your feet. In the distance, you see a figure in red lying on the ground.//

''Perception Check''
DC 10: There's drops of wet blood on the cobblestones ahead. There are also smears of what must be dried blood.
DC 14: The figure on the ground must be Taris. She looks passed out.
DC 17: Both the padlock and the inner crossbar for the double doors is strangely missing.
DC 19: Taris lies almost still, barely breathing, and pale as a ghost.

''Dungeoneering Check''
DC 12: You're not that far underground. This must be a cellar entrance to the sewers for one of the expensive mansions above.

1 Pale Reaver Lord @ C9
1 Rage Drake @ A3
1 Unconscious Debutante @ E8
2 Carcass Eater (arriving round 2 @ B5)
2 Carcass Eater (arriving round 2 @ J5)
2 Carcass Eater (arriving round 2 @ L6)
1 Human Noble (arriving round 5 @ P5)

When the party closes within line of sight of the Rage Drake, read the following:

//The hallway opens up into a large stone cellar. The stench of rotting death hangs in the cold, damp air. You see another body lying to the left, by a statue. Several piles of bones are stacked about the room. And in the far left corner, the glowing eyes of a large, reptilian beast stare at you.//

''Perception Check''
DC 12: Taris Liphon appears to have stopped breathing. If you hurry, you may stabilize her before she dies.


Lady Detourvel has placed Taris Hilphon dying in a pool of blood - not her own, but the last victim's. The players have six rounds to stabilize her before she dies. Lady Detourvel has used Image of Life and appears as an attractive middle aged noblewoman with long red hair - red, not white, as she has just fed on Taris - lying unconscious on the raised lip of the fountain. She awaits until the party approaches, near enough within reach of the Rage Drake.

A chain leash encircles the neck of the Rage Drake, leashing it to the statue in the southwest corner. The chain is long enough to allow it to move up to 8 squares from A10, and with the Drake constantly moving, the thick iron chain would have to be cut by a single might blow - it would be easier to cleave a dancing sword in half. The Rage Drake fears the pale reaver and will not go near her, but smells fresh meat. It will attack the party on sight.

The Pale Reaver Lord waits until the drake or the party begins to attack. She then will then attempt to surprise the party, attacking the nearest PC with Deadly Mane. A successful DC 25 Insight check will allow the PCs to not be surprised.

__Round 1__: The Pale Reaver Lord will attack with Terrifying Shriek, capturing as many PCs in range as possible, then use Insubstantial Transformation. She will use Insubstantial Transformation at the end of every round while she still has a minor action available. The shriek awakens the other occupants of the house: the Carcass Eaters in the cellar and Lord Detourvel.

The Rage Drake will charge the nearest PC and use Raking Charge.

__Round 2__: The Pale Reaver Lord will continue to use Deadly Mane on the same target until he or she becomes bloodied while attempting to flank for Combat Advantage and set herself up for Blood Drain.

The Drake will Bite the nearest PC, unless another PC at range attacks it, in which case it will use Raking Charge again. In subsequent rounds, once in a Bloodied Rage, the Drake will use Raking Charge whenever possible, even if it provokes Opportunity Attacks.

2 Carcass Eaters burrowed in each bone pile burst forth and attack the PCs. They will team up, always attempting to Flank. The Carcass Eaters are weary of the Drake and will stay out of reach when possible.

__Round 3__: The Pale Reaver will use Blood Drain on any target as soon as possible. If the Pale Reaver Lord is Bloodied, it will use Insubstantial Transformation and fly through the eastern double doors, waiting for Lord Detourvel.

__Round 5__: Lord Detourvel arrives after hearing the preternatural scream of his undead bride and the sound of combat. He will use Inspirational Authority on the Pale Reaver Lord and scream out the name of his dead wife, "Sarah!" The eastern doors are now unlocked.

The Pale Reaver will use the free action from Inspirational Authority to use Deadly Mane. Her Standard Action will be to use Deadly Mane. If she is set up for it, she will use her Action Point and use Blood Drain.

__Round 6__: The Human Noble will close with the Pale Reaver and use Urge Hesitation if any PCs are near.

The Pale Reaver will close with her husband and use Entrapping Gaze on any PC standing next to another PC.

At the end of this round, if the party has not stabilized Taris Liphon yet, she dies.

__Round 7__: The Pale Reaver will use the dominated PC to attack the adjacent PC, then attack the closest PC to her with Deadly Mane.

The Noble will attempt to flank the Pale Reaver's target and use Appoint Champion on the Reaver every round.

In subsequent rounds, the Pale Reaver Lord will continue attacking targets near the Human Noble until the Noble dies. If the Rage Drake is still alive, she will attack the same target as the Drake. If both the Noble and the Drake are dead, she will use Insubstantial Transformation and flee through the eastern double doors.

If the Pale Reaver Lord dies, she will let loose an inhuman scream and dissipate. A golden wedding band will appear in mid-air and drop to the ground. If the Pale Reaver Lord dies before the Human Noble, he will scream, "Sarah! How dare you murder my wife!" and attack the PCs until he or they are dead.

*Illumination: Bright light illuminates the cellar, coming from an oil lantern hanging from the ceiling at F1.
*Ceiling: The ceiling of the cellar rises 20 feet above the main floor.
*Killing floor: A slightly recessed 20'x20' pit (E5 to H5 to H8 to E8) pools with a thin layer of fresh blood. Bits of clothing and bone are strewn about. A DC 15 History will identify the clothing as a female uniform from a nearby school.
*Bone piles: Gnawed-on bones have been swept into piles at B5, J5, and L6. They look humanoid. Moving adjacent to or disturbing the piles before the Pale Reaver Lord uses Terrifying Shriek will awaken the Carcass Eaters.
*Statue: At the center of a recessed fountain in the southwest corner of the room is a life-size statue depicting a damesel carrying a basket of grapes over one shoulder. A thick iron chain encircles one bent arm, with a large rusted padlock securing one end of the chain. The other end of the long chain connects to the Rage Drake. The padlock is too rusted to be picked, but may be broken - it has 30 HP. Breaking the padlock will release the Rage Drake's chain. If the Drake is not Bloodied, it will escape through the hole in the northwest corner of the floor.
*Fountain: The fountain appears to have been dry for quite some time. The lip of the fountain rises up three feet. Crossing over the lip counts as moving through one square of difficult terrain. Crouching behind the lip of the fountain provides cover.
*Collapsed floor: The cellar floor slopes slightly downward to the northwest, and decades of water damage have caused the northwest corner of the room to collapse into rubble, sloping downward to the city sewers directly below. Traversing the slope counts as moving through difficult terrain.
*Doors: Along the east wall are iron double doors. They are locked and require a DC 26 Thievery check to unlock, or the black iron key carried by Lord Detourvel. The doors lead up to the kitchen and exit to the city streets.
*Platforms: On the eastern side of the room, 10 foot ramps lead up to wooden platforms 10 feet off the main floor. Scattered about are small barrels and sacks of dried sundry goods that can offer cover.


If the Pale Reaver Lord died, the tarnished golden wedding band she dropped is worth 110gp.

If the party does not save the life of Taris Liphon, but brings her body to the city watch, her family will reward the party for returning her body, giving them 500gp.

If the party manages to save the life of Taris Liphon, she will awaken after the fight and become enamored with the most attractive member of the party. She will reward him or her with a gift: a date with her, and her [[Contortionist's Cord|http://www.wizards.com/dndinsider/compendium/item.aspx?id=3161]]. Liphon insists her crush and the party must accompany her to fetch her cord. She accidentally left it in her last boyfriend's bedroom. It seems he's quite the thug, with a large entourage...

If the party manages to subdue Lord Detourvel instead of killing him outright, he will completely break down once he awakens, giving away the truth that he had his wife murdered. Turning in Lord Detourvel results acquiring the City Watch as a new resource for information.

If Lady Detourvel manages to escape, she will seek revenge upon any PCs who return to the noble district at night. The party will continue to hear news of missing debutantes until they act to end Lady Detourvel's villainy.

*A wealthy sycophant saw the PCs run after Liphon the night of her disappearance and holds them accountable. She has hired a gang of thugs to track down the PCs and exact revenge.
*Clothing and a signet ring found in the killing pit belongs to a student at a nearby school. Taking the ring to the school results in a reward, as well as a new patron for quests or a new resource for information.
*A search of Lord Detourvel uncovers a scrap of parchment and a missive. The scrap lists the names of several debutantes who have gone missing in the past weeks. The names are all scratched out, except for Taris Liphon and Misrael Goadwright. The missive appears be from the young Goadwright, professing her love not for Lady Detourvel, but Lord Detourvel! It hints at her involvement in the murder, and acknowledges her awareness of the plot, in the least. Damning information, but the wealthy Goadwrights have given hefty gifts to the city...
The Order of the Rose was founded in 1466 DR by the third chancellor of the Planarversity, [[Arcueid Tenjou]]. The order is the official policing - and many say military - arm of the Planarversity.

The crest of the Order is a circle of red petals surrounded by black thorns. Members of the order wear black tabards emblazoned with the rose crest, as well as rose crested signet rings. The rings and tabards have small variations denoting to which company the bearers belong.

The Order is headquarted at [[Shadowfell Planarversity]], though garrisons exist at every campus. Order presence is heaviest at the Shadowfell campus, as it is home to the College of Martial Science and sees heavy activity from regular skirmishes with denizens of the Shadowfell along its borders.

!!Order Companies
#1st Company (//Shadowfell Planarversity//) - the first and original Order of the Rose, founded at Shadowfell Planarversity by the Order founder and Planarversity Chancellor, Arcueid Tenjou. It serves as the primary policing company for the Shadowfell campus and is directly run by Shadowfell Preceptor [[Akioh the Autumn Lord]].
#2nd Company (//Waterdeep Planarversity//) - the smallest garrison company, primarily because of its secure location in the Castle Ward of Waterdeep.
#3rd Company (//Shadowfell Planarversity//) - Planarversity's largest garrison company, the 3rd sees more action along the school borders than most mercenary companies. The [[College of Martial Science]] is practically an extension of the 3rd.
#4th Company (//Shadowfell Planarversity//) - the 4th rare steps foot on the Shadowfell campus, primarily functioning as the forward arm of Shadowfell forces. They are more a small army than any other company, being so removed from the regular school life.
#5th Company (//Sigil Planarversity//) - a small, elite force with extensive planar experience. The 5th has seen it all.
#6th Company (//Feywild Planarversity//) - the 6th was almost wiped out entirely ten years ago in the battle that claimed the school founder, and now has regrown in size to become the second largest garrison company.
#7th Company (//Feywild Planarversity//) - a small, magic-heavy strike group often sent to trouble spots. The 4th has larger numbers, but the 7th has more firepower.
!!!Order Ranks
#Captain - highest rank in the order, commander of a company
#Vice Captain - second highest rank in the order, assists a captain
#Lieutenant - commander of several vice lieutenants and many squads
#Vice Lieutenant - assists a lieutenant, commands a few squads, lowest rank for graduates of the College of Martial Science
#First Guardian - commander of a squad of typically 4-5 protectors
#Guardian- unranked lowest level Order member
!!!Typical Squad Details
*First Guardians always wear [[Rose Colored Glasses]].
*Guardians wear leather armor are armed with hand crossbows, and either short swords, maces, or long swords.

During orientation, new undergraduates are introduced to their college [[advisers|Advisers]], given a tour of the campus, instructed in the rules of the Planarversity, introduced to their fellow classmates, and shown to their new [[housing|Housing]].

Undergraduates are also expected to submit to the [[Rite of Enrollment]] during their orientation, and are given their orientation package, which includes:
*Planarversity course catalog and [[Code of Conduct]]
*[[Signet Rings]]
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Date:''|Apr 19, 2007|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			// checkbox linked with this password "save this password on this computer"
			// text savePasswordCheckboxLabel
		onChange: config.macros.option.genericOnChange

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
		return config.options[name] ? "true" : "false";

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
		set: function(name,value) {config.options[name] = decodeCookie(value);}

// need to reload options to load passwordOptions

if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

		pasPassword: "Test password"

The Planar Geographic Society (PGS), headquarted in [[Sigil]], is one of the largest non-profit scientific and educational institutions in Sigil and the known worlds. Its interests include planar geography, archaeology and natural science, the promotion of environmental and historical conservation, and the study of planar culture and history.

The Planar Geographic Society's historical mission is to increase and diffuse planar knowledge while promoting the conservation of planar cultural, historical, and natural resources.

General membership dues are 100g per anum, and entitle the member to a monthly subscription to //[[Planes Illustrated]]//, access to the Society library in Sigil, and access to special events hosted at the Society headquarters. As of 1479 DR, the Society counts over five thousand active members. The present Chairwoman of the Society is the deva [[Serra]].

The Planarversity is a multiplanar, multicampus private institution dedicated to the pursuit of knowledge across the known worlds.

The Planarversity was founded in [[Sigil]] and the planet of [[Abeir-Toril|http://forgottenrealms.wikia.com/wiki/Toril]] in The Year of the Secret, 1396 DR, eleven years after [[the Spellplague|http://forgottenrealms.wikia.com/wiki/Spellplague]] and the assassination of [[Mystra]], the last Goddess of Magic of Abeir-Toril. The many [[Planarversity Founders |Founders]] included several archmagi, an archfey, and even a demigod.

The main campus is [[Sigil Planarversity]], with extended learning branches of the Planarversity in many other planes, including the [[Feywild]], the [[Shadowfell]], and the [[Forgotten Realms|http://forgottenrealms.wikia.com/wiki/Forgotten_Realms]]. It is the Year of the Ageless One (1479 DR) and the beginning of the school's 84th year.
The Planarversity Central Spire is located in the Clerk's Ward of [[Sigil]] and primarily hosts administrative offices for the [[Planarversity]]. Most who come to the Spire come by way of the [[Door of Rooms]]. The Spire also hosts special classes and the 5th Company of the [[Order of the Rose]].
//Planes Illustrated// is a monthly chapbook produced by the [[Planar Geographic Society]] in [[Sigil]] and distributed exclusively to society members. The //Illustrated// is a high-end publication, printed at a standard size of 64 pages of paper with color lithograph covers and inserts. With a print run of over five thousand copies each month, the //Illustrated// is one of the largest and most expensive printing operations in Sigil.

''Planarversity 101: //So You Want to Be a Hero?//''

[[Dungeons & Dragons|http://www.wizards.com/default.asp?x=dnd/welcome]] meets academia! //Plumes & Parchments// is a Dungeons & Dragons 4E campaign centering around the [[Planarversity]], a school for heroes.

The prestigious private institution of higher learning was founded in the famed city of [[Sigil]], and over the past century since its founding, has spread to the most distant corners of the known worlds. The Planarversity exists to uncover and unify the knowledge of the planes. As a secondary function, the Planarversity gathers the brightest exemplars from the each world to nurture, educate and polish into heroic examples of its ideals.

Players begin as newly enrolled students at the local [[Forgotten Realms|http://forgottenrealms.wikia.com/wiki/Forgotten_Realms]] campus of the Planarversity at [[Waterdeep|http://forgottenrealms.wikia.com/wiki/Waterdeep]], undergraduates at campaign start, brought to the school by chance, by birth, or by fortune, yet all united by a common thread: the thirst for knowledge and adventure.

//Plumes & Parchments// spans from levels 1 all the way to 30. At the Heroic tier, a wayward group unlikely heroes uncover the secrets of thousand year old plots about to hatch. At the Paragon tier, the band of adventurers will ford through the barriers of time and space in their quest to do no less than save their world. And at the Epic tier, elder gods and their eternal armies shall descend upon the shores of a hundred worlds, with the party standing as the final bulwark against Armageddon.

Though //Plumes & Parchments// begins in the Forgotten Realms, its connection to the planes makes it a perfect fit with D&D 4E's [[Points of Light|http://www.wizards.com/default.asp?x=dnd/drdd/20070829a]] setting. The starting campus can be set up anywhere the DM feels is a good springboard for Heroic adventure. Rumor has it that the next Planarversity campus will be established on the continent of [[Khorvaire|http://eberron.wikia.com/wiki/Khorvaire]] in [[Eberron|http://en.wikipedia.org/wiki/Eberron]]. Planarversity campuses can be set up in any of your campaigns!

Powered by [[Monkey Pirate TiddlyWiki|MPTW]] and hosted on [[TiddlySpot|http://tiddlyspot.com]].

A portal exists at each [[Planarversity]] campus, linking the campus to the [[Planarversity Central Spire]] in [[Sigil]]. At the Spire, the [[Door of Rooms]] has portals linked to each Planarversity campus. In this fashion, students and faculty can regularly travel between each campus.

Magical portal guardians exist at portal location, verifying the identities of all who enter and all who exit the portals and barring access to enemies of the school.

!!!Role: Controller
*[[Mika Sevens]] – Female Human Wizard
*[[Torn]] – Male Human Invoker
!!!Role: Defender
*[[Aradun Mistwalker]] - Male Moon Elf Paladin
*[[Nico Seablade]] - Male Human Fighter
*[[Tarsith of Solace]] – Male Drow Paladin
!!!Role: Leader
*[[Arkadio Durothil]] – Male Sun Elf Bard
*[[Elisi Freep]] - Female ~Half-Elf Cleric
*[[Ino]] – Female ~Shadar-Kai Warlord
*[[Li Ping]] - Female Human Human Shaman
!!!Role: Striker
*[[Aya Solice]] – Female Eladrin Rogue
*[[Cheren of Khaghun]] – Female Human Ranger
*[[Jarl Beornson]] – Male ~Half-Elf Barbarian
*[[Maya Solice]] – Female Eladrin Rogue
*[[Mercy]] – Female Tiefling Sorcerer
*[[Nar'talas]] - Female Warforged Sorcerer
*[[Sasuke]] - Male Human Monk
|Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
* If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin.
* Inspired by http://ejohn.org/files/pretty.js
Date.prototype.prettyDate = function() {
	var diff = (((new Date()).getTime() - this.getTime()) / 1000);
	var day_diff = Math.floor(diff / 86400);

	if (isNaN(day_diff))      return "";
	else if (diff < 0)        return "in the future";
	else if (diff < 60)       return "just now";
	else if (diff < 120)      return "1 minute ago";
	else if (diff < 3600)     return Math.floor(diff/60) + " minutes ago";
	else if (diff < 7200)     return "1 hour ago";
	else if (diff < 86400)    return Math.floor(diff/3600) + " hours ago";
	else if (day_diff == 1)   return "Yesterday";
	else if (day_diff < 7)    return day_diff + " days ago";
	else if (day_diff < 14)   return  "a week ago";
	else if (day_diff < 31)   return Math.ceil(day_diff/7) + " weeks ago";
	else if (day_diff < 62)   return "a month ago";
	else if (day_diff < 365)  return "about " + Math.ceil(day_diff/31) + " months ago";
	else if (day_diff < 730)  return "a year ago";
	else                      return Math.ceil(day_diff/365) + " years ago";

Date.prototype.formatString_orig_mptw = Date.prototype.formatString;

Date.prototype.formatString = function(template) {
	return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate());

// for MPTW. otherwise edit your ViewTemplate as required.
// config.mptwDateFormat = 'pppp (DD/MM/YY)'; 
config.mptwDateFormat = 'pppp'; 


''Gotta Catch 'Em All''
Level 1
Individual Quest

//Welcome to the Planarversity! On your first day at the Planarversity, your [[adviser]] handed you a [[Student Passport]] and asked you to complete a series of tasks before the end of orientation week.
*Obtain a stamp from a [[portal guardian]] at each [[campus]]:
**[[Feywild Planarversity]]
**[[Shadowfell Planarversity]]
**[[Sigil Planarversity]]
**[[Waterdeep Planarversity]]
*Obtain a stamp from your [[college]]

''Reward'': 100xp and a random [[Traveler's Card]]
//Examples of quests to be found in the campaign.//
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
config.quickOpenTag = {

	dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?

	createTagButton: function(place,tag,excludeTiddler) {
		// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
		var splitTag = tag.split("|");
		var pretty = tag;
		if (splitTag.length == 2) {
			tag = splitTag[1];
			pretty = splitTag[0];
		var sp = createTiddlyElement(place,"span",null,"quickopentag");
		var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
		if (excludeTiddler)

	miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var tagged = store.getTaggedTiddlers(tiddler.title);
		if (tagged.length > 0) {
			var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
			theTag.className = "miniTag";

	allTagsHandler: function(place,macroName,params) {
		var tags = store.getTags(params[0]);
		var filter = params[1]; // new feature
		var ul = createTiddlyElement(place,"ul");
		if(tags.length == 0)
		for(var t=0; t<tags.length; t++) {
			var title = tags[t][0];
			if (!filter || (title.match(new RegExp('^'+filter)))) {
				var info = getTiddlyLinkInfo(title);
				var theListItem =createTiddlyElement(ul,"li");
				var theLink = createTiddlyLink(theListItem,tags[t][0],true);
				var theCount = " (" + tags[t][1] + ")";
				var theDropDownBtn = createTiddlyButton(theListItem," " +

	// todo fix these up a bit
	styles: [
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
"	{ margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
"	{ border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
"	{ margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
"	{ margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
"	/* looks better in right justified main menus */",
"	{ margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }", 
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",

	init: function() {
		// we fully replace these builtins. can't hijack them easily
		window.createTagButton = this.createTagButton;
		config.macros.allTags.handler = this.allTagsHandler;
		config.macros.miniTag = { handler: this.miniTagHandler };
		config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;



|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0 ($Rev: 5501 $)|
|Date:|$Date: 2008-06-10 23:11:55 +1000 (Tue, 10 Jun 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
config.renameTags = {

	prompts: {
		rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
		remove: "Remove the tag '%0' from %1 tidder%2?"

	removeTag: function(tag,tiddlers) {
		for (var i=0;i<tiddlers.length;i++) {

	renameTag: function(oldTag,newTag,tiddlers) {
		for (var i=0;i<tiddlers.length;i++) {
			store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
			store.setTiddlerTag(tiddlers[i].title,true,newTag);  // add new

	storeMethods: {

		saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,

		saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
			if (title != newTitle) {
				var tagged = this.getTaggedTiddlers(title);
				if (tagged.length > 0) {
					// then we are renaming a tag
					if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))

					if (!this.tiddlerExists(title) && newBody == "")
						// dont create unwanted tiddler
						return null;
			return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);

		removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,

		removeTiddler: function(title) {
			var tagged = this.getTaggedTiddlers(title);
			if (tagged.length > 0)
				if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
			return this.removeTiddler_orig_renameTags(title);


	init: function() {



!Ritual: Rite of Enrollment
Component Cost: 10 gp
Market Price: not for sale
Key Skill: Arcana (no check)
Level: 10
Category: Creation
Time: 5 minutes
Duration: Permanent

All students are required to undergo the Rite of Enrollment ritual upon accepting admission to a college of the [[Planarversity]]. The ritual requires a willing target and an everburning seed of a fire blossom tree as the material component. The rite is similar to an Arcane Mark, but unlike the mark, the Rite of Enrollment creates a unique magical glyph that that is not determined by the ritual caster. The glyph is inscribed on the target's forehead and is invisible. Seen by a creature using Arcana to detect magic, the glyph appears only as an [[everburning seed|Everburning Seeds]]. To a person wearing [[Rose Colored Glasses]], a glyph telepathically reveals the following details to the wearer:
*The name of person glyph marked
*The college of enrollment of the person glyph marked
*The name of the person who cast the Rite of Enrollment
*The date and location of the casting
Arcana skill checks reveal the following information:
*DC 20: an everburning seed is visible on the bearer's forehead
*DC 30: the name of person glyph marked
*DC 40: the same information as if wearing Rose Colored Glasses

The enrollment rune can be removed or rewritten with an additional casting of the Rite of Enrollment. 
The River of Remembrance is a magical river supplying the school with all its water. The river comes from a deep underground fissure surrounding the Central Campus of [[Sigil Planarversity]], erupting at the surface as hot springs and running off into the [[Astral Sea]]. Fish do not live in the river. Instead, forgotten memories lie in its depths.

The water has strange properties. Strong memories may sometimes come into one who drinks or bathes in the river as a sense of deja vu—memories from another time or another world. The water has been claimed to both help remember and help forget, though neither claim has been proven.
1 part sour
2 parts sweet
3 parts strong
4 parts weak
and spice
<tabs Character>
<tab Background>
//5'8", 135 lbs., 20 yrs., dark tan, short black hair, black eyes//
//(~SAHSS-kay ~ten-JOH)//

Originally from Kozakura.
Illegitimate son of a lord, mother a concubine, sent to a Shou Lung monastery and raised as a monk.
Escaped back to Kozakura, tried to confront father but was stopped before he could get the chance and was almost killed.
Rescued by Etuan Himemiya, who brought him to the Planarversity.
Student of Li Po.
Enamored with Li Ping.
Goal is to become stronger, to prove his worth to his father and claim his noble blood.

<tab Stats>
Sasuke, level 1
Human Monk
Build: Centered Breath Monk
Monastic Tradition: Centered Breath

Str 14, Con 14, Dex 18, Int 10, Wis 13, Cha 8.

Str 14, Con 14, Dex 16, Int 10, Wis 13, Cha 8.

AC: 16 Fort: 16 Reflex: 17 Will: 14
HP: 26 Surges: 9 Surge Value: 6

Stealth +9, Perception +6, Endurance +7, Acrobatics +9, Athletics +7

Arcana, Bluff -1, Diplomacy -1, Dungeoneering +1, Heal +1, History, Insight +1, Intimidate -1, Nature +1, Religion, Streetwise -1, Thievery +4

Human: Stubborn Survivor
Level 1: Focused Expertise (Monk Unarmed Strike)

Monk at-will 1: Crane's Wings
Monk at-will 1: Dancing Cobra
Bonus ~At-Will Power: Five Storms
Monk daily 1: Masterful Spiral
Monk encounter 1: Drunken Monkey

Cloth Armor (Basic Clothing), Lifedrinker Monk Unarmed Strike +1, Amulet of Mental Resolve +1
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0 ($Rev: 5502 $)|
|Date:|$Date: 2008-06-10 23:31:39 +1000 (Tue, 10 Jun 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
To use these you must add them to the tool bar in your EditTemplate

	saveCloseTiddler: {
		text: 'done/close',
		tooltip: 'Save changes to this tiddler and close it',
		handler: function(ev,src,title) {
			var closeTitle = title;
			var newTitle = story.saveTiddler(title,ev.shiftKey);
			if (newTitle)
				closeTitle = newTitle;
			return config.commands.closeTiddler.handler(ev,src,closeTitle);

	cancelCloseTiddler: {
		text: 'cancel/close',
		tooltip: 'Undo changes to this tiddler and close it',
		handler: function(ev,src,title) {
			// the same as closeTiddler now actually
			return config.commands.closeTiddler.handler(ev,src,title);



|Description:|Lets you easily switch theme and palette|
|Version:|1.0.1 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
* Borrows largely from ThemeSwitcherPlugin by Martin Budden http://www.martinswiki.com/#ThemeSwitcherPlugin
* Theme is cookie based. But set a default by setting config.options.txtTheme in MptwConfigPlugin (for example)
* Palette is not cookie based. It actually overwrites your ColorPalette tiddler when you select a palette, so beware. 
* {{{<<selectTheme>>}}} makes a dropdown selector
* {{{<<selectPalette>>}}} makes a dropdown selector
* {{{<<applyTheme>>}}} applies the current tiddler as a theme
* {{{<<applyPalette>>}}} applies the current tiddler as a palette
* {{{<<applyTheme TiddlerName>>}}} applies TiddlerName as a theme
* {{{<<applyPalette TiddlerName>>}}} applies TiddlerName as a palette

config.macros.selectTheme = {
	label: {
      		selectTheme:"select theme",
      		selectPalette:"select palette"
	prompt: {
		selectTheme:"Select the current theme",
		selectPalette:"Select the current palette"
	tags: {

config.macros.selectTheme.handler = function(place,macroName)
	var btn = createTiddlyButton(place,this.label[macroName],this.prompt[macroName],this.onClick);
	// want to handle palettes and themes with same code. use mode attribute to distinguish

config.macros.selectTheme.onClick = function(ev)
	var e = ev ? ev : window.event;
	var popup = Popup.create(this);
	var mode = this.getAttribute('mode');
	var tiddlers = store.getTaggedTiddlers(config.macros.selectTheme.tags[mode]);
	// for default
	if (mode == "selectPalette") {
		var btn = createTiddlyButton(createTiddlyElement(popup,'li'),"(default)","default color palette",config.macros.selectTheme.onClickTheme);
	for(var i=0; i<tiddlers.length; i++) {
		var t = tiddlers[i].title;
		var name = store.getTiddlerSlice(t,'Name');
		var desc = store.getTiddlerSlice(t,'Description');
		var btn = createTiddlyButton(createTiddlyElement(popup,'li'), name?name:t, desc?desc:config.macros.selectTheme.label['mode'], config.macros.selectTheme.onClickTheme);
	return stopEvent(e);

config.macros.selectTheme.onClickTheme = function(ev)
	var mode = this.getAttribute('mode');
	var theme = this.getAttribute('theme');
	if (mode == 'selectTheme')
	else // selectPalette
	return false;

config.macros.selectTheme.updatePalette = function(title)
	if (title != "") {
		if (title != "(default)")

config.macros.applyTheme = {
	label: "apply",
	prompt: "apply this theme or palette" // i'm lazy

config.macros.applyTheme.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var useTiddler = params[0] ? params[0] : tiddler.title;
	var btn = createTiddlyButton(place,this.label,this.prompt,config.macros.selectTheme.onClickTheme);
	btn.setAttribute('mode',macroName=="applyTheme"?"selectTheme":"selectPalette"); // a bit untidy here

config.macros.selectPalette = config.macros.selectTheme;
config.macros.applyPalette = config.macros.applyTheme;

config.macros.refreshAll = { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
	createTiddlyButton(place,"refresh","refresh layout and styles",function() { refreshAll(); });




The legendary deva [[Serra]] is the Chairwoman of the [[Planar Geographic Society]] in [[Sigil]], having held the post for the past fifty years. For many, the charismatic and captivating face of Serra is the face of the Society and its magazine, //[[Planes Illustrated]]//. She prefers to delegate most of the day-to-day administrative tasks and still takes an active role in the field, gathering research for //Planes Illustrated// and promoting the Society abroad.

Like the [[Feywild]], the Shadowfell is a plane parallel to the world. It a darker form of the world, a plane of shadows, death, and undeath. All souls who die must pass through the Shadowfell and the realm of the Raven Queen, Goddess of Death, on their way to the Far Realms and beyond.

Of note, the [[Shadowfell Planarversity]] is located in the Shadowfell.

The Shadowfell Planarversity was founded in 1466 DR under the direction of Chancellor [[Arcueid Tenjou]].

[[Akioh the Autumn Lord]] is the current Preceptor of the Shadowfell Planarversity. The grounds of the campus are under the protection of his demesne.

The campus is the home to the [[Order of the Rose]] and the College of Martial Science -- the college had been previously located at the Waterdeep campus until the founding of the Shadowfell campus.
|''Source''|[[FND's DevPad|http://devpad.tiddlyspot.com/#ShortURLPlugin]]|
|''License''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Description''|automatically abbreviates excessively long URLs|
!Revision History
!!v0.5 (2008-02-10)
* initial release
!To Do
* rename
* code sanitzing
// override urlLink formatter
for(var i = 0; i < config.formatters.length; i++) {
	var f = config.formatters[i];
	if(f.name == "urlLink") {
		f.handler = function(w){
			var link = createExternalLink(w.output, w.matchText);
			createTiddlyText(link, abbreviateURL(w.matchText));

 * @param {String} URL URL to process
 * @param {Integer} threshold Number of characters above which URLs are abbreviated (optional; default is 80)
 * @param {String} ellipsis String to use for ellipsis (optional; default is " [...] ")
function abbreviateURL(URL, threshold, ellipsis) {
	threshold = threshold || 80;
	if(URL.length < threshold)
		return URL;
	ellipsis = ellipsis || " [...] ";
	// remove protocol
	URL = URL.replace(/.*?:\/\//, "");
	// split by directories
	var parts = URL.split("/");
	if(parts.length > 2) {
		return parts[0] + ellipsis + parts[parts.length - 1];
	} else {
		// split by domains
		parts = URL.split(".");
		if(parts.length > 2) {
			return parts[parts.length - 2] + "." + parts[parts.length - 1];
		} else { // do not abbreviate
			return URL;
|Created by|SaqImtiaz|
|Version|0.2 |
Allows you to list tiddlers that have changed since the users last visit. You can list only all changed tiddlers, or filter them to only show tiddlers that have or do not have a specific tag. By default a simple list of the titles of changed tiddlers is created. However, using an extremely versatile syntax you can provide a custom template for the generated text.


Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.

additional optional params:
{{{<showUpdates excludeTag:TagToExclude onlyTag:TagToList maxEntries:10 write:CustomWriteParameter >>}}}
excludeTag: ~TagToExclude
onlyTag: ~TagToList
maxEntries: max number of entries displayed when there are no updates. (default is 10, which can be changed in the config.macros.showUpdates.settings part of the code)
write: if a write parameter is not provided, an un-numbered list of the updates is generated. Alternatively, you can specify a custom 'template' for the text generated. The syntax for the write parameter is identical to that of the forEachTiddler macro. Additonal documentation on this syntax will be provided soon.
Some of the variables available in the write parameter are 'index', 'count' and 'lastVisit' where lastVisit is the date of the last visit in the format YYYYMMDDHHMM. Also areUpdates is a boolean that is true if there are new updates since the users last visit.

!!!To Do:
*refactor code to facilitate translations
*a streamlined version without the custom write parameter

window.lewcidLastVisit = '';
window.old_lewcid_whatsnew_restart = window.restart;
window.restart = function()
                 lewcidLastVisit= config.options.txtLastVisit;
        config.options.txtLastVisit = (new Date()).convertToYYYYMMDDHHMM();

TiddlyWiki.prototype.lewcidGetTiddlers = function(field,excludeTag,includeTag,updatesOnly)
              var results = [];
                      if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
                                    if(includeTag == undefined ||  tiddler.isTagged(includeTag))
                                            if ( updatesOnly == false || tiddler.modified.convertToYYYYMMDDHHMM()>lewcidLastVisit)
                  results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
              return results;

config.macros.showUpdates.settings =
         maxEntries: 10  //max items to show, if there are no updates since last visit

config.macros.showUpdates.handler = function(place,macroName,params,wikifier,paramString,tiddler)
          var args = paramString.parseParams("list",null,true);
          var write = getParam(args, "write", undefined);
          var onlyTag = getParam(args, "onlyTag", undefined);
          var excludeTag = getParam(args, "excludeTag", undefined);
          var sortBy = "modified";
          var maxEntries = getParam(args,"maxEntries",this.settings.maxEntries);

          if (lewcidLastVisit) 
                {var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,true);
                 var areUpdates = tiddlers.length>0? true:false;}

          if (!lewcidLastVisit)
               {var countLine = "!!Recent Updates:";
               var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);
               var areUpdates = false;}
          else if (tiddlers.length == 0)
               {var countLine = "!!@@color:red;No new updates@@ since your last visit. @@color:#999;font-size:70%;" + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@\n!!Recent Updates:";
               var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);}
               {var countLine ="!!@@color:red;"+ tiddlers.length + "@@ new " + (tiddlers.length==1?"update":"updates") + " since your last visit: @@color:#999;font-size:70%;" + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@";}

          tiddlers = tiddlers.reverse();
          var lastVisit = lewcidLastVisit? lewcidLastVisit:undefined;
          var count = areUpdates == true? tiddlers.length : maxEntries;
          var sp = createTiddlyElement(place,"span","showUpdates");
          if (write==undefined)
                  var list = createTiddlyElement(sp,"ul");
                  for (var i = 0; i < count; i++)
                           var tiddler = tiddlers[i];
                           createTiddlyLink(createTiddlyElement(list,"li"), tiddler.title, true);
                 var list = '';
                 for (var index = 0; index < count; index++) {
                 var tiddler = tiddlers[index];
                 list += eval(write); }
                 wikify(list, sp);
Sigil, the City of Doors.

From Sigil, one could conceivably walk to the Nine Hells and back. Sigil itself is a demiplane teeming with doorways to all the known planes of existence.

Sigil is the home of myriad planar factions of countless origin. Every major god and every major mortal empire has some presence in Sigil. As a result, Sigil is a neutral ground. Though fights among immortals may commonly flare up, open warfare is a rarity. Everyone must wear at least the semblance of civility in Sigil.

The unique ecology of Sigil and its existence as a cultural and literal nexus of the known worlds makes it the perfect home for [[the Planarversity|The Planarversity]].

Sigil is divided into six wards:
*The Lady's Ward – where the cream of Sigil resides.
*Market Ward – where Sigil spends its money.
*Guildhall Ward – the middle class of Sigil.
*Lower Ward – blue collar Sigil.
*The Hive – the other side of the planar tracks.
*Clerk's Ward – the seat of Sigil bureaucracy and culture, and the location of The Planarversity Central Spire.

Sigil Planarversity is home to the adminstrative offices of the [[Planarversity]], and the majority of its graduate students hail the [[Sigil]] campus as home.

The name is a misnomer of sorts. The main entrance to Sigil Planarversity is the [[Planarversity Central Spire]] in the city of Sigil, but the Central Campus itself is located in a large private demesne hidden away in a distant corner of the [[Astral Sea]]. The Spire is located in the Clerk's Ward of Sigil, occupying what appears to be a relatively modest archmage's tower. The Spire primarily serves as a nexus between campuses. Doorways exist to and from the Central Spire to every Planarversity campus. Without using a Planarversity portal, traveling to the Sigil Planarversity via the [[Astral Sea]] is a long and perilous journey.

Chancellor [[Etuan Himemiya]] currently presides over the Planarversity from the Hall of Humility at the Central Campus.

The campus is home to the [[Academy of Magic]], the [[College of Divine and Primal Studies]], and the [[Graduate School of Planar Studies]].

!!!Points of Interest
*The [[Door of Rooms]] in the [[Central Spire]] is a portal to the Planarversity campuses. Depending on how one opens the door determines one's destination.
*The [[Forest of Knowledge]] surrounds the Central Campus and is home to the Planarversity's largest repository of knowledge, as well as the largest shrine to the demigod [[Solace]].
*The [[River of Remembrance]] is the source of water for the school, erupting from hot springs above surrounding Central Campus and flowing out into the Astral Sea.
*The Hall of Humility at Central Campus is the main administrative building of the Planarversity.
All students and faculty are given signet rings to show their status at the Planarversity. They are non-magical, but unique.

There are signficant differences between the signet rings for undergraduates, graduates, and faculty. Each year's design is different as well. In this way, one can distinguish between the years at a glance.

For new undergraduate students beginning in the Year of the Ageless One, their class ring is a thick silver band mounted with a disc of polished black onyx, inset with five small purple amethyst roses encircling the disc.
a Dungeons & Dragons 4E campaign by H.P. Nghiem
Plumes & Parchments
!!!Unaligned Demigod of Growth and Learning

In Solace is a demigod of Growth and Learning, and a [[co-founder|Founders]] of the [[Planarversity]]. Little is known of Solace, as he has few worshipers outside of the Planarversity -- he is almost unknown within the Realms. He is an exarch under the recently returned god [[Amaunator|http://en.wikipedia.org/wiki/Amaunator]], the Lawful Good Greater God of the Sun and Time in the Forgotten Realms.

Shrines to Solace exist on every Planarversity campus. His largest temple is located in The [[Forest of Knowledge]], on the grounds of the Central Campus of [[Sigil Planarversity]], and has attendant priests, known as [[Seekers]]. His holy symbol is an [[everburning seed|Everburning Seeds]].

Students are often found at his shrine during finals and exam periods, offering tokens of obeisance, or praying for a boon before a long journey.

All [[Planarversity]] students receive a Student Passport, a magical chapbook that keeps track of their travels through the planes. Every time a passport bearer travels through a planar portal, the passport marks the passage in its pages. Planarversity faculty use the passport to keep track of their students' comings and goings. Well traveled upperclassmen often flaunt their passports loaded with stamps as signs of prestige.
The Planarversity offers undergraduate and graduate level degree programs.

Undergraduate students are generally in their first through fourth year of education at the Planarversity. Undergrads spend the majority of their time at a primary planar campus, such as [[Waterdeep Planarversity]], to safely pursue their education. Short periods of study abroad occur every year, though only within sanctioned relatively safe regions.

//Undergraduate Players correspond to the Heroic tier (levels 1-10).//

Graduate students are generally in their fifth through seventh year of education at the Planarversity. Grad students share their time across all the campuses, and often go on extended planar travel abroad.

//Graduate Players correspond to the Paragon tier (levels 11-20).//

!!Notable Undergraduates
[[Arkadio Durothil]]
[[Aya Solice]]
[[Cheren of Khaghun]]
[[Jarl Beornson]]
[[Maya Solice]]
[[Tarsith of Solace]]
<<allTags excludeLists>>
<<tabs txtMoreTab "Tags" "All Tags" TabAllTags "Miss" "Missing tiddlers" TabMoreMissing "Orph" "Orphaned tiddlers" TabMoreOrphans "Shad" "Shadowed tiddlers" TabMoreShadowed>>
<<allTags excludeLists [a-z]>>

//A cup of wine, under the flowering trees;
I drink alone, for no friend is near.
Raising my cup I beckon the bright moon,
For her, with my shadow, will make three people.

The moon, alas, is no drinker of wine;
Listless, my shadow creeps about at my side.
Yet with the moon as friend and the shadow as slave
I must make merry before the Spring is spent.

To the songs I sing the moon flickers her beams;
In the dance I weave my shadow tangles and breaks.
While we were sober, three shared the fun;
Now we are drunk, each goes their way.
May we long share our eternal friendship,
And meet at last on the Cloudy River of the sky.
- Drinking Alone by Moonlight, Li Bai//

Tafan is a Lesser Immortal from the [[Celestial Empire|http://forgottenrealms.wikia.com/wiki/Celestial_Empire]] of [[Kara-Tur|http://forgottenrealms.wikia.com/wiki/Kara-Tur]] and is a recent import to western Faerûn, coming in with Shou traders who settled down along the [[Golden Way|http://forgottenrealms.wikia.com/wiki/Golden_Way]]. Tafan is the God of Cookery. In legend, he is depicted as a thin wandering monk, with alcohol on his breath, ever hungry, eternally seeking warm food from the hearths of the people he encounters. It is written that sharing food with Tafan will bless a family to never know hunger forever more. Tafan is also represented as a chubby, laughing baby. Small kitchen shrines to Tafan always depict him in his baby aspect - known as Chifan //(~CHEE-FAHN)//, "God of the Happy Home". Offerings to Chifan are usually a small amount of uncooked rice or round fruits, such as tangerines and pears.

Only a minor god in his homeland, Tafan worship took off in recent years with the increased trade along the Golden Way. As Shou traders headed westward, Shou tastes spread. The domains of the greater Shou gods already had occidental counterparts, but a lack of a counterpart for Tafan created the perfect recipe for the spread of Tafan into the hearts and bellies of Faerûn. Set up a shrine, give a prayer before cooking, and inspirational, delectable dinners would spring into the mind of devotees. It didn't hurt that the church of Tafan's tenets were written into its recipes, and those recipes were shared freely to its followers far and wide. Shou cooking is known for its exotic oriental spices, and its novelty has spread far and wide, even into the finest dining rooms of Waterdhavian nobles - in great part because of the spread of Tafan.

Tafan's itinerant priests are found along the busiest trade routes of the Realms, spreading the faith and the food of Tafan. Many follow in Tafan's footsteps, traveling from town to town, offering their services in the kitchens in exchange for food and lodging. In the wariest of villages, the monk cooks travel door to door, offering [[stone soup|http://en.wikipedia.org/wiki/Stone_soup]] freely. At busy crossroads and large trade ports, they set up restaurants - temples to cuisine - offering food and libations to the weary. Some priests specialize in drink, setting up breweries or building legends as cantankerous drunken monks. A small Shou contingent settled in the South Ward of Waterdeep, originally catering to Shou tradesmen from a few Shou restaurants, but now other traders and even Waterdhavians have begun to come to their tables regularly. The faith and the food of Tafan has made it as as far north as Neverwinter and as far south as Calimport, for the hunger for good food knows no boundaries.

Of note, [[Li Po]], a priest of Tafan teaches several courses at [[Waterdeep Planarversity]], including //The Cuisine of ~Kara-Tur// and //An Introduction to Shou Lung//.
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 9828 $)|
|Date:|$Date: 2009-06-03 21:38:41 +1000 (Wed, 03 Jun 2009) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
See http://mptw.tiddlyspot.com/#TagglyTagging


	parseTagExpr: function(debug) {

		if (this.trim() == "")
			return "(true)";

		var anyLogicOp = /(!|&&|\|\||\(|\))/g;
		var singleLogicOp = /^(!|&&|\|\||\(|\))$/;

		var spaced = this.
			// because square brackets in templates are no good
			// this means you can use [(With Spaces)] instead of [[With Spaces]]
			replace(/\[\(/g," [[").
			replace(/\)\]/g,"]] "). 
			// space things out so we can use readBracketedList. tricky eh?
			replace(anyLogicOp," $1 ");

		var expr = "";

		var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!

		for (var i=0;i<tokens.length;i++)
			if (tokens[i].match(singleLogicOp))
				expr += tokens[i];
				expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think

		if (debug)

		return '('+expr+')';


	getTiddlersByTagExpr: function(tagExpr,sortField) {

		var result = [];

		var expr = tagExpr.parseTagExpr();

		store.forEachTiddler(function(title,tiddler) {
			if (eval(expr))

			sortField = "title";

		result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
		return result;

config.taggly = {

	// for translations
	lingo: {
		labels: {
			asc:        "\u2191", // down arrow
			desc:       "\u2193", // up arrow
			title:      "title",
			modified:   "modified",
			created:    "created",
			show:       "+",
			hide:       "-",
			normal:     "normal",
			group:      "group",
			commas:     "commas",
			sitemap:    "sitemap",
			numCols:    "cols\u00b1", // plus minus sign
			label:      "Tagged as '%0':",
			exprLabel:  "Matching tag expression '%0':",
			excerpts:   "excerpts",
			descr:      "descr",
			slices:     "slices",
			contents:   "contents",
			sliders:    "sliders",
			noexcerpts: "title only",
			noneFound:  "(none)"

		tooltips: {
			title:      "Click to sort by title",
			modified:   "Click to sort by modified date",
			created:    "Click to sort by created date",
			show:       "Click to show tagging list",
			hide:       "Click to hide tagging list",
			normal:     "Click to show a normal ungrouped list",
			group:      "Click to show list grouped by tag",
			sitemap:    "Click to show a sitemap style list",
			commas:     "Click to show a comma separated list",
			numCols:    "Click to change number of columns",
			excerpts:   "Click to show excerpts",
			descr:      "Click to show the description slice",
			slices:     "Click to show all slices",
			contents:   "Click to show entire tiddler contents",
			sliders:    "Click to show tiddler contents in sliders",
			noexcerpts: "Click to show entire title only"

		tooDeepMessage: "* //sitemap too deep...//"

	config: {
		showTaggingCounts: true,
		listOpts: {
			// the first one will be the default
			sortBy:     ["title","modified","created"],
			sortOrder:  ["asc","desc"],
			hideState:  ["show","hide"],
			listMode:   ["normal","group","sitemap","commas"],
			numCols:    ["1","2","3","4","5","6"],
			excerpts:   ["noexcerpts","excerpts","descr","slices","contents","sliders"]
		valuePrefix: "taggly.",
		excludeTags: ["excludeLists","excludeTagging"],
		excerptSize: 50,
		excerptMarker: "/%"+"%/",
		siteMapDepthLimit: 25

	getTagglyOpt: function(title,opt) {
		var val = store.getValue(title,this.config.valuePrefix+opt);
		return val ? val : this.config.listOpts[opt][0];

	setTagglyOpt: function(title,opt,value) {
		// create it silently if it doesn't exist
		if (!store.tiddlerExists(title)) {
			store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");

			// <<tagglyTagging expr:"...">> creates a tiddler to store its display settings
			// Make those tiddlers less noticeable by tagging as excludeSearch and excludeLists
			// Because we don't want to hide real tags, check that they aren't actually tags before doing so
			// Also tag them as tagglyExpression for manageability
			// (contributed by RA)
			if (!store.getTaggedTiddlers(title).length) {

		// if value is default then remove it to save space
		return store.setValue(title, this.config.valuePrefix+opt, value == this.config.listOpts[opt][0] ? null : value);

	getNextValue: function(title,opt) {
		var current = this.getTagglyOpt(title,opt);
		var pos = this.config.listOpts[opt].indexOf(current);
		// supposed to automagically don't let cols cycle up past the number of items
		// currently broken in some situations, eg when using an expression
		// lets fix it later when we rewrite for jquery
		// the columns thing should be jquery table manipulation probably
		var limit = (opt == "numCols" ? store.getTaggedTiddlers(title).length : this.config.listOpts[opt].length);
		var newPos = (pos + 1) % limit;
		return this.config.listOpts[opt][newPos];

	toggleTagglyOpt: function(title,opt) {
		var newVal = this.getNextValue(title,opt);

	createListControl: function(place,title,type) {
		var lingo = config.taggly.lingo;
		var label;
		var tooltip;
		var onclick;

		if ((type == "title" || type == "modified" || type == "created")) {
			// "special" controls. a little tricky. derived from sortOrder and sortBy
			label = lingo.labels[type];
			tooltip = lingo.tooltips[type];

			if (this.getTagglyOpt(title,"sortBy") == type) {
				label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
				onclick = function() {
					return false;
			else {
				onclick = function() {
					return false;
		else {
			// "regular" controls, nice and simple
			label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
			tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
			onclick = function() {
				return false;

		// hide button because commas don't have columns
		if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
			createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");

	makeColumns: function(orig,numCols) {
		var listSize = orig.length;
		var colSize = listSize/numCols;
		var remainder = listSize % numCols;

		var upperColsize = colSize;
		var lowerColsize = colSize;

		if (colSize != Math.floor(colSize)) {
			// it's not an exact fit so..
			upperColsize = Math.floor(colSize) + 1;
			lowerColsize = Math.floor(colSize);

		var output = [];
		var c = 0;
		for (var j=0;j<numCols;j++) {
			var singleCol = [];
			var thisSize = j < remainder ? upperColsize : lowerColsize;
			for (var i=0;i<thisSize;i++) 

		return output;

	drawTable: function(place,columns,theClass) {
		var newTable = createTiddlyElement(place,"table",null,theClass);
		var newTbody = createTiddlyElement(newTable,"tbody");
		var newTr = createTiddlyElement(newTbody,"tr");
		for (var j=0;j<columns.length;j++) {
			var colOutput = "";
			for (var i=0;i<columns[j].length;i++) 
				colOutput += columns[j][i];
			var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
		return newTable;

	createTagglyList: function(place,title,isTagExpr) {
		switch(this.getTagglyOpt(title,"listMode")) {
			case "group":  return this.createTagglyListGrouped(place,title,isTagExpr); break;
			case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
			case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
			case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;

	getTaggingCount: function(title,isTagExpr) {
		// thanks to Doug Edmunds
		if (this.config.showTaggingCounts) {
			var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
			if (tagCount > 0)
				return " ("+tagCount+")";
		return "";

	getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
		return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);

	getExcerpt: function(inTiddlerTitle,title,indent) {
		if (!indent)
			indent = 1;

		var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
		var t = store.getTiddler(title);

		if (t && displayMode == "excerpts") {
			var text = t.text.replace(/\n/," ");
			var marker = text.indexOf(this.config.excerptMarker);
			if (marker != -1) {
				return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
			else if (text.length < this.config.excerptSize) {
				return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
			else {
				return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
		else if (t && displayMode == "contents") {
			return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
		else if (t && displayMode == "sliders") {
			return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
		else if (t && displayMode == "descr") {
			var descr = store.getTiddlerSlice(title,'Description');
			return descr ? " {{excerpt{" + descr  + "}}}" : "";
		else if (t && displayMode == "slices") {
			var result = "";
			var slices = store.calcAllSlices(title);
			for (var s in slices)
				result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
			return result ? "\n{{excerpt excerptIndent{\n" + result  + "}}}" : "";
		return "";

	notHidden: function(t,inTiddler) {
		if (typeof t == "string") 
			t = store.getTiddler(t);
		return (!t || !t.tags.containsAny(this.config.excludeTags) ||
				(inTiddler && this.config.excludeTags.contains(inTiddler)));

	// this is for normal and commas mode
	createTagglyListNormal: function(place,title,useCommas,isTagExpr) {

		var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);

		if (this.getTagglyOpt(title,"sortOrder") == "desc")
			list = list.reverse();

		var output = [];
		var first = true;
		for (var i=0;i<list.length;i++) {
			if (this.notHidden(list[i],title)) {
				var countString = this.getTaggingCount(list[i].title);
				var excerpt = this.getExcerpt(title,list[i].title);
				if (useCommas)
					output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
					output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");

				first = false;

		return this.drawTable(place,
			this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
			useCommas ? "commas" : "normal");

	// this is for the "grouped" mode
	createTagglyListGrouped: function(place,title,isTagExpr) {
		var sortBy = this.getTagglyOpt(title,"sortBy");
		var sortOrder = this.getTagglyOpt(title,"sortOrder");

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")
			list = list.reverse();

		var leftOvers = []
		for (var i=0;i<list.length;i++)

		var allTagsHolder = {};
		for (var i=0;i<list.length;i++) {
			for (var j=0;j<list[i].tags.length;j++) {

				if (list[i].tags[j] != title) { // not this tiddler

					if (this.notHidden(list[i].tags[j],title)) {

						if (!allTagsHolder[list[i].tags[j]])
							allTagsHolder[list[i].tags[j]] = "";

						if (this.notHidden(list[i],title)) {
							allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
										+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";

							leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers


		var allTags = [];
		for (var t in allTagsHolder)

		var sortHelper = function(a,b) {
			if (a == b) return 0;
			if (a < b) return -1;
			return 1;

		allTags.sort(function(a,b) {
			var tidA = store.getTiddler(a);
			var tidB = store.getTiddler(b);
			if (sortBy == "title") return sortHelper(a,b);
			else if (!tidA && !tidB) return 0;
			else if (!tidA) return -1;
			else if (!tidB) return +1;
			else return sortHelper(tidA[sortBy],tidB[sortBy]);

		var leftOverOutput = "";
		for (var i=0;i<leftOvers.length;i++)
			if (this.notHidden(leftOvers[i],title))
				leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";

		var output = [];

		if (sortOrder == "desc")
		else if (leftOverOutput != "")
			// leftovers first...

		for (var i=0;i<allTags.length;i++)
			if (allTagsHolder[allTags[i]] != "")
				output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);

		if (sortOrder == "desc" && leftOverOutput != "")
			// leftovers last...

		return this.drawTable(place,


	// used to build site map
	treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")

		var indent = "";
		for (var j=0;j<depth;j++)
			indent += "*"

		var childOutput = "";

		if (depth > this.config.siteMapDepthLimit)
			childOutput += indent + this.lingo.tooDeepMessage;
			for (var i=0;i<list.length;i++)
				if (list[i].title != title)
					if (this.notHidden(list[i].title,this.config.inTiddler))
						childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);

		if (depth == 0)
			return childOutput;
			return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;

	// this if for the site map mode
	createTagglyListSiteMap: function(place,title,isTagExpr) {
		this.config.inTiddler = title; // nasty. should pass it in to traverse probably
		var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
		return this.drawTable(place,
				this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic

	macros: {
		tagglyTagging: {
			handler: function (place,macroName,params,wikifier,paramString,tiddler) {
				var parsedParams = paramString.parseParams("tag",null,true);
				var refreshContainer = createTiddlyElement(place,"div");

				// do some refresh magic to make it keep the list fresh - thanks Saq

				var tag = getParam(parsedParams,"tag");
				var expr = getParam(parsedParams,"expr");

				if (expr) {
				else {
					if (tag) {
					else {

			refresh: function(place) {
				var title = place.getAttribute("title");
				var isTagExpr = place.getAttribute("isTagExpr") == "true";
				var showEmpty = place.getAttribute("showEmpty") == "true";
				var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
				if (countFound > 0 || showEmpty) {
					var lingo = config.taggly.lingo;
					if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
								isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
						if (countFound == 0 && showEmpty)

	// todo fix these up a bit
	styles: [
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
"	margin-top:0px; padding-top:0.5em; padding-left:2em;",
"	margin-bottom:0px; padding-bottom:0px;",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
"	color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
"	border:0px; padding-left:0.3em;padding-right:0.3em;",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active  {",
"	border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
"  margin-bottom:0.5em; }",
".tagglyTagging .indent1  { margin-left:3em;  }",
".tagglyTagging .indent2  { margin-left:4em;  }",
".tagglyTagging .indent3  { margin-left:5em;  }",
".tagglyTagging .indent4  { margin-left:6em;  }",
".tagglyTagging .indent5  { margin-left:7em;  }",
".tagglyTagging .indent6  { margin-left:8em;  }",
".tagglyTagging .indent7  { margin-left:9em;  }",
".tagglyTagging .indent8  { margin-left:10em; }",
".tagglyTagging .indent9  { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",

	init: function() {
		config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;



By Saq Imtiaz

// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed

config.formatters.unshift( {
	name: "inlinesliders",
	// match: "\\+\\+\\+\\+|\\<slider",
	match: "\\<slider",
	// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
	lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
	handler: function(w) {
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
			var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
			var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
			panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
   onClickSlider : function(e) {
		if(!e) var e = window.event;
		var n = this.nextSibling;
		n.style.display = (n.style.display=="none") ? "block" : "none";
		return false;


<tabs Character>
<tab Background>
!Tarsith of Solace
//[[Drow|http://forgottenrealms.wikia.com/wiki/Drow]], 6', 180 lbs., 22 yrs., smokey black complexion, white topknot, violet eyes//

Tarsith is a private man. He does not speak of how he came to be a student at the Planarversity, or how he became a paladin of [[Solace]]. He is amiable if approached, but does not speak much of himself at all. He prefers to listen first and to act when necessity dictates.

Tarsith is shrewd, but will never hide his face or his faith. When given the chance, he often reminds people that as the insane god [[Cyric|http://forgottenrealms.wikia.com/wiki/Cyric]] did not speak for all humans, [[Lolth|http://forgottenrealms.wikia.com/wiki/Lolth]] does not speak for him. He will freely speak regarding Solace if asked, but church of Solace itself does not proselytize and neither does he.

As a rare drow in Waterdeep, he draws enough unwanted attention. He almost never leaves the campus, and has conceded that strolling across the city by himself will land him in jail or in the harbor, face down. As a paladin of Solace, the relatively new and unknown demigod of Growth and Learning, necessity dictated he prove his faith – by blood at times – on more than one occasion. So far, he has managed to limit his encounters with the Waterdeep Watch to only a few nights imprisoned, each time until an official from the university bailed him out.

There is no love lost between Tarsith and his people, but it is not his crusade to expunge the drow from the surface of ~Abeir-Toril. He judges each person on his or her own merit, but knowing well the general nature of his people, he finds it wiser to simply avoid other drow when possible. The drow goddess Lolth and her followers are not welcome at the Planarversity, but of note, Tarsith is neither the only drow enrolled in the Planarversity, nor the only student clergy of Solace. The double novelty combined with his naturally cool demeanor and striking presence has make him a minor celebrity among his classmates. He ignores the attention as much as possible.

Tarsith has made good friends with [[Mercy]], [[Aya Solice]] and [[Maya Solice]], also outsiders who draw more than their share of attention, because of their blood.
<tab Stats>
Tarsith of Solace, level 1
Drow Paladin
Build: Avenging Paladin

Str 16, Con 10, Dex 12, Int 11, Wis 14, Cha 16.

Str 16, Con 10, Dex 10, Int 11, Wis 14, Cha 14.

AC: 21 Fort: 14 Reflex: 14 Will: 14
HP: 25 Surges: 10 Surge Value: 6

Religion +5, Diplomacy +8, Insight +7, Perception +9

Acrobatics -3, Arcana, Bluff +3, Dungeoneering +2, Endurance -4, Heal +2, History, Intimidate +5, Nature +2, Stealth -1, Streetwise +3, Thievery -3, Athletics -1

Level 1: Alertness

Paladin at-will 1: Holy Strike
Paladin at-will 1: Bolstering Strike
Paladin daily 1: On Pain of Death
Paladin encounter 1: Piercing Smite

Holy Symbol, Black Iron Plate Armor +1, Jousting Shield Heavy Shield (heroic tier), Vanguard Warhammer +1
|!Starting (Bottom) Level|!Middle Level|!Top Level|h
| [img[The Cage - level 1|http://farm4.static.flickr.com/3642/3631709559_829937694b_m.jpg][http://www.flickr.com/photos/perci/3631709559/in/set-72157619822754582/]] | [img[The Cage - level 2|http://farm4.static.flickr.com/3364/3632523464_a95545b52f_m.jpg][http://www.flickr.com/photos/perci/3632523464/in/set-72157619822754582/]] | [img[The Cage - level 3|http://farm4.static.flickr.com/3627/3632523518_0cd173c033_m.jpg][http://www.flickr.com/photos/perci/3632523518/in/set-72157619822754582/]] |
*Fully enclosed cage prevents fleeing/knockouts
*Pit in center of ground floor slows down charging
*10' ladders throughout lead to platforms - ascend/descend at half movement rate
*Walkway runs the perimeter of the cage at the highest level
*Anyone on the middle floor has concealment versus anyone on the ground floor, and full concealment if lying prone.
*Anyone on the top floor has concealment versus anyone on the middle or ground floors, and full concealment if lying prone.
*//Printing out the upper levels and cutting out the black areas will help with determining line of sight between levels//
The Explanar is the Planarversity's student-run broadsheet, published weekly and distributed freely to all Planarversity campuses.

The paper is headquartered at [[Waterdeep Planarversity]] and published in Waterdeep. 
[img[The Labyrinth|http://farm3.static.flickr.com/2596/3662756552_15559a9051.jpg][http://www.flickr.com/photos/perci/3662756552/]]

*5 10 foot square starting locations per team
*Each contestant randomly begins at a different starting location for their team
*Contestants may pick any square in their 10 foot square to begin
*Beginning round two, any contestant beginning their round in or entering one of their team's starting locations is disqualified from the match - note this also includes the starting location in the middle of the map
*Note that contestants can enter the opposing team's starting locations without being disqualified
*//Print out copies of each map and give them to each player to track their movement, to let them move through the labyrinth without knowing anyone else's locations//
|''Version:''|1.0.0 BETA 4 (2009-03-30)|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2009 [[abego Software|http://www.abego-software.de]]|
|''Browser:''|Firefox or better; InternetExplorer 6.0|

Reference a tiddler through an alias (or even through many aliases). E.g. a tiddler "William Shakespeare" may also be referenced as {{{[[Shaxper]]}}}.

When editing a tiddler you may enter alternative names for the tiddler in the "Alias" field (below the tags field), similar to the way you enter tags. You may even specify multiple alias names, separated by spaces. Alias names containing spaces must be written as {{{[[...]]}}}

Also this plugin implements the "Auto Non-Space Alias" feature: for tiddlers with titles containing whitespaces an alias is automatically created that has every whitespace replaced by a dash ("-"). E.g. a tiddler called [[Tiddler with no alias defined]] can also be referenced by [[Tiddler-with-no-alias-defined]].

!Revision history
* v1.0.0 Beta 4 (2009-03-30)
** Bugfix: ToggleLinks does not work when TiddlerAliasPlugin is installed (Thanks to Jonnan West for reporting the bug)
* v1.0.0 Beta 3 (2006-09-23)
** Support "Auto Non-Space Alias" feature: For tiddler with titles containing whitespaces an alias is automatically created that has every whitespace replaced by a dash ("-")
* v1.0.0 Beta 2 (2006-09-22)
** Bugfix: Tiddler is displayed more than once when opened both through title and alias (Thanks to KenGirard for reporting)
* v1.0.0 Beta 1 (2006-09-21)
** Beta 1 release
//		   TiddlerAliasPlugin

// Only install once
if (!version.extensions.TiddlerAliasPlugin) {

version.extensions.TiddlerAliasPlugin = {
	major: 1, minor: 0, revision: 0, beta: 4,
	date: new Date(2009,2,30), 
	source: "http://tiddlywiki.abego-software.de/Beta.html#TiddlerAliasPlugin",
	licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
	copyright: "Copyright (c) abego Software GmbH, 2005-2009 (www.abego-software.de)"

(function() {

window.abegoTiddlerAlias = {
	lingo:  {
		aliasPrompt: "Type alias names (i.e. alternative names for this tiddler) separated with spaces, [[use double square brackets]] if necessary"
	editTemplateExtension: "<div class='editor' macro='edit alias'></div><div class='editorFooter'><span macro='message abegoTiddlerAlias.lingo.aliasPrompt'></span></div>"

var oldFetchTiddler;
var oldSaveTiddler;
var oldDisplayTiddler;

var fWithAutoNonSpaceAlias = true;

function withAutoNonSpaceAlias() {
	return fWithAutoNonSpaceAlias;

function addNonSpaceAlias(map, title) {
	var s = title.replace(/\s/g,"-");
	if (s != title)
		map[s] = title;

function calcAliases() {
	var result = {};
	store.forEachTiddler(function(title,tiddler) {
		var s = store.getValue(tiddler,"alias");
		if (s) {
			var p = s.parseParams("list",null,false,true);
			for(var i=1; i<p.length; i++)
				result[p[i].value] = title;
		if (withAutoNonSpaceAlias())
	return result;

// Returns a map that maps an alias name to the title of the tiddler
abegoTiddlerAlias.getAliases = function() {
	if (!store.aliases)
		store.aliases = calcAliases();
	return store.aliases;

// Returns the title of the tiddler for the given alias.
// When no such alias is defined but a tiddler with that name exists the alias is returned.
// Otherwise null is returned.
abegoTiddlerAlias.getAliasTitle = function(alias) {
	var t = abegoTiddlerAlias.getAliases()[alias];
	return t ? t : (store.fetchTiddler(alias) ? alias : null)

function hasEditTemplateExtension(s) {
	return s.indexOf(abegoTiddlerAlias.editTemplateExtension) >= 0;

function addEditTemplateExtension(s) {
	if (s && !hasEditTemplateExtension(s)) {
		var i = s.lastIndexOf("</div>");
		if (i >= 0)
			return s.slice(0,i+6)+"\n"+abegoTiddlerAlias.editTemplateExtension+s.slice(i+6);
	return null;

function hijackFetchTiddler() {
	oldFetchTiddler = store.fetchTiddler;

	store.fetchTiddler = function(title) {
		var result = oldFetchTiddler.apply(this, arguments);
		if (!result && title) {
			title = abegoTiddlerAlias.getAliases()[title];
			if (title)
				result = oldFetchTiddler.apply(this, [title])
		return result;	

function hijackSaveTiddler() {
	oldSaveTiddler = TiddlyWiki.prototype.saveTiddler;
	TiddlyWiki.prototype.saveTiddler = function() {
		var result = oldSaveTiddler.apply(this, arguments);
		delete store.aliases;				
		return result;	

function hijackDisplayTiddler() {
	oldDisplayTiddler = Story.prototype.displayTiddler;
	Story.prototype.displayTiddler = function(srcElement,title,template,animate,slowly,customFields,toggle,animationSrc) {
		// Ensure that a tiddler is always opened with its "original" title (not an alias)
		var tiddler = store.fetchTiddler(title);
		if (tiddler) 
			title = tiddler.title;
		return oldDisplayTiddler.apply(this, [srcElement,title,template,animate,slowly,customFields,toggle,animationSrc]);

function modifyEditTemplate() {
	// The shadow tiddler
	var s = addEditTemplateExtension(config.shadowTiddlers["EditTemplate"]);
	if (s) 
		config.shadowTiddlers["EditTemplate"] = s;
	// The "real" tiddler (if defined)
	var t = store.getTiddler("EditTemplate");
    if (t && !hasEditTemplateExtension(t.text))

// Requires store is defined.
function doHijacking() {

// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag. 
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
	var oldRestartFunc = restart;
	window.restart = function() {
} else

// To support the access through the "message" macro
config.abegoTiddlerAlias = abegoTiddlerAlias;
} // of "install only once"

!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.


|Author|Lyall Pearce|
|License|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|Overrides|store.getSaver().externalizeTiddler(), store.getTiddler() and store.getTiddlerText()|
|Description|Encrypt/Decrypt Tiddlers with a Password key|

* Tag a tiddler with Encrypt(prompt)
** Consider the 'prompt' something to help you remember the password with. If multiple tiddlers can be encrypted with the same 'prompt' and you will only be asked for the password once.
* Upon save, the Tiddler will be encrypted and the tag replaced with Decrypt(prompt).
** Failure to encrypt (by not entering a password) will leave the tiddler unencrypted and will leave the Encrypt(prompt) tag in place. This means that the next time you save, you will be asked for the password again.
** To have multiple tiddlers use the same password - simply use the same 'prompt'.
** Tiddlers that are encrypted may be automatically tagged 'excludeSearch' as there is no point in searching encrypted data - this is configurable by an option - you still may want to search the titles of encrypted tiddlers
** Tiddlers that are encrypted may be automatically tagged 'excludeLists', if you have them encrypted, you may also want to keep them 'hidden' - this is configurable by an option.
** Automatic removal of excludeLists and excludeSearch tags is performed, if the above two options are set, only if these two tags are the last 2 tags for a tiddler, if they are positioned somewhere else in the tags list, they will be left in place, meaning that the decrypted tiddler will not be searchable and/or will not appear in lists.
** Encrypted tiddlers are stored as displayable hex, to keep things visibly tidy, should you display an encrypted tiddler. There is nothing worse than seeing a pile of gobbledy gook on your screen. Additionally, the encrypted data is easily cut/paste/emailed if displayed in hex form.
* Tiddlers are decrypted only if you click the decrypt button or the decryptAll button, not when you load the TiddlyWiki
** If you don't display a tiddler, you won't have the option to decrypt it (unless you use the {{{<<EncryptionDecryptAll>>}}} macro)
** Tiddlers will re-encrypt automatically on save.
** Decryption of Tiddlers does not make your TiddlyWiki 'dirty' - you will not be asked to save if you leave the page.
* Errors are reported via diagnostic messages.
** Empty passwords, on save, will result in the tiddler being saved unencrypted - this should only occur with new tiddlers, decrypted tiddlers or with tiddlers who have had their 'prompt' tag changed.
** Encrypted tiddlers know if they are decrypted successfully - failure to decrypt a tiddler will ''not'' lose your data.
** Editing of an encrypted (that has not been unencrypted) tiddler will result in loss of that tiddler as the SHA1 checksums will no longer match, upon decryption. To this end, it is best that you do not check the option. You can, however edit an encrypted tiddler tag list - just do ''not'' change the tiddler contents.
** To change the password on a Tiddler, change the Encrypt('prompt') tag to a new prompt value, after decrypting the tiddler.
** You can edit the tags of an encrypted tiddler, so long as you do not edit the text.
** To change the password for all tiddlers of a particular prompt, use the {{{<<EncryptionChangePassword ["button text" ["tooltip text" ["prompt string" ["accessKey"]]]]>>}}} macro.
** To decrypt all tiddlers of a particular "prompt string", use the {{{<<EncryptionDecryptAll ["button text" ["tooltip text" ["prompt string" ["accessKey"]]]]>>}}} macro - this will make tiddlers encrypted with "prompt string" searchable - or prompt for all 'prompt strings', if none is supplied.
Useful Buttons: 
<<EncryptionChangePassword>> - Change passwords of encrypted tiddlers.
<<EncryptionDecryptAll>> - Decrypt ALL tiddlers - enables searching contents of encrypted tiddlers.
<<option chkExcludeEncryptedFromSearch>> - If set, Encrypted Tiddlers are excluded from searching by tagging with excludeSearch. If Clear, excludeSearch is not added and it is also removed from existing Encrypted Tiddlers only if it is the last Tag. Searching of Encrypted Tiddlers is only meaningful for the Title and Tags.
<<option chkExcludeEncryptedFromLists>> - If set, Encrypted Tiddlers are excluded from lists by tagging with excludeLists. If Clear, excludeLists is not added and it is also removed from existing Encrypted Tiddlers only if it is the last Tag. Preventing encrypted tiddlers from appearing in lists effectively hides them.
<<option chkShowDecryptButtonInContent>> - If set, Encrypted Tiddlers content is replaced by <<EncryptionDecryptThis>> button. This has consequences, in the current version as, if you edit the tiddler without decrypting it, you lose the contents.
!!!!!Revision History
* 3.2.1 - Returned the <<EncryptionDecryptThis>> button as an option.
* 3.2.0 - Ditched the 'Decrypt' button showing up in the tiddler contents if the tiddler is encrypted. It caused too much pain if you edit the tiddler without decrypting it - you lost your data as it was replaced by a Decrypt Macro call!  Additionally, a 'decrypt' button will now appear in the toolbar, just before the edit button, if the tiddler is encrypted. This button only appears if using core TiddlyWiki version 2.4 or above.
* 3.1.1 - Obscure bug whereby if an encrypted tiddler was a certain length, it would refuse to decrypt.
* 3.1.0 - When creating a new Encrypt(prompt) tiddler and you have not previously decrypted a tiddler with the same prompt, on save, you will be prompted for the password to encrypt the tiddler. Prior to encrypting, an attempt to decrypt all other tiddlers with the same prompt, is performed. If any tiddler fails to decrypt, the save is aborted - this is so you don't accidentally have 2 (or more!) passwords for the same prompt. Either you enter the correct password, change the prompt string and try re-saving or you cancel (and the tiddler is saved unencrypted).
* 3.0.1 - Allow Enter to be used for password entry, rather than having to press the OK button.
* 3.0.0 - Major revamp internally to support entry of passwords using forms such that passwords are no longer visible on entry. Completely backward compatible with old encrypted tiddlers. No more using the javascript prompt() function.
!!!!!Additional work

version.extensions.TiddlerEncryptionPlugin = {major: 3, minor: 2, revision: 1, date: new Date(2008,10,26)};

// where I cache the passwords - for want of a better place.
config.encryptionPasswords = new Array();
config.encryptionReEnterPasswords = false;

if(config.options.chkExcludeEncryptedFromSearch == undefined) config.options.chkExcludeEncryptedFromSearch = false;
if(config.options.chkExcludeEncryptedFromLists == undefined) config.options.chkExcludeEncryptedFromLists = false;
if(config.options.chkShowDecryptButtonInContent == undefined) config.options.chkShowDecryptButtonInContent = false;

config.macros.EncryptionChangePassword = {};
config.macros.EncryptionChangePassword.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    var theButton = createTiddlyButton(place,
				       (params[0] && params[0].length > 0) ? params[0] : "Change Passwords", 
				       (params[1] && params[1].length > 0) ? params[1] : "Change Passwords" + (params[2] ? " for prompt "+params[2] : ""), 
    if(params[2] && params[2].length > 0) {
	theButton.setAttribute("promptString", params[2]);

config.macros.EncryptionDecryptAll = {};
config.macros.EncryptionDecryptAll.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    var theButton = createTiddlyButton(place,
				       (params[0] && params[0].length > 0) ? params[0] : "Decrypt All", 
				       (params[1] && params[1].length > 0) ? params[1] : "Decrypt All Tiddlers" + ((params[2] && params[2].length > 0) ? " for prompt "+params[2] : " for a given 'prompt string'"), 
    if(params[2] && params[2].length > 0) {
	theButton.setAttribute("promptString", params[2]);

config.macros.EncryptionDecryptThis = {};
config.macros.EncryptionDecryptThis.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    var theButton = createTiddlyButton(place,
				       (params[0] && params[0].length > 0) ? params[0] : "Decrypt", 
				       (params[1] && params[1].length > 0) ? params[1] : "Decrypt this Tiddler", 
    if(params[2] && params[2].length > 0) {
	theButton.setAttribute("theTiddler", params[2]);
// toolbar button to decrypt tiddlers.
config.commands.decryptThis = {
  text: "decrypt",
  tooltip: "Decrypt this tiddler",
  isEnabled : function(tiddler) {
	// Only show decrypt button if tiddler is tagged as Decrypt(
	if(tiddler.tags.join().indexOf('Decrypt(') == -1)  {
	    return false;
	} else {
	    return true;
  handler: function(event, src, title) {
	return false; 
// core version 2.4 or above get a 'decrypt' button in the toolbar.
if(config.shadowTiddlers && config.shadowTiddlers.ToolbarCommands  && config.shadowTiddlers.ToolbarCommands.indexOf('decryptThis') == -1) {
    // put our toolbar button in before the edit button.
    // won't work if editTiddler is not the default item (prefixed with plus)
    config.shadowTiddlers.ToolbarCommands.replace(/\+editTiddler/,'decryptThis +editTiddler');

// Called by the EncryptionChangePassword macro/button
// Also invoked by the callback for password entry
function onClickEncryptionChangePassword(eventObject) {
    var promptString;
    if(!promptString && this.getAttribute) {
	promptString = this.getAttribute("promptString");
    // I do call this function directly
    if(!promptString && typeof(eventObject) == "string") {
	promptString = eventObject;
    if(!promptString) {
	promptString = prompt("Enter 'prompt string' to change password for:","");
    if(!promptString) {
    if(! config.encryptionPasswords[promptString]) {
	var changePasswordContext = {changePasswordPromptString: promptString,
				     callbackFunction: MyChangePasswordPromptCallback_TiddlerEncryptionPlugin};
	// Callback function will re-invoke this function

    // Decrypt ALL tiddlers for that prompt
    // Now ditch the cached password, this will force the re-request for the new password, on save.
    displayMessage("Save TiddlyWiki to set new password for '"+promptString+"'");
    config.encryptionPasswords[promptString] = null;
    // mark store as dirty so a save will be requrested.
// Called by the password entry form when the user clicks 'OK' button.
function MyChangePasswordPromptCallback_TiddlerEncryptionPlugin(context) {
    config.encryptionPasswords[context.passwordPrompt] = context.password;
// Called by the EncryptionDecryptThis macro/button
function onClickEncryptionDecryptThis() {
    var theTiddler = this.getAttribute("theTiddler");
    if(!theTiddler) {

function encryptionGetAndDecryptTiddler(title) {
    config.encryptionReEnterPasswords = true;
    try {
	theTiddler = store.getTiddler(title);
	config.encryptionReEnterPasswords = false;
    } catch (e) {
	if(e == "DecryptionFailed") {
	    displayMessage("Decryption failed");
    } // catch

// called by the EncryptionDecryptAlll macro/button
// Also called by the callback after the user clicks 'OK' button on the password entry form
function onClickEncryptionDecryptAll(eventObject) {
    var promptString;
    if(!promptString && this.getAttribute) {
	promptString = this.getAttribute("promptString");
    // I do call this function directly
    if(!promptString && typeof(eventObject) == "string") {
	promptString = eventObject;
    if(!promptString) {
	promptString = "";

    // Loop through all tiddlers, looking to see if there are any Decrypt(promptString) tagged tiddlers
    // If there are, check to see if their password has been cached.
    // If not, ask for the first one that is missing, that we find
    // the call back function will store that password then invoke this function again, 
    // which will repeat the whole process. If we find all passwords have been cached
    // then we will finally do the decryptAll functionality, which will then
    // be able to decrypt all the required tiddlers, without prompting.
    // We have to do this whole rigmarole because we are using a 'form' to enter the password
    // rather than the 'prompt()' function - which shows the value of the password.
    var tagToSearchFor="Decrypt("+promptString;
    config.encryptionReEnterPasswords = true; 
    var promptGenerated = false;
    store.forEachTiddler(function(store,tiddler) {
	    // Note, there is no way to stop the forEachTiddler iterations
	    if(!promptGenerated && tiddler && tiddler.tags) {
		for(var ix=0; ix<tiddler.tags.length && !promptGenerated; ix++) {
		    if(tiddler.tags[ix].indexOf(tagToSearchFor) == 0) {
			var tag = tiddler.tags[ix];
			var lastBracket=tag.lastIndexOf(")");
			if(lastBracket >= 0) {
			    // Ok, tagged with Encrypt(passwordPrompt)
			    // extract the passwordPrompt name
			    var passwordPromptString=tag.substring(8,lastBracket);
			    if(!config.encryptionPasswords[passwordPromptString]) {
				// no password cached, prompt and cache it, rather than decryptAll
				// callback from prompting form will resume decryptAll attempt.
				var decryptAllContext = {decryptAllPromptString: promptString,
							 callbackFunction: MyDecryptAllPromptCallback_TiddlerEncryptionPlugin};
				promptGenerated = true;
			    } // if(!config.encryptionPasswords
			} // if(lastBracket
		    } // if(tiddler.tags[ix]..
		} // for
	    } // if
	}); // store.forEachTiddler
    // If we get here, all passwords have been cached.
    if(!promptGenerated) {
	config.encryptionReEnterPasswords = false;
	// Now do the decrypt all functionality
	try {
	    store.forEachTiddler(function(store,tiddler) {
		    // Note, there is no way to stop the forEachTiddler iterations
		    if(tiddler && tiddler.tags) {
			for(var ix=0; ix<tiddler.tags.length; ix++) {
			    if(tiddler.tags[ix].indexOf(tagToSearchFor) == 0) {
				try {
				} catch (e) {
				    displayMessage("Decryption of '"+tiddler.title+"' failed.");
				    // throw e;
			    } // if(tiddler.tags
			} // for
		    } // if
		}); // store.forEachTiddler
	    displayMessage("All tiddlers" + (promptString != "" ? " for '"+promptString+"'" : "") + " have been decrypted");
	} catch (e) {
	    if(e == "DecryptionFailed") {
	} // catch

function MyDecryptAllPromptCallback_TiddlerEncryptionPlugin(context) {
    config.encryptionPasswords[context.passwordPrompt] = context.password;
    // restart the decryptAll process again after the user has entered a password.

saveChanges_TiddlerEncryptionPlugin = saveChanges;
saveChanges = function(onlyIfDirty,tiddlers) {
    // Loop through all tiddlers, looking to see if there are any Encrypt(string) tagged tiddlers
    // If there are, check to see if their password has been cached.
    // If not, ask for the first one that is missing, that we find
    // the call back function will store that password then invoke this function again, 
    // which will repeat the whole process. If we find all passwords have been cached
    // then we will finally call the original saveChanges() function, which will then
    // be able to save the tiddlers.
    // We have to do this whole rigmarole because we are using a 'form' to enter the password
    // rather than the 'prompt()' function - which shows the value of the password.
    config.encryptionReEnterPasswords = true; 
    var promptGenerated = false;
    store.forEachTiddler(function(store,tiddler) {
	    if(!promptGenerated && tiddler && tiddler.tags) {
		for(var ix=0; ix<tiddler.tags.length && !promptGenerated; ix++) {
		    if(tiddler.tags[ix].indexOf("Encrypt(") == 0) {
			var tag = tiddler.tags[ix];
			var lastBracket=tag.lastIndexOf(")");
			if(lastBracket >= 0) {
			    // Ok, tagged with Encrypt(passwordPrompt)
			    // extract the passwordPrompt name
			    var passwordPrompt=tag.substring(8,lastBracket);
			    if(!config.encryptionPasswords[passwordPrompt]) {
				// no password cached, prompt and cache it, rather than save
				var saveContext = {onlyIfDirty: onlyIfDirty, 
						   tiddlers: tiddlers, 
				                   callbackFunction: MySavePromptCallback_TiddlerEncryptionPlugin};
				promptGenerated = true;
			    } // if(!config.encryptionPasswords
			} // if(lastBracket
		    } // if(tiddler.tags[ix]..
		} // for
	    } // if
	}); // store.forEachTiddler
    // If we get here, all passwords have been cached.
    if(!promptGenerated) {
	config.encryptionReEnterPasswords = false;

function MySavePromptCallback_TiddlerEncryptionPlugin(context) {
    config.encryptionPasswords[context.passwordPrompt] = context.password;
    // validate the password entered by attempting to decrypt all tiddlers
    // with the same encryption prompt string.

    // restart the save process again
    saveChanges(context.onlyIfDirty, context.tiddlers);

store.getSaver().externalizeTiddler_TiddlerEncryptionPlugin = store.getSaver().externalizeTiddler;
store.getSaver().externalizeTiddler = function(store, tiddler) {
    // Ok, got the tiddler, track down the passwordPrompt in the tags.
    // track down the Encrypt(passwordPrompt) tag
    if(tiddler && tiddler.tags) {
	for(var g=0; g<tiddler.tags.length; g++) {
	    var tag = tiddler.tags[g];
	    if(tag.indexOf("Encrypt(") == 0) {
		var lastBracket=tag.lastIndexOf(")");
		if(lastBracket >= 0) {
		    // Ok, tagged with Encrypt(passwordPrompt)
		    // extract the passwordPrompt name
		    var passwordPrompt=tag.substring(8,lastBracket);
		    // Ok, Encrypt this tiddler!
		    var decryptedSHA1 = Crypto.hexSha1Str(tiddler.text);
		    var password =  GetAndSetPasswordForPrompt_TiddlerEncryptionPlugin(passwordPrompt);
		    if(password) {
			var encryptedText = TEAencrypt(tiddler.text, password);
			encryptedText = StringToHext_TiddlerEncryptionPlugin(encryptedText);
			tiddler.text = "Encrypted("+decryptedSHA1+")\n"+encryptedText;
			// Replace the Tag with the Decrypt() tag
			// let the store know it's dirty
			store.setDirty(tiddler.title, true);
			// prevent searches on encrypted tiddlers, still nice to search on title though.
			if(config.options.chkExcludeEncryptedFromSearch == true) {
			// prevent lists of encrypted tiddlers
			if(config.options.chkExcludeEncryptedFromLists == true) {
		    } else {
			// do not encrypt - no password entered
		} // if (lastBracket...
	    } // if(tag.indexOf(...
	} // for(var g=0;...
    } // if(tiddler.tags...
    // Then, finally, do the save by calling the function we override.

    return store.getSaver().externalizeTiddler_TiddlerEncryptionPlugin(store, tiddler);

function CheckTiddlerForDecryption_TiddlerEncryptionPlugin(tiddler) {
    if(tiddler && tiddler.tags) {
	for(var g=0; g<tiddler.tags.length; g++) {
	    var tag = tiddler.tags[g];
	    if(tag.indexOf("Decrypt(") == 0) {
		var lastBracket=tag.lastIndexOf(")");
		if(lastBracket >= 0) {
		    if(tiddler.text.substr(0,10) == "Encrypted(") {
			var closingSHA1Bracket = tiddler.text.indexOf(")");
			var decryptedSHA1 = tiddler.text.substring(10, closingSHA1Bracket);
			// Ok, tagged with Decrypt(passwordPrompt)
			// extract the passwordPrompt name
			var passwordPrompt=tag.substring(8,lastBracket);
			// Ok, Decrypt this tiddler!
			var decryptedText = tiddler.text.substr(closingSHA1Bracket+2);
			decryptedText = HexToString_TiddlerEncryptionPlugin(decryptedText);
                        // prompt("Decryption request for Tiddler '"+tiddler.title+"'");
			var password = GetAndSetPasswordForPromptToDecrypt_TiddlerEncryptionPlugin(passwordPrompt);
			if(password) {
			    decryptedText = TEAdecrypt(decryptedText, password );
			    var thisDecryptedSHA1 = Crypto.hexSha1Str(decryptedText);
			    if(decryptedSHA1 == thisDecryptedSHA1) {
				tiddler.text = decryptedText;
				// Replace the Tag with the Encrypt() tag
				if(tiddler.tags[tiddler.tags.length-1] == 'excludeLists') {
				    // Remove exclude lists only if it's the last entry
				    // as it's automatically put there by encryption
				if(tiddler.tags[tiddler.tags.length-1] == 'excludeSearch') {
				    // Remove exclude search only if it's the last entry
				    // as it's automatically put there by encryption
			    } else {
				// Did not decrypt, discard the password from the cache
				config.encryptionPasswords[passwordPrompt] = null;
				config.encryptionReEnterPasswords = false;
				throw "DecryptionFailed";
			} else {
			    // no password supplied, dont bother trying to decrypt
			    config.encryptionReEnterPasswords = false;
			    throw "DecryptionFailed";
		    } else {
			// Tagged as encrypted but not expected format, just leave it unchanged
		    break; // out of for loop
		} // if (lastBracket...
	    } // if(tag.indexOf(...
	} // for(var g=0;...
    } // if (tiddler && tags)
    return tiddler;

store.getTiddler_TiddlerEncryptionPlugin = store.getTiddler;
store.getTiddler = function(title) {
    var tiddler = store.getTiddler_TiddlerEncryptionPlugin(title);
    if(tiddler) { // shadow tiddlers are not expected to be encrypted.
	try {
	    return CheckTiddlerForDecryption_TiddlerEncryptionPlugin(tiddler);
	} catch (e) {
	    if (config.options.chkShowDecryptButtonInContent == true) {
		if(e == "DecryptionFailed") {
		    var tiddler = store.getTiddler("DecryptionFailed");
		    if(!tiddler) {
			tiddler = new Tiddler();
				    "<<EncryptionDecryptThis \"Decrypt\" \"Decrypt this tiddler\" \""+title+"\">>",
		    return tiddler;
		} // if(e)
	} // catch
    } // if(tiddler) {
    return null;

store.getTiddlerText_TiddlerEncryptionPlugin = store.getTiddlerText;
store.getTiddlerText = function(title,defaultText) {
    // Simply retrieve the tiddler, normally, if it requires decryption, it will be decrypted
    var decryptedTiddler = store.getTiddler(title);
    if(decryptedTiddler) {
	return decryptedTiddler.text;
    //Ok, rather than duplicate all the core code, the above code should fail if we reach here
    // let the core code take over.
    return  store.getTiddlerText_TiddlerEncryptionPlugin(title,defaultText);

// Given a prompt, search our cache to see if we have already entered the password.
// Can return null if the user enters nothing.
function MyPrompt_TiddlerEncryptionPlugin(promptString,defaultValue,context) {
    if(!context) {
	context = {};
    context.passwordPrompt = promptString;
    PasswordPrompt.prompt(MyPromptCallback_TiddlerEncryptionPlugin, context);

function MyPromptCallback_TiddlerEncryptionPlugin(context) {
    if(context.callbackFunction) {
    } else {
	config.encryptionPasswords[context.passwordPrompt] = context.password;

function GetAndSetPasswordForPrompt_TiddlerEncryptionPlugin(promptString) {
    if(!config.encryptionPasswords[promptString]) {
	config.encryptionPasswords[promptString] = MyPrompt_TiddlerEncryptionPlugin(promptString, "");
    return config.encryptionPasswords[promptString]; // may be null, prompt can be cancelled.

function GetAndSetPasswordForPromptToDecrypt_TiddlerEncryptionPlugin(promptString) {
    if(config.encryptionReEnterPasswords) {
	return GetAndSetPasswordForPrompt_TiddlerEncryptionPlugin(promptString);
    } else {
	return config.encryptionPasswords[promptString];

// Make the encrypted tiddlies look a little more presentable.
function StringToHext_TiddlerEncryptionPlugin(theString) {
    var theResult = "";
    for(var i=0; i<theString.length; i++) {
	var theHex = theString.charCodeAt(i).toString(16);
	if(theHex.length<2) {
	    theResult += "0"+theHex;
	} else {
	    theResult += theHex;
	if(i && i % 32 == 0)
	    theResult += "\n";
    return theResult;

function HexToString_TiddlerEncryptionPlugin(theString) {
    var theResult = "";
    for(var i=0; i<theString.length; i+=2) {
	if(theString.charAt(i) == "\n") {
	    i--;	// cause us to skip over the newline and resume
	theResult += String.fromCharCode(parseInt(theString.substr(i, 2),16));
    return theResult;
// Heavily leveraged from http://trac.tiddlywiki.org/browser/Trunk/contributors/SaqImtiaz/verticals/Hesperian/PasswordPromptPlugin.js  Revision 5635
PasswordPrompt ={
  prompt : function(callback,context){
	if (!context) {
	    context = {};
	var box = createTiddlyElement(document.getElementById("contentWrapper"),'div','passwordPromptBox');
	box.innerHTML = store.getTiddlerText('PasswordPromptTemplate');
	box.style.position = 'absolute';
	document.getElementById('promptDisplayField').value = context.passwordPrompt;
	var passwordInputField = document.getElementById('passwordInputField');
	passwordInputField.onkeyup = function(ev) {
	    var e = ev || window.event;
	    if(e.keyCode == 10 || e.keyCode == 13) { // Enter
		PasswordPrompt.submit(callback, context);
	document.getElementById('passwordPromptSubmitBtn').onclick = function(){PasswordPrompt.submit(callback,context);};
	document.getElementById('passwordPromptCancelBtn').onclick = function(){PasswordPrompt.cancel(callback,context);};
  center : function(el){
	var size = this.getsize(el);
	el.style.left = (Math.round(findWindowWidth()/2) - (size.width /2) + findScrollX())+'px';
	el.style.top = (Math.round(findWindowHeight()/2) - (size.height /2) + findScrollY())+'px';
  getsize : function (el){
	var x = {};
	x.width = el.offsetWidth || el.style.pixelWidth;
	x.height = el.offsetHeight || el.style.pixelHeight;
	return x;
  submit : function(cb,context){
	context.passwordPrompt = document.getElementById('promptDisplayField').value;
	context.password = document.getElementById('passwordInputField').value;
	var box = document.getElementById('passwordPromptBox');
	return false;

  cancel : function(cb,context){
	var box = document.getElementById('passwordPromptBox');
	return false;
  setStyles : function(){
	    "#passwordPromptBox dd.submit {margin-left:0; font-weight: bold; margin-top:1em;}\n"+
	    "#passwordPromptBox dd.submit .button {padding:0.5em 1em; border:1px solid #ccc;}\n"+
	    "#passwordPromptBox dt.heading {margin-bottom:0.5em; font-size:1.2em;}\n"+
	    "#passwordPromptBox {border:1px solid #ccc;background-color: #eee;padding:1em 2em;}",'passwordPromptStyles');
  template : '<form action="" onsubmit="return false;" id="passwordPromptForm">\n'+
  '    <dl>\n'+
  '        <dt class="heading">Please enter the password:</dt>\n'+
  '        <dt>Prompt:</dt>\n'+
  '        <dd><input type="text" readonly id="promptDisplayField" class="display"/></dd>\n'+
  '        <dt>Password:</dt>\n'+
  '        <dd><input type="password" tabindex="1" class="input" id="passwordInputField"/></dd>\n'+
  '        <dd class="submit">\n'+
  '            <a tabindex="2" href="javascript:;" class="button" id="passwordPromptSubmitBtn">OK</a>\n'+
  '            <a tabindex="3" href="javascript:;" class="button" id="passwordPromptCancelBtn">Cancel</a>\n'+
  '        </dd>\n'+
  '    </dl>\n'+
  init : function(){
	config.shadowTiddlers.PasswordPromptTemplate = this.template;

// http://www.movable-type.co.uk/scripts/tea-block.html
// TEAencrypt: Use Corrected Block TEA to encrypt plaintext using password
//             (note plaintext & password must be strings not string objects)
// Return encrypted text as string
function TEAencrypt(plaintext, password)
    if (plaintext.length == 0) return('');  // nothing to encrypt
    // 'escape' plaintext so chars outside ISO-8859-1 work in single-byte packing, but keep
    // spaces as spaces (not '%20') so encrypted text doesn't grow too long (quick & dirty)
    var asciitext = escape(plaintext).replace(/%20/g,' ');
    var v = strToLongs(asciitext);  // convert string to array of longs
    if (v.length <= 1) v[1] = 0;  // algorithm doesn't work for n<2 so fudge by adding a null
    var k = strToLongs(password.slice(0,16));  // simply convert first 16 chars of password as key
    var n = v.length;

    var z = v[n-1], y = v[0], delta = 0x9E3779B9;
    var mx, e, q = Math.floor(6 + 52/n), sum = 0;

    while (q-- > 0) {  // 6 + 52/n operations gives between 6 & 32 mixes on each word
        sum += delta;
        e = sum>>>2 & 3;
        for (var p = 0; p < n; p++) {
            y = v[(p+1)%n];
            mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z);
            z = v[p] += mx;

    var ciphertext = longsToStr(v);

    return escCtrlCh(ciphertext);

// TEAdecrypt: Use Corrected Block TEA to decrypt ciphertext using password
function TEAdecrypt(ciphertext, password)
    if (ciphertext.length == 0) return('');
    var v = strToLongs(unescCtrlCh(ciphertext));
    var k = strToLongs(password.slice(0,16)); 
    var n = v.length;

    var z = v[n-1], y = v[0], delta = 0x9E3779B9;
    var mx, e, q = Math.floor(6 + 52/n), sum = q*delta;

    while (sum != 0) {
        e = sum>>>2 & 3;
        for (var p = n-1; p >= 0; p--) {
            z = v[p>0 ? p-1 : n-1];
            mx = (z>>>5 ^ y<<2) + (y>>>3 ^ z<<4) ^ (sum^y) + (k[p&3 ^ e] ^ z);
            y = v[p] -= mx;
        sum -= delta;

    var plaintext = longsToStr(v);

    // strip trailing null chars resulting from filling 4-char blocks:
    plaintext = plaintext.replace(/\0+$/,'');

    return unescape(plaintext);

// supporting functions

function strToLongs(s) {  // convert string to array of longs, each containing 4 chars
    // note chars must be within ISO-8859-1 (with Unicode code-point < 256) to fit 4/long
    var l = new Array(Math.ceil(s.length/4));
    for (var i=0; i<l.length; i++) {
        // note little-endian encoding - endianness is irrelevant as long as 
        // it is the same in longsToStr() 
        l[i] = s.charCodeAt(i*4) + (s.charCodeAt(i*4+1)<<8) + 
               (s.charCodeAt(i*4+2)<<16) + (s.charCodeAt(i*4+3)<<24);
    return l;  // note running off the end of the string generates nulls since 
}              // bitwise operators treat NaN as 0

function longsToStr(l) {  // convert array of longs back to string
    var a = new Array(l.length);
    for (var i=0; i<l.length; i++) {
        a[i] = String.fromCharCode(l[i] & 0xFF, l[i]>>>8 & 0xFF, 
                                   l[i]>>>16 & 0xFF, l[i]>>>24 & 0xFF);
    return a.join('');  // use Array.join() rather than repeated string appends for efficiency

function escCtrlCh(str) {  // escape control chars etc which might cause problems with encrypted texts
    return str.replace(/[\0\t\n\v\f\r\xa0'"!]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });

function unescCtrlCh(str) {  // unescape potentially problematic nulls and control characters
    return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });

|''Date:''|Jan 1, 2006|
|''Version:''|1.0 beta|
|''Author:''|Saq Imtiaz|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Based on:''|DC3.LightBox<br>Light Box Gone Wild <br>Ibox|

config.macros.imagebox ={};
config.macros.imagebox.handler = function (place,macroName,params,wikifier,paramString,tiddler)
    var e = place.lastChild;
    e.onclick = function(){TiddlyLightBox.initBox('image',this,params[1],params[2],params[0]);return false;};

config.macros.divbox ={};
config.macros.divbox.handler = function (place,macroName,params,wikifier,paramString,tiddler)
    if (params[0]!=".")
        createTiddlyButton(place,params[0],params[0],function(){TiddlyLightBox.initBox('html',params[1],params[3],params[4],params[2]);return false;});
        var e = place.lastChild;
        e.onclick = function(){TiddlyLightBox.initBox('html',params[1],params[3],params[4],params[2]);return false;};

config.macros.tiddlerbox ={}
config.macros.tiddlerbox.handler = function (place,macroName,params,wikifier,paramString,tiddler)
    return false;


if (!window.TiddlyLightBox)
    window.TiddlyLightBox = {};
    var loadingImage = "indicator.gif";
    window.TiddlyLightBox =
    _curBox: null, // [sentinel]

    lightBoxHtml : '<div id="lightBoxOverlay" onclick="TiddlyLightBox.hideBox()" style="display:none"></div><div id="lightboxprogress" style="display:none;"><img src=\''+loadingImage+'\' alt=\'loading\' style="width:128px;height:128px;"></div><div class="lightBox" id="lightBox" style="display:none"><div id="lightBoxContent"></div><div id="lightBoxTitle">This is a title</div><div id="lightBoxClose"><a href:"#" onclick="TiddlyLightBox.hideBox();return false;">Click to close</a></div></div>',

    createBoxWrapper : function()
        var wrapper = createTiddlyElement(document.getElementsByTagName("body")[0],"div","tiddlyLightBoxWrapper");
        wrapper.innerHTML = this.lightBoxHtml;

    initBox : function(contentType,url,w,h,text)
        if (this._curBox)
        this._curBox = true;
        if (contentType == 'image')
        else if (contentType == 'html')
        return false;
    sizeTheBox : function(contentType,w,h)
        var box = document.getElementById("lightBoxContent");
        if (w && isNaN(parseInt(w)))
        else if (w ||h || contentType == 'html')
            box.style.width = w? w+ "px" : "450px";
            box.style.height = h? h+ "px" : "280px";
            if (contentType=='image')
                setStylesheet("#lightBoxContent img{height:100%;width:100%;}","lightBoxImageSizeHack");

    showProgress : function()
        var progress = document.getElementById("lightboxprogress");
    hideProgress: function()
        var progress = document.getElementById("lightboxprogress");

    //this function lifted from Lightbox Gone Wild
    hideSelects: function(visibility)
        var selects = document.getElementsByTagName('select');
        for(i = 0; i < selects.length; i++)
            selects[i].style.visibility = visibility;

    showBg: function()
        var overlay = document.getElementById('lightBoxOverlay');
        if (config.browser.isIE)
            overlay.style.height = Math.max(document.documentElement.scrollHeight,document.documentElement.offsetHeight);
            overlay.style.width = document.documentElement.scrollWidth;
        overlay.style.display = 'block';

    showImage: function (url,text)
        imgPreloader = new Image();
        imgPreloader.onload = function ()
            var lb = document.getElementById("lightBoxContent");
            lb.innerHTML = "<img src="+url+">";
            lb.onclick = function(){TiddlyLightBox.hideBox();return false;};
        imgPreloader.src = url;
    showHtml : function(theID,text)
        var lb = document.getElementById("lightBoxContent");
        if (theID.indexOf("tiddler:")==-1)
             lb.innerHTML = document.getElementById(theID).innerHTML;
        lb.style.overflow = "auto";

    posBox: function(text)
       var lb = document.getElementById("lightBox");
       lb.style.display = "";
       lb.style.visibilty = "hidden";
       lb.style.position = "absolute";
       if(!TiddlyLightBox._curBox) return;
       lb.style.visibility = "visible";
       lb.style.display = "block";

     setTitle: function(text)
        document.getElementById("lightBoxTitle").innerHTML=  (text==undefined)? '': text;

    _center: function(lb)
       var lbSize = new TiddlyLightBox.getElementSize(lb);
       lb.style.left = (Math.round(findWindowWidth()/2) - (lbSize.width /2) + findScrollX())+'px';
       lb.style.top = (Math.round(findWindowHeight()/2) - (lbSize.height /2) + findScrollY())+'px';

    //this function lifted from Ibox
    getElementSize : function(elem)
       this.width = elem.offsetWidth || elem.style.pixelWidth;
       this.height = elem.offsetHeight || elem.style.pixelHeight;

     hideBox: function()
         document.getElementById("tiddlyLightBoxWrapper").innerHTML= this.lightBoxHtml;
         this._curBox = null;
         return false;


Story.prototype.findContainingTiddler = function(e)
    while(e && (!hasClass(e,"tiddler") || !e.getAttribute("tiddler")))
        e = e.parentNode;

config.shadowTiddlers.TiddlyLightBoxStyles="/*{{{*/\n#lightBoxOverlay {\n position:absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 90; \n background-color: #000;\n -moz-opacity: 0.75;\n opacity: .75;\n filter: alpha(opacity=75);\n}\n#lightBoxOverlay[id]{ \n position: fixed;\n}\n\n#lightboxprogress { \n margin:0;padding:0;\n position: absolute;\n z-index:95;\n}\n\ndiv.lightBox {\n background: #fff;\n color: #fff;\n border: 4px solid #525252;\npadding:20px 20px 25px 20px; position:absolute; z-index:99;\n}\n\n#lightBoxClose {text-align:right; color:#000; font-size:1.0em; position:absolute; bottom:6px; right:20px;}\n#lightBoxClose a{color:#666; border-bottom:1px solid #666;cursor:pointer;}\n#lightBoxClose a:hover {color:#111; border-bottom:1px solid #666; cursor:pointer; background:transparent;}\n\n#lightBoxContent {border:1px solid #525252;color:#000; background:#fff;}\n#lightBox .tiddler {background:#fff;}\n\n#lightBoxContent img {border:0;margin:0;padding:0;display:block;cursor:pointer;}\n\n#lightBoxTitle {padding:0px; font-weight:bold; position:absolute; left:20px;bottom:6px; font-size:1.1em; color:#000;}\n\n/*}}}*/";

|Created by|SaqImtiaz|
Provides a button for toggling visibility of the SideBar. You can choose whether the SideBar should initially be hidden or displayed.

<<toggleSideBar "Toggle Sidebar">>

{{{<<toggleSideBar>>}}} <<toggleSideBar>>
additional options:
{{{<<toggleSideBar label tooltip show/hide>>}}} where:
label = custom label for the button,
tooltip = custom tooltip for the button,
show/hide = use one or the other, determines whether the sidebar is shown at first or not.
(default is to show the sidebar)

You can add it to your tiddler toolbar, your MainMenu, or where you like really.
If you are using a horizontal MainMenu and want the button to be right aligned, put the following in your StyleSheet:
{{{ .HideSideBarButton {float:right;} }}}

*23-07-06: version 1.0: completely rewritten, now works with custom stylesheets too, and easier to customize start behaviour. 
*20-07-06: version 0.11
*27-04-06: version 0.1: working.


         styleHide :  "#sidebar { display: none;}\n"+"#contentWrapper #displayArea { margin-right: 1em;}\n"+"",
         styleShow : " ",
         arrow1: "«",
         arrow2: "»"

config.macros.toggleSideBar.handler=function (place,macroName,params,wikifier,paramString,tiddler)
          var tooltip= params[1]||'toggle sidebar';
          var mode = (params[2] && params[2]=="hide")? "hide":"show";
          var arrow = (mode == "hide")? this.settings.arrow1:this.settings.arrow2;
          var label= (params[0]&&params[0]!='.')?params[0]+" "+arrow:arrow;
          var theBtn = createTiddlyButton(place,label,tooltip,this.onToggleSideBar,"button HideSideBarButton");
          if (mode == "hide")

config.macros.toggleSideBar.onToggleSideBar = function(){
          var sidebar = document.getElementById("sidebar");
          var settings = config.macros.toggleSideBar.settings;
          if (sidebar.getAttribute("toggle")=='hide')
              this.firstChild.data= (this.firstChild.data).replace(settings.arrow1,settings.arrow2);
               this.firstChild.data= (this.firstChild.data).replace(settings.arrow2,settings.arrow1);

     return false;

setStylesheet(".HideSideBarButton .button {font-weight:bold; padding: 0 5px;}\n","ToggleSideBarButtonStyles");

|Description:|Makes a checkbox which toggles a tag in a tiddler|
|Version:|3.1.0 ($Rev: 4907 $)|
|Date:|$Date: 2008-05-13 03:15:46 +1000 (Tue, 13 May 2008) $|
|Author:|Simon Baird <simon.baird@gmail.com>|
{{{<<toggleTag }}}//{{{TagName TiddlerName LabelText}}}//{{{>>}}}
* TagName - the tag to be toggled, default value "checked"
* TiddlerName - the tiddler to toggle the tag in, default value the current tiddler
* LabelText - the text (gets wikified) to put next to the check box, default value is '{{{[[TagName]]}}}' or '{{{[[TagName]] [[TiddlerName]]}}}'
(If a parameter is '.' then the default will be used)
* TouchMod flag - if non empty then touch the tiddlers mod date. Note, can set config.toggleTagAlwaysTouchModDate to always touch mod date
|{{{<<toggleTag>>}}}|Toggles the default tag (checked) in this tiddler|<<toggleTag>>|
|{{{<<toggleTag TagName>>}}}|Toggles the TagName tag in this tiddler|<<toggleTag TagName>>|
|{{{<<toggleTag TagName TiddlerName>>}}}|Toggles the TagName tag in the TiddlerName tiddler|<<toggleTag TagName TiddlerName>>|
|{{{<<toggleTag TagName TiddlerName 'click me'>>}}}|Same but with custom label|<<toggleTag TagName TiddlerName 'click me'>>|
|{{{<<toggleTag . . 'click me'>>}}}|dot means use default value|<<toggleTag . . 'click me'>>|
* If TiddlerName doesn't exist it will be silently created
* Set label to '-' to specify no label
* See also http://mgtd-alpha.tiddlyspot.com/#ToggleTag2
!!Known issues
* Doesn't smoothly handle the case where you toggle a tag in a tiddler that is current open for editing
* Should convert to use named params

if (config.toggleTagAlwaysTouchModDate == undefined) config.toggleTagAlwaysTouchModDate = false;


	toggleTag: {

		createIfRequired: true,
		shortLabel: "[[%0]]",
		longLabel: "[[%0]] [[%1]]",

		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			var tiddlerTitle = tiddler ? tiddler.title : '';
			var tag   = (params[0] && params[0] != '.') ? params[0] : "checked";
			var title = (params[1] && params[1] != '.') ? params[1] : tiddlerTitle;
			var defaultLabel = (title == tiddlerTitle ? this.shortLabel : this.longLabel);
			var label = (params[2] && params[2] != '.') ? params[2] : defaultLabel;
			var touchMod = (params[3] && params[3] != '.') ? params[3] : "";
			label = (label == '-' ? '' : label); // dash means no label
			var theTiddler = (title == tiddlerTitle ? tiddler : store.getTiddler(title));
			var cb = createTiddlyCheckbox(place, label.format([tag,title]), theTiddler && theTiddler.isTagged(tag), function(e) {
				if (!store.tiddlerExists(title)) {
					if (config.macros.toggleTag.createIfRequired) {
						var content = store.getTiddlerText(title); // just in case it's a shadow
						store.saveTiddler(title,title,content?content:"",config.options.txtUserName,new Date(),null);
						return false;
				if ((touchMod != "" || config.toggleTagAlwaysTouchModDate) && theTiddler)
						theTiddler.modified = new Date();
				return true;


<tabs Character>
<tab Background>
//5'8", 110 lbs., 16 yrs., dark tan skin, shoulder length dark blue hair, spellplagued blue eyes//

Often sick, afraid of being alone, afraid of crowded spaces, distrusts people, doesn't talk much.
Grew up in Downshadow (Waterdeep).
Born with a spellscar - blue tattoos underneath his hair that look like eyes that slowly move on his scalp. If one looks closely, one will notice the eyes staring back.
Orphan, treated as "special," traded, used, abused by gangs.
"Saved" by Solace at an early age.
Accidentally killed a lot of people when he lost control.
Was going to hang, but saved by the Church of Solace on the condition that they take full responsibility.

<tab Stats>
Torn, level 1
Human Invoker
Build: Preserving Invoker
Student of the Plague: Flamespeed
Divine Covenant: Covenant of Preservation

Str 10, Con 15, Dex 8, Int 14, Wis 18, Cha 11.

Str 10, Con 15, Dex 8, Int 14, Wis 16, Cha 11.

AC: 17 Fort: 16 Reflex: 16 Will: 18
HP: 25 Surges: 8 Surge Value: 6

Endurance +6, Religion +7, Insight +9, Streetwise +5, Intimidate +5

Acrobatics -2, Arcana +2, Bluff, Diplomacy, Dungeoneering +4, Heal +4, History +2, Nature +4, Perception +4, Stealth -2, Thievery -2, Athletics -1

Invoker: Ritual Caster
Human: Student of the Plague
Level 1: Timely Respite

Invoker at-will 1: Divine Bolts
Invoker at-will 1: Avenging Light
Bonus ~At-Will Power: Grasping Shards
Invoker daily 1: Summon Angel of Fire
Invoker encounter 1: Blades of Astral Fire

Ritual Book, Defensive Staff +1, Amulet of Mental Resolve +1, Delver's Chainmail +1
Hand of Fate, Purify Water
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'esper';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");

// create some shadow tiddler content

 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."

 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"

 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"

 "tiddlyspot password:",
 "<<option pasUploadPassword>>",

As can be imagined, tuition to the Planarversity can be expensive, even for minor landed lords, and usually well beyond the means of most people. Scholarships and financial aid have been established in order to allow the school to bring in the best and brightest, despite their economic means.

Present annual undergraduate fees run approximately 300 gold per quarter, including tuition, room and board, due at the beginning of each quarter. A standard four-year undergraduate term amounts to four quarters per year, 4,800 gold in total.

Financial aid options include employment within the school, paid internships, and outright merit based scholarships. 

//Players are expected to pay for the tuition fees, either through specific backgrounds, feats, or in character methods, e.g. scholarship, employment, financial aid, etc. Level one characters enrolled in the Planarversity are assumed to have paid the first quarter fees. Please determine tuition arrangements with the DM.//
What? Haen't ye heard o' the twelve kings o' gold? They lie in their darkest court, richer than the gods, biding eternity in the deeps.

//Twelve kings of gold
Set sail across the sea
From elven lands of old
Gifts to humanity

Poured from dwarfen fires
Forged for mighty thrones
Magical burning pyres
Turned men to golden stones

Bright kings of wisdom
Would bring prosperity
Give counsel to new kingdoms
And crowns for eternity

But gods weren't told
Or given their just fee
So claimed yon kings of gold
Their due beneath the sea//
Uniforms are required per the [[Code of Conduct]] for all students and faculty during school hours on Planarversity campuses. Anyone not in uniform will be stopped by the Order of the Rose who regularly patrol the campuses. Exceptions for classes or activities which require different uniforms (e.g. sparring armor, swimsuits) are allowed. In those instances, uniforms also exist.

//In practice, uniform enforcement varies per campus. Having once been a student, [[Preceptor Solice|Elerrielle Solice]] at [[Waterdeep Planarversity]] is very strict, whereas at [[Shadowfell Planarversity]], [[Preceptor Akioh|Akioh the Autumn Lord]] doesn't care in the slightest. In his eyes, uniforms are only needed when you don't know what your men look like. He knows every single one of them, by look and by smell… Students with special circumstances, such as the new undergraduate [[Nar'talas]], have received exemption from the full uniform requirements.//

Two sets of uniforms and laundering are provided free of charge by the school. Additional clothing is for sale from the college bookstores.

!!!Male Uniforms
*Black peacoat or black cloak in winter (optional)
*White tunic
*Black pants (or armor)
*Black boots (or armor)
*Epaulet ribbon
*[[Signet ring|Signet Rings]]

!!!Female Uniforms
*Black bolero jacket, short or long sleeve (optional)
*Red overcoat and/or red cloak in winter (optional)
*White blouse, short or long sleeve
*Knee-length rose skirt, or black riding pants in winter (or armor)
*Knee-length white hose
*Black shoes or boots (or armor)
*Epaulet ribbon
*[[Signet ring|Signet Rings]]


Epaulet ribbons are part of the uniform and must be worn to designate the College attended.

*[[College of Cultural Studies]] (//CCS//) – Silver
*[[College of Natural Studies]] (//CNS//) – Purple
*[[College of Cosmology]] (//CC//) – Yellow
*[[College of Martial Science]] (//CMS//) – Vermillion
*[[Academy of Magic]] (//Solice//) – Emerald Green
*[[Divine and Primal Studies]] (//DPS//) – Cobalt
*[[Graduate School of Planar Studies]] (//Espers//) – Gold
*[[Order of the Rose]] – Rose

Wearing epaulet ribbons of another college is a violation of the [[Code of Conduct]]. It is common practice for female students to wear ribbons and bows around their necks or in their hair the same color of their epaulet ribbons.
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 27/06/2009 06:32:52 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . | ok |
| 28/06/2009 23:34:25 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 28/06/2009 23:36:20 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 28/06/2009 23:38:04 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . | ok | ok |
| 28/06/2009 23:52:43 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 01/07/2009 15:09:34 | Esper | [[Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm|file:///C:/Users/percival/Desktop/Plumes%20&%20Parchments%20-%20a%20Dungeons%20&%20Dragons%204E%20campaign%20by%20H.P.%20Nghiem.htm]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 04/07/2009 03:57:07 | Esper | [[/|http://esper.tiddlyspot.com/]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 03/08/2010 01:28:01 | Esper | [[/|http://esper.tiddlyspot.com/]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
| 18/07/2011 03:17:29 | Esper | [[/|http://esper.tiddlyspot.com/]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . | failed |
| 18/07/2011 03:17:46 | Esper | [[/|http://esper.tiddlyspot.com/]] | [[store.cgi|http://esper.tiddlyspot.com/store.cgi]] | . | [[index.html | http://esper.tiddlyspot.com/index.html]] | . |
|''Description:''|Save to web a TiddlyWiki|
|''Date:''|Feb 24, 2008|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
version.extensions.UploadPlugin = {
	major: 4, minor: 1, revision: 3,
	date: new Date("Feb 24, 2008"),
	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	coreVersion: '2.2.0'

// Environment

if (!window.bidix) window.bidix = {}; // bidix namespace
bidix.debugMode = false;	// true to activate both in Plugin and UploadService
// Upload Macro

config.macros.upload = {
// default values
	defaultBackupDir: '',	//no backup
	defaultStoreScript: "store.php",
	defaultToFilename: "index.html",
	defaultUploadDir: ".",
	authenticateUser: true	// UploadService Authenticate User
config.macros.upload.label = {
	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
	saveLabel: "save to web", 
	saveToDisk: "save to disk",
	uploadLabel: "upload"	

config.macros.upload.messages = {
	noStoreUrl: "No store URL in parmeters or options",
	usernameOrPasswordMissing: "Username or password missing"

config.macros.upload.handler = function(place,macroName,params) {
	if (readOnly)
	var label;
	if (document.location.toString().substr(0,4) == "http") 
		label = this.label.saveLabel;
		label = this.label.uploadLabel;
	var prompt;
	if (params[0]) {
		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0], 
			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
	} else {
		prompt = this.label.promptOption;
	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);

config.macros.upload.action = function(params)
		// for missing macro parameter set value from options
		if (!params) params = {};
		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
		var username = params[4] ? params[4] : config.options.txtUploadUserName;
		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter	
		// for still missing parameter set default value
		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http")) 
			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
		if (storeUrl.substr(0,4) != "http")
			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
		if (!toFilename)
			toFilename = bidix.basename(window.location.toString());
		if (!toFilename)
			toFilename = config.macros.upload.defaultToFilename;
		if (!uploadDir)
			uploadDir = config.macros.upload.defaultUploadDir;
		if (!backupDir)
			backupDir = config.macros.upload.defaultBackupDir;
		// report error if still missing
		if (!storeUrl) {
			return false;
		if (config.macros.upload.authenticateUser && (!username || !password)) {
			return false;
		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password); 
		return false; 

config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir) 
	if (!storeUrl)
		return null;
		var dest = bidix.dirname(storeUrl);
		if (uploadDir && uploadDir != '.')
			dest = dest + '/' + uploadDir;
		dest = dest + '/' + toFilename;
	return dest;

// uploadOptions Macro

config.macros.uploadOptions = {
	handler: function(place,macroName,params) {
		var wizard = new Wizard();
		var markList = wizard.getElement("markList");
		var listWrapper = document.createElement("div");
		var uploadCaption;
		if (document.location.toString().substr(0,4) == "http") 
			uploadCaption = config.macros.upload.label.saveLabel;
			uploadCaption = config.macros.upload.label.uploadLabel;
				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption, 
					onClick: config.macros.upload.action},
				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}
	options: [
	refreshOptions: function(listWrapper) {
		var opts = [];
		for(i=0; i<this.options.length; i++) {
			var opt = {};
			opt.option = "";
			n = this.options[i];
			opt.name = n;
			opt.lowlight = !config.optionsDesc[n];
			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
		for(n=0; n<opts.length; n++) {
			var type = opts[n].name.substr(0,3);
			var h = config.macros.option.types[type];
			if (h && h.create) {
	onCancel: function(e)
		return false;
	wizardTitle: "Upload with options",
	step1Title: "These options are saved in cookies in your browser",
	step1Html: "<input type='hidden' name='markList'></input><br>",
	cancelButton: "Cancel",
	cancelButtonPrompt: "Cancel prompt",
	listViewTemplate: {
		columns: [
			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
			{name: 'Option', field: 'option', title: "Option", type: 'String'},
			{name: 'Name', field: 'name', title: "Name", type: 'String'}
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'} 

// upload functions

if (!bidix.upload) bidix.upload = {};

if (!bidix.upload.messages) bidix.upload.messages = {
	//from saving
	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
	backupSaved: "Backup saved",
	backupFailed: "Failed to upload backup file",
	rssSaved: "RSS feed uploaded",
	rssFailed: "Failed to upload RSS feed file",
	emptySaved: "Empty template uploaded",
	emptyFailed: "Failed to upload empty template file",
	mainSaved: "Main TiddlyWiki file uploaded",
	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
	//specific upload
	loadOriginalHttpPostError: "Can't get original file",
	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
	storePhpNotFound: "The store script '%0' was not found."

bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
	var callback = function(status,uploadParams,original,url,xhr) {
		if (!status) {
		if (bidix.debugMode) 
		// Locate the storeArea div's 
		var posDiv = locateStoreArea(original);
		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
	if(onlyIfDirty && !store.isDirty())
	// save on localdisk ?
	if (document.location.toString().substr(0,4) == "file") {
		var path = document.location.toString();
		var localPath = getLocalPath(path);
	// get original
	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
	var originalPath = document.location.toString();
	// If url is a directory : add index.html
	if (originalPath.charAt(originalPath.length-1) == "/")
		originalPath = originalPath + "index.html";
	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
	var log = new bidix.UploadLog();
	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
	if (bidix.debugMode) 
		alert("about to execute Http - GET on "+originalPath);
	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
	if (typeof r == "string")
	return r;

bidix.upload.uploadRss = function(uploadParams,original,posDiv) 
	var callback = function(status,params,responseText,url,xhr) {
		if(status) {
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
		} else {
	// do uploadRss
	if(config.options.chkGenerateAnRssFeed) {
		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
		var rssString = generateRss();
		// no UnicodeToUTF8 conversion needed when location is "file" !!!
		if (document.location.toString().substr(0,4) != "file")
			rssString = convertUnicodeToUTF8(rssString);	
	} else {

bidix.upload.uploadMain = function(uploadParams,original,posDiv) 
	var callback = function(status,params,responseText,url,xhr) {
		var log = new bidix.UploadLog();
		if(status) {
			// if backupDir specified
			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
		} else {
	// do uploadMain
	var revised = bidix.upload.updateOriginal(original,posDiv);

bidix.upload.httpUpload = function(uploadParams,data,callback,params)
	var localCallback = function(status,params,responseText,url,xhr) {
		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
		if (xhr.status == 404)
		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
			if (responseText.indexOf("Debug mode") >= 0 )
				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
		} else if (responseText.charAt(0) != '0') 
		if (responseText.charAt(0) != '0')
			status = null;
	// do httpUpload
	var boundary = "---------------------------"+"AaB03x";	
	var uploadFormName = "UploadPlugin";
	// compose headers data
	var sheader = "";
	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
	sheader += uploadFormName +"\"\r\n\r\n";
	sheader += "backupDir="+uploadParams[3] +
				";user=" + uploadParams[4] +
				";password=" + uploadParams[5] +
				";uploaddir=" + uploadParams[2];
	if (bidix.debugMode)
		sheader += ";debug=1";
	sheader += ";;\r\n"; 
	sheader += "\r\n" + "--" + boundary + "\r\n";
	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
	sheader += "Content-Length: " + data.length + "\r\n\r\n";
	// compose trailer data
	var strailer = new String();
	strailer = "\r\n--" + boundary + "--\r\n";
	data = sheader + data + strailer;
	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
	if (typeof r == "string")
	return r;

// same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
bidix.upload.updateOriginal = function(original, posDiv)
	if (!posDiv)
		posDiv = locateStoreArea(original);
	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
				store.allTiddlersAsHtml() + "\n" +
	var newSiteTitle = getPageTitle().htmlEncode();
	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
	return revised;

// UploadLog
// config.options.chkUploadLog :
//		false : no logging
//		true : logging
// config.options.txtUploadLogMaxLine :
//		-1 : no limit
//      0 :  no Log lines but UploadLog is still in place
//		n :  the last n lines are only kept
//		NaN : no limit (-1)

bidix.UploadLog = function() {
	if (!config.options.chkUploadLog) 
		return; // this.tiddler = null
	this.tiddler = store.getTiddler("UploadLog");
	if (!this.tiddler) {
		this.tiddler = new Tiddler();
		this.tiddler.title = "UploadLog";
		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
		this.tiddler.created = new Date();
		this.tiddler.modifier = config.options.txtUserName;
		this.tiddler.modified = new Date();
	return this;

bidix.UploadLog.prototype.addText = function(text) {
	if (!this.tiddler)
	// retrieve maxLine when we need it
	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
	if (isNaN(maxLine))
		maxLine = -1;
	// add text
	if (maxLine != 0) 
		this.tiddler.text = this.tiddler.text + text;
	// Trunck to maxLine
	if (maxLine >= 0) {
		var textArray = this.tiddler.text.split('\n');
		if (textArray.length > maxLine + 1)
			this.tiddler.text = textArray.join('\n');		
	// update tiddler fields
	this.tiddler.modifier = config.options.txtUserName;
	this.tiddler.modified = new Date();
	// refresh and notifiy for immediate update
	store.notify(this.tiddler.title, true);

bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
	if (!this.tiddler)
	var now = new Date();
	var text = "\n| ";
	var filename = bidix.basename(document.location.toString());
	if (!filename) filename = '/';
	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
	text += config.options.txtUserName + " | ";
	text += "[["+filename+"|"+location + "]] |";
	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
	text += uploadDir + " | ";
	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
	text += backupDir + " |";

bidix.UploadLog.prototype.endUpload = function(status) {
	if (!this.tiddler)
	this.addText(" "+status+" |");

// Utilities

bidix.checkPlugin = function(plugin, major, minor, revision) {
	var ext = version.extensions[plugin];
	if (!
		(ext  && 
			((ext.major > major) || 
			((ext.major == major) && (ext.minor > minor))  ||
			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
			// write error in PluginManager
			if (pluginInfo)
				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"

bidix.dirname = function(filePath) {
	if (!filePath) 
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(0, lastpos);
	} else {
		return filePath.substring(0, filePath.lastIndexOf("\\"));

bidix.basename = function(filePath) {
	if (!filePath) 
	var lastpos;
	if ((lastpos = filePath.lastIndexOf("#")) != -1) 
		filePath = filePath.substring(0, lastpos);
	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
		return filePath.substring(lastpos + 1);
	} else
		return filePath.substring(filePath.lastIndexOf("\\")+1);

bidix.initOption = function(name,value) {
	if (!config.options[name])
		config.options[name] = value;

// Initializations

// require PasswordOptionPlugin 1.0.1 or better
bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

// styleSheet
setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
	txtUploadUserName: "Upload Username",
	pasUploadPassword: "Upload Password",
	chkUploadLog: "do Logging in UploadLog (default: true)",
	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"

// Options Initializations

// Backstage
	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}


//Human, 6'3", 190 lbs., shaven blond head, light blue eyes//

Volker, level 1
Human, Monk
Build: Centered Breath Monk
Monastic Tradition: Centered Breath

Str 10, Con 10, Dex 20, Int 10, Wis 14, Cha 9.

Str 10, Con 10, Dex 18, Int 10, Wis 14, Cha 9.

AC: 17 Fort: 13 Reflex: 17 Will: 14
HP: 26 Surges: 7 Surge Value: 6

Perception +7, Stealth +10, Endurance +5, Athletics +5, Acrobatics +10

Arcana, Bluff -1, Diplomacy -1, Dungeoneering +2, Heal +2, History, Insight +2, Intimidate -1, Nature +2, Religion, Streetwise -1, Thievery +5

Human: Improved Initiative
Level 1: Stubborn Survivor

Monk at-will 1: Five Storms
Monk at-will 1: Dragon's Tail
Bonus ~At-Will Power: Crane's Wings
Monk daily 1: Masterful Spiral
Monk encounter 1: Open the Gate of Battle

Cloth Armor (Basic Clothing), Adventurer's Kit, Bloodclaw Monk Unarmed Strike +1, Lifedrinker Monk Unarmed Strike +1

Waterdeep Planarversity, formerly known as the Solice Academy, is located in [[Waterdeep]], the largest city on the continent of Toril, on the planet of Abeir-Toril, better known in Lore as the Forgotten Realms.

The Waterdeep Planarversity is the largest campus of the [[Planarversity]], and was founded by the late sun elf archmage, [[Esperifiel Solice]], co-founder of the Planarversity.

The Solice estates had been home to a small, private school of magic. After the death of [[Mystra]], Solice rededicated the school to rekindling the lost flame of magic from the Realms, and took great effort into expanding the Solice Academy, bringing in more teachers and more students. His efforts were the foundation for the future Planarversity.

The western cliffs of Waterdeep overlooking the sea are home to the school campus, a large rocky estate along the Cliffride in the exclusive Castle Ward. Of note, the school neighbors famed Blackstaff Tower and the bardic college New Olamn, and lies far above the ruins of the legendendary dungeon of Undermountain.

The campus is home to the [[College of Natural Studies]] and the [[College of Cosmology]].

[[Elerrielle Solice]], human granddaughter of Esperifiel Solice and daughter of [[Grazielle Solice]], serves as the current Preceptor of Waterdeep Planarversity.
|''Version:''|2.1.3 (2008-04-16)|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2008 [[abego Software|http://www.abego-software.de]]|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; ~InternetExplorer 6.0|
!About YourSearch
YourSearch gives you a bunch of new features to simplify and speed up your daily searches in TiddlyWiki. It seamlessly integrates into the standard TiddlyWiki search: just start typing into the 'search' field and explore!

For more information see [[Help|YourSearch Help]].
This plugin requires TiddlyWiki 2.1. 
Check the [[archive|http://tiddlywiki.abego-software.de/archive]] for ~YourSearchPlugins supporting older versions of TiddlyWiki.
!Source Code
This plugin's source code is compressed (and hidden). Use this [[link|http://tiddlywiki.abego-software.de/archive/YourSearchPlugin/Plugin-YourSearch-src.2.1.3.js]] to get the readable source code.
if(!version.extensions.YourSearchPlugin){version.extensions.YourSearchPlugin={major:2,minor:1,revision:3,source:"http://tiddlywiki.abego-software.de/#YourSearchPlugin",licence:"[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",copyright:"Copyright (c) abego Software GmbH, 2005-2008 (www.abego-software.de)"};if(!window.abego){window.abego={};}
if(!Array.forEach){Array.forEach=function(_1,_2,_3){for(var i=0,len=_1.length;i<len;i++){_2.call(_3,_1[i],i,_1);}};Array.prototype.forEach=function(_5,_6){for(var i=0,len=this.length;i<len;i++){_5.call(_6,this[i],i,this);}};}
abego.toInt=function(s,_9){if(!s){return _9;}
var n=parseInt(s);return(n==NaN)?_9:n;};abego.createEllipsis=function(_b){var e=createTiddlyElement(_b,"span");e.innerHTML="&hellip;";};abego.shallowCopy=function(_d){if(!_d){return _d;}
var _e={};for(var n in _d){_e[n]=_d[n];}
return _e;};abego.copyOptions=function(_10){return!_10?{}:abego.shallowCopy(_10);};abego.countStrings=function(_11,s){if(!s){return 0;}
var len=s.length;var n=0;var _15=0;while(1){var i=_11.indexOf(s,_15);if(i<0){return n;}
return n;};abego.getBracedText=function(_17,_18,_19){if(!_18){_18=0;}
var re=/\{([^\}]*)\}/gm;re.lastIndex=_18;var m=re.exec(_17);if(m){var s=m[1];var _1d=abego.countStrings(s,"{");if(!_1d){if(_19){_19.lastIndex=re.lastIndex;}
return s;}
var len=_17.length;for(var i=re.lastIndex;i<len&&_1d;i++){var c=_17.charAt(i);if(c=="{"){_1d++;}else{if(c=="}"){_1d--;}}}
return _17.substring(m.index+1,i-1);}}};abego.select=function(_21,_22,_23,_24){if(!_24){_24=[];}
_21.forEach(function(t){if(_22.call(_23,t)){_24.push(t);}});return _24;};abego.consumeEvent=function(e){if(e.stopPropagation){e.stopPropagation();}
var _29=_27;if(!_28.textIsRegExp){_29=_27.escapeRegExp();if(_28.fullWordMatch){_29="\\b"+_29+"\\b";}}
var _2a=new RegExp(_29,"m"+(_28.caseSensitive?"":"i"));this.tester=new abego.MultiFieldRegExpTester(_2a,_28.fields,_28.withExtendedFields);};abego.TiddlerFilterTerm.prototype.test=function(_2b){return this.tester.test(_2b);};abego.parseNewTiddlerCommandLine=function(s){var m=/(.*?)\.(?:\s+|$)([^#]*)(#.*)?/.exec(s);if(!m){m=/([^#]*)()(#.*)?/.exec(s);}
if(m){var r;if(m[3]){var s2=m[3].replace(/#/g,"");r=s2.parseParams("tag");}else{r=[[]];}
var _30=m[2]?m[2].trim():"";r.push({name:"text",value:_30});r[0].text=[_30];return{title:m[1].trim(),params:r};}else{return{title:s.trim(),params:[[]]};}};abego.parseTiddlerFilterTerm=function(_31,_32,_33){var re=/\s*(?:(?:\{([^\}]*)\})|(?:(=)|([#%!])|(?:(\w+)\s*\:(?!\/\/))|(?:(?:("(?:(?:\\")|[^"])+")|(?:\/((?:(?:\\\/)|[^\/])+)\/)|(\w+\:\/\/[^\s]+)|([^\s\)\-\"]+)))))/mg;var _35={"!":"title","%":"text","#":"tags"};var _36={};var _37;re.lastIndex=_32;while(1){var i=re.lastIndex;var m=re.exec(_31);if(!m||m.index!=i){throw"Word or String literal expected";}
if(m[1]){var _3a={};var _3b=abego.getBracedText(_31,0,_3a);if(!_3b){throw"Invalid {...} syntax";}
var f=Function("tiddler","return ("+_3b+");");return{func:f,lastIndex:_3a.lastIndex,markRE:null};}
if(m[2]){_37=true;}else{if(m[3]){_36[_35[m[3]]]=1;}else{if(m[4]){_36[m[4]]=1;}else{var _3d=m[6];var _3e=m[5]?window.eval(m[5]):m[6]?m[6]:m[7]?m[7]:m[8];var _33=abego.copyOptions(_33);_33.fullWordMatch=_37;_33.textIsRegExp=_3d;var _3f=[];for(var n in _36){_3f.push(n);}
var _41=new abego.TiddlerFilterTerm(_3e,_33);var _42=_3d?_3e:_3e.escapeRegExp();if(_42&&_37){_42="\\b"+_42+"\\b";}
return{func:function(_43){return _41.test(_43);},lastIndex:re.lastIndex,markRE:_42?"(?:"+_42+")":null};}}}}};abego.BoolExp=function(s,_45,_46){this.s=s;var _47=_46&&_46.defaultOperationIs_OR;var _48=/\s*(?:(\-|not)|(\())/gi;var _49=/\s*\)/g;var _4a=/\s*(?:(and|\&\&)|(or|\|\|))/gi;var _4b=/\s*[^\)\s]/g;var _4c=/\s*(\-|not)?(\s*\()?/gi;var _4d;var _4e=function(_4f){_4c.lastIndex=_4f;var m=_4c.exec(s);var _51;var _52;if(m&&m.index==_4f){_4f+=m[0].length;_51=m[1];if(m[2]){var e=_4d(_4f);_49.lastIndex=e.lastIndex;if(!_49.exec(s)){throw"Missing ')'";}
if(_51){_52.func=(function(f){return function(_55){return!f(_55);};})(_52.func);_52.markRE=null;}
return _52;};_4d=function(_56){var _57=_4e(_56);while(1){var l=_57.lastIndex;_4a.lastIndex=l;var m=_4a.exec(s);var _5a;var _5b;if(m&&m.index==l){_5a=!m[1];_5b=_4e(_4a.lastIndex);}else{try{_5b=_4e(l);}
catch(e){return _57;}
_57.func=(function(_5c,_5d,_5e){return _5e?function(_5f){return _5c(_5f)||_5d(_5f);}:function(_60){return _5c(_60)&&_5d(_60);};})(_57.func,_5b.func,_5a);_57.lastIndex=_5b.lastIndex;if(!_57.markRE){_57.markRE=_5b.markRE;}else{if(_5b.markRE){_57.markRE=_57.markRE+"|"+_5b.markRE;}}}};var _61=_4d(0);this.evalFunc=_61.func;if(_61.markRE){this.markRegExp=new RegExp(_61.markRE,_46.caseSensitive?"mg":"img");}};abego.BoolExp.prototype.exec=function(){return this.evalFunc.apply(this,arguments);};abego.BoolExp.prototype.getMarkRegExp=function(){return this.markRegExp;};abego.BoolExp.prototype.toString=function(){return this.s;};abego.MultiFieldRegExpTester=function(re,_63,_64){this.re=re;this.fields=_63?_63:["title","text","tags"];this.withExtendedFields=_64;};abego.MultiFieldRegExpTester.prototype.test=function(_65){var re=this.re;for(var i=0;i<this.fields.length;i++){var s=store.getValue(_65,this.fields[i]);if(typeof s=="string"&&re.test(s)){return this.fields[i];}}
if(this.withExtendedFields){return store.forEachField(_65,function(_69,_6a,_6b){return typeof _6b=="string"&&re.test(_6b)?_6a:null;},true);}
return null;};abego.TiddlerQuery=function(_6c,_6d,_6e,_6f,_70){if(_6e){this.regExp=new RegExp(_6c,_6d?"mg":"img");this.tester=new abego.MultiFieldRegExpTester(this.regExp,_6f,_70);}else{this.expr=new abego.BoolExp(_6c,abego.parseTiddlerFilterTerm,{defaultFields:_6f,caseSensitive:_6d,withExtendedFields:_70});}
this.getQueryText=function(){return _6c;};this.getUseRegExp=function(){return _6e;};this.getCaseSensitive=function(){return _6d;};this.getDefaultFields=function(){return _6f;};this.getWithExtendedFields=function(){return _70;};};abego.TiddlerQuery.prototype.test=function(_71){if(!_71){return false;}
if(this.regExp){return this.tester.test(_71);}
return this.expr.exec(_71);};abego.TiddlerQuery.prototype.filter=function(_72){return abego.select(_72,this.test,this);};abego.TiddlerQuery.prototype.getMarkRegExp=function(){if(this.regExp){return"".search(this.regExp)>=0?null:this.regExp;}
return this.expr.getMarkRegExp();};abego.TiddlerQuery.prototype.toString=function(){return(this.regExp?this.regExp:this.expr).toString();};abego.PageWiseRenderer=function(){this.firstIndexOnPage=0;};merge(abego.PageWiseRenderer.prototype,{setItems:function(_73){this.items=_73;this.setFirstIndexOnPage(0);},getMaxPagesInNavigation:function(){return 10;},getItemsCount:function(_74){return this.items?this.items.length:0;},getCurrentPageIndex:function(){return Math.floor(this.firstIndexOnPage/this.getItemsPerPage());},getLastPageIndex:function(){return Math.floor((this.getItemsCount()-1)/this.getItemsPerPage());},setFirstIndexOnPage:function(_75){this.firstIndexOnPage=Math.min(Math.max(0,_75),this.getItemsCount()-1);},getFirstIndexOnPage:function(){this.firstIndexOnPage=Math.floor(this.firstIndexOnPage/this.getItemsPerPage())*this.getItemsPerPage();return this.firstIndexOnPage;},getLastIndexOnPage:function(){return Math.min(this.getFirstIndexOnPage()+this.getItemsPerPage()-1,this.getItemsCount()-1);},onPageChanged:function(_76,_77){},renderPage:function(_78){if(_78.beginRendering){_78.beginRendering(this);}
try{if(this.getItemsCount()){var _79=this.getLastIndexOnPage();var _7a=-1;for(var i=this.getFirstIndexOnPage();i<=_79;i++){_7a++;_78.render(this,this.items[i],i,_7a);}}}
var _7d=this;var _7e=function(e){if(!e){var e=window.event;}
abego.consumeEvent(e);var _80=abego.toInt(this.getAttribute("page"),0);var _81=_7d.getCurrentPageIndex();if(_80==_81){return;}
var _82=_80*_7d.getItemsPerPage();_7d.setFirstIndexOnPage(_82);_7d.onPageChanged(_80,_81);};var _83;var _84=this.getCurrentPageIndex();var _85=this.getLastPageIndex();if(_84>0){_83=createTiddlyButton(_7c,"Previous","Go to previous page (Shortcut: Alt-'<')",_7e,"prev");_83.setAttribute("page",(_84-1).toString());_83.setAttribute("accessKey","<");}
for(var i=-this.getMaxPagesInNavigation();i<this.getMaxPagesInNavigation();i++){var _87=_84+i;if(_87<0){continue;}
var _88=(i+_84+1).toString();var _89=_87==_84?"currentPage":"otherPage";_83=createTiddlyButton(_7c,_88,"Go to page %0".format([_88]),_7e,_89);_83.setAttribute("page",(_87).toString());}
if(_84<_85){_83=createTiddlyButton(_7c,"Next","Go to next page (Shortcut: Alt-'>')",_7e,"next");_83.setAttribute("page",(_84+1).toString());_83.setAttribute("accessKey",">");}}});abego.LimitedTextRenderer=function(){var _8a=40;var _8b=4;var _8c=function(_8d,_8e,_8f){var n=_8d.length;if(n==0){_8d.push({start:_8e,end:_8f});return;}
var i=0;for(;i<n;i++){var _92=_8d[i];if(_92.start<=_8f&&_8e<=_92.end){var r;var _94=i+1;for(;_94<n;_94++){r=_8d[_94];if(r.start>_8f||_8e>_92.end){break;}}
var _95=_8e;var _96=_8f;for(var j=i;j<_94;j++){r=_8d[j];_95=Math.min(_95,r.start);_96=Math.max(_96,r.end);}
_8d.splice(i,0,{start:_8e,end:_8f});};var _98=function(_99){var _9a=0;for(var i=0;i<_99.length;i++){var _9c=_99[i];_9a+=_9c.end-_9c.start;}
return _9a;};var _9d=function(c){return(c>="a"&&c<="z")||(c>="A"&&c<="Z")||c=="_";};var _9f=function(s,_a1){if(!_9d(s[_a1])){return null;}
for(var i=_a1-1;i>=0&&_9d(s[i]);i--){}
var _a3=i+1;var n=s.length;for(i=_a1+1;i<n&&_9d(s[i]);i++){}
return{start:_a3,end:i};};var _a5=function(s,_a7,_a8){var _a9;if(_a8){_a9=_9f(s,_a7);}else{if(_a7<=0){return _a7;}
if(!_a9){return _a7;}
if(_a8){if(_a9.start>=_a7-_8b){return _a9.start;}
if(_a9.end<=_a7+_8b){return _a9.end;}}else{if(_a9.end<=_a7+_8b){return _a9.end;}
if(_a9.start>=_a7-_8b){return _a9.start;}}
return _a7;};var _aa=function(s,_ac){var _ad=[];if(_ac){var _ae=0;var n=s.length;var _b0=0;do{_ac.lastIndex=_ae;var _b1=_ac.exec(s);if(_b1){if(_ae<_b1.index){var t=s.substring(_ae,_b1.index);_ad.push({text:t});}
return _ad;};var _b3=function(_b4){var _b5=0;for(var i=0;i<_b4.length;i++){if(_b4[i].isMatch){_b5++;}}
return _b5;};var _b7=function(s,_b9,_ba,_bb,_bc){var _bd=Math.max(Math.floor(_bc/(_bb+1)),_8a);var _be=Math.max(_bd-(_ba-_b9),0);var _bf=Math.min(Math.floor(_ba+_be/3),s.length);var _c0=Math.max(_bf-_bd,0);_c0=_a5(s,_c0,true);_bf=_a5(s,_bf,false);return{start:_c0,end:_bf};};var _c1=function(_c2,s,_c4){var _c5=[];var _c6=_b3(_c2);var pos=0;for(var i=0;i<_c2.length;i++){var t=_c2[i];var _ca=t.text;if(t.isMatch){var _cb=_b7(s,pos,pos+_ca.length,_c6,_c4);_8c(_c5,_cb.start,_cb.end);}
return _c5;};var _cc=function(s,_ce,_cf){var _d0=_cf-_98(_ce);while(_d0>0){if(_ce.length==0){_8c(_ce,0,_a5(s,_cf,false));return;}else{var _d1=_ce[0];var _d2;var _d3;if(_d1.start==0){_d2=_d1.end;if(_ce.length>1){_d3=_ce[1].start;}else{_8c(_ce,_d2,_a5(s,_d2+_d0,false));return;}}else{_d2=0;_d3=_d1.start;}
var _d4=Math.min(_d3,_d2+_d0);_8c(_ce,_d2,_d4);_d0-=(_d4-_d2);}}};var _d5=function(_d6,s,_d8,_d9,_da){if(_d9.length==0){return;}
var _db=function(_dc,s,_de,_df,_e0){var t;var _e2;var pos=0;var i=0;var _e5=0;for(;i<_de.length;i++){t=_de[i];_e2=t.text;if(_df<pos+_e2.length){_e5=_df-pos;break;}
var _e6=_e0-_df;for(;i<_de.length&&_e6>0;i++){t=_de[i];_e2=t.text.substr(_e5);_e5=0;if(_e2.length>_e6){_e2=_e2.substr(0,_e6);}
var _e7=_da;for(var i=0;i<_d9.length&&_e7>0;i++){var _e9=_d9[i];var len=Math.min(_e9.end-_e9.start,_e7);_db(_d6,s,_d8,_e9.start,_e9.start+len);_e7-=len;}};this.render=function(_eb,s,_ed,_ee){if(s.length<_ed){_ed=s.length;}
var _ef=_aa(s,_ee);var _f0=_c1(_ef,s,_ed);_cc(s,_f0,_ed);_d5(_eb,s,_ef,_f0,_ed);};};(function(){function alertAndThrow(msg){alert(msg);throw msg;}
if(version.major<2||(version.major==2&&version.minor<1)){alertAndThrow("YourSearchPlugin requires TiddlyWiki 2.1 or newer.\n\nCheck the archive for YourSearch plugins\nsupporting older versions of TiddlyWiki.\n\nArchive: http://tiddlywiki.abego-software.de/archive");}
abego.YourSearch={};var _f2;var _f3;var _f4=function(_f5){_f2=_f5;};var _f6=function(){return _f2?_f2:[];};var _f7=function(){return _f2?_f2.length:0;};var _f8=4;var _f9=10;var _fa=2;var _fb=function(s,re){var m=s.match(re);return m?m.length:0;};var _ff=function(_100,_101){var _102=_101.getMarkRegExp();if(!_102){return 1;}
var _103=_100.title.match(_102);var _104=_103?_103.length:0;var _105=_fb(_100.getTags(),_102);var _106=_103?_103.join("").length:0;var _107=_100.title.length>0?_106/_100.title.length:0;var rank=_104*_f8+_105*_fa+_107*_f9+1;return rank;};var _109=function(_10a,_10b,_10c,_10d,_10e,_10f){_f3=null;var _110=_10a.reverseLookup("tags",_10f,false);try{var _111=[];if(config.options.chkSearchInTitle){_111.push("title");}
_f3=new abego.TiddlerQuery(_10b,_10c,_10d,_111,config.options.chkSearchExtendedFields);}
var _112=_f3.filter(_110);var _113=abego.YourSearch.getRankFunction();for(var i=0;i<_112.length;i++){var _115=_112[i];var rank=_113(_115,_f3);_115.searchRank=rank;}
var _117=function(a,b){var _11a=a.searchRank-b.searchRank;if(_11a==0){if(a[_10e]==b[_10e]){return(0);}else{return(a[_10e]<b[_10e])?-1:+1;}}else{return(_11a>0)?-1:+1;}};_112.sort(_117);return _112;};var _11b=80;var _11c=50;var _11d=250;var _11e=50;var _11f=25;var _120=10;var _121="yourSearchResult";var _122="yourSearchResultItems";var _123;var _124;var _125;var _126;var _127;var _128=function(){if(version.extensions.YourSearchPlugin.styleSheetInited){return;}
version.extensions.YourSearchPlugin.styleSheetInited=true;setStylesheet(store.getTiddlerText("YourSearchStyleSheet"),"yourSearch");};var _129=function(){return _124!=null&&_124.parentNode==document.body;};var _12a=function(){if(_129()){document.body.removeChild(_124);}};var _12b=function(e){_12a();var _12d=this.getAttribute("tiddlyLink");if(_12d){var _12e=this.getAttribute("withHilite");var _12f=highlightHack;if(_12e&&_12e=="true"&&_f3){highlightHack=_f3.getMarkRegExp();}
return(false);};var _130=function(){if(!_125){return;}
var root=_125;var _132=findPosX(root);var _133=findPosY(root);var _134=root.offsetHeight;var _135=_132;var _136=_133+_134;var _137=findWindowWidth();if(_137<_124.offsetWidth){_124.style.width=(_137-100)+"px";_137=findWindowWidth();}
var _138=_124.offsetWidth;if(_135+_138>_137){_135=_137-_138-30;}
_124.style.left=_135+"px";_124.style.top=_136+"px";_124.style.display="block";};var _139=function(){if(_124){window.scrollTo(0,ensureVisible(_124));}
if(_125){window.scrollTo(0,ensureVisible(_125));}};var _13a=function(){_130();_139();};var _13b;var _13c;var _13d=new abego.PageWiseRenderer();var _13e=function(_13f){this.itemHtml=store.getTiddlerText("YourSearchItemTemplate");if(!this.itemHtml){alertAndThrow("YourSearchItemTemplate not found");}
this.place=document.getElementById(_122);if(!this.place){this.place=createTiddlyElement(_13f,"div",_122);}};merge(_13e.prototype,{render:function(_140,_141,_142,_143){_13b=_143;_13c=_141;var item=createTiddlyElement(this.place,"div",null,"yourSearchItem");item.innerHTML=this.itemHtml;applyHtmlMacros(item,null);refreshElements(item,null);},endRendering:function(_145){_13c=null;}});var _146=function(){if(!_124||!_125){return;}
var html=store.getTiddlerText("YourSearchResultTemplate");if(!html){html="<b>Tiddler YourSearchResultTemplate not found</b>";}
_124.innerHTML=html;applyHtmlMacros(_124,null);refreshElements(_124,null);var _148=new _13e(_124);_13d.renderPage(_148);_13a();};_13d.getItemsPerPage=function(){var n=(config.options.chkPreviewText)?abego.toInt(config.options.txtItemsPerPageWithPreview,_120):abego.toInt(config.options.txtItemsPerPage,_11f);return(n>0)?n:1;};_13d.onPageChanged=function(){_146();};var _14a=function(){if(_125==null||!config.options.chkUseYourSearch){return;}
if((_125.value==_123)&&_123&&!_129()){if(_124&&(_124.parentNode!=document.body)){document.body.appendChild(_124);_13a();}else{abego.YourSearch.onShowResult(true);}}};var _14b=function(){_12a();_124=null;_123=null;};var _14c=function(self,e){while(e!=null){if(self==e){return true;}
return false;};var _14f=function(e){if(e.target==_125){return;}
_12a();};var _151=function(e){if(e.keyCode==27){_12a();}};addEvent(document,"click",_14f);addEvent(document,"keyup",_151);var _153=function(text,_155,_156){_123=text;_f4(_109(store,text,_155,_156,"title","excludeSearch"));abego.YourSearch.onShowResult();};var _157=function(_158,_159,_15a,_15b,_15c,_15d){_128();_123="";var _15e=null;var _15f=function(txt){if(config.options.chkUseYourSearch){_153(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}else{story.search(txt.value,config.options.chkCaseSensitiveSearch,config.options.chkRegExpSearch);}
_123=txt.value;};var _161=function(e){_15f(_125);return false;};var _163=function(e){if(!e){var e=window.event;}
_125=this;switch(e.keyCode){case 13:if(e.ctrlKey&&_127&&_129()){_127.onclick.apply(_127,[e]);}else{_15f(this);}
break;case 27:if(_129()){_12a();}else{this.value="";clearMessage();}
var txt=this;_15e=setTimeout(function(){_15f(txt);},500);}}else{if(_15e){clearTimeout(_15e);}}}
if(this.value.length==0){_12a();}};var _166=function(e){this.select();clearMessage();_14a();};var args=_15c.parseParams("list",null,true);var _169=getFlag(args,"buttonAtRight");var _16a=getParam(args,"sizeTextbox",this.sizeTextbox);var btn;if(!_169){btn=createTiddlyButton(_158,this.label,this.prompt,_161);}
var txt=createTiddlyElement(_158,"input",null,null,null);if(_15a[0]){txt.value=_15a[0];}
_125=txt;_126=btn;};var _16d=function(){_12a();var _16e=_f6();var n=_16e.length;if(n){var _170=[];for(var i=0;i<n;i++){_170.push(_16e[i].title);}
story.displayTiddlers(null,_170);}};var _172=function(_173,_174,_175,_176){invokeMacro(_173,"option",_174,_175,_176);var elem=_173.lastChild;var _178=elem.onclick;elem.onclick=function(e){var _17a=_178.apply(this,arguments);_146();return _17a;};return elem;};var _17b=function(s){var _17d=["''","{{{","}}}","//","<<<","/***","***/"];var _17e="";for(var i=0;i<_17d.length;i++){if(i!=0){_17e+="|";}
return s.replace(new RegExp(_17e,"mg"),"").trim();};var _180=function(){var i=_13b;return(i>=0&&i<=9)?(i<9?(i+1):0):-1;};var _182=new abego.LimitedTextRenderer();var _183=function(_184,s,_186){_182.render(_184,s,_186,_f3.getMarkRegExp());};var _187=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_188,_189,_18a,_18b,_18c,tags,_18e){_187.apply(this,arguments);_14b();};var _18f=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_190){_18f.apply(this,arguments);_14b();};config.macros.yourSearch={label:"yourSearch",prompt:"Gives access to the current/last YourSearch result",handler:function(_191,_192,_193,_194,_195,_196){if(_193.length==0){return;}
var name=_193[0];var func=config.macros.yourSearch.funcs[name];if(func){func(_191,_192,_193,_194,_195,_196);}},tests:{"true":function(){return true;},"false":function(){return false;},"found":function(){return _f7()>0;},"previewText":function(){return config.options.chkPreviewText;}},funcs:{itemRange:function(_199){if(_f7()){var _19a=_13d.getLastIndexOnPage();var s="%0 - %1".format([_13d.getFirstIndexOnPage()+1,_19a+1]);createTiddlyText(_199,s);}},count:function(_19c){createTiddlyText(_19c,_f7().toString());},query:function(_19d){if(_f3){createTiddlyText(_19d,_f3.toString());}},version:function(_19e){var t="YourSearch %0.%1.%2".format([version.extensions.YourSearchPlugin.major,version.extensions.YourSearchPlugin.minor,version.extensions.YourSearchPlugin.revision]);var e=createTiddlyElement(_19e,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#YourSearchPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_1a1){var e=createTiddlyElement(_1a1,"a");e.setAttribute("href","http://www.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2005-2008 <b><font color=\"red\">abego</font></b> Software<font>";},newTiddlerButton:function(_1a3){if(_f3){var r=abego.parseNewTiddlerCommandLine(_f3.getQueryText());var btn=config.macros.newTiddler.createNewTiddlerButton(_1a3,r.title,r.params,"new tiddler","Create a new tiddler based on search text. (Shortcut: Ctrl-Enter; Separators: '.', '#')",null,"text");var _1a6=btn.onclick;btn.onclick=function(){_12a();_1a6.apply(this,arguments);};_127=btn;}},linkButton:function(_1a7,_1a8,_1a9,_1aa,_1ab,_1ac){if(_1a9<2){return;}
var _1ad=_1a9[1];var text=_1a9<3?_1ad:_1a9[2];var _1af=_1a9<4?text:_1a9[3];var _1b0=_1a9<5?null:_1a9[4];var btn=createTiddlyButton(_1a7,text,_1af,_12b,null,null,_1b0);btn.setAttribute("tiddlyLink",_1ad);},closeButton:function(_1b2,_1b3,_1b4,_1b5,_1b6,_1b7){var _1b8=createTiddlyButton(_1b2,"close","Close the Search Results (Shortcut: ESC)",_12a);},openAllButton:function(_1b9,_1ba,_1bb,_1bc,_1bd,_1be){var n=_f7();if(n==0){return;}
var _1c0=n==1?"open tiddler":"open all %0 tiddlers".format([n]);var _1c1=createTiddlyButton(_1b9,_1c0,"Open all found tiddlers (Shortcut: Alt-O)",_16d);_1c1.setAttribute("accessKey","O");},naviBar:function(_1c2,_1c3,_1c4,_1c5,_1c6,_1c7){_13d.addPageNavigation(_1c2);},"if":function(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd){if(_1ca.length<2){return;}
var _1ce=_1ca[1];var _1cf=(_1ce=="not");if(_1cf){if(_1ca.length<3){return;}
var test=config.macros.yourSearch.tests[_1ce];var _1d1=false;try{if(test){_1d1=test(_1c8,_1c9,_1ca,_1cb,_1cc,_1cd)!=_1cf;}else{_1d1=(!eval(_1ce))==_1cf;}}
if(!_1d1){_1c8.style.display="none";}},chkPreviewText:function(_1d2,_1d3,_1d4,_1d5,_1d6,_1d7){var _1d8=_1d4.slice(1).join(" ");var elem=_172(_1d2,"chkPreviewText",_1d5,_1d7);elem.setAttribute("accessKey","P");elem.title="Show text preview of found tiddlers (Shortcut: Alt-P)";return elem;}}};config.macros.foundTiddler={label:"foundTiddler",prompt:"Provides information on the tiddler currently processed on the YourSearch result page",handler:function(_1da,_1db,_1dc,_1dd,_1de,_1df){var name=_1dc[0];var func=config.macros.foundTiddler.funcs[name];if(func){func(_1da,_1db,_1dc,_1dd,_1de,_1df);}},funcs:{title:function(_1e2,_1e3,_1e4,_1e5,_1e6,_1e7){if(!_13c){return;}
var _1e8=_180();var _1e9=_1e8>=0?"Open tiddler (Shortcut: Alt-%0)".format([_1e8.toString()]):"Open tiddler";var btn=createTiddlyButton(_1e2,null,_1e9,_12b,null);btn.setAttribute("tiddlyLink",_13c.title);btn.setAttribute("withHilite","true");_183(btn,_13c.title,_11b);if(_1e8>=0){btn.setAttribute("accessKey",_1e8.toString());}},tags:function(_1eb,_1ec,_1ed,_1ee,_1ef,_1f0){if(!_13c){return;}
var name=_1f9[1];var len=_1f9.length>2?abego.toInt(_1f9[2],_11e):_11e;var v=store.getValue(_13c,name);if(v){_183(_1f7,_17b(v),len);}},number:function(_200,_201,_202,_203,_204,_205){var _206=_180();if(_206>=0){var text="%0)".format([_206.toString()]);createTiddlyElement(_200,"span",null,"shortcutNumber",text);}}}};var opts={chkUseYourSearch:true,chkPreviewText:true,chkSearchAsYouType:true,chkSearchInTitle:true,chkSearchInText:true,chkSearchInTags:true,chkSearchExtendedFields:true,txtItemsPerPage:_11f,txtItemsPerPageWithPreview:_120};for(var n in opts){if(config.options[n]==undefined){config.options[n]=opts[n];}}
config.shadowTiddlers.AdvancedOptions+="\n<<option chkUseYourSearch>> Use 'Your Search' //([[more options|YourSearch Options]]) ([[help|YourSearch Help]])// ";config.shadowTiddlers["YourSearch Help"]="!Field Search\nWith the Field Search you can restrict your search to certain fields of a tiddler, e.g"+" only search the tags or only the titles. The general form is //fieldname//'':''//textToSearch// (e."+"g. {{{title:intro}}}). In addition one-character shortcuts are also supported for the standard field"+"s {{{title}}}, {{{text}}} and {{{tags}}}:\n|!What you want|!What you type|!Example|\n|Search ''titles "+"only''|start word with ''!''|{{{!jonny}}} (shortcut for {{{title:jonny}}})|\n|Search ''contents/text "+"only''|start word with ''%''|{{{%football}}} (shortcut for {{{text:football}}})|\n|Search ''tags only"+"''|start word with ''#''|{{{#Plugin}}} (shortcut for {{{tags:Plugin}}})|\n\nUsing this feature you may"+" also search the extended fields (\"Metadata\") introduced with TiddlyWiki 2.1, e.g. use {{{priority:1"+"}}} to find all tiddlers with the priority field set to \"1\".\n\nYou may search a word in more than one"+" field. E.g. {{{!#Plugin}}} (or {{{title:tags:Plugin}}} in the \"long form\") finds tiddlers containin"+"g \"Plugin\" either in the title or in the tags (but does not look for \"Plugin\" in the text). \n\n!Boole"+"an Search\nThe Boolean Search is useful when searching for multiple words.\n|!What you want|!What you "+"type|!Example|\n|''All words'' must exist|List of words|{{{jonny jeremy}}} (or {{{jonny and jeremy}}}"+")|\n|''At least one word'' must exist|Separate words by ''or''|{{{jonny or jeremy}}}|\n|A word ''must "+"not exist''|Start word with ''-''|{{{-jonny}}} (or {{{not jonny}}})|\n\n''Note:'' When you specify two"+" words, separated with a space, YourSearch finds all tiddlers that contain both words, but not neces"+"sarily next to each other. If you want to find a sequence of word, e.g. '{{{John Brown}}}', you need"+" to put the words into quotes. I.e. you type: {{{\"john brown\"}}}.\n\nUsing parenthesis you may change "+"the default \"left to right\" evaluation of the boolean search. E.g. {{{not (jonny or jeremy)}}} finds"+" all tiddlers that contain neither \"jonny\" nor \"jeremy. In contrast to this {{{not jonny or jeremy}}"+"} (i.e. without parenthesis) finds all tiddlers that either don't contain \"jonny\" or that contain \"j"+"eremy\".\n\n!'Exact Word' Search\nBy default a search result all matches that 'contain' the searched tex"+"t. E.g. if you search for {{{Task}}} you will get all tiddlers containing 'Task', but also '~Complet"+"edTask', '~TaskForce' etc.\n\nIf you only want to get the tiddlers that contain 'exactly the word' you"+" need to prefix it with a '='. E.g. typing '=Task' will find the tiddlers that contain the word 'Tas"+"k', ignoring words that just contain 'Task' as a substring.\n\n!~CaseSensitiveSearch and ~RegExpSearch"+"\nThe standard search options ~CaseSensitiveSearch and ~RegExpSearch are fully supported by YourSearc"+"h. However when ''~RegExpSearch'' is on Filtered and Boolean Search are disabled.\n\nIn addition you m"+"ay do a \"regular expression\" search even with the ''~RegExpSearch'' set to false by directly enterin"+"g the regular expression into the search field, framed with {{{/.../}}}. \n\nExample: {{{/m[ae][iy]er/"+"}}} will find all tiddlers that contain either \"maier\", \"mayer\", \"meier\" or \"meyer\".\n\n!~JavaScript E"+"xpression Filtering\nIf you are familiar with JavaScript programming and know some TiddlyWiki interna"+"ls you may also use JavaScript expression for the search. Just enter a JavaScript boolean expression"+" into the search field, framed with {{{ { ... } }}}. In the code refer to the variable tiddler and e"+"valuate to {{{true}}} when the given tiddler should be included in the result. \n\nExample: {{{ { tidd"+"ler.modified > new Date(\"Jul 4, 2005\")} }}} returns all tiddler modified after July 4th, 2005.\n\n!Com"+"bined Search\nYou are free to combine the various search options. \n\n''Examples''\n|!What you type|!Res"+"ult|\n|{{{!jonny !jeremy -%football}}}|all tiddlers with both {{{jonny}}} and {{{jeremy}}} in its tit"+"les, but no {{{football}}} in content.|\n|{{{#=Task}}}|All tiddlers tagged with 'Task' (the exact wor"+"d). Tags named '~CompletedTask', '~TaskForce' etc. are not considered.|\n\n!Access Keys\nYou are encour"+"aged to use the access keys (also called \"shortcut\" keys) for the most frequently used operations. F"+"or quick reference these shortcuts are also mentioned in the tooltip for the various buttons etc.\n\n|"+"!Key|!Operation|\n|{{{Alt-F}}}|''The most important keystroke'': It moves the cursor to the search in"+"put field so you can directly start typing your query. Pressing {{{Alt-F}}} will also display the pr"+"evious search result. This way you can quickly display multiple tiddlers using \"Press {{{Alt-F}}}. S"+"elect tiddler.\" sequences.|\n|{{{ESC}}}|Closes the [[YourSearch Result]]. When the [[YourSearch Resul"+"t]] is already closed and the cursor is in the search input field the field's content is cleared so "+"you start a new query.|\n|{{{Alt-1}}}, {{{Alt-2}}},... |Pressing these keys opens the first, second e"+"tc. tiddler from the result list.|\n|{{{Alt-O}}}|Opens all found tiddlers.|\n|{{{Alt-P}}}|Toggles the "+"'Preview Text' mode.|\n|{{{Alt-'<'}}}, {{{Alt-'>'}}}|Displays the previous or next page in the [[Your"+"Search Result]].|\n|{{{Return}}}|When you have turned off the 'as you type' search mode pressing the "+"{{{Return}}} key actually starts the search (as does pressing the 'search' button).|\n\n//If some of t"+"hese shortcuts don't work for you check your browser if you have other extensions installed that alr"+"eady \"use\" these shortcuts.//";config.shadowTiddlers["YourSearch Options"]="|>|!YourSearch Options|\n|>|<<option chkUseYourSearch>> Use 'Your Search'|\n|!|<<option chkPreviewText"+">> Show Text Preview|\n|!|<<option chkSearchAsYouType>> 'Search As You Type' Mode (No RETURN required"+" to start search)|\n|!|Default Search Filter:<<option chkSearchInTitle>>Title ('!')     <<option chk"+"SearchInText>>Text ('%')     <<option chkSearchInTags>>Tags ('#')    <<option chkSearchExtendedFiel"+"ds>>Extended Fields<html><br><font size=\"-2\">The fields of a tiddlers that are searched when you don"+"'t explicitly specify a filter in the search text <br>(Explictly specify fields using one or more '!"+"', '%', '#' or 'fieldname:' prefix before the word/text to find).</font></html>|\n|!|Number of items "+"on search result page: <<option txtItemsPerPage>>|\n|!|Number of items on search result page with pre"+"view text: <<option txtItemsPerPageWithPreview>>|\n";config.shadowTiddlers["YourSearchStyleSheet"]="/***\n!~YourSearchResult Stylesheet\n***/\n/*{{{*/\n.yourSearchResult {\n\tposition: absolute;\n\twidth: 800"+"px;\n\n\tpadding: 0.2em;\n\tlist-style: none;\n\tmargin: 0;\n\n\tbackground: #ffd;\n\tborder: 1px solid DarkGra"+"y;\n}\n\n/*}}}*/\n/***\n!!Summary Section\n***/\n/*{{{*/\n.yourSearchResult .summary {\n\tborder-bottom-width:"+" thin;\n\tborder-bottom-style: solid;\n\tborder-bottom-color: #999999;\n\tpadding-bottom: 4px;\n}\n\n.yourSea"+"rchRange, .yourSearchCount, .yourSearchQuery   {\n\tfont-weight: bold;\n}\n\n.yourSearchResult .summary ."+"button {\n\tfont-size: 10px;\n\n\tpadding-left: 0.3em;\n\tpadding-right: 0.3em;\n}\n\n.yourSearchResult .summa"+"ry .chkBoxLabel {\n\tfont-size: 10px;\n\n\tpadding-right: 0.3em;\n}\n\n/*}}}*/\n/***\n!!Items Area\n***/\n/*{{{*"+"/\n.yourSearchResult .marked {\n\tbackground: none;\n\tfont-weight: bold;\n}\n\n.yourSearchItem {\n\tmargin-to"+"p: 2px;\n}\n\n.yourSearchNumber {\n\tcolor: #808080;\n}\n\n\n.yourSearchTags {\n\tcolor: #008000;\n}\n\n.yourSearc"+"hText {\n\tcolor: #808080;\n\tmargin-bottom: 6px;\n}\n\n/*}}}*/\n/***\n!!Footer\n***/\n/*{{{*/\n.yourSearchFoote"+"r {\n\tmargin-top: 8px;\n\tborder-top-width: thin;\n\tborder-top-style: solid;\n\tborder-top-color: #999999;"+"\n}\n\n.yourSearchFooter a:hover{\n\tbackground: none;\n\tcolor: none;\n}\n/*}}}*/\n/***\n!!Navigation Bar\n***/"+"\n/*{{{*/\n.yourSearchNaviBar a {\n\tfont-size: 16px;\n\tmargin-left: 4px;\n\tmargin-right: 4px;\n\tcolor: bla"+"ck;\n\ttext-decoration: underline;\n}\n\n.yourSearchNaviBar a:hover {\n\tbackground-color: none;\n}\n\n.yourSe"+"archNaviBar .prev {\n\tfont-weight: bold;\n\tcolor: blue;\n}\n\n.yourSearchNaviBar .currentPage {\n\tcolor: #"+"FF0000;\n\tfont-weight: bold;\n\ttext-decoration: none;\n}\n\n.yourSearchNaviBar .next {\n\tfont-weight: bold"+";\n\tcolor: blue;\n}\n/*}}}*/\n";config.shadowTiddlers["YourSearchResultTemplate"]="<!--\n{{{\n-->\n<span macro=\"yourSearch if found\">\n<!-- The Summary Header ============================"+"================ -->\n<table class=\"summary\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">"+"<tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Result <span class=\"yourSearchRange\" macro=\"yourSearc"+"h itemRange\"></span>\n\t\t&nbsp;of&nbsp;<span class=\"yourSearchCount\" macro=\"yourSearch count\"></span>\n"+"\t\tfor&nbsp;<span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>\n\t</td>\n\t<td class=\"yourSea"+"rchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch chkPreviewText\"></span><span class=\"chkBoxLabel"+"\">preview text</span>\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch openAllButton\"></span>\n\t\t<span macro=\"yourSearch lin"+"kButton 'YourSearch Options' options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkB"+"utton 'YourSearch Help' help 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch clo"+"seButton\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n\n<!-- The List of Found Tiddlers ================="+"=========================== -->\n<div id=\"yourSearchResultItems\" itemsPerPage=\"25\" itemsPerPageWithPr"+"eview=\"10\"></div>\n\n<!-- The Footer (with the Navigation) ==========================================="+"= -->\n<table class=\"yourSearchFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody"+">\n  <tr>\n\t<td align=\"left\">\n\t\tResult page: <span class=\"yourSearchNaviBar\" macro=\"yourSearch naviBar"+"\"></span>\n\t</td>\n\t<td align=\"right\"><span macro=\"yourSearch version\"></span>, <span macro=\"yourSearc"+"h copyright\"></span>\n\t</td>\n  </tr>\n</tbody></table>\n<!-- end of the 'tiddlers found' case ========="+"================================== -->\n</span>\n\n\n<!-- The \"No tiddlers found\" case ================="+"========================== -->\n<span macro=\"yourSearch if not found\">\n<table class=\"summary\" border="+"\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n  <tr>\n\t<td align=\"left\">\n\t\tYourSearch Resu"+"lt: No tiddlers found for <span class=\"yourSearchQuery\" macro=\"yourSearch query\"></span>.\n\t</td>\n\t<t"+"d class=\"yourSearchButtons\" align=\"right\">\n\t\t<span macro=\"yourSearch newTiddlerButton\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Options'"+" options 'Configure YourSearch'\"></span>\n\t\t<span macro=\"yourSearch linkButton 'YourSearch Help' help"+" 'Get help how to use YourSearch'\"></span>\n\t\t<span macro=\"yourSearch closeButton\"></span>\n\t</td>\n  <"+"/tr>\n</tbody></table>\n</span>\n\n\n<!--\n}}}\n-->\n";config.shadowTiddlers["YourSearchItemTemplate"]="<!--\n{{{\n-->\n<span class='yourSearchNumber' macro='foundTiddler number'></span>\n<span class='yourSea"+"rchTitle' macro='foundTiddler title'/></span>&nbsp;-&nbsp;\n<span class='yourSearchTags' macro='found"+"Tiddler field tags 50'/></span>\n<span macro=\"yourSearch if previewText\"><div class='yourSearchText' macro='fo"+"undTiddler field text 250'/></div></span>\n<!--\n}}}\n-->";config.shadowTiddlers["YourSearch"]="<<tiddler [[YourSearch Help]]>>";config.shadowTiddlers["YourSearch Result"]="The popup-like window displaying the result of a YourSearch query.";config.macros.search.handler=_157;var _20a=function(){if(config.macros.search.handler!=_157){alert("Message from YourSearchPlugin:\n\n\nAnother plugin has disabled the 'Your Search' features.\n\n\nYou may "+"disable the other plugin or change the load order of \nthe plugins (by changing the names of the tidd"+"lers)\nto enable the 'Your Search' features.");}};setTimeout(_20a,5000);abego.YourSearch.getStandardRankFunction=function(){return _ff;};abego.YourSearch.getRankFunction=function(){return abego.YourSearch.getStandardRankFunction();};abego.YourSearch.getCurrentTiddler=function(){return _13c;};abego.YourSearch.closeResult=function(){_12a();};abego.YourSearch.getFoundTiddlers=function(){return _f2;};abego.YourSearch.getQuery=function(){return _f3;};abego.YourSearch.onShowResult=function(_20b){highlightHack=_f3?_f3.getMarkRegExp():null;if(!_20b){_13d.setItems(_f6());}