Register    Login    Forum    FAQ    PinSimDB.org

Board index » Resources » Tutorials, how-to's, bug report and docs




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Wecoc's Future Pinball Scripting Guide
 Post Posted: Sat Jun 13, 2015 3:05 am 
Offline
User avatar

Joined: Fri Sep 09, 2011 9:14 pm
Posts: 142
Wecoc's Future Pinball Scripting Guide (PART 1)


This is a tutorial for those who already know the basics about FP scripting.
So please if your don't know how to do things like this, look for a more basic script:

Image

Also first of all I want to recommend these other tutorials, if you never read them. They are great.

Big Draco's FP guide
MadMax's Quick Future Pinball Scripting Guide

The tutorial will have two parts, and I don't know exactly when will I be able to do the second, so please be patient with that.
I have to say my english is not the best, but I believe you will understand me...

Well, let's start.

1. Script Structure

The script structure on FP is not difficult. It's based on methods, which are defined, generally, using Sub.

Image

So that's the point, you call the method and everything inside it is executed.

Furthermore, these can have arguments, which work like variables and make things easier to define what the method has to do exactly.

Image

I know you already knew that. But apart from Sub there is also Function.

When you call a Sub, what it does is making some things in a row; turns lights on, adds score... whatever, but it does not return any value by itself.
Function works like Sub but returns a value, so you can use it like some sort of variable.
To do so you have to equalize it to a value, certainly like a variable.

Image

The most common usage, as in the example, is defining it by True or False depending on some factors, so later you can use it as a shortcut inside If, to check all directly.

Image

Also, Function can also have its arguments.

Image

As a side note, Exit Sub is used to skip the rest of the process of the method in a certain case, it literally exits the Sub.

Image

Function always has to return a value, so it makes no sense a 'Exit Function'.

2. Loops

A loop allows to do something lots of times in your script, and reduce the number of lines of the code.
I'm not good at explaining this, but you have to understand they will be carried simultaneously, because the reading speed of the code is very high.
If you want some things to happen not simultaneously in a row, you have to use Timers.

I will not talk about all the loops but the most common.

The most known loop is For and has this structure:

Image

As you can see it uses a variable as a counter, which has to be defined previously, and has a starting point and a fixed end point. By default, the counter increases by 1 but you can define the Step manually.

Image

As a special case, you can use Each with For, when you use Arrays. Each takes each value of the Array and uses it as a variable.
I guess you will understand it better with the example:

Image

Another interesting loop is While

While repeats our code while its condition is true, so doesn't have a fixed end point like For.

The next example uses a counter which increases, and the loop runs until his counter equals our defined max.
It's just one of a lot of different examples we could do with this type of loop.

Image

Before I talked about Exit Sub to abort a Sub. You can also use Exit For to abort a For loop and Exit Do to abort a Do type loop (While can be called also using Do - Loop).

Image

3. Defining a Class

Although it is not particularly common, defining a Class on FP can allow you to define lots of properties which can make your code easier to manage.
Class is used to group some methods which will be used only on certain objects defined previously.

Before talking about how to define a class, I want to talk about the object classes. Every object of the table is part of an internal and unmodifiable class defined by the program.
You can't modifiy the class but use its methods, directly on the object (SolenoidOn, Frame ...)

The class gives identity to the object; the code can differentiate the type of object because its class.
To do that you can use Type and TypeName (TypeName returns the Type as a String)

Imagine you have a light on the table, Light1. To check what type of light it is on the script is this easy:

Image

But not only that, you know a variable can be a such amount of different things and you can't manage all the same way. Every one of these are different types of objects:

Image

And in short that's what a Class is.

Creating your own Class is easy. You use Class - End Class and all its methods and variable will be inside that.
Also, you have to define an object which will be your class, so you can apply on it all the class methods.
To define the object you use Set. See the example below:

Image

As you can also see on the example, variables can be Public or Private.

Public (which is the same as Dim) will define a variable that can be used inside the class and also outside, but in different ways. Inside the class it's like any other variable, but outside it's applied on the object as shown in the example. You can get and set new values to the variable without getting any Error message.

Private can only be used inside the class, that's why if you try to use them like they were public, you get an Error.

And exactly the same with Sub and Function, you can define a Public Sub (it's the same as just write Sub) or a Private Sub.

Image

Apart from this you can also define Property. Property does exactly the funcion of a variable but will make other changes any time you change its value.
Property can use Get if you only want to get a value (not so useful), Let if you want the capacity to modify it as a public variable, and Set if you want to define it as an object.

On the next example you get an Error if you try to modify a Property which was defined only with Get.

Image

And on the next example, Test.UpdateInterval always equals Light1.UpdateInterval and everytime you change Test.UpdateInterval, Light1.UpdateInterval and Light2.UpdateInterval also change automatically.

Image

4. Eval and Execute

Eval and Execute are two internal methods which do basically the same. They read a string as it is part of the code, so if you write on the code Eval("Light" & 1) it's the same than writing Light1.
You don't need to think so much to see why it is really useful.

Image

Eval usually is used when the variable part of your line is short, and Execute when all the line depends on one or more variables.
Also, Eval can be used inside a condition. My recommendation is to use always Eval.

Because what is inside the Eval or Execute are strings, you can't put a string between the " directly, except if you use two ("").

Image

-----------------------

And that's all!
Hope it will be useful. If some has any question don't hesitate to ask.


Top 
 Profile  
 
 Post subject: Re: Wecoc's Future Pinball Scripting Guide
 Post Posted: Sat Jun 13, 2015 10:01 am 
Offline

Joined: Mon Jan 27, 2014 12:36 pm
Posts: 2855
Location: Ontario, Canada
Thanks Wecoc !!!
I understood some of it :)
It's a great reference


Top 
 Profile  
 
 Post subject: Re: Wecoc's Future Pinball Scripting Guide
 Post Posted: Sat Jun 13, 2015 4:56 pm 
Offline
User avatar

Joined: Sun Oct 05, 2014 11:57 pm
Posts: 405
Gimli wrote:
Thanks Wecoc !!! I understood some of it :) It's a great reference


:) Same here. Good reference. Some is more complex. Very good guide.


Top 
 Profile  
 
 Post subject: Re: Wecoc's Future Pinball Scripting Guide
 Post Posted: Mon Jun 15, 2015 1:17 pm 
Offline
User avatar

Joined: Fri Sep 09, 2011 9:14 pm
Posts: 142
Wecoc's Future Pinball Scripting Guide (PART 2)


This second part of the guide is focused on how to work with Strings and Numerics, which are the most important types of variables on our code.
I will also talk a bit more about Arrays in the end.

A String (Str) is a text, goes in quotes ("), and is displayed purple-pink in the code.
A Numeric (Num) is a number, and is displayed cyan in the code.

Image

Numerics can be positive or negative, they can have or not decimals, and there are different types depending on how big they can be.
But to manage pinball data (score, player ID, current ball ...) we will practically always use short positive integer numbers; Integers.

You can switch the type of the variables (or make sure you are using the right type of variable) using type conversion functions.
The most used for us will be CInt (convert to Integer) and CStr (convert to String). Some of others are not valid in FP.

Image

Obviously if we try to convert to Integer a non numeric text, we get a error.

So with this introduction given, I'll focus on explain how to control Strings and Integers.
They both have their own methods and functions, but since you can change their type manually, the methods can be equally used in they both.

5. Strings

A String is any text. They are case-sensitive, so "A" does not equal "a".

The most basic fact; the Strings can be checked using = and can be concatenated using & as you can see in the example.

Image

The most interesting when using Strings is knowing how to divide them in "Substrings", so with that control what's on there exactly, character by character.
This is what Mid do.

Mid is a function which requieres a string, a value indicating the index of the first character we will get of the string (being 1 the first one), and an optional value of characters we take of the string.
If we omit this last number Mid takes all the chr until the very end of the String.

Image

Along with Mid another interesting thing to get is the String length. We use Len.

Only with these two methods we can do lots of things on our Strings. I'll show you some examples so you can see the high potential of these two methods (and how to use them).
The examples are other similar functions which can be applied on Strings once defined. You can use them if you need, they are independent.

Code:
'-----------------------------------------------------------------------
' Insert String
'-----------------------------------------------------------------------
' InsertStr(String, Integer, String)
' Example: InsertStr(" Pinball", 0, "Future") => "Future Pinball"
'-----------------------------------------------------------------------

Function InsertStr(ByVal sString, ByVal index, ByVal chr)
   InsertStr = Mid(sString, 1, index - 1) & chr & Mid(sString, index)
End Function

'-----------------------------------------------------------------------
' Count character (or string)
'-----------------------------------------------------------------------
' CountStr(String, String)
' Example: CountStr("Hello", "l") => 2
'-----------------------------------------------------------------------

Function CountStr(ByVal sString, ByVal chr)
   Dim counter
   counter = 0
   Dim i : For i = 1 To Len(sString)
      If Mid(sString, i, Len(chr)) = chr Then
         counter = counter + 1
      End If
   Next
   CountStr = counter
End Function

'-----------------------------------------------------------------------
' String Index (Left)
'-----------------------------------------------------------------------
' LStrIndex(String, String)
' Example: LStrIndex("BlindManKind", "ind") => 3
'-----------------------------------------------------------------------

Function LStrIndex(sString, chr)
   Dim index
   Dim i : For i = 1 To Len(sString)
      If Mid(sString, i, Len(chr)) = chr Then
         index = i
         Exit For
      End If
   Next
   LStrIndex = index
End Function

'-----------------------------------------------------------------------
' String Index (Right)
'-----------------------------------------------------------------------
' RStrIndex(String, String)
' Example: RStrIndex("BlindManKind", "ind") => 10
'-----------------------------------------------------------------------

Function RStrIndex(sString, chr)
   Dim index
   Dim i : For i = 1 To Len(sString)
      If Mid(sString, i, Len(chr)) = chr Then
         index = i
      End If
   Next
   RStrIndex = index
End Function

'-----------------------------------------------------------------------
' Substitute String
'-----------------------------------------------------------------------
' SubStr(String, String, String)
' Example: SubStr("Wizard", "W", "L") => "Lizard"
'-----------------------------------------------------------------------

Function SubStr(ByVal sString, ByVal chr, ByVal chr2)
   Dim NewString
   NewString = ""
   Dim i : i = 1
   While i < Len(sString) + 1
      If Mid(sString, i, Len(chr)) = chr Then
         NewString = NewString & chr2
         i = i + Len(chr)
      Else
         NewString = NewString & Mid(sString, i, 1)
         i = i + 1
      End If
   WEnd
   SubStr = NewString
End Function

'-----------------------------------------------------------------------
' Delete String
'-----------------------------------------------------------------------
' DeleteStr(String, String)
' Example: DeleteStr("Wizard", "iz") => "Ward"
'-----------------------------------------------------------------------

Function DeleteStr(ByVal sString, ByVal chr)
   Dim NewString
   NewString = ""
   Dim i : i = 1
   While i < Len(sString) + 1
      If Mid(sString, i, Len(chr)) = chr Then
         i = i + Len(chr)
      Else
         NewString = NewString & Mid(sString, i, 1)
         i = i + 1
      End If
   WEnd
   DeleteStr = NewString
End Function

'-----------------------------------------------------------------------
' Justify String (Left)
'-----------------------------------------------------------------------
' LJustStr(String, Integer, String)
' Example: LJustStr("Test", 10, " ") => "Test      "
'-----------------------------------------------------------------------

Function LJustStr(ByVal sString, ByVal TotalLen, ByVal chr)
   Dim NewString
   NewString = ""
   If Len(sString) < TotalLen Then
      Dim a
      a = TotalLen - Len(sString)
      NewString = NewString & sString
      Dim i, si
      i = 1 : si = 1
      While i < (a + 1)
         NewString = NewString & Mid(chr, si, 1)
         i = i + 1 : si = si + 1
         If si > Len(chr) Then si = 1
      Wend
   Else
      NewString = sString
   End If
   LJustStr = NewString
End Function

'-----------------------------------------------------------------------
' Justify String (Right)
'-----------------------------------------------------------------------
' RJustStr(String, Integer, String)
' Example: RJustStr("Test", 10, " ") => "      Test"
'-----------------------------------------------------------------------

Function RJustStr(ByVal sString, ByVal TotalLen, ByVal chr)
   Dim NewString
   NewString = ""
   If Len(sString) < TotalLen Then
      Dim a
      a = TotalLen - Len(sString)
      Dim i, si
      i = 1 : si = 1
      While i < (a + 1)
         NewString = NewString & Mid(chr, si, 1)
         i = i + 1 : si = si + 1
         If si > Len(chr) Then si = 1
      Wend
      NewString = NewString & sString
   Else
      NewString = sString
   End If
   RJustStr = NewString
End Function

'-----------------------------------------------------------------------
' Center String
'-----------------------------------------------------------------------
' CenterStr(String, Integer, String)
' Example: CenterStr("Test", 10, " ") => "    Test   "
'-----------------------------------------------------------------------

Function CenterStr(ByVal sString, ByVal TotalLen, ByVal chr)
   Dim NewString
   NewString = ""
   If Len(sString) < TotalLen Then
      Dim a
      a = Round((TotalLen - Len(sString)) / 2)
      Dim i, si
      i = 1 : si = 1
      While i < (a + 1)
         NewString = NewString & Mid(chr, si, 1)
         i = i + 1 : si = si + 1
         If si > Len(chr) Then si = 1
      Wend
      NewString = NewString & sString
      i = 1 : si = 1
      While i < (a + 1)
         NewString = NewString & Mid(chr, si, 1)
         i = i + 1 : si = si + 1
         If si > Len(chr) Then si = 1
      Wend
   Else
      NewString = sString
   End If
   NewString = Mid(NewString, 1, TotalLen)
   CenterStr = NewString
End Function

'-----------------------------------------------------------------------
' Unify characters
'-----------------------------------------------------------------------
' UniqStr(String)
' Example: UniqStr("AAABBBCCCDDD") => "ABCD"
'-----------------------------------------------------------------------

Function UniqStr(ByVal sString)
   Dim OldString, NewString
   OldString = sString
   NewString = ""
   Dim i, chr
   i = 1
   While i < (Len(OldString) + 1)
      chr = Mid(OldString, i, 1)
      NewString = NewString & chr
      OldString = Replace(OldString, chr, "")
   Wend
   UniqStr = NewString
End Function


Apart from these two there are other, but not so used.

Left and Right get a Substring with the length you want from left or right of the String.
The same can be done playing a bit with Mid and Len again.

Image

Replace allows to change a char to another one through the String.

Image

LTrim and RTrim return the same string without initial spaces or end spaces. Trim is the same but both initial and end.
The legend tells once someone used them on a table... but nobody cares.

StrReverse writes the string backwards.

And also in VB we would have StrDup but FP doesn't support it, anyway it's easy to make. Repeats the String as many times as you want.

Code:
'-----------------------------------------------------------------------
' Duplicate String
'-----------------------------------------------------------------------
' StrDup(String, Integer)
' Example: StrDup("TILT! ", 4) => "TILT! TILT! TILT! TILT!"
'-----------------------------------------------------------------------

Function StrDup(ByVal sString, ByVal times)
   Dim NewString
   NewString = ""
   Dim i : For i = 1 to times
      NewString = NewString & sString
   Next
   StrDup = NewString
End Function


And at last but not least, we have LCase (LowerCase) and UCase (UpperCase).

Image

With them it's easy to make Capitalize and SwapCase.

Code:
'-----------------------------------------------------------------------
' Capitalize
'-----------------------------------------------------------------------
' Capitalize(String)
' Example: Capitalize("PINBALL") => "Pinball"
'-----------------------------------------------------------------------

Function Capitalize(ByVal sString)
   Capitalize = UCase(Mid(sString, 1, 1)) & LCase(Mid(sString, 2))
End Function

'-----------------------------------------------------------------------
' SwapCase
'-----------------------------------------------------------------------
' SwapCase(String)
' Example: SwapCase("Pinball") => "pINBALL"
'-----------------------------------------------------------------------

Function SwapCase(ByVal sString)
   Dim NewString, chr
   NewString = ""
   Dim i : For i = 1 To Len(sString) + 1
      chr = Mid(sString, i, 1)
      If chr = UCase(chr) Then
         NewString = NewString & LCase(chr)
      Else
         NewString = NewString & UCase(chr)
      End If
   Next
   SwapCase = NewString
End Function


In conclusion, we don't have a big amount of functions for String but with only those we can do all we need (and more) for our codes.

6. Integers

Integers have some operators:

+
-
*
/
\ (integer division)
Mod (modulus)

Image

Besides having a few functions.

Numbers have also Len which gets the number of digits (integer part) of that value.
We use Abs to get the absolute value of the number and finally Round to get the nearest Integer of a non-integer number.
I made the function Floor using Round. Floor gets the integer part of the value.

Code:
Function Floor(ByVal Val)
   Floor = Round(Val)
   If (Floor > Val) Then Floor = Floor - 1
   Floor = CInt(Floor)
End Function


Image

7. The default arrays

Arrays are variables which have some variant values together, like a list.
Default Arrays are very very limited, that's why I made a class C_Array which is an alternative of those.

The most common way to define an Array is defining its length with parenthesis and later assigning every value individually.

Image

Although there are alternatives:

Image

Its main methods are LBound and UBound, who get the limits of the Array.

Image

To display an Array on the Debug Window we have to convert it to String using the method Join. Join also lets you select the separator.

Image

Once we defined the Array with its length, it can not be altered. But we can define the Array again using Redim.
Using Redim preserve you can redefine the length of the Array without losing the variables of the current Array.

Image

And that's all they have.

-------------------------

End of the Tutorial ;)


Top 
 Profile  
 
 Post subject: Re: Wecoc's Future Pinball Scripting Guide
 Post Posted: Mon Jun 15, 2015 3:06 pm 
Offline

Joined: Mon Jan 27, 2014 12:36 pm
Posts: 2855
Location: Ontario, Canada
for my purposes, Thanks to you Wecoc,
I have used a list of numbers in my array (1,0,2,3,2,etc)
And converted to a NUMERIC string (10232etc) to be saved in the FP nVS 1-16 (Fp savers)

So clearly strings are either numeric or text


Top 
 Profile  
 
 Post subject: Re: Wecoc's Future Pinball Scripting Guide
 Post Posted: Mon Jun 15, 2015 5:53 pm 
Offline
User avatar

Joined: Fri Sep 09, 2011 9:14 pm
Posts: 142
Quote:
So clearly strings are either numeric or text


Strings are always text. But you are not so wrong... The type change, in this case from number to string (CStr), is executed internally when it's necessary. That's why we can do directly things like AddDebugText(0) where in fact we are displaying "0", or we can do "Light" & 1 --> "Light1" ...

So what you saved in nVS1-16 was the string "10232(etc)". Anyway if the string has only numbers you can get the integer back with CInt (or I would work directly with the string) so there's not any problem with that.

I forgot to talk about Format but I'm not sure how it works, when I learn it I'll add it in the Tutorial.


Top 
 Profile  
 
Display posts from previous:  Sort by  
 
Post new topic Reply to topic  [ 6 posts ] 

Board index » Resources » Tutorials, how-to's, bug report and docs


Who is online

Users browsing this forum: No registered users and 6 guests

 
 

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to: