XToys.app vs DG-Lab and other toys

This is the place where you can share your thoughts on selfbondage with like minded people.
Post Reply
KinkInSpace
*****
Posts: 2141
Joined: 24 Dec 2015, 16:11
Location: Netherlands

XToys.app vs DG-Lab and other toys

Post by KinkInSpace »

We've been made aware recently that XToys.app has full support for the DG-Lab now, as they released their api to the public. This opens new possibilities of customization, but it also comes with a little learning curve.

I've decided to repost my post from the DG-Lab experiences post because its buried down on page 12 or so and it deserves to be easily searchable.

So here's a short manual on how to use the XToys.app with scripts and patterns. I'm currently figuring out how to make scripts such that I can create scripts suitable for self-bondage.

Anyway, here's the manual:

Manual: how to get started with XToys.app and the DG-Lab Coyote
Okay, I figured out how to use the Basic Auto Increase script with the DG-Lab.

Here is a step-by-step instruction on how to do it. I use the android app so I can type in my browser while seeing the screen, but the steps are about the same on the website and it does sync. (though patterns don't seem to sync, but that's okay)

First, hit the ⁝ in the upper right and select clear layout. We're going to start from scratch.

Now hit the + on the top-right and press Coyote to add your dg-lab and select Add to session.

Hit the ≡ and go to Public Scripts (or local scripts if you have that one already there)

Under Generic Output, seach for Ramp up until you say "Stop" or Basic Auto Increase (both by mumble) After you click on it, select Save to My Scripts if you haven't done that before. The popup goes away after that. Click it again and now choose Add To Session. You can see that the script requires a generic output and a Speech Recognition. Since the DG-Lab already is the generic output, we still need to also add the Speech Recognition module. We'll do that in a minute.

Hit the ≡ again and select Dashboard mode. On Android, the script has now been added and you can swipe left/right to scroll your dashboard.

Hit the + in the top-right and go to Tools, and scroll down to Speech Recognition, and click it to add it to your session.

On the top left of each block, there's a ‖ separator block. You can drag that and place the script under your main controller if you wish. (not necessary, but on a phone that looks great). To do so, first scroll such that you see half of both, then drag it under, scroll more, and place it entirely under.

At the top of the scripts, you'll find the icon of a plug, next to the play button. Press it and you can then select which output(s) the script will control. You have to select the DG-Lab channels you want the script to control, and below also click on Speech Recognition in order to use that too. The script will work without, except that you can't say "stop" then and restart the script.

Once done, the script may display you the settings it has. Set it up.

Now on the DG-Lab controller, press the box that says On to select your pattern that you wish to use. The My Patterns tab will have your saved patterns, the public patterns tab will have all public available ones. The 01 She is my sin gets my personal recommendation here, so select that one.

Now that everything is linked up, we still need to activate our components.

On the Speech Recognition module, press its text balloon icon button so it turns green. You should get a permission dialog requesting access to your microphone. If you use Google Chrome, it should use your default microphone on your windows pc. On Android it will use your phone's mic.

On the top left of the DG-Lab block, press the bluetooth icon to connect to your DG-Lab and ensure that the eyes of your estim unit go from green (or whichever pattern you selected there before) to white, indicating that it is paired using bluetooth.

You can now move the slider from the DG-Lab block up on the desired channel(s) to increase its intensity until you reached a starting position.

Once ready, press the green play button on the script and it will start controlling the DG-Lab block.

But lets not do that just yet. Lets put the intensity slider back to 0.

Now comes the most important part.

Hit the ⁝ again and choose Save Layout. Give it a name that you want to use. For example "auto increase stop", optionally add a description, and hit save.

If you now go to ≡, Manage your data, Layouts, you will find your layout there.

It does not actually save the location of each block, so you have to manually move them back into position each time you load it up. It will also not presave the pattern, so you have to choose that one each time too.

It will however link the DG-Lab to the script, so once you load the layout, all you have to do is reorder, select pattern, set intensity then hit play.

oh, note of warning, before going full into a session with scripts, TEST everything out properly. You can test the script out without even connecting to the DG-Lab and be sure that everything works and how it functions when performing actions. For example, if you hit the play button, it will automatically increase the current intensity by 1 from the start even though the seconds before increase is set to 5. Then again, changing that value is how much delay is between the increments. So you may read one thing, but it may mean something else. You can also see if saying Stop works.
Last edited by KinkInSpace on 27 Jun 2021, 14:23, edited 1 time in total.
Formally known as Slave_L.
I'm not yet very comfortable expressing my love for kink from my private life. I will therefor hide behind my username KinkInSpace and not allow any connections to who I really am. I'm sure you'll understand.
User avatar
kinbaku
*****
Posts: 5047
Joined: 10 Jan 2020, 20:26
Location: Belgium

Re: XToys.app vs DG-Lab and other toys

Post by kinbaku »

Thank you for the description, KinkInSpace. I've found also: https://xtoys.app/guides/basics-scripts and lot of information on https://milovana.com/forum/search.php?keywords=xtoys.
Unfortunately I can't install the Android app xtoys.apk on my android mobile phone. He give me an error.
I can access it via my browser on the mobile phone and yesterday I did a few more tests with scripts already made from the public domain. Voice control still didn't work for me. So still a lot to try.
Jonnydom16
*
Posts: 38
Joined: 21 Feb 2020, 04:24

Re: XToys.app vs DG-Lab and other toys

Post by Jonnydom16 »

Thank you for making a separate post, probably what i shouldve done when I discovered the xtoys app lol! And thank you for tinkering with the app to bring us scripts ! I am very excited to see what you come up with!
KinkInSpace
*****
Posts: 2141
Joined: 24 Dec 2015, 16:11
Location: Netherlands

Re: XToys.app vs DG-Lab and other toys

Post by KinkInSpace »

I've played some more with it and now got Speech Recognition to work. I had to perform a few steps, so I've edited the first post to include those.

But to summarize, from the dashboard, you have to press the + button, go to the Tools menu and add a Speech Recognition module first. Once the module is added to your dashboard, you go back to the script where it now says D (next to the play button) to select what you want to connect, activate Speech Recognition, and after that, on the Speech Recognition module itself, you must press the button to actually activate the mode. It will then ask for permission to use the microphone. This should work in Google Chrome just fine.
Formally known as Slave_L.
I'm not yet very comfortable expressing my love for kink from my private life. I will therefor hide behind my username KinkInSpace and not allow any connections to who I really am. I'm sure you'll understand.
User avatar
kinbaku
*****
Posts: 5047
Joined: 10 Jan 2020, 20:26
Location: Belgium

Re: XToys.app vs DG-Lab and other toys

Post by kinbaku »

Short explanation xtoys.app (without figures) from https://xtoys.app/guides/compatibility
For the full explanation go to their website mentioned above.


GETTING STARTED
Definitions
Block: A single control part that can be added to your Controls screen to interact with your toys. Toys, Devices, and Scripts are all types of Blocks. Blocks contain the button for connecting to the Toy/Device as well as controls.
Toy: A sex toy that XToys can connect to.
Tool: Something other than a sex toy that XToys can connect to.
Script: A Script connects one or more Blocks and interacts with them in some pre-configured way.
Pattern: A Pattern modulates the intensity of a Toy in some pre-configured way.
Layout: A Layout is a collection of Blocks that can be saved and loaded later.
Session: A Session allows for online controls of your Toys.

Basics - Connecting your First Toy
On the Controls screen click the + button in the top right to pull up a list of sex toys.
1. Select the toy that you want to connect.
2. A Block will be added with the controls for your toy.
3. Click on the name of your toy to pull up a menu to edit or delete the toy.
4. Click on the top left of the Toy Block to drag it around the screen. Click on the bottom right of the Toy Block to resize the Block.
5. Click on the large connect button at the top of the Toy Block to initiate a connection to your toy and follow any prompts to connect.
6. Once connected control your toy using the available controls.
Next you can try sharing control of your toy with others by clicking the Globe in the top right, or you can go back into the + menu and add some other Devices and Scripts and connect them to your toy.

Basics - Adding Scripts and Patterns

After creating an account your Scripts and Patterns will be empty. Open the sidebar and navigate to Browse Public Data to find some Scripts and Patterns to add to your account for your use.
Note: If you are not signed in then some sample Scripts and Patterns are automatically loaded and you won't be able to add new ones.
1. Navigate to Browse Public Data > Scripts.
2. Use the filters to narrow down to scripts you'd be interested in. For example scripts that use a Gamepad and connect to the toy you own.
3. Select the desired Script and click Save to My Scripts.
4. The Script will now be available in the + menu when adding a new Block.

Basics - Running your First Script

1. In the + menu under Scripts click your desired script to add the Block to your Layout.
2. Click the plug button in the top right of the Script Block to connect it to the other Blocks.
3. Click the Block you want connected to each part of the script. If there are no compatible Blocks found then go back into the + menu and add those Blocks.
4. Start the Script by clicking the green play button in the top right of the Script Block.

TOOLS OVERVIEW

Beacons
USAGE
Beacons allow you to have your toys react based on how close your phone is to a Bluetooth Beacon. The Beacon can be any iBeacon, Eddystone, or AltBeacon. For standalone beacons we recommend the Blue Charm line of beacons. You can also use another phone running XToys as a Beacon.
1. Add your desired toy, a Beacon Detector tool, and a Script that uses the Beacon Detector. Connect the Script to the toy and Beacon Detector.
2. If you are using a phone as a Beacon, then on a separate phone add just a Beacon tool and click the Bluetooth icon to start it (icon will turn green). If you are using a physical Beacon then make sure it's on and that you know its broadcast information.
3. Back on your original device under the Script block make sure the UUID and Major matches your Beacon info.
When using XToys as a Beacon the info is...
UUID: b4ff13c0-3017-4164-a2ee-7da1ecb109d6
Major: 1
4. Start the Beacon Detector and the script. You should now see the toy intensity change based on your proximity to the Beacon.

Additional Notes
• Both the Beacons and Beacon Detector only work in the Android app currently
• Different Beacons are going to have different levels of accuracy so you'll likely need to edit the Script and adjust the distance ranges to suite your needs
• Bluetooth range detection is not super accurate and the distance can sometimes jump to incorrect values
• The XToys iOS app doesn't support Beacons yet but you can instead use any other iOS app that acts as a Beacon
Script Developer Notes
• You'll probably want to expose at least the ID 1 and ID 2 values to the end user so they can edit it easily to match their Beacon
• ID 1, 2, and 3 correspond to the first, second, and third identifier of the given Beacon standard as defined by the AltBeacon library

Webhooks

USAGE
Webhooks allow you to have your toys react to events that happen from an external application or from a web service like IFTTT.
To use Webhooks you need to set up a Webhook ID, create a script that uses Webhooks, and then call that Webhook URL from your external service.
1. Add your desired toy, the Process Monitor tool, and a Script that uses Process Monitor.
2. Add your desired toy, the Process Monitor tool, and a Script that uses Process Monitor.
3. Make a GET request from your external service to the url https://xtoys.app/webhook?id={webhookID}&{whatever data the script expects}.
4.
For example, the Webhook Sample script expects an action of either 'set-intensity' or 'temporary-on', an intensity of a number from 0-100, and the 'temporary-on' action also expects a number of seconds.

So valid GET requests would be like:
https://xtoys.app/webhook?id=HNV9lZLsOr ... tensity=50
https://xtoys.app/webhook?id=HNV9lZLsOr ... ensity=100

Remember to replace HNV9lZLsOrop with your Webhook ID
Additional Notes
• Data sent via a webhook is temporarily cached on XToys servers
• It is not possible to read data from a webhook
Script Developer Notes
• All arguments should be passed as GET parameters. POST is not supported
• All Webhooks expect at least 1 argument of an 'action' and the value of the action is used to determine which Trigger to fire
• Any additional values passed to the webhook will be passed to connected actions under {trigger-keyname} variables. For example in the above script actions would be able to use {trigger-intensity} and {trigger-seconds} variables
• The Webhook GET call does not respond with any data that would inform you whether any Script has actually reacted to the Webhook
XToys Discord Bot
OVERVIEW
The XToys Discord Bot allows you to have your toys react to messages and reactions that happen in a Discord channel.
The Discord bot has 4 ways of reacting to Discord events:
• Listen for Keyword - Trigger anytime someone says a certain keyword anywhere in their message
• Listen for Reaction (My Posts) - Trigger anytime someone reacts with a specific reaction on any of your messages
• Listen for Reaction (Bot Post) - Trigger anytime someone reactions with a specific reaction to the XToys Bot post that gets created when you connect to the bot
• Listen for Command - Trigger anytime someone starts a message with a specific keyword. The command can include additional arguments to customize the trigger action.
Adding the Bot to a Guild
1. Click here to add the Discord Bot to your Guild.
2. In Discord send the message .xtoys register in your Guild. It will respond with your Guild ID.
3. Go to your XToys Profile and enter your Guild ID under the Discord section. Click Save. If you do not have a Premium XToys Membership this area will instead have steps on how to sign up for a Premium membership via Patreon or Paypal.

USAGE
1. Add your desired toy, the Discord Bot tool, and a Script that uses the Discord Bot. Connect the Script to the toy and Discord Bot.
2. Click the Discord Bot connect button. It will display a command to send in Discord. Enter the command in the Discord channel. The bot will respond saying it's connected.
3. Start the script. The bot's message will update to show what commands are active as a result of the script.
4. Do the action in the Discord channel and your toy should react as scripted.
Additional Notes
• The Discord bot has some additional commands that a Guild owner can run to configure it:
◦ .xtoys settings keywordreactions {on/off} - Toggle whether the bot should react with a purple heart when it detects a keyword to react to
◦ .xtoys settings commandreactions {on/off} - Toggle whether the bot should react with a purple heart when it detects a command to react to
◦ .xtoys settings botpostreactions {on/off} - Toggle whether the bot should put initial reactions for each reaction that it will react to on its bot post
◦ .xtoys settings userlimit {number} - Set the maximum number of users that can be connected to the bot from a single channel (default is 25)
In addition .xtoys help will display info on how to use XToys and connect to the bot for new users.
• If people are tagged in a message than the XToys Bot will only react to those people
• The bot will only work in channels marked NSFW
• Remove View Channel permission for the bot in any channels you don't want it active in
• The bot will only update a post at most every 5s
• If the bot is under heavy usage in a channel its updates may be delayed
Script Developer Notes
• To use the bot you must both send an Action to the bot and also set up a Trigger with the exact same keyword/command/reaction
• Any matched groups in an XToys Bot command will be passed to connected actions. Ex. If the command is vibrate {intensity} and someone uses the command vibrate 50 then the variable {trigger-intensity} will contain the number 50

XToys Process Monitor
USAGE
The XToys Process Monitor allows you to have your toys react to events that happen within Windows games or other Windows apps.
1. Add your desired toy, a Process Monitor tool, and a Script that uses the Process Monitor. Connect the Script to the toy and Process Monitor.
2. Click the Process Monitor connect button and follow the directions to install both the Chrome extension and the Process Monitor software.
3. Start the game the script was designed for and ensure the game shows up as being connected in the Process Monitor block. Your actions in the game should now trigger your toys.

Additional Notes
• Process Monitor may be blocked or deleted by your Antivirus. Whitelist the Process Monitor installer and files to allow Process Monitor to function
• Instead of using the Process Monitor installer you can instead download the source Python files and use them instead. Instructions and files are on Github
• The game exe must exactly match the game name listed in the script
• Process Monitor scripts are in many cases version specific and will only work with a certain version of the game
• Process Monitor is for Windows games only
• Process Monitor may trigger anti-cheat detection in games. We don't recommend running Process Monitor on online games or games that use Valve Anti-Cheat detection
Script Developer Notes
• For info on how to create a new Process Monitor script refer to the Creating a Script - Process Monitor tutorial
• Actions must be configured to tell Process Monitor to monitor each memory address, and then a Trigger can be created to react to changes from that address
• Identifiers are evaluated in the order the Actions are defined, so if an identifier starts from the address of a different identifier ensure that previous identifier is defined first
• Array of Bytes uses a . to identify any bytes (instead of question marks like in Cheat Engine)
• Refer to Cheat Engine tutorials to get an overview of how to find memory addresses for games
• Array of Bytes, Offset, and Pointers array are all optional for any given identifier. If multiple are given they are evaluated in the listed order.
• Memory addresses may already have been found for the game you want to use with XToys. Check LiveSplit AutoSplitters, or search online for a 'Cheat Table' for your game

XToys Webpage Monitor
USAGE
The XToys Webpage Monitor allows you to have your toys react to events that happen on a different tab or send text automatically to a chat on that tab.
1. Add your desired toy, a Webpage Monitor tool, and a Script that uses the Webpage Monitor. Connect the Script to the toy and Webpage Monitor.
2. Click the Webpage Monitor connect button and follow the directions to install the Chrome extension.
3. Click the Webpage Monitor connect button again and confirm the icon now turns green.
4. Open a tab for the relevant website and click the XToys extension icon in the toolbar. Ensure it lights up and on the XToys webpage ensure that the website is now shown as a connected site.
5. Peform the action on the website that the Script is configured to watch for and your toy should react as scripted.
Additional Notes
• The extension needs to be reconnected to the webpage any time it loads a new page. If the page changes as part of the event you're trying to monitor then it won't be possible to monitor that event
Script Developer Notes
• When the extension is connected to the webpage jQuery is embedded in the webpage and can be called from the Chrome Developer console by changing the context in the console (the dropdown labelled 'top') to the XToys Webpage Monitor context. This can be used to test your jQuery expressions
• Any matched groups in the regex expression will be passed to connected actions under the {trigger-1}, {trigger-2}, etc variables

SCRIPTING
Creating a Script - Section Overview
All scripts are divided into a number of distinct sections as outlined below.
Blocks Interacted With
The other toys or devices you want the script to interact with. Define these first when starting a new script.
Controls
Controls you want to expose for quickly making config changes within the script. Each control directly modified a variable. There’s no need to define these until your script is working otherwise.
Initial Actions
Things to trigger immediately when the script starts.
You probably want to set up at least an action that starts your main Job here.
Global Triggers
Things to always watch for and react to regardless of which Jobs are running in the script.
Jobs
Generally the main area where things will be happening in the script.
Scripts can have any number of Jobs and any number running at the same time. Jobs have to be started from an Action.
Each Job has only one Step active at a time. When a Step starts the Actions defined in it trigger once. Any Triggers defined in a Step will trigger once they’re true as long as that Step is still the active Step.
Of note:
• The start Action for a Job won’t do anything if the Job is already started.
• An Action can Go To the same Step that a Job is already on and it will re-run the Steps Actions.
Queues
Queues are a way of scheduling Jobs to run one after another. Their main purpose is for handling scripts that react to events from multiple users (ex. reacting to tip donations from performers) but where you don’t want to interrupt reacting to the previous event.
Of note:
• They can’t start other Jobs. The only Job related action they can (and must do) is call Stop on their own Job at some point so the queue can go to the next Job.
• Variables scoped only to that specific instance of the Job can be passed in when the Job is queued. So you can have a Job that is generalized (ex. turn on toy for {queue-seconds}), and add the same Job multiple times to the queue with a different value for {queue-seconds} for each.
Triggers
Triggers can trigger multiple times but will not trigger continually. The Trigger has to switch to false before it’ll Trigger again (except for a few Triggers that have a Repeat option like Game Controllers).
Variables
Scripts can set and use variables.
Variables are defined using the Variables Action.
Triggers can fire when a Variable has a certain value.
Variables can be used within any text field instead of defining a preset value. To do so use curly braces around the variable name. {myvar}
Actions
Actions can either set something to a specific value, or modify the existing value by some amount. They can also use a value from a variable, generate a random value, or calculate a new value using a math equation.
Examples of possible action values:
50
+10
{myvar}
{myvar}/2
(0|0|0|5|10|20)
(1-5)

Creating a Script - Behaviour Notes
Controls
• Controls set and reflect the state of a variable in the script
• For debugging purposes you can have a text input control for a variable in the script to monitor it
Initial Actions
• Start actions are called immediately when the script is started. Stop actions are called immediately when the script is stopped.
• You likely want to define a start action that calls your Job
Global Triggers
• Global triggers are checked continually as long as the script is active, regardless of what else is going on in the script
• Global triggers can not be stopped. If you need the ability to toggle whether these triggers fire you may want to define them in a new job instead
Jobs
• Jobs are not started automatically. You must call an action to start the job.
• The 'Go to Step' job action does nothing unless the Job is already started
• When a job is started it always starts with the 'START' step
Steps
• When a step is started is always calls all associated actions and then waits and listens for all associated triggers
• The order the steps are displayed in the Job do not have any meaning (they just sort alphabetically)
• To change steps have a trigger from the current step call an action to change steps for the given job
Queues
• Jobs started from a queue cannot start other jobs. The only job related action they can (and must) perform is to stop their own Job (at which point the next Job in the Queue will start
• To delay between Queued Jobs have the Job go to a Step that just waits for a bit, or create a separate Job that just waits for a bit
Triggers
• Triggers call all connected actions in the order that they are listed
• Triggers are checked continually as long as the step is the active step for the job and the job is active (or it's a global trigger)
• Triggers will not fire a second time until the trigger expression becomes false first. The only exception are 'Any' value triggers which fire any time the value is different then it was before.
Variables
• All variables are global to the entire script except for {queue-} variables which are only accessible to a given Job in a Queue, and {trigger-} variables which are only available to actions connected to a given trigger
• To store {trigger-} variables for use elsewhere in the script store them to global variables. ex. {myvar} = {trigger-1}
• Variables are not shared across multiple scripts, or with any patterns

Creating a Script - Tutorial
Let's try creating a basic script to learn the ins and outs of XToys scripts.
Goal
Create a script that reacts to custom voice commands. For this script we'll create a virtual assistant that will listen to our commands and speak back that they're doing the task we requested.
Commands:
• "stop" - Stop the toy immediately
• "set speed to (slow|medium|fast)" - Set the toy to a certain speed
• "tease them for x seconds" - Slowly ramp up and then ramp down over the requested number of seconds.
Steps
1. On the General tab under the Blocks Interacted With area click Add Block and add three Blocks:
◦ Speech Recognition - The block we'll use for listening to commands we say
◦ Text to Speech - The block we'll use for having the bot talk back to us
◦ Generic Output - A basic block that can output a command to any sex toy

2. On the Jobs tab click the Jobs button, + New Job, name the job Tease, and click Update. We'll use this job for when the tease command is kicked off.
3. On the Global Triggers tab click Add Global Trigger. Select Block, Speech Recognition, and enter the first command stop. Repeat for each of the other two commands. Skip punctuation as the speech recognition doesn't use it.

For the tease command use the phrase [a-z]* for ([0-9]*) seconds. [a-z]* is a regex matching any word ([0-9]*) is a regex matching any number. You don't need to know or understand what a regex is, just know that it matches any single word or number respectively. And by wrapping it in () brackets it will allow the portion in the brackets to populate the {trigger-1} variable and for us to use the value in our Actions that we'll soon set up. The speech recognition being used by XToys filters out nsfw words and thus instead of listening for the word tease we're just going to trigger on any word that fits the pattern of "word for x seconds".
4. Click the + button beside the "stop" trigger to add an Action that will trigger when the command is said. Select Block, Generic Output, Intensity, and enter 0 for the intensity. Click Add. Now whenever you say "stop" the connected toys will turn off.
5. Click the + button beside the "speed to" trigger to add an Action that will trigger when that command is said. Select Block, Generic Output, Intensity, and enter {trigger-1} == 'slow' ? 33 : {trigger-1} == 'medium' ? 66 : 100 for the intensity. Click Add.

Again we're getting in to some programming lingo. Basically if the command contained the word "slow" then we'll set the intensity to 33%, if it was "medium" we'll set it to 66% and otherwise (ie. "fast" was said) we'll set it to 100%.
6. Click the + button beside the "for x seconds" trigger to add an Action that will trigger when that command is said. We want to keep track of how many seconds you said so we'll grab that value from {trigger-1} and store it in a different {seconds} variable (since trigger- variables only exist during the Actions connected to the Trigger).

Select Variable, enter seconds for the variable name, and {trigger-1} for the value. Click Add.
Click the + button again and select Job, Tease, Start. Click Add.

Since we want this Trigger to do multiple things we're going to have it start a Job that will perform the desired actions (increase toy speed and then decrease it).
7. Under the Jobs tab click + Action in the START row. The START step is the step that becomes active when a Job is started. We want to increase the speed over the span of half the requested number of seconds. So for example if we said "tease for 10 seconds" it should ramp up to 100% over 5 seconds, and then decrease over 5 seconds. And would thus need to increase by 20% per second. In other words it needs to increase by 100/seconds/2 every second. Hurray math!

Select Block, Generic Output, Intensity, and enter 100/{seconds}/2.
8. After 1 second has passed we want to re-run that Action. We can do so by having the Job re-run the START step. Click + Trigger, select Step, and enter 1 for the Time Elapsed. Click Add. Click the + beside the 1s Trigger we just created and select Job, Tease, Go to Step, and enter START. Click Add.

The actions in the START step will now re-run every second.
9. Once the toy has reached 100% intensity we want to stop repeating the START step and switch to a new step that will lower the intensity every second until we're back to 0.

Click the Add Step button, name the new step Ramp Down and click Add.

We want to go to this step when the toy hits 100% intensity so click + Trigger on the START step, Block, Generic Output, Intensity, In Rage, and enter 100 for the min and max.
Add an Action to this Trigger to go to the Ramp Down step.
10. Instead of having the decrease Action run immediately we'll instead put it behind the 1s time elapsed Trigger. This will allow us to see that we can have multiple Actions run from a Trigger, and also it will allow the intensity to sit at 100% for 1s instead of immediately dropping.

Click + Trigger on the RampDown Step. Create a 1s Time Elapsed Trigger just like before.

Click the + button beside the 1s Trigger and create a Intensity change Action that is the same as before but we're now subtracting instead {value}-100/{seconds}*2. Also create an Action to repeat the RampDown job just like before.
11. Create a new Trigger for when the intensity is back at 0%. When it is we want to stop this Tease Job (New Action, Job, Tease, Stop).
12. Everything should work now for the 3 commands and you can test it to confirm. Before we're finished there's a couple other improvements we should make.
First we're not actually using the Text to Speech Block yet. So let's add speech actions to each of the Triggers, as well as after the Tease Job is complete.
13. And lastly we should make the stop and (slow|medium|fast) Triggers stop the Tease job if it's already running since the Tease Job attempting to adjust the toy intensity will conflict with us trying to set it to a steady intensity
14. We're finally done. Save the Script and test it.

Creating a Script - Process Monitor
Process Monitor monitors memory addresses in games so XToys can react to them. To find these memory addresses you'll need to understand some assembly and how to find these addresses.
Cheat Engine is a very useful software title for finding memory addresses so familiarize yourself with Cheat Engine first and follow their tutorials.
Goal
For this script we'll connect to the Link to the Past rom running in Snes9x and have our script vibrate the toy any time we lose health.
Needed
• Snes9x v1.60 (x64)
• Link to the Past rom
• Cheat Engine software
Steps
1. In XToys add the Process Monitor connector to a new script. Put in the emulator exe name.
2. Add an Initial Action that creates an Identifier for the base address for your emulator that points to the start of the SNES game memory. Finding this address is outside of the scope of this guide, but valid values for a variety of emulators and versions can be found in various locations like on Github.

We're using Snes9x 1.60 (x64) so create an Identifier for the static address 0x1408D8BE8 and call it 'GameBase'.

You would not need this value if using Process Monitor with a Windows game.
3. Open Snes9x and start Zelda, open Cheat Engine, connect Cheat Engine to the Snes9x process.
4. Click Add Address Manually, enter 0x1408D8BE8 for the address and click the Hexidecimal checkbox. Note down the result for use later (0x0229AFD0 in my case). This is the starting address for the Zelda game data and will change each time you restart Snes9x. But since we're always having XToys start from 0x1408D8BE8 it will always point to the correct memory location.
5. Start a New Scan. We don't know how Zelda is storing health data.

It might be 3 when you have 3 hearts. And it might be an Int type. So you could try that...but it'd be wrong and I don't feel like writing up those wrong attempts so I'll just tell you health is stored in a single Byte.

So we'll set the Value Type to Byte, and Scan Type to Unknown Initial Value. Click First Scan.
6. Go get hit by an enemy and then set the Scan Type to Decreased value and click Next Scan.
7. Keep doing that until you only have 1 value in the list of addresses left. If you die you can change Scan Type to Increased Value and then back to Decreased Value.
8. We did it! Looks like your health is actually stored as the number of displayed half hearts * 4. When at 3 hearts your health is 24.
9. The address is my case is 0x022AA33D. Do some quick math to find the difference between this value and the start value you wrote down in step 4. 0x022AA33D - 0x0229AFD0 = 0xF36D. Cool, so your health value is always stored 0xF36D away from the address pointed to by 'GameBase'.
10. Back in XToys create a new Initial Action that create a Health Identifier. It's a single byte, starts at the result from the GameBase Identifier, and has an F36D pointer.
11. Save the Script and run it. You should see your health displayed in XToys. Get hit and confirm it updates correctly.
12. And now you can use that value in a Trigger however you want. Turn on a vibrator/estim depending on how much health you have, or whenever you health goes down, or whatever other ideas you have.

For example you can store the health value and then start a Job that checks if the new health is less than what it was previously. If it was start a Job to turn on the vibrator for a bit. And then update the current health.

Available Functions and System Variables
Most areas in an XToys script that accepts text input can also have a dynamic value be calculated using mathjs and other XToys specific custom functions.
Random Number in Range (x-y)
(0-10)
(1-5)
Random Number from List (x|y|z)
(1|7)
(1|1|1|5|5|10)
Relative Change +|-|*|/x
+5
-3
Variable {varname}
{myvar}
Relative Change +|-|*|/x
+5
-20
Expression
100-{trigger}
{myvar}/2
An expression can be anything that can be evaluated using Math.js syntax and XToys variables.
Additional Custom Functions
Note that these functions will not work in 'Set Text' actions. If you need to display the text result of these functions save the result into a variable first.
Note that when passing variables you still must use {} around the variable. So for example calling getHours() with a timestamp variable you've named time you would enter getHours({time}).
gps_position(lat1,lng1,lat2,lng2) - Returns the distance in meters between the two given GPS coordinates. Lat/lng values should be in decimal degrees and without N/E/S/W designators.
getSeconds(timestamp) - Returns the number of seconds (0-59) according to local time
getMinutes(timestamp) - Returns the number of minutes (0-59) according to local time
getHours(timestamp) - Returns the number of hours (0-23) according to local time
System Variables
These system variables are automatically populated in all scripts:
{timestamp} - Contains the current time as a timestamp (milliseconds since July 1, 1970)
{time-elapsed} - Milliseconds that have passed since the script was started
Additional Notes
• Negative values when setting a variable will cause the variable to decrement. If your goal is to actually set a variable to a given negative value you will need to use something like 0+{value}
• Inline if statements can be used as part of the Mathjs functionality {myvar} > 5 ? 1 : 0
User avatar
kinbaku
*****
Posts: 5047
Joined: 10 Jan 2020, 20:26
Location: Belgium

Re: XToys.app vs DG-Lab and other toys

Post by kinbaku »

See also on viewtopic.php?f=11&t=13602#p103219 for an imported warning for using XToys.app.
Post Reply