# Satellite Kore ver 1008 Fatless Custom 人柱版 [Base:я-Float kore 9.0N] #各種拡張の読み込み use Time::HiRes qw(time usleep sleep gettimeofday); use IO::Socket; use Win32::API; use HTTP::Lite; use Getopt::Long; srand(time()); use Win32::Console;$CONSOLE = new Win32::Console(STD_OUTPUT_HANDLE);system(cls); use Tk; use Encode; print "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n"; print "■ ■\n"; print "■ Satellite Kore ver 1008 Fatless Custom 人柱版 ■\n"; print "■ Base[я-Float kore 9.0N] ■\n"; print "■ ┗[jkore氏/あるプログラマー氏/curoad氏コード] ■\n"; print "■ ■\n"; print "■ 改悪:BOT星人 ■\n"; print "■ ぶろぐ:http://ameblo.jp/botalien/ ■\n"; print "■ ■\n"; print "■ \さて、これ使お〜にゃ♪/ ■\n"; print "■ ∧_∧ ∧_∧ ■\n"; print "■ ( ・∀・) (・∀・ ) ■\n"; print "■ ノ( )ヽ[さてkore]ノ( )ヽ ■\n"; print "■ レ^J レ^J ■\n"; print "■ ■\n"; print "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\n"; # ParsePacketList $parsePacket = <<"PPL"; 0069 1 006A 1 006B 1 006C 1 0071 1 0073 1 0075 1 0077 1 0078 1 0079 1 01D9 1 007A 1 007B 1 01DA 1 007C 1 007F 1 0080 1 0081 1 0087 1 0088 1 008A 1 008D 1 008E 1 0091 1 0092 1 0095 1 0097 1 0098 1 009A 1 009C 1 009D 1 009E 1 00A0 1 00A1 1 01EE 1 00A3 1 00A4 1 01F0 1 00A5 1 00A6 1 00A8 1 00AA 1 00AC 1 00AF 1 00B0 1 00B1 1 00B3 1 00B4 1 00B5 1 00B6 1 00B7 1 00BD 1 00BE 1 00C0 1 00C2 1 00C4 1 00C6 1 00C7 1 00D1 1 00D2 1 00D4 1 00E5 1 01F4 1 00EE 1 00F0 1 00F2 1 00F4 1 00F6 1 00F8 1 00FB 1 00FE 1 0101 1 0109 1 010A 1 010B 1 010E 1 010F 1 0110 1 0111 1 0114 1 01DE 1 0117 1 0119 1 011A 1 011C 1 011F 1 0120 1 0121 1 0122 1 01EF 1 0123 1 0125 1 012C 1 0136 1 0137 1 0139 1 013B 1 013C 1 013D 1 013E 1 0141 1 0142 1 0147 1 0148 1 016C 1 O17F 1 0187 1 0189 1 018B 1 018C 1 018D 1 018F 1 0195 1 0196 1 019B 1 01A2 1 01A3 1 01A4 1 01AB 1 01AC 1 01AD 1 01B0 1 01B5 1 01B9 1 01C4 1 0124 1 01C5 1 01C7 1 01C8 1 01C9 1 01D0 1 01D2 1 01D8 1 01DC 1 01E1 1 0207 1 022A 1 022B 1 022C 1 PPL @parsePacket = split("\n", $parsePacket); foreach $sLine (@parsePacket) { chomp($sLine); @a = split(" ", $sLine); $parsePacket{$a[0]} = $a[1]; } $VK_KEYDOWN = 256; $VK_KEYUP = 257; $VK_INSERT = 45; $VK_RETURN = 13; $VK_F1 = 112; $VK_F8 = 119; $packSize0089 = 0; $packSize0113 = 0; $moveFlag = 2; &GetOptions('Xkore_mode', \$WithRagexe); addParseFiles("control/config.txt", \%config, \&parseDataFile2); addParseFiles("control/boutique.txt", \%boutique, \&parseDataFile2); addParseFiles("control/roten.txt", \%roten, \&parseDataFile2); addParseFiles("control/items_control.txt", \%items_control, \&parseItemsControl); addParseFiles("control/mon_control.txt", \%mon_control, \&parseMonControl); addParseFiles("control/pickupitems.txt", \%itemsPickup, \&parseDataFile_lc); addParseFiles("control/responses.txt", \%responses, \&parseResponses); addParseFiles("control/timeouts.txt", \%timeout, \&parseTimeouts); addParseFiles("control/sorryword.txt", \@sorryWord, \&parseDataFile3); addParseFiles("control/angryword.txt", \@angryWord, \&parseDataFile3); addParseFiles("control/namuword.txt", \@namuWord, \&parseDataFile3); addParseFiles("control/autores.txt", \%autores, \&parseDataFile); addParseFiles("control/importantitems.txt", \@ImportantItems, \&parseDataFile3); addParseFiles("tables/headitems.txt", \%headItems_lut, \&parseDataFile2); addParseFiles("tables/cities.txt", \%cities_lut, \&parseROLUT); addParseFiles("tables/emotions.txt", \%emotions_lut, \&parseEmotions); addParseFiles("tables/emotions.txt", \%emotionsCom, \&parseEmotionsCom); addParseFiles("tables/equiptypes.txt", \%equipTypes_lut, \&parseDataFile2); addParseFiles("tables/items.txt", \%items_lut, \&parseROLUT); addParseFiles("tables/itemslotscount.txt", \%itemslotscount_lut, \&parseROLUT); addParseFiles("tables/itemslots.txt", \%itemSlots_lut, \&parseROSlotsLUT); addParseFiles("tables/itemtypes.txt", \%itemTypes_lut, \&parseDataFile2); addParseFiles("tables/jobs.txt", \%jobs_lut, \&parseDataFile2); addParseFiles("tables/maps.txt", \%maps_lut, \&parseROLUT); addParseFiles("tables/mapsin.txt", \%mapsin_lut, \&parseDataFile2); addParseFiles("tables/monsters.txt", \%monsters_lut, \&parseDataFile2); addParseFiles("tables/npcs.txt", \%npcs_lut, \&parseNPCs); addParseFiles("tables/portals.txt", \%portals_lut, \&parsePortals); addParseFiles("tables/portalsLOS.txt", \%portals_los, \&parsePortalsLOS); addParseFiles("tables/sex.txt", \%sex_lut, \&parseDataFile2); addParseFiles("tables/skills.txt", \%skills_lut, \&parseSkillsNewLUT); addParseFiles("tables/skills.txt", \%skillsID_lut, \&parseSkillsNewIDLUT); addParseFiles("tables/skills.txt", \%skillsCD_lut, \&parseSkillsNewCDLUT); addParseFiles("tables/skills.txt", \%skills_rlut, \&parseSkillsNewReverseLUT_lc); addParseFiles("tables/skills.txt", \%skillsCD_rlut, \&parseSkillsNewCDReverseLUT_lc); addParseFiles("tables/skillssp.txt", \%skillsSP_lut, \&parseSkillsSPLUT); addParseFiles("tables/skillstime.txt", \%skillsTime_lut, \&parseSkillsSPLUT); addParseFiles("tables/cards.txt", \%cards_lut, \&parseCARDLUT); addParseFiles("tables/attribute.txt", \%attribute_lut, \&parseROLUT); addParseFiles("tables/star.txt", \%star_lut, \&parseROLUT); addParseFiles("tables/pluralmodify.txt", \%plural, \&parseDataFile2); addParseFiles("tables/gamemasters.txt", \@GameMasters, \&parseDataFile3); addParseFiles("tables/root_monsters.txt", \@root_monsters, \&parseDataFile3); addParseFiles("log/defeat.txt", \%defeatMonster, \&parseDataFile2); addParseFiles("tables/modifiedWalk.txt", \%modifiedWalk, \&parseDataFile2); addParseFiles("tables/effects.txt", \%effectsID, \&parseSkillsNewIDLUT); addParseFiles("tables/effects.txt", \%effectsCD, \&parseSkillsNewCDLUT); addParseFiles("tables/archer.txt", \@archer, \&parseDataFile3); addParseFiles("tables/packetRotation.txt", \%packetRotation, \&parseDataFile2); addParseFiles("tables/packetLength.txt", \%hPacketLen, \&parseDataFile2); if(!-d "log"){ PrintMessage("There is no directory 'log'\n", "def"); PrintMessage("Making directory...\n", "def"); mkdir("log"); } load(\@parseFiles); $packetRotationItr = 0; $packetModify = 0; foreach (%packetRotation) { $packetRotationItr++; my $number = sprintf("p%04d", $packetRotationItr); my $length = sprintf("p%04d_0", $packetRotationItr); if ($hPacketLen{$packetRotation{$number}} ne $packetRotation{$length}){ print "$packetRotation{$number} のパケ長を変更します。($hPacketLen{$packetRotation{$number}})->($packetRotation{$length})\n"; $hPacketLen{$packetRotation{$number}} = $packetRotation{$length}; $packetModify = 1; } } if (1 == $packetModify){ print "パケット長に変更があったのでpacketLength.txtを上書きします...\n"; writeDataFileIntact("tables/packetLength.txt", \%hPacketLen); } our $WithRagexe = 0; if ( $config{'Xkore_mode'} ) { $WithRagexe = 1; } if (!$config{'buildType'}) { $CalcPath_init = new Win32::API("Tools", "CalcPath_init", "PPNNPPN", "N"); die "Could not locate Tools.dll" if (!$CalcPath_init); $CalcPath_pathStep = new Win32::API("Tools", "CalcPath_pathStep", "N", "N"); die "Could not locate Tools.dll" if (!$CalcPath_pathStep); $CalcPath_destroy = new Win32::API("Tools", "CalcPath_destroy", "N", "V"); die "Could not locate Tools.dll" if (!$CalcPath_destroy); $X_WakeUp = new Win32::API("x_util", "X_WakeUp", "P", "V"); die "Could not locate x_util.dll" if (!$X_WakeUp); $X_AutoLogin = new Win32::API("x_util", "X_AutoLogin", "NNNPPN", "V"); die "Could not locate x_util.dll" if (!$X_AutoLogin); $CreateSnapshot = new Win32::API("kernel32", "CreateToolhelp32Snapshot", "NN", "N"); $Process32First = new Win32::API("kernel32", "Process32First", "NP", "N"); $Process32Next = new Win32::API("kernel32", "Process32Next", "NP", "N"); $CloseHandle = new Win32::API("kernel32", "CloseHandle", "N", "N"); $FindWindow = new Win32::API("user32", "FindWindow", "PN", "N"); $SendMessage = new Win32::API("user32", "SendMessageA", "NNNN", "N"); } if ($config{'adminPassword'} eq 'x' x 10) { PrintMessage("\nAuto-generating Admin Password\n", "def"); configModify("adminPassword", vocalString(8)); } PrintMessage("\n", "def"); $proto = getprotobyname('tcp'); $MAX_READ = 30000; if ($WithRagexe) { ###START SERVERS $server_socket = IO::Socket::INET -> new( Listen => 5, LocalAddr => $config{'local_host'}, LocalPort => $config{'local_port'}, Proto => 'tcp', Timeout => 2, Reuse => 1); ($server_socket) || die "Error creating local server: $!"; PrintMessage("Local server started ($config{'local_host'}:$config{'local_port'})\n", "def"); $injectServer_socket = IO::Socket::INET -> new( Listen => 5, LocalAddr => $config{'local_host'}, LocalPort => $config{'inject_port'}, Proto => 'tcp', Timeout => 999, Reuse => 1); ($server_socket) || die "Error creating local inject server: $!"; PrintMessage("Local inject server started ($config{'local_host'}:$config{'inject_port'})\n", "def"); $remote_socket = IO::Socket::INET->new(); } else { $remote_socket = IO::Socket::INET -> new(); $server_socket = IO::Socket::INET -> new( Listen => 5, LocalAddr => $config{'local_host'}, LocalPort => $config{'local_port'}, Proto => 'tcp', Timeout => 2, Reuse => 1); ($server_socket) || die "Error creating local server: $!"; PrintMessage("Local server started ($config{'local_host'}:$config{'local_port'})\n", "def"); } $input_pid = input_client(); PrintMessage("\n", "def"); $conState = 0; ###COMPILE PORTALS### print "\nChecking for new portals..."; compilePortals_check(\$found); if ($found) { PrintMessage("found new portals!\n", "def"); PrintMessage("Compile portals now? (y/n)\n", "def"); PrintMessage("Auto-compile in $timeout{'compilePortals_auto'}{'timeout'} seconds...", "def"); $timeout{'compilePortals_auto'}{'time'} = time; undef $msg; while (!timeOut(\%{$timeout{'compilePortals_auto'}})) { if (dataWaiting(\$input_socket)) { $input_socket->recv($msg, $MAX_READ); } last if $msg; } if ($msg =~ /y/ || $msg eq "") { PrintMessage("compiling portals\n\n", "def"); compilePortals(); } else { PrintMessage("skipping compile\n\n", "def"); } } else { PrintMessage("none found\n", "def"); } undef $msg; $KoreStartTime = time; $ParseMsgTimeOut = time; $AI = 1 if ($config{'Stealth'}); if (!$WithRagexe) { while(1){ usleep($config{'sleepTime'}); &koremainloop; if ($quit >0) { &quitkore; } } close($server_socket); close($input_socket); kill 9, $input_pid; killConnection(\$remote_socket); PrintMessage("Bye!\n", "def"); exit; } else { $conState = 1; $timeout{'injectSync'}{'time'} = time; while ($quit != 1) { &koremainloopX; } close($server_socket); close($input_socket); close($remote_socket); kill 9, $input_pid; PrintMessage("Bye!\n", "def"); exit; } sub koremainloop { if (dataWaiting(\$input_socket)) { $stop = 1; $input_socket->recv($input, $MAX_READ); parseInput($input); } elsif (dataWaiting(\$remote_socket)) { $remote_socket->recv($new, $MAX_READ); $msg .= $new; $msg_length = length($msg); while ($msg ne "") { $msg = parseMsg($msg); last if ($msg_length == length($msg)); $msg_length = length($msg); } } AI() if ($conState == 5 && timeOut(\%{$timeout{'ai'}}) && $remote_socket && $remote_socket->connected()); checkConnection(); } sub koremainloopX { usleep($config{'sleepTime'}); if ( dataWaiting(\$input_socket) ) { $input_socket->recv($input, $MAX_READ); parseInput($input); } if ( dataWaiting(\$remote_socket) ) { $remote_socket->recv( $new, $MAX_READ ); if ( $WithRagexe && $rag_socket->connected() ) { $rag_socket->send( $new ); } $msg .= $new; $msg_length = length($msg); while ($msg ne "") { $msg = parseMsg( $msg ); last if ( $msg_length == length( $msg ) ); $msg_length = length( $msg ); } } if ( $WithRagexe ) { if ( dataWaiting(\$inject_socket) ) { $inject_socket->recv( $injectMsg, $MAX_READ ); if ( !$injectMsg ) { killConnection( \$inject_socket ); $conState = 1; $timeout{'injectKeepAlive'}{'time'} = 0; } else { $timeout{'injectKeepAlive'}{'time'} = time; } } if ( dataWaiting(\$rag_socket) && $inject_socket->connected() ) { $rag_socket->recv( $new, $MAX_READ ); if ( !$new ) { killConnection( \$remote_socket ); killConnection( \$rag_socket ); undef $sMsg; } else { $sMsg .= $new; while ( $sMsg ne "" ) { last if ( length($sMsg) < 3 ); $type = substr( $sMsg, 0, 1 ); $len = unpack( "S", substr($sMsg, 1, 2) ); last if ( length( $sMsg ) < $len + 3 ); $newMsg = substr( $sMsg, 3, $len ); $sMsg = substr( $sMsg, $len + 3 ); if ( $type eq "S" ) { parseSendMsg($newMsg); } elsif ( $type eq "C" ) { $host = inet_ntoa(substr($newMsg, 0, 4)); $port = unpack("S", substr($newMsg, 4, 2)); PrintMessage(" $host : $port\n", "def"); if ( !connection( \$remote_socket, $host ,$port ) ) { killConnection( \$rag_socket ); undef $sMsg; } } } } } } AI() if ($AI && $conState == 5 && timeOut(\%{$timeout{'ai'}}) && $remote_socket && $remote_socket -> connected()); checkConnection(); } sub koretimes{ &koremainloop if (!$config{'Xkore_mode'}); &koremainloopX if ($config{'Xkore_mode'}); if ($quit >0) { $my->destroy(); &quitkore; } $my->after($config{'window_sleepTime'}, \&koretimes); } sub pointchk{ $mvcpx=$_[1]; $mvcpy = $mvw_y - $_[2]; $my->title("$mvw - $mvw_px $mvw_py \[$mvcpx $mvcpy\]"); $my ->update; } sub dblchk{ $mvcpx=$_[1]; $mvcpy = $mvw_y - $_[2]; $input="move $mvcpx $mvcpy"; PrintMessage("Move $mvcpx\,$mvcpy\n", "def"); parseInput($input); $my->title("$mvw - $mvw_px $mvw_py \[$mvcpx $mvcpy\]"); $my ->update; } sub xbmmake{ my $i,$j,$k,$hx,$hy; my $line=0; my $dump=''; my @data=[]; $mvw_x=$field{'width'};$mvw_y=$field{'height'}; if (($mvw_x % 8)==0){ $hx=$mvw_x; }else{ $hx=$mvw_x+(8-($mvw_x % 8)); } for($j=0;$j<$mvw_y;$j++){ $hy=($mvw_x*($mvw_y-$j-1)); for($k=0;$k<$hx;$k++){ if($field{'field'}[$hy+$k] >0){$dump+=256;} $dump=$dump/2; if(($k % 8) ==7){ $line.=sprintf("0x%02x\,",$dump); $dump=0; } } } $line="#define data_width $mvw_x\n#define data_height $mvw_y\nstatic unsigned char data_bits[] = {\n".$line."};"; return \$line; } sub quitkore{ close($server_socket); close($input_socket); close($remote_socket); kill 9, $input_pid; PrintMessage("Bye!\n", "def"); exit; } #INITIALIZE VARIABLES sub initConnectVars { initMapChangeVars(); undef @{$chars[$config{'char'}]{'inventory'}}; undef %{$chars[$config{'char'}]{'skills'}}; undef @skillsID; } sub initMapChangeVars { @portalsID_old = @portalsID; %portals_old = %portals; %{$chars_old[$config{'char'}]{'pos_to'}} = %{$chars[$config{'char'}]{'pos_to'}}; undef $chars[$config{'char'}]{'sitting'}; undef $chars[$config{'char'}]{'dead'}; $timeout{'play'}{'time'} = time; $timeout{'ai_sync'}{'time'} = time; $timeout{'ai_sit_idle'}{'time'} = time; $timeout{'ai_teleport_idle'}{'time'} = time; $timeout{'ai_teleport_search'}{'time'} = time; $timeout{'ai_teleport_safe_force'}{'time'} = time; undef %incomingDeal; undef %outgoingDeal; undef %currentDeal; undef $currentChatRoom; undef @currentChatRoomUsers; undef @playersID; undef @monstersID; undef @portalsID; undef @itemsID; undef @npcsID; undef @identifyID; undef @spellsID; undef @petsID; undef %players; undef %monsters; undef %portals; undef %items; undef %npcs; undef %spells; undef %incomingParty; undef $msg; undef %talk; undef $ai_v{'temp'}; undef @{$cart{'inventory'}}; undef %storage; undef %vender; undef @venderListsID; undef $venderLists; } #Check Connection sub checkConnection { return if ($quit); return checkConnectionX() if ( $WithRagexe || $conState <= 1); if ($conState == 1 && !($remote_socket && $remote_socket->connected()) && timeOut(\%{$timeout_ex{'master'}}) && !$conState_tries) { #メンテナスであればログインしない while(1){ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time()); if ($hour > 9 && $hour < 15 && $wday == 2 && $config{'MaintenanceNotLogin'}) { PrintMessage("Now Maintenance Time...Please wait 60 sec\n", "def"); sleep(60); next; } else { last; } } #回数指定wait ++$countConnect; PrintMessage("$countConnect回目の接続...\n", "def"); if ($countConnect > $config{'connect_maxNum'}) { PrintMessage("$config{'connect_maxNum'}回以上接続し直したので$config{'connect_restTime'}秒休みます\n", "def"); sleep($config{'connect_restTime'}); undef $countConnect; } PrintMessage("Connecting to Master Server...\n", "def"); $conState_tries++; undef $msg; connection(\$remote_socket, $config{"master_host_$config{'master'}"},$config{"master_port_$config{'master'}"}); if ($remote_socket && $remote_socket->connected()) { if ($config{'login'} == 1) { PrintMessage("Secure Login...\n", "def"); undef $msg1DC; undef $log1; $timeout{'master'}{'time'} = time; sendMasterCodeRequest(\$remote_socket); } else { sendMasterLogin(\$remote_socket, $config{'username'}, $config{'password'}); } } } elsif ($conState == 1 && $config{'login'} == 1 && $msg1DC ne "" && $log1 == 0 && $conState_tries) { $log1 = 1; PrintMessage("Encode password...\n", "def"); $msg1DD = "\0" x (47); $Encode->Call($config{'version'}, $config{'servertype'}, $config{'servicetype'}, $config{'username'}.pack("C", 0), $config{'password'}.pack("C", 0), $msg1DC, $msg1DD); sendMasterSecureLogin(\$remote_socket, $msg1DD); $timeout{'master'}{'time'} = time; } elsif ($conState == 1 && timeOut(\%{$timeout{'master'}}) && timeOut(\%{$timeout_ex{'master'}})) { PrintMessage("Timeout on Master Server, reconnecting...\n", "def"); killConnection(\$remote_socket); # 再接続ウェイト sleepVisually($config{'wait_ReConnect'}); undef $conState_tries; } elsif ($conState == 2 && !($remote_socket && $remote_socket->connected()) && $config{'server'} ne "" && !$conState_tries) { PrintMessage("Connecting to Game Login Server...\n", "def"); $conState_tries++; connection(\$remote_socket, $servers[$config{'server'}]{'ip'},$servers[$config{'server'}]{'port'}); sendGameLogin(\$remote_socket, $accountID, $sessionID, $accountSex); $timeout{'gamelogin'}{'time'} = time; } elsif ($conState == 2 && timeOut(\%{$timeout{'gamelogin'}}) && $config{'server'} ne "") { PrintMessage("Timeout on Game Login Server, reconnecting...\n", "def"); killConnection(\$remote_socket); killConnection(\$inject_socket); killConnection( \$rag_socket ); # 再接続ウェイト sleepVisually($config{'wait_ReConnect'}); undef $conState_tries; $conState = 1; } elsif ($conState == 3 && !($remote_socket && $remote_socket->connected()) && $config{'char'} ne "" && !$conState_tries) { PrintMessage("Connecting to Game Login Server...\n", "def"); $conState_tries++; connection(\$remote_socket, $servers[$config{'server'}]{'ip'},$servers[$config{'server'}]{'port'}); sendCharLogin(\$remote_socket, $config{'char'}); $timeout{'charlogin'}{'time'} = time; } elsif ($conState == 3 && timeOut(\%{$timeout{'charlogin'}}) && $config{'char'} ne "") { PrintMessage("Timeout on Game Login Server, reconnecting...\n", "def"); killConnection(\$remote_socket); killConnection(\$inject_socket); killConnection( \$rag_socket ); # 再接続ウェイト sleepVisually($config{'wait_ReConnect'}); $conState = 1; undef $conState_tries; } elsif ($conState == 4 && !($remote_socket && $remote_socket->connected()) && !$conState_tries) { PrintMessage("Connecting to Map Server...\n", "def"); $conState_tries++; initConnectVars(); connection(\$remote_socket, $map_ip, $map_port); sendMapLogin(\$remote_socket, $accountID, $charID, $sessionID, $accountSex2); $timeout{'maplogin'}{'time'} = time; } elsif ($conState == 4 && timeOut(\%{$timeout{'maplogin'}})) { PrintMessage("Timeout on Map Server, connecting to Master Server...\n", "def"); killConnection(\$remote_socket); killConnection(\$inject_socket); killConnection( \$rag_socket ); # 再接続ウェイト sleepVisually($config{'wait_ReConnect'}); $conState = 1; undef $conState_tries; $WithRagexe = 1 if ( $config{'Xkore_mode'} ); } elsif ($conState == 5 && !($remote_socket && $remote_socket->connected())) { relog(); } # TimeOut by jkore if ($conState == 5 && time - $ParseMsgTimeOut > 300) { print "Timeout on Map Server(play), connecting to Master Server...\n"; undef_ai_seq(); relog(); } if ($config{'autoRestart'} && time - $KoreStartTime > $config{'autoRestart'}) { undef %ai_v; &undef_ai_seq(); $KoreStartTime = time; PrintMessage("\nAuto-restarting!!\n\n", "def"); relog(); } } sub checkConnectionX { my $inject_connected; $inject_connected = $inject_socket->connected() if $inject_socket; if ($WithRagexe) { undef $inject_connected if !GetProcByName_lc($config{'exeName'}); } if (!$inject_connected || timeOut(\%{$timeout{'injectKeepAlive'}}) ) { $conState = 1; killConnection( \$rag_socket ); killConnection( \$inject_socket ); killConnection( \$remote_socket ); $maintenanceTime = getMaintenanceRemain() + getSleepHour(); if ($maintenanceTime > 0) { PrintMessage("now sleep time, waiting...\n", "def"); PrintMessage(sprintf("retry after %.2fhours later\n",$maintenanceTime/3600), "def"); sleepVisually( $maintenanceTime ); } undef $printed; do { $procID = GetProcByName_lc($config{'exeName'}); $procID2 = GetProcByName_lc($config{'roName'}); if ($procID || $procID2) { PrintMessage("正規クライアントが起動されているためログイン試行できません。\n終了するまで待機します", "pink") if (!$printed); if ($printed && $times + 3 < time) { print "."; $times = time; } $printed = 1; } sleep(1); } while ($procID || $procID2); PrintMessage("終了確認。\n", "def") if ($printed); PrintMessage("Execute $config{'roName'}...\n", "def"); $X_WakeUp->Call( "control/config.txt" ); # ← 引数はconfig.txtへのパス PrintMessage("Waiting for InjectDLL to connect...\n", "def"); $inject_socket = $injectServer_socket->accept(); (inet_aton($inject_socket->peerhost()) == inet_aton('localhost')) || die "Inject Socket must be connected from localhost"; PrintMessage("InjectDLL Socket connected\n", "def"); $timeout{'injectKeepAlive'}{'time'} = time; $inject_connected = $inject_socket->connected(); } if ($inject_connected && !($rag_socket && $rag_socket->connected()) ) { sleep(2); # exe落ちるまでのラグ対策 if (!GetProcByName_lc($config{'exeName'})) { undef $inject_connected; } else { $maintenanceTime = getMaintenanceRemain() + getSleepHour(); if ($maintenanceTime > 0) { killConnection( \$inject_socket ); # ←← 【重要】ここだけこの1行を入れて!! PrintMessage("* now maintenance time, waiting...\n", "def"); printf("retry after %.2fhours later\n",$maintenanceTime/3600); sleepVisually( $maintenanceTime ); } PrintMessage("Waiting for Ragexe to connect...\n", "def"); $rag_socket = $injectServer_socket->accept(); (inet_aton($rag_socket->peerhost()) == inet_aton('localhost')) || die "Ragnarok Socket must be connected from localhost"; PrintMessage("Ragexe Socket connected\n", "def"); $timeout{'injectKeepAlive'}{'time'} = time; } } } sub getMaintenanceRemain { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time()); my $now = sprintf("%02d%02d", $hour, $min); my $arg1 =sprintf("%02d%02d", $config{'MaintenanceNotLogin_starthour'}, $config{'MaintenanceNotLogin_startmin'}); my $arg2 =sprintf("%02d%02d", $config{'MaintenanceNotLogin_endhour'}, $config{'MaintenanceNotLogin_endmin'}); my $temp; if ($wday == 2 && $now > $arg1 && $now < $arg2){ $temp = (($config{'MaintenanceNotLogin_endhour'}*60 + $config{'MaintenanceNotLogin_endmin'}) - ($hour*60 + $min)) * 60; } else { $temp = 0; } return $temp; } sub getSleepHour { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time()); my $now = sprintf("%02d%02d", $hour, $min); my $arg1 =sprintf("%02d%02d", $config{'SleepHour_starthour'}, $config{'SleepHour_startmin'}); my $arg2 =sprintf("%02d%02d", $config{'SleepHour_endhour'}, $config{'SleepHour_endmin'}); if ($wday != 2 && $now > $arg1 && $now < $arg2){ $temp = (($config{'SleepHour_endhour'}*60 + $config{'SleepHour_endmin'}) - ($hour*60 + $min)) * 60; } else { $temp = 0; } return $temp; } #PARSE INPUT sub parseInput { my $xrel = 0; my $input = shift; my ($arg1, $arg2, $switch, $prefix); my @params; my $printType = shift; if ($WithRagexe || $printType == 2) { open BUFFER, "> buffer"; select(BUFFER); } print "Echo: $input\n" if ($config{'debug'} >= 2); ($switch) = $input =~ /^(\w*)/; ($prefix) = $input =~ /^(\W{1})/; ($command) = $input =~ /^\W{1}([\s\S]*)/; ($params[1]) = $input =~ /^[\s\S]*? (\w+)/; ($params[2]) = $input =~ /^[\s\S]*? \w+ (\d+)/; ($params[3]) = $input =~ /^[\s\S]*? \w+ \d+ (\d+)/; #Check if in special state if ($conState == 2 && $waitingForInput && !$WithRagexe) { $config{'server'} = $input; $waitingForInput = 0; writeDataFileIntact("control/config.txt", \%config); } elsif ($conState == 3 && $waitingForInput && !$WithRagexe) { $config{'char'} = $input; $waitingForInput = 0; writeDataFileIntact("control/config.txt", \%config); sendCharLogin(\$remote_socket, $config{'char'}); $timeout{'charlogin'}{'time'} = time; #Parse command...ugh } elsif ($switch eq "a") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? [\s\S]*? (\d+)/; if ($arg1 =~ /^\d+$/ && $monstersID[$arg1] eq "") { PrintMessage("コマンドエラー 'a' (Attack Monster)\n" ."Monster $arg1 がありません。\n", "def"); } elsif ($arg1 =~ /^\d+$/) { attack($monstersID[$arg1]); } elsif ($arg1 eq "no") { configModify("attackAuto", 1); } elsif ($arg1 eq "yes") { configModify("attackAuto", 2); } else { PrintMessage("コマンドエラー 'a' (Attack Monster)\n" ."入力方法\: attack \n", "def"); } } elsif ($switch eq "buy") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)$/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'buy' (Buy Store Item)\n" ."入力方法\: buy []\n", "def"); } elsif ($storeList[$arg1] eq "") { PrintMessage("コマンドエラー 'buy' (Buy Store Item)\n" ."Store Item $arg1 がありません。\n", "def"); } else { if ($arg2 <= 0) { $arg2 = 1; } sendBuy(\$remote_socket, $storeList[$arg1]{'nameID'}, $arg2); } } elsif ($switch eq "c") { ($arg1) = $input =~ /^[\s\S]*? ([\s\S]*)/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'c' (Chat)\n" ."入力方法\: c \n", "def"); } else { sendMessage(\$remote_socket, "c", $arg1); } } elsif ($switch eq "conf") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? \w+ ([\s\S]+)$/; @{$ai_v{'temp'}{'conf'}} = keys %config; if ($arg1 eq "") { PrintMessage("コマンドエラー 'conf' (config.txtの書き換え)\n" ,"入力方法\:\n" ," conf <項目> [<値>] - 書き換え\n" ," conf <項目> value - 値の参照\n"); } elsif (binFind(\@{$ai_v{'temp'}{'conf'}}, $arg1) eq "") { PrintMessage("設定値 '$arg1' がありません。\n", "def"); } elsif ($arg2 eq "value") { PrintMessage("設定値 '$arg1'の値:$config{$arg1}\n", "def"); } else { configModify($arg1, $arg2); } } elsif ($switch eq "drop") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)$/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'drop' (アイテム捨放)\n" ."入力方法\: drop []\n", "def"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'drop' (アイテム捨放)\n" ."アイテム $arg1 がありません。\n", "def"); } else { if (!$arg2 || $arg2 > $chars[$config{'char'}]{'inventory'}[$arg1]{'amount'}) { $arg2 = $chars[$config{'char'}]{'inventory'}[$arg1]{'amount'}; } sendDrop(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $arg2); } } elsif ($switch eq "dump") { dumpData($msg); quit(); } elsif ($switch eq "e") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; if ($arg1 eq "" || $arg1 > 45 || $arg1 < 0) { PrintMessage("コマンドエラー 'e' (エモーション)\n" ,"入力方法\: e \n\n" ,"また、/ハート など、クライアント同様にも記述できます。'emotion'コマンドで一覧表\示。"); } else { sendEmotion(\$remote_socket, $arg1); } } elsif ($switch eq "emotion") { my $command; PrintMessage("- エモーション一覧 ---------------------\n", "def"); foreach $command (sort keys %emotionsCom) { PrintFormat(< 45 || $arg1 < 0) { PrintMessage("コマンドエラー /??? (エモーション)\n" ,"'emotion'コマンドで一覧表\示。"); } else { sendEmotion(\$remote_socket, $arg1); } } elsif ($switch eq "eq") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\w+)/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'equip' (アイテム装備)\n" ."入力方法\: equip [r]\n"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'equip' (アイテム装備)\n" ."アイテム $arg1 がありません。\n", "def"); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'} == 0) { PrintMessage("コマンドエラー 'equip' (アイテム装備)\n" ."アイテム $arg1 は装備できません。\n", "def"); } else { if ($chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'} == 256 || $chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'} == 513) { sendEquip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, 0, 1); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'} == 512) { sendEquip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, 0, 2); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'} == 1) { sendEquip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, 1, 0); } else { if ($arg2 eq "r") { sendEquip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, 32, 0); } else { sendEquip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $chars[$config{'char'}]{'inventory'}[$arg1]{'type_equip'}, 0); } } } #RAG287より(By あるプログラマー氏) } elsif ($switch eq "i") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? \w+ (\d+)/; if ($arg1 eq "" || $arg1 eq "eq" || $arg1 eq "u" || $arg1 eq "nu" || $arg1 eq "st") { my @useable; my @equipNow; my @equipment; my @non_useable; for ($i = 0; $i < @{$chars[$config{'char'}]{'inventory'}};$i++) { next if (!%{$chars[$config{'char'}]{'inventory'}[$i]}); if ($chars[$config{'char'}]{'inventory'}[$i]{'type_equip'} != 0) { if ($chars[$config{'char'}]{'inventory'}[$i]{'equipped'}) { push @equipNow, $i; }else{ push @equipment, $i; } } elsif ($chars[$config{'char'}]{'inventory'}[$i]{'type'} <= 2) { push @useable, $i; } else { push @non_useable, $i; } } PrintMessage("☆----------------------- 所 持 品 -----------------------☆\n", "ItemList_title"); if ($arg1 eq "" || $arg1 eq "eq") { PrintMessage("◆------- 装 備 品 (コマンド'i eq') -------◆\n", "ItemList_title"); for ($i = 0; $i < @equipNow; $i++) { PrintMessage(sprintf("%-4dE【%-10s】%s\n", $equipNow[$i], $equipTypes_lut{$chars[$config{'char'}]{'inventory'}[$equipNow[$i]]{'type_equip'}}, $chars[$config{'char'}]{'inventory'}[$equipNow[$i]]{'name'}), "ItemList_equip"); } for ($i = 0; $i < @equipment; $i++) { my $display; if ($chars[$config{'char'}]{'inventory'}[$equipment[$i]]{'identified'}) { $display = "     "; }else{ $display = "(未鑑定)"; } PrintMessage(sprintf("%-4d 【%-10s】%s\n", $equipment[$i], $display, $chars[$config{'char'}]{'inventory'}[$equipment[$i]]{'name'}), "ItemList_equip"); } PrintMessage("\n", "def"); } if ($arg1 eq "" || $arg1 eq "nu") { PrintMessage("◆------- 収 集 品 (コマンド'i nu') -------◆\n", "ItemList_title"); my $Equip_arrowidx = findIndex(\@{$chars[$config{'char'}]{'inventory'}}, "index", $Equip_arrowid); for ($i = 0; $i < @non_useable; $i++) { if ($non_useable[$i] == $Equip_arrowidx) { PrintMessage(sprintf("%-4d %3d x %s -- Eqp: Arrow\n", $non_useable[$i], $chars[$config{'char'}]{'inventory'}[$non_useable[$i]]{'amount'}, $chars[$config{'char'}]{'inventory'}[$non_useable[$i]]{'name'}), "ItemList_nonuse"); }else{ PrintMessage(sprintf("%-4d %3d x %s\n", $non_useable[$i], $chars[$config{'char'}]{'inventory'}[$non_useable[$i]]{'amount'}, $chars[$config{'char'}]{'inventory'}[$non_useable[$i]]{'name'}), "ItemList_nonuse"); } } PrintMessage("\n", "def"); } if ($arg1 eq "" || $arg1 eq "u") { PrintMessage("◆------- 消 耗 品 (コマンド'i u') -------◆\n", "ItemList_title"); for ($i = 0; $i < @useable; $i++) { PrintMessage(sprintf("%-4d %3d x %s\n", $useable[$i], $chars[$config{'char'}]{'inventory'}[$useable[$i]]{'amount'}, $chars[$config{'char'}]{'inventory'}[$useable[$i]]{'name'}), "ItemList_useable"); } PrintMessage("\n", "def"); } if ($arg1 eq "st") { PrintMessage("◆------- 倉 庫 (コマンド'i st') -------◆\n", "ItemList_title"); if(!-e "log/storage.txt"){ PrintMessage("NotFound Storage.txt\n", "ItemList_storage"); }else{ PrintMessage("-- Storage --\n", "ItemList_storage"); open(F,"log/storage.txt"); while(){ print; } close(F); } } PrintMessage("--------------------------------------------------------------\n", "ItemList_title"); PrintMessage("倉庫内のアイテムを見るには'i st'コマンドを入力します。\n") if ($arg1 ne "st"); } else { PrintMessage("コマンドエラー 'i' (Iventory List)\n" ."入力方法\: i [] []\n"); } } elsif ($switch eq "ignore") { ($arg1, $arg2) = $input =~ /^[\s\S]*? (\d+) ([\s\S]*)/; if ($arg1 eq "" || $arg2 eq "" || ($arg1 ne "0" && $arg1 ne "1")) { PrintMessage("コマンドエラー 'ignore' (耳打ち拒否 プレイヤ/すべて)\n" ."入力方法\: ignore \n"); } else { if ($arg2 eq "all") { sendIgnoreAll(\$remote_socket, !$arg1); } else { sendIgnore(\$remote_socket, $arg2, !$arg1); } } } elsif ($switch eq "il") { PrintMessage("-----------Item List-----------\n" ."# Name \n", "def"); for ($i = 0; $i < @itemsID; $i++) { next if ($itemsID[$i] eq ""); $display = $items{$itemsID[$i]}{'name'}; $display .= " x $items{$itemsID[$i]}{'amount'}"; PrintFormat(< \n", "def"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'im' (Use Item on Monster)\n" ."アイテム $arg1 がありません。\n", "def"); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type'} > 2) { PrintMessage("コマンドエラー 'im' (Use Item on Monster)\n" ."アイテム $arg1 is not of type Usable.\n", "def"); } elsif ($monstersID[$arg2] eq "") { PrintMessage("コマンドエラー 'im' (Use Item on Monster)\n" ."Monster $arg2 がありません。\n", "def"); } else { sendItemUse(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $monstersID[$arg2]); } } elsif ($switch eq "ip") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)/; if ($arg1 eq "" || $arg2 eq "") { PrintMessage("コマンドエラー 'ip' (プレイヤへアイテム使用)\n" ."入力方法\: ip <アイテム番号> <プレイヤ番号>\n"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'ip' (プレイヤへアイテム使用)\n" ."アイテム $arg1 がありません。\n", "def"); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type'} > 2) { PrintMessage("コマンドエラー 'ip' (プレイヤへアイテム使用)\n" ."アイテム $arg1 is not of type Usable.\n", "def"); } elsif ($playersID[$arg2] eq "") { PrintMessage("コマンドエラー 'ip' (プレイヤへアイテム使用)\n" ."Player $arg2 がありません。\n", "def"); } else { sendItemUse(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $playersID[$arg2]); } } elsif ($switch eq "is") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'is' (自分にアイテム使用)\n" ."入力方法\: is <アイテム番号>\n"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'is' (自分にアイテム使用)\n" ."アイテム $arg1 がありません。\n", "def"); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'type'} > 2) { PrintMessage("コマンドエラー 'is' (自分にアイテム使用)\n" ."アイテム $arg1 は消耗品ではありません。\n", "def"); } else { sendItemUse(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $accountID); } } elsif ($switch eq "memo") { sendMemo(\$remote_socket); } elsif ($switch eq "ml") { my $dMDist; PrintMessage("-----------Monster List-----------\n" ."# Pos Dist Name DmgTo DmgFrom\n", "def"); for ($i = 0; $i < @monstersID; $i++) { next if ($monstersID[$i] eq ""); $dMDist = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$monsters{$monstersID[$i]}{'pos_to'}}); $dmgTo = ($monsters{$monstersID[$i]}{'dmgTo'} ne "") ? $monsters{$monstersID[$i]}{'dmgTo'} : 0; $dmgFrom = ($monsters{$monstersID[$i]}{'dmgFrom'} ne "") ? $monsters{$monstersID[$i]}{'dmgFrom'} : 0; PrintFormat(<<'MLIST', $i,$monsters{$monstersID[$i]}{'pos_to'}{'x'},$monsters{$monstersID[$i]}{'pos_to'}{'y'},$dMDist,$monsters{$monstersID[$i]}{'name'},$dmgTo,$dmgFrom); @<<< @<<< @<<< @<<<<< @<<<<<<<<<<<<<<<<<<<<<<< @<<<< @<<<< MLIST } PrintMessage("----------------------------------\n", "def"); } elsif ($switch eq "move") { ($arg1, $arg2, $arg3) = $input =~ /^[\s\S]*? (\d+) (\d+)(.*?)$/; undef $ai_v{'temp'}{'map'}; if ($arg1 eq "") { ($ai_v{'temp'}{'map'}) = $input =~ /^[\s\S]*? (.*?)$/; } else { $ai_v{'temp'}{'map'} = $arg3; } $ai_v{'temp'}{'map'} =~ s/\s//g; if (($arg1 eq "" || $arg2 eq "") && !$ai_v{'temp'}{'map'}) { PrintMessage("コマンドエラー 'move' (Move Player)\n" ."入力方法\: move &| \n"); } elsif ($ai_v{'temp'}{'map'} eq "stop") { aiRemove("move"); aiRemove("route"); aiRemove("route_getRoute"); aiRemove("route_getMapRoute"); PrintMessage("Stopped all movement\n", "def"); } else { $ai_v{'temp'}{'map'} = $field{'name'} if ($ai_v{'temp'}{'map'} eq ""); if ($maps_lut{$ai_v{'temp'}{'map'}.'.rsw'}) { if ($arg2 ne "") { PrintMessage("移動ルート計算: $maps_lut{$ai_v{'temp'}{'map'}.'.rsw'}($ai_v{'temp'}{'map'}): $arg1, $arg2\n", "route"); $ai_v{'temp'}{'x'} = $arg1; $ai_v{'temp'}{'y'} = $arg2; } else { PrintMessage("移動ルート計算中: $maps_lut{$ai_v{'temp'}{'map'}.'.rsw'}($ai_v{'temp'}{'map'})\n", "route"); undef $ai_v{'temp'}{'x'}; undef $ai_v{'temp'}{'y'}; } ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $ai_v{'temp'}{'x'}, $ai_v{'temp'}{'y'}, $ai_v{'temp'}{'map'}, 0, 0, 1, 0, 0, 1); } else { PrintMessage("Map $ai_v{'temp'}{'map'} がありません。\n", "pink"); } } } elsif ($switch eq "nl") { PrintMessage("-----------NPC List-----------\n" ."# Name Coordinates\n", "def"); for ($i = 0; $i < @npcsID; $i++) { next if ($npcsID[$i] eq ""); $ai_v{'temp'}{'pos_string'} = "($npcs{$npcsID[$i]}{'pos'}{'x'}, $npcs{$npcsID[$i]}{'pos'}{'y'})"; PrintFormat(<<'NLIST', $i,$npcs{$npcsID[$i]}{'name'},$ai_v{'temp'}{'pos_string'}); @<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< NLIST } PrintMessage("---------------------------------\n", "def"); } elsif ($switch eq "pl") { my $dPDist; PrintMessage("-----------Player List-----------\n" ."# Pos Dist Name Sex Job\n", "def"); for ($i = 0; $i < @playersID; $i++) { next if ($playersID[$i] eq ""); $dPDist = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$players{$playersID[$i]}{'pos_to'}}); if (%{$players{$playersID[$i]}{'guild'}}) { $name = "$players{$playersID[$i]}{'name'} [$players{$playersID[$i]}{'guild'}{'name'}]"; } else { $name = $players{$playersID[$i]}{'name'}; } PrintFormat(<<'PLIST', $i, $players{$playersID[$i]}{'pos_to'}{'x'}, $players{$playersID[$i]}{'pos_to'}{'y'}, $dPDist, $name, $sex_lut{$players{$playersID[$i]}{'sex'}}, $jobs_lut{$players{$playersID[$i]}{'jobID'}}); @<<< @<<< @<<< @<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<< @<<<<<<<<<< PLIST } PrintMessage("---------------------------------\n", "def"); } elsif ($switch eq "portals") { PrintMessage("-----------Portal List-----------\n" ."# Name Coordinates\n", "def"); for ($i = 0; $i < @portalsID; $i++) { next if ($portalsID[$i] eq ""); $coords = "($portals{$portalsID[$i]}{'pos'}{'x'},$portals{$portalsID[$i]}{'pos'}{'y'})"; PrintFormat(<<'PORTALLIST', $i, $portals{$portalsID[$i]}{'name'}, $coords); @<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<< PORTALLIST } PrintMessage("---------------------------------\n", "def"); } elsif ($switch eq "quit") { quit(); } elsif ($switch eq "reload") { ($arg1) = $input =~ /^[\s\S]*? ([\s\S]*)/; parseReload($arg1); PrintMessage("ファイルをリロードしました。\n", "red"); } elsif ($switch eq "relog") { relog(); } elsif ($switch eq "respawn") { sendTeleport(\$remote_socket, $config{'saveMap'}.".gat"); } elsif ($switch eq "s") { if ($chars[$config{'char'}]{'exp_last'} > $chars[$config{'char'}]{'exp'}) { $baseEXPKill = $chars[$config{'char'}]{'exp_max_last'} - $chars[$config{'char'}]{'exp_last'} + $chars[$config{'char'}]{'exp'}; } elsif ($chars[$config{'char'}]{'exp_last'} == 0 && $chars[$config{'char'}]{'exp_max_last'} == 0) { $baseEXPKill = 0; } else { $baseEXPKill = $chars[$config{'char'}]{'exp'} - $chars[$config{'char'}]{'exp_last'}; } if ($chars[$config{'char'}]{'exp_job_last'} > $chars[$config{'char'}]{'exp_job'}) { $jobEXPKill = $chars[$config{'char'}]{'exp_job_max_last'} - $chars[$config{'char'}]{'exp_job_last'} + $chars[$config{'char'}]{'exp_job'}; } elsif ($chars[$config{'char'}]{'exp_job_last'} == 0 && $chars[$config{'char'}]{'exp_job_max_last'} == 0) { $jobEXPKill = 0; } else { $jobEXPKill = $chars[$config{'char'}]{'exp_job'} - $chars[$config{'char'}]{'exp_job_last'}; } $lastBase = $hp_string = $chars[$config{'char'}]{'hp'}."/".$chars[$config{'char'}]{'hp_max'}." (" .int($chars[$config{'char'}]{'hp'}/$chars[$config{'char'}]{'hp_max'} * 100) ."%)" if $chars[$config{'char'}]{'hp_max'}; $sp_string = $chars[$config{'char'}]{'sp'}."/".$chars[$config{'char'}]{'sp_max'}." (" .int($chars[$config{'char'}]{'sp'}/$chars[$config{'char'}]{'sp_max'} * 100) ."%)" if $chars[$config{'char'}]{'sp_max'}; $base_string = $chars[$config{'char'}]{'exp'}."/".$chars[$config{'char'}]{'exp_max'}." /$baseEXPKill (" .sprintf("%.2f",$chars[$config{'char'}]{'exp'}/$chars[$config{'char'}]{'exp_max'} * 100) ."%)" if $chars[$config{'char'}]{'exp_max'}; $job_string = $chars[$config{'char'}]{'exp_job'}."/".$chars[$config{'char'}]{'exp_job_max'}." /$jobEXPKill (" .sprintf("%.2f",$chars[$config{'char'}]{'exp_job'}/$chars[$config{'char'}]{'exp_job_max'} * 100) ."%)" if $chars[$config{'char'}]{'exp_job_max'}; $weight_string = $chars[$config{'char'}]{'weight'}."/".$chars[$config{'char'}]{'weight_max'}." (" .int($chars[$config{'char'}]{'weight'}/$chars[$config{'char'}]{'weight_max'} * 100) ."%)" if $chars[$config{'char'}]{'weight_max'}; $job_name_string = "$jobs_lut{$chars[$config{'char'}]{'jobID'}} $sex_lut{$chars[$config{'char'}]{'sex'}}"; PrintMessage("-----------Status-----------\n", "def");; PrintFormat(<<'STATUS', $chars[$config{'char'}]{'name'}, $hp_string, $job_name_string, $sp_string, $chars[$config{'char'}]{'lv'}, $base_string, $chars[$config{'char'}]{'lv_job'}, $job_string, $weight_string, $chars[$config{'char'}]{'zenny'}); @<<<<<<<<<<<<<<<<<<<<<<<< HP: @<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< SP: @<<<<<<<<<<<<<<<<<< Base: @<< @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Job: @<< @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Weight: @>>>>>>>>>>>>>>>> Zenny: @<<<<<<<<<<<<<< STATUS PrintMessage("----------------------------\n", "def"); foreach(sort keys %skillsTimeout){ next if(!$_); if(time-$skillsTimeout{$_}{'time'}<$skillsTime_lut{$_}{$skillsTimeout{$_}{'lv'}} ){ $iTemp=$skillsTime_lut{$_}{$skillsTimeout{$_}{'lv'}}-int(time-$skillsTimeout{$_}{'time'}); PrintMessage("$_($iTemp)\n", "def"); } } foreach(keys %itemsTimeout){ if($time < $itemsTimeout{$_}+1800) { $iTemp = ($itemsTimeout{$_}+1800) - $time; PrintMessage("$items_lut{$_}($iTemp)\n", "def"); } } PrintMessage("----------------------------\n", "def"); } elsif ($switch eq "sell") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)$/; if ($arg1 eq "" && $talk{'buyOrSell'}) { sendGetSellList(\$remote_socket, $talk{'ID'}); } elsif ($arg1 eq "") { PrintMessageEx("コマンドエラー 'sell' (Sell アイテム)\n" ."入力方法\: ^00FFFFsell []\n"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'sell' (Sell アイテム)\n" ."持ち物に $arg1 がありません。\n", "def"); } else { if (!$arg2 || $arg2 > $chars[$config{'char'}]{'inventory'}[$arg1]{'amount'}) { $arg2 = $chars[$config{'char'}]{'inventory'}[$arg1]{'amount'}; } sendSell(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}, $arg2); } } elsif ($switch eq "send") { ($args) = $input =~ /^[\s\S]*? ([\s\S]*)/; sendRaw(\$remote_socket, $args); } elsif ($switch eq "sit") { $ai_v{'attackAuto_old'} = $config{'attackAuto'}; $ai_v{'route_randomWalk_old'} = $config{'route_randomWalk'}; $ai_v{'route_pointWalk_old'} = $config{'route_pointWalk'}; configModify("attackAuto", 1); configModify("route_randomWalk", 0); configModify("route_pointWalk", 0); aiRemove("move"); aiRemove("route"); aiRemove("route_getRoute"); aiRemove("route_getMapRoute"); sit(); $ai_v{'sitAuto_forceStop'} = 0; } elsif ($switch eq "sm") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)/; ($arg3) = $input =~ /^[\s\S]*? \d+ \d+ (\d+)/; if ($arg1 eq "" || $arg2 eq "") { PrintMessage("コマンド入力エラー 'sm' (Use Skill on Monster)\n" ."入力方法\: sm []\n"); } elsif ($monstersID[$arg2] eq "") { PrintMessage("コマンドエラー 'sm' (Use Skill on Monster)\n" ."Monster $arg2 がありません。\n", "def"); } elsif ($skillsID[$arg1] eq "") { PrintMessage("コマンドエラー 'sm' (Use Skill on Monster)\n" ."Skill $arg1 がありません。\n", "def"); } else { if (!$arg3 || $arg3 > $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}) { $arg3 = $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}; } if (!ai_getSkillUseType($skillsID[$arg1])) { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg3, 0,0, $monstersID[$arg2]); } else { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg3, 0,0, $monsters{$monstersID[$arg2]}{'pos_to'}{'x'}, $monsters{$monstersID[$arg2]}{'pos_to'}{'y'}); } } } elsif ($switch eq "skills") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? \w+ (\d+)/; if ($arg1 eq "") { PrintMessage("----------Skill List-----------\n", "def"); PrintMessage("# Skill Name Lv SP\n", "def"); for ($i=0; $i < @skillsID; $i++) { PrintFormat(<<'SKILLS', $i, $skills_lut{$skillsID[$i]}, $chars[$config{'char'}]{'skills'}{$skillsID[$i]}{'lv'}, $skillsSP_lut{$skillsID[$i]}{$chars[$config{'char'}]{'skills'}{$skillsID[$i]}{'lv'}}); @< @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<< @<<< SKILLS } PrintMessage("\nSkill Points: $chars[$config{'char'}]{'points_skill'}\n", "def"); PrintMessage("-------------------------------\n", "def"); } elsif ($arg1 eq "add" && $arg2 =~ /\d+/ && $skillsID[$arg2] eq "") { PrintMessage("コマンドエラー 'skills add' (Add Skill Point)\n" ."スキル $arg2 がありません。\n", "def"); } elsif ($arg1 eq "add" && $arg2 =~ /\d+/ && $chars[$config{'char'}]{'points_skill'} < 1) { PrintMessage("コマンドエラー 'skills add' (Add Skill Point)\n" ."スキル $skills_lut{$skillsID[$arg2]}を上げるために十分なポイントがありません。\n", "def"); } elsif ($arg1 eq "add" && $arg2 =~ /\d+/) { sendAddSkillPoint(\$remote_socket, $skillsCD_lut{$skillsID[$arg2]}); } else { PrintMessage("コマンド入力エラー 'skills' (Skills Functions)\n" ."入力方法\: skills [] []\n"); } } elsif ($switch eq "sp") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)/; ($arg3) = $input =~ /^[\s\S]*? \d+ \d+ (\d+)/; if ($arg1 eq "" || $arg2 eq "") { PrintMessage("コマンド入力エラー 'sp' (Use Skill on Player)\n" ."入力方法\: sp []\n"); } elsif ($playersID[$arg2] eq "") { PrintMessage("コマンドエラー 'sp' (Use Skill on Player)\n" ."プレイヤー $arg2 がいません。\n", "def"); } elsif ($skillsID[$arg1] eq "") { PrintMessage("コマンドエラー 'sp' (Use Skill on Player)\n" ."スキル $arg1 がありません。\n", "def"); } else { if (!$arg3 || $arg3 > $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}) { $arg3 = $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}; } if (!ai_getSkillUseType($skillsID[$arg1])) { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg3, 0,0, $playersID[$arg2]); } else { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg3, 0,0, $players{$playersID[$arg2]}{'pos_to'}{'x'}, $players{$playersID[$arg2]}{'pos_to'}{'y'}); } } } elsif ($switch eq "spb") { if ($params[1]) { $config{'seconds_per_block'} = $params[1]; $chars[$config{'char'}]{'seconds_per_block'} = $config{'seconds_per_block'}; } } elsif ($switch eq "ss") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; ($arg2) = $input =~ /^[\s\S]*? \d+ (\d+)/; if ($arg1 eq "") { PrintMessage("コマンド入力エラー 'ss' (Use Skill on Self)\n" ."入力方法\: ss []\n"); } elsif ($skillsID[$arg1] eq "") { PrintMessage("コマンドエラー 'ss' (Use Skill on Self)\n" ."スキル $arg1 がありません。\n", "def"); } else { if (!$arg2 || $arg2 > $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}) { $arg2 = $chars[$config{'char'}]{'skills'}{$skillsID[$arg1]}{'lv'}; } if (!ai_getSkillUseType($skillsID[$arg1])) { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg2, 0,0, $accountID); } else { ai_skillUse($skillsCD_lut{$skillsID[$arg1]}, $arg2, 0,0, $chars[$config{'char'}]{'pos_to'}{'x'}, $chars[$config{'char'}]{'pos_to'}{'y'}+1); } } } elsif ($switch eq "st") { PrintMessage("---------------Char Stats-------------------\n", "def"); $tilde = "~"; PrintFormat(<<'STATS', $chars[$config{'char'}]{'str'}, $chars[$config{'char'}]{'str_bonus'}, $chars[$config{'char'}]{'points_str'}, $chars[$config{'char'}]{'attack'}, $chars[$config{'char'}]{'attack_bonus'}, $chars[$config{'char'}]{'def'}, $chars[$config{'char'}]{'def_bonus'},, $chars[$config{'char'}]{'agi'}, $chars[$config{'char'}]{'agi_bonus'}, $chars[$config{'char'}]{'points_agi'}, $chars[$config{'char'}]{'attack_magic_min'}, $tilde, $chars[$config{'char'}]{'attack_magic_max'}, $chars[$config{'char'}]{'def_magic'}, $chars[$config{'char'}]{'def_magic_bonus'},, $chars[$config{'char'}]{'vit'}, $chars[$config{'char'}]{'vit_bonus'}, $chars[$config{'char'}]{'points_vit'}, $chars[$config{'char'}]{'hit'}, $chars[$config{'char'}]{'flee'}, $chars[$config{'char'}]{'flee_bonus'},, $chars[$config{'char'}]{'int'}, $chars[$config{'char'}]{'int_bonus'}, $chars[$config{'char'}]{'points_int'}, $chars[$config{'char'}]{'critical'}, $chars[$config{'char'}]{'attack_speed'},, $chars[$config{'char'}]{'dex'}, $chars[$config{'char'}]{'dex_bonus'}, $chars[$config{'char'}]{'points_dex'}, $chars[$config{'char'}]{'points_free'},, $chars[$config{'char'}]{'luk'}, $chars[$config{'char'}]{'luk_bonus'}, $chars[$config{'char'}]{'points_luk'}, $chars[$config{'char'}]{'guild'}{'name'}); Str: @<<+@<< #@< Atk: @<<+@<< Def: @<<+@<< Agi: @<<+@<< #@< Matk: @<<@@<< Mdef: @<<+@<< Vit: @<<+@<< #@< Hit: @<< Flee: @<<+@<< Int: @<<+@<< #@< Critical: @<< Aspd: @<< Dex: @<<+@<< #@< Status Points: @<< Luk: @<<+@<< #@< Guild: @<<<<<<<<<<<<<<<<<<<<< STATS PrintMessage("--------------------------------------------\n", "def"); } elsif ($switch eq "stand") { if ($ai_v{'attackAuto_old'} ne "") { configModify("attackAuto", $ai_v{'attackAuto_old'}); configModify("route_randomWalk", $ai_v{'route_randomWalk_old'}); configModify("route_pointWalk", $ai_v{'route_pointWalk_old'}); } stand(); $ai_v{'sitAuto_forceStop'} = 1; } elsif ($switch eq "stat_add") { ($arg1) = $input =~ /^[\s\S]*? ([\s\S]*)$/; if ($arg1 ne "str" && $arg1 ne "agi" && $arg1 ne "vit" && $arg1 ne "int" && $arg1 ne "dex" && $arg1 ne "luk") { PrintMessage("コマンド入力エラー 'stat_add' (Add Status Point)\n" ."入力方法\: stat_add \n"); } else { if ($arg1 eq "str") { $ID = 0x0D; } elsif ($arg1 eq "agi") { $ID = 0x0E; } elsif ($arg1 eq "vit") { $ID = 0x0F; } elsif ($arg1 eq "int") { $ID = 0x10; } elsif ($arg1 eq "dex") { $ID = 0x11; } elsif ($arg1 eq "luk") { $ID = 0x12; } if ($chars[$config{'char'}]{"points_$arg1"} > $chars[$config{'char'}]{'points_free'}) { PrintMessage("コマンドエラー 'stat_add' (Add Status Point)\n" ."$arg1を上げる為に必要なステータスポイントがありません。\n", "def"); } else { $chars[$config{'char'}]{$arg1} += 1; sendAddStatusPoint(\$remote_socket, $ID); } } } elsif ($switch eq "storage") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? \w+ (\d+)/; ($arg3) = $input =~ /^[\s\S]*? \w+ \d+ (\d+)/; if ($arg1 eq "" || $arg1 eq "eq" || $arg1 eq "u" || $arg1 eq "nu") { my @useable; my @equipNow; my @equipment; my @non_useable; for ($i = 0; $i < @{$storage{'inventory'}};$i++) { next if (!%{$storage{'inventory'}[$i]}); if ($storage{'inventory'}[$i]{'type_equip'} != 0) { if ($storage{'inventory'}[$i]{'equipped'}) { push @equipNow, $i; }else{ push @equipment, $i; } } elsif ($storage{'inventory'}[$i]{'type'} <= 2) { push @useable, $i; } else { push @non_useable, $i; } } PrintMessage("☆------------------- 倉庫内アイテム -------------------☆\n", "ItemList_title"); if ($arg1 eq "" || $arg1 eq "u") { PrintMessage("◆------- 消 耗 品 (コマンド'storage u') -------◆\n", "ItemList_title"); for ($i = 0; $i < @useable; $i++) { PrintMessage(sprintf("%-4d %3d x %s\n", $useable[$i], $storage{'inventory'}[$useable[$i]]{'amount'}, $storage{'inventory'}[$useable[$i]]{'name'}), "ItemList_useable"); } PrintMessage("\n", "def"); } if ($arg1 eq "" || $arg1 eq "eq") { PrintMessage("◆------- 装 備 品 (コマンド'storage eq') -------◆\n", "ItemList_title"); for ($i = 0; $i < @equipment; $i++) { my $display; if ($storage{'inventory'}[$equipment[$i]]{'identified'}) { $display = " "; }else{ $display = "*"; } PrintMessage(sprintf("%-4d %s %s\n", $equipment[$i], $display, $storage{'inventory'}[$equipment[$i]]{'name'}), "ItemList_equip"); } PrintMessage("\n", "def"); } if ($arg1 eq "" || $arg1 eq "nu") { PrintMessage("◆------- 収 集 品 (コマンド'storage nu') -------◆\n", "ItemList_title"); my $Equip_arrowidx = findIndex(\@{$storage{'inventory'}}, "index", $Equip_arrowid); for ($i = 0; $i < @non_useable; $i++) { if ($non_useable[$i] == $Equip_arrowidx) { PrintMessage(sprintf("%-4d %3d x %s -- Eqp: Arrow\n", $non_useable[$i], $storage{'inventory'}[$non_useable[$i]]{'amount'}, $storage{'inventory'}[$non_useable[$i]]{'name'}), "ItemList_nonuse"); }else{ PrintMessage(sprintf("%-4d %3d x %s\n", $non_useable[$i], $storage{'inventory'}[$non_useable[$i]]{'amount'}, $storage{'inventory'}[$non_useable[$i]]{'name'}), "ItemList_nonuse"); } } PrintMessage("\n", "def"); } PrintMessage("----------------------------------------------------------\n", "ItemList_title"); PrintMessage("倉庫のアイテムの出し入れは'storage []'コマンドを使用します。\n"); } elsif ($arg1 eq "add" && $arg2 =~ /\d+/ && $chars[$config{'char'}]{'inventory'}[$arg2] eq "") { PrintMessage("コマンドエラー 'storage add' (倉庫に追加)\n" ."アイテム $arg2 がありません。\n", "def"); } elsif ($arg1 eq "add" && $arg2 =~ /\d+/) { if (!$arg3 || $arg3 > $chars[$config{'char'}]{'inventory'}[$arg2]{'amount'}) { $arg3 = $chars[$config{'char'}]{'inventory'}[$arg2]{'amount'}; } sendStorageAdd(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg2]{'index'}, $arg3); } elsif ($arg1 eq "get" && $arg2 =~ /\d+/ && !%{$storage{'inventory'}[$arg2]}) { PrintMessage("コマンドエラー 'storage get' (倉庫から取得)\n" ."倉庫アイテム $arg2 がありません。\n", "def"); } elsif ($arg1 eq "get" && $arg2 =~ /\d+/) { if (!$arg3 || $arg3 > $storage{'inventory'}[$arg2]{'amount'}) { $arg3 = $storage{'inventory'}[$arg2]{'amount'}; } sendStorageGet(\$remote_socket, $arg2, $arg3); } elsif ($arg1 eq "close") { sendStorageClose(\$remote_socket); } else { PrintMessage("コマンド入力エラー 'storage' (倉庫コマンド)\n" ."入力方法\: storage [] [<アイテム番号 | 倉庫アイテム番号>] [<数量>]\n"); } } elsif ($switch eq "store") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? \w+ (\d+)/; if ($arg1 eq "" && !$talk{'buyOrSell'}) { PrintMessage("----------Store List-----------\n", "def"); PrintMessage("# Name Type Price\n", "def"); for ($i=0; $i < @storeList;$i++) { $display = $storeList[$i]{'name'}; PrintFormat(<<'STORELIST', $i, $display, $itemTypes_lut{$storeList[$i]{'type'}}, $storeList[$i]{'price'}); @< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<< @>>>>>>>z STORELIST } PrintMessage("-------------------------------\n", "def"); PrintMessage("商品を購入するには、'buy <アイテム番号> [<数量>]'コマンドを使用します。'\n"); } elsif ($arg1 eq "" && $talk{'buyOrSell'}) { sendGetStoreList(\$remote_socket, $talk{'ID'}); } else { PrintMessage("コマンド入力エラー 'store' (Store Functions)\n"); } } elsif ($switch eq "take") { ($arg1) = $input =~ /^[\s\S]*? (\d+)$/; if ($arg1 eq "") { PrintMessage("コマンド入力エラー 'take' (Take Item)\n" ."入力方法\: take \n"); } elsif ($itemsID[$arg1] eq "") { PrintMessage("コマンドエラー 'take' (Take Item)\n" ."Item $arg1 がありません。\n","def"); } else { take($itemsID[$arg1]); } } elsif ($switch eq "talk") { ($arg1) = $input =~ /^[\s\S]*? (\w+)/; ($arg2) = $input =~ /^[\s\S]*? [\s\S]*? (\d+)/; if ($arg1 =~ /^\d+$/ && $npcsID[$arg1] eq "") { PrintMessage("コマンドエラー 'talk' (NPC会話開始)\n" ."NPC番号 $arg1 がありません。\n", "def"); } elsif ($arg1 =~ /^\d+$/) { sendTalk(\$remote_socket, $npcsID[$arg1]); } elsif ($arg1 eq "resp" && (!%talk || $talk{'status'} eq 'close')) { PrintMessage("コマンドエラー 'talk resp' (NPCへ返答)\n" ."NPCとの会話が開始していません。\n", "def"); } elsif ($arg1 eq "resp" && $arg2 eq "") { $display = $npcs{$talk{'nameID'}}{'name'}; PrintMessage("----------Responses-----------\n", "def"); PrintMessage("NPC: $display\n", "def"); PrintMessage("# Response\n", "def"); for ($i=0; $i < @{$talk{'responses'}}; $i++) { PrintMessage(sprintf("%d %s\n", $i, $talk{'responses'}[$i])); } PrintMessage("-------------------------------\n", "def"); PrintMessage("項目を選択するには'talk resp #'と入力します。\n"); } elsif ($arg1 eq "resp" && $arg2 ne "" && $talk{'responses'}[$arg2] eq "") { PrintMessage("コマンドエラー 'talk resp' (NPCへ返答)\n" ."選択項目 $arg2 がありません。\n", "def"); } elsif ($arg1 eq "resp" && $arg2 ne "") { if ($talk{'responses'}[$arg2] eq "Cancel Chat") { $arg2 = 255; } else { $arg2 += 1; } sendTalkResponse(\$remote_socket, $talk{'ID'}, $arg2); } elsif ($arg1 eq "cont" && (!%talk || $talk{'status'} eq 'close')) { PrintMessage("コマンドエラー 'talk cont' (NPC会話の続行)\n" ."NPCとの会話が開始していません。\n", "def"); } elsif ($arg1 eq "cont") { sendTalkContinue(\$remote_socket, $talk{'ID'}); } elsif ($arg1 eq "no") { sendTalkCancel(\$remote_socket, $talk{'ID'}); } elsif ($arg1 eq "input" && (!%talk || $talk{'status'} eq 'close' || $talk{'status'} ne "input")) { PrintMessage("NPCとの会話が開始していないか、数値入力状態になっていません。\n", "def"); } elsif ($arg1 eq "input" && $arg2 ne "") { sendTalkAmount(\$remote_socket, $talk{'ID'}, $arg2); } else { PrintMessage("コマンド入力エラー 'talk' (NPC会話開始)\n" ."入力方法\: talk [<選択肢番号>]\n"); } } elsif ($switch eq "tele") { sendTeleport(\$remote_socket, "Random"); } elsif ($switch eq "timeout") { ($arg1, $arg2) = $input =~ /^[\s\S]*? ([\s\S]*) ([\s\S]*?)$/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'timeout' (set a timeout)\n" ."入力方法\: timeout []\n", "def"); } elsif ($timeout{$arg1} eq "") { PrintMessage("コマンドエラー 'timeout' (set a timeout)\n" ."Timeout $arg1 doesn't exist\n", "def"); } elsif ($arg2 eq "") { PrintMessage("Timeout '$arg1' is $config{$arg1}\n", "def"); } else { setTimeout($arg1, $arg2); } } elsif ($switch eq "uneq") { ($arg1) = $input =~ /^[\s\S]*? (\d+)/; if ($arg1 eq "") { PrintMessage("コマンドエラー 'unequip' (Unequip アイテム)\n" ."入力方法\: unequip \n", "def"); } elsif (!%{$chars[$config{'char'}]{'inventory'}[$arg1]}) { PrintMessage("コマンドエラー 'unequip' (Unequip アイテム)\n" ."アイテム $arg1 がありません。\n", "def"); } elsif ($chars[$config{'char'}]{'inventory'}[$arg1]{'equipped'} == 0) { PrintMessage("コマンドエラー 'unequip' (Unequip アイテム)\n" ."アイテム $arg1 is not equipped.\n", "def"); } else { sendUnequip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$arg1]{'index'}); } } elsif ($switch eq "where") { ($map_string) = $map_name =~ /([\s\S]*)\.gat/; PrintMessage("Location $maps_lut{$map_string.'.rsw'}($map_string) : $chars[$config{'char'}]{'pos_to'}{'x'}, $chars[$config{'char'}]{'pos_to'}{'y'}\n", "def"); } elsif ($switch eq "who") { sendWho(\$remote_socket); } elsif ($switch eq "xrel") { if ( $WithRagexe == 1 && $conState == 5 ) { $xrel = 1; } # 時給表示 } elsif ($switch eq "exp") { ($arg1) = $input =~ /^.*? (\w+)/; if($arg1 eq ""){ $endTime_EXP = time; $w_hour = 0; $w_min = 0; $w_sec = int($endTime_EXP - $startTime_EXP); $bExpPerHour = int($totalBaseExp * 3600 / $w_sec); $jExpPerHour = int($totalJobExp * 3600 / $w_sec); if ($w_sec >= 3600) { $w_hour = int($w_sec / 3600); $w_sec %= 3600; } if ($w_sec >= 60) { $w_min = int($w_sec / 60); $w_sec %= 60; } PrintMessage("-----------EXP/Hour----------\n", "def"); PrintMessage(sprintf("PlayTime : %dh %dm %ds\n", $w_hour, $w_min, $w_sec),"def"); PrintMessage("TotalBaseExp: $totalBaseExp\n", "def"); PrintMessage("TotalJobExp : $totalJobExp\n", "def"); PrintMessage("BaseExp/Hour: $bExpPerHour\n", "def"); PrintMessage("JobExp/Hour : $jExpPerHour\n", "def"); PrintMessage("-----------------------------\n", "def"); } elsif($arg1 eq "reset") { $bExpSwitch = 0; $jExpSwitch = 0; $totalBaseExp = 0; $totalJobExp = 0; $bExpPerHour = 0; $jExpPerHour = 0; $startTime_EXP = time; } else { PrintMessage("コマンドエラー 'drop' (Drop アイテム)\n", "def"); PrintMessage("入力方法\: exp [reset]\n", "def"); } } elsif ($switch eq "defeat") { my @defeatKey = keys(%defeatMonster); PrintMessage("------ Defeated Monster List ------\n", "def"); foreach (sort{$defeatMonster{$a} <=> $defeatMonster{$b}} @defeatKey) { $defeatMonsterName = $_; $defeatMonsterNum = $defeatMonster{$_}; PrintFormat(<<'DEFEAT', $defeatMonsterName, $defeatMonsterNum); @<<<<<<<<<<<<<<<<<<<<<<<< @>>>> 匹 DEFEAT } PrintMessage("-----------------------------------\n", "def"); } elsif ($switch eq "ai") { if ($AI) { undef $AI; $AI_forcedOff = 1; PrintMessage("AI turned off\n", "def"); } else { $AI = 1; undef $AI_forcedOff; PrintMessage("AI turned on\n", "def"); } } elsif ($switch eq "v") { if ($config{'verbose'}) { configModify("verbose", 0); } else { configModify("verbose", 1); } $params[1] = lc($params[1]); } elsif ($switch eq "worp"){ ($arg1) = $input =~ /^.*? ([0-4]+)/; if ($arg1 ne "" && @worpPortalMaps) { sendWorpPortal(\$remote_socket, $worpPortalMaps[$arg1]) if $arg1 < 4; sendWorpPortal(\$remote_socket, "cancel") if $arg == 4; } undef @worpPortalMaps; } elsif ($switch eq "buyAuto") { unshift @ai_seq, "buyAuto"; unshift @ai_seq_args, {}; } elsif ($switch eq "storageAuto") { unshift @ai_seq, "storageAuto"; unshift @ai_seq_args, {}; } elsif ($switch eq "viewattack") { if ($ai_seq[0] eq "attack") { print "ai_seq_args[0]{'ai_attack_giveup'}{'time'} = ". ($ai_seq_args[0]{'ai_attack_giveup'}{'time'} - time) ."\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'name'}' = $monsters{$ai_seq_args[0]{'ID'}}{'name'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'attack_failed'}' = $monsters{$ai_seq_args[0]{'ID'}}{'attack_failed'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'dmgFromYou'}' = $monsters{$ai_seq_args[0]{'ID'}}{'dmgFromYou'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'dmgFrom'}' = $monsters{$ai_seq_args[0]{'ID'}}{'dmgFrom'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'dmgTo'}' = $monsters{$ai_seq_args[0]{'ID'}}{'dmgTo'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'missedFromPlayer'}' = $monsters{$ai_seq_args[0]{'ID'}}{'missedFromPlayer'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'missedToPlayer'}' = $monsters{$ai_seq_args[0]{'ID'}}{'missedToPlayer'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'castOnByPlayer'}' = $monsters{$ai_seq_args[0]{'ID'}}{'castOnByPlayer'}\n"; print "'monsters{ai_seq_args[0]{'ID'}}{'lastTarget'}' = $players{$monsters{$ai_seq_args[0]{'ID'}}{'lastTarget'}}{'name'}\n" if ($monsters{$ai_seq_args[0]{'ID'}}{'lastTarget'} ne $accountID); print "'monsters{ai_seq_args[0]{'ID'}}{'lastTarget'}' = $chars[$config{'char'}]{'name'}\n" if ($monsters{$ai_seq_args[0]{'ID'}}{'lastTarget'} eq $accountID); print "ai_seq_args[0]{'attackMethod'}{'distance'} = $ai_seq_args[0]{'attackMethod'}{'distance'}\n"; print "ai_seq_args[0]{'attackMethod'}{'type'} = $ai_seq_args[0]{'attackMethod'}{'type'}\n"; print "ai_seq_args[0]{'attackMethod'}{'skillSlot'} = $ai_seq_args[0]{'attackMethod'}{'skillSlot'}\n"; print "ai_seq_args[0]{'attackMethod'}{'acce'} = $ai_seq_args[0]{'attackMethod'}{'acce'}\n"; print "ai_seq_args[0]{'dmgTo_last'} = $ai_seq_args[0]{'dmgTo_last'}\n"; print "ai_seq_args[0]{'aruki'} = $ai_seq_args[0]{'aruki'}\n"; print "ai_seq_args[0]{'naguri'} = $ai_seq_args[0]{'naguri'}\n"; } } elsif ($switch eq "debug") { configModify("debug", !$config{'debug'}); } if ($WithRagexe || $printType == 2) { my $msg; open BUFFER, "buffer"; while () { $msg .= $_; } select(STDOUT); if (!$printType) { print $msg; } elsif ($printType == 1) { $msg =~ s/\n*$//; $msg =~ s/\n/\\n/g; sendMessage(\$remote_socket, "k", $msg); } close BUFFER; } if ( $xrel ) { PrintMessage("正規クライアントを切り離します。\n", "red"); close( $rag_socket ); close( $inject_socket ); $WithRagexe = 0; } } #AI sub AI { my $i, $j; if (!$accountID) { $AI = 0; injectAdminMessage("Kore does not have enough account information, so AI has been disabled. Relog to enable AI.") if ($config{'verbose'}); return; } ##### MISC ##### if (timeOut(\%{$timeout{'ai_wipe_check'}})) { foreach (keys %players_old) { delete $players_old{$_} if (time - $players_old{$_}{'gone_time'} >= $timeout{'ai_wipe_old'}{'timeout'}); } foreach (keys %monsters_old) { delete $monsters_old{$_} if (time - $monsters_old{$_}{'gone_time'} >= $timeout{'ai_wipe_old'}{'timeout'}); } foreach (keys %npcs_old) { delete $npcs_old{$_} if (time - $npcs_old{$_}{'gone_time'} >= $timeout{'ai_wipe_old'}{'timeout'}); } foreach (keys %items_old) { delete $items_old{$_} if (time - $items_old{$_}{'gone_time'} >= $timeout{'ai_wipe_old'}{'timeout'}); } foreach (keys %portals_old) { delete $portals_old{$_} if (time - $portals_old{$_}{'gone_time'} >= $timeout{'ai_wipe_old'}{'timeout'}); } $timeout{'ai_wipe_check'}{'time'} = time; print "Wiped old\n" if ($config{'debug'} >= 2); } if (timeOut(\%{$timeout{'ai_wipe_check'}})) { #fix foreach (keys %players) { $ai_v{'temp'}{'distance'} = distance(\%{$chars[$config{'char'}]{'pos_to'}},\%{$players{$_}{'pos_to'}}); if ($ai_v{'temp'}{'distance'} > 30) { %{$players_old{$_}} = %{$players{$_}}; $players_old{$_}{'disappeared'} = 1; $players_old{$_}{'gone_time'} = time; binRemove(\@playersID, $_); delete $players{$_}; } } } if (timeOut(\%{$timeout{'ai_getInfo'}})) { foreach (keys %players) { if ($players{$_}{'name'} eq "Unknown") { sendGetPlayerInfo(\$remote_socket, $_); last; } } foreach (keys %monsters) { if ($monsters{$_}{'name'} =~ /Unknown/) { sendGetPlayerInfo(\$remote_socket, $_); last; } } foreach (keys %npcs) { if ($npcs{$_}{'name'} =~ /Unknown/) { sendGetPlayerInfo(\$remote_socket, $_); last; } } foreach (keys %pets) { if ($pets{$_}{'name_given'} =~ /Unknown/) { sendGetPlayerInfo(\$remote_socket, $_); last; } } $timeout{'ai_getInfo'}{'time'} = time; } if (timeOut(\%{$timeout{'ai_sync'}}) && !$WithRagexe) { $timeout{'ai_sync'}{'time'} = time; sendSync(\$remote_socket, getTickCount()); } return if (!$AI); if ($ai_seq[0] eq "look" && timeOut(\%{$timeout{'ai_look'}})) { $timeout{'ai_look'}{'time'} = time; sendLook(\$remote_socket, $ai_seq_args[0]{'look_body'}, $ai_seq_args[0]{'look_head'}); &shift_ai_seq(); } if ($ai_seq[0] eq "deal" && !%currentDeal) { &shift_ai_seq(); } if ($config{'dealAutoCancel'} && %incomingDeal && timeOut(\%{$timeout{'ai_dealAutoCancel'}})) { sendDealCancel(\$remote_socket); $timeout{'ai_dealAutoCancel'}{'time'} = time; } if ($config{'partyAutoDeny'} && %incomingParty && timeOut(\%{$timeout{'ai_partyAutoDeny'}})) { sendPartyJoin(\$remote_socket, $incomingParty{'ID'}, 0); $timeout{'ai_partyAutoDeny'}{'time'} = time; undef %incomingParty; } if ($config{'friendsAutoDeny'} && %incomingFriends && timeOut(\%{$timeout{'ai_friendsAutoDeny'}})) { sendFriendsMakeAccept(\$remote_socket, pack("L1", $incomingFriends{'ID'}), pack("L1", $incomingFriends{'ID2'}), 0); $timeout{'ai_friendsAutoDeny'}{'time'} = time; undef %incomingFriends; } if ($ai_v{'portalTrace_mapChanged'}) { undef $ai_v{'portalTrace_mapChanged'}; $ai_v{'temp'}{'first'} = 1; undef $ai_v{'temp'}{'foundID'}; undef $ai_v{'temp'}{'smallDist'}; foreach (@portalsID_old) { $ai_v{'temp'}{'dist'} = distance(\%{$chars_old[$config{'char'}]{'pos_to'}}, \%{$portals_old{$_}{'pos'}}); if ($ai_v{'temp'}{'dist'} <= 7 && ($ai_v{'temp'}{'first'} || $ai_v{'temp'}{'dist'} < $ai_v{'temp'}{'smallDist'})) { $ai_v{'temp'}{'smallDist'} = $ai_v{'temp'}{'dist'}; $ai_v{'temp'}{'foundID'} = $_; undef $ai_v{'temp'}{'first'}; } } if ($ai_v{'temp'}{'foundID'}) { $ai_v{'portalTrace'}{'source'}{'map'} = $portals_old{$ai_v{'temp'}{'foundID'}}{'source'}{'map'}; $ai_v{'portalTrace'}{'source'}{'ID'} = $portals_old{$ai_v{'temp'}{'foundID'}}{'nameID'}; %{$ai_v{'portalTrace'}{'source'}{'pos'}} = %{$portals_old{$ai_v{'temp'}{'foundID'}}{'pos'}}; } } if (%{$ai_v{'portalTrace'}} && portalExists($ai_v{'portalTrace'}{'source'}{'map'}, \%{$ai_v{'portalTrace'}{'source'}{'pos'}}) ne "") { undef %{$ai_v{'portalTrace'}}; } elsif (%{$ai_v{'portalTrace'}} && $field{'name'}) { $ai_v{'temp'}{'first'} = 1; undef $ai_v{'temp'}{'foundID'}; undef $ai_v{'temp'}{'smallDist'}; foreach (@portalsID) { $ai_v{'temp'}{'dist'} = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$portals{$_}{'pos'}}); if ($ai_v{'temp'}{'first'} || $ai_v{'temp'}{'dist'} < $ai_v{'temp'}{'smallDist'}) { $ai_v{'temp'}{'smallDist'} = $ai_v{'temp'}{'dist'}; $ai_v{'temp'}{'foundID'} = $_; undef $ai_v{'temp'}{'first'}; } } if (%{$portals{$ai_v{'temp'}{'foundID'}}}) { if (portalExists($field{'name'}, \%{$portals{$ai_v{'temp'}{'foundID'}}{'pos'}}) eq "" && $ai_v{'portalTrace'}{'source'}{'map'} && $ai_v{'portalTrace'}{'source'}{'pos'}{'x'} ne "" && $ai_v{'portalTrace'}{'source'}{'pos'}{'y'} ne "" && $field{'name'} && $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'x'} ne "" && $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'y'} ne "") { $portals{$ai_v{'temp'}{'foundID'}}{'name'} = "$field{'name'} -> $ai_v{'portalTrace'}{'source'}{'map'}"; $portals{pack("L",$ai_v{'portalTrace'}{'source'}{'ID'})}{'name'} = "$ai_v{'portalTrace'}{'source'}{'map'} -> $field{'name'}"; $ai_v{'temp'}{'ID'} = "$ai_v{'portalTrace'}{'source'}{'map'} $ai_v{'portalTrace'}{'source'}{'pos'}{'x'} $ai_v{'portalTrace'}{'source'}{'pos'}{'y'}"; $portals_lut{$ai_v{'temp'}{'ID'}}{'source'}{'map'} = $ai_v{'portalTrace'}{'source'}{'map'}; %{$portals_lut{$ai_v{'temp'}{'ID'}}{'source'}{'pos'}} = %{$ai_v{'portalTrace'}{'source'}{'pos'}}; $portals_lut{$ai_v{'temp'}{'ID'}}{'dest'}{'map'} = $field{'name'}; %{$portals_lut{$ai_v{'temp'}{'ID'}}{'dest'}{'pos'}} = %{$portals{$ai_v{'temp'}{'foundID'}}{'pos'}}; updatePortalLUT("tables/portals.txt", $ai_v{'portalTrace'}{'source'}{'map'}, $ai_v{'portalTrace'}{'source'}{'pos'}{'x'}, $ai_v{'portalTrace'}{'source'}{'pos'}{'y'}, $field{'name'}, $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'x'}, $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'y'}); $ai_v{'temp'}{'ID2'} = "$field{'name'} $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'x'} $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'y'}"; $portals_lut{$ai_v{'temp'}{'ID2'}}{'source'}{'map'} = $field{'name'}; %{$portals_lut{$ai_v{'temp'}{'ID2'}}{'source'}{'pos'}} = %{$portals{$ai_v{'temp'}{'foundID'}}{'pos'}}; $portals_lut{$ai_v{'temp'}{'ID2'}}{'dest'}{'map'} = $ai_v{'portalTrace'}{'source'}{'map'}; %{$portals_lut{$ai_v{'temp'}{'ID2'}}{'dest'}{'pos'}} = %{$ai_v{'portalTrace'}{'source'}{'pos'}}; updatePortalLUT("tables/portals.txt", $field{'name'}, $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'x'}, $portals{$ai_v{'temp'}{'foundID'}}{'pos'}{'y'}, $ai_v{'portalTrace'}{'source'}{'map'}, $ai_v{'portalTrace'}{'source'}{'pos'}{'x'}, $ai_v{'portalTrace'}{'source'}{'pos'}{'y'}); } undef %{$ai_v{'portalTrace'}}; } } ##### CLIENT SUSPEND ##### if ($ai_seq[0] eq "clientSuspend" && timeOut(\%{$ai_seq_args[0]})) { &shift_ai_seq(); } elsif ($ai_seq[0] eq "clientSuspend") { if ($ai_seq_args[0]{'type'} eq "0089") { # 0190 0089 行動要求 if ($ai_seq_args[0]{'args'}[0] == 2) { if ($chars[$config{'char'}]{'sitting'}) { $ai_seq_args[0]{'time'} = time; } } elsif ($ai_seq_args[0]{'args'}[0] == 3) { $ai_seq_args[0]{'timeout'} = 6; } else { if (!$ai_seq_args[0]{'forceGiveup'}{'timeout'}) { $ai_seq_args[0]{'forceGiveup'}{'timeout'} = 6; $ai_seq_args[0]{'forceGiveup'}{'time'} = time; } if ($ai_seq_args[0]{'dmgFromYou_last'} != $monsters{$ai_seq_args[0]{'args'}[1]}{'dmgFromYou'}) { $ai_seq_args[0]{'forceGiveup'}{'time'} = time; } $ai_seq_args[0]{'dmgFromYou_last'} = $monsters{$ai_seq_args[0]{'args'}[1]}{'dmgFromYou'}; $ai_seq_args[0]{'missedFromYou_last'} = $monsters{$ai_seq_args[0]{'args'}[1]}{'missedFromYou'}; if (%{$monsters{$ai_seq_args[0]{'args'}[1]}}) { $ai_seq_args[0]{'time'} = time; } else { $ai_seq_args[0]{'time'} -= $ai_seq_args[0]{'timeout'}; } if (timeOut(\%{$ai_seq_args[0]{'forceGiveup'}})) { $ai_seq_args[0]{'time'} -= $ai_seq_args[0]{'timeout'}; } } } elsif ($switch eq "009F") { # 00F5 009F アイテム取得 if (!$ai_seq_args[0]{'forceGiveup'}{'timeout'}) { $ai_seq_args[0]{'forceGiveup'}{'timeout'} = 4; $ai_seq_args[0]{'forceGiveup'}{'time'} = time; } if (%{$items{$ai_seq_args[0]{'args'}[0]}}) { $ai_seq_args[0]{'time'} = time; } else { $ai_seq_args[0]{'time'} -= $ai_seq_args[0]{'timeout'}; } if (timeOut(\%{$ai_seq_args[0]{'forceGiveup'}})) { $ai_seq_args[0]{'time'} -= $ai_seq_args[0]{'timeout'}; } } } #####AUTO STORAGE##### AUTOSTORAGE: { if (($ai_seq[0] eq "" || $ai_seq[0] eq "route") && $config{'storageAuto'} && get_npc('storageAuto') ne "" && (percent_weight(\%{$chars[$config{'char'}]}) >= $config{'itemsMaxWeight'} || CheckRecoveryItem()==1 || (JudgeItemAmount()==0 && $config{'RecoveryItem'}))) { $ai_v{'temp'}{'ai_route_index'} = binFind(\@ai_seq, "route"); if ($ai_v{'temp'}{'ai_route_index'} ne "") { $ai_v{'temp'}{'ai_route_attackOnRoute'} = $ai_seq_args[$ai_v{'temp'}{'ai_route_index'}]{'attackOnRoute'}; } if (!($ai_v{'temp'}{'ai_route_index'} ne "" && $ai_v{'temp'}{'ai_route_attackOnRoute'} <= 1) && (ai_storageAutoCheck() || CheckRecoveryItem()==1)) { for ($i = 0; $i < @ai_seq; $i++){ last if ($ai_seq[$i] eq "storageAuto"); } if ($i == @ai_seq && $config{'storageAuto'} && get_npc('storageAuto') ne "" ) { unshift @ai_seq, "storageAuto"; unshift @ai_seq_args, {}; configModify("route_pointNo", 0); } } } if ($ai_seq[0] eq "storageAuto" && $ai_seq_args[0]{'done'}) { undef %{$ai_v{'temp'}{'ai'}}; %{$ai_v{'temp'}{'ai'}{'completedAI'}} = %{$ai_seq_args[0]{'completedAI'}}; &shift_ai_seq(); if (!$ai_v{'temp'}{'ai'}{'completedAI'}{'sellAuto'}) { $ai_v{'temp'}{'ai'}{'completedAI'}{'storageAuto'} = 1; unshift @ai_seq, "sellAuto"; unshift @ai_seq_args, {%{$ai_v{'temp'}{'ai'}}}; } elsif ($config{'exchangeAuto_afterStorage'} && binFind(\@ai_seq, "exchangeAuto") eq ""){ unshift @ai_seq, "exchangeAuto"; unshift @ai_seq_args, {}; } } elsif ($ai_seq[0] eq "storageAuto" && timeOut(\%{$timeout{'ai_storageAuto'}})) { if (!$config{'storageAuto'} || !%{$npcs_lut{get_npc('storageAuto')}}) { $ai_seq_args[0]{'done'} = 1; last AUTOSTORAGE; } undef $ai_v{'temp'}{'do_route'}; if ($field{'name'} ne $npcs_lut{get_npc('storageAuto')}{'map'}) { $ai_v{'temp'}{'do_route'} = 1; } else { $ai_v{'temp'}{'distance'} = distance(\%{$npcs_lut{get_npc('storageAuto')}{'pos'}}, \%{$chars[$config{'char'}]{'pos_to'}}); if ($ai_v{'temp'}{'distance'} > 14) { $ai_v{'temp'}{'do_route'} = 1; } } if ($ai_v{'temp'}{'do_route'}) { if ($ai_seq_args[0]{'warpedToSave'} && !$ai_seq_args[0]{'mapChanged'}) { undef $ai_seq_args[0]{'warpedToSave'}; } if ($ai_seq_args[0]{'mapChanged'} && $field{'name'} ne $npcs_lut{get_npc('storageAuto')}{'map'}) { undef $ai_seq_args[0]{'mapChanged'}; undef $ai_seq_args[0]{'warpedToSave'}; } if ($config{'saveMap'} ne "" && $config{'saveMap_warpToBuyOrSell'} && !$ai_seq_args[0]{'warpedToSave'} && !$cities_lut{$field{'name'}.'.rsw'}) { $ai_seq_args[0]{'warpedToSave'} = 1; sendTeleport(\$remote_socket, $config{'saveMap'}.".gat"); $timeout{'ai_storageAuto'}{'time'} = time(); } else { my $dist = $config{'storageAuto_'.get_npc('storageAuto',1).'_dist'}; $dist = ($dist ? $dist : 0); PrintMessage("移動ルート計算(自動倉庫): ".$maps_lut{$npcs_lut{get_npc('storageAuto')}{'map'}.'.rsw'}."(".$npcs_lut{get_npc('storageAuto')}{'map'}."): ".$npcs_lut{get_npc('storageAuto')}{'pos'}{'x'}.", ".$npcs_lut{get_npc('storageAuto')}{'pos'}{'y'}."\n", "route"); ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $npcs_lut{get_npc('storageAuto')}{'pos'}{'x'}+int(rand(14))-7, $npcs_lut{get_npc('storageAuto')}{'pos'}{'y'}+int(rand(14))-7, $npcs_lut{get_npc('storageAuto')}{'map'}, 0, 0, 1, 0, $dist, 1); } } else { if (!$ai_seq_args[0]{'sentStore'}) { sendTalk(\$remote_socket, pack("L1",get_npc('storageAuto'))); $ai_seq_args[0]{'sentStore'} = 1; undef $ai_seq_args[0]{'respCnt'}; $timeout{'ai_storageAuto'}{'time'} = time; last AUTOSTORAGE; } elsif ((%talk && $talk{'status'} ne 'close') && $ai_seq_args[0]{'sentStore'}) { sendTalkContinue(\$remote_socket, $talk{'ID'}) if $talk{'status'} eq "cont"; if($talk{'status'} eq "resp") { my @respIndex = split /,/,$config{'storageAuto_'.get_npc('storageAuto',1).'_resp'}; $respcnt = @respIndex; if ($respcnt) { if ($respcnt > $ai_seq_args[0]{'respCnt'}) { sendTalkResponse(\$remote_socket, $talk{'ID'}, $respIndex[$ai_seq_args[0]{'respCnt'}]+1); $ai_seq_args[0]{'respCnt'} ++; } else { sendTalkClose(\$remote_socket, $talk{'ID'}); } } else { sendTalkResponse(\$remote_socket, pack("L1",get_npc('storageAuto')),'2'); } } $timeout{'ai_storageAuto'}{'time'} = time; last AUTOSTORAGE; } $ai_seq_args[0]{'done'} = 1; for ($i = 0; $i < @{$chars[$config{'char'}]{'inventory'}};$i++) { next if (!%{$chars[$config{'char'}]{'inventory'}[$i]} || $chars[$config{'char'}]{'inventory'}[$i]{'equipped'}); if ($items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'storage'} && $chars[$config{'char'}]{'inventory'}[$i]{'amount'} > $items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'keep'}) { if ($ai_seq_args[0]{'lastIndex'} ne "" && $ai_seq_args[0]{'lastIndex'} == $chars[$config{'char'}]{'inventory'}[$i]{'index'} && timeOut(\%{$timeout{'ai_storageAuto_giveup'}})) { last AUTOSTORAGE; } elsif ($ai_seq_args[0]{'lastIndex'} eq "" || $ai_seq_args[0]{'lastIndex'} != $chars[$config{'char'}]{'inventory'}[$i]{'index'}) { $timeout{'ai_storageAuto_giveup'}{'time'} = time(); } undef $ai_seq_args[0]{'done'}; $ai_seq_args[0]{'lastIndex'} = $chars[$config{'char'}]{'inventory'}[$i]{'index'}; sendStorageAdd(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$i]{'index'}, $chars[$config{'char'}]{'inventory'}[$i]{'amount'} - $items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'keep'}); $timeout{'ai_storageAuto'}{'time'} = time(); last AUTOSTORAGE; } } @temp=keys(%items_control); if($config{'storageGet'}==1){ for ($i = 0; $i < @temp;$i++) { $invIndex = findIndexString_lc(\@{$chars[$config{'char'}]{'inventory'}}, "name", $temp[$i]); $j=$chars[$config{'char'}]{'inventory'}[$invIndex]{'amount'}; $j=0 if($invIndex eq ''); $invIndex = findIndexString_lc(\@{$storage{'inventory'}}, "name",$temp[$i]); if($storage{'inventory'}[$invIndex]{'amount'} > 0 && $invIndex ne '' && $items_control{$temp[$i]}{'keep'}-$j > 0){ if ($chars[$config{'char'}]{'inventory'}[$invIndex]{'equipped'} && ($chars[$config{'char'}]{'inventory'}[$invIndex]{'type_equip'} == 128)) { sendUnequip(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$invIndex]{'index'}); } if($storage{'inventory'}[$invIndex]{'amount'} < $items_control{$temp[$i]}{'keep'}-$j){ sendStorageGet(\$remote_socket,$invIndex,$storage{'inventory'}[$invIndex]{'amount'}); } else { sendStorageGet(\$remote_socket,$invIndex,$items_control{$temp[$i]}{'keep'}-$j); } } elsif(!$storage{'inventory'}[$invIndex]{'amount'} && $invIndex ne '' && $items_control{$temp[$i]}{'keep'}-$j > 0) { if($config{'nostorage'} == 1) { quit(); }elsif($config{'nostorage'} == 2) { configModify("CheckRecoveryItem", 0); } } } } ### 現在の倉庫の中身をtxt出力 ### recordStorageItem(); sendStorageClose(\$remote_socket); $mapchange++; if ($KoreStartTime && $config{'autoRestart'} && time() - $KoreStartTime > $config{'autoRestart'} && !$config{'exchangeAuto_afterStorage'} && !$config{'buyAuto_0'} && !$config{'sellAuto'}) { $relog=1; } } } } #END OF BLOCK AUTOSTORAGE #####AUTO SELL##### AUTOSELL: { if (($ai_seq[0] eq "" || $ai_seq[0] eq "route") && $config{'sellAuto'} && get_npc('sellAuto') ne "" && percent_weight(\%{$chars[$config{'char'}]}) >= $config{'itemsMaxWeight'}) { $ai_v{'temp'}{'ai_route_index'} = binFind(\@ai_seq, "route"); if ($ai_v{'temp'}{'ai_route_index'} ne "") { $ai_v{'temp'}{'ai_route_attackOnRoute'} = $ai_seq_args[$ai_v{'temp'}{'ai_route_index'}]{'attackOnRoute'}; } if (!($ai_v{'temp'}{'ai_route_index'} ne "" && $ai_v{'temp'}{'ai_route_attackOnRoute'} <= 1) && ai_sellAutoCheck()) { unshift @ai_seq, "sellAuto"; unshift @ai_seq_args, {}; } } if ($ai_seq[0] eq "sellAuto" && $ai_seq_args[0]{'done'}) { undef %{$ai_v{'temp'}{'ai'}}; %{$ai_v{'temp'}{'ai'}{'completedAI'}} = %{$ai_seq_args[0]{'completedAI'}}; &shift_ai_seq(); if (!$ai_v{'temp'}{'ai'}{'completedAI'}{'buyAuto'}) { $ai_v{'temp'}{'ai'}{'completedAI'}{'sellAuto'} = 1; unshift @ai_seq, "buyAuto"; unshift @ai_seq_args, {%{$ai_v{'temp'}{'ai'}}}; } } elsif ($ai_seq[0] eq "sellAuto" && timeOut(\%{$timeout{'ai_sellAuto'}})) { if (!$config{'sellAuto'} || !%{$npcs_lut{get_npc('sellAuto')}}) { $ai_seq_args[0]{'done'} = 1; last AUTOSELL; } undef $ai_v{'temp'}{'do_route'}; if ($field{'name'} ne $npcs_lut{get_npc('sellAuto')}{'map'}) { $ai_v{'temp'}{'do_route'} = 1; } else { $ai_v{'temp'}{'distance'} = distance(\%{$npcs_lut{get_npc('sellAuto')}{'pos'}}, \%{$chars[$config{'char'}]{'pos_to'}}); if ($ai_v{'temp'}{'distance'} > 14) { $ai_v{'temp'}{'do_route'} = 1; } } if ($ai_v{'temp'}{'do_route'}) { if ($ai_seq_args[0]{'warpedToSave'} && !$ai_seq_args[0]{'mapChanged'}) { undef $ai_seq_args[0]{'warpedToSave'}; } if ($ai_seq_args[0]{'mapChanged'} && $field{'name'} ne $npcs_lut{get_npc('sellAuto')}{'map'}) { undef $ai_seq_args[0]{'mapChanged'}; undef $ai_seq_args[0]{'warpedToSave'}; } if ($config{'saveMap'} ne "" && $config{'saveMap_warpToBuyOrSell'} && !$ai_seq_args[0]{'warpedToSave'} && !$cities_lut{$field{'name'}.'.rsw'}) { $ai_seq_args[0]{'warpedToSave'} = 1; sendTeleport(\$remote_socket, $config{'saveMap'}.".gat"); $timeout{'ai_sellAuto'}{'time'} = time; } else { my $dist = $config{'sellAuto_'.get_npc('sellAuto',1).'_dist'}; $dist = ($dist ? $dist : 2); PrintMessage("移動ルート計算中(自動売却): ".$maps_lut{$npcs_lut{get_npc('sellAuto')}{'map'}.'.rsw'}."(".$npcs_lut{get_npc('sellAuto')}{'map'}."): ".$npcs_lut{get_npc('sellAuto')}{'pos'}{'x'}.", ".$npcs_lut{get_npc('sellAuto')}{'pos'}{'y'}."\n", "route"); ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $npcs_lut{get_npc('sellAuto')}{'pos'}{'x'}, $npcs_lut{get_npc('sellAuto')}{'pos'}{'y'}, $npcs_lut{get_npc('sellAuto')}{'map'}, 0, 0, 1, 0, $dist, 1); } } else { if ($ai_seq_args[0]{'sentSell'} <= 1) { sendTalk(\$remote_socket, pack("L1",get_npc('sellAuto'))) if !$ai_seq_args[0]{'sentSell'}; sendGetSellList(\$remote_socket, pack("L1",get_npc('sellAuto'))) if $ai_seq_args[0]{'sentSell'}; $ai_seq_args[0]{'sentSell'}++; $timeout{'ai_sellAuto'}{'time'} = time; last AUTOSELL; } $ai_seq_args[0]{'done'} = 1; for ($i = 0; $i < @{$chars[$config{'char'}]{'inventory'}};$i++) { next if (!%{$chars[$config{'char'}]{'inventory'}[$i]} || $chars[$config{'char'}]{'inventory'}[$i]{'equipped'}); if ($items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'sell'} && $chars[$config{'char'}]{'inventory'}[$i]{'amount'} > $items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'keep'}) { if ($ai_seq_args[0]{'lastIndex'} ne "" && $ai_seq_args[0]{'lastIndex'} == $chars[$config{'char'}]{'inventory'}[$i]{'index'} && timeOut(\%{$timeout{'ai_sellAuto_giveup'}})) { last AUTOSELL; } elsif ($ai_seq_args[0]{'lastIndex'} eq "" || $ai_seq_args[0]{'lastIndex'} != $chars[$config{'char'}]{'inventory'}[$i]{'index'}) { $timeout{'ai_sellAuto_giveup'}{'time'} = time; } undef $ai_seq_args[0]{'done'}; $ai_seq_args[0]{'lastIndex'} = $chars[$config{'char'}]{'inventory'}[$i]{'index'}; sendSell(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$i]{'index'}, $chars[$config{'char'}]{'inventory'}[$i]{'amount'} - $items_control{lc($chars[$config{'char'}]{'inventory'}[$i]{'name'})}{'keep'}); $timeout{'ai_sellAuto'}{'time'} = time; last AUTOSELL; } } } } } #END OF BLOCK AUTOSELL #####AUTO BUY##### AUTOBUY: { if (($ai_seq[0] eq "" || $ai_seq[0] eq "route" || $ai_seq[0] eq "attack") && timeOut(\%{$timeout{'ai_buyAuto'}})) { undef $ai_v{'temp'}{'found'}; $i = 0; while (1) { last if (!$config{"buyAuto_$i"} || !$config{"buyAuto_$i"."_npc"}); $ai_v{'temp'}{'invIndex'} = findIndexString_lc(\@{$chars[$config{'char'}]{'inventory'}}, "name", $config{"buyAuto_$i"}); if ($config{"buyAuto_$i"."_minAmount"} ne "" && $config{"buyAuto_$i"."_maxAmount"} ne "" && ($ai_v{'temp'}{'invIndex'} eq "" || ($chars[$config{'char'}]{'inventory'}[$ai_v{'temp'}{'invIndex'}]{'amount'} <= $config{"buyAuto_$i"."_minAmount"} && $chars[$config{'char'}]{'inventory'}[$ai_v{'temp'}{'invIndex'}]{'amount'} < $config{"buyAuto_$i"."_maxAmount"})) && ($chars[$config{'char'}]{'zenny'} >= $config{"buyAuto_$i"."_price"} * ($config{"buyAuto_$i"."_minAmount"} + 1))) { $ai_v{'temp'}{'found'} = 1; } $i++; } $ai_v{'temp'}{'ai_route_index'} = binFind(\@ai_seq, "route"); if ($ai_v{'temp'}{'ai_route_index'} ne "") { $ai_v{'temp'}{'ai_route_attackOnRoute'} = $ai_seq_args[$ai_v{'temp'}{'ai_route_index'}]{'attackOnRoute'}; } if (!($ai_v{'temp'}{'ai_route_index'} ne "" && $ai_v{'temp'}{'ai_route_attackOnRoute'} <= 1) && $ai_v{'temp'}{'found'}) { unshift @ai_seq, "buyAuto"; unshift @ai_seq_args, {}; } $timeout{'ai_buyAuto'}{'time'} = time; } if ($ai_seq[0] eq "buyAuto" && $ai_seq_args[0]{'done'}) { undef %{$ai_v{'temp'}{'ai'}}; %{$ai_v{'temp'}{'ai'}{'completedAI'}} = %{$ai_seq_args[0]{'completedAI'}}; &shift_ai_seq(); if (!$ai_v{'temp'}{'ai'}{'completedAI'}{'storageAuto'}) { $ai_v{'temp'}{'ai'}{'completedAI'}{'buyAuto'} = 1; unshift @ai_seq, "storageAuto"; unshift @ai_seq_args, {%{$ai_v{'temp'}{'ai'}}}; } } elsif ($ai_seq[0] eq "buyAuto" && timeOut(\%{$timeout{'ai_buyAuto_wait'}}) && timeOut(\%{$timeout{'ai_buyAuto_wait_buy'}})) { $i = 0; undef $ai_seq_args[0]{'index'}; while (1) { last if (!$config{"buyAuto_$i"} || !%{$npcs_lut{$config{"buyAuto_$i"."_npc"}}}); $ai_seq_args[0]{'invIndex'} = findIndexString_lc(\@{$chars[$config{'char'}]{'inventory'}}, "name", $config{"buyAuto_$i"}); if (!$ai_seq_args[0]{'index_failed'}{$i} && $config{"buyAuto_$i"."_maxAmount"} ne "" && ($ai_seq_args[0]{'invIndex'} eq "" || $chars[$config{'char'}]{'inventory'}[$ai_seq_args[0]{'invIndex'}]{'amount'} < $config{"buyAuto_$i"."_maxAmount"})) { $ai_seq_args[0]{'index'} = $i; last; } $i++; } if ($ai_seq_args[0]{'index'} eq "" || ($ai_seq_args[0]{'lastIndex'} ne "" && $ai_seq_args[0]{'lastIndex'} == $ai_seq_args[0]{'index'} && !$ai_seq_args[0]{'repeat'} && timeOut(\%{$timeout{'ai_buyAuto_giveup'}}))) { $ai_seq_args[0]{'done'} = 1; last AUTOBUY; } undef $ai_v{'temp'}{'do_route'}; if ($field{'name'} ne $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'map'}) { $ai_v{'temp'}{'do_route'} = 1; } else { $ai_v{'temp'}{'distance'} = distance(\%{$npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'pos'}}, \%{$chars[$config{'char'}]{'pos_to'}}); if ($ai_v{'temp'}{'distance'} > 14) { $ai_v{'temp'}{'do_route'} = 1; } } if ($ai_v{'temp'}{'do_route'}) { if ($ai_seq_args[0]{'warpedToSave'} && !$ai_seq_args[0]{'mapChanged'}) { undef $ai_seq_args[0]{'warpedToSave'}; } if ($ai_seq_args[0]{'mapChanged'} && $field{'name'} ne $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'map'}) { undef $ai_seq_args[0]{'mapChanged'}; undef $ai_seq_args[0]{'warpedToSave'}; } if ($config{'saveMap'} ne "" && $config{'saveMap_warpToBuyOrSell'} && !$ai_seq_args[0]{'warpedToSave'} && !$cities_lut{$field{'name'}.'.rsw'}) { $ai_seq_args[0]{'warpedToSave'} = 1; sendTeleport(\$remote_socket, $config{'saveMap'}.".gat"); $timeout{'ai_buyAuto_wait'}{'time'} = time; } else { PrintMessage(qq~移動ルート計算中(自動購入): $maps_lut{$npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'map'}.'.rsw'}($npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'map'}): $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'pos'}{'x'}, $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'pos'}{'y'}\n~, "route"); my $dist = ($config{"buyAuto_$ai_seq_args[0]{'index'}"."_dist"} ? $config{"buyAuto_$ai_seq_args[0]{'index'}"."_dist"} : 2); ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'pos'}{'x'}, $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'pos'}{'y'}, $npcs_lut{$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"}}{'map'}, 0, 0, 1, 0, $dist, 1); } } else { if ($ai_seq_args[0]{'lastIndex'} eq "" || $ai_seq_args[0]{'lastIndex'} != $ai_seq_args[0]{'index'}) { undef $ai_seq_args[0]{'itemID'}; if ($config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"} != $config{"buyAuto_$ai_seq_args[0]{'lastIndex'}"."_npc"}) { undef $ai_seq_args[0]{'sentBuy'}; } $timeout{'ai_buyAuto_giveup'}{'time'} = time; } $ai_seq_args[0]{'lastIndex'} = $ai_seq_args[0]{'index'}; if ($ai_seq_args[0]{'itemID'} eq "") { foreach (keys %items_lut) { if (lc($items_lut{$_}) eq lc($config{"buyAuto_$ai_seq_args[0]{'index'}"})) { $ai_seq_args[0]{'itemID'} = $_; } } if ($ai_seq_args[0]{'itemID'} eq "") { $ai_seq_args[0]{'index_failed'}{$ai_seq_args[0]{'index'}} = 1; print "autoBuy index $ai_seq_args[0]{'index'} failed\n" if $config{'debug'}; last AUTOBUY; } } if ($ai_seq_args[0]{'repeat'} == 1) { sendTalkCancel(\$remote_socket, pack("L1",$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"})); undef $ai_seq_args[0]{'sentBuy'}; $ai_seq_args[0]{'repeat'} = 2; $timeout{'ai_buyAuto_wait'}{'time'} = time; last AUTOBUY; } if (!$ai_seq_args[0]{'sentBuy'}) { sendTalk(\$remote_socket, pack("L1",$config{"buyAuto_$ai_seq_args[0]{'index'}"."_npc"})); $ai_seq_args[0]{'sentBuy'} = 1; undef $ai_seq_args[0]{'respCnt'}; $timeout{'ai_buyAuto_wait'}{'time'} = time; last AUTOBUY; } elsif ((%talk && $talk{'status'} ne 'close') && $talk{'status'} ne "input" && $talk{'status'} ne "store") { sendGetStoreList(\$remote_socket, $talk{'ID'}) if $talk{'status'} eq "buyOrSell"; sendTalkContinue(\$remote_socket, $talk{'ID'}) if $talk{'status'} eq "cont"; if($talk{'status'} eq "resp") { my @respIndex = split /,/,$config{"buyAuto_$ai_seq_args[0]{'index'}"."_resp"}; $respcnt = @respIndex; if ($respcnt > $ai_seq_args[0]{'respCnt'}) { sendTalkResponse(\$remote_socket, $talk{'ID'}, $respIndex[$ai_seq_args[0]{'respCnt'}]+1); $ai_seq_args[0]{'respCnt'} ++; } else { sendTalkClose(\$remote_socket, $talk{'ID'}); } } $timeout{'ai_buyAuto_wait'}{'time'} = time; last AUTOBUY; } if ($ai_seq_args[0]{'invIndex'} ne "") { $amount = $config{"buyAuto_$ai_seq_args[0]{'index'}"."_maxAmount"} - $chars[$config{'char'}]{'inventory'}[$ai_seq_args[0]{'invIndex'}]{'amount'}; } else { $amount = $config{"buyAuto_$ai_seq_args[0]{'index'}"."_maxAmount"}; } if ($chars[$config{'char'}]{'zenny'} < $amount * $config{"buyAuto_$ai_seq_args[0]{'index'}"."_price"}) { $amount = int($chars[$config{'char'}]{'zenny'} / $config{"buyAuto_$ai_seq_args[0]{'index'}"."_price"}); } undef $ai_seq_args[0]{'repeat'}; if ($config{"buyAuto_$ai_seq_args[0]{'index'}"."_buyable"} && $amount >= $config{"buyAuto_$ai_seq_args[0]{'index'}"."_buyable"}) { $amount = $config{"buyAuto_$ai_seq_args[0]{'index'}"."_buyable"}; $ai_seq_args[0]{'repeat'} = 1; } if ($talk{'status'} ne "input") { sendBuy(\$remote_socket, $ai_seq_args[0]{'itemID'}, $amount); } else { sendTalkAmount(\$remote_socket, $talk{'ID'}, $amount); } $timeout{'ai_buyAuto_wait_buy'}{'time'} = time; } } } #END OF BLOCK AUTOBUY ##### LOCKMAP ##### if (($ai_seq[0] eq "" || $ai_seq[0] eq "follow") && $config{'lockMap'} && $field{'name'} && ($field{'name'} ne $config{'lockMap'} || ($config{'lockMap_x'} ne "" && ( $chars[$config{'char'}]{'pos_to'}{'x'} < $config{'lockMap_x'}-1 || $chars[$config{'char'}]{'pos_to'}{'x'} > $config{'lockMap_x'}+1 || $chars[$config{'char'}]{'pos_to'}{'y'} < $config{'lockMap_y'}-1 || $chars[$config{'char'}]{'pos_to'}{'y'} > $config{'lockMap_y'}+1 )))) { if ($maps_lut{$config{'lockMap'}.'.rsw'} eq "") { PrintMessage("Invalid map specified for lockMap - map $config{'lockMap'} doesn't exist\n", "def"); } else { if ($config{'lockMap_x'} ne "") { PrintMessage("移動ルート計算中(狩場まで): $maps_lut{$config{'lockMap'}.'.rsw'}($config{'lockMap'}): $config{'lockMap_x'}, $config{'lockMap_y'}\n", "route"); } else { PrintMessage("移動ルート計算中(狩場まで): $maps_lut{$config{'lockMap'}.'.rsw'}($config{'lockMap'})\n", "route"); } ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $config{'lockMap_x'}, $config{'lockMap_y'}, $config{'lockMap'}, 0, 0, 1, 0, 0, 1); } } ##### AUTO LOGOUT ##### if (int($config{'dcWhenZenyBelow'}) && $config{'dcWhenZenyBelow'} > $chars[$config{'char'}]{'zenny'}) { PrintMessage("所持金が最低金額より下回ったためログアウトします\n", "red"); chatLog("etc","所持金が最低金額より下回ったためログアウトします。\n"); sleep(5); quit(); } if (int($config{'dcWhenWeightOver'}) && $config{'dcWhenWeightOver'} < int($chars[$config{'char'}]{'weight'}/$chars[$config{'char'}]{'weight_max'} * 100)) { PrintMessage("重量が指定量を超えたためログアウトします\n", "red"); chatLog("etc","重量が指定量を超えたためログアウトします。\n"); sleep(5); quit(); } ##### RANDOM WALK ##### if ($config{'route_randomWalk'} && $ai_seq[0] eq "" && binFind(\@ai_seq, "attack") eq "" && $currentChatRoom eq "" && @{$field{'field'}} > 1 && !$cities_lut{$field{'name'}.'.rsw'}) { if (timeOut($ai_v{'stuck'}{'lasttime'}, 5)) { $ai_v{'stuck'}{'count'} = 0; }else{ $ai_v{'stuck'}{'count'} ++; } $ai_v{'stuck'}{'lasttime'} = time; do { $ai_v{'temp'}{'randX'} = int(rand() * ($field{'width'} - 1)); $ai_v{'temp'}{'randY'} = int(rand() * ($field{'height'} - 1)); } while ($field{'field'}[$ai_v{'temp'}{'randY'}*$field{'width'} + $ai_v{'temp'}{'randX'}]); PrintMessage("移動ルート計算中(ランダム): $maps_lut{$field{'name'}.'.rsw'}($field{'name'}): $ai_v{'temp'}{'randX'}, $ai_v{'temp'}{'randY'}\n", "route"); ai_route(\%{$ai_v{'temp'}{'returnHash'}}, $ai_v{'temp'}{'randX'}, $ai_v{'temp'}{'randY'}, $field{'name'}, 0, $config{'route_randomWalk_maxRouteTime'}, 2); } ##### DEAD ##### if ($ai_seq[0] eq "dead" && !$chars[$config{'char'}]{'dead'}) { &shift_ai_seq(); #force storage after death unshift @ai_seq, "storageAuto"; unshift @ai_seq_args, {}; } elsif ($ai_seq[0] ne "dead" && $chars[$config{'char'}]{'dead'}) { &undef_ai_seq(); unshift @ai_seq, "dead"; unshift @ai_seq_args, {}; } if ($ai_seq[0] eq "dead" && time - $chars[$config{'char'}]{'dead_time'} >= $timeout{'ai_dead_respawn'}{'timeout'}) { sendRespawn(\$remote_socket); $chars[$config{'char'}]{'dead_time'} = time; } if ($ai_seq[0] eq "dead" && $config{'dcOnDeath'}) { PrintMessage("Disconnecting on death!\n", "def"); quit(); } ##### AUTO-ITEM USE ##### if (($ai_seq[0] eq "" || $ai_seq[0] eq "route" || $ai_seq[0] eq "route_getRoute" || $ai_seq[0] eq "route_getMapRoute" || $ai_seq[0] eq "follow" || $ai_seq[0] eq "sitAuto" || $ai_seq[0] eq "take" || $ai_seq[0] eq "items_gather" || $ai_seq[0] eq "items_take" || $ai_seq[0] eq "attack") && timeOut(\%{$timeout{'ai_item_use_auto'}})) { $i = 0; while (1) { last if (!$config{"useSelf_item_$i"}); if (percent_hp(\%{$chars[$config{'char'}]}) <= $config{"useSelf_item_$i"."_hp_upper"} && percent_hp(\%{$chars[$config{'char'}]}) >= $config{"useSelf_item_$i"."_hp_lower"} && percent_sp(\%{$chars[$config{'char'}]}) <= $config{"useSelf_item_$i"."_sp_upper"} && percent_sp(\%{$chars[$config{'char'}]}) >= $config{"useSelf_item_$i"."_sp_lower"} && timeOut($config{"useSelf_item_$i"."_timeout"}, $ai_v{"useSelf_item_$i"."_time"}) && (!$config{"useSelf_item_$i"."_lockMap"} || ($config{"useSelf_item_$i"."_lockMap"} && ($config{"useSelf_item_$i"."_lockMap"} eq $field{'name'} || (lc($config{"useSelf_item_$i"."_lockMap"}) eq 'lockmap' && $field{'name'} eq $config{'lockMap'}) || (lc($config{"useSelf_item_$i"."_lockMap"}) eq 'notcity' && !$cities_lut{$field{'name'}.'.rsw'})))) && !($config{"useSelf_item_$i"."_stopWhenHit"} && ai_getMonstersWhoHitMe()) && $config{"useSelf_item_$i"."_minAggressives"} <= ai_getAggressives() && (!$config{"useSelf_item_$i"."_maxAggressives"} || $config{"useSelf_item_$i"."_maxAggressives"} >= ai_getAggressives())) { undef $ai_v{'temp'}{'invIndex'}; $ai_v{'temp'}{'invIndex'} = findIndexString_lc(\@{$chars[$config{'char'}]{'inventory'}}, "name", $config{"useSelf_item_$i"}); $ai_v{"useSelf_item_$i"."_time"} = time; if ($ai_v{'temp'}{'invIndex'} ne "") { $timeout{'ai_item_use_auto'}{'time'} = time; # ラグ時のアイテム連続使用 if(!$config{'useSelf_item_continue'}){ $config{'useSelf_item_continue'} = 1; } my $c; for($c = 0; $c < $config{'useSelf_item_continue'}; $c++){ sendItemUse(\$remote_socket, $chars[$config{'char'}]{'inventory'}[$ai_v{'temp'}{'invIndex'}]{'index'}, $accountID); print qq~Auto-item use: $items_lut{$chars[$config{'char'}]{'inventory'}[$ai_v{'temp'}{'invIndex'}]{'nameID'}}\n~ if $config{'debug'}; } last; } } $i++; } } ##### AUTO-SKILL USE ##### if ($ai_seq[0] eq "" || $ai_seq[0] eq "move" || $ai_seq[0] eq "route" || $ai_seq[0] eq "route_getRoute" || $ai_seq[0] eq "route_getMapRoute" || $ai_seq[0] eq "follow" || $ai_seq[0] eq "sitAuto" || $ai_seq[0] eq "take" || $ai_seq[0] eq "items_gather" || $ai_seq[0] eq "items_take" || $ai_seq[0] eq "attack") { $i = 0; undef $ai_v{'useSelf_skill'}; undef $ai_v{'useSelf_skill_lvl'}; while (1) { last if (!$config{"useSelf_skill_$i"}); $ai_v{'useSelf_skill_uses'}{$i} = 0; if (checkSkillUseable($skills_rlut{lc($config{"useSelf_skill_$i"})})) { if (percent_hp(\%{$chars[$config{'char'}]}) <= $config{"useSelf_skill_$i"."_hp_upper"} && percent_hp(\%{$chars[$config{'char'}]}) >= $config{"useSelf_skill_$i"."_hp_lower"} && percent_sp(\%{$chars[$config{'char'}]}) <= $config{"useSelf_skill_$i"."_sp_upper"} && percent_sp(\%{$chars[$config{'char'}]}) >= $config{"useSelf_skill_$i"."_sp_lower"} && checkstatus($skills_rlut{lc($config{"useSelf_skill_$i"})}) && !($config{"useSelf_skill_$i"."_dontUseWhenSitting"} && $chars[$config{'char'}]{'sitting'}) && $chars[$config{'char'}]{'sp'} >= $skillsSP_lut{$skills_rlut{lc($config{"useSelf_skill_$i"})}}{$config{"useSelf_skill_$i"."_lvl"}} && timeOut($config{"useSelf_skill_$i"."_timeout"}, $ai_v{"useSelf_skill_$i"."_time"}) && !($config{"useSelf_skill_$i"."_stopWhenHit"} && ai_getMonstersWhoHitMe()) && (!$config{"useSelf_skill_$i"."_lockMap"} || ($config{"useSelf_skill_$i"."_lockMap"} && ($config{"useSelf_skill_$i"."_lockMap"} eq $field{'name'} || (lc($config{"useSelf_skill_$i"."_lockMap"}) eq 'lockmap' && $field{'name'} eq $config{'lockMap'}) || (lc($config{"useSelf_skill_$i"."_lockMap"}) eq 'notcity' && !$cities_lut{$field{'name'}.'.rsw'})))) && $config{"useSelf_skill_$i"."_minAggressives"} <= ai_getAggressives() && (!$config{"useSelf_skill_$i"."_maxUses"} || $ai_v{'useSelf_skill_uses'}{$i} < $config{"useSelf_skill_$i"."_maxUses"}) && ((!$config{"useSelf_skill_$i"."_maxAggressives"} && !$config{"useSelf_skill_$i"."_useAfterBattle"}) || $config{"useSelf_skill_$i"."_maxAggressives"} >= ai_getAggressives()) && (!$config{"useSelf_skill_$i"."_checkItem"} || itemCheck($config{"useSelf_skill_$i"."_checkItem"})) ) { if ($ai_v{'pneuma'}{'flag'} && !timeOut($ai_v{'pneuma'}{'time'}, 1)) { $ai_v{'pneuma'}{'flag'} = 0; last; } $ai_v{"useSelf_skill_$i"."_time"} = time; $ai_v{'useSelf_skill'} = $config{"useSelf_skill_$i"}; $ai_v{'useSelf_skill_lvl'} = $config{"useSelf_skill_$i"."_lvl"}; $ai_v{'useSelf_skill_maxCastTime'} = $config{"useSelf_skill_$i"."_maxCastTime"}; $ai_v{'useSelf_skill_minCastTime'} = $config{"useSelf_skill_$i"."_minCastTime"}; last; } } $i++; } if (!$chars[$config{'char'}]{'skills'}{'AL_HEAL'}{'lv'} && $ai_v{'useSelf_skill'} eq "ヒール" && $config{"autoEquip_accessory_heal"} && $ai_v{'useSelf_skill_lvl'} > 0) { if ($chars[$config{'char'}]{'sitting'}) { ai_setSuspend(0); stand(); } $autoEquip_accessory_heal = 1; undef $ai_v{'useSelf_skill'}; undef $ai_v{'useSelf_skill_lvl'}; } if ($config{'useSelf_skill_smartHeal'} && $skills_rlut{lc($ai_v{'useSelf_skill'})} eq "AL_HEAL") { undef $ai_v{'useSelf_skill_smartHeal_lvl'}; $ai_v{'useSelf_skill_smartHeal_hp_dif'} = $chars[$config{'char'}]{'hp_max'} - $chars[$config{'char'}]{'hp'}; for ($i = 1; $i <= $chars[$config{'char'}]{'skills'}{$skills_rlut{lc($ai_v{'useSelf_skill'})}}{'lv'}; $i++) { $ai_v{'useSelf_skill_smartHeal_lvl'} = $i; $ai_v{'useSelf_skill_smartHeal_sp'} = 10 + ($i * 3); $ai_v{'useSelf_skill_smartHeal_amount'} = int(($chars[$config{'char'}]{'lv'} + $chars[$config{'char'}]{'int'}) / 8) * (4 + $i * 8); if ($chars[$config{'char'}]{'sp'} < $ai_v{'useSelf_skill_smartHeal_sp'}) { $ai_v{'useSelf_skill_smartHeal_lvl'}--; last; } last if ($ai_v{'useSelf_skill_smartHeal_amount'} >= $ai_v{'useSelf_skill_smartHeal_hp_dif'}); } $ai_v{'useSelf_skill_lvl'} = $ai_v{'useSelf_skill_smartHeal_lvl'}; } if ($ai_v{'useSelf_skill_lvl'} > 0) { print qq~Auto-skill on self: $skills_lut{$skills_rlut{lc($ai_v{'useSelf_skill'})}} (lvl $ai_v{'useSelf_skill_lvl'})\n~ if $config{'debug'}; if (!ai_getSkillUseType($skills_rlut{lc($ai_v{'useSelf_skill'})})) { ai_skillUse($skillsCD_lut{$skills_rlut{lc($ai_v{'useSelf_skill'})}}, $ai_v{'useSelf_skill_lvl'}, $ai_v{'useSelf_skill_maxCastTime'}, $ai_v{'useSelf_skill_minCastTime'}, $accountID); } else { ai_skillUse($skillsCD_lut{$skills_rlut{lc($ai_v{'useSelf_skill'})}}, $ai_v{'useSelf_skill_lvl'}, $ai_v{'useSelf_skill_maxCastTime'}, $ai_v{'useSelf_skill_minCastTime'}, $chars[$config{'char'}]{'pos_to'}{'x'}, $chars[$config{'char'}]{'pos_to'}{'y'}); } } } ##### SKILL USE ##### if ($ai_seq[0] eq "skill_use" && $ai_seq_args[0]{'suspended'}) { $ai_seq_args[0]{'ai_skill_use_giveup'}{'time'} += time - $ai_seq_args[0]{'suspended'}; $ai_seq_args[0]{'ai_skill_use_minCastTime'}{'time'} += time - $ai_seq_args[0]{'suspended'}; $ai_seq_args[0]{'ai_skill_use_maxCastTime'}{'time'} += time - $ai_seq_args[0]{'suspended'}; undef $ai_seq_args[0]{'suspended'}; } if ($ai_seq[0] eq "skill_use") { if ($chars[$config{'char'}]{'sitting'}) { ai_setSuspend(0); stand(); } elsif (!$ai_seq_args[0]{'skill_used'}) { $ai_seq_args[0]{'skill_used'} = 1; $ai_seq_args[0]{'ai_skill_use_giveup'}{'time'} = time; if ($ai_seq_args[0]{'skill_use_target_x'} ne "") { sendSkillUseLoc(\$remote_socket, $ai_seq_args[0]{'skill_use_id'}, $ai_seq_args[0]{'skill_use_lv'}, $ai_seq_args[0]{'skill_use_target_x'}, $ai_seq_args[0]{'skill_use_target_y'}); } else { sendSkillUse(\$remote_socket, $ai_seq_args[0]{'skill_use_id'}, $ai_seq_args[0]{'skill_use_lv'}, $ai_seq_args[0]{'skill_use_target'}); } $ai_seq_args[0]{'skill_use_last'} = $chars[$config{'char'}]{'skills'}{$skillsCD_rlut{$ai_seq_args[0]{'skill_use_id'}}}{'time_used'}; } elsif (($ai_seq_args[0]{'skill_use_last'} != $chars[$config{'char'}]{'skills'}{$skillsCD_rlut{$ai_seq_args[0]{'skill_use_id'}}}{'time_used'} || (timeOut(\%{$ai_seq_args[0]{'ai_skill_use_giveup'}}) && (!$chars[$config{'char'}]{'time_cast'} || !$ai_seq_args[0]{'skill_use_maxCastTime'}{'timeout'})) || ($ai_seq_args[0]{'skill_use_maxCastTime'}{'timeout'} && timeOut(\%{$ai_seq_args[0]{'skill_use_maxCastTime'}}))) && timeOut(\%{$ai_seq_args[0]{'skill_use_minCastTime'}})) { &shift_ai_seq(); } } ##### autoEquip_accessory_SKILLS ##### # 解毒使用 if ($autoEquip_accessory_curepoison && $chars[$config{'char'}]{'skills'}{'TF_DETOXIFY'}{'lv'}) { sendSkillUse(\$remote_socket, $skillsCD_lut{'TF_DETOXIFY'}, 1, $accountID); $autoEquip_accessory_curepoison = 0; } # キュアー使用 if ($autoEquip_accessory_cure && $chars[$config{'char'}]{'skills'}{'AL_CURE'}{'lv'}) { sendSkillUse(\$remote_socket, $skillsCD_lut{'AL_CURE'}, 1, $accountID); $autoEquip_accessory_cure = 0; } # ヒール使用 if ($autoEquip_accessory_heal && $chars[$config{'char'}]{'skills'}{'AL_HEAL'}{'lv'}) { sendSkillUse(\$remote_socket, $skillsCD_lut{'AL_HEAL'}, 1, $accountID); $autoEquip_accessory_heal = 0; } ##### AUTO-SIT/SIT/STAND ##### if ($config{'sitAuto_idle'} && ($ai_seq[0] ne "" && $ai_seq[0] ne "follow")) { $timeout{'ai_sit_idle'}{'time'} = time; } if (($ai_seq[0] eq "" || $ai_seq[0] eq "follow") && $config{'sitAuto_idle'} && !$chars[$config{'char'}]{'sitting'} && timeOut(\%{$timeout{'ai_sit_idle'}})) { sit(); } if ($ai_seq[0] eq "sitting" && ($chars[$config{'char'}]{'sitting'} || $chars[$config{'char'}]{'skills'}{'NV_BASIC'}{'lv'} < 3)) { &shift_ai_seq(); $timeout{'ai_sit'}{'time'} -= $timeout{'ai_sit'}{'timeout'}; } elsif ($ai_seq[0] eq "sitting" && !$chars[$config{'char'}]{'sitting'} && timeOut(\%{$timeout{'ai_sit'}}) && timeOut(\%{$timeout{'ai_sit_wait'}})) { sendSit(\$remote_socket); $timeout{'ai_sit'}{'time'} = time; } if ($ai_seq[0] eq "standing" && !$chars[$config{'char'}]{'sitting'} && !$timeout{'ai_stand_wait'}{'time'}) { $timeout{'ai_stand_wait'}{'time'} = time; } elsif ($ai_seq[0] eq "standing" && !$chars[$config{'char'}]{'sitting'} && timeOut(\%{$timeout{'ai_stand_wait'}})) { &shift_ai_seq(); undef $timeout{'ai_stand_wait'}{'time'}; $timeout{'ai_sit'}{'time'} -= $timeout{'ai_sit'}{'timeout'}; } elsif ($ai_seq[0] eq "standing" && $chars[$config{'char'}]{'sitting'} && timeOut(\%{$timeout{'ai_sit'}})) { sendStand(\$remote_socket); $timeout{'ai_sit'}{'time'} = time; } if ($ai_v{'sitAuto_forceStop'} && percent_hp(\%{$chars[$config{'char'}]}) >= $config{'sitAuto_hp_lower'} && percent_sp(\%{$chars[$config{'char'}]}) >= $config{'sitAuto_sp_lower'}) { $ai_v{'sitAuto_forceStop'} = 0; } if (!$ai_v{'sitAuto_forceStop'} && ($ai_seq[0] eq "" || $ai_seq[0] eq "follow" || $ai_seq[0] eq "route" || $ai_seq[0] eq "route_getRoute" || $ai_seq[0] eq "route_getMapRoute") && binFind(\@ai_seq, "attack") eq "" && !ai_getAggressives(1) && percent_weight(\%{$chars[$config{'char'}]}) < 50 && (percent_hp(\%{$chars[$config{'char'}]}) < $config{'sitAuto_hp_lower'} || percent_sp(\%{$chars[$config{'char'}]}) < $config{'sitAuto_sp_lower'})) { unshift @ai_seq, "sitAuto"; unshift @ai_seq_args, {}; print "Auto-sitting\n" if $config{'debug'}; } if ($ai_seq[0] eq "sitAuto" && !$chars[$config{'char'}]{'sitting'} && $chars[$config{'char'}]{'skills'}{'NV_BASIC'}{'lv'} >= 3) { if (!ai_getAggressives(1)) { undef $c_plDist_small; undef $avoid_ID; $judgeFirst = 1; $c_plDist_small = 8; for ($i = 0; $i < @playersID; $i++) { next if ($playersID[$i] eq ""); $c_plDist = distance(\%{$chars[$config{'char'}]{'pos_to'}},\%{$players{$playersID[$i]}{'pos_to'}}); if ($c_plDist < $c_plDist_small) { $c_plDist_small = $c_plDist; $judgeFirst = 0; $avoid_ID=$playersID[$i]; } } if(!$config{'follow'} && $judgeFirst == 0 && $config{'lockMap'} eq $field{'name'}){ if(int(rand(1)+0.5) == 0){ getVector(\%{$ai_v{'temp'}{'vec'}},\%{$chars[$config{'char'}]{'pos_to'}},\%{$players{$avoid_ID}{'pos_to'}}); moveAlongVector(\%{$ai_v{'temp'}{'pos'}}, \%{$players{$avoid_ID}{'pos_to'}}, \%{$ai_v{'temp'}{'vec'}}, 10-$c_plDist_small ); move($ai_v{'temp'}{'pos'}{'x'}, $ai_v{'temp'}{'pos'}{'y'}); }else{ sendTeleport(\$remote_socket, "Random"); } }else{ sit(); } } else { sendTeleport(\$remote_socket, "Random"); PrintMessage("自動テレポート:自動座りモード時に敵に補足されたためテレポートします。", "pink"); } } if ($ai_seq[0] eq "sitAuto" && ($ai_v{'sitAuto_forceStop'} || (percent_hp(\%{$chars[$config{'char'}]}) >= $config{'sitAuto_hp_upper'} && percent_sp(\%{$chars[$config{'char'}]}) >= $config{'sitAuto_sp_upper'}) || (percent_sp(\%{$chars[$config{'char'}]}) > 90 && ($chars[$config{'char'}]{'skills'}{'AL_HEAL'}{'lv'} || $config{'autoEquip_accessory_heal'})))) { &shift_ai_seq(); if (!$config{'sitAuto_idle'} && $chars[$config{'char'}]{'sitting'}) { stand(); } } ##### AUTO-ATTACK ##### AUTOATTACK:{ if (($config{'attackAuto_OnLockMap'} && $chars[$config{'char'}]{'lockMap'} ne $field{'name'}) || !$config{'attackAuto'} || binFind(\@ai_seq, "skill_use") ne "" || ($config{'attackAuto_onlyWhenSafe'} == 1 && binSize(\@playersID)) || ($config{'attackAuto_onlyWhenSafe'} > 1 && ai_getPlayersCount($config{'attackAuto_onlyWhenSafe'})) ) { last AUTOATTACK; } if (binFind(\@ai_seq, "attack") eq "" && ($ai_seq[0] eq "" || $ai_seq[0] eq "move" || $ai_seq[0] eq "route" || $ai_seq[0] eq "route_getRoute" || $ai_seq[0] eq "route_getMapRoute" || $ai_seq[0] eq "follow" || $ai_seq[0] eq "sitAuto" || $ai_seq[0] eq "take" || $ai_seq[0] eq "items_gather" || $ai_seq[0] eq "items_take") && !($config{'itemsTakeAuto'} >= 2 && ($ai_seq[0] eq "take" || $ai_seq[0] eq "items_take")) && !($config{'itemsGatherAuto'} >= 2 && ($ai_seq[0] eq "take" || $ai_seq[0] eq "items_gather")) && timeOut(\%{$timeout{'ai_attack_auto'}}) && $currentChatRoom eq "") { undef @{$ai_v{'ai_attack_agMonsters'}}; undef @{$ai_v{'ai_attack_cleanMonsters'}}; undef @{$ai_v{'ai_attack_partyMonsters'}}; undef $ai_v{'temp'}{'foundID'}; if ($config{'tankMode'}) { undef $ai_v{'temp'}{'found'}; foreach (@playersID) { next if ($_ eq ""); if ($config{'tankModeTarget'} eq $players{$_}{'name'}) { $ai_v{'temp'}{'found'} = 1; last; } } } if (!$config{'tankMode'} || ($config{'tankMode'} && $ai_v{'temp'}{'found'})) { $ai_v{'temp'}{'ai_follow_index'} = binFind(\@ai_seq, "follow"); if ($ai_v{'temp'}{'ai_follow_index'} ne "") { $ai_v{'temp'}{'ai_follow_following'} = $ai_seq_args[$ai_v{'temp'}{'ai_follow_index'}]{'following'}; $ai_v{'temp'}{'ai_follow_ID'} = $ai_seq_args[$ai_v{'temp'}{'ai_follow_index'}]{'ID'}; } else { undef $ai_v{'temp'}{'ai_follow_following'}; } $ai_v{'temp'}{'ai_route_index'} = binFind(\@ai_seq, "route"); if ($ai_v{'temp'}{'ai_route_index'} ne "") { $ai_v{'temp'}{'ai_route_attackOnRoute'} = $ai_seq_args[$ai_v{'temp'}{'ai_route_index'}]{'attackOnRoute'}; } @{$ai_v{'ai_attack_agMonsters'}} = ai_getAggressives() if ($config{'attackAuto'} && !($ai_v{'temp'}{'ai_route_index'} ne "" && !$ai_v{'temp'}{'ai_route_attackOnRoute'})); # 高優先MOBから検索 my $priority = 0; foreach (@monstersID) { next if ($_ eq ""); $priority = $mon_control{lc($monsters{$_}{'name'})}{'priority_target'} if ($priority < $mon_control{lc($monsters{$_}{'name'})}{'priority_target'}); } while(1) { last if ($priority < 0); foreach (@monstersID) { next if ($_ eq ""); if (($mon_control{lc($monsters{$_}{'name'})}{'priority_target'}? $mon_control{lc($monsters{$_}{'name'})}{'priority_target'}: 0) eq $priority && !($config{'attackAuto_OnLockMap'} && $config{'lockMap'} ne $field{'name'}) && $mon_control{lc($monsters{$_}{'name'})}{'priority_target'} != -1) { # MOB無視 if ((($config{'attackAuto_party'} && $ai_seq[0] ne "take" && $ai_seq[0] ne "items_take" && ($monsters{$_}{'dmgToParty'} > 0 || $monsters{$_}{'dmgFromParty'} > 0)) || ($config{'attackAuto_followTarget'} && $ai_v{'temp'}{'ai_follow_following'} && ($monsters{$_}{'dmgToPlayer'}{$ai_v{'temp'}{'ai_follow_ID'}} > 0 || $monsters{$_}{'dmgFromPlayer'}{$ai_v{'temp'}{'ai_follow_ID'}} > 0))) && !($ai_v{'temp'}{'ai_route_index'} ne "" && !$ai_v{'temp'}{'ai_route_attackOnRoute'}) && $monsters{$_}{'attack_failed'} == 0 && ($mon_control{lc($monsters{$_}{'name'})}{'attack_auto'} >= 1 || (!%{$mon_control{lc($monsters{$_}{'name'})}} && $mon_control{'all'}{'attack_auto'} >= 1))) { push @{$ai_v{'ai_attack_partyMonsters'}}, $_; } elsif ($config{'attackAuto'} >= 2 && $ai_seq[0] ne "sitAuto" && $ai_seq[0] ne "take" && $ai_seq[0] ne "items_gather" && $ai_seq[0] ne "items_take" && !($monsters{$_}{'dmgFromYou'} == 0 && ($monsters{$_}{'dmgTo'} > 0 || $monsters{$_}{'dmgFrom'} > 0 || %{$monsters{$_}{'missedFromPlayer'}} || %{$monsters{$_}{'missedToPlayer'}} || %{$monsters{$_}{'castOnByPlayer'}})) && $monsters{$_}{'attack_failed'} == 0 && !($ai_v{'temp'}{'ai_route_index'} ne "" && $ai_v{'temp'}{'ai_route_attackOnRoute'} <= 1) && ($mon_control{lc($monsters{$_}{'name'})}{'attack_auto'} >= 1 || (!%{$mon_control{lc($monsters{$_}{'name'})}} && $mon_control{'all'}{'attack_auto'} >= 1)) && (!$config{'attackAuto_onlyWhenSafe'} || !binSize(\@playersID) || $monsters{$_}{'lastTarget'} eq $accountID) && !ai_getMOBAggressiveCount($_) && (!$monsters{$_}{'lastAttackFrom'} || $monsters{$_}{'lastAttackFrom'} eq $accountID)) { push @{$ai_v{'ai_attack_cleanMonsters'}}, $_; } } } $priority--; } undef $ai_v{'temp'}{'distSmall'}; undef $ai_v{'temp'}{'foundID'}; $ai_v{'temp'}{'first'} = 1; foreach (@{$ai_v{'ai_attack_agMonsters'}}) { next if ($config{'attackAuto_OnLockMap'} && $config{'lockMap'} ne $field{'name'}) || $mon_control{lc($monsters{$_}{'name'})}{'priority_target'} == -1; # MOB無視 $ai_v{'temp'}{'dist'} = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$monsters{$_}{'pos_to'}}); if ($ai_v{'temp'}{'first'} || $ai_v{'temp'}{'dist'} < $ai_v{'temp'}{'distSmall'}) { $ai_v{'temp'}{'distSmall'} = $ai_v{'temp'}{'dist'}; $ai_v{'temp'}{'foundID'} = $_; undef $ai_v{'temp'}{'first'}; } } if (!$ai_v{'temp'}{'foundID'}) { undef $ai_v{'temp'}{'distSmall'}; undef $ai_v{'temp'}{'foundID'}; $ai_v{'temp'}{'first'} = 1; foreach (@{$ai_v{'ai_attack_partyMonsters'}}) { $ai_v{'temp'}{'dist'} = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$monsters{$_}{'pos_to'}}); if ($ai_v{'temp'}{'first'} || $ai_v{'temp'}{'dist'} < $ai_v{'temp'}{'distSmall'}) { $ai_v{'temp'}{'distSmall'} = $ai_v{'temp'}{'dist'}; $ai_v{'temp'}{'foundID'} = $_; undef $ai_v{'temp'}{'first'}; } } } if (!$ai_v{'temp'}{'foundID'}) { undef $ai_v{'temp'}{'distSmall'}; undef $ai_v{'temp'}{'foundID'}; $ai_v{'temp'}{'first'} = 1; $ai_v{'temp'}{'priorityTarget'} = 0; foreach (@{$ai_v{'ai_attack_cleanMonsters'}}) { $ai_v{'temp'}{'dist'} = distance(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$monsters{$_}{'pos_to'}}); undef $ai_v{'temp'}{'reg'}; if ($ai_v{'temp'}{'priorityTarget'} && !$mon_control{lc($monsters{$_}{'name'})}{'priority_target'}) { $ai_v{'temp'}{'reg'} = 0; }elsif (!$ai_v{'temp'}{'priorityTarget'} && $mon_control{lc($monsters{$_}{'name'})}{'priority_target'}) { $ai_v{'temp'}{'priorityTarget'} = 1; $ai_v{'temp'}{'reg'} = 1; }elsif ($ai_v{'temp'}{'first'} || $ai_v{'temp'}{'dist'} < $ai_v{'temp'}{'distSmall'}) { $ai_v{'temp'}{'reg'} = 1; } if ($ai_v{'temp'}{'reg'}) { $ai_v{'temp'}{'distSmall'} = $ai_v{'temp'}{'dist'}; $ai_v{'temp'}{'foundID'} = $_; undef $ai_v{'temp'}{'first'}; } } } } ##### ポータル近くにいるMobは叩かない by butaneko if ($config{'targetting_portal'} == 1 && $ai_v{'temp'}{'foundID'}) { undef $m_plDist; for ($i = 0; $i < @portalsID; $i++) { next if ($portalsID[$i] eq ""); $m_PoDist = distance(\%{$portals{$portalsID[$i]}{'pos'}}, \%{$monsters{$ai_v{'temp'}{'foundID'}}{'pos'}}); if ($m_PoDist <= 6 && $field{'name'} ne $config{'lockMap'} && !$config{'follow'}) { $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; } elsif ($m_PoDist <= 6 && $field{'name'} eq $config{'lockMap'} && !$config{'follow'}) { undef $ai_v{'temp'}{'foundID'}; sendTeleport(\$remote_socket, "Random"); } } } #### きのこは叩かない if ($config{'targetting_kinoko'} == 1 && $ai_v{'temp'}{'foundID'}) { foreach (@kinoko) { if ($_ eq $monsters{$ai_v{'temp'}{'foundID'}}{'name'}) { $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; last; } } } #### 多重に被ったのは破棄して叩かない if ($config{'targetting_multiple'} == 1 && $ai_v{'temp'}{'foundID'} && $count_error >10) { undef $ai_v{'temp'}{'foundID'}; undef $count_error; initMapChangeVars(); &undef_ai_seq(); PrintMessage("[Rep] スタックッぽいので飛びます\n", "def"); sendTeleport(\$remote_socket, "Random"); } #### 状態異常MOB対策(packet0119関係) if ($config{'targetting'} && $ai_v{'temp'}{'foundID'} && binSize(\@playersID) && ($monsters{$ai_v{'temp'}{'foundID'}}{'param1'} || $monsters{$ai_v{'temp'}{'foundID'}}{'param2'})) { if ($config{'targetting_any'} ||($config{'targetting_stoned'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param1'} == 1) ||($config{'targetting_iced'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param1'} == 2) ||($config{'targetting_stan'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param1'} == 3) ||($config{'targetting_sleeping'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param1'} == 4) ||($config{'targetting_ankoku'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param1'} == 6) ||($config{'targetting_doku'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param2'} & 0x0001) ||($config{'targetting_cursed'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param2'} & 0x0002) ||($config{'targetting_silent'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param2'} & 0x0004) ||($config{'targetting_anten'} && $monsters{$ai_v{'temp'}{'foundID'}}{'param2'} & 0x0010)) { $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; } } # 地面系スキルに近い敵は無視 if ($config{'targetting'} && $ai_v{'temp'}{'foundID'} && $config{'targetting_firewall'}) { foreach (@spellsID) { next if ($spells{$_}{'type'} ne 0x7F ); if ( %{$players{$spells{$_}{'sourceID'}}} && distance(\%{$spells{$_}{'pos'}}, \%{$monsters{$ai_v{'temp'}{'foundID'}}{'pos_to'}}) < 4 ) { PrintMessage("$monsters{$ai_v{'temp'}{'foundID'}}{'name'} ($monsters{$ai_v{'temp'}{'foundID'}}{'binID'})はファイアーウォールに近いため無視します。\n", "monlost"); $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; last; } } } if ($config{'targetting'} && $ai_v{'temp'}{'foundID'} && $config{'targetting_numa'}) { foreach (@spellsID) { next if ($spells{$_}{'type'} ne 0x85 ); if ( %{$players{$spells{$_}{'sourceID'}}} && distance(\%{$spells{$_}{'pos'}}, \%{$monsters{$ai_v{'temp'}{'foundID'}}{'pos_to'}}) < 2 ) { PrintMessage("$monsters{$ai_v{'temp'}{'foundID'}}{'name'} ($monsters{$ai_v{'temp'}{'foundID'}}{'binID'})はニューマに近いため無視します。\n", "monlost"); $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; last; } } } if ($config{'targetting'} && $ai_v{'temp'}{'foundID'} && $config{'targetting_ankle'}) { foreach (@spellsID) { next if ($spells{$_}{'type'} ne 0x91 ); if ( %{$players{$spells{$_}{'sourceID'}}} && distance(\%{$spells{$_}{'pos'}}, \%{$monsters{$ai_v{'temp'}{'foundID'}}{'pos_to'}}) < 2 ) { PrintMessage("$monsters{$ai_v{'temp'}{'foundID'}}{'name'} ($monsters{$ai_v{'temp'}{'foundID'}}{'binID'})はアンクルに近いため無視します。\n", "monlost"); $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); undef $ai_v{'temp'}{'foundID'}; last; } } } if ($ai_v{'temp'}{'foundID'} && findWall(\%{$chars[$config{'char'}]{'pos_to'}}, \%{$monsters{$ai_v{'temp'}{'foundID'}}{'pos_to'}})) { if (!$monsters{$ai_v{'temp'}{'foundID'}}{'target_start'}) { $monsters{$ai_v{'temp'}{'foundID'}}{'target_start'} = time; } elsif (timeOut($monsters{$ai_v{'temp'}{'foundID'}}{'target_start'}, $timeout{'ai_attack_target_giveup'}{'timeout'})) { PrintMessage("$monsters{$ai_v{'temp'}{'foundID'}}{'name'} ($monsters{$ai_v{'temp'}{'foundID'}}{'binID'})は壁の向こう側なので破棄します。\n", "monlost"); $monsters{$ai_v{'temp'}{'foundID'}}{'attack_failed'}++ if (%{$monsters{$ai_v{'temp'}{'foundID'}}}); } undef $ai_v{'temp'}{'foundID'}; } if ($ai_v{'temp'}{'foundID'}) { ai_setSuspend(0); attack($ai_v{'temp'}{'foundID'}); } else { $timeout{'ai_attack_auto'}{'time'} = time(); } } } ##### ATTACK ##### ATTACK: { if ($ai_seq[0] eq "attack" && $ai_seq_args[0]{'suspended'}) { $ai_seq_args[0]{'ai_attack_giveup'}{'time'} += time - $ai_seq_args[0]{'suspended'}; undef $ai_