1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
Dismiss Notice
Like RaceDepartment on Facebook.

RSX / RCX & REX Files {Scripting}

Discussion in 'Racer Physics and Technical' started by QuadCoreMax, Mar 22, 2011.

  1. Hey everyone,

    I'm starting this thread because I can't achieve what I want, so I count on you to get some assistance...

    Feel free to post your code too, so we can integrate them in tracks...

    My code is just about checking if the car beats my actual record time (~36000 ms) on my LiL Lake track :

    Code:
    rcar $car
    int $bestlaptime = 36000
    int $currentlap
    string $messageBad = "You didn't beat my record !"
    string $messageGood = "Yeah, you did a new record time !"
    
    func int getLapTime () 
    {
        $currentlap = get $car bestlap
        return $currentlap
    }
    
    func void showCurrentLap ()
    {
        //trace value
        send "info " + getLapTime () to console
    }
    
    getLapTime()
    showCurrentLap()
    
    /*
        if $currentlap > $bestlaptime
        {
            send "info " + $messageBad to console
            //send "remove scripts" to console
        }
        else if $currentlap < $bestlaptime
        {
            send "info " + $messageGood to console
            //send "remove scripts" to console
        }
    */
    
    It's showing 0 ms & then disappear...
    What's wrong in my logic ? Do I forgotten something ?

    I have 1 triggerline just after the 1st spline & special.ini contains for the TL :

    Code:
    command=run data/tracks/LiL_Lake/scripts/bestlap.rcx
    
    Also, the 0 appears on my middle + right screen only, the 0 is white & black colored on the 2nd screen..
    Is it normal ?

    =================
    Surround Config
    3 x 19" DVI
    2 x ATI 4670 ~ 1.5 GB
     
  2. What a dumb....for sure the car variable !

    So here's the code, feel free to mod it, just replace your best time for your track & play with it !

    Code:
    rcar $car = get local car
    int $bestlaptime = 36000
    int $currentlap
    string $messageBad = "You didn't beat my record !"
    string $messageGood = "Yeah, you did a new record time !"
    
    func int getLapTime () 
    {
        $currentlap = get $car bestlap
        return $currentlap
    }
    
    /*
    func void showCurrentLap ()
    {
        //trace value
        send "info " + getLapTime () to console
    }
    */
    
    getLapTime()
    //showCurrentLap()
    
        if $currentlap > $bestlaptime
        {
            send "info " + $messageBad to console
            //send "remove scripts" to console
        }
        else if $currentlap < $bestlaptime
        {
            send "info " + $messageGood to console
            //send "remove scripts" to console
        }
    
    I'll probably create clean functions & then call them in specific scripts just to keep it tidy :)
    Quite cool for a first one, still have this black & white issue on 2 screens, hope to get a fix from someone here.

    ====================
    Now, as most of you know & with what Ruud/Mitch preparing for next releases, I like to build something solid for our pits which could be 'theoretically' re-used easily without any struggle.


    The big idea (as F1 2010 does) is :

    1. When car enters the pit zone (with TL at the beginning + at the end), cars should automatically slow down gradually from the current velocity to pit velocity. A slow motion effect could take place even here, more info below.

    2. The car should then stop exactly where I've set my pit pos (Tracked) as if you would press 'shift + p'. All that happens in a nice interpolated way. Hope to see all my AI on their pits positions in the next releases.

    3. Once the car has stopped, 2 guys begin to animate, one in the front & one in back refueling the car. Animation should last the time it needs to animate properly, maybe playing with 'realtime <factor>' from commands just to have a cool 'slow motion'.

    4. Once done, the 2 guys animate for the 'out' sequence (inverse of the 'in' sequence) & the car is ready to go. Sure, all that happens, disabling completely the car controls, idk, seems logical, or we would end up with chaos like fuel explosions in pits (for the future maybe, haha).

    5. Finally, the car gradually accelerates till reaching the pit velocity ~ 80 km/h (my actual pits are little ; 10 cars only, so hmm) & leave the pit area. The car controls are back to the user/player once out from the pits.

    6. Done ! A 'real' scripted pit area for Racer is born.

    ==============
    I really would like to have some advices & layouts since I'm not a everyday programmer...
    Suggestions, tips & all that that are welcomed !

    I'm almost sure I forgot something in the logical process, so feedback my ideas please, sure you better know exactly Racer limitations/scripts etc...
     
  3. Interesting that you don't use while 1 in your script and you in fact run it once per lap. Hadn't thought of that yet.

    w.r.t pits, they really shouldn't be scripted. (at least as far as you've gone)
    Sure, have animated guys and everything...but don't make the car automatically slow down for the pits. Have a script to check your speed and display it, also have the pit speed limit displayed - somewhere before the actual pit lane speed limit is enforced. Then call a black flag if the speed limit is broken within the pit lane. I'm pretty sure there's a console command to show a black flag. You could also have another script run as you're exiting the pits to make sure you exit safely - i.e. don't cross the line prematurely

    Stuff like that is much better than a fully scripted pit IMHO. It means there's much more of a dynamic to the race then. Otherwise everyone's pit stop will be exactly the same time (ignoring what actually happens during the stop)

    A good start to scripting though. I look forward to more.
     
  4. The script doesn't work as I expected, hmm...
    Can we convert types, from 'string' to 'int' ?
    Because right now, once you've beat the 36 s & then drive another round under 36 s, the wrong message is output. Since the 'info <text>' command displays text white on black, on the 3 screens the underlying black layer is offset to my right screen, if that could be fixed in future...still with 1 monitor no problems of displaying text as it should.

    Here's the function which makes problems :

    Code:
    laptime (int) to string
    Returns:
    string
    Comment:
    Converts laptime (ms) to a string
    
    Ok, the console command 'flag <type>' don't work as I would imagine, grrrr, even if I set all the stuff it requires, like 'declare pit in/out' + 'declare pit in/out speedlimit'. I guess it comes from the fact that the pit lane doesn't own any splines like the main road, so that could be 1 reason why...idk why but I can't set any speed limit neither (manually in special.ini) so that's wacky actually speaking, really need this to be fixed !

    Originally, I thought I would just script the pits with 1 easy command/control => 'shift + p' which works perfectly well, only works for the 1st 'declare pits pos' from Tracked as stated before. That is quite important for the animations to align them correctly with the car. Have some marks on the road to help myself & from there I've created the pits positions.

    Since that would look kind of ugly, because once the 'shift + p' controls triggered from the TL which activates it, that would just bring the car in one step to my pit position, without actually going thru the whole pits. For now, my 1st pit is created at the end of the pits lane...+ for sure, it needs absolutely some constraints/conditions to avoid too much chaos, so some rules scripting seems to be quite important.

    I hope you understand what I mean.

    I really want something more similar to F1 2010, which imho was quite nicely thought...
    Anyways, let's begin from the start & try to do it the easy way for testing purposes, how do I trigger controls (shift + p) ? How would it look like in our custom rsx script ?

    Code:
    is key (int) pressed
    Returns:
    int
    Comment:
    Is key pressed (range 0 to 255).
    
    ASCII LookUp Table :
    http://asciitable.com/

    I guess something with '15' & '80'...I did a try but wasn't that successful, hm...:frown:
     
  5. what you can do to test what input is given, is just iterate the entire list.

    from the top of my head:
    Code:
    int $c=0
    in $score=0
    for $c<256 do ++$c
    {
      if is key $c pressed 
      {
        paint $c at float[2]{10,30*$score}
        ++$score
      }
    }
    
    I don't know how fast this is going to be now, but the virtual machine in the next release is going to be much faster



    The function 'laptime (int) to string' just formats a laptime in ms to something like "1:34.548". int to string or string to int conversions are done implicitely. You can pass a string as an integer and the string will be converted to a int automatically.

    Nice project Quadcore, dont hesitate to contact me when you need some help !

    PS: I think the next release of Racer will support better speed limiting .. Ruud has been working on it
     
  6. Thanks Mitch, your code works & shift + P would be 16 + 80 in ASCII.

    Now, I'm wondering how do I set my car pos, it doesn't seem to exist this function, so something like that would be practical for us :

    Code:
    set (rcar) AI pos (float[3])
    Comment :
    Sets AI of given car at given pos
    
    set (rcar) AI rot (float[3])
    Comment :
    Sets AI of given car at given rot
    
    get (rcar) AI pos (float[3])
    Returns float[3]
    Comment :
    Gets AI of given car at given pos
    
    set (rcar) pos (float[3])
    Comment:
    Sets position for given car.
    
    set (rcar) rot (float[3])
    Comment:
    Sets rotation for given car.
    
    set (rcar) scriptcontrolled (int)
    Comment:
    Set if this car is controlled by the script (pos/rot).
    
    
    I was thinking, when I pass the pit TL (triggerline), my AI would go on. A message would be output, to tell the driver is entering the pit zone.

    Then, from the new functions above, I would interpolate the 'hardcoded' AI positions (which I've extracted manually from the NullPoint value from Racer debug 'surface') ~ 8 positions in total ; I would need some help on how to do it the most efficiently way.

    Finally, the out TL would deactivate AI & output a message which tells the driver that pitting went OK. Those could be mapped to a custom rex file to avoid overloading the rsx/rcx file.

    Notice with those new functions, we could also create 'custom' AI drivelines...& create some random AI behaviours.
     
  7. About the scripts functions & types, they're really great, & lots of ways are thinkable of achieving the same result, that's why I opened this thread.

    For example, (for future or maybe already do-able now) setting a new spline file in the track which would go thru the pits & use it, to script the AI behavior, could be one way too.

    Really interesting :)
     
  8. We already have something in the pipeline for that .. Something really cool ! Wait and see !! ;)
     
  9. I feel the rumble of a large tsunami-like learning curve approaching... Head for the hills!
     
  10. Since this is the scripting thread...And I can't think straight atm...asking for the collective to weigh in.

    So the mp4-12c has the active air-brake, this is it working in-game atm:


    Using this code:
    Code:
    rcar $car=get scriptowner car
    rcarmodel $wing = get generic model 0 of $car
    set $wing scriptcontrolled 1
    rcarmodel $wingstruts = get generic model 1 of $car
    set $wingstruts scriptcontrolled 1
    
    float $brake = get $car brake
    float $vel = get $car tachovelocity
    int $ABpos = 0
    int $time = 0
    int $deltatime = 400
    
    
    	  if $vel<10 {
    	  $ABpos = 0
    	  paint $ABpos at float[2]{30,10}
    	  } else if $brake!=0 {
    	  $ABpos = 2
    	  paint $ABpos at float[2]{30,10}
    	  } else {
    	  $ABpos = 1
    	  paint $ABpos at float[2]{30,10}
    	  //paint interval at float[2]{300,10}
    	  }
    	  
    	 
    	 if $ABpos>1 {
    		  //wait 4
    		  set $wingstruts 	position float[3]{0		,0.18       +(0.15*$brake)	,-2.074}
    		  set $wing 		position float[3]{0.03	,0.42       +(0.15*$brake)	,-2.05}
    		  set $wing 		rotation float[3]{0		,1.047      *$brake			,0}
    		  
    		  if $vel<35 {
    		  //paint "lower" at float[2]{200,10}
    			int $vara=0
    			while $vara < 40 do ++$vara
    			{
    				wait 0.05
    				set $wingstruts position float[3]{0		,0.33	-(0.15*$vara/40)		,-2.074}
    				set $wing 		position float[3]{0.03	,0.57	-(0.15*$vara/40)		,-2.05}
    				set $wing 		rotation float[3]{0		,1.047	-(1.047*$vara/40)	,0}
    				paint $vara at float[2]{50,250}
    			}
    		  }
    		
    	 }
    	 else {
    	 
    		set $wingstruts position float[3]{0,0.18,-2.074}
    		set $wing position float[3]{0.03,0.42,-2.05}
    		set $wing rotation float[3]{0,0,0}
    	 
    	 }
    
    However I'm wanting to use a skinned mesh from Max (i.e. bones controlling the movement of the wing...this way I can correctly time the raising and lowering of the wing [i.e. it takes 700ms for the wing to raise and a few seconds I think for it to lower - not sure on the lowering time though])

    Currently the script obviously just uses the brake pedal position whereas it needs to realise what "heavy braking" is - how should I define that? Pedal pos>50% or similar
    Also my speeds are probably wrong...I think I just set them for testing.

    However all that's well and good but I want to play an animation, not have to worry about all that scripting about angles and stuff...the animation part is easy, it's the getting it working the way I want that I'm somewhat stumped by. Is it possible to pause an animation sequence part-way through? i.e I have one sequence of the wing raising and I'm able to have it paused at the start (starting low position) braking occurs, playback begins - wing fully deploys, playback stops then playback plays backwards as brake pedal pos. lowers?

    Either that or I have a sequence of it raising, a sequence of it raised that lasts basically indefinitely (what's the longest sequence length allowed? Does it add more data the longer the sequence or is it just the movement that changes sequence file size?), a sequence of it lowering (since it takes a few seconds IIRC) and finally a sequence the same length of the raised seq. that's in a fully un-deployed position.

    THEN after all of that, I need to ask how the hell we integrate animated generic objects...since I can't find the documentation for that.
     
  11. Stereo

    Stereo
    Premium Member

    To do the animation, hmm...

    I guess I have a couple thoughts on that, which depends how the scripting system works. Really need to just get my hands dirty, write some scripts myself so I can test things... which would require me stop being lazy about learning how to use them. Anyway.
    1 - use while loop within the script to raise/lower at a predetermined rate, so long as braking stays past some limit. Eg. the 0.05 second wait, then raise it 1/x degrees, etc.
    This depends on how the script "update" method works: is it called every time paint goes off, or does it wait until the script finishes executing.
    Anyway, the result would be a while loop, where the condition is that brakes are held down - followed by a for loop, which lowers down the wing again slowly.
    2 - set up some external variable determining wing height. Paint script just reads the variable and adjusts wing to match. External script does physics calculations, smoothly raises/lowers, etc. (since eventually we would want movable wings to also move aerodynamics).
    This would need some variables to be initialized once, then updated dynamically. Not entirely sure how to do this either, but seems like it's quite straightforward.


    In fact, something that would be equally good for testing this is a key to open the doors (or trunk). Should press it once to trigger an opening animation, not just have it open/shut instantly. Or possibly have it open while the key's held down, then shut again. Hrm. Gotta decide if I want to re-export the Aronde right now with generic objects for the doors/trunk, or wait until I get more modeling work done.
     
  12. Freaking cool, Camsinny, I love it ! :)

    The time used for raising & lowering the wing could use a 'factor' or 'ratio' in your script, so we can decide the speed movement of the wing. In Racer script functions, there's a 'simtime' & 'timeline' that could be used. This factor would depend on the car acceleration/deceleration, so the more acceleration you have, the quicker the wing gets to its 'maximal' height position, when the inverse occurs, then it'll just pop up slower.

    The "heavy breaking" is just a ratio, isn't ? Could be defined as speed/braking, the more speed you have & more braking => heavy ; the inverse case, the more speed + less braking => soft braking, something in this direction ?

    The pedal pos, you're right, we could really use ALL debugging values from Racer (ctrl+1..ctrl+9) in our scripts, the pedal pos is there => ctrl + 8 in controls...depends on the profile1.ini file too.

    I know what you mean with scripting animation in 3D space, can become quite difficult to manage in a manner we want...Anyway, it's more powerful, more easily upgradable & more CPU/FPS friendly ?...If you had 3 sequences, one for the raising & lowering + one for the 'idle' state, you still would need some-kind of a coefficient as I described before, something relative to the car velocity & acc/decc.

    AFAIK, the length of animation can last some minutes from my testing...still be careful cause 3DS Max will take huge amount of time generating it & Racer could drop in performance because of the huge anim file size reading when triggered by the scripts. It's also bones keyframes dependent.

    Lastly, it's true, we need some more info, Racer.nl needs to update faster, so we know what's the 'actual' standards & be able to implement all available features. About the animated generic objects, Mitch/Ruud are working on them afaik...

    Great stuff you're doing !!
     
  13. How's your other script looking like ?
    To get some controls over animations, we only have the console commands with play/stop/reset/loop functions, but we can't use them in our car.ini files for now...
     
  14. Well I don't have an updated script because I'm unsure of how exactly to do the animation. Aren't there flags or something for the type of animated generic object?
    Or did I dream about that? O.o

    Lack of sleep is seriously hurting my thinking atm...but keep those ideas coming. The speed/braking or braking/speed seems like a somewhat logical solution. The brake pedal pos is essentially the same as the braking amount which is 0...1 and is in my $brake var: float $brake = get $car brake

    I'd assumed I'd need probably 4 sequences: raising, lowering, up and down; was just hoping for a more eloquent solution.

    I have this for the lowering mechanism. Perhaps another use would be a wait function after the airbrake is applied...I'm sure it would stay up for a certain amount of time before dropping rapidly.
    I guess the main problem now is that I haven't seen any footage of the airbrake in action. If I could have a few good minutes of it going up and down it'd make it a lot easier :)
     
  15. [​IMG]

    It also works here, had to change some of your code to get it working, I also extracted the wing + strut polies & exported them from WC {0,0,0} with their CoG/PP re-centered. I'm struggling with the rotation & the re-centering of the PP + placement at 0,0,0 doesn't help either, hm....Everything seems to be related to the 'Nullpoint'...

    2 codes : 1 rex + 1 rsx/rcx

    oncar.rex :
    Code:
    ; This script is run right after loading each car
    echo OnCar.rex
    
    run data/tracks/LiL_Lake/scripts/airbrake.rcx
    
    airbrake.rsx
    Code:
    rcar $car = get local car
    
    rcarmodel $wing = get generic model 0 of $car
    set $wing scriptcontrolled 1
    rcarmodel $wingstruts = get generic model 1 of $car
    set $wingstruts scriptcontrolled 1
    
    //int $maxvel = 360 
    //int $time = 0
    
    while 1
    {
        float $vel = get $car tachovelocity
        int $c=0
        
        for $c < $vel do ++$c 
        {
        float $brake = get $car brake
        set $wingstruts position float[3]{0, 0.463 + (0.162 * $brake), -1.290}
        set $wing         position float[3]{0, 0.619 + (0.162 * $brake), -1.303}
        set $wing         rotation float[3]{0, 0.01 * $brake, 0}
        //wait 5
        }
        
        interrupt
    }
    
    Was thinking yesterday, looking at the debug screens, the output aero wings values could be used (graph step min max..) by our scripts, to get a more realistic behavior...

    Also, did anyone tried to use rtex or file ?
    Was thinking about creating some sort of Pacejka code which would iterate thru coeff value available range [min, max] in car.ini.pacejka for a certain interval of time, to test quicker all kind of curve variations. :)
     
  16. Another 'dynamical wing', this time velocity based, gets really nicely interpolated...

    Code:
    // Dynamical Wing for Racer 0.8.32
    // 2 generics models 0 & 1 => wing & struts
    // Velocity based
    
    rcar $car = get local car
    
    rcarmodel $wing = get generic model 0 of $car
    set $wing scriptcontrolled 1
    rcarmodel $wingstruts = get generic model 1 of $car
    set $wingstruts scriptcontrolled 1
    
    int $maxvel = 360 
    //int $time = 0
    
    while 1
    {
        float $vel = get $car tachovelocity
        float $brake = get $car brake
        
        int $c=0
        for $c < 1 do ++$c 
        {
    
        set $wingstruts position float[3]{0, 0.463 + (0.162 * ($vel / $maxvel)), -1.290}
        set $wing         position float[3]{0, 0.619 + (0.162 * ($vel / $maxvel)), -1.303}
        //6 degrees = 0.104719755 radians around Nullpoint
        set $wing         rotation float[3]{0, 0 + (0.104 * ($vel / $maxvel)), 0}
        
        }
        
        interrupt
    }
    
    $maxvel is your maximal car velocity in km/h
    0.612 is the dynamical height range where wing moves up & down

    We might need more Racer car/track events for our scripts !
     
  17. Shouldn't need the oncar script...anything in your scripts/paint(or physics)/ folders are run automatically. Velocity based is interesting, though it probably makes sense for it to be inverse speed, I.e. No wing at high speed and lots of wing at low speed...don't want too much drag holding you back ;)

    All this should probably be in the scripts/physics dir. Currently I've got it in paint but only cause it was one of my first scripts.

    No one knows anything about getting skinned generic objects to work?
    If I can figure that out I can move forward.
     
  18. hopefully you talking about it, actually I have the rsx/rcx files in my_track/scripts folder & it works too...

    About car skinned generic meshes, they don't work for now as Mitch explained, I already tried some crazy stuff...maybe I missed something somewhere..but actually speaking I can't make it work.

    What a story to set the wing values, I hope they'll fix the PP/CoG of generic objects, so they behave 'relatively' to their original 3D PP when doing rotations...

    For example, for doors animation, that could ease our work....

    Was also thinking, with car scripts, the 'rumbling' of the exhausts can be quite easily done, same for antenna, all of them might be animated with velocity in a certain range at a certain interval....
     
  19. Could you explain what you did? At least if it's not enabled in this version I can have it ready for the next if I go through all the steps...
     
  20. I tried to put another character in my co-pilot seat... & you probably meant the pbody/rmovable types ?

    About skinned objects, apart from testing movables => primitives, I didn't test them with scripts.
    I really need to test out all script features to know what's actual do-able & get a big picture...

    What's exactly the problem with your skinned mesh & your code ?