[WIP] Race Engineer (Spotter) plugin for rFactor 2

Discussion in 'Other' started by cosimo, Mar 19, 2014.

  1. alpha-bravo

    alpha-bravo Registered

    Joined:
    Dec 22, 2012
    Messages:
    1,374
    Likes Received:
    31
    Wow :) ! Thank you Gerald !
     
  2. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    Here a description of the customization power of this spotter:

    First, the spotter need a main ini file named Spotter.ini
    Code:
    // if the vehicle class does not have it own parameter, the one in [DEFAULT] will be used instead. 
    // In addition to the predefined parameters, you can create your own parameters and use them as Inputs in the rules files.
    // Those parameters must be prefixed by "v:"
    [DEFAULT]
    Rules.file=DefaultRules.ini
    Sounds.subPath=Sounds/EN
    Mapping.VehicleClass.file=vehiculeClass.ini	// usefull for multi category (when the mod does not have already one class per category)
    maxDetailLevel=2
    v:breakTooHot=600
    v:breakTooCold=500
    
    // You can override any DEFAULT parameter in a section named as a rF2 Vehicle Class, for exemple
    // [Megane]
    // maxDetailLevel=2
    // v:breakThreshold=900
    
    As you can see, there is a [DEFAULT] section, and you can override any number of parameters in a section named with the VehicleClass provided by rF2 to the plugin.
    So it will be possible to point to another spotter rules, for vehicle classes who run in NASCAR.
    Here some explained parameters :
    • Rules.file : point to a file containing the spotter rules to apply (relative path from the Spotter directory)
    • Sounds.subPath : sub path to add to find sounds directory (usefull for multilanguage support)
    • maxDetailLevel : Each Event have a level, so this spotter will only analyse events having a detail value lower or equals to this max
    • Mapping.VehicleClass.file : point to a file providing category for each vehicle class. This is use to group best laps per category, indeed in endurance race, there is no reason to compare the best lap of a GT to a P2.
    • v:<name> : this allows to create any number of user defined variable and provide them as input of event evaluation. For example, the breaks temperature threshold (thanks to the overridable mechanism in this ini file, you can create a section for a given vehicle class, and set a nother value for a given user variable - ex: different threshold for different class cars)

    Now looking to the vehicleClass file (the provided one, is very simple as all cars are grouped into a single category) - if you want to provide me a customized one, don't hesitate (for example if you already do the job in my plugin TV)
    Code:
    // The [**DEFAULT**] is usefull for mono category config in case of you still want to display category informations - Those data are taken into account when there is no matching section equals to the rF2 vehicule class info
    [**DEFAULT**]
    category.name=***
    
    // each section must have the name of each rF2 vehicule class string (used for multi category race)
    //[Corvette ALMS GT2 2009]
    //category.name=GT2
    
    So when the plugin must compare your best lap, or any other relating timing comapraison, it will do it only with the other cars in the same category as you

    Now, we enter in the main subject, starting with the rules file (example with an extract of DefaultRules.ini)
    Code:
    [Main]
    Events.file=DefaultEvents.ini
    Rules.count=12
    
    // One section per rule
    // [Rule.1] for the first rule, [Rule.2] for the second rule, ...
    
    The [Main] section is very simple:
    • Events.file : the file containing the detail of each events (algorhytm engine)
    • Rules.count : the number of rules, so the spotter will read all section from [Rule.1] to [Rule.n]

    Then, you can define each rules. Here an example of the rule who compare your S1 time to your best lap S1
    Code:
    [Rule.1]
    Trigger=S1
    Event=SelfGapSector1
    Input1=SelfGap
    
    A rule can contain those parameters:
    • Trigger : When this rule must be evaluated
    • Event : The name a the event (in the event file) to evaluate
    • Input1 : the value of the first input provided to the event (optional, depends to the choosen event)
    • Input2 : the value of the second input provided to the event (optional, depends to the choosen event)
    • Input3 : the value of the third input provided to the event (optional, depends to the choosen event)
    A Trigger can be one of the predefined triggers (S1, OnPlaceChanged, ...)
    An input can be several think like a fixed value (10.3), a user defined variable (v:breakTempMinThreshold), or a predefined spotter variable (Laptime)

    So as soon as a trigger exist and a data is provided by the spotter, you can create any kind of event (it is the "near" 100% customizable) - but like all my tools, if a something is missing to achieve a work, i will add it - for now, its is only a first version of the plugins, so several rf2 data and triggers are still missing.

    Here what already exists as trigger and predefined variable
    Code:
    // Possible values for Trigger
    //     ScoreUpdate 		: correspond to a call to the UpdateScoring method of the plugin API (around every 0.5s) - WARNING: do not put too many rule with this trigger to avoid FPS loss
    //     AnySector 		: when the car reach a sector
    //     S1 			: when the car reach the sector 1
    //     S2 			: when the car reach the sector 2
    //     S3 			: when the car reach the sector 3 (just finish a lap)
    //     PlaceChanged 		: when you rank change
    //     StartLightGo		: When the starting light is green
    //     SectorFlagChanged	: When one of the 3 sector flag change
    //     NewBestLap		: When the beat the best laptime (all drivers best lap)
    //     NewCategoryBestLap	: When the beat "only" the category best laptime
    //     NewSelfBestLap		: When the beat "only" your own best laptime
    //     Finished			: When you finish the session 
    // ---------------------------------------------------------------------------------------------------------------------------
    // Possible values for Input1/2/3 
    //     <"hardcoded" number>	: such as -0.37, range is that of IEEE double-precision floating point number
    //     v:<name>			: one of the custom variable defined in the Spotter.ini file
    //     Session			: 0 - 13, 0=test day, 1=practice1 ..., 5=qual1, ..., 9=warmup, 10=race1..., 13=race3 
    //     Laptime			: your laptime of the just finished lap (if trigger S3), else it is the current laptime
    //     MyBestLaptime		: your current best lap (not yet updated in trigger S3, if you just beat it)
    //     Place			: your current position 
    //     LastPlace		: your last position 
    //     OilTemp			: your oil temperature (celcius)
    //     WaterTemp		: your water temperature (celcius)
    //     BreakTemp		: your breaks temperature (celcius) - (take the higher temperature of the 4 wheels)
    //     TireTemp			: your tire temperature (celcius) - (take the higher temperature of the 4 wheels - the center part of the wheel)
    //     TireInnerLayer		: your inner layer (before carcass) tire temperature (celcius) - (take the higher temperature of the 4 wheels - the center part of the wheel)
    //     TireCarcass		: your carcass tire temperature (celcius) - (take the higher temperature of the 4 wheels)
    //     TireTemp			: your tire temperature (celcius) - (take the higher temperature of the 4 wheels - the center part of the wheel)
    //     Fuel			: your fuel left (liters)
    //     FuelCapacity		: your fuel tank capacity (liters)
    //     FuelPerLap		: Fuel quantity used to completed the last lap - (updated at S3)
    //     RemainingLapsWithFuel	: Number of laps remaining before empty fuel (based on FuelPerLap) - (updated at S3) - equals to "1000001" if FuelPerLap is not yet computed
    //     RemainingLaps		: Number of laps remaining before the end of the session - (updated at S3) - equals to "1000000" if not yet computed
    //     NumberOfStartLight	: Number of light in the start sequence (track specificity)
    //     CurrentStartLight	: Current number of light (on) - if CurrentStartLight == NumberOfStartLight means the race start.
    //     Lap			: the current lap number (0 for the first lap)
    //     TrackLapDist		: The track lap distance (meter)
    //     LapDist			: you current lap distance (meter)
    //     LapDistRatio		: you current lap distance compare to the track lap distance(0.0 to 1.0)
    //     S1Flag			: 0 = no flag, 1 = yellow flag
    //     S2Flag			: 0 = no flag, 1 = yellow flag
    //     S3Flag			: 0 = no flag, 1 = yellow flag
    //     OldSelfBestLaptime	: my previous self best laptime (updated on trigger NewBestLap > NewCategoryBestLap > NewSelfBestLap - if you beat a any king of best lap only one will be triggered)
    //     OldBestLaptime		: the beaten best laptime (updated on trigger NewBestLap > NewCategoryBestLap > NewSelfBestLap - if you beat a any king of best lap only one will be triggered)
    //     SelfGap			: the gap to your previous best (updated at each sector)
    //     FinishStatus		: your finish status (0=none, 1=finish, 2=dnf, 3=dq)
    
    Now the most power full part of the spotter (this is based on the logic used by ISI in its own spotter, but in an enhanced way as i added several new features)
    Mainly, this logic allow you to define event parameters and then create any number of condition (if) and action. Here the exemple of the "SelfGapSector1" event, as it will be easyer to explain with an example:
    Note: the explaination is in the comments (// .......)
    Code:
    // Tells player a sector 1 gap (compare to s1 of self best lap)
    Event=SelfGapSector1 // Input1 = sector1 gap 
    {
      // Event properties (note that these are not applied if this event is played by another event)
      Detail=1  // Detail level (so this event will be evaluated as soon as the maxDetailLevel is t lest equals to 1 in the Spotter.ini
      Spacing=0.0 // Number of second to wait before another event of this type is evaluate (0.0 as this event is used only on Trigger=S1)
      Priority=1 // highest priority (used to priorize event in the awaiting queues - when several event occurs in the same time) - from 0.0 (lowest) to 1.0 (highest)
      Probability=1.0 // probability to evaluate this event (0.0 (never - 0%) - 1.0 (always - 100%)
      TTL=10.0 // Time to live (in seconds) in the awaiting queue before he is discarded - so if this time is reached without being yet evaluated, it is discarded
      Break=0.25 // number of second (pause) to wait before any other awaiting event is evaluated
    
      // Repeat until duration ends (Not yet supported)
      Repeat=Off
      Duration=0.0
    
      Volume=1.0  // volume from 0.0 to 1.0 (not yes supported)
    
      // Now the real algorhytm to see if a sound must be played and which sound(s)
    	Variable=Session       // set the working variable to the Session value 
    	{
    		Value=(>=0,<=8) { // check if we are not in WarmUp or Race
    			Variable=Input1   // set the working variable to Input1 (the rule file set "SelfGap" as input1)
    			{
    				Value=(>0,<=1.0) {  // look if the gap is positive and lower than 1.0s (so the spotter only speak if the gap is less than a second) 
    					File=slow_on_first.wav   // tell "Sector one is slower by..."
    					PlayEvent=Gap              // play the other event which is used to tell the gap value (using the working variable as Input1 of the event)
    				}
    				Value=(>=-1.0, <0) {  // look if the gap is negative and lower than 1.0s (so the spotter only speak if the gap is less than a second) 
    					Variable=Absolute {  // get the absolution value of input1 (need a positive value for the "Gap" event)
    						File=fast_on_first.wav   // tell "sector one is faster by..."
    						PlayEvent=Gap    // play the other event which is used to tell the gap value (using the working variable as Input1 of the event)
    					}
    				}
    			}
    		}
    	}
    }
    
    Now the Gap event who is used to tell the gap value. As in our example, the Gap event is played by another event, its own properties (Detail, Spacing, etc...) are ignored. Only the logic is taken into account, and the Input1 is the one inherited from the calling event
    Code:
    // Tells player a gap
    Event=Gap // Input1 = gap (speak only if gap < 30s)
    {
      // Event properties (note that these are not applied if this event is played by another event)
      Detail=1  // lap time is based on option, so this needs to be played at all detail levels
      Spacing=0.0
      Priority=1
      Probability=1.0
      TTL=10.0
      Break=0.25
    
      // Repeat until duration ends
      Repeat=Off
      Duration=0.0
    
      // Play introduction to laptime
      Volume=1.0
    
      // Variable used to choose one File to play for this Sound (Variable compared to Value)
      Variable=Input1
      {
        Value=(>0) { 
    		Value=(>0;<0.10) { File=gap_000.wav } // tell "less than 0.1 second"
    		Value=(>=0.1;<0.15) { File=gap_001.wav } // tell "less 0.1 second"
    		Value=(>=0.15;<0.25) { File=gap_002.wav }
    		Value=(>=0.25;<0.35) { File=gap_003.wav }
    		Value=(>=0.35;<0.45) { File=gap_004.wav }
    		Value=(>=0.45;<0.55) { File=gap_005.wav }
    		Value=(>=0.55;<0.65) { File=gap_006.wav }
    		Value=(>=0.65;<0.75) { File=gap_007.wav }
    		Value=(>=0.75;<0.85) { File=gap_008.wav }
    		Value=(>=0.85;<0.95) { File=gap_009.wav }
    		Value=(>=0.95;<1.5) { File=gap_010.wav }  // tell "less 1 second"
    		Value=(>=1.5;<2.5) { File=gap_020.wav }
    		Value=(>=2.5;<4.0) { File=gap_030.wav }
    		Value=(>=4.0;<5.5) { File=gap_050.wav }
    		Value=(>=5.5;<7.0) { File=gap_060.wav }
    		Value=(>=7.0;<9.0) { File=gap_080.wav }
    		Value=(>=9.0;<12.5) { File=gap_100.wav }
    		Value=(>=12.5;<17.5) { File=gap_150.wav }
    		Value=(>=17.5;<=25.0) { File=gap_200.wav } // tell "less 2 second"
    		Value=(>=25.0;<=30.0) { File=gap_300.wav }// tell "less 3 second"
    	}
      }
    }
    
    Voilà ! I think now, if your reach this point :), you understand the possibilities provided by the spotter.

    PS: I use sound of the rF1 spotter, hope he will have already all need sounds that will need in the future.
     
  3. alpha-bravo

    alpha-bravo Registered

    Joined:
    Dec 22, 2012
    Messages:
    1,374
    Likes Received:
    31
    Hehe paradise for customization :) I see I will have much fun and before much to learn :p

    For testing if changes in the ini are work as expected do I have to restart the rF2 session or is it enough to drive to pit switch to desktop change the value in the ini and switch back to rF2 and go on track again ?

    Would it be possible (from developers view) to include a voice trigger for example: designated push button for activate voice command like:
    "spotter" - "Fuel duration?" - spotter answer as defined in the ini for example "55l around 22 laps" or something else ?

    Last but not least.
    Gerald I have to say it again your plugins are always so well done.
    Many thanks for that.
    Now it will take some time to form a friendship with my personal spotter :D

    greets alex
     
  4. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    Thanks

    Not for now, but a key shortcut will be added to reload all ini files
    Once the spotter will be in a "finished" state, i will look to those kind of things and if it is possible to avoid conflict with Team Speak, for example.
     
  5. bwana

    bwana Registered

    Joined:
    Dec 25, 2011
    Messages:
    2,139
    Likes Received:
    1,040
    Wow Gerald, another fantastic creation..thanks

    Sent from my RM-821_apac_australia_new_zealand_218 using Tapatalk
     
  6. GauchoRS

    GauchoRS Registered

    Joined:
    Nov 23, 2011
    Messages:
    471
    Likes Received:
    9
    outstanding work and very very appreciated documentation, Gerald !!
    Thank you so much for your dedication !!
     
  7. baked bean

    baked bean Registered

    Joined:
    Jan 17, 2012
    Messages:
    1,306
    Likes Received:
    56
    This is fantastic, love it and thank you so much. :cool:
     
  8. alpha-bravo

    alpha-bravo Registered

    Joined:
    Dec 22, 2012
    Messages:
    1,374
    Likes Received:
    31
    Thanks for your answers and your statement to look into on a later timepoint.
    The plugin as it is now is a milestone and in the meantime we know how clean and fast your development projects are.
    To be honest sometimes you are faster with updates and new features to your plugins as I'm with understanding configuring and testing :D

    ps: please post a donation link.

    thx byyyyyy yours sincerely alex ;)
     
  9. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    Thanks and donation can be found in my own thread of other plugins
     
  10. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    New version Available

    - Added a configurable shortcup to reload ini files on the fly (default is : Right Alt + Up)
    - Add two new spotter events : "Driver behind you is faster by xxxs" and "Driver in front of you is slower by xxxs" every 3 laps (configurable)
    - Add a debugMode (who create a Spotter.log file near the Spotter.ini) when debugMode=1

    Note: Here the asked Donate link
     
  11. alpha-bravo

    alpha-bravo Registered

    Joined:
    Dec 22, 2012
    Messages:
    1,374
    Likes Received:
    31
    lol
    gerald I must admit "sometimes" was a big understatement :p

    thx for adding the link and THIS features it makes playing with settings and learning how the things work together much more comfortable:).
     
  12. Bjørn

    Bjørn Registered

    Joined:
    Oct 4, 2010
    Messages:
    1,821
    Likes Received:
    919
    I've searched the topic but haven't found anything about 64-bit... It doesn't work for 64, does it?
     
  13. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    Yes it works in 64bit and 32bits
     
  14. TIG_green

    TIG_green Registered

    Joined:
    Jul 21, 2012
    Messages:
    3,038
    Likes Received:
    44
    This sounds really cool. But I think I'll prefer to wait until you don't have to fiddle that much with sound volumes in order to hear it (difficult fix?).

    One more thing, my antivirus program (Norton) reported that SpotterPlugin_x64.dll is dangerous and deleted it :eek: something you can do about that? So atm I can't use it even if I would want to.
     
  15. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    It seems to be related to a choice made by ISI since an old build. I asked them if they can revert this spotter volume limit and wait their response.

    But i know some peolple found the my spotter volume enough without touching rF2 sound preset.

    No, and i know notron tell that about many plugin. I use as few API as possible so i cannot do anything about Norton. Maybe you can configure it.
     
  16. whitmore

    whitmore Registered

    Joined:
    Feb 26, 2012
    Messages:
    552
    Likes Received:
    142
    Greta work again Gerald. I can say I have no issues with the level of the sound. Spotter VOL 100 engine 30 Opposition 50.

    Question where do I find the specifics for the class name to enter into the class.ini file?

    Also will these INI files need to become JSON files?
     
    Last edited by a moderator: Sep 9, 2014
  17. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    I reach a limit, as i have a limited list of predefined sound, so i will not be able to have spotter sound for weather, contact, etc...

    I think i will use a "Text to Wav" Tools, like this site: https://www.fromtexttospeech.com
    I know it is not as natural/alive as a human people but it will let me done any kind of message.
     
  18. MMartin

    MMartin Registered

    Joined:
    Oct 30, 2010
    Messages:
    515
    Likes Received:
    4

    Nice job guys!
    Can we help with the sound? Can we create a library of live recorded sound (multilanguage)?
     
  19. Gerald Jacobson

    Gerald Jacobson Registered

    Joined:
    Jan 26, 2013
    Messages:
    827
    Likes Received:
    18
    It will be perfect, but i must be sure that the one who start to make a voice will be highly reacting to create sound i need asap and don't stop after few times, as i don't think having heterogenous voice between message will be sweet.

    So, no problemif people want to help, i will be very happy, but as you know (i think), i make upgrade very regulary until the "full" version is achieved, so i need reactvity for sound creation.
     
  20. MMartin

    MMartin Registered

    Joined:
    Oct 30, 2010
    Messages:
    515
    Likes Received:
    4
    Yes Gerald, I have suggested this possibility but I'm not the right person to do this job, just a suggestion for the community.

    In the mean time you can write down the list of file and the relative message ;)
     

Share This Page