summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/toy.groovy316
-rw-r--r--scripts/toy/play.groovy322
2 files changed, 326 insertions, 312 deletions
diff --git a/scripts/toy.groovy b/scripts/toy.groovy
index 4e030ae..5c3ab02 100644
--- a/scripts/toy.groovy
+++ b/scripts/toy.groovy
@@ -25,13 +25,10 @@ return new Object() {
// toy.permission.<name>
final CUM = "cum", EDGE = "edge"
final PERMIT = "permit";
- final PLAY = "play";
final PERM_CHASTE = "perm_chaste", PERM_CHASTE_ASK = "perm_chaste_ask";
// toy.state.<name>
final CHASTE = "chaste", COLLARED = "collared", CUFFED = "cuffed", CLAMPED = "clamped", GAGGED = "gagged", NAKED = "naked";
- final REDRESS = "redress";
final TOYTOYS = [CUFFED, COLLARED, CLAMPED, GAGGED];
- final RELEASEFROM = "releaseFrom";
// toy.position
final KNEELING = "kneeling", ALLFOURS = "allfours", STANDING = "standing";
def OWNER = null;
@@ -259,32 +256,6 @@ return new Object() {
return tt;
};
- // Play
- def stateToyName = { state ->
- switch (state) {
- case CUFFED:
- return "cuffs";
- case COLLARED:
- return "collar";
- case CLAMPED:
- return "nipple clamps";
- case GAGGED:
- return "gag";
- }
- return null;
- };
- def removeToy = { toy, imageSpec ->
- if (!stateIs(toy)) return;
- def toyName = stateToyName(toy);
- present(imageSpec, [
- ["OK,"],
- ["you may remove your $toyName.", "the $toyName can come off.", "take the $toyName off."]]);
- showButtonG("Thank you, ${dommeTitle()}", "ok");
- wait(5);
- set(toy, false);
- removeEvent("$RELEASEFROM-$toy");
- showButtonGT("Removed, ${dommeTitle()}", "removed", 20, 1);
- };
// Session
def sessionSummon = { imageSpec ->
final limit = 5;
@@ -323,297 +294,18 @@ return new Object() {
final addActivity = { String name, func ->
activityList[name] = func;
}
- def sessionPlay = {
- if (stateIs(CHASTE)) sessionToys[CHASTITY] = getTime();
- def playScope = [
- 'randRange': { min, max -> randRange(min, max) },
- 'currentPunishment': { getPunish() },
- 'sessionAborted': { return sessionAborted },
- 'can': { return can(it) },
- 'has': { return has(it) },
- 'is': { return stateIs(it) },
- 'likes': { return likes(it) },
- 'punishMultiple': (float)1.0,
- 'prop': load('toy') ?: [:]
- ];
- def apply = { activitity, use = null ->
- if (!activitity) return;
- def val = activitity();
- playBackgroundSound(null);
- if (use && val instanceof Number) {
- use(val);
- }
- };
- def interval = { activities ->
- if (activities) {
- apply(activities[getRandom(activities.size())], null);
- }
- };
- def funcMap = [
- 'use': [
- 'punishMultiply': { val ->
- if (val) {
- playScope.punishMultiple *= val;
- }
- },
- 'punishApply': { val ->
- if (val) {
- adjustPunish(-val * playScope.punishMultiple);
- }
- }
- ],
- 'select': [
- 'repeat': { amount, activities, intervals, use = null ->
- amount.times {
- if (!sessionAborted) {
- apply(activities[getRandom(activities.size())], use);
- interval(intervals);
- }
- };
- },
- 'take': { amount, activities, intervals, use = null ->
- Collections.shuffle(activities);
- activities.take(amount).each {
- if (!sessionAborted) {
- apply(it, use);
- interval(intervals);
- }
- };
- }
- ],
- 'activities': activityList
- ];
- final eval = { expr -> Eval.me('toy', playScope, expr.toString()) };
- if (stateIs("DEBUG")) {
- // Check everything in DOMME evaluates and resolves
- final checkIsFunc = { group, name ->
- if (!name) return;
- show("checking $group:$name is a function");
- if (!(funcMap[group][name] instanceof Closure)) {
- showPopup("$group:$name is not a function");
- }
- }
- final checkEval = { expr ->
- show("checking $expr evaluates");
- eval(expr);
- };
- DOMME.sessions.forEach { session ->
- checkEval(session.require ?: true);
- checkEval(session.probability);
- session.phases.forEach { phase ->
- checkEval(phase.require ?: true);
- checkIsFunc("select", phase.select);
- checkEval(phase.number ?: 1);
- phase.activities.forEach { a ->
- checkIsFunc("activities", a);
- }
- (phase.intervals ?: []).forEach { i ->
- checkIsFunc("activities", i);
- }
- checkIsFunc("use", phase.use);
- };
- };
- }
- final sessions = DOMME.sessions.findAll { s -> eval(s.require ?: true) };
- final probabilities = sessions.withIndex().collect { s, idx -> [idx] * s.probability }.sum();
- final sessionIdx = probabilities[getRandom(probabilities.size)];
- sessions[sessionIdx].phases.forEach { phase ->
- if (eval(phase.require ?: true)) {
- funcMap.select[phase.select ?: 'take'](eval(phase.number ?: 1),
- (phase.activities ?: []).collect { f -> funcMap.activities[f] },
- (phase.intervals ?: []).collect { f -> funcMap.activities[f] },
- funcMap.use[phase.use]);
- }
- };
- };
- def sessionRelease = { goodToy ->
- if (goodToy) {
- present([DRESSED], [
- ["Ahhh,", "OK,"],
- ["I'm done with you for now.", "That was fun... for me at least."]]);
- }
- else {
- present([DRESSED], [
- ["I don't ask much of you, toy."]]);
- wait(getRandom(10) + 5);
- postChastity();
- }
- wait(getRandom(10) + 5);
- def toys = TOYTOYS.findAll { t -> stateIs(t) };
- Collections.shuffle(toys);
- if (toys) {
- if (!goodToy) {
- present([DRESSED], [
- ["I should leave you like that.", "I suppose you still want letting free?"],
- ["Maybe.", "Let me ponder on it."]]);
- wait(getRandom(20) + 20);
- }
- toys.each { toy ->
- if (getRandom(100) > ((goodToy && (getPunish() < 100)) ? 10 : 80)) {
- removeToy(toy, [DRESSED]);
- }
- else {
- addEvent("$RELEASEFROM-$toy", getTime() + 100 + getRandom(10 * (getPunish() + 1)),
- RELEASEFROM, toy);
- adjustPunish(-5);
- }
- };
- }
- if (stateIs(NAKED)) {
- if (goodToy && getRandom(1)) {
- present([DRESSED], [
- ["Put some clothes back on.", "Cover yourself up!"]]);
- wait(getRandom(10) + 15);
- set(NAKED, false);
- }
- else {
- present([DRESSED], [
- ["No clothes now for a while,", "Keep those clothes off,"],
- ["you don't get clothes until I say.", "I like seeing you naked."]]);
- addEvent(REDRESS, getTime() + 600 + getRandom(1200), "redress");
- showButtonG("Yes, ${dommeTitle()}", "ok");
- }
- }
- if (goodToy) {
- present([DRESSED], [
- ["Off you go.", "You may leave."]]);
- }
- else {
- present([DRESSED], [
- ["Get out of my sight.", "Go!"]]);
- removeEvent(CUM);
- revokePermission(CUM);
- }
- wait(10);
- save("toy.lastPlay", getTime());
- showLounge();
- sessionAborted = null;
- sessionToys = [:];
- if (goodToy) {
- adjustPunish(-20);
- }
- else {
- setProp(DISAPPOINT, getProp(DISAPPOINT, loadI, 0) + 1);
- }
- show(null);
- };
def playActivity = {
final keys = new ArrayList<?>(activityList.keySet());
final act = getSelectedValue("Choose activity", keys);
activityList[keys[act]]();
};
- def playWait = {
- present([DRESSED,nTEASE], [
- ["Hello,", "Hi,", "Hey there,"],
- ["toy.", "slut.", "slave."],
- ["On your knees,", "On the floor,", "Down... at my feet,",],
- ["wait there.", "wait patiently.", "don't move."],
- ["I'll be with you shortly.", "I won't be a moment."]]);
- showButtonGT("Yes, ${dommeTitle()}", "ok", 10, 1);
- showLounge();
- show(null);
- wait(20 + getRandom(20));
- };
- def playSchedule = {
- if (getAway()) return;
- final lastPlay = loadInteger("toy.lastPlay") ?: 0;
- if (lastPlay < getTime() - (4 * HOUR)) {
- addEventIfMissing(PLAY, getTime() + 120 + getRandom(480), PLAY, true); // 2-10mins
- }
- else {
- addEventIfMissing(PLAY, getTime() + 1200 + getRandom(5400), PLAY, false); // 20-90mins
- }
- };
- def playEvent = { rt = true, first = true ->
- if (!rt || getAway()) return;
- dress([[DRESSED,nTEASE],[DRESSED,TEASE],[TITS],[STOOD]]);
- if (sessionSummon([DRESSED,nTEASE])) {
- if (first.asBoolean()) {
- playWait();
- }
- sessionPlay();
- sessionRelease(sessionAborted == null);
- }
- else {
- adjustPunish(25);
- }
- playSchedule();
- showLounge();
- }
- def redress = { rt ->
- if (!rt || !sessionSummon([DRESSED])) {
- addEvent(REDRESS, getTime() + 300, "redress");
- return;
- }
- present([DRESSED], [
- ["OK, toy,"],
- ["you can put some clothes back on now.", "get yourself covered up."]]);
- wait(getRandom(10) + 15);
- showButtonG("Thank you, ${dommeTitle()}", "ok");
- set(NAKED, false);
- showLounge();
- };
- def releaseFrom = { rt, arg, name ->
- if (!rt || !sessionSummon([DRESSED])) {
- addEvent(name, getTime() + 300, RELEASEFROM, arg);
- return;
- }
- removeToy(arg, [DRESSED]);
- showLounge();
- };
- def requestClothes = {
- adjustPunish(5);
- present([DRESSED], [
- ["Really?", "Disappointing."],
- ["You want to clothes back on?", "You wish to cover up?"]]);
- if (getBoolean(null)) {
- present([DRESSED], [["Hmm, very well.", "If you must."]]);
- adjustPunish(50);
- set(NAKED, false);
- removeEvent(REDRESS);
- }
- else {
- present([DRESSED], [["Good boy."]]);
- }
- showButtonG("Thank you, ${dommeTitle()}", "ok");
- showLounge();
- };
- def requestRelease = { toy ->
- adjustPunish(5);
- present([DRESSED], [
- ["Really?", "Disappointing."],
- ["You wish to be un-$toy?"]]);
- if (getBoolean(null)) {
- adjustPunish(10);
- if (getRandom(100) > getPunish()) {
- present([DRESSED], [["No.", "You may not."],
- ["Not yet.", "Not until later."]]);
- }
- else {
- present([DRESSED], [["Hmm, very well.", "If you must."]]);
- set(toy, false);
- removeEvent("$RELEASEFROM-$toy");
- }
- }
- else {
- present([DRESSED], [["Good boy."]]);
- }
- showButtonG("Thank you, ${dommeTitle()}", "ok");
- showLounge();
- };
// Setup
- def setupEvents = {
- playSchedule();
- };
def setDefault = { prop, val ->
if (loadString(prop) == null) {
save(prop, val);
}
};
def namedEvents = [
- play: { name, arg, schedTime, rt -> playEvent(rt, arg) },
- releaseFrom: { name, arg, schedTime, rt -> releaseFrom(rt, arg, name) },
- redress: { name, arg, schedTime, rt -> redress(rt) },
permit: { name, arg, schedTime, rt -> givePermission(arg) }
];
def setupShowState = {
@@ -687,7 +379,6 @@ return new Object() {
};
setDefault("toy.punishment", 0);
execEvents(false);
- setupEvents();
tidyAvail();
final cycleTime = 60;
@@ -729,14 +420,14 @@ return new Object() {
def opts = requestables.values().toList();
if (stateIs("DEBUG")) {
opts.push([ lbl: "Status", act: setupShowState ]);
- opts.push([ lbl: "Play", act: playEvent, arg: true ]);
+ opts.push([ lbl: "Play", act: { playEvent() }, arg: true ]);
opts.push([ lbl: "Activity", act: playActivity ]);
}
if (stateIs(NAKED)) {
- opts.push([ lbl: "May I wear clothes", act: requestClothes ]);
+ opts.push([ lbl: "May I wear clothes", act: { requestClothes() } ]);
}
TOYTOYS.findAll { stateIs(it) }.each {
- opts.push([ lbl: "May I be un-$it".toString(), act: requestRelease, arg: it ]);
+ opts.push([ lbl: "May I be un-$it".toString(), act: { requestRelease() }, arg: it ]);
};
opts.push([ lbl: "Back", act: null ]);
def opt = getSelectedValue(stateIs("DEBUG") ? DOMME : "Yes, toy?", opts.collect { it.lbl });
@@ -768,6 +459,7 @@ return new Object() {
* scripts/toy/intro.groovy
* scripts/toy/misc.groovy
* scripts/toy/orgasmControl.groovy
+ * scripts/toy/play.groovy
* scripts/toy/pain.groovy
* scripts/toy/sleep.groovy
* scripts/toy/social.groovy
diff --git a/scripts/toy/play.groovy b/scripts/toy/play.groovy
new file mode 100644
index 0000000..a383bef
--- /dev/null
+++ b/scripts/toy/play.groovy
@@ -0,0 +1,322 @@
+{ toy ->
+ final PLAY = "play";
+ final REDRESS = "redress";
+ final RELEASEFROM = "releaseFrom";
+
+ toy.metaClass.stateToyName { state ->
+ switch (state) {
+ case CUFFED:
+ return "cuffs";
+ case COLLARED:
+ return "collar";
+ case CLAMPED:
+ return "nipple clamps";
+ case GAGGED:
+ return "gag";
+ }
+ return null;
+ };
+
+ toy.metaClass.removeToy { state, imageSpec ->
+ if (!stateIs(state)) return;
+ def toyName = stateToyName(state);
+ present(imageSpec, [
+ ["OK,"],
+ ["you may remove your $toyName.", "the $toyName can come off.", "take the $toyName off."]]);
+ showButtonG("Thank you, ${dommeTitle()}", "ok");
+ pause(5);
+ set(state, false);
+ removeEvent("$RELEASEFROM-$state");
+ showButtonGT("Removed, ${dommeTitle()}", "removed", 20, 1);
+ };
+
+ toy.metaClass.sessionPlay {
+ if (stateIs(CHASTE)) sessionToys[CHASTITY] = getTime();
+ def playScope = [
+ 'randRange': { min, max -> randRange(min, max) },
+ 'currentPunishment': { getPunish() },
+ 'sessionAborted': { return sessionAborted },
+ 'can': { return can(it) },
+ 'has': { return has(it) },
+ 'is': { return stateIs(it) },
+ 'likes': { return likes(it) },
+ 'punishMultiple': (float)1.0,
+ 'prop': load('toy') ?: [:]
+ ];
+ def apply = { activitity, use = null ->
+ if (!activitity) return;
+ def val = activitity();
+ playBackgroundSound(null);
+ if (use && val instanceof Number) {
+ use(val);
+ }
+ };
+ def interval = { activities ->
+ if (activities) {
+ apply(activities[getRandom(activities.size())], null);
+ }
+ };
+ def funcMap = [
+ 'use': [
+ 'punishMultiply': { val ->
+ if (val) {
+ playScope.punishMultiple *= val;
+ }
+ },
+ 'punishApply': { val ->
+ if (val) {
+ adjustPunish(-val * playScope.punishMultiple);
+ }
+ }
+ ],
+ 'select': [
+ 'repeat': { amount, activities, intervals, use = null ->
+ amount.times {
+ if (!sessionAborted) {
+ apply(activities[getRandom(activities.size())], use);
+ interval(intervals);
+ }
+ };
+ },
+ 'take': { amount, activities, intervals, use = null ->
+ Collections.shuffle(activities);
+ activities.take(amount).each {
+ if (!sessionAborted) {
+ apply(it, use);
+ interval(intervals);
+ }
+ };
+ }
+ ],
+ 'activities': activityList
+ ];
+ final eval = { expr -> Eval.me('toy', playScope, expr.toString()) };
+ if (stateIs("DEBUG")) {
+ // Check everything in DOMME evaluates and resolves
+ final checkIsFunc = { group, name ->
+ if (!name) return;
+ show("checking $group:$name is a function");
+ if (!(funcMap[group][name] instanceof Closure)) {
+ showPopup("$group:$name is not a function");
+ }
+ }
+ final checkEval = { expr ->
+ show("checking $expr evaluates");
+ eval(expr);
+ };
+ DOMME.sessions.forEach { session ->
+ checkEval(session.require ?: true);
+ checkEval(session.probability);
+ session.phases.forEach { phase ->
+ checkEval(phase.require ?: true);
+ checkIsFunc("select", phase.select);
+ checkEval(phase.number ?: 1);
+ phase.activities.forEach { a ->
+ checkIsFunc("activities", a);
+ }
+ (phase.intervals ?: []).forEach { i ->
+ checkIsFunc("activities", i);
+ }
+ checkIsFunc("use", phase.use);
+ };
+ };
+ }
+ final sessions = DOMME.sessions.findAll { s -> eval(s.require ?: true) };
+ final probabilities = sessions.withIndex().collect { s, idx -> [idx] * s.probability }.sum();
+ final sessionIdx = probabilities[getRandom(probabilities.size)];
+ sessions[sessionIdx].phases.forEach { phase ->
+ if (eval(phase.require ?: true)) {
+ funcMap.select[phase.select ?: 'take'](eval(phase.number ?: 1),
+ (phase.activities ?: []).collect { f -> funcMap.activities[f] },
+ (phase.intervals ?: []).collect { f -> funcMap.activities[f] },
+ funcMap.use[phase.use]);
+ }
+ };
+ };
+
+ toy.metaClass.sessionRelease { goodToy ->
+ if (goodToy) {
+ present([DRESSED], [
+ ["Ahhh,", "OK,"],
+ ["I'm done with you for now.", "That was fun... for me at least."]]);
+ }
+ else {
+ present([DRESSED], [
+ ["I don't ask much of you, toy."]]);
+ pause(getRandom(10) + 5);
+ postChastity();
+ }
+ pause(getRandom(10) + 5);
+ def toys = TOYTOYS.findAll { t -> stateIs(t) };
+ Collections.shuffle(toys);
+ if (toys) {
+ if (!goodToy) {
+ present([DRESSED], [
+ ["I should leave you like that.", "I suppose you still want letting free?"],
+ ["Maybe.", "Let me ponder on it."]]);
+ pause(getRandom(20) + 20);
+ }
+ toys.each { toyState ->
+ if (getRandom(100) > ((goodToy && (getPunish() < 100)) ? 10 : 80)) {
+ removeToy(toyState, [DRESSED]);
+ }
+ else {
+ addEvent("$RELEASEFROM-$toyState", getTime() + 100 + getRandom(10 * (getPunish() + 1)),
+ RELEASEFROM, toyState);
+ adjustPunish(-5);
+ }
+ };
+ }
+ if (stateIs(NAKED)) {
+ if (goodToy && getRandom(1)) {
+ present([DRESSED], [
+ ["Put some clothes back on.", "Cover yourself up!"]]);
+ pause(getRandom(10) + 15);
+ set(NAKED, false);
+ }
+ else {
+ present([DRESSED], [
+ ["No clothes now for a while,", "Keep those clothes off,"],
+ ["you don't get clothes until I say.", "I like seeing you naked."]]);
+ addEvent(REDRESS, getTime() + 600 + getRandom(1200), "redress");
+ showButtonG("Yes, ${dommeTitle()}", "ok");
+ }
+ }
+ if (goodToy) {
+ present([DRESSED], [
+ ["Off you go.", "You may leave."]]);
+ }
+ else {
+ present([DRESSED], [
+ ["Get out of my sight.", "Go!"]]);
+ removeEvent(CUM);
+ revokePermission(CUM);
+ }
+ pause(10);
+ save("toy.lastPlay", getTime());
+ showLounge();
+ sessionAborted = null;
+ sessionToys = [:];
+ if (goodToy) {
+ adjustPunish(-20);
+ }
+ else {
+ setProp(DISAPPOINT, getProp(DISAPPOINT, loadI, 0) + 1);
+ }
+ show(null);
+ };
+
+ toy.metaClass.playWait {
+ present([DRESSED,nTEASE], [
+ ["Hello,", "Hi,", "Hey there,"],
+ ["toy.", "slut.", "slave."],
+ ["On your knees,", "On the floor,", "Down... at my feet,",],
+ ["wait there.", "wait patiently.", "don't move."],
+ ["I'll be with you shortly.", "I won't be a moment."]]);
+ showButtonGT("Yes, ${dommeTitle()}", "ok", 10, 1);
+ showLounge();
+ show(null);
+ pause(20 + getRandom(20));
+ };
+
+ toy.metaClass.playSchedule {
+ if (getAway()) return;
+ final lastPlay = loadInteger("toy.lastPlay") ?: 0;
+ if (lastPlay < getTime() - (4 * HOUR)) {
+ addEventIfMissing(PLAY, getTime() + 120 + getRandom(480), PLAY, true); // 2-10mins
+ }
+ else {
+ addEventIfMissing(PLAY, getTime() + 1200 + getRandom(5400), PLAY, false); // 20-90mins
+ }
+ };
+
+ toy.metaClass.playEvent { rt = true, first = true ->
+ if (!rt || getAway()) {
+ playSchedule();
+ return;
+ }
+ dress([[DRESSED,nTEASE],[DRESSED,TEASE],[TITS],[STOOD]]);
+ if (sessionSummon([DRESSED,nTEASE])) {
+ if (first.asBoolean()) {
+ playWait();
+ }
+ sessionPlay();
+ sessionRelease(sessionAborted == null);
+ }
+ else {
+ adjustPunish(25);
+ }
+ playSchedule();
+ showLounge();
+ }
+
+ toy.metaClass.redress { rt ->
+ if (!rt || !sessionSummon([DRESSED])) {
+ addEvent(REDRESS, getTime() + 300, "redress");
+ return;
+ }
+ present([DRESSED], [
+ ["OK, toy,"],
+ ["you can put some clothes back on now.", "get yourself covered up."]]);
+ pause(getRandom(10) + 15);
+ showButtonG("Thank you, ${dommeTitle()}", "ok");
+ set(NAKED, false);
+ showLounge();
+ };
+
+ toy.metaClass.releaseFrom { rt, arg, name ->
+ if (!rt || !sessionSummon([DRESSED])) {
+ addEvent(name, getTime() + 300, RELEASEFROM, arg);
+ return;
+ }
+ removeToy(arg, [DRESSED]);
+ showLounge();
+ };
+
+ toy.metaClass.requestClothes {
+ adjustPunish(5);
+ present([DRESSED], [
+ ["Really?", "Disappointing."],
+ ["You want to clothes back on?", "You wish to cover up?"]]);
+ if (getBoolean(null)) {
+ present([DRESSED], [["Hmm, very well.", "If you must."]]);
+ adjustPunish(50);
+ set(NAKED, false);
+ removeEvent(REDRESS);
+ }
+ else {
+ present([DRESSED], [["Good boy."]]);
+ }
+ showButtonG("Thank you, ${dommeTitle()}", "ok");
+ showLounge();
+ };
+
+ toy.metaClass.requestRelease { toyState ->
+ adjustPunish(5);
+ present([DRESSED], [
+ ["Really?", "Disappointing."],
+ ["You wish to be un-$toyState?"]]);
+ if (getBoolean(null)) {
+ adjustPunish(10);
+ if (getRandom(100) > getPunish()) {
+ present([DRESSED], [["No.", "You may not."],
+ ["Not yet.", "Not until later."]]);
+ }
+ else {
+ present([DRESSED], [["Hmm, very well.", "If you must."]]);
+ set(toyState, false);
+ removeEvent("$RELEASEFROM-$toyState");
+ }
+ }
+ else {
+ present([DRESSED], [["Good boy."]]);
+ }
+ showButtonG("Thank you, ${dommeTitle()}", "ok");
+ showLounge();
+ };
+
+ toy.addNamedEvent(PLAY, { name, arg, schedTime, rt -> toy.playEvent(rt, arg) });
+ toy.addNamedEvent(RELEASEFROM, { name, arg, schedTime, rt -> toy.releaseFrom(rt, arg, name) });
+ toy.addNamedEvent(REDRESS, { name, arg, schedTime, rt -> toy.redress(rt) });
+ toy.playSchedule();
+}