[Tease AI Java] Developer's Guide and Help Thread
Posted: Thu Sep 06, 2018 6:26 pm
Important Notes
I am ski23, creator of the Tease AI Java personality Mischevious and contributor to Tease AI Java itself. I am a senior in Computer Science at Virginia Tech, and I have real world programming job experience. Most likely any question you may have about Tease AI Java or personalities I will be able to answer.
Introduction
This is the general guide for developers for Tease AI Java. This guide is focused towards demonstrating how to create modules and personalities for Tease AI Java.
Resources
TAJUtils: TAJUtils are a series of utility files that I wrote that will allow developers to write modules and personalities quickly and easily. You can see my detailed post about TAJUtils and how to use everything provided in them here.
TAJ wiki: You can view the detailed TAJ wiki here. Some of this post repeats what is on the wiki. However, when that is the case, I tried to go into more detail or explain concepts from a different angle than the wiki.
Javascript guide: Here is a decent javascript guide. However there are plenty of others online.
Java guide: Here is a decent java guide. However there are plenty of others online.
The Developers: GodDragon and I are here to help with any questions related to TAJ and we will make sure to get an answer to your question. Don't be afraid to post or pm us with a question.
Mischevious/TAJUtils Structure and Intro
Throughout this guide, I will be explaining how to implement most concepts using TAJUtils. The reason for this is that TAJ does not have a default way to do a personality without extra coding on the developer end. If you use TAJUtils, you will not have to do this coding and it will make your life easier. All of these concepts, however, could be implemented without TAJUtils with a bit of extra code.
Here, I will outline the general structure for Mischevious (The first personality available using TAJUtils). Note that not all personalities that use TAJUtils will need to use this exact structure. However, it is the structure that made sense to me when writing Mischevious.
First, the Responses, System, and Vocabularies folder need to be in every personality.
Next, in Mischevious, I put TAJUtils in the main directory. However, it may be beneficial for some to put them in a utils folder.
The next important thing to understand is the Structure folder. This folder is the core of the structure of the personality. Inside of Structure, there is an End, Link, Modules, Start folder, and a javascript file called MischeviousStructure. This javascript file is what defines the structure of the personality to be the same as the original Tease AI. You can make your own personalities with TAJUtils that do not have the same structure as Tease AI by modifying or creating your own version of this javascript file.
The next thing to note is the End, Link, and Start Folders. Any modules you create of these types need to go in these folders, and the disabled folder inside of these folders can be used to disable certain scripts.
The next folder is the Modules folder. Inside the Modules folder is a script called ModuleSelector and several folders for different categories of modules: Fetishes, Games, Learning, LongModules, MediumModules, and ShortModules. The ModuleSelector will choose one of these folders to select a random module from as long as the folder is not empty. You may be asking, "Why not just have all of the scripts in one folder and randomly select from there?" I originally laid it out this way. However, there would be issues of if there are 10 very short scripts and 1 long script, there would be an overwhelmingly high chance that the short scripts would get run, thus making the personality more repetitive and boring.
When you create a module, simply figure out which folder it should go in and place it inside. The module will now be active and ready to run. You can put all other modules in the disabled folder temporarily to ensure that only your new module will run for testing
Part 1: Creating a simple module with TAJUtils
Here I will show you how to create a simple module with TAJUtils. First, we are going to look at emulating the structure from the original Tease AI. This is useful because it allows us to be able to use personalities from Tease AI, and have a designated structure. For those unaware, the structure of Tease AI is as follows where the section in parenthesis will repeat:
Start->(StrokeCycle->Module->Link->)->End
To emulate this structure in TeaseAI Java, the developer needs to know 2 things:
This may look overwhelming to you, but stick with me, this will look simple to you soon.
Let's go line by line:
Here we call the method CMessage which is a method inside of TAJUtils. A method may also be known as a function. Basically it just does something. Methods always have the following structure: MethodName(parameter1, parameter2,...,parameterN); This method, CMessage, is sending a message from the domme to the sub. The first parameter is the text that she will send; the second is the delay after the message is sent to wait; the third is whether or not to show the domme typing the message. Text inside of the % symbol represents a vocabulary. This refers to a vocabulary file or predefined variable, and will randomly select one of the vocabularies within the vocabulary file. You can view what a vocabulary references by going to the Vocabularies folder in the personality. Vocabularies are useful because they help keep modules from feeling repetitive and boring because they will choose random words to say. The more vocabularies you use in your modules, the less repetitive it will seem. So, this first line will send a message from the domme to the sub that tells the sub to stop stroking. There will be no delay after this message because we want the next method to execute immediately after we send this message. Always make sure you use a delay of 0 when you send a message before a command like stopStroking, startStroking, startEdging, etc.
Let's look at the next line now:
This is what will stop the current stroking cycle and end the stroking metronome. This is pretty simple so let's move on:
Here is another example where the domme sends a message. Except here, no delay is specified so the default delay will be used. This is preferable most of the time you want to send a message.
This method will make the sub start edging. This won't continue to the next line until the sub tells the domme that the sub is on the edge.
This line is another example of the CMessage example. However, there is a bit more going on here. In this line, we are using all 3 available parameters to the CMessage Method. The first parameter is the same as we saw above. The second parameter is "null". Null basically means nothing so, we aren't providing a value for this parameter so it will use the default value. For the 3rd parameter, we set it to false because in this example we don't want the domme to show that she is typing because we want this message to display as fast as possible after the sub says they are on the edge.
Finally, we send the message that tells the sub to let the edge fade. It is advisable to pretty much always have a %stopstrokingedge% and a %lettheedgefade% message sent after the sub finishes an edge and isn't going to do an edge hold. Once your module is complete, simply put it in the modules folder. If you are adding a module to Mischevious, add the module to the folder that it corresponds to. For example this is a pretty short module so it would go into the short modules folder in Mischevious.
Congratulations! You've just learned how a simple module works. I recommend using what you've learned here to make some of your own modules and get some experience with what you've learned.
Part 2: Testing and Debugging in Tease AI Java
You've now created your first module for Tease AI Java. If you did everything perfectly, your module will run and everything will work exactly as you intended. However, we are all humans, and unfortunately no one writes perfect code on the first time every time. I'm going to teach you some basics on how to fix your code when it doesn't work how you want. The first thing you need to know is that every time Tease AI Java runs, it creates a log file in the Logs folder. You can go into this folder and look for the most recent log file and this will show you the logs for your most recent run. Let's create an error and see what happens. We are going to use our module from part 1 but make an error by misspelling CMessage:
Let's see what the logs show when we execute this:
You'll see there is a lot here, and it looks quite overwhelming. However, whenever you see an error message like this there are generally only 2 places you need to look. The first one is at the very beginning of the error message:
Here this tells us that CMessag is not defined at line number 1. This makes sense because CMessag doesn't mean anything. CMessage is what we meant to do. In the first of these 2 lines, you can see the file in which the error occurred. So between the first and second lines here, we can see that our error is at line number 1 in the file edge_2_85.js. In a more complicated error where it is not just a typo, knowing the file and line where the error occurs is very useful to be able to look at that line and figure out what the issue is. The second useful place you may want to look in the error message is here:
Look for the words "Caused by:" In our example, this basically tells us the same thing as the first 2 lines so this isn't particularly useful for us. However, in some cases this may be a useful area to search.
So, now you know some basics about how to track down your bugs and find them. While using log files to search for bugs is useful, often-times, code may get complicated across many files and another technique may prove useful. This technique is using debug messages in your code to be able to easily track and understand your bugs. Let me present an example module:
Here we are using an if statement. If you aren't aware of what these are, basically they just check some condition and go into the brackets if that condition is true. In this case it will only start edging if x is 2. For simplicity here, you can clearly see that x is set to 1 just higher above so we know that the code inside this if statement will not be executed. However, pretend that the value of x comes from a variable somewhere we cant see and we do not know its value but we think it should be 2. In this case, we run our program and see that we get the message %stopstrokingedge% and %lettheedgefade% but the program never tells the sub to edge. So, we suspect the if statement code is never getting executed so, we can use a debug message to further investigate (NOTE- to see debug messages in chat, the debug flag in personality settings must be set to true).
Here, we added a debug message (DMessage) right before our if statement that will show us the value of x. If we run this, we will see that the value of x is actually 1 before the if statement which explains why the if statement did not execute. We also added debug messages at the beginning and end of the module so if there is an error, it is easy to determine which module was the cause. This is a good practice and is required for a module to be added to Mischevious. You can view the style guidelines in Part 8.
Part 3: Creating a More Complicated Module
After parts 1 and 2, you should be able to create, debug, and run a very simple module. Now, I'm going to teach you some more advanced methods you can use in your modules to be able to achieve more complicated designs. Here is a module from Mischevious:
Lets go through this together. First we have this line:
This will send a message to the sub and store the sub's response in the answer variable. The use of inputs like this are very important to make the module feel more like a conversation and less like a guided tour.
Here we check if the sub's response is like yes, yea, yep. If so, we make the domme a bit happier. We also take advantage of CMessage's formatting feature to be able to make the word more in italics.
Here we have the else that corresponds to the if statement earlier for the sub's response. Then, we make the domme angrier if the sub replied with something other than yes. We then make the sub do an edge. Then, we take advantage of the randomInteger function that generates a random number between the first number inclusive and the second number inclusive. If the random number is 7 or lower, we let the sub stop edging and calm down. If the number is 8-10, we make the sub hold the edge for a while before letting the sub calm down. In plain English, this basically means that there is a 30% chance the domme will make the sub hold the edge. The use of randoms is incredibly useful because it allows you to make modules different every time they are run and make them feel less repetitive over time. You now know how to make a bit more complex modules. To see even more tools you can use, you can reference my TAJUtils guide for other possibilities. You can use these same principles to create Start and Link modules. Just keep in mind that Start and End modules always need to end with stroking and begin not stroking.
Part 4: Creating End Modules
End modules are very similar to the other types of modules with a few small differences. Let's look at an end module:
This looks like a lot of code but it isn't too complicated. The one thing that ALL end modules that use TAJUtils need is to call the calculateOrgasm method to determine if the sub will orgasm. If the method returns true, you also need to call calculateRuin to determine if the orgasm will be ruined. Then, you can just use an if statement to determine what will happen in each situation: orgasm, ruin, denial. If the personality uses daily tasks or something like that, this may need to go inside the End module as well.
Part 5: Creating Responses
Now you know everything you need to know to make many modules. However, to help make the experience more like a conversation and less like a guided tour, responses are invaluable. You've already learned about using user inputs to questions the domme asks. We will refer to these as inputs. Responses are very similar to inputs; However, responses can be triggered at any time the user types the keyword(s) that trigger the response. Let's look at the example response Test.js:
Two important things to note here is the name of the file and the name of the function in the file. The function name MUST be named the same as the name of the file with the first letter lowercase and "Response" added to the end. So in this case, the file name is "Test.js" so the function name is "testResponse". You can view more details about the naming in the TAJ wiki page. Let's start analysing this response:
Every response needs to begin with this method that tells TAJ what will trigger this response. In this case, we are looking for the phrase "this is a test" contained somewhere in the message the sub entered. You can also use:
to be able to use regular expressions for the triggers for the responses. Then, we have the function that gets called when the response is triggered.
Here, we utilize TAJUtil's feature to disable responses. Whenever getInput is called using TAJUtils, responses will be disabled and this response will not continue even if the keyword was in the sub's input. Next, we check for several different program states to figure out what to do in these different scenarios:
Here we check what state the sub is in and perform different actions accordingly. In another example, if the trigger word was "can I stop?", and the sub wasn't even doing anything, then the response needs to know that and maybe say "You aren't even supposed to be doing anything." ALWAYS be careful to make sure you have covered all the program states related to your response.
Part 6: Creating and using vocabulary
The use of vocabulary is one of the key features of TAJ that keeps modules feeling fresh and new no matter how many times they are run. Here, I'll show you how to use and create vocabularies in a variety of ways. First, let's look at how to use vocabularies:
To use a vocabulary in a module, simply put the name of the vocabulary inside of percent signs. TAJ will then pick the word(s) to use from that vocabulary. There are 3 different ways to create vocabularies. The first is by registering the vocabulary in code using the name of the vocab and the pool of vocab choices.
When the vocab is used, it will randomly select one of the choices from the pool. I find this to be least useful of the 3 methods. The next method is the most common and generally one of the most useful. In this method, you need to create a vocabulary .txt file inside of the Vocabularies folder of the personality. Then, each line in the file will be one choice in the pool and the name of the file will be the name of the vocabulary. Vocabularies can use vocabularies within them to create more unique vocabularies. The final method to create vocabularies is the one that allows the most developer freedom and possibilities. This method is the use of Runnable Vocabularies. Runnable vocabularies simply return the choice that will be used and allow vocabularies to choose options from a pool without necessarily being random. Runnable vocabularies also allow an action to happen when a vocab is used such as displaying an image, sound, video, or any other action. Here is an example Runnable Vocabulary:
It's important to note that the function must end with "Vocabulary" and start with the name of the vocabulary file with the first letter lower-case. This Runnable Vocabulary will simply choose a vocabulary from the list of choices to return and have a 10% chance to play a sound. Runnable Vocabularies must go in the Vocabularies folder of the personality just like normal vocabularies except the vocabulary will be a javascript (.js) file. You can more about vocabularies in GodDragon's TAJ wiki page.
Part 7: Advanced personality creation
You should now know everything you need to know to create a personality. However, here I will teach you a few advanced principles that can be useful in personalities.
Accessing Java through scripts:
Everything you've done so far is in javascript. Javascript is a very useful scripting language, and you can do lots with it. However, there are some parts where we need to use a different language. TAJ, itself, is written in java, and it utilizes a library called Nashorn to use javascript scripts. Because of this, the javascript scripts are able to access java methods and classes. For this part, it is reccomended that you know some java. You can access any java class by referencing its path in javascript using java.path.path. Let's look at an example from TAJUtils:
This will get a java file at the specified path if one exists. Then, we output the path of the file. Note that once you have a java object, you can call all of its methods just as you would in Java. Note that we use the java.io.File.separator for the separation in the file path. You need to use this for any file paths because this will ensure the file path works on all operating systems.
Using load and unload:
There isn't much to mention here beyond GodDragon's wiki page on this topic.
Auto Updating:
You can look at Mischevious or GodDragon's wiki post to see how to make your new personality automatically update with github
Using runnables for advanced scheduling:
Here is GodDragon's wiki page on this topic. Only use scheduling if you really know what you are doing.
Part 8: Style Guidelines
You now know everything you need to know to be able to create modules and even entire personalities. However, here I'm going to cover some style guidelines that you should adhere to to keep your personality or module(s) readable to other developers. In the case of Mischevious, I will not accept any modules as additions to Mischevious if they do not meet these standards. All naming needs to be meaningful and easy for a developer to understand that did not write the code. Here are the [https://google.github.io/styleguide/jsguide.html]guidelines for naming[/url].
You also must at least add a Debug message DMessage() (or another form of debug message if you don't use TAJUtils) at the beginning and end of any modules you create and use the format:
It is also advised you have some other debug messages inside your module especially if it is medium sized or long.
Conclusion
Congratulations on making it through this marathon of a guide (or skipping to the bottom if you're lazy). I hope you found it useful. Please post any and all questions regarding development for TAJ below.
- You DO NOT need to know how to code to be able to create simple modules. However, you will need to know some javascript to be able to make more complicated modules or a personality. There are plenty of great guides on javascript out there so, I won't be covering that here.
- If you don't know what Tease AI Java is, you can see the main thread for it here.
I am ski23, creator of the Tease AI Java personality Mischevious and contributor to Tease AI Java itself. I am a senior in Computer Science at Virginia Tech, and I have real world programming job experience. Most likely any question you may have about Tease AI Java or personalities I will be able to answer.
Introduction
This is the general guide for developers for Tease AI Java. This guide is focused towards demonstrating how to create modules and personalities for Tease AI Java.
Resources
TAJUtils: TAJUtils are a series of utility files that I wrote that will allow developers to write modules and personalities quickly and easily. You can see my detailed post about TAJUtils and how to use everything provided in them here.
TAJ wiki: You can view the detailed TAJ wiki here. Some of this post repeats what is on the wiki. However, when that is the case, I tried to go into more detail or explain concepts from a different angle than the wiki.
Javascript guide: Here is a decent javascript guide. However there are plenty of others online.
Java guide: Here is a decent java guide. However there are plenty of others online.
The Developers: GodDragon and I are here to help with any questions related to TAJ and we will make sure to get an answer to your question. Don't be afraid to post or pm us with a question.
Mischevious/TAJUtils Structure and Intro
Throughout this guide, I will be explaining how to implement most concepts using TAJUtils. The reason for this is that TAJ does not have a default way to do a personality without extra coding on the developer end. If you use TAJUtils, you will not have to do this coding and it will make your life easier. All of these concepts, however, could be implemented without TAJUtils with a bit of extra code.
Here, I will outline the general structure for Mischevious (The first personality available using TAJUtils). Note that not all personalities that use TAJUtils will need to use this exact structure. However, it is the structure that made sense to me when writing Mischevious.
First, the Responses, System, and Vocabularies folder need to be in every personality.
Next, in Mischevious, I put TAJUtils in the main directory. However, it may be beneficial for some to put them in a utils folder.
The next important thing to understand is the Structure folder. This folder is the core of the structure of the personality. Inside of Structure, there is an End, Link, Modules, Start folder, and a javascript file called MischeviousStructure. This javascript file is what defines the structure of the personality to be the same as the original Tease AI. You can make your own personalities with TAJUtils that do not have the same structure as Tease AI by modifying or creating your own version of this javascript file.
The next thing to note is the End, Link, and Start Folders. Any modules you create of these types need to go in these folders, and the disabled folder inside of these folders can be used to disable certain scripts.
The next folder is the Modules folder. Inside the Modules folder is a script called ModuleSelector and several folders for different categories of modules: Fetishes, Games, Learning, LongModules, MediumModules, and ShortModules. The ModuleSelector will choose one of these folders to select a random module from as long as the folder is not empty. You may be asking, "Why not just have all of the scripts in one folder and randomly select from there?" I originally laid it out this way. However, there would be issues of if there are 10 very short scripts and 1 long script, there would be an overwhelmingly high chance that the short scripts would get run, thus making the personality more repetitive and boring.
When you create a module, simply figure out which folder it should go in and place it inside. The module will now be active and ready to run. You can put all other modules in the disabled folder temporarily to ensure that only your new module will run for testing
Part 1: Creating a simple module with TAJUtils
Here I will show you how to create a simple module with TAJUtils. First, we are going to look at emulating the structure from the original Tease AI. This is useful because it allows us to be able to use personalities from Tease AI, and have a designated structure. For those unaware, the structure of Tease AI is as follows where the section in parenthesis will repeat:
Start->(StrokeCycle->Module->Link->)->End
To emulate this structure in TeaseAI Java, the developer needs to know 2 things:
- All Start and Link modules must end with a stroking method.
- When a module starts, the sub will still be stroking. At some point, in the module, the developer needs to either make the sub stop stroking or do an edge so that at the end of the module, the sub will not be stroking.
Code: Select all
CMessage("%stopstroking%", 0);
stopStroking();
CMessage("On second thought");
startEdging();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%");Let's go line by line:
Code: Select all
CMessage("%stopstroking%", 0);Let's look at the next line now:
Code: Select all
stopStroking();Code: Select all
CMessage("On second thought");Code: Select all
startEdging();Code: Select all
CMessage("%stopstrokingedge%", null, false);Code: Select all
CMessage("%lettheedgefade%");Congratulations! You've just learned how a simple module works. I recommend using what you've learned here to make some of your own modules and get some experience with what you've learned.
Part 2: Testing and Debugging in Tease AI Java
You've now created your first module for Tease AI Java. If you did everything perfectly, your module will run and everything will work exactly as you intended. However, we are all humans, and unfortunately no one writes perfect code on the first time every time. I'm going to teach you some basics on how to fix your code when it doesn't work how you want. The first thing you need to know is that every time Tease AI Java runs, it creates a log file in the Logs folder. You can go into this folder and look for the most recent log file and this will show you the logs for your most recent run. Let's create an error and see what happens. We are going to use our module from part 1 but make an error by misspelling CMessage:
Code: Select all
CMessag("%stopstroking%", 0);
stopStroking();
CMessage("On second thought");
startEdging();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%");Code: Select all
01:09:11 PM SEVERE: Latest loaded file was 'C:\Users\ski23\Desktop\githubta\Personalities\Mischevious\Structure\Modules\ShortModules\edge_2_85.js' and error was found in line 1
Error: ReferenceError: "CMessag" is not defined in <eval> at line number 1
javax.script.ScriptException: ReferenceError: "CMessag" is not defined in <eval> at line number 1
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(Unknown Source)
at java.scripting/javax.script.AbstractScriptEngine.eval(Unknown Source)
at me.goddragon.teaseai.api.scripts.ScriptHandler.runScript(ScriptHandler.java:142)
at me.goddragon.teaseai.api.scripts.ScriptHandler.evalScript(ScriptHandler.java:124)
at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$249$\^eval\_$cu1$restOf.:program(<eval>:39)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(Unknown Source)
at java.scripting/javax.script.AbstractScriptEngine.eval(Unknown Source)
at me.goddragon.teaseai.api.scripts.ScriptHandler.runScript(ScriptHandler.java:142)
at me.goddragon.teaseai.api.scripts.ScriptHandler.evalScript(ScriptHandler.java:124)
at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$158$\^eval\_/1765819540.:scopeCall(<eval>)
at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$158$\^eval\_/1765819540.:program(<eval>:8)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(Unknown Source)
at java.scripting/javax.script.AbstractScriptEngine.eval(Unknown Source)
at me.goddragon.teaseai.api.scripts.ScriptHandler.runScript(ScriptHandler.java:142)
at me.goddragon.teaseai.api.scripts.ScriptHandler.evalScript(ScriptHandler.java:124)
at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$40$\^eval\_/1119693123.:program(<eval>:10)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.api.scripting.NashornScriptEngine.eval(Unknown Source)
at java.scripting/javax.script.AbstractScriptEngine.eval(Unknown Source)
at me.goddragon.teaseai.api.scripts.ScriptHandler.runScript(ScriptHandler.java:142)
at me.goddragon.teaseai.api.scripts.ScriptHandler.startPersonality(ScriptHandler.java:103)
at me.goddragon.teaseai.api.session.Session$1.run(Session.java:58)
Caused by: <eval>:1 ReferenceError: "CMessag" is not defined
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.error(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ECMAErrors.referenceError(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.objects.Global.__noSuchProperty__(Unknown Source)
at jdk.scripting.nashorn.scripts/jdk.nashorn.internal.scripts.Script$Recompilation$251$\^eval\_/333258056.:program(<eval>:1)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptFunction.invoke(Unknown Source)
at jdk.scripting.nashorn/jdk.nashorn.internal.runtime.ScriptRuntime.apply(Unknown Source)
... 42 more
Code: Select all
'C:\Users\ski23\Desktop\githubta\Personalities\Mischevious\Structure\Modules\ShortModules\edge_2_85.js' and error was found in line 1
Error: ReferenceError: "CMessag" is not defined in <eval> at line number 1Code: Select all
Caused by: <eval>:1 ReferenceError: "CMessag" is not definedSo, now you know some basics about how to track down your bugs and find them. While using log files to search for bugs is useful, often-times, code may get complicated across many files and another technique may prove useful. This technique is using debug messages in your code to be able to easily track and understand your bugs. Let me present an example module:
Code: Select all
CMessage("%stopstroking%", 0);
let x = 1;
stopStroking();
CMessage("On second thought");
if (x == 2)
{
startEdging();
}
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%");Code: Select all
DMessage("Beginning of module (modulename)");
CMessage("%stopstroking%", 0);
let x = 1;
stopStroking();
CMessage("On second thought");
DMessage("Value of x = " + x);
if (x == 2)
{
startEdging();
}
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%");
DMessage("End of module (modulename)");Part 3: Creating a More Complicated Module
After parts 1 and 2, you should be able to create, debug, and run a very simple module. Now, I'm going to teach you some more advanced methods you can use in your modules to be able to achieve more complicated designs. Here is a module from Mischevious:
Code: Select all
answer = getInput("Are you aching a lot right now %subname%?", 0);
if (answer.isLike("yes", "yea", "yep"))
{
increaseAnger(-1);
CMessage("Mmmm");
CMessage("I want you to ache <i>more<>");
startEdging();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}
else
{
CMessage("No?");
CMessage("Well I can't have that %Grin%");
increaseAnger(4);
startEdging();
if (randomInteger(0, 10) <= 6)
{
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}
else
{
holdEdge();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}
}
CMessage("Don't worry %PetName%");
CMessage("There's plenty more ache where that came from %Grin%");
Code: Select all
answer = getInput("Are you aching a lot right now %subname%?", 0);Code: Select all
if (answer.isLike("yes", "yea", "yep"))
{
increaseAnger(-1);
CMessage("Mmmm");
CMessage("I want you to ache <i>more<>");
startEdging();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}Code: Select all
else
{
CMessage("No?");
CMessage("Well I can't have that %Grin%");
increaseAnger(4);
startEdging();
if (randomInteger(1, 10) <equalsign 7){
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}
else{
holdEdge();
CMessage("%stopstrokingedge%", null, false);
CMessage("%lettheedgefade%", 0);
}
}Part 4: Creating End Modules
End modules are very similar to the other types of modules with a few small differences. Let's look at an end module:
Code: Select all
CMessage("%TimeToFindIfYouGetToCum%");
let cumming = calculateOrgasm();
let ruining = false;
if (cumming)
{
ruining = calculateRuin();
}
if (ruining)
{
startEdging(220, "Bring yourself to the edge one more time");
let answer = getInput("%ruinyourorgasm%");
if (answer.isLike("ruined", "finished", "did")) {
CMessage("Good %Grin%");
}
else {
CMessage("Hehe just calm down now");
CMessage("I love building up all that pleasure just to snatch it away from you");
CMessage("Better luck next time");
}
}
else if (cumming)
{
startEdging(220, "Bring yourself to the edge one more time");
let answer = getInput("%cumforme%");
if (answer.isLike("came", "finished", "did")) {
CMessage("Good %Grin%");
}
else {
CMessage("You're welcome %PetName% %Grin%");
CMessage("Hehe just calm down now");
CMessage("I hope you enjoyed that orgasm %SubName%");
CMessage("Who knows how many you're actually going to get?");
}
}
else
{
startEdging(220, "Bring yourself to the edge one more time");
let answer = getInput("Put it back in your pants, you don't get to cum tonight");
CMessage("Too bad");
CMessage("Better luck next time %Grin%");
}
CMessage("Thanks for giving me such a good time tonight %PetName%");
CMessage("I can't wait to see you again %EmoteHappy%");
Part 5: Creating Responses
Now you know everything you need to know to make many modules. However, to help make the experience more like a conversation and less like a guided tour, responses are invaluable. You've already learned about using user inputs to questions the domme asks. We will refer to these as inputs. Responses are very similar to inputs; However, responses can be triggered at any time the user types the keyword(s) that trigger the response. Let's look at the example response Test.js:
Code: Select all
addResponseIndicator("this is a test");
function testResponse(message) {
if (getResponsesDisabled()) {
return false;
}
if (isEdging())
{
CMessge("edging test");
}
else if (isStroking())
{
CMessage("stroking test");
}
else
{
CMessage("test");
}
}
Code: Select all
addResponseIndicator("this is a test");Code: Select all
addResponseRegex("test([ ])");Code: Select all
if (getResponsesDisabled()) {
return false;
}Code: Select all
if (isEdging())
{
CMessge("edging test");
}
else if (isStroking())
{
CMessage("stroking test");
}
else
{
CMessage("test");
}
Part 6: Creating and using vocabulary
The use of vocabulary is one of the key features of TAJ that keeps modules feeling fresh and new no matter how many times they are run. Here, I'll show you how to use and create vocabularies in a variety of ways. First, let's look at how to use vocabularies:
Code: Select all
CMessage("Hello %subname%");Code: Select all
registerVocab("name", "bob", "bill", "joe");Code: Select all
function goodToKnowVocabulary() {
let answers = ["Good", "Very good", "Excellent", "Perfect", "Great", "Marvelous", "Wonderful", "Splendid"];
if(randomInteger(1, 10) == 1) playSound("Audio/Spicy/QuestionAndShortWords/Good/*.mp3");
return answers[randomInteger(0, answers.length - 1)];
}Part 7: Advanced personality creation
You should now know everything you need to know to create a personality. However, here I will teach you a few advanced principles that can be useful in personalities.
Accessing Java through scripts:
Everything you've done so far is in javascript. Javascript is a very useful scripting language, and you can do lots with it. However, there are some parts where we need to use a different language. TAJ, itself, is written in java, and it utilizes a library called Nashorn to use javascript scripts. Because of this, the javascript scripts are able to access java methods and classes. For this part, it is reccomended that you know some java. You can access any java class by referencing its path in javascript using java.path.path. Let's look at an example from TAJUtils:
Code: Select all
let separator = java.io.File.separator;
let path = "C:" + separator + "users" + separator + "username" + separator + "Desktop" + separator + "fileName"
let file = new java.io.File(path);
CMessage(file.getPath());Using load and unload:
There isn't much to mention here beyond GodDragon's wiki page on this topic.
Auto Updating:
You can look at Mischevious or GodDragon's wiki post to see how to make your new personality automatically update with github
Using runnables for advanced scheduling:
Here is GodDragon's wiki page on this topic. Only use scheduling if you really know what you are doing.
Part 8: Style Guidelines
You now know everything you need to know to be able to create modules and even entire personalities. However, here I'm going to cover some style guidelines that you should adhere to to keep your personality or module(s) readable to other developers. In the case of Mischevious, I will not accept any modules as additions to Mischevious if they do not meet these standards. All naming needs to be meaningful and easy for a developer to understand that did not write the code. Here are the [https://google.github.io/styleguide/jsguide.html]guidelines for naming[/url].
You also must at least add a Debug message DMessage() (or another form of debug message if you don't use TAJUtils) at the beginning and end of any modules you create and use the format:
Code: Select all
DMessage("(ModuleName): Beginning");
DMessage("(ModuleName): End");
Conclusion
Congratulations on making it through this marathon of a guide (or skipping to the bottom if you're lazy). I hope you found it useful. Please post any and all questions regarding development for TAJ below.