function reqmultiplier_dohook($hookname, $args)
{
    global $session;
    switch ($hookname) {
        case "creatureencounter":
            $args['creaturegold'] = round($args['creaturegold'] * get_module_pref("multiplier"), 0);
            break;
        case "newday":
            clear_module_pref("multiplier");
            break;
    }
    return $args;
}
function referral_bonus_dohook($hookname, $args)
{
    global $session;
    switch ($hookname) {
        case "newday":
            if (get_module_pref("days") >= get_module_setting("daysperbonus")) {
                increment_module_pref("days");
                $sql = "UPDATE " . db_prefix("accounts") . " SET donation=donation+" . get_module_setting("pointsperbonus") . " WHERE acctid={$session['user']['referer']}";
                db_query($sql);
                clear_module_pref("days");
            }
            break;
    }
    return $args;
}
function watcher_quests_run()
{
    global $session;
    switch (httpget('plotpoint')) {
        case 1:
            page_header("Meanwhile, somewhere offshore...");
            output("`\$The Watcher`0 is in her control room, and about to boot her computer.  She yawns, setting her cup of tea down on the shelf next to the keyboard.  She takes a seat, puts her foot on the clutch, switches on the heating coils and presses the starter button.`n`nNothing happens.`n`n\"`7Arse,`0\" she mutters, remembering that the starter motor died a couple of days ago.  She takes a brief stroll around to the back of the computer, picking up the six-foot-long iron crank handle as she passes.`n`nWith a total electromechanical equivalent of one hundred and twenty eight kilobytes of memory, starting this three-ton supercomputer by hand requires three strong men, lots of sweat, and language that would make a sailor blush.  `\$The Watcher`0 inserts the crank handle, pushes her glasses up onto the bridge of her nose, grabs the handle, takes a firm stance and gives it a spin.`n`nThe five-litre diesel engine, currently running on used vegetable oil, coughs into life.  Its heavy, thumping compressions send little shockwaves through the floor.  `\$The Watcher`0 pulls out the crank handle, pats the computer's casing, and returns to her seat.`n`nNobody saw her start the machine, either today or yesterday.  She intends to let the technicians know about the broken starter motor, but it keeps slipping her mind.  Probably because people are already noticing little things about her.  People are already talking.  People's smiles already seem a little frozen when they wish her a good morning.  If they knew that she had just started a three-ton supercomputer by hand, the worry in their eyes might turn to naked fear, and her already-shrinking circle of close friends might just shrink a little more.  Of course, she could always lie - just go up to the technicians tomorrow morning, declare that the starter had just broken, and ask the strong tech lads to give a girl a hand.  One more little white lie probably wouldn't hurt.`n`nShe puts her foot on the clutch and wrenches the monitor into gear.  As she slowly lets the clutch up, a mounted arm begins to spin, generating a warm breeze onto `\$The Watcher`0's face.  Arranged in one straight row on the arm are a dozen flickering thumbnail-sized light bulbs.`n`n`\$The Watcher`0 noticed something was wrong about six months ago.  She was lifting herself by her arms on a pull-up bar as part of her morning exercise routine.  Her mind wandered as she listened to the waves crashing outside.  Within ten pull-ups she was remembering the hours she used to spend playing pirates with Paul Stevens, both of them no older than seven or eight.  The radio was announcing the time when she realised she'd been doing pull-ups for over an hour.`n`nAs the mounted arm spins faster and faster, words begin to form in the blur, generated by the rapidly-flickering lamps and `\$The Watcher`0's persistence of vision.  When they converge into a clear picture, `\$The Watcher`0 sets the auto-throttle and takes her foot off the clutch.`n`nEvery day that she remains near the Island, she grows stronger.  Even if she hasn't bothered to exercise, even if she's pushed herself so hard she should have been exhausted.  Even if she's stuffed her face with junk food, even if she's starved herself all day.  No matter what she does, she becomes more powerful with each passing minute.  And with every extra foot-pound of force she can generate, she feels a little more unsure of her own capacity to handle this sort of power - and a little more lonely.`n`nShe laces her fingers together, pushes them outwards with a series of satisfying cracks and pops, and begins to press keys, pull levers, push pedals.  The supercomputer responds with the clatter of a million relays and mechanical sequencers, audible even over the roar of the diesel engine.  Words and numbers appear in the air where the swinging monitor arm now spins at several thousand rotations per minute.`n`nAfter a few minutes, the analysis routine is complete.  One name appears in the list of results.  One contestant who seems to be gaining strength nearly as quickly as `\$The Watcher`0 did herself.  One person who might, perhaps, understand what is happening to `\$The Watcher`0.  One person with whom she could potentially share a secret.`n`n\"`7%s`7... Huh.  Bit of a funny name,`0\" says `\$The Watcher`0 quietly, \"`7but I'll be watching you.`0\"", $session['user']['name']);
            set_module_pref("plotpoint1", 1);
            addnav("Continue");
            addnav("Get on with it", "village.php");
            break;
        case 2:
            page_header("Something Improbable!");
            output("`0As you head into the Outpost, something big and black appears in front of you, moving at speed.  It impacts on your face, knocking you on your back.  As you push yourself up onto your elbows, you try to make sense of what just happened.`n`nYou're not `ientirely`i sure, but you think... as strange as it sounds... it might have been someone's arse.`n`nYou replay the scene - yup.  Someone's arse, in a black skirt.  You only know one person on this Island who wears a black skirt.`n`n`\$The Watcher`0 - or at least, the top half of her - leans out of the air.  Her bespectacled eyes lock onto yours, and her face lights up in a huge grin.  \"`7Hey, it's you!  Well, isn't this a coincidence!`0\"  She reaches out to you.  You extend a hand, ready for her to help you up and, perhaps, explain where her legs are - and why she just beat you to the ground with her now-invisible posterior.`n`nNothing of the sort happens.  Instead, `\$The Watcher`0 expertly steals a cigarette from your pocket, lights it, gives you a cheery wink and leans back, disappearing right before your eyes.`n`nYou lie for a moment, staring at the space she just occupied.`n`n\"`#RIGHT THEN!`0\" you cry, in the vain hope that `\$The Watcher`0 can still hear you.  Birds scatter from the trees.  \"`#So THAT'S the sort of day this is going to be!  OKAY!  Thanks for the heads-up!`0\"  You get to your feet.  \"`#I'll expect to be mugged by a floating pair of boobs any second now!`0\"`n`nA passing contestant looks your way, lip curled up in distaste.  \"`2Weirdo,`0\" she mutters, before continuing on her way.");
            set_module_pref("plotpoint2", 1);
            $session['user']['gems']--;
            addnav("Damn it.");
            addnav("Dust yourself off and head into the Outpost", "village.php");
            break;
        case 3:
            page_header("The Deal with the Turtleneck");
            output("\"`&What?`0\"`n`n\"`#I mean... um.\"  You swallow.  \"`#The turtleneck.  It seems that every time I see you, you're... well, it's the red turtleneck, every time.  I mean... aren't you a bit hot, in that?`0\"`n`n`\$The Watcher`0 frowns at you for a moment.  Then she smiles, sits back in her chair and chuckles softly.  \"`&Well, it's pretty much all marketing, mate.`0\"`n`n\"`#Marketing?`0\"`n`n`\$The Watcher`0 leans forwards, pushing her glasses up onto her nose.  \"`&Well, you see, it's like this.  Since this particular artform was created, women in my line of work have been expected to fall into one of two categories.  We're either useless pansies whose only function is to be kidnapped and then saved by powerful men; or, we're strong, capable warriors with amazing bodies.  But if you go for being strong and capable, you're expected to have a regrettable tendency to wear `ipreposterously`i impractical armour.  Since I didn't think I'd suit the \"useless pansy\" trope, I decided to opt for the latter anyway.`0\"`n`nYou blink.  You open your mouth, then close it again and choose your words carefully, sensing an awkward discussion in your near future - one that would probably, sooner or later, end up revolving around chainmail bikinis.  \"`#...preposterously impractical armour?`0\"`n`n\"`&A calf-length black skirt and a turtleneck?  In `ithis`i weather?`0\"`n`n\"`#Oh.`0\"`n`n\"`&It's a bloody `inylon`i skirt, too.  You wouldn't believe the amount of static electricity this thing generates.  I suppose I could top it all off with a black leather jacket, or a nice knitted scarf, if I wanted to go the whole hog.  But honestly, my heart just isn't in it.`0\"`n`n\"`#Yeah, that would be... yeah.`0\"  Something nags at you.  \"`#You mentioned something... you said \"since this artform was created.\"  Which artform is that, exactly?`0\"`n`n`\$The Watcher`0 frowns.  \"`&Televised post-EMP warfare.`0\"  She laughs.  \"`7What did you `ithink`i I was talking about?`0\"`n`n\"`#Never mind.`0\"`n`n\"`&I draw the line at the boots, though.  You've got to have practical boots.`0\"  She leans back and a pair of steel-toed black leather monoliths clomp onto the desk.  \"`&I mean, technically these are bloke's boots, but I've always had quite broad feet, and I find men's boots tend to hold up better than women's and I'm `ibabbling`i, aren't I.`0\"`n`nIt wasn't phrased as a question.  `\$The Watcher`0 looks down at her boots, and there's a somewhat awkward pause.  \"`#Not really,`0\" you say.`n`n\"`&It felt like it.`0\"  With a heavy `ithump,`i she sets her feet back onto the floor.  \"`&To me, anyway... it's kinda hard to tell, really.  Sorry.`0\"  She toys distractedly with a pen.  \"`&My conversation skills are rusty because nobody talks to me.`0\"`n`nThere was something very disconcerting about the way she said that last sentence.  Not whining; not complaining; not even seeking interaction, really.  Just stating a fact.  Symptom and cause.  Like it's something she's gotten thoroughly used to.`n`n\"`#Really?`0\"`n`n\"`&Yes.  I suppose people must think of me like they think of, oh, I don't know... let's say an undertaker, or a repairman, or... or an angry boss, or something.  Contract says I've gotta give you guys a rough time down here in the Pits, but...  Most of it is just for show, and it doesn't give much room for creativity, and when you live on a boat and you do a boring job, you don't end up with much to talk about on the rare occasions when someone `idoes`i come along and try to engage you.  It's just the same damned thing, day after day.  Honestly sometimes I feel like I'm `iprogrammed`i to do this stuff.`0\"`n`nThere's another awkward pause.  You wonder how you got here from turtlenecks.`n`n\"`&I mean, I tried, like, wearing weird necklaces and stuff,`0\" `\$The Watcher`0 continues.  \"`&You know, you wear something old or unusual or interesting, it's like a conversation prop, sort of thing.  Sooner or later somebody's gonna come along and say \"Hey, that's an interesting... thing,\" and you tell the story, and... well, it's a `istart,`i you know?  But that doesn't work when you're contractually obliged to scowl at people, and even if you weren't... people don't feel too talkative when they're beaten half to death and running on adrenaline.`0\"  She looks up at you.  \"`&I'm glad to see you're still managing to be sociable.`0\"`n`nYou smile nervously.  It's the only way you can smile, right now.  \"`#I try my best.`0\"`n`n`\$The Watcher`0 gives a little nervous laugh, and glances back towards a monitor.  \"`&Sorry.  Listen to me going on about my problems like I don't have a Retraining Vessel to run.  It's just I only ever see people when something goes wrong, y'know?`0\"`n`nYou sense yourself edging over a precipice.  Unable to stop yourself, the words are out of your mouth before you've had a chance to consider what you're letting yourself in for.`n`n\"`#Well, drop me a line sometime when things `iaren't`i going wrong.`0\"`n`n`\$The Watcher`0 looks back up at you.  She shows a little hopeful grin, and rests her chin on her hand.  \"`&Yeah?`0\"`n`n\"`#Yeah,`0\" you say, feeling your future changing as you speak.  \"`#We'll go get a beer or something.`0\"`n`n`\$The Watcher`0's grin spreads wider.  \"`&Heaven knows I could use one.`0\"`n`nYou smile at each other for a moment.  `\$The Watcher`0's smile is warm, relieved, and joyful.  Your own smile is doing a really, really good job of emulating hers.`n`n\"`&The only way to get here is to be knocked out,`0\" says `\$The Watcher`0.  \"`&So I'll come and see you, instead.`0\"  You suspect she's thinking something like `iI made a friend!  We'll talk about monsters and shotguns and boots and everything!`i  \"`&I'll drop you a line, like you say.`0\"`n`n\"`#Great,`0\" you reply.  \"`#I'll look forward to it.`0\"`n`n\"`&I'm gonna let you get back to the mainland, now.  Thanks for talking to me.  Only...`0\"`n`n\"`#Yes?`0\"`n`n\"`&Sorry in advance for the gas.  I've got to keep up appearances.  Network might be watching.`0\"`n`nYou nod.  \"`#Okay.`0\"`n`n\"`&Try to look surprised.`0\"  She leaps out of her chair, slams her hands down on the desk, and ejects the vapour into your face with a sound like a hissing cat.  You collapse gently to the floor, wondering how the hell you've managed to make such a dangerous friend.");
            addnav("What have you gotten yourself into?");
            addnav("Return to Improbable Island", "shades.php");
            $session['user']['resurrections']++;
            $session['user']['hitpoints'] = $session['user']['maxhitpoints'];
            $buffs = unserialize(get_module_pref("bufflist", "alternativeresurrect"));
            if (is_array($buffs)) {
                foreach ($buffs as $buff => $values) {
                    apply_buff($buff, $values);
                }
            }
            clear_module_pref("bufflist", "alternativeresurrect");
            set_module_pref("plotpoint3", 1);
            break;
    }
    page_footer();
}
function hundredpointrally_winrally()
{
    //run this when a player has won a rally
    //todo: actually win the rally, award cigs and so forth
    global $session;
    $data = unserialize(get_module_setting("data", "hundredpointrally"));
    //first, award the player with their cigarettes
    $session['user']['gems'] += $data['current']['jackpot'];
    output("You won %s Cigarettes!`n`n", $data['current']['jackpot']);
    $next = time();
    $next += 86400;
    $data['next']['starttime'] = $next;
    require_once "lib/systemmail.php";
    //notify players in this rally that it's over
    foreach ($data['current']['competitors'] as $key => $vals) {
        $to = $key;
        $subj = "The Hundred-Point Rally has ended!";
        $body = "This is just a quick message to let you know that the Hundred-Point Rally has been won!  " . $session['user']['name'] . " finished all one hundred points first, and takes home " . $data['current']['jackpot'] . " Cigarettes as the prize.  The next Rally starts in 24 hours!";
        systemmail($to, $subj, $body);
        //clear their prefs
        clear_module_pref("data", "hundredpointrally", $to);
    }
    //close this rally
    $data['current']['open'] = 0;
    $data['current']['endtime'] = time();
    //notify players signed up for the next rally that a start time has been chosen
    if (is_array($data['next']['competitors']) && count($data['next']['competitors']) > 1) {
        foreach ($data['next']['competitors'] as $key => $vals) {
            $to = $key;
            $subj = "The next Hundred-Point Rally begins in 24 hours!";
            $body = "This is just a quick message to let you know that the starting time for the next Hundred-Point Rally has been set!  The next Rally will begin 24 hours from when you get this message!";
            systemmail($to, $subj, $body);
        }
    }
    set_module_setting("data", serialize($data), "hundredpointrally");
}
<?php

global $session;
$hid = httpget('hid');
require_once "modules/improbablehousing/lib/lib.php";
$house = improbablehousing_gethousedata($hid);
//Run through the rooms and make sure the player isn't registered as being in them or sleeping in them
if (is_array($house['data']['rooms'])) {
    foreach ($house['data']['rooms'] as $rkey => $rvals) {
        if (isset($rvals['sleepslots'])) {
            foreach ($rvals['sleepslots'] as $skey => $svals) {
                if ($svals['occupier'] == $session['user']['acctid']) {
                    unset($house['data']['rooms'][$rkey]['sleepslots'][$skey]['occupier']);
                }
            }
        }
        if (isset($rvals['occupants'])) {
            foreach ($rvals['occupants'] as $okey => $ovals) {
                if ($okey == $session['user']['acctid']) {
                    unset($house['data']['rooms'][$rkey]['occupants'][$okey]);
                }
            }
        }
    }
    improbablehousing_sethousedata($house);
}
//set the player's world map location, just in case...
set_module_pref("worldXYZ", $house['location'], "worldmapen");
$session['user']['location'] = "World";
clear_module_pref("sleepingat", "improbablehousing");
redirect("runmodule.php?module=worldmapen&op=continue");
function racejoker_dohook($hookname, $args)
{
    //yeah, the $resline thing is a hack.  Sorry, not sure of a better way
    // to handle this.
    // Pass it as an arg?
    global $session, $resline;
    $city = "AceHigh";
    $race = "Joker";
    switch ($hookname) {
        case "racenames":
            $args[$race] = $race;
            break;
        case "changesetting":
            // Ignore anything other than villagename setting changes
            if ($args['setting'] == "villagename" && $args['module'] == "racejoker") {
                if ($session['user']['location'] == $args['old']) {
                    $session['user']['location'] = $args['new'];
                }
                $sql = "UPDATE " . db_prefix("accounts") . " SET location='" . addslashes($args['new']) . "' WHERE location='" . addslashes($args['old']) . "'";
                db_query($sql);
                if (is_module_active("cities")) {
                    $sql = "UPDATE " . db_prefix("module_userprefs") . " SET value='" . addslashes($args['new']) . "' WHERE modulename='cities' AND setting='homecity'" . "AND value='" . addslashes($args['old']) . "'";
                    db_query($sql);
                }
            }
            break;
        case "chooserace":
            if ($session['user']['dragonkills'] < 12) {
                break;
            }
            output("`0You grin, and pull a six-sided die from your left ear.  <a href='newday.php?setrace={$race}{$resline}'>\"Well, let's see, shall we?\"</a>`n`n", true);
            addnav("`&Joker`0", "newday.php?setrace={$race}{$resline}");
            addnav("", "newday.php?setrace={$race}{$resline}");
            break;
        case "setrace":
            if ($session['user']['race'] == $race) {
                output("The gatekeeper's smile doesn't go away.  Instead, it freezes, locks carefully into place - and the gatekeeper begins to pray that he can persuade it to stay there until you go away, or at least until your eyes stop doing that `@green glowy thing`0.  \"`6Yes,`0\" he says, carefully.  \"`6Yes, that would be fine.`0\"`n`nYou roll your die.  It skitters along, making a clattering sound like bone on wood.  The fact that it's still four feet above the ground doesn't seem to faze the gatekeeper, or if it does, he's very good at not letting it show.`n`nIt finally comes to rest, seven spots facing the sun.  You look up and grin, teeth white and gleaming and not entirely friendly.  \"`#It seems I am a Joker!`0\" you exclaim in a breathy growl.`n`nThe gatekeeper nods, and picks up his journal.  \"`6Very good.  As you say.  Jay.  Oh.  Kay.  Are.  Ee.  Joker.  All done.`0\"  He looks up, to see you preparing to roll your die again.  He opens his mouth to ask you what you're doing, and bites his tongue.  Never ask what a Joker is doing; they might tell you.`n`nYou roll your die.  It skitters along the invisible table, bounces against an invisible wall, and comes up at two.`n`n\"`#Shame,`0\" you say.  \"`#You would have been more interesting with some additional eyes.  Still, if the die says two are enough, then who am I to disagree?`0\"`n`nYou give the gatekeeper a grin and a wink, and head into the outpost.`n`nA minute later, he remembers to exhale.  He shudders and puts the kettle on, hoping that it isn't going to turn out to be one of `ithose`i days.");
                if (is_module_active("cities")) {
                    set_module_pref("homecity", $city, "cities");
                    if ($session['user']['age'] == 0) {
                        $session['user']['location'] = $city;
                    }
                }
            }
            break;
        case "startofround-prebuffs":
            if ($session['user']['race'] == $race && $session['user']['alive']) {
                $chain = unserialize(get_module_pref("chain"));
                if (!is_array($chain)) {
                    $chain = array();
                }
                $suit = httpget("suit");
                if (!$suit) {
                    $suit = e_rand(1, 4);
                }
                switch ($suit) {
                    case 1:
                        $chain[] = "heart";
                        break;
                    case 2:
                        $chain[] = "diamond";
                        break;
                    case 3:
                        $chain[] = "spade";
                        break;
                    case 4:
                        $chain[] = "club";
                        break;
                }
                $hearts = 0;
                $diamonds = 0;
                $spades = 0;
                $clubs = 0;
                $num = 0;
                output("You draw a card from your rather Improbable deck, and add it to your hand.`n");
                foreach ($chain as $card) {
                    rawoutput("<img src=\"images/" . $card . ".png\">");
                    switch ($card) {
                        case "heart":
                            $hearts++;
                            break;
                        case "diamond":
                            $diamonds++;
                            break;
                        case "spade":
                            $spades++;
                            break;
                        case "club":
                            $clubs++;
                            break;
                    }
                    $num++;
                }
                output_notl("`n");
                if ($hearts == $num || $diamonds == $num || $spades == $num || $clubs == $num) {
                    if ($num > 1) {
                        output("`0With a grin you realise that all your cards match up - Joker tradition now allows you to expand your hand by one card!`n");
                    }
                } else {
                    if ($num > 1) {
                        output("`0The bottom card from your hand vanishes.`n");
                    }
                    array_shift($chain);
                }
                set_module_pref("chain", serialize($chain));
                //calculate and award buffs
                $bhearts = round($session['user']['maxhitpoints'] / 100 * e_rand($hearts * $hearts * $hearts / 100, $hearts * $hearts * $hearts / 5));
                $bdiamonds = e_rand($diamonds, $diamonds * $diamonds);
                $bspades = $spades * $spades * $spades * 0.005 + 1;
                $bclubs = $clubs * $clubs * $clubs * 0.005 + 1;
                if ($bhearts > 1) {
                    apply_buff("Hearts", array("regen" => $bhearts, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => 1, "expireafterfight" => 1, "effectmsg" => "The mysterious power of your Hearts aura causes you to regenerate {damage} hitpoints...`0", "schema" => "module-racejoker"));
                }
                if ($bdiamonds > 0) {
                    if ($bdiamonds == 1) {
                        output("`@The reward hopper mounted to the closest camera is briefly enveloped in crackling green lightning.  You step back and deftly catch the single Requisition token that clatters out of it, before heading straight back into the fight!`0`n");
                    } else {
                        output("`@The reward hopper mounted to the closest camera is briefly enveloped in crackling green lightning.  You step back and deftly catch the `b%s`b Requisition tokens that pour out of it, before heading straight back into the fight!`0`n", $bdiamonds);
                    }
                    $session['user']['gold'] += $bdiamonds;
                }
                if ($bspades > 1) {
                    apply_buff("Spades", array("defmod" => $bspades, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => 1, "startmsg" => "You feel an aura of protection gathering around you!", "expireafterfight" => 1, "roundmsg" => "Thanks to the power of the Spades suit, {badguy} is having trouble hitting you!", "schema" => "module-racejoker"));
                }
                if ($bclubs > 1) {
                    apply_buff("Clubs", array("atkmod" => $bclubs, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => 1, "startmsg" => "You feel a burning energy in your muscles...", "expireafterfight" => 1, "roundmsg" => "Thanks to the power of the Clubs suit, your attacks are more powerful!", "schema" => "module-racejoker"));
                }
            }
            break;
            // case "alternativeresurrect":
        // case "alternativeresurrect":
        case "stamina-newday":
            if ($session['user']['race'] == $race) {
                clear_module_pref("chain");
                racejoker_checkcity();
                //new Joker grenade -> improbabombs routine
                $bandolier = 0;
                $blprefs = array("inventorylocation" => "fight");
                $bandolier += has_item_quantity("banggrenade", $blprefs);
                $bandolier += has_item_quantity("whoomphgrenade", $blprefs);
                $bandolier += has_item_quantity("zapgrenade", $blprefs);
                $count = 0;
                $count += delete_all_items_of_type("banggrenade");
                $count += delete_all_items_of_type("whoomphgrenade");
                $count += delete_all_items_of_type("zapgrenade");
                if ($count) {
                    output("`0All of your Grenades have turned into Improbability Bombs overnight.  Well, that's what happens when you store explosives around such high levels of Improbability.`n");
                    $backpack = $count - $bandolier;
                    for ($i = 0; $i < $backpack; $i++) {
                        give_item("improbabilitybomb");
                    }
                    for ($i = 0; $i < $bandolier; $i++) {
                        give_item("improbabilitybomb", $blprefs);
                    }
                }
                //Combat buffs
                $jokerattack = e_rand(1, 20) / 10;
                $jokerdefence = e_rand(1, 20) / 10;
                $jokerregen = 0;
                $jokerregenchance = e_rand(1, 100);
                if ($jokerregenchance > 80) {
                    $jokerregen = 5 - e_rand(1, 10);
                }
                apply_buff("joker", array("name" => "Joker Bonus - Improbability", "atkmod" => $jokerattack, "defmod" => $jokerdefence, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racejoker"));
                if ($jokerregen < 0) {
                    output("`n`&Today is a bad day.  Your internal organs appear to have shifted themselves into a rather unfortunate configuration.  Internal bleeding will cause you to lose some hitpoints with every round of battle.`n`0");
                    apply_buff("jokerregen", array("regen" => $jokerregen, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "effectmsg" => "`3Your internal bleeding causes you to lose {damage} hitpoints.`0", "schema" => "module-racejoker"));
                }
                if ($jokerregen > 0) {
                    output("`n`&Today is a good day.  You appear to have discovered the secret of cellular regeneration.  You will gain hitpoints in every battle.`n`0");
                    apply_buff("jokerregen", array("regen" => $jokerregen, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "effectmsg" => "`3Your accelerated cellular regeneration causes you to gain {damage} hitpoints.`0", "schema" => "module-racejoker"));
                }
                $c1 = e_rand(10, 200) / 100;
                $c2 = e_rand(10, 200) / 100;
                $c3 = e_rand(10, 200) / 100;
                $c4 = e_rand(10, 200) / 100;
                $c5 = e_rand(10, 200) / 100;
                $e1 = e_rand(10, 200) / 100;
                $e2 = e_rand(10, 200) / 100;
                $e3 = e_rand(10, 200) / 100;
                $e4 = e_rand(10, 200) / 100;
                $e5 = e_rand(10, 200) / 100;
                //Stamina Buffs
                require_once "modules/staminasystem/lib/lib.php";
                apply_stamina_buff('joker1', array("name" => "Joker Improbability Modifier: Travelling", "class" => "Travelling", "costmod" => $c1, "expmod" => $e1, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                apply_stamina_buff('joker2', array("name" => "Joker Improbability Modifier: Cooking and Carcass Cleaning", "class" => "Meat", "costmod" => $c2, "expmod" => $e2, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                apply_stamina_buff('joker3', array("name" => "Joker Improbability Modifier: Hunting", "class" => "Hunting", "costmod" => $c3, "expmod" => $e3, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                apply_stamina_buff('joker4', array("name" => "Joker Improbability Modifier: Combat", "class" => "Combat", "costmod" => $c4, "expmod" => $e4, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                apply_stamina_buff('joker5', array("name" => "Joker Improbability Modifier: ScrapBots", "class" => "ScrapBots", "costmod" => $c5, "expmod" => $e5, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
            }
            break;
        case "validforestloc":
        case "validlocation":
            if (is_module_active("cities")) {
                $args[$city] = "village-{$race}";
            }
            break;
        case "moderate":
            if (is_module_active("cities")) {
                tlschema("commentary");
                $args["village-{$race}"] = sprintf_translate("City of %s", $city);
                tlschema();
            }
            break;
        case "villagetext":
            racejoker_checkcity();
            if ($session['user']['location'] == $city) {
                $args['text'] = array("`0You are standing in the heart of AceHigh.  Though relatively new, this town seems to be prospering.  The houses are built of stone and timber frames, and well-dressed gentlemen and ladies stroll about with impeccable manners.  Every now and then, one of them explodes in an astonishing flash of green light, drawing polite applause from those nearby.`n`n");
                $args['schemas']['text'] = "module-racejoker";
                $args['clock'] = "`0The great clockwork readout at the centre of the city reads `&%s`0.`n`n";
                $args['schemas']['clock'] = "module-racejoker";
                if (is_module_active("calendar")) {
                    $args['calendar'] = "`0A smaller contraption next to it reads `&%s`0, `&%s %s %s`0.`n`n";
                    $args['schemas']['calendar'] = "module-racejoker";
                }
                $args['title'] = array("%s, Home of the Jokers", $city);
                $args['schemas']['title'] = "module-racejoker";
                $args['sayline'] = "says";
                $args['schemas']['sayline'] = "module-racejoker";
                $args['talk'] = "`0Nearby some people converse politely:`n";
                $args['schemas']['talk'] = "module-racejoker";
                $new = get_module_setting("newest-{$city}", "cities");
                if ($new != 0) {
                    $sql = "SELECT name FROM " . db_prefix("accounts") . " WHERE acctid='{$new}'";
                    $result = db_query_cached($sql, "newest-{$city}");
                    $row = db_fetch_assoc($result);
                    $args['newestplayer'] = $row['name'];
                    $args['newestid'] = $new;
                } else {
                    $args['newestplayer'] = $new;
                    $args['newestid'] = "";
                }
                if ($new == $session['user']['acctid']) {
                    $args['newest'] = "`n`0As you wander your new home, you feel your jaw dropping at the wonders around you.";
                } else {
                    $args['newest'] = "`n`0Wandering the village, jaw agape, is `&%s`0.";
                }
                $args['schemas']['newest'] = "module-racejoker";
                $args['section'] = "village-{$race}";
                $args['stablename'] = "Mike's Chop Shop";
                $args['schemas']['stablename'] = "module-racejoker";
                $args['gatenav'] = "Village Gates";
                $args['schemas']['gatenav'] = "module-racejoker";
                unblocknav("stables.php");
            }
            break;
    }
    return $args;
}
 case "unblock":
     $ublo = get_module_pref('blocked');
     $my = explode(',', $ublo);
     $str = "";
     foreach ($my as $val) {
         if ($val == $target) {
         } else {
             $str .= $val . ",";
             if ($val > 0) {
                 $count++;
             }
         }
     }
     set_module_pref('blocked', $str);
     if ($count == 0) {
         clear_module_pref("blocked");
     }
     output("`^You have chosen to unblock `%%s`^. They will receive a notice that you have unblocked them.  If the need arises you may block them again at any time.", $name);
     break;
 case "block":
     //Blocking is the same as shunning AND ignoring along with preventing the blocked player from flirting anymore
     $blo = get_module_pref('blocked');
     $my = explode(',', $blo);
     $str = "";
     foreach ($my as $val) {
         if ($val != '') {
             if ($val == $target) {
                 $done = 1;
             } else {
                 $str .= $val . ",";
             }
function rail_ironhorse_cleanup($hid)
{
    // code here is copied from exit.php in improbablehousing/run.
    // the train extracts the player from the station dwelling
    //   so we need to remove all traces that they were there.
    global $session;
    $house = improbablehousing_gethousedata($hid);
    // Run through the rooms and make sure the player isn't registered as
    // being in them or sleeping in them
    foreach ($house['data']['rooms'] as $rkey => $rvals) {
        if (isset($rvals['sleepslots'])) {
            foreach ($rvals['sleepslots'] as $skey => $svals) {
                if ($svals['occupier'] == $session['user']['acctid']) {
                    unset($house['data']['rooms'][$rkey]['sleepslots'][$skey]['occupier']);
                }
            }
        }
        if (isset($rvals['occupants'])) {
            foreach ($rvals['occupants'] as $okey => $ovals) {
                //				output("`0Occupant %s: %s`0`n",$okey,$house['data']['rooms'][$rkey]['occupants'][$okey]);
                //				output("okey..%s, acctid..%s`n",$okey,$session['user']['acctid']);
                if ($okey == $session['user']['acctid']) {
                    //					output("- unset`n");
                    unset($house['data']['rooms'][$rkey]['occupants'][$okey]);
                }
            }
        }
    }
    improbablehousing_sethousedata($house);
    clear_module_pref("sleepingat", "improbablehousing");
    return true;
}
function racerobot_dohook($hookname, $args)
{
    global $session, $resline;
    $city = "Cyber City 404";
    $race = "Robot";
    switch ($hookname) {
        case "load_inventory":
            if ($session['user']['race'] == $race) {
                foreach ($args as $itemid => $prefs) {
                    if ($prefs['blockrobot']) {
                        $args[$itemid]['blockuse'] = true;
                    }
                }
            }
            break;
        case "racenames":
            $args[$race] = $race;
            break;
        case "changesetting":
            // Ignore anything other than villagename setting changes
            if ($args['setting'] == "villagename" && $args['module'] == "racerobot") {
                if ($session['user']['location'] == $args['old']) {
                    $session['user']['location'] = $args['new'];
                }
                $sql = "UPDATE " . db_prefix("accounts") . " SET location='" . addslashes($args['new']) . "' WHERE location='" . addslashes($args['old']) . "'";
                db_query($sql);
                if (is_module_active("cities")) {
                    $sql = "UPDATE " . db_prefix("module_userprefs") . " SET value='" . addslashes($args['new']) . "' WHERE modulename='cities' AND setting='homecity'" . "AND value='" . addslashes($args['old']) . "'";
                    db_query($sql);
                }
            }
            break;
        case "chooserace":
            if ($session['user']['dragonkills'] < 7) {
                break;
            }
            clear_module_pref("heat");
            clear_module_pref("atk");
            clear_module_pref("def");
            clear_module_pref("heal");
            output("`0<a href='newday.php?setrace={$race}{$resline}'>You grin at the gatekeeper</a>, exposing your sharp, bitey metal teeth.`n`n", true);
            addnav("`&Robot`0", "newday.php?setrace={$race}{$resline}");
            addnav("", "newday.php?setrace={$race}{$resline}");
            break;
        case "setrace":
            if ($session['user']['race'] == $race) {
                output("\"`6Oh, I see, right,`0\" says the gatekeeper, and takes out his ledger.  \"`6Are, oh, double-you, bee, oh, tee, tee.  Robot.  I must say, it's nice to see some straightforward logic in this place.`0\"`n`nYou nod.  \"`#Yes,`0\" you reply, \"`#it is.`0\"`n`nThe gatekeeper looks up and says, with a mischievous grin, \"`6So - would you like to play a game of chess?`0\"`n`nYou scowl.  \"`#Do not play games with me, human.  Just because you know how to press my buttons does not mean I will allow you to press them.`0\"`n`n\"`6Sorry,`0\" says the gatekeeper with an even wider smile, \"`6I meant - SUDO play a game of chess.`0\"`n`n\"`#I'd love to,`0\" you reply.`n`nAfter you checkmate the gatekeeper in three moves, he sits back, obviously miffed.`n`n\"`#As I won,`0\" you say, \"`#you must answer my question: what is this \"love\" of which you humans speak?`0\"`n`nThe gatekeeper looks up at you, pouting, arms folded.  \"`6This statement is false.`0\"`n`nYou twitch a little, let out a quiet, sad \"`#beep,`0\" and fall over onto your back.`n`nWhen you regain consciousness, you draw yourself up to your full height and stare the grinning gatekeeper in the face.  \"`#I have processed all the relevant data,`0\" you say, in a low, mechanical growl, \"`#and have come to the conclusion that you, fleshbag, are a bastard.`0\"`n`nThe gatekeeper winks and smiles.  \"`6Don't tell the others.`0\"`n`nYou turn and head towards the gate, muttering under your breath.`n`n\"`6Pi is exactly three, by the way!`0\" he calls after you.  But you're too wily for him, oh yes indeed.  Just two minutes later, you reboot successfully and place him on your \"ignore\" list.");
                if (is_module_active("cities")) {
                    set_module_pref("homecity", $city, "cities");
                    if ($session['user']['age'] == 0) {
                        $session['user']['location'] = $city;
                    }
                }
            }
            break;
        case "alternativeresurrect":
            if ($session['user']['race'] == $race) {
                racerobot_checkcity();
                set_module_pref("heat", 0);
                //Stamina buffs
                require_once "modules/staminasystem/lib/lib.php";
                apply_stamina_buff('robot3', array("name" => "Robot Bonus: Fast-Moving and Fast-Learning", "action" => "Global", "costmod" => 0.7, "expmod" => 1.2, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                //combat buffs
                apply_buff("robotatk", array("name" => "`7Robot Bonus: Stabbity Claws`0", "atkmod" => "1.3", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                apply_buff("robotdef", array("name" => "`7Robot Penalty: Glass Skin`0", "defmod" => "0.4", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                if (get_module_pref("atk") > 0) {
                    $atk = get_module_pref("atk") / 10 + 1;
                    apply_buff("robotatkoc", array("name" => "`7Overclock: Increased Upper Body Servo Power`0", "atkmod" => $atk, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                }
                if (get_module_pref("def") > 0) {
                    $def = get_module_pref("def") / 10 + 1;
                    apply_buff("robotdefoc", array("name" => "`7Overclock: Increased Lower Body Servo Power`0", "defmod" => $def, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                }
                if (get_module_pref("heal") > 0) {
                    $heal = get_module_pref("heal");
                    apply_buff("robothealoc", array("name" => "`7Overclock: In-Combat Self-Repair Subsystem`0", "regen" => $heal, "effectmsg" => "`#SYSTEM MESSAGE: {damage} POINTS OF DAMAGE AUTO-REPAIRED`0", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                } else {
                    strip_buff("robothealoc");
                }
            }
            break;
        case "stamina-newday":
            if ($session['user']['race'] == $race) {
                racerobot_checkcity();
                set_module_pref("heat", 0);
                increment_module_pref("amber", -200000, "staminasystem");
                //Stamina buffs
                require_once "modules/staminasystem/lib/lib.php";
                apply_stamina_buff('robot3', array("name" => "Robot Bonus: Fast-Moving and Fast-Learning", "action" => "Global", "costmod" => 0.7, "expmod" => 1.2, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                apply_stamina_buff('raceclassy', array("name" => "Robot Penalty: Insults Incompetence", "class" => "Insults", "costmod" => 2, "expmod" => 0.5, "rounds" => -1, "roundmsg" => "", "wearoffmsg" => ""));
                //combat buffs
                apply_buff("robotatk", array("name" => "`7Robot Bonus: Stabbity Claws`0", "atkmod" => "1.3", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                apply_buff("robotdef", array("name" => "`7Robot Penalty: Glass Skin`0", "defmod" => "0.4", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                if (get_module_pref("atk") > 0) {
                    $atk = get_module_pref("atk") / 10 + 1;
                    apply_buff("robotatkoc", array("name" => "`7Overclock: Increased Upper Body Servo Power`0", "atkmod" => $atk, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                }
                if (get_module_pref("def") > 0) {
                    $def = get_module_pref("def") / 10 + 1;
                    apply_buff("robotdefoc", array("name" => "`7Overclock: Increased Lower Body Servo Power`0", "defmod" => $def, "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                }
                if (get_module_pref("heal") > 0) {
                    $heal = get_module_pref("heal");
                    apply_buff("robothealoc", array("name" => "`7Overclock: In-Combat Self-Repair Subsystem`0", "regen" => $heal, "effectmsg" => "`#SYSTEM MESSAGE: {damage} POINTS OF DAMAGE AUTO-REPAIRED`0", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => -1, "schema" => "module-racerobot"));
                } else {
                    strip_buff("robothealoc");
                }
            }
            break;
        case "validforestloc":
        case "validlocation":
            if (is_module_active("cities")) {
                $args[$city] = "village-{$race}";
            }
            break;
        case "moderate":
            if (is_module_active("cities")) {
                tlschema("commentary");
                $args["village-{$race}"] = sprintf_translate("City of %s", $city);
                tlschema();
            }
            break;
        case "villagetext":
            racerobot_checkcity();
            if ($session['user']['location'] == $city) {
                $args['text'] = array("`0You are standing in the heart of %s.  Though called a city by outsiders, this stronghold of robots is little more than a glorified scrapyard.  Puddles of rusted, oily water cover the bare, muddy earth, and piles of scrap metal lie here and there.  Some residents are engaged in stilted, mechanical conversation around the well in the village square.`n", $city, $city);
                $args['schemas']['text'] = "module-racerobot";
                $args['clock'] = "`n`0The great clockwork readout at the centre of the city reads `&%s`0.`n";
                $args['schemas']['clock'] = "module-racerobot";
                if (is_module_active("calendar")) {
                    $args['calendar'] = "`n`0A smaller contraption next to it reads `&%s`0, `&%s %s %s`0.`n";
                    $args['schemas']['calendar'] = "module-racerobot";
                }
                $args['title'] = array("%s, Home of the Robots", $city);
                $args['schemas']['title'] = "module-racerobot";
                $args['sayline'] = "says";
                $args['schemas']['sayline'] = "module-racerobot";
                $args['talk'] = "`n`&Nearby some robots talk:`n";
                $args['schemas']['talk'] = "module-racerobot";
                $new = get_module_setting("newest-{$city}", "cities");
                if ($new != 0) {
                    $sql = "SELECT name FROM " . db_prefix("accounts") . " WHERE acctid='{$new}'";
                    $result = db_query_cached($sql, "newest-{$city}");
                    $row = db_fetch_assoc($result);
                    $args['newestplayer'] = $row['name'];
                    $args['newestid'] = $new;
                } else {
                    $args['newestplayer'] = $new;
                    $args['newestid'] = "";
                }
                if ($new == $session['user']['acctid']) {
                    $args['newest'] = "`n`0As you wander your new home, you feel your jaw dropping at the wonders around you.";
                } else {
                    $args['newest'] = "`n`0Wandering the village, jaw agape, is `&%s`0.";
                }
                $args['schemas']['newest'] = "module-racerobot";
                $args['section'] = "village-{$race}";
                $args['stablename'] = "Mike's Chop Shop";
                $args['schemas']['stablename'] = "module-racerobot";
                $args['gatenav'] = "Village Gates";
                $args['schemas']['gatenav'] = "module-racerobot";
                unblocknav("stables.php");
            }
            break;
        case "stabletext":
            if ($session['user']['location'] != $city) {
                break;
            }
            $args['title'] = "Mike's Chop Shop";
            $args['schemas']['title'] = "module-racerobot";
            $args['desc'] = array("`0Just outside the outskirts of the mighty scrapyard, a training area and riding range has been set up.", "You can see a tall, spindly Robot whose name you assume to be Mike.  He's busily tending to his flock of abominations, using his many custom-built appendages to care for the creatures and machines in his care.  Vehicles, animals, and Genetically-Engineered Beasts of Burden are arrayed in front of you.", array("As you approach, \"Mike\" spins around to meet you, brandishing a screwdriver.  \"`^HOW MAY I HELP YOU MY FINE YOUNG %s?`0\" he asks in a buzzing, 8-bit monotone.", translate_inline($session['user']['sex'] ? 'LASS' : 'LAD', 'stables')));
            $args['schemas']['desc'] = "module-racerobot";
            $args['lad'] = "friend";
            $args['schemas']['lad'] = "module-racerobot";
            $args['lass'] = "friend";
            $args['schemas']['lass'] = "module-racerobot";
            $args['nosuchbeast'] = "`0\"`^I DO NOT STOCK ANY SUCH BEAST OR MACHINE.  PERHAPS IT WAS A DREAM OF YOURS`0\", Mike says apologetically.";
            $args['schemas']['nosuchbeast'] = "module-racerobot";
            $args['finebeast'] = array("`0\"`^THIS ONE WILL ASSIST WITH YOUR OBJECTIVE OF CRUSHING YOUR FOES TO A FINE PASTE BENEATH YOUR MIGHTY METAL FEET,`0\" says Mike.`n`n", "`0\"`^TO THIS ONE, THERE ARE NO SUPERIOR EXAMPLES`0\" Mike boasts.`n`n", "`0\"`^DOES THIS ONE NOT HAVE A FINE SHINE`0\" he asks.`n`n", "`0\"`^THIS ONE I FIND AESTHETICALLY PLEASING, BEING AS ITS ANGLES AND SIZES ARE ALMOST A PERFECT 1:1.6180339887 RATIO`0\" exclaims Mike.`n`n", "`0\"`^THIS ONE WOULD BE A VERY ADVISABLE PURCHASE AT 2.1516 TIMES THE PRICE I AM ASKING,`0\" booms Mike.`n`n");
            $args['schemas']['finebeast'] = "module-racerobot";
            $args['toolittle'] = "`0Mike looks over the gold and gems you offer and turns up his mechanical nose, \"`^THIS IS NOT THE CORRECT AMOUNT.  THE %s WILL COST YOU `&%s `^REQUISITION TOKENS  AND `%%s`^ CIGARETTES.  THE PRICE IS NOT NEGOTIABLE.`0\"";
            $args['schemas']['toolittle'] = "module-racerobot";
            $args['replacemount'] = "`0Patting %s`0 on the rump, you hand the reins as well as the money for your new mount, and Mike hands you the reins of a `&%s`0.";
            $args['schemas']['replacemount'] = "module-racerobot";
            $args['newmount'] = "`0You hand over the money for your new mount, and Mike hands you the reins of a new `&%s`0.";
            $args['schemas']['newmount'] = "module-racerobot";
            $args['nofeed'] = "`0\"`^I AM SORRY %s, BUT I DO NOT STOCK FUEL OR FEED HERE.  YOU MUST LOOK ELSEWHERE.`0\"";
            $args['schemas']['nofeed'] = "module-racerobot";
            $args['nothungry'] = "`&%s`0 picks briefly at the food and then ignores it.  Mike, lacking the imagination to be dishonest, shakes his head and hands you back your money.";
            $args['schemas']['nothungry'] = "module-racerobot";
            $args['halfhungry'] = "`&%s`0 dives into the provided food and gets through about half of it before stopping.  \"`^WELL, %s WAS NOT AS HUNGRY AS YOU THOUGHT.`0\" says Mike as he hands you back all but %s Requisition tokens.";
            $args['schemas']['halfhungry'] = "module-racerobot";
            $args['hungry'] = "`0%s`0 seems to inhale the food provided.  %s`0, the greedy creature that it is, then goes snuffling at Mike's pockets for more food.`nMike shakes his head in amusement and collects `&%s`0 Requisition tokens from you.";
            $args['schemas']['hungry'] = "module-racerobot";
            $args['mountfull'] = "`n`0\"`^IT APPEARS, %s, THAT YOUR %s`^ IS NOW FULL.  YOU WILL RETURN WHEN IT IS EMPTY ONCE MORE.`0\" says Mike with a genial smile.";
            $args['schemas']['mountfull'] = "module-racerobot";
            $args['nofeedgold'] = "`0\"`^THAT IS NOT ENOUGH MONEY TO PAY FOR FOOD HERE`0\"  Mike turns his back on you, and you lead %s away to find other places for feeding.";
            $args['schemas']['nofeedgold'] = "module-racerobot";
            $args['confirmsale'] = "`n`n`0UMike eyes your mount up and down, checking it over carefully.  \"`^ARE YOU QUITE SURE YOU WISH TO RELINQUISH THIS CONVEYANCE?`0\"";
            $args['schemas']['confirmsale'] = "module-racerobot";
            $args['mountsold'] = "`0With but a single tear, you hand over the reins to your %s`0 to Mike's stableboy.  The tear dries quickly, and the %s in hand helps you quickly overcome your sorrow.";
            $args['schemas']['mountsold'] = "module-racerobot";
            $args['offer'] = "`n`n`0Mike strokes your creature's flank and offers you `&%s`0 Requisition tokens and `%%s`0 cigarettes for %s`0.";
            $args['schemas']['offer'] = "module-racerobot";
            break;
        case "potion":
            if ($session['user']['race'] == $race) {
                blocknav("healer.php?op=buy&pct=100&return=village.php");
                blocknav("healer.php?op=buy&pct=90&return=village.php");
                blocknav("healer.php?op=buy&pct=80&return=village.php");
                blocknav("healer.php?op=buy&pct=70&return=village.php");
                blocknav("healer.php?op=buy&pct=60&return=village.php");
                blocknav("healer.php?op=buy&pct=50&return=village.php");
                blocknav("healer.php?op=buy&pct=40&return=village.php");
                blocknav("healer.php?op=buy&pct=30&return=village.php");
                blocknav("healer.php?op=buy&pct=20&return=village.php");
                blocknav("healer.php?op=buy&pct=10&return=village.php");
                blocknav("healer.php?op=buy&pct=100");
                blocknav("healer.php?op=buy&pct=90");
                blocknav("healer.php?op=buy&pct=80");
                blocknav("healer.php?op=buy&pct=70");
                blocknav("healer.php?op=buy&pct=60");
                blocknav("healer.php?op=buy&pct=50");
                blocknav("healer.php?op=buy&pct=40");
                blocknav("healer.php?op=buy&pct=30");
                blocknav("healer.php?op=buy&pct=20");
                blocknav("healer.php?op=buy&pct=10");
                output("`n`nThe man stops suddenly and looks you up and down, examining your cracked glass skin and visible wiring harnesses.  \"`6'ere,`3\" he says, \"`6Are you `isure`i you're not a Robot?`3\"`n`nYou're really not sure what to say.");
            }
            break;
        case "village":
            if ($session['user']['race'] == $race) {
                blocknav("runmodule.php?module=bloodbank");
                blocknav("healer.php?op=buy");
                addnav("Robot Talents");
                addnav("Configure Overclocking", "runmodule.php?module=racerobot&op=config&from=village");
                if ($session['user']['hitpoints'] < $session['user']['maxhitpoints']) {
                    $scost = 400 * ($session['user']['maxhitpoints'] - $session['user']['hitpoints']);
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Repaired (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=repaired&from=village", true);
                }
                $heat = get_module_pref("heat");
                if ($heat > 0) {
                    $scost = 40 * $heat;
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Cooled (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=cooled&from=village", true);
                }
            }
            break;
        case "forest":
            if ($session['user']['race'] == $race) {
                addnav("Robot Talents");
                addnav("Configure Overclocking", "runmodule.php?module=racerobot&op=config&from=forest");
                if ($session['user']['hitpoints'] < $session['user']['maxhitpoints']) {
                    $scost = 400 * ($session['user']['maxhitpoints'] - $session['user']['hitpoints']);
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Repaired (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=repaired&from=forest", true);
                }
                $heat = get_module_pref("heat");
                if ($heat > 0) {
                    $scost = 40 * $heat;
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Cooled (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=cooled&from=forest", true);
                }
            }
            break;
        case "worldnav":
            if ($session['user']['race'] == $race) {
                addnav("Robot Talents");
                addnav("Configure Overclocking", "runmodule.php?module=racerobot&op=config&from=worldnav");
                if ($session['user']['hitpoints'] < $session['user']['maxhitpoints']) {
                    $scost = 400 * ($session['user']['maxhitpoints'] - $session['user']['hitpoints']);
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Repaired (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=repaired&from=worldnav", true);
                }
                $heat = get_module_pref("heat");
                if ($heat > 0) {
                    $scost = 40 * $heat;
                    $spct = $scost * 100 / 1000000;
                    addnav(array("Standby until Cooled (`Q%s%%`0)", $spct), "runmodule.php?module=racerobot&op=standby&til=cooled&from=worldnav", true);
                }
            }
            break;
        case "stablelocs":
            tlschema("mounts");
            $args[$city] = sprintf_translate("%s", $city);
            tlschema();
            break;
        case "startofround":
            if ($session['user']['race'] == $race && $session['user']['alive'] == 1) {
                $heat = get_module_pref("heat");
                debug("Heat level: " . $heat);
                $fail = e_rand(100, 1500);
                debug("Fail Threshold: " . $fail);
                if ($heat >= $fail) {
                    $penalty = $session['user']['maxhitpoints'] / 100 * ($heat / 10);
                    debug($penalty);
                    $damage = 0 - $penalty;
                    debug("Robot is Overheating!");
                    apply_buff("robotoverheat", array("regen" => $damage, "effectmsg" => "`4`bYou feel a horrible burning, popping sensation deep within your chest!  Something has gone badly wrong, and one of your internal components is overheating!  You lose {damage} hitpoints!`b", "allowinpvp" => 1, "allowintrain" => 1, "rounds" => 1, "schema" => "module-racerobot"));
                }
                //increase player heat level
                $heat += get_module_pref("atk") * 10;
                $heat += get_module_pref("def") * 10;
                $heat += get_module_pref("heal") * 10;
                set_module_pref("heat", $heat);
                debug("Heat level: " . $heat);
            }
            break;
        case "charstats":
            if ($session['user']['race'] == $race) {
                $heat = get_module_pref("heat");
                $col = "#00FF00";
                if ($heat > 200) {
                    $col = "#FDFF00";
                }
                if ($heat > 400) {
                    $col = "#FFA200";
                }
                if ($heat > 600) {
                    $col = "#FF5A00";
                }
                if ($heat > 800) {
                    $col = "#FF0000";
                }
                $width = $heat / 10;
                if ($width > 100) {
                    $width = 100;
                }
                $nwidth = 100 - $width;
                $bar = "<table style='border: solid 1px #000000' bgcolor='#333333' cellpadding='0' cellspacing='0' width='70' height='5'><tr><td width='{$width}%' bgcolor='{$col}'></td><td width='{$nwidth}%' bgcolor='\$#333333'></td></tr></table>";
                setcharstat("Vital Info", "Heat Level", $bar);
            }
            break;
    }
    return $args;
}
function commentaryinfo_dohook($hookname, $args)
{
    global $session;
    switch ($hookname) {
        case "viewcommentary":
            if (get_module_pref("user_usecommentaryextras") == 0) {
                break;
            }
            if (preg_match('/bio\\.php\\?char=(\\d+)\\&ret/', $args['commentline'], $matches)) {
                $userid = $matches[1];
            }
            if ($userid == 0) {
                if (get_module_pref("user_linebreak") == 1) {
                    rawoutput("<br />");
                }
                break;
            }
            $sql = "SELECT race, sex, donation, weapon, loggedin, laston FROM " . db_prefix("accounts") . " WHERE acctid = {$userid}";
            $result = db_fetch_assoc(db_query_cached($sql, "commentaryinfo-{$userid}"));
            if (!get_module_pref("user_hidemyinfo", "commentaryinfo", $userid)) {
                $racefilename = strtolower($result['race']);
                $racefilename = strtr($racefilename, " '-_.!,", "");
                $racefilename = str_replace(" ", "", $racefilename);
                if ($result['sex'] == 0) {
                    $gender = "m";
                    $gendertitle = "Male";
                } else {
                    $gender = "f";
                    $gendertitle = "Female";
                }
                $racefilename .= $gender;
                $race = "<img src=\"/images/races/" . $racefilename . ".png\" alt=\"" . $gendertitle . " " . $result['race'] . "\" title=\"" . $gendertitle . " " . $result['race'] . "\">";
                $weaponfilename = strtolower($result['weapon']);
                $weaponfilename = strtr($weaponfilename, " '-_.!+1234567890,", "                  ");
                $weaponfilename = str_replace(" ", "", $weaponfilename);
                $weaponfilename = "images/weapons/" . $weaponfilename . ".png";
                if (file_exists($weaponfilename)) {
                    $weapon = "<img src=\"" . $weaponfilename . "\" alt=\"Weapon: " . $result['weapon'] . "\" title=\"Weapon: " . $result['weapon'] . "\">";
                } else {
                    $weapon = "Weapon: " . $result['weapon'];
                }
            }
            $offline = date("Y-m-d H:i:s", strtotime("-" . getsetting("LOGINTIMEOUT", 900) . " seconds"));
            if ($result['laston'] > $offline && $result['loggedin'] == 1) {
                if (get_module_pref("loc", "commentaryinfo", $userid) == get_module_pref("loc", "commentaryinfo")) {
                    $online = "<img src=\"/modules/commentaryinfo/nearby.png\" alt=\"Nearby\" title=\"Nearby\">";
                    if ($userid != $session['user']['acctid']) {
                        $ret = URLEncode($_SERVER['REQUEST_URI']);
                        if (!strpos($ret, "bio.php") && !strpos($ret, "commentaryinfo")) {
                            $online = "<a href=\"runmodule.php?module=commentaryinfo&op=closetalk&player={$userid}&ret={$ret}\"><img src=\"/modules/commentaryinfo/nearby.png\" alt=\"Nearby (click to whisper)\" title=\"Nearby (click to whisper)\"></a>";
                            addnav("", "runmodule.php?module=commentaryinfo&op=closetalk&player={$userid}&ret={$ret}");
                        }
                    }
                } else {
                    $online = "<img src=\"/modules/commentaryinfo/online.png\" alt=\"Logged In\" title=\"Logged In\">";
                }
            } else {
                $online = "<img src=\"/modules/commentaryinfo/offline.png\" alt=\"Logged Out\" title=\"Logged Out\">";
            }
            if ($result['donation'] > 100) {
                $donation = "<img src=\"/modules/commentaryinfo/donator1.png\" alt=\"Site Supporter\" title=\"Site Supporter\">";
            }
            if ($result['donation'] > 1000) {
                $donation = "<img src=\"/modules/commentaryinfo/donator2.png\" alt=\"Extra Awesome Site Supporter\" title=\"Extra Awesome Site Supporter\">";
            }
            if ($result['donation'] > 2000) {
                $donation = "<img src=\"/modules/commentaryinfo/donator3.png\" alt=\"Ultra Awesome Site Supporter\" title=\"Ultra Awesome Site Supporter\">";
            }
            if (get_module_pref("user_linebreak") == 1) {
                $out .= "<br />";
            }
            $out .= "{$online} {$close} {$race} {$donation}";
            if (get_module_pref("user_showweapons") == 1) {
                $out .= " {$weapon}";
            }
            if (get_module_pref("user_showinline") == 0) {
                $out .= "<br />";
            }
            rawoutput("{$out}");
            break;
        case "forest":
        case "worldnav":
            clear_module_pref("loc");
            break;
        case "viewcommentaryheader":
            set_module_pref("loc", $args['section']);
            invalidatedatacache("commentaryinfo-" . $session['user']['acctid']);
            break;
    }
    return $args;
}
function implantlaser_dohook($hookname, $args)
{
    global $session, $resline;
    $spec = "HL";
    $name = "Skull-Mounted Laser";
    $ccode = "`\$";
    switch ($hookname) {
        case "dragonkill":
            set_module_pref("primary", 0);
            set_module_pref("secondary", 0);
            set_module_pref("status", 0);
            break;
        case "choose-specialty":
            if ($session['user']['dragonkills'] < 5) {
                break;
            }
            if ($session['user']['specialty'] == "" || $session['user']['specialty'] == '0') {
                addnav("{$ccode}{$name}`0", "newday.php?setspecialty={$spec}{$resline}");
                output("\"`5This one - goodness, it's rather heavy - actually bolts on to the side of your head, rather than going in the brain.  It's a `\$Skull-Mounted Laser`5, you see.  Most of the weight is taken up by the batteries - you get one small battery which is recharged every day, and one large battery that has to last you for your whole adventure.  It's a very, very powerful combat-orientated Implant, but you've got to keep an eye on your battery levels, or you'll be in trouble later on.\"`n`n");
            }
            break;
        case "set-specialty":
            if ($session['user']['specialty'] == $spec) {
                page_header($name);
                output("`\$Not all implants are as subtle as a chip in the brain.  You learn this after examining the housebrick-sized box jutting out of the side of your head.`n`n");
                output("It's painted black, and features a small aperature on the front.  The warning symbols for Laser Radiation and Oxidizing Element are displayed in yellow triangles just above your ear.`n`n");
                output("The user manual states that the laser's output power is pretty well infinitely-adjustable - however, taking it up too high will deplete the primary battery pretty well straight away, prompting the laser to begin draining the secondary battery.`n`nThe medic's warnings about the secondary battery come back to haunt you; use it sparingly, because it has to last you for a long time.");
                clear_module_pref("primary");
                clear_module_pref("secondary");
            }
            break;
        case "specialtycolor":
            $args[$spec] = $ccode;
            break;
        case "specialtynames":
            $args[$spec] = translate_inline($name);
            break;
        case "specialtymodules":
            $args[$spec] = "implantlaser";
            break;
        case "newday":
            if ($session['user']['specialty'] == $spec) {
                output("`nThe primary battery on your Head-Mounted Laser has been charged overnight, and is now at full capacity.`n");
                $primary = $session['user']['level'] * 2 + 20;
                set_module_pref("primary", $primary);
                set_module_pref("status", 0);
            }
            set_module_pref("status", 0);
            strip_buff('headlaser');
            break;
        case "forest":
            if ($session['user']['specialty'] == $spec) {
                if (get_module_pref("primary") > 0 || get_module_pref("secondary") > 0) {
                    addnav(array("{$ccode} `bSkull-Mounted Laser`b`0", ""));
                    addnav(array("Battery: (%s/%s)`0", get_module_pref("primary"), get_module_pref("secondary")), "");
                    addnav(array("Power output: %sKw`0", get_module_pref("powerlevel")), "");
                    addnav("Increase laser power`0", "runmodule.php?module=implantlaser&op=inc&from=forest");
                    if (get_module_pref("powerlevel") > 1) {
                        addnav("Decrease laser power`0", "runmodule.php?module=implantlaser&op=dec&from=forest");
                    }
                }
            }
            break;
        case "village":
            if ($session['user']['specialty'] == $spec) {
                if (get_module_pref("primary") > 0 || get_module_pref("secondary") > 0) {
                    addnav(array("{$ccode} `bSkull-Mounted Laser`b`0", ""));
                    addnav(array("Battery: (%s/%s)`0", get_module_pref("primary"), get_module_pref("secondary")), "");
                    addnav(array("Power output: %sKw`0", get_module_pref("powerlevel")), "");
                    addnav("Increase laser power`0", "runmodule.php?module=implantlaser&op=inc&from=village");
                    if (get_module_pref("powerlevel") > 1) {
                        addnav("Decrease laser power`0", "runmodule.php?module=implantlaser&op=dec&from=village");
                    }
                }
                set_module_pref("status", 0);
                strip_buff('headlaser');
            }
            break;
        case "worldnav":
            if ($session['user']['specialty'] == $spec) {
                if (get_module_pref("primary") > 0 || get_module_pref("secondary") > 0) {
                    addnav(array("{$ccode} `bSkull-Mounted Laser`b`0", ""));
                    addnav(array("Battery: (%s/%s)`0", get_module_pref("primary"), get_module_pref("secondary")), "");
                    addnav(array("Power output: %sKw`0", get_module_pref("powerlevel")), "");
                    addnav("Increase laser power`0", "runmodule.php?module=implantlaser&op=inc&from=worldnav");
                    if (get_module_pref("powerlevel") > 1) {
                        addnav("Decrease laser power`0", "runmodule.php?module=implantlaser&op=dec&from=worldnav");
                    }
                }
                set_module_pref("status", 0);
                strip_buff('headlaser');
            }
            break;
        case "fightnav-specialties":
            if ($session['user']['specialty'] == $spec) {
                // Evaluate the number of rounds that the battle has lasted thus far.  Because this is only called once per click, and the user can choose to play five rounds, ten rounds or to the end of the fight, we've got to get the number of rounds by looking at the remaining rounds left in the buff we set up the last time the user clicked to fight.
                if (has_buff("headlaser")) {
                    $roundsplayed = 1000 - $session['bufflist']['headlaser-roundtrack']['rounds'];
                    set_module_pref("primary", get_module_pref("primary") - get_module_pref("powerlevel") * $roundsplayed);
                    if (get_module_pref("primary") < 0) {
                        $discrepancy = get_module_pref("primary");
                        $discrepancy = $discrepancy - $discrepancy - $discrepancy;
                        debug($discrepancy);
                        set_module_pref("secondary", get_module_pref("secondary") - $discrepancy);
                        set_module_pref("primary", 0);
                        if (get_module_pref("secondary") < 0) {
                            set_module_pref("secondary", 0);
                            set_module_pref("status", 0);
                            strip_buff('headlaser');
                            strip_buff('headlaser-roundtrack');
                        }
                    }
                } else {
                    $roundsplayed = 0;
                    set_module_pref("status", 0);
                }
                apply_buff('headlaser-roundtrack', array("rounds" => 1000, "dmgmod" => 1));
                $script = $args['script'];
                $primary = get_module_pref("primary");
                $secondary = get_module_pref("secondary");
                if ($primary > 0 || $secondary > 0) {
                    addnav(array("{$ccode} `bSkull-Mounted Laser`b`0", ""));
                    addnav(array("Battery: %s (%s)`0", $primary, $secondary), "");
                    addnav(array("Power output: %sKw`0", get_module_pref("powerlevel")), "");
                    if (get_module_pref("status") == 0) {
                        if ($primary + $secondary > get_module_pref("powerlevel")) {
                            addnav(array("{$ccode} &#149; Turn on laser`0"), $script . "op=fight&skill={$spec}&l=on", true);
                        } else {
                            addnav("Not enough battery power to fire laser", "");
                        }
                        addnav(array("{$ccode} &#149; Increase laser power`0"), $script . "op=fight&skill={$spec}&l=inc", true);
                        if (get_module_pref("powerlevel") > 1) {
                            addnav(array("{$ccode} &#149; Decrease laser power`0"), $script . "op=fight&skill={$spec}&l=dec", true);
                        }
                    }
                    if (get_module_pref("status") == 1) {
                        addnav(array("{$ccode} &#149; Turn off laser`0"), $script . "op=fight&skill={$spec}&l=off", true);
                    }
                }
            }
            break;
        case "apply-specialties":
            if ($session['user']['specialty'] == $spec) {
                $skill = httpget('skill');
                $l = httpget('l');
                if ($skill == $spec) {
                    switch ($l) {
                        case "inc":
                            set_module_pref("powerlevel", get_module_pref("powerlevel") + 1);
                            output("`\$You reach up and twiddle the knobs on your housebrick-sized cranial implant.  You have `bincreased`b your laser's output power by one kilowatt, taking it up to %s.`n", get_module_pref("powerlevel"));
                            break;
                        case "dec":
                            set_module_pref("powerlevel", get_module_pref("powerlevel") - 1);
                            output("`\$You reach up and twiddle the knobs on your housebrick-sized cranial implant.  You have `bdecreased`b your laser's output power by one kilowatt, taking it down to %s.`n", get_module_pref("powerlevel"));
                            break;
                        case "on":
                            if (get_module_pref("secondary") > 0 || get_module_pref("primary") > 0) {
                                apply_buff('headlaser', array("startmsg" => "`\$Your laser steams into life, sending a beam of burning light towards {badguy}!", "name" => "`\$Head-Mounted Laser", "effectmsg" => "`\${badguy} yelps in pain as the laser burns into its body, doing `^{damage}`\$ points' worth of damage!", "rounds" => -1, "minioncount" => 1, "minbadguydamage" => ceil(get_module_pref("powerlevel") / 2), "maxbadguydamage" => ceil(get_module_pref("powerlevel") * 2), "schema" => "module-implantlaser"));
                                set_module_pref("status", 1);
                            } else {
                                output("Your laser's batteries are DEAD!");
                            }
                            break;
                        case "off":
                            set_module_pref("status", 0);
                            strip_buff('headlaser');
                            break;
                    }
                }
            }
            break;
        case "battle-defeat":
        case "battle-victory":
            if ($session['user']['specialty'] == $spec) {
                if (get_module_pref("status") == 1) {
                    set_module_pref("status", 0);
                    if (has_buff("headlaser")) {
                        $roundsplayed = 1001 - $session['bufflist']['headlaser-roundtrack']['rounds'];
                        set_module_pref("primary", get_module_pref("primary") - get_module_pref("powerlevel") * $roundsplayed);
                        if (get_module_pref("primary") < 0) {
                            set_module_pref("secondary", get_module_pref("secondary") - get_module_pref("powerlevel") * $roundsplayed);
                            set_module_pref("primary", 0);
                            if (get_module_pref("secondary") < 0) {
                                set_module_pref("secondary", 0);
                                set_module_pref("status", 0);
                                strip_buff('headlaser');
                                strip_buff('headlaser-roundtrack');
                            }
                        }
                    }
                    output("`n`\$Your head-mounted laser, seeing its target suitably chastised, switches off automatically.`n");
                }
                strip_buff('headlaser');
            }
            break;
    }
    return $args;
}
function alternativeresurrect_run()
{
    global $session;
    $op = httpget('op');
    if ($op == "resurrect") {
        if ($session['user']['deathpower'] >= 100) {
            page_header("The Graveyard");
            $session['user']['deathpower'] -= 100;
            $session['user']['resurrections']++;
            $deathoverlord = getsetting('deathoverlord', 'Ramius');
            output("`\$%s`0 waves his skeletal arms as he begins to command the very fabric of life.`n`n", $deathoverlord);
            output("\"`)Noitcerruser evah llahs ut...`\$\"  The air begins to crackle around you.`n`n");
            output("\"`)Tnavres o htaed eht morf esir.`\$\" Your soul begins to burn with the pain of a thousand frosty fires.`n`n");
            output("\"`)Enim si htaed revo rewop.`\$\" Gradually you begin to become aware that the fires are dimming and are replaced by the blinding pain last known by your body before it fell.`n`n");
            output("\"`)Niaga ut tnarg oge efil ruoy.`\$\" You begin to look around you, and you watch as your muscles knit themselves back together.`n`n");
            output("\"`)Niaga em ot nruter llahs ut wonk oge rof.`\$\" With a gasp, you laboriously again draw your first breath.`n`n`n");
            $hppercentage = get_module_setting("hppercentage");
            $turnslost = get_module_setting("turnslost");
            $charmlost = get_module_setting("charmlost");
            $session['user']['hitpoints'] = max(round($session['user']['maxhitpoints'] / 100 * $hppercentage), 1);
            if ($hppercentage < 100) {
                output("`QYou are alive again, but you seem to be far from healthy. You should really see a doctor.`n");
            }
            if ($turnslost > 0) {
                $session['user']['turns'] -= $turnslost;
                if ($session['user']['turns'] < 0) {
                    $session['user']['turns'] = 0;
                }
                if ($turnslost == 1) {
                    output("`QYou realize that you lost `\$one`Q turn wandering among the dead.`n");
                } else {
                    output("`QYou realize that you lost `\$%s`Q turns wandering among the dead.`n", $turnslost);
                }
            }
            if ($charmlost > 0) {
                output("`QYou can feel the beginning decay of your own flesh. The breath-taking smell makes you choke ");
                if ($session['user']['charm'] > 0) {
                    output(". You loose`\$ %s `Qcharm.`n", $charmlost);
                    $session['user']['charm'] -= $charmlost;
                } else {
                    output(" but even the stinking flesh can't make you less attractive, than you already are.`n");
                }
            }
            modulehook("alternativeresurrect");
            addnews("`&%s`& has been returned to the mainland by %s`&.", $session['user']['name'], $deathoverlord);
            addnav("Return to the living", "shades.php");
            //restore suspended buffs
            $buffs = unserialize(get_module_pref("bufflist"));
            if (is_array($buffs)) {
                foreach ($buffs as $buff => $values) {
                    apply_buff($buff, $values);
                }
            }
            clear_module_pref("bufflist");
            page_footer();
        } else {
            page_header("The Graveyard");
            output("You do not have enough favor to resurrect.");
            addnav("Return to the shades", "shades.php");
            page_footer();
        }
    }
}
function timedcombat_dohook($hookname, $args)
{
    global $session, $last_timestamp;
    switch ($hookname) {
        case "creatureencounter":
        case "gravefight-start":
            set_module_pref("willing", 0);
            if (!get_module_pref("able")) {
                if ($session['user']['donation'] >= 2000) {
                    set_module_pref("able", true);
                }
            }
            break;
        case "battle":
            if (get_module_pref("able")) {
                if (!get_module_pref("willing")) {
                    $target = e_rand(4, 7);
                    rawoutput("<table cellpadding=0 cellspacing=0><tr><td width=\"220px\"><div style=\"width:200; height:25; background:url(/images/timedcombat-background.png); border:1px solid #000000;\"></div></td><td>");
                    set_module_pref("target", $target);
                    output("Next target: `b%s seconds`b", $target);
                    rawoutput("</td></tr></table>");
                    set_module_pref("willing", true);
                    $now = microtime(true);
                    set_module_pref("lasttime", $now);
                } else {
                    $now = microtime(true);
                    $last = get_module_pref("lasttime");
                    $target = get_module_pref("target");
                    $offset = round($now - $last, 1);
                    $offset -= $target;
                    if ($offset < 60) {
                        $pass = 0;
                        while ($offset > $target / 2) {
                            $offset -= $target;
                            $pass++;
                        }
                        $pixeloffset = 91 + $offset * 20;
                        if ($pixeloffset < 4) {
                            $pixeloffset = 4;
                        }
                        if ($pixeloffset > 180) {
                            $pixeloffset = 180;
                        }
                        rawoutput("<table cellpadding=0 cellspacing=0><tr><td width=\"220px\"><div style=\"width:200; height:25; background:url(/images/timedcombat-background.png); border:1px solid #000000;\"><div style=\"width: 196; height: 21; padding-left:10px; background: url(/images/timedcombat-pointer.png); background-repeat: no-repeat; line-height: 25px; background-position: " . $pixeloffset . "px\"></div></div></td><td>");
                        if ($offset == 1 || $offset == -1) {
                            $sdisp = "Second";
                        } else {
                            $sdisp = "Seconds";
                        }
                        if ($pass > 1) {
                            output("Repeater: ");
                        }
                        if ($offset > 0.1) {
                            output("`b%s %s late`b / ", $offset, $sdisp);
                            clear_module_pref("chain");
                        } else {
                            if ($offset < -0.1) {
                                output("`b%s %s early`b / ", $offset * -1, $sdisp);
                                clear_module_pref("chain");
                            } else {
                                output("`b`@Perfect!`0`b / ");
                                increment_module_pref("hits");
                                increment_module_pref("chain");
                                $chain = get_module_pref("chain");
                                if ($chain > 1) {
                                    output("`b`@%s-chain!`b`0 / ", $chain);
                                    if ($chain > get_module_pref("maxchain")) {
                                        set_module_pref("maxchain", $chain);
                                        output("`b`@New Personal Chain Record!`0`b / ");
                                        if (get_module_pref("maxchain") == 4) {
                                            $subj = "Congratulations!";
                                            $body = "You've just got your first four-chain, and now you can teach Timed Combat to other players!  You can teach a maximum of one player per Game Day.  To teach a player, ensure that you're both logged in and in the same chatspace, then click on their Bio and you should see the option to teach them the new skill.  Have fun!";
                                            require_once "lib/systemmail.php";
                                            systemmail($session['user']['acctid'], $subj, $body);
                                        }
                                    }
                                    if (is_module_active("medals")) {
                                        if ($chain >= 25) {
                                            require_once "modules/medals.php";
                                            medals_award_medal("timedcombat_chain_25", "Master of the Metronome", "This player got a 25-Chain in Timed Combat!", "medal_timedchaingold.png");
                                        } else {
                                            if ($chain >= 10) {
                                                require_once "modules/medals.php";
                                                medals_award_medal("timedcombat_chain_10", "Split-Second Savant", "This player got a 10-Chain in Timed Combat!", "medal_timedchainsilver.png");
                                            } else {
                                                if ($chain >= 5) {
                                                    require_once "modules/medals.php";
                                                    medals_award_medal("timedcombat_chain_5", "Perfect Timing", "This player got a 5-Chain in Timed Combat!", "medal_timedchainbronze.png");
                                                }
                                            }
                                        }
                                    }
                                }
                                switch (httpget('auto')) {
                                    case "five":
                                        $rounds = 5;
                                        break;
                                    case "ten":
                                        $rounds = 10;
                                        break;
                                    case "full":
                                        $rounds = -1;
                                        break;
                                    default:
                                        $rounds = 1;
                                        break;
                                }
                                apply_buff('timedcombat', array("roundmsg" => "`0Your perfect timing really makes a difference!", "rounds" => $rounds, "atkmod" => 2, "defmod" => 2, "expireafterfight" => 1, "schema" => "module-timedcombat"));
                            }
                        }
                        $newtarget = e_rand(4, 7);
                        set_module_pref("target", $newtarget);
                        output("Next target: `b%s seconds`b", $newtarget);
                        rawoutput("</td></tr></table>");
                    }
                    set_module_pref("lasttime", $now);
                }
            }
            break;
    }
    return $args;
}