ソラマメブログ

2007年06月25日

リファレンス【A】

llA・・・から始まる関数のリファレンスです。
リファレンス【A】

llAbs
llAcos
llAddToLandBanList
llAddToLandPassList
llAdjustSoundVolume
llAllowInventoryDrop
llAngleBetween
llApplyImpulse
llApplyRotationalImpulse
llAsin
llAtan2
llAttachToAvatar
llAvatarOnSitTarget
llAxes2Rot
llAxisAngle2Rot




llAbs

integer llAbs(integer val)

引数valに指定した整数値の絶対値を返す。
絶対値とは0との差であり、常に正の数値となる。

例えば4の絶対値は4であり、-4の絶対値も4である。
マイナスの数値がプラスに変換されると考えてよい。

この関数の使いどころは、例えば二つの数値の間がいくつ離れているかを計算したい場合などに使用できる(ゲームで1位と2位の成績の差を求めたい場合など)。

以下のユーザー関数は二つの整数値がいくつ離れているかを返す。
integer get_abs(integer a, integer b){
  return llAbs(a - b);
}


aとbのどちらが大きいかを意識する必要がない。
例えば、a=100、b=75の場合、a-bは25、これの絶対値25を返す。
逆にa=75、b=100の場合は、a-bが-25になり、絶対値を取ってやはり25を返す。

また、フラグの切り替えを行う際に使用することもある。
例えばタッチするたびに0、5、0、5と交互に繰り返し変化するフラグを使いたいときには、
integer flg = 0;
(略)
touch_start(integer detected){
  flg = llAbs(flg - 5);
}


なお、小数の絶対値を得る場合にはllFabs関数を使用する。




llAcos

float llAcos(float val)

引数valで指定された値のアークコサインを得る。
アークコサインとは通常、コサインの逆関数である。

コサインが何のことやらわからないという方には理解不能な関数なので悪しからず。

コサインを得る関数はllCosであるが、llCosで得た値をllAcosに渡すと、元の数値が得られる。
例えば以下の関数は引数radに指定した小数値と同じ値を返す。
float test(float rad) {
  float cos = llCos(rad);
  float acos = llAcos(cos);
  return acos;
}

radに3.14を指定したとすると、llCosの戻り値は-1.0。
llAcosの引数に-1.0を指定すると、戻り値は3.14である。

使いどころ?
例えばX-Z平面上を速度1m/sで移動する物体を1秒間にX軸方向に50cmだけ移動させたいような場合、どのくらい角度をつけて移動させれば良いかを計算するときに使う。
この場合、llAcos(0.5)の戻り値が回転角度である(単位はラジアン)。




llAddToLandBanList

llAddToLandBanList(key agent, float hours)

agentに指定したUUIDのアバターをhoursに指定した時間だけ土地のBANリストに追加する。
hoursに0.0を指定すると、無期限のBANとなる。
また、hoursの下限値は0.01で、1時間の1%は36秒であるから、最小BAN期間は30秒程度である。

BANリストからアバターを取り除く場合(=立ち入りを許可する場合)はllRemoveFromLandBanList関数を使用する。

なお、BANしたいアバターのUUIDがわからない場合はこの関数を使ってBANすることができない。
LSLにはアバター名からUUIDを取得する関数が存在しないので、名前だけしかわからない相手をBANするのは困難である。
「すみません、あなたをBANしたいのでUUIDを教えていただけますか?」
と尋ねるのも現実的ではない。

通常、BANするのは何らかの迷惑行為等があった場合であるが、わざわざUUIDを調べてこの関数を使わなくても、土地の設定ウインドウを開いて名前を入力したほうが手っ取り早い。
この関数を使ってBANを自動化するような場合は、何らかのスクリプトが介在するのが普通であるから、UUIDの取得は出来るというのが前提である。
例えば、以下の例はオブジェクトに触れた者を片っ端からBANする(3分間)。
touch_start(integer detected) {
  llAddToLandBanList(llDetectedKey(0), 0.06);
}

この例のように、llDetectedKey関数などを使ってUUIDを取得可能である。

それでもどうしても名前を元にしてBANをしたいのだというこだわりのBANユーザーも居ないとも限らない。
そんな変わり者のために、外部Webサービスを利用して調べる方法が一応ある。
ただし、外部DBを参照する以上、常に利用可能とは限らないし、動作が保証されているものではない。

以下はLSL-Wikiのサンプルを改造した例である。
key requestid;
string resident;

name2key(string name){
  list names = llParseString2List(name,[" "],[]);
  resident = llDumpList2String(names," ");
  requestid = llHTTPRequest("http://w-hat.com/name2key?name="+llDumpList2String(names,"+"),[HTTP_METHOD,"GET"],"");
}

default{
  state_entry(){
    name2key("hoge hogera");
  }
  
  http_response(key request_id, integer status, list metadata, string body){
    if (request_id == requestid){
      integer i = llSubStringIndex(body,resident);
      if ( i != -1 ){
        llSay(0,llGetSubString(body,i,i+llStringLength(resident)+36));
      }else{
        llSay(0,"No resident named \""+resident+"\" found in the w-hat name2key database");
      }
    } else {
      llSay(0,(string)status+" error");
    }
  }
}

名前が"hoge hogera"のアバターのUUIDを調べる例である。
この例を利用して問題が生じた場合の責任は負いかねるのでご注意を。

もしhoge hogeraさんが実在した場合は、別に悪意があって例に使用しているわけではないということをご了承いただきたい。




llAddToLandPassList

llAddToLandPassList(key agent, float hours)

agentに指定したUUIDのアバターをhoursに指定した時間だけ土地のPASSリストに追加する。
PASSリストとは土地に立ち入る許可を与えるアバターの一覧のこと。
hoursに0.0を指定すると、無期限に立ち入り許可を与えたことになる。




llAdjustSoundVolume

llAdjustSoundVolume(float volume)

現在再生中のサウンドのボリュームを変更する。
変更できるのはllPlaySound関数かllLoopSound関数で再生されているサウンドである。
llTriggerSound関数によるサウンドには効果がない。

volumeに指定するのは0.0~1.0の値である。
これはサウンドの元々のボリュームを何%にするかの指定であり、元のボリューム以上の音量にすることはできない。

使いどころは、例えばサウンドのフェードアウトである。
fadeout(float delay){
  float v;
  float wait = (delay / 10.0) - 0.1;
  if (wait < 0.0) {
    wait = 0.0;
  }
  for (v = 0.9; v >= 0; v -= 0.1){
    llAdjustSoundVolume(v);
    llSleep(wait);
  }
}

このユーザー関数は再生中のサウンドをdelay秒でフェードアウトさせる。

なお、llSleep関数に渡すスリープ時間waitを-0.1しているのは、llAdjustSoundVolume関数自体が0.1秒ディレイするためである。




llAllowInventoryDrop

llAllowInventoryDrop(integer add)

オブジェクトのコンテンツへのアイテムドロップを許可/不許可にする。
引数addにTRUEを指定した場合はドロップ許可、FALSEにすると不許可である。

通常、オブジェクトのmodify権限を持っていない場合は、コンテンツの中にアイテムを入れることはできない。
しかしこの関数を使ってドロップを許可すると、誰でも任意のアイテムをコンテンツに入れることができるようになる。
なお、FALSEを指定してドロップを不許可にしたからといって、modify権限を持っているユーザーがドロップできなくなるわけではない。
つまりこの関数は、modify権限持っていないユーザーに関して、コンテンツへのアイテムドロップを許可するかしないかを設定する関数である。

参考までに、コンテンツへのアイテムドロップが行われるとchangeイベントが発生するが、modify権限の有無によってセットされるフラグが異なる。
modify権限を保持しているユーザーによるアイテムドロップ時はCHANGED_INVENTORYフラグ、modify権限の無いユーザーの場合はCHANGED_ALLOWED_DROPフラグがセットされる。

以下のようにして判定が可能である。
changed(integer mask){
  if(mask & CHANGED_INVENTORY){
    llWhisper(0, "Contents has changed by user who have modify permission.");
  }else if(mask & CHANGED_ALLOWED_DROP){
    llWhisper(0, "Contents has changed by user who dose not have modify permission.");
  }
}

modify権限の有無に関わらずコンテンツへのアイテムドロップを検知するには以下の判定で良い。
changed(integer mask){
  if(mask & (CHANGED_INVENTORY | CHANGED_ALLOWED_DROP)){
    llWhisper(0, "Contents has changed.");
  }
}





llAngleBetween

float llAngleBetween(rotation a, rotation b)

二つの回転データa,b間の角度(ラジアン)を返す。




llApplyImpulse

llApplyImpulse(vector force, integer local)

物理オブジェクトに瞬間的な力を加える。
力の方向及び強さは引数forceで指定する。
引数localがTRUEの場合、forceはオブジェクトのローカル軸に対して働き、FALSEの場合はグローバル座標に対して働く。

物理オブジェクトに力を加える関数としては、大別してこのllApplyImpulse関数とllSetForce関数の二つがある。
この二種類の関数の違いは、加える力が瞬間的か恒久的かの違いである。

インパルス系の関数は、瞬間的な力である。
例えばゴルフボールをグラブで引っぱたいたような場合、ボールに加えられる力は瞬間的なものであって、その後ボールは徐々にエネルギーを失い、落下する。
フォース系の関数は恒久的な力である。
ロケットの推進力のように、常に加速を加えるような場合にはフォース系関数を使う。

言い換えるなら、インパルス系の関数とは、オブジェクトのエネルギーを消費する関数である。
エネルギーがあれば効果を発揮するが、エネルギーがなくなると効果がなくなる。

セカンドライフにおけるエネルギーは、時間によって回復するという特性がある。
インパルス系の関数を使ってオブジェクトを動かした場合、オブジェクトはエネルギーを消費するが、エネルギーがゼロになるとそれ以上インパルス系の関数を使って動かすことができなくなる。
しばらく待つと、エネルギーが回復して動くようになるのだが、一度引っぱたいたゴルフボールが落下した後、すぐに引っぱたいても動かないという事態があり得るので注意する必要がある。

オブジェクトのエネルギーを調べるにはllGetEnergy関数を使う。
エネルギーの値は1.0~0.0で、1.0ならインパルス系関数の効果は100%発動するが、0.0だとまったく発動しない。

なお、llApplyImpulse関数はアタッチメントにおいても使うことができる。

オブジェクトを特定の速度で動かすには、オブジェクトの質量を考慮する必要がある。
質量の大きなオブジェクトほど、大きな力を加えないと動かない。
さらには重力の影響もあるので注意すること。
セカンドライフにおける物理オブジェクトは、常にマイナスZ方向(下方向)に向かって秒速9.8mの重力が加わっている。

以下の例はオブジェクトを秒速10mの速度で上空に打ち上げる。
llApplyImpulse(llGetMass()*<0,0,10>,FALSE);


以下の例はオブジェクトにブレーキをかける(オブジェクトに加わっている力と正反対の力を加える)。
llApplyImpulse(-llGetMass()*llGetVel(),FALSE);


なお、オブジェクトに加えることのできるインパルスの最大パワーは20,000である。
20,000以上の力を加えても、20,000の力までしか効果がない。
ここで言う20,000とは、引数forceに与えるベクトルの長さである。

瞬間的な回転力を与えるにはllApplyRotationalImpulseを参照。




llApplyRotationalImpulse

llApplyRotationalImpulse(vector force, integer local)

物理オブジェクトに瞬間的な回転力を加える。
回転の方向及び強さは引数forceで指定する。
引数localがTRUEの場合、forceはオブジェクトのローカル軸に対して働き、FALSEの場合はグローバル座標に対して働く。

物理オブジェクトに回転力を加える関数としては、大別してこのllApplyRotationalImpulse関数とllSetTorque関数の二つがある。
この二種類の関数の違いは、加える回転力が瞬間的か恒久的かの違いである。

インパルス系の関数は、瞬間的な力である。
例えばコマの回転のように、最初に勢いよく回転力を与えた後は、徐々に勢いがなくなって停止する。
トルク系の関数は恒久的な力である。
扇風機の回転のように、常に回転をし続けるのがトルク系の回転である。

言い換えるなら、インパルス系の関数とは、オブジェクトのエネルギーを消費する関数である。
エネルギーがあれば効果を発揮するが、エネルギーがなくなると効果がなくなる。

セカンドライフにおけるエネルギーは、時間によって回復するという特性がある。
インパルス系の関数を使ってオブジェクトを動かした場合、オブジェクトはエネルギーを消費するが、エネルギーがゼロになるとそれ以上インパルス系の関数を使って動かすことができなくなる。
しばらく待つと、エネルギーが回復して動くようになるのだが、一度回したコマが停止した後、すぐに回そうとしても動かないという事態があり得るので注意する必要がある。

オブジェクトのエネルギーを調べるにはllGetEnergy関数を使う。
エネルギーの値は1.0~0.0で、1.0ならインパルス系関数の効果は100%発動するが、0.0だとまったく発動しない。

なお、llApplyRotationalImpulse関数はアタッチメントにおいては使うことができない。
この点llApplyImpulse関数と異なるので注意すること。




llAsin

float llAsin(float val)

引数valで指定された値のアークサインを得る。
アークサインとは通常、サインの逆関数である。

サインが何のことやらわからないという方には理解不能な関数なので悪しからず。

サインを得る関数はllSinであるが、llSinで得た値をllAsinに渡すと、元の数値が得られる。
例えば以下の関数は引数radに指定した小数値と同じ値を返す。
float test(float rad) {
  float sin = llSin(rad);
  float asin = llAsin(sin);
  return asin;
}

radに1.57を指定したとすると、llSinの戻り値は1.0。
llAsinの引数に1.0を指定すると、戻り値は1.57である。

使いどころ?
例えばX-Z平面上を速度1m/sで移動する物体を1秒間にZ軸方向に50cmだけ移動させたいような場合、どのくらい角度をつけて移動させれば良いかを計算するときに使う。
この場合、llAsin(0.5)の戻り値が回転角度である(単位はラジアン)。




llAtan2

float llAtan2(float y, float x)

y/xで得られるタンジェントのアークタンジェントを得る。
アークタンジェントとは通常、タンジェントの逆関数である。

例えば以下の関数は引数radに指定した小数値と同じ値を返す。
float test(float rad) {
  float tan = llTan(rad);
  float atan = llAtan2(tan, 1.0);
  return atan;
}

radに1.57を指定したとすると、llTanの戻り値は1255.765592。
llAtanの引数に1255.765592, 1.0を指定すると、戻り値は1.57である。




llAttachToAvatar

llAttachToAvatar(integer attachment)

オブジェクトを指定した位置にアタッチさせる。
オブジェクトはワールド内にrezされていなければならず、かつスクリプトからパーミッションPERMISSION_ATTACHを取得する必要がある。
また、オブジェクトのオーナーでなければアタッチはできない。
従って、オーナー以外のユーザーに対してPERMISSION_ATTACHを取得しても無意味である。

アタッチしようとした箇所にすでに別のアタッチメントが付いていた場合、もとのアタッチメントは自動的にデタッチされ、この関数を実行したオブジェクトが新たにアタッチされる。
初めてアタッチされた場合、オブジェクトはアタッチ箇所の0,0,0の位置に付くが、位置調整を行っておけば、二度目以降は調整した位置に付く。
以上、基本的にインベントリからアタッチした場合と同様の動作である。

引数attachmentには以下の値を使用可能である。
定数名 説明
なし0前回のアタッチ箇所に付く。初めてアタッチする場合は右手に付く。
ATTACH_CHEST 1
ATTACH_HEAD 2
ATTACH_LSHOULDER 3左肩
ATTACH_RSHOULDER 4右肩
ATTACH_LHAND 5左手
ATTACH_RHAND 6右手
ATTACH_LFOOT 7左足
ATTACH_RFOOT 8右足
ATTACH_BACK 9背中
ATTACH_PELVIS 10骨盤
ATTACH_MOUTH 11
ATTACH_CHIN 12あご
ATTACH_LEAR 13左耳
ATTACH_REAR 14右耳
ATTACH_LEYE 15左目
ATTACH_REYE 16右目
ATTACH_NOSE 17
ATTACH_RUARM 18右上腕部
ATTACH_RLARM 19右下腕部
ATTACH_LUARM 20左上腕部
ATTACH_LLARM 21左下腕部
ATTACH_RHIP 22右尻
ATTACH_LHIP 23左尻
ATTACH_RULEG 24右上脚部
ATTACH_RLLEG 25右下脚部
ATTACH_LULEG 26左上脚部
ATTACH_LLLEG 27左下脚部
ATTACH_BELLY 28腹/胃
ATTACH_RPEC 29右胸部
ATTACH_LPEC 30左胸部
なし31HUD-中央2
なし32HUD-右上
なし33HUD-上
なし34HUD-左上
なし35HUD-中央
なし36HUD-左下
なし37HUD-下
なし38HUD-右下


以下の例はタッチするとオブジェクトを右手にアタッチしようとする。
default {
  touch_start(integer num_detected) {
    if (llDetectedKey(0) == llGetOwner()){
      llRequestPermissions(llDetectedKey(0), PERMISSION_ATTACH);
    }
  }

  run_time_permissions(integer perm) {
    if (perm & PERMISSION_ATTACH) {
      llAttachToAvatar(ATTACH_RHAND);
    }
  }
}





llAvatarOnSitTarget

key llAvatarOnSitTarget()

オブジェクトの上に座っているアバターのUUIDを返す。
誰も座っていない場合はNULL_KEYを返す。
ただし、この関数はllSitTarget関数を使ってsit位置を設定しているオブジェクトでしか機能しない。

この関数はしばしば「アバターがsitしたとき」のイベントを擬似的に実装する際に使われる。
default {
  state_entry() {
    llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION);
  }

  changed(integer change) { // something changed
    if (change & CHANGED_LINK) {
      llSleep(0.5);
      if (llAvatarOnSitTarget() != NULL_KEY) {
        llSay(0, "Somebody is sitting.");
      }else{
        llSay(0, "Nobody is sitting.");
      }
    }
  }
}


llSitTarget関数の使用をお忘れなく。




llAxes2Rot

rotation llAxes2Rot(vector fwd, vector left, vector up)

前方向、左方向、上方向を示す3つのベクトル値から、回転データを得る。
犬が西向きゃ尾は東、ではないが、この3つのベクトルは通常互いに直交している。

顔が西向いて左耳が南向いてりゃ、頭頂部は上。
顔が下向いて左耳が北向いてりゃ、頭頂部は東、というように。

このとき顔と左耳の方向を示すベクトルに対して、頭頂部の方向を示すベクトルのことを外積と言う。
顔をa、左耳をbとするとき、ベクトルの外積cは以下のようにして求めることができる。

  a % b = c

従って、llAxes2Rot関数では、前方向、左方向、上方向のうち2つの方向さえわかれば、
llAxes2Rot(fwd, left, fwd % left);

このようにして回転角度を得ることが可能である。




llAxisAngle2Rot

rotation llAxisAngle2Rot(vector axis, float angle)

axisで指定された軸の周囲をangleラジアン回転させた場合の回転データを得る。
例えばaxisに0.0,0.0,1.0を指定した場合はZ軸周囲を回転させるのと同等である。

同じカテゴリー(リファレンス)の記事
 リファレンス【M-P】 (2007-09-21 12:15)
 リファレンス【L】 (2007-08-28 13:54)
 リファレンス【GetU-K】 (2007-08-24 15:06)
 リファレンス【GetS-GetT】 (2007-08-13 13:49)
 リファレンス【GetP-GetR】 (2007-07-25 16:52)
 リファレンス【GetM-GetO】 (2007-07-14 12:15)
この記事へのコメント
mizさん、こんにちは~
一生懸命LSLwikiを眺めつつつまらないものを制作していますが。英語の壁が思ったより厚く細かな部分がつかめずにやきもきしておりました^^;

素晴しい丁重なレファレンス、ぜひぜひ全ての完成を期待しつつエールをおくります。

・・・このブログをみてスクリプトに手を出し、多分むいているのではと思っている今日この頃です。楽しいもの作れるよう精進します!

では~
Posted by mk at 2007年06月25日 18:55
>mkさん

はっ・・・がんばります(^^;;
Posted by Miz at 2007年06月26日 09:55
llAttachToAvatar
関連で質問です。

オブジェクトAを作成して装着位置を右手にします。

ある条件を拾って、装着位置を
腹(ATTACH_BELLY)に変更しようと思ったとき

①もとの装着位置からデタッチ
②腹にアタッチ
って出来るものなんでしょうか?
デタッチされたときにスクリプトは生きているものなのでしょうか?
Posted by Nekooyaxi voom at 2007年07月05日 14:49
>Nekooyaxi voomさん

デタッチするとインベントリに入ってしまうので、スクリプトは停止します。
llAttachToAvatar関数を使えるのは、ワールド内にrezされているオブジェクトのみです。
これは追記しておくべきですね(^^:

あるアタッチメントの装備箇所を移動させて見せる手法としては、llSetAlpha関数を使った透明度のコントロールが一般的です。
例えば、
1、鞘を腰にアタッチ
2、手に刀をアタッチ
抜刀する前は、鞘を可視状態、刀を不可視状態にしておきます。
抜刀したときには、鞘(の柄部分)を不可視、刀を可視状態にします。

こうすることであたかも腰の刀が手に移動したかのように見せかけることができます。
Posted by Miz at 2007年07月05日 15:04
ありがとうございます。
すいません。
更新キーを押して2重投稿になってしましたした。

透明にしておくのは参考になります。

llSetAlphaは
複数箇所の面にテクスチャを数種る尾張ったとしても
オブジェクト全体で透明になるのですね。
Posted by Nekooyaxi voom at 2007年07月05日 15:13
>Nekooyaxi voomさん

あっと、言葉足らずでした。
llSetAlphaは単一primだけにしか効かないので、オブジェクト全体を完全透明にしたい場合は、
 llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES);
を使ってください。
Posted by Miz at 2007年07月05日 16:20
お返事が遅れました。スクリプトについて教えていただきありがとうございました。^^7 
定期的に見ております。応援してます。
Posted by kuwatto at 2007年11月03日 01:24
Exceptionally well written!
I will immediately seize your rss as I can’t in finding your
e-mail subscription link or e-newsletter service.
Do you’ve any? Please permit me recognise so that I may just subscribe.
Posted by natamolestr at 2016年02月24日 16:53
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。