[[Nasal スクリプト集]] * 概要 [#pf776953] daytime.nas はスピードアップ状態 (a/A キーを押して1〜n倍速で飛行する) に応じて時計を進める為のスクリプトです。オリジナルはコンコルド用のファイルです。daytime.nas はそこから必要な物を取り出して、特別な設定なしで、どの機体でも動作可能なように変更したものです。なお、コンコルドは既にこの機能がありますので、コンコルド以外の機体で有効になるようにしています。 * インストール方法 [#zd32fd28] 下のソースをエディタにコピーして、 ~/.fgfs/Nasal/daytime.nas として保存してください (Windows の場合は C:/Documents and Settings/<ユーザ名>/Applciation Data/flightgear.org/Nasal/daytime.nas)。 あとは FlightGear を起動するだけで反映されます。特に機体側の変更は必要ありません。OV10 でも時計がチャキチャキ進むのを確認しました。 添付ファイルをダウンロードして、 ~/.fgfs/Nasal/daytime.nas として保存してください (Windows の場合は C:/Documents and Settings/<ユーザ名>/Applciation Data/flightgear.org/Nasal/daytime.nas)。 あとは FlightGear を起動するだけで反映されます。特に機体側の変更は必要ありません。OV10 でも時計がチャキチャキ進むのを確認しました。 * 処理概要 [#t8297fd7] settimer で 1 秒毎に Daytime.schedule を呼び出しています。schedule 内では スピードアップ状態に応じて時計を進める処理をしています。また、安全措置としてスピードアップ(単位時間当たりの高度変化)が早すぎる場合はデフォルトの速度に戻す処理も行っています。System クラスはそんなに大事ではないですが、コンコルドの Nasal クラスが再利用のために全てこの System を利用するようになっていたので、そのまま残しておきました。 * ソース [#u781142e] 添付しようとしたら #attach がないと怒られたのでとりあえず貼付けておきます。 このソースは参考迄に表示しています。ダウンロードは下の添付から行ってください。 ############################################################################### # daytime.nas by Tatsuhiro Nishioka # - Clock that considers "warp" in FlightGear world, extracted from Concorde with # some modification # Copyright (C) 2008 Tatsuhiro Nishioka (tat dot fgmacosx at gmail dot com) # This file is licensed under the GPL license version 2 or later. # $Id: air-racing.nas,v 1.2 2008/04/08 00:16:00 tat Exp $ # ############################################################################### var constant = { HOURTOMINUTE : 60, HOURTOSECOND : 3600, MINUTETOSECOND : 60, }; # ====== # SYSTEM # ====== # for inheritance, the system must be the last of parents. var System = {}; # not called by child classes !!! System.new = func { obj = { parents : [System], SYSSEC : 0.0, # to be defined ! RELOCATIONFT : 0.0, # max descent speed around 6000 feet/minute. altseaft : 0.0, noinstrument : {}, slave : {} }; return obj; }; System.init_ancestor = func( path ) { obj = System.new(); me.SYSSEC = obj.SYSSEC; me.RELOCATIONFT = obj.RELOCATIONFT; me.altseaft = obj.altseaft; me.noinstrument = obj.noinstrument; me.slave = obj.slave; me.loadtree( path ~ "/slave" ); me.loadprop( path ~ "/noinstrument" ); } System.set_rate_ancestor = func( rates ) { me.SYSSEC = rates; me.RELOCATIONFT = constantaero.MAXFPM / ( constant.MINUTETOSECOND / me.SYSSEC ); } # property access is faster through its node, than parsing its string System.loadtree = func( path ) { if( props.globals.getNode(path) != nil ) { children = props.globals.getNode(path).getChildren(); foreach( c; children ) { name = c.getName(); subchildren = c.getChildren(); # <slave> # <engine> # <component>/engines</component> # <subcomponent>engine</subcomponent> # </engine> if( size(subchildren) > 0 ) { component = c.getChild("component").getValue(); subcomponent = c.getChild("subcomponent").getValue(); me.slave[name] = props.globals.getNode(component).getChildren(subcomponent); } # <altimeter>/instrumentation/altimeter[0]</altimeter> # </slave> else { value = c.getValue(); me.slave[name] = props.globals.getNode(value); } } } } System.loadprop = func( path ) { if( props.globals.getNode(path) != nil ) { children = props.globals.getNode(path).getChildren(); foreach( c; children ) { name = c.getName(); subchildren = c.getChildren(); # <noinstrument> # <cloud> # <component>/environment/clouds</component> # <subcomponent>layer</subcomponent> # </cloud> if( size(subchildren) > 0 ) { component = c.getChild("component").getValue(); subcomponent = c.getChild("subcomponent").getValue(); me.noinstrument[name] = props.globals.getNode(component).getChildren(subcomponent); } # <agl>/position/altitude-agl-ft</agl> # </noinstrument> else { value = c.getValue(); me.noinstrument[name] = props.globals.getNode(value); } } } } System.is_moving = func { # must exist in XML aglft = me.noinstrument["agl"].getValue(); speedkt = me.noinstrument["airspeed"].getValue(); if( aglft >= constantaero.AGLTOUCHFT or speedkt >= constantaero.TAXIKT ) { result = constant.TRUE; } else { result = constant.FALSE; } return result; } System.is_relocating = func { # must exist in XML altft = me.noinstrument["altitude"].getValue(); # relocation in flight, or at another airport variationftpm = altft - me.altseaft; if( variationftpm < - me.RELOCATIONFT or variationftpm > me.RELOCATIONFT ) { result = constant.TRUE; } else { result = constant.FALSE; } me.altseaft = altft; return result; } # # Daytime considering wrap # # ============= # SPEED UP TIME # ============= var Daytime = {}; Daytime.new = func { obj = { parents : [Daytime, System], thesim : nil, warpnode : nil, SPEEDUPSEC : 1.0, CLIMBFTPMIN : 3500, # max climb rate MAXSTEPFT : 0.0, # altitude change for step lastft : 0.0 }; obj.init(); return obj; } Daytime.init = func { climbftpsec = me.CLIMBFTPMIN / constant.MINUTETOSECOND; me.MAXSTEPFT = climbftpsec * me.SPEEDUPSEC; me.thesim = props.globals.getNode("/sim"); me.warpnode = props.globals.getNode("/sim/time/warp"); me.init_ancestor("/instrumentation/clock"); } Daytime.schedule = func { # altitudeft = me.noinstrument["altitude"].getValue(); altitudeft = getprop("/position/altitude-ft"); speedup = me.thesim.getChild("speed-up").getValue(); if( speedup > 1 ) { # accelerate day time multiplier = speedup - 1; offsetsec = me.SPEEDUPSEC * multiplier; warp = me.warpnode.getValue() + offsetsec; me.warpnode.setValue(warp); # safety stepft = me.MAXSTEPFT * speedup; maxft = me.lastft + stepft; minft = me.lastft - stepft; # too fast if( altitudeft > maxft or altitudeft < minft ) { me.thesim.getChild("speed-up").setValue(1); } } me.lastft = altitudeft; } var daytime = nil; # called every second var cron_1sec = func { daytime.schedule(); settimer( func { cron_1sec(); }, 1); } # start the cron loop when FDM is initialized _setlistener("/sim/signals/fdm-initialized", func { if (getprop("/sim/aircraft") != "Concorde") { daytime = Daytime.new(); cron_1sec(); } });