How to write scripts for SexScripts -------------------------------------- 1. Introduction 2. Getting started in SexScripts 2.1. Getting SexScripts 2.2. Getting more Scripts 2.3. Configuring Options 2.4. SexScripts folders 2.5. The Editor 2.6. The scripts' user interface 3. Hello world! 3.1. Creating new scripts 3.2. Put a license on your script! 3.3. Executing and testing our work 3.4. Publishing our work 4. Let's start with Groovy 4.1. Groovy scripting 4.2. Variables 4.3. More on assigning values to a variable 4.4. Expressions 4.5. Comments 4.6. Practice your skills! 5. The SexScripts API 5.1. API? What's that? 5.2. Some programming slang 5.3. What I need to know to start 6. My first script! 7. A little more of Groovy 7.1. Booleans 7.2. Strings 7.3. Lists 7.4. Ranges 7.5. Conditional Statements 7.6. Loops 8. SexScripts API, second round 9. Let's do something fancy! 10. I wish I could do that... 10.1. What time is it? 10.2. How long has my script been running? And how many times has it been executed? 10.3. Opening other scripts 10.4. Writing and reading files 10.5. Ask the user for a picture 10.6. Wait while showing the exact waiting time 10.7. Dynamic text 10.8. Dynamic images 11. Rocking with Groovy 11.1. Advanced Operators 11.2. Maps 11.3. Closures 11.4. Math 12. And what now? 13. Quick API guide 1. Introduction ----------------- ----------------- This file is an unofficial faq/manual that shows how to write scripts for the SexScripts software. If you're a begginer on the matter, or you would like to make scripts but find coding them in Groovy a really hard task, this can be very useful to you. Even if you have some experience writing scripts, you may find here useful information you may not know yet. It covers a big amount of topics that can be useful when writing scripts, starting in the guess that you have zero programming knowledge, and finishes showing how to properly get profit from closures and other advanced Groovy structures. 2. Getting started in SexScripts ---------------------------------- ---------------------------------- On this chapter we'll have a little overview on the SexScripts software and its tools. If you're already used to it, you can skip this chapter. 2.1. Getting SexScripts ------------------------ You can get the sofware freely on its webpage, http://ss.deviatenow.com/, go and download it if you haven't done it yet! It is distributed under gpl license. To install it, only decompress the zip file you downloaded in any folder you want to have it in your computer. SexScripts can run in all systems that have a working version of the java virtual machine installed. If you don't have it go to http://java.com and get the latest version of JRE. To open it, Windows users can double-click sexscripts.exe, and Linux and Mac users can run sexscripts.sh instead. If it's the first time you open it, you'll be asked to answer some questions to configure the software to your taste. 2.2. Getting more Scripts -------------------------- Once you installed SexScripts on your system, you will probably want to get some scripts to play. To do this, go to SexScripts webpage scripts section (http://ss.deviatenow.com/scripts.php) and look for all the scripts that match your tastes (you can filter them by their tags). To get a script, right-click its name with the mouse and select 'copy url to clipboard' or something similar depending on your browser. Then, open SexScripts on your computer, and select File > Import from URL from the menu. Paste the URL you just copied and click Ok. That's all, The script should be downloaded and installed properly, and you should be able to see it in the scripts folder of SexScripts. You can also manually install a script by downloading them normally from the SexScripts webpage, and decompressing it in the same folder you have SexScripts installed. To run it, select File > Open from the menu and select it. 2.3. Configuring Options ------------------------- For a big amount of scripts, the more kinky items you have, the funnier they will become. So you can let SexScripts know what you have, selecting Options from the menu and then toys, women's clothes or men's clothes. Also if you find the script you're running to be too slow or too fast for your taste, you can select another speed in the Options menu. 2.4. SexScripts folders ------------------------ Scripts usually use various resources when running, like pictures and sounds. And when you create a script, you'll need to add all the resources you might use to SexScripts folders. If you have a look inside the SexScripts folder, you'll find the next folders contained in it: - images Here is the right place to put all the pictures you want to use in your script. - sounds Put in here all the sounds your script is going to need. - videos If your script's going to use some viedo files, this is the best place for them. - scripts All the script files (*.groovy) that you have installed will be here. When you create a new script place it here. - lib You better don't mess with this folder The right place for any other kind of file (a text file for example) your script might use is the SexScripts folder itself. Or better, create a subfolder yourself to put them into. To keep things cleaner, for your script pictures, sounds and videos it's always a good idea to put them in a subfolder in its proper resource folder (for example, don't put your picture 'boobs.png' into 'images/boobs.png', but rather into 'images/myScript/boobs.png') You will also see if you examine this resource folders, that there are already some resources for you to use in your script. 2.5. The Editor ---------------- The editor is the best tool to directly start to write scripts. You could use other text editors to write your scripts with (like notepad or gedit), but you'll find that this built-in editor has some features that can be very useful when writing scripts. To open the editor, select Script > Edit from the menu. It will open in a new window. There are various ways to create a script, and the Editor will leave you things easy to do this. To create a new script, you can either import some picture gallery, import it from a CyberMistress script, or import it from a Milovana online script (either flash or normal). Or you can just start to type code in the editor from the scratch or from other script. This manual is focused on this last option, to get help about importing from other resources you can visit the SexScripts forums (http://ss.deviatenow.com/forum.php). In the Editor, apart from typing code and classic text editting features (Undo, Redo, Search, Replace, Copy, Paste, Cut,...) you can find very useful the code snippets. If you right-click anywere on the code of a script, a menu will be shown. On that menu you can select one ordinary task to get the code snippet to do it. Very useful for begginers. Don't worry if you don't understand a character from the code, you will learn how it works through this manual. Another good feature from the editor that can come handy, is the Syntax parser. Go with it to let the Editor detect syntax errors (things typed incorrectly) you might have done, but don't expect it to fix all the bugs from your script. To run it click on the 'Check' button in the toolbar. 2.6. The scripts' user interface --------------------------------- If you're going to write scripts for SexScripts, you should know first how to communicate your script with the user that plays it. The main way your script has to communicate something to the user is through showing some text in the SexScripts window. A script can also show a picture or launch a PopUp alert with some message in it. To recieve input from the user, a script can also show buttons for the user to click them, show a text field for the user to input some data, and others. You will see all of them through the reading of this manual. 3. Hello World! ----------------- ----------------- Now that we have had a little overview about the program, let's see how we can actually create our own scripts and publish them at SexScripts' official repository for everyone to play them. Don't worry about writing code yet, we'll get into that later. We will see that creating, mantaining and publishing our scripts is in fact a very simple task with the help of the tools provided by our beloved god doti, that we saw on the last chapter. 3.1. Creating new Scripts -------------------------- First things first. To create a new script open SexScripts if you haven't done it yet, and select Script > Edit from the menu to open the Editor. In the Editor window, select File > New from the menu, and a blank script with some template code will be presented. Now select the Save option either from the toolbar or the File menu, and provide whatever name you like for your script. In the example of this chapter I've chosen 'helloWorld' for it. If you check now the scripts folder, you'll be able to see that a new script 'helloWorld.groovy' (or whatever you named the script) has been added. Great! We have just created a brand new script ready to be coded, that simple. 3.2. Put a license on your script! ----------------------------------- But before starting to smash code, It's highly recommended to put a license line in your script, so the community will know how to distribute and/or modify it. If you pay attention to the template lines added when you created the script, you will see that a default cc by-nc license has been added to it. Modifying this lines you'll be able to select whatever other license you'll like for your script, but the most common ones are: CC by-NC 3.0 (see http://creativecommons.org/licenses/by-nc/3.0/ for detailed information) GNU gpl-3.0 (see http://www.gnu.org/licenses/gpl.html for detailed information) 3.3. Executing and testing our work ------------------------------------ Now we have all we need to start coding our script. But for now, just delete all the template lines that were added when we first created our script and copy-paste the next code: setInfos(4, "helloWorld", "", "Anonymous", "example", 0xFFFFFF, "en", []) show("Hello World!") // This script is protected by this license : // CC by-NC, see http://creativecommons.org/licenses/by-nc/3.0/ Don't worry if you don't understand this code yet, we will go into it step by step later. Every time we write a script, or add modifications to its code, we will be eager to run it to test if our script is working properly. So once added the code, save it in the Editor window and change back to the SexScripts main window. Note that it is not needed to close the editor window to run our script. And to run it, we can select Script > Reset from the menu, or press the CTRL+R shortcut on the keyboard. You can also open it form the File menu, like any other script. Our script should run, showing the text 'Hello World!' to finish afterwards. Be sure every time you write and modify your scripts to run it several times, trying to test all the cases your script can run through, to find and fix any bug that can appear, before releasing them. 3.4. Publishing our work ------------------------- Great! Our example script worked fine! What to do now? You will usually want to publish your script at the SexScripts webpage for all the dudes of the community to enjoy it, once you finished writing them. To achieve that is fairly easy, you just have to select File > Publish from the Editor window. A list showing all the resources your script may use will be shown. Carefully check that list, and manually add any item that can be missing. Then press the Ok button, wait while your script is being uploaded, and that's all! You should be able to see your scripts in the SexScripts repository by now. Be sure to run your script just before publishing it, to re-sure it's working fine. And re-check also the resource files list of your script, if you publish it with a pic or a sound missing, any user who downloads and plays it will get an error when yor script uses that pic or sound. The only resources that are not needed to be in this list are the SexScripts default resources. Note: Do not try to publish helloWorld.groovy, it would be a very bad idea! 4. Let's start with Groovy ---------------------------- ---------------------------- All the scripts that run on SexScripts are written in a language called Groovy. Don't start to panic yet! You'll see that learning it is very easy, and differently as other programming languages, Groovy is really very simple and not so strict as Java or the C family languages. Programming in Groovy it's really kids stuff, don't be afraid to start with it! 4.1. Groovy scripting ---------------------- The words 'programming' and 'scripting' shouldn't freak you out at all. If those words freak you out, you'll probably have wrong concepts about what do they mean. Let's suppose we want to write some example script, so to design it we would open a new text file and write down what we want our script to do: - First of all, my script will show the picture 'coolgirl.jpg' - Then, it will show the text 'Hello there, boy!' - It will give the user 5 seconds to read it, and then change the text to 'Did you like this example?' - After that, my script will show a Button with the text 'Sure!' on it - When the user clicks on it, my script will finish And, well, we have just programmed our script. You're a programmer now! What? Do you think that this does not look like programming code? Well, it may not look, but in fact it is. The point is that it is written in English, but we can translate it to a programming language like Groovy. The meaning of the instructions will be the same, it will only change the way we write them to follow the Groovy syntax. So, we go to the SexScripts forums and read a bit of the scripting documentation pages. We will find out the next: - To show a picture, let's say 'myPic.png'; in Groovy it is written as: setImage("myPic.png") - To show some text, let's say 'Hello World'; in Groovy it is written as: show("Hello World") - To wait, let's say 10 seconds, before continuing with the next instruction; in Groovy it is written as: wait(10) - To show a Button with the text, let's say 'Okay' on it, and wait for the user to click on it before continuing with the next instruction; in Groovy it is written as: showButton("Okay") - And last, to finish the script; in Groovy it is written as: return null So with all that knowledge in hand, we can proceed to translate our example script from English to Groovy, and it will look like: setImage("coolgirl.jpg") show("Hello there, boy!") wait(5) show("Did you like this example?") showButton("Sure!") return null And we have now our script fully written in Groovy. Pretty simple, right? We can now write that code on the SexScripts editor and run it. In fact, you should do it now, and experiment with these instructions modifying this code, and designing and creating your own test scripts like the one in this example. To do it follow the same steps we done for the example in the last chapter, helloWorld.groovy. But keep in mind the following when you're at it: - Do not delete the line starting with 'setInfos' from the template code, we'll step into it in the next chapter. Apart from comments (see below), this should be always the first instruction of any script. Summarizing, it registers your script so it can be properly executed and published. - Every line starting with // it's a comment, and they will be all ignored by SexScripts. More on that later. - Put at most only one instruction per line - To put return null as the last instruction is not mandatory, after the last instruction is executed the script will equally end - Do not forget to copy any picture your script is going to show into the images folder of SexScripts, for it being able to find it. Note that you can put a semicolon ';' at the end of each instruction if you want to make the code look more 'javish', but this isn't mandatory. You can also write all of your doubts in the SexScripts forums. Do not hesitate to do it if you need help, there are never silly questions. 4.2. Variables --------------- Like any other programming language, Groovy has variables. You can imagine a variable as a container where you can store values to use it later. Variables are identified in Groovy by their names. When you define them in your script, you have to give them a name. For example, the next Groovy instruction: def x Creates a variable called 'x'. You can use as a variable name whatever you want but with some limitations. A variable name can only contain letters, numbers, and the underscore character '_'. And all variable names must begin with a letter. So, these variable definitions are correct: def seconds def limit1 def limit2 def slaveAge def slave_age While, in the other hand, these definitions are incorrect: def 3things def amountOf$ def slave age def _time Note that in Groovy, uppercase letters are not the same as lowercase. So the name 'Index' is not the same as 'index'. Also note that you can't create two variables with the same name. So this code: def aux def aux Will produce an error. Note also that there is yet another limitation: You can't use Groovy reserved words as a variable names. For example, you can't use 'def' to name a variable, in Groovy that word is used to create variables. Here's a list with all Groovy reserved words: abstract as assert boolean break byte case catch char class const continue def default do double else enum extends false final finally float for goto if implements import in instanceof int interface is long native new null package private protected public return short static strictfp super switch synchronized this threadsafe throw throws transient true try void volatile while Additionally, you can't use the name of a method of the SexScripts API. We'll see in the next chapters what are they, but you've already seen some (remember the show(message) or wait(time) instructions? You can't use 'show' or 'wait' as variable names, for example). You can also declare more than one variable in a single instruction separating their names with commas: def x, y def seconds, minutes, hours Now we know how to properly create variables. But it won't be that useful if we don't know how to use them. To store a value into a variable we follow its name with a = symbol and the value. For example, this code: def x x = 5 Will create a variable called 'x' and then store the number 5 in it. You can also store a value into a variable when defining them. So the above code can be written with a single instruction as follows: def x = 5 Having the same exact result. And by now, you will be probably wondering what kind of values you can store into a variable. And as you will see through this manual, you can store virtually any kind of value. But the most common ones are numbers and texts, as you can see here: def number = 8 number = 0 number = -36542125 def pi = 3.1416 def message = "Hello World!" There's also a special value refered by the reserved word null. In fact null isn't a value at all, but a word to indicate the absence of any value. Okay, we know how to input a value into a variable, but how do we retrieve it? Really easy. Just write the name of the variable instead of a literal value in any instructions that requires some value to operate, like the show(message) or wait(time) instructions, or even when assigning a value into a variable: def seconds = 5 def greeting = "Hello" show(greeting) wait(seconds) def t = seconds The show instruction in this code will show the text 'Hello'. The wait instruction will wait for 5 seconds, and the variable t will store a 5. If we retrieve the value of a variable which is not containing any value (for example if we have created it with def but we haven't put any value into it) we will get null. And using null in some commands that needs an actual value can cause a malfunctioning. Take care with that and get used to put into variables some default values after defining them. This is a huge source of bugs. 4.3. More on assigning values to a variable -------------------------------------------- Rather than just assigning a value into a variable, if the variable already contains a numeric value, you can add the value to the variable using += instead of = def x = 4 def y = 2 x += 3 x += y After these instructions are executed, x will be containing 9. Similarly, you can use -=, *= and /= to subtract, multiply, or divide the value with the variable. After this code is executed: def x = 3 def y = 4 x -= 1 y *= 3 y /= x x will be storing 2, and y will be storing 6. There's also a shorcut for += 1 and for -= 1, called increments and decrements. You can write ++ insted of += 1, and -- instead of -= 1 def x = 5 def y = x x++ y-- After this insctructions, x will be 6, and y will be 4 4.4. Expressions ----------------- An expression is an operation between one, two, or more values that return another value as a result. Don't let this technical words intimidate you. An expression is something as simple as 2 + 3. And the returned value will be 5, as the expression 2 + 3 evaluates to 5. Simple, isn't it? To write expressions we use what it's called operators. If the operator operates with one value it's called unary operator. To use a unary operator we write its symbol to the left of the value to operate. For example, the negator operator, represented by the symbol - , negates a numeric value. That is, that turns it negative (or positive if the value was already negative). Let's see an example: def x = 12 def y = -x After these instructions are executed, x will be storing 12, and y will be storing -12. We'll see a few more unary operators in the next chapters. The operators that operate with two values are the most common. They are called binary operators. To use them, write its symbol between the two values to operate. Binary operators are, for example + , - , * , / and % . The first 4 are pretty straightforward, they return the addition, subtraction, multiplication and the division of the values they operate with. The last one, % , is the modulo operator, and returns the remainder of the integer division between the values it operates with. When this code is executed: def x = 1 def y = x+5 def z = 16 x = z/2 y = y-1 z = x*y def t = y%4 x will be 8, y will be 5, z will be 40 and t will be 1. There are more binary operators that we'll see on the next chapters. And operators can only make operations between numeric values? Of course not. For example, if you use the + operator between 2 text values, the result will be its concatenation. For example: def hello = "Hello " + "world!" After this instruction, hello will contain "Hello world!". You can use this operation to write some large texts in various lines: def longText = "Groovy is an object-oriented programming language for the Java platform. It is a dynamic " + "language with features similar to those of Python, Ruby, Perl and Smalltalk. It can be " + "used as a scripting language for the Java Platform." And if you operate a text value with some other value, it will be 'transformed' into a text value and concatenated like above. You can use this to see what's contained in any variable: def x = 5 show("Variable x contains: " + x) These instructions will show the text 'Variable x contains: 5' to the user. But we'll get into text operations later. Instead of using just literal numbers or variables as values to operate, we can also take another expression. This is better seen with an example: def x = 4 def y = x/2 + 7 def z = 1 + y - x*2 def sum = x + y + z After this, sum will be 14, as multiplications and divisions have preference over additions and subtractions. But when the things are not clear you can enclose an expression between parentheses '(' and ')'. So the expression (5+3)/(6-4) will evaluate to 4. With all that, pretty complicated expressions can be written: def x=2, y=3, z=4, t=5 def op = ((z /((x*y)-4))+8) + ((t-z)*3) - 2 After that code, op will be storing 11. 4.5. Comments -------------- A comment is some text that SexScripts will completely ignore when executing the script, but for us the programmers they're still there and can be useful. Everything in a line after // will be ignored. To write a multiline comment, place it between /* and this */. Let's see an example: def x = 5 // Line comment, x was created and initialized with 5 /* Multi Line Comment */ Comments are very useful to anotate what is our script doing at some point in the code, so we will easily understand what is doing that piece of code we wrote: // Show our cool girl setImage("coolgirl.jpg") // Greet the user show("Hello there, boy!") wait(5) // Ask the user a question show("Did you like this example?") showButton("Sure!") // Finish the script return null Or it can be very useful to, temporaly, 'disable' some lines of code: def x = 5 /* def y = 2 x += y*2 x *= 3 */ x-- After that code, x will store 4, cause all the instructions between /* and */ are 'comments' and won't be executed. 4.6. Practice your skills! --------------------------- Though writing things in Groovy is easy, you'll first need to know how to do it. And as any other programming language, you will learn to write in Groovy, writing in Groovy. So to start open any of the default example scripts in the editor (simpleexample.groovy or test.groovy) and try to do some little changes until you get confident with it. 5. The SexScripts API ----------------------- ----------------------- For the moment we have seen a lot of things to do with variables, but really we haven't figured out yet how to benefit from them. Don't worry, as we learn more we'll see that variables are really useful. But for now, let's focus on doing more 'script' things like showing messages and buttons. 5.1. API? What's that? ----------------------- To not get things more complicated than the needed, lets informally say that the SexScripts API is a set of commands that the scripts for SexScripts use to achieve things like showing some text to the user or showing buttons for the user to click them. They are the basic instructions to use in your script, and most of the time you will be using them when writing scripts. For a quick glance of all the commands that exists in the SexScripts API, have a look to chapter 13. 5.2. Some programming slang ---------------------------- All the commands in the API perform some functionality your script might need to use, and are also known as functions or methods in programming slang. When we use a method somewhere in the script, we programmers like to say that we are calling that method. In Groovy, all the methods have the same format. They have a name so they can be referenced with. They can have 0 or more parameters to operate, and they may return a value. For example, the method showButton(label) shows a button for the user to click it. It has a name, 'showButton'. It also has one parameter, label (placed between parentheses), that is the text to be shown on the button. And it returns a value, the amount of seconds that the user lasted to click on it. To call (use) a method we simply write its name followed by the values we want to assign as its parameters separated by commas (if there are more than one) and placed between parentheses. If it returns a value, we can also assign it to a variable or use it in a expression. For example, to call the showButton(label) method to show a button labeled "Okay", and assign to a variable the amount of seconds the user lasted to click the button, we will write: def t = showButton("Okay") And if we don't mind the time the user lasts to click on it, we might simply write: showButton("Okay") And the returned value by the method will be ignored. Note that for methods that don't have any parameters we still have to write the parentheses: exit() 5.3. What I need to know to start ---------------------------------- To write any script you will have to use the methods in the API. So let's start with the most basic you will need for your script. setInfos(api, title, summary, author, status, color, language, tags) setInfos is a method that registers your script and gets it ready to be properly executed and published. Every script in SexScripts must call it once, and only once. And it must be the very first instruction to be executed in your script. setInfos won't return any value, but it has a lot of parameters as you can see. Let's explain them one by one. - api This should be a number indicating the version of the SexScripts API required to run your script. The latest version at the time of this writing is 4. - title This is a text value indicating the title of your script. Write it with less than 50 characters. - summary This is also a text containing a little summary (less than 250 characters) describing your script. Try it to be descriptive, avoid summaries like "My first script" or "A fun script for SexScripts". - author Another text value indicating the author of the script, namely your name or nick for the scripts you write. - status A text consisting of a word defining the development status of your script, usually "started" if you're making it, "complete" if you finished it, "incomplete" if there are still some features missing, and "test" if you're debugging it. - color A RGB code indicating the background color for your script. See http://www.colorhexa.com/ for more information about color RGB coding. The codes of some basic colors are: 0xFFFFFF (white) 0x000000 (black) 0x808080 (gray) 0xC0C0C0 (light gray) 0x404040 (dark gray) 0xFF0000 (red) 0x800000 (dark red) 0xFFFF00 (yellow) 0xFFFF80 (light yellow) 0x808000 (dark yellow) 0x00FF00 (green) 0x80FF80 (light green) 0x008000 (dark green) 0x0000FF (blue) 0x8080FF (light blue) 0x000080 (dark blue) 0x800080 (purple) 0xFF00FF (light purple) 0x00FFFF (cyan) 0x80FFFF (light cyan) 0x008080 (dark cyan) 0xFF0080 (pink) 0xFF80C0 (light pink) 0x804000 (brown) 0x402000 (dark brown) 0xFF8000 (orange) 0x00FF80 (turquoise) 0x8000FF (lilac) - language A text composed of two letters coding the language your script speaks, following the standard ISO 639-1 to code it. For English this two letters are "en", for German are "de", for Spanish are "es", for French are "fr", for Italian are "it", for Arabian are "ar", etc. - tags This is a list of all the tags your script is into. We are going to explain lists better on chapter 7, but for now you can define this tag list with something similar to ["femaledom", "formale", "pain"] show(message) This is perhaps the method you're going to use most. It will set 'message' as the current text shown by SexScripts. If 'message' is null or is an empty text "", then the current shown text will be hidden and no text will be shown at all. setImage(imageFile) This method will set the picture located at 'imageFile' as the current image shown. 'imageFile' must be the path from the images folder of SexScripts to your picture file. For example, if you have your picture 'boobs.png' inside a folder called 'myScriptPics' in the images folder of SexScripts, then 'imageFile' will be "myScriptPics/boobs.png". The picture file to be shown must be a jpg, gif or a png file. If 'imageFile' is null, then the current shown image will be hidden and no image will be shown at all. wait(time) This method will wait 'time' seconds before continuing with the next instruction. waitWithGauge(time) This method is similar to the above wait(time), but during the wait, it will show a filling gauge bar. showButton(label) and showButton(label, timeout) This method will show a button with the text 'label' on it, and will wait until the user clicks on it. Note that you can specify a second parameter 'timeout', that will be a number of seconds. In that last case, showButton will wait until the user clicks the button or 'timeout' seconds have elapsed. It will return the number of seconds that the user take to click the button, or 'timeout' if this second parameter exists and the user's not clicked the button before the timeout has elapsed. showPopup(message) This method will launch a Pop-Up window with the text 'message' in it and an [Ok] button, and will wait unitl the user clicks the [Ok] button or closes the window. It will return the number of seconds that the user take to click [Ok] or close the Pop-Up. playSound(soundFile) This method will play the sound located at the path 'soundFile', and wait for it to end its playing. 'soundFile' must be the path from the sounds folder of SexScripts to your sound file. For example, if you have yor sound 'giggles.wav' inside a folder called 'myScriptSounds' in the sounds folder of SexScripts, then 'soundFile' will be "myScriptSounds/giggles.wav". The sound file must be either a wav or a mp3 file. playBackgroundSound(soundFile) This method is similar to the above playSound(soundFile), but it will not wait for the sound to end its playing. exit() This method will close SexScripts. Use it carefully, it can be a bad experience for the user if you close his SexScripts window without him expecting it. If you only want to exit from your script, just use this instruction: return null Make sure to do various tests with all this basic methods, and see how they work on your computer, until you get comfortable with them and understand them pretty well. Knowing how to properly manage the API methods is the key to script programming. So experience a lot with all the above explained methods before going further in this manual. 6. My first script! --------------------- --------------------- With all the knowledge we have now in hand, we are ready to attempt writing some real scripts. First of all, we need to have an idea of what's our script going to do. For our first script we've decided to base it on orgasm denial. A pretty girl will command the user to jerk his cock to finish denying him to cum. So with that in mind, we are ready to get to work! To create our script we first open the editor (Script > Edit) and from the editor menu we select File > New. We'll get a brand new blank script for us to use with some template code in it. As we want to write it all from the scratch, delete all this template lines. Now the first thing a script must always do is to call setInfos. Here we put a title to our script (We've decided to name it 'Jerk it!'), a short description to it and our name ('Wololo' in this example). As the development status for now we are going to set it to 'started'. We are going to write the dialogues in English, so we're going to use the language code 'en'. As background color we'd like it to be pink, so we'll use the code 0xFF80C0. And last, the tags our script is into will be 'femaledom', 'formale' and 'denial'. The call will look like this: setInfos(4, "Jerk it!", "Obey and jerk as the girl says and you may be rewarded", "Wololo", "started", 0xFF80C0, "en", ["femaledom", "formale", "denial"]) And for the last lines of our script we are going to set some cc by-nc license: // This script is protected by this license: // CC by-NC, see http://creativecommons.org/licenses/by-nc/3.0/ So we got our script ready to be programmed! But before start to smash instructions into it, probably we are going to need some resources, like cool pictures. So we go to internet, and search for pics of a cool girl to star our script. After a bit of searching, we ended up with 5 pictures: 'coolgirl01.jpg', 'coolgirl02.jpg', 'coolgirl03.jpg', 'coolgirl04.jpg' and 'coolgirl05.jpg'; going to fully clothed in 'coolgirl01.jpg' to fully naked in 'coolgirl05.jpg'. To save those pics, we go to the SexScripts images folder and create a new folder, we're going to name it 'JerkIt'. We copy all our pics into that new folder. So with the pictures added to SexScripts, we can begin to write some code. To start, the girl should be shown and greet the user. So we put these lines after our setInfos call: setImage("JerkIt/coolgirl01.jpg") show("Hi there boy!") wait(4) Then, our star should present herself and ask the user to get naked: show("I'm a very cool girl. You know why?") showButton("Why?") show("Because I am very used to have men under control. I know how to make them do anything I want.") wait(7) show("I know that I turn you on. I can see that bulge in your pants. Why don't you strip naked for me?") showButton("I'm naked") We have to use a button to wait for the user to get naked, because we don't know a priori how long it will take. We can undress now a little bit our star. Then, our cool girl will ask the user to get hard and explain some instructions: setImage("JerkIt/coolgirl02.jpg") show("Great! But I prefer cocks to be rock hard. Could you get it hard for me?") showButton("I'm hard") show("Fine. Now hands out of your cock! You will follow every of my commands to the letter " + "if you want to be rewarded. Undersootd?") wait(11) For now, we have done nothing so hard, haven't we? Scripting is really easy. Now Our girl will command the user to jerk his cock at different speeds. Easy to do, too. Only one thing, we're going to use waitWithGauge instead of simple wait calls while the user is jerking, so the user can have an idea about how many time is left for the next instruction. setImage("JerkIt/coolgirl03.jpg") show("Okay. Then start jerking your cock. Slow strokes for now.") waitWithGauge(60) show("Stroke it faster!") waitWithGauge(120) setImage("JerkIt/coolgirl04.jpg") show("Don't cum yet! slow a bit that speed.") waitWithGauge(60) show("Continue jerking that cock. Do it the fastest you can! Do not cum without my permission!") waitWithGauge(60) And finally, our star girl will command the user to edge. We need to show a button to know when the user is edging. setImage("JerkIt/coolgirl05.jpg") show("Now I want you to edge! Edge for me! Quick!!") showButton("Edging!") And after edging, as our script is into orgasm denial, our girl will deny the user to cum setImage("JerkIt/coolgirl01.jpg") show("Hands out of that cock! You didn't impress me at all!") wait(6) But now comes an issue. For now the script has been very easy to write. But now we'd like our girl to 'punish' the user based on how many time took him to edge. To achieve that, we first should save the time returned by the call to showButton("Edging!") into a variable: def time = showButton("Edging!") We have decided the punishment to be cock slapings. So now with the time stored in the variable 'time', we can calculate the numbers of slaps the user will recieve: def slaps = ( time / 2 ) + 3 But there's one problem here. The result of that calculation won't very probably be an integer number. And we can't command the user to give him 7.35 slaps... We'd prefer him to give 7 in that case. For now, we don't have any idea on how to do that, so we go to the SexScripts forums, and post our problem asking for help in the 'Script Writing' section of the forums. Very quickly, we get an answer with this fancy trick: If we create the variable slaps with the reserved word 'int' instead of 'def', we will force slaps to contain only integer numbers. So we better change the above line of code, and put this instead: int slaps = ( time / 2 ) + 3 And to give the punishment a good background, it would be fancy to play some slapping sound. So we open our favourite sound recording software and record the sound of a slap. We save it under the name 'slap.wav'. Then we need to add that sound to SexScripts', so we go into the sounds folder of SexScripts and create a brand new folder called 'JerkIt'. We can now safely copy our awesome 'slap.wav' into that new folder and use it in our script. The only thing that remainds is our girl to command the user his punishment: playBackgroundSound("JerkIt/slap.wav") show("Give your cock " + slaps + " hard slaps to learn the lesson!") showButton("Done") It's almost all done. Our girl has done her job, she can say good bye show("I will now leave. Good Bye!") wait(6) And our script could end right here. But it's always recommended to clean up the image and text our script last used before finishing our script: show(null) setImage(null) And now, our script is completed! we can change the parameter "started" of the setInfos call to "complete". We should now run it to check it's working properly. You can do that by saving your script in the editor, and pressing CTRL+R in the SexScripts main window. After we have checked its correct working, we might publish it in SexScripts community. See the 'Hello World!' chapter to know how to do that. You should now try to do some other scripts on your own, you will always learn things when trying to do interesting stuff. Experiment and play with all the instructions you know. The more scripts you write, the better you will get at writing them. And don't worry if your scripts aren't as super cool and super amazing as other scripts you could find in the SexScripts webpage, surelly there will be people who will find your script fun and entertaining, although it is as simple as the one we made in this chapter. So don't ever be afraid to publish your work, and try to publish all the scripts you write! The community will be very happy with your work, mindlessly your writing skills. Here is the full code of the script we made in this chapter: setInfos(4, "Jerk it!", "Obey and jerk as the girl says and you may be rewarded", "Wololo", "complete", 0xFF80C0, "en", ["femaledom", "formale", "denial"]) setImage("JerkIt/coolgirl01.jpg") show("Hi there boy!") wait(4) show("I'm a very cool girl. You know why?") showButton("Why?") show("Because I am very used to have men under control. I know how to make them do anything I want.") wait(7) show("I know that I turn you on. I can see that bulge in your pants. Why don't you strip naked for me?") showButton("I'm naked") setImage("JerkIt/coolgirl02.jpg") show("Great! But I prefer cocks to be rock hard. Could you get it hard for me?") showButton("I'm hard") show("Fine. Now hands out of your cock! You will follow every of my commands to the letter " + "if you want to be rewarded. Undersootd?") wait(11) setImage("JerkIt/coolgirl03.jpg") show("Okay. Then start jerking your cock. Slow strokes for now.") waitWithGauge(60) show("Stroke it faster!") waitWithGauge(120) setImage("JerkIt/coolgirl04.jpg") show("Don't cum yet! slow a bit that speed.") waitWithGauge(60) show("Continue jerking that cock. Do it the fastest you can! Do not cum without my permission!") waitWithGauge(60) setImage("JerkIt/coolgirl05.jpg") show("Now I want you to edge! Edge for me! Quick!!") def time = showButton("Edging!") setImage("JerkIt/coolgirl01.jpg") show("Hands out of that cock! You didn't impress me at all!") wait(6) int slaps = ( time / 2 ) + 3 playBackgroundSound("JerkIt/slap.wav") show("Give your cock " + slaps + " hard slaps to learn the lesson!") showButton("Done") show("I will now leave. Good Bye!") wait(6) show(null) setImage(null) // This script is protected by this license: // CC by-NC, see http://creativecommons.org/licenses/by-nc/3.0/ 7. A little more of Groovy --------------------------- --------------------------- After our publication of our awesome script 'Jerk it!' at SexScripts community, it has been a great hit. So after that big succes, we have decided to write another script. But this time we want to make it fancier, and not as simple as 'Jerk it!'. Then, we first better learn a little more of Groovy and make another step on our way to become SexScripts gurus. We are going to see now what tools Groovy offer us to make super awesome scripts. 7.1. Booleans -------------- A boolean value is a logical value in programming. Despite their fancy name, they can only be either the value 'true', or the value 'false'. Speaking in technical therms of booleans can get a little tricky, but in fact they're simple as a stone. A boolean value is the simplest value. A variable containing a boolean value, will only contain true, or false. That variable can be used to store the state of so many things that can be only in one of two states! For example, the room lights can be on (true) and off (false), the user can be a male (true) or a female (false), the user can be wearing panties (true), or not wearing them (false), the user can be kneeling (true) or not (false), etc. def areLightsOn = true def isSlaveMale = true def arePantiesOn = false def isKneeling = false show("On your knees slave!") showButton("kneeling") isKneeling = true show("Put on your panties!") showButton("Panties on") arePantiesOn = true show("Switch the lights off, slave!") showButton("Lights off") areLightsOn = false show("Stand up slave!") showButton("done") isKneeling = false And you can be wondering by now, for what reason would I store that into a variable? Because it can be so useful! Not that I'm saying that your script should create the variable 'areLightsOn' if it won't be needed, but you can store the booleans values that can be useful in your script for later do different things depending on it. For example, if we store the lights state into a variable, we will be later able to do different things depending if the lights are on, or if they are off. We will see how to do that later in this chapter, in the 'Conditional Statements' section. But instead of just storing true or false into a variable, we can use a boolean expression. Boolean expressions are like any other expressions, but they evaluate to a boolean value (true or false). To build them, we use boolean operators (if you need to refresh the 'theory' about expressions have a look at section 4.4 of chapter 4). The most common boolean operators are these (all of them are binary operators, that is, take two values to operate): == This operator will return true if the two values are equal, or false if they're different. != This operator will return true if the two values are different, or false if they're equal. < This operator will return true if the value to the left is smaller than the value to the right, or false otherwise. > This operator will return true if the value to the left is greater than the value to the right, or false otherwise. <= This operator will return true if the value to the left is smaller or equal to the value to the right, or false otherwise. >= This operator will return true if the value to the left is greater or equal to the value to the right, or false otherwise. To understand all of this better, let's have a look to an example: def x=1, y=2, z=3, t=2 def equal = y == t def diff = x != y def smaller = y < z def greatEq = y >= z def greatEq2 = y >= t After this code is executed, the variable equal will contain true, diff will contain true, smaller will contain true, greatEq will contain false, and greatEq2 will contain true. Boolean expressions can look a bit tricky, but actually they're very intuitive. For example, we could use one to store into a variable a boolean value that indicates if the user performed an action in time or if he didn't: show("Now I want you to do 30 push ups! You have one minute!") def time = showButton("Done") def inTime = time <= 60 So later we can do different things depending on it. The boolean operators we've seen can operate with any two values, even with other booleans. But the two values we operate must be the same kind of values, that is, two numbers, two texts, two booleans, etc: def greet = "Hello" def x = 10 def b1 = greet == "Hello" def b2 = x >= 5 def b3 = b1 != b2 After this code, the variables b1 and b2 will be storing true, and b3 will be storing false. But in Groovy, there's also what we call logical operators. Those are boolean operators (evaluates to true or false), but will only take other boolean values to operate. In Groovy we have one unary logical operator, the 'not' operator represented by the symbol '!'. It will turn the boolean value true into false, and the boolean value false into true: def x = 1 def y = 7 def b = x <= y def notB = !b After these lines execute, the variable notB will contain false. In Groovy there's also two more binary logical operators: && Logical 'and'. Returns true if the two values are true, false otherwise. || Logical 'or'. Returns true if at least one of the two values is true, false otherwise. Let's see an example of this: def x = 1 def y = 7 def z = 10 def b1 = x <= y def b2 = z <= y def andTest = b1 && b2 def orTest = b1 || b2 After these lines, andTest will be storing false, and orTest will be storing true. With all these boolean and logical operators we can write very complicated boolean expressions. If you only read this and only keep in your mind this 'booleans explanation' you are in the risk of not understanding them. So you better open SexScripts and the editor now and begin to play with booleans and build boolean expressions, until you feel comfortable using them. To see the value of a boolean stored in a variable, let's say a variable called b, you can use the instruction show("b = " + b). 7.2. Strings ------------- For the moment, we have been using in our code values like "Hello world!", or "Get on your knees, slave!". We have been calling them text values. But now we're actual Groovy programmers, and Groovy programmers like us call these values Strings. So, in fact, Strings aren't something new to you, you have been using them a lot with those show(message) and showButton(label) among others. Like you must know by this time, Strings can be stored into variables: def greeting = "Hello World!" show(greeting) So, let's talk about things from Strings you may not know. The value of a String is the text between the double quotes ("). This text, can contain any letter and digit, and any character that can be typed. But there're also some special characters, called escape characters, that you can't type like any other characters. The most famous of them all is the new line character, that let's you to have Strings consisting of various lines of text. To write this character, write \n somewhere into your String. Try executing this line of code in some test script: show("This is a line in a test String.\nI'm another line.\nAnd I'm the last line.") You will see the String properly shown in 3 lines of text. Try replacing the '\n' characters by simple spaces, and you will see the String printed in the screen as only one line. So as you can guess by now, all the characters begining with a backslash (\) in a String are escape characters. Then, what if you only want your String to have a simple backslash character? Don't worry, you can use the escape character \\ (two backslashes one next the other) to write a simple backslash: show("This is a backslash: \\") Escape characters can be the solution to questions like: How do I write a double quote character (") into a String without closing it? Simple! use the escape character \" : show("This is a double quote: \"") But in Groovy to enclose the text of a String you can either use double quotes (") or single quotes ('). So this last line of code will have the exact same result as: show('This is a double quote: "') Without the need to use an escape character to input the double quotes. But if you're using single quotes to write your String and want it to have a single quote character, then you will have to use its escape character (\'): show('This is a single quote: \'') But there's no need of using an escape character to write a single quote in a String enclosed by double quotes: show("This is a single quote: '") So what you should use to enclose the text of a String, double or single quotes? The answer is easy. Use what you like most. But if your String is going to contain some double quotes in it, use single quotes to build it. And if your String is going to contain some single quotes in it, use double quotes to build it. Regular Strings should be written in one line of code. So, the following code: show ("Groovy is an object-oriented programming language for the Java platform. It is a dynamic language with features similar to those of Python, Ruby, Perl and Smalltalk. It can be used as a scripting language for the Java Platform."); Will launch a syntax error and will not run. But there are a pair of tricks if you wish to use a String consisting of a large piece of text. First, you can concatenate shorter Strings into a larger one using the + operator: show ("Groovy is an object-oriented programming language for the Java platform. It is a dynamic " + "language with features similar to those of Python, Ruby, Perl and Smalltalk. It can be " + "used as a scripting language for the Java Platform."); Or you can put a backslash (\) as the final character of a line when writing a String to extend it to the next line: show ("Groovy is an object-oriented programming language for the Java platform. It is a dynamic \ language with features similar to those of Python, Ruby, Perl and Smalltalk. It can be \ used as a scripting language for the Java Platform."); Either code will have the exact same result. But for using large Strings consisting of various lines of text, there's also exists a easy way of doing it. You only have to use triple double-quotes (""") to enclose the text of your String. Every line between the triple double-quotes (""") will be a line of text in your String, so no need of using the \n escape character. If you want to extend one of the lines with the next, you can still use the \ character at the end of it. And also, when defining a String this way, there's no need of using escape characters to write single or double quotes: show ( """\ Groovy is an object-oriented programming language for the Java platform. It is a dynamic language with features similar to those of Python, Ruby, Perl and Smalltalk. It can be used as a scripting language for the Java Platform. """ ) This show call will print three lines of text, because of the leading backslash just after the first """. To compare two Strings, to check if they're equal, for example; you can use the boolean operator ==, and the operator != to check if they're different: def str = "Cool! I'm a string!" def b = str == "Cool! I'm a string!" After these instructions, b will be true. If you use the operators < , > , <= , >= with Strings; they will return true or false depending on the alphabetic order of the Strings: def str1 = "almost" def str2 = "because" def b = str1 < str2 After that code is executed, b will contain true. Note that Groovy considers all capital letters to be before in the 'alphabetic' order than all the lowercase letters, so in this case: def str1 = "almost" def str2 = "Because" def b = str1 < str2 b will be false. But sometimes it can happen that for what you need to compare two Strings, the default boolean operators are not enough. For those cases, Strings have some built-in methods that can come handy. Use them as any other method in the API, but write it's name just after a period just after the String you want to operate with. For example, the String method contains(subString) will return true if the String 'subString' is contained in the String. For example: def str = "Hello world!" def b = str.contains("world") In that case b will be true, because the String "world" is a part (or a subString) of the String "Hello world!". Very intuitive. Another String method you may use is startsWith(subString). This method will return true if the String starts with the String subString, and false otherwise: def str = "Hello world!" def b = str.startsWith("Hello") Similarly, endsWith(subString) will return true if the String ends with the String subString, and false otherwise: def str = "Hello Mistress" def b = str.endsWith("Mistress") You can get the 'size' of a String (the number of characters it contains) with the String method size(), or the String method length(). They're equivalent and do exactly the same: def str = "elephant" def x = str.size() def y = str.length() After that code, both x and y will be containing 8. If you want to transform a String by turning all its uppercase letters to lowercase, you can use the String method toLowerCase(), it will return a String like the original but with all uppercase letters turned into lowercase: def str = "HELLO WORLD!" show( str.toLowerCase() ) This code will show the text 'hello world!' (in lowercase letters). The method toUpperCase works similarly, but this time turning all lowercase letters into uppercase: def str = "Elephant" show( str.toUpperCase() ) This code will show the text 'ELEPHANT'. But if you wish to transform your String your own way, you can use the String method replace(oldString, newString). This method returns a String that is like the original but with all the ocurrences of 'oldString' in it, replaced by 'newString': def str = "I am a girl. Like any other girl I like to be a girl." show( str.replace("girl", "woman") ) This code will show the text 'I am a woman. Like any other woman I like to be a woman.' And for last the String method trim() will return a String like the original but with all the starting and ending blankspaces removed: def str = " Elephant!!! " show( str.trim() ) These lines will show the text 'Elephant!!!' (without any leading nor ending spaces). All this last examples of the usage of String methods are used with Strings contained in a variable named str. But you can use them not only with Strings stored in any other variable, but with any Strings. Incluiding the ones you directly write with the double or single quotes, and those returned from a String method. This line: show( " Hello World! ".toLowerCase().replace("world", "universe").trim() ) Will show the text 'hello universe!'. 7.3. Lists ----------- When you feel comfy using Strings, we can step to the next and cool Groovy object. Lists. In Groovy Lists are what their name says, a list of things. And with things I mean values. Lists can contain any kind of values: numbers, Strings, booleans, even other lists, etc. To write a list containing the numbers 1, 2 and 3 in that order in Groovy, we write them, separated by commas, and placed between square brackets ( '[' and ']' ): [ 1, 2, 3 ] Like all things in Groovy, we can store lists into a variable: def list = [ 1, 2, 3 ] There can be mixed various kinds of values in one list: def weirdList = [ 1, null, "potato", true, -0.365 ] But in fact they're usually only contain one kind of value, like numbers, strings, booleans: def numsList = [ 1, 5, -8, 0, 6 ] def strList = [ "hello", "world", "elephant" ] def boolList = [ true, false, false, true ] You see, creating lists in Groovy is very easy. And they're really not that new to you. By now, you should have seen a few examples of them. Yes, you're right. Actually the last parameter of any setInfos(...) call, the tags parameter, is a list of Strings. So you've used them already! But let's see what can we do with lists apart of using them in the setInfos call. When we are creating large lists, we can use various lines to write its elements: def largeList = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ] And we can also create an empty list, with no elements at all in it (We'll see later how to add elements in a list): def emptyList = [ ] Each element in a list have a position. For example, in the list [ "a", "b", "c", "d", "e" ], the String "a" is the first element, "b" is the second, "c" is the third, and so on. But in Groovy we won't be referring them by its position, we rather will do it by its index. The index of an element in a list, is the position they are in the list, starting with the first as 0, the second as 1, the third as 2, the fourth as 3, and so on. For example, in the above list [ "a", "b", "c", "d", "e" ], the String "a" has the index 0, "b" has the index 1, "c" has the index 2, and so on. To get the element that is in a certain position in a list, we will place its index between square brackets left to the list: def list = ["a", "b", "c", "d", "e"] def x = list[2] After these lines of code are executed, x will be containing "c". We can also use the index of an element in a list to modify that element in a list: def list = ["a", "b", "c", "d", "e"] list[2] = "x" After that, the elements of the list will be ["a", "b", "x", "d", "e"]. To access or modify an element of a list inside another list, we first place the index of the list contained in the 'container' list, and then next to it the index of the element in the contained list: def list = [ ["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"] ] def x = list[1][0] After this, x will be storing the String "d". To index the elements in a list starting from the end, we can use negative indexes. Note that this time, the last element in the list will have the index -1 and not -0! def list = ["a", "b", "c", "d", "e"] def x = list[-1] def y = list[-2] def z = list[-3] After that code, x will contain "e", y will contain "d", and z will contain "c". To add elements at the end of a list, we can use the += operator placing the list on the left side of +=, or we can use the << operator in the very same way: def list = [ 1, 2, 3 ] list += 4 list << 5 After these lines, list will be [ 1, 2, 3, 4, 5 ]. Note that if we 'add' a list to another list, rather than adding the list as an element of the first list, all the elements of the list will be added to the first list: def list = [ 1, 2, 3 ] list << [ 4, 5 ] After that, list will be [ 1, 2, 3, 4, 5 ]. You can remove all the occurrences of an element in a list with the -= operator placing the list on the left side of the operator: def list = ['a', 'b', 'c', 'b', 'b', 'd'] list -= 'b' After that, list will be ['a', 'c', 'd']. Note that if you remove a list from a list, all the elements of the second list will be removed from the first: def list = ['a', 'b', 'c', 'b', 'b', 'd'] list -= ['b', 'c'] After that, list will be ['a', 'd']. If you 'multiply' a list by an integer number, the result will be a list with all the elements of the original list repeated the number of times you multiplied it by: def list = [1, 2, 3] * 3 After this, list will be [1, 2, 3, 1, 2, 3, 1, 2, 3]. To know how many elements are contained in a list, we can just write '.size' rigth after the list: def list = ['a', 'b', 'c', 'b', 'b', 'd'] def x = list.size After this, x will be storing 6. Note that the 'size' of an empty list is 0: def x = [].size A 0 will be stored in x with that instruction. And finally, if you want to check if an element is contained in a list, you can use the 'in' operator. Place the element to the left of 'in', and the list to the right. This operator will return true if the element is contained in the list, and false otherwise. def list = ['a', 'b', 'c'] def b = 'a' in list After these lines, b will be storing true. If you find that using Groovy operators to manage your lists is not enough for you, there's also a full built-in set of lists methods like it happened with Strings. You can use them the very same way. For example, to get an element of the list in a certain index, you can use the methods get(index), or getAt(index). Both work the same way and are equivalent as using the square brackets to get that element (with something like list[index]). Let's see an example: def list = ['a', 'b', 'c'] def x = list.get(0) def y = list.getAt(1) After this code, x will be containing 'a' and y will be containing 'b'. We can also set the element in a certain index in a list with the methods putAt(index, element), set(index, element). Both will work the same as the instruction list[index] = element, but the last one (set) will additionally return the old value that was at that index: def list = ['a', 'b', 'c'] list.set(0, 'x') list.putAt(1, 'y') def old = list.set(2, 'z') After that code the list will be ['x', 'y', 'z'] and the variable old will contain 'c'. To get the greatest and the smallest elements in a list, we can use the methods max() and min() respectively: def list = [3, 1, 2, 8, 5, 4] def min = list.min() def max = list.max() After this, min will be 1 and max will be 8. Note that for a list of Strings, the greatest String is the one that would be the last if the list was sorted alphabetically, and the smallest would be the first. The sum() method of lists, performs the same action as if all the elements of the list were operated using the + operator: def numList = [1, 2, 3, 4, 5] def strList = ['a', 'b', 'c', 'd', 'e'] def x = numList.sum() def y = strList.sum() After this, x will be storing 15, and y will be storing the String 'abcde'. To add new elements to the list, you can use the lists method add(element) to add it at the end of the list, or the method add(index, element) to add it into a certain index: def list = ['a', 'b', 'c'] list.add('x') list.add(1, 'z') After this, the list will be ['a', 'z', 'b', 'c', 'x']. To remove one element from the list, you can use the method remove(element) and the first ocurrence of that element in the list will be removed. To remove an element that is in a certain index, you can use the method remove(index): def list = ['a', 'b', 'c', 'b', 'b', 'd'] list.remove('b') list.remove(0) After this, the list will be ['c', 'b', 'b', 'd']. To remove the last element from a list, you can use the method pop(). This method will also return this last removed element form the list: def list = ['a', 'b', 'c', 'b', 'b', 'd'] list.pop() def x = list.pop() In this code, the first pop() call removes 'd' from the list. The second call removes what is now the last element (the last 'b' String) and stores it into variable x. To remove all the elements from a list, you can use the method clear(): def list = ['a', 'b', 'c', 'b', 'b', 'd'] list.clear() After this, the list will be empty. We can check if a list is empty with the isEmpty() method. It will return true if the list is empty, and false otherwise: def list = [] def b = list.isEmpty() That code will store true into b. We can say that the size of a list is the number of elements it contains, being 0 the size of an empty list. To know the size of a list, we can use its size() method, it will return the same as if we'd write list.size: def list = ['a', 'b', 'c', 'b', 'b', 'd'] def x = list.size() This code will store 6 into x. But if we are not interested in the list size, but we are in how many times an element is repeated in a list, we should use the method count(element): def list = ['a', 'b', 'c', 'b', 'b', 'd'] def x = list.count('b') After this, x will be storing 3. If the element is not in the list, the count call will return 0. If we are only interested into knowing if an element is contained in the list, we can use the method contains(element). This method returns the same as the expression 'element in list': def list = ['a', 'b', 'c'] def b = list.contains('b') After this code, true will be stored in b. But if we want to know the index of an element in our list, we can use its method indexOf(element), and the index of the first ocurrence of the element in the list will be returned. If the element is not in the list, -1 will be returned. The method lastIndexOf(element) works in a very similar way, but instead of the first, it returns the index of the last ocurrence of element in the list: def list = ['a', 'b', 'c', 'b', 'b', 'd'] def x = list.indexOf('b') def y = list.indexOf('x') def z = list.lastIndexOf('b') After this code, x will be 1, y will be -1, and z will be 4. Before ending the lists section, there is a last method that is worth mentioning it. The lists method sort(), will sort all the elements of the list in ascending order. After this code: def numList = [4, 8, 2, 10, 3, 9] def strList = [ "because", "almost", "sex", "canoe" ] numList = numList.sort() strList = strList.sort() The list numList will be [2, 3, 4, 8, 9, 10] and strList will be [ "almost", "because", "canoe", "sex" ] 7.4. Ranges ------------ In Groovy we can use what's called a range, that is a list of consecutive values, for example [1, 2, 3, 4, 5, 6]. To write a range value in Groovy we write the first element of the range followed by .. and the last element of the range. For example, the range 5..10 will correspond to the list [5, 6, 7, 8, 9, 10]. Like everything in Groovy, we can store ranges into variables: def r = 5..10 We can also define semi-open ranges (that is the last element of the range is not included in it) writing a < symbol before the upper edge of the range. After the following instruction is executed: def r = 5..<10 The variable r will be containing a range that corresponds to the list [5, 6, 7, 8, 9]. We can also use single-character Strings to build a range: def r = 'a'..'d' After this line, r will contain the range ['a', 'b', 'c', 'd']. When we are defining a list, we can use ranges to write the elements in it. To do this, we write the range just after a * symbol: def list1 = [*3..5] def list2 = [1, *3..5, 7, *9..<12] These instructions will set [3, 4, 5] in list1 and [1, 3, 4, 5, 7, 9, 10, 11] in list2. Ranges can also be accessed like lists: def r = 5..10 def x = r[0] def y = r[-1] This code will set x to 5 and y to 10. But if what we only want is to access the first and last element of the range, we can write '.from' or '.to' right next to the range. So the above code will have the exact same result as this: def r = 5..10 def x = r.from def y = r.to You can also define ranges using the values stored in variables as the range limits: def lower = 5 def upper = 10 def r1 = 1..upper def r2 = lower..<9 def r3 = lower..upper After these instructions, the range r1 will contain [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], the range r2 will contain [5, 6, 7, 8] and the range r3 will contain [5, 6, 7, 8, 9, 10]. We will see that ranges can be very useful when writing scripts in the reading of this manual. 7.5. Conditional Statements ---------------------------- With variables, booleans, Strings, lists, and ranges we know a very useful handful of Groovy objects. But we are not going to be able to take profit from them if we don't know how to write basic Groovy flow statements. That technicism means informally how to do our scripts to do things depending of certain conditions. With conditional statements we can achieve that. That is let our script execute some code if some condition is met (for example, if a variable has some value in it), and other different code if it is not. And it's now when booleans reveal all their power, because how to code 'a condition is met' or a 'condition is not met'? It is, or it is not. That sounds very 'booleanistic' to me. So in Groovy, we are going to code 'a condition is met' with a boolean expression. That sounds very tricky, but in fact is very simple and intuitive. We can have for example the user's age stored into a variable. And then if he is young (let's say less than 40 years) make our script to command him to do some chores, and if he is not that young (more than 40 years) make our script command him very different chores. In that case, we could 'code' the condition 'the user is young' with the boolean expression 'age <= 40' if we had his age stored into a variable called 'age'. The simplest conditional statement in Groovy is the if statement. We can use it to execute an instruction only if a boolean expression is evaluated to true. To use it we write the reserved word 'if' followed by the boolean expression enclosed between parentheses, and followed by the instruction. For example: if ( x == 0 ) show("Damn! x is zero!") In this groovy line the 'show("Damn! x is zero!")' call will be only made if the variable x is storing a 0. If we want to also execute another instruction if the boolean expression returns false, we can add just after the if statement the reserved word 'else' followed with the 'else case' instruction: if ( age <= 40 ) show("Cool! You are young!") else show("Cool! You are an old wolf!") After this piece of code, if the variable age is 40 or less, the text "Cool! You are young!" will be shown. Otherwise, the text "Cool! You are an old wolf!" will be shown. We can write the if and the else statements in separated lines to make them more readable. This code does exactly the same as the above: if ( age <= 40 ) show("Cool! You are young!") else show("Cool! You are an old wolf!") And this one piece of code also is the same: if ( age <= 40 ) show("Cool! You are young!") else show("Cool! You are an old wolf!") But instead of just writing one instruction to be executed in the if statement, we can add more enclosing them between curly brackets ('{' and '}'). All the instructions between the curly brackets will only execute if the boolean expression evaluated in the if statement returns true: if ( x == 0 ) { show("Damn! x is zero!") wait(4) show("Let's change it, okay?") showButton("Okay!") x = 5 show("Done!") wait(5) } All these instructions between { and } will only execute if the variable x is storing a 0. Note that it doesn't matter if we change the x value inside these instructions. Once the condition is evaluated to true, all the instructions between { and } will be executed sequentially. We are going to call all the instructions between { and } a block. And instead of just one instruction in the else case, a block can be used too: if ( age <= 40 ) { show("Cool! You are young!") wait(5) show("I am young too!") wait(4) } else { show("Cool! You are an old wolf!") wait(4) show("I am an old bitch too!") wait(5) } You can imagine which block of instructions will be executed depending on the value the variable age is storing. If we want to, we can put another if statement inside an if statement, and so on. Let's say we have in our script a variable called hour that contains the current hour our script is running. This piece of code: if (hour < 7) { // This block executes between 0:00 and 6:59 show("It's too late! go to sleep!") } else { if (hour < 12) { // This block executes between 7:00 and 11:59 show("Good morning!") } else { if (hour < 16) { // This block executes between 12:00 and 15:59 show("Good afternoon!") } else { // This block executes between 16:00 and 23:59 show("Good evening!") } } } Will properly greet the user depending of the time it is. If you examine well all the nested if and else constructions you will see that in all possible values of the variable hour (between 0 and 23) The user is properly gret. But all this complicated construction of nested if-elses to make such a simple thing? Don't worry, there's a way of writing the exact same thing of above but in a more easy way: if (hour < 7) { // This block executes between 0:00 and 6:59 show("It's too late! go to sleep!") } else if (hour < 12) { // This block executes between 7:00 and 11:59 show("Good morning!") } else if (hour < 16) { // This block executes between 12:00 and 15:59 show("Good afternoon!") } else { // This block executes between 16:00 and 23:59 show("Good evening!") } This If-Else-If construction will have the exact same result as the previous code, but it is written in a easier way, it is more readable, and more intuitive. But for these conditional constructions like the above that do several different things depending only on the value a variable is containing, in Groovy there is another conditional statement called switch statement. To know how to use it, let's better see an example: switch (x) { case 1: show("Variable x is storing 1") wait(4) break case 2: show("Variable x is storing 2") wait(4) break case 3: show("Variable x is storing 3") wait(4) break deafult: show("Variable x is not storing 1, 2 or 3") wait(4) } In the above piece of code, first the variable x will be evaluated. If it is containing 1, the script will execute the case 1: instructions, if it is containing a 2, it will execute the case 2: instructions, and so on. If the value contained in x does not match any of the cases, the instructions below default: will be executed. In fact the working of a switch statement is easy and intuitive. You will be wondering what are all those 'breaks' put at the end of each case. They're a Groovy reserved word that will interrupt the execution of the switch block. If we don't put them, and case 1: is executed, when all the instructions in that case are executed, it will follow with the instructions in the case 2:, even if the variable x doesn't contain a 2. And when all the instructions in the case 2: are executed, it will follow with the case 3: instructions. To prevent this, we put a break at the end of each case, so when all the instructions of a case are executed, the break will jump out of the switch block instead of continuing with the below case. To get a better sense of how a switch statement works, play with it executing the above switch example in a test script (create the x variable first and put some value into it). Try deleting the 'breaks', and then putting them again one by one. Add more cases. Try to get comfortable with the switch construction and its way of working. We can also use Strings in a switch statement. Let's guess that we have in our script a variable called str containing some String: switch(str) { case "hello": show("Hello there!") wait(4) break case "bye": show("See you soon!") wait(4) break default: show("And what else?") wait(4) } And we can also use ranges to define the cases: switch(x) { case 0: show("Variable x contains 0") wait(4) break case 1..5: show("Variable x contains some value between 1 and 5") wait(4) break case 6: show("Variable x contains 6") wait(4) break case 7..<12: show("Variable x is greater than 6 but smaller than 12") wait(4) break default: show("Variable x is not between 0 and 11") wait(4) } So with that, returning with our previous if-else-if statement example, if we have in our script a variable hour containing the current hour our script is running, we can now use a switch statement to properly greet the user: switch(hour) { case 0..6: show("It's too late! go to sleep!") break case 7..11: show("Good morning!") break case 12..15: show("Good afternoon!") break default: show("Good evening!") } 7.6. Loops ----------- Now we know how to use conditional statements. But other not less important statements in programming are the looping statements. With them, we can repeat one or more instructions several times. They're very useful and will save us a lot of time! Like we've just said, loops will let us repeat some instructions several times. Let's say we want to repeat some set of instructions 10 times. In Groovy, the easiest way of doing that, is iterating (doing the same thing for all the elements) over the range 1..10, with the help of the each statement. We will do that with something like the following: def x = 0 (1..10).each { x++ } In this example, we first create a variable called x and input a 0 into it. Then we iterate over the range 1..10 with the each statement. The each statement, will repeat all the instructions in the block (all the instructions between { and } ) for each element in the range. And as in the range 1..10 there are 10 elements, in that case the instructions in the block will be repeated 10 times. In this example the only instruction in the block is an increment to variable x (a shorcut to x = x+1), so at the end of the bucle x will have been incremented 10 times, so x will be storing 10 at the end of the above piece of code. Note that differently from the other looping statements, in the each statement you can't replace the instructions block with a single instruction. You must always put the curly brackets, although there's only one instruction in the block. If you're curious about the why, let's say that in fact the each statement block isn't actually a block but a closure. You will learn more about closures in chapter 11. You can also use a similar construction of the above to repeat a set of instructions the number of times indicated by a variable with something like: def x = 0 def times = 10 (1..times).each { x++ } In all the each statements you can use an implicit variable called 'it', that will be storing the element of the range you are iterating over in each loop. 'Implicit' here means that you do not create it anywhere, but it is still there anyways. But be careful, the variable it will only be available in the each statement block (between the curly brackets) def x = 0 (1..10).each { x += it } In the above code, the variable it will be 1 in the first loop, it will be 2 in the second loop, and so on. So at the end of this code, x will be storing 55 (1+2+3+4+5+6+7+8+9+10). You can use the each statement to iterate not only over ranges, but also over lists: def list = ['a', 'b', 'c', 'd', 'e'] def x = "" list.each { x += it } In this case, the each statement will iterate over all the elements in the list, and the implicit variable it will be storing in each loop the list element you are iterating over. So in the first loop it will be 'a', in the second loop it will be 'b', and so on. At the end of the each bucle, x will be storing the String 'abcde'. But to iterate over ranges and lists, you can also use a for-loop. To repeat a block of instructions 10 times using the for-loop you will write something like: def x = 0 for (i in 1..10) { x++ } In the above example, the for loop iterates over all the elements in the range 1..10, that is 10 loops. So x will be storing 10 at the end of the for bucle. Like with the each bucle, you can use a variable to indicate how many times you want to repeat the block of instructions: def x = 0 def times = 10 for (i in 1..times) { x++ } Like in the each bucle, in the for bucle you also have an implicit variable that will be storing the element in the range you are iterating over. But in the for loop you can put the name you want to that implicit variable. It is usually called i but you can put the one you find that fits better. In this piece of code: def x = 0 for (i in 1..10) { x += i } i will be 1 in the first loop. It will be 2 in the second loop, and so on. You can use this for construction to iterate over lists too: def list = ['a', 'b', 'c', 'd', 'e'] def x = "" for (letter in list) { x += letter } At the end of this piece of code x will be storing the String 'abcde'. Note that here, We have called the implicit variable letter instead of i. For all the for bucles and the other bucles different from each in Groovy, if the block of instructions they use to repeat has only one instruction in it, you can replace the block by this instruction (that is, deleting the curly brackets). So the above code is equivalent to the next one: def list = ['a', 'b', 'c', 'd', 'e'] def x = "" for (letter in list) x += letter You can also use the for bucle to iterate over the characters in a String: def text = "abc" def list = [] for (c in text) { list << c } After this piece of code, list will be ["a", "b", "c"]. If you want to perform complicated iterations over a range, a list or a String you can use the extended form of the for bucle. It looks as follows: def list = ['a', 'b', 'c', 'd', 'e'] def x = "" for (def i = 0; i < list.size; i++) { x += list[i] } In that form of the for loop, in the parentheses instead of having something like (variable in list) we have a variable definition followed by a semicolon ';', a boolean expression followed by another semicolon, and an increment over the previous defined variable. The variable definition will be our 'implicit' variable, but it is not implicit anymore as we are fully defining it. But it will still only exist in the for block of instructions. The boolean expression will evaluate if there are more loops to perform. When it evaluates to false, the next loop won't be performed. The last increment, is an assignment to update our 'implicit' variable for the next loop. It is usually a simple increment like i++, but it can be any assignment you want, like i += 3, or anything else. This assignment will be executed at the end of each loop. As in this example we want to simply iterate over the list, we will define the variable i and use it as the list elements index. To start from the beginning of the list, we input a 0 (the first index) into it. We will want to end our for bucle when all the indexes have been iterated. As the last index in any list is list.size - 1, we will iterate while the index (represented by variable i) is smaller than the list size. And we want to iterate over all the elements of the list and not skip any one. So we use i++ to let i have at the end of each loop the index of the next element in the list. Nothing more to say about this for bucle example, it performs the same as the other simpler for bucle example that iterates over a list. The variable x will be storing the String "abcde" at the end of this for bucle. With that extended form of the for bucle, we can perform more complicated iterations. Let's say we want this time to iterate over the first half of the list. And we want to iterate only over the even indexes of the list. To do that, we could use a for bucle as follows: def list = ['a', 'b', 'c', 'd', 'e'] def x = "" for (def i = 0; i <= (list.size / 2); i += 2) { x += list[i] } This time, x will contain the String "ac". If we want to perform a bucle to repeat a block of instructions several times, but we don't know how many times we are going to need to repeat the block, and want to repeat it while a boolean expression is evaluated to true, we should use the while bucle. Let's say that we want the user in our script to perform a chore and repeat it until he does it in some time. We can use a while bucle like the following to do this: def inTime = false while (!inTime) { show("Do 5 push ups! You have 15 seconds!") inTime = showButton("Done") <= 15 if (inTime) show("Good job!") else show("Too late! Repeat it!") wait(4) } We see that to use a while bucle first we write the 'while' reserved word followed by a boolean expression enclosed between parentheses. Next to it we can put the while instructions block. That block will be executed until the boolean expression is evaluated to false. Note that if in a while bucle this expression evaluates to false just before the while bucle, no loops will be performed at all and the block won't be executed at all. In this example, we are going to repeat the block until the users does 5 pushups in 15 or less seconds. The variable inTime will contain that boolean information. So this while bucle will loop until the variable inTime is true, and will continue to the next loop 'while' inTime is false, so we use the expression !inTime to code that. The instructions inside the while block shouldn't represent a dare for you to understand. It puts into variable inTime true if the user performed the push ups in time (and so finishing the bucle), and false if he lasted more than 15 seconds (and so performing another loop). Then an if statement is used to show some different text if the user succeded or if he failed. The while bucle is the most general form of a bucle in Groovy, and in fact, all the other bucles can always be 'translated' into a while bucle. For example, to repeat an action 10 times as the first bucle example in this section we could have also used a while bucle like this: def x = 0 def it = 1 while (it <= 10) { x++ it++ } Having the same exact result. But the first way of doing it is easier and more intuitive. At this point you should experiment and play with all that new Groovy theory in some test script until you understand all that is explained in this chapter pretty well. The conditional statements and looping statements in Groovy are very important, so make sure you know how to use them pretty well before going further in this manual. 8. SexScripts API, second round ---------------------------------- ---------------------------------- We want now to make fancy scripts. We learned a lot about Groovy for that in the last chapter. But this won't be still enough, we first need to also have a good knowledge about the SexScripts API, and know all the cave-eats of it. By now, we already know how to use the most basic methods in the API. But with the remaining methods, we will have all the tools we need to cope with practically any script that can come to our mind. Let's see them! getBoolean(message) and getBoolean(message, yesText, noText) This method will set message as the current shown text (usually it will be a String containing a question for the user to answer) and show to the user two buttons for him to click one of them. If you put the yesText and noText parameters, they will be the texts that will be shown on the buttons. If you don't put them, the texts shown on the buttons will be a default "Yes" and "No". This method will wait for the user to click on one of the buttons. And then, it will return true if the user clicked on the 'yes' button and false if he clicked on the 'no' button. This method can be used to ask the user any question that can be answered with yes or no, but it can also be used to ask the user any question with two possible answers. Just put the answers as the yesText and the noText parameters, indepently if they mean 'yes' or 'no'. getInteger(message, defaultValue) As the getBoolean method, this one will set message as the shown text. It will also show the user a text field for him to input some data and a [Ok] button. The data the user is going to input will be an integer number. This method will wait until the user inputs the number and clicks on the [Ok] button. Then, the integer number the user's typed will be returned. The parameter defaultValue should be an integer number to be shown as default value in the text field to the user. If you don't mind it, just put a 0 as defaultValue. This method is useful to ask the user questions that can be answered with an integer number, like his age, the number of sons he have, how many times he masturbated in the last week, etc. getFloat(message, defaultValue) This method will work very similar to getInteger(message, defaultValue), but instead of asking the user to input an integer number he can put any real number. That is, any number, with posibly a period with a decimal part. This method can be used to ask the user any question that needs to be answered with a number with possibly a decimal part, like his height, his weight, the length of his pennis, etc. getString(message, defaultValue) This method is very similar to getInteger(message, defaultValue) and getFloat(message, defaultValue). But instead of asking the user to input a number, he will put some text. A String containing the user's answer will be returned. The defaultValue parameter here should be a String containing a default answer to be shown in the text field the user has to input his answer. If you do not want there to be any default answer, just put "" (an empty String) as defaultValue. This method can be used to ask the user questions that will be answered with text, like his name, his job, his eye color, etc. getSelectedValue(message, texts) This method will put message as the current shown text, and show the user various options for him to choose one. Depending on the number and 'size' of the options they can be shown as buttons or as a drop list, if they don't fit the buttons. The parameter texts must be a list of Strings, where each String in the list is a possible option for the user to choose. This method will wait until the user selects an option, and when he does, the index of the option he selected in the list texts will be returned. getBooleans(message, texts, defaultValues) This method will launch a dialog window with the text message in it, followed by a number of checkboxes and an [Ok] button. The parameter texts must be a list of Strings, where each String in the list will be the label of each checkbox (the text that is shown next to each checkbox) in the dialog window. So in the dialog window will be as many checkboxes as elements in the texts list. The parameter defaultValues must be a list of booleans of the same size as texts (with the exact same amount of elements in it). They will be the default state of the checkboxes (true will mean that the checkbox is checked and false will mean it is unchecked). This method will wait for the user to check and uncheck the checkboxes he wants to, and clicks [Ok]. Then the dialog window will be closed and a list of booleans will be returned, again with the exact same size as texts. In that returned list, each element will be true if the user left the corresponding checkbox checked, or false if he left it unchecked. getFile(caption) This method will open a file choosing window for the user to choose any file. The parameter caption must be a String containing the file choosing window caption. This method will wait until the user selects a file or closes the window. Then, a String containing the full path of the file the user's selected will be returned, or null if he closes the window. getTime() This method will return the number of seconds that have elapsed since 01/01/1970 to the current moment. It can be used for timestamps, or to know how many seconds have elapsed from one point in your code to another, getting the timestamps in both points, and then subtracting the first timestamp from the last. getRandom(max) This method returns an integer value randomly chosen from the range 0..= 17) { // Reward } else { // Punishment } As a reward we will command the user to jerk his cock while randomly showing the girls. But first we can let him aknowledge that we know if he answered all question right or not. So we're going to put this in the first block of that last if: if (correctAnswers == 20) show("You haven't given any wrong answer!") else show("Pretty good! You missed very few answers.") wait(5) Then we can command the user to get hard and start jerking: show("Let's celebrate it!\n\nWhy don't you stick out that cock and get it hard for me?") showButton("Done") show("Jerk your cock to the girls!") wait(2) Now we want the user to jerk for 3 minutes while showing randomly pictures of the girls. We can use a construction like this one for that: def startTime = getTime() def time = getTime()-startTime while (time < 180) { time = getTime()-startTime } If you carefully study that bucle you will notice that it actually performs a wait of 180 seconds (3 minutes) as if we had used wait(180). You can be wondering by now, then why not use a simple wait(180)? Because differently when using a wait call, performing waits with a bucle like that will let you to do things during the wait, like seting some image or showing some text. For example to show a text when 1 minute has elapsed and another when two minutes has elapsed during this wait, we could put this inside the bucle: if (time == 60) show("Go on " + loadString("intro.name") + "! \n\nJerk it!") else if (time == 120) show("Stroke your cock faster! But do not cum yet!") But we also want to set some image meanwhile, let's say, every 10 seconds. So that we really want is to set a random picture of a girl every ten seconds. That is, when the variable time takes the values 0, 10, 20, 30, 40, ... and so on. What all this values have in common is that they're multiples of 10, so when dividing they by 10 it will be an exact division. That is, that the remainder of the integer division between all this values and 10 will be 0. So in fact, we want to show a new picture when this expresion is true: (time % 10) == 0. So we would do something like that: if ( (time % 10) == 0 ) { setImage("GuessIt/" + girls[getRandom(10)] + ".jpg") wait(1.5) } Note that we have added a call to wait(1.5) after seting the image. This is to ensure time will have a different value in the next loop, so we do not change immediately the picture we just set in the previous loop. Packing all that together, our 'custom' wait will look as follows: def startTime = getTime() def time = getTime()-startTime while (time < 180) { if (time == 60) show("Go on " + loadString("intro.name") + "! \n\nJerk it!") else if (time == 120) show("Stroke your cock faster! But do not cum yet!") if ( (time % 10) == 0 ) { setImage("GuessIt/" + girls[getRandom(10)] + ".jpg") wait(1.5) } time = getTime()-startTime } After having had the user jerking for 3 minutes, we can command him to hit the edge: show("Okay! Jerk your dick to the edge!") showButton("Edging!") Then we will leave two options for the user. If he has answered right all the questions, he can have a full orgasm. And if he has not, he will have to ruin that orgasm: if (correctAnswers < 20) { setImage("default-female.jpg") show("Ruin it! Ruin that orgasm now!") showButton("Ruined") show("Try to do better next time if you want to enjoy a full orgasm.") wait(7) } else { show("Cum! Cum now! Download all that excitation!") showButton("I cum") setImage("default-female.jpg") } With that we have finished rewarding the user. Now it's time to write the punishment the user will recieve if he doesn't answer right the questions. We will write the punishment code inside the else block of the if that checks if the user should be rewarded or punished. We can start filling it with this: show("Not good at all! You must be punished.") wait(5) As a punishment we are going to spank the user. We can check the toy list of the user in the data registry to select a spanking implement. This is very easy to do with the method loadFirstTrue and a switch statement: def spankTool switch( loadFirstTrue("toys.paddle", "toys.crop", "toys.whip") ) { case "toys.paddle": spankTool = "paddle" break case "toys.crop": spankTool = "crop" break case "toys.whip": spankTool = "whip" break default: spankTool = "wooden spoon" } Now in the variable spankTool is a String with the spanking implement. As you can see, if the user doesn't have any spanking toy, we are going to use a wooden spoon, assuming that everybody have wooden spoons in their homes. We can now get the user ready to be spanked: show("Bring me a " + spankTool + "! Now!") showButton("Got it") show("I'm going to spank your ass! Take off your pants and undies!") showButton("Done") show("To the floor now! Get on all fours!") wait(7) show("Get ready to spank your ass to the beat! Spank it hard! Like I would spank you!") wait(10) As you probably have seen in other scripts, is common to command the user to spank himself everytime that a sound of a spank is played in the script. So to 'spank' the user, we can do something like this: show("Spank your ass hard!") (1..25).each { playBackgroundSound("swat.wav"); wait(3) } This will reproduce the default SexScripts 'swat.wav' 25 times as you can easily see. So the user, will have to spank himself 25 times under this convention. But 25 spanks is not really that much. Let's spank him another 25 times, but this time faster (waiting 1.5 seconds instead of 3 between swats) show("You call that hard? Spank your ass harder! And I mean really hard!") wait(10) show("Spank it very hard! I want it red!") (1..25).each { playBackgroundSound("swat.wav"); wait(1.5) } And with that we can finish the punishment: show("Well, I guess it is enough.") wait(5) The only thing that remains is to say good bye and finish our script: show("I enjoyed our game!\n\nI hope to see you soon to play again!\n\nChao!!!") wait(7) show(null) setImage(null) And that's all. We have finished writting our script!!! We can now change the develop state of our script from "started" to "complete" in the setInfos call. But before releasing it, we should run it several times trying to find any bug that managed to escape from us, and to see that everything is working fine. Now you should try to write more and more scripts. Surely you will have your mind full of ideas about new and original scripts. Well, now is the perfect moment to start developing them, and making them a reality like we have just done with 'Guess it!'. Do not forget to use the SexScripts forums to ask any doubt about SexScripts and script writing, or just to explain your opinion and ideas to the community. And do not forget either to publish all the scripts you write as soon as they're ready! Here is the whole code of the example script we've programmed in this chapter setInfos(4, "Guess It!", "Try to guess the name of the girl by only looking at one part of her body.", "Wololo", "complete", 0xFFFF80, "en", ["formale", "feet", "spanking", "game"]) def girls = [ "alice", "ashley", "chelsea", "christina", "dolly", "francise", "kate", "lucy", "samantha", "stella" ] def bodyParts = [ "boobs", "groin", "feet" ] // Presentation setImage("default-female.jpg") if (loadBoolean("guessit.runbefore")) { // The script has been executed before show("Hi " + loadString("intro.name") + "!\n\nI'm glad to see you again!") wait(4) if (!getBoolean("Do you want to play the 'Guess it!' game again?")) { show("Okay...\n\nI hope to see you soon to play it!") wait(5) show(null) setImage(null) return null } } else { // First time running the script show("Hello " + loadString("intro.name") + "!") wait(4) show("I want to play a funny game with you honey.") wait(5) show("This game it's called 'Guess it!'. The rules are simple: First I'll show you some girls " + "and tell you their names. Try to remember them! This is important for you, because after that, " + "I will show you only a part of the body of one of those girls, and you will have to tell me " + "that girl's name. ") showButton("Understood") show("I will continue asking you to guess to what's girl belong more body parts. If you answer correctly " + "most of the girls, you will be rewarded!\n\nBut do a bad performance and you will be punished...") showButton("Okay!") save("guessit.runbefore", true) } show("Okay!\nThen let's start playing!") wait(5) // Present the girls show("I'm going to show you the girls. Try to remember their names... and their bodies!") wait(10) for (girl in girls) { setImage("GuessIt/" + girl + ".jpg") def presentGirlMsg = [ "That girl is ", "This beauty is called ", "This girl's name is " ] show( presentGirlMsg[ getRandom(3) ] + girl ) wait(9) } setImage("default-female.jpg") show("I hope you remember the girls! Are you ready to start?") showButton("I'm ready!") // Game rounds show("Okay!\n\nThen let's go!") wait(5) def correctAnswers = 0 def lastGirl = null def lastPart = null (1..20).each { def girl = girls[ getRandom(10) ] def part = bodyParts[ getRandom(3) ] while (girl == lastGirl) girl = girls[ getRandom(10) ] while (part == lastPart) part = bodyParts[ getRandom(3) ] setImage("GuessIt/" + girl + part + ".jpg") def questions = [ "Who is this girl?", "What's her name?", "Which girl has this "+part+"?" ] def answer = getString(questions[ getRandom(3) ], "") answer = answer.toLowerCase().trim() setImage("GuessIt/" + girl + ".jpg") if (answer == girl) { // Correct answer show("Correct!\n\nShe is " + girl + "!") correctAnswers++ } else { // Wrong answer show("Wrong!\n\nShe is " + girl + "!") } wait(8) setImage("default-female.jpg") def nextMsg = [ "Let's go with the next!", "Ready for the next one?", "Get ready to guess the next girl!" ] if (it < 20) show(nextMsg[ getRandom(3) ]) else show("Well, that's enough. That was the last question.") showButton("Okay") lastGirl = girl lastPart = part } // Show results show("You got " + correctAnswers + " correct answers.") wait(7) if (correctAnswers >= 17) { // Reward if (correctAnswers == 20) show("You haven't given any wrong answer!") else show("Pretty good! You missed very few answers.") wait(5) show("Let's celebrate it!\n\nWhy don't you stick out that cock and get it hard for me?") showButton("Done") show("Jerk your cock to the girls!") wait(2) def startTime = getTime() def time = getTime()-startTime while (time < 180) { if (time == 60) show("Go on " + loadString("intro.name") + "! \n\nJerk it!") else if (time == 120) show("Stroke your cock faster! But do not cum yet!") if ( (time % 10) == 0 ) { setImage("GuessIt/" + girls[getRandom(10)] + ".jpg") wait(1.5) } time = getTime()-startTime } show("Okay! Jerk your dick to the edge!") showButton("Edging!") if (correctAnswers < 20) { setImage("default-female.jpg") show("Ruin it! Ruin that orgasm now!") showButton("Ruined") show("Try to do better next time if you want to enjoy a full orgasm.") wait(7) } else { show("Cum! Cum now! Download all that excitation!") showButton("I cum") setImage("default-female.jpg") } } else { // Punishment show("Not good at all! You must be punished.") wait(5) def spankTool switch( loadFirstTrue("toys.paddle", "toys.crop", "toys.whip") ) { case "toys.paddle": spankTool = "paddle" break case "toys.crop": spankTool = "crop" break case "toys.whip": spankTool = "whip" break default: spankTool = "wooden spoon" } show("Bring me a " + spankTool + "! Now!") showButton("Got it") show("I'm going to spank your ass! Take off your pants and undies!") showButton("Done") show("To the floor now! Get on all fours!") wait(7) show("Get ready to spank your ass to the beat! Spank it hard! Like I would spank you!") wait(10) show("Spank your ass hard!") (1..25).each { playBackgroundSound("swat.wav"); wait(3) } show("You call that hard? Spank your ass harder! And I mean really hard!") wait(10) show("Spank it very hard! I want it red!") (1..25).each { playBackgroundSound("swat.wav"); wait(1.5) } show("Well, I guess it is enough.") wait(5) } show("I enjoyed our game!\n\nI hope to see you soon to play again!\n\nChao!!!") wait(7) show(null) setImage(null) // This script is protected by this license: // CC by-NC, see http://creativecommons.org/licenses/by-nc/3.0/ 10. I wish I could do that... ------------------------------- ------------------------------- In this chapter you will find simple Groovy code snippets to do some cool things you might want to do in your scripts. Some of them use Java objects, but don't be afraid, we will always use them in a very simple way. We don't like things to get too complicated. 10.1. What time is it? ----------------------- Sometimes you will find that is useful to know the time your script is running at. To get the current time in a script is actually very simple: def time = new Date().format("HH:mm") This instruction will store into variable time a String containing the current time, in the format HH:mm (hours:minutes) you can see that result with the following code: def time = new Date().format("HH:mm") show("Now it's" + time) If you want, you can get the time more precise, extending it with the current second: def time = new Date().format("HH:mm:ss") show("Now it's" + time) With a very similar instruction, you can get the current date: def date = new Date().format("yyyy-MM-dd") show("Today is " + date) That code will show the current date in the format year-month-day. But we can change it to write it in the format we most like. For example, to show the current date in a day/month/year format we can write this: def date = new Date().format("dd/MM/yyyy") show("Today is " + date) We can also, get the current date and time together: def dateTime = new Date().format("yyyy-MM-dd HH:mm:ss") show("Current date-time: " + dateTime) And by now, if you carefully look at that format String you can guess how to get the current date and time in the format you like most. For example, you can try this one: def dateTime = new Date().format("dd/MM (yyyy) - HH:mm") show("Current date-time: " + dateTime) But sometimes you'll want to do more things with the current date/time than showing it as a text. For example, you might want to know the current hour to know if it is at night, or at day that your script is running. You could get the current hour similarly as the above codes with something like: def hour = new Date().format("HH") But with that comes the issue that now the variable hour is containing the hour, but as a String, and you will want it to be an integer number. Of course there're ways to transform that String in the number it contains, but you can easier get the current hour as an integer number directly with something like this: def hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) And now you have the hour as an integer number, you can easily check if the script is running by day or by night. Let's say that the sun is shinning between 6:00 and 20:59 to make it easy: switch (hour) { case 6..20: show("You are running this crap by day") break default: show("You are running this crap by night") } Like we got the hour as an integer, we can also get the current year, month, day, minute and second as integer numbers: def year = Calendar.getInstance().get(Calendar.YEAR) def month = Calendar.getInstance().get(Calendar.MONTH) def day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) def hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) def minute = Calendar.getInstance().get(Calendar.MINUTE) def second = Calendar.getInstance().get(Calendar.SECOND) 10.2. How long has my script been running? And how many times has it been executed? ------------------------------------------------------------------------------------ For some scripts you could write, you might want to know how long your script has been running at some point in the code. You could achieve that by taking a timestamp with getTime() at the very beginning of your script, let's say just before the setInfos call: def startTimestamp = getTime() And then wherever you want in your code you can get the number of seconds your script has been running with: def time = getTime() - startTimestamp And it would work perfectly fine. But really, there's no need of you to take that timestamp at the begining of your script because SexScripts does it for you. For any script you are writing, you can access the key "yourScript.launch.lasttime" (replace 'yourScript' here for your script name! It has to be the same as the groovy file containing your script without the .groovy extension, not the title of your script) in the data registry of SexScripts. Under this key, there will be stored as an integer number the timestamp your script has begun at. So without any need to declare anything at the beginning of your script, you can use this instruction to get the number of seconds your script has been running at any point in the code: def time = getTime() - loadInteger("yourScript.launch.lasttime") Only remember to change 'yourScript' by your actual script name. SexScripts also stores for each script it runs another timestamp, under the key "yourScript.launch.firsttime", that is the timestamp when your script was executed for its very first time. So if it happens that you are interested in knowing how many seconds have elapsed since your script was executed for the very first time, you can use that line of code: def time = getTime() - loadInteger("yourScript.launch.firsttime") Probably that last info can be curious, but won't be that useful at all. But another info that can be useful is the number of times your script has been executed. Not that it would be hard to keep that count ourselves, but we already don't have the need of doing it because SexScripts keeps that count for us. The number of times your script has been executed is stored in the data registry under the key "yourScript.launch.nb" (remember to replace 'yourScript' by your script name). We can very easily get that count: def times = loadInteger("yourScript.launch.nb") And do whatever we want with it. Note that that value will be 1 for the very first time your script is executed, it will be 2 for the second time, 3 for the third, and so on. 10.3. Opening other scripts ----------------------------- You should know by now how to close your script. A return null statement will finish your script immediately: return null But sometimes you will want to execute some other script when closing your script instead of just finishing it and doing noyhing more. That can be the case if for example your script is a big routine and is composed of various subscripts. Each one in a separate groovy file. That's not a problem at all, in SexScripts it is really easy to open another script. You just have to 'return' it when closing your script instead of returning null: return "someOtherScript" Replace in that line of code 'someOtherScript' by the name of the script you wish to open. The name of a script it's not its title, but the name of the groovy file it is without the groovy extension. For example, if you wish to open a script that is in the file 'coolscript.groovy', you should write this: return "coolscript" If you put return "coolscript.groovy" instead, SexScripts will try to open the file 'coolscript.groovy.groovy' and fail to open it. Also note that you must provide the path to the script you want to open if it is in any subfolder. For example, let's assume we want to open 'coolscript.groovy' that is in the folder 'Coolest' located in the scripts folder of SexScripts. Then you will use: return "Coolest/coolscript" to open it. 10.4. Writing and reading files --------------------------------- Writing and reading from any file in groovy is really very simple. In this manual tough, we are only going to see how to write and read from simple text files, the more basic ones. Let's start with writing to them. Let's say we want to write the text "I'm sexy and I know it" in a file called 'myScript.dat'. We will do something like this: def file = new File("myScript.dat") file.write("I'm sexy and I know it") And that's all. Pretty simple, isn't it? But note a pair of things here: First, if the file 'myScript.dat' didn't exist before executing that code, it would be created with the instruction that performs the write, and not with the first instruction def file = new File("myScript.dat"). Do not let that 'new File' decieve you, it doesn't create any new file in your filesystem, it only creates a new 'file object' to be used in your script. And note also that the file 'myScript.dat' would be created in the SexScripts folder. Second, if the file 'myScript.dat' already exists when executing that code, all the text it contained will be overwritten. To append (write at the end of the file) the text in the file instead of overwritting it we could have used something like this instead: def file = new File("myScript.dat") file.append("I'm sexy and I know it") If the file didn't existed before the execution of the above piece of code, append will create it the same way as write does. Write will always overwrite the file and append will always write its text at the end of the file without deleting a single character from the file. Use one or the other depending on what you want to do. Note that you can also delete all the contents of a file with these instructions: def file = new File("myScript.dat") file.write("") But if what you want is to write different lines to your file, you could append them followed by the "\n" character. But if you do it that way, you run the risk of not being able to read it properly later, depending on the system your script is executed. The reason for this is that not all the systems use "\n" to separate lines in files. Some use it, but others use "\r", and others use "\r\n", ... But this problem has an easy solution. The system's line separator character can be get this way: def newLine = System.getProperty("line.separator") So instead of using "\n" to separate the lines we write, now we just have to use newLine. So now we can properly write several lines into a file: def newLine = System.getProperty("line.separator") def file = new File("myScript.dat") file.append("This is the first line" + newLine) file.append("This is the second line" + newLine) file.append("And this is the last line") The only issue with this last code is that what happens if the file 'myScript.dat' exists before the code is executed. If it had already some text in it, it won't be deleted, and all these lines we write will be added at the end of what it prevously had. If this is the behaivour we want our code to have, then perfect, this won't be an issue at all. But if we want to overwrite the file in that case with all our lines, we can change the above code as follows: def newLine = System.getProperty("line.separator") def file = new File("myScript.dat") file.write("This is the first line" + newLine) file.append("This is the second line" + newLine) file.append("And this is the last line") And it will all work perfectly. If writing a file in Groovy is simple, reading it is simpler: def fileLines = new File("myScript.dat").readLines() And that's all. The variable fileLines contains now a list of Strings, where each String is a line of the file. We can now do whatever we want with them, like showing them in the SexScripts window: def fileLines = new File("myScript.dat").readLines() for(line in fileLines) { show(line) wait(2) } But if we can't be bothered to create a list to read the file, we can use the following code to reach the same exact result: new File("myScript.dat").eachLine { line -> show(line) wait(2) } 10.5. Ask the user for a picture --------------------------------- Asking the user to send the script a picture, to later show it, is a task a lot of scripts want to perform. And doing that in Groovy is as easy as walk on the street. To do that, we simply ask the user for a picture with the getFile(caption) method, and make a copy of that picture in our script images folder. We will then be able to show that picture elsewhere in our code like if it'd been always there. So, first we get the path of the user's picture with getFile: def filePath = getFile("Select a picture") We are going to make a copy of it in our script's images folder and we are going to name that copy 'yourPic.jpg' in that example. But before copying it, we must be sure it doesn't exist already: new File("images/yourscript/yourPic.jpg").delete() This instruction deletes 'yourPic.jpg' if it already existed, and does nothing if it didn't exist. So now we can safely copy the picture the user gave us to 'yourPic.jpg': new File("images/yourscript/yourPic.jpg") << new File(filePath).getBytes() And that's all! From that point on the code, we can show that image with a simple setImage(pic) call: setImage("yourscript/yourPic.jpg") That easy. If your script is going to use a lot this feature, it can come handy to enclose this functionality into a closure to easily use it several times in your script (we'll see better the closures in the next chapter): def saveUserPicture = { pic -> def filePath = getFile("Select a picture") new File("images/"+pic).delete() new File("images/"+pic) << new File(filePath).getBytes() } And from now on we can use saveUserPicture(pic) as any other method in the API, where pic is the name we want to put to the copy of the user's picture, relative to SexScripts images folder. Let's see a full example of its usage: def saveUserPicture = { pic -> def filePath = getFile("Select a picture") new File("images/"+pic).delete() new File("images/"+pic) << new File(filePath).getBytes() } setImage("default-female.jpg") show("Hello!") wait(4) show("Can you send me a picture?") wait(4) saveUserPicture("yourscript/yourPic.jpg") show("Great! Do you want to see it?") showButton("Yeah!") show("Here it is!") setImage("yourscript/yourPic.jpg") 10.6. Wait while showing the exact waiting time ------------------------------------------------ When in our scripts we are performing long waits is always better to use the waitWithGauge(time) method instead of the wait(time) method, so the user knows at least that the script hasn't frozen. But while the gauge bar in the waitWithGauge(time) call is pretty cool, sometimes in our scripts we'll prefer to perform a wait showing a 'clock' with the exact time the wait is taking instead a gauge bar. We can do that with some code like the following: setImage("default-female.jpg") show ("Wait there for 2 minutes!") wait(4) def startTime = getTime() def waitedTime = getTime()-startTime while ( waitedTime < 120 ) { int minutes = waitedTime / 60 int seconds = waitedTime % 60 def minutesExtraDigit = "" if (minutes < 10) minutesExtraDigit = "0" def secondsExtraDigit = "" if (seconds < 10) secondsExtraDigit = "0" show( minutesExtraDigit + minutes + ":" + secondsExtraDigit + seconds ) waitedTime = getTime()-startTime } show ("Here I am again!") This piece of code doesn't contain anything new to you, so try to execute it to see how it works, and then read every line of code carefuly to understand it. If we liked this way to perform waits, and we are going to perform several waits like this in our script we can think of enclosing the wait functionality into a closure (More on closures in the next chapter): def waitWithCount = { time -> def startTime = getTime() def waitedTime = getTime()-startTime while ( waitedTime < time ) { int minutes = waitedTime / 60 int seconds = waitedTime % 60 def minutesExtraDigit = "" if (minutes < 10) minutesExtraDigit = "0" def secondsExtraDigit = "" if (seconds < 10) secondsExtraDigit = "0" show( minutesExtraDigit + minutes + ":" + secondsExtraDigit + seconds ) waitedTime = getTime()-startTime } } setImage("default-female.jpg") show ("Wait there for 2 minutes!") wait(4) waitWithCount(120) show ("Here I am again!") If we prefer the time counting during the wait to count down instead of counting up, we can make it very easily with that subtle change: def waitWithCountDown = { time -> def startTime = getTime() def waitedTime = getTime()-startTime while ( waitedTime < time ) { int minutes = (time - waitedTime) / 60 int seconds = (time - waitedTime) % 60 def minutesExtraDigit = "" if (minutes < 10) minutesExtraDigit = "0" def secondsExtraDigit = "" if (seconds < 10) secondsExtraDigit = "0" show( minutesExtraDigit + minutes + ":" + secondsExtraDigit + seconds ) waitedTime = getTime()-startTime } } setImage("default-female.jpg") show ("Wait there for 2 minutes!") wait(4) waitWithCountDown(120) show ("Here I am again!") 10.7. Dynamic text ------------------- The show(message) call is probably along with wait(time) and posibly with setImage(picture) the most used methods in the API. So to create very cool scripts we will have to use those methods in a very cool way, they're probably the most important methods in any script. To perform waits, in addition to wait(time) we can use waitWithGauge(time), or perform some of the waits described in the above section of this chapter. To show images in a very cool way we can use the code described in the below section. So in this section we can see how to show text in a very fancy way. With a simple show(message) call the message will be shown in one shot. But it can be sometimes cool to let the message appear slowly instead than in one shot. There are various ways to show a message slowly, but one very simple is the following one: def message = "Hello!\n\nDon't you think this is a very awesome message?" def appearedMessage = "" for (c in message) { appearedMessage += c show(appearedMessage) wait(0.025) } showButton("Yes!") You can run it to see how it performs the showing of the message. There's not a lot to say about that code, is very simple. You shouldn't have any problem understanding it. If you find it shows the message too slow or too fast for your taste you can modify the time in the wait call. Or better than that, you can define a variable like this one: def textSpeed = 40 And change the previous wait call by this one: wait( 1/textSpeed ) And now you can define at what speed the message is going to be shown only modifing the variable textSpeed anywhere in your code. The speed in that variable represents characters/second, that is, the number of characters that are going to appear in one second. If you are thinking about using this way or some other similar to show the messages in your script, you better enclose that code in a closure and not write all the time the same loop everywhere in your script every time you are going to show a message: def textSpeed = 40 def showDynamically = { message -> if (textSpeed <= 0) textSpeed = 0.1 def appearedMessage = "" for (c in message) { appearedMessage += c show(appearedMessage) wait(1/textSpeed) } } wait(1) showDynamically("Hello!\n\nDon't you think this is a very awesome message?") showButton("Yes!") We'll see more about closures in the next chapter. 10.8. Dynamic images --------------------- If you use the method setImage(picture) a lot in your scripts but start to get a bit bored of it, this section is for you! A simple call to setImage(picture) will show the picture in one shot. Sometimes you just want that, but other times it would be cool to have a similar method, let's say setImageFancy(picture), that will animate a bit the showing of the picture. Well then, like everything that can come up to your mind, if you want it in your script, you can have it. You only need to know the how. Graphics handling is out of the scope of this simple manual, so we are not going to enter too much in the details of the code in this chapter. But you can copy-paste it into your script and use it anyways as you like. By the way, why don't you try to copy this pair of closures somewhere at the begining of some test script? def imageSpeed = 40 def setImageFancy = { picture -> if (imageSpeed <= 0) imageSpeed = 0.1 def image = java.awt.Toolkit.getDefaultToolkit().getImage("images/"+picture) def width = image.getWidth() def height = image.getHeight() (1..10).each { def frameBuffer = new java.awt.image.BufferedImage( (int)((width*it)/10), (int)((height*it)/10), java.awt.image.BufferedImage.TYPE_4BYTE_ABGR) def sprite = javax.imageio.ImageIO.read(new File("images/"+picture)) java.awt.Graphics2D graphics = frameBuffer.createGraphics() graphics.drawImage(sprite, 0, 0, (int)((width*it)/10), (int)((height*it)/10), null) setImage(frameBuffer, false) wait(1/imageSpeed) } } def setImageOffFancy = { picture -> if (imageSpeed <= 0) imageSpeed = 0.1 def image = java.awt.Toolkit.getDefaultToolkit().getImage("images/"+picture) def width = image.getWidth() def height = image.getHeight() (1..10).each { def frameBuffer = new java.awt.image.BufferedImage( (int)(width/it), (int)(height/it), java.awt.image.BufferedImage.TYPE_4BYTE_ABGR) def sprite = javax.imageio.ImageIO.read(new File("images/"+picture)) java.awt.Graphics2D graphics = frameBuffer.createGraphics() graphics.drawImage(sprite, 0, 0, (int)(width/it), (int)(height/it), null) setImage(frameBuffer, false) wait(1/imageSpeed) } setImage(null) } More on closures in the next chapter! Do not worry if you do not understand this code pretty well. What that closures do is the next: The first one, setImageFancy(picture) will set a picture to be shown just like setImage(picture) does, but it will let the picture to appear gradually instead than doing it in one shot. The second closure, setImageOffFancy(picture), will gradually show off the picture, and when it finishes, it has the same effect as setImage(null). You can play and call this pair of closures in some test script, to check if they're fancy enough for your scripts. You can also modify the variable imageSpeed anywhere in the code to change the speed the images are going to appear and disappear at. Just remember to resize your images to a normal size (Do not use images with big resolutions like 2000x3000) before adding them to SexScripts, if you are looking forward to show them with these closures (you won't lose, SexScripts will resize them anyways before showing them if they're too big). You can try how this closures perform with that test code for example: setImage(null) wait(2) setImageFancy("default-female.jpg") show("Hello!\n\nI'm the default female!") showButton("Great!") setImageOffFancy("default-female.jpg") setImageFancy("default-male.jpg") show("And I'm the default male.") wait(4) setImageOffFancy("default-male.jpg") setImageFancy("default-female.jpg") show("I hope to see you soon!") wait(4) show(null) setImageOffFancy("default-female.jpg") 11. Rocking with Groovy --------------------------- --------------------------- By now you should have quite a good basis and enough script writing knowloedge to practically write any script you want to. And everytime you write a new script, you will probably want to make it fancier than your previous scripts. And you will want to use more advanced programming concepts every time to achieve your goals. So, although posibly slowly, the complexity of the scripts you write will increase with the time. All the Groovy topics explained in this guide are only a small part of the whole world of Groovy. And if you find that what you know about Groovy is not enough to write some cool features in your script, maybe you find useful this chapter. Here we are going to see some more advanced topics in Groovy than the ones explained by now. Note that practically all the topics discussed in this chapter are too complex and unnecesary for the most of the scripts. When writing scripts for SexScripts you should try always to avoid doing things more complex than the needed. Always write your code as simple and understandable as posible. Despite of this, for some complex scripts, one or more of the concepts explained in this chapter can be useful. 11.1. Advanced Operators ------------------------- There are a lot more operators in Groovy than the ones we've seen. With them you can write really complex expressions. In this section we are going to see some of them. The first ones we are going to see are a pair of unary operators that are not that new to you. I am talking about the increment (++) and decrement (--) operators. You know they increment and decrement respectively a variable by one. What you may not know is that they can be assigned into another variable or used in a expression while incrementing/decrementing a variable. And if we write them to the right of the variable (as we are used) they will return the value that variable had before incrementing/decrementing it. But if we write it to the left of the variable, they will return the value that variable have after incrementing/decrementing it. Let's an example: def x = 5 def y = 5 def foo = x++ // Post-increment def cow = ++y // Pre-increment At the end of this code, both variables x and y will be 6. But while foo will be 5, cow will be 6. Pre and post decrements work exactly the same way: def x = 5 def y = 5 def foo = x-- // Post-decrement def cow = --y // Pre-decrement In this case, at the end of this code, both variables x and y will be 4. But foo will be 5 and cow will be 4. The next operator we'll see is the ternary conditional operator. Posibly the only ternary operator in Groovy. It is used to assing one between two values depending on the result of a boolean expression into a variable or using it in a expression. If I only speak about it, probably you won't understand a crap. So let's see better how it works with an example. Imagine you have the following code in one script: def undies if ( loadBoolean("clothes.thong") ) undies = "thong" else undies = "no undies" Using the ternary conditional operator you can write this in one single line with the same exact result: def undies = loadBoolean("clothes.thong") ? "thong" : "no undies" You see how it works now don't you? It is as follows: ? : But apart than using it as a shorcut for if statements like the one above, it can be used in a expression, allowing you to write very complex ones: def x = -5 def y = 10 def foo = y * ( x < 0 ? -x : x ) This code multiplies y by the absolute value of x and stores the result into foo. As you can see the absolute value of a number is to turn it into positive if it is negative, and to left it as it is if it's already positive or zero. At the end of the above code then, foo will be 50. There is also a shortcut for the ternary conditional operator to return the same evaluated value on the true case and some other on the false case. Let's better see that with an example. Imagine we have that code in our script: def lastName = loadString("slave.LastName") ? loadString("slave.LastName") : "Unknown" As null turns into false when evaluated as a boolean, and all Strings turn into true when evaluated as a boolean, this instruction will set in lastName the value stored under the key "slave.LastName" if it exists. And if that key doesn't exist, it will just set "Unknown" in lastName. This can be written with the same exact result as: def lastName = loadString("slave.LastName") ?: "Unknown" The next operator we are going to see that can come handy sometimes, is the spread operator. Its symbol is *. and it is used to perform an action over all the items in a collection, like lists, ranges or maps (We'll see them later). It returns a list with the same size as the collection we have operated, containing for every item in the original collection the result of the operation. It sounds very weird with words, but as we can see in this example, the spread operator is really intuitive and easy to use: def greetList = [ "Hi", "world", "!" ] def resultList = greetList*.size() After these two lines are executed, resultList will contain the list [ 2, 5, 1 ]. The last operator we are going to see, is the less/equal/greater comparator. Its symbol is <=> and is used to compare two values. It works similarly as the other comparator operators (==, <, >, <=, etc) but instead of returning a boolean it returns an integer number. More precisely, it returns -1 if the value to the left is smaller than the value to the right, it returns 0 if the two values are equal, and it returns 1 if the value to the left is greater than the value to the right. It's a simple operator let's just see an example of it. Imagine we have somewhere in our code two variables defined: timeElapsed containing the amount of seconds it took the user to perform the action, and timeThreshold containing the maximum amount of seconds allowed for the user to perform that action. We could put the following in our code: switch (timeElapsed <=> timeThreshold) { case 1: show("You are late!") wait(4) break case 0: show("Wow! just in the exact time") wait(4) break case -1: show("You've done it in time") wait(4) } 11.2. Maps ----------- Maps are in Groovy something very similar to lists, but instead of having its elements ordered and accessed by an index starting at 0, the items in a map are accessed with a key. The keys are usually Strings identifying the item that's stored under them. Maps work similarly as the data registry of SexScripts. To create a map, you can do something like the following: def map = [ id:12345, hours:15, minutes:21, seconds:14 ] As you see you write them similarly as you write lists. You enclose the pairs key-item contained in a map between square brackets, and separate them by commas. To define each item in a map you write its key folowed by : and followed by the item. The keys that exist in the map of the above example are "id", "hours", "minutes" and "seconds". And the values contained under them are all integer numbers, that are 12345, 15, 21 and 14 respectively. Note that you do not have the need to enclose the keys between single or double quotes when defining the map, despite they are Strings. This is because a key like those in a map is always a String, so it is understood that they are Strings although you do not put the " nor the '. If you really have the need to define the key in a map as the String contained in some variable, you can enclose it between parentheses and it will be interpreted as a variable and not directly as a String: def var = "id" def map = [ (var):12345, hours:15, minutes:21, seconds:14 ] This code will define the exact same map as the previous. As you can create an empty list with [], you can also create an empty map with [:] def map = [:] def x = map.size() As with you do with lists, you can also use the method size() to get the number of elements contained in a map. After this last example is executed, x will be 0. And of course, as it happened with lists, various types of values can be contained in a map: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] To access to an item in a map is very easy: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] def whatName = map.name After these lines are executed, the variable whatName will contain "John". Note that again, we have not enclosed the key between any quotes. You can also access an element in a map using the referencing square brackets [ ] as we do with lists. The next example is equivalent to the above: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] def whatName = map["name"] But this time we have to use quotes when writing the key or it will be interpreted as a variable. And we can also use if we like the method get(key) that returns the map item under the given key: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] def whatName = map.get("name") If we access a key that is not contained in the map we will get null: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] def x = map.weight After these lines are executed, the variable x will be containing null. To insert items in a map is the easiest thing in the world in Groovy: def map = [ name:"John" ] map.lastName = "Doe" map["age"] = 45 map.put("isBlonde", false) After this code is executed, map will be the map [ name:"John", lastName:"Doe", age:45, isBlonde:false ]. If you don't like to use Strings as keys, you can also use numbers: def map = [ 1:"one", 2:"two", 5:"five", 6:6, 12:3.1416 ] Or inclusive both key types mixed: def map = [ 1:"one", 2:"two", 5:"five", six:6, coolKey:":-)" ] But be aware when accessing keys that are not Strings. While this code will run perfectly: def map = [ 1:"one", 2:"two", 5:"five", 6:6, 12:3.1416 ] def x = map[2] def y = map.get(12) Accessing like this will launch an error: def map = [ 1:"one", 2:"two", 5:"five", 6:6, 12:3.1416 ] def x = map.2 Similarly, you can input items under a numeric key in a map like this: def map = [:] map[1] = "one" map.put(2, "two") But do not do anything like this if you don't want a nasty error to slap your face: def map = [:] map.1 = "one" Accessing an item in a map and inserting items into a map with the way map.key is reserved for String keys only. We can also if we feel the need, use boolean values as keys in a map: def map = [ (true):"That's true", (false):"No way!" ] def t = map[true] def f = map.get(false) But there are only two possible boolean keys: true and false. Thanks captain obvious! We can even use null as a key in a map: def map = [ (null):"Nothing here!" ] def n = map[null] As it happened with lists, in Groovy there are a full set of built-in methods to operate with maps. We've already seen some, like size(), get(key) an put(key, value). But there are a lot more. for example, isEmpty() will return true if there are no items in the map at all, and false otherwise: def map = [:] def b = map.isEmpty() After that, b will be true. To remove all the items from a map, we can use the method clear(): def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] map.clear() def b = map.isEmpty() After that, b will be also true. The methods containsKey(key) and containsValue(value) are also very intuitive. They will return true if the given key/value is contained in the map, and return false otherwise: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] def a = map.containsKey("name") def b = map.containsValue("John") def c = map.containsValue("name") After that, a and b will be true and c will be false. If we want to remove an item from the map, we can use the method remove(key): def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] map.remove("age") After the execution of this example, map will be the map [ name:"John", lastName:"Doe", isBlonde:false, height:1.85 ]. To iterate over all the items in a map, as we did with lists, we can use the each bucle. This time, the implicit variable it, will be a pair key-value from the map. To access the key of the item we are iterating in a given loop, we will use it.key. Similarly to get its value we will use it.value: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] map.each { show("key: " + it.key + "\nvalue: " + it.value ) wait(3) } Note that in Groovy maps don't care about the order of its elements. So when iterating over a map with a bucle like this you can expect to iterate over each item in the map once and only once. But do not expect to iterate over them in any particular order. You can also use a for bucle to iterate over a map in a very similar way like each: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] for ( i in map ) { show("key: " + i.key + "\nvalue: " + i.value ) wait(3) } If you don't care about the keys, you can specificly iterate only over the values in a map: def map = [ name:"John", lastName:"Doe", age:45, isBlonde:false, height:1.85 ] for ( v in map.values() ) { show("value: " + v ) wait(3) } 11.3. Closures --------------- Doesn't happened to you that sometimes you find yourself repating again and again the same lines of code at several points just because you need to do the same things at several points in your code? That can lead to make scripts larger harder to read. But don't worry, Groovy has a solution for you! Imagine we are writing some script where we spank the user a lot: show("Okay get ready to be spanked!") wait(7) show("Spank your ass hard!") (1..20).each { playBackgroundSound("swat.wav") wait(3) } show("This isn't over...") wait(5) show("Spank your ass harder!") (1..20).each { playBackgroundSound("swat.wav") wait(3) } show("Hope you learned the lesson") if ( getBoolean("How should be always a slave?", "Sitting on the sofa", "Kneeling at your feet") ) { show("Wrong! More spanking to you!") wait(7) show("Spank your ass to red!") (1..20).each { playBackgroundSound("swat.wav") wait(3) } } else show("Correct!") wait(5) And our script goes on, and every time we want to spank the user we find ourselves writing the same bucle again and again: (1..20).each { playBackgroundSound("swat.wav") wait(3) } It would be cool to have these instructions stored somewhere for us to execute them every time we want to. In Groovy that is possible. You first have to enclose the code you want to store between curly brackets: { (1..20).each { playBackgroundSound("swat.wav") wait(3) } } And you have created what in Groovy is known as a closure. And as everything in Groovy, we can store closures into variables: def spank = { (1..20).each { playBackgroundSound("swat.wav") wait(3) } } Now our variable spank contains a closure. And a closure is in fact executable code. So actually, what is contained in the variable spank is executable code. And we can easily execute it by calling it. We will call the variable spank as it was a method in order to execute the code that contains: spank() This easy! Every time we want to execute the code in the closure, we just have to call the variable it is contained in. So with that in mind we can write our spanko script easier: def spank = { (1..20).each { playBackgroundSound("swat.wav") wait(3) } } show("Okay get ready to be spanked!") wait(7) show("Spank your ass hard!") spank() show("This isn't over...") wait(5) show("Spank your ass harder!") spank() show("Hope you learned the lesson") if ( getBoolean("How should be always a slave?", "Sitting on the sofa", "Kneeling at your feet") ) { show("Wrong! More spanking to you!") wait(7) show("Spank your ass to red!") spank() } else show("Correct!") wait(5) This closure will make it less painful to write our script. But what if we want at some point spank the user more than 20 times? And if we want to spank him faster? If we have to write a closure for each spanking configuration we want closures won't be that helpful at all... Don't worry my nerdy firend! We can use parameters within a script. To define the parameters in a closure we will do something like this: def spank = { message, spanks, time -> show(message) (1..spanks).each { playBackgroundSound("swat.wav") wait(time) } } We have defined in our closure 3 parameters: message, spanks and time. If you look carefuly at the code of the closure you will see that they are respectively a message to be shown during the spanking, the number of spanks, and the seconds to wait between the spanks. We can now call our variable spank as if it was a method with parameters: spank(message, spanks, time) We can re-write our script using this new parametrized closure: def spank = { message, spanks, time -> show(message) (1..spanks).each { playBackgroundSound("swat.wav") wait(time) } } show("Okay get ready to be spanked!") wait(7) spank("Spank your ass hard!", 20, 3) show("This isn't over...") wait(5) spank("Spank your ass harder!", 20, 1.5) show("Hope you learned the lesson") if ( getBoolean("How should be always a slave?", "Sitting on the sofa", "Kneeling at your feet") ) { show("Wrong! More spanking to you!") wait(7) spank("Spank your ass to red!", 30, 3) } else show("Correct!") wait(5) Closures can be really useful in some scripts, and they're really very easy to use. They can 'emulate' perfectly the functionality of any method. They can also return a value, just like methods. To return a value from a closure we can use the return statement. That statement will immediatelly finish the execution of the closure and return some value: def getRandomItem = { itemKeys -> for ( key in itemKeys ) { if ( !loadBoolean(key) ) itemKeys -= key } if ( itemKeys.isEmpty() ) return null return itemKeys[ getRandom(itemKeys.size()) ] } This closure has one parameter that should be a list of keys of either toys or clothes. It will randomly pick one of them that the user has. It will return the key of the picked item or null if the user doesn't have any item from the list. It could be called as follows for example: def implement = getRandomItem(["toys.crop", "toys.paddle", "toys.whip"]) But in fact all closures always return a value. If a return statement is not put at the end of the code of a closure, the value that the last line of the closure is evaluated will be the returned value. So the above closure could be written as follows: def getRandomItem = { itemKeys -> for ( key in itemKeys ) { if ( !loadBoolean(key) ) itemKeys -= key } if ( itemKeys.isEmpty() ) return null itemKeys[ getRandom(itemKeys.size()) ] } And it would work perfectly and with the same exact result as before. Just keep in mind one thing when writing closures. Do not use return null to close your script from a closure. It will only finish the closure, but not your script. To close your script you have to use return null from outside any closure. Closures can be useful to save you time when you use some code again and again in your script. But they can also be useful if you're planning to write some large script. And with large I mean with a lot of hundred of lines of code, maybe thousands. In these cases, using closures to enclose and separate the functionalities of your script can make it more readable. You could finish having a large script with some code structure as this: // Variables .... def initializations = { ... } def greeting = { ... } def performFirstPhase = { ... } def performSecondPhase = { ... } def everythingOk = { ... } def reward = { ... } def punish = { ... } .... initializations() greeting() performFirstPhase() performSecondPhase() if ( everythingOk() ) reward() else punish() And end up with a script that executes the most of the code into closures and not directly into the script. But always think twice if you really need to write such a large script. Most of the time it will be a cleaner and better solution to separate your large script in various smaller subscripts, each one in its own groovy file, where each subscript performs a functionality of your larger script like closures do in the example. So in this case you could finish having the subscript files 'myScriptInitializations.groovy', 'myScriptGreeting.groovy', 'myScriptFirstPhase.groovy', and so on. If you want to share data between various scripts you can easily use the SexScripts data registry for that. 11.4. Math ----------- In some cases it can be necessary to perform some more complicated operations between numbers than the ones we can achieve using the basic operations that Groovy operators let us (+, -, *, /, %). But this isn't an issue at all because the java Math library is totally available in Groovy. There we will find all we need to do the most complicated mathematical operations we can figure out. Most probably we won't ever need to make such complicated calculations in our scripts, but sometimes a pair of methods from that library can come handy. In Math, we can find constants as Math.E (Euler's e number) and Math.PI: show("Number e = " + Math.E + "\n\nNumber pi = " + Math.PI ) But we can find also methods like Math.round(x), that returns the closest integer from a real number: def time = showButton("Done!") time = Math.round(time) The Math methods you will find most useful for your script are the following: Math.abs(x) Returns the absolute value of x Math.round(x) Returns x rounded to the nearest integer Math.ceil(x) Returns x rounded up Math.floor(x) Returns x rounded down Math.pow(x, n) Returns x raised to the power of n Math.sqrt(x) Returns the square root of x Math.cbrt(x) Returns the cube root of x Math.log(x) Returns the natural logarithm (base e) of x Math.exp(x) Returns the number e raised to the power of x Math.sin(x) Returns the sine of x (x must be an angle in radians) Math.cos(x) Returns the cosine of x (x must be an angle in radians) Math.tan(x) Returns the tangent of x (x must be an angle in radians) Math.asin(x) Returns the arc sine of x (smallest angle in radians) Math.acos(x) Returns the arc cosine of x (smallest angle in radians) Math.atan(x) Returns the arc tangent of x (smallest angle in radians) 12. And what now? ------------------ ------------------ You should have by now some good scripting abilities if you read and followed this manual from the begining to the end. So now is a perfect moment to try to do that incredible fancy script you always had in mind but thought it would be very hard to write. You have a proper background and knowledge to write some serious scripts, it may surprise you! So now, get hands to work, and make a handful of good scripts, and don't forget to publish them all to the SexScripts community for everyone to enjoy them!!! You should be by now a good SexScripts scripts writer, but there's always more to learn. And the best way to learn more about script writing, is writing scripts. Put yourself hard dares, try to write hard and intelligent scripts that originally and cleverly gives the user a new experience he has never felt before. And surelly you will learn a lot writing them. There's a lot of Groovy topics not covered in this manual, like String regular expressions (Regex) and bitwise operations, which can bring you the tools you need to build a very clever Mistress that understands his slave written English, or to make a script that efficiently plays various kinds of games. But there's still a lot more of Groovy than that. To read a fully user's guide of Groovy you can check the following link: http://groovy.codehaus.org/ And also you can ask any question about groovy or SexScripts in the SexScripts forums at: http://ss.deviatenow.com/forums.php 13. Quick API guide --------------------- --------------------- Here you will find a reference for each method in the API SexScripts version 4 by alphabetic order. exit() This method will close SexScripts. Use it carefully, it can be a bad experience for the user if you close his SexScripts window without him expecting it. If you only want to exit from your script, it's enough with a return null instruction. getBoolean(message) and getBoolean(message, yesText, noText) This method will set message as the current shown text (usually it will be a String containing a question for the user to answer) and show to the user two buttons for him to click one of them. If you put the yesText and noText parameters, they will be the texts that will be shown on the buttons. If you don't put them, the texts shown on the buttons will be a default "Yes" and "No". This method will wait for the user to click on one of the buttons. And then, it will return true if the user clicked on the 'yes' button and false if he clicked on the 'no' button. This method can be used to ask the user any question that can be answered with yes or no, but it can also be used to ask the user any question with two possible answers. Just put the answers as the yesText and the noText parameters, indepently if they mean 'yes' or 'no'. getBooleans(message, texts, defaultValues) This method will launch a dialog window with the text message in it, followed by a number of checkboxes and an [Ok] button. The parameter texts must be a list of Strings, where each String in the list will be the label of each checkbox (the text that is shown next to each checkbox) in the dialog window. So in the dialog window will be as many checkboxes as elements in the texts list. The parameter defaultValues must be a list of booleans of the same size as texts (with the exact same amount of elements in it). They will be the default state of the checkboxes (true will mean that the checkbox is checked and false will mean it is unchecked). This method will wait for the user to check and uncheck the checkboxes he wants to, and clicks [Ok]. Then the dialog window will be closed and a list of booleans will be returned, again with the exact same size as texts. In that returned list, each element will be true if the user left the corresponding checkbox checked, or false if he left it unchecked. getFile(caption) This method will open a file choosing window for the user to choose any file. The parameter caption must be a String containing the file choosing window caption. This method will wait until the user selects a file or closes the window. Then, a String containing the full path of the file the user's selected will be returned, or null if he closes the window. getFloat(message, defaultValue) This method will set message as the current shown text and will also show the user a text field for him to input some data and a [Ok] button. The data the user is going to input will be a real number, that is, any number, with possibly a period and a decimal part. This method will wait until the user inputs the number and clicks on the [Ok] button. Then, the number the user's typped will be returned. The parameter defaultValue should be a number to be shown as default value in the text field to the user. If you don't mind it, just put a 0.0 as defaultValue. This method is useful to ask the user questions that can be answered with a number that will possibly need to have a decimal part, like his height, his weight, the length of his pennis, etc. getInteger(message, defaultValue) This method will set message as the current shown text and will also show the user a text field for him to input some data and a [Ok] button. The data the user is going to input will be an integer number. This method will wait until the user inputs the number and clicks on the [Ok] button. Then, the integer number the user's typped will be returned. The parameter defaultValue should be an integer number to be shown as default value in the text field to the user. If you don't mind it, just put a 0 as defaultValue. This method is useful to ask the user questions that can be answered with an integer number, like his age, the number of sons he have, how many times he masturbated in the last week, etc. getSelectedValue(message, texts) This method will put message as the current shown text, and show the user various options for him to choose one. Depending on the number and 'size' of the options they can be shown as buttons or as a drop list if they don't fit the buttons. The parameter texts must be a list of Strings, where each String in the list is a possible option for the user to choose. This method will wait until the user selects an option, and when he does, the index of the option he selected in the list texts will be returned. getString(message, defaultValue) This method will set message as the current shown text and will also show the user a text field for him to input some data and a [Ok] button. The data the user is going to input will be some text. This method will wait until the user inputs the text and clicks on the [Ok] button. Then, a String containing the text the user's typped will be returned. The parameter defaultValue should be a String to be shown as default text in the text field to the user. If you don't want there to be any default text, just put "" (an empty String) as defaultValue. This method can be used to ask the user questions that will be answered with text, like his name, his job, his eye color, etc. getTime() This method will return the number of seconds that have elapsed since 01/01/1970 to the current moment. It can be used for timestamps, or to know how many seconds have elapsed from one point in your code to another, getting the timestamps in both points, and then subtracting the first timestamp from the last. getRandom(max) This method returns an integer value randomly chosen from the range 0..