Loop through each car (function?) to make a leaderboard?

Discussion in 'Programming' started by danielr, Jun 1, 2021.

  1. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    Hello,

    I have a vehicle lua extension (lua\vehicle\extensions) that counts the total driven distance for every spawned car:
    Code:
    local function updateGFX(dt)
        distancem = electrics.values.wheelspeed * dt
        distanceTotalm = distancem + distanceTotalm
        Speed = electrics.values.wheelspeed * 3.6
        if Speed > topSpeed then
          topSpeed = Speed
        end
    end
    local function getVar()
        state.fuelPercent = electrics.values['fuel']
        state.fuelCap = electrics.values['fuelCapacity']
        state.fuelVol = electrics.values['fuelVolume']
        state.tSpeed = topSpeed
        state.carModel = v.config.model
        state.carConfig = v.config.partConfigFilename
        state.progress = distanceTotalm
        guihooks.trigger('sendState', state)
    end
    In my app.js, the distance is correctly be displayed for the current car (lua variable "distance" is send to app js)
    Code:
    scope.$on('sendState', function (event, data) {
                        state = data;
                  
                        scope.vehicleModel = data.carModel;
                        scope.vehicleConfig = data.carConfig;
                  
                        scope.tSpeed = Math.round(data.tSpeed * 10) / 10;
                        scope.tSpeed2 = Math.round((data.tSpeed / 1.609344) * 10) / 10;
                
                        scope.progress = Math.round((data.progress / 1000) * 100) / 100;
                        scope.progress2 = Math.round((data.progress / 1609.3440057765) * 100) / 100;
                        scope.progressEst = Math.round(((scope.fuelVol / scope.fuelLperKM) * 100) * 10) / 10;
                        scope.progressEst2 = Math.round((scope.progressEst / 1.6093440057765) * 10) / 10;
                  
                        scope.fuelPercent = Math.round((data.fuelPercent * 100) * 10) / 10;
                        scope.fuelCap = data.fuelCap;
                        scope.fuelVol = Math.round(data.fuelVol * 100) / 100;
                        scope.fuelLperKM = Math.round((((scope.fuelCap - scope.fuelVol) / scope.progress) * 100) * 10) / 10;
                        scope.fuelMperG = Math.round((235.214583 / scope.fuelLperKM) * 10) / 10;
                  
                        scope.endurancePoints = formatter.format(data.progress / scope.fuelLperKM * (100 - scope.beams.deformed.percentage));
                  
                        scope.$apply();
                    });
    scope.$on('streamsUpdate', function (event, streams) {
                        scope.$evalAsync(function () {
                            bngApi.activeObjectLua('extensions.separatedistancecounter.getVar()');
                            if (streams.electrics && streams.engineInfo) {
                                var wheelSpeed = streams.electrics.wheelspeed;
            
                                prevTime = curTime;
            
                                curTime = performance.now();
                                timer -= 0.001 * (curTime - prevTime);
            
                                if (timer < 0) {
                                  totalDistance += ((1.0 - timer) * wheelSpeed);
                                  count++;
                                  timer = 1;
                                }
                            
                              }
                      
                        });
                    });

    However, I was wondering if there is a way to cycle/loop through all the spawned cars to read & update this value for all of them once, without needing to swap the current vehicle. Basically I'd like to display a ordered list or leaderboard of all the spawned cars.

    Anyone has a recomendation how to approach this? Write a separate game lua extension and/or can it be done right in the app.js?
     
  2. angelo234

    angelo234
    Expand Collapse
    Programmer
    BeamNG Team

    Joined:
    Aug 11, 2017
    Messages:
    540
    So it looks like to me that you need to make a few adjustments.

    1. Change
    Code:
    bngApi.activeObjectLua('extensions.separatedistancecounter.getVar()');
    to
    Code:
    bngApi.queueAllObjectLua('extensions.separatedistancecounter.getVar()');
    This will call the "separatedistancecounter.getVar()" function of all vehicles, which retrieves the values from all vehicles.

    2. Now "scope.$on('sendState', function (event, data)" will be called by all vehicles. So store the values retrieved from this function in an array per vehicle.

    And note that "streams" data (e.g. streams.electrics.wheelspeed) only comes from the current vehicle, so you want to retrieve them from your Lua file in the "getVar()" function and send them off like you are doing now for other values.
     
    • Like Like x 1
  3. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    Hey angelo 234,

    thank you very much, the queueAllObjectLua is exactly what I was looking for. Time to learn more about arrays now.

    Btw, the streams data is a leftover from trying a few different things last time I was working on my app.
     
    • Like Like x 1
  4. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    @angelo234 Thanks again for your help, I managed to get an array working in JS and used the car-config as a (sort of) unique identifier/key, if a new car has to be added or just updated in the list.

    Also had to restructure the code a bit because getting all variables for all cars like fuel related parameters messed up the original HUD display. Now there are 2 separate LUA & JS functions for HUD/leaderboard in the same app.

    Here's the leaderboard in action:
     
    • Like Like x 1
  5. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    Did the new update (0.23) change something regarding the queueAllObjectLua function? Seems it's behaving like before where I would only get the value of the currently viewed car and not all of them.
     
  6. angelo234

    angelo234
    Expand Collapse
    Programmer
    BeamNG Team

    Joined:
    Aug 11, 2017
    Messages:
    540
    Nope it still calls all vehicles for me.
     
  7. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    That's really strange, something else must be going on. The only thing I changed (to make it work with the new version) was
    Code:
    .directive('distanceDisplay', ['bngApi', 'StreamsManager', 'UiUnits', 'VehicleService', function (bngApi, StreamsManager, UiUnits, VehicleService) {
    to
    Code:
    .directive('distanceDisplay', ['VehicleService', function (VehicleService) {
    and
    Code:
    controller: ['$log', '$scope', 'bngApi', 'StreamsManager', function ($log, $scope, bngApi, StreamsManager) {
    to
    Code:
    controller: ['$log', '$scope', function ($log, $scope) {
    Once ingame the app sends out a bngApi.queueAllObjectLua('extensions.separatedistancecounter.getAllVar()'); which is
    Code:
    local function getAllVar()
        all.carConfig2 = v.config.partConfigFilename
        all.progress2 = distanceTotalm
        guihooks.trigger('sendAllState', all)
    end
    After that in the app scope.$on('sendAllState', function (event, data) { is triggered
    Code:
    all = data;
    console.log("State " + JSON.stringify(all));
    //leaderboard code
    Here is where I'd get all the values of all the spawned vehicles before, but now it only passes the distance only for the currently viewed car.
     
    #7 danielr, Jul 6, 2021
    Last edited: Jul 6, 2021
  8. Diamondback

    Diamondback
    Expand Collapse
    Vehicle Systems Lead
    BeamNG Team

    Joined:
    Apr 8, 2014
    Messages:
    1,957
    Are you using traffic pooling?
     
  9. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    Traffic/vehicle pooling (in gameplay options right?) was off and it doesn't seem to change the app behaviour when enabled.

    In my previous posted video (link) you can see the "debug" at the bottom and all values updating. Right now it only updates the value of the currently viewed car. For clarification, when I said "it behaves like before" I meant when using
    activeObjectLua rather than queueAllObjectLua.
     
  10. Diamondback

    Diamondback
    Expand Collapse
    Vehicle Systems Lead
    BeamNG Team

    Joined:
    Apr 8, 2014
    Messages:
    1,957
    Hm you're trying to send data from multiple vehicles to the UI? I don't think that's supported.

    I just checked queueAllObjectLua and that's working fine.
     
  11. angelo234

    angelo234
    Expand Collapse
    Programmer
    BeamNG Team

    Joined:
    Aug 11, 2017
    Messages:
    540
    Yeah it seems like the update now makes it so
    Code:
    guihooks.trigger()
    only works with the current vehicle.
     
  12. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    Ahh well, it was fun while it lasted :) Thanks again both of you for your time and help
    Triggering this for all vehicles on streamupdate was resource intensive anyway, that's why I had it call every 5 seconds in the end.

    One thing I also noticed is the saving function for a settings.json (explained here: https://documentation.beamng.com/modding/ui/app_creation/) not working since 0.23 but yeah I think this way is mostly outdated by now. Hopefully there will be more documentation on this topic later on.
     
  13. Q_Hung

    Q_Hung
    Expand Collapse

    Joined:
    Jul 2, 2021
    Messages:
    21
    Couldn't you just drop a little lua controller into each vehicle that queues distance information to the game engine every half second or so? Then game engine -> ui is easy.

    Q
    --- Post updated ---
    (So yeah full disclosure: I'm a noob and I'm just making this stuff up off the top of my head. I'm about to try doing exactly this tho once my infrastructural lua is set up correctly)
     
    • Like Like x 2
  14. angelo234

    angelo234
    Expand Collapse
    Programmer
    BeamNG Team

    Joined:
    Aug 11, 2017
    Messages:
    540
    That's a great idea and below is a working solution which literally just makes the Game Engine Lua call the "guihooks.trigger" function :)

    Code:
    local json_data = jsonEncode(data)
    obj:queueGameEngineLua("guihooks.trigger('sendRadarInfo', '" .. json_data .. "')")
    The "data" variable is your Lua table/data you want to send to JS. I had to encode "data" into a JSON string in order for it to work.

    And in the JS, you need to decode the sent JSON string in the called function using:
    Code:
    var data = JSON.parse(json_data);
     
    #14 angelo234, Jul 12, 2021
    Last edited: Jul 12, 2021
    • Like Like x 3
  15. danielr

    danielr
    Expand Collapse

    Joined:
    Jan 6, 2014
    Messages:
    81
    That is a great solution, it is working again now. Thank you so much :)
     
    • Like Like x 2
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice