The online racing simulator
Can someone explain Sub header (brackets) use?
Although I've been using and doing things in 'lapper' now for a couple of years, everything I've done is basically opening and closing buttons.

This has been fine for my needs, and has basically proved that you don't need to be a programmer of any sort of computer language to be able to change the look and feel of the interaction between an InSim like LFSLapper and LFS - although if you are a programmer then you've not only got a good head start, but you can simplify and condense things enormously - just look at my original Winnerflags.lpr to Gai's proper programmer version!

Anyway. Although I've used sub-routines to perform specific tasks, I've always had to play around with what would or wouldn't work within the brackets on the Sub header line.

I don't even know what the term is for that part of the sub procedure.

I'm now working on adding a drag race system to the layout that's currently on my server (just for fun and not the main reason for the layout), but am having problems with errors being thrown up regarding the sub-routine header lines.

Errors such as;
Quote :Syntax error in cfg file: Number of function argument not matche at line #146 in function 'se_dragrace' script aborted

For instance, I get that message if I do something like
CASE "!drag":
SE_DragRace(0,0)
and then start the sub-routine
Sub SE_DragRace($KeyFlags,$id)
or if I do
CASE "!drag":
SE_DragRace()
and then start the sub-routine
Sub SE_DragRace($userName)
Thinking about it, I realise that I have no idea what the brackets (to tell/warn lapper that it's the end of the header line of an event or sub-routine?), or even what the text in brackets (even if empty) are for.

I've seen all the following in use;

()
as in Sub MyTest()

( $userName )
as in Sub DisplaySpeed( $userName )

( $KeyFlags )
as in Sub Config_Pitboard( $KeyFlags )

( $KeyFlags,$id )
as in Sub OnConnectClose( $KeyFlags,$id )
- within a CASE command, this would likely be shown as OnConnectClose( 0.0)

I've also seen others used, such as;

( $id, $argv )
($userName,$argv)
($KeyFlags,$userName)


Can anyone explain what they are, how to use them, what's a $KeyFlag, an $id, etc?

Also, what to use, how, etc., when they are called from within another sub-routine or an Event?
Attached is part of my code, which as written does show the lights when I type !drag, and does not show any errors in the log, but any further sub-routines with nothing inside the brackets can then throw an error, not only on the sub-routine just added, but previous sub-routines that had no problems.

If I start using $userName within the brackets of this last sub-routine, I might get rid of the error for that particular sub-routine, but likely errors will still stay for earlier subs.
Attached files
drag.txt - 4.9 KB - 427 views
#3 - Krayy
Oh where to start...

Back in the bad old days of strongly typed languages, BASIC interprters ruled the earth and confused bedroom programmers all around the world with their subtle differences between Subroutines and Functions. In laymans terms a Sub (optionally) took some parameters and did some black magic with them and a Function (optionally) took some parameters and did some black magic and then told you what it did via a return value.

This odument iwll only talk about Subs and not Events. The definitions and parameters for the Events are predefined in lapper and cannot be changed. I have attached a handy reference to this post for you.

A GLscript Sub can do either of these scenarios so we don't have to worrry about whether we declare a particular piece of code as a Sub or Function. So with that history lesson out of the way, how the heck do we use them?

Glad you asked...firstly, let's talk about what types of Subs GLscript has...User Defined and Internal (these aren't the names that Gai uses for them it's just so that I can make a distinction. He probably calls them Peter and Mary, or Pierre and Marie, he being of the French/Italian persuasion).

A User Defined Sub is one that you create and then call directly from within your script, e.g:

<?php 
Sub NoParams 
() # A Subroutine that takes no parameters
    
privMsg ("We don't need no steeken parameters");
EndSub
...
    
privMsg ("I'm calling a Sub now");
    
NoParams;
    
privMsg ("I'm back! Let's go to the pub!");
...
?>

So in the code above, you create a Sub called NoParams and then you explicity call it from somwhere else in your script and it goes about it's business then returns to where you called it from.

An Internal Sub is one that you create the code for and the Lapper calls it from somewhere else, usually when you click a button:

<?php 
# This sub is called by someone clicking on a button
Sub ClickedOn $KeyFlags$id )
    
privMsg "Button clicked was " $id);
    IF (
$KeyFlags 1)
    
THEN
        privmsg 
("Left mouse click");
    ELSE
        
privmsg ("Right mouse click");
    ENDIF
EndSub

...
  
openPrivButton (MyButton50,50,11,8,1,-1,32,"Click Me"ClickedOn);
...
?>

When you click on the button, Lapper will then run the Sub called ClickedOn and pass it 2 parameters, $KeyFlags and $id. $id is simple enough, it's the name of the button which in this case is MyButton.

$KeyFlags is a little more tricky in that it is an integer (whole number) that will corresond to a value that is defined in InSim as:

<?php 
// CFlags byte : click flags

#define ISB_LMB            1        // left click
#define ISB_RMB            2        // right click
#define ISB_CTRL        4        // ctrl + click
#define ISB_SHIFT        8        // shift + click
?>

So if you right click on a button, $KeyFlags will be 2. If you left click while holding the Ctrl key it will be 5. If you left click while holding the Ctrl and Shift keys it will be ummm...8 plus 4, carry the 5, add 3 subtract the age of my dog...13! yeah, thats it. I'm sure it is. Easy huh?

Note: Have a look at my CIF module for handicap configs which has some interesting ways of handling those 2 parameters, as I use an underscore to separate parts of the button name that I can then use to bury other variables in, like the button number or racer UCID.

Coming up...we take a closer look at passing parameters, return values and does being able program actually make you more attractive to the ladies? (or men if you prefer, who am I to judge?)

So where we? Oh yes, parameters and return values. Take the code below:

<?php 
Sub TwoParams 
$param1$param2# A Subroutine that takes no parameters
    
privMsg ("I have 2 parameters " $param1 " and " $param2);
EndSub
...
TwoParams "foo""bar");
...
?>

This defines a Subroutine that takes 2 parameters and just prints them out. It doesn't matter what the parameter names are, you can use whatever you like but I prefer to use names that are significant to the purpose that they are to be used for.

Now this code:

<?php 
Sub UserIsAdmin
($userName)
    IF ( 
UserIsServerAdmin$userName ) == ||  GetPlayerVar($userName,"UCID") == ||  UserInGroup"superusers",$userName) == )
    
THEN
        
return(ToNum(1));
    ELSE
        return(
ToNum(0));
    ENDIF
EndSub
?>


Actually does something useful (I just cut & pasted this from the utils.lpr as it's Friday afternoon and I'm getting tired). It takes someones user name as a parameter and then uses that to see if the user is and administrator and then returns either a 1 or a 0. You can either call it and use it return value to populate a variable like this:

<?php 
$IsAdmin 
UserIsAdmin("krayy");
?>

or use it directly in the code like this:

<?php 
IF ( UserIsAdmin("krayy") == )
THEN
privMsg 
("Krayy is a god");
ELSE
privMsg ("No he isn't");
ENDIF
?>

Just remember that a return code can be a number or a string, although i have never tried an array...I'll save that for another thread.

Top tip: Look at other peoples code, particularly things like the utils.lpr as it has some easy to read examples of this sort of thing.

Good luck all!!
Nice write-up.

The bit about ( $KeyFlags, $id ) has enlightened me somewhat, as has other bits.

Quote from Krayy :I have attached a handy reference to this post for you.

Nothing attached.

Quote from Krayy :
Top tip: Look at other peoples code, particularly things like the utils.lpr as it has some easy to read examples of this sort of thing.

I do, I do!

I've no scruples about plagiarising public code if I can make sense of what it does (or is doing), and can make use of it myself.

Quote from Krayy :
Sub NoParams () # A Subroutine that takes no parameters
privMsg ("We don't need no steeken parameters");
EndSub
...
privMsg ("I'm calling a Sub now");
NoParams;


I've noticed that most people (actually, you might be the only one who doesn't), when calling a sub without parameters within another sub tend to put empty brackets after the sub name.

So your Sub NoParams () would normally be written as NoParams (); within another sub, but you've ignored the brackets.

Does that mean that if you've defined a sub without parameters, then if you then call that sub from within another sub, you can ignore the brackets?
#5 - Krayy
I think the brackets are optional, but yes for readability I would put them there.

BTW:

OnAcceleration( $userName );
OnAngleVelocity( $userName );
OnAuthAllowed( $userName );
OnAuthNotAllowed( $userName );
OnAuthReached( $userName );
OnBeginPit( $userName );
OnBeginPitWindow( $userName );
OnButtonFunction( $userName, $SubT );
OnCarReset( $userName );
OnChangePos( $userName, $lastPos, $currPos );
OnChangeTyres( $userName, $FL_Changed, $FR_Changed, $RL_Changed, $RR_Changed );
OnConnect( $userName );
OnDisConnect( $userName );
OnDistDone( $userName );
OnDriftLap( $userName );
OnDriftPB( $userName );
OnDriftResetScore( $userName );
OnDriftScore( $userName );
OnDriftTooLow( $userName );
OnEndPit( $userName );
OnEndPitWindow( $userName );
OnEnterPitLane( $userName, $reason );
OnExitPitLane( $userName );
OnFalseStartL1( $userName );
OnFalseStartL2( $userName );
OnFastDriveOnPitL1( $userName );
OnFastDriveOnPitL2( $userName );
OnFinish( $userName );
OnFlood( $userName );
OnGoodDrift( $userName );
OnIdle1( $userName );
OnIdle2( $userName );
OnLap( $userName );
OnLapperStart( );
OnLeaveRace( $userName );
OnMaxAllowedLapTime1( $userName );
OnMaxAllowedLapTime2( $userName );
OnMaxCarResets( $userName );
OnMaxFastDriveOnPit( $userName );
OnMaxNbInStunt( $userName );
OnMaxSessionLaps( $userName );
OnMSO( $text, $userName );
OnNameChange( $userName, $oldNickName, $newNickName );
OnNewGapPlayerBefore( $userName, $split );
OnNewGapPlayerBehind( $userName, $split );
OnNewPlayerJoin( $userName );
OnNotMatchFlags( $userName );
OnNotPitWindow( $userName );
OnPB( $userName );
OnPBQual( $userName );
OnPit( $userName );
OnPracStart( $NumP );
OnQualStart( );
OnRaceEnd( );
OnRaceStart( $NumP );
OnREO( $NumP, $ReqI, $currRaceOrder );
OnResult( $userName, $flagConfirm );
OnRotateCar( );
OnRotateTrack( );
OnSpbLast( $userName );
OnSpbSplit1( $userName );
OnSpbSplit2( $userName );
OnSpbSplit3( $userName );
OnSplit1( $userName );
OnSplit2( $userName );
OnSplit3( $userName );
OnSwearWords1( $userName );
OnSwearWords2( $userName );
OnToLowHandicap( $userName );
OnVoteEndChange( );
OnVoteEndReach( );
OnVoteEndZero( );
OnVoteQualifyChange( );
OnVoteQualifyReach( );
OnVoteQualifyZero( );
OnVoteRestartChange( );
OnVoteRestartReach( );
OnVoteRestartZero( );

FGED GREDG RDFGDR GSFDG