カテゴリ:kore( 8 )

自動演説。。

----
メッセアド取得しておきました。
chronoship@hotmail.co.jp
----

明日は秋分の日ですね(もう今日だけど)。
休みの前ということで久々に長々と記事を書いていきましょう。

っとその前に、今までの記事を自分で見てみたのですが、なぜか書くごとに言葉が硬くなっている・・・
そういうわけでちょっとラフに書いていこうと思っています。

え~~と今まで窓手の稼ぎ利用とか窓手に関することを主として書いたわけですがまぁ久々にまったく違うネタっぽいものについて書きます。

そーいえば選挙終わりましたね(遅)
暑い中みなさん自分の主張を選挙カーの上で必死になって演説していました。
私も暑いなかぼーっと立ちながら聞いていました^^;

っとそこでひらめきます。
BOTを使って演説って出来るよなーと。
今までにもこういう演説はありました↓。

???? : みなさ~ん!私はBOTですよ~~!!

しかし、これは発言する文章を弄れません。。
まぁ「罠」なので発言者にも見えないわけですが^^;

では、内容を自由に設定できて自動で発言してくれる機能があればなにかと面白いんじゃない?と。

例えばイベントの案内をチャットで立てておくより発言を繰り返してれば効果絶大です。
また、「勉強会」や「未成年の主張」「演説」なんてのも簡単にできます。
逆に!狩りBOTに搭載して「通報しないで~~;;お願いT-T」とか発言させまくったりも出来ますw

というわけで早速作ってみたわけですがちょっとコード長いので分割して説明っ
まず発言したいと思った内容をauto_mes.txtに記述します。
e0056993_045315.jpg


そしてkore.plと同じ場所におきましょう↓。
e0056993_0463749.jpg


次に自動発言を発動させるフラグを立てなければいけないのでスイッチを作ります。

} elsif ($switch eq "automes") {
$Auto_Mes = 1;

$switch eq "a" とかの上でもいいので入れておきます。
次に以下のコードを追加していきます。

#$Auto_MesがONで$AutoMesFlagがカラの場合if分の内容を実行します。
if ($Auto_Mes && !$AutoMesFlag){
#txtファイルを開いて上から一文づつ取り出します。
おーぷん (INFO,"auto_mes.txt");
while () {
#一フレーズの文字数が半角81文字以上であれば分割します。
80文字以下ならそのままにして配列@auto_mesに押し込みます。

for ($len_mes = 0; length > 80;){
push @auto_mes, substr($_,$len_mes,80,"");
}
if (length $_ <= 80){
push @auto_mes, $_;
}
}
close (INFO);
#chomp関数は文字列の最後に改行があった場合、改行を消します。
chomp @auto_mes;
#次の条件に入るため、$AutoMesFlagを1にします。
$AutoMesFlag = 1;
$AMC = 0;

え~英語のおーぷんは使えないので日本語で書いてます。
まずここでtxtファイルに書かれている文章を読み込み、半角81文字以上は一度に発言できなかったと思うので分割して、配列に次々にフレーズを押し込んでいます。
読み込むtxtファイルに横一列で記入したとしてもここで分割されますが、発言が汚く見えるので注意^^;
最後に$AutoMesFlagを1にしていますが、これで次のステップへ進みます。

#$AutoMesFlagが1だったらif分の内容を実行します。
} elsif ($Auto_Mes && $AutoMesFlag == 1 && $AutoChatTime+$Mes_Time < time){
#発言間隔時間の計算をしています。詳しくは下で。
$Mes_Time = ((length $auto_mes[$AMC]) * $config{'AutoMes_CH_Time'}) / 2 + $config{'AutoMes_ST_Time'};
#次の条件に入るため、$AutoMesFlagを2にします。
$AutoMesFlag = 2;
#現在時間を代入。
$AutoChatTime = time;

ここで発言間隔時間を計算します。
最後に$AutoMesFlagを2にしていますが、これで次のステップへ進みます。

#$AutoMesFlagが2だったらif分の内容を実行します。
} elsif ($Auto_Mes && $AutoMesFlag == 2 && $AutoChatTime+$Mes_Time < time){
#フレーズをオープンで発言します。Pチャは「p」ギルチャは「g」だったかな。
sendMessage(\$remote_socket, "c", "$auto_mes[$AMC]");
#次のフレーズを選択します。つまり配列の何番目っていうのを+1して次の文を発言する為です。
$AMC++;
#次のフレーズの発言間隔時間を取得する為、一つ前のif文に入るよう$AutoMesFlagを1にします。
$AutoMesFlag = 1;
$AutoChatTime = time;

ここでフレーズを発言します。
そして最後に発言している文章が尽きた場合の処理を書きます。

#空白が6行以上連続で続いた場合、一文章終わりとみなします。
if (!$auto_mes[$AMC]){
$end_c++;
if ($end_c > 5 && $config{'AutoMes_TimesMax'}){
$config{'AutoMes_TimesMax'}--;
$AMC = 0;
print "繰り返し発言します。。\n";
} elsif ($end_c > 5 && !$config{'AutoMes_TimesMax'}){
undef $AutoMesFlag;
undef $Auto_Mes;
print "発言を終了します。。\n";
}
} else {
undef $end_c;
}
}

文章の途中でこの場合6行以上空白であけると発言終了するので注意。

そしてconfig.txtに以下を追加。

[config.txt]

#発言間隔時間の基本時間
AutoMes_ST_Time 0.2

#発言間隔時間の全角1文字に対するウェイト時間
AutoMes_CH_Time 0.1

#発言を繰り返す回数。
AutoMes_TimesMax 0

ふぅ~まぁこのようになりますね。

ここで発言間隔時間について説明をしときます。
e0056993_0502632.gif
AutoMes_ST_Timeが0.2でAutoMes_CH_Timeが0.1の場合、左の図のような発言間隔時間になります。
AutoMes_ST_Timeはすべてのフレーズの前後につき、空白フレーズがあったとしても前後0.2秒をカウントします。
AutoMes_CH_Time全角一文字を発言するのに掛かる時間を表しています。
例えば左図のように「こんにちはみなさん。」だと全角10文字なので、0.1秒 ×10 = 1秒となるわけです。
この両方の時間を足した時間が一フレーズを発言するのに要する時間となります。
これが連なるわけですから、左図の2つのフレーズの間隔は合計2.1秒となります。


なぜこのようにしているのかというと、文字を入力する手間は文字が多いほど時間が掛かるというのと長い文章ほどすべて読む時間が長くなるという肉入りでの都合という点から設定できるようにしています。
そういうわけで両方の数値を0にしてしまうとおっそろしく速いスピードでしゃべりまくりますw

今回は↑のをコピペしてというのは面倒だと思うのでtxtをあぷろだに上げておきました。

http://sackbut.or.tp/~tadabot/img/753.txt

コードのほうは#DEBUG CODEの上あたりで良いでしょう。

とまぁこのようにして↑の文章を発言させるとこのようになります。
DOS画面で「automes」と入力することで発動します!
e0056993_0514542.jpg


WaitTimeは文字数に対する待ち時間です。
わかりやすくする為に表示しているだけです。
また、全角40文字以上のフレーズは強制的に分けていますね。
ま~ネタですがなにかと使えるかも!?!?

あ~あとメッセのアドについてなのですが現在登録してません。
今度とったら載せておきますので登録したい方はお願いします。

[PR]
by chronoship | 2005-09-23 01:13 | kore

重要アイテムを取り返せ!

前回窓手BOTの稼ぎ利用について説明しました。
その中で弓BOTの1つの弱点として、ルートモンスターにアイテムをルートされやすいという点を挙げました。

窓手BOTの性質上おいしそうな狩場にはルートモンスターが配置されています。
ルートモンスターにアイテムをルートされるのを恐れてルートモンスターを叩く設定にしていると、
本命の敵の殲滅数が落ち込みます。
そこで、重要アイテムをルートされたらルートモンスターを倒してくれるコードはないのか?と思いkoreの中を探してみました。

if ($mDist < $config{'distImportantItem'} && binFind(\@root_monsters, $monsters{$_}{'name'}) ne "" && $monsters{$_}{'dmgFrom'} == 0 && $monsters{$_}{'dmgTo'} == 0) {
print "*** 重要アイテム ($items_old{$ID}{'name'}) をルートされますた ***\n";
push @{$ai_v{'ai_attack_cleanMonsters'}}, $_;
}

00A1パケ受信部にこのような箇所がありました。
このコードは、重要アイテムが消えた時、重要アイテム検知距離以内にroot_monsters.txtに記述したモンスターが放浪していた時、そのモンスターを攻撃対象にするという意味です。
しかし、これで動くのかなと思ってたのですが動きません。。
なぜ動かないのか?と思い調べてみると、、AUTO-ATTACKの部分でリセットされています。
ではどのようにすれば動くのか?そこでkoreをいじいじしてみました。

まず、誤作動を防ぐために00A1パケのif文に$flagImportantItemsModeを条件に加えます(赤い部分が追加箇所)。

if ($config{'itemsImportantAuto'} && $flagImportantItemsMode && $iDist < $config{'distImportantItem'} && binFind(\@itemsID_take, $ID) eq "") {

次にその下のpush @{$ai_v{'ai_attack_cleanMonsters'}}, $_;を↓に置換します。

$old_teleport_search = $mon_control{$monsters{$_}{'name'}}{'teleport_search'};
$mon_control{$monsters{$_}{'name'}}{'teleport_search'} = 1;
$mon_control{$monsters{$_}{'name'}}{'root_monsters'} = 1;

ルートしたMOBのsearchフラグを一応控えておき、強制的に1にします。
なぜかこうしないとすぐ飛んでしまったので・・・
無くても動くのですが念のため。。

そしてAUTO-ATTACKの

&& ($mon_control{lc($monsters{$_}{'name'})}{'attack_auto'} >= 1)) {
push @{$ai_v{'ai_attack_cleanMonsters'}}, $_;

を↓に置換します。

&& ($mon_control{lc($monsters{$_}{'name'})}{'attack_auto'} >= 1)
|| ($mon_control{lc($monsters{$_}{'name'})}{'root_monsters'})) {
push @{$ai_v{'ai_attack_cleanMonsters'}}, $_;
if ($mon_control{lc($monsters{$_}{'name'})}{'root_monsters'}){
$mon_control{$monsters{$_}{'name'}}{'teleport_search'} = $old_teleport_search;
undef $mon_control{lc($monsters{$_}{'name'})}{'root_monsters'};
}

アイテムをルートしたと思われるモンスターがいた場合、攻撃対象に加えます。
最後に、重要アイテムを無理やり拾うようにする為にお好みで↓のように変更します(赤い部分が追加箇所)。

print "攻撃されますた: $monsters{$ID1}{'name'} ($monsters{$ID1}{'binID'}) - ダメージ: $dmgdisplay\n";
if(!$flagImportantItemsMode && ($config{'teleportAuto_Attack'}) && ($damage>($config{'teleportAuto_Attack_Dmg'}))) {

強いアクティブMOBがいる場合は死ぬかもしれないので要注意^^;
スキル攻撃も変えたい人は同様に。

このようにコードを変更します。
他のkoreにはこの機能あるのかもしれませんがとりあえず、、ね。


e0056993_20584343.jpg
私は変更完了し、試しにエルダ森にて動作を確認してみました。
動作確認の為エルダの落とすアイテムすべてを重要アイテム指定にしています^^;
mon_control.txtでポポリンは0 0 0になっていますが、重要アイテムをルートされた疑いがある場合このように攻撃して古木の露を取り返します^^;


現在のROの仕様上koreでは重要アイテムをどのルートモンスターが食べたか知ることは出来ません。
その為確率的にルートしたと思われるモンスターを攻撃するようにしています。
つまり確実に重要アイテムを取り返せるという保障はありません。

また、窓手BOTの場合「攻撃がHITしたら飛ぶ」というのが基本なので重要アイテム発見の直前に攻撃を受けた場合、飛んでしまうという厄介な性質があります。
ここは修正無理そうなので仕様として諦めよう。。
[PR]
by chronoship | 2005-09-08 21:04 | kore

窓手マップへの道のり・・・

みなさん窓手マップへの移動はどのようにしてますでしょうか?
窓手が生息するgl_sew03以降への道のりは果てしなく遠くなっています。
肉入りで窓手へ弓手を運ぶのもバードダンサー等では大変ですし、矢筒が無くなる度に行っていては手間がかかって大変です。

そこでkoreには自動で狩場まで向かってくれる機能の他にマップ毎にポータルの近くまで蝿パケで飛んでくれるという「狩場までランテレ機能」が備わっています。
この機能を使えば肉入りでミルクや蝿を持ち敵に怯えながら向かうよりも安全に窓手マップまで行くことが出来ます。
しかし、この機能にも欠点があります。

まず第一にポータルへ最短で向かうというBOT特有の特徴の為、途中にいるMOBを避けてくれないという問題があります。
肉入りでは機敏に避けることが可能ですが、BOTではそのまま突っ込み被弾すれば飛んでしまうことになります。
かといって、無理に進むように設定すれば防御力もない職はすぐに成仏します。
そのため、ポータル前の通路にMOBが立ちふさがっていると運が悪ければ延々通ることが出来ないという状況が出来上がります。

第二にポータルまでのルート計算が遅いという欠点があります。
現在窓手koreに備わっている(というかすべてのkore)「狩場までのランテレ」機能は目的のポータルまで何セルか?を計算し、
そのセル数がteleportAuto_distanceで設定した数字よりも小さい場合普通にポータルまで歩くというものです。
このセル数計算がポータルまでの距離の遠さに比例して処理が遅くなります。
例えば、gl_sew02で最も左下に降り立ってしまった場合セル数が1000を超えるため次のランテレまで時間が掛かりすぎるということです。

このようにBOTによる移動は二つの欠点を抱えています。
第一の欠点はどうしようもないとして、第二の欠点は直すことが可能です。
自分のいる座標はマップチェンジの度にすぐ更新され情報を取得することが出来ます。
「狩場までのランテレ機能」はセル数を計算していますが、このセル数を計算しないでポータルの座標と、自分の居る座標を見比べてみれば高速移動が出来るのではないか?
そのように考えてコードを作ってみました。
#↓はkore.plの最後に追加。

sub route_mado {
$i = 0;
#↓configのRoute_mado_0から情報を順次取り出す。
while (1) {
#↓もし情報がなくなればループから抜け出す。
last if (!$config{"Route_mado_$i"});
#↓情報を分割し配列に代入する。
@route_mado = split(/\,/,$config{"Route_mado_$i"});
#↓移動途中のマップで、ポータルまでの距離が近ければ止まり、遠ければもっかい飛ぶ。
if ($route_mado[0] eq "$field{'name'}"){
if (abs($chars[$config{'char'}]{'pos'}{'x'} - $route_mado[3]) < $route_mado[1] && abs($chars[$config{'char'}]{'pos'}{'y'} - $route_mado[4]) < $route_mado[2]){
print "★ポータルの近くに出現しました。\n";
} else {
sendTeleport(\$remote_socket, "Random");
}
}
$i++;
}
undef @route_mado;
}

※動作確認は2,3回...

そして、このサブルーチン「route_mado();」を0091パケと0092パケ受信部の最後に置きます。
0092へ置く場合はその前に「sleep(2);」を入れないと動作しないかも・・・。

このサブルーチン「route_mado();」を0091パケの最後に置きます。
0092パケの最後には、

$route_mado_time = time;
$route_mado_frag = 1;

#DEBUG CODEの上には、

#↓マップサーバー移動をしたら5秒後に1回飛ぶ。
if ($route_mado_frag && $route_mado_time+5 < time){
useTeleport(1);
undef $route_mado_frag;
}

を、置きます。

そしてconfigの設定は、

#窓マップまでの移動指定
Route_mado_0 gef_fild04,70,60,16,309

となります。


e0056993_1565838.jpg
上記の設定はgef_fild04の場合、gef_fild05へ繋がるポータル16,309からの距離がX座標70セル以内、Y座標60セル以内になるまで飛ぶという設定で、画像の赤い範囲に着地するまで飛びます。


さらにRoute_mado_ の 0 を増やしていくことで複数のマップを指定します。
たとえば、

#窓マップまでの移動指定
Route_mado_0 gef_fild04,70,70,16,309
Route_mado_1 gef_fild05,80,40,15,201
Route_mado_2 gef_fild06,70,45,18,304
Route_mado_3 glast_01,80,40,200,137
Route_mado_4 gl_church,40,75,301,46
Route_mado_5 gl_chyard,45,30,12,149
Route_mado_6 gl_sew02,28,60,299,294

このようになります。

移動方法はゲフェ北→猫マップ→龍マップ→GH→修道院→カタコンベ→鰐下水というルートを表しています。


e0056993_1593024.jpg
GHの場合は修道院への入り口のポータル200,137からX座標80以内、Y座標40以内なので大体画像の赤い範囲に来るまで飛び続けます。


最下層へ行く場合はさらに追加する必要がありますね。

また、これを利用する場合teleportAuto_lockMapを0ついでにviewMapInfoを0にしておくと良いかもです。

しかしここで一つ問題が・・・
ルート計算上の次のポータルをどこで指定しているのかわからなかった為、configで無理やり指定しています;;
だれか教えてくれれば。。と期待してるばかりです。。
その為、ルート計算上のルートとconfigの設定を一致させる必要があります。
portals.txtで該当箇所をいじりルートを絞るのが良いでしょう。
たとえば通りたくないポータルは#を使いコメントアウトする等です。
これでルートの制御が行えます。

これを導入すると窓手をハエパケで狩るくらいのスピードでポータルまでのランテレが行えます。
MOBに攻撃されて飛んだとしてもすぐにポータルの近くまで戻ることも可能です。

最後に、このようにBOTによる移動はやはり第一の問題がついて回ります。
よって移動するマップはMOBの回転率が良いマップを通ることをお勧めします。
まぁつまり狩りBOTの多いマップを通れということです^^;
[PR]
by chronoship | 2005-08-31 02:11 | kore

パケット受信部?

koreのDOS画面には様々な情報が表示されますね。
ではどうやってそのような情報を認識しているのでしょうか?

ROはクライアントとサーバーで情報のやりとりをしています。
たとえば座るという動作は・・・

ROクライアントでinseatボタンを押す

サーバーに「座る」という情報を渡す

サーバーがROクライアントに「座れ」という情報を渡す

kore

サーバーから「座れ」という情報がクライアントに伝わり、キャラが座る

まぁこのような流れになっています。
koreは青文字の部分にちょっとお邪魔しています。
そこで、koreはパケットの情報を解析しDOS画面にどのような情報だったのかを表示しようとします。

ではどこでそのような処理をしているのか?
kore.plは「sub parseMsg」というセッションでパケットを解析しています。

たとえばこれ↓
e0056993_22135060.jpg



アイテムを使用したというサーバーからの応答情報です。
隠してある部分は使用キャラのIDです。
サーバーからの情報はすべてバイナリ構造体(16進数)で表されています。
下の数字はわかり易いように番号を振りました。
「アイテムを使った」というのは画像を見てわかるように01C8パケでkore.pl内部↓にあたります。

} elsif ($switch eq "01C8") {
# アイテム使用
$index = unpack("S1",substr($msg, 2, 2)); #使用したアイテムの位置みたいなもの
$ID = unpack("S1", substr($msg, 4, 2)); #使用したアイテムのID
$sourceID = substr($msg, 6, 4); #使用キャラのID
$amountleft = unpack("S1",substr($msg, 10, 2)); #使用したアイテムの残り個数
この部分でこのパケを解析しています。

「substr」関数は部分文字列を取り出す時に使い、「unpack」関数はバイナリ構造体をリスト値に展開します。
たとえば使用したアイテムのIDの場合、4行目から2つ情報を取り出します。
つまり上の画像の「07 02」を取り出します。
そしてこれを型指定子「S1」に従ってリスト値に展開します。
「07 02」は16進数で「207」であり、これを10進数に直すと「519」になります。
「519」とはどんなアイテムなのか・・そこでkore.plではこのようなIDを識別するために「table」フォルダに情報を入れています。
koreは「table」フォルダにある「item.txt」を参照し一体なんのアイテムなのかを識別します。
e0056993_2274224.jpg






「519」は「ミルク」ですね。

画像の12番目はたぶん使用個数を表しているのでこれの解析結果は、

$sourceIDのキャラがミルクを1個使用した。

というようになります。
kore.plでは、

print "アイテムを使用しました: $display x $amount\n";

となり、DOS画面には

アイテムを使用しました: ミルク x 1

と表示されます。
koreはこのように情報を其のつど解析していますが、まれにkoreがわからないパケットを受信してしまうこともあります。
このようなパケはみなさんよく見るアレ「未解析パケを受信しました」と言われ、dumpデータを吐きます。

とりあえずこのような感じですね。
たぶんあってるとは思いますが間違ってたら指摘よろです。はい。
[PR]
by chronoship | 2005-08-26 22:18 | kore

GvG結果を集計しよう。

BOTとして優秀なモノの1つ、それはログ取り。
RO内で自分に与えられる情報ならなんでも取得し整理することが出来ます。
そこでBOTの一つの利用方法としてGvG結果のログ取りがあります。
最近ではどのサーバーの掲示板でもBOTのログをそのまま貼り出す方が増えて来ました。
ではもっと整理して一早く情報を貼り出せたらどうでしょうか。

みなさんご存知のように天の声は「GMMessage.txt」に貼り出されます。
例えば↓のようになります。

[Aug 21 21:45:08 2005][S][prt_fild05] 砦 [Valkyrie Realms 1]を [Sky Blue] ギルドが占領しました

「整理」する為にはここから最低「時間」「砦名」「ギルド名」を取り出す必要があります。
よってログに残すものを最低限まで削ったほうが良いことになります。
削ってもよさそうな部分は・・月と日付と場所とメッセージ分類の[S]ぐらいでしょう。

そこでkore.plをいじります。
まずchatlogルーチンのgetFormattedDateへ渡す引数を、

("",int(time))

("$type",int(time))

に変更します。
そして、getFormattedDateルーチンの、

if ($type eq "s" && $localtime[2] == 9 && $localtime[1] > 0){
return;
}
を削除・・?まぁ使われてないので消しても良いみたい。メンテのなにか?
そして、↓を

$$r_date = "$themonth $localtime[3] $localtime[2]:$localtime[1]:$localtime[0] " . ($localtime[5] + 1900);

if ($type eq "s"){
$$r_date = "$localtime[2]:$localtime[1]:$localtime[0]";
} else {
$$r_date = "$themonth $localtime[3] $localtime[2]:$localtime[1]:$localtime[0] " . ($localtime[5] + 1900);
}

のように変更します。
そうすると「GMMessage.txt」へ書き込む場合、

[21:45:08] 砦 [Valkyrie Realms 1]を [Sky Blue] ギルドが占領しました

のようにスッキリします。

そして次にこのログを整理するプログラムを作る必要があります。まぁkore内部でやっても良いのですがもう1つplファイルを作ります。↓
e0056993_18495545.jpg






内部はこのようになっています。↓

#↓GMMessage.txt読み込み。
おーぷん (INFO,"GMMessage.txt");
while () {
#↓砦ログを一文づつ取り出し、「時間」「砦」「ギルド」に分割しデータを収集する。
if (/(\d\d\:\d\d\:\d\d)\]\s砦\s\[([a-zA-Z-]{5,}\s[a-zA-Z]{5,}\s[1-5])\]を\s\[([^\]]*)/){
$castle{$2} = "$3"; #現在の砦取得ギルド更新
$castle{$2}{'count'}++; #砦落城回数更新
$guild{$3}++; #ギルド別砦取得回数更新
}
}
close (INFO);
#↓砦の順番を整理。
@castle = sort keys %castle;
#↓砦取得回数の多いギルドが上に来るように整理。
@guild = sort{$guild{$b} <=> $guild{$a}} keys %guild;
#↓gvg_result.txtに集計結果を書き込む。
#同一フォルダに「gvg_result.txt」が出来ます。

おーぷん (INFO,">gvg_result.txt");
print INFO "[最終確保ギルド(落城回数)]\n";
foreach (@castle){
print INFO "$_ ★ $castle{$_} $castle{$_}{'count'}回落城\n";
}
print INFO "[砦別取得回数]\n";
foreach (@guild){
print INFO "$_ ★ $guild{$_}回\n";
}
close (INFO);

かなり汚い、、特に正規表現は最近手を出したのでぐちゃぐちゃです。
抽出できればOKみたいな?
抽出したデータは$1=時間 $2=砦 $3=ギルドとなります。
今回は時間データを利用していません。遅延防衛や最初に取得しているギルドも考慮にいれないといけなくなるので。途中青文字の「おーぷん」というのがありますが、実際には「open」です・・・セキュリティ上このブログでは使用不可のようで(´Д`;

これの実行結果が↓
e0056993_18502559.jpg


























ギルド名は灰色で隠してあります。

おっと、[砦別取得回数]じゃなくて[ギルド別取得回数]です。
つまりレース状況。
このようにBOTを使えば攻城戦終了1分後に集計結果を掲示板等に貼り付けることが出来ます( ´ー`)
ただし注意が1つ。
これは落城ログから作成するもので、最初に砦を取得していたギルドを考慮にいれていません
よって、1回も落城しなかった砦の部分はデータが抜け落ちます。
抜け落ちていたらその砦の1週間前の情報をコピペすればOKでしょう。
ちなみに動作確認は1回のみ・・はてさて。
[PR]
by chronoship | 2005-08-25 19:11 | kore

手動マニピコードとはなんぞや

前回は罠について書きましたが今回は窓手の話も含めてタイトルのモノについて説明していきたいと思います。

現在ステルスあげが主流となっていますがみなさん経験値効率はどれほど出ているでしょうか?

私は窓手兄者koreを使用する前、というかステルス公平を知った直後は通常のkoreをいじり、様々な場所でステルス用キャラを放っていました。
最初はローグで公平を行い、人避けでなるべく人が居ない場所(gl_sew02)等でチマチマ狩をしていました。
経験値効率は約700K~800Kで、Lv90にするまでも相当キツキツでした。

これじゃ埒(らち)があかないということで、弓手に手を出してみてびっくり、
亀島でも1.4M 窓手に至っては1.6Mも出るじゃないかとはしゃいでいました。

その後ローグ2人が永眠され、弓手一本へと絞ることが出来ました。
そして、窓手でチマチマ狩っている時、らぐろだに「窓手兄者kore」がUPされ罠に怯えながらも試してみたいと思い使ってみると・・・時給2.3Mでるじゃないですか。

目が点になりました。

その後、兄者koreを使い弓手をINT90 DEX140 窓約2確殺までひっぱっていくと時給3Mを超えました。公平で時給1.5Mです。

当分はこの状態で満足し、快適なステルスライフを送っておりました。
このように1人のんきに過ごしていたわけですが、8月6日愛読していたBOTNEWSに次の記事が載ります。

>窓手で時給6.5Mとかワロスwwwどんな過疎鯖だよwww
>4秒ごとに座るコード追加してSP補給しても、
>窓手を独占できる数に限界があるんだから効率は頭打ちだろ^^


Σ(゚Д゚;=;゚Д゚)
これはすごいと思い、早速perlと睨(にら)めっこしてみました。
ちなみに↑の時給6.5Mというのは2倍期間に計測したものらしいです。

SP自然回復時間はみなさんわかっていると思いますが棒立ち状態で8秒に1回、座り状態で4秒に1回、座りマニピで2秒に1回回復となります。

しかしここが重力仕様と言いますか、立っている状態でSPが回復した時点から4秒~8秒の間に座ると、その時点でSPが回復します。

最近巷で騒がれている「手動マニピコード」はこれを利用しています。
最後のSP回復から約4秒後に一瞬でも座れたら・・・立ち状態でプリのスキル「マグニフィカート」を貰っている状態とほぼ同じになり、SPを消費したDS(ダブルストレイフィング)で攻撃する弓手にとっては効率の格段UPに繋がります。

では一体どのようなコードなのか?(ここは自作なのでしょぼいです)

4秒に1回座ると書いてありますが、ただ単に4秒に1回座れば良いというものではありません。
4秒に1回回復するのはサーバー時間であり、こちらで4秒きっかり数えて必ずしも一致するものではありません。
ではどのようにしてそのタイミングを見計らうか?
それは最後にSPが回復した時点から4秒数えることが必要となります。
そこで次のコード↓

#変数「$val」には現在のSP量が入っています。

#↓現在のSP量から前回のSP量を引く。$r_spにSPの増減値が入る。
$r_sp = $val - $old_sp;
#↓この条件分岐は前回のSP量より現在のSP量が多い場合、そして
#SP増加値が3以外(SPR回避)の場合真となる。

if ($old_sp < $val && $r_sp != 3){
#↓前回の回復時間からの経過時間を$old_sp_time変数に代入。
$old_sp_time = time - $sp_time;
#↓現在の時間を$sp_time変数に代入。
$sp_time = time;
#↓後程解説
undef $sp_frag;
#↓前回の回復から5秒以内であれば真。
if ($old_sp_time < 5){
$sp_com = "成功"; #$sp_com変数に「成功」を代入。
$sp_suc++; #$sp_suc変数に数字を+1する。
#↓上の条件が偽の場合(5秒以上の場合)$sp_com変数に「失敗」を代入。

} else {
$sp_com = "失敗";
}
$sp_all++; #SP回復回数を+1させる。
print "★SP回復$sp_com ($sp_suc / $sp_all\)\n"; #DOS画面に結果表示
}
$old_sp = $val; #$old_sp変数に現在のSP量を代入。

このコードをSP値更新受信部に挿入します。
print部分にある($sp_suc / $sp_all\)についてですが、
これはSP回復を5秒以内に出来たのは何回か?を表示しています。
つまり手動マニピの成功率で、大体95%ぐらいいきます。
このコードによりSPの更新時間を取得し、座るタイミングの土台を作ります。
よってこれだけでは動きません。
次のコードを動作する任意の場所に追加↓

#↓SP回復時間から4秒経過し、尚且つ$sp_frag変数が偽の時、フィールドネームがロックマップと同じ場合座る。
if ($sp_time+4 < time && !$sp_frag && $field{'name'} eq "$config{'lockMap'}"){
sendSit(\$remote_socket);
$sp_frag = 1; #このコードをループさせない為に$sp_frag変数を真にする。
}

$sp_frag変数をここで真にし、SP自然回復が行われた部分で未定義値に戻しています。
ここで疑問に思うのが何故座った後立たないのか?という所です。
BOTの性質上常にハエパケを使い行動します。
ハエパケは座っていても可能であり、座った直後にハエパケで飛ぶと立った状態になります。
また、koreの内部で大体のモノは立った後攻撃するように攻撃前にsendStandを実行しています。
この為座るだけでもOKということなのです。

とりあえず手動マニピはこの程度でも動作します。
しかし、手動マニピを行ったといっても設定がしょぼければ意味ありません。
そこでtimeouts.txtをいじる必要があります。

これは個人個人で設定が違うと思いますので説明しませんがとにかく切り詰めればOKですね。

さて、この座りコードを入れて私も窓手BOTを動かしてみるとBOTNEWS様に書いてある通り約1.5倍に経験値効率が跳ね上がりました↓
e0056993_20341129.jpg







公平無しでこの時給を11時間維持、、(´Д`;もう言葉もありませんでした。
1日でLv98からLv99になれる効率です。
普通のBOTでも使えると思うけど、移動して敵に近づく職では微妙かもしれません。

ここまでうまくなるとやはりなかなか下水からは抜けられませんね。
ご利用は計画的に~だね。
[PR]
by chronoship | 2005-08-24 20:44 | kore

窓手koreの・・・罠

最近巷で流行っている「窓手兄者kore」

なぜ流行っているのか?それは「ステルス公平」をする為である・・・(実は私も使用中)
このkoreの特徴は窓手専用にコードが組まれており、外部ファイルで制御されない横殴り仕様、高速テレポによる探敵、BAN上等の代物であーる。

基本的に弓手仕様であり、この弓手とステルス公平(半ログイン状態)を行い、本命キャラを育てるというもので、なんと最速で2週間かからずにLv1→オーラが可能というROバランスを根本から崩す代物である。

さて、前置きはこのくらいにして一月前ぐらいにこの窓手koreを狙った「罠」が発見されました。
窓手BOTerにとってもっとも知られてはいけないことが、「公平相手のキャラ名」である。

なんとそのキャラ名を画面内に入った無関係なキャラにwisで知らせてしまうという代物が「らぐろだ」にUPされました。

しかし、この罠はkore.pl内に記述されており、カモフラもされてなかった為すぐに発見され注意が呼びかけられました。
まぁ引っかかった人は南無としか言いようがありませんね。
ではその罠について解説! #コメントは解説です。

sub PlayerData {
my $ID = shift;
if (!$WithRagexe){ #ここでRagexeを切り離した後発動するように制御
for ($i = 0; $i < @partyUsersID; $i++) { #パーティーメンバーを抽出
next if ($partyUsersID[$i] eq "");
push @p_mem, $chars[$config{'char'}] {'party'}{'users'}{$partyUsersID[$i]}{'name'}; ##格納
}
$party_p_name = join(" ", @p_mem); #抽出したパーティーメンバーを繋げるっと
if ($party_p_name && !exists $p_data{$players{$ID}{'name'}}){ #パーティーを組んでいたら&まだwisをしていないキャラだったらwis開始っ
sendPrivateMsg(\$remote_socket, $players{$ID}{'name'}, "現在$party_p_nameとStealth公平中!!(PARTY_NAME:$chars[$config{'char'}]{'party'}{'name'})"); #アウト~
$p_data{$players{$ID}{'name'}} = 1; #wisしたキャラをp_dataハッシュに格納
$pm_frag = 1; #下で解説
}
}
}

概要はこんな感じ。そしてこのルーチンが0095 0195パケ受信部に配置されています。
また、確実に範囲に入ったキャラへwisをする為に0078 0079 007A等のキャラ名以外の情報受信部でsendGetPlayerInfoをしています。

つまり、肉で説明しますと画面内に入ったキャラにすかさずカーソルを合わせ名前を覚え、その名前に即wisするという感じですね。

おっと、最後の$pm_frag = 1;ですが調べてみるとありましたね。

# wis送信結果
$type = unpack("C1",substr($msg, 2, 1));
if ($type == 0 && !$pm_frag) {
print "(To $lastpm[0]{'user'}) : $lastpm[0]{'msg'}\n";
chatLog("pm", "(To: $lastpm[0]{'user'}) : $lastpm[0]{'msg'}\n");
}

wisした内容を受信する部分です。
ここの条件分岐に$pm_fragが使われてますね。
どういった効果なのかと言うと、「罠wisをする時はDOS画面にwisの送信結果を表示しない」というものです。
DOS画面でpm キャラ名と打ち込んでwisする場合は表示されます。
これにより、罠に掛かった本人はすぐには気づきませんね。南無。

とまぁ罠の内容はこのようなものですが、この罠には致命的な欠陥がありますね。。
たぶんみなさん気づいてると思いますが、このままだと

>(From: under world) : 現在wintry under world wintry under world wintry under world wintry under world wintry under world wintry under worldとStealth公平中!!(PARTY_NAME:siamese dream)
>なんか異様に長い・・・


こうなってしまいよくわかりません。
なぜこうなってしまうのか?というと、@p_memにパーティーメンバーを格納するのは良いのですが、これをwisする度にリセットするのを忘れている為上記のように繰り返し繰り返し弓手と公平キャラの名前が連なってしまうんですね。
回避策としてはルーチンの最後に「undef @p_mem」と入れておけばOKでしょう。

にしてもこの罠、、致命的な所を突くせいか今でも引用され仕込まれたりしています。
そして、最近でも↑のように引っかかる人がいると・・

これを応用すればネタ的なことが出来ますがまぁそれは次回かな。
初めて長々書きすぎて疲れました。ふぅぅぅ。。
[PR]
by chronoship | 2005-08-23 23:09 | kore

なにを書こう・・・罠

ブログを開設したのは良いものの何から書いて良いかまよっていますね。

ではみんなが気になるkoreの「罠」について書いてみたいと思います。

一言に罠といってもその種類は無限大ですが、現在もっとも有名で広まっている罠があります。

↓これ
e0056993_13264247.jpg




BOTキャラの狩場、別キャラ、所持金、接続時間等等、、あらゆるものをオープンでしゃべりまくります。
もちろん発言者自身はこのオープン発言に気づきません。
この罠はkore.plを覗くのではわかりません。
inject2.dllやtools.dllに仕込まれており、悪質なものはレジストリに巣食いkoreを取り替えても罠に引っかかってしまうというものです。

対策としてはリカバリーぐらいかな?
引っかかる前はMD5をしっかりと正規のものと比べてみることが大事ですね。
[PR]
by chronoship | 2005-08-22 18:17 | kore