Advanced Racing With race timer/Script: Difference between revisions

From Armagetron Advanced
Smart (talk | contribs)
No edit summary
Armanelgtron (talk | contribs)
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<pre>
Last updated 1 June 2012
#!/usr/bin/php
 
<pre>#!/usr/bin/php
<?php
<?php
/*  Race Script
/*  Race Script
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 = 2; //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","100Watts.cfg","Aflac.cfg","AnimusonConfusion.cfg","Aoi.cfg","ApplePie.cfg","AQuickExplosion.cfg","Arco.cfg","AroundandAround.cfg","AroundTheHorn.cfg","Arsenal.cfg","AtlanticCharter.cfg","Axe.cfg","BatPigBear.cfg","BenignRevolution.cfg","Berlin.cfg","BlazingParadise.cfg","BloodyHell.cfg","Broken.cfg","Buffalo.cfg","CandyBar.cfg","Cell.cfg","Charriot.cfg","Cherrio.cfg","Chicken.cfg","Chihuahua.cfg","Claw.cfg","Colombo.cfg","Compact.cfg","Croma.cfg","DeathOctagon.cfg","DeathTrap.cfg","Disastro.cfg","Divided.cfg","Dizzy.cfg","DontFlinch.cfg","Dragrace.cfg","Eighty.cfg","FirePalace.cfg","Fobia.cfg","Four.cfg","Flex.cfg","FrizzleFraz.cfg","Glacier.cfg","Guitar.cfg","Handgrip.cfg","Holiday.cfg","Hurricania.cfg","Hyperpod.cfg","Illusion.cfg","Insanity.cfg","ItsABug.cfg","JailBreak.cfg","Jelly.cfg","Jester.cfg","KirbyDance.cfg","LetsDance.cfg","Lava.cfg","lol.cfg","Luigi.cfg","Marathon.cfg","Margarita.cfg","Mario.cfg","Mint.cfg","Moon.cfg","MovinOnUp.cfg","MrRoboto.cfg","Mutant.cfg","Nebraska.cfg","Nova.cfg","OctaGone2Death.cfg","Octarace.cfg","One.cfg","OnePathv2.cfg","Organius.cfg","Paura.cfg","PewPew.cfg","PillsburyDrummerboy.cfg","Pirata.cfg","PointOfNoReturn.cfg","Pow.cfg","PureRacingTorture.cfg","RacersOnYourMark.cfg","RatTunnels.cfg","Resurrection.cfg","RoadLessTraveled.cfg","Roundabout.cfg","Seven.cfg","Shield.cfg","ShoppingMall.cfg","SidebySide.cfg","Six.cfg","SmallSpaces.cfg","Spiral.cfg","SpiralHam.cfg","SquareRoot.cfg","Stardome.cfg","Sun.cfg","Symmetry.cfg","TannersBigTronDaddy.cfg","TheMachine.cfg","TheRoadNotTaken.cfg","Three.cfg","TikiTime.cfg","TortureChamber.cfg","Trijecture.cfg","Trucco.cfg","TurnAround.cfg","Two.cfg","Unfortunate.cfg","Verta.cfg","Verta2.cfg","Voltrobe.cfg","What.cfg","WhatTheHECK.cfg","Wrapper.cfg","XploderPro.cfg","Zero.cfg","ZigZag.cfg","ZigZagZaney.cfg","Zipper.cfg","Zone4.cfg");
"DevilsSandglass.cfg","Dizzy.cfg","FirePalace.cfg","AQuickExplosion.cfg","BenignRevolution.cfg","BloodyHell.cfg","Chihuahua.cfg","DeathOctagon.cfg","DeathTrap.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",
"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","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.
$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 = 2; //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 = 3; //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


$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 once when the script is loaded
class Player
class Player
{
{
Line 51: Line 60:
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 101:
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, $file;
$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 119:
{
{
$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 126:
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 138:
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 0xcd7f32fastest 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 0xaaaaaaof ".(count(file($file)))." as the fastest time for 0xcccccc{$current_inc}0xaaaaaa!");
}
}
echo "add_score_player $this->name " . $score . " \n";
echo "add_score_player $this->name " . $score . "\n";
}
}
}
}
$players = array();
$players = array();
$finished = 0;
$finished = 0;
 
$i=0;
while(true)
while(true)
{
{
Line 152: Line 159:
$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 191:
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 of ".count(file($file)).".");
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 198: Line 208:
$split = explode(" ", $line);
$split = explode(" ", $line);
$pretty[] = $split[1] . "*%$" . $split[3] . " " . $split[4] . " " . $split[5];
$pretty[] = $split[1] . "*%$" . $split[3] . " " . $split[4] . " " . $split[5];
$pretty = array_slice($pretty,sizeof($pretty)-40,40);
}
}
if(preg_match("/^PLAYER_RENAMED/", $line))
if(preg_match("/^PLAYER_RENAMED/", $line))
Line 208: Line 219:
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 223: Line 233:
$current_inc = retrieve($pick);
$current_inc = retrieve($pick);
c("Reading $current_inc.txt...");
c("Reading $current_inc.txt...");
if($display_mode == 1) echo "center_message $display_prefix$current_inc\n";
switch($display_mode)
if($display_mode == 2) c("$display_prefix$current_inc");
if($display_mode == 3)  
{
{
echo "center_message $display_prefix$current_inc\n";
case 3:
c("$display_prefix$current_inc");
c("$display_prefix$current_inc");
case 2:
echo "center_message $display_prefix$current_inc\n";
break;
case 1:
c("$display_prefix$current_inc");
}
}
$file = "$save_directory_location" . "$current_inc" . ".txt";
$file = "$save_directory_location" . "$current_inc" . ".txt";
Line 235: Line 248:
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 272:
}
}
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 282:
$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;
$obj = getObject($split[2]);
if(empty($split[5]))
if(empty($split[6]) || !isset($split[6])) $split[6] = 3;
{
if(empty($split[5]) || !isset($split[5]))
pm($split[2], "0xff7777Invalid usage, try 0xffffff/stats <name> <amount>");
$split[5] = $split[2];
goto end;
search($obj, $split[5], $split[6]);
}
filetee($split[5], $split[2], $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 294:
$obj = getObject($split[2]);
$obj = getObject($split[2]);
version($obj);
version($obj);
}
elseif($split[1] == "/debug")
{
pm($split[2], "Number of maps rotating: " . count($includes));
pm($split[2], "Number pnames in memory: " . count($pretty));
pm($split[2], "Player Objects:");
foreach($players as $p)
pm($split[2], "$p->name");
}
}
else
else
Line 320: Line 348:
{
{
$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 356:
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 337: Line 367:
}
}
}
}
if(preg_match("/^ROUND_WINNER/", $line))
foreach($players as $p)
{
if(!(strstr($p->name, '@')))
pm($p->name, "0xffddaaYou should /login to protect your times!");
}
end:
end:
Line 371: Line 407:
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 424:
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 439:
}
}
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 412: Line 451:
$color = ($cut[1] == $search) ? '0xffff88' : '0xcccccc';
$color = ($cut[1] == $search) ? '0xffff88' : '0xcccccc';
if(!empty($cut[0])) pm($requester, $color . ($x+1) . ") $cut[0] - $cut[1]");
if(!empty($cut[0])) pm($requester, $color . ($x+1) . ") $cut[0] - $cut[1]");
usleep(20000);
}
}
}
}
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 474:
$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 484:
}
}
$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 516:
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 535:
}
}
}
}
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 containing '$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 609:
pm($me->name, "0xffff00Made for smart's server");
pm($me->name, "0xffff00Made for smart's server");
}
}
/*
known bugs:
-/stats on rank 1 display twise
-respawn breaks script
+fixed: you should login to protect your times not showing
-times showed twise if time run out -> instead make all score things shown before round_Commencing?
- $me->num_plays doesn't incriment unless you beat your time //because it doesn't write
+ fixed x of y
*/
?>
?>
</pre>
</pre>
[[Category:Administration]]

Latest revision as of 01:22, 9 March 2023

Last updated 1 June 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 = 2; //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","100Watts.cfg","Aflac.cfg","AnimusonConfusion.cfg","Aoi.cfg","ApplePie.cfg","AQuickExplosion.cfg","Arco.cfg","AroundandAround.cfg","AroundTheHorn.cfg","Arsenal.cfg","AtlanticCharter.cfg","Axe.cfg","BatPigBear.cfg","BenignRevolution.cfg","Berlin.cfg","BlazingParadise.cfg","BloodyHell.cfg","Broken.cfg","Buffalo.cfg","CandyBar.cfg","Cell.cfg","Charriot.cfg","Cherrio.cfg","Chicken.cfg","Chihuahua.cfg","Claw.cfg","Colombo.cfg","Compact.cfg","Croma.cfg","DeathOctagon.cfg","DeathTrap.cfg","Disastro.cfg","Divided.cfg","Dizzy.cfg","DontFlinch.cfg","Dragrace.cfg","Eighty.cfg","FirePalace.cfg","Fobia.cfg","Four.cfg","Flex.cfg","FrizzleFraz.cfg","Glacier.cfg","Guitar.cfg","Handgrip.cfg","Holiday.cfg","Hurricania.cfg","Hyperpod.cfg","Illusion.cfg","Insanity.cfg","ItsABug.cfg","JailBreak.cfg","Jelly.cfg","Jester.cfg","KirbyDance.cfg","LetsDance.cfg","Lava.cfg","lol.cfg","Luigi.cfg","Marathon.cfg","Margarita.cfg","Mario.cfg","Mint.cfg","Moon.cfg","MovinOnUp.cfg","MrRoboto.cfg","Mutant.cfg","Nebraska.cfg","Nova.cfg","OctaGone2Death.cfg","Octarace.cfg","One.cfg","OnePathv2.cfg","Organius.cfg","Paura.cfg","PewPew.cfg","PillsburyDrummerboy.cfg","Pirata.cfg","PointOfNoReturn.cfg","Pow.cfg","PureRacingTorture.cfg","RacersOnYourMark.cfg","RatTunnels.cfg","Resurrection.cfg","RoadLessTraveled.cfg","Roundabout.cfg","Seven.cfg","Shield.cfg","ShoppingMall.cfg","SidebySide.cfg","Six.cfg","SmallSpaces.cfg","Spiral.cfg","SpiralHam.cfg","SquareRoot.cfg","Stardome.cfg","Sun.cfg","Symmetry.cfg","TannersBigTronDaddy.cfg","TheMachine.cfg","TheRoadNotTaken.cfg","Three.cfg","TikiTime.cfg","TortureChamber.cfg","Trijecture.cfg","Trucco.cfg","TurnAround.cfg","Two.cfg","Unfortunate.cfg","Verta.cfg","Verta2.cfg","Voltrobe.cfg","What.cfg","WhatTheHECK.cfg","Wrapper.cfg","XploderPro.cfg","Zero.cfg","ZigZag.cfg","ZigZagZaney.cfg","Zipper.cfg","Zone4.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 = 2; //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 = 3; //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, $file;
		$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 0xcd7f32fastest time for $current_inc!0xff3333*0xffff33*0x33ff33*0x3366ff*");
			else
				pm($this->name, "     0xaaaaaaYou are now rank 0xffffff$newrank 0xaaaaaaof ".(count(file($file)))." as the fastest time for 0xcccccc{$current_inc}0xaaaaaa!");
			
		}
		echo "add_score_player $this->name " . $score . "\n";
	}
}
$players = array();
$finished = 0;
$i=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 of ".count(file($file)).".");
		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];
		$pretty = array_slice($pretty,sizeof($pretty)-40,40);
	}
	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...");
		switch($display_mode)
		{
			case 3:
				c("$display_prefix$current_inc");
			case 2:
				echo "center_message $display_prefix$current_inc\n";
				break;
			case 1:
				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")
		{
			$obj = getObject($split[2]);
			if(empty($split[6]) || !isset($split[6])) $split[6] = 3;
			if(empty($split[5]) || !isset($split[5]))
				$split[5] = $split[2];
			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")
		{
			pm($split[2], "Number of maps rotating: " . count($includes));
			pm($split[2], "Number pnames in memory: " . count($pretty));
			pm($split[2], "Player Objects:");
			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");
		}
	}
	if(preg_match("/^ROUND_WINNER/", $line))
		foreach($players as $p)
		{
			if(!(strstr($p->name, '@')))
				pm($p->name, "0xffddaaYou should /login to protect your times!");
		}
	
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]");
		usleep(20000);
	}
}
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 containing '$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:
-/stats on rank 1 display twise
-respawn breaks script
+fixed: you should login to protect your times not showing
-times showed twise if time run out -> instead make all score things shown before round_Commencing?
- $me->num_plays doesn't incriment unless you beat your time //because it doesn't write
+ fixed x of y
*/

?>