sub GetThereWindow { # returns hook on the There window or null string if fails my @w = Win32::GuiTest::FindWindowLike(); my $title; for (@w) { $title = Win32::GuiTest::GetWindowText($_); if ($title eq "There (DX8)") { return $_;} if ($title eq "There (DX9)") { return $_;} if ($title eq "There (OGL)") { return $_;} # IMPORTANT: if your There window shows something different from DX8 # or DX9 or OGL then you must change the above line accordingly. if ($title =~ m/^There \(...\)/) { return $_;} } return ""; } sub SendShiftCtrlL { # send SHIFT-CTRL-L to a specified window my $wintarget = shift; my $winsave = Win32::GuiTest::GetForegroundWindow(); Win32::GuiTest::SetForegroundWindow($wintarget); sleep 1; Win32::GuiTest::SendKeys("^+L"); Win32::GuiTest::SetForegroundWindow($winsave); return 0; } sub GetPilotDoid { # return DOID of the logged-on avatar $req = HTTP::Request->new('GET', $URLpilot); $res = $ua->request($req); $res->content =~ m/([0-9]+)<\/PilotDoid>/ ; return $1; } sub GetThobLocation { # returns (x,y,z,heading,altitude) for specified Thob my $dob = shift; my ($x,$y,$z,$head,$alt,$ret,$xmlh); $req = HTTP::Request->new('GET', $URLloc . $dob ); $res = $ua->request($req); $ret = $res->content; $xmlh = XMLin($ret, ForceArray => 0); # parse returned XML $x = $xmlh->{posX}; $y = $xmlh->{posY}; $z = $xmlh->{posZ}; $head = $xmlh->{heading}; $alt = (sqrt($x**2+$y**2+$z**2)-6000000) ; return ($x,$y,$z,$head,$alt); } sub HowMuchToTurn { # returns heading correction needed to face an object at specified x,y # positive means turn left; negative means turn right my ($doid, $xto, $yto) = @_; my ($x, $y, $z, $head) = &GetThobLocation($doid); $globalmyx = $x; $globalmyy = $y; my $b = -atan2($xto-$x,$yto-$y) * (180/3.14159) ; if ($b < 0) {$b += 360;} my $corr = $b - $head; if ($corr < -180) {$corr += 360;} if ($corr > 180) {$corr -= 360;} return $corr; } sub SendTimedArrow { my ($code,$time,$sleepfor) = @_; $key->Call($arrowcodes{$code}, 0x45, 0x01, 0); $sleep->Call($time); $key->Call($arrowcodes{$code}, 0x45, 0x03, 0); $sleep->Call($sleepfor); } sub StepAvatar { my $steps = shift; &SendTimedArrow("U",int(475*$steps),400); } sub StepBackAvatar { my $steps = shift; &SendTimedArrow("D",int(680*$steps),400); } sub TurnLeftAvatar { &SendTimedArrow("L",615,400); } sub TurnRightAvatar { &SendTimedArrow("R",615,400); } sub RunAvatar { my $steps = shift; $key->Call(0x26, 0x45, 0x01, 0); $sleep->Call(100); $key->Call(0x26, 0x45, 0x03, 0); $sleep->Call(100); $key->Call(0x26, 0x45, 0x01, 0); $sleep->Call(100); $key->Call(0x26, 0x45, 0x03, 0); $sleep->Call(100); $key->Call(0x26, 0x45, 0x01, 0); $sleep->Call(312*$steps); $key->Call(0x26, 0x45, 0x03, 0); $sleep->Call(500); } sub SteerToLocation { # send left and right arrows to steer towards a destination # returns distance to destination my ($doid, $therewin, $xto, $yto) = @_; Win32::GuiTest::SetForegroundWindow($therewin); $sleep->Call(1000); my $corr = &HowMuchToTurn($doid, $xto, $yto); if ($corr > 0) {$key->Call(0x25, 0x45, 0x01, 0);} # press left if ($corr < 0) {$key->Call(0x27, 0x45, 0x01, 0);} # press right if (abs($corr) > 10) {$sleep->Call(150);} else {$sleep->Call(15*abs($corr));} if ($corr > 0) {$key->Call(0x25, 0x45, 0x03, 0);} # release left if ($corr < 0) {$key->Call(0x27, 0x45, 0x03, 0);} # release right return sqrt(($xto-$globalmyx)**2+($yto-$globalmyy)**2); } sub StopMe { # sends 2 secs of Down key five times my $i; $key->Call(0x26, 0x45, 0x03, 0); # release up for ($i = 0; $i < 5; $i++) { $key->Call(0x28, 0x45, 0x01, 0); # press down $sleep->Call(2000); $key->Call(0x28, 0x45, 0x03, 0); # release down $sleep->Call(100); } } sub TeleportToPlace { my $place = shift; $place =~ s/ /+/g; $place =~ s/\'/%27/g; my $resp = &GetWebappsURL($URLtelePlace . $place, $myavname, $mypassword); if ($resp =~ m/([^<]+)<\/Value>/) { return $1; } else { return 99; # unable to parse return value } print $resp; } sub TeleportToDoid { my $doid = shift; my $resp = &GetWebappsURL($URLteleDoid . $doid, $myavname, $mypassword); if ($resp =~ m/([^<]+)<\/Value>/) { return $1; } else { return 99; # unable to parse return value } print $resp; } sub TeleportToFavorite { my ($therewin,$favno) = @_; Win32::GuiTest::SetForegroundWindow($therewin); sleep 1; ($x,$y) = Win32::GuiTest::GetWindowRect($therewin); Win32::GuiTest::MouseMoveAbsPix($x+242,$y+613); sleep 1; Win32::GuiTest::SendMouse("{LEFTCLICK}"); # Places button sleep 1; Win32::GuiTest::MouseMoveAbsPix($x+242,$y+542); sleep 1; Win32::GuiTest::SendMouse("{LEFTCLICK}"); # Go to Favorites button sleep 1; Win32::GuiTest::MouseMoveAbsPix($x+356,$y+542); sleep 1; Win32::GuiTest::MouseMoveAbsPix($x+356,$y+612-23*$favno); sleep 1; Win32::GuiTest::SendMouse("{LEFTCLICK}"); # Teleport! sleep 20; Win32::GuiTest::MouseMoveAbsPix($x+100,$y+100); sleep 1; Win32::GuiTest::SendMouse("{LEFTCLICK}"); # click on main window } sub MainMenuChoice { my @clicks = @_; my $click; my $url = $URLmainMenu; # must take window focus, else MainMenu is unavailable Win32::GuiTest::SetForegroundWindow(&GetThereWindow()); foreach $click (@clicks) { $click =~ s/ /+/g; $click =~ s/\'/%27/g; $url .= ($click . "%2F"); } $url .= "activate"; $req = HTTP::Request->new('GET', $url); $res = $ua->request($req); my $ret = $res->content; if ($ret =~ m/([^<]+)<\/ErrorCode>/) { return $1; } else {return 0;} } sub PrintTeleportableDOIDs { my @refs = @_;; my ($ref,$doid,$loc,$tag,$descr,$owner); foreach $ref (@refs) { $ref =~ m/doid=([0-9]+)$/ ; $doid = $1; $req = HTTP::Request->new('GET', $ref); $res = $ua->request($req); $loc = ""; if ($res->content =~ m/Position<\/td>(\([^)]+\))/ ) {$loc = $1;} if ($loc) { $loc =~ m/\(([0-9-]+)\..+,([0-9-]+)\..+,([0-9-]+)\./ ; $loc = "($1,$2,$3)"; } $tag = ""; $descr = ""; $owner = ""; if ($res->content =~ m/signScript=/) { $tag = "Sign"; if ($res->content =~ m/ownerDoid=([0-9]+)/) {$owner=$1;} } if ($res->content =~ m/zoneHouseName=\"([^"]+)\"/) { if ($1 ne "None") {$tag = "$1";} if ($res->content =~ m/code=52 textSlot=\{text=\"([^\"]+)\"/) {$tag = $1;} if ($res->content =~ m/code=50 textSlot=\{text=\"([^\"]+)\"/) {$descr = $1;} } if ($res->content =~ m/PortaZone/) { $tag = "PortaZone"; if ($res->content =~ m/ownerDoid=([0-9]+)/) {$owner=$1;} } if ($tag) { print "$doid $loc <$tag> <$descr> <$owner>\n";} } } sub GetThobDetailURLs { my @tmp = (); $req = HTTP::Request->new('GET', $URLdobs ); $res = $ua->request($req); my $output = $res->content; while ($output =~ m/details\?doid=([0-9]+)/g) { push @tmp, $URLdetails . $1 ;} return @tmp; } sub PrintDOIDdetails { my @refs = @_;; my ($ref,$doid,$profile,$name,$married,$gender,$age,$response,$country); foreach $ref (@refs) { $ref =~ m/doid=([0-9]+)$/ ; $doid = $1; $req = HTTP::Request->new('GET', $ref); $res = $ua->request($req); if ($res->content =~ m/Clide<\/td>Avatar3<\/td>/ ) { $response = GetWebappsURL($URLprofileDoid . $doid, $myavname,$mypassword); $profile = XMLin($response, ForceArray => 0); $name = $profile->{profile}->{attrib}->{AvatarName}->{value}; $gender = $profile->{profile}->{attrib}->{gender}->{value}; $married = $profile->{profile}->{attrib}->{maritalstatus}->{value}; $age = $profile->{profile}->{attrib}->{age}->{value}; $country = $profile->{profile}->{attrib}->{country}->{value}; $lout = "$name $gender $age $married $country\n"; if ($lout =~ m/\S/) {print $lout;} } } } sub GetWebappsURL { my ($wptcURL,$avatar,$passwd) = @_; if ($wptcURL !~ m/^${URLwptc}/i) { return "First arg must begin with $URLwptc\n"; } $req = HTTP::Request->new('GET' => $wptcURL); $res = $ua->request($req); my $response = $res->content; if ($response =~ m/]+URL=([^\"]+login\?)redirect=[^\"]+\"/) { $head = $1; print "LOGGING IN.....\n"; my $loginARG = "sendAsLoginData=1&avname=$avatar&password=$passwd"; $req = HTTP::Request->new('GET' => $head.$loginARG); $res = $ua->request($req); $response = $res->content; if ($response =~ m/Login Succeeded!/) { $req = HTTP::Request->new('GET' => $wptcURL ); $res = $ua->request($req); $response = $res->content; return $response; } else { return "Login Failed!\n"; } } return $response; } 1;