2007年07月30日
ペット
あひゃひゃひゃひゃ(≧∀≦*) 2週間ぶりの更新〜
最近ちょとスクリプト書く時間が取れたのでへろへろと書いてました。
SLでは需要がありそうでなさそうなペットのスクリプトです〜
ペットって言ってもいろいろありますが、
attach するだけして動かないのはスクリプト関係ないので却下〜。
今回作ったのは…
・空中に浮いてて
・特定の人物を追いかけたり
・ある程度の範囲を自由に動き回って
・その場に止まっていることもできて
・タイマーで勝手に消えてくれて
・そのペットに乗ることもできる
です〜。
というわけでまずはオブジェ作り

うん ハチです。足4つしかないけど。
やる気ないわけじゃないですよ。
センスが無いだけです ≧(´▽`)≦アハハハ
んで このハチの Content の中に…
・pet (←スクリプト)
・timeout (←スクリプト)
・pickup (←アニメーション)
の3つを用意します。
アニメーションはどんなのでもいいです。
座ったときに発動させるアニメーションなだけ〜。
スクリプトがかなり長くなってますが先に載せますね。(400 lineぐらい)
後ろの方に一応解説入れてます。スクリプト好きな方はどうぞ〜^^
これ流し込めば30プリム以下のオブジェだったら
それっぽく動きます〜。(向きの微調整が必要ですが…)
30プリム以下なのは物理属性じゃないと動いてくれないからです。
31プリム以上だと物理属性になってくれないのね〜。
petの中身
// -------------------------------------------------------------
// Variable Declaration
// -------------------------------------------------------------
key _OWNER;
string _STATE;
list _COMMANDS = [ "come" // follow owner
, "stay" // stay at the place
, "free" // move about freely
, "follow" // follow someone
, "timeout" // set timeout
];
integer _COMMAND_HANDLE;
integer _COMMAND_CHANNEL = -9522;
float _COMMAND_TIMEOUT = 20.0;
string _COMMAND_MESSAGE = "Did you call?";
float _SENSOR_RANGE = 30.0;
float _SENSOR_INTERVAL = 2.0;
float _VELOCITY = 3.0;
integer _TARGET_ID;
vector _TARGET_POS;
float _TARGET_MARGIN = 0.1;
float _TARGET_Z_ADJUST = 2.5;
float _FREE_RANGE = 10.0;
string _SIT_TEXT = "Ride";
string _SIT_ANIMATION = "pickup";
vector _SIT_POS = < 0.7, 0.1, -0.7>;
vector _SIT_ROT = < 0.0,-90.0, 0.0>;
key _SIT_KEY = NULL_KEY;
list _FOLLOW_KEY;
list _FOLLOW_NAME;
integer _FOLLOW_HANDLE;
integer _FOLLOW_CHANNEL = -4579;
float _FOLLOW_TIMEOUT = 20.0; // second
string _FOLLOW_MESSAGE = "Who should I follow?";
integer _SEARCH_AV = FALSE;
key _SEARCH_KEY;
integer _TIMEOUT_HANDLE;
integer _TIMEOUT_CHANNEL = -1039;
float _TIMEOUT_TIMEOUT = 20.0;
string _TIMEOUT_MESSAGE = "Please select the time.";
list _TIMEOUT = [ 60 // 1 minuite
, 300 // 5 minuite
, 600 // 10 minuite
, 1800 // 30 minuite
, 3600 // 1 hour
, 0 // no limit
];
list _TIMEOUT_SELECT = [ "1 min"
, "5 min"
, "10 min"
, "30 min"
, "1 hour"
, "no limit"
];
string _DEFAULT_TIMEOUT = "10 min";
// -------------------------------------------------------------
// Functions
// -------------------------------------------------------------
setTarget(key av, vector pos)
{
_TARGET_POS = pos;
if (_SIT_KEY == NULL_KEY) {
if (av != NULL_KEY) {
vector av_size = llGetAgentSize(av);
_TARGET_POS -= < 0.0, 0.0, av_size.z / 2.0>;
}
_TARGET_POS += < 0.0, 0.0, _TARGET_Z_ADJUST>;
_TARGET_POS += < llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
, llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
, llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
>;
} else {
vector root_pos = llGetRootPosition();
float root_z = root_pos.z;
_TARGET_POS = < _TARGET_POS.x
, _TARGET_POS.y
, root_z
>;
}
}
move()
{
vector current_pos = llGetPos();
float distance = llVecDist(_TARGET_POS, current_pos);
float time = distance / _VELOCITY;
_TARGET_ID = llTarget(_TARGET_POS, _TARGET_MARGIN);
llLookAt(_TARGET_POS, 0.5, 0.5);
llMoveToTarget(_TARGET_POS, time);
}
setTimeout(string time)
{
integer lim;
if (time == "") {
lim = llList2Integer( _TIMEOUT
, llListFindList( _TIMEOUT_SELECT
, [_DEFAULT_TIMEOUT]
)
);
} else {
lim = llList2Integer( _TIMEOUT
, llListFindList( _TIMEOUT_SELECT
, [time]
)
);
}
llMessageLinked(LINK_THIS, lim, "timeout", NULL_KEY);
}
init()
{
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
llSitTarget(_SIT_POS, llEuler2Rot(_SIT_ROT * DEG_TO_RAD));
llSetSitText(_SIT_TEXT);
llSetBuoyancy(1.0);
_OWNER = llGetOwnerKey(llGetKey());
_FOLLOW_KEY = [];
_FOLLOW_NAME = [];
_STATE = "";
setTimeout("");
}
// -------------------------------------------------------------
// Main Statement
// -------------------------------------------------------------
default
{
on_rez(integer param)
{
llResetScript();
}
state_entry()
{
init();
}
touch_start(integer num_detected)
{
if (_OWNER == llDetectedKey(0)) {
_COMMAND_HANDLE = llListen( _COMMAND_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _COMMAND_MESSAGE
, _COMMANDS
, _COMMAND_CHANNEL
);
llSetTimerEvent(_COMMAND_TIMEOUT);
}
}
listen(integer channel, string name, key id, string msg)
{
if (id == _OWNER && channel == _COMMAND_CHANNEL) {
llSetPrimitiveParams([PRIM_PHYSICS, TRUE]);
llListenRemove(_COMMAND_HANDLE);
llSetTimerEvent(FALSE);
llSensorRemove();
_STATE = msg;
if (_STATE == "come") {
llSensorRepeat( ""
, _OWNER
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (_STATE == "stay") {
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
}
if (_STATE == "free") {
llSensorRepeat( ""
, _OWNER
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (_STATE == "follow") {
_SEARCH_AV = TRUE;
llSensor( ""
, NULL_KEY
, AGENT
, _SENSOR_RANGE
, PI * 2
);
}
if (_STATE == "timeout") {
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
_TIMEOUT_HANDLE = llListen( _TIMEOUT_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _TIMEOUT_MESSAGE
, _TIMEOUT_SELECT
, _TIMEOUT_CHANNEL
);
llSetTimerEvent(_TIMEOUT_TIMEOUT);
}
}
if (id == _OWNER && channel == _FOLLOW_CHANNEL) {
_SEARCH_AV = FALSE;
_SEARCH_KEY = llList2Key( _FOLLOW_KEY
, llListFindList(_FOLLOW_NAME, [msg])
);
llSensorRepeat( ""
, _SEARCH_KEY
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (id == _OWNER && channel == _TIMEOUT_CHANNEL) {
setTimeout(msg);
}
}
sensor(integer num_detected)
{
if (_STATE == "come") {
setTarget(_OWNER, llDetectedPos(0));
move();
}
if (_STATE == "free") {
vector pos = llDetectedPos(0);
float omg = llFrand(1) * PI * 2;
float t_r = llFrand(1) * _FREE_RANGE;
float t_x = t_r * llCos(omg);
float t_y = t_r * llSin(omg);
setTarget(NULL_KEY, pos + <t_x, t_y, 0.0>);
move();
}
if (_STATE == "follow" && _SEARCH_AV) {
integer i;
string str;
_FOLLOW_KEY = [];
_FOLLOW_NAME = [];
for (i = 0 ; i < num_detected ; i++) {
_FOLLOW_KEY += [llDetectedKey(i)];
str = llDetectedName(i);
if (llStringLength(str) > 24) {
str = llGetSubString(str, 0, 23);
}
_FOLLOW_NAME += [str];
}
_FOLLOW_HANDLE = llListen( _FOLLOW_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _FOLLOW_MESSAGE
, _FOLLOW_NAME
, _FOLLOW_CHANNEL
);
llSetTimerEvent(_FOLLOW_TIMEOUT);
}
if (_STATE == "follow" && !_SEARCH_AV) {
setTarget(_SEARCH_KEY, llDetectedPos(0));
move();
}
}
no_sensor()
{
}
at_target(integer number, vector targetpos, vector ourpos)
{
llTargetRemove(_TARGET_ID);
llStopMoveToTarget();
}
not_at_target()
{
}
changed(integer change)
{
if (change & CHANGED_LINK) {
key av = llAvatarOnSitTarget();
if (_SIT_KEY != NULL_KEY) {
if (av == NULL_KEY) {
llStopAnimation(_SIT_ANIMATION);
_SIT_KEY = NULL_KEY;
}
} else {
if (av != NULL_KEY) {
_SIT_KEY = av;
llRequestPermissions( _SIT_KEY
, PERMISSION_TRIGGER_ANIMATION
);
}
}
}
}
run_time_permissions(integer perm)
{
key perm_key = llGetPermissionsKey();
if (perm_key == _SIT_KEY) {
if (perm & PERMISSION_TRIGGER_ANIMATION) {
list anms = llGetAnimationList(_SIT_KEY);
integer i;
for (i = 0 ; i < llGetListLength(anms) ; i++) {
llStopAnimation(llList2Key(anms, i));
}
llStartAnimation(_SIT_ANIMATION);
}
}
}
timer()
{
llListenRemove(_COMMAND_HANDLE);
if (_STATE == "follow") {
llListenRemove(_FOLLOW_HANDLE);
}
if (_STATE == "timeout") {
llListenRemove(_TIMEOUT_HANDLE);
}
llSetTimerEvent(FALSE);
}
}
timeout の中身
default
{
on_rez(integer param)
{
llResetScript();
}
link_message(integer sender, integer num, string str, key id)
{
llSetTimerEvent(num);
}
timer()
{
llDie();
}
}
んじゃ解説〜
簡単な timeout の中身から…
default
{
on_rez(integer param)
{
llResetScript();
}
link_message(integer sender, integer num, string str, key id)
{
llSetTimerEvent(num);
}
timer()
{
llDie();
}
}
見てお分かりの通りリンクメッセージを受け取って初めて発動することにしています。
発信するのは pet スクリプトからでして、num に秒数を入れて発信してます。
受け取った秒数をllSetTimerEventにあげて
その指定秒数後にllDieしちゃいます。
llDieは自分の Inventory に残らない削除の仕方なので
no copy のオブジェクトだと完全に消えちゃいますのでご注意を〜。
ほい 次は長ったらしい pet のスクリプト見てきます。
変数宣言(Variable Declaration)のところはどうでもいいですね。
いっぱいありますが、フィーリングでカバーしてください。
関数群(Functions)はでてきたら解説入れます〜。
というわけで本体(Main Statement)から…
// -------------------------------------------------------------
// Main Statement
// -------------------------------------------------------------
default
{
on_rez(integer param)
{
llResetScript();
}
state_entry()
{
init();
}
...
on_rezはどうでもいいですね。リセットしてます。
state_entryは初期化する自作関数(init)を呼び出してます。
init()
{
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
llSitTarget(_SIT_POS, llEuler2Rot(_SIT_ROT * DEG_TO_RAD));
llSetSitText(_SIT_TEXT);
llSetBuoyancy(1.0);
_OWNER = llGetOwnerKey(llGetKey());
_FOLLOW_KEY = [];
_FOLLOW_NAME = [];
_STATE = "";
setTimeout("");
}
いきなり物理属性にしてるとフラフラと動き回ってしまうので
llSetPrimitiveParamsで最初は非物理にしちゃいます。
あとは座る位置やらリストを初期化してますが、見慣れないllSetBuoyancyてのも入れてます。
こいつは浮力を設定する奴でして、引数を 0 にすると何も起きずに重力をそのまま受けます。
1 にすることで重力を相殺する力をオブジェクトに与え続けるもので、1 より大きくすると
どんどん上に昇って行っちゃいます。こいつは当然、物理属性のオブジェクトにしか効果ありませぬ。
で、最終行の setTimeout ですが、こいつも自作関数です。
setTimeout(string time)
{
integer lim;
if (time == "") {
lim = llList2Integer( _TIMEOUT
, llListFindList( _TIMEOUT_SELECT
, [_DEFAULT_TIMEOUT]
)
);
} else {
lim = llList2Integer( _TIMEOUT
, llListFindList( _TIMEOUT_SELECT
, [time]
)
);
}
llMessageLinked(LINK_THIS, lim, "timeout", NULL_KEY);
}
タイマーをセットするのに引数が string なのは気にしないで〜。
引数が""のときにはデフォルトの時間(今回は10分)をセットしてます。
引数が""以外だと _TIMEOUT と _TIMEOUT_SELECT のリストから目的の
秒数を探してきます。SLにはハッシュ配列が無いのでこの辺の処理がだるだる〜 (-_-;ウーン
とまぁ、指定秒数を最後にllMessageLinkedを使って自分自身に投げています。
受け取れるのは pet スクリプトではなくて timeout スクリプトですね。
pet スクリプトは link_messageイベントを書いてませんので〜。
ほい んじゃ次
touch_start(integer num_detected)
{
if (_OWNER == llDetectedKey(0)) {
_COMMAND_HANDLE = llListen( _COMMAND_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _COMMAND_MESSAGE
, _COMMANDS
, _COMMAND_CHANNEL
);
llSetTimerEvent(_COMMAND_TIMEOUT);
}
}
えと、オーナーがオブジェにタッチしたときにダイアログを出すだけです。
こんな感じですね。

・come
オーナーに向かって飛んでくる
・stay
その場でピタッと止まる
・free
オーナーを中心にある一定距離(今回は10m)をフラフラ飛び回る
・follow
近くに居る人(今回は30m以内)を探して、オーナーにダイアログで
誰に向かって飛んで行けばいいかを選択する。んで、その人を追尾。
・timeout
自分自身を削除する時間設定のダイアログを出す。
ダイアログから選択するとllDialogの第4引数のチャンネルで発言がされるので
その発言をlistenできるように事前にllListenでチャンネルを開いておきます。
というわけでlistenは…
listen(integer channel, string name, key id, string msg)
{
if (id == _OWNER && channel == _COMMAND_CHANNEL) {
llSetPrimitiveParams([PRIM_PHYSICS, TRUE]);
llListenRemove(_COMMAND_HANDLE);
llSetTimerEvent(FALSE);
llSensorRemove();
_STATE = msg;
if (_STATE == "come") {
llSensorRepeat( ""
, _OWNER
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (_STATE == "stay") {
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
}
if (_STATE == "free") {
llSensorRepeat( ""
, _OWNER
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (_STATE == "follow") {
_SEARCH_AV = TRUE;
llSensor( ""
, NULL_KEY
, AGENT
, _SENSOR_RANGE
, PI * 2
);
}
if (_STATE == "timeout") {
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
_TIMEOUT_HANDLE = llListen( _TIMEOUT_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _TIMEOUT_MESSAGE
, _TIMEOUT_SELECT
, _TIMEOUT_CHANNEL
);
llSetTimerEvent(_TIMEOUT_TIMEOUT);
}
}
if (id == _OWNER && channel == _FOLLOW_CHANNEL) {
_SEARCH_AV = FALSE;
_SEARCH_KEY = llList2Key( _FOLLOW_KEY
, llListFindList(_FOLLOW_NAME, [msg])
);
llSensorRepeat( ""
, _SEARCH_KEY
, AGENT
, _SENSOR_RANGE
, PI * 2
, _SENSOR_INTERVAL
);
}
if (id == _OWNER && channel == _TIMEOUT_CHANNEL) {
setTimeout(msg);
}
}
うん ぐだぐだ。( ̄~ ̄;)
選ばれた各行動によって処理を延々とifで振り分けてます。
注意が必要なのは follow と timeout のときで、こいつらは
行動選択のダイアログの次にさらにダイアログを出す必要があるので
sensorイベントとlistenイベントを行ったり来たりします。
なので変なフラグ立てを余儀なくされてます。
(stateを使ってもう少しきれいに書けばよかったかも〜(T-T)
followが選ばれたときの次のダイアログ
(自分1人しか居なかったのでボタンは一つ…だって引きこもりだもん)

まわりに人がいると、その人たちのNameとKeyを取得して
Nameをダイアログボタンに表示します。
(24文字より長いNameはエラーにならないように文字列処理が必要)
こっちは timeout が選ばれたときのダイアログ

ほぃ sensorイベントの中身もぐだぐだでっす。
sensor(integer num_detected)
{
if (_STATE == "come") {
setTarget(_OWNER, llDetectedPos(0));
move();
}
if (_STATE == "free") {
vector pos = llDetectedPos(0);
float omg = llFrand(1) * PI * 2;
float t_r = llFrand(1) * _FREE_RANGE;
float t_x = t_r * llCos(omg);
float t_y = t_r * llSin(omg);
setTarget(NULL_KEY, pos + <t_x, t_y, 0.0>);
move();
}
if (_STATE == "follow" && _SEARCH_AV) {
integer i;
string str;
_FOLLOW_KEY = [];
_FOLLOW_NAME = [];
for (i = 0 ; i < num_detected ; i++) {
_FOLLOW_KEY += [llDetectedKey(i)];
str = llDetectedName(i);
if (llStringLength(str) > 24) {
str = llGetSubString(str, 0, 23);
}
_FOLLOW_NAME += [str];
}
_FOLLOW_HANDLE = llListen( _FOLLOW_CHANNEL
, ""
, _OWNER
, ""
);
llDialog( _OWNER
, _FOLLOW_MESSAGE
, _FOLLOW_NAME
, _FOLLOW_CHANNEL
);
llSetTimerEvent(_FOLLOW_TIMEOUT);
}
if (_STATE == "follow" && !_SEARCH_AV) {
setTarget(_SEARCH_KEY, llDetectedPos(0));
move();
}
}
no_sensor()
{
}
llSensorRepeatで見つかった対象のKeyと位置を使って
自分自身が移動する先を決めて動きます。移動する先を決めるのは自作関数の setTarget で、
実際に動かすのはこれまた自作関数の move の中でやってます。
setTarget の中は…
setTarget(key av, vector pos)
{
_TARGET_POS = pos;
if (_SIT_KEY == NULL_KEY) {
if (av != NULL_KEY) {
vector av_size = llGetAgentSize(av);
_TARGET_POS -= < 0.0, 0.0, av_size.z / 2.0>;
}
_TARGET_POS += < 0.0, 0.0, _TARGET_Z_ADJUST>;
_TARGET_POS += < llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
, llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
, llFrand(2) * _TARGET_MARGIN - _TARGET_MARGIN
>;
} else {
vector root_pos = llGetRootPosition();
float root_z = root_pos.z;
_TARGET_POS = < _TARGET_POS.x
, _TARGET_POS.y
, root_z
>;
}
}
setTargetの第1引数は追尾対象のUUIDが入ります。
本当は第2引数の位置情報だけでハチは動かせるのですが
Z軸の調整のためにアバターのサイズを取得する必要があったからです。
最初のifはハチにSitしているかどうかで分岐してます。
これがないと対象がハチにSitしていると延々と上に昇ってしまうから
それを防ぐためにですね。対象がSitしているとZ値(=高度)を維持して
動きます。
move関数は…
move()
{
vector current_pos = llGetPos();
float distance = llVecDist(_TARGET_POS, current_pos);
float time = distance / _VELOCITY;
_TARGET_ID = llTarget(_TARGET_POS, _TARGET_MARGIN);
llLookAt(_TARGET_POS, 0.5, 0.5);
llMoveToTarget(_TARGET_POS, time);
}
llMoveToTargetで動かすだけです〜。
その前にllLookAtでハチの正面を対象に向けてます。
at_target(integer number, vector targetpos, vector ourpos)
{
llTargetRemove(_TARGET_ID);
llStopMoveToTarget();
}
not_at_target()
{
}
で、移動終了後の処理。止めてるだけ〜。
ほぃ、これでハチ自体の移動関係のところはしゅ〜りょ〜。
あとはハチそのものにSitしたときの処理です。
パーミッションのやり取りやらアニメーションのStart/Stopの
タイミングを工夫しないと変なことになります〜。
というわけで、Mizさんのとこのポーズボール(スクリプト初級第十四回)から
拝借させてもらいました。(^▽^)/お借りします〜
changed(integer change)
{
if (change & CHANGED_LINK) {
key av = llAvatarOnSitTarget();
if (_SIT_KEY != NULL_KEY) {
if (av == NULL_KEY) {
llStopAnimation(_SIT_ANIMATION);
_SIT_KEY = NULL_KEY;
}
} else {
if (av != NULL_KEY) {
_SIT_KEY = av;
llRequestPermissions( _SIT_KEY
, PERMISSION_TRIGGER_ANIMATION
);
}
}
}
}
run_time_permissions(integer perm)
{
key perm_key = llGetPermissionsKey();
if (perm_key == _SIT_KEY) {
if (perm & PERMISSION_TRIGGER_ANIMATION) {
list anms = llGetAnimationList(_SIT_KEY);
integer i;
for (i = 0 ; i < llGetListLength(anms) ; i++) {
llStopAnimation(llList2Key(anms, i));
}
llStartAnimation(_SIT_ANIMATION);
}
}
}
これで追尾もSitもできるペットの出来上がり〜 °゜°。。ヾ( ~▽~)ツ ワーイ♪
timerイベントはダイアログのチャンネルを
開けっ放しにしないようのストッパーです〜。
(SIMやら環境やら周りの人のことを考えてちゃんと閉じておきましょう〜)
timer()
{
llListenRemove(_COMMAND_HANDLE);
if (_STATE == "follow") {
llListenRemove(_FOLLOW_HANDLE);
}
if (_STATE == "timeout") {
llListenRemove(_TIMEOUT_HANDLE);
}
llSetTimerEvent(FALSE);
}
そんなこんなで完成〜〜

で、ハチにSitしたときにアニメーション発動〜

ハチに連れ去られる河童 ((o(T^T)o))バタバタ
この記事へのトラックバックURL
スクリプトは勝手に使っていいんです?
ペットスクリプト欲しくて公式の掲示板とかも見てたんですけど、ここまでのはなかなかなくてー。
コメントありがとございます〜
どうぞどうぞ〜ご自由に〜
オブジェのルートプリムの向きで微調整が
必要になると思いますが、適当にいじって
調整してくださ〜い。
近いうちに japan 01 のかっぱ池に
フル権限でフリーで置いときますので
それをお持ち帰り頂いても大ジョブです。
再販される場合もご連絡頂かなくても
大ジョブです。
著作権は放棄します ( 。・・)/⌒□ポイ
自己責任でお願いします〜〜。
って放棄できるものなのかな?
≧(´▽`)≦アハハハ
あたしも挑戦してみよっと
ありがとうございまーす
なんて自由な世界なんだ〜
あひゃひゃひゃひゃ(≧∀≦*)
あしあとからお邪魔しました。
スクリプトすごいですね。
私はクリエイターではないので
こういうのをみるだけで頭が痛くなりそうです><
このスクリプト、すごいですw
なんでも飛行体にできてー
おまけに装着すれば、上昇ターボになりましたー(^o^)
天空が自由自在でーす
感謝、感謝 って、ペットの領域から離れていますけどw
こんど、あたしの作った「ぱぴっ(蝶々)」連れてかっぱ池に遊びに行きますねー
こんにちわー^^
スクリプト慣れてないと確かにうねうねした
文字が並んでるだけですよね〜o(*^▽^*)oあはっ♪
かっぱはてんちょーさんみたいにマネジメントが
できないので逆に羨ましぃw
> Hahikさん
Σ( ̄ロ ̄|||)なんと!?
そうかぁ〜attachすると上昇し続けますね〜
試したこと無かったw ご報告ありがとございます〜
ぱぴっちゃんぜひぜひー
ばっちり動作しました。
本当に感謝です!
無事に組み込めたみたいですね〜
おめでとうございます〜!
さてさて次は何作ろ〜
(ΦωΦ)ふふふ・・・・
このスクリプト、うまく作動しないものがあるんです(30プリム以内で)。
オブジェのリンクなどの関係があるのでしょうか・・・。
ダイアログはでるのですが、followにしても微妙に動くだけでついてきてくれません><
このスクリプト、うまく作動しないものがあるんです(30プリム以内で)。
オブジェのリンクなどの関係があるのでしょうか・・・。
ダイアログはでるのですが、followにしても微妙に動くだけでついてきてくれません><
こんばんわ〜
(○ ̄ 〜  ̄○;)ウーン・・・
なんだろ〜
微妙に動くということは多分その人をサーチはできていそうですね。
ということは…
移動ができない=物理属性になってない
かな…。
そのペットの0.1m以内に違うオブジェクト/アバターがいると
物理になってくれませんが、それかも??
もしだめでしたら今ちょうど河童池に
いるのでどうぞ〜
http://slurl.com/secondlife/japan 01/190/21/30
見せて頂いて差し支えなければですが〜
今日はずっと朝まで作業してますので
ご遠慮なく〜^^
作り直したら、多分大丈夫そうです。
あの現象はいったい何なのかが不明なので気持ち悪いですが・・・^^;
INでお会いできた時は、出来上がりみてくださいね^^
もうピョンピョンです。
おめでとうございます〜
°゜°。。ヾ( ~▽~)ツ ワーイ♪
昨日の現象なんとなくわかりました〜
変な球はlightのRadiusでした。
どうもlightをonにしてるプリムがあるとeditしたときにかっぱのPCでは球で表現されてる…。
球の正体はそれだったんですが、それとは別に
どうもlightをonにしているオブジェクトだと
うまく物理になってくれない模様…
(物理になってからlightをonにする分には大丈夫みたい)
いろいろ文献探したけどなかったんですが
かっぱの実験で再現性があったので多分これが原因かと〜
今度、例のもの見せてだくさーい。
> 玉光さん
≧(´▽`)≦アハハハ
ぴょんぴょんしてますか〜
あれ、なかなか止まれないのが欠点w
ハチさんめちゃかわいいですね~^^
SLでも犬を飼いたいと思っているのですが
このスクリプトをお借りしたら、
もしや超従順なわんこができるのではw
諸事情でINできないので、すぐに試せなくて残念です。
でも、わんこを試す前に
私もハチさんに追いかけられたいです^^
at 2007年08月15日 00:58コメントありがとございます〜^^
ブログ拝見させてもらいました。
なにやらinできないそうで…はやく戻って来れるといいですね〜。
ハチは追い掛けられるを通り越して拉致されるのでお気をつけて〜w
at 2007年08月16日 06:08かっぱさんが連れ去られてる写真は
フィクションじゃなかったんですね!!
うわ~ますます楽しみです^^
>なにやらinできないそうで…はやく戻って来れるといいですね〜。
やさしいお言葉ありがとうございます。
たまぁ~に中毒症状が出てネットカフェからINしていますw
at 2007年08月19日 11:48風船を作ろうとして、この記事を参考にさせていただきました。
まだまだ力不足なので、とても全部を理解できているわけではありませんが、とりあえずわかった範囲でスクリプトが完成しました。
とても丁寧な解説ありがとうございました。
at 2007年09月20日 20:45風船うまくいったみたいですね^^
おめでとおございます〜!
こんなコードでも参考になったみたいで
ちょと嬉し〜ヽ( ´¬`)ノ ワ〜イ !!
at 2007年09月20日 21:49これからも参考になる記事を楽しみにしています。ありがとうございました。
at 2007年10月09日 23:40あ〜!その現象、自分もよく遭遇します〜。
物理にしているオブジェクトをず〜っと放っておくと
ピタっと止まっていたり、お互いぶつかってSIMを
出ちゃう(勝手に消えてる)ことが…
ただでさえ扱いにくい物理なのにこういう問題もあると
つくづく面倒くさいですよね〜…
商品にするとなるとこの辺もクリアにしておかないとですか…
大変ですが頑張ってください〜!
at 2007年10月10日 10:30やっぱりそうですか。。。
たまにMath Errorとかいって止まってるし。。。
物理は環境の影響を受けるんでしょうね。10分おきにリセットを呼び出しているのですが、だめでした。エラーハンドリングができるといいのですが。。。
あきらめずに調整していきます。
今後ともよろしくお願いします。
素敵なスクリプトですね!
僕もスクリプト頂いてさっそく作ったオブジェクトに入れてみたのですが、
fellowでもcomeでも、微妙にピクっと動く程度で、移動はしてもらえません。
何が原因なのでしょうか。。。
以前の書き込みであった、lightの設定もしていないですし、プリムの設定も数も大丈夫なはずなんですが。。。
現物を見ないとなんともですね…。
せっかくコメント頂いたので原因究明の
お手伝いさせてもらいますよ〜。
お時間あれば今かっぱ池に来てみましたので
よろしければどうぞです〜。
http://slurl.com/secondlife/japan 01/190/21/30
と、すんごい久し振りのinだ…。
Flexibleかなぁ??
ただの木箱でまず試してもらって
段階を追ってご自身のオブジェになるようにして
どこで動かなくなるか試していけば
原因がわかるかもです〜。
今夜の22時以降、もしinされるようであれば、レス頂けると嬉しいです!
設定でコメントがあればメール来るようになってますので
何気にすぐ気付くんですね。(o ̄∀ ̄)ノ”ぁぃ
では22時にかっぱ池でお待ちしてますね^^
その前に原因がわかったらお知らせくださ〜い。
at 2007年10月25日 19:32先日の物理にならない現象は子プリムに
Flexibleのものが紛れていたのが原因でした。
init()で物理にする前にFlexibleがあるかどうかの
チェックをする記述をすれば、通知なり無条件に
Flexibleを外せたりすることは可能そうですね^^

