summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--images/toy/ancilla/domme.groovy12
-rw-r--r--index.md2
-rw-r--r--scripts/toy.groovy84
3 files changed, 97 insertions, 1 deletions
diff --git a/images/toy/ancilla/domme.groovy b/images/toy/ancilla/domme.groovy
index 71863fd..f32b10b 100644
--- a/images/toy/ancilla/domme.groovy
+++ b/images/toy/ancilla/domme.groovy
@@ -29,6 +29,18 @@
]
]
], [
+ theme: 'blowjob training',
+ require: 'toy.has("dildo")',
+ probability: 5,
+ phases: [
+ [
+ number: 'toy.randRange(1, 3)',
+ activities: [ 'preClamps', 'preCollar', 'preStrip' ]
+ ], [
+ activities: [ 'playSuck' ]
+ ]
+ ]
+ ], [
theme: 'punishment',
require: 'toy.prop.punishment > 40',
probability: 50,
diff --git a/index.md b/index.md
index f4b9d6f..711ffb2 100644
--- a/index.md
+++ b/index.md
@@ -42,7 +42,7 @@ I plucked these from reading back through the original [forum post](http://ss.de
* Toy currently allows the installation of extra image packs for those who aren't a fan of the beautiful Ancilla Tilia or just like a little variety. These do not affect the behaviour of your mistress, just her appearance. See notes below on image packs.
* There are plans to move all the configurable bits of the script into these packs. This will allow for the creation of custom experiences and longer term "toy trading", where your owner may trade you between different [installed] owners.
* What toys can I use?
- * Any you like... but mistress will instruct you to apply/remove any of the following if you have them marked as available: nipple clamps, collar, gag, wooden spoon (or similar), handcuffs, chastity device/cage. This list will likely increase over time.
+ * Any you like... but mistress will instruct you to apply/remove/use any of the following if you have them marked as available: nipple clamps, collar, gag, wooden spoon (or similar), handcuffs, chastity device/cage, dildo (ideally one which can be used hands-free). This list will likely increase over time.
### House rules
1. Remember this is a game! It's meant to be fun! Don't do anything stupid or dangerous!
diff --git a/scripts/toy.groovy b/scripts/toy.groovy
index 0d1f069..e8cb381 100644
--- a/scripts/toy.groovy
+++ b/scripts/toy.groovy
@@ -980,6 +980,89 @@ def playBondage = {
showButtonGT("Freed, mistress", "freed", 120, 1);
return waitTime;
};
+def playSuck = {
+ def playWait = { file, time ->
+ playBackgroundSound(file);
+ wait(time);
+ playBackgroundSound(null);
+ };
+ def suck = { file, n, delay ->
+ n.times {
+ playWait(file, delay);
+ };
+ };
+ def suckBeat = { beat, n ->
+ suck("toy/${beat}bpm.mp3", n, 2 * (60 / beat));
+ };
+ present([DRESSED], [
+ ["Time for you to amuse me, you little slut."],
+ ["Get your dildo and secure it somewhere nearby, about eye level when kneeling."]]);
+ wait(10);
+ showButtonGT("Done, mistress", "done", 60, 1);
+ present([DRESSED], [
+ ["The rules are simple:\n"],
+ ["On my first bell, you take the head in your mouth and start to pleasue it.\n"],
+ ["When you hear the beat, you suck the shaft, one beat in, one beat out again.\n"],
+ ["Lastly, on the crack of my whip, you take the whole thing in and suck from the base.\n"],
+ ["I know you'll enjoy it, don't be shy.\n"],
+ ["One more thing..."],
+ ["That cock doesn't doesn't leave your mouth until I say so, listen for second bell and then return to me."]]);
+ showButtonGT("Understood, mistress", "understood", 30, 1);
+ present([TEASE], [
+ ["Get ready"]]);
+ showButtonGT("Ready, mistress", "ready", 10, 1);
+ show(null);
+
+ final target = loadInteger("toy.deepthroat.goal") ?: 5;
+ def completed = loadInteger("toy.deepthroat.completed") ?: 0;
+ def session = 0;
+
+ wait(randRange(10, 20));
+ playWait("bell.wav", randRange(10, 40)); // Head
+ while (session < target) {
+ suckBeat(30, randRange(5, 15)); // Slow
+ suckBeat(90, randRange(10, 30)); // Quick
+ wait(0.5);
+ final deep = randRange(target / 4, target / 2);
+ suck("shortwhip.wav", deep, 2.5); // Deep
+ session += deep;
+ }
+ suckBeat(30, randRange(5, 15)); // Slow
+ wait(randRange(10, 20)); // Head
+ playBackgroundSound("bell.wav"); // End
+
+ showButtonGT("Back, mistress", "back", 15, 1);
+ if (getBoolean("Did you perform as ordered?", "Yes, mistress", "No, mistress")) {
+ present([DRESSED], [
+ ["Good boy"]]);
+ adjustPunish(-4 * target);
+ completed += 1;
+ if (completed >= 5) {
+ save("toy.deepthroat.goal", target + 1);
+ completed = 0;
+ }
+ }
+ else {
+ final missed = getInteger("How many deep sucks did you miss?", 1);
+ if (missed > 5) {
+ present([DRESSED], [
+ ["Very disappointing."]]);
+ }
+ else {
+ present([DRESSED], [
+ ["Mmm"],
+ ["More practice required."]]);
+ }
+ adjustPunish(10 * missed);
+ completed -= 1;
+ if (completed <= -5) {
+ save("toy.deepthroat.goal", target - 1);
+ completed = 0;
+ }
+ }
+ save("toy.deepthroat.completed", completed);
+ wait(10);
+};
def playClamps = {
if (!has(CLAMPS)) return;
if (!is(CLAMPED)) clamps();
@@ -1145,6 +1228,7 @@ def sessionPlay = {
'playClamps': playClamps,
'playNothing': playNothing,
'playBondage': playBondage,
+ 'playSuck': playSuck,
'postCum': postCum,
'postPermitCum': {
addEventIfMissing(CUM, getTime() + (DAY * 2) + getRandom(DAY * 2), PERMIT, CUM); // 2 - 4 days from now