Hello guys!
First of all, I want to say thank you for this awesome software and affordable price 😍
I am almost finishing my dashboard for hotlapping in Assetto Corsa, but I am needing a bit of help.
All is working great, but the only problem is, when I go offtrack, dashboard still registers the lap when I complete it.
There is no property in Simhub that show TRUE when you Offtrack or cut track, but there is a property that can work I think.
I think I have all the needed, but I don't know how to code it, I don't know C or Javascript. I am trying things, but never works haha.
[CurrentLap] - (Current Lap Number: lap1, lap2, lap3..)
[LastLapTime] - (Time of the last lap you completed)
[CurrentLapTime] - (Current Lap Time: 1.02.30, 2.48.58, etc)
[GameRawData.Physics.NumberOfTyresOut] - (This is the property that can work to detect Offtracks or cut, if NumberOfTyresOut is 3 or more, there was an Offtrack or cut)
Knowing this, I don't know how to make the next:
--- If in the [CurrentLap], [GameRawData.Physics.NumberOfTyresOut] => 3 in any moment of the lap, put the CurrentLapTime in red color until next lap starts.
--- If in the [CurrentLap], [GameRawData.Physics.NumberOfTyresOut] => 3 in any moment of the lap, don't register the [LastLapTime] when I finish the lap.
Can you help me with that? Thank you so much!!
My best regards.
Sorry for bothering you, but you are the best at this ❤️
Please don't laugh XDD. I don't know what more to try, I am going to sleep right now, tomorrow I will test next code (#FFFF0000 Red Color in actual lap when I made a cut or offtrack until I complete the lap, then, time white again):
var tyresout = $prop('GameRawData.Physics.NumberOfTyresOut'); var laptime = timespantoseconds($prop('CurrentLapTime')); var condition; var offtrack; condition = changed(100,tyresout) if (condition = true && laptime > 0 && tyresout > 2) { offtrack = 1; while (laptime > 0) { return '#FFFF0000'; } } return '#FFFFFFFF'; offtrack = 0;
Hi, you'll need to use root variables to store values accros executions:
https://github.com/SHWotever/SimHub/wiki/Javascript-Formula-Engine
I will look something like this (not tested)
var tyresout = $prop('GameRawData.Physics.NumberOfTyresOut');
var lap = $prop('CurrentLap')
if (root.lapValid == null){
root.lapValid = true;
root.lapOld = lap;
}
if (root.lapOld != lap) {
root.lapValid = true;
}
root.lapOld = lap;
if (tyresout > 2){
root.lapValid = false;
}
return root.lapValid ? '#FFFFFFFF' : '#FFFF0000';
@romainrob Oh my god, It's working flawless! I envy and admire you so much, I spent last 2 days like 8-10 hours each testing things, trying functions.. you would laugh If you see what things I did. LOT OF THANKS.
I promise you I did read the code you made 50 times and still I can't understand it, but I promise I will try to understand how the procedure is.
I am trying now the last thing, when I complete a lap with new time record, I actually show a message for 5 seconds:
if((changed(5000,[PersistantTrackerPlugin.PreviousLap_00]) == true) && [PersistantTrackerPlugin.AllTimeBestLastLapDelta] < 0, true, false)
It's possible to implement the code you made in this? That message only would appear if the Lap I made was valid lap?
Actually I see, everything is bad in Assetto Corsa.
If I make best lap record with a cut, [BestLapTime] registers the time with the cut.
If I make best lap record with a cut, [DeltaToBestTime] shows delta compared to the record cutted lap.
If I show [BestSessionLapTime], it doesn't register the best lap with cut, but [BestSessionDeltaLapTime] registers it, so maybe I am doing better time than registered in best session time and I am having possitive delta.
Wtf. I don't know what to do. Is this normal or is something wrong in my Assetto Corsa game?
Hi, you're welcome. And I'm not laughing, I've been there, I know the feeling...
I don't know if there is a reliable way to tell to detect invalid lap in AC.
Here are some commentaries if it can help you understand it
var tyresout = $prop('GameRawData.Physics.NumberOfTyresOut');
var lap = $prop('CurrentLap')
//Inialise the root variables with their default values (the 1st time the Fx runs)
if (root.lapValid == null){ // if root.lapValid == null, we know the Fx runs for the 1 time
root.lapValid = true;
root.lapOld = lap;
}
// Reset the lap validity on lap change
if (root.lapOld != lap) { // If the current lap value changed
root.lapValid = true; // Set the lap to Valid
}
root.lapOld = lap; // Store the current lap value as 'old' to compare it the next frame
if (tyresout > 2){
root.lapValid = false; // Set the lap to invalid
}
return root.lapValid ? '#FFFFFFFF' : '#FFFF0000'; //return a color or another depending on root.lapValid
//condition ? trueresult : falseresult (another syntax of the if function)
It should be possible to control the visibility of the splash screen in a similar way, if you find a proper way to detect invalid laps.
@romainrob I understand now, wow, thank you soooo much, really.
I am trying to make my own best session time delta, I don't know if It's logic or not, but I am trying
My actual code is:
var deltasession = secondstotimespan(timespantoseconds($prop('PersistantTrackerPlugin.EstimatedLapTime')) - timespantoseconds($prop('GameRawData.Graphics.BestTime'))); return deltasession;
I transform to seconds the "$prop('PersistantTrackerPlugin.EstimatedLapTime')" and the best session valid time "$prop('GameRawData.Graphics.BestTime')" to seconds to calculate the difference, but result is not logic. Seems that "$prop('GameRawData.Graphics.BestTime')" can't transform to seconds.
I tried this code to transform "$prop('PersistantTrackerPlugin.EstimatedLapTime')" to seconds and It works:
var bestlapsession = $prop('GameRawData.Graphics.BestTime'); if (bestlapsession == null) { bestlapsession = '0'; } function timespantoseconds(timespan) { if (typeof timespan !== 'string' || timespan.length < 8) { throw new Error('El argumento debe ser una cadena de texto válida en formato "mm:ss:fff".'); } var timeParts = timespan.split(":"); var totalSeconds = parseInt(timeParts[0]) * 60 + parseInt(timeParts[1]) + parseFloat(timeParts[2]) / 1000; return totalSeconds; } var bestlapseconds = timespantoseconds(bestlapsession); return bestlapseconds;
But I don't know how to make both work together and make the calculation of "ESTIMATED - BEST SESSION LAP" to show the difference in +0.00;-0.00
Coding is haaaaaaard
var estimate = timespantoseconds($prop('GameRawData.Graphics.BestTime'));
return estimate;
RESULT: null
var estimate = $prop('GameRawData.Graphics.BestTime');
return estimate;
RESULT: 1:28:334
I can't understand xD
I will try in future make an ALL BEST TIME + ALL BEST TIME DELTA checking both for valid and invalid laps, but while I do that, I would like to have BestSessionTime, BestSessionTimeDelta and BestSessionTimeDeltaProgress, but I think that's not possible (Maybe BestSessionTimeDeltaProgress is possible checking if estimated lap time is increasing or decreasing)
I am so sad to be honest. Why Assetto Corsa give wrong values and doesn't check if lap is valid or not to register it? It's so hard coding all this only for make useful the display with Simhub..
Okay, with a little help of ChatGPT I finally have custom delta of the best session lap without CUT register.
var time = $prop('GameRawData.Graphics.BestTime'); var parts = time.split(":"); var minutes = parseInt(parts[0]); var secondss = parseInt(parts[1]); var miliseconds = parseInt(parts[2]); var totalTime = minutes * 60 + seconds + miliseconds / 1000; var estimated = timespantoseconds($prop('PersistantTrackerPlugin.EstimatedLapTime')); var delta = estimated - totalTime; var deltaString = delta.toFixed(2); if (delta > 0) { deltaString = "+" + deltaString; } root.Delta = deltaString; return root.Delta;
Now, it's time to think if its possible to create the same with best lap record in each map with each car + delta for that record lap, I think that's not possible. The Fx should load the best lap ever made in that car and in that map, getting the info on a local file in my computer, or loading the info from Content Manager, then in "Fx" check lap validity each time I make a lap, and if lap is valid and lap is record, it should save the record on the .txt overwriting it. Or if is possible to get the time of Content Manager it should way easier, but I think both are not possible, right? @romainrob
Maybe we will have to live with the information (record + delta of the session) and not with the absolute record lap + delta to the absolute record lap..?
@bartun Hi, idk how CM stores lap times.
You can read a text file with a formula using readtextfile() but you can't write one, so you won't be able to save new lap times.
@romainrob I am using "Sidekick app", it storages automatically the best lap in a file. For example, yesterday I made 3 test laps with Ferrari FXX K, in Monza Junior track.
First lap was 1:05:284 doing cut.
Second lap was 1:08:511 without doing cut.
Third lap was 1:13:647 without doing cut.
Sidekick saved an archive called "ks_ferrari_fxx_k_ks_monza66-junior_pb.ini" on "assettocorsa\apps\python\Sidekick\personal_best"
Opening the file with Notepad, shows this:
€L68511 .
Avoiding that weird icons, the first 2 numbers are the seconds and third last numbers are the milliseconds of the best lap without doing cut, in that track (Monza Junior) with that car (Ferrari FXX K).
It would be possible then to load that file deppending of the car name and the track name and detect that best time in Simhub?
Something like this is on my head:
open file "assettocorsa\apps\python\Sidekick\personal_best\*[CAR_NAME]_[TRACK_NAME]*.ini" read the file and apply point or comma between 3rd and 4th number starting from right, so we have time in seconds (68.511) with the "Ferrari FXX K" on "Monza Junior", then we can transform this to time, 1:08:511. With that time formated, we can show Best absolute lap without doing cut, thanks to Sidekick is creating files of our best laps without doing cuts. With the same time in seconds (68.511) we can make our own delta, calculating estimatedLapTimeInSeconds - bestTimeInSeconds.
@bartun Maybe. Try to build the path to the file with the car model and track name.
Something like that:
readtextfile('d:\\...pathtothefile...\\personal_best\\'+$prop('CarModel')+'-'+$prop('TrackName')+'_pb.ini')
@romainrob Thank you so much, again. This formula works great , but finally I can't do it.
Sidekick creates other files but not the personal best files, but If i go to Content Manager > Lap Times > Sources, and I click on Export to Sidekick, then all the personal best times of all the cars in all maps appears in Sidekick folder, so I am gonna try to search in the assetto corsa folder any file that save all the personal best times.. crossing fingers.
I really need to have Personal best time + Personal best time delta instead of Session, but I don't know what to do. My brain is gonna explode. 😆 😆
Okay, new file found.
My Documents > Assetto Corsa > Personalbest.ini
It shows something like this:
[KS_FERRARI_FXX_K@KS_MONZA66-JUNIOR] DATE=1680542334000 TIME=58001 [KS_ALFA_ROMEO_155_V6@KS_MONZA66-JUNIOR] DATE=1680544212913 TIME=61494 [KS_AUDI_R8_PLUS@KS_MONZA66-JUNIOR] DATE=1680544860305 TIME=62898 [LOTUS_2_ELEVEN_GT4@KS_MONZA66-JUNIOR] DATE=1680545328561 TIME=57147
With this code, I was able to grab the TIME= of the specified CAR@TRACK in personalbest.ini and It was working, but I made a new personal best, and stopped working, now shows value 0.
root.BestLap = 0; root.Car = ucase($prop('CarId')); root.Track = ucase($prop('TrackCode')); var key = "[" + root.Car + "@" + root.Track + "]\r\nTIME="; var content = readtextfile('F:\\Documentos\\Assetto Corsa\\personalbest.ini'); var regex = new RegExp(key + "(\\d+)"); var match = regex.exec(content); if (match) { root.BestLap = parseInt(match[1]); } return root.BestLap;