デモ用商品
デモ用の商品に関しては、いろいろと制限方法があるかと思いますが、今回は単純に、
「一定時間のみ使用可能」
「特定回数のみrez可能」
この二つを実装してみたいと思います。
まず「一定時間のみ使用可能」ですが、ここまで読み進んできた皆さんであれば、タイマーイベントを使えば「一定時間が経過したとき」の処理ができることはすぐ思い当たるかと思います。
「特定回数のみrez可能」のほうについても、少し前にやったrezのスクリプトで、「rezされたとき」のイベントがありましたので、回数を数える変数を用意すれば簡単にできますね。
スクリプトの前半部分では、タイマーイベントとrezイベントを使い、デモ商品の使用期限をチェックするようにします。
使用期限が切れた後が今回のポイントです。
今回はアタッチメントを想定していますので、「使用期限が切れたら」まず「アタッチを解除」します。
強引にインベントリに戻してしまうわけですね。
しかしそれだけでは再びアタッチ可能です。
「期限が切れたあと」に「アタッチされたら」そのたびに「アタッチを解除」する仕組みが必要でしょう。
これでアタッチしようとしてもアタッチできなくなります。
これだけでも使用不能にはなりますが、人によっては使用期限の切れたアタッチメントをオブジェとして使い続けようとするかもしれませんw
そこでトドメの一撃として、「rezされたら」「オブジェクトを消去する」ようにしておくと完璧です。
なんと陰険なスクリプトでしょうかw
以上の仕組みをまとめてみます。
例の「ステート」「イベント」「処理」を念頭に置いて考えて下さいね。
ステートイベント処理デモ期間中
(default)タイマー使用可能時間を減らす
使用可能時間がゼロになったら「使用不能」ステートへrezrez回数をカウントする
rez可能回数を超えたら「使用不能」ステートへ使用不能ステートエントリーアタッチを解除アタッチアタッチを解除rezオブジェクトを消去
以上のような構成のスクリプトができればOKですね。
アタッチの制御
構成は見えましたが、実現するための関数やイベントは今までに登場していないものです。
まず難しいところから行きましょう。
「アタッチを解除」する関数です。
llDetachFromAvatar();
この関数でアタッチを解除することができます。
引数や戻り値はありません。
一体これのどこが難しいのかと言うと、この関数、パーミッションがなければ使えないのです。
パーミッションについてはお金の支払いやアニメーションのところで説明しましたが、覚えていますでしょうか。
lslの中でも特にわかりにくい概念の一つがパーミッションかと思います。
復習をかねて簡単に説明すると、セキュリティの観点から勝手に実行してはマズイようなスクリプトに関して、使用者の許可を取らなければいけない仕組みがパーミッションです。
アタッチメントを勝手に着脱されてしまったら、やはり困りますよね。
例えば公衆の面前でいきなりハゲにされたり、股間から何やらにょっこり生えてきたりしたら、不愉快に感じる人がいるでしょう。
ですのでアタッチメントの制御にはパーミッションが要ります。
アタッチメント制御のパーミッションを取得するには以下のようにします。
llRequestPermissions(key, PERMISSION_ATTACH);
keyはパーミッションを要求する相手のUUIDですね。
PERMISSION_ATTACHがアタッチメント制御のパーミッション要求の指定です。
基本的にはこの要求が出された時点で、パーミッションダイアログが開きます。
(ここで「基本的には」と書いた理由はコメントを参照して下さい(^^)
要求に対して許可・不許可の回答が為されると、run_time_permissionsイベントが起きます。
run_time_permissionsイベントの中でアタッチメント制御が許可されたかどうかを調べるには以下のようにします。
run_time_permissions(integer p){
if (p & PERMISSION_ATTACH){
// 許可された
}else{
// 許可されなかった
}
}
パーミッションが許可されて始めて、先ほどのアタッチを解除する関数llDetachFromAvatar()が使えます。
面倒ですが、この手続きは必須です。
次に、「アタッチされた」ときのイベントを見てみましょう。
これはズバリ、attachイベントというのがあります。
attach(key attached) {
// attachedはアタッチした人のUUID
// NULL_KEYの場合はデタッチされたことを意味する
}
このイベントは「デタッチされたとき」にも起こります。
その場合は引数にNULL_KEYが入ってきます。
それほど難しくはないでしょう。
最後に、これはアタッチメントに関係ありませんが、「オブジェクトを消去する」方法です。
これにはllDie()という物騒な関数を使います。
llDie();
引数・戻り値はありません。
この関数を実行すると問答無用でオブジェクトが消去されます。
ただし、この関数はアタッチメントに対しては使えません。
あくまでも地面などにrezされた状態でなければ機能しません。
もしこの関数がアタッチメントに対して使えるのであれば、「使用期限が切れたとき」にわざわざ「アタッチ解除」などというまだるっこしい真似をせず、いきなり「オブジェクト消去」できるのですが・・・。
それができないがために「アタッチ解除」で済ませています。
デモ商品用スクリプト
では実際のスクリプトを組んでみましょう。
integer rez_count=5; // 残りrez回数(今回は5回までrez可能に設定)
integer use_hour=4; // 残り使用時間(今回は4時間使用可能に設定)
settext(){ // デモであることを示す文字列を表示するユーザー関数
string msg="***DEMO***\n";
msg += "You can rez this attachiment " + (string)rez_count + "times,\n"; // 残りrez回数を表示
msg += "or use for " + (string)use_hour + " hours."; // 残り使用時間を表示
llSetText(msg, <1.0, 0.0, 0.0>, 1.0); // 赤い文字でフロートテキストとして表示する
}
default { // デモ期間中のステート
state_entry(){
settext();
llSetTimerEvent(3600.0); // 一時間ごとのタイマーを起動
}
timer(){
use_hour --; // 一時間ごとに残り使用時間を減算
if (use_hour < 0){ // 使用時間が0以下になったらステートdeadに遷移
state dead;
return;
}
settext();
}
on_rez(integer p){
rez_count --; // rezされるたびに残りrez回数を減算
if (rez_count < 0) { // 使用回数が0以下になったらステートdeadに遷移
state dead;
return;
}
settext();
}
}
state dead { // デモ期間終了後のステート
state_entry(){
llSetObjectName("Expired Attachment - Delete Me");
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH); // アタッチ解除のためにパーミッション要求
}
run_time_permissions(integer p){
if (p & PERMISSION_ATTACH){ // パーミッションが許可されたらメッセージを表示してデタッチ
llSay(0, "This attachiment was expired!");
llDetachFromAvatar();
llDie(); // 一応書いてあるがこれは動作しない
}else{ // パーミッションが許可されなかったらシツコク再要求w
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
}
}
attach(key attached) {
if (attached != NULL_KEY) { // アタッチされたらアタッチ解除のためにパーミッション要求
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
} else {
llDie(); // 一応書いてあるがこれは動作しない
}
}
on_rez(integer p){
llDie(); // 地面にrezされた瞬間にオブジェクト消滅
}
}
デモであることを示すために、llSetText関数を使って「DEMO」の文字と残りrez回数・残り使用時間を表示するようにしました。
llSetText関数に渡す文字列msgの中で"\n"と書いてあるのは「改行」です。
メッセージは折り返されて3行に表示されます。
今回のポイント
・アタッチの解除:
llDetachFromAvatar();
・アタッチイベント:
attach(key attached) {
// attachedはアタッチした人のUUID
// NULL_KEYの場合はデタッチされたことを意味する
}
・オブジェクト消去:
llDie();
アタッチを制御する関数は他にもいくつかありますが、そのうちどこかでお目にかかる機会もあるでしょう。
着脱するときにはパーミッションが必要であることを忘れないで下さい。
アタッチイベントは、アタッチするたびにスクリプトを初期化したいときなどにも使えます。
llDieの使用には注意して下さい。
きちんとインベントリにオブジェクトのコピーを保持しておかないと、完全にオブジェクトは消滅してしまいます(^^;
さて、初級スクリプトも残りあとわずかです。
来週には完結予定・・・ですかね?(^^;