BetterFap - Fap Gauntlet

Fap Gauntlet for BetterFap

As of 2018-03-06. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        BetterFap - Fap Gauntlet
// @author      Goog
// @description Fap Gauntlet for BetterFap
// @namespace   https://aint-got-none.fap/
// @include     https://test.betterfap.com/*
// @include     https://betterfap.com/*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require     http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js
// @grant       unsafeWindow
// @version 0.55
// ==/UserScript==

// Change/Add/Remove masturbation styles here

var masturbationStyle = [	
	'Normal Grip', 
	'Inverse Grip', 
	'Only Down-Strokes',
	'Only Up-Strokes',
	'Palm Circles',
	'Squeeze',
	'Top half only',
	'Bottom half only'
];

var gripStrength = [	
	'Loose',
	'Normal',
	'Tight'
];

// Change/Add/Remove speeds as you like

var fapsPerSec = [
	0.1,
	0.2,
	0.33,
	0.5,
	1,
  1.5,
	2,
  2.5,
	3,
  3.5,
	4,
  4.5,
	5
];

// Change/Add/Remove dildo styles here

var dildoStyle = [
	'Rub outside',
	'Prod',
	'Normal Thrusts',
	'Deep thrusts',
	'All the way'
];

// Strict speeds with a dildo didn't make sense to me 
// so add any speeds you'd like with a dildo here

var dildoSpeed = [
	'Slow',
	'Moderate',
	'Fast'
];

// Below is non-user-friendly stuff. 
// Don't touch it if you dont want the script to break!

var FGisON = false;
var firstStart = true;
var isPlaying = false;
var currViewObj = null;
var lines = 0;
var currFPS = 0;
var denialMode = false;
var dildoMode = false;
var canCum = null;
var canCumNext = false;
var currIntensity = null;
var currDilInt = null;
var currDilSpeed = null;
var randTime = 1000;
var changedNormally = null;
var dildoStuff = [];
var handsOffMode = false;
var visualGuideMode = false;
var autoOverride = false;
var currCurve;
var buttonsHidden = false;
var cumText;

// Don't touch this.
var visualCurve = [
	'linear',
	'ease',
	'ease-in',
	'ease-in-out',
	'ease-out'
];

var context = new AudioContext();
var o = context.createOscillator();
o.type = "sawtooth";
o.connect(context.destination);
o.frequency.value = 0;

function getRandomInt(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getRandomFPS() {
    
    // check bottom of script if you want to see the depths of autism
    
    //return cleanGauss(generateGaussianNoise(3 ,2));
    
	 var rand = getRandomInt(0, fapsPerSec.length - 1);
	 return fapsPerSec[rand]; 
}

function getCumState() { // 1 in 7 chance to be allowed to cum
	if (getRandomInt(1, 7) == 1) {
    canCum = canCumNext;
    canCumNext = true;		
	} else {
    canCum = canCumNext;
		canCumNext = false;
	}
	return canCum;
}

function getCumText() {
	if (canCum === true) {
		cumText = "You can cum.";
	} else {
		cumText = "Do not cum.";
	}
	return cumText;
}

// autistically defined percent chances for each intensity, no equal chances here (except for 4 of them)

function getRandomIntensity() {
	var rand = getRandomInt(1, 75);
	var x = 2000;

	//below code depreciated
	// if (rand <= 10) { // 10% for Feather Light
	// x = 0;
	// } else if (rand > 10 && rand <= 25) { // 15% for Very Light
	// x = 1;
	// } else if (rand > 25 && rand <= 40) { // 15% for Light
	// x = 2;
	// } else if (rand > 40 && rand <= 60) { // 20% for Medium
	// x = 3;
	// } else if (rand > 60 && rand <= 75) { // 15% for Hard
	// x = 4;
	// } else if (rand > 75 && rand <= 90) { // 15% for Very Hard
	// x = 5;
	// } else if (rand > 90) { // 10% for Deathgrip
	// x = 6;
	// }

	return masturbationStyle[getRandomInt(0, masturbationStyle.length - 1)];
}

// made it get only multiples of 10, no more 33 seconds of fapping #trueautism
function getRandTime(randFPS) {
	randTime = 30000;

	// more deprecated code #butwhatifIneedit
	// if (dildoMode == false) {
	// if (randFPS == 0.33) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 0.5) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 1) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 2) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 3) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 4) {
	// randTime = getRandomInt(1, 4) * 10;
	// } else if (randFPS == 5) {
	// randTime = getRandomInt(1, 2) * 10;
	// }
	// } else {
	// randTime = getRandomInt(1,4) * 10;
	// }

	return getRandomInt(1, 4) * 10;
}

function getDildoSpeed() {
	var rand = getRandomInt(0, 2);
	return dildoSpeed[rand];
}

function getdildoStyle() {
	var rand = getRandomInt(0, 4);
	return dildoStyle[rand];
}

function getGripStrength(style) {
	var rand = getRandomInt(0, 2);
  if (style == 'Palm Circles'){return "";}
	return gripStrength[rand];
}

function getVisualCurve() {
	var rand = getRandomInt(0, visualCurve.length - 1);
		return visualCurve[rand];
}

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

function getNewFapData(lastInten, lastFPS) { // sets the next image's fap data
  
	i = 0;
	currIntensity = getRandomIntensity();
	currFPS = getRandomFPS();
	randTime = getRandTime(currFPS) + 1;
	getCumState();
	currDilInt = getdildoStyle();
	currDilSpeed = getDildoSpeed();
	currCurve = getVisualCurve();
  currGripStrength = getGripStrength(currIntensity);

	//prevents repeats

	if (lastInten == currIntensity || lastFPS == currFPS) {
		getNewFapData(lastInten, lastFPS);
	}

	// it's fucking hard to maintain a feather-light touch four or five times a second, so let's not.

	if (((currFPS >= 4) && currIntensity == 'Inverse Grip') ||
      ((currFPS >= 4) && currIntensity == 'Squeeze') || 
      ((currFPS > 3) && currIntensity == 'Palm Circles') ||
      ((currFPS > 3) && currIntensity == 'Only Up-Strokes') ||
      ((currFPS > 3) && currIntensity == 'Only Down-Strokes')   
     ) {
		do {
			currIntensity = getRandomIntensity();
			currFPS = getRandomFPS();
      currGripStrength = getGripStrength(currIntensity);
		} while (((currFPS >= 4) && currIntensity == 'Inverse Grip') ||
      ((currFPS >= 4) && currIntensity == 'Squeeze') || 
      ((currFPS > 3) && currIntensity == 'Palm Circles') ||
      ((currFPS > 3) && currIntensity == 'Only Up-Strokes') ||
      ((currFPS > 3) && currIntensity == 'Only Down-Strokes'));	
	}

	if (isPlaying) {
		o.frequency.value = currFPS;
	}

	if (visualGuideMode) {
        if (currFPS < 2)
        {
            $("#VisualGuide")[0].style.animation = "play 0s infinite " + currCurve;
            $("#VisualGuide")[0].style.animation = "play " + (1 / currFPS) + "s infinite " + currCurve;
        }else
        {
             $("#VisualGuide")[0].style.animation = "play 0s infinite " + currCurve;
            $("#VisualGuide")[0].style.animation = "play " + (1 / currFPS) + "s infinite linear";
	}   }
}

function remakeDialog() {

    $("#FapDialog")[0].style.display = "block";

	document.querySelector('div[id="FapDialog"]').innerHTML = "Starting...";

	if (remakeDialog.interval) {
		clearInterval(remakeDialog.interval);
	}

	// set the first image's length, faps per sec, etc

	i = 0;
	currIntensity = getRandomIntensity();
	currFPS = getRandomFPS();
	randTime = getRandTime(currFPS); // every randtime after this has +1 so that the numbers show as multiples of ten on the first stroke instead of 10x + 9 which was annoying my autism greatly
	getCumState();
	currDilInt = getdildoStyle();
	currDilSpeed = getDildoSpeed();
	currCurve = getVisualCurve();
  currGripStrength = getGripStrength(currIntensity);

	// it's fucking hard to maintain a feather-light touch four or five times a second, so let's not.

		if (((currFPS >= 4) && currIntensity == 'Inverse Grip') ||
      ((currFPS >= 4) && currIntensity == 'Squeeze') || 
      ((currFPS > 3) && currIntensity == 'Palm Circles') ||
      ((currFPS > 3) && currIntensity == 'Only Up-Strokes') ||
      ((currFPS > 3) && currIntensity == 'Only Down-Strokes')   
     ) {
		do {
			currIntensity = getRandomIntensity();
			currFPS = getRandomFPS();
		} while (((currFPS >= 4) && currIntensity == 'Inverse Grip') ||
      ((currFPS >= 4) && currIntensity == 'Squeeze') || 
      ((currFPS > 3) && currIntensity == 'Palm Circles') ||
      ((currFPS > 3) && currIntensity == 'Only Up-Strokes') ||
      ((currFPS > 3) && currIntensity == 'Only Down-Strokes'));	
	}

	if (isPlaying) { // if the user has the audio helper enabled, change it to match current FPS
		o.frequency.value = currFPS;
	}

	if (visualGuideMode) {
		$("#VisualGuide")[0].style.display = "block";
		$("#VisualGuide")[0].style.animation = "play " + (1 / currFPS) + "s infinite " + currCurve;
	}

	currViewObj = unsafeWindow.AppState.viewing;

	remakeDialog.interval = setInterval(
			function oneSecTimer() {

			if (handsOffMode && !canCum) {
				document.querySelector('div[id="FapDialog"]').innerHTML = "Hands Off, " + (randTime - i);
			} else if (handsOffMode && canCum) {
				document.querySelector('div[id="FapDialog"]').innerHTML = "Hands Off, " + (randTime - i) + "<br> You could have cum.";
			} else if (denialMode === false && dildoMode === false) {
				document.querySelector('div[id="FapDialog"]').innerHTML = currIntensity + ", " + currGripStrength + "<br />" + currFPS + "/sec, " + (randTime - i);
			} else if (denialMode === true && dildoMode === false) {
				document.querySelector('div[id="FapDialog"]').innerHTML = currIntensity + ", " + currGripStrength + "<br />" + currFPS + "/sec, " + (randTime - i) + "<br />" + getCumText();
			} else if (denialMode === false && dildoMode === true) {
				document.querySelector('div[id="FapDialog"]').innerHTML = currDilInt + "<br />" + currDilSpeed + ", " + (randTime - i);
			} else if (denialMode === true && dildoMode === true) {
				document.querySelector('div[id="FapDialog"]').innerHTML = currDilInt + "<br />" + currDilSpeed + ", " + (randTime - i) + "<br />" + getCumText();
			}
			
			//if (visualGuideMode)
				//document.querySelector('div[id="FapDialog"]').innerHTML = document.querySelector('div[id="FapDialog"]').innerHTML + "<br />" + currCurve;
            
			if ((randTime - i <= 1) && !(autoOverride)) { // aka if the time ticked down normally to 0, go to next image and get new fap data

				handsOffMode = false;
        
        document.querySelector('div[id="errordiv"]').innerHTML += "<br/> "+ (lines++) + "   thought it was normal!";

        
				getNewFapData(currIntensity, currFPS);

				//****next image function****

				var $ = unsafeWindow.jQuery;
        
				window.top.postMessage({
					action: 'next',
					cr: $.cookie().cr
				}, window.top.location.protocol + window.top.location.host);
				setTimeout(function () {
					currViewObj = unsafeWindow.AppState.viewing;
				}, 1000);
        
        
        
        /*
        if (canCum) 
        {          
          document.querySelector('span[tip="Filter Results"]').click();
          sleep(500);
          document.querySelector('a[title="Sort By    Random"]').click();
        } 

        if(canCumNext) {
          window.top.postMessage({action:'mode', mode: 'favorites', cr: $.cookie().cr}, window.top.location.protocol + window.top.location.host); 
        } else {
          window.top.postMessage({action:'mode', mode: 'recommend', cr: $.cookie().cr}, window.top.location.protocol + window.top.location.host); 
        }
        
        */
        
				//****

				changedNormally = true;

			} else if ((currViewObj != unsafeWindow.AppState.viewing) && (!(changedNormally) && !(handsOffMode))) { // if the user skipped their current image (or hit backspace or the image changed literally at all)

				currViewObj = unsafeWindow.AppState.viewing;

				getNewFapData(currIntensity, currFPS);
                
        document.querySelector('div[id="errordiv"]').innerHTML += "<br/> "+ (lines++) + "   thought it was changed!";

			} else if (autoOverride && randTime - i <= 1) {
				getNewFapData(currIntensity, currFPS);
			}

			i = i + 1;

			if (i > 2) {
				changedNormally = false;
			}

		},
			1000);
}

function redrawOptions() {

	$("div#tippy-top").first().append('<div class="view-item-container" id="embed-container-copy" style="width: 200px; height: 300px, position: relative;">');

	$("div#tippy-top").first().append('<div id="FapDialog" style="font-size:400%; color: #00FF00"></div>'); 
	
  $("#embed-container-copy").append('<div id="dropdown" style="font-size:100%; color: white; width: 100px; position: fixed; left: -20px; top: 50px; z-index:81000 !important">▼ Hide</div>');
	$("#embed-container-copy").append('<div id="ToggleAutoAdvance" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 100px; z-index:81000 !important">Disable Auto-Advance</div>');
	$("#embed-container-copy").append('<div id="ToggleFG" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 70px; z-index:81000 !important">Enable Fap Gauntlet</div>');
	$("#embed-container-copy").append('<div id="ToggleDenial" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 190px; z-index:81000 !important">Enable Denial Mode</div>');
	$("#embed-container-copy").append('<div id="ToggleVG" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 130px; z-index:81000 !important">Enable Visual Guide</div>');
	$("#embed-container-copy").append('<div id="ToggleDildo" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 220px; z-index:81000 !important">Enable Dildo Mode</div>');
	$("#embed-container-copy").append('<div id="ToggleAH" style="font-size:120%; color: white; width: 200px; position: fixed; left: -10px; top: 160px; z-index:81000 !important">Enable Audio Helper</div>');
  $("#embed-container-copy").append('<div id="errordiv" style="font-size:100%; display:none; color: white; width: 400px; position: fixed; right: -20px; top: 50px; z-index:81000 !important">ErrorLog:</div>');
  
	var visualguide = document.createElement('div');
	visualguide.innerHTML = '<div id="VisualGuide"></div>';
	$("#embed-container-copy")[0].appendChild(visualguide);

	var topBar = document.getElementsByClassName("top-bar-center top-bar-interact")[1];
	var edgedDiv = document.createElement('div');
	edgedDiv.innerHTML = "";
	edgedDiv.zIndex = 81000;
	edgedDiv.id = "EdgedButton";
	edgedDiv.style.width = "auto";
	edgedDiv.style.alignSelf = "left";
	topBar.prepend(edgedDiv);

	$("#VisualGuide")[0].style.backgroundImage = "url('https://www.dropbox.com/s/b4s8lyqexgg4app/sprite.png?raw=1')";
	$("#VisualGuide")[0].style.height = "600px";
	$("#VisualGuide")[0].style.width = "50px";
	$("#VisualGuide")[0].style.position = "fixed";
	$("#VisualGuide")[0].style.left = "10px";
	$("#VisualGuide")[0].style.top = "250px";
	$("#VisualGuide")[0].style.zIndex = "81000";
	$("#VisualGuide")[0].style.animation = "play 0s infinite linear";
	$("#VisualGuide")[0].style.display = "none";

	var style = document.createElement('style');
	style.type = 'text/css';
	var keyFrames = '\
		@keyframes play {\
		100% {\
		background-position: 100%;\
		}\
		}';
	style.innerHTML = keyFrames; //.replace(/A_DYNAMIC_VALUE/g, "180deg");
	document.getElementsByTagName('head')[0].appendChild(style);

	//--- Activate the dialog.

	$("#FapDialog")[0].style.position = "fixed";
	$("#FapDialog")[0].style.left = "200px";
	$("#FapDialog")[0].style.top = "50px";
	$("#FapDialog")[0].style.zIndex = "80000";
	$("#ToggleAutoAdvance")[0].style.zIndex = "81000";
	$("#ToggleAutoAdvance")[0].style.cursor = "pointer";
	$("#ToggleFG")[0].style.cursor = "pointer";
	$("#ToggleAH")[0].style.cursor = "pointer";
	$("#ToggleVG")[0].style.cursor = "pointer";
	$("#ToggleDenial")[0].style.cursor = "pointer";
	$("#ToggleDildo")[0].style.cursor = "pointer";
	$("#EdgedButton")[0].style.cursor = "pointer";
    $("#dropdown")[0].style.cursor = "pointer";
  
	
	
}

function reassignEventListeners() {
  
  $(document).keypress(function (e) {
		// if t pressed remake the dialog
		if (e.which == 116 || e.keyCode == 116) {
      randTime = 1;
		}
  });
    
  $("#dropdown")[0].addEventListener("click", function (e) {
		if (buttonsHidden) {
        $("#dropdown")[0].innerHTML = "▼ Hide";
      	$("#ToggleAutoAdvance")[0].style.display = "block";
        $("#ToggleFG")[0].style.display = "block";
        $("#ToggleAH")[0].style.display = "block";
        $("#ToggleVG")[0].style.display = "block";
        $("#ToggleDenial")[0].style.display = "block";
        $("#ToggleDildo")[0].style.display = "block";
		buttonsHidden = false;
		} else {
        $("#dropdown")[0].innerHTML = "▲ Unhide";
        $("#ToggleAutoAdvance")[0].style.display = "none";
        $("#ToggleFG")[0].style.display = "none";
        $("#ToggleAH")[0].style.display = "none";
        $("#ToggleVG")[0].style.display = "none";
        $("#ToggleDenial")[0].style.display = "none";
        $("#ToggleDildo")[0].style.display = "none";
      	buttonsHidden = true;
		}
    }, false);

	$("#ToggleAutoAdvance")[0].addEventListener("click", function (e) {
		if (autoOverride) {
			alert('Automatic Page Cycling Re-enabled!');
			$("#ToggleAutoAdvance")[0].innerHTML = "Disable Auto-Advance";
			autoOverride = false;
		} else {
			alert('Automatic Page Cycling disabled!');
			$("#ToggleAutoAdvance")[0].innerHTML = "Enable Auto-Advance";
			autoOverride = true;
		}
    }, false);
    

    $("#ToggleFG")[0].addEventListener("click", function (e) {
		if (FGisON) {
            $("#ToggleFG")[0].innerHTML = "Enable Fap Gauntlet";
			clearInterval(remakeDialog.interval);
			o.frequency.value = 0;
			$("#VisualGuide")[0].style.animation = "play 0s infinite linear";
            $("#FapDialog")[0].style.display = "none";
            FGisON = false;
		} else {
			FGisON = true;
			$("#VisualGuide")[0].style.animation = "play " + (1 / currFPS) + "s infinite " + currCurve;
            $("#ToggleFG")[0].innerHTML = "Disable Fap Gauntlet";
			remakeDialog();
		}
    }, false);
    
    $("#ToggleVG")[0].addEventListener("click", function (e) {
		$ = unsafeWindow.jQuery;
		if (visualGuideMode) {
            $("#ToggleVG")[0].innerHTML = "Enable Visual Guide";
            $("#VisualGuide")[0].style.display = "none";
            visualGuideMode = false;
            $("#VisualGuide")[0].style.animation = "play 0s infinite linear";
		} else {
            $("#ToggleVG")[0].innerHTML = "Disable Visual Guide";
            $("#VisualGuide")[0].style.display = "block";
            visualGuideMode = true;
            $("#VisualGuide")[0].style.animation = "play " + (1 / currFPS) + "s infinite " + currCurve;
		}
	}, false);

	$("#ToggleDildo")[0].addEventListener("click", function (e) {
		// if (dildoMode) {
			// 	$("#ToggleDildo")[0].innerHTML = "Enable Dildo Mode";
			// 	dildoMode = false;
			// } else {
			// 	$("#ToggleDildo")[0].innerHTML = "Disable Dildo Mode";
			// 	dildoMode = true;
			// }
			randTime = 1;
	}, false);
	
	$("#ToggleAH")[0].addEventListener("click", function (e) {
		if (isPlaying) {
			$("#ToggleAH")[0].innerHTML = "Enable Audio Helper";
			o.frequency.value = 0;
			isPlaying = false;
		} else if (firstStart){
			$("#ToggleAH")[0].innerHTML = "Disable Audio Helper";
			o.start();
			firstStart = false;
			o.frequency.value = currFPS;
			isPlaying = true;
		} else {
			$("#ToggleAH")[0].innerHTML = "Disable Audio Helper";
			o.frequency.value = currFPS;
			isPlaying = true;
		}
    }, false);

	$("#ToggleDenial")[0].addEventListener("click", function (e) {
		if (denialMode) {
			$("#ToggleDenial")[0].innerHTML = "Enable Denial Mode";
			$("#EdgedButton")[0].innerHTML = "";
			denialMode = false;
		} else {
			$("#ToggleDenial")[0].innerHTML = "Disable Denial Mode";
			$("#EdgedButton")[0].innerHTML = "I Edged!";
			denialMode = true;
		}
	}, false);

	$("#EdgedButton")[0].addEventListener("click", function (e) {
		if (denialMode) {		
			handsOffMode = true;

			$ = unsafeWindow.jQuery;

			$("#VisualGuide")[0].style.animation = "play 0s infinite linear";

			//change image
			var $ = unsafeWindow.jQuery;

			window.top.postMessage({
				action: 'next',
				cr: $.cookie().cr
			}, window.top.location.protocol + window.top.location.host);
			setTimeout(function () {
				currViewObj = unsafeWindow.AppState.viewing;
			}, 1000);

			o.frequency.value = 0;
			randTime = 45;
			i = 0;
		}
    
    
    
	}, false);
}

$(window).bind('hashchange', function() {
     reassignEventListeners();
});

setTimeout(function () { // thanks for not having a sleep function js //update: using GM's built in wait until document loaded @thing breaks jquery on the site, weird

	redrawOptions();
  reassignEventListeners();
	
}, 2000);