function staminatest_run()
{
    global $session;
    page_header("Stamina Testing");
    switch (httpget("op")) {
        case "start":
            output("Testing Testing!");
            break;
        case "add":
            output("Attempting to install an action called Sexins, with these parameters:`n`nStarting and Maximum costs: 500`nMinimum cost: 200`nReps for a Reduction: 20`nReduction: 10`n");
            install_action("Sexins", array("maxcost" => 25000, "mincost" => 10000, "expperrep" => 100, "expforlvl" => 1000, "costreduction" => 10, "dkpct" => 2.5));
            break;
        case "process":
            output("Processing the Sexins action");
            process_action("Sexins");
            break;
        case "newday":
            output("Processing a New Day");
            stamina_process_newday();
            break;
        case "buff":
            output("Applying a stamina buff to Sexins for the current user, for 20 rounds, reducing action cost to half.");
            apply_stamina_buff('ultra-sexy-buff-for-sexins', array("name" => "Ultra Sexy Buff for Sexins", "action" => "Sexins", "costmod" => 0.5, "expmod" => 0.8, "rounds" => 5, "roundmsg" => "Round Message!", "wearoffmsg" => "Wearoff Message!"));
            output("Also applying a Stamina Class buff to all Hunting actions, reducing their cost to half for twenty rounds.");
            apply_stamina_buff('huntclasstest', array("name" => "Hunting Class test buff", "class" => "Hunting", "costmod" => 0.5, "expmod" => 0.8, "rounds" => 20, "roundmsg" => "Round Message!", "wearoffmsg" => "Wearoff Message!"));
            break;
        case "get":
            $thingtodebug = get_player_action("Sexins");
            debug($thingtodebug);
            break;
        case "uninstall":
            output("Uninstalling the Sexins action, deleting all actions entries and associated buffs");
            uninstall_action("Sexins");
            break;
        case "dragonkill":
            output("Processing a Dragon Kill");
            stamina_process_dragonkill();
            break;
        case "calcbuffs":
            output("Calculating Buffs");
            stamina_calculate_buffed_cost("Sexins");
            break;
        case "calcexp":
            output("Calculating Buffed EXP");
            stamina_calculate_buffed_exp("Sexins");
            break;
    }
    addnav("Install an action called Sexins", "runmodule.php?module=staminatest&op=add");
    addnav("Uninstall", "runmodule.php?module=staminatest&op=uninstall");
    addnav("Process the Sexins Action for the current user", "runmodule.php?module=staminatest&op=process");
    addnav("Process newday", "runmodule.php?module=staminatest&op=newday");
    addnav("Add a buff", "runmodule.php?module=staminatest&op=buff");
    addnav("Get Stamina", "runmodule.php?module=staminatest&op=get");
    addnav("Process a Dragon Kill", "runmodule.php?module=staminatest&op=dragonkill");
    addnav("Calculate Buffed Cost", "runmodule.php?module=staminatest&op=calcbuffs");
    addnav("Calculate Buffed exp", "runmodule.php?module=staminatest&op=calcexp");
    addnav("Back to the Grotto", "superuser.php");
    page_footer();
    return true;
}
function meatschool_run()
{
    global $session;
    page_header("Maiko's Cookery Academy");
    switch (httpget('op')) {
        case "start":
            if (get_module_pref("meatsmith", "meatsystem") == 0) {
                //this is the player's first trip to the Meat School
                output("\"`%Don't worry, it won't feel a thing!`0\"`n`nThe voice comes through confidently - one that's clearly used to carrying across a room full of students.  A teacher's voice.  You step into the hall.`n`nTwenty or so students sit on slightly rickety-looking chairs inside, facing a raised platform.  You barely have time to register the petite, smiling KittyMorph woman before a loud `iBOOM-ch-KA`i draws your attention to the captive bolt pistol in her hand, and the cow-sized, green-furred beast that is at this very moment falling to the floor with a bass-heavy `ithump`i.  Several students squirm in their seats.`n`nThe teacher looks in your direction, and gives you a smile as she puts down the bolt pistol and picks up a pair of razor-sharp knives.  \"`%A new recruit!  I'll bring you up to speed real quick - I'm Maiko, and today we're learning how to cook Bewilderbeest steaks.  From scratch!  Come in, sit down, the first lesson's free!`0\"`n`nYou nervously make your way to a chair and take a seat.  \"`%James, tell me why it's important to begin the bleeding process right away.`0\"`n`nA sick-looking youth stutters a reply.  \"S-s-so it doesn't wake up?\"`n`n\"`%No.  No, if you've kept your gun looked after and done the stunning properly, it won't wake up from that.  The stunning pretty well destroys the forebrain - the animal's alive only in a very clinical sense of the term.  In every sense that matters, to you or to it, it's dead.  No, we start the bleeding process straight away because the blood pressure increases the longer we leave it, and that can rupture blood vessels, and cause muscular haemorrhages - which just makes the meat spoil faster.  Also, when you're out killing monsters in the jungle, if you don't get the meat from them straight away, something's apt to take the carcass the moment you turn your back, be it Midgets or other monsters.  So we butcher the monsters the moment they're unconscious, right?  Now, watch as I make the cuts.  First one, down here - and now we pull that out, and if you want to, you can tie a knot in it.  Second one, this way, and then again, and now we reach in and...  One more...  Aah!  There we go.  Hold these for me, James.  And now - see?  Just like that.  Can you see, there, at the back?  Good.  Look here - the meat can sometimes jump around a little bit.  Don't be freaked out, it's not still alive.  That's just the muscle reacting to the air - it's not used to this much oxygen.  See?  This bit in my hand is still twitching around, even though it's not attached to anything.  I'd like to point out as I'm doing this that it won't always be possible to do it so neatly while you're cleaning the animals that tried to kill you - but just do the best you can.  We're only interested in the best cuts, these ones here - the Zombies and Humans will take the other meat, and the Midgets will only take the... well, James, you could probably sell `ithose`i to them.  Now, we'll do a couple more over here, and...  Um... you there, the new recruit, are you okay?  You look a bit, um...`0\"`n`nVarious students turn around to look at you.  \"Fine,\" you squeak.`n`n\"`%Jolly good then - come on, up you come, let's see if you can do this bit.  You'll soon learn to swim if we chuck you in the deep end, eh?`0\"  You gulp, and head up to the platform.  Right into the deep end.`n`nAn hour later, Maiko shakes your hand.  \"`%That was a very successful first lesson!  If you want to gain some experience in field-dressing, cleaning and cooking, I can offer private tuition at ten Requisition per lesson.  But to be honest - you're a natural!`0\"`n`nYou're not entirely sure how to take that.`n`n`c`bYou have gained two new skills!`b`nYou are now at level one in Carcass Cleaning and Cooking!`c");
                require_once "modules/staminasystem/lib/lib.php";
                get_player_action("Cleaning the Carcass");
                get_player_action("Cooking");
                set_module_pref("meatsmith", 1, "meatsystem");
            } else {
                //lessons
                require_once "modules/staminasystem/lib/lib.php";
                $amber = get_stamina();
                if ($amber == 100) {
                    output("Maiko greets you at the door with a wide grin.  \"`%Back for some more training, eh?  Ten Req per lesson, and I keep the meat.  How's that sound?`0\"`n`n`JMaiko, like other teachers in Improbable Island, can help you level up some of your skills.  When you pay to train with Maiko, you'll use as much Stamina in performing your chosen actions as normal, but you'll receive two and a half times the experience.  Higher levels in Cooking and Carcass Cleaning will make these actions cost fewer Stamina points.`n`n`0Will you train with Maiko?`n`n");
                    addnav("Train with Maiko");
                    if ($session['user']['gold'] >= 10) {
                        $cleancost = stamina_getdisplaycost("Cleaning the Carcass");
                        addnav(array("Pay 10 Req for a Carcass Cleaning lesson (`Q%s%%`0)", $cleancost), "runmodule.php?module=meatschool&op=train&train=clean");
                        $cookcost = stamina_getdisplaycost("Cooking");
                        addnav(array("Pay 10 Req for a Cookery lesson (`Q%s%%`0)", $cookcost), "runmodule.php?module=meatschool&op=train&train=cook");
                    } else {
                        addnav("You don't have enough money.  No lessons for you.", "");
                    }
                } else {
                    output("Maiko greets you at the door with a wide grin.  \"`%Back for some more training, eh?  Well, you look half-asleep to me.  Training won't do you any good at all if you're too tired to take it in.  Go and get some rest, or a coffee or something, then we'll talk.`0\"  She shoos you out of the door.");
                }
            }
            addnav("Leave this place");
            addnav("Return to Kittania", "village.php");
            break;
        case "train":
            if (is_module_active("medals")) {
                require_once "modules/medals.php";
                medals_award_medal("maiko_train", "Maiko's Meat School", "This player took lessons at Maiko's Meat School!", "medal_maiko.png");
            }
            $session['user']['gold'] -= 10;
            require_once "modules/staminasystem/lib/lib.php";
            switch (httpget('train')) {
                case "clean":
                    apply_stamina_buff('maikoclean', array("name" => "Maiko\\'s Training", "action" => "Cleaning the Carcass", "costmod" => 1, "expmod" => 2.5, "rounds" => 1, "roundmsg" => "", "wearoffmsg" => ""));
                    output("Maiko shows you a big smile.  \"`%Another butchery lesson!  Great stuff.  Let's get started!`0\"`n`nMaiko grabs her knives and captive bolt pistol, you don your gloves, and the two of you spend the next little while up to your elbows in warm, still-twitching muscle.  Under Maiko's careful watch, her gentle hands occasionally guiding yours to make a difficult cut, you learn one or two things that you didn't know before.");
                    $return = process_action("Cleaning the Carcass");
                    output("You receive %s experience in Cleaning the Carcass.`n`n", $return['exp_earned']);
                    if ($return['lvlinfo']['levelledup'] == true) {
                        output("`c`b`0You gained a level in Cleaning Carcasses!  You are now level %s!  This action will cost fewer Stamina points now, so you can butcher more creatures each day!`b`c`n", $return['lvlinfo']['newlvl']);
                    }
                    break;
                case "cook":
                    apply_stamina_buff('maikocook', array("name" => "Maiko\\'s Training", "action" => "Cooking", "costmod" => 1, "expmod" => 2.5, "rounds" => 1, "roundmsg" => "", "wearoffmsg" => ""));
                    output("Maiko shows you a big smile.  \"`%Another cookery lesson!  Great stuff.  Let's get started!`0\"`n`nMaiko grabs her pans and some ingredients, and you don the 'hilarious' apron Maiko has so thoughtfully provided.  Under Maiko's helpful guidance, you learn one or two things that you didn't know before.");
                    $return = process_action("Cooking");
                    output("You receive %s experience in Cooking.`n`n", $return['exp_earned']);
                    if ($return['lvlinfo']['levelledup'] == true) {
                        output("`n`c`b`0You gained a level in Cooking!  You are now level %s!  This action will cost fewer Stamina points now, so you can cook more tasty meals each day!`b`c`n", $return['lvlinfo']['newlvl']);
                    }
                    break;
            }
            $amber = get_stamina();
            if ($amber == 100) {
                addnav("More Training");
                if ($session['user']['gold'] >= 10) {
                    $cleancost = stamina_getdisplaycost("Cleaning the Carcass");
                    addnav(array("Pay 10 Req for a Carcass Cleaning lesson (`Q%s%%`0)", $cleancost), "runmodule.php?module=meatschool&op=train&train=clean");
                    $cookcost = stamina_getdisplaycost("Cooking");
                    addnav(array("Pay 10 Req for a Cookery lesson (`Q%s%%`0)", $cookcost), "runmodule.php?module=meatschool&op=train&train=cook");
                } else {
                    addnav("You don't have enough money.  No more lessons for you.", "");
                }
            } else {
                output("Maiko shows you a grin.  \"`%Well, that was a lot of fun.  But I can see you're getting tired - no point in training any more today, I'm afraid.`0\"  She shoos you out of the door.");
            }
            addnav("Leave this place");
            addnav("Return to Kittania", "village.php");
            break;
    }
    page_footer();
    return true;
}
function stamina_minihof_old($action, $userid = false)
{
    global $session;
    if ($userid === false) {
        $userid = $session['user']['acctid'];
    }
    $st = microtime(true);
    $boardfilename = str_replace(" ", "", $action);
    $boardinfo = datacache("staminaboardinfo_" . $boardfilename, 20);
    $en = microtime(true);
    $to = $en - $st;
    debug("Cache: " . $to);
    if (!is_array($boardinfo)) {
        $board = array();
        $staminasql = "SELECT setting,value,userid FROM " . db_prefix("module_userprefs") . " WHERE modulename='staminasystem' AND setting='actions'";
        $staminaresult = db_query($staminasql);
        $scount = db_num_rows($staminaresult);
        for ($i = 0; $i < $scount; $i++) {
            $row = db_fetch_assoc($staminaresult);
            $actions_array = @unserialize($row['value']);
            $actiondetails = $actions_array[$action];
            if (!$actiondetails['exp']) {
                continue;
            }
            $board[$row['userid']]['xp'] = $actiondetails['exp'];
            $board[$row['userid']]['id'] = $row['userid'];
            //$board[$row['userid']]['lvl'] = $actiondetails['lvl'];
        }
        $boardinfo = stamina_minihof_assignranks($board);
        updatedatacache("staminaboardinfo_" . $boardfilename, $boardinfo);
    }
    //set the player's entry in the board with brand-new data
    $player_action = get_player_action($action);
    $boardinfo['board'][$userid]['xp'] = $player_action['exp'];
    $smallboard = stamina_minihof_smallboard($boardinfo, $userid);
    debug($smallboard);
}
function insultschool_run()
{
    global $session;
    page_header("Cuthbert's Academy of Lingual Defence");
    switch (httpget('op')) {
        case "start":
            if (!get_module_pref("able", "insults")) {
                //this is the player's first trip to the Insults Academy
                //ronsengi
                output("\"`qAh.  Not seen you here before.`0\"`n`nA three-eyed, broad-mouthed Mutant sits behind a desk, wearing a loose-fitting black garment reminiscent of a kimono.  \"`qMy name's Cuthbert, and this is my Academy of Lingual Defence.`0\"`n`n\"`#Lingual Defence?`0\" you ask.`n`n\"`qLingual Defence,`0\" replies Cuthbert proudly.  \"`qA perfect supplement to your preferred martial art, perfected over twenty years by my good self.`0\"`n`n\"`#I see.`0\"  You look around the room.  \"`#I don't see any weaponry?`0\"`n`n\"`qNot `iphysical`i weaponry, no.  The art of Lingual Defence, or Ronsen-Kiai, doesn't require any equipment except for every now and then in training.`0\"  He grins.  \"`qThat's not a `iprecise`i translation, by the way, but I find throwing a bit of Japanese in there helps with the marketing.`0\"`n`nYou nod, looking around at the empty room and the rather sparse student list hanging on one wall.  You decide to indulge the guy - it seems he could use the business.  \"`#Can you show me a bit of this Ronsen-Kiai?`0\"`n`nCuthbert shows you an excited grin.  \"`qAbsolutely!  Here, take this.`0\"  He reaches below his desk and hands you a heavy wooden axe handle, before moving to the center of the room.  \"`qNow come and attack me with that.`0\"  He grins.  \"`qDon't be shy, now.  I'll tell you when to stop.`0\"`n`nYou shrug, heft the axe handle, and rush towards him, bringing your weapon down in a crushing arc onto his head, which isn't there.  The Mutant has stepped to the inside, and now stands close enough for you to feel his breath.`n`n\"`qFUCKWIT!`0\" roars the Mutant as you swing the axe handle towards his sides.  \"`qI've seen `iMOLD`i-`0\" the tip of the axe handle sails harmlessly past his stomach - \"`q...swing an axe handle better than that!  Holy shit you're slow!`0\"  The Mutant takes a step back and another breath, and you flick the axe handle around so that you can charge him with the tip.  \"`qAnd FAT!  Jesus Christ, your arse looks like two Volkswagens parked side-by-side!`0\" the Mutant steps back and away from your axe handle, then takes a very rapid step first towards and then past you, your axe handle chasing but not quite catching his thighs.  You switch into opposite stance, to see the Mutant giving you the finger.  \"`qAnd stupid!  Damn, you're denser than that axe handle!`0\"  Man, that's distracting.  You piston your leading leg upwards, hoping to catch the Mutant in the chest.  The Mutant catches your foot and sniffs.  \"`qAnd the stench of your feet could kill a concrete elephant at twenty paces!`0\"  Enraged, you slam your leading leg downwards while pouncing from your back leg, using the Mutant's arms like a set of stairs so that you can kick his stupid mean face like a football.`n`nYou land poorly.`n`nThe Mutant stands over you.  \"`qYou imbecilic, mewling, malodorous pervert.  You feeble-minded, cloth-eared, illigitimate buffoon.  You twisted, disgusting, Thatcher-licking dullard.  Your father f***s sheep and your mother says \"Baaa.\"  You're a disgrace.  An obscenity.  An embarrassment.\"`n`n\"`#Stop!`0\" you cry.  \"`#Why're you saying these things?`0\"`n`nThe Mutant leans down and helps you to your feet.  \"`qBecause they distract you,`0\" he says kindly.  \"`qThey get you so riled up that you try silly maneouvers like the one that just ended with you winded on the floor.  And even though I can tell that you're a better fighter than me, and would have stoved my head in under different circumstances, I was still able to get away with not being hit because a part of you was paying attention to what I was saying.`0\"`n`nYou blink.  \"`#`iThat's`i Ronsen-Kai?  Spouting a load of insults while fighting?`0\"`n`nThe Mutant nods, smiling.  \"`qTwenty cigarettes for your first lesson.  You'll learn the two starter techniques, Coarse and Confusing.  Then when you can prove to me that you're ready, I'll teach you the third technique - Classy, or as some call it, \"Shakespearean.\"  So.  Are you interested in learning how to fight with your tongue as well as your fists and feet?`0\"`n`nWell?  `iAre`i you?");
                addnav("Learn a new combat technique for 20 cigarettes?");
                if ($session['user']['gems'] >= 20) {
                    addnav("Hell yes!", "runmodule.php?module=insultschool&op=learnbasic");
                } else {
                    addnav("No, because you don't have 20 cigarettes.", "village.php");
                }
            } else {
                //lessons
                require_once "modules/staminasystem/lib/lib.php";
                $amber = get_stamina();
                if ($amber == 100) {
                    output("Cuthbert greets you with a firm handshake.  \"`qHello again!  Back for some more training, eh?  Well, you've completed the basic course, so I can give you refresher lessons at 25 Requisition each.`0\"`n`n");
                    $coarse = get_player_action("Insults - Coarse");
                    $confusing = get_player_action("Insults - Confusing");
                    $level = $coarse['lvl'] + $confusing['lvl'];
                    if ($level > 20) {
                        if (!get_module_pref("ableclassy", "insults")) {
                            output("Cuthbert pauses for a moment and looks you up and down.  \"`qYou know,`0\" he says, \"`qI think you might be ready to learn some Classy insults.  It'll be another 20 cigarettes for the basic Classy course, if you're interested.`0\"`n`n");
                            addnav("Train with Cuthbert");
                            if ($session['user']['gems'] >= 20) {
                                addnav("Pay 20 Cigarettes to learn the Classy Insults action", "runmodule.php?module=insultschool&op=learnclassy");
                            }
                        }
                    }
                    output("`JCuthbert, like other teachers in Improbable Island, can help you level up some of your skills.  When you pay to train with Cuthbert, you'll use as much Stamina in performing your chosen actions as normal, but you'll receive two and a half times the experience.  Higher levels in any given Stamina action will make that action cost fewer Stamina points.  Higher levels in Insults skills will also improve your chances of casting successful Insults, and reduce the chances of fumbling.`n`n`0Will you train with Cuthbert?`n`n");
                    addnav("Train with Cuthbert");
                    if ($session['user']['gold'] >= 25) {
                        $coarsecost = stamina_getdisplaycost("Insults - Coarse");
                        addnav(array("Pay 25 Req for a lesson in Coarse Insults (`Q%s%%`0)", $coarsecost), "runmodule.php?module=insultschool&op=train&train=coarse");
                        $confusingcost = stamina_getdisplaycost("Insults - Confusing");
                        addnav(array("Pay 25 Req for a lesson in Confusing Insults (`Q%s%%`0)", $confusingcost), "runmodule.php?module=insultschool&op=train&train=confusing");
                        if (get_module_pref("ableclassy", "insults")) {
                            $classycost = stamina_getdisplaycost("Insults - Classy");
                            addnav(array("Pay 25 Req for a lesson in Classy Insults (`Q%s%%`0)", $classycost), "runmodule.php?module=insultschool&op=train&train=classy");
                        }
                    } else {
                        addnav("You don't have enough Requisition to improve your existing Insults skills.", "");
                    }
                } else {
                    output("Cuthbert greets you with a firm handshake.  He grins.  \"`qI know what you're thinking - you want more lessons, huh?  Well, you look half-asleep to me.  This isn't something you should try without a good night's rest.  Come see me tomorrow.`0\"");
                }
            }
            addnav("Leave this place");
            addnav("Return to Pleasantville", "village.php");
            break;
        case "train":
            $session['user']['gold'] -= 25;
            if (is_module_active("medals")) {
                require_once "modules/medals.php";
                medals_award_medal("cuthbert_train", "Cuthbert's Academy of Lingual Defence", "This player took lessons at Cuthbert's Academy of Lingual Defence!", "medal_cuthbert.png");
            }
            require_once "modules/staminasystem/lib/lib.php";
            switch (httpget('train')) {
                case "coarse":
                    apply_stamina_buff('traincoarse', array("name" => "Cuthbert's Training", "action" => "Insults - Coarse", "costmod" => 1, "expmod" => 2.5, "rounds" => 1, "roundmsg" => "", "wearoffmsg" => ""));
                    require_once "modules/insults.php";
                    $i1 = insults_coarse();
                    $i2 = insults_coarse();
                    $i3 = insults_coarse();
                    $i4 = insults_coarse();
                    $i5 = insults_coarse();
                    output("Cuthbert shows you a big smile.  \"`qIt's good to train with you again.  Coarse insults it is.  Let's get started!`0\"`n`nOutside the hut, for the next half an hour or so, people stop to listen to the bizzarre and filthy profanities spouted from within.`n`n");
                    output("`i\"`#%s!`0\"`n`n\"`q%s!`0\"`n`n\"`#%s!`0\"`n`n\"`q%s!`0\"`n`n\"`#%s!`0\"`n`n\"`qVery good!`0\"", $i1, $i2, $i3, $i4, $i5);
                    $return = process_action("Insults - Coarse");
                    output("You receive %s experience in Coarse Insults.`n`n", $return['exp_earned']);
                    if ($return['lvlinfo']['levelledup'] == true) {
                        output("`c`b`0You gained a level in Coarse Insults!  You are now level %s!  This action will cost fewer Stamina points now, and you have a higher chance of casting a successful Insult!`b`c`n", $return['lvlinfo']['newlvl']);
                    }
                    break;
                case "confusing":
                    apply_stamina_buff('trainconfusing', array("name" => "Cuthbert's Training", "action" => "Insults - Confusing", "costmod" => 1, "expmod" => 2.5, "rounds" => 1, "roundmsg" => "", "wearoffmsg" => ""));
                    require_once "modules/insults.php";
                    $i1 = insults_confusing();
                    $i2 = insults_confusing();
                    $i3 = insults_confusing();
                    $i4 = insults_confusing();
                    $i5 = insults_confusing();
                    output("Cuthbert shows you a big smile.  \"`qIt's good to train with you again.  Confusing insults it is.  Let's get started!`0\"`n`nOutside the hut, for the next half an hour or so, people stop to listen to the bizzarre and surreal propositions spouted from within.`n`n");
                    output("`i\"`#%s!`0\"`n`n\"`q%s!`0\"`n`n\"`#%s!`0\"`n`n\"`q%s!`0\"`n`n\"`#%s!`0\"`n`n\"`qVery good!`0\"", $i1, $i2, $i3, $i4, $i5);
                    $return = process_action("Insults - Confusing");
                    output("You receive %s experience in Confusing Insults.`n`n", $return['exp_earned']);
                    if ($return['lvlinfo']['levelledup'] == true) {
                        output("`c`b`0You gained a level in Confusing Insults!  You are now level %s!  This action will cost fewer Stamina points now, and you have a higher chance of casting a successful Insult!`b`c`n", $return['lvlinfo']['newlvl']);
                    }
                    break;
                case "classy":
                    apply_stamina_buff('trainclassy', array("name" => "Cuthbert's Training", "action" => "Insults - Classy", "costmod" => 1, "expmod" => 2.5, "rounds" => 1, "roundmsg" => "", "wearoffmsg" => ""));
                    require_once "modules/insults.php";
                    $i1 = insults_classy();
                    $i2 = insults_classy();
                    $i3 = insults_classy();
                    $i4 = insults_classy();
                    $i5 = insults_classy();
                    output("Cuthbert shows you a big smile.  \"`qIt's good to train with you again.  Classy insults it is.  Let's get started!`0\"`n`nOutside the hut, for the next half an hour or so, people stop to listen to the witty and scathing insults spouted from within.`n`n");
                    output("`i\"`#You %s!`0\"`n`n\"`qI retort that you are a %s!`0\"`n`n\"`#I've never seen such a %s!`0\"`n`n\"`qIt is a matter of public record that you are a %s!`0\"`n`n\"`#And proud of it!  You sir, on the other hand, are a %s!`0\"`n`n\"`qVery good!`0\"`n`n`i", $i1, $i2, $i3, $i4, $i5);
                    $return = process_action("Insults - Classy");
                    output("You receive %s experience in Classy Insults.`n`n", $return['exp_earned']);
                    if ($return['lvlinfo']['levelledup'] == true) {
                        output("`c`b`0You gained a level in Classy Insults!  You are now level %s!  This action will cost fewer Stamina points now, and you have a higher chance of casting a successful Insult!`b`c`n", $return['lvlinfo']['newlvl']);
                    }
                    break;
            }
            $amber = get_stamina();
            if ($amber == 100) {
                addnav("More Training");
                if ($session['user']['gold'] >= 25) {
                    $coarsecost = stamina_getdisplaycost("Insults - Coarse");
                    addnav(array("Pay 25 Req for a lesson in Coarse Insults (`Q%s%%`0)", $coarsecost), "runmodule.php?module=insultschool&op=train&train=coarse");
                    $confusingcost = stamina_getdisplaycost("Insults - Confusing");
                    addnav(array("Pay 25 Req for a lesson in Confusing Insults (`Q%s%%`0)", $confusingcost), "runmodule.php?module=insultschool&op=train&train=confusing");
                    if (get_module_pref("ableclassy", "insults")) {
                        $classycost = stamina_getdisplaycost("Insults - Classy");
                        addnav(array("Pay 25 Req for a lesson in Classy Insults (`Q%s%%`0)", $classycost), "runmodule.php?module=insultschool&op=train&train=classy");
                    }
                } else {
                    addnav("You don't have enough Requisition to improve your existing Insults skills.", "");
                }
            } else {
                output("Cuthbert shows you a grin.  \"`qWell, that was a lot of fun.  But I can see you're getting tired - no point in training any more today, I'm afraid.`0\"");
            }
            addnav("Leave this place");
            addnav("Return to Pleasantville", "village.php");
            break;
        case "learnbasic":
            $session['user']['gems'] -= 20;
            output("\"`qExcellent!  Let's get started.  There are three classes of Insults - Coarse, Confusing, and Classy.  Coarse insults are the most vulgar sort, Confusing tend to be surreal and off-putting, and Classy insults are more formal and refined.  Each type has different effects upon the foe, and different difficulties.  Obviously, you'll get better at each one with time - I'm only going to teach you the Coarse and Confusing types today, and you can come back to learn the Classy insults when I think you're ready.`0\"`n`n\"`qCoarse insults are quite predictable.  They usually have only minor effects upon the enemy, but if they backfire the damage won't be too great either.  Obviously, once in a while you'll either land a critical insult or suffer a catastrophic fumble, but for the most part you'll find this happens more rarely with Coarse insults.`0\"`n`n\"`qConfusing insults are a little more erratic - your chances of fumbling or scoring a critical emotional hit are increased when compared with Coarse insults.  Similarly, the effects are slightly more potent.`0\"`n`n\"`qClassy insults go even further than Confusing insults, with potentially devastating effects - but, of course, those effects can backfire and just as easily throw `iyou`i off-kilter.`0\"`n`n\"`qRemember, a poorly-cast insult can backfire against you, so use these techniques carefully.`0\"`n`n\"`qWhen you first start using Ronsen-Kiai, you'll probably end up doing yourself about as much harm as good.  But don't be discouraged - as you gain more experience in each Insult type, you'll get the hang of it.  Now let's get started.`0\"`n`nFor the next few hours, passers-by are shocked by the profanities, obscene suggestions, bizarre propositions and scathing retorts emanating from the Academy.  By the time Cuthbert shakes your hand and sends you out into the world, you're sweating, red-faced and sore-throated - but you feel a sense of true accomplishment.`n`n`c`bYou have gained two new skills!`b`nYou are now qualified to cast Coarse and Confusing Insults against your foes!`c");
            set_module_pref("able", 1, "insults");
            addnav("Leave this place");
            addnav("Return to Pleasantville", "village.php");
            break;
        case "learnclassy":
            $session['user']['gems'] -= 20;
            output("\"`qExcellent!  Let's get started.  Remember, Classy insults are more unpredictable than others, but their effects are greater, so use them carefully.`0\"For the next few hours, passers-by are shocked by the bizarre, Shakespearean language emanating from the Academy.  By the time Cuthbert shakes your hand and sends you out into the world, you're sweating, red-faced and sore-throated - but you feel a sense of true accomplishment.`n`n`c`bYou have gained a new skill!`b`nYou are now qualified to cast Classy Insults against your foes!`c");
            set_module_pref("ableclassy", 1, "insults");
            addnav("Leave this place");
            addnav("Return to Pleasantville", "village.php");
            break;
    }
    page_footer();
    return true;
}
function stamina_advance_buffs($action, $userid = false)
{
    global $session;
    if ($userid === false) {
        $userid = $session['user']['acctid'];
    }
    $bufflist = unserialize(get_module_pref("buffs", "staminasystem", $userid));
    $actiondetails = get_player_action($action, $userid);
    $write = 0;
    if (is_array($bufflist)) {
        foreach ($bufflist as $buff => $values) {
            if ($values['action'] == $action || $values['action'] == "Global" || $values['class'] == $actiondetails['class']) {
                if ($values['roundmsg']) {
                    output_notl("%s`n", stripslashes($values['roundmsg']));
                }
                if ($values['rounds'] > 0) {
                    $values['rounds']--;
                    $write = 1;
                }
                if ($values['rounds'] == 0) {
                    if ($values['wearoffmsg']) {
                        output_notl("%s`n", stripslashes($values['wearoffmsg']));
                    }
                    $write = 1;
                    unset($bufflist[$buff]);
                } else {
                    $bufflist[$buff] = $values;
                }
            }
        }
    }
    if ($write) {
        if (count($bufflist) != 0) {
            set_module_pref("buffs", serialize($bufflist), "staminasystem", $userid);
        } else {
            set_module_pref("buffs", "array()", "staminasystem", $userid);
        }
    }
    return true;
}
function onslaught_run()
{
    global $session, $battle, $enemies;
    global $companions, $companion, $newcompanions;
    debug($session['user']['location']);
    switch (httpget('op')) {
        case "lookaround":
            page_header("What's the situation?");
            $rawnum = onslaught_nummonsters();
            require_once "lib/dialogue.php";
            $vague = vagueify($rawnum);
            output("Taking a moment during a lull in the fighting to look around, you'd say as a rough estimate that there are between %s and %s monsters rampaging through the Outpost.`n`n", $vague['low'], $vague['high']);
            $playercount = 0;
            output("Looking around you, you can see the following players engaged in battle alongside you:`n");
            $sql = "SELECT name,acctid,level FROM " . db_prefix("accounts") . " WHERE locked=0 AND loggedin=1 AND alive=1 AND location='" . $session['user']['location'] . "' AND laston>'" . date("Y-m-d H:i:s", strtotime("-" . getsetting("LOGINTIMEOUT", 900) . " seconds")) . "' ORDER BY level DESC";
            $result = db_query($sql);
            while ($row = db_fetch_assoc($result)) {
                $playercount++;
                output("`0%s`0`n", $row['name']);
            }
            if (!$playercount) {
                output("`bNobody!`b  You're fighting all on your lonesome!`n`n");
            } else {
                output_notl("`n");
            }
            $def = onslaught_checkwalls();
            output("You take a quick glance at the walls, and see they've got %s hitpoints, whatever the hell a \"hitpoint\" is.`n`n", $def);
            $breakchance = e_rand(0, 100);
            if ($breakchance > 50) {
                addnav("What will you do?");
                addnav("Reinforce the defences", "runmodule.php?module=onslaught&op=reinforce");
                addnav("Get back into the fight", "runmodule.php?module=onslaught&op=start&nodesc=1");
                addnav("Run outside and let the Outpost fend for itself", "runmodule.php?module=onslaught&op=runmap");
            } else {
                addnav("And here comes another monster!");
                addnav("Fight!", "runmodule.php?module=onslaught&op=continue&nodesc=1");
            }
            break;
        case "reinforce":
            page_header("Outpost Walls");
            $lv = onslaught_checkmonsters();
            $num = onslaught_nummonsters();
            $def = onslaught_checkwalls();
            output("`0You take a look at the Outpost walls.  Fortunately there are some lengths of timber, a hammer, and some nails sat conveniently next to a portion that's looking a little worse for wear.`n`nThis Outpost's hitpoints: `b%s`b`n`n", number_format($def));
            $stopchance = e_rand(0, 100);
            if ($lv > 100 && $def < $num && $stopchance > 80) {
                output("Before you have a chance to pick up the hammer, you hear the sound of approaching thunderous footsteps from behind you!  You whirl around, dropping the hammer and drawing your weapon, to see a slavering beast bearing down upon you!`n`n");
                addnav("Oh dear...");
                addnav("Fight!", "runmodule.php?module=onslaught&op=start&nodesc=1");
            } else {
                addnav("What will you do?");
                require_once "modules/staminasystem/lib/lib.php";
                $cost = stamina_getdisplaycost("Reinforcement");
                addnav(array("Reinforce the defences (`Q%s%%`0)", $cost), "runmodule.php?module=onslaught&op=reinforceconfirm");
                addnav("Return to the Outpost", "village.php");
            }
            break;
        case "reinforceconfirm":
            $iterations = httpget('iterations');
            if (!$iterations) {
                $iterations = 1;
            }
            page_header("Outpost Walls");
            $lv = onslaught_checkmonsters();
            $num = onslaught_nummonsters();
            output("`0You pick up the hammer and nails, and set about reinforcing the walls with new wood.`n`n");
            require_once "modules/staminasystem/lib/lib.php";
            for ($i = 0; $i < $iterations; $i++) {
                $def = onslaught_checkwalls();
                $stopchance = e_rand(0, 100);
                if ($lv > 100 && $def < $num && $stopchance > 80) {
                    output("Before you have a chance to pound a single nail, you hear the sound of approaching thunderous footsteps from behind you!  You whirl around, dropping the hammer and drawing your weapon, to see a slavering beast bearing down upon you!`n`n");
                    addnav("Oh dear...");
                    addnav("Fight!", "runmodule.php?module=onslaught&op=start&nodesc=1");
                    $nomore = 1;
                    break;
                } else {
                    $act = process_action("Reinforcement");
                    $actinfo = get_player_action("Reinforcement");
                    $actlvl = $actinfo['lvl'];
                    if ($act['lvlinfo']['levelledup'] == true) {
                        output("`n`c`b`0You gained a level in Reinforcement!  You are now level %s!  This action will cost fewer Stamina points now, so reinforcing Outposts will tire you out a little less.`b`c`n", $act['lvlinfo']['newlvl']);
                    }
                    $stamina = get_stamina();
                    $failchance = e_rand(1, 100);
                    if ($failchance > $stamina) {
                        output("`4`c`bDisaster!`b`c`0`n");
                        $red = get_stamina(0);
                        $death = e_rand(0, 100);
                        if ($death > $red) {
                            output("`\$Your exhaustion makes itself known - the hammer rebounds rather spectacularly and hits you square in the forehead, knocking you out cold.  The head injury causes you to lose 10% of your experience, and all your Requisition is stolen by opportunistic Midgets.`n`n`0");
                            $session['user']['hitpoints'] = 0;
                            $session['user']['experience'] = round($session['user']['experience'] * 0.9);
                            $session['user']['gold'] = 0;
                            addnav("It's FailBoat time!");
                            addnav("Well, damn.", "shades.php");
                            $nomore = 1;
                            break;
                        } else {
                            output("You're so exhausted that you make a right pig's ear of the job!`n`nThe fresh plank hangs for a second on one lonely nail before falling off.  What a waste of time!`n`n");
                        }
                    } else {
                        $definc = e_rand($actlvl * 0.8, $actlvl * 1.2);
                        if ($definc < 2) {
                            $definc = 2;
                        }
                        $newdef = $def + $definc;
                        output("You hammer the board to the walls, reinforcing them quite nicely and adding %s hitpoints to this Outpost's defences.`n`nThis Outpost's hitpoints: `b%s`b`n`n", $definc, number_format($newdef));
                        require_once "modules/cityprefs/lib.php";
                        $cid = get_cityprefs_cityid("location", $session['user']['location']);
                        if ($cid) {
                            set_module_objpref("city", $cid, "defences", $newdef);
                        }
                    }
                }
            }
            if (!$nomore) {
                $cost = stamina_getdisplaycost("Reinforcement");
                addnav(array("Wall reinforcement: (`Q%s%%`0)", $cost));
                addnav("Reinforce once", "runmodule.php?module=onslaught&op=reinforceconfirm");
                addnav("5?Reinforce x 5", "runmodule.php?module=onslaught&op=reinforceconfirm&iterations=5");
                addnav("1?Reinforce x 10", "runmodule.php?module=onslaught&op=reinforceconfirm&iterations=10");
                addnav("O?Return to the Outpost", "village.php");
            }
            break;
        case "runsuccess":
            page_header("Run Like Hell!");
            output("You manage to flee your opponent.  You stand close to the Outpost gates, watching the carnage inside.  For the moment, everybody and everything is leaving you alone.  That will not last for long.`n`nNearby, someone has abandoned their timber, hammer and nails.  Abandoned or been dragged from, anyway.`n`n");
            addnav("What will you do?");
            addnav("Reinforce the defences", "runmodule.php?module=onslaught&op=reinforce");
            addnav("Get back into the fight", "runmodule.php?module=onslaught&op=start&nodesc=1");
            addnav("Run outside and let the Outpost fend for itself", "runmodule.php?module=onslaught&op=runmap");
            addnav("Take stock of the situation", "runmodule.php?module=onslaught&op=lookaround");
            break;
        case "runmap":
            redirect("runmodule.php?module=worldmapen&op=beginjourney", "Onslaught - Running Away");
            break;
        case "start":
            page_header("Breach!");
            output("`b`i`4THE WALLS OF %s ARE BREACHED!`0`i`b`nMonsters are pouring into the Outpost through jagged, splintered holes in the Outpost defences!  You picked one `ihell`i of a time to go about your business here!`n`n", strtoupper($session['user']['location']));
            onslaught_getenemy();
            break;
        case "run":
            page_header("Breach!");
            if (e_rand(1, 5) < 3) {
                // They managed to get away.
                $battle = false;
                redirect("runmodule.php?module=onslaught&op=runsuccess", "Onslaught: successful running");
            } else {
                output("You try to run, but your enemy gives chase!`n");
                $op = "fight";
                httpset('op', $op);
                $battle = true;
            }
            break;
        case "fight":
            page_header("Breach!");
            $battle = true;
            break;
        case "continue":
            page_header("Breach!");
            $out1 = onslaught_getcompanion();
            $out2 = onslaught_companion_escape();
            if ($out1) {
                output("`0%s`n", $out1);
            } else {
                if ($out2) {
                    output("`0%s`n", $out2);
                }
            }
            onslaught_getenemy();
            if (!$battle) {
                $left = onslaught_checkmonsters();
                if ($left > 100) {
                    $breakchance = e_rand(0, 100);
                    if ($breakchance > 70) {
                        addnav("Phew!");
                        addnav("Looks like everything else is busy...", "");
                        addnav("Reinforce the defences", "runmodule.php?module=onslaught&op=reinforce");
                        addnav("Get back into the fight", "runmodule.php?module=onslaught&op=start&nodesc=1");
                        addnav("Run outside and let the Outpost fend for itself", "runmodule.php?module=onslaught&op=runmap");
                        addnav("Take stock of the situation", "runmodule.php?module=onslaught&op=lookaround");
                    } else {
                        addnav("They just keep coming!");
                        addnav("Here comes another one!", "runmodule.php?module=onslaught&op=continue&nodesc=1");
                    }
                } else {
                    output("There are no more monsters to fight...`n`n");
                    //Display cleanup text, tart this up a bit
                    addnav("Village", "village.php");
                }
            }
            break;
    }
    if ($battle) {
        include_once "battle.php";
        // if( isset( $enemies ) && !$pvp )
        // $badguy = &$enemies;
        if ($victory) {
            $experience = e_rand($badguy['creatureexp'] * 1.25, $badguy['creatureexp'] * 2);
            $experience = round($experience);
            output("`#You receive `6%s `#experience!`n", $experience);
            $session['user']['experience'] += $experience;
            $left = onslaught_checkmonsters();
            if ($left > 100) {
                $breakchance = e_rand(0, 100);
                if ($breakchance > 70) {
                    addnav("Phew!");
                    addnav("Looks like everything else is busy...", "");
                    addnav("Reinforce the defences", "runmodule.php?module=onslaught&op=reinforce");
                    addnav("Get back into the fight", "runmodule.php?module=onslaught&op=start&nodesc=1");
                    addnav("Run outside and let the Outpost fend for itself", "runmodule.php?module=onslaught&op=runmap");
                    addnav("Take stock of the situation", "runmodule.php?module=onslaught&op=lookaround");
                } else {
                    addnav("They just keep coming!");
                    addnav("Here comes another one!", "runmodule.php?module=onslaught&op=continue&nodesc=1");
                }
            } else {
                output("You lower your weapon, blood splattered over your clothing.  It looks like you're winning - there are no more monsters to fight just now.`n`n");
                //Display cleanup text, tart this up a bit
                addnav("Village", "village.php");
            }
        } elseif ($defeat) {
            require_once "lib/forestoutcomes.php";
            forestdefeat(array($badguy), "in an Outpost");
        } else {
            require_once "lib/fightnav.php";
            fightnav(true, true, "runmodule.php?module=onslaught&nodesc=1");
        }
    }
    page_footer();
}
function insults_roll($type)
{
    require_once "lib/bell_rand.php";
    require_once "modules/staminasystem/lib/lib.php";
    //Coarse are more predictably average, Classy can go really well or really poorly, Confusing is somewhere in the middle.
    //Insult efficacy is affected by Action level.
    if ($type == "Classy") {
        $r = bell_rand(100);
        $a = get_player_action("Insults - Classy");
        $r += $a['lvl'] / 5;
    }
    if ($type == "Confusing") {
        $r = bell_rand(10, 90);
        $a = get_player_action("Insults - Confusing");
        $r += $a['lvl'] / 5;
    }
    if ($type == "Coarse") {
        $r = bell_rand(20, 80);
        $a = get_player_action("Insults - Coarse");
        $r += $a['lvl'] / 5;
    }
    if ($r <= 0) {
        return 1;
    }
    if ($r <= 20) {
        return 2;
    }
    if ($r <= 40) {
        return 3;
    }
    if ($r <= 60) {
        return 4;
    }
    if ($r <= 80) {
        return 5;
    }
    if ($r <= 100) {
        return 6;
    }
    return 7;
}