I wanted to give it a try, to show off my abominable regexp skillz! 
It was funny.
(sort of
)
// Finish footnotes if we have any.
if (strpos($message, '% fn%'))
// ____________________________^_ nospace
{
global $fn_num, $fn_content, $fn_count, $has_footnote;
static $fn_total;
$fn_num = 1;
$has_footnote = false;
$fn_content = array();
$fn_count = isset($fn_total) ? $fn_total : 0;
$message = preg_replace_callback('~(% fn%|%/fn%)~is', create_function('$m', '
// __________________________________________________^_ nospace
global $fn_num, $fn_content, $fn_count;
if ($m[0] == \'% fn%\')
// _____________________________________^_ nospace
return \'% fn\' . $fn_num++ . \'%\';
// _____________________________________^_ nospace
else
return \'%/fn\' . --$fn_num . \'%\';
'), $message);
$message = footnotes__callback($message);
ksort($fn_content);
$fn_total += $fn_num;
if (!empty($has_footnote))
$message .= '<div class="bbc_footnotes">' . implode('<br>', $fn_content) . '</div>';
}
function footnotes__callback($message)
{
$message = preg_replace_callback('~(%(fn(\d)+)%(.*?)%/\\2%)~is', create_function('$m', '
global $fn_content, $fn_count, $has_footnote;
$has_footnote = true;
if (strpos($m[4], \'%fn\'))
$m[4] = footnotes__callback($m[4]);
$fn_num = $m[3];
$fn_content[$fn_num] = "<sup id=\"fn$fn_num" . "_" . "$fn_count\">$fn_num </sup>$m[4]<a class=\"footnote_return\" href=\"#ref$fn_num" . "_" . "$fn_count\">↵</a>";
return "<a href=\"#fn$fn_num" . "_" . "$fn_count\" id=\"ref$fn_num" . "_" . "$fn_count\">[$fn_num]</a>";'), $message);
return $message;
}
And the bbcode changed to:
array(
'tag' => 'footnote',
'before' => '<sup class="bbc_footnotes">% fn%',
// ______________________________________________________________________^_ nospace
'after' => '%/fn%</sup>',
'disallow_parents' => array('quote', 'anchor', 'url', 'iurl'),
'disallow_before' => '',
'disallow_after' => '',
'block_level' => true,
),