• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

MSFS20 Event management in javascript

Lagaffe

Resource contributor
Messages
989
Country
france
Good evening,

Reading a lot of B-21-soaring 's javascript (present in many freeware) I was able to write a js that allows me to manage via a 3D button on the VC the extension/closure of a cargo door on an aircraft.
The animation of this opening is managed by the variable A:FLAPS HANDLE PERCENT.

I also wanted this door to be able to open in MSFS External view via two keys on the keyboard that are mapped to the RETRACT FLAPS (event FLAPS_UP) and EXTEND FLAPS (event FLAPS_DOWN).
There is also an visual effect displayed wihen this door is opening via an L;var PBV_TankDumping (boolean).
The code has already been written for the model/aircraft.xml and works very well when the door is controlled via the VC and a click on the 3D button.

Is it possible in the javascript to read a variable like A:FLAPS HANDLE PERCENT (it varies from 0 to 100 for a press on FLAPS DOWN) and to set the L:Var to display the effect?

I have read this afternoon a lot of topic on this subject without finding a reale solution to my problem.
One test of mine:
Code:
update_keypress() {

        this.FLAPS = SimVar.GetSimVarValue("A:FLAPS HANDLE PERCENT","percent");
        if (this.FLAPS != 0) {
             this.tank_open = true;
        } else {
               this.tank_open = false;
        }
  }

Code:
tank_system_update()
        this.tank_system_init();       // initialization of local variables tank_open, this.tank_dumping, this.witch_tank

        let time_delta = this.TIME - this.prev_time;
        if (time_delta < 0 || time_delta > 5) {
            this.prev_time = this.TIME;
            return;
        }

        if (time_delta_s < 1) {
            return;
        }

        this.prev_time = this.TIME;
        let tank_changed = false;

        if (this.tank_left > 0 && this.tank_right > 0 && this.switch_tank) {
            tank_changed = true;
            if (!this.tank_dumping && !this.ON_GROUND) {
                this.tank_dumping = true;
                SimVar.SetSimVarValue("L:pBV_TankDumping","number",1);
            }
            this.tank_left = Math.max(this.tank_left - time_delta * this.DumpRate , 0);
            this.tank_right = Math.max(this.tank_right - time_delta * this.DumpRate , 0);

            SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:4","kilograms", this.tank_right);
            SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:3","kilograms", this.tank_left);
        }

        if (!tank_changed && this.tank_dumping) {
            SimVar.SetSimVarValue("L:pBV_TankDumping","number",0);
            this.tank_dumping = false;
        }
       if (this.tank_open) {
            this.switch_tank = ! this.switch_tank;
            SimVar.SetSimVarValue("L:pBV_SwitchTank","number", this.switch_tank ? 100 : 0);  // for the 3D button in the VC
      }
      if (!this.tank_open) {
            this.switch_tank = ! this.switch_tank;
            SimVar.SetSimVarValue("L:pBV_SwitchTank","number", this.switch_tank ? 100 : 0);
      }
    }
In DEV Mod - Windows - Behaviors - LocalVariables, I cann't see PBV_SwitchTank changing when KEY is press as PBV_TankDumping which does not want to be modificated.

[EDIT] I just modify my post to be more exhaustive, with the time management and the update cycle used.
 
Last edited:
Code:
update_keypress() {
    this.FLAPS = SimVar.GetSimVarValue("A:FLAPS HANDLE PERCENT","percent");
    if (this.FLAPS != 0) {
        this.tank_open = true;
    } else {
        this.tank_open = false;
    }
}

Code:
tank_system_update()
     this.tank_system_init(); // initialization of local variables tank_open, this.tank_dumping, this.witch_tank

    let tank_changed = false;

    if (this.tank_left > 0 && this.tank_right > 0 && this.switch_tank) {
        tank_changed = true;
        if (!this.tank_dumping && !this.ON_GROUND) {
            this.tank_dumping = true;
            SimVar.SetSimVarValue("L:PBV_TankDumping","number",1);
        }
        this.tank_left = Math.max(this.tank_left - time_delta * this.DumpRate , 0);
        this.tank_right = Math.max(this.tank_right - time_delta * this.DumpRate , 0);

        SimVar.SetSimVarValue("A:PAYLOAD STATION WEIGHT:4","kilograms", this.tank_right);
        SimVar.SetSimVarValue("A:PAYLOAD STATION WEIGHT:3","kilograms", this.tank_left);
    }

    if (!tank_changed && this.tank_dumping) {
        SimVar.SetSimVarValue("L:PBV_TankDumping","number",0);
        this.tank_dumping = false;
    }
    if (this.tank_open) {
        this.switch_tank = ! this.switch_tank;
       SimVar.SetSimVarValue("L:PBV_SwitchTank","number", this.switch_tank ? 100 : 0); // for the 3D button in the VC
    }
    if (!this.tank_open) {
        this.switch_tank = ! this.switch_tank;
        SimVar.SetSimVarValue("L:PBV_SwitchTank","number", this.switch_tank ? 100 : 0);
    }
}

Hey Didier I'm sure you're getting close to what you want. The code (if (this.tank_open) { onwards has an issue. I assume your task_system_update() is called on EVERY update cycle. If ,say, this.tank_open is TRUE, then the first of the last pair of if blocks will be called on every update cycle (18 times/sec) which means this.switch_tank[/ICODE will be toggled true/false 18 times/sec. The same will happen if [ICODE]this.tank_open is FALSE, because of the if (!this.tank_open) {... block.So in both situations you are rapidly flipping the this.switch_tank true/false and then flipping L:PBV_SwitchTank rapidly 0/100.

If you want to update the L: var when the flap CHANGES, then you need to have code like:
Code:
if (this.prev_tank_open != this.tank_open) {
    SimVar.SetSimVarValue("L:PBV_SwitchTank","number", this.switch_tank ? 100 : 0);
    this,prev_tank_open = this.tank_open;
}
This is because of the constant looping of the update cycle, and you only want to write the L: var ONCE when this.tank_open changes.

BTW he correct forum tag for code blocks is CODE surrounded by square brackets.[/CODE]
 
Hi,
No, this routine isn't called at each cycle, I have forget to specify some calculations on time. I test theses locales only 1 time per seconde. i will update the correct code and try your advice.

[EDIT] The code that I have posted yesterday is now updated ;-)

Two more question, I have seen many script which used
Code:
            let debug_el = document.getElementById("tank_system_debug");
            debug_el.innerHTML = "Ex."+this.ex;
and
Code:
       SetStoredData("BALLAST OPEN", this.FLAPS);
I understand why theses codes are added and how they are initialized
Code:
Include.addScript("/JS/dataStorage.js");
but I don't see where I can find the debug results or where the DATA file is writed.
 
Last edited:
Well, reading one more time the SDK, I have succeed to load my aircraft project and then launch Debugger.exe from the SDK.
- My JS script is loaded in memory,
- I can see 17 elements and read my code tank_system.js
but when I leave the Debugger and MSFS where is "tank_system_debug file" ?
In the Debugger.exe directory, I can read CoherentGTDebugger.log file but nothing interesting in it.
 
You're getting there with the debugger Didier -

there are 3 useful methods in debugging an HTML/JS gauge, and you're nearly there with all of them:

1) Using the Coherent Debugger (Debugger.exe). The great advantage of this is your JS console.log("My Error Message") will send that text to the CONSOLE tab in the Coherent Debugger, the same ordinary web pages would send the text to the console window available in a regular web browser under menu More Tools... Development Tools. So the only piece your missing is the need to use console.log(...) statements.

2) Create a special HTML div with id="tank_system_debug" on your gauge, size it and position it appropriately (you can check by setting it's background color temporarily to pink in the CSS) and THAT is what gets written to with debug_el.innerHTML = "Ex. "+this.ex; . This is fairly basic compared to using the Debugger but has the unique advantage that the fact an Exception has occurred in your code gets automatically reported to you whenever you're test flying the plane regardless of whether you happen to be running the Debugger.

3) Update an L:var. As you've already done and recognized you can monitor that value in the Behaviours debug window. A couple of tips: (i) initialize the variable, perhaps to 0, in your gauge initialization code so at least you see that value exists (otherwise maybe there's something really bad gone wrong with your code) and (ii) you can increment that debug variable at various stages in your code (for this you might keep a this.var, and increment that, and use that to Set the L:var), (iii) if you name your L:vars with a common prefix (I use B21) it's easy to use the Filter box on the Behaviours window to just see the L:vars you're interested in.

Of these, I'd say if you complete option (1) and see your debug messages in the Debugger console tab, you'll be fine.

[EDIT] Oh by the way, the SetStoredData is always SetStoredData(STRING key, STRING value). It's a key,value store for storing STRINGS. You have to convert numbers to strings when you store them, and convert back from strings to numbers when you retrieve them. Note the WHOLE point of SetStoredData is to store a key,value which will still be there when you next start the simulator, so it is useful for persisting an aircraft setting but not really designed for general variables that would be changing during a flight. A tricky point is the data ONLY GETS PERSISTED WHEN YOU EXIT THE SIM CLEANLY VIA THE HOME MENU. If you quit the sim quickly via the [x] in the corner of the window or the sim just crashes, your SetStoredData will NOT work.
 
Last edited:
A tricky point is the data ONLY GETS PERSISTED WHEN YOU EXIT THE SIM CLEANLY VIA THE HOME MENU. If you quit the sim quickly via the [x] in the corner of the window [...], your SetStoredData will NOT work.
That, IMNSHO, is a bug. Any program that is ended by using the Close button should capture all required data during the window_close event. I don't have MSFS but I'd certainly be reporting that one.
 
Good evening,

Well, I was able to make progress on the 3 tracks that B21-soaring indicated:

- As far as the Coherent Debugger is concerned, I was indeed able to find my script and see a few things, but as far as using it in the strict sense is concerned, that's another matter. It takes a good investment in the manual of this product to be able to do something.

- the creation of an HTML div : by re-reading several freeware, I was able to see some of my mistakes and correct both the script and the css file but despite specifying a pink background, I didn't manage to have the information displayed on the screen.
Would it be necessary to add a plane in the 3D model and associate a texture to it $ ? ... I did not succeed. (others informations would be very appreciated)

drop_system.html:
<link rel="stylesheet" href="drop_system.css?jkhl" />
<script type="text/html" id="drop_system_script">
<div id="drop_system_debug"></div>
</script>
<script type="text/html" import-script="/JS/dataStorage.js"></script>
<script type="text/html" import-script="/Pages/VCockpit/Instruments/Generic/Misc/Drop_System/drop_system.js"></script>

drop_system.css:
/** This mixin makes a single line element fit exactly on the Roboto font for easier integration. */
@font-face {
font-family: "Quartz";
src: url("/Pages/VCockpit/Instruments/Shared/Fonts/Quartz.ttf") format("truetype");
font-weight: normal;
font-style: normal; }

@font-face {
font-family: "Digital";
src: url("/Pages/VCockpit/Instruments/Shared/Fonts/digital.ttf") format("truetype");
font-weight: normal;
font-style: normal; }

:root {
--bodyHeightScale: 1; }

@keyframes TemporaryShow {
0%, 100% {
visibility: visible; } }

@keyframes TemporaryHide {
0%, 100% {
visibility: hidden; } }

html {
height: 100%;
width: 100%;
overflow: hidden; }
html body {
-webkit-user-select: none;
font-family: Roboto-Regular;
font-size: calc(var(--viewportHeightRatio) * (36px / 21.6) * var(--currentPageHeight) / 100);
color: white;
height: 100%;
width: 100%;
margin: 0;
padding: 0; }

drop_system-element {
background: yellow;
height: 100vh;
width: 100vw;
display: inline-block;
overflow: hidden;
}

#drop_system_debug {
background: pink;
position: absolute;
left: 0px;
top: 60px;
width: 100%;
height: 30%;
font-size: 20px;
}
- the update of an L:var, there by modifying one of my <model/aircraft.xml> I could succeed in posting an L:var which is the Ballast_Status used in the JS script to know the progress of the process in the script (=> this.exe;)
Thanks to this last solution, the script has been simplified ( it could be simplified again ) and tuned.

Currently it works and make what I wanted at the beggening of the study.
drop_system.js :
Code:
/*
  drop_system
*/

class drop_system_class extends BaseInstrument {
    constructor() {
        super();
        this._isConnected = false;
    }

    get templateID() { return "drop_system_script"; } // ID of <script> tag in drop_system.html

    connectedCallback() {
        super.connectedCallback();
        this._isConnected = true;
    }

    disconnectedCallback() {
        super.disconnectedCallback();
    }

    Update() {
        if (!this._isConnected) {
            return;
        }

        this.TIME = SimVar.GetSimVarValue("E:ABSOLUTE TIME","seconds");
        this.ON_GROUND = SimVar.GetSimVarValue("SIM ON GROUND","bool") ? true : false;
        this.ex=0;

        try {
            this.ex=1;this.drop_system_update();
        } catch (e) {
            SimVar.SetSimVarValue("L:pBV_TankStatus","number", this.ex);
            let debug_el = document.getElementById("drop_system_debug");
            debug_el.innerHTML = "Ex."+this.ex;
        }
    }


    // Payload Station Index:
    // 1 : Pilots
    // 2 : Navigator
    // 3 : Water Tank Right - 3300 kg
    // 4 : Water Tank Left  - 3300 kg

    // Runs once on startup
    drop_system_init() {
        this.ex=11;
       SimVar.SetSimVarValue("L:pBV_TankStatus","number", this.ex);
        if (this.drop_system_init_complete == null) {

        this.TANK_MAX = 3300;
        this.TANK_MIN = 1350;
        this.tank_left = this.TANK_MAX;         // kg
        this.tank_right = this.TANK_MAX;         // kg
        this.DUMP_RATE = 1000.0;     // We can adjust this. 1 = tanks dump in 50 seconds.

        SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:4","kilograms", this.TANK_MAX);
        SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:3","kilograms", this.TANK_MAX);

        this.tank_toogle = 0;        // tank status : 0 in standby and 1 open
        this.tank_dumping = 0;       // 0 in standby and 1 when drop effect displayed
        this.switch_tank = 0;        // 0 tank closed and 100 tank open (animation switch)

        this.tank_full = true;
        this.prev_TIME = this.TIME;

        this.drop_system_init_complete = true;
        }
    }

    drop_system_update() {
        this.drop_system_init();

        this.ex=12;
        SimVar.SetSimVarValue("L:pBV_TankStatus","number", this.ex);
        let time_delta = this.TIME - this.prev_TIME;

        if (time_delta < 0 || time_delta > 5) {
            this.prev_TIME = this.TIME;
            return;
        }

        if (time_delta < 2) {
             return;
        }


        this.ex=13;
        SimVar.SetSimVarValue("L:pBV_TankStatus","number", this.ex);
        this.prev_TIME = this.TIME;

      // Mouse click on 3D button or FLAPS DOWN => TankToggle 0 => 1
      this.tank_toogle = SimVar.GetSimVarValue("L:pBV_TankToggle","number");

     // When tank status change: ballasts => open
     if (this.tank_toogle) {

     // When water quantity is lower than "this.TANK_MIN", drop effect is stopped only if aircraft is flying
     if (this.tank_left < this.TANK_MIN && !this.ON_GROUND) {
           this.tank_dumping = 0;
        }

        // If tanks containing water
        if (3000 < this.tank_left) {

            // If drop effetct not displayed and aircraft is flying
                    if (!this.tank_dumping && !this.ON_GROUND) {

                // Drop effect and switch animation are validated
                        this.tank_dumping = 1;
                       this.switch_tank = true;

                // Calculations on water quantity which stay in tanks
                        this.tank_left = Math.max(this.tank_left - time_delta * this.DUMP_RATE , 0);
                       this.tank_right = Math.max(this.tank_right - time_delta * this.DUMP_RATE , 0);

                // Payload stations are synchonized with water quantity which stays in tanks
                    SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:4","kilograms", this.tank_right);
                    SimVar.SetSimVarValue("A:pAYLOAD STATION WEIGHT:3","kilograms", this.tank_left);
            }
        }
    }

    // When tank status change: ballasts => closed, switch animation should be stopped
    if (!this.tank_toogle) {
        this.switch_tank = false;
    }

     this.ex=19;
     SimVar.SetSimVarValue("L:pBV_TankStatus","number", this.ex);

    // L:vars used in <model/aircraft>.xml should be synchronized
    SimVar.SetSimVarValue("L:pBV_TankDumping","number", this.tank_dumping);
    SimVar.SetSimVarValue("L:pBV_SwitchTank","number", this.switch_tank);
    }
}

registerInstrument("drop_system-element", drop_system_class);

As I want an effect displayed once the ballast is open, and only once (before a new scooping operation) I could simplified one more again et use a timer (3 or 4 s) to display the effect and stop it after that. Calculations to know the weight of the remaining water isn't really necessary.
 
Last edited:
Would it be necessary to add a plane in the 3D model and associate a texture to it $ ?
The aircraft panel.cfg is doing two things (i) telling MSFS to run the HTML/JS of your gauge (ii) mapping the xy coordinates used in the HTML/CSS to pixel coordinates on a $texture in your 3D model.

I'm sure you're doing (i), because your gauge code would not be running at all otherwise.

For (ii) you would need to paste your panel.cfg entry here to see what you're doing.

Typically for a set of gauges (i.e. a VCOCKPIT) in MSFS you might have a 1024x1024 $texture containing the backgrounds of four gauges in four 256x256 areas making up the 1024x1024 texture. That texture is UV-mapped to the appropriate model elements in the cockpit, just like any other texture. The difference with a $texture is panel gauges can be assigned areas on that texture (see panel.cfg) and UPDATE it. The HTML/JS gauge's main element (i.e. your drop_system-element) is given a width/height in the CSS of 100% x 100% so it FILLS the assigned texture area, and everything the gauge then paints is inside that texture area (including your debug area).
 
Thanks for your answer.

My panel.cfg

Code:
[Color]
Day      = 255,255,255
Night    = 255,255,255
Luminous = 201, 64, 64

[VCockpit01]
Background_color=0,0,0
size_mm=1024,1024
visible=0
pixel_size=1024,1024
texture=$Panel_MSFS
gauge00=Canso!PBY_Init, 0, 0, 1, 1
gauge01=Canso!PBY_Mngt, 0, 0, 834,600
gauge02=Canso!PBY_KeyEvents, 0, 0, 1, 1
gauge03=Canso!PBY_Logics, 0, 0, 1, 1

[VCockpit02]
size_mm=256,512
pixel_size=256,512
texture=$WaterDrop
emissive= 0

htmlgauge00 = Generic/Misc/Drop_System/drop_system.html,0,0,1,1
Ok so I'm not too far from the solution as I understand it.
I had added in my panel.cfg my $WaterDrop texture just in case but it didn't exist in the Blender 3D model. I will review this and test again.
 
Code:
[VCockpit02]
size_mm=256,512
pixel_size=256,512
texture=$WaterDrop
emissive= 0

htmlgauge00 = Generic/Misc/Drop_System/drop_system.html,0,0,1,1

That entry says:

you have a texture $WaterDrop which is 256px x 512px,

and you are defining one gauge, the top-left corner of which is positioned at 0,0 on that texture. The size of the texture area allocated to the gauge is 1px x 1px.

So your gauge is running, but it effectively has no space for its HTML display area.

This is what I do when I want to define HTML/JS code which is invisible to the pilot - this works if the entire UI of the gauge is the animation of a needle, but also enables you to write just about any utility module using the full power of the JS environment and the Gauge API.

But if you want to display anything from the gauge (like the debug text) then the $texture needs to be UV-wrapped onto some surface in the model, and a reasonable area (for example 256x256) allocated to the gauge.

In your case, if there is some digital display to show water amount, then I'd combine that into the same drop_system html/js code, doing both the data display and the water calculations.
 
Thanks, sorry to answer too late. I will test your solution.

I was too busy debugging my code and incorporating the function which manage the filling of ballast tanks on the surface of the water

For the debugging phases, finally, I opted for the creation of additional L:vars that I declared in my HTML/JS and in which I store some calculation variables.
Coupled with the menu DEV Mode - Windows - Behaviors tab "Locales variables" and a good filter, this allows to display the internal variables that I chose in my HTML/JS .

I reserve the Coherent Debugger for the first tests in order to isolate the "big errors".

If I'm not mistaken, the HTML/JS scripts are called via the panel.cfg and are executed at 18 Hz, i.e. 18 times per second.
On the other hand I did not find particular instructions to modify this frequency except to put a counter in order to execute only 1 or 2 times/s (for a ballast calculation, it's enought) .
 
Last edited:
If I'm not mistaken, the HTML/JS scripts are called via the panel.cfg and are executed at 18 Hz, i.e. 18 times per second.
On the other hand I did not find particular instructions to modify this frequency except to put a counter in order to execute only 1 or 2 times/s (for a ballast calculation, it's enought) .
You should not need to concern yourself with the execution rate. Simply subtract the current time from the previous time to know how much has elapsed from the previous loop.
 
It is exactly that I have make (see m'y first code at the bottom), but m'y question was: as in modelbehaviors you have new instructions like UPDATE FREQUENCY, perhaps in JS some code existe for that. Currently i use a counter and return instruction to solve this annoying point.
 
Sorry, I misunderstood. The connectedCallback() is run only once, so that's a good place to call your init code. Otherwise, just test against the sim time. You can't count on any expected execution rate as the Coherent thread can get blocked by other sim code. But it's cheap to test a condition in the update loop.

It should be able to support a setTimeout() or setInterval() I would think.
 
Thanks you for your tip: I have just been looking for information on these two commands (setTimeout() or setInterval() ) and indeed it looks very interesting.
By the way, here is the address of a site where I found a lot of information on this language, it's https://javascript.info/settimeout-setinterval
 
I would advise against using JS asynchronous timers as well as the asynchronous callbacks from the MSFS engine unless you have some really special requirement, i.e. pick one timer loop and stick with it and the sensible choice is the MSFS update cycle. I have a lot of code on different update rates and I've never needed to use setTimeout or setInterval (I use those a lot in regular web JS).

Top Tip: do NOT use the ANIMATION DELTA TIME SimVar as it has a serious bug at the moment if the pilot toggles from the interior view to the exterior view.

The method I would recommend is as follows:

* I refer to the 'main' BaseInstrument update callback as "Update()" and all the secondary update callbacks that will call as "update routines"

* In your main 'Update()' callback, update a var this.TIME_S to contain the current (E:ABSOLUTE TIME, seconds) SimVar Value that can be used in all the 'update routines'

* typically the 'update routines' of your various gauge components will either need updating only when some dependent information has changed, or perhaps at a slower rate that 18 times / second. There is a lot of FSX/MSFS gauge code which simply updates everything every update cycle but that sucks. Basically in each 'update routine' you keep track of how much time has passed since it last updated, and ONLY update it when sufficient time has passed. You do this by having a class variable used by the 'update routine' (e.g. this.prev_map_time_s) which on startup should be initialised with this.TIME_S.

* So the top of each "update routine" begins with something like (for a twice-per-second update rate):
Code:
update_map() {
    let time_delta = this.TIME_S - this.prev_map_time_s;
    if ( time_delta > 0 && time_delta < 0.5) { 
        return; 
    }
    this.prev_map_time_s = this.TIME_S;
    <all your update code continues here>
}
So you can see the 'update routine' effectively does nothing until it's update slot comes round, and this is about as efficient as it can be while can still be absolutely clear what you're doing. You do need to be careful with pilots sliding the UI Weather time slider BACKWARDS (hence the if condition needs to detect a negative delta as in my code above). An alternative is to use ("SIMULATION TIME",seconds) which IIRC always increases and pauses with the UI pause, but after having been burned many times with sim time variables with unexpected edge behaviour (like ANIMATION DELTA TIME), I've found E:ABSOLUTE TIME to be consistently reliable.
 
OK, I note theses points.

[EDIT]
Thanks you B21-soaring, with all yours advices, I have finally succeed to create the JS script: all key events and mouse clicks are managed.
I have also succed in the creation of a LCD screen which display ballast contents in front of pilots (the best would be a digital bar status, perhaps changing the font used).

I still have a few small bugs to fix (the code handling mouse clicks in the VC generates unwanted effects: 3D button jerking) ) but the main part is already done and it makes you believe that the rest is feasible :cool:
 
Last edited:
Back
Top