前回から一ヶ月近くも過ぎようとしています。が、デバッグはあまり進捗していません。ひとつには最近意欲減退中ということ、もうひとつは乗り物がリターンされる現象が再現しないのです。まぁ、Gridの調子があまりよろしくないときはさっさと寝てしまうのも影響しています。
とりあえず、土地の許認可にかかわるLSL関数としては進入禁止設定されていないかが分かるllGetParcelFlags()というものがあるのですがこれには致命的な欠陥があります。というのはこの関数は一個のvectorを渡しそのx、yで指定された座標の状態を調べる関数なのですが、それはつまり自分が居るSIMの情報しか取れないということなのです。
SIMを跨いで移動する場合SIMの境界に問題を引き起こす土地があると結局のところ入ってみるしか知る方法が無いのです。したがって今回は土地の情報は確保していません。
さて、書き忘れている姿勢制御のパラメータの設定について。まず、乗り物のパラメータ設定は専用の関数群を使います。関数群なのは設定するパラメータの型によって使う関数が違うためです。オーバーロードくらいしようよね、とは思いますが無いものねだりをしても仕方ないのでこのままいきます。
一番使う機会が多いのはllSetVehicleFloatParam()でしょう、あと型違い用にllSetVehicleVectorParam()、llSetVehicleRotationParam()があります。これを使って乗り物が移動する際の各種挙動を制御します。そうです、乗り物の挙動はHavocという物理エンジンが自動的に計算するのでLSLから直接的に姿勢を変えさせることはできません。与えた力(とトルク)を元に乗り物の動きはシステム側で制御されています。
今回使用しているものは
VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY上昇または下降時にどれだけピッチが変化するか指定します。0.0なら影響を受けず、1.0は垂直に上昇すると機首が真上を向きます。今回は0.0を設定しています。
VEHICLE_ANGULAR_DEFLECTION_TIMESCALE上昇(または下降)を開始してからどれくらいで姿勢に反映されるかの尺度(大きいほど機敏に姿勢が変わる)。今回は姿勢は固定なので数値は適当に1.0を入れています。(1.0は非常に鈍い動きです)
VEHICLE_BANKING_EFFICIENCY旋回時にどちらにバンクするか。-1から1まであり、-1はリーンアウト。逆に1はリーンイン。今回はフラットスピンの0.0です。
VEHICLE_BANKING_MIX旋回率に対するバンク角の設定。0.0だと全くバンクしません。
VEHICLE_BANKING_TIMESCALEバンク角がどれだけ早く反映されるかの尺度。Wikiの原文だとexponential timescale for the banking behavior to take full effectとなっているのですが、つまりは完全にバンクした状態の半分の位置に達するまでの時間ということでしょう。短いほと高機動な乗り物になります。
VEHICLE_BUOYANCY既出ですが浮力を設定します。0だと重力加速度が働き、1で無重力状態です。内部的には変更可能ですが、初期値は1.0です。
VEHICLE_HOVER_HEIGHT滞空高度を設定します。(単位メートル)
VEHICLE_HOVER_EFFICIENCY外部からの力に対してどれだけ滞空高度に滞在する強さの指数。0だと柔軟、1は堅固。
VEHICLE_HOVER_TIMESCALE滞空高度に到達するまでの時間。いろいろあって現在は10秒です。(あまり早いとカメラが追いつかず自分を見失います)
あと、これらの挙動の補助としてVehicleFlagsというものがあり、今回指定しているのはVEHICLE_FLAG_NO_DEFLECTION_UPとVEHICLE_FLAG_HOVER_UP_ONLYです。HOVER_UP_ONLYについては搭乗者が選んだときだけセットしています。(上昇気流があればより高度が上がるようになります)。
さて、これらの変数ですが、設定値を変更するにはLSLを書き直さなければいけません。しかし、LSLを変更するとリセットがかかってしまい、リセットがかかると墜落します。いや、初期化後にdefaultステートでVehicleType等々をセットすればいいのですが、編集ミスでエラーになった場合そこにたどり着かないのでやっぱり墜落します。痛いのはいやですし、数値を変更する度にいったん降りて回収し、自宅にテレポートしてインベントリから取り出し...をやるのは非常に面倒くさいのでパラメータを外部ファイルで定義できるようにしました。設定値が書かれたNotecardを読み込んでパラメータの初期化を行います。こうすればLSLにリセットをかけずにパラメータの変更が実行できます。
とりあえず、全リストはまだ出せるレベルになっていないのでパラメータ読む部分だけをダミーのdefault stateコード付きで貼っておきます。
string VehicleParam = "VehicleParams" ;
// Vehicle Parameters index. order and nullparams are maenful do NOT remove them.
list VP = [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // param 0-15 are absense
"VEHICLE_LINEAR_FRICTION_TIMESCALE",
"VEHICLE_ANGULAR_FRICTION_TIMESCALE",
"VEHICLE_LINEAR_MOTOR_DIRECTION",
"VEHICLE_ANGULAR_MOTOR_DIRECTION",
"VEHICLE_LINEAR_MOTOR_OFFSET", // here is 20th param
"", "", "",
"VEHICLE_HOVER_HEIGHT",
"VEHICLE_HOVER_EFFICIENCY",
"VEHICLE_HOVER_TIMESCALE",
"VEHICLE_BUOYANCY",
"VEHICLE_LINEAR_DEFLECTION_EFFICIENCY",
"VEHICLE_LINEAR_DEFLECTION_TIMESCALE",
"VEHICLE_LINEAR_MOTOR_TIMESCALE", // here is 30th param
"VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE",
"VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY",
"VEHICLE_ANGULAR_DEFLECTION_TIMESCALE",
"VEHICLE_ANGULAR_MOTOR_TIMESCALE",
"VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE",
"VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY",
"VEHICLE_VERTICAL_ATTRACTION_TIMESCALE",
"VEHICLE_BANKING_EFFICIENCY",
"VEHICLE_BANKING_MIX",
"VEHICLE_BANKING_TIMESCALE", // here is 40th param
"", "", "",
"VEHICLE_REFERENCE_FRAME"
] ;
parsedata(string T)
{
integer index ;
list pT = llParseString2List( T, ["="], [] ) ;
if ( llGetListLength( pT ) < 2 ) jump endproc ; // too few params
string op = llStringTrim( llList2String( pT, 0 ), STRING_TRIM ) ; // get first string to opeland
index = llListFindList( VP, [ op ] ) ; // lookup VehicleParameter table
if ( index > 15 && index < 20 ) // constant from 15 through 20 has vector type param
llSetVehicleVectorParam( index, (vector) llList2String( pT, 1 ) ) ;
if ( index > 24 && index < 40 ) // constant from 24 through 40 has float type param
llSetVehicleFloatParam( index, (float) llList2String( pT, 1 ) ) ;
if ( index == 44 )
llSetVehicleRotationParam( index, (rotation) llList2String( pT, 1 ) ) ;
@endproc ;
}
integer DEBUG = TRUE ;
key DS_QID ;
key DS_KID ;
integer Line ;
default
{
changed( integer change )
{
integer card ;
if (change & CHANGED_INVENTORY)
{
card = llGetInventoryType( VehicleParam ) ;
if (card == INVENTORY_NOTECARD )
{
state readnote ;
}
}
}
}
state readnote
{
state_entry( )
{
Line = 0 ;
llSetTimerEvent( 30.0 ) ; // set watchdog timer
DS_QID = llGetNotecardLine( VehicleParam, Line ) ;
}
dataserver(key id, string data)
{
if ( id == DS_QID )
{
if ( data == EOF ) state default ;
if ( llGetSubString( data, 0, 0 ) != "#" )
{
if (DEBUG) llWhisper( 0, "Added : "+data) ;
parsedata( data ) ;
}
}
Line ++ ;
DS_QID = llGetNotecardLine( VehicleParam, Line ) ;
}
timer( )
{
if (DEBUG) llWhisper( 0, "Watchdog " ) ;
state default ;
}
}
読ませるNotecardはこんな感じです。これをVehicleParamという名前でインベントリに入れておいてください
#
#
VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 0.0
VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 1.0
VEHICLE_ANGULAR_FRICTION_TIMESCALE = <0.0, 0.0, 0.0>
VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 1.0
VEHICLE_ANGULAR_MOTOR_DIRECTION = <0.0, 0.0, 1.0>
VEHICLE_ANGULAR_MOTOR_TIMESCALE = 1.0
VEHICLE_BANKING_EFFICIENCY = 0.0
VEHICLE_BANKING_MIX = 0.0
VEHICLE_BANKING_TIMESCALE = 1.0
VEHICLE_BUOYANCY = 1.0
VEHICLE_HOVER_HEIGHT
VEHICLE_HOVER_EFFICIENCY = 0.9
VEHICLE_HOVER_TIMESCALE = 10
VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 0.01
VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 1.0
VEHICLE_LINEAR_FRICTION_TIMESCALE = 1.0
VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 1.0
VEHICLE_LINEAR_MOTOR_DIRECTION = <0.0, 0.0, 0.0>
VEHICLE_LINEAR_MOTOR_TIMESCALE = 1.0
VEHICLE_LINEAR_MOTOR_OFFSET = <0.0, 0.0, 0.0>
VEHICLE_REFERENCE_FRAME = <0.0, 0.0, 0.0, 1.0>
VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 0.0
VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 1.0
ちなみにデータは単に文字から数値に変換するだけですので変数名やマクロ名は使えません。