storyjs.tw2 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. ::StoryJS [script]
  2. //install favicon
  3. ;(function () {
  4. var favicon = document.createElement("link");
  5. favicon.rel = "icon";
  6. favicon.type = "image/png";
  7. favicon.href = Story.get('bikini_favicon').text;
  8. document.head.appendChild(favicon);
  9. }());
  10. /*! <<cyclinglink>> macro for SugarCube 2.x */ ! function() {
  11. "use strict";
  12. if ("undefined" == typeof version || "undefined" == typeof version.title || "SugarCube" !== version.title || "undefined" == typeof version.major || version.major < 2) throw new Error("<<cyclinglink>> macro requires SugarCube 2.0 or greater, aborting load");
  13. version.extensions.cyclinglinkMacro = {
  14. major: 3,
  15. minor: 3,
  16. revision: 2
  17. }, macros.cyclinglink = {
  18. handler: function(a, b, c) {
  19. function toggleText(w) {
  20. w.classList.remove("cyclingLinkInit"), w.classList.toggle(rl + "Enabled"), w.classList.toggle(rl + "Disabled"), w.style.display = "none" === w.style.display ? "inline" : "none"
  21. }
  22. var rl = "cyclingLink";
  23. switch (c[c.length - 1]) {
  24. case "end":
  25. var end = !0;
  26. c.pop();
  27. break;
  28. case "out":
  29. var out = !0;
  30. c.pop()
  31. }
  32. var v = null;
  33. c.length && "$" === c[0][0] && (v = c[0].slice(1), c.shift());
  34. var h = State.variables;
  35. if (!out || !v || "" !== h[v]) {
  36. var l = insertElement(a, "a");
  37. l.className = "link-internal cyclingLink", l.setAttribute("data-cycle", 0);
  38. for (var i = 0; i < c.length; i++) {
  39. var on = i === (v ? Math.max(c.indexOf(h[v]), 0) : 0),
  40. d = insertElement(null, "span", null, "cyclingLinkInit cyclingLink" + (on ? "En" : "Dis") + "abled");
  41. on ? (v && (h[v] = c[i]), l.setAttribute("data-cycle", i)) : d.style.display = "none", insertText(d, c[i]), on && end && i === c.length - 1 ? l.parentNode.replaceChild(d, l) : l.appendChild(d)
  42. }
  43. jQuery(l).ariaClick(function() {
  44. var t = this.childNodes,
  45. u = this.getAttribute("data-cycle") - 0,
  46. m = t.length;
  47. if (toggleText(t[u]), u += 1, out && u === m ? v && (h[v] = "") : (u %= m, v && (h[v] = c[u])), (end || out) && u === m - (end ? 1 : 0)) {
  48. if (!end) return void this.parentNode.removeChild(this);
  49. var n = this.removeChild(t[u]);
  50. return n.className = rl + "End", n.style.display = "inline", void this.parentNode.replaceChild(n, this)
  51. }
  52. toggleText(t[u]), this.setAttribute("data-cycle", u)
  53. })
  54. }
  55. }
  56. }
  57. }();
  58. /*! <<cyclinglinka>> macro for SugarCube 2.x */ ! function() {
  59. "use strict";
  60. if ("undefined" == typeof version || "undefined" == typeof version.title || "SugarCube" !== version.title || "undefined" == typeof version.major || version.major < 2) throw new Error("<<cyclinglink>> macro requires SugarCube 2.0 or greater, aborting load");
  61. version.extensions.cyclinglinkMacro = {
  62. major: 3,
  63. minor: 3,
  64. revision: 2
  65. }, macros.cyclinglinka = {
  66. handler: function(a, b, c) {
  67. function toggleText(w) {
  68. w.classList.remove("cyclingLinkInit"), w.classList.toggle(rl + "Enabled"), w.classList.toggle(rl + "Disabled"), w.style.display = "none" === w.style.display ? "inline" : "none"
  69. }
  70. var rl = "cyclingLink";
  71. switch (c[c.length - 1]) {
  72. case "end":
  73. var end = !0;
  74. c.pop();
  75. break;
  76. case "out":
  77. var out = !0;
  78. c.pop()
  79. }
  80. var v = null;
  81. c.length && "$" === c[0][0] && (v = c[0].slice(1), c.shift());
  82. c = c[0]
  83. var h = State.variables;
  84. if (!out || !v || "" !== h[v]) {
  85. var l = insertElement(a, "a");
  86. l.className = "link-internal cyclingLink", l.setAttribute("data-cycle", 0);
  87. for (var i = 0; i < c.length; i++) {
  88. var on = i === (v ? Math.max(c.indexOf(h[v]), 0) : 0),
  89. d = insertElement(null, "span", null, "cyclingLinkInit cyclingLink" + (on ? "En" : "Dis") + "abled");
  90. on ? (v && (h[v] = c[i]), l.setAttribute("data-cycle", i)) : d.style.display = "none", insertText(d, c[i]), on && end && i === c.length - 1 ? l.parentNode.replaceChild(d, l) : l.appendChild(d)
  91. }
  92. jQuery(l).ariaClick(function() {
  93. var t = this.childNodes,
  94. u = this.getAttribute("data-cycle") - 0,
  95. m = t.length;
  96. if (toggleText(t[u]), u += 1, out && u === m ? v && (h[v] = "") : (u %= m, v && (h[v] = c[u])), (end || out) && u === m - (end ? 1 : 0)) {
  97. if (!end) return void this.parentNode.removeChild(this);
  98. var n = this.removeChild(t[u]);
  99. return n.className = rl + "End", n.style.display = "inline", void this.parentNode.replaceChild(n, this)
  100. }
  101. toggleText(t[u]), this.setAttribute("data-cycle", u)
  102. })
  103. }
  104. }
  105. }
  106. }();
  107. /*! <<cyclinglinkd>> macro for SugarCube 2.x */ ! function() {
  108. "use strict";
  109. if ("undefined" == typeof version || "undefined" == typeof version.title || "SugarCube" !== version.title || "undefined" == typeof version.major || version.major < 2) throw new Error("<<cyclinglink>> macro requires SugarCube 2.0 or greater, aborting load");
  110. version.extensions.cyclinglinkMacro = {
  111. major: 3,
  112. minor: 3,
  113. revision: 2
  114. }, macros.cyclinglinkd = {
  115. handler: function(a, b, c) {
  116. function toggleText(w) {
  117. w.classList.remove("cyclingLinkInit"), w.classList.toggle(rl + "Enabled"), w.classList.toggle(rl + "Disabled"), w.style.display = "none" === w.style.display ? "inline" : "none"
  118. }
  119. var rl = "cyclingLink";
  120. switch (c[c.length - 1]) {
  121. case "end":
  122. var end = !0;
  123. c.pop();
  124. break;
  125. case "out":
  126. var out = !0;
  127. c.pop()
  128. }
  129. var v = null;
  130. c.length && "$" === c[0][0] && (v = c[0].slice(1), c.shift());
  131. var ks = Object.keys(c[0]);
  132. c = Object.values(c[0])
  133. var h = State.variables;
  134. if (!out || !v || "" !== h[v]) {
  135. var l = insertElement(a, "a");
  136. l.className = "link-internal cyclingLink", l.setAttribute("data-cycle", 0);
  137. for (var i = 0; i < c.length; i++) {
  138. var on = i === (v ? Math.max(ks.indexOf(h[v]), 0) : 0),
  139. d = insertElement(null, "span", null, "cyclingLinkInit cyclingLink" + (on ? "En" : "Dis") + "abled");
  140. on ? (v && (h[v] = ks[i]), l.setAttribute("data-cycle", i)) : d.style.display = "none", insertText(d, c[i]), on && end && i === c.length - 1 ? l.parentNode.replaceChild(d, l) : l.appendChild(d)
  141. }
  142. jQuery(l).ariaClick(function() {
  143. var t = this.childNodes,
  144. u = this.getAttribute("data-cycle") - 0,
  145. m = t.length;
  146. if (toggleText(t[u]), u += 1, out && u === m ? v && (h[v] = "") : (u %= m, v && (h[v] = ks[u])), (end || out) && u === m - (end ? 1 : 0)) {
  147. if (!end) return void this.parentNode.removeChild(this);
  148. var n = this.removeChild(t[u]);
  149. return n.className = rl + "End", n.style.display = "inline", void this.parentNode.replaceChild(n, this)
  150. }
  151. toggleText(t[u]), this.setAttribute("data-cycle", u)
  152. })
  153. }
  154. }
  155. }
  156. }();
  157. /* from http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html */
  158. window.myutils = {};
  159. window.myutils.isEqual = function isEqual(a, b) {
  160. // Create arrays of property names
  161. var aProps = Object.getOwnPropertyNames(a);
  162. var bProps = Object.getOwnPropertyNames(b);
  163. // If number of properties is different,
  164. // objects are not equivalent
  165. if (aProps.length != bProps.length) {
  166. return false;
  167. }
  168. for (var i = 0; i < aProps.length; i++) {
  169. var propName = aProps[i];
  170. // If values of same property are not equal,
  171. // objects are not equivalent
  172. if (typeof a[propName] === 'object'){
  173. if (!window.myutils.isEqual(a[propName], b[propName])){
  174. return false;
  175. }
  176. }else if(a[propName] !== b[propName]) {
  177. return false;
  178. }
  179. }
  180. // If we made it this far, objects
  181. // are considered equivalent
  182. return true;
  183. }
  184. /*! <<bugreport>> macro for SugarCube 2.x */
  185. !function(){"use strict";if("undefined"==typeof version||"undefined"==typeof version.title||"SugarCube"!==version.title||"undefined"==typeof version.major||version.major<2)throw new Error("<<bugreport>> macro requires SugarCube 2.0 or greater, aborting load");Macro.add("bugreport",{handler:function(){function serializeVariables(varObj,diffObj,doSort){function renderDiff(diff,orig){for(var keys=Object.keys(diff||{}),render=orig?clone(orig):{},i=0,klen=keys.length;klen>i;i++){var p=keys[i],diffP=diff[p];if(diffP===Util.DiffOp.Delete)delete render[p];else if(Array.isArray(diffP))switch(diffP[0]){case Util.DiffOp.SpliceArray:try{render.splice(diffP[1],1+(diffP[2]-diffP[1]))}catch(e){}break;case Util.DiffOp.Copy:render[p]=clone(diffP[1]);break;case Util.DiffOp.CopyDate:render[p]=new Date(diffP[1])}else{var recurse=renderDiff(diffP,render[p]);0!==Object.keys(recurse).length&&(render[p]=recurse)}}return render}var varList=[],diff=renderDiff(Util.diff(varObj,diffObj));for(var p in diff){var sName="$"+(-1===p.search(/[^\w]/)?p:'"'+p+'"');varList.push(sName+"="+JSON.stringify(diff[p]))}return doSort&&("function"==typeof doSort?varList.sort(doSort):varList.sort()),0!==varList.length?varList.join(", "):""}var srcMatch,passages,varsPre,varsPost,dialog,dataEl,info=null!=this.args[0]&&Story.has(this.args[0])?Story.get(this.args[0]):null,last=State.length-1,source=unescape(window.location);null!==(srcMatch=/\/([^\/]+)$/.exec(source))&&(source=srcMatch[1]),passages=[];for(var i=0;last>=i;i++)passages.push('"'+State.index(i).title+'"');passages=passages.join(", "),varsPre=serializeVariables(State.index(0).variables,State.index(last).variables),varsPost=serializeVariables(State.index(last).variables,State.variables),dialog=UI.setup("Bug Report","bugreport"),dialog.innerHTML=(null!==info?'<div id="bugreport-info"></div>':"")+'<div><b>Bug report:</b> <a id="bugreport-data-select" class="link-internal macro-bugreport">[Select]</a></div><code id="bugreport-data" tabindex="0"></code>'+(/applewebkit|chrome/.test(Browser.userAgent)?"":'<div class="scroll-pad">&nbsp;</div>'),dataEl=dialog.querySelector("#bugreport-data"),null!==info&&new Wikifier(dialog.querySelector("#bugreport-info"),info.processText()),addAccessibleClickHandler("#bugreport-data-select",function(self){return function(){jQuery(dataEl).focus(),self.selectData(dataEl)}}(this.self)),insertText(dataEl,"[spoiler][code]"),insertElement(dataEl,"br"),insertText(dataEl,"SOURCE: "+source),insertElement(dataEl,"br"),insertElement(dataEl,"br"),insertText(dataEl,"PASSAGES:"),insertElement(dataEl,"br"),insertText(dataEl,passages),insertElement(dataEl,"br"),insertElement(dataEl,"br"),insertText(dataEl,"VARIABLES (PRE-EXECUTION):"),insertElement(dataEl,"br"),varsPre&&(insertText(dataEl,varsPre),insertElement(dataEl,"br")),insertElement(dataEl,"br"),insertText(dataEl,"VARIABLES (POST-EXECUTION):"),insertElement(dataEl,"br"),varsPost&&(insertText(dataEl,varsPost),insertElement(dataEl,"br")),insertText(dataEl,"[/code][/spoiler]"),UI.open()},selectData:function(e){if(window.getSelection){var s=window.getSelection();if(s.setBaseAndExtent)s.setBaseAndExtent(e,0,e,e.innerText.length-1);else{window.opera&&"<br>"===e.innerHTML.substring(e.innerHTML.length-4)&&(e.innerHTML+="&nbsp;");var r=document.createRange();r.selectNodeContents(e),s.removeAllRanges(),s.addRange(r)}}else if(document.getSelection){var s=document.getSelection(),r=document.createRange();r.selectNodeContents(e),s.removeAllRanges(),s.addRange(r)}else if(document.selection){var r=document.body.createTextRange();r.moveToElementText(e),r.select()}}})}();
  186. /*! <<checkvars>> macro for SugarCube 2.x */
  187. !function(){"use strict";if("undefined"==typeof version||"undefined"==typeof version.title||"SugarCube"!==version.title||"undefined"==typeof version.major||version.major<2)throw new Error("<<checkvars>> macro requires SugarCube 2.0 or greater, aborting load");Macro.add("checkvars",{handler:function(){function toString(value,indent){var baseType=typeof value;switch(baseType){case"number":return isNaN(value)?"NaN":isFinite(value)?String(value):"Infinity";case"string":return JSON.stringify(value);case"function":return"(function)";default:if("object"!==baseType||null==value)return String(value);var objType=Object.prototype.toString.call(value);if("[object Date]"===objType)return'(object: Date, value: "'+value.toISOString()+'")';if("[object RegExp]"===objType)return"(object: RegExp, value: "+value.toString()+")";var opener,closer,result=[],indentText="  ";return indent||(indent=""),("[object Set]"===objType||value instanceof Set)&&(value=Array.from(value)),Array.isArray(value)?(opener="[\n",closer="\n"+indent+"]",value.forEach(function(p,i){result.push(indent+indentText+i+" ⇒ "+toString(value[i],indent+indentText))}),Object.keys(value).forEach(function(p){/^\d+$/.test(p)||result.push(indent+indentText+toString(p)+" ⇒ "+toString(value[p],indent+indentText))})):"[object Map]"===objType||value instanceof Map?(opener="{\n",closer="\n"+indent+"}",Array.from(value).map(function(kv){result.push(indent+indentText+toString(kv[0],indent+indentText)+" ⇒ "+toString(kv[1],indent+indentText))})):(opener="{\n",closer="\n"+indent+"}",Object.keys(value).forEach(function(p){result.push(indent+indentText+toString(p)+" ⇒ "+toString(value[p],indent+indentText))})),opener+result.join(",\n")+closer}}var dialog,sv=State.variables,names=Object.keys(sv);if(dialog=UI.setup("Story $variables","checkvars"),0===names.length)return dialog.innerHTML="<h1>Story $variables (<code>State.variables</code>):</h1><p><em>No $variables currently set…</em></p>",void UI.open();dialog.innerHTML="<h1>Story $variables (<code>State.variables</code>):</h1><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody></tbody></table>"+(/applewebkit|chrome/.test(Browser.userAgent)?"":'<div class="scroll-pad">&nbsp;</div>');var tbody=dialog.querySelector("tbody");names.sort(function(a,b){return Util.isNumeric(a)&&Util.isNumeric(b)?Number(a)-Number(b):a.localeCompare(b)});for(var i=0;i<names.length;i++){var tr=document.createElement("tr"),tdName=document.createElement("td"),tdValue=document.createElement("td");tdName.textContent="$"+names[i],tdValue.textContent=toString(sv[names[i]]),tr.appendChild(tdName),tr.appendChild(tdValue),tbody.appendChild(tr)}UI.open()}})}();
  188. ::StoryInit <1304,233>
  189. <<set
  190. //Clothing
  191. $current_top = 't-shirt'
  192. $current_bottom = 'jeans'
  193. $current_genitals = 'penis'
  194. $current_bust = 'AA'
  195. //rewards/promises
  196. $reward = "nothing"
  197. //karmic actions
  198. $times_spied = 0
  199. $lies = 0
  200. $girls_know_you_spied = false
  201. //how much people like you, 0 for neutral.
  202. $nat_disposition = 0
  203. $jess_disposition = 0
  204. $sally_disposition = 0
  205. //long-term tracking
  206. $keep_the_bikini = 'no agreement' //or new, or destroy
  207. $bottom_style = "vagina" //or girlcock, or ken doll
  208. $nat_offlimits = false
  209. $heather_bikini_options = 'custom_bikini'
  210. $tournament_bikini = 'custom_bikini';
  211. $heather_bikini_options = 'custom'
  212. $eyes_closed = false
  213. $nat_present = false
  214. $mood = ''
  215. $boy_name = '#ERROR haven\'t set $boy_name yet'
  216. $girl_name = 'Amanda'
  217. $girl_names = [
  218. 'Nikki',
  219. 'Bailey',
  220. 'Serena',
  221. 'Ashley',
  222. 'Brittany',
  223. 'Becca',
  224. 'Sabrina',
  225. 'Karla',
  226. 'Maria',
  227. 'Margot',
  228. 'Vanessa',
  229. 'Kate',
  230. 'Amanda',
  231. ]
  232. >>
  233. ::StoryCaption <1445,226>
  234. <a href="https://www.tfgamessite.com/index.php?module=viewgame&id=1291">Rate and Discuss this game on IGDB</a>
  235. <a data-passage="License"><<=Story.get('cc0_image').text>></a>
  236. Disposition:
  237. Jessica (your sister): $jess_disposition
  238. Natalie: $nat_disposition
  239. Sally: $sally_disposition
  240. Karmic Actions
  241. times_spied=$times_spied
  242. times_lied=$lies
  243. ::StoryMenu <1593,233>
  244. [[Knowledge->knowledge]]
  245. <<click "Create Bug Report">><<bugreport>><</click>>
  246. <<click "Checkvars (for debugging)">><<checkvars>><</click>>
  247. ::PassageHeader [nobr] <1166,232>
  248. <<set
  249. _old_state = State.peek(1);
  250. _old_vars = _old_state && _old_state.variables;
  251. _girls = ['nat', 'jess', 'sally'];
  252. _clothing_slots = ['top', 'bottom']
  253. >>
  254. <<for _i to 0; _i lt _girls.length; _i++>>
  255. <<set
  256. _g = _girls[_i];
  257. _gd = _g + '_disposition';
  258. _old_d = _old_vars && _old_vars[_gd];
  259. _cur_d = variables()[_gd];
  260. >>
  261. <<if _old_d gt _cur_d >>
  262. @@.flashed-message; <<=_g.toUpperFirst()>> didn't like that.@@
  263. <<elseif _old_d lt _cur_d >>
  264. @@.flashed-message; <<=_g.toUpperFirst()>> appreciates that.@@
  265. <</if>>
  266. <</for>>
  267. <<silently>>The following will go away.<</silently>>
  268. <<if _old_vars && _old_vars['current_top'] != $current_top>>
  269. <<if $current_top == 'topless'>>
  270. @@.flashed-message; You are now topless.@@
  271. <<else>>
  272. @@.flashed-message; You are now wearing: $current_top.@@
  273. <</if>>
  274. <</if>>
  275. <<if _old_vars && _old_vars['current_bottom'] != $current_bottom>>
  276. <<if $current_bottom != 'naked'>>
  277. @@.flashed-message;You are now naked
  278. <<else>>
  279. @@.flashed-message;You are now wearing $current_bottom.@@
  280. <</if>>
  281. <</if>>
  282. <<if _old_vars && _old_vars['current_genitals'] != $current_genitals>>
  283. @@.flashed-message;You now have a $current_genitals.@@
  284. <</if>>
  285. <<if _old_vars && _old_vars['current_bust'] != $current_bust>>
  286. @@.flashed-message;You now have $current_bust cup breasts.@@
  287. <</if>>
  288. ::knowledge [nobr] <1590,406>
  289. <<set
  290. _knowledge = {
  291. "bikini-magical": "the bikini is magical",
  292. "sally-enchanted-bikini": "Sally enchanted the bikini(s)",
  293. "bikini-busty": "the bikini top makes you busty",
  294. "bikini-clones": "each bikini top clones a particular person",
  295. "tournament-beach-volleyball": "the \"tournament\" is a beach volleyball tournament",
  296. "tournament-busty": "the tournament has a minimum bust size, so your sister and her friends are going to be wearing magic bikinis too",
  297. "what-bottoms-do": "the bikini bottoms do on bottom much like the top: they\'ll turn you into a woman completely",
  298. "bikini-heather": "your bikini turns you into Jessica\'s friend Heather",
  299. "bikini-feminizes": "the bikini feminizes it\'s wearer",
  300. "tournament-girls-only": "the beach volleyball tournament is for girl\'s only"
  301. };
  302. >>
  303. <<set _k_keys = Object.keys(_knowledge) >>
  304. <<for _i to 0; _i lt _k_keys.length; _i++>>
  305. <<set
  306. _k = 'know-' + _k_keys[_i];
  307. _kd = _knowledge[_k_keys[_i]];
  308. >>
  309. <<if visitedTags(_k)>>
  310. You know that _kd.<br>
  311. <</if>>
  312. <</for>>
  313. <<back>>