Difference between revisions of "Advanced Racing With race timer/Script"

From Armagetron
Line 1: Line 1:
 +
Last Updated - 8 May 2012
 
<pre>
 
<pre>
 
#!/usr/bin/php
 
#!/usr/bin/php
Line 5: Line 6:
 
Includes highscores per map, finish timers, map/cfg rotator, and more
 
Includes highscores per map, finish timers, map/cfg rotator, and more
 
Requires a TargetZone as a finish line, winzones will not work
 
Requires a TargetZone as a finish line, winzones will not work
If you are not using Rx Hosting, make sure your directory has write permissions
+
If you are not using Rx Hosting your directory needs write permission
 
Made by dukevin (dukevinjduke@gmail.com)
 
Made by dukevin (dukevinjduke@gmail.com)
 
*/
 
*/
  
 
$save_directory_location = "/home/duke/aa/servers/smart/var/logs/";  //The directory to save files. Must end with trailing slash
 
$save_directory_location = "/home/duke/aa/servers/smart/var/logs/";  //The directory to save files. Must end with trailing slash
 +
 
$countdown_secs_after_finish = 30; //After someone finishes, how many seconds on the timer before the round ends?
 
$countdown_secs_after_finish = 30; //After someone finishes, how many seconds on the timer before the round ends?
 +
 
$countdown_if_last_player = true; //If only 1 player remaining, start the timer?
 
$countdown_if_last_player = true; //If only 1 player remaining, start the timer?
$countdown_last_player_extra_time = 0; //If only 1 player remaining, give the last racer this many seconds of extra time to finish
+
 
 
$max_time_limit = -1; //start the timer after this many seconds, -1 to disable time limits
 
$max_time_limit = -1; //start the timer after this many seconds, -1 to disable time limits
 +
 
$points = array(10, 7, 5, 4, 3, 2, 1, 1, 1, 1); //points awarded for 1st, 2nd, 3rd, 4th, 5th, etc...
 
$points = array(10, 7, 5, 4, 3, 2, 1, 1, 1, 1); //points awarded for 1st, 2nd, 3rd, 4th, 5th, etc...
 +
 
$display_mode = 1; //If set to "1" display a center_message of the map name, 2 for console_message, 3 for both, 0 for no message
 
$display_mode = 1; //If set to "1" display a center_message of the map name, 2 for console_message, 3 for both, 0 for no message
 +
 
$display_prefix = "Current race: 0xffff00"; //When showing the map name, this is appended before it, if $display_mode is 0, this is disabled
 
$display_prefix = "Current race: 0xffff00"; //When showing the map name, this is appended before it, if $display_mode is 0, this is disabled
 +
 +
$smart_time = true; //If true, the game will determine how many seconds to put on the timer based on previous records instead of using $countdown_secs_after_finish which will be used as the minimum amount of time instead.
 +
 +
$countdown_last_player_extra_time = 0; //If only 1 player remaining, give the last racer this many seconds of extra time to finish. Not needed if $smart_time is true
  
 
//Below, inbetween quotes, if you are including maps, put something like: "/path/to/map.aamap.xml". If you are using cfgs, put "mycfg.cfg"  
 
//Below, inbetween quotes, if you are including maps, put something like: "/path/to/map.aamap.xml". If you are using cfgs, put "mycfg.cfg"  
$includes = array("8Ball.cfg","100Watts.cfg","Aflac.cfg","AnimusonConfusion.cfg","Aoi.cfg","Arsenal.cfg","AtlanticCharter.cfg","Cell.cfg","Cherrio.cfg","Compact.cfg",
+
$includes = array("Default.cfg","8Ball.cfg","100Watts.cfg","AQuickExplosion.cfg","Aflac.cfg","AnimusonConfusion.cfg","Aoi.cfg","Arsenal.cfg","AtlanticCharter.cfg","Berlin.cfg","Cell.cfg","Cherrio.cfg",
"DevilsSandglass.cfg","Dizzy.cfg","FirePalace.cfg","AQuickExplosion.cfg","BenignRevolution.cfg","BloodyHell.cfg","Chihuahua.cfg","DeathOctagon.cfg","DeathTrap.cfg",
+
"Compact.cfg","DevilsSandglass.cfg","Dizzy.cfg","FirePalace.cfg","BenignRevolution.cfg","BloodyHell.cfg","Chihuahua.cfg","DeathOctagon.cfg","DeathTrap.cfg","Flex.cfg","FrizzleFraz.cfg","Glacier.cfg",
"Flex.cfg","FrizzleFraz.cfg","Glacier.cfg","Handgrip.cfg","Holiday.cfg","Hyperpod.cfg","Insane.cfg","ItsABug.cfg","JailBreak.cfg","Jelly.cfg","Killzone.cfg","KirbyDance.cfg",
+
"Handgrip.cfg","Holiday.cfg","Hyperpod.cfg","Illusion.cfg","Insane.cfg","ItsABug.cfg","JailBreak.cfg","Jelly.cfg","Killzone.cfg","KirbyDance.cfg","lol.cfg","Marathon.cfg","Mint.cfg","MissionImpossible.cfg",
"lol.cfg","Marathon.cfg","Mint.cfg","MissionImpossible.cfg","Moon.cfg","MovinOnUp.cfg","MrRoboto.cfg","Mutant.cfg","Nebraska.cfg","Nova.cfg","OctaGone2Death.cfg","PointOfNoReturn.cfg",
+
"Moon.cfg","MovinOnUp.cfg","MrRoboto.cfg","Mutant.cfg","Nebraska.cfg","Nova.cfg","OctaGone2Death.cfg","PointOfNoReturn.cfg","PureRacingTorture.cfg","RatTunnels.cfg","Red.cfg","Resurrection.cfg",
"PureRacingTorture.cfg","RatTunnels.cfg","Red.cfg","Resurrection.cfg","RoadLessTraveled.cfg","RoadOfDeath.cfg","Roundabout.cfg","Shield.cfg","SidebySide.cfg","SmallSpaces.cfg","Spiral.cfg",
+
"RoadLessTraveled.cfg","RoadOfDeath.cfg","Roundabout.cfg","Shield.cfg","SidebySide.cfg","SmallSpaces.cfg","Spiral.cfg","SpiralHam.cfg","SquareRoot.cfg","Stardome.cfg","Sun.cfg","Symmetry.cfg",
"SpiralHam.cfg","SquareRoot.cfg","Stardome.cfg","Sun.cfg","Symmetry.cfg","TannersBigTronDaddy.cfg","TheMachine.cfg","TikiTime.cfg","TortureChamber.cfg","Trijecture.cfg","TurnAround.cfg",
+
"TannersBigTronDaddy.cfg","TheMachine.cfg","TheRoadNotTaken.cfg","TikiTime.cfg","TortureChamber.cfg","Trijecture.cfg","TurnAround.cfg","Unfair.cfg","Unfortunate.cfg","Verta.cfg","Wrapper.cfg","XploderPro.cfg",
"Unfair.cfg","Unfortunate.cfg","Verta.cfg","Wrapper.cfg","XploderPro.cfg","Zero.cfg","ZigZagZaney.cfg","Zipper.cfg","Zone3.cfg");
+
"Zero.cfg","ZigZagZaney.cfg","Zipper.cfg","Zone3.cfg");
 +
 
 
$rotate_mode = 2; //Set to 1 for simple random, 2 to play each map in order, 3 to randomly pick a map that hasn't been picked yet.
 
$rotate_mode = 2; //Set to 1 for simple random, 2 to play each map in order, 3 to randomly pick a map that hasn't been picked yet.
 +
 
$num_map_plays = 1; //play each map how many times before switching to next map
 
$num_map_plays = 1; //play each map how many times before switching to next map
  
 
$zombie_win = false;  //Does the winner get a zombie? (adjust zombie_zone_speed to fit your liking)
 
$zombie_win = false;  //Does the winner get a zombie? (adjust zombie_zone_speed to fit your liking)
  
/*=================================================================*/
+
$precision = 2; //How many decimal places to show times? A value of 3 shows X.xxx, 2 shows X.xx.  5 is max.
 +
 
 +
/*============================== End of customization options ===================================*/
  
$reccomended_settings = array("target_initial_score 0", "sp_game_type 0", "game_type 0", "sp_finish_type 0", "finish_type 0", "sp_num_ais 0", "num_ais 0", "shot_seek_update_time 0.1", "ladderlog_write_all 1|1");   
+
$reccomended_settings = array("target_initial_score 0", "sp_game_type 0", "game_type 0", "sp_finish_type 0", "finish_type 0", "sp_num_ais 0", "num_ais 0", "shot_seek_update_time 0.1",  
//these settings should be set for racing mode and is run once when the script is loaded
+
"ladderlog_write_all 1|1");  //these settings should be set for racing mode and is run every round
 
class Player
 
class Player
 
{
 
{
Line 51: Line 65:
 
function read()
 
function read()
 
{
 
{
global $file;
+
global $file, $precision;
 
$lines = file($file);
 
$lines = file($file);
 
foreach($lines as $line)
 
foreach($lines as $line)
 
{
 
{
$pieces = explode(" ", $line);  //time name num_plays       (if time is -1, never won it)
+
$pieces = explode(" ", $line);  //time name num_plays
 
if($pieces[1] == $this->name)
 
if($pieces[1] == $this->name)
 
{
 
{
$this->best_time = round($pieces[0],2);
+
$this->best_time = round($pieces[0], $precision);
 
$this->num_plays = $pieces[2];
 
$this->num_plays = $pieces[2];
 
break;
 
break;
Line 92: Line 106:
 
file_put_contents($file, $lines);
 
file_put_contents($file, $lines);
 
fclose($fp);
 
fclose($fp);
//return pos
 
 
}
 
}
 
function finished($time, $place)
 
function finished($time, $place)
 
{
 
{
global $points, $players, $current_inc;
+
global $points, $players, $current_inc, $precision;
 
$this->num_plays++;
 
$this->num_plays++;
$time = round($time,2);
+
$time = round($time,$precision);
 
$this->finish_time = $time;
 
$this->finish_time = $time;
 
$this->place = $place;
 
$this->place = $place;
Line 111: Line 124:
 
{
 
{
 
$first = $p->finish_time;
 
$first = $p->finish_time;
$difference = " 0xffffff(" . round($this->finish_time - $p->finish_time,2) . " s behind 1st)";
+
$difference = " 0xffffff(" . round($this->finish_time - $p->finish_time,$precision) . " s behind 1st)";
 
break;
 
break;
 
}
 
}
Line 118: Line 131:
 
else  
 
else  
 
$difference = "";
 
$difference = "";
c("0xffff00 > 0xffff99$this->pname 0x55ccfffinished $place$sufx in 0xffff99$time 0x55ccffseconds.$difference 0x808080+{$score} pts");
+
c("0x55ccff > 0xffff99$this->pname 0x55ccfffinished $place$sufx in 0xffff99$time 0x55ccffseconds.$difference 0x808080+{$score} pts");
 
if($this->finish_time >= $this->best_time && !empty($this->best_time)) //took longer than alltime best
 
if($this->finish_time >= $this->best_time && !empty($this->best_time)) //took longer than alltime best
 
{
 
{
pm($this->name, "    0xaaaaffYour all-time best on 0xddddff{$current_inc}0xaaaaff is 0xffffff{$this->best_time} 0xaaaaffs, you are 0xffffff".($this->finish_time - $this->best_time)." 0xaaaaffs 0xff7777slower0xaaaaff.");
+
pm($this->name, "    0xaaaaffYour all-time best on 0xddddff{$current_inc}0xaaaaff is 0xffffff{$this->best_time} 0xaaaaffs, you are 0xffffff". round($this->finish_time - $this->best_time, $precision)." 0xaaaaffs 0xff7777slower0xaaaaff.");
 
}
 
}
 
if($this->finish_time < $this->best_time || empty($this->best_time))
 
if($this->finish_time < $this->best_time || empty($this->best_time))
Line 130: Line 143:
 
if(empty($this->best_time))  
 
if(empty($this->best_time))  
 
pm($this->name, "    0xaaaaffThis is your first time finishing 0xddddff{$current_inc}0xaaaaff!");
 
pm($this->name, "    0xaaaaffThis is your first time finishing 0xddddff{$current_inc}0xaaaaff!");
else pm($this->name, "  0x3388ff* 0x55ff88New personal record! You improved 0xffffff" . round($this->best_time - $this->finish_time,2) . "0x55ff88 s raising 0xffffff". ($oldrank - $newrank) ." 0x55ff88ranks!");
+
else pm($this->name, "  0x3388ff* 0x55ff88New personal record! You improved 0xffffff" . round($this->best_time - $this->finish_time,$precision) . "0x55ff88 s raising 0xffffff". ($oldrank - $newrank) ." 0x55ff88ranks!");
+
if($newrank == 1) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffd700Congratulate 0xffffff$this->name 0xffd700for setting a new record on 0xffddaa$current_inc 0xffd700as the fastest time ever!0xff3333*0xffff33*0x33ff33*0x3366ff*");
if($newrank == 1) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffd700Congratulate 0xffffff$this->pname 0xffd700for setting a new record on 0xffddaa$current_inc 0xffd700as the fastest time ever!0xff3333*0xffff33*0x33ff33*0x3366ff*");
+
else if($newrank == 2) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->name 0xc0c0c0just ranked as the 0xffffff2nd 0xc0c0c0fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*\n");
else if($newrank == 2) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->pname 0xc0c0c0just ranked 0xffffff2nd 0xc0c0c0as the fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*\n");
+
else if($newrank == 3) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->name 0xcd7f32just ranked as the 0xffcc003rd 0xcd7f32 fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*");
else if($newrank == 3) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->name 0xcd7f32just ranked 0xffcc003rd 0xcd7f32as the fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*");
 
 
else
 
else
pm($this->name, "   0xaaaaaaYou are now rank 0xffffff$newrank 0xaaaaaaon the list of fastest times for 0xcccccc{$current_inc}0xaaaaaa!");
+
pm($this->name, "     0xaaaaaaYou are now rank 0xffffff$newrank 0xaaaaaaon the list of fastest times for 0xcccccc{$current_inc}0xaaaaaa!");
 
 
 
}
 
}
echo "add_score_player $this->name " . $score . " \n";
+
echo "add_score_player $this->name " . $score . "\n";
 
}
 
}
 
}
 
}
Line 152: Line 164:
 
$split = explode(" ",$line);
 
$split = explode(" ",$line);
 
$name = $split[1];
 
$name = $split[1];
 +
if(getObject($name) !== false)
 +
{
 +
$num_racers++;
 +
goto end;
 +
}
 
if(strstr($name,"\""))
 
if(strstr($name,"\""))
 
{
 
{
Line 179: Line 196:
 
if(!empty($players[$i]->best_time)) $rank = filetee($players[$i]->name, $players[$i]->name, 1, false, true) + 1;
 
if(!empty($players[$i]->best_time)) $rank = filetee($players[$i]->name, $players[$i]->name, 1, false, true) + 1;
 
$sufx = suffix($rank);
 
$sufx = suffix($rank);
 +
pm($players[$i]->name, "0x808080Top 3 times for $current_inc:");
 +
filetee($players[$i]->name, $players[$i]->name, 3, true);
 
if(!(strstr($players[$i]->name, '@')))
 
if(!(strstr($players[$i]->name, '@')))
 
$remind = "0x808080(Maybe because you're logged out?)";
 
$remind = "0x808080(Maybe because you're logged out?)";
 
else
 
else
 
$remind = null;
 
$remind = null;
if(!empty($players[$i]->best_time)) pm($players[$i]->name, "0xaaddaaYour best time for $current_inc is 0xffffff{$players[$i]->best_time}0xaaddaa s ranking 0xffffff$rank{$sufx}0xaaddaa.");
+
if(!empty($players[$i]->best_time)) pm($players[$i]->name, "0x99ddffYour best time for $current_inc is 0xffffff{$players[$i]->best_time}0x99ddff s ranking 0xffffff$rank{$sufx}0x99ddff. 0x808080{$players[$i]->num_plays} finishes");
if(empty($players[$i]->best_time)) pm($players[$i]->name, "0xaaddaaYou have never won 0xcccccc$current_inc 0xaaddaabefore. $remind");
+
if(empty($players[$i]->best_time)) pm($players[$i]->name, "0x99ddffYou have never won 0xcccccc$current_inc 0x99ddffbefore. $remind");
pm($players[$i]->name, "0x808080Top 3 times for $current_inc:");
 
filetee($players[$i]->name, $players[$i]->name, 3, true);
 
if(!(strstr($players[$i]->name, '@')))
 
pm($players[$i]->name, "0xffddaaYou should /login to protect your times!");
 
 
 
 
$i++;
 
$i++;
Line 208: Line 223:
 
foreach($reccomended_settings as $s)
 
foreach($reccomended_settings as $s)
 
echo "$s \n";
 
echo "$s \n";
echo "target_survive_time " . ($countdown_secs_after_finish+1) ."\n";
 
 
unset($players);
 
unset($players);
 
$finished = 0;
 
$finished = 0;
Line 235: Line 249:
 
c("0xffff77Warning: 0xffffff$current_inc.txt not found, creating it...");
 
c("0xffff77Warning: 0xffffff$current_inc.txt not found, creating it...");
 
fopen($file, 'w');
 
fopen($file, 'w');
 +
sleep(1);
 +
if(!file_exists($file))
 +
c("0xff7777Warning: 0xffffffFile creation failed, scores cannot be saved! Does your directory have write permission?");
 
}
 
}
if(mt_rand(0,7)==7) c("0x808080You can type /stats <name> <amount> to view high scores for maps.");
+
if($smart_time)
 +
$countdown_secs_after_finish = smart_time($countdown_secs_after_finish);
 +
echo "target_survive_time " . ($countdown_secs_after_finish+1) ."\n";
 +
if(mt_rand(0,7)==7) c("0x808080You can type /stats <name> <optional amount> to view high scores for maps.");
 +
 
@clock("stop");
 
@clock("stop");
 
}
 
}
Line 252: Line 273:
 
}
 
}
 
sleep(1);
 
sleep(1);
echo "center_message Winner: $split[6]\n";
+
if(!empty($split[6])) echo "center_message Winner: {$split[6]}\n";
 
echo "collapse_zone\n";
 
echo "collapse_zone\n";
 +
if(empty($split[6]))
 +
echo "spawn_zone win $xPos $yPos 1000000 10000 0 0 false 0 0 0\n";
 
$a_player_finished = true;
 
$a_player_finished = true;
 
}
 
}
Line 260: Line 283:
 
$split = explode(" ", $line);
 
$split = explode(" ", $line);
 
//INVALID_COMMAND /cast rx"dukevin 76.174.69.46 accesslevel argument 50
 
//INVALID_COMMAND /cast rx"dukevin 76.174.69.46 accesslevel argument 50
if($split[1] == "/stats" || $split[1] == "/s")
+
if($split[1] == "/stats" || $split[1] == "/s"|| $split[1] == "/search")
 
{
 
{
if($split[6] < 0) $split[6] = 0;
 
 
if(empty($split[5]))
 
if(empty($split[5]))
 
{
 
{
Line 268: Line 290:
 
goto end;
 
goto end;
 
}
 
}
filetee($split[5], $split[2], $split[6]);
+
$obj = getObject($split[2]);
 +
if(empty($split[6]) || !isset($split[6])) $split[6] = 3;
 +
search($obj, $split[5], $split[6]);
 
}
 
}
 
elseif($split[1] == "/version" || $split[1] == "/v" || $split[1] == "/ver" || $split[1] == "/vers")
 
elseif($split[1] == "/version" || $split[1] == "/v" || $split[1] == "/ver" || $split[1] == "/vers")
Line 274: Line 298:
 
$obj = getObject($split[2]);
 
$obj = getObject($split[2]);
 
version($obj);
 
version($obj);
 +
}
 +
elseif($split[1] == "/debug")
 +
{
 +
foreach($players as $p)
 +
pm($split[2], "$p->name");
 
}
 
}
 
else
 
else
Line 320: Line 349:
 
{
 
{
 
$split = explode(" ", $line);
 
$split = explode(" ", $line);
if(empty(getObject($split[1])->place))
+
if(empty(getObject($split[1])->finish_time))
 
$num_racers--;
 
$num_racers--;
 
if(sizeof($players) <= 1) //if only 1 player, don't start the timer
 
if(sizeof($players) <= 1) //if only 1 player, don't start the timer
Line 328: Line 357:
 
if($num_racers <= 1)
 
if($num_racers <= 1)
 
{
 
{
if(@clock("getState") == "active")
+
if(@clock("getState") == "active" && (empty(getObject($split[1])->finish_time))) //only winner alive, last racer died &&racer not finish
 
{
 
{
 
echo "spawn_zone win $xPos $yPos 1000000 100000 0 0 false 0 0 0\n";
 
echo "spawn_zone win $xPos $yPos 1000000 100000 0 0 false 0 0 0\n";
 +
foreach($players as $p)
 +
filetee($p->name, $p->name, 3);
 
@clock("stop");
 
@clock("stop");
 
goto end;
 
goto end;
Line 371: Line 402:
 
echo "admin_kill_message 0\n";
 
echo "admin_kill_message 0\n";
 
foreach($players as $p)
 
foreach($players as $p)
{
 
 
echo "kill $p->name \n";
 
echo "kill $p->name \n";
}
 
 
echo "admin_kill_message 1\n";
 
echo "admin_kill_message 1\n";
 
}
 
}
 +
sleep(1);
 +
foreach($players as $p)
 +
filetee($p->name, $p->name, 3);
 
$state = "stopped";
 
$state = "stopped";
 
return;
 
return;
Line 387: Line 419:
 
function filetee($search, $requester, $amount = 3, $display_top = false, $onlyrank = false)
 
function filetee($search, $requester, $amount = 3, $display_top = false, $onlyrank = false)
 
{
 
{
global $file, $current_inc;
+
global $file;
 
$found = false;
 
$found = false;
 
$lines = file($file);
 
$lines = file($file);
Line 402: Line 434:
 
}
 
}
 
if($display_top) $i = 0;
 
if($display_top) $i = 0;
 +
if($amount > 150) $amount = 150;
 
if($amount %2 == 0) $amount += 1;
 
if($amount %2 == 0) $amount += 1;
 
$amount = floor($amount/2);
 
$amount = floor($amount/2);
 
if($i == 0 || $i == sizeof($lines)-1) //display an extra entry for 1st and last place
 
if($i == 0 || $i == sizeof($lines)-1) //display an extra entry for 1st and last place
 
$amount += 1;
 
$amount += 1;
if($found == false && !$display_top && !$onlyrank) pm($requester, "0xff7777$search not found on the list of fastest times for $current_inc");
+
if($found == false && $display_top == false)
 +
return false;
 
for($x = $i-$amount; $x <= $i+$amount; $x++)
 
for($x = $i-$amount; $x <= $i+$amount; $x++)
 
{
 
{
Line 416: Line 450:
 
function suffix($number)
 
function suffix($number)
 
{
 
{
if($number == 1) $sufx = "st";
+
$n = (string)$number;
elseif($number == 2) $sufx = "nd";
+
    $n = $n[strlen($n)-1];
elseif($number == 3) $sufx = "rd";
+
if($n == 1) $sufx = "st";
 +
elseif($n == 2) $sufx = "nd";
 +
elseif($n == 3) $sufx = "rd";
 
else $sufx = "th";
 
else $sufx = "th";
 +
if($number == 11 || $number == 12 || $number == 13) //english is weird
 +
$sufx = "th";
 
return $sufx;
 
return $sufx;
 
}
 
}
Line 430: Line 468:
 
$tail = $mapname;
 
$tail = $mapname;
 
echo $head . " " . $tail . "\n";
 
echo $head . " " . $tail . "\n";
foreach($players as $p)
 
$p->finish_time = -1;
 
 
 
 
$cut = explode("/", $tail);
 
$cut = explode("/", $tail);
Line 442: Line 478:
 
}
 
}
 
$cut = explode("-", $current_inc);
 
$cut = explode("-", $current_inc);
$current_inc = $cut[0];
+
$current_inc = trim($cut[0]);
$current_inc = trim($current_inc);
+
if(empty($current_inc)) c("0xff7777Warning: 0xffffffUnable to retrieve current map name.");
 
return empty($current_inc) ? "null" : $current_inc;
 
return empty($current_inc) ? "null" : $current_inc;
 
}
 
}
Line 474: Line 510:
 
function pickmap($includes, $rotate_mode)
 
function pickmap($includes, $rotate_mode)
 
{
 
{
static $i, $played;
+
static $i;
 
if($rotate_mode == 1)
 
if($rotate_mode == 1)
 
return $includes[mt_rand(0, sizeof($includes)-1)];
 
return $includes[mt_rand(0, sizeof($includes)-1)];
Line 493: Line 529:
 
}
 
}
 
}
 
}
 +
function smart_time($countdown_secs_after_finish)
 +
{
 +
global $file, $current_inc;
 +
static $initial_countdown_secs;
 +
if(empty($initial_countdown_secs)) $initial_countdown_secs = $countdown_secs_after_finish;
 +
if($initial_countdown_secs < 100)
 +
$MAX_TIME = 75; //smart time will not allow more than 75 secs
 +
else
 +
$MAX_TIME = $initial_countdown_secs * 1.3;
 +
$lines = file($file);
 +
if(!file_exists($file)) return $initial_countdown_secs;
 +
$split = explode(" ", $lines[0]);
 +
$hs = $split[0];
 +
$split = explode(" ", $lines[1]);
 +
$hs2nd = $split[0];
 +
if(empty($hs)) return 60;
 +
 +
if($hs*1.3 < $initial_countdown_secs) return $initial_countdown_secs;
 +
if(empty($hs2nd)) return ($hs*2) > $MAX_TIME ? $MAX_TIME : round($hs*2);
 +
if(($hs2nd - $hs) > 8) $hs = $hs2nd;
 +
return ($hs*1.3) > $MAX_TIME ? $MAX_TIME : round($hs*1.3);
 +
}
 +
function search($me, $search, $amount = 3)
 +
{
 +
global $players;
 +
$count = 0;
 +
foreach($players as $p)
 +
{
 +
if($p->pname == $search || $p->name == $search)
 +
{
 +
$found = $p->name;
 +
$count = 1;
 +
break;
 +
}
 +
if(stripos("{$p->pname}","$search") !== false || stripos("{$p->name}","$search") !== false)
 +
{
 +
$count++;
 +
$found = $p->name;
 +
}
 +
}
 +
if($count > 1)
 +
pm($me->name, "More than one player with the name '$search', using $found.");
 +
if(empty($count))
 +
{
 +
if(filetee($search, $me->name, $amount, false, false) == false)
 +
{
 +
global $file;
 +
$lines = file($file);
 +
foreach($lines as $line)
 +
{
 +
$pieces = explode(" ", $line);
 +
if(stripos("$pieces[1]","$search") !== false)
 +
{
 +
$found = $pieces[1];
 +
$count++;
 +
break;
 +
}
 +
}
 +
}
 +
}
 +
if(empty($found) || empty($count) || filetee($found, $me->name, -2, false, false) === false)
 +
{
 +
pm($me->name, "No times found for player: $search");
 +
return;
 +
}
 +
filetee($found, $me->name, $amount, false, false);
 +
}
 +
 
function version($me)
 
function version($me)
 
{
 
{
Line 499: Line 603:
 
pm($me->name, "0xffff00Made for smart's server");
 
pm($me->name, "0xffff00Made for smart's server");
 
}
 
}
 +
/*
 +
known bugs:
 +
-respawn breaks script
 +
-you should login to protect your times not showing
 +
-times showed twise if time run out
 +
-if you never won, top 3 won't show
 +
 +
foreach($players as $p)
 +
{
 +
if(!(strstr($p->name, '@')))
 +
pm($p->name, "0xffddaaYou should /login to protect your times!");
 +
}
 +
 +
*/
 
?>
 
?>
 
</pre>
 
</pre>

Revision as of 05:54, 8 May 2012

Last Updated - 8 May 2012

#!/usr/bin/php
<?php
/*  Race Script
		Includes highscores per map, finish timers, map/cfg rotator, and more
		Requires a TargetZone as a finish line, winzones will not work
		If you are not using Rx Hosting your directory needs write permission
		Made by dukevin (dukevinjduke@gmail.com)
*/

$save_directory_location = "/home/duke/aa/servers/smart/var/logs/";   //The directory to save files. Must end with trailing slash

$countdown_secs_after_finish = 30;	//After someone finishes, how many seconds on the timer before the round ends?

$countdown_if_last_player = true; //If only 1 player remaining, start the timer?

$max_time_limit = -1; //start the timer after this many seconds, -1 to disable time limits

$points = array(10, 7, 5, 4, 3, 2, 1, 1, 1, 1); //points awarded for 1st, 2nd, 3rd, 4th, 5th, etc...

$display_mode = 1; //If set to "1" display a center_message of the map name, 2 for console_message, 3 for both, 0 for no message

$display_prefix = "Current race: 0xffff00"; //When showing the map name, this is appended before it, if $display_mode is 0, this is disabled

$smart_time = true; //If true, the game will determine how many seconds to put on the timer based on previous records instead of using $countdown_secs_after_finish which will be used as the minimum amount of time instead.

$countdown_last_player_extra_time = 0; //If only 1 player remaining, give the last racer this many seconds of extra time to finish. Not needed if $smart_time is true

//Below, inbetween quotes, if you are including maps, put something like: "/path/to/map.aamap.xml". If you are using cfgs, put "mycfg.cfg" 
$includes = array("Default.cfg","8Ball.cfg","100Watts.cfg","AQuickExplosion.cfg","Aflac.cfg","AnimusonConfusion.cfg","Aoi.cfg","Arsenal.cfg","AtlanticCharter.cfg","Berlin.cfg","Cell.cfg","Cherrio.cfg",
"Compact.cfg","DevilsSandglass.cfg","Dizzy.cfg","FirePalace.cfg","BenignRevolution.cfg","BloodyHell.cfg","Chihuahua.cfg","DeathOctagon.cfg","DeathTrap.cfg","Flex.cfg","FrizzleFraz.cfg","Glacier.cfg",
"Handgrip.cfg","Holiday.cfg","Hyperpod.cfg","Illusion.cfg","Insane.cfg","ItsABug.cfg","JailBreak.cfg","Jelly.cfg","Killzone.cfg","KirbyDance.cfg","lol.cfg","Marathon.cfg","Mint.cfg","MissionImpossible.cfg",
"Moon.cfg","MovinOnUp.cfg","MrRoboto.cfg","Mutant.cfg","Nebraska.cfg","Nova.cfg","OctaGone2Death.cfg","PointOfNoReturn.cfg","PureRacingTorture.cfg","RatTunnels.cfg","Red.cfg","Resurrection.cfg",
"RoadLessTraveled.cfg","RoadOfDeath.cfg","Roundabout.cfg","Shield.cfg","SidebySide.cfg","SmallSpaces.cfg","Spiral.cfg","SpiralHam.cfg","SquareRoot.cfg","Stardome.cfg","Sun.cfg","Symmetry.cfg",
"TannersBigTronDaddy.cfg","TheMachine.cfg","TheRoadNotTaken.cfg","TikiTime.cfg","TortureChamber.cfg","Trijecture.cfg","TurnAround.cfg","Unfair.cfg","Unfortunate.cfg","Verta.cfg","Wrapper.cfg","XploderPro.cfg",
"Zero.cfg","ZigZagZaney.cfg","Zipper.cfg","Zone3.cfg");

$rotate_mode = 2; //Set to 1 for simple random, 2 to play each map in order, 3 to randomly pick a map that hasn't been picked yet.

$num_map_plays = 1; //play each map how many times before switching to next map

$zombie_win = false;  //Does the winner get a zombie? (adjust zombie_zone_speed to fit your liking)

$precision = 2; //How many decimal places to show times? A value of 3 shows X.xxx, 2 shows X.xx.  5 is max. 

/*============================== End of customization options ===================================*/

$reccomended_settings = array("target_initial_score 0", "sp_game_type 0", "game_type 0", "sp_finish_type 0", "finish_type 0", "sp_num_ais 0", "num_ais 0", "shot_seek_update_time 0.1", 
"ladderlog_write_all 1|1");  //these settings should be set for racing mode and is run every round
class Player
{
	var $name;
	var $pname;
	var $place;
	var $finish_time;
	var $best_time;
	var $num_plays;
	function __construct($name) 
	{
		$this->name = $name;
		$this->read();
		if(empty($this->num_plays)) $this->num_plays = 0;
	}
	function read()
	{
		global $file, $precision;
		$lines = file($file);
		foreach($lines as $line)
		{
			$pieces = explode(" ", $line);  //time name num_plays
			if($pieces[1] == $this->name)
			{
				$this->best_time = round($pieces[0], $precision);
				$this->num_plays = $pieces[2];
				break;
			}
		}
	}
	function write()
	{
		global $file, $current_inc;
		$found = false;
		$lines = file($file);
		if(!file_exists($file))
		{
			c("0xff7777Warning: 0xffffffFile '$current_inc.txt' not found, file creation may have failed. Retrying...");
			$fp = fopen($file, 'w');
		}
		foreach($lines as $i => $line)
		{
			$pieces = explode(" ", $line);
			$pieces[1] = trim($pieces[1]);
			if($pieces[1] == $this->name)
			{
				$lines[$i] = "$this->finish_time $this->name $this->num_plays \n";
				$found = true;
				break;
			}
		}
		if(!$found)
		{
			$lines[] = "$this->finish_time $this->name $this->num_plays \n";
		}
		sort(&$lines, SORT_NUMERIC);
		file_put_contents($file, $lines);
		fclose($fp);
	}
	function finished($time, $place)
	{
		global $points, $players, $current_inc, $precision;
		$this->num_plays++;
		$time = round($time,$precision);
		$this->finish_time = $time;
		$this->place = $place;
		$sufx = suffix($place);
		$score = $points[$place-1];
		if(empty($score)) $score = 0;
		if($place > 1)
		{
			foreach($players as $p)
			{
				if($p->place == 1)
				{
					$first = $p->finish_time;
					$difference = " 0xffffff(" . round($this->finish_time - $p->finish_time,$precision) . " s behind 1st)";
					break;
				}
			}
		}
		else 
			$difference = "";
		c("0x55ccff > 0xffff99$this->pname 0x55ccfffinished $place$sufx in 0xffff99$time 0x55ccffseconds.$difference 0x808080+{$score} pts");
		if($this->finish_time >= $this->best_time && !empty($this->best_time)) //took longer than alltime best
		{
			pm($this->name, "    0xaaaaffYour all-time best on 0xddddff{$current_inc}0xaaaaff is 0xffffff{$this->best_time} 0xaaaaffs, you are 0xffffff". round($this->finish_time - $this->best_time, $precision)." 0xaaaaffs 0xff7777slower0xaaaaff.");
		}
		if($this->finish_time < $this->best_time || empty($this->best_time))
		{
			if(!empty($this->best_time)) $oldrank = filetee($this->name, $this->name, 1, false, true) + 1;
			$this->write();
			$newrank = filetee($this->name, $this->name, 1, false, true) + 1;
			if(empty($this->best_time)) 
				pm($this->name, "    0xaaaaffThis is your first time finishing 0xddddff{$current_inc}0xaaaaff!");
			else pm($this->name, "  0x3388ff* 0x55ff88New personal record! You improved 0xffffff" . round($this->best_time - $this->finish_time,$precision) . "0x55ff88 s raising 0xffffff". ($oldrank - $newrank) ." 0x55ff88ranks!");
			if($newrank == 1) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffd700Congratulate 0xffffff$this->name 0xffd700for setting a new record on 0xffddaa$current_inc 0xffd700as the fastest time ever!0xff3333*0xffff33*0x33ff33*0x3366ff*");
			else if($newrank == 2) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->name 0xc0c0c0just ranked as the 0xffffff2nd 0xc0c0c0fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*\n");
			else if($newrank == 3) c("0xff3333*0xffff33*0x33ff33*0x3366ff*0xffffff$this->name 0xcd7f32just ranked as the 0xffcc003rd 0xcd7f32 fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*");
			else
				pm($this->name, "     0xaaaaaaYou are now rank 0xffffff$newrank 0xaaaaaaon the list of fastest times for 0xcccccc{$current_inc}0xaaaaaa!");
			
		}
		echo "add_score_player $this->name " . $score . "\n";
	}
}
$players = array();
$finished = 0;

while(true)
{
	$line = rtrim(fgets(STDIN, 1024));
	if(preg_match("/^CYCLE_CREATED/", $line))
	{
		$split = explode(" ",$line);
		$name = $split[1];
		if(getObject($name) !== false)
		{
			$num_racers++;
			goto end;
		}
		if(strstr($name,"\""))
		{	
			c("0x000000 ! 0xffff00 $name is not allowed to use the characters 0xffffff« or \" 0xffff00 in their name.");
			$clean = str_replace("\"","_",$name);
			$wo = str_replace("\"","",$name);
			echo "rename $wo $clean \n";
			echo "rename $name $clean \n";
		}
		$players[$i] = new Player($split[1]);
		if(isset($pretty))
		{
			for($x = 0; $x < sizeof($pretty); $x++)
			{
				$crack = explode("*%$", $pretty[$x]);
				if($crack[0] == $players[$i]->name)
					$players[$i]->pname = trim($crack[1]);
			}
		}
		if(!isset($players[$i]->pname))
			$players[$i]->pname = $players[$i]->name;
		if($i == 0)
		{
			$xPos = $split[2];
			$yPos = $split[3];
		}
		if(!empty($players[$i]->best_time)) $rank = filetee($players[$i]->name, $players[$i]->name, 1, false, true) + 1;
		$sufx = suffix($rank);
		pm($players[$i]->name, "0x808080Top 3 times for $current_inc:");
		filetee($players[$i]->name, $players[$i]->name, 3, true);
		if(!(strstr($players[$i]->name, '@')))
			$remind = "0x808080(Maybe because you're logged out?)";
		else
			$remind = null;
		if(!empty($players[$i]->best_time)) pm($players[$i]->name, "0x99ddffYour best time for $current_inc is 0xffffff{$players[$i]->best_time}0x99ddff s ranking 0xffffff$rank{$sufx}0x99ddff. 0x808080{$players[$i]->num_plays} finishes");
		if(empty($players[$i]->best_time)) pm($players[$i]->name, "0x99ddffYou have never won 0xcccccc$current_inc 0x99ddffbefore. $remind");
	
		$i++;
		$num_racers = $i;
	}
	if(preg_match("/^PLAYER_ENTERED/", $line))
	{   
		//PLAYER_ENTERED rx"dukevin 76.174.69.46 Rx«dukevin
		$split = explode(" ", $line);
		$pretty[] = $split[1] . "*%$" . $split[3] . " " . $split[4] . " " . $split[5];
	}
	if(preg_match("/^PLAYER_RENAMED/", $line))
	{
		$split = explode(" ", $line);
		$pretty[] = $split[2] . "*%$" . $split[5] . " " . $split[6] . " " . $split[7];
	}
	if(preg_match("/^ROUND_COMMENCING/", $line))
	{
		foreach($reccomended_settings as $s)
			echo "$s \n";
		unset($players);
		$finished = 0;
		$num_racers = 0;
		$a_player_finished = false;
		$i = 0;
		if(empty($num_plays)) $num_plays = 0;
		$num_plays++;
		if($num_plays >= $num_map_plays)
		{
			$pick = pickmap($includes, $rotate_mode);
			$num_plays = 0;
		}
		$current_inc = retrieve($pick);
		c("Reading $current_inc.txt...");
		if($display_mode == 1) echo "center_message $display_prefix$current_inc\n";
		if($display_mode == 2) c("$display_prefix$current_inc");
		if($display_mode == 3) 
		{
			echo "center_message $display_prefix$current_inc\n";
			c("$display_prefix$current_inc");
		}
		$file = "$save_directory_location" . "$current_inc" . ".txt";
		if(!file_exists($file))
		{
			c("0xffff77Warning: 0xffffff$current_inc.txt not found, creating it...");
			fopen($file, 'w');
			sleep(1);
			if(!file_exists($file))
				c("0xff7777Warning: 0xffffffFile creation failed, scores cannot be saved! Does your directory have write permission?");
		}
		if($smart_time)
			$countdown_secs_after_finish = smart_time($countdown_secs_after_finish);
		echo "target_survive_time " . ($countdown_secs_after_finish+1) ."\n";
		if(mt_rand(0,7)==7) c("0x808080You can type /stats <name> <optional amount> to view high scores for maps.");
		
		@clock("stop");
	}
	if(preg_match("/^TARGETZONE_CONQUERED/", $line) || preg_match("/^ROUND_SCORE/",$line))
	{
		if($finished == 0 || $a_player_finished == true)
			goto end;
		@clock("stop");
		$split = explode(" ", $line);
		if(preg_match("/^TARGETZONE_CONQUERED/", $line))
		{
			echo "spawn_zone win $split[3] $split[4] 1000000 10000 0 0 false 0 0 0\n";
			foreach($players as $p)
				filetee($p->name, $p->name, 3);
		}
		sleep(1);
		if(!empty($split[6])) echo "center_message Winner: {$split[6]}\n";
		echo "collapse_zone\n";
		if(empty($split[6]))
			echo "spawn_zone win $xPos $yPos 1000000 10000 0 0 false 0 0 0\n";
		$a_player_finished = true;
	}
	if(preg_match("/^INVALID_COMMAND/", $line))
	{
		$split = explode(" ", $line);
		//INVALID_COMMAND /cast rx"dukevin 76.174.69.46 accesslevel argument 50
		if($split[1] == "/stats" || $split[1] == "/s"|| $split[1] == "/search")
		{
			if(empty($split[5]))
			{
				pm($split[2], "0xff7777Invalid usage, try 0xffffff/stats <name> <amount>");
				goto end;
			}
			$obj = getObject($split[2]);
			if(empty($split[6]) || !isset($split[6])) $split[6] = 3;
			search($obj, $split[5], $split[6]);
		}
		elseif($split[1] == "/version" || $split[1] == "/v" || $split[1] == "/ver" || $split[1] == "/vers")
		{
			$obj = getObject($split[2]);
			version($obj);
		}
		elseif($split[1] == "/debug")
		{
			foreach($players as $p)
				pm($split[2], "$p->name");
		}
		else
		{
			pm($split[2], "0xff7777Invalid command, try 0xffffff/stats <name> <amount>");
		}
	}
	if(preg_match("/^TARGETZONE_PLAYER_ENTER/", $line))
	{
		//TARGETZONE_PLAYER_ENTER 2 zonename 100 100 dukevin 90.8824 103.506 1 0 37.6366
		$split = explode(" ", $line);
		$name = $split[5];
		$time = $split[10];
		$obj = getObject($name);
		if(!method_exists($obj,'finished'))
		{	
			c("0xffff77Warning: 0xffffffNo object to operate on, perhaps you just loaded scripts?");
			echo "admin_kill_message 0\n";
			echo "kill $name\n";
			echo "admin_kill_message 1\n";
			goto end;
		}
		if($obj->finish_time > 0) //already hit the finish line
			goto end;
		$finished++;
		$obj->finished($time, $finished);
		$num_racers--;
		if($zombie_win) zombieplz($split[5], $split[6], $split[7]);
		@clock("start", $countdown_secs_after_finish);
		if($num_racers <= 0)
			echo "target_survive_time " . 1 ."\n";
	}
	if(preg_match("/^GAME_TIME/", $line))
	{
		@clock("tick");
		if($max_time_limit <= 0)
			goto end;
		else
		{
			$split = explode(" ", $line);
			if($split[1] == $max_time_limit)
				clock("start", $countdown_secs_after_finish, "kill");
		}
	}
	if(preg_match("/^DEATH_FRAG|DEATH_SUICIDE|PLAYER_KILLED|DEATH_SHOT_FRAG|DEATH_DEATHZONE|DEATH_SHOT_SUICIDE|DEATH_TEAMKILL|DEATH_SHOT_TEAMKILL|DEATH_ZOMBIEZONE|DEATH_DEATHSHOT|DEATH_SELF_DESTRUCT/", $line))
	{
		$split = explode(" ", $line);
		if(empty(getObject($split[1])->finish_time))
			$num_racers--;
		if(sizeof($players) <= 1) //if only 1 player, don't start the timer
			goto end;
		if($countdown_if_last_player == false) //don't start the timer if user doesn't want it
			goto end;
		if($num_racers <= 1)
		{
			if(@clock("getState") == "active" && (empty(getObject($split[1])->finish_time))) //only winner alive, last racer died &&racer not finish
			{
				echo "spawn_zone win $xPos $yPos 1000000 100000 0 0 false 0 0 0\n";
				foreach($players as $p)
					filetee($p->name, $p->name, 3);
				@clock("stop");
				goto end;
			}
			if($num_racers != 0) clock("start", $countdown_secs_after_finish + $countdown_last_player_extra_time, "kill");
		}
	}
	
end:
}

function clock($action, $duration, $options)
{
	static $state, $time, $options;
	if($action == "start")
	{
		if($state == "active")
			return;
		$state = "active";
		$time = $duration;
		echo("center_message 0xff7777$time               \n");
	}
	if($action == "stop" || $state == "stopped")
	{
		$state = "stopped";
		$options = null;
		return;
	}
	if($action == "tick")
	{
		if($state == "stopped")
			return;
		$time--;
		echo("center_message 0xff7777$time               \n");
		if(empty($time) || $time < 0)
		{
			if($options = "kill")
			{
				global $players;
				echo "admin_kill_message 0\n";
				foreach($players as $p)
					echo "kill $p->name \n";
				echo "admin_kill_message 1\n";
			}
			sleep(1);
			foreach($players as $p)
				filetee($p->name, $p->name, 3);
			$state = "stopped";
			return;
		}
	}
	if($action == "getState")
	{
		return $state;
	}
}
function filetee($search, $requester, $amount = 3, $display_top = false, $onlyrank = false)
{
	global $file;
	$found = false;
	$lines = file($file);
	foreach($lines as $i => $line)
	{
		$pieces = explode(" ", $line);
		$pieces[1] = trim($pieces[1]);
		if($pieces[1] == $search) 
		{	
			$found = true;
			if($onlyrank) return $i;
			break;
		}
	}
	if($display_top) $i = 0;
	if($amount > 150) $amount = 150;
	if($amount %2 == 0) $amount += 1;
	$amount = floor($amount/2);
	if($i == 0 || $i == sizeof($lines)-1) //display an extra entry for 1st and last place
		$amount += 1;
	if($found == false && $display_top == false)
		return false;
	for($x = $i-$amount; $x <= $i+$amount; $x++)
	{
		$cut = explode(" ", $lines[$x]);
		$color = ($cut[1] == $search) ? '0xffff88' : '0xcccccc';
		if(!empty($cut[0])) pm($requester, $color . ($x+1) . ") $cut[0] - $cut[1]");
	}
}
function suffix($number)
{
	$n = (string)$number;
    $n = $n[strlen($n)-1];
	if($n == 1) $sufx = "st";
	elseif($n == 2) $sufx = "nd";
	elseif($n == 3) $sufx = "rd";
	else $sufx = "th";
	if($number == 11 || $number == 12 || $number == 13) //english is weird
		$sufx = "th";
	return $sufx;
}
function retrieve($mapname)
{
	$type = explode(".", $mapname);
	if($type[sizeof($type)-1] == "xml") $head = "MAP_FILE";
	elseif($type[sizeof($type)-1] == "cfg") $head = "INCLUDE";
	
	$tail = $mapname;
	echo $head . " " . $tail . "\n";
	
	$cut = explode("/", $tail);
	$split = explode(".", $cut[sizeof($cut)-1]);
	foreach($split as $element)
	{
		if($element == "aamap" || $element == "xml" || $element == "cfg")
			unset($element);
		$current_inc .= $element;
	}
	$cut = explode("-", $current_inc);
	$current_inc = trim($cut[0]);
	if(empty($current_inc)) c("0xff7777Warning: 0xffffffUnable to retrieve current map name.");
	return empty($current_inc) ? "null" : $current_inc;
}

function zombieplz($name, $x, $y)
{
	echo "spawn_zone zombieOwner $name $name $x $y 1 0 0 0 false\n";
}
function c($string){
	echo "console_message $string \n";
}
function pm($name, $string){
	echo "player_message {$name} \"{$string}\"\n";
}
function getObject($name)
{
	global $players;
	foreach($players as $p)
	{
		if($p->name == $name)
		return $p;
	}
	foreach($players as $p)
	{
		if($p->pname == $name)
		return $p;
	}
	return false;
}
function pickmap($includes, $rotate_mode)
{
	static $i;
	if($rotate_mode == 1)
		return $includes[mt_rand(0, sizeof($includes)-1)];
	if($rotate_mode == 2)
	{
		if($i > sizeof($includes)-1 || empty($i)) $i = 0;
		$x = $i;
		$i++;
		return $includes[$x];
	}
	if($rotate_mode == 3)
	{
		if($i > sizeof($includes)-1 || empty($i)) $i = 0;
		if($i == 0) shuffle($includes);
		$x = $i;
		$i++;
		return $includes[$x];
	}
}
function smart_time($countdown_secs_after_finish)
{
	global $file, $current_inc;
	static $initial_countdown_secs;
	if(empty($initial_countdown_secs)) $initial_countdown_secs = $countdown_secs_after_finish;
	if($initial_countdown_secs < 100)
		$MAX_TIME = 75; //smart time will not allow more than 75 secs
	else
		$MAX_TIME = $initial_countdown_secs * 1.3;
	$lines = file($file);
	if(!file_exists($file))	return $initial_countdown_secs;
	$split = explode(" ", $lines[0]);
	$hs = $split[0];
	$split = explode(" ", $lines[1]);
	$hs2nd = $split[0];
	if(empty($hs)) return 60;
	
	if($hs*1.3 < $initial_countdown_secs) return $initial_countdown_secs;
	if(empty($hs2nd)) return ($hs*2) > $MAX_TIME ? $MAX_TIME : round($hs*2);
	if(($hs2nd - $hs) > 8) $hs = $hs2nd;
	return ($hs*1.3) > $MAX_TIME ? $MAX_TIME : round($hs*1.3);
}
function search($me, $search, $amount = 3)
{
	global $players;
	$count = 0;
	foreach($players as $p)
	{
		if($p->pname == $search || $p->name == $search)
		{
			$found = $p->name;
			$count = 1;
			break;
		}
		if(stripos("{$p->pname}","$search") !== false || stripos("{$p->name}","$search") !== false)
		{
			$count++;
			$found = $p->name;
		}
	}
	if($count > 1)
		pm($me->name, "More than one player with the name '$search', using $found.");
	if(empty($count))
	{
		if(filetee($search, $me->name, $amount, false, false) == false)
		{
			global $file;
			$lines = file($file);
			foreach($lines as $line)
			{
				$pieces = explode(" ", $line); 
				if(stripos("$pieces[1]","$search") !== false)
				{
					$found = $pieces[1];
					$count++;
					break;
				}
			}
		}
	}
	if(empty($found) || empty($count) || filetee($found, $me->name, -2, false, false) === false)
	{
		pm($me->name, "No times found for player: $search");
		return;
	}
	filetee($found, $me->name, $amount, false, false);
}

function version($me)
{
	pm($me->name, "0xffff00Script programming by 0xffffffdukevin");
	pm($me->name, "0xffff00Email at 0xffffffdukevinjduke@gmail.com0xffff00 for suggestions, comments");
	pm($me->name, "0xffff00Made for smart's server");
}
/*
known bugs:
-respawn breaks script
-you should login to protect your times not showing
-times showed twise if time run out
-if you never won, top 3 won't show

		foreach($players as $p)
		{
			if(!(strstr($p->name, '@')))
				pm($p->name, "0xffddaaYou should /login to protect your times!");
		}

*/
?>