This Category : はじめてのAurigaスクリプト応用編

--.--.-- *--*
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

はじめてのAurigaスクリプト 応用編(7)

2012.03.03 *Sat*

複数のマップのOnKilledイベントを同じNPCに発生させるには?


別マップにモンスターを出現させて、そのモンスターが倒されたときにOnKilledイベントを発生させようとすると何故かOnKilledイベントが発生しません。
Aurigaは同じマップのNPCにしかOnKilledイベントが飛ばないようです。
しかし、NPC定義の先頭のマップ名の記述を「-」にすることでその制約を無効化できてしまいます。

【例】

- script 古く悪しき者 -1,{
OnSummon:
mapannounce 'gatname$,"古く悪しき者 : ククク……、愚かな人間ども……",0xFF0000;
sleep 3000;
mapannounce 'gatname$,"古く悪しき者 : 我が、絶対究極の力……",0xFF0000;
sleep 3000;
mapannounce 'gatname$,"古く悪しき者 : とくと味わうが良い!!!",0xFF0000,FW_EXTRABOLD,20;
sleep 3000;
areamonster 'gatname$,0,0,500,500,'mobname$,'mobid,'mobcnt,strnpcinfo(0)+"::OnKilled";
end;
OnKilled:
~~どのマップからも呼び出される~~
}
スポンサーサイト

はじめてのAurigaスクリプト 応用編(6)

2011.12.16 *Fri*
アタッチとデタッチについて

Athena系のスクリプトの特徴として
アタッチという概念があります。

既存スクリプトの例を見ると、プロンテラ大聖堂の結婚NPCに
アタッチ&デタッチが使用されています。

npc_quest_marriage.txt(430行)

//もし嫁がログインしてるなら仕込まれたタイムアップフラグを堕ろす
if(attachrid(getcharid(3,'bride$))) {
set @defend,0;
detachrid;
}
if(attachrid(getcharid(3,'groom$))) { //再度アタッチ
//PTが解体されていようが嫁がすでにログアウト状態であろうが関係なし!性転換は考慮しない
announce "国王陛下: 汝、その富める時も、貧しき時も、病めるときも、健やかなる時も",9;
mes "[トリスタン3世]";
mes "新郎" +'groom$+ "よ。";
mes "汝、その富める時も、貧しき時も、";
mes "病めるときも、健やかなる時も、";
mes "" +'bride$+ "を愛し";
mes "敬い、慰め、助け、その命の限り";
mes "堅く節操を守ることを誓うか。";
next;


■アタッチとは?
通常のスクリプトでは、NPC会話や、アイテム使用時など、
そのユーザが直接関わったスクリプト内でのみ
キャラクタのパラメータ・ユーザ変数などへのアクセスが行えます。

NPC会話時やアイテムスクリプト実行時には、内部で自動的にそのキャラクタへ
アタッチが行われています。

OnTimerなどのイベント時には、特定キャラクタへのアタッチが行われていませんので
全体アナウンスなどの、キャラクタとの対話以外の命令しか実行できません。
アクセスしようとするとmapserverの画面に「fatal error ! player not attached!」などと表示されます。

しかし、結婚NPCの場合のように、話しかけたキャラとは別のキャラの
パラメータや変数を扱ったりすることが必要となることがあります。

その場合、アタッチという手続きが必要になります。

■アタッチの利点
アタッチができるとなにができるかというと
・パーティIDからパーティメンバーへのアクセス
・IDや名前が判ればログイン中かどうか判別できる
・他、ワープさせる、アイテムを渡す、キャラ永続変数の変更・・・などなど

■アタッチの方法

if(attachrid(getcharid(3,<キャラクター名>))){
~~~アタッチしたキャラへの処理~~~
detachrid; //必ずデタッチする。しないとアタッチされたキャラが固まることがあります!
} else {
~~~ログアウトしている場合の処理~~~
}


■注意点
Aurigaでは、アタッチしたキャラクタへの変数やパラメータを参照・書換は行えますが
mes や menu や input などのユーザ入力待ちの命令は使用できません。
メッセージ表示は行えても、next、closeなどで、NPCスクリプトが再開できずに固まってしまいます。

script_ref.txt にもこう書いてあります。
この命令でPCをアタッチした場合、mes,menu,nextなどの
ウィンドウ(やボタン)が出る命令を実行してはいけません。
相手が他のNPCと会話中の場合、これらの命令は正しく動作しません。
情報取得命令などだけで済ませるべきです。


※結婚NPCの場合は、最初に話しかけたNPCなので、キャラクタにたまたま
NPCセッションが残っており、かなり奇跡的に動くスクリプトだったりします。

※eAthenaではこの問題は解決されています。C_EOL でのスタックの扱いの違いだけっぽい。

■アタッチを使用した例

パーティ用の討伐クエストの一部です。
「案内人」というNPCで参加パーティメンバーのチェック、クールタイムのチェックを行い、
資格があるキャラをクエストマップへ転送します。
転送する際、入室者のキャラ名を配列変数「'INOUT$」へ登録しています。

これは、そのクエストマップの入退出の監視を行うイベント型NPCです。
OnPC系のイベントでも行えますが、PTを抜けたときに退場させたいのでこのような処理になっています。


prontera.gat,0,0,0 script mission_chk_inout -1,{
OnInit:
OnTimer1000:
//NPC「案内人」の配列変数「'INOUT$[n]」の配列の長さ取得
set '@len,getarraysize(getvariableofnpc('INOUT$,"案内人"))-1;

//配列に登録されているキャラを順番に処理する
for(set '@i,'@len; '@i>=0; set '@i,'@i-1){
set '@chr$, getvariableofnpc('INOUT$['@i],"案内人"); //キャラ名取得
set '@dummy,getmapxy('@mapname$,'@dummy,'@dummy,0,'@chr$); //該当キャラがいるマップ名取得

if('@dummy==0 && '@mapname$=="bat_a01.gat") { //クエストマップにいるかどうか
if(attachrid(getcharid(3,'@chr$))){
set QUEST_CURSE_TIME,gettimetick(2)+300; //クールタイムの更新
if(getcharid(1)==0) { //PTID==0ならパーティを抜けているので退場させる
deletearray getvariableofnpc('INOUT$['@i],"案内人"),1;
warp "SavePoint",0,0;
}
detachrid;
}else{
//ログアウトしているのでリストから削除
deletearray getvariableofnpc('INOUT$['@i],"案内人"),1;
}
} else {
//該当マップに居ないのでリストから削除
deletearray getvariableofnpc('INOUT$['@i],"案内人"),1;
}
}
initnpctimer;
}


■sleepとアタッチ
sleepという命令があります。一定時間ウェイトを行う命令です。
会話型NPCの場合、sleep命令が呼ばれるとその後、nextやcloseが反応しなくなります。

これはアタッチが外れたのではなく、キャラ側にNPCIDが残っていないので、ユーザー入力系のスクリプトの再開ができない(アタッチのときと同じ現象)ようです。

スリープ後に会話を再開したい場合、素直にsleep2を使いましょう。

はじめてのAurigaスクリプト 応用編(5)

2010.12.30 *Thu*

prontera.gat,0,0,0 script 新年カウントダウン -1,{

OnClock2330: //23:30
OnClock2350: //23:50

set '@Month, gettime(6);
set '@MonthDay, gettime(5);

if('@Month!=12 || '@MonthDay!=31) end;

announce "こんばんは、Auriga鯖運営チームです。",0x0;
sleep 5000;
announce "本日23時59分55秒から新年のカウントダウンを行います。",0x0;
sleep 5000;
announce "記念すべき時を皆様と迎えられる事を楽しみにしております。",0x0;
sleep 5000;
announce "それでは、カウントダウンが開始されるまでしばらくお待ちください。",0x0;

end;

OnClock2359: //24:00

set '@Month, gettime(6);
set '@MonthDay, gettime(5);

if('@Month!=12 || '@MonthDay!=31) end;

sleep 25000;
announce "こんばんは、Auriga鯖運営チームです。",0x0; //35
sleep 5000;
announce "カウントダウンが近づいてまいりました!",0x0; //30
sleep 5000;
announce "皆さん準備はいかがでしょうか?",0x0; //25
sleep 5000;
announce "2011年まであと20秒!",0x0;
sleep 5000;
announce "15秒前!",0x0;
sleep 5000;
announce "10秒前!",0x0;
sleep 5000;
announce "5秒前!",0x0;
sleep 1000;
announce "4!",0x0;
sleep 1000;
announce "3!",0x0;
sleep 1000;
announce "2!",0x0;
sleep 1000;
announce "1!",0x0;
sleep 1000;
announce "Happy New Year !!",0x0;
sleep 5000;
announce "皆様、明けましておめでとうございます。",0x0;
sleep 5000;
announce "2011年が皆様にとって良い年となりますよう、運営チーム一同お祈り申し上げます。",0x0;
sleep 5000;
announce "改めまして、本年もよろしくお願い申し上げます。",0x0;
sleep 5000;
announce "それでは、皆さん引き続きAuriga鯖をお楽しみください。",0x0;

end;
}

/*
  解説:
応用編(4)の時報NPCを拡張したものです。
日付を確認するようにして、あとはsleepを調節して
カウントダウンがぴったりになるようにしています。
もちろん、サーバーの時刻はちゃんと合わせておかないと
カッコ悪いので時間合わせツールなどで合わせておきましょうね。

*/

はじめてのAurigaスクリプト 応用編(4)

2010.12.27 *Mon*

//------------------------------
// 非表示NPCの使い道
//------------------------------

prontera.gat,0,0,0 script イベント型 -1,{

OnClock1159: //12:00
OnClock2359: //24:00
sleep 55000;
announce "ミッドガルド放送局が、12時をお知らせします。",0x0;
sleep 2000;
announce "ピッ",0x0;
sleep 1000;
announce "ピッピッ",0x0;
sleep 1000;
announce "ピッピッピッ",0x0;
sleep 1000;
announce "ピッピッピッ、ピーン!",0x0;
end;
}


prontera.gat,154,90,4 script ふきだしNPC 111,{
mes "‐何か紙が落ちているぞ?";
mes " なになに、";
mes " ***領収証***";
mes " 精錬費 10,000z";
mes " 精錬ショップホルグレン‐";
mes " ";
mes " ‐ペッ、クシャポイ!‐";
close;
}

prontera.gat,154,93,4 script 接触専用 139,1,1,{
mes "落とし穴だ!";
close2;
warp "prt_sewb1.gat",0,0;
}

prontera.gat,154,96,4 script ぴかぴかエフェクト 139,{
OnInit:
OnTimer1000:
initnpctimer;
misceffect 165;
}

/*
解説:

非表示NPCにはいろいろな使い道があります。

イベント型(-1)については前回で使ったのでわかるかと思いますが
この番号を指定すると、自動会話や接触イベントは発生せず、位置情報も無視され
エフェクトなどを表示することはできません。

ふきだし型NPC(111)は一般的なクエストでよく使われています。
背景オブジェクトに重ねて表示したり、
MOB型NPCに重ねて話しかけれるようにしたりなど、本家でも多用されています。

次に139番ですが、ふきだしは表示されませんが接触イベントが実行でき、
位置情報もあるので、自動会話やミニマップの位置表示などによく使われています。
使い道の幅が広いので、活用すると面白いスクリプトが作れます。
*/

はじめてのAurigaスクリプト 応用編(3)

2010.12.17 *Fri*

//=====================================
//簡単な討伐クエスト
//----------------------------------

//----------------------------------
//討伐数カウント用NPC
//----------------------------------
map.gat,0,0,0 script test_killed -1,{

OnStart:
//値を初期化
set 'mob_count,0;
end;

OnKilled: //モンスターが倒されたら処理がここに飛んできます

//討伐数カウント

//※注目すべきなのは変数の種類です。
// これはNPC変数。鯖再起動まで消えない性質の変数です。
set 'mob_count, 'mob_count + 1;

if('mob_count < 30) end; // カウントが30未満ならば処理終了

announce "おめでとー!",8; //クリア時アナウンス

set $test_quest_flag,2; //クリアフラグを立てる

end;

}

//----------------------------
// クエスト開始用NPC
//----------------------------
map.gat,100,100,4 script テスト討伐クエスト 888,{


// フラグ 0:クエスト開始前 1:クエスト開始中 2:クリア
// この変数の種類はサーバー永続変数。鯖再起動でも消えません。
switch ($test_quest_flag) {

case 1: // 開始中
mes "まだ敵が全部倒されていません!";
close; //何もしないで終了!

case 2: //クリア時
goto L_CLEAR; //クリア処理へGO!
}

//開始前
mes "討伐クエストを開始しますか?";

menu "開始する", L_START, "なにもしない", -;

mes "-なにもしなかった-";
close;

L_START: //開始処理

mes "開始します!";

close2;

//討伐数カウントNPCを初期化させる。
donpcevent "test_killed::OnStart";

//モンスターを発生させる
monster "map.gat",0,0,"ポリン", 1002, 30, "test_killed::OnKilled";

set $test_quest_flag, 1; //フラグは「開始中」に。

end;

L_CLEAR: //クリア処理

mes "お!クリアしましたか!";
mes "ではこれをどうぞ。";
next;

getitem 512,100; //リンゴ100個を渡す

mes "おめでとうございます。";
mes "おつかれさま!";
close2;

set $test_quest_flag, 0; //フラグを元に戻す

}

/*-------------------------------------------

解説:

まず、NPCを二つに分けた理由の説明から。

NPCは非イベント型、イベント型と2種類に分けられます。

非イベント型というのは
通常の会話型NPCなどがそれです。

イベント型NPCは
OnTouch: OnTimerXXXX: など特殊なラベルを持ったNPCです。
そのようなNPCの場合、NPC名が長すぎたり、同じ名前のNPCがあってはダメで
ユニークな名前を付けないといけません。



今回は、モンスターが倒された時に実行されるイベント型NPCなので
test_killedという名前でイベント型NPCを設置しています。
このイベント型NPCは非表示NPCにしていますので、NPC番号は -1 としています。



そしてもうひとつ重要なのは ラベルの書き方です。
通常のラベルは L~~~: と書かないといけませんと説明しましたが
イベント専用のラベルは

On~~~:

と書かないと動作しません。
(理由はよくわかりませんが、そういう決まりです。eAthenaも共通。)


討伐された時のラベルは別に決まっていませんが、OnKilled: とするのが通例です。

donpcevent <イベント名>

イベント型ラベルの処理を実行します。
OnInit、OnTouch、OnTimer、OnClock などの
定義済みのラベルも実行することができます。

donpcevent "test_killed::OnStart";

書き方は、 "NPC名::ラベル" となります。

別のNPCの処理を実行させたい場合などに非常に便利です。

ちなみに、次のようにNPC名を省略するとどうなるでしょうか。

donpcevent "::OnStart";

なんと、このラベルを持つ全てのNPCのOnStartラベルが実行されます!
使い方を間違えれば、バグの原因となりそうですが
これは仕様となっており、上手に使えば有効な手段となるかもしれません。


次にモンスターの召喚です。

monster "map.gat", 0,0, "ポリン", 1002, 30, "test_killed::OnKilled";
// ↑ ↑座標 ↑ ↑ ↑
// マップ名 0,0とするとランダム mob_ID 数 討伐数をカウントさせる為のNPC名とラベルを指定。

こうすると、このモンスターが倒されるた時に、
指定されたイベント型ラベルの処理が実行されます。




追記となりますが、このスクリプトでは $test_quest_flag という
サーバー永続変数を使用して、NPC同士の値のやり取りを行っていますが、
サーバの再起動で消えることが無い為、再起動後に初期化を行わないと
バグの原因となってしまいますので、実は賢い方法とは言えません。

多少ソースの可読性が落ちるのを厭わないのであれば、
getvariableofnpc 関数を使い、NPC変数の参照・書換えを行うほうが
スマートかもしれません。

getvariableofnpc(<変数名>, "<ユニークなNPC名>")

これは、'ABC 'xyz$ というような、
NPC依存型の(再起動まで消えない)変数にのみ有効な関数で
特定のNPC内の変数を参照できる便利な関数です。

C#やJavaなどで言えば、 original_npc.FLAG 、original_npc->FLAG というような
classや構造体内のメンバ変数を参照するイメージです。

使用例:

if( getvariableofnpc( 'FLAG, "original_npc" ) == 1) { ~~ 略 ~~ }

 original_npcというNPCの 'FLAG という変数が 1 だったら・・・・

 C#/Java風 if(original_npc.FLAG == 1){ ~~~ }

set getvariableofnpc( 'FLAG, "original_npc" ), 2;

 original_npcというNPCの 'FLAG という変数に 2 をセット

 C#/Java風 original_npc.FLAG = 2;

*/

プロフィール

Author:みのり

すごく面倒臭がりで大雑把です。
なので、すぐ楽をしようとして
ツールを作り始めます。
ツールを作る時間と手作業で費やす時間
はたしてどちらが短いのか……


-構築環境-

Auriga0945 MySQL 5.5
with 2011-12-20bRagexeRE

3CeAM rev525
with 2010-07-30aRagexeRE



カテゴリ

未分類 (9)
RagexeRE (9)
eAthena (1)
Auriga (5)
ツール:eAthena用 (4)
ツール:Auriga用 (6)
ツール:その他 (14)
はじめてのAurigaスクリプト (8)
はじめてのAurigaスクリプト基本編 (21)
はじめてのAurigaスクリプト応用編 (7)
Aurigaスクリプト (3)
本鯖 (7)
Aurigaスクリプト:冒険者アカデミー (6)
ドラクエ10 (2)
新生FF14 (3)
EVE Online (2)



最新記事



最新コメント



月別アーカイブ



検索フォーム



リンク

このブログをリンクに追加する



ブロとも申請フォーム

この人とブロともになる



QRコード

QR



12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Copyright © Rocco di Forte All Rights Reserved.
テンプレート配布者: サリイ  ・・・  素材: HELIUM  ・・・ 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。