diff --git a/.gitignore b/.gitignore index dfacdbb2c958b4a10bb6a18b65a735c72f851fb2..a8e5e95aaf38882c899baf4745d843619fbed5fe 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,9 @@ yarn.lock # WebStorm .idea +# Gulp +build/ + # backup *.bak *.gho diff --git a/Changelog.txt b/Changelog.txt index 5329be35e9e64017f102ba2c7eb6fa53e57800a4..9b37f150b7c4d2dc104d1bc07bb991a5a69209e5 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -2,6 +2,18 @@ Pregmod 0.10.7.1-3.8.x + 5 + -added the toy shop (custom sex toy printing) + -added extreme implant breast shape "spherical" + -added associated nipple shape "flat" (preventable via piercings and lactation) + -tweaked NCS hormone balance effects + -shoes to data + -buttplugs to data + -dildos to data + -more lingering .tw files to DOM + -SC tweaks to facilitate complete conversion to JS from tweeScript + -fixes + 12/22/2020 4 diff --git a/Makefile b/Makefile index e1bee417127f5b00a480ce5923ec21aa3d9b6423..45577632899afb6f539f1a14520626fcd896429a 100644 --- a/Makefile +++ b/Makefile @@ -36,9 +36,13 @@ bin/%.html: bin/tmp bin/fc.js: bin/ devTools/concatFiles.sh js/ '*.js' $@ -bin/tmp: bin/fc.js injectGitCommitHash - $(TWEEGO) --module=bin/fc.js --head devTools/head.html src/ > $@ +bin/fc.css: bin/ + devTools/concatFiles.sh css/ '*.css' $@ + +bin/tmp: bin/fc.js bin/fc.css injectGitCommitHash + $(TWEEGO) --module=bin/fc.js --module=bin/fc.css --head resources/raster/favicon/arcologyVector.html src/ > $@ rm -f bin/fc.js + rm -f bin/fc.css injectGitCommitHash: printf "App.Version.commitHash = '%s';\n" $(COMMIT) > src/002-config/fc-version.js.commitHash.js diff --git a/build.config.json b/build.config.json index 53df91f839f39eaa1e6a83b4fc521639ec8f7d10..29c318251814ba9a463de44b1909ddf65c75d40a 100644 --- a/build.config.json +++ b/build.config.json @@ -8,7 +8,8 @@ "gitVersionFile": "src/002-config/fc-version.js.commitHash.js", "sources": { "module": { - "js": ["js/**/*.js"] + "js": ["js/**/*.js"], + "css": ["css/**/*.css"] }, "story": { "css": ["src/**/*.css"], @@ -19,7 +20,7 @@ "src/art/vector_revamp/layers" ] }, - "head": "devTools/head.html" + "head": "resources/raster/favicon/arcologyVector.html" }, "options": { "css": { diff --git a/compile.bat b/compile.bat index ac1bb770ee1a70e6a490379eecd9b98d1b7111da..ec8bda25248803f824719dd59c073a36896d52d6 100644 --- a/compile.bat +++ b/compile.bat @@ -28,13 +28,15 @@ if %GITFOUND% == yes ( if not exist "bin\resources" mkdir bin\resources CALL devTools/concatFiles.bat js\ "*.js" bin\fc.js +CALL devTools/concatFiles.bat css\ "*.css" bin\fc.css :: Run the appropriate compiler for the user's CPU architecture. if %PROCESSOR_ARCHITECTURE% == AMD64 ( - CALL "%~dp0devTools\tweeGo\tweego_win64.exe" -o "%~dp0bin/FC_pregmod.html" --module=bin/fc.js --head devTools/head.html "%~dp0src" + CALL "%~dp0devTools\tweeGo\tweego_win64.exe" -o "%~dp0bin/FC_pregmod.html" --module=bin/fc.js --module=bin/fc.css --head resources/raster/favicon/arcologyVector.html "%~dp0src" ) else ( - CALL "%~dp0devTools\tweeGo\tweego_win86.exe" -o "%~dp0bin/FC_pregmod.html" --module=bin/fc.js --head devTools/head.html "%~dp0src" + CALL "%~dp0devTools\tweeGo\tweego_win86.exe" -o "%~dp0bin/FC_pregmod.html" --module=bin/fc.js --module=bin/fc.css --head resources/raster/favicon/arcologyVector.html "%~dp0src" ) DEL bin\fc.js +DEL bin\fc.css IF EXIST "%~dp0src\002-config\fc-version.js.commitHash.js" DEL "%~dp0src\002-config\fc-version.js.commitHash.js" popd diff --git a/compile.sh b/compile.sh index 1f2e8cc85866d5d8404a616314fdfd430ad36fbe..5c6ab810026d650dd61a1a97ce65c845ab272dfd 100755 --- a/compile.sh +++ b/compile.sh @@ -75,8 +75,10 @@ function compile() { fi devTools/concatFiles.sh js/ '*.js' bin/fc.js - $TWEEGO_EXE -o $file --module=bin/fc.js --head devTools/head.html src/ || build_failed="true" + devTools/concatFiles.sh css/ '*.css' bin/fc.css + $TWEEGO_EXE -o $file --module=bin/fc.js --module=bin/fc.css --head resources/raster/favicon/arcologyVector.html src/ || build_failed="true" rm -f bin/fc.js + rm -f bin/fc.css if [ "$build_failed" = "true" ]; then echoError "Build failed." exit 1 @@ -136,7 +138,7 @@ if [[ "$dry" ]]; then echoMessage "Dry run finished." else compile - echoMessage "Compilation finished." + echoMessage "Compilation finished at $(date +%T)." fi # compile themes @@ -149,5 +151,5 @@ if [[ "$themes" ]]; then fi done ) - echoMessage "Themes compiled" + echoMessage "Themes compiled at $(date +%T)" fi diff --git a/src/001-lib/Jquery/CSS.tw b/css/001-lib/Jquery.css similarity index 99% rename from src/001-lib/Jquery/CSS.tw rename to css/001-lib/Jquery.css index 47b288174bb6cd331925d8c5804890485fda83c7..5345c366310a8f252eb1fa4fb0988b62d51f1419 100644 --- a/src/001-lib/Jquery/CSS.tw +++ b/css/001-lib/Jquery.css @@ -1,8 +1,7 @@ -:: JQuery UI stylesheet [stylesheet] /*! jQuery UI - v1.12.1 - 2017-05-29 * http://jqueryui.com * Includes: draggable.css, core.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css * To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=ui-darkness&cornerRadiusShadow=8px&offsetLeftShadow=-7px&offsetTopShadow=-7px&thicknessShadow=7px&opacityShadow=60&bgImgOpacityShadow=30&bgTextureShadow=flat&bgColorShadow=cccccc&opacityOverlay=80&bgImgOpacityOverlay=50&bgTextureOverlay=flat&bgColorOverlay=5c5c5c&iconColorError=a83300&fcError=111111&borderColorError=ffb73d&bgImgOpacityError=40&bgTextureError=glass&bgColorError=ffc73d&iconColorHighlight=4b8e0b&fcHighlight=2e7db2&borderColorHighlight=cccccc&bgImgOpacityHighlight=80&bgTextureHighlight=highlight_soft&bgColorHighlight=eeeeee&iconColorActive=222222&fcActive=ffffff&borderColorActive=ffaf0f&bgImgOpacityActive=30&bgTextureActive=inset_soft&bgColorActive=f58400&iconColorHover=ffffff&fcHover=ffffff&borderColorHover=59b4d4&bgImgOpacityHover=40&bgTextureHover=glass&bgColorHover=0078a3&iconColorDefault=cccccc&fcDefault=eeeeee&borderColorDefault=666666&bgImgOpacityDefault=20&bgTextureDefault=glass&bgColorDefault=555555&iconColorContent=cccccc&fcContent=ffffff&borderColorContent=666666&bgImgOpacityContent=25&bgTextureContent=inset_soft&bgColorContent=000000&iconColorHeader=ffffff&fcHeader=ffffff&borderColorHeader=333333&bgImgOpacityHeader=25&bgTextureHeader=gloss_wave&bgColorHeader=333333&cornerRadius=6px&fsDefault=1.1em&fwDefault=bold&ffDefault=Segoe%20UI%2CArial%2Csans-serif * Copyright jQuery Foundation and other contributors; Licensed MIT */ -.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Segoe UI,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Segoe UI,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #666}.ui-widget-content{border:1px solid #666;background:#000 url("images/ui-bg_inset-soft_25_000000_1x100.png") 50% bottom repeat-x;color:#fff}.ui-widget-content a{color:#fff}.ui-widget-header{border:1px solid #333;background:#333 url("images/ui-bg_gloss-wave_25_333333_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #666;background:#555 url("images/ui-bg_glass_20_555555_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eee}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#eee;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #59b4d4;background:#0078a3 url("images/ui-bg_glass_40_0078a3_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#fff;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #ffaf0f;background:#f58400 url("images/ui-bg_inset-soft_30_f58400_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#ffaf0f;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #ccc;background:#eee url("images/ui-bg_highlight-soft_80_eeeeee_1x100.png") 50% top repeat-x;color:#2e7db2}.ui-state-checked{border:1px solid #ccc;background:#eee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#2e7db2}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #ffb73d;background:#ffc73d url("images/ui-bg_glass_40_ffc73d_1x400.png") 50% 50% repeat-x;color:#111}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#111}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#111}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_4b8e0b_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_a83300_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:6px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:6px}.ui-widget-overlay{background:#5c5c5c;opacity:.8;filter:Alpha(Opacity=80)}.ui-widget-shadow{-webkit-box-shadow:-7px -7px 7px #ccc;box-shadow:-7px -7px 7px #ccc} \ No newline at end of file +.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Segoe UI,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Segoe UI,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #666}.ui-widget-content{border:1px solid #666;background:#000 url("images/ui-bg_inset-soft_25_000000_1x100.png") 50% bottom repeat-x;color:#fff}.ui-widget-content a{color:#fff}.ui-widget-header{border:1px solid #333;background:#333 url("images/ui-bg_gloss-wave_25_333333_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #666;background:#555 url("images/ui-bg_glass_20_555555_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eee}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#eee;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #59b4d4;background:#0078a3 url("images/ui-bg_glass_40_0078a3_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#fff;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #ffaf0f;background:#f58400 url("images/ui-bg_inset-soft_30_f58400_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#ffaf0f;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #ccc;background:#eee url("images/ui-bg_highlight-soft_80_eeeeee_1x100.png") 50% top repeat-x;color:#2e7db2}.ui-state-checked{border:1px solid #ccc;background:#eee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#2e7db2}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #ffb73d;background:#ffc73d url("images/ui-bg_glass_40_ffc73d_1x400.png") 50% 50% repeat-x;color:#111}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#111}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#111}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_4b8e0b_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_a83300_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_cccccc_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:6px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:6px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:6px}.ui-widget-overlay{background:#5c5c5c;opacity:.8;filter:Alpha(Opacity=80)}.ui-widget-shadow{-webkit-box-shadow:-7px -7px 7px #ccc;box-shadow:-7px -7px 7px #ccc} diff --git a/css/001-lib/macros.css b/css/001-lib/macros.css new file mode 100644 index 0000000000000000000000000000000000000000..39a2dd5778ec12fd4f0bb7b9e179053e5fbf61a8 --- /dev/null +++ b/css/001-lib/macros.css @@ -0,0 +1,2 @@ +/*! <<checkvars>> macro for SugarCube 2.x */ +#ui-dialog-body.checkvars{padding:1em}#ui-dialog-body.checkvars h1{font-size:1em;margin-top:0}#ui-dialog-body.checkvars table{border-collapse:collapse;border-spacing:0}#ui-dialog-body.checkvars thead tr{border-bottom:2px solid #444}#ui-dialog-body.checkvars tr:not(:first-child){border-top:1px solid #444}#ui-dialog-body.checkvars td,#ui-dialog-body.checkvars th{padding:.25em 1em}#ui-dialog-body.checkvars td:first-child,#ui-dialog-body.checkvars th:first-child{padding-left:.5em;border-right:1px solid #444}#ui-dialog-body.checkvars td:last-child,#ui-dialog-body.checkvars th:last-child{padding-right:.5em}#ui-dialog-body.checkvars th:first-child{text-align:center}#ui-dialog-body.checkvars td:first-child{font-weight:700;text-align:right}#ui-dialog-body.checkvars td{font-family:monospace,monospace;vertical-align:top;white-space:pre-wrap}#ui-dialog-body.checkvars .scroll-pad{margin:0;padding:0} diff --git a/src/002-config/colors.css b/css/002-variables/colors.css similarity index 100% rename from src/002-config/colors.css rename to css/002-variables/colors.css diff --git a/css/003-sugarcube-overwrite/general.css b/css/003-sugarcube-overwrite/general.css new file mode 100644 index 0000000000000000000000000000000000000000..08a03244235a115489a0718a3cdbd419b39bbcec --- /dev/null +++ b/css/003-sugarcube-overwrite/general.css @@ -0,0 +1,24 @@ +body { + overflow-x: hidden; +} + +/* clears SugarCube's default transition */ +.passage { + transition: none; + -webkit-transition: none; +} + +.passage-in { + opacity: 1 !important; +} + +#passages { + /* max-width: 54em */ + max-width: 100%; +} + +/* makes HR colorflip compatible */ +hr { + background:#ccc; + border:0; +} diff --git a/src/002-config/modSC.css b/css/003-sugarcube-overwrite/sidebar.css similarity index 75% rename from src/002-config/modSC.css rename to css/003-sugarcube-overwrite/sidebar.css index b09893b63ac65cc1c62b2bedf44ecd1bf831cbfd..a43d1b8df06cb7da002cf9538860637ae89bf423 100644 --- a/src/002-config/modSC.css +++ b/css/003-sugarcube-overwrite/sidebar.css @@ -7,11 +7,19 @@ height: calc(100% - 1.5em); margin: 1.5em 0; } + #ui-bar-body > :not(:first-child) { /* margin-top: 2em; */ margin-top: 1.5em; } + #story-author { /* margin-top: 2em; */ margin-top: 0; } + +/* make cheat text boxes fit in sidebar */ +#story-caption input { + min-width: 0; + width: calc(100% - 0.8em - 2px); +} diff --git a/src/003-assets/CSS/arcologyBuilding.css b/css/arcologyBuilding/arcologyBuilding.css similarity index 100% rename from src/003-assets/CSS/arcologyBuilding.css rename to css/arcologyBuilding/arcologyBuilding.css diff --git a/css/art/art.css b/css/art/art.css new file mode 100644 index 0000000000000000000000000000000000000000..2610af5ed5c82ca8c8a1a98820ad24740e1022f0 --- /dev/null +++ b/css/art/art.css @@ -0,0 +1,112 @@ +/* small trick to hide broken images */ +img { + text-indent: -10000px; +} + +.imageColumn { /* TODO: this is mostly a copy of imageRef to get its flex features working properly. They can probably be removed from imageRef at some point */ + display: flex; + flex-direction: column; + flex-wrap: wrap; + align-items: flex-start; + position: relative; + float: right; +} + +.imageRef { + display: flex; + flex-direction: column; + flex-wrap: wrap; + align-items: flex-start; + position: relative; + background-color: rgba(80, 80, 80, 0.5); + margin: 2px; +} + +.tinyImg { + height: 120px; + width: 120px; + float: left; +} + +.smlImg { + height: 150px; + width: 150px; + float: left; +} + +.smlImg > img, .smlImg > video { + height: auto; +} + +.medImg { + height: 300px; + width: 300px; + float: right; +} + +.medImg > img, .medImg > video { + height: auto; +} + +.lrgRender { + height: 531px; + width: 531px; + margin-right: -50px; + margin-left: -50px; + float: right; + z-index: -1; +} + +.lrgVector { + height: 600px; + width: 600px; + margin-right: -125px; + margin-left: -125px; + float: right; + z-index: -1; +} + +.lrgRender > div.mask { + width: 150px; + height: 100%; + background: linear-gradient(90deg, rgba(17, 17, 17, 1), rgba(17, 17, 17, 0.8) 60%, rgba(17, 17, 17, 0)); + z-index: 1; + /*position: absolute;*/ +} + +.lrgRender > img, .lrgRender > video { + margin-left: -150px; + height: 531px; + width: auto; +} + +.lrgVector > div.mask { + width: 150px; + height: 100%; + background: linear-gradient(90deg, rgba(17, 17, 17, 1), rgba(17, 17, 17, 0.8) 60%, rgba(17, 17, 17, 0)); + z-index: 1; +} + +.lrgVector > img, .lrgVector > video { + margin-left: -150px; + height: 600px; + width: auto; +} + +.lrgVector svg { + width: 336px; +} + +object { + object-fit: scale-down; + position: absolute; + top: 0; + left: 0; +} + +img.paperdoll { + position: absolute; + top: 0; + left: 0; + margin-left: 0; +} diff --git a/css/corporation/corporation.css b/css/corporation/corporation.css new file mode 100644 index 0000000000000000000000000000000000000000..2c6e95350204026e0da50b0bc8b4294b3af35426 --- /dev/null +++ b/css/corporation/corporation.css @@ -0,0 +1,39 @@ +.founding { + font-size: 0.8em; + margin-top: -0.8em; + margin-left: 0.5em; + font-style: italic; +} + +table.corporate { + border: 3px darkgreen double; + border-collapse: collapse; + min-width: 33%; +} + +table.corporate tbody tr:nth-child(even) { + background-color: rgb(0, 30, 0); +} + +table.corporate tbody tr:nth-child(odd) { + background-color: rgb(15, 40, 15); +} + +table.corporate td { + vertical-align: top; +} + +table.corporate tbody th, table.corporate thead th { + background-color: black; + font-weight: bold; +} + +.minor-note { + font-size: 0.75em; + font-style: italic; +} + +.majorText { + margin-top: 0.5em; + margin-bottom: 1.5em; +} diff --git a/css/css.md b/css/css.md new file mode 100644 index 0000000000000000000000000000000000000000..f259684518eda9eb52a1895036d44904fbfcc39c --- /dev/null +++ b/css/css.md @@ -0,0 +1,22 @@ +# CSS module + +This directory contains ALL style files for this project. + +## Structure + +Most of the structure should be self-explanatory, this is a list of the main rules when adding new styles + +* `general/`: Only Styles that can be used in many different places and are not part of a specific system may be added + here. + +* When adding styles that are only used in one place put them in a directory that matches the top directory of the + corresponding JS file in `src/` or `js/`. + +* There is no catch-all file, if there is no place where your style goes create one instead of mixing them together with + unrelated styles. This does mean there are many small files, but properly sorted and named this is preferable to one + large catch-all file. + +## Compiling + +During compiling all CSS files in this directory get combined and then added as a module, which means the styles are put +directly into <head> element of the final HTML file. diff --git a/src/pregmod/FCTV/FCTV.css b/css/endWeek/FCTV.css similarity index 79% rename from src/pregmod/FCTV/FCTV.css rename to css/endWeek/FCTV.css index f7a3b69f149ad68fc4437c2355e9f3c0d18bc199..8d7bdd5ac3342703136f3e88971cefb6200354d5 100644 --- a/src/pregmod/FCTV/FCTV.css +++ b/css/endWeek/FCTV.css @@ -1,13 +1,14 @@ -.FCTV { +.fctv { display: float; } + .fctv-remote { text-align: center; justify-items: center; display: grid; - float:left; - width:min-content; - padding-right:20px; + float: left; + width: min-content; + padding-right: 20px; } .fctv-remote-numbers { display: grid; @@ -17,4 +18,4 @@ } .fctv-remote-button { margin-top: 10px; -} \ No newline at end of file +} diff --git a/src/003-assets/CSS/endWeekAnim.css b/css/endWeek/endWeekAnim.css similarity index 100% rename from src/003-assets/CSS/endWeekAnim.css rename to css/endWeek/endWeekAnim.css diff --git a/css/endWeek/slavesReport.css b/css/endWeek/slavesReport.css new file mode 100644 index 0000000000000000000000000000000000000000..f07dbecbe1e82f6363fb316a8bff981287e33acf --- /dev/null +++ b/css/endWeek/slavesReport.css @@ -0,0 +1,4 @@ +div.slave-report { + margin-top: 1em; + margin-bottom: 1em; +} diff --git a/src/facilities/facilities.css b/css/facilities/facilities.css similarity index 100% rename from src/facilities/facilities.css rename to css/facilities/facilities.css diff --git a/src/facilities/farmyard/farmyard.css b/css/facilities/farmyard.css similarity index 100% rename from src/facilities/farmyard/farmyard.css rename to css/facilities/farmyard.css diff --git a/src/facilities/incubator/incubator.css b/css/facilities/incubator.css similarity index 100% rename from src/facilities/incubator/incubator.css rename to css/facilities/incubator.css diff --git a/src/facilities/nursery/nursery.css b/css/facilities/nursery.css similarity index 69% rename from src/facilities/nursery/nursery.css rename to css/facilities/nursery.css index f2276b59eeaa1d146949dd10b1c48286e0e3b609..b9de00814e2aac8a1eb9f28a38ea1169985b95d0 100644 --- a/src/facilities/nursery/nursery.css +++ b/css/facilities/nursery.css @@ -1,5 +1,3 @@ -/* FEEL FREE TO MOVE */ - .child-section { margin-top: 1em; margin-bottom: 1em; diff --git a/src/facilities/pit/pit.css b/css/facilities/pit.css similarity index 100% rename from src/facilities/pit/pit.css rename to css/facilities/pit.css diff --git a/src/facilities/statistics.css b/css/facilities/statistics.css similarity index 61% rename from src/facilities/statistics.css rename to css/facilities/statistics.css index 91320c60544b476fb4f354b35bdc4ce5e865ca77..092409605f4aa23e6ff477e4b9d2391283795252 100644 --- a/src/facilities/statistics.css +++ b/css/facilities/statistics.css @@ -1,46 +1,46 @@ -table.stats { +table.facility-stats { width: 100%; padding-left: 20px; padding-right: 20px; } -table.stats > tr.header { +table.facility-stats > tr.header { border-bottom: 2px solid white; } -table.stats > tr.total { +table.facility-stats > tr.total { border-top: 1px solid white; } -table.stats > tr > th.narrow { +table.facility-stats > tr > th.narrow { width: 10em; text-align: right; } -table.stats > tr > th.wide { +table.facility-stats > tr > th.wide { width: 20em; text-align: right; } -table.stats-slave { +table.facility-stats-slave { width: 100%; font-size: 90%; line-height: 110%; } -table.stats-slave > tr { +table.facility-stats-slave > tr { border-bottom: 1px solid #aaa; border-left: none; border-right: none; border-top: none } -table.stats-slave > tr > th.narrow { +table.facility-stats-slave > tr > th.narrow { width: 11em; text-align: right; } -table.stats-slave > tr > th.wide { +table.facility-stats-slave > tr > th.wide { width: 22em; text-align: right; } @@ -52,4 +52,4 @@ td.value { .decimalZero { opacity: 0.3; -} \ No newline at end of file +} diff --git a/src/facilities/wardrobe/wardrobeShopping.css b/css/facilities/wardrobe.css similarity index 100% rename from src/facilities/wardrobe/wardrobeShopping.css rename to css/facilities/wardrobe.css diff --git a/css/general/formatting.css b/css/general/formatting.css new file mode 100644 index 0000000000000000000000000000000000000000..b0a408d0c50b27bd40e337e754731380ccefb372 --- /dev/null +++ b/css/general/formatting.css @@ -0,0 +1,71 @@ +/* Styles that mainly affect how text looks, but not where it is */ + +/* setting at the beginning of a scene / subscene */ +.scene-intro { + font-style: italic; +} + +/* adds detail to an option: Do something. <span class="detail">Sentence that explains the effect/conditions */ +.detail { + font-style: italic; +} + +/* additional information not related to a specific option */ +.note { + font-style: italic; +} + +.icons { + font-family: 'tme-fa-icons'; +} + +.story-label, .regularParties, .underline { + text-decoration: underline; +} + +/* Note: Do not do a linebreak after span in HTML, because it will underline the automatic space it inserts: "Matilda_is a cow" */ +.slave-name { + color: pink; + font-weight: bold; + text-decoration: underline; + text-decoration-color: white; +} + +.name { + font-weight: bold; +} + +.custom-label { + color: yellow; + font-weight: bold; +} + +/* strong is deprecated, use bold instead */ +.major-link, .bold, .strong { + font-weight: bold; +} + +.clear-formatting { + color: white; + font-weight: normal; + font-style: normal; +} + +.major-warning { + font-weight: bold; + color: red; +} + +input:invalid { + border-color: #900; + background-color: rgba(255, 0, 0, 0.25); +} + +input:focus:invalid { + outline: none; +} + +input:out-of-range { + background-color: rgba(255, 0, 0, 0.25); + border: 2px solid #900; +} diff --git a/css/general/layout.css b/css/general/layout.css new file mode 100644 index 0000000000000000000000000000000000000000..6d5fa3a1b13e5d428190a773473115da02a90708 --- /dev/null +++ b/css/general/layout.css @@ -0,0 +1,43 @@ +/* Styles that mainly affect where text is, but not how it looks */ + +h1, h2, h3 { + margin-bottom: 0; + margin-top: 0.25em; +} + +h1 + p, h2 + p, h3 + p { + margin-top: 0; +} + +div.center, p.center { + margin-left: auto; + margin-right: auto; + text-align: center; +} + +div.flex-container { + display: flex; +} + +/* makes the first line indented */ +div.indent, p.indent { + text-indent: 2em; +} + +div.double-indent, p.double-indent { + text-indent: 4em; +} + +/* makes avery line indented */ +.choices, .choices { + margin-left: 2em; +} + +.double-choices, .double-choices { + margin-left: 4em; +} + +div.grid-2columns-auto { + display: grid; + grid-template-columns: max-content auto; +} diff --git a/css/general/textColors.css b/css/general/textColors.css new file mode 100644 index 0000000000000000000000000000000000000000..3b1292571e8b0bf5ccf11b7593e46e9c4440c4b6 --- /dev/null +++ b/css/general/textColors.css @@ -0,0 +1,201 @@ +/* Colors are made as css classes, to allow them to be changed for a light color scheme (for example). */ +/* a version is for this case: <span class="..."><a>text</a></span> */ + +/* link color */ +.link, .link a { + color: var(--link-color) +} + +.aquamarine, .aquamarine a, .skill, .skill a { + color: aquamarine +} + +.coral, .coral a, .fetish.loss, .fetish.loss a { + color: coral +} + +/* used for aphrodisiac & neighbor arcs */ +.cyan, .cyan a, .hotkey { + color: cyan +} + +.darkgoldenrod, .darkgoldenrod a, .trust.extremely-terrified, .trust.extremely-terrified a { + color: darkgoldenrod +} + +.darkred, .darkred a, .defiant.full, .defiant.full a { + color: darkred +} + +.darkviolet, .darkviolet a, .devotion.hateful, .devotion.hateful a { + color: darkviolet +} + +/* used for devotion once & agent */ +.deeppink, .deeppink a, .devotion.devoted, .devotion.devoted a { + color: deeppink +} + +.steelblue, .steelblue a { + color: steelblue +} + +.deepskyblue, .deepskyblue a, .intelligent, .intelligent a { + color: deepskyblue +} + +.dodgerblue, .dodgerblue a { + color: dodgerblue +} + +.blue, .blue a { + color: blue +} + +.gold, .gold a, .trust.dec, .trust.dec a, .trust.frightened, .trust.frightened a { + color: gold +} + +.goldenrod, .goldenrod a, .trust.terrified, .trust.terrified a { + color: goldenrod +} + +.gray, .gray a { + color: gray +} + +.green, .green a, .reputation.inc, .reputation.inc a, .improvement, .improvement a, .flaw.break, .flaw.break a, +.skill.inc, .skill.inc a, .fuckdoll, .fuckdoll a, .positive, .positive a, .health.inc, .health.inc a { + color: green +} + +.hotpink, .hotpink a, .devotion.inc, .devotion.inc a, .devotion.accept, .devotion.accept a { + color: hotpink +} + +.lawngreen, .lawngreen a { + color: lawngreen +} + +.lightblue, .lightblue a { + color: lightblue +} + +/* compare pink for fetish */ +.lightcoral, .lightcoral a, .fetish.gain, .fetish.gain a { + color: lightcoral +} + +.lightgreen, .lightgreen a, .relationship, .relationship a, .rivalry.dec, .rivalry.dec a { + color: lightgreen +} + +.lightpink, .lightpink a { + color: lightpink +} + +.lightsalmon, .lightsalmon a, .fetish.inc, .fetish.inc a, .rivalry.inc, .rivalry.inc a, +.relationship.dec, .relationship.dec a { + color: lightsalmon +} + +/* tight orifices, breast changes, take virginity, not sure on good aliases */ +.lime, .lime a, .change.positive, .change.positive a, .virginity.loss, .virginity.loss a, .puberty, .puberty a, +.pregnant, .pregnant a { + color: lime +} + +/* multiple questionable uses */ +.limegreen, .limegreen a { + color: limegreen +} + +.magenta, .magenta a, .devotion.worship, .devotion.worship a { + color: magenta +} + +.mediumaquamarine, .mediumaquamarine a, .trust.inc, .trust.inc a, .trust.careful, .trust.careful a { + color: mediumaquamarine +} + +.mediumorchid, .mediumorchid a, .devotion.dec, .devotion.dec a, .devotion.resistant, .devotion.resistant a { + color: mediumorchid +} + +.mediumseagreen, .mediumseagreen a, .trust.trusting, .trust.trusting a { + color: mediumseagreen +} + +/* generally between red and green, and a lot of other places */ +.orange, .orange a, .stupid, .stupid a, .change.negative, .change.negative a, .defiant.careful, .defiant.careful a, +.ncs, .ncs a, .miscarriage, .miscarriage a, .intro.question { + color: orange +} + +.orangered, .orangered a, .defiant.inc, .defiant.inc a, .defiant.bold, .defiant.bold, .education.neg a { + color: orangered +} + +/* used once (wrong? */ +.orchid, .orchid a { + color: orchid +} + +/* also fetish start ??? , and a lot of other stuff */ +.pink, .pink a, .slave.name.simple { + color: pink +} + +/* generally bad stuff */ +/* note: .error is for unexpected behavior, .warning for player feedback */ +.red, .red a, .health.dec, .health.dec a, .cash.dec, .cash.dec a, .stat.drop, .stat.drop a, .flaw.gain, .flaw.gain a, +.mindbreak, .mindbreak a, .error, .error a, .elites.loss, .elites.loss a, .reputation.dec, .reputation.dec a, +.warning, .warning a { + color: red +} + +.seagreen, .seagreen a, .trust.prof-trusting, .trust.prof-trusting a { + color: seagreen +} + +.springgreen, .springgreen a, .skill.player, .skill.player a { + color: springgreen +} + +/* some ethnicity */ +.tan, .tan a { + color: tan +} + +.chocolate, .chocolate a { + color: chocolate +} + +.saddlebrown, .saddlebrown a { + color: saddlebrown +} + +.teal, .teal a { + color: teal +} + +.yellow, .yellow a, .noteworthy, .noteworthy a, .paraphilia.gain, .paraphilia.gain a, +.devotion.ambivalent, .devotion.ambivalent a, .trust.fearful, .trust.fearful a, .job.change { + color: yellow +} + +.yellowgreen, .yellowgreen a, .cash.inc, .cash.inc a, .cash, .cash a { + color: yellowgreen +} + +.white a { + color: white +} + +.violet, .libido.inc { + color: violet +} + +.khaki, .libido.dec { + color: khaki +} diff --git a/src/gui/css/accordion.css b/css/gui/accordion.css similarity index 100% rename from src/gui/css/accordion.css rename to css/gui/accordion.css diff --git a/src/gui/Encyclopedia/encyclopedia.css b/css/gui/encyclopedia.css similarity index 100% rename from src/gui/Encyclopedia/encyclopedia.css rename to css/gui/encyclopedia.css diff --git a/css/gui/favorite.css b/css/gui/favorite.css new file mode 100644 index 0000000000000000000000000000000000000000..e6069066bcdaa3aa9953bb5751391e7a0e2605b3 --- /dev/null +++ b/css/gui/favorite.css @@ -0,0 +1,9 @@ +.favorite, .favorite:hover { + color: yellow; + text-decoration: none; +} + +.not-favorite, .not-favorite:hover { + color: grey; + text-decoration: none; +} diff --git a/src/gui/options/hotkeySettings.css b/css/gui/hotkeySettings.css similarity index 100% rename from src/gui/options/hotkeySettings.css rename to css/gui/hotkeySettings.css diff --git a/css/gui/linksStrip.css b/css/gui/linksStrip.css new file mode 100644 index 0000000000000000000000000000000000000000..2ae24c635862ceb42a6a35fbaf6b12049055aafe --- /dev/null +++ b/css/gui/linksStrip.css @@ -0,0 +1,20 @@ +ul.choicesStrip { + display: inline; + list-style-type: none; + padding: 0mm; + margin-left: 0em; +} + +ul.choicesStrip li { + display: inline; +} + +ul.choicesStrip li + li:before { + content: " | "; +} + +a.disabled { + color: white; + pointer-events: none; + cursor: default; +} diff --git a/src/gui/css/options.css b/css/gui/options.css similarity index 100% rename from src/gui/css/options.css rename to css/gui/options.css diff --git a/src/003-assets/CSS/quicklinks.css b/css/gui/quicklinks.css similarity index 100% rename from src/003-assets/CSS/quicklinks.css rename to css/gui/quicklinks.css diff --git a/src/003-assets/CSS/cardStyle.css b/css/gui/slaveList/cardStyle.css similarity index 100% rename from src/003-assets/CSS/cardStyle.css rename to css/gui/slaveList/cardStyle.css diff --git a/src/gui/css/quickListCSS.css b/css/gui/slaveList/quickListCSS.css similarity index 100% rename from src/gui/css/quickListCSS.css rename to css/gui/slaveList/quickListCSS.css diff --git a/src/003-assets/CSS/slaveList.css b/css/gui/slaveList/slaveList.css similarity index 90% rename from src/003-assets/CSS/slaveList.css rename to css/gui/slaveList/slaveList.css index 1622a6a9f60b779856d1aa0468867cb8aadfaf3e..a88ed7430ab4fa4a8937d62476a57f45b9d22ae1 100644 --- a/src/003-assets/CSS/slaveList.css +++ b/css/gui/slaveList/slaveList.css @@ -20,7 +20,3 @@ span.freeAssignment { margin-right: 2em; text-indent: 0; } - -.strong { - font-weight: bold; -} diff --git a/src/003-assets/CSS/tabs.css b/css/gui/tabs.css similarity index 100% rename from src/003-assets/CSS/tabs.css rename to css/gui/tabs.css diff --git a/css/gui/tooltips/hasTooltip.css b/css/gui/tooltips/hasTooltip.css new file mode 100644 index 0000000000000000000000000000000000000000..1eaca7af0ac5c88d57e07a07314f5ac8ab93b4eb --- /dev/null +++ b/css/gui/tooltips/hasTooltip.css @@ -0,0 +1,21 @@ +/* TODO unify tooltip systems */ +.hasTooltip { + text-decoration: underline; +} + +/* interactable tooltip-like container - created/destroyed dynamically */ +.details-overlay { + display: inline-block; + font-size: smaller; + width: max-content; + height: max-content; + border-style: solid; + border-color: slategray; + border-width: 2px; + border-radius: 3px; + background-color: rgb(17, 17, 17); + padding: 3px; + position: absolute; + z-index: 2; + text-indent: 0; +} diff --git a/css/gui/tooltips/textWithTooltip.css b/css/gui/tooltips/textWithTooltip.css new file mode 100644 index 0000000000000000000000000000000000000000..60036f7ff6dfdb4509470a83523403b9c0b68d5f --- /dev/null +++ b/css/gui/tooltips/textWithTooltip.css @@ -0,0 +1,48 @@ +/* TODO unify tooltip systems */ +.textWithTooltip { + position: relative; + display: inline-block; + text-decoration: underline; + text-decoration-color: lightblue; +} + +.textWithTooltip .tooltip { + visibility: hidden; + display: block; + font-size: smaller; + width: 20em; + margin-left: -10em; + background-color: rgb(29, 30, 32); + text-align: center; + border-radius: 3px; + padding: 3px; + position: absolute; + z-index: 1; + bottom: 100%; + left: 50%; +} + +.textWithTooltip .tooltip ul { + margin-left: 5px; + margin-right: 0px; + padding-left: 10px; + padding-right: 0px; + text-align: left; +} + +.textWithTooltip .tooltip::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: #555 transparent transparent transparent; +} + +.textWithTooltip:hover .tooltip { + visibility: visible; + opacity: 1; + transition-delay: 0.3s; +} diff --git a/css/interaction/export.css b/css/interaction/export.css new file mode 100644 index 0000000000000000000000000000000000000000..72eabfbdb7af31eb594f96cf15d088517b088ca2 --- /dev/null +++ b/css/interaction/export.css @@ -0,0 +1,6 @@ +div.output { + width: 100vw; + max-width: 100%; + word-break: break-all; + white-space: normal; +} diff --git a/src/gui/css/familyTree.css b/css/interaction/familyTree.css similarity index 100% rename from src/gui/css/familyTree.css rename to css/interaction/familyTree.css diff --git a/src/003-assets/CSS/gridTemplates.css b/css/interaction/prosthetics.css similarity index 75% rename from src/003-assets/CSS/gridTemplates.css rename to css/interaction/prosthetics.css index bdc2adf2e7f4ce6c1b970d3059b45c2dcb7cf382..0b6a4b4b2dec88df4948f78efe87e67b5327fd0b 100644 --- a/src/003-assets/CSS/gridTemplates.css +++ b/css/interaction/prosthetics.css @@ -1,12 +1,3 @@ -/* general use */ -div.grid-2columns-auto { - display: grid; - grid-template-columns: max-content auto; -} - -/* specific uses */ - -/* limb selector in limbs.js */ div.limb-selector { display: grid; grid-template-columns: 200px 100px 100px 100px 100px; @@ -18,7 +9,6 @@ div.limb-selector div.full { text-align: center; } -/* prostheticConfig.tw */ div.eyeContainer { display: grid; grid-template-columns: 80px 50px 70px 50px; diff --git a/css/interaction/slaveInteract.css b/css/interaction/slaveInteract.css new file mode 100644 index 0000000000000000000000000000000000000000..587ffa7234093ab4d043479cc9ee4c0b403336a8 --- /dev/null +++ b/css/interaction/slaveInteract.css @@ -0,0 +1,7 @@ +.adjacent-slave { + font-weight: bold; +} + +.interact-name { + margin: 0 2em; +} diff --git a/src/interaction/wardrobe.css b/css/interaction/wardrobe.css similarity index 100% rename from src/interaction/wardrobe.css rename to css/interaction/wardrobe.css diff --git a/src/events/intro/customizeSlaveTrade/customizeSlaveTrade.css b/css/intro/customizeSlaveTrade.css similarity index 100% rename from src/events/intro/customizeSlaveTrade/customizeSlaveTrade.css rename to css/intro/customizeSlaveTrade.css diff --git a/src/003-assets/CSS/table.css b/css/manage/budget.css similarity index 72% rename from src/003-assets/CSS/table.css rename to css/manage/budget.css index d71878e44483a7243eb66aa161bf63a4a53419a2..eca4573e7de36fe73373de9e5aa2346db05897aa 100644 --- a/src/003-assets/CSS/table.css +++ b/css/manage/budget.css @@ -1,16 +1,3 @@ -table.wardrobe { - text-align: left; - border-collapse: separate; - border-spacing: 5px; - /*border-style: hidden;*/ - /*empty-cells: hide;*/ - width: 900px -} -table.wardrobe td { - width: 50%; - border: 1px solid white; -} - table.budget { text-align: right; border-collapse: separate; diff --git a/css/manage/main.css b/css/manage/main.css new file mode 100644 index 0000000000000000000000000000000000000000..3b1c3042dd81fd8e6ed1c4756b96fd8921e051d1 --- /dev/null +++ b/css/manage/main.css @@ -0,0 +1,4 @@ +.main-fcnn { + text-align: center; + margin: 0 auto; +} diff --git a/css/manage/manage.css b/css/manage/manage.css new file mode 100644 index 0000000000000000000000000000000000000000..9b5838df9f4b328cc5549a4763a8b2e36915d9e3 --- /dev/null +++ b/css/manage/manage.css @@ -0,0 +1,6 @@ +/* puts a div in the right upper corner while not influencing the layout of the rest of the page */ +div.cheat-menu { + font-style: italic; + position: absolute; + right: 50px; +} diff --git a/src/neighbor/neighborDisplay.css b/css/neighbor/neighborDisplay.css similarity index 100% rename from src/neighbor/neighborDisplay.css rename to css/neighbor/neighborDisplay.css diff --git a/src/npc/interaction/slaveOnSlaveFeeding/slaveOnSlaveFeeding.css b/css/npc/slaveOnSlaveFeeding.css similarity index 98% rename from src/npc/interaction/slaveOnSlaveFeeding/slaveOnSlaveFeeding.css rename to css/npc/slaveOnSlaveFeeding.css index e4fb2cc907eab6d4d2fc07e8aef967eeb0ec919a..bb7e81979fb99693ae0f5b52904a374e0c06bfd1 100644 --- a/src/npc/interaction/slaveOnSlaveFeeding/slaveOnSlaveFeeding.css +++ b/css/npc/slaveOnSlaveFeeding.css @@ -4,4 +4,4 @@ table.slave-on-slave-feeding { table.slave-on-slave-feeding tr { vertical-align: top; -} \ No newline at end of file +} diff --git a/css/rulesAssistant/raLists.css b/css/rulesAssistant/raLists.css new file mode 100644 index 0000000000000000000000000000000000000000..70cd924e242db5577c85ede9dd4c92025361e5e3 --- /dev/null +++ b/css/rulesAssistant/raLists.css @@ -0,0 +1,41 @@ +.rajs-list-item { + display: inline-block; + color: var(--link-color); + margin-right: 1em; +} + +.rajs-list-item.selected { + color: gray; + text-decoration: none; +} + +.rajs-list-item:last-of-type { + margin-right: 0; +} + +.rajs-list-item:hover { + cursor: pointer; + text-decoration: underline; +} + +.rajs-list-item.selected:hover { + cursor: default; + text-decoration: none; +} + +.rajs-list strong:first-of-type, .rajs-list input { + margin-right: 2em; +} + +.rajs-list-item input { + margin: 0.25em; +} + +.rajs-section h1 { + border-bottom: 1px solid white; + cursor: pointer; +} + +.rajs-section h1:hover { + text-decoration: underline; +} diff --git a/src/003-assets/CSS/RAoptions.css b/css/rulesAssistant/raOptions.css similarity index 99% rename from src/003-assets/CSS/RAoptions.css rename to css/rulesAssistant/raOptions.css index 3a3c4fcc3d53779a892516ff7aedc21e424ff436..079895f20ae600c74c1b04f739d18d4529700d98 100644 --- a/src/003-assets/CSS/RAoptions.css +++ b/css/rulesAssistant/raOptions.css @@ -4,33 +4,40 @@ vertical-align: middle; -webkit-user-select:none; -moz-user-select:none; -ms-user-select: none; } + .ra-onoffswitch-checkbox { display: none; } + .ra-onoffswitch-label { display: block; overflow: hidden; cursor: pointer; border: 2px solid #999999; border-radius: 2px; } + .ra-onoffswitch-inner { display: block; width: 200%; margin-left: -100%; transition: margin 0.3s ease-in 0s; } + .ra-onoffswitch-inner:before, .ra-onoffswitch-inner:after { display: block; float: left; width: 50%; height: 3.5ex; padding: 0; line-height: 3.5ex; font-size: x-small; color: white; font-family: FreeSans, sans-serif; font-weight: bold; box-sizing: border-box; } + .ra-onoffswitch-inner:before { content: "ON"; padding-left: 7px; background-color: #111111; color: #FFFFFF; } + .ra-onoffswitch-inner:after { content: "OFF"; padding-right: 7px; background-color: #111111; color: #D9D9D9; text-align: right; } + .ra-onoffswitch-switch { display: block; width: 1.5em; margin: 1px; background: #8A8A8A; @@ -39,13 +46,16 @@ border: 2px solid #414141; border-radius: 2px; transition: all 0.3s ease-in 0s; } + .ra-onoffswitch-checkbox:checked + .ra-onoffswitch-label .ra-onoffswitch-inner { margin-left: 0; } + .ra-onoffswitch-checkbox:checked + .ra-onoffswitch-label .ra-onoffswitch-switch { right: 0px; background-color: #2D80E0; } + .ra-radio-label { margin: 0.5em; } diff --git a/css/rulesAssistant/raSummary.css b/css/rulesAssistant/raSummary.css new file mode 100644 index 0000000000000000000000000000000000000000..b9734d8fc017ea4f50347937dd2f3aa377bdfc3c --- /dev/null +++ b/css/rulesAssistant/raSummary.css @@ -0,0 +1,3 @@ +.scroll { + overflow: auto; +} diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index b859b9718de84ccb55cad8f0f9e0a02895929dcc..a2781ac42b6a9e7e0029e5c805ac4cce61669259 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -163,7 +163,7 @@ App.Data.defaultGameStateVariables = { summaryStats: 0, surnameOrder: 0, /** @type {Object.<string, string>} */ - tabChoice: {Main: "all"}, + tabChoice: { Main: "all" }, universalRulesAssignsSelfFacility: 0, universalRulesBirthing: 0, universalRulesCSec: 0, @@ -342,7 +342,7 @@ App.Data.resetOnNGPlus = { }, /** @type {assistant} */ assistant: {}, - targetArcology: {fs: "New"}, + targetArcology: { fs: "New" }, readySlaves: 0, plot: 1, @@ -782,6 +782,11 @@ App.Data.resetOnNGPlus = { smartVaginalAttachments: 0, }, }, + customItem: { + /** @type {Map<string, slaveButtplugs>} */ + buttplug: new Map([]), + vaginalAccessory: new Map([]), + }, dairyPiping: 0, milkPipeline: 0, cumPipeline: 0, @@ -911,11 +916,11 @@ App.Data.resetOnNGPlus = { ui: "start", tooltipsEnabled: 0, - brandTarget: {primary: "left buttock", secondary: "left buttock", local: "left buttock"}, - brandDesign: {primary: "your initials", official: "your initials", local: "your initials"}, + brandTarget: { primary: "left buttock", secondary: "left buttock", local: "left buttock" }, + brandDesign: { primary: "your initials", official: "your initials", local: "your initials" }, - scarTarget: {primary: "left cheek", secondary: "left cheek", local: "left cheek"}, - scarDesign: {primary: "generic", local: "generic"}, + scarTarget: { primary: "left cheek", secondary: "left cheek", local: "left cheek" }, + scarDesign: { primary: "generic", local: "generic" }, oralTotal: 0, vaginalTotal: 0, @@ -1000,6 +1005,7 @@ App.Data.resetOnNGPlus = { animalTesticles: 0, /* {pigTestes: 0, dogTestes: 0, horseTestes: 0, cowTestes: 0} currently unused*/ animalMpreg: 0, /* {pigMpreg: 0, dogMpreg: 0, horseMpreg: 0, cowMpreg: 0} currently unused*/ geneticMappingUpgrade: 0, + toyShop: false, pregnancyMonitoringUpgrade: 0, cloningSystem: 0, geneticFlawLibrary: 0, diff --git a/js/003-data/slaveWearData.js b/js/003-data/slaveWearData.js index acce98a8329fa781d6d392059ee753aa1f261429..2f8b6e4374e123e50e6cec791162894b4f484e77 100644 --- a/js/003-data/slaveWearData.js +++ b/js/003-data/slaveWearData.js @@ -828,12 +828,12 @@ App.Data.clothes = new Map([ */ /** - * @typedef {Map<string, slaveWear|slaveWearChastity>} slaveWearCategory + * @typedef {Map<string, slaveWear>} slaveWearCategory */ -/** @type {Object.<string, slaveWearCategory>} */ +/** @type {Object.<string, slaveWearCategory>} string should be the slave property being modified.*/ App.Data.slaveWear = { - collars: new Map([ + collar: new Map([ ["stylish leather", {name: "Stylish leather"}], ["satin choker", {name: "Satin choker"}], ["silk ribbon", {name: "Silken ribbon"}], @@ -940,7 +940,7 @@ App.Data.slaveWear = { ], ]), - bellyAccessories: new Map([ + bellyAccessory: new Map([ ["none", {name: "None"}], ["a corset", {name: "Tight corset"}], ["an extreme corset", {name: "Extreme corset"}], @@ -983,54 +983,7 @@ App.Data.slaveWear = { ] ]), - vaginalAccessories: new Map([ - ["none", {name: "None"}], - ["bullet vibrator", {name: "Bullet vibrator"}], - ["smart bullet vibrator", - { - name: "Smart bullet vibrator", - get requirements() { - return V.boughtItem.toys.smartVibes === 1; - } - } - ], - ["dildo", {name: "Dildo"}], - ["long dildo", - { - name: "Long dildo", - get requirements() { - return V.boughtItem.toys.dildos === 1; - } - } - ], - ["large dildo", {name: "Large dildo"}], - ["long, large dildo", - { - name: "Long, large dildo", - get requirements() { - return V.boughtItem.toys.dildos === 1; - } - } - ], - ["huge dildo", - { - name: "Huge dildo", - get requirements() { - return V.boughtItem.toys.dildos === 1; - } - } - ], - ["long, huge dildo", - { - name: "Long, huge dildo", - get requirements() { - return V.boughtItem.toys.dildos === 1; - } - } - ] - ]), - - vaginalAttachments: new Map([ + vaginalAttachment: new Map([ ["none", {name: "None"}], ["vibrator", { @@ -1050,7 +1003,7 @@ App.Data.slaveWear = { ] ]), - dickAccessories: new Map([ + dickAccessory: new Map([ ["none", {name: "None"}], ["bullet vibrator", {name: "Bullet vibrator"}], ["smart bullet vibrator", @@ -1063,7 +1016,7 @@ App.Data.slaveWear = { ] ]), - buttplugAttachments: new Map([ + buttplugAttachment: new Map([ ["none", {name: "None"}], ["tail", { @@ -1195,15 +1148,14 @@ App.Data.shoes = new Map([ // TODO: add lift property * @property {string} name * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. * @property {boolean} [requirements] - * @property {boolean} [harsh] - * @property {0|1|2|3} width height in cm. Adds to heel height. - * @property {0|1|2} length height in cm. Over 4cm they may totter. 21cm and over (8 inch heels) will be painful/extreme + * @property {0|1|2|3} width + * @property {0|1|2} length */ /** - * @type {Map<string, slaveButtplugs>} slaveShoesCategory + * @type {Map<string, slaveButtplugs>} */ -App.Data.buttplugs = new Map([ +App.Data.buttplug = new Map([ ["none", { name: "None", @@ -1263,17 +1215,110 @@ App.Data.buttplugs = new Map([ } ] ]); +/** + * @typedef {object} vaginalAccessories + * @property {string} name + * @property {FC.FutureSociety} [fs] Automatically unlocked with this FS. + * @property {boolean} [requirements] + * @property {0|1|2|3} width + * @property {0|1|2} length + * @property {0|1|2} [vibrates=0] 0: none, 1: standard, 2: "smart" vibe + */ +/** + * @type {Map<string, vaginalAccessories>} + */ +App.Data.vaginalAccessory = new Map([ + ["none", + { + name: "None", + width: 0, + length: 0 + } + ], + ["bullet vibrator", + { + name: "Bullet vibrator", + width: 0, + length: 1, + vibrates: 1 + } + ], + ["smart bullet vibrator", + { + name: "Smart bullet vibrator", + get requirements() { + return V.boughtItem.toys.smartVibes === 1; + }, + width: 0, + length: 1, + vibrates: 2 + } + ], + ["dildo", + { + name: "Dildo", + width: 1, + length: 1 + } + ], + ["long dildo", + { + name: "Long dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + }, + width: 1, + length: 2 + } + ], + ["large dildo", + { + name: "Large dildo", + width: 2, + length: 1 + } + ], + ["long, large dildo", + { + name: "Long, large dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + }, + width: 2, + length: 2 + } + ], + ["huge dildo", + { + name: "Huge dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + }, + width: 3, + length: 1 + } + ], + ["long, huge dildo", + { + name: "Long, huge dildo", + get requirements() { + return V.boughtItem.toys.dildos === 1; + }, + width: 3, + length: 2 + } + ] +]); /** * @typedef {object} slaveWearChastity * @property {string} name - * @property {string} value * @property {object} updateSlave * @property {FC.FutureSociety} [fs] */ /** @type {Map<string, slaveWearChastity>} */ -App.Data.slaveWear.chastityDevices = new Map([ +App.Data.chastity = new Map([ // '.value' must be a string, so using update slave so I can update multiple values. ["none", { @@ -1382,3 +1427,4 @@ App.Data.slaveWear.chastityDevices = new Map([ } ] ]); + diff --git a/resources/raster/favicon/arcologyVector.html b/resources/raster/favicon/arcologyVector.html new file mode 100644 index 0000000000000000000000000000000000000000..654baa88eae790a8a1967a201a6c8a75e7413a04 --- /dev/null +++ b/resources/raster/favicon/arcologyVector.html @@ -0,0 +1,2 @@ +<!-- embedded icon so no resources folder is required to display it. --> +<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAMAQEAAAAEAIAAoQgAANgAAACAgAAABACAAqBAAAF5CAAAQEAAAAQAgAGgEAAAGUwAAKAAAAEAAAACAAAAAAQAgAAAAAAAAQAAAwQ4AAMEOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKSkgCCgoJVl5eY/JmZmv+ZmZr/mZma/5mZmv+ZmZr/mZma/5mZmv+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ZmZn/mZmZ/5mZmf+ampr/ZmZm/z4+Pv9nZ2f/jIyM/5GRkf+RkZH/kZGR/5GRkf+Ojo7/hYWF/4WFhf+FhYX/hYWF/4GBgf94eHjsZmZmMGhoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9+wA/vftKf/z5Ob/8N3//+/Z///t1f//6s3//+rN///qzf//9ef/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////xcXF/1RUVP9ra2v/ysrK/+vr6//t7e3/7e3t/+3t7f/t7e3/5ubm/9TU1P/T09P/09PT/9PT0//IyMj/v7+/zL+/vxG/v78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+nLAP/pywn/6s25/+fH///kvv//4rv//9ur///aqP//2qf//+bD///+/f//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////xcXF/1JSUv9qamr/zMzM/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+Li4v/T09P/09PT/9PT0//S0tL/xMTE/7+/v5u/v78Bv7+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/qzgD/6s4A/+rOhf/py///5MD//+S////esv//26r//9up///esv//+fH/////////////////////////////////////////////////////////////////////////////////////////////////////////////////xcXF/1JSUv9qamr/zMzM//Hx8f/w8PD/7e3t/+3t7f/t7e3/7e3t/+3t7f/e3t7/09PT/9PT0//T09P/0NDQ/8HBwf+/v79pv7+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+rOAP/qzk//6s36/+XC///kv///4bf//9uq///bqv//26r///Dc////////////////////////////////////////////////////////////////////////////////////////////////////////////xcXF/1JSUv9qamr/zMzM//Hx8f/7+/v/8PDw/+3t7f/t7e3/7e3t/+3t7f/s7Oz/2tra/9PT0//T09P/09PT/83Nzf+/v7/yv7+/PL+/vwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/t1QD/7dYk/+3U4v/nxv//5L///+O8///crf//26r//9qp///mxP///v3/////////////////////////////////////////////////////////////////////////////////////////////////xcXF/1JSUv9qamr/zMzM//Hx8f/9/f3//f39/+/v7//t7e3/7e3t/+3t7f/t7e3/6urq/9fX1//T09P/09PT/9PT0//IyMj/v7+/1L+/vxe/v78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7tcA//DbCf/v2bn/6cz//+XB///lwf//37T//9yt///crP//4LX///ny////////////////////////////////////////////////////////////////////////////////////////////xcXF/1JSUv9qamr/zMzM//Hx8f/9/f3///////v7+//u7u7/7e3t/+3t7f/t7e3/7e3t/+fn5//U1NT/09PT/9PT0//S0tL/xMTE/7+/v6a/v78Dv7+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+nLAP///gD/+vSF//rz///58P//+fD///ft///26v//9uv///fr///9+v//////////////////////////////////////////////////////////////////////////////////////39/f/1dXV/9qamr/zMzM//Hy8v/9/v7////////////7+/v/7u7u/+3t7v/t7e7/7e3u/+3u7v/k5OX/09PU/9PT1P/T09T/0NDR/8HBwv+/v79vv7+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9OUA//bpT//z4/r/8d3//+/a///v2f//69D//+rO///qzv//6s3//+jI///mw///5sP//+bD///mw///4bj//9+z///ftP//37T//9+0///ftP//37T//9+0///ftP//37L//+/W/87Oz/9RUVH/ubi3//XdvP/+3bH//9+0///ftP//37T/+9uw/+7Qp//t0Kf/7dCn/+3Qp//t0Kf/5Mig/9m+l//Zvpj/2b6Y/9S5kf/LsIfyybKPPMmxjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+nNAP/pzCT/6s3i/+bF///jvv//477//96w///aqP//2qj//9qp///Yo///05j//9OX///Tl///05f//82I///IfP//yH3//8h9///Iff//yH3//8h9///Iff//yH3//8d6///htf/Pz9D/VVVW/8PBv//70pn//8h7///Iff//yH3//8h9//vFe//uu3T/7bp0/+26dP/tunT/7bp0/+Ozb//drmz/3a5s/92ubP/Xp2H/06Nb2dSjWRrUo1kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/qzgD/6s4J/+rPuf/oyv//5L///+S////ht///26r//9uq///bqv//2qj//9Wc///Umf//1Jn//9SZ///Pjv//yX///8l////Jf///yX///8l////Jf///yX///8l////Iff//4rb/z8/Q/1RUVP/Avrv/+9Ob///Iff//yX///8l////Jf//6xXz/7bt2/+27dv/tu3b/7bt2/+y6df/gsXD/3a9u/92vbv/crmz/1KZf/9OkXbDTpF0F06RdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/6s4A/+7XAP/u1oX/6s7//+XB///kv///47z//9ys///bqf//26n//9up///Xn///1Jj//9SY///Umf//0ZH//8l////Jfv//yX7//8l+///Jfv//yX7//8l+///Jfv//yHz//+K2/8/Q0P9NTU3/mJiY/+jSs///zIX//8h9///Jfv//yX7/+MN6/+27df/tu3X/7bt1/+27df/quXT/3rBu/92vbf/dr23/2qxp/9OkXf/TpF1606RcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/x3QD/8dxP//Da+v/rzf//6cj//+nI///kvP//4bb//+G2///htv//37H//9un///bp///26f//9mj///Skv//0ZD//9GQ///RkP//0ZD//9GQ///RkP//0ZD//9CO///nwP/P0ND/S0tL/19gYP+gn5//7te4///Skv//0ZD//9GQ//jLi//uwob/7sKG/+7Chv/vw4b/6L2C/920e//dtHv/3bR7/9eucv/RqGn40admSNGnZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADk4dwA5eHcJNjW0+LW1ND/19PP/9fTz//X087/19LM/9fSzP/X0sz/19LM/9fRyv/X0cr/19HK/9fRyv/X0Mj/19DH/9fQx//X0Mf/19DH/9fQx//X0Mf/19DH/9fQx//Z1dD/sLCw/1VVVf+bm5v/b29v/5+fnv/Vz8f/19DH/9bQx//QysH/zMa+/8zGvv/Mxr7/zMa+/8bAuP++uLH/vrix/764sf+3san/tK6l3ryyoiG8sqMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdHR1AHR1dQlbW1u5WFhZ/1hYWf9YWFn/WFhY/1dXWP9XV1j/V1dY/1dXWP9XV1j/V1dY/1dXWP9XV1j/V1dY/1dXWP9XV1j/V1dY/1dXWP9XV1j/V1dY/1dXWP9XV1j/V1hY/1BQUP9QUFD/y8vL/8nJyf9sbG3/VlZX/1dXWP9XV1j/V1dY/1dYWP9XWFj/V1hY/1dYWP9XWFj/WFhZ/1hZWf9YWVn/WFlZ/1pbW7dpa20HZ2lsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQUFABHR0cAPj4+eT4+PuQ+Pj7hPj4+4EVFRehUVVX+VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9UVVX/Z2dn/+Dg4P//////1dXV/2tra/9TU1P/U1NT/1NTU/9TU1P/U1NT/1JSUv9QUFD/UFBQ/0VFRe0+Pj7gPj4+4T4+PuQ+Pj55R0dHABQUFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAAEBAQAxAQEAeQEBAHigoKBu8u7pW6Ofm9+jn5v/o5+b/6Ofl/+jn5v/o6Oj/6Ofl/+jn5f/o5+X/6Ofk/+jm5P/o5uT/6Obk/+jm5P/o5uT/6Obk/+jm5P/o5uT/6Obk/+vp5v/8+vj///77///+/P/x7+3/393a/9jW1P/Y19T/2NfU/9nX1f/NzMn/wsC+/7y7uP6enZtwLS4uGkBAQB5AQEAeQEBADEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8dwA//HcP//w2vb/7dL//+rM///lwP//6sz///z4///qy///4LP//+Cz///apf//2KD//9ig///YoP//2KD//9ig///YoP//2KD//9ig///YoP//2KD//9ef///Wn///1p///9eg//XPmf/uyJX/7smV/+7Jlf/vyZX/5MCO/9y5iP/WtIH0z615Pc+seAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+rNAP/qzj//6cv2/+TA///huf//26n//9yt///26v//68///9OX///Tl///y4T//8h9///Iff//yH3//8h9///Iff//yH3//8h9///Iff//yH3//8h9///Iff//yH3//8h9//7Iff/yvnf/7bp0/+26dP/tunT/7bp0/+Ozb//drmz/2Khj39KiWCDUo1oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/qzgD/6s4//+nM9v/lwf//4rr//9ur///aqP//6s7///bq///XoP//05j//8yF///Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf//+yH7/8L54/+27dv/tu3b/7bt2/+y6dv/hsnD/3K5t/9aoY8LQoFcL06RdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/6s4A/+rOP//pzPb/5cH//+K6///bq///2qj//9+z///68///37P//9OX///Mhf//yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///cd+/++9d//tu3b/7bt2/+27dv/runX/37Fv/9ytbP/VpmGgu4o1AdOkXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+vQAP/r0D//6s32/+XB///iuv//26v//9up///Yov//9Ob//+vQ///Tl///zIX//8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l///vGff/uvHf/7bt2/+27dv/tu3b/6rh0/96wb//brGr/1KVfe9anYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/v2QD/8No//+vR9v/lwf//4rr//9ur///bqf//1Zz//+nK///26v//1p///8yF///Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf//6xX3/7rt2/+27dv/tu3b/7bt2/+i3c//dr27/2qto+9OkXVDTpV4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8NsA//DcP//s0fb/5cH//+K6///bq///26n//9Wc///drv//+vP//9+y///LhP//yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX//+MR8/+27dv/tu3b/7bt2/+27dv/ltXL/3a9u/9mqZu3So1wy06RdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//HbAP/x3D//7NL2/+XB///iuv//3Kv//9up///Wnf//1p3///Xm///s0P//y4T//8l+///Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l///bCe//tu3b/7bt2/+27dv/tu3b/47Nx/92vbv/XqGTZ0aJaGdOkXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPbw5wD28Og/9u7j9vbr3f/26tr/9ufT//bn0//25c7/9uTM//bv5v/28u3//Nim///Jfv//yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf//0wXr/7bt2/+27dv/tu3b/7Lp2/+GycP/crm3/1qdivM+gVgjTpF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGhocAhoaHP4aHh/aGh4f/hoeH/4aHiP+Gh4j/hoeI/4aHiP+Ghob/jIyN/8jCu//71qL//8l+///Jf///yX///8l////Jf///yX///8l////Jf///yX///8l////Jf///yX//8795/+27dv/tu3b/7bt2/+u6df/fsW//261r/9WmYJbrvoUA06RdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz8/AD8/Pz8/Pz/2Pz8//z8/P/8+Pj7/PT09/z09Pf89PT3/PT09/z4+Pv9sbW3/yMK6//vWov//yX7//8l////Jf///yX///8l////Jf///yX///8l////Jf///yX///sh///G+eP/tu3b/7bt2/+27dv/quHT/3rBv/9qsav/UpV9t1aZgAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Pz8APj4+bz4+Pv8+Pj7/Pj4+/z4+Pv8+Pj7/Pj4+/z4+Pv8+Pj7/Pj4+/z4+Pv8+Pj7/Pj4+9j4+Pj8+Pj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+AAAAAAAAf/4AAAAAAAB//gAAAAAAAH//AAAAAAAA//8AAAAAAAD//wAAAAAAAP//AAAAAAAA//+AAAAAAAH//4AAAAAAAf//gAAAAAAB//+AAAAAAAH//8AAAAAAA///wAAAAAAD///AAAAAAAP//8AAAAAAA///4AAAAAAH///gAAAAAAf///4AAAAAf////gAAAAB////+AAAAAH////4AAAAAf////gAAAAD////+AAAAAP////4AAAAA/////gAAAAD////+AAAAAP////4AAAAB/////gAAAAH////+AAAAAf/////gAAAB/////+AAAAH/////4AAAAf/////gAAAD/////+AAAAP/////4AAAA//////wAAAD//////AAAAP/////8AAAA//////wAAAH//////AAAAf/////8AAAB//////wAAB///////AAAH//////8AAAf//////4AAD///////gAAP//////+AAA///////4AAD///////gAAP//////+AAB///////4AAH///////gAAf//////+AAB///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAH///////8AAf///////wAB////////AAH///////+AAf///////4AB////ygAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMEOAADBDgAAAAAAAAAAAAAAAAAAAAAAAL+6tAC8uLIr0Me96NLIuf/SxbP/0sm7/9LS0f/S0tL/0tLS/9LS0v/S0tL/0tLS/9LS0v/S0tL/0tLS/9LS0v/T09P/0dHR/4KCgv+BgYH/wsLC/8XFxf/BwcH/srKy/7CwsP+kpKTcjo6OHZCQkAAAAAAAAAAAAAAAAAAAAAAA//DVAP/x2Q3/683D/+bB///fsP//47r///z3//////////////////////////////////////////////////39/f+1tbX/i4uL/97e3v/v7+//7+/v/+fn5//V1dX/0tLS/8XFxbe9vb0HxMTEAAAAAAAAAAAAAAAAAAAAAAD/6s4A/+bDAP/qzpD/5cL//96y///bqv//8+P////////////////////////////////////////////9/f3/s7Oz/4iJif/k5OT/9vf3/+3t7f/t7u7/4eLi/9PT0//Ozs7/wcHBhcTExQC/v78AAAAAAAAAAAAAAAAAAAAAAAAAAAD/8+MA//PiWf/w2/z/7NL//+jJ///z4v///vz///37///9+////fr///36///9+v///fr////9/729vf+Ih4b/5OLf///++//18/H/7evo/+3r6f/e3Nr/09LP/8vJx/q/vrxPwL68AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/y4AD/8+Ir/+7X6P/rz///5sP//+S////ht///37L//9ys///Wn///1p///9af///Wnf//4bf/m5ua/8y7pP//2KD//9ef//TOmP/tx5P/7ceT/+C8i//at4b/0rB95MqsfyXMroAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+rOAP/s0w3/6s3D/+bB///gs///3Kn//9mi///VmP//0pL//8p+///Jff//yX3//8h7///Xnv+ZmJf/wK+Y///MhP//yX3/9cB3/+67dP/tunP/4bFt/92taf/VpV2+0qFWC9SjWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/79oAk5CNAOfczpDg1ML/4NG8/+DOtf/gzbP/4Mut/+DKq//gxaH/4MWg/+DFoP/gxJ//4Myw/4qKiP+HhoT/zbmf/+HFoP/WvZn/0rmX/8+3lf/Fro7/waqJ/7+lfY2ZnKEA0qVhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWVlcAX2BgUlhZWd9cXV7ma2xt/Wxtb/9sbW//bG1v/2xucP9sbnD/bG5w/2xucP9rbW//cXJz/8vMzv+SlJb/amtu/2prbf9pamz/ZWdp/lpbXOhWV1jfWltdUVRVVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ0NAAzMzMIIiIkG6eim0fl287v59nH/+ff1P/n2cb/59O4/+fQsv/n0LL/59Cy/+fQsv/q1LX//OfJ//TfwP/bxqn/18Km/9K9ov/BrpTwjYJySicpKxs0NDQINTU1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/688A/+zQLv/ox+3/37L//+jG///lv///0I7//8qA///KgP//yoD//8qA///KgP//yX7//sh+//G/eP/uvHf/6Ld0/9ytatnVpl4a1qZfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/rzwD/69Au/+fG7f/esv//3rD//+rO///Qkf//yX///8l////Jf///yX///8l////Jf//9x37/77x3/+27dv/ktXL/2atou8+fVQnTpF0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+/XAP/v2C7/6Mjt/9+y///Zo///6s3//9ae///Jfv//yX///8l////Jf///yX///8l///vGff/uvHb/7bt2/+KzcP/YqmaW/9iuANOkXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz6NkA8+jaLvPjzu3z3b//89iz//Phyf/43bj//8qA///Jf///yX///8l////Jf///yX//+sV8/+27dv/sunb/37Fu/9eoZHDbrGoA06RdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG1tbQBtbW0sbW1t5G9vbvlzc3P/cXFy/4mGgv/nx5r//8uB///Jf///yX///8l////Jf//4w3v/7bt2/+u5df/dr2351qdiS9eoZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANjY2ADY2NgsuLi44goB9ZsvEuvPMxLj/iYiH/398eP/nx5v//8uB///Jf///yX///8l///bC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"> diff --git a/slave variables documentation - Pregmod.txt b/slave variables documentation - Pregmod.txt index 07e8635e15b2a2004fb496f862f8a8988ce7c22b..3fd1bbcc574f229c16f676c107dc4f7975ab7a63 100644 --- a/slave variables documentation - Pregmod.txt +++ b/slave variables documentation - Pregmod.txt @@ -46,7 +46,449 @@ career: career prior to enslavement accepts string -setup.gratefulCareers +App.Data.Careers.General.veryYoung +"a babysitter" +"a beggar" +"a bully hunter" +"a bully" +"a camp counselor" +"a cheerleader" +"a child actress" +"a child prodigy" +"a child prostitute" +"a child soldier" +"a club manager" +"a club recruiter" +"a club treasurer" +"a cum dump" +"a dropout" +"a drug mule" +"a farmer's daughter" +"a girl scout" +"a hall monitor" +"a handmaiden" +"a hospital volunteer" +"a housesitter" +"a juvenile delinquent" +"a latchkey kid" +"a lemonade stand operator" +"a marching band leader" +"a meat toilet" +"a military brat" +"a model-UN star" +"a model" +"a noblewoman" +"a pageant star" +"a paper girl" +"a part-time farm laborer" +"a pick-pocket" +"a refugee" +"a school nurse's assistant" +"a shrine maiden" +"a street thug" +"a street urchin" +"a student council president" +"a student from a boarding school" +"a student from a private school" +"a student from a public school" +"a sweatshop worker" +"a teacher's pet" +"an apprentice" +"an aspiring pop star" +"an idol" +"an orphan" +"being homeschooled by her parents" +"captain of the kendo club" +"from a lower class family" +"from a middle class family" +"from an upper class family" +"homeless" + +App.Data.Careers.General.young +"a babysitter" +"a ballerina" +"a barista" +"a bartender" +"a beggar" +"a blogger" +"a butler" +"a camgirl" +"a camp counselor" +"a camwhore" +"a cashier" +"a cheerleader" +"a cocktail waitress" +"a comedian" +"a con artist" +"a cook" +"a courier" +"a cowgirl" +"a criminal" +"a croupier" +"a cum dump" +"a dairy worker" +"a dancer" +"a delivery woman" +"a dominatrix" +"a drug mule" +"a factory worker" +"a farm laborer" +"a farmer's daughter" +"a florist" +"a gang member" +"a gardener" +"a groomer" +"a gymnast" +"a handmaiden" +"a house DJ" +"a housesitter" +"a housewife" +"a law enforcement officer" +"a lifeguard" +"a magician's assistant" +"a maid" +"a mail-order bride" +"a masseuse" +"a meat toilet" +"a mechanic" +"a medical student" +"a mistress" +"a model" +"a musician" +"a noblewoman" +"a nun" +"a nurse" +"a paramedic" +"a party girl" +"a personal assistant" +"a personal trainer" +"a pirate" +"a political activist" +"a porn star" +"a prisoner" +"a programmer" +"a prostitute" +"a racing driver" +"a reality show star" +"a receptionist" +"a refugee" +"a ride attendant" +"a saleswoman" +"a school nurse" +"a secretary" +"a security guard" +"a service worker" +"a shrine maiden" +"a shut-in" +"a soldier" +"a street performer" +"a street vendor" +"a stripper" +"a student" +"a switchboard operator" +"a teaching assistant" +"a tour guide" +"a trophy wife" +"a truck driver" +"a video game streamer" +"a waitress" +"a wet nurse" +"a yoga instructor" +"an actress" +"an air hostess" +"an apprentice" +"an arcade attendant" +"an artist" +"an aspiring pop star" +"an assassin" +"an athlete" +"an au pair" +"an escort" +"an exotic dancer" +"an idol" +"an installation technician" +"an intern" +"an office worker" +"homeless" +"in a militia" +"unemployed" + +App.Data.Careers.General.educated +"a ballerina" +"a banker" +"a bureaucrat" +"a business owner" +"a businessman" +"a captain" +"a chemist" +"a chief of police" +"a classical dancer" +"a classical musician" +"a coach" +"a college scout" +"a concierge" +"a coroner" +"a corporate executive" +"a cosmetologist" +"a counselor" +"a criminal" +"a critic" +"a cult leader" +"a dean" +"a dentist" +"a director" +"a dispatch officer" +"a doctor" +"a historian" +"a housekeeper" +"a journalist" +"a judge" +"a lawyer" +"a librarian" +"a lobbyist" +"a madam" +"a manager" +"a mechanic" +"a mediator" +"a medical student" +"a mercenary" +"a military officer" +"a military recruiter" +"a nanny" +"a noblewoman" +"a nun" +"a painter" +"a paramedic" +"a personal assistant" +"a pharmacist" +"a photographer" +"a physician" +"a pilot" +"a poet" +"a police detective" +"a police negotiator" +"a police officer" +"a political activist" +"a politician" +"a practitioner" +"a principal" +"a prison warden" +"a private detective" +"a private instructor" +"a procuress" +"a producer" +"a professional bartender" +"a professor" +"a programmer" +"a prostitute" +"a psychologist" +"a refugee" +"a scholar" +"a scientist" +"a sculptor" +"a secretary" +"a serial divorcee" +"a shut-in" +"a stockbroker" +"a surgeon" +"a teacher" +"a teaching assistant" +"a therapist" +"a train conductor" +"a transporter" +"a veterinarian" +"a wedding planner" +"a writer" +"a zookeeper" +"an actress" +"an air hostess" +"an animator" +"an archaeologist" +"an architect" +"an artist" +"an assassin" +"an astronaut" +"an economist" +"an editor" +"an engineer" +"an escort" +"an estate agent" +"an investor" +"an MS pilot" +"an office worker" +"an orchestra conductor" +"retired" +"unemployed" + +App.Data.Careers.General.uneducated +"a baker" +"a barber" +"a barista" +"a bartender" +"a beekeeper" +"a beggar" +"a blacksmith" +"a blogger" +"a bodyguard" +"a bouncer" +"a bounty hunter" +"a boxer" +"a brewer" +"a bullfighter" +"a bus driver" +"a butcher" +"a butler" +"a camgirl" +"a camp counselor" +"a camwhore" +"a candlestick maker" +"a caregiver" +"a carpenter" +"a cashier" +"a charity worker" +"a chauffeur" +"a cheerleader" +"a chiropractor" +"a clown" +"a cobbler" +"a cocktail waitress" +"a comedian" +"a con artist" +"a construction worker" +"a cook" +"a cowgirl" +"a criminal" +"a croupier" +"a cum dump" +"a dairy worker" +"a dancer" +"a delivery woman" +"a dominatrix" +"a driller" +"a drug mule" +"a factory worker" +"a farm laborer" +"a farmer's daughter" +"a farmer" +"a firefighter" +"a fisherwoman" +"a florist" +"a fortune teller" +"a gang leader" +"a gang member" +"a gardener" +"a gravedigger" +"a groomer" +"a gymnast" +"a handmaiden" +"a hotel manager" +"a house DJ" +"a housewife" +"a hunter" +"a janitor" +"a landlady" +"a launderer" +"a law enforcement officer" +"a lifeguard" +"a local news anchor" +"a lumberjack" +"a magician's assistant" +"a maid" +"a mail carrier" +"a mail-order bride" +"a masseuse" +"a meat toilet" +"a medic" +"a medium" +"a messenger" +"a midwife" +"a milkmaid" +"a mime" +"a miner" +"a missionary" +"a mistress" +"a model" +"a mortician" +"a musician" +"a nanny" +"a nurse" +"a paramedic" +"a park ranger" +"a party girl" +"a peddler" +"a personal trainer" +"a pimp" +"a pirate" +"a plumber" +"a political activist" +"a prison guard" +"a prisoner" +"a procuress" +"a prostitute" +"a racing driver" +"a radio show host" +"a rancher" +"a receptionist" +"a referee" +"a refugee" +"a repairman" +"a revolutionary" +"a ride attendant" +"a roadie" +"a rodeo star" +"a sailor" +"a saleswoman" +"a school nurse" +"a seamstress" +"a secretary" +"a security guard" +"a service worker" +"a shepherd" +"a shrine maiden" +"a soldier" +"a stage magician" +"a street performer" +"a street vendor" +"a stripper" +"a student" +"a student athlete" +"a stuntwoman" +"a switchboard operator" +"a tailor" +"a talent scout" +"a taxi driver" +"a teacher" +"a tour guide" +"a trophy wife" +"a truck driver" +"a waitress" +"a weathergirl" +"a welder" +"a wet nurse" +"a whaler" +"a wrestler" +"a zookeeper" +"an acrobat" +"an actress" +"an arcade attendant" +"an artist" +"an aspiring pop star" +"an athlete" +"an electrician" +"an enforcer" +"an escort" +"an exotic dancer" +"an exterminator" +"an innkeeper" +"an installation technician" +"an office worker" +"an orderly" +"homeless" +"in a militia" +"retired" +"unemployed" + +App.Data.Careers.General.grateful "a beggar" "a drug mule" "a peddler" @@ -63,7 +505,7 @@ setup.gratefulCareers "homeless" "unemployed" -setup.menialCareers +App.Data.Careers.General.menial "a baker" "a blacksmith" "a bus driver" @@ -129,7 +571,7 @@ setup.menialCareers "an installation technician" "an intern" -setup.entertainmentCareers +App.Data.Careers.General.entertainment "a ballerina" "a blogger" "a camgirl" @@ -166,7 +608,8 @@ setup.entertainmentCareers "an artist" "an athlete" -setup.whoreCareers +App.Data.Careers.General.whore +"a bimbo" "a child prostitute" "a criminal" "a cum dump" @@ -188,15 +631,7 @@ setup.whoreCareers "an escort" "an exotic dancer" -setup.servantCareers -"a butler" -"a cook" -"a handmaiden" -"a housewife" -"a maid" -"a shrine maiden" - -setup.HGCareers +App.Data.Careers.Leader.HG "a captain" "a corporate executive" "a director" @@ -213,7 +648,7 @@ setup.HGCareers "a slaver" "a student council president" -setup.madamCareers + App.Data.Careers.Leader.madam "a banker" "a business owner" "a businessman" @@ -229,7 +664,7 @@ setup.madamCareers "a stockbroker" "an innkeeper" -setup.DJCareers + App.Data.Careers.Leader.DJ "a classical dancer" "a classical musician" "a dancer" @@ -241,7 +676,7 @@ setup.DJCareers "an idol" "an orchestra conductor" -setup.bodyguardCareers + App.Data.Careers.Leader.bodyguard "a bodyguard" "a boxer" "a bully hunter" @@ -261,7 +696,7 @@ setup.bodyguardCareers "in a militia" "spec ops" -setup.wardenessCareers + App.Data.Careers.Leader.wardeness "a bouncer" "a bounty hunter" "a bully" @@ -279,7 +714,7 @@ setup.wardenessCareers "an enforcer" "an orderly" -setup.nurseCareers + App.Data.Careers.Leader.nurse "a chemist" "a chiropractor" "a coroner" @@ -298,7 +733,7 @@ setup.nurseCareers "a school nurse" "a surgeon" -setup.attendantCareers + App.Data.Careers.Leader.attendant "a barber" "a cosmetologist" "a counselor" @@ -315,14 +750,14 @@ setup.attendantCareers "a therapist" "a yoga instructor" -setup.matronCareers + App.Data.Careers.Leader.matron "a babysitter" "a nanny" "a practitioner" "a wet nurse" "an au pair" -setup.milkmaidCareers + App.Data.Careers.Leader.milkmaid "a cowgirl" "a dairy worker" "a farmer's daughter" @@ -330,7 +765,7 @@ setup.milkmaidCareers "a shepherd" "a veterinarian" -setup.farmerCareers + App.Data.Careers.Leader.farmer "a beekeeper" "a bullfighter" "a farmer" @@ -339,7 +774,7 @@ setup.farmerCareers "a rodeo star" "a zookeeper" -setup.stewardessCareers + App.Data.Careers.Leader.stewardess "a barista" "a bartender" "a brewer" @@ -363,7 +798,7 @@ setup.stewardessCareers "an investor" "an office worker" -setup.schoolteacherCareers + App.Data.Careers.Leader.schoolteacher "a child prodigy" "a coach" "a dean" @@ -381,7 +816,7 @@ setup.schoolteacherCareers "an astronaut" "an economist" -setup.recruiterCareers + App.Data.Careers.Leader.recruiter "a club recruiter" "a college scout" "a con artist" @@ -397,36 +832,13 @@ setup.recruiterCareers "a talent scout" "retired" -setup.otherCareers -"a bioreactor" -"a breeder" -"a breeding bull" -"a businesswoman" -"a cat burglar" -"a criminal businesswoman" -"a dairy cow" -"a dairy slave" -"a drug pusher" -"a drug smuggler" -"a fence" -"a Fuckdoll" -"a lady courtier" -"a merchant" -"a murderer" -"a priest" -"a producer" -"a slave since birth" -"a slave" -"a smuggler" -"a trophy spouse" -"a wanderer" -"a well connected individual" -"an antislavery activist" -"an arcology owner" -"an arms dealer" -"being homeschooled by her parents" -"from a middle class family" -"from an upper class family" + App.Data.Careers.Leader.servant +"a butler" +"a cook" +"a handmaiden" +"a housewife" +"a maid" +"a shrine maiden" ID: diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js index c0159ceb1e40363fe3d02c90f290ad8926aefd46..3237b6715c38fbe0ccc74c8a364f1738b51b00bd 100644 --- a/src/002-config/fc-version.js +++ b/src/002-config/fc-version.js @@ -2,5 +2,5 @@ App.Version = { base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed. pmod: "3.8.4", commitHash: null, - release: 1112 // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. + release: 1115 // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js. }; diff --git a/src/002-config/fc-version.js_after.js b/src/002-config/z_after_fc-version.js similarity index 100% rename from src/002-config/fc-version.js_after.js rename to src/002-config/z_after_fc-version.js diff --git a/src/003-assets/CSS/general.css b/src/003-assets/CSS/general.css deleted file mode 100644 index f3467c9abe50b08fbfaa5a0fb83f80f058e02fe1..0000000000000000000000000000000000000000 --- a/src/003-assets/CSS/general.css +++ /dev/null @@ -1,13 +0,0 @@ -input:invalid{ - border-color: #900; - background-color: rgba(255, 0, 0, 0.25); -} - -input:focus:invalid { - outline: none; -} - -input:out-of-range { - background-color: rgba(255, 0, 0, 0.25); - border: 2px solid #900; -} diff --git a/src/003-assets/CSS/links.css b/src/003-assets/CSS/links.css deleted file mode 100644 index 5ea75b9308265e8e8d462f309f020e44ac34d277..0000000000000000000000000000000000000000 --- a/src/003-assets/CSS/links.css +++ /dev/null @@ -1,68 +0,0 @@ -.textWithTooltip { - position: relative; - display: inline-block; - text-decoration: underline; - text-decoration-color: lightblue; -} - -.textWithTooltip .tooltip { - visibility: hidden; - display: block; - font-size: smaller; - width: 20em; - margin-left: -10em; - background-color: rgb(29, 30, 32); - text-align: center; - border-radius: 3px; - padding: 3px; - position: absolute; - z-index: 1; - bottom: 100%; - left: 50%; -} - -.textWithTooltip .tooltip ul { - margin-left: 5px; - margin-right: 0px; - padding-left: 10px; - padding-right: 0px; - text-align: left; -} - -.textWithTooltip .tooltip::after { - content: ""; - position: absolute; - top: 100%; - left: 50%; - margin-left: -5px; - border-width: 5px; - border-style: solid; - border-color: #555 transparent transparent transparent; -} - -.textWithTooltip:hover .tooltip { - visibility: visible; - opacity: 1; - transition-delay: 0.3s; -} - -ul.choicesStrip { - display: inline; - list-style-type: none; - padding: 0mm; - margin-left: 0em; -} - -ul.choicesStrip li { - display: inline; -} - -ul.choicesStrip li + li:before { - content: " | "; -} - -a.disabled { - color: white; - pointer-events: none; - cursor: default; -} diff --git a/src/004-base/arcologyBuilding.js b/src/004-base/arcologyBuilding.js index e596b090e05544c2e994854a83e02f107ab581bb..72518f5534887576f354236cbd56026db8c957b9 100644 --- a/src/004-base/arcologyBuilding.js +++ b/src/004-base/arcologyBuilding.js @@ -237,7 +237,7 @@ App.Arcology.Cell.BaseCell = class extends App.Entity.Serializable { // BC code } - /** @return {App.Arcology.Cell.BaseCell} */ + /** @returns {App.Arcology.Cell.BaseCell} */ clone() { return new App.Arcology.Cell.BaseCell(this.owner)._init(this); } diff --git a/src/004-base/domPassage.js b/src/004-base/domPassage.js index 31887f0129b10160e43bd262a3ce7f3edbb46769..c5bc9037593c7ba8fc742b79c4f96208f4c952f9 100644 --- a/src/004-base/domPassage.js +++ b/src/004-base/domPassage.js @@ -21,6 +21,11 @@ App.DomPassage = class extends Passage { * @returns {Node} */ render() { - return this.callback(); + // In case the callback fails give out a nice error message instead of breaking completely. + try { + return this.callback(); + } catch (ex) { + return App.UI.DOM.formatException(ex); + } } }; diff --git a/src/005-passages/bcPassages.js b/src/005-passages/bcPassages.js new file mode 100644 index 0000000000000000000000000000000000000000..1cf82e5ac49e4725e18ce05fdaecdf64cf691620 --- /dev/null +++ b/src/005-passages/bcPassages.js @@ -0,0 +1,14 @@ +new App.DomPassage("Backwards Compatibility", + () => { + V.nextButton = "Continue"; + V.nextLink = "Main"; + V.returnTo = "Main"; + + App.Update.setNonexistentProperties(V, App.Data.defaultGameStateVariables); + + /* resetOnNGPlus contains half of the variables we need, but we use it politely here instead of forcing it so it fills in holes instead of overwriting data */ + App.Update.setNonexistentProperties(V, App.Data.resetOnNGPlus); + + return App.Update.backwardsCompatibility(); + } +); diff --git a/src/005-passages/endWeekPassages.js b/src/005-passages/endWeekPassages.js index 510a03aaa94a118e1d3745ea7d21e684f24cc5d9..b039a2bed3eb32f3585a4b7c80ac6461bed695eb 100644 --- a/src/005-passages/endWeekPassages.js +++ b/src/005-passages/endWeekPassages.js @@ -1,13 +1,29 @@ new App.DomPassage("Slave Assignments Report", () => { - V.nextLink = "Economics"; V.nextButton = "Continue"; + V.nextLink = "Economics"; + V.nextButton = "Continue"; const f = document.createDocumentFragment(); - App.UI.DOM.appendNewElement("h1", f, `${V.arcologies[0].name} Weekly Slave Report - Week ${V.week}`); - f.append(App.EndWeek.slaveAssignmentReport()); - App.UI.EndWeekAnim.end(); + try { + App.UI.DOM.appendNewElement("h1", f, `${V.arcologies[0].name} Weekly Slave Report - Week ${V.week}`); + f.append(App.EndWeek.slaveAssignmentReport()); + } finally { + // whatever happens, stop the end week animation so we at least know there is an error. + App.UI.EndWeekAnim.end(); + } return f; } ); + +new App.DomPassage("Next Week", + () => { + App.EndWeek.nextWeek(); + + // simulate <<goto "Main">> macro behaviour + setTimeout(() => Engine.play("Main"), Engine.minDomActionDelay); + + return document.createDocumentFragment(); + } +); diff --git a/src/005-passages/facilitiesPassages.js b/src/005-passages/facilitiesPassages.js index 0a372a4f922ae23e0d70ba36c8b93d31a79ab590..0fcb73572a5b57709a5a37271459a350aeddc86b 100644 --- a/src/005-passages/facilitiesPassages.js +++ b/src/005-passages/facilitiesPassages.js @@ -68,3 +68,12 @@ new App.DomPassage("Rules Assistant", return div; }, ["jump-to-safe", "jump-from-safe"] ); + +new App.DomPassage("Toy Shop", + () => { + V.nextButton = "Back"; + V.nextLink = "Manage Penthouse"; + + return App.UI.toyShop(); + }, ["jump-to-safe", "jump-from-safe"] +); diff --git a/src/005-passages/interactPassages.js b/src/005-passages/interactPassages.js index 96a797b5b1d1dff2ac02747d0d20545f80d1a6fd..70eadbd4824d506ed94f06e39785c4d38edf62a6 100644 --- a/src/005-passages/interactPassages.js +++ b/src/005-passages/interactPassages.js @@ -54,3 +54,12 @@ new App.DomPassage( return huskSwapSelection(getSlave(V.AS)); } ); + +new App.DomPassage( + "Agent Company", + () => { + V.nextButton = "Continue"; + V.nextLink = "Neighbor Interact"; + return App.UI.SlaveInteract.agentCompany(getSlave(V.AS)); + }, ["jump-from-safe"] +); diff --git a/src/005-passages/managePassages.js b/src/005-passages/managePassages.js index b1d1e2f7731581e4b97d0ca64133c3d2704a5af6..e05ee918eb52a2180ce1368dbad4626d38f79458 100644 --- a/src/005-passages/managePassages.js +++ b/src/005-passages/managePassages.js @@ -1 +1,11 @@ +new App.DomPassage("Main", + () => { + V.nextButton = "END WEEK"; + V.nextLink = "End Week"; + V.encyclopedia = "How to Play"; + + return App.MainView.full(); + }, ["jump-to-safe", "jump-from-safe"] +); + new App.DomPassage("Future Society", () => { return App.UI.fsPassage(); }, ["jump-to-safe", "jump-from-safe"]); diff --git a/src/005-passages/slaveMarketPassages.js b/src/005-passages/slaveMarketPassages.js index 9ea818ab7347c1648da5d39668e6af1a7ad1b56a..2969e72df114a05d57ee88546bc90025a0023870 100644 --- a/src/005-passages/slaveMarketPassages.js +++ b/src/005-passages/slaveMarketPassages.js @@ -1,4 +1,10 @@ -new App.DomPassage("Market", () => App.Markets[V.market.slaveMarket](), ["jump-from-safe"]); +new App.DomPassage("Market", + () => { + const span = App.UI.DOM.makeElement("span", App.Markets[V.market.slaveMarket]()); + span.id = "slave-markets"; + return span; + }, ["jump-from-safe"] +); new App.DomPassage("Buy Slaves", () => { diff --git a/src/art/vector/VectorArtJS.js b/src/art/vector/VectorArtJS.js index 05f494ec1451c625adb5cec15ef0962e1ffd8c42..d58a6ce3ed272f59a680a1cada7789984ef2df1e 100644 --- a/src/art/vector/VectorArtJS.js +++ b/src/art/vector/VectorArtJS.js @@ -1771,7 +1771,7 @@ App.Art.vectorArtElement = (function() { } else if (slave.vaginalAccessory === "long, huge dildo") { svgQueue.add("Art_Vector_Dildo_Huge_Long"); } - } /* else if (slave.vaginalAccessory === "bullet vibrator" || slave.vaginalAccessory === "smart bullet vibrator") { + } /* else if (dildoWidth(slave) === 0) { svgQueue.add("Art_Vector_Bullet_Vibrator"); } */ } diff --git a/src/data/backwardsCompatibility/BackwardsCompatibility.tw b/src/data/backwardsCompatibility/BackwardsCompatibility.tw deleted file mode 100644 index 0a3ff856077b2e720b146f89553a7100f218f495..0000000000000000000000000000000000000000 --- a/src/data/backwardsCompatibility/BackwardsCompatibility.tw +++ /dev/null @@ -1,12 +0,0 @@ -:: Backwards Compatibility [nobr] - -<<set $nextButton = "Continue", $nextLink = "Main", $returnTo = "Main">> - -<<run App.Update.setNonexistentProperties(V, App.Data.defaultGameStateVariables)>> - -/* resetOnNGPlus contains half of the variables we need, but we use it politely here instead of forcing it so it fills in holes instead of overwriting data */ -<<run App.Update.setNonexistentProperties(V, App.Data.resetOnNGPlus)>> -<span id="backwards-compatibility"></span> -<script> - App.Update.backwardsCompatibility(); -</script> \ No newline at end of file diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js index f34d42d3980f5448940186ea22ba0ddda9220429..19182f0e0c937bc90b3f445ca0c4705927ffdd14 100644 --- a/src/data/backwardsCompatibility/backwardsCompatibility.js +++ b/src/data/backwardsCompatibility/backwardsCompatibility.js @@ -53,64 +53,68 @@ App.Update.setExistentProperties = function(obj, array) { } }; +/** + * @returns {DocumentFragment} + */ App.Update.backwardsCompatibility = function() { + const f = document.createDocumentFragment(); let div; - jQuery('#backwards-compatibility').empty(); try { - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Check for old version... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.oldVersions(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Updating gene pool records... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.genePoolRecords(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Updating global variables... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.globalVariables(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Updating slave variables... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.slaveVariables(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Updating slave records... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.slaveRecords(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Updating Rule Assistant data... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.RAassistantData(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Checking for old arcology locations... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.arcologyLocation(div); - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Checking for old variables... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.autoshred(div); // leave this at the bottom of BC - div = document.createElement('div'); + div = document.createElement("div"); div.append(`Cleaning up... `); - jQuery('#backwards-compatibility').append(div); + f.append(div); App.Update.cleanUp(div); App.UI.SlaveSummary.settingsChanged(); } catch (error) { - div = document.createElement('p'); - div.className = "red"; + div = document.createElement("p"); + div.className = "error"; div.textContent = `Backwards compatibility has failed for your save. Please upload your save to https://gitgud.io/pregmodfan/fc-pregmod/ with notes on what went wrong so that we can fix the backwards compatibility process for everyone. Thank you!`; - jQuery('#backwards-compatibility').append(div); + f.append(div); + f.append(App.UI.DOM.formatException(error)); State.restore(); - throw (error); // rethrow the exception to SugarCube so we get a fancy stack trace } + return f; }; App.Update.globalVariables = function(node) { @@ -148,6 +152,14 @@ App.Update.globalVariables = function(node) { if (jQuery.isEmptyObject(V.scarDesign)) { V.scarDesign = {primary: "generic", local: "generic"}; } + if (V.customItem.hasOwnProperty("dildos")) { + V.customItem.vaginalAccessory = V.customItem.dildos; + delete V.customItem.dildos; + } + if (V.customItem.hasOwnProperty("buttPlugs")) { + V.customItem.buttplug = V.customItem.buttPlugs; + delete V.customItem.buttPlugs; + } if (V.releaseID <= 1110) { V.researchLab.tasks = V.researchLab.tasks.filter((t) => (!(t.hasOwnProperty("slaveID")) || Object.keys(V.slaveIndices).includes(t.slaveID))); } diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js index 2e2b2f24c18820e9a5c1c5fe6248358faa5ba9ed..25f92ba850c43cdeb62058b216ee8d1dee109ecd 100644 --- a/src/data/backwardsCompatibility/datatypeCleanup.js +++ b/src/data/backwardsCompatibility/datatypeCleanup.js @@ -609,6 +609,9 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() { if (typeof slave.boobShape !== "string") { slave.boobShape = "normal"; } + if (slave.boobShape === "spherical" && slave.boobsImplants === 0) { + slave.boobShape = "normal"; + } if (typeof slave.nipples !== "string") { slave.nipples = "cute"; } @@ -2097,6 +2100,30 @@ App.Entity.Utils.RARuleDatatypeCleanup = function() { break; } delete set.eyeColor; + + // Look for and remove pieces of a rule that would apply an accessory that is not in data. A common example is the old "chastity" accessories, which have now been moved to a different system + const vaginalAccessories = new Set([ + "virginAccessory", + "aVirginAccessory", + "vaginalAccessory", + ]); + + for (const acc of vaginalAccessories) { + if (set[acc] && !(App.Data.vaginalAccessory.get(set[acc]) || V.customItem.vaginalAccessory.get(set[acc]))) { + set[acc] = null; + } + } + + const dickAccessories = new Set([ + "aVirginDickAccessory", + "dickAccessory" + ]); + + for (const acc of dickAccessories) { + if (set[acc] && !(App.Data.slaveWear.dickAccessory.get(set[acc]))) { + set[acc] = null; + } + } } }(); diff --git a/src/data/backwardsCompatibility/updateSlaveObject.js b/src/data/backwardsCompatibility/updateSlaveObject.js index 7567a248fe8e0bf378e875e673bb34761204e9b9..7b93adc17b724f159287a3983dc643f17b736e90 100644 --- a/src/data/backwardsCompatibility/updateSlaveObject.js +++ b/src/data/backwardsCompatibility/updateSlaveObject.js @@ -926,30 +926,29 @@ App.Update.Slave = function(slave, genepool = false) { slave.pregControl = "labor suppressors"; } - if (slave.chastityAnus === undefined || slave.chastityPenis === undefined || slave.chastityVagina === undefined) { - if (slave.dickAccessory === "combined chastity") { - slave.chastityAnus = 1; - slave.chastityPenis = 1; - slave.dickAccessory = "none"; - } else if (slave.vaginalAccessory === "combined chastity") { - slave.chastityAnus = 1; - slave.chastityVagina = 1; - slave.vaginalAccessory = "none"; - } else if (slave.dickAccessory === "anal chastity" || slave.vaginalAccessory === "anal chastity") { - slave.chastityAnus = 1; - slave.dickAccessory = "none"; - slave.vaginalAccessory = "none"; - } else if (slave.dickAccessory === "chastity") { - slave.chastityPenis = 1; - slave.dickAccessory = "none"; - } else if (slave.vaginalAccessory === "chastity belt") { - slave.chastityVagina = 1; - slave.vaginalAccessory = "none"; - } else { - slave.chastityAnus = 0; - slave.chastityPenis = 0; - slave.chastityVagina = 0; - } + // Fix dickAccessory + if (slave.dickAccessory === "combined chastity") { + slave.chastityAnus = 1; + slave.chastityPenis = 1; + slave.dickAccessory = "none"; + } else if (slave.dickAccessory === "chastity") { + slave.chastityPenis = 1; + slave.dickAccessory = "none"; + } else if (slave.dickAccessory === "anal chastity") { + slave.chastityAnus = 1; + slave.dickAccessory = "none"; + } + // Fix vaginalAccessory + if (slave.vaginalAccessory === "combined chastity") { + slave.chastityAnus = 1; + slave.chastityVagina = 1; + slave.vaginalAccessory = "none"; + } else if (slave.vaginalAccessory === "chastity belt") { + slave.chastityVagina = 1; + slave.vaginalAccessory = "none"; + } else if (slave.vaginalAccessory === "anal chastity") { + slave.chastityAnus = 1; + slave.vaginalAccessory = "none"; } if (slave.rules !== undefined && slave.rules.rest === undefined) { diff --git a/src/descriptions/familySummaries.js b/src/descriptions/familySummaries.js index dd7b45d6fa77566f651aa9a7319ee3d47cf5cb11..f46d88c11776178917116fd91cec4750a7decdbf 100644 --- a/src/descriptions/familySummaries.js +++ b/src/descriptions/familySummaries.js @@ -53,6 +53,7 @@ App.Desc.family = (function() { if (character === V.PC) { return PCFamilySummary(); } else { + // FIXME: Argument of type 'HumanState' is not assignable to parameter of type 'SlaveState'. return slaveFamilySummary(character); } } @@ -497,7 +498,7 @@ App.Desc.family = (function() { } else if (slave.inbreedingCoeff >= 0.25) { r.push("very"); } else if (slave.inbreedingCoeff >= 0.125) { - + // TODO: ? } else if (slave.inbreedingCoeff >= 0.0625) { r.push("somewhat"); } else { diff --git a/src/descriptions/officeDescription.js b/src/descriptions/officeDescription.js index 4ecac53c275b09bf69800c17cb5e04b75ea9c2ce..6c38742fa843b58a7abbf5b013e0ec97dfb2e539 100644 --- a/src/descriptions/officeDescription.js +++ b/src/descriptions/officeDescription.js @@ -454,7 +454,7 @@ App.Desc.officeDescription = function(lastElement) { } r.push(` face stares back at you.`); if (V.playerAging !== 0 && V.PC.birthWeek === 51) { - r.push(`You'll be turning ${V.V.PC.actualAge + 1} next week.`); + r.push(`You'll be turning ${V.PC.actualAge + 1} next week.`); } r.push(App.Desc.Player.boobs(), App.Desc.Player.belly(), App.Desc.Player.crotch(), App.Desc.Player.butt()); diff --git a/src/endWeek/economics/personalNotes.js b/src/endWeek/economics/personalNotes.js index 3a9cfbff16870944e742b4750e00cde2675145c9..c7111acd02effe3fd1a3be98cb72ae0cf243ca4c 100644 --- a/src/endWeek/economics/personalNotes.js +++ b/src/endWeek/economics/personalNotes.js @@ -159,7 +159,7 @@ App.EndWeek.personalNotes = function() { if ((V.PC.boobs - V.PC.boobsImplant) < boobTarget) { r.push(`${His} breasts <span class="lime">greatly swell</span> to meet the upcoming demand.`); V.PC.boobs += 100; - if (V.PC.boobShape !== "saggy" && V.PC.preg > V.PC.pregData.normalBirth/1.25 && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone")) { + if (V.PC.boobShape !== "saggy" && V.PC.preg > V.PC.pregData.normalBirth/1.25 && (V.PC.boobsImplant / V.PC.boobs < 0.5) && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone")) { r.push(`${His} immensely engorged <span class="orange">breasts become saggy</span> in the last stages of ${his} pregnancy as ${his} body undergoes changes in anticipation of the forthcoming birth.`); V.PC.boobShape = "saggy"; } @@ -178,7 +178,7 @@ App.EndWeek.personalNotes = function() { } else if ((V.PC.pregType >= 10)) { if (random(1,100) > 80 && ((V.PC.boobs - V.PC.boobsImplant) < boobTarget)) { V.PC.boobs += 50; - if (V.PC.boobShape !== "saggy" && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone")) { + if (V.PC.boobShape !== "saggy" && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone") && (V.PC.boobsImplant / V.PC.boobs < 0.5)) { if (V.PC.preg > random(V.PC.pregData.normalBirth/1.25, V.PC.pregData.normalBirth*2.05)) { r.push(`${His} swollen <span class="orange">breasts become saggy</span> in the last stages of ${his} pregnancy as ${his} body undergoes changes in anticipation of the forthcoming birth.`); V.PC.boobShape = "saggy"; @@ -258,7 +258,7 @@ App.EndWeek.personalNotes = function() { } } } - if (V.PC.boobShape !== "saggy" && V.PC.preg > random(V.PC.pregData.normalBirth / 1.25, V.PC.pregData.normalBirth * 2.5) && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone")) { + if (V.PC.boobShape !== "saggy" && V.PC.preg > random(V.PC.pregData.normalBirth / 1.25, V.PC.pregData.normalBirth * 2.5) && (V.PC.boobsImplant / V.PC.boobs < 0.5) && (V.PC.breastMesh !== 1) && (V.PC.drugs !== "sag-B-gone")) { r.push(`Your <span class="orange">breasts become saggy</span> in the last stages of pregnancy as your body undergoes changes in anticipation of the forthcoming birth.`); V.PC.boobShape = "saggy"; } diff --git a/src/endWeek/economics/reputation.js b/src/endWeek/economics/reputation.js index 66c3e8668376c8c6a44afdb57440fcdb5993ebf8..bbc9d8d15a1aedda1e9ffe6d5d1dcb8ec90b6a86 100644 --- a/src/endWeek/economics/reputation.js +++ b/src/endWeek/economics/reputation.js @@ -638,7 +638,7 @@ App.EndWeek.reputation = function() { if (V.slaves.length > 20 && V.cash > 50000) { r.push(`Society <span class="green">strongly approves</span> of your great wealth and prosperity, as is only fitting for an`); if (V.PC.customTitle) { - r.push(`${V.PC.customTitle}`); + r.push(`${V.PC.customTitle}.`); } else if (V.PC.title === 1) { r.push(`proper Imperial noble.`); } else { diff --git a/src/endWeek/nextWeek/nextWeek.tw b/src/endWeek/nextWeek/nextWeek.tw deleted file mode 100644 index 0502b990dafac6a88e36ae42cd9bdc901abcf735..0000000000000000000000000000000000000000 --- a/src/endWeek/nextWeek/nextWeek.tw +++ /dev/null @@ -1,5 +0,0 @@ -:: Next Week [nobr] - -<<run App.EndWeek.nextWeek()>> - -<<goto "Main">> diff --git a/src/endWeek/reports/clinicReport.js b/src/endWeek/reports/clinicReport.js index 65dec26f6805a49a127d461c23cdbdbf1f95fc32..4583fe9839926d0ad1e958d41ef58a852817cf20 100644 --- a/src/endWeek/reports/clinicReport.js +++ b/src/endWeek/reports/clinicReport.js @@ -135,7 +135,7 @@ App.EndWeek.clinicReport = function() { r.push(`It's not uncommon for ${him} to receive a load to the face; before long, <span class="fetish gain">${he} starts to enjoy the taste.</span>`); S.Nurse.fetish = "cumslut"; } else if (S.Nurse.fetish === "cumslut") { - r.push(`${canSmell(S.Nurse) ? `The smell of ${his2}` : `${His2}`} semen is irresistable to ${him} and sometimes ${he} can't help but`); + r.push(`${canSmell(S.Nurse) ? `The smell of ${his2}` : `${His2}`} semen is irresistible to ${him} and sometimes ${he} can't help but`); if (slave.chastityPenis === 0 && slave.rules.release.facilityLeader === 1) { r.push(`wrap ${his} lips around ${him2} and sample the stuff directly,`); seX(S.Nurse, "oral", slave, "penetrative"); diff --git a/src/endWeek/reports/spaReport.js b/src/endWeek/reports/spaReport.js index d0d4f0770c1b3f351f57f31453f46ce16c9829fb..d127e367b02fe02e9085e35fdfaa42c301f1e3cc 100644 --- a/src/endWeek/reports/spaReport.js +++ b/src/endWeek/reports/spaReport.js @@ -121,7 +121,7 @@ App.EndWeek.spaReport = function() { slave.intelligence = gp.intelligence - 30; } if (V.arcologies[0].FSPaternalist !== "unset" && V.arcologies[0].FSPaternalist > 0) { - curedArray.push(`Society <span class="green">strongly approves</span> of${slave.slaveName} being restored to sanity, which advances ideals about enlightened slaveownership.`); + curedArray.push(`Society <span class="green">strongly approves</span> of ${slave.slaveName} being restored to sanity, which advances ideals about enlightened slaveownership.`); V.arcologies[0].FSPaternalist += 0.01 * V.FSSingleSlaveRep; repX(2 * V.FSSingleSlaveRep * (V.arcologies[0].FSPaternalist / V.FSLockinLevel), "spa", slave); } diff --git a/src/endWeek/saAgent.js b/src/endWeek/saAgent.js index 3e126472438c6312fdfaed4f96861dfc108713bf..4e0e1d3e7b0e06180f4ba526acb1e2f624359aaa 100644 --- a/src/endWeek/saAgent.js +++ b/src/endWeek/saAgent.js @@ -45,6 +45,19 @@ App.SlaveAssignment.agent = function(slave) { slave.boobs += 10; } } + if (slave.breastMesh !== 1) { + if (slave.boobs - (slave.muscles * 30) > 5000 && slave.boobs <= 8000 && slave.boobsImplant / slave.boobs < .50) { + if (slave.physicalAge < random(10, 200)) { + if (slave.boobShape === "perky") { + slave.boobShape = "torpedo-shaped"; + } else if (slave.boobShape !== "saggy") { + slave.boobShape = "saggy"; + } + } + } else if (slave.boobsImplant / slave.boobs >= .90 && slave.boobs > 2000 && !["saggy", "downward-facing", "spherical"].includes(slave.boobShape) && random(1, 100) > 70) { + slave.boobShape = "spherical"; + } + } if (slave.buttImplantType === "string") { slave.buttImplant += 0.25; slave.butt += 0.25; @@ -235,7 +248,7 @@ App.SlaveAssignment.agent = function(slave) { if ((slave.geneMods.NCS === 0) && (random(1, 100) > 60)) { if ((slave.boobs - slave.boobsImplant) < boobTarget) { slave.boobs += 200; - if (slave.boobShape !== "saggy" && slave.preg > slave.pregData.normalBirth / 1.25 && (slave.breastMesh !== 1)) { + if (slave.boobShape !== "saggy" && slave.preg > slave.pregData.normalBirth / 1.25 && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { slave.boobShape = "saggy"; } } @@ -249,7 +262,7 @@ App.SlaveAssignment.agent = function(slave) { } else if ((slave.geneMods.NCS === 0) && (slave.pregType >= 10)) { if (random(1, 100) > 80 && ((slave.boobs - slave.boobsImplant) < boobTarget)) { slave.boobs += 100; - if (slave.boobShape !== "saggy" && (slave.breastMesh !== 1)) { + if (slave.boobShape !== "saggy" && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2)) { slave.boobShape = "saggy"; } @@ -258,7 +271,7 @@ App.SlaveAssignment.agent = function(slave) { } else if (((slave.geneMods.NCS === 0) && ((slave.boobs - slave.boobsImplant) < boobTarget))) { if (random(1, 100) > 80) { slave.boobs += 50; - if (slave.boobShape !== "saggy" && slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2.5) && (slave.breastMesh !== 1)) { + if (slave.boobShape !== "saggy" && slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2.5) && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { slave.boobShape = "saggy"; } } diff --git a/src/endWeek/saClothes.js b/src/endWeek/saClothes.js index 30075c19d6384c3c14d08d3fd865829da542269d..9f4f4c782a46a7e0ca4018925c1ec2a9e9021737 100644 --- a/src/endWeek/saClothes.js +++ b/src/endWeek/saClothes.js @@ -71,7 +71,7 @@ App.SlaveAssignment.clothes = (function() { slave.vaginalAccessory = "none"; slave.vaginalAttachment = "none"; } else { - if (["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory)) { + if (dildoWidth(slave) === 0) { slave.vaginalAttachment = "none"; } } @@ -241,7 +241,7 @@ App.SlaveAssignment.clothes = (function() { r.push(`The outfit ${he}'s wearing constantly give ${him} little twinges of pain, <span class="hotpink">titillating ${him}.</span>`); slave.devotion += 2; } else if (slave.devotion <= 20 && slave.trust >= -50) { - r.push(`The outfit ${he}'s wearing keep ${him} <span class="hotpink">servile</span> and <span class="gold">afraid.</span>`); + r.push(`The outfit ${he}'s wearing keeps ${him} <span class="hotpink">servile</span> and <span class="gold">afraid.</span>`); slave.devotion += 1; slave.trust -= 1; if (slave.fetish === "masochist" && slave.fetishKnown === 0) { @@ -920,9 +920,10 @@ App.SlaveAssignment.clothes = (function() { * */ function vaginaAccessories(slave) { + const dildo = App.Data.vaginalAccessory.get(slave.vaginalAccessory) || V.customItem.vaginalAccessory.get(slave.vaginalAccessory); if (slave.vaginalAccessory !== "none") { - if (slave.vaginalAccessory === "bullet vibrator" || slave.vaginalAccessory === "smart bullet vibrator") { - r.push(`Constantly wearing a bullet vibrator`); + if (dildo.width === 0) { + r.push(`Constantly wearing a ${slave.vaginalAccessory}`); if (slave.devotion < 20) { r.push(`habituates ${him} to sexual slavery and <span class="hotpink">increases ${his} submissiveness.</span>`); slave.devotion += 2; @@ -930,7 +931,7 @@ App.SlaveAssignment.clothes = (function() { r.push(`reminds ${him} of ${his} place and <span class="hotpink">increases ${his} devotion to you.</span>`); slave.devotion++; } - } else if (slave.vaginalAccessory === "dildo") { + } else if (dildo.width === 1) { if (slave.vagina < 1 && jsRandom(1, 100) > 50) { r.push(`Constantly wearing a dildo in ${his} virgin pussy <span class="lime">gets it used to penetration.</span>`); slave.vagina += 1; @@ -943,29 +944,16 @@ App.SlaveAssignment.clothes = (function() { slave.sexualFlaw = "none"; } } - } else if (slave.vaginalAccessory === "long dildo") { - if (slave.vagina < 1 && jsRandom(1, 100) > 50) { - r.push(`Constantly wearing a dildo in ${his} virgin pussy <span class="lime">gets it used to penetration.</span>`); - slave.vagina += 1; - } else { - r.push(`${His} pussy easily accommodates the dildo ${he}'s required to wear.`); - } - if (slave.fuckdoll === 0) { - if (slave.fetish !== "mindbroken") { - if (slave.sexualFlaw === "hates penetration" && jsRandom(1, 100) > 50) { - r.push(`The habit <span class="green">reduces ${his} dislike of having ${his} pussy filled.</span>`); - slave.sexualFlaw = "none"; - } - if (slave.sexualQuirk === "size queen") { - r.push(`Being able to hold such a long dildo is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); - slave.devotion += 2; - } else { - r.push(`It penetrates ${his} cervix causing ${him} tremendous discomfort, making ${him} a little <span class="gold">less trusting</span> of you.`); - slave.trust -= 1; - } + if (dildo.length > 1) { + if (slave.sexualQuirk === "size queen") { + r.push(`Being able to hold such a long dildo is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); + slave.devotion += 2; + } else { + r.push(`It penetrates ${his} cervix causing ${him} tremendous discomfort, making ${him} a little <span class="gold">less trusting</span> of you.`); + slave.trust -= 1; } } - } else if (slave.vaginalAccessory === "large dildo") { + } else if (dildo.width === 2) { if (slave.vagina < 3) { if (jsRandom(1, 4) === 1) { r.push(`Constantly wearing a large dildo in ${his} pussy <span class="lime">stretches it out.</span>`); @@ -979,105 +967,93 @@ App.SlaveAssignment.clothes = (function() { if (slave.fuckdoll === 0) { if (slave.fetish !== "mindbroken") { if (slave.vagina < 2) { - r.push(`The big dildo in ${his} tight cunt`); - if (slave.sexualQuirk === "size queen") { - r.push(`is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); - slave.devotion += 2; - } else { - r.push(`<span class="hotpink">breaks ${him} to sexual slavery</span> slightly.`); - slave.devotion += 1; - } - if (slave.vagina === 1) { - r.push(`It stretches ${his} tight cunt to soreness by the end of every day, so it also makes ${him} a little <span class="gold">less trusting</span> of you.`); - slave.trust -= 1; - } - } - } - } - } else if (slave.vaginalAccessory === "long, large dildo") { - if (slave.vagina < 3) { - if (jsRandom(1, 4) === 1) { - r.push(`Constantly wearing a large dildo in ${his} pussy <span class="lime">stretches it out.</span>`); - slave.vagina += 1; - } else { - r.push(`The large dildo ${he}'s required to wear is a stretch for ${his} cunt, but pussies are resilient and ${he}rs isn't seriously affected.`); - } - } else { - r.push(`${His} pussy accommodates the large dildo ${he}'s required to wear.`); - } - if (slave.vagina < 2) { - if (slave.fuckdoll === 0) { - if (slave.fetish !== "mindbroken") { - r.push(`The big, long dildo in ${his} tight cunt`); - if (slave.sexualQuirk === "size queen") { - r.push(`is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); - slave.devotion += 2; + if (dildo.length === 1) { + r.push(`The big dildo in ${his} tight cunt`); + if (slave.sexualQuirk === "size queen") { + r.push(`is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); + slave.devotion += 2; + } else { + r.push(`<span class="hotpink">breaks ${him} to sexual slavery</span> slightly.`); + slave.devotion += 1; + } + if (slave.vagina === 1) { + r.push(`It stretches ${his} tight cunt to soreness by the end of every day, so it also makes ${him} a little <span class="gold">less trusting</span> of you.`); + slave.trust -= 1; + } } else { - r.push(`<span class="hotpink">breaks ${him} to sexual slavery</span> slightly. It also penetrates ${his} cervix, causing ${him} tremendous discomfort, and making ${him} a little <span class="gold">less trusting</span> of you.`); - slave.devotion += 1; - slave.trust -= 1; - } - if (slave.vagina === 1) { - r.push(`It stretches ${his} tight cunt to soreness by the end of every day, so it also makes ${him} a little <span class="gold">less trusting</span> of you.`); - slave.trust -= 1; + r.push(`The big, long dildo in ${his} tight cunt`); + if (slave.sexualQuirk === "size queen") { + r.push(`is a <span class="hotpink">point of pride</span> for the ostentatious size queen.`); + slave.devotion += 2; + } else { + r.push(`<span class="hotpink">breaks ${him} to sexual slavery</span> slightly. It also penetrates ${his} cervix, causing ${him} tremendous discomfort, and making ${him} a little <span class="gold">less trusting</span> of you.`); + slave.devotion += 1; + slave.trust -= 1; + } + if (slave.vagina === 1) { + r.push(`It stretches ${his} tight cunt to soreness by the end of every day, so it also makes ${him} a little <span class="gold">less trusting</span> of you.`); + slave.trust -= 1; + } } } } } - } else if (slave.vaginalAccessory === "huge dildo") { - if (slave.vagina < 4) { - if (slave.fuckdoll === 0) { - if (slave.fetish !== "mindbroken") { - if (slave.sexualQuirk === "size queen") { - r.push(`${He} thinks of the massive dildo stretching out ${his} womanhood as <span class="lime">preparation for the biggest cocks,</span> and <span class="hotpink">looks forward</span> to take anything — dicks, hands, truly anything — inside ${his} newly capacious cunt.`); - slave.devotion += 4; - } else if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} gets off on the agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo. The terrible combination of pain and pleasure <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); - slave.devotion += 5; - slave.trust -= 5; - } else if (slave.fetish === "submissive" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} submits to the agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo. Having ${his} hole ruined at your whim <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); - slave.devotion += 5; - slave.trust -= 5; - } else { - r.push(`The agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo fills ${him} with <span class="mediumorchid">resentment</span> and <span class="gold">fear.</span>`); - slave.devotion -= 5; - slave.trust -= 5; + } else if (dildo.width === 3) { + if (dildo.length === 1) { + if (slave.vagina < 4) { + if (slave.fuckdoll === 0) { + if (slave.fetish !== "mindbroken") { + if (slave.sexualQuirk === "size queen") { + r.push(`${He} thinks of the massive dildo stretching out ${his} womanhood as <span class="lime">preparation for the biggest cocks,</span> and <span class="hotpink">looks forward</span> to take anything — dicks, hands, truly anything — inside ${his} newly capacious cunt.`); + slave.devotion += 4; + } else if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} gets off on the agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo. The terrible combination of pain and pleasure <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); + slave.devotion += 5; + slave.trust -= 5; + } else if (slave.fetish === "submissive" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} submits to the agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo. Having ${his} hole ruined at your whim <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); + slave.devotion += 5; + slave.trust -= 5; + } else { + r.push(`The agony of having ${his} cunt <span class="lime">permanently stretched</span> by a huge dildo fills ${him} with <span class="mediumorchid">resentment</span> and <span class="gold">fear.</span>`); + slave.devotion -= 5; + slave.trust -= 5; + } } } + slave.vagina += 1; + } else { + r.push(`${His} cavernous pussy accommodates the huge dildo ${he}'s required to wear.`); } - slave.vagina += 1; - } else { - r.push(`${His} cavernous pussy accommodates the huge dildo ${he}'s required to wear.`); - } - } else if (slave.vaginalAccessory === "long, huge dildo") { - if (slave.vagina < 4) { - if (slave.fuckdoll === 0) { - if (slave.fetish !== "mindbroken") { - if (slave.sexualQuirk === "size queen") { - r.push(`${He} thinks of the massive dildo stretching out ${his} womanhood and stomach as <span class="lime">preparation for the biggest cocks,</span> and <span class="hotpink">looks forward</span> to take anything — dicks, hands, arms, truly anything — inside ${his} newly capacious cunt.`); - slave.devotion += 4; - } else if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} gets off on the agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo. The terrible combination of pain and pleasure <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); - slave.devotion += 5; - slave.trust -= 5; - } else if (slave.fetish === "submissive" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} submits to the agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo. Having ${his} hole and cervix ruined at your whim <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); - slave.devotion += 5; - slave.trust -= 5; - } else { - r.push(`The agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo fills ${him} with <span class="mediumorchid">resentment</span> and <span class="gold">fear.</span>`); - slave.devotion -= 5; - slave.trust -= 5; + } else { + if (slave.vagina < 4) { + if (slave.fuckdoll === 0) { + if (slave.fetish !== "mindbroken") { + if (slave.sexualQuirk === "size queen") { + r.push(`${He} thinks of the massive dildo stretching out ${his} womanhood and stomach as <span class="lime">preparation for the biggest cocks,</span> and <span class="hotpink">looks forward</span> to take anything — dicks, hands, arms, truly anything — inside ${his} newly capacious cunt.`); + slave.devotion += 4; + } else if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} gets off on the agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo. The terrible combination of pain and pleasure <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); + slave.devotion += 5; + slave.trust -= 5; + } else if (slave.fetish === "submissive" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} submits to the agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo. Having ${his} hole and cervix ruined at your whim <span class="hotpink">breaks ${his} will</span> but fills ${him} with <span class="gold">fear.</span>`); + slave.devotion += 5; + slave.trust -= 5; + } else { + r.push(`The agony of having ${his} cunt <span class="lime">permanently stretched</span> and ${his} cervix penetrated by a huge dildo fills ${him} with <span class="mediumorchid">resentment</span> and <span class="gold">fear.</span>`); + slave.devotion -= 5; + slave.trust -= 5; + } } } + slave.vagina += 1; + } else { + r.push(`${His} cavernous pussy accommodates the huge dildo ${he}'s required to wear.`); } - slave.vagina += 1; - } else { - r.push(`${His} cavernous pussy accommodates the huge dildo ${he}'s required to wear.`); } } - if (slave.vaginalAccessory === "long, huge dildo" || slave.vaginalAccessory === "long, large dildo" || slave.vaginalAccessory === "long dildo") { + if (dildo.length > 1) { if ((slave.preg > slave.pregData.normalBirth / 10) && slave.pregKnown === 1) { if (jsRandom(1, 100) > 50) { r.push(`The dildo penetrating ${his} womb <span class="orange">caused ${him} to miscarry,</span> which <span class="health dec">damages ${his} health.</span>`); diff --git a/src/endWeek/saDevotion.js b/src/endWeek/saDevotion.js index 72238362d3a9b51f4cb505bdc7d160092af42b86..700a5eb1e6425bc63660334a5f7c3d1144ace209 100644 --- a/src/endWeek/saDevotion.js +++ b/src/endWeek/saDevotion.js @@ -305,7 +305,7 @@ App.SlaveAssignment.devotion = (function() { * */ function bodySwapThoughts(slave) { - if (V.slaveIndices[slave.origBodyOwnerID] === undefined) { + if (getSlave(slave.origBodyOwnerID) === undefined) { slave.origBodyOwnerID = 0; if (slave.devotion > 20) { r.push(`${slave.slaveName} is somewhat saddened to see ${his} body leave forever.`); diff --git a/src/endWeek/saDiet.js b/src/endWeek/saDiet.js index cd181294e04ea7a9b008e17bedc5dd8c7cb8d62d..4446e28c06ea416fe152b08bc7db93af43a04409 100644 --- a/src/endWeek/saDiet.js +++ b/src/endWeek/saDiet.js @@ -591,6 +591,7 @@ App.SlaveAssignment.diet = (function() { target = Math.trunc(Math.clamp(weightShift * 1000 + (buttSize * 1000 - growthGoal) * 4, 0, 72000)); } if (random(1, roll) <= target && buttSize > 0) { + // FIXME: identical branches if (slave.geneMods.NCS === 1 && buttSize > 2) { // TODO: WRITE BRANCH r.push(`<span class="change negative">${His} butt gets a little smaller.</span>`); slave.butt -= 1; diff --git a/src/endWeek/saDrugs.js b/src/endWeek/saDrugs.js index 5a0580f1e90b69beff68356a963817b7eead1a94..c6081130168b2b1a933d0d04ec6babefc57001f0 100644 --- a/src/endWeek/saDrugs.js +++ b/src/endWeek/saDrugs.js @@ -211,7 +211,7 @@ App.SlaveAssignment.drugs = (function() { if (slave.boobs < 800) { r += ` small chest tends to grow rapidly.`; growth += 10; - if ((slave.boobShape !== "saggy") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "saggy") && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) < 5) { r += ` As ${his} boobs rapidly grow, they become saggy under their own rapid weight gain.`; slave.boobShape = "saggy"; @@ -220,7 +220,7 @@ App.SlaveAssignment.drugs = (function() { } else if (slave.boobs < 2000) { r += ` modest tits tend to grow fast.`; growth += 8; - if ((slave.boobShape !== "saggy") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "saggy") && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) < 5) { r += ` As ${his} boobs rapidly grow, they become saggy under their own rapid weight gain.`; slave.boobShape = "saggy"; @@ -229,7 +229,7 @@ App.SlaveAssignment.drugs = (function() { } else if (slave.boobs < 5000) { r += ` heavy boobs tend to grow modestly.`; growth += 6; - if ((slave.boobShape !== "saggy") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "saggy") && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) === 1) { r += ` As they grow, they <span class="coral">begin to sag</span> under their own monstrous weight, ${his} mass of breastflesh directing ${his} nipples downward.`; slave.boobShape = "saggy"; @@ -238,7 +238,7 @@ App.SlaveAssignment.drugs = (function() { } else if (slave.boobs < 10000) { r += ` huge boobs tend to grow slowly.`; growth += 4; - if ((slave.boobShape !== "saggy") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "saggy") && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) === 1) { r += ` As they grow, they <span class="coral">begin to sag</span> under their own monstrous weight, ${his} mass of breastflesh directing ${his} nipples downward.`; slave.boobShape = "saggy"; @@ -247,7 +247,7 @@ App.SlaveAssignment.drugs = (function() { } else { r += ` monstrous udders are just the right size to experience the explosive growth the drugs promise.`; growth += 10; - if ((slave.boobShape !== "normal") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "normal") && (slave.boobsImplant / slave.boobs < 0.9) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) === 1) { r += ` ${His} <span class="coral">breasts lose their unique shape</span> as they adapt to their monstrous, unnatural size. There's simply nowhere else for ${his} mass of boob to go, and its expansion fills ${his} breasts out and points ${his} nipples forward.`; slave.boobShape = "normal"; @@ -265,7 +265,7 @@ App.SlaveAssignment.drugs = (function() { r += ` The increase in breast size <span class="lime">stretches and broadens ${his} areolae.</span>`; slave.areolae += 1; } - if ((jsRandom(1, 100) > 70) && (slave.nipples !== "inverted") && (slave.nipples !== "fuckable")) { + if ((jsRandom(1, 100) > 70) && (slave.nipples !== "inverted") && (slave.nipples !== "fuckable") && (slave.nipples !== "flat")) { if (["cute", "huge", "puffy", "tiny"].includes(slave.nipples)) { r += ` The explosive increase in breast flesh also <span class="lime">completely swallows ${his} nipples.</span>`; slave.nipples = "inverted"; @@ -400,7 +400,7 @@ App.SlaveAssignment.drugs = (function() { } else if (slave.boobs < 5000) { r += ` heavy boobs tend to grow slowly.`; growth++; - if ((slave.boobShape !== "saggy") && (slave.breastMesh !== 1)) { + if ((slave.boobShape !== "saggy") && (slave.boobsImplant / slave.boobs < 0.5) && (slave.breastMesh !== 1)) { if (jsRandom(1, 10) === 1) { r += ` <span class="coral">As they grow, they begin to sag</span> under their own monstrous weight, ${his} mass of breastflesh directing ${his} nipples downward. `; slave.boobShape = "saggy"; @@ -428,7 +428,7 @@ App.SlaveAssignment.drugs = (function() { slave.areolae += 1; } } - if (slave.nipples !== "huge" && (slave.nipples !== "fuckable")) { + if (slave.nipples !== "huge" && (slave.nipples !== "fuckable") && (slave.nipples !== "flat")) { if (jsRandom(1, 200) < growth) { if ((slave.nipples === "tiny")) { r += ` The hormones also <span class="lime">cause nipple growth.</span>`; @@ -509,6 +509,12 @@ App.SlaveAssignment.drugs = (function() { slave.nipples = "huge"; } break; + case "flat": + if (jsRandom(1, 100) > nippleThreshold) { + r += ` <span class="lime">${His} flat nipples swell painfully,</span> becoming spectacularly immense.`; + slave.nipples = "huge"; + } + break; case "huge": r += ` ${His} nipples are now so massive that further drug use will fail to grow them further; <span class="yellow">${his} drug regimen has been ended.</span>`; slave.drugs = "no drugs"; diff --git a/src/endWeek/saGetMilked.js b/src/endWeek/saGetMilked.js index 96240a88cdcab11e1b8ecc4b3d7e42511d70fcf8..79bad3646e8b2762333491ec1182960ecbbd9c21 100644 --- a/src/endWeek/saGetMilked.js +++ b/src/endWeek/saGetMilked.js @@ -398,6 +398,9 @@ App.SlaveAssignment.getMilked = (function() { } else if (slave.nipples === "tiny") { r.text += ` Producing this river of milk <span class="change positive">makes ${his} nipples grow to a nice size.</span>`; slave.nipples = "cute"; + } else if (slave.nipples === "flat") { + r.text += ` Producing this river of milk <span class="change positive">forces ${his} nipples to grow to a more suitable size.</span>`; + slave.nipples = "huge"; } else if (slave.areolae < 4 && jsRandom(1, 100) > (30 + (slave.areolae * 20))) { if (slave.nipples === "fuckable") { r.text += ` The constant suction around of ${his} nipples as their depths are drained of milk`; diff --git a/src/endWeek/saHormonesEffects.js b/src/endWeek/saHormonesEffects.js index 9332be379b8aabc6aeb89947b6720dd5f1c6bcc5..6cc50080d1d4fbf6eef1e5f161316f92cd4744a1 100644 --- a/src/endWeek/saHormonesEffects.js +++ b/src/endWeek/saHormonesEffects.js @@ -723,7 +723,7 @@ App.SlaveAssignment.hormonesEffects = (function() { } if (slave.geneMods.NCS === 1 && slave.nipples === "tiny") { /* nothing, just don't advance to cute */ - } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable") { + } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable" && slave.nipples !== "flat") { r.push(`Hormonal effects cause ${his} <span class="orange">nipples to shrink to a more masculine size.</span>`); slave.nipples = "cute"; } @@ -813,7 +813,7 @@ App.SlaveAssignment.hormonesEffects = (function() { } if (slave.geneMods.NCS === 1 && slave.nipples === "tiny") { /* nothing, just don't advance to cute */ - } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable") { + } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable" && slave.nipples !== "flat") { r.push(`Hormonal effects cause ${his} <span class="orange">nipples to shrink to a more masculine size.</span>`); slave.nipples = "cute"; } @@ -898,7 +898,7 @@ App.SlaveAssignment.hormonesEffects = (function() { } if (slave.geneMods.NCS === 1 && slave.nipples === "tiny") { /* nothing, just don't advance to cute */ - } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable") { + } else if (slave.nipples !== "cute" && slave.nipples !== "fuckable" && slave.nipples !== "flat") { r.push(`Hormonal effects cause ${his} <span class="orange">nipples to shrink to a more masculine size.</span>`); slave.nipples = "cute"; } diff --git a/src/endWeek/saLiveWithHG.js b/src/endWeek/saLiveWithHG.js index 08172820250ceec0d0432f329f2df2478f8a21df..733f91b673730f237f4c38bc152be5e36c1b3a20 100644 --- a/src/endWeek/saLiveWithHG.js +++ b/src/endWeek/saLiveWithHG.js @@ -1123,7 +1123,7 @@ App.SlaveAssignment.liveWithHG = (function() { slave.clothes = "slutty business attire"; } else if (HG.fetish === "masochist") { r.push(`${HG.slaveName} keeps ${slave.slaveName}`); - if (isItemAccessible.entry("battledress", "clothing")) { + if (isItemAccessible.entry("battledress", "clothes")) { r.push(`in battledress, since ${he2} likes the fantasy of being raped by a soldier ${girl}.`); slave.clothes = "battledress"; } else { diff --git a/src/endWeek/saLongTermEffects.js b/src/endWeek/saLongTermEffects.js index ffd4fa19f3efdf8345cb6a1b3502b348449177a9..7e77d0ec17aaede93447ca79b9bed4d9a2d44492 100644 --- a/src/endWeek/saLongTermEffects.js +++ b/src/endWeek/saLongTermEffects.js @@ -328,6 +328,11 @@ App.SlaveAssignment.longTermEffects = (function() { r.push(`Having ${his} nipples held protruded by ${his} piercings is very uncomfortable, which ${he}`); masochistic = 2; } + } else if (slave.nipples === "flat") { + if (random(1, 100) > 90) { + r.push(`${His} piercings tug at ${his} nipples constantly, eventually <span class="change positive">preventing the fat nubs from flattening out again.</span>`); + slave.nipples = "huge"; + } } } else if (slave.nipplesPiercing === 2) { if (slave.nipples === "tiny") { @@ -365,6 +370,11 @@ App.SlaveAssignment.longTermEffects = (function() { r.push(`Having ${his} nipples held protruded by ${his} piercings is extremely uncomfortable, which ${he}`); masochistic = 2; } + } else if (slave.nipples === "flat") { + if (random(1, 100) > 50) { + r.push(`${He}'s got so much metal in ${his} nipples that the weight eventually <span class="change positive">stretches them out.</span>`); + slave.nipples = "huge"; + } } } if (masochistic === 1) { @@ -407,6 +417,11 @@ App.SlaveAssignment.longTermEffects = (function() { r.push(`${He}'s lactating so heavily that ${his} swollen nipples almost never retreat into their inverted state. Lactation has <span class="change positive">permanently protruded them,</span> leaving them engorged and puffy.`); slave.nipples = "puffy"; } + } else if (slave.nipples === "flat") { + if (random(1, 100) > 50) { + r.push(`${He}'s lactating so heavily that ${his} swollen nipples almost never get the chance to flatten back out. Lactation has <span class="change positive">permanently engorged them,</span> leaving them positively massive.`); + slave.nipples = "huge"; + } } else { if (random(1, 100) > 90) { r.push(`Lactation has <span class="change positive">swollen ${his} nipples</span> to an absurd size, making ${his} status as a cow obvious even when ${his} chest faucets aren't gushing cream.`); @@ -932,7 +947,7 @@ App.SlaveAssignment.longTermEffects = (function() { if (boobSize(slave) < 400 * gigantomastiaMod && random(1, 100) < 30) { r.push(`${His} breasts feel <span class="change positive">heavy, hot and sensitive.</span>`); slave.boobs += 50; - if (random(1, 100) < 10 && slave.breastMesh !== 1) { + if (random(1, 100) < 10 && slave.boobShape !== "perky" && slave.boobShape !== "spherical" && slave.breastMesh !== 1) { slave.boobShape = "perky"; } } @@ -1032,7 +1047,7 @@ App.SlaveAssignment.longTermEffects = (function() { if (boobSize(slave) < 400 * gigantomastiaMod && random(1, 100) < 30 && gigantomastiaMod !== 3) { r.push(`${His} chest feels <span class="change positive">hot and sensitive.</span>`); slave.boobs += 50; - if (random(1, 100) < 10 && slave.breastMesh !== 1) { + if (random(1, 100) < 10 && slave.boobShape !== "perky" && slave.boobShape !== "spherical" && slave.breastMesh !== 1) { slave.boobShape = "perky"; } } diff --git a/src/endWeek/saLongTermPhysicalEffects.js b/src/endWeek/saLongTermPhysicalEffects.js index b900d14cad38a796c175906622d970b80024d41e..eff87fd781964b00f73486d15e26a6f917221322 100644 --- a/src/endWeek/saLongTermPhysicalEffects.js +++ b/src/endWeek/saLongTermPhysicalEffects.js @@ -233,7 +233,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() { if (slave.assignment !== "serve in the master suite" || V.masterSuiteUpgradeLuxury < 2) { if (slave.assignment !== "work in the dairy" || V.dairyStimulatorsSetting === 0) { if (slave.geneMods.rapidCellGrowth !== 1) { - if (slave.vagina >= 3 && !["huge dildo", "large dildo", "long, huge dildo", "long, large dildo"].includes(slave.vaginalAccessory)) { + if (slave.vagina >= 3 && dildoWidth(slave) < 2) { r.push(`With a rest from strenuous use, <span class="improvement">${his} loose vagina recovers a little.</span>`); slave.vagina -= 1; } else if (slave.anus >= 3 && plugWidth(slave) < 2) { @@ -791,7 +791,7 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() { r.push(`${His} <span class="ncs">NCS</span> has <span class="change negative">reduced the size of ${his} bouncing breasts.</span>`); slave.boobs -= Math.round(slave.boobs * .11); countNCS++; - } else if ((boobSize <= 5000) && (!["cute", "fuckable", "tiny"].includes(slave.nipples)) && (random(1, 100) < 30)) { + } else if ((boobSize <= 5000) && (!["cute", "fuckable", "tiny", "flat"].includes(slave.nipples)) && (random(1, 100) < 30)) { if (slave.nipples === "inverted") { nipplesString = "partially inverted"; } else if (slave.nipples === "partially inverted") { @@ -1139,15 +1139,20 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() { } } } - if (slave.boobs - (slave.muscles * 30) > 5000 && slave.boobs <= 8000 && slave.boobsImplant / slave.boobs < .50 && slave.breastMesh !== 1) { // Check now requires breasts to be less than half implant to sag. - if (slave.physicalAge < random(10, 200)) { - if (slave.boobShape === "perky") { - r.push(`${His} <span class="change negative">breasts lose their perkiness</span> under their own titanic weight. Their nipples now point forward and ${his} boobs rest more heavily against the chest beneath them.`); - slave.boobShape = "torpedo-shaped"; - } else if (slave.boobShape !== "saggy") { - r.push(`${His} <span class="change negative">breasts become saggy</span> under their own titanic weight. Their nipples now point downward and ${his} bosom sways pendulously with ${his} every movement.`); - slave.boobShape = "saggy"; + if (slave.breastMesh !== 1) { + if (slave.boobs - (slave.muscles * 30) > 5000 && slave.boobs <= 8000 && slave.boobsImplant / slave.boobs < .50) { // Check now requires breasts to be less than half implant to sag. + if (slave.physicalAge < random(10, 200)) { + if (slave.boobShape === "perky") { + r.push(`${His} <span class="change negative">breasts lose their perkiness</span> under their own titanic weight. Their nipples now point forward and ${his} boobs rest more heavily against the chest beneath them.`); + slave.boobShape = "torpedo-shaped"; + } else if (slave.boobShape !== "saggy") { + r.push(`${His} <span class="change negative">breasts become saggy</span> under their own titanic weight. Their nipples now point downward and ${his} bosom sways pendulously with ${his} every movement.`); + slave.boobShape = "saggy"; + } } + } else if (slave.boobsImplant / slave.boobs >= .90 && slave.boobs > 2000 && !["saggy", "downward-facing", "spherical"].includes(slave.boobShape) && random(1, 100) > 70) { + r.push(`${His} <span class="change negative">breasts become firm and round</span> under the weight of ${his} massive implants. Their nipples now point forward, if not a little downward and to the side, as ${his} boobs begin to pull away from ${his} chest.`); + slave.boobShape = "spherical"; } } // Oversized breast shrinkage @@ -1178,10 +1183,16 @@ App.SlaveAssignment.longTermPhysicalEffects = (function() { } } } - // boobs too small for fuckable nipples + // boobs size nipple effects if (slave.nipples === "fuckable" && (slave.boobs - slave.boobsImplant < 500)) { r.push(`Without the necessary flesh to support them, ${his} fuckable nipples pop out and stay out. They have <span class="change negative">reverted to being huge.</span>`); slave.nipples = "huge"; + } else if (slave.nipples === "flat" && (slave.boobsImplant / slave.boobs < 0.75)) { + r.push(`With ${his} breasts no longer being overstretched by implants, ${his} flat nipples regain a more normal shape. They now <span class="change positive">protrude hugely.</span>`); + slave.nipples = "huge"; + } else if (slave.boobShape === "spherical" && slave.nipples !== "flat" && slave.lactation === 0 && slave.nipplesPiercings === 0) { // Lactation and piercings discourage flattening and convert flat nipples to huge ones. + r.push(`With the skin of ${his} breasts stretched so thin by ${his} implants, it's only natural that ${his} nipples are soon <span class="change negative">pulled flat</span> as well.`); + slave.nipples = "flat"; } } diff --git a/src/endWeek/saPregnancy.js b/src/endWeek/saPregnancy.js index 4ed68a461faecb90d59026b3bd27ca3dd6ee9f6b..9373cec6d5aa8964905a220c80aba4f36e6d6628 100644 --- a/src/endWeek/saPregnancy.js +++ b/src/endWeek/saPregnancy.js @@ -700,7 +700,7 @@ App.SlaveAssignment.pregnancy = (function() { if (boobSize < boobTarget) { r.push(`${His} breasts <span class="change positive">greatly swell</span> to meet the upcoming demand.`); slave.boobs += 100; - if (slave.boobShape !== "saggy" && slave.preg > slave.pregData.normalBirth / 1.25 && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { + if (slave.boobShape !== "saggy" && slave.preg > slave.pregData.normalBirth / 1.25 && (slave.boobsImplant / slave.boobs < 0.5) && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { r.push(`${His} immensely engorged <span class="change negative">breasts become saggy</span> in the last stages of ${his} pregnancy as ${his} body undergoes changes in anticipation of the forthcoming birth.`); slave.boobShape = "saggy"; } @@ -720,7 +720,7 @@ App.SlaveAssignment.pregnancy = (function() { if (random(1, 100) > 80 && boobSize < boobTarget) { r.push(`${His} breasts <span class="change positive">swell</span> in preparation for ${his} growing brood.`); slave.boobs += 50; - if (slave.boobShape !== "saggy" && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { + if (slave.boobShape !== "saggy" && (slave.boobsImplant / slave.boobs < 0.5) && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { if (slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2.05)) { r.push(`${His} swollen <span class="change negative">breasts become saggy</span> in the last stages of ${his} pregnancy as ${his} body undergoes changes in anticipation of the forthcoming birth.`); slave.boobShape = "saggy"; @@ -731,7 +731,7 @@ App.SlaveAssignment.pregnancy = (function() { if (random(1, 100) > 80) { r.push(`Pregnancy <span class="change positive">causes ${his} breasts to swell somewhat.</span>`); slave.boobs += 25; - if (slave.boobShape !== "saggy" && slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2.5) && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { + if (slave.boobShape !== "saggy" && slave.preg > random(slave.pregData.normalBirth / 1.25, slave.pregData.normalBirth * 2.5) && (slave.boobsImplant / slave.boobs < 0.5) && slave.breastMesh !== 1 && slave.drugs !== "sag-B-gone") { r.push(`${His} <span class="change negative">breasts become saggy</span> in the last stages of ${his} pregnancy as ${his} body undergoes changes in anticipation of the forthcoming birth.`); slave.boobShape = "saggy"; } diff --git a/src/endWeek/saSmartPiercingEffects.js b/src/endWeek/saSmartPiercingEffects.js index 7b13bbba49b4293714d45b25fa80c3eee48c523c..56bdc815258f98808601d286cc9bf1c209807011 100644 --- a/src/endWeek/saSmartPiercingEffects.js +++ b/src/endWeek/saSmartPiercingEffects.js @@ -409,7 +409,7 @@ App.SlaveAssignment.SmartPiercing.sadist = class extends App.SlaveAssignment.Sma App.SlaveAssignment.saSmartPiercingEffects = function(slave) { const {he, his, His, him} = getPronouns(slave); const hasBV = slave.vaginalAccessory === "bullet vibrator" || slave.dickAccessory === "bullet vibrator"; - const hasSmartBV = slave.vaginalAccessory === "smart bullet vibrator" || slave.dickAccessory === "smart bullet vibrator"; + const hasSmartBV = dildoVibeLevel(slave) > 1 || slave.dickAccessory === "smart bullet vibrator"; const hasDildoVibe = slave.vaginalAttachment === "vibrator"; const hasSmartDildoVibe = slave.vaginalAttachment === "smart vibrator"; const hasSP = slave.clitPiercing === 3; diff --git a/src/endWeek/saStayConfined.js b/src/endWeek/saStayConfined.js index eda744d2db9db9247912625bf90bd19cf06011c0..e019cacd79360b45642e4f8308021805615e597e 100644 --- a/src/endWeek/saStayConfined.js +++ b/src/endWeek/saStayConfined.js @@ -1,7 +1,7 @@ /** * @typedef {Object} confinedResults * @property {string} text - * @property {Boolean} broken + * @property {boolean} broken */ /** diff --git a/src/events/RESS/lazyEvening.js b/src/events/RESS/lazyEvening.js index 283c49dd12cab7be2ffed19dfae870259cfce0f6..add2da8f962bc980016d7e0e2711bc8f4e0dbcfa 100644 --- a/src/events/RESS/lazyEvening.js +++ b/src/events/RESS/lazyEvening.js @@ -34,7 +34,7 @@ App.Events.RESSLazyEvening = class RESSLazyEvening extends App.Events.BaseEvent } else if (slave.intelligence+slave.intelligenceImplant > 50) { return "a halter top dress"; } else if (slave.muscles > 30) { - if (isItemAccessible.entry("sport shorts", "clothing")) { + if (isItemAccessible.entry("sport shorts", "clothes")) { if (slave.boobs >= 650) { return "sport shorts and a sports bra"; } else { diff --git a/src/events/RESS/obedientIdiot.js b/src/events/RESS/obedientIdiot.js index b3834b62be36781094118362557193fc55022975..b35935488864e7e64495b0c11b3ad6a3639e4e61 100644 --- a/src/events/RESS/obedientIdiot.js +++ b/src/events/RESS/obedientIdiot.js @@ -76,9 +76,10 @@ App.Events.RESSObedientIdiot = class RESSObedientIdiot extends App.Events.BaseEv t.push(`${He} mumbles a hesitant question:`); t.push(Spoken(eventSlave, `"${eventSlave.rudeTitle === 1 ? PoliteRudeTitle(eventSlave) : Master}, am I a good slave?"`)); } - t.push(`You tell ${him} that ${he} is, running a hand ${eventSlave.hStyle === "shaved bald" ? `across ${his} bald scalp` : `through ${his} hair`}. ${He} seems <span class="hotpink">reassured,</span> and thankful when you give ${him} a cup of ${his} proper rations from your own hand.`); + t.push(`You tell ${him} that ${he} is, running a hand ${eventSlave.hStyle === "shaved bald" ? `across ${his} bald scalp` : `through ${his} hair`}. ${He} seems <span class="devotion inc">reassured,</span> and <span class="trust inc">thankful</span> when you give ${him} a cup of ${his} proper rations from your own hand.`); - eventSlave.devotion += 4; + eventSlave.devotion += 2; + eventSlave.trust += 2; seX(eventSlave, "oral", PC, "penetrative"); return t; } diff --git a/src/events/reRelativeRecruiter.js b/src/events/reRelativeRecruiter.js index d468e0b59fafc4f071501b5c2376854dad158e61..2bf1c798bfe1b82d12543c885b7c73c5241215ae 100644 --- a/src/events/reRelativeRecruiter.js +++ b/src/events/reRelativeRecruiter.js @@ -392,6 +392,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba slave.boobsImplant = 600; slave.boobsImplantType = "normal"; slave.boobs += slave.boobsImplant; + slave.boobsShape = "normal"; slave.skill.oral += random(30, 50); slave.skill.vaginal += random(30, 50); slave.skill.anal += random(30, 50); @@ -413,6 +414,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba slave.boobsImplant = 600; slave.boobsImplantType = "normal"; slave.boobs += slave.boobsImplant; + slave.boobsShape = "normal"; slave.skill.oral += random(30, 50); slave.skill.vaginal += random(30, 50); slave.skill.anal += random(30, 50); @@ -509,6 +511,12 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba slave.boobsImplant = (random(20, 40)*100); slave.boobsImplantType = "string"; slave.boobs += slave.boobsImplant; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } slave.buttImplant = random(5, 7); slave.buttImplantType = "string"; slave.butt += slave.buttImplant; diff --git a/src/facilities/bodyModification/bodyModification.js b/src/facilities/bodyModification/bodyModification.js index 93e3be757f1c1fa864bbd37018aa0e28c5c1aa97..83bc6d6ba04e82f98d82fa0e8377ae41017f7c98 100644 --- a/src/facilities/bodyModification/bodyModification.js +++ b/src/facilities/bodyModification/bodyModification.js @@ -362,11 +362,11 @@ App.UI.bodyModification = function(slave, cheat = false) { // DESCRIPTIONS App.UI.DOM.appendNewElement("h2", el, "Tattoos"); - for (const name of tattooLocations.keys()) { - if (name === "leg") { - r.push(App.UI.DOM.makeElement("div", App.Desc.tattoo(slave, "thigh"))); - } else { - r.push(App.UI.DOM.makeElement("div", App.Desc.tattoo(slave, name))); + for (let name of tattooLocations.keys()) { + name = (name === "leg") ? "thigh" : name; // Leg/thigh is a weird naming exception for now. + const desc = App.Desc.tattoo(slave, name); + if (desc) { + r.push(App.UI.DOM.makeElement("div", desc)); } } if (r.length === 0) { diff --git a/src/facilities/farmyard/farmyard.js b/src/facilities/farmyard/farmyard.js index 0c51e6a6676479a35766a14cca9694772af441b2..fcbb9365ac2a8d298cf19e81c7b6ba2542515dcf 100644 --- a/src/facilities/farmyard/farmyard.js +++ b/src/facilities/farmyard/farmyard.js @@ -13,7 +13,14 @@ App.Facilities.Farmyard.farmyard = function() { V.returnTo = "Farmyard"; V.encyclopedia = "Farmyard"; - frag.append(intro(), expand(), menials()); + frag.append( + intro(), + expand(), + menials(), + rules(), + upgrades(), + animals() + ); App.UI.DOM.appendNewElement("div", frag, App.UI.SlaveList.stdFacilityPage(App.Entity.facilities.farmyard), "farmyard-slaves"); diff --git a/src/facilities/incubator/incubatorInteract.js b/src/facilities/incubator/incubatorInteract.js index 8e3d2aeb432cf1bd8898de6778d10865fd6b060a..30c240ada7f1bf1477ba13c1968198eb5167fae5 100644 --- a/src/facilities/incubator/incubatorInteract.js +++ b/src/facilities/incubator/incubatorInteract.js @@ -1651,17 +1651,7 @@ App.UI.incubator = function() { el.append(p); row = document.createElement("div"); - row.append(`Rename ${V.incubatorName}: `); - row.append( - App.UI.DOM.makeTextBox( - V.incubatorName, - (v) => { - V.incubatorName = v; - refresh(); - } - ) - ); - App.UI.DOM.appendNewElement("span", row, ` Use a noun or similar short phrase`, "note"); + row.append(App.Facilities.rename(App.Entity.facilities.incubator, () => refresh())); el.append(row); return el; diff --git a/src/facilities/nursery/utils/nurseryUtils.js b/src/facilities/nursery/utils/nurseryUtils.js index 72068bf72602f708495dfae9eb1d0b32d4a44274..b31bcfe02d56dd34320e56daf2c25b05460425f7 100644 --- a/src/facilities/nursery/utils/nurseryUtils.js +++ b/src/facilities/nursery/utils/nurseryUtils.js @@ -107,7 +107,7 @@ App.Facilities.Nursery.infantToChild = function infantToChild(child) { child.bellySagPreg = 0; child.bellyTat = 0; child.bodySwap = 0; - child.boobShape = "normal"; + child.boobShape = jsEither(["normal", "normal", "normal", "perky", "perky", "perky", "torpedo-shaped", "downward-facing", "wide-set"]); child.boobs = jsRandom(200, 500); child.boobsImplant = 0; child.boobsImplantType = "none"; @@ -233,7 +233,11 @@ App.Facilities.Nursery.infantToChild = function infantToChild(child) { child.nails = 0; child.navelPiercing = 0; child.need = 0; - child.nipples = "cute"; + if (child.boobs > 500 || child.weight > 95) { + child.nipples = jsEither(["cute", "puffy", "partially inverted", "inverted", "tiny"]); + } else { + child.nipples = jsEither(["cute", "cute", "cute", "tiny"]); + } child.nipplesAccessory = "none"; child.nipplesPiercing = 0; child.nosePiercing = 0; @@ -747,9 +751,9 @@ App.Facilities.Nursery.nurserySort = function nurserySort() { if (slave.preg <= 5) { r += `someone's, though it is too early to tell whose,`; } else { - let t = V.slaveIndices[slave.pregSource]; - if (jsDef(t)) { - r += `${V.slaves[t].slaveName}'s`; + let source = getSlave(slave.pregSource); + if (source !== undefined) { + r += `${source.slaveName}'s`; } } break; diff --git a/src/facilities/salon/salonPassage.js b/src/facilities/salon/salonPassage.js index f2e6f5189f9286600a5fc64a0837c81f514619dd..31ba8037f5b6ca460feb03dd4b0b9c18216860c0 100644 --- a/src/facilities/salon/salonPassage.js +++ b/src/facilities/salon/salonPassage.js @@ -128,6 +128,7 @@ App.UI.salon = function(slave, cheat = false) { const options = new App.UI.OptionsGroup(); options.addOption(App.Desc.makeup(slave), "makeup", slave) + .addValue("Makeup free", 0) .addValue("Nice", 1, billMod) .addValue("Gorgeous", 2, billMod) .addValue("Slutty", 4, billMod) @@ -159,11 +160,11 @@ App.UI.salon = function(slave, cheat = false) { .addValue("Very long and garish", 4, billMod) .addValue("Color-coordinate with hair", 2, billMod); - options.addOption("", "makeup", slave) + options.addOption("", "nails", slave) .addValue("Neon", 6, billMod) .addValue("Neon, color-coordinate with hair", 7, billMod); - options.addOption("", "makeup", slave) + options.addOption("", "nails", slave) .addValue("Metallic", 8, billMod) .addValue("Metallic, color-coordinate with hair", 9, billMod); diff --git a/src/facilities/statistics.js b/src/facilities/statistics.js index 380e5499cf6ce95d5624ade61565755554b1ed56..4d0af165db08327df3725360cc19bccfede5d8cd 100644 --- a/src/facilities/statistics.js +++ b/src/facilities/statistics.js @@ -6,7 +6,7 @@ App.Facilities.StatsHelper = class { makeStatsTable(columns) { const table = document.createElement("table"); table.border = "1"; - table.className = "stats"; + table.className = "facility-stats"; const header = App.UI.DOM.appendNewElement("tr", table, "", "header"); App.UI.DOM.appendNewElement("th", header, "Items"); // first column, flexible width App.UI.DOM.appendNewElement("th", header, columns[0], "wide"); // "revenue" column, wider @@ -155,7 +155,7 @@ App.Facilities.StatsHelper = class { row.appendChild(bigCell); const table = document.createElement("table"); - table.className = "stats-slave"; + table.className = "facility-stats-slave"; const header = App.UI.DOM.appendNewElement("tr", table, "", "header"); App.UI.DOM.appendNewElement("th", header, columns[0]); // first column, flexible width App.UI.DOM.appendNewElement("th", header, columns[1], "narrow"); // facility-specific output details diff --git a/src/facilities/toyShop/toyShop.js b/src/facilities/toyShop/toyShop.js new file mode 100644 index 0000000000000000000000000000000000000000..9cc2b7269adf5f03c626c3d1a49050cee88bfa83 --- /dev/null +++ b/src/facilities/toyShop/toyShop.js @@ -0,0 +1,241 @@ +/** + * UI for the Body Modification system/studio. Refreshes without refreshing the passage. + */ +App.UI.toyShop = function() { + const container = document.createElement("span"); + let buttPlugName; + let buttPlugData; + let selectedPlug; + init(); + + container.append(createPage()); + return container; + + function createPage() { + const el = new DocumentFragment(); + el.append(intro()); + el.append(buttPlugs()); + return el; + } + + function init() { + buttPlugName = ""; + buttPlugData = { + name: "", + width: 1, + length: 1 + }; + } + + function intro() { + const el = new DocumentFragment(); + App.UI.DOM.appendNewElement("h1", el, "Toy Shop"); + App.UI.DOM.appendNewElement("div", el, `The room is filled with the smell of rubber, latex, and various synthetic materials and solvents. A series of screens allows you to design toys of various shapes and sizes, and then produce them at scale. A bin of defects sits in the corner, glistening a bit under a layer of lubrication.`, "scene-intro"); + return el; + } + + + function buttPlugs() { + const el = new DocumentFragment(); + let linkArray; + App.UI.DOM.appendNewElement("h2", el, "Buttplugs"); + const select = App.UI.DOM.appendNewElement("div", el, App.UI.DOM.link("Start a new design", () => { + init(); + refresh(); + })); + if (V.customItem.buttplug.size > 0) { + select.append(selectDesign()); + } + el.append(create()); + return el; + + function create() { + const el = new DocumentFragment(); + const existingDesign = V.customItem.buttplug.get(buttPlugName); + if (existingDesign) { + el.append(descLocked()); + } else { + el.append(desc()); + } + if (buttPlugData.name) { + el.append(title()); + } + el.append( + width(), + length(), + ); + + if (existingDesign) { + const build = App.UI.DOM.appendNewElement("div", el, `Send updated design to production and make sure all appropriate slaves are updated `); + const linkArray = []; + linkArray.push( + App.UI.DOM.link( + "Update the mold", + () => { buildPlug(); } + ) + ); + + linkArray.push( + App.UI.DOM.link( + `Recall "${buttPlugName}"`, + () => { deletePlug(); } + ) + ); + build.append(App.UI.DOM.generateLinksStrip(linkArray)); + } else if (buttPlugName && buttPlugData.name){ + el.append(apply()); + } + + return el; + + function descLocked() { + return App.UI.DOM.makeElement("div", `Description has already been selected for this model: "${buttPlugName}"`); + } + } + function selectDesign() { + const el = new DocumentFragment(); + const choice = App.UI.DOM.appendNewElement("span", el, ` or choose an existing design to edit `); + const select = App.UI.DOM.appendNewElement("select", choice); + let matchFound = false; + for (const [key, values] of V.customItem.buttplug) { + const option = App.UI.DOM.appendNewElement("option", select, values.name); + option.value = key; + if (option.value === buttPlugName) { + option.selected = true; + matchFound = true; + } + } + if (!matchFound) { + select.selectedIndex = -1; + } + select.onchange = () => { + const O = select.options[select.selectedIndex]; + selectedPlug = O.value; + buttPlugName = selectedPlug; + buttPlugData = V.customItem.buttplug.get(selectedPlug); + refresh(); + }; + return el; + } + + function desc() { + const value = App.UI.DOM.makeElement("div", `Enter shape here as it will appear in descriptions `); + value.append(App.UI.DOM.makeTextBox( + buttPlugName, + v => { + buttPlugName = v; + buttPlugData.name = capFirstChar(v); + refresh(); + } + )); + App.UI.DOM.appendNewElement("span", value, ` Your slave has a standard ${buttPlugName ? buttPlugName : `spade-shaped plug`} wedged firmly in their asshole.`, "note"); + return value; + } + + function title() { + const title = App.UI.DOM.makeElement("div", `Enter title as it will appear in lists of choices `); + title.append(App.UI.DOM.makeTextBox( + buttPlugData.name, + v => { + buttPlugData.name = capFirstChar(v); + refresh(); + } + )); + return title; + } + + function width() { + const widthOptions = new Map([ + ["standard", 1], + ["large", 2], + ["huge", 3], + ]); + const width = App.UI.DOM.makeElement("div", `Select width `); + linkArray = []; + for (const [key, value] of widthOptions) { + if (buttPlugData.width === value) { + linkArray.push( + App.UI.DOM.disabledLink( + key, + ["Currently selected"] + ) + ); + } else { + linkArray.push( + App.UI.DOM.link( + key, + () => { + buttPlugData.width = value; + refresh(); + } + ) + ); + } + } + width.append(App.UI.DOM.generateLinksStrip(linkArray)); + return width; + } + + function length() { + const lengthOptions = new Map([ + ["standard", 1], + ["long", 2], + ]); + const length = App.UI.DOM.makeElement("div", `Select length `); + linkArray = []; + for (const [key, value] of lengthOptions) { + if (buttPlugData.length === value) { + linkArray.push( + App.UI.DOM.disabledLink( + key, + ["Currently selected"] + ) + ); + } else { + linkArray.push( + App.UI.DOM.link( + key, + () => { + buttPlugData.length = value; + refresh(); + } + ) + ); + } + } + length.append(App.UI.DOM.generateLinksStrip(linkArray)); + return length; + } + + function buildPlug() { + V.customItem.buttplug.set(buttPlugName, buttPlugData); + init(); + refresh(); + } + + function apply() { + const build = App.UI.DOM.appendNewElement("div", el, `Send design to production and make available for all slaves `); + build.append( + App.UI.DOM.link( + "Start the mold", + () => { buildPlug(); } + ) + ); + return build; + } + + function deletePlug() { + V.customItem.buttplug.delete(buttPlugName); + for (const slave of V.slaves) { + if (slave.buttplug === buttPlugName) { + slave.buttplug = "none"; + } + } + refresh(); + } + } + + function refresh() { + jQuery(container).empty().append(createPage()); + } +}; diff --git a/src/facilities/wardrobe/wardrobeShopping.js b/src/facilities/wardrobe/wardrobeShopping.js index c1aa035e680c1476eb3d57537a7c0d7ffcdbdffb..06f4beb7f1f361ca747db9634745aa1aaad9ac70 100644 --- a/src/facilities/wardrobe/wardrobeShopping.js +++ b/src/facilities/wardrobe/wardrobeShopping.js @@ -7,7 +7,7 @@ App.UI.WardrobeShopping = function() { let r = []; r.push(`The room containing all the clothes and accessories you have available to dress your slaves in, as well as the supplies and tools your tailor needs to resize them to better fit your slaves. Several mirrors are set up for a slave to try on outfits should they be allowed to dress themselves. The selection includes`); - const ownItAll = Array.from(App.Data.clothes.keys()).every((key) => isItemAccessible.entry(key, "clothing")); + const ownItAll = Array.from(App.Data.clothes.keys()).every((key) => isItemAccessible.entry(key, "clothes")); if (ownItAll) { r.push(`outfits from all manner of cultures and societies; not a single style eludes you.`); @@ -117,7 +117,7 @@ App.UI.WardrobeShopping = function() { } } } - if (clothing !== "egypt" && !isItemAccessible.entry(model.clothes, "clothing") || + if (clothing !== "egypt" && !isItemAccessible.entry(model.clothes, "clothes") || (clothing === "egypt" && !isItemAccessible.entry("ancient Egyptian", "collar")) // Fuck Egypt ) { if (cost < V.cash) { diff --git a/src/gui/PassageDone.tw b/src/gui/PassageDone.tw deleted file mode 100644 index bc45bd374f8e5c4d4e58cd0b4973265d341c3270..0000000000000000000000000000000000000000 --- a/src/gui/PassageDone.tw +++ /dev/null @@ -1,6 +0,0 @@ -:: PassageDone - -<<if window.savedColorMap>> - <<addclass "body" "lightTheme">> -<</if>> - diff --git a/src/gui/css/mainStyleSheet.css b/src/gui/css/mainStyleSheet.css deleted file mode 100644 index 7c5b01938e6b32475f8084c2c965795994bbe61f..0000000000000000000000000000000000000000 --- a/src/gui/css/mainStyleSheet.css +++ /dev/null @@ -1,419 +0,0 @@ -body { - overflow-x: hidden; -} - -/* makes HR colorflip compatible */ -hr { - background:#ccc; - border:0; -} - -/* clears SugarCube's default transition */ -.passage { - transition: none; - -webkit-transition: none; -} - -.passage-in { - opacity: 1 !important; -} - -/* default is 54em */ -#passages { - max-width: 100%; -} - -/* small trick to hide broken images */ -img { - text-indent: -10000px; -} - -.imageColumn { /* TODO: this is mostly a copy of imageRef to get its flex features working properly. They can probably be removed from imageRef at some point */ - display: flex; - flex-direction: column; - flex-wrap: wrap; - align-items: flex-start; - position: relative; - float: right; -} - -.imageRef { - display: flex; - flex-direction: column; - flex-wrap: wrap; - align-items: flex-start; - position: relative; - background-color: rgba(80, 80, 80, 0.5); - margin: 2px; -} - -.tinyImg { - height: 120px; - width: 120px; - float: left; -} - -.smlImg { - height: 150px; - width: 150px; - float: left; -} - -.smlImg > img, .smlImg > video { - height: auto; -} - -.medImg { - height: 300px; - width: 300px; - float: right; -} - -.medImg > img, .medImg > video { - height: auto; -} - -.lrgRender { - height: 531px; - width: 531px; - margin-right: -50px; - margin-left: -50px; - float: right; - z-index: -1; -} - -.lrgVector { - height: 600px; - width: 600px; - margin-right: -125px; - margin-left: -125px; - float: right; - z-index: -1; -} - -.lrgRender > div.mask { - width: 150px; - height: 100%; - background: linear-gradient(90deg, rgba(17,17,17,1), rgba(17,17,17,0.8) 60%, rgba(17,17,17,0)); - z-index: 1; - /*position: absolute;*/ -} - -.lrgRender > img, .lrgRender > video { - margin-left: -150px; - height: 531px; - width: auto; -} - -.lrgVector > div.mask { - width: 150px; - height: 100%; - background: linear-gradient(90deg, rgba(17,17,17,1), rgba(17,17,17,0.8) 60%, rgba(17,17,17,0)); - z-index: 1; -} - -.lrgVector > img, .lrgVector > video { - margin-left: -150px; - height: 600px; - width: auto; -} - -.lrgVector svg { - width: 336px; -} - -object { - object-fit: scale-down; - position: absolute; - top: 0; - left: 0; -} - -img.paperdoll { - position: absolute; - top: 0; - left: 0; - margin-left: 0; -} - -/* Colors are made as css classes, to allow them to be changed for a light color scheme (for example). */ -/* a version is for this case: <span class="-.."><a>text</a></span> */ -.link, .link a { color: var(--link-color) } /* link color */ -.aquamarine, .aquamarine a, .skill, .skill a { color: aquamarine } -.coral, .coral a, .fetish.loss, .fetish.loss a { color: coral } -.cyan, .cyan a, .hotkey { color: cyan } /* used for aphrodisiac & neighbor arcs */ -.darkgoldenrod, .darkgoldenrod a, .trust.extremely-terrified, .trust.extremely-terrified a { color: darkgoldenrod } -.darkred, .darkred a, .defiant.full, .defiant.full a { color: darkred } -.darkviolet, .darkviolet a, .devotion.hateful, .devotion.hateful a { color: darkviolet } -.deeppink, .deeppink a, .devotion.devoted, .devotion.devoted a { color: deeppink } /* used for devotion once & agent */ -.steelblue, .steelblue a { color: steelblue } -.deepskyblue, .deepskyblue a, .intelligent, .intelligent a { color: deepskyblue } -.dodgerblue, .dodgerblue a { color: dodgerblue } -.blue, .blue a { color: blue } -.gold, .gold a, .trust.dec, .trust.dec a, .trust.frightened, .trust.frightened a { color: gold } -.goldenrod, .goldenrod a, .trust.terrified, .trust.terrified a { color: goldenrod } -.gray, .gray a { color: gray } -.green, .green a, .reputation.inc, .reputation.inc a, .improvement, .improvement a, .flaw.break, .flaw.break a, .skill.inc, .skill.inc a, .fuckdoll, .fuckdoll a, .positive, .positive a, .health.inc, .health.inc a { color: green } -.hotpink, .hotpink a, .devotion.inc, .devotion.inc a, .devotion.accept, .devotion.accept a { color: hotpink } -.lawngreen, .lawngreen a { color: lawngreen } -.lightblue, .lightblue a { color: lightblue } -.lightcoral, .lightcoral a, .fetish.gain, .fetish.gain a { color: lightcoral } /* compare pink for fetish */ -.lightgreen, .lightgreen a, .relationship, .relationship a, .rivalry.dec, .rivalry.dec a { color: lightgreen } -.lightpink, .lightpink a { color: lightpink } -.lightsalmon, .lightsalmon a, .fetish.inc, .fetish.inc a, .rivalry.inc, .rivalry.inc a, .relationship.dec, .relationship.dec a { color: lightsalmon } -.lime, .lime a, .change.positive, .change.positive a, .virginity.loss, .virginity.loss a, .puberty, .puberty a, .pregnant, .pregnant a { color: lime } /* tight orifices, breast changes, take virginity, not sure on good aliases */ -.limegreen, .limegreen a { color: limegreen } /* multiple questionable uses */ -.magenta, .magenta a, .devotion.worship, .devotion.worship a { color: magenta } -.mediumaquamarine, .mediumaquamarine a, .trust.inc, .trust.inc a, .trust.careful, .trust.careful a { color: mediumaquamarine } -.mediumorchid, .mediumorchid a, .devotion.dec, .devotion.dec a, .devotion.resistant, .devotion.resistant a { color: mediumorchid } -.mediumseagreen, .mediumseagreen a, .trust.trusting, .trust.trusting a { color: mediumseagreen } -.orange, .orange a, .stupid, .stupid a, .change.negative, .change.negative a, .defiant.careful, .defiant.careful a, .ncs, .ncs a, .miscarriage, .miscarriage a, .intro.question { color: orange } /* generally between red and green, and a lot of other places */ -.orangered, .orangered a, .defiant.inc, .defiant.inc a, .defiant.bold, .defiant.bold, .education.neg a { color: orangered } -.orchid, .orchid a { color: orchid } /* used once (wrong? */ -.pink, .pink a, .slave.name.simple { color: pink } /* also fetish start ??? , and a lot of other stuff */ -.red, .red a, .health.dec, .health.dec a, .cash.dec, .cash.dec a, .stat.drop, .stat.drop a, .flaw.gain, .flaw.gain a, .mindbreak, .mindbreak a, .error, .error a, .elites.loss, .elites.loss a, .reputation.dec, .reputation.dec a, .warning, .warning a { color: red } /* also generally bad stuff */ -/* note: .error is for unexpected behavior, .warning for player feedback */ -.seagreen, .seagreen a, .trust.prof-trusting, .trust.prof-trusting a { color: seagreen } -.springgreen, .springgreen a, .skill.player, .skill.player a { color: springgreen } -.tan, .tan a { color: tan } /* some ethnicity */ -.chocolate, .chocolate a { color: chocolate } -.saddlebrown, .saddlebrown a { color: saddlebrown } -.teal, .teal a { color: teal } -.yellow, .yellow a, .noteworthy, .noteworthy a, .paraphilia.gain, .paraphilia.gain a, .devotion.ambivalent, .devotion.ambivalent a, .trust.fearful, .trust.fearful a, .job.change { color: yellow } -.yellowgreen, .yellowgreen a, .cash.inc, .cash.inc a, .cash, .cash a { color: yellowgreen } -.white a { color: white } -.violet, .libido.inc { color: violet } -.khaki, .libido.dec { color: khaki } - -/*! <<checkvars>> macro for SugarCube 2.x */ -#ui-dialog-body.checkvars{padding:1em}#ui-dialog-body.checkvars h1{font-size:1em;margin-top:0}#ui-dialog-body.checkvars table{border-collapse:collapse;border-spacing:0}#ui-dialog-body.checkvars thead tr{border-bottom:2px solid #444}#ui-dialog-body.checkvars tr:not(:first-child){border-top:1px solid #444}#ui-dialog-body.checkvars td,#ui-dialog-body.checkvars th{padding:.25em 1em}#ui-dialog-body.checkvars td:first-child,#ui-dialog-body.checkvars th:first-child{padding-left:.5em;border-right:1px solid #444}#ui-dialog-body.checkvars td:last-child,#ui-dialog-body.checkvars th:last-child{padding-right:.5em}#ui-dialog-body.checkvars th:first-child{text-align:center}#ui-dialog-body.checkvars td:first-child{font-weight:700;text-align:right}#ui-dialog-body.checkvars td{font-family:monospace,monospace;vertical-align:top;white-space:pre-wrap}#ui-dialog-body.checkvars .scroll-pad{margin:0;padding:0} - -div.output{ -width: 100%; -width: 100vw; -max-width: 100%; -word-break: break-all; -white-space: normal; -} -/* css rules for rules assistant */ -.rajs-list-item { - display: inline-block; - color: var(--link-color); - margin-right: 1em; -} -.rajs-list-item.selected { - color: gray; - text-decoration: none; -} -.rajs-list-item:last-of-type { margin-right: 0; } -.rajs-list-item:hover { - cursor: pointer; - text-decoration: underline; -} -.rajs-list-item.selected:hover { - cursor: default; - text-decoration: none; -} -.rajs-list strong:first-of-type, .rajs-list input { - margin-right: 2em; -} -.rajs-list-item input { - margin: 0.25em; -} -.rajs-section h1 { - border-bottom: 1px solid white; - cursor: pointer; -} -.rajs-section h1:hover { text-decoration: underline; } - -.scroll { - overflow: auto; -} - -h1, h2, h3 { - margin-bottom: 0; - margin-top: 0.25em; -} -.founding { - font-size: 0.8em; - margin-top: -0.8em; - margin-left: 0.5em; - font-style: italic; -} -table.corporate { - border: 3px darkgreen double; - border-collapse: collapse; - min-width: 33%; -} -table.corporate tbody tr:nth-child(even) { - background-color: rgb(0, 30, 0); -} -table.corporate tbody tr:nth-child(odd) { - background-color: rgb(15, 40, 15); -} -table.corporate td { - vertical-align: top; -} -table.corporate tbody th, table.corporate thead th { - background-color: black; - font-weight: bold; -} -.minor-note { - font-size: 0.75em; - font-style: italic; -} -.majorText { - margin-top: 0.5em; - margin-bottom: 1.5em; -} -.tab { - margin-left: 2em; -} -div.slave-report { - margin-top: 1em; - margin-bottom: 1em; -} -div.indent, p.indent { - text-indent: 2em; -} -div.double-indent, p.double-indent { - text-indent: 4em; -} -div.choices, p.choices { - margin-left: 2em; -} -div.double-choices, p.double-choices { - margin-left: 4em; -} - -/* setting at the beginning of a scene / subscene */ -.scene-intro { - font-style: italic; -} - -/* adds detail to an option: Do something. <span class="detail">Sentence that explains the effect/conditions */ -.detail { - font-style: italic; -} - -/* additional information not related to a specific option */ -.note { - font-style: italic; -} - -.story-label, .regularParties, .underline { - text-decoration: underline; -} - -/* Note: Do not do a linebreak after span in HTML, because it will underline the automatic space it inserts: "Matilda_is a cow" */ -.slave-name { - color: pink; - font-weight: bold; - text-decoration: underline; - text-decoration-color: white; -} - -.name { - font-weight: bold; -} - -.custom-label { - color: yellow; - font-weight: bold; -} - -div.cheat-menu { - font-style: italic; - position: absolute; - right: 50px; -} - -h1 + p { - margin-top: 0; -} -h2 + p { - margin-top: 0; -} -h3 + p { - margin-top: 0; -} - -.main-fcnn { - text-align: center; - margin: 0 auto; -} - -.major-link, .bold { - font-weight: bold; -} - -.clear-formatting { - color: white; - font-weight: normal; - font-style: normal; -} - -.major-warning { - font-weight: bold; - color: red; -} - -div.center, p.center { - margin-left: auto; - margin-right: auto; - text-align: center; -} - -div.flex-container { - display: flex; -} - -/* TODO unify tooltip systems */ -.hasTooltip { - text-decoration: underline; -} - -/* interactable tooltip-like container - created/destroyed dynamically */ -.details-overlay { - display: inline-block; - font-size: smaller; - width: max-content; - height: max-content; - border-style: solid; - border-color: slategray; - border-width: 2px; - border-radius: 3px; - background-color: rgb(17, 17, 17); - padding: 3px; - position: absolute; - z-index: 2; - text-indent: 0; -} - -/* make cheat textboxes fit in sidebar */ -#story-caption input { - min-width: 0; - width: calc(100% - 0.8em - 2px); -} - -/* slave interact navigation */ -.adjacent-slave { - font-weight: bold; -} -.interact-name { - margin: 0 2em; -} - -.icons { - font-family: 'tme-fa-icons'; -} - -.favorite, .favorite:hover { - color: yellow; - text-decoration: none; -} - -.not-favorite, .not-favorite:hover { - color: grey; - text-decoration: none; -} diff --git a/src/gui/css/wardrobeUse.css b/src/gui/css/wardrobeUse.css deleted file mode 100644 index 94a110b434caf8680e6b94b7d7fb28987dc18ea3..0000000000000000000000000000000000000000 --- a/src/gui/css/wardrobeUse.css +++ /dev/null @@ -1,24 +0,0 @@ -/* Style sheet for WardrobeUse.tw */ - -#passage-wardrobe-use .optionMacro { - display: inline; -} - -#passage-wardrobe-use .optionDescription { - width: unset; - text-align: left; -} - -#passage-wardrobe-use .optionValue { - display: flex; -} - -#passage-wardrobe-use .optionMacroOption { - flex-grow: 1; -} - -/* Last line shouldn't grow */ -#passage-wardrobe-use .optionValue::after { - flex-grow: 1000000000; - content: ''; -} diff --git a/src/gui/quicklinks.js b/src/gui/quicklinks.js index c7a5dbb9347e69d586d7466daa550ebb0a43e461..f993e46a2038ab8f40f373312f0e156ea1212795 100644 --- a/src/gui/quicklinks.js +++ b/src/gui/quicklinks.js @@ -65,6 +65,7 @@ App.UI.quickMenu = (function() { "Implant Manufactory": true, "Prosthetic Lab": true, "Wardrobe": true, + "Toy Shop": true, "The Black Market": true, }, Tools: { @@ -96,6 +97,7 @@ App.UI.quickMenu = (function() { "Firebase": () => !V.SF.Toggle || V.SF.Toggle < 1 || V.SF.Active < 1, "Future Society": () => !V.FSAnnounced, "Gene Lab": () => !V.geneticMappingUpgrade, + "Toy Shop": () => !V.toyShop, "Head Girl Suite": () => !V.HGSuite, "Implant Manufactory": () => !V.ImplantProductionUpgrade, "Incubator": () => !V.incubator, diff --git a/src/init/setupVars.tw b/src/init/setupVars.tw deleted file mode 100644 index 8a2594427cb0c8c5c94617b59777f0f01ee4e951..0000000000000000000000000000000000000000 --- a/src/init/setupVars.tw +++ /dev/null @@ -1,10 +0,0 @@ -:: setupVars [widget nobr] - -/* -* This passage is tagged as widget, so it will be loaded whenever any passage is loaded. The global setup object seems to reset itself to {} (empty object): until we figure out why, this is where we set properties for it. -*/ -<<for _k,_v range App.Data.misc>> - <<set setup[_k] = _v>> -<</for>> -<<run App.Art.cacheArtData()>> -<<run App.Corporate.Init()>> diff --git a/src/interaction/main/walkPast.js b/src/interaction/main/walkPast.js index 516e06e3e8e2d7ac1e6af9de0ef477bf78c4d90e..4e7e2a8267e464aa028447e84de82fe004130a71 100644 --- a/src/interaction/main/walkPast.js +++ b/src/interaction/main/walkPast.js @@ -8374,7 +8374,7 @@ globalThis.walkPast = (function() { t += `You get a good view of ${his} pussy.`; } } - if ((slave.vaginalAccessory === "long dildo") || (slave.vaginalAccessory === "long, large dildo") || (slave.vaginalAccessory === "long, huge dildo")) { + if (dildoLength(slave) > 1) { t += `With every motion ${he} makes, ${his} dildo shifts, bulging out ${his} stomach.`; if (plugLength(slave) > 1) { t += `Beside it, a second bulge caused by ${his} extra long buttplug.`; @@ -8964,7 +8964,7 @@ globalThis.walkPast = (function() { t += `You get a good view of ${his} pussy.`; } } - if ((slave.vaginalAccessory === "long dildo") || (slave.vaginalAccessory === "long, large dildo") || (slave.vaginalAccessory === "long, huge dildo")) { + if (dildoLength(slave) > 1) { t += `With every motion ${he} makes, ${his} dildo shifts, bulging out ${his} stomach.`; if (plugLength(slave) > 1) { t += `Beside it, a second bulge caused by ${his} extra long buttplug.`; diff --git a/src/interaction/prostheticConfig.tw b/src/interaction/prostheticConfig.tw index 4326995e2739557b650eb27dddce73f1203e6b58..d6dade1c2a87e361ba903f195ec5e179568523c1 100644 --- a/src/interaction/prostheticConfig.tw +++ b/src/interaction/prostheticConfig.tw @@ -32,7 +32,7 @@ This room is lined with shelves and cabinets; it could be easily mistaken for a <<if hasAnyCyberneticEyes(getSlave($AS))>> <h2>Eyes</h2> - <p class="tab"> /* tab works better with links */ + <p class="choices"> /* tab works better with links */ $He has <<if hasBothCyberneticEyes(getSlave($AS))>> ocular implants <<else>> an ocular implant <</if>> installed. You can change <<if hasBothCyberneticEyes(getSlave($AS))>>their<<else>>its<</if>> settings: <div class="eyeContainer"> diff --git a/src/interaction/siFinancial.js b/src/interaction/siFinancial.js index 25968a6cad73bd99c2716833399c04ba173e2bc6..62c75f25c15f3648502a62f8736c49cb2dd22f53 100644 --- a/src/interaction/siFinancial.js +++ b/src/interaction/siFinancial.js @@ -210,7 +210,7 @@ App.UI.SlaveInteract.financial = function(slave) { `Retire ${him}`, () => { V.retiree = slave.ID; - V.retired = 1; + V.retired = 1; // FIXME: Property 'retired' does not exist on type 'GameVariables'. }, [], "SE retirement", diff --git a/src/interaction/siPhysicalRegimen.js b/src/interaction/siPhysicalRegimen.js index 147d59bbfbadc891f2ff8ed57af956b70eabee1e..93fbc5120149ea44a46472d3c7f59f302d64d360 100644 --- a/src/interaction/siPhysicalRegimen.js +++ b/src/interaction/siPhysicalRegimen.js @@ -91,7 +91,7 @@ App.UI.SlaveInteract.physicalRegimen = function(slave) { } } if (V.dispensary) { - if (["inverted", "partially inverted", "cute", "tiny", "puffy"].includes(slave.nipples)) { + if (["inverted", "partially inverted", "cute", "tiny", "puffy", "flat"].includes(slave.nipples)) { nipples.push({text: `Enhancement`, updateSlave: {drugs: `nipple enhancers`}}); } else if (slave.nipples === "huge") { nipples.push({text: `Enhancement`, disabled: `Nipples are already huge`}); diff --git a/src/interaction/siRules.js b/src/interaction/siRules.js index b5e02a194109390fe129440b443977390d131e8e..2d96e64db46a466810f4c76f21e32b5591372196 100644 --- a/src/interaction/siRules.js +++ b/src/interaction/siRules.js @@ -374,7 +374,7 @@ App.UI.SlaveInteract.rules = function(slave) { function smartSettings(slave) { let el = document.createElement('div'); - const smartBulletVibe = slave.vaginalAccessory === "smart bullet vibrator" || slave.dickAccessory === "smart bullet vibrator"; + const smartBulletVibe = dildoVibeLevel(slave) > 1 || slave.dickAccessory === "smart bullet vibrator"; const smartDildoVibe = slave.vaginalAttachment === "smart vibrator"; if (slave.clitPiercing === 3 || smartBulletVibe || smartDildoVibe) { diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js index 6db2efd28da4339f90816a23490cfeb35002f723..6d72f7debae4cd83bfd2f0754b8018d06c59c557 100644 --- a/src/interaction/siWardrobe.js +++ b/src/interaction/siWardrobe.js @@ -7,7 +7,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let filters = {}; const el = document.createElement("span"); el.id = "content"; - el.append(contents()) + el.append(contents()); return el; @@ -34,7 +34,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { App.UI.DOM.appendNewElement("h3", frag, `Shopping`); frag.append(shopping()); - + return frag; } @@ -182,10 +182,11 @@ App.UI.SlaveInteract.wardrobe = function(slave) { const el = new DocumentFragment(); let array = []; - for (const [key, object] of App.Data.slaveWear.collars) { + for (const [key, object] of App.Data.slaveWear.collar) { if (key === "choosing her own clothes") { continue; } + // FIXME: Property 'harsh' does not exist on type 'slaveWear | slaveWearChastity'. if (filters.hasOwnProperty("harsh") && ((filters.harsh === false && object.harsh) || (filters.harsh === true && !object.harsh))) { continue; } @@ -427,7 +428,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - for (const [key, object] of App.Data.slaveWear.bellyAccessories) { + for (const [key, object] of App.Data.slaveWear.bellyAccessory) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -495,7 +496,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let normalArray = []; let longArray = []; - for (const [key, object] of App.Data.buttplugs) { + for (const [key, object] of App.Data.buttplug) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -519,6 +520,19 @@ App.UI.SlaveInteract.wardrobe = function(slave) { App.UI.DOM.appendNewElement("div", el, generateRows(normalArray, "buttplug", true), "choices"); App.UI.DOM.appendNewElement("div", el, generateRows(longArray, "buttplug", true), "choices"); + if (V.customItem.buttplug.size > 0) { + let customArray = []; + for (const [key, object] of V.customItem.buttplug) { + const reshapedItem = { + text: object.name, + updateSlave: {buttplug: key}, + FS: object.fs, + }; + customArray.push(reshapedItem); + } + App.UI.DOM.appendNewElement("div", el, generateRows(customArray, "buttplug", false), "choices"); + } + return el; } @@ -544,7 +558,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - for (const [key, object] of App.Data.slaveWear.buttplugAttachments) { + for (const [key, object] of App.Data.slaveWear.buttplugAttachment) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -588,9 +602,11 @@ App.UI.SlaveInteract.wardrobe = function(slave) { } el.appendChild(label); - let optionsArray = []; + let bulletArray = []; + let normalArray = []; + let longArray = []; - for (const [key, object] of App.Data.slaveWear.vaginalAccessories) { + for (const [key, object] of App.Data.vaginalAccessory) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -600,24 +616,29 @@ App.UI.SlaveInteract.wardrobe = function(slave) { updateSlave: {vaginalAccessory: key}, FS: object.fs, }; - optionsArray.push(reshapedItem); + if (object.width === 0) { + bulletArray.push(reshapedItem); + } else if (object.length > 1) { + longArray.push(reshapedItem); + } else { + normalArray.push(reshapedItem); + } } // Sort // No sort here since we want small -> large. optionsArray = optionsArray.sort((a, b) => (a.text > b.text) ? 1 : -1); // Options - let links = document.createElement('div'); - links.className = "choices"; - links.appendChild(generateRows(optionsArray, "vaginalAccessory", true)); - el.appendChild(links); + App.UI.DOM.appendNewElement("div", el, generateRows(bulletArray, "vaginalAccessory", true), "choices"); + App.UI.DOM.appendNewElement("div", el, generateRows(normalArray, "vaginalAccessory", true), "choices"); + App.UI.DOM.appendNewElement("div", el, generateRows(longArray, "vaginalAccessory", true), "choices"); return el; } function vaginalAttachment() { let el = document.createElement('div'); - if (["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory)) { + if (dildoWidth(slave) === 0) { return el; } @@ -637,14 +658,14 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - for (const [key, object] of App.Data.slaveWear.vaginalAttachments) { + for (const [key, object] of App.Data.slaveWear.vaginalAttachment) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; } const reshapedItem = { text: object.name, - updateSlave: {vaginalAttachments: key}, + updateSlave: {vaginalAttachment: key}, FS: object.fs, }; optionsArray.push(reshapedItem); @@ -681,7 +702,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - for (const [key, object] of App.Data.slaveWear.dickAccessories) { + for (const [key, object] of App.Data.slaveWear.dickAccessory) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -756,7 +777,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { let optionsArray = []; - for (const [key, object] of App.Data.slaveWear.chastityDevices) { + for (const [key, object] of App.Data.chastity) { if (key === "none") { // skip none in set, we set the link elsewhere. continue; @@ -766,6 +787,7 @@ App.UI.SlaveInteract.wardrobe = function(slave) { updateSlave: {}, FS: object.fs, }; + // FIXME: Property 'updateSlave' does not exist on type 'slaveWear | slaveWearChastity'. Object.assign(reshapedItem.updateSlave, object.updateSlave); optionsArray.push(reshapedItem); } diff --git a/src/js/DefaultRules.js b/src/js/DefaultRules.js index 2be10f42af25719beac240af7d229d475669a3c6..4ec6ae7de1b2090b828ef9584a62f941b7b22814 100644 --- a/src/js/DefaultRules.js +++ b/src/js/DefaultRules.js @@ -1394,7 +1394,7 @@ globalThis.DefaultRules = (function() { break; case "nipple enhancers": - if (!(["inverted", "partially inverted", "cute", "tiny", "puffy"].includes(slave.nipples))) { + if (!(["inverted", "partially inverted", "cute", "tiny", "puffy", "flat"].includes(slave.nipples))) { flag = false; } break; diff --git a/src/js/ibcJS.js b/src/js/ibcJS.js index ea09c7c542d8648881007e4d03abdc5d425f61fb..c0a19002c7a8a7c73046f90388739301ca05920d 100644 --- a/src/js/ibcJS.js +++ b/src/js/ibcJS.js @@ -9,6 +9,8 @@ * @property {number} [inbreedingCoeff] */ +// TODO: replace snake_case with camelCase + globalThis.ibc = (() => { // These IDs are considered to be unknown parents let or_null = (s) => specificCharacterID(s) ? s : null; diff --git a/src/js/itemAvailability.js b/src/js/itemAvailability.js index 3721d2bf853d8c39bb4ea85fc3bd070776488a5e..88c30da783e1db0cffa0fa171930d404468a8773 100644 --- a/src/js/itemAvailability.js +++ b/src/js/itemAvailability.js @@ -7,52 +7,15 @@ globalThis.isItemAccessible = (function() { /** * Checks whether an item is accessible * @param {string} string Name of wearable item - * @param {string} [category="clothing"] that item is in clothing, collar, etc + * @param {string} [category="clothes"] that item is in clothing, collar, etc * @param {App.Entity.SlaveState} [slave] * @returns {boolean|string} Returns true if item is accessible, and false if it is not. If the slave param is set, it may sometimes return a string instead of false, explaining why the item can't be used with that slave. */ - function entry(string, category = "clothing", slave) { + function entry(string, category = "clothes", slave) { if (V.cheatMode === 1) { return true; } - let selectedDB; - switch (category) { - case "clothing": - case "clothes": - selectedDB = App.Data.clothes; - break; - case "collar": - selectedDB = App.Data.slaveWear.collars; - break; - case "bellyAccessory": - selectedDB = App.Data.slaveWear.bellyAccessories; - break; - case "buttplug": - selectedDB = App.Data.buttplugs; - break; - case "buttplugAttachment": - selectedDB = App.Data.slaveWear.buttplugAttachments; - break; - case "vaginalAccessory": - selectedDB = App.Data.slaveWear.vaginalAccessories; - break; - case "vaginalAttachment": - selectedDB = App.Data.slaveWear.vaginalAttachments; - break; - case "dickAccessory": - selectedDB = App.Data.slaveWear.dickAccessories; - break; - case "shoes": - selectedDB = App.Data.shoes; - break; - case "chastity": - selectedDB = App.Data.slaveWear.chastityDevices; - break; - default: - // console.log(`made a category for ${category} automatically, may need to define this by hand`); - selectedDB = App.Data.slaveWear[category]; - break; - } + const selectedDB = App.Data.slaveWear[category] || App.Data[category]; const item = selectedDB.get(string); if (!item) { console.log(`${string} is not a registered piece of clothing! Check App.Data.slaveWear.${category}`); @@ -63,13 +26,13 @@ globalThis.isItemAccessible = (function() { /** * Returns array of wearable clothing in format [name, value], basically player facing / game data. * @param {Map} map Map to look in (such as App.Data.clothes) - * @param {string} [filter] for example, if we want to filer clothing data by the "harsh" property, pass harsh as the parameter here. + * @param {string} [filter] for example, if we want to filter clothing data by the "harsh" property, pass harsh as the parameter here. * @param {any} [filterValue] remove any clothing where the .filter property does not match this value. Function will evaluate undefined as false. * @returns {Array} */ function array(map, filter, filterValue) { const array = []; - for (const [key, obj] of map) { + for (const [key, obj] of map) { // FIXME: 'key' is declared but its value is never read. if (filter && filterValue !== (obj[filter] || false)) { continue; } @@ -83,11 +46,11 @@ globalThis.isItemAccessible = (function() { /** * @param {object} item - * @param {string} [category="clothing"] that item is in clothing, collar, etc + * @param {string} [category="clothes"] that item is in clothing, collar, etc * @param {App.Entity.SlaveState} [slave] * @returns {boolean|string} Returns true if item is accessible, and false if it is not. If the slave param is set, it may sometimes return a string instead of false, explaining why the item can't be used with that slave. */ - function isAvailable(item, category, slave) { + function isAvailable(item, category = "clothes", slave) { let slaveResults; if (slave) { slaveResults = isAvailableForSlave(item, category, slave); @@ -117,13 +80,12 @@ globalThis.isItemAccessible = (function() { /** * @param {object} item - * @param {string} [category="clothing"] that item is in clothing, collar, etc + * @param {string} [category="clothes"] that item is in clothing, collar, etc * @param {App.Entity.SlaveState} [slave] * @returns {boolean|string} Returns true if item is accessible, and false if it is not. If the slave param is set, it may sometimes return a string instead of false, explaining why the item can't be used with that slave. */ function isAvailableForSlave(item, category, slave) { switch (category) { - case "clothing": case "clothes": break; case "collar": @@ -224,7 +186,9 @@ globalThis.isItemAccessible = (function() { case "vibrator": if (slave.vaginalAccessory === "none") { return "No vaginal accessory to attach it to"; - } else if (slave.vaginalAccessory === "bullet vibrator" || slave.vaginalAccessory === "smart bullet vibrator") { + } else if (dildoWidth(slave) === 0) { + return "Vaginal accessory is too small"; + } else if (dildoVibeLevel(slave)) { return "Vaginal accessory already vibrates"; } else { return true; diff --git a/src/js/main.js b/src/js/main.js index c5c79eaa41ef4ae343827bab732036b628f9773b..7999c7603212a83e156bc04d596f575bce22f14d 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,97 +1,3 @@ -/** - * @returns {DocumentFragment} - */ -App.MainView.errors = function() { - const fragment = document.createDocumentFragment(); - - /** - * @returns {HTMLParagraphElement} - */ - function newError() { - const error = document.createElement("p"); - fragment.append(error); - return error; - } - - // check for correct version - if (V.releaseID >= 1000 || ["0.9", "0.8", "0.7", "0.6"].includes(V.ver)) { - if (V.releaseID < App.Version.release) { - newError().append(App.UI.DOM.makeElement("span", "INCOMPATIBILITY WARNING:", "major-warning"), - ` Your saved game was created using version: ${V.ver}, build: ${V.releaseID}. You must run `, - App.UI.DOM.passageLink("Backwards Compatibility", "Backwards Compatibility")); - } - } else { - newError().append(App.UI.DOM.makeElement("span", "INCOMPATIBLE SAVE WARNING:", "major-warning"), - ` Your saved game was created using version: ${V.ver}, and you are using a later version which New Game Plus cannot reconcile. Please start a new game.`); - } - - // check for correct rules - if (V.defaultRules.length > 0 && (V.defaultRules[0].condition === undefined || V.defaultRules[0].set === undefined)) { - const error = newError(); - error.append(App.UI.DOM.makeElement("span", "INCOMPATIBILITY WARNING:", "major-warning"), - " The rules assistant format has changed. In the Options Menu, please "); - const ra = document.createElement("strong"); - ra.append("Reset RA Rules"); - error.append(ra); - } - - // check for NaN - if (V.NaNArray.length > 0) { - const error = newError(); - error.id = "NaNArray"; - error.append(App.UI.DOM.makeElement("span", "ERROR: The following variables are NaN! Please report this.", "error")); - V.NaNArray.forEach(e => { - const div = document.createElement("div"); - div.append(e); - error.append(div); - }); - error.append(App.UI.DOM.link("Hide NaN variables until next week", - () => { - error.outerHTML = ""; - V.NaNArray = []; - }) - ); - } - - // check custom slaves - if (App.Utils.IsCustomSlaveMutated(V.customSlave)) { - newError().append(App.UI.DOM.makeElement("span", "ERROR: Your custom slave order has taken on a mutated life of its own and has been summarily shot. Refile your custom slave order, if necessary, and notify the appropriate authorities if you see this message again.", "error")); - V.customSlave = new App.Entity.CustomSlaveOrder(); - } - if (App.Utils.IsCustomSlaveMutated(V.huskSlave)) { - newError().append(App.UI.DOM.makeElement("span", "ERROR: Your husk slave order has taken on a mutated life of its own and has been summarily shot. Refile your husk slave order, if necessary, and notify the appropriate authorities if you see this message again.", "error")); - V.huskSlave = new App.Entity.CustomSlaveOrder(); - } - - return fragment; -}; - -/** - * @returns {Text} - */ -App.MainView.fcnn = function() { - let text; - - if (V.FCNNstation !== 1 && V.week >= 90) { - text = "FCNN: FCNN service has been temporarily suspended. Please stand by."; - } else { - text = V.fcnn.random(); - } - - return document.createTextNode(`${text} `); -}; - -App.MainView.useFucktoys = function() { - const fragment = document.createDocumentFragment(); - for (const slave of V.slaves) { - if (slave.assignment !== Job.FUCKTOY) { - continue; - } - fragment.append(App.MainView.useFucktoy(slave)); - } - return fragment; -}; - /** * @param {App.Entity.SlaveState} slave * @returns {HTMLDivElement} @@ -210,25 +116,116 @@ App.MainView.useGuard = function() { return outerDiv; }; -App.MainView.walkPast = function() { - const outerDiv = document.createElement("div"); +App.MainView.full = function() { + /** + * @returns {DocumentFragment} + */ + function errors() { + const fragment = document.createDocumentFragment(); + + /** + * @returns {HTMLParagraphElement} + */ + function newError() { + const error = document.createElement("p"); + fragment.append(error); + return error; + } + + // check for correct version + if (V.releaseID >= 1000 || ["0.9", "0.8", "0.7", "0.6"].includes(V.ver)) { + if (V.releaseID < App.Version.release) { + newError().append(App.UI.DOM.makeElement("span", "INCOMPATIBILITY WARNING:", "major-warning"), + ` Your saved game was created using version: ${V.ver}, build: ${V.releaseID}. You must run `, + App.UI.DOM.passageLink("Backwards Compatibility", "Backwards Compatibility")); + } + } else { + newError().append(App.UI.DOM.makeElement("span", "INCOMPATIBLE SAVE WARNING:", "major-warning"), + ` Your saved game was created using version: ${V.ver}, and you are using a later version which New Game Plus cannot reconcile. Please start a new game.`); + } + + // check for correct rules + if (V.defaultRules.length > 0 && (V.defaultRules[0].condition === undefined || V.defaultRules[0].set === undefined)) { + const error = newError(); + error.append(App.UI.DOM.makeElement("span", "INCOMPATIBILITY WARNING:", "major-warning"), + " The rules assistant format has changed. In the Options Menu, please "); + const ra = document.createElement("strong"); + ra.append("Reset RA Rules"); + error.append(ra); + } + + // check for NaN + if (V.NaNArray.length > 0) { + const error = newError(); + error.id = "NaNArray"; + error.append(App.UI.DOM.makeElement("span", "ERROR: The following variables are NaN! Please report this.", "error")); + V.NaNArray.forEach(e => { + const div = document.createElement("div"); + div.append(e); + error.append(div); + }); + error.append(App.UI.DOM.link("Hide NaN variables until next week", + () => { + error.outerHTML = ""; + V.NaNArray = []; + }) + ); + } + + // check custom slaves + if (App.Utils.IsCustomSlaveMutated(V.customSlave)) { + newError().append(App.UI.DOM.makeElement("span", "ERROR: Your custom slave order has taken on a mutated life of its own and has been summarily shot. Refile your custom slave order, if necessary, and notify the appropriate authorities if you see this message again.", "error")); + V.customSlave = new App.Entity.CustomSlaveOrder(); + } + if (App.Utils.IsCustomSlaveMutated(V.huskSlave)) { + newError().append(App.UI.DOM.makeElement("span", "ERROR: Your husk slave order has taken on a mutated life of its own and has been summarily shot. Refile your husk slave order, if necessary, and notify the appropriate authorities if you see this message again.", "error")); + V.huskSlave = new App.Entity.CustomSlaveOrder(); + } - const slave = V.slaves.filter(s => ![Job.BODYGUARD, Job.FUCKTOY].includes(s.assignment)).random(); - if (slave) { - App.UI.DOM.appendNewElement("span", outerDiv, walkPast(slave), "scene-intro"); + return fragment; } - return outerDiv; -}; + /** + * All main passage logic that should be performed at the beginning ogf the passage but generate no visual output. + */ + function cleanup() { + if (V.tabChoice.SlaveInteract !== "Description") { + V.tabChoice.SlaveInteract = "Description"; + } -App.MainView.full = function() { + penthouseCensus(); + V.costs = Math.trunc(calculateCosts.predict()); + V.currentRule = V.defaultRules[0]; + SlaveSort.slaves(V.slaves); + + App.UI.SlaveList.ScrollPosition.restore(); + } + + /** + * @returns {Text} + */ + function fcnn() { + let text; + + if (V.FCNNstation !== 1 && V.week >= 90) { + text = "FCNN: FCNN service has been temporarily suspended. Please stand by."; + } else { + text = V.fcnn.random(); + } + + return document.createTextNode(`${text} `); + } + + /** + * @returns {HTMLDivElement} + */ function mainMenu() { const div = document.createElement("div"); div.append(App.UI.DOM.makeElement("span", "MAIN MENU", "name")); App.UI.DOM.appendNewElement("span", div, App.UI.DOM.passageLink("Summary Options", "Summary Options"), - ["tab", "note"]); + ["choices", "note"]); if (V.rulesAssistantMain !== 0) { div.append(" | "); @@ -269,30 +266,91 @@ App.MainView.full = function() { return div; } - const fragment = document.createDocumentFragment(); + /** + * @returns {DocumentFragment} + */ + function useFucktoys() { + const fragment = document.createDocumentFragment(); + for (const slave of V.slaves) { + if (slave.assignment !== Job.FUCKTOY) { + continue; + } + fragment.append(App.MainView.useFucktoy(slave)); + } + return fragment; + } - fragment.append(App.Reminders.list({maxFuture: 5, link: true})); + /** + * @returns {HTMLDivElement} + */ + function walkPast() { + const outerDiv = document.createElement("div"); - if (V.seeFCNN === 1) { - const div = document.createElement("div"); - div.classList.add("main-fcnn"); - div.append(App.MainView.fcnn(), - App.UI.DOM.passageLink("Hide", passage(), () => { V.seeFCNN = 0; }) - ); - fragment.append(div); + const slave = V.slaves.filter(s => ![Job.BODYGUARD, Job.FUCKTOY].includes(s.assignment)).random(); + if (slave) { + App.UI.DOM.appendNewElement("span", outerDiv, globalThis.walkPast(slave), "scene-intro"); + } + + return outerDiv; } - fragment.append(mainMenu()); + /** + * @returns {DocumentFragment} + */ + function assemble() { + const fragment = document.createDocumentFragment(); + if (V.newModelUI === 1) { + fragment.append(V.building.render()); + } + + if (V.seeArcology === 1) { + fragment.append(App.Desc.playerArcology( + App.UI.DOM.passageLink("Hide", "Main", () => {V.seeArcology = 0;}))); + } - fragment.append(App.UI.SlaveList.penthousePage()); + if (V.seeDesk === 1) { + fragment.append(App.Desc.officeDescription( + App.UI.DOM.passageLink("Hide", "Main", () => {V.seeDesk = 0;}))); + } + + fragment.append(App.Reminders.list({maxFuture: 5, link: true})); - if (V.fucktoyInteractionsPosition === 0) { - fragment.append(App.MainView.useFucktoys()); + if (V.seeFCNN === 1) { + const div = document.createElement("div"); + div.classList.add("main-fcnn"); + div.append(fcnn(), App.UI.DOM.passageLink("Hide", passage(), () => { V.seeFCNN = 0; }) + ); + fragment.append(div); + } + + fragment.append(mainMenu()); + + fragment.append(App.UI.SlaveList.penthousePage()); + + if (V.fucktoyInteractionsPosition === 0) { + fragment.append(useFucktoys()); + } + if (V.useSlaveSummaryOverviewTab === 0) { + fragment.append(App.MainView.useGuard()); + } + fragment.append(walkPast()); + + return fragment; } - if (V.useSlaveSummaryOverviewTab === 0) { - fragment.append(App.MainView.useGuard()); + + const fragment = document.createDocumentFragment(); + + fragment.append(errors()); + + // wrap everything in a try/catch statement, so App.MainView.errors() always gets shown. At the end print error out + // as well. + try { + cleanup(); + + fragment.append(assemble()); + } catch (ex) { + fragment.append(App.UI.DOM.formatException(ex)); } - fragment.append(App.MainView.walkPast()); return fragment; }; diff --git a/src/js/pregJS.js b/src/js/pregJS.js index 37a43d9378fde86db687d47cf19c4c072cbe118f..4447999dbbb2477629026f3fed4bce8dc4c29342 100644 --- a/src/js/pregJS.js +++ b/src/js/pregJS.js @@ -524,7 +524,7 @@ globalThis.getNurseryReserved = function( /* slaves */ ) { globalThis.findFather = function(fatherID) { let father; - father = V.slaves[V.slaveIndices[fatherID]]; + father = getSlave(fatherID); if (father === undefined) { if (V.incubator > 0) { father = V.tanks.find(s => s.ID === fatherID); diff --git a/src/js/pronouns.js b/src/js/pronouns.js index b90c0540243c28783cafda92140ad249d07b95ab..7aff23fdc14e6411866c137c62ca34acd41312e5 100644 --- a/src/js/pronouns.js +++ b/src/js/pronouns.js @@ -61,8 +61,12 @@ App.Utils.Pronouns = class { get sister() { return this.noun === "girl" ? "sister" : "brother"; } get Sister() { return capFirstChar(this.sister); } + // TODO: remove this once overhauled + // eslint-disable-next-line sonarjs/no-all-duplicated-branches get wife() { return this.noun === "girl" ? "wife" : "wife"; } get Wife() { return capFirstChar(this.wife); } + // TODO: remove this once overhauled + // eslint-disable-next-line sonarjs/no-all-duplicated-branches get wives() { return this.noun === "girl" ? "wives" : "wives"; } get Wives() { return capFirstChar(this.wives); } diff --git a/src/js/rbuttonJS.js b/src/js/rbuttonJS.js deleted file mode 100644 index 3afeec6c318f915275d2c15918eef9d6c7135519..0000000000000000000000000000000000000000 --- a/src/js/rbuttonJS.js +++ /dev/null @@ -1,101 +0,0 @@ -/* This is modified radiobutton macro, for automatic checked state setup*/ -/* Usage (be sure to use quotes around parameters): - - <<rbutton "$variable" "value">> -Or: - <<rbutton "$variable" "value" "HTML_element_ID" "Text to replace with, inside html element with ID from previous parameter. <br> HTML tags allowed.">> - -Group of radiobutton will be created based on variable name. Checked state will be set up if variable contain value matched with second parameter. Full form of macro call can be used to display extended description of selected value. -*/ - -Macro.add('rbutton', { - handler() { - if (this.args.length < 2) { - const errors = []; - if (this.args.length === 0) { errors.push('variable name'); } - if (this.args.length < 2) { errors.push('checked value'); } - return this.error(`no ${errors.join(' or ')} specified`); - } - - // Ensure that the variable name argument is a string. - if (typeof this.args[0] !== 'string') { - return this.error('variable name argument is not a string'); - } - - const varName = this.args[0].trim(); - - // Try to ensure that we receive the variable's name (incl. sigil), not its value. - if (varName[0] !== '$' && varName[0] !== '_') { - return this.error(`variable name "${this.args[0]}" is missing its sigil ($ or _)`); - } - - const initValue = Wikifier.getValue(this.args[0]); - const varId = Util.slugify(varName); - const checkValue = this.args[1]; - const el = document.createElement('input'); - - let replaceID = ""; - let replaceText = ""; - if (typeof this.args[2] === 'string') { - replaceID = this.args[2]; - } - if (typeof this.args[3] === 'string') { - replaceText = this.args[3]; - } - - /* - Setup and initialize the group counter. - */ - if (!TempState.hasOwnProperty(this.name)) { - TempState[this.name] = {}; - } - - if (!TempState[this.name].hasOwnProperty(varId)) { - TempState[this.name][varId] = 0; - } - - /* - Setup and append the input element to the output buffer. - */ - jQuery(el) - .attr({ - id: `${this.name}-${varId}-${TempState[this.name][varId]++}`, - name: `${this.name}-${varId}`, - type: 'radio', - tabindex: 0 // for accessibility - }) - .addClass(`macro-${this.name}`) - .on('change', function() { - if (this.checked) { - Wikifier.setValue(varName, checkValue); - - if (replaceID.length > 0 && replaceText.length > 0) { - let replaceEl = document.getElementById(replaceID); - // alert (replaceEl); - if (replaceEl !== null) { - replaceEl.innerHTML = replaceText; - } - } - } - }) - .ready(function() { - // alert ("DOM finished"); - if (el.checked && replaceID.length > 0 && replaceText.length > 0) { - let replaceEl = document.getElementById(replaceID); - // alert (replaceEl); - if (replaceEl !== null) { - replaceEl.innerHTML = replaceText; - } - } - }) - .appendTo(this.output); - - /* - Set the story variable to the checked value and the input element to checked, if requested. - */ - if (initValue === checkValue) { - el.checked = true; - Wikifier.setValue(varName, checkValue); - } - } -}); diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js index 294b86564f30c9595c969fb68c540dbb72a02da9..78be3d3730f617fe11a0ed7724cf2a022b5ddbb6 100644 --- a/src/js/rulesAssistantOptions.js +++ b/src/js/rulesAssistantOptions.js @@ -1836,11 +1836,11 @@ App.RA.options = (function() { ]; super("Collar", items); - const niceCollars = isItemAccessible.array(App.Data.slaveWear.collars, "harsh", false); + const niceCollars = isItemAccessible.array(App.Data.slaveWear.collar, "harsh", false); niceCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._nice = new ListSubSection(this, "Nice", niceCollars); - const harshCollars = isItemAccessible.array(App.Data.slaveWear.collars, "harsh", true); + const harshCollars = isItemAccessible.array(App.Data.slaveWear.collar, "harsh", true); harshCollars.sort(function(a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } return 0; }); this._harsh = new ListSubSection(this, "Harsh", harshCollars); @@ -1882,7 +1882,7 @@ App.RA.options = (function() { class CorsetList extends ListSelector { constructor() { - super("Corsetage", isItemAccessible.array(App.Data.slaveWear.bellyAccessories)); + super("Corsetage", isItemAccessible.array(App.Data.slaveWear.bellyAccessory)); this.setValue(current_rule.set.bellyAccessory); this.onchange = (value) => current_rule.set.bellyAccessory = value; } @@ -1928,7 +1928,7 @@ App.RA.options = (function() { class VagAccVirginsList extends ListSelector { constructor() { - super("Vaginal accessories for virgins", isItemAccessible.array(App.Data.slaveWear.vaginalAccessories)); + super("Vaginal accessories for virgins", isItemAccessible.array(App.Data.vaginalAccessory)); this.setValue(current_rule.set.virginAccessory); this.onchange = (value) => current_rule.set.virginAccessory = value; } @@ -1936,7 +1936,7 @@ App.RA.options = (function() { class VagAccAVirginsList extends ListSelector { constructor() { - super("Vaginal accessories for anal virgins", isItemAccessible.array(App.Data.slaveWear.vaginalAccessories)); + super("Vaginal accessories for anal virgins", isItemAccessible.array(App.Data.vaginalAccessory)); this.setValue(current_rule.set.aVirginAccessory); this.onchange = (value) => current_rule.set.aVirginAccessory = value; } @@ -1944,7 +1944,7 @@ App.RA.options = (function() { class VagAccOtherList extends ListSelector { constructor() { - super("Vaginal accessories for other slaves", isItemAccessible.array(App.Data.slaveWear.vaginalAccessories)); + super("Vaginal accessories for other slaves", isItemAccessible.array(App.Data.vaginalAccessory)); this.setValue(current_rule.set.vaginalAccessory); this.onchange = (value) => current_rule.set.vaginalAccessory = value; } @@ -1952,7 +1952,7 @@ App.RA.options = (function() { class VaginalAttachmentsList extends ListSelector { constructor() { - super("Vaginal attachments for slaves with vaginal accessories", isItemAccessible.array(App.Data.slaveWear.vaginalAttachments)); + super("Vaginal attachments for slaves with vaginal accessories", isItemAccessible.array(App.Data.slaveWear.vaginalAttachment)); this.setValue(current_rule.set.vaginalAttachment); this.onchange = (value) => current_rule.set.vaginalAttachment = value; } @@ -1972,7 +1972,7 @@ App.RA.options = (function() { class DickAccVirginsList extends ListSelector { constructor() { - super("Dick accessories for anal virgins", isItemAccessible.array(App.Data.slaveWear.dickAccessories)); + super("Dick accessories for anal virgins", isItemAccessible.array(App.Data.slaveWear.dickAccessory)); this.setValue(current_rule.set.aVirginDickAccessory); this.onchange = (value) => current_rule.set.aVirginDickAccessory = value; } @@ -1980,7 +1980,7 @@ App.RA.options = (function() { class DickAccOtherList extends ListSelector { constructor() { - super("Dick accessories for other slaves", isItemAccessible.array(App.Data.slaveWear.dickAccessories)); + super("Dick accessories for other slaves", isItemAccessible.array(App.Data.slaveWear.dickAccessory)); this.setValue(current_rule.set.dickAccessory); this.onchange = (value) => current_rule.set.dickAccessory = value; } @@ -2000,7 +2000,7 @@ App.RA.options = (function() { class ButtplugsVirginsList extends ListSelector { constructor() { - super("Buttplugs for anal virgins", isItemAccessible.array(App.Data.buttplugs)); + super("Buttplugs for anal virgins", isItemAccessible.array(App.Data.buttplug)); this.setValue(current_rule.set.aVirginButtplug); this.onchange = (value) => current_rule.set.aVirginButtplug = value; } @@ -2008,7 +2008,7 @@ App.RA.options = (function() { class ButtplugsOtherList extends ListSelector { constructor() { - super("Buttplugs for other slaves", isItemAccessible.array(App.Data.buttplugs)); + super("Buttplugs for other slaves", isItemAccessible.array(App.Data.buttplug)); this.setValue(current_rule.set.buttplug); this.onchange = (value) => current_rule.set.buttplug = value; } @@ -2016,7 +2016,7 @@ App.RA.options = (function() { class ButtplugAttachmentsList extends ListSelector { constructor() { - super("Buttplug attachments for slaves with buttplugs", isItemAccessible.array(App.Data.slaveWear.buttplugAttachments)); + super("Buttplug attachments for slaves with buttplugs", isItemAccessible.array(App.Data.slaveWear.buttplugAttachment)); this.setValue(current_rule.set.buttplugAttachment); this.onchange = (value) => current_rule.set.buttplugAttachment = value; } diff --git a/src/js/salon.js b/src/js/salon.js index 74916eb4ff5a80df035fa3a44c6ce96fda0e8b43..a3fa942df208b74281cc2222cfa2eb672fca41bb 100644 --- a/src/js/salon.js +++ b/src/js/salon.js @@ -1,6 +1,6 @@ /** * @param {FC.HumanState} entity - * @param {Boolean} cheat + * @param {boolean} cheat * @returns {HTMLDivElement} */ App.Medicine.Modification.eyeSelector = function(entity, cheat = false) { @@ -229,7 +229,7 @@ App.Medicine.Modification.eyeSelector = function(entity, cheat = false) { * @param {object} params * @param {number|string} [params.primaryEarColor=0] * @param {string} [params.secondaryEarColor=""] - * @param {Boolean} [params.cheat=false] + * @param {boolean} [params.cheat=false] * @returns {HTMLElement} */ App.Medicine.Salon.ears = function(slave, {primaryEarColor = 0, secondaryEarColor = "", cheat = false} = {}) { @@ -334,7 +334,7 @@ App.Medicine.Salon.ears = function(slave, {primaryEarColor = 0, secondaryEarColo * @param {object} params * @param {number|string} [params.primaryTailColor] * @param {string} [params.secondaryTailColor] - * @param {Boolean} [params.cheat] + * @param {boolean} [params.cheat] * @returns {JQuery<HTMLElement>} */ App.Medicine.Salon.tail = function(slave, {primaryTailColor = 0, secondaryTailColor = "", cheat = false} = {}) { diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js index 98d54d5a1ef59b370acc8d40768f49aade5c63cf..633da1e21d77e95b794b663b65e554f3619d8556 100644 --- a/src/js/slaveCostJS.js +++ b/src/js/slaveCostJS.js @@ -213,9 +213,9 @@ globalThis.BeautyArray = (function() { } } else { if (heightPass(slave)) { - adjustBeauty("Height: Statuesque Glorification", ((slave.height + heelLength(slave) - 169) * ((arcology.FSStatuesqueGlorification / 50) + 0.5))); + adjustBeauty("Height: Statuesque Glorification", ((slave.height + shoeHeight(slave) - 169) * ((arcology.FSStatuesqueGlorification / 50) + 0.5))); } else { - adjustBeauty("Height: Statuesque Glorification", -(((arcology.FSStatuesqueGlorification / 10) + (170 - slave.height + heelLength(slave))) * 2)); + adjustBeauty("Height: Statuesque Glorification", -(((arcology.FSStatuesqueGlorification / 10) + (170 - slave.height + shoeHeight(slave))) * 2)); } } } else { @@ -809,6 +809,14 @@ globalThis.BeautyArray = (function() { adjustBeauty("Boob Shape", -4); } else if (slave.boobShape === "saggy") { adjustBeauty("Boob Shape", -4); + } else if (slave.boobShape === "spherical") { + if (arcology.FSTransformationFetishist !== "unset") { + adjustBeauty("Boob Shape: Transformation Fetishist", (arcology.FSTransformationFetishist / 10)); + } else if (arcology.FSBodyPurist !== "unset") { + adjustBeauty("Boob Shape: Body Purist", -(arcology.FSBodyPurist / 2)); + } else { + adjustBeauty("Boob Shape", -1); + } } } if (slave.nipples === "huge") { @@ -823,6 +831,12 @@ globalThis.BeautyArray = (function() { if (arcology.FSTransformationFetishist !== "unset") { adjustBeauty("Nipples: Transformation Fetishist", (arcology.FSTransformationFetishist / 10)); } + } else if (slave.nipples === "flat") { + if (arcology.FSTransformationFetishist !== "unset") { + adjustBeauty("Nipples: Transformation Fetishist", (arcology.FSTransformationFetishist / 20)); + } else { + adjustBeauty("Nipples", -2); + } } } diff --git a/src/js/textbox2.js b/src/js/textbox2.js deleted file mode 100644 index 9f6330d631498671f21c0888e2690ca695dbcf3c..0000000000000000000000000000000000000000 --- a/src/js/textbox2.js +++ /dev/null @@ -1,88 +0,0 @@ -Macro.add("textbox2", { - handler: function() { - if (this.args.length < 2) { - const e = []; - return this.args.length < 1 && e.push("variable name"), this.args.length < 2 && e.push("default value"), this.error(`no ${e.join(" or ")} specified`); - } - if (typeof this.args[0] !== "string") { return this.error("variable name argument is not a string"); } - const t = this.args[0].trim(); - if (t[0] !== "$" && t[0] !== "_") { return this.error(`variable name "${this.args[0]}" is missing its sigil ($ or _)`); } - Config.debug && this.debugView.modes({ - block: true - }); - const r = Util.slugify(t); - const a = this.args[1]; - const isNumber = typeof(a) === "number"; - const inputElement = document.createElement("input"); - let autofocus = false; - let passage = void 0; - let setargs = null; - if (this.args.length > 3) { - passage = this.args[2]; - autofocus = this.args[3] === "autofocus"; - if (!autofocus) { - setargs = this.args[3]; - } - } else if (this.args.length > 2) { - if (this.args[2] === "autofocus") { - autofocus = true; - } else { - passage = this.args[2]; - } - } - if (passage !== (void 0) && typeof(passage) === "object") { - passage = passage.link; - } - if (!passage) { - passage = State.passage; - } - - function gotoPassage() { - if (passage) { - const currentScrollPosition = window.pageYOffset; - const currentPassage = State.passage; - if (setargs) { - Scripting.evalTwineScript(setargs); - } - Engine.play(passage); - if (currentPassage === passage) { - Scripting.evalJavaScript(`window.scrollTo(0, ${currentScrollPosition});`); - } - } - } - - function valueToNumberIfSame(v) { - if (!isNumber) { - return v; - } // Do nothing - try { - return parseInt(v, 10); - } catch (error) { - return v; - } - } - - jQuery(inputElement).attr({ - id: `${this.name}-${r}`, - name: `${this.name}-${r}`, - // type: isNumber ? "number" : "text", /* TODO - hide spinner if we do this */ - tabindex: 0 - }).addClass(`macro-${this.name}`) - .on("change", function() { - State.setVar(t, valueToNumberIfSame(this.value)); - }).on("blur", function() { - State.setVar(t, valueToNumberIfSame(this.value)); - // eslint-disable-next-line eqeqeq - if (this.value != a) { // If the value has actually changed, reload the page. Note != and not !== because types might be different - gotoPassage(); - } - }) - .on("keypress", function(e) { - e.which === 13 && (e.preventDefault(), State.setVar(t, valueToNumberIfSame(this.value)), gotoPassage()); - }).appendTo(this.output), State.setVar(t, a), inputElement.value = a, autofocus && (inputElement.setAttribute("autofocus", "autofocus"), postdisplay[`#autofocus:${inputElement.id}`] = function(e) { - delete postdisplay[e], setTimeout(function() { - return inputElement.focus(); - }, Engine.minDomActionDelay); - }); - } -}); diff --git a/src/js/textboxJS.js b/src/js/textboxJS.js deleted file mode 100644 index 0e0aaae708ffe40f67d5ef6b435489a3ac9e7b02..0000000000000000000000000000000000000000 --- a/src/js/textboxJS.js +++ /dev/null @@ -1,26 +0,0 @@ -/* Nicked off greyelf, works for replace textboxes */ -globalThis.setReplaceTextboxMaxLength = function(storyVarName, maxLength) { - const textboxId = `#textbox-${Util.slugify(storyVarName)}`; - $(textboxId) - .attr("maxlength", maxLength) - .css({ - "min-width": "initial", - "width": `${maxLength}em`, - "padding": "3px 2px" - }); -}; - -/* Nicked off TheMadExile, works for non-replace textboxes */ -globalThis.setTextboxMaxLength = function(storyVarName, maxLength) { - const textboxId = `#textbox-${Util.slugify(storyVarName)}`; - postdisplay[`${textboxId}-maxlength`] = function(taskName) { - delete postdisplay[taskName]; - $(textboxId) - .attr("maxlength", maxLength) - .css({ - "min-width": "initial", - "width": `${maxLength}em`, - "padding": "3px 2px" - }); - }; -}; diff --git a/src/js/utilsAssessSlave.js b/src/js/utilsAssessSlave.js index 5dfda9f45376541bcf3a49cdc56a67136472f72a..eb84a673e9283ba12d04584d2a8fcef2d62b9e02 100644 --- a/src/js/utilsAssessSlave.js +++ b/src/js/utilsAssessSlave.js @@ -274,7 +274,8 @@ globalThis.shoeHeight = function(slave) { * @returns {0|1|2|3} */ globalThis.plugWidth = function(slave) { - return App.Data.buttplugs.get(slave.buttplug) ? App.Data.buttplugs.get(slave.buttplug).width : 0; + const plug = App.Data.buttplug.get(slave.buttplug) || V.customItem.buttplug.get(slave.buttplug); + return plug.width || 0; }; /** @@ -282,8 +283,37 @@ globalThis.plugWidth = function(slave) { * @returns {0|1|2|3} */ globalThis.plugLength = function(slave) { - return App.Data.buttplugs.get(slave.buttplug) ? App.Data.buttplugs.get(slave.buttplug).length : 0; + const plug = App.Data.buttplug.get(slave.buttplug) || V.customItem.buttplug.get(slave.buttplug); + return plug.length || 0; }; +/** + * @param {App.Entity.SlaveState} slave + * @returns {0|1|2|3} + */ +globalThis.dildoWidth = function(slave) { + const dildo = App.Data.vaginalAccessory.get(slave.vaginalAccessory) || V.customItem.vaginalAccessory.get(slave.vaginalAccessory); + if (dildo === undefined) { + console.log("missing dildo: ", slave.vaginalAccessory) + return 0 + } + return dildo.width || 0; +}; +/** + * @param {App.Entity.SlaveState} slave + * @returns {0|1|2} + */ +globalThis.dildoLength = function(slave) { + const dildo = App.Data.vaginalAccessory.get(slave.vaginalAccessory) || V.customItem.vaginalAccessory.get(slave.vaginalAccessory); + return dildo.length || 0; +}; +/** + * @param {App.Entity.SlaveState} slave + * @returns {number} + */ +globalThis.dildoVibeLevel = function(slave) { + const dildo = App.Data.vaginalAccessory.get(slave.vaginalAccessory) || V.customItem.vaginalAccessory.get(slave.vaginalAccessory); + return dildo.vibrates || 0; +}; diff --git a/src/js/utilsDOM.js b/src/js/utilsDOM.js index a904b1117d55ad28749c8419ac08551872fc53e8..9d50e766450f6034b6757e0b4253532fed5c35da 100644 --- a/src/js/utilsDOM.js +++ b/src/js/utilsDOM.js @@ -438,3 +438,65 @@ App.UI.DOM.cashFormat = function(s) { span.textContent = cashFormat(Math.trunc(s)); return span; }; + +/** + * Renders an exception to DOM. + * Tries it's best to not fail itself. + * + * @param {Error } ex Exception + * @param {boolean} recursion set if formatException() called itself, never set from outside + * @returns {DocumentFragment|HTMLParagraphElement} + */ +App.UI.DOM.formatException = function formatException(ex, recursion = false) { + /** + * In case the normal rendering failed attempts to provide some information on it. + * In the worst case gives back a default error message. + * + * @param {Error} exception + * @returns {DocumentFragment|HTMLParagraphElement} + */ + function failSafe(exception) { + if (!recursion) { + return formatException(exception, true); + } else { + // Not using custom functions here, as they may be the cause of the error + const p = document.createElement("p"); + p.classList.add("bold", "error"); + p.append("Unrecoverable error in App.UI.DOM.formatException()! Please report this."); + return p; + } + } + + /** + * Renders the exception to DOM + * + * @returns {DocumentFragment} + */ + function render() { + const fragment = document.createDocumentFragment(); + + App.UI.DOM.appendNewElement("p", fragment, `${ex.name}: ${ex.message}; ${Config.saves.version}`, ["bold", "error"]); + + const p = document.createElement("p"); + const lines = ex.stack.split("\n"); + for (const ll of lines) { + const div = document.createElement("div"); + // remove file path from error message + div.append(ll.replace(/file:.*\//, "<path>/")); + p.append(div); + } + fragment.append(p); + + return fragment; + } + + try { + if (!ex) { + // Create a new Error so we have access to a stacktrace. + return failSafe(new Error("No exception provided!")); + } + return render(); + } catch (ex) { + return failSafe(ex); + } +}; diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js index 09a09b0cb5564b77eb26e7fa8019c14adb4e112d..08c031f857896596e3e96e3643f1e404bc0c6410 100644 --- a/src/js/utilsSlave.js +++ b/src/js/utilsSlave.js @@ -2636,6 +2636,8 @@ globalThis.DegradingName = function(slave) { } if (slave.nipples === "fuckable") { names.push("Nipplefuck", "Nipplecunt"); + } else if (slave.nipples === "flat") { + names.push("Pancakes", "Stretched"); } else if (slave.nipples !== "tiny" && slave.nipples !== "cute") { names.push("Pointy", "Titclit"); suffixes.push("Nipples"); diff --git a/src/js/vignettes.js b/src/js/vignettes.js index 19d378fcf5ea2b02adac30a3bb662bdccc2dc7ca..336f7d970abdbb7cfb7363c49f3c1b73b6c102a5 100644 --- a/src/js/vignettes.js +++ b/src/js/vignettes.js @@ -1669,7 +1669,7 @@ globalThis.GetVignette = function(slave) { effect: 2, }); } - if (slave.nipples === "fuckable") { + if (slave.nipples === "fuckable" || slave.nipples === "flat") { vignettes.push({ text: `${he} lost a customer who refused ${he} could possibly be a proper cow with nipples like ${hers},`, type: "cash", @@ -3661,7 +3661,7 @@ globalThis.GetVignette = function(slave) { effect: 2, }); } - if (slave.nipples === "fuckable") { + if (slave.nipples === "fuckable" || slave.nipples === "flat") { vignettes.push({ text: `${he} left a citizen deeply confused over how ${he} could possibly be a proper cow without suitable teats,`, type: "rep", diff --git a/src/markets/specificMarkets/eliteSlave.js b/src/markets/specificMarkets/eliteSlave.js index c7334622a6ab9ecb9351a590dc884b991625d617..cb7d7dc545967695421102e3c27b55df5833ac59 100644 --- a/src/markets/specificMarkets/eliteSlave.js +++ b/src/markets/specificMarkets/eliteSlave.js @@ -159,14 +159,19 @@ App.Markets["Elite Slave"] = function() { slave.buttImplantType = "normal"; } } + if (slave.nipples === "tiny") { + slave.nipples = "puffy"; + } if (V.arcologies[0].FSTransformationFetishist > 20) { - slave.boobShape = "normal"; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } } else { slave.boobShape = either("perky", "perky", "torpedo-shaped", "wide-set"); } - if (slave.nipples === "tiny") { - slave.nipples = "puffy"; - } slave.face = 100; slave.faceShape = either("cute", "cute", "exotic", "exotic", "normal", "normal", "sensual", "sensual", "sensual"); slave.lips = random(45, 75); diff --git a/src/markets/specificMarkets/prestigiousSlave.js b/src/markets/specificMarkets/prestigiousSlave.js index a3d787f709e58dcfa83d46054e821368c71a41e8..6b23545247eefbb46eebde4fb5ab2960c0dcfcd0 100644 --- a/src/markets/specificMarkets/prestigiousSlave.js +++ b/src/markets/specificMarkets/prestigiousSlave.js @@ -49,7 +49,12 @@ App.Markets["Prestigious Slave"] = function() { slave.boobsImplant += random(4, 6) * 200; slave.boobs += slave.boobsImplant; slave.boobsImplantType = "string"; - slave.nipples = either("cute", "huge", "puffy"); + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.nipples = either("cute", "huge", "puffy"); + } slave.areolae = 1; slave.butt += 1; slave.buttImplant += 1; @@ -205,7 +210,12 @@ App.Markets["Prestigious Slave"] = function() { slave.boobsImplant += random(10, 15) * 200; slave.boobs += slave.boobsImplant; slave.boobsImplantType = "fillable"; - slave.nipples = either("cute", "huge", "puffy"); + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.nipples = either("cute", "huge", "puffy"); + } slave.areolae = 2; slave.butt += 4; slave.buttImplant += 4; @@ -351,7 +361,12 @@ App.Markets["Prestigious Slave"] = function() { slave.boobs += slave.boobsImplant; slave.boobsImplantType = "advanced fillable"; slave.boobs += 1000; - slave.nipples = either("cute", "huge", "puffy"); + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.nipples = either("cute", "huge", "puffy"); + } slave.areolae = 2; slave.buttImplant += random(6, 8); slave.butt += slave.buttImplant; @@ -512,7 +527,12 @@ App.Markets["Prestigious Slave"] = function() { slave.boobsImplant += random(4, 6) * 200; slave.boobs += slave.boobsImplant; slave.boobsImplantType = "fillable"; - slave.nipples = either("cute", "huge", "puffy"); + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.nipples = either("cute", "huge", "puffy"); + } slave.areolae = 1; slave.butt += 1; slave.buttImplant += 1; @@ -666,7 +686,12 @@ App.Markets["Prestigious Slave"] = function() { slave.boobsImplant += random(10, 15) * 200; slave.boobs += slave.boobsImplant; slave.boobsImplantType = "advanced fillable"; - slave.nipples = either("cute", "huge", "puffy"); + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.nipples = either("cute", "huge", "puffy"); + } slave.areolae = 2; slave.butt += 4; slave.buttImplant += 4; diff --git a/src/neighbor/neighborInteract.js b/src/neighbor/neighborInteract.js index d97e7bf72689244e2ca69640739276515373f89c..0c33267cb3be5417179b872eec9afc5437aee92d 100644 --- a/src/neighbor/neighborInteract.js +++ b/src/neighbor/neighborInteract.js @@ -292,24 +292,24 @@ App.Neighbor.Interact = (function() { } } - addAcquisitionBlock("FSRomanRevivalist", "a toga", "clothing", "togas", () => { V.boughtItem.clothing.toga = 1; }); - addAcquisitionBlock("FSEdoRevivalist", "a kimono", "clothing", "kimonos", () => { V.boughtItem.clothing.kimono = 1; }); - addAcquisitionBlock("FSArabianRevivalist", "harem gauze", "clothing", "silken harem garb", () => { V.boughtItem.clothing.harem = 1; }); - addAcquisitionBlock("FSAztecRevivalist", "a huipil", "clothing", "huipils", () => { V.boughtItem.clothing.huipil = 1; }); - addAcquisitionBlock("FSChineseRevivalist", "a slutty qipao", "clothing", "skimpy qipaos", () => { V.boughtItem.clothing.qipao = 1; }); + addAcquisitionBlock("FSRomanRevivalist", "a toga", "clothes", "togas", () => { V.boughtItem.clothing.toga = 1; }); + addAcquisitionBlock("FSEdoRevivalist", "a kimono", "clothes", "kimonos", () => { V.boughtItem.clothing.kimono = 1; }); + addAcquisitionBlock("FSArabianRevivalist", "harem gauze", "clothes", "silken harem garb", () => { V.boughtItem.clothing.harem = 1; }); + addAcquisitionBlock("FSAztecRevivalist", "a huipil", "clothes", "huipils", () => { V.boughtItem.clothing.huipil = 1; }); + addAcquisitionBlock("FSChineseRevivalist", "a slutty qipao", "clothes", "skimpy qipaos", () => { V.boughtItem.clothing.qipao = 1; }); addAcquisitionBlock("FSEgyptianRevivalist", "ancient Egyptian", "collar", "Egyptian necklace replicas", () => { V.boughtItem.clothing.egypt = 1; }); - addAcquisitionBlock("FSPaternalist", "conservative clothing", "clothing", "conservative clothing", () => { V.boughtItem.clothing.conservative = 1; }); - addAcquisitionBlock("FSDegradationist", "chains", "clothing", "binding chains", () => { V.boughtItem.clothing.chains = 1; }); - addAcquisitionBlock("FSGenderFundamentalist", "a bunny outfit", "clothing", "bunny suits", () => { V.boughtItem.clothing.bunny = 1; }); - addAcquisitionBlock("FSIntellectualDependency", "a bimbo outfit", "clothing", "bimbo attire", () => { V.boughtItem.clothing.bimbo = 1; }); - addAcquisitionBlock("FSSlaveProfessionalism", "a courtesan dress", "clothing", "courtesan dresses", () => { V.boughtItem.clothing.courtesan = 1; }); - // addAcquisitionBlock("FSPetiteAdmiration", "petite dress", "clothing", "petite-sized dresses", () => { V.boughtItem.clothing.petite = 1; }); - addAcquisitionBlock("FSPhysicalIdealist", "body oil", "clothing", "body oil", () => { V.boughtItem.clothing.oil = 1; }); - addAcquisitionBlock("FSHedonisticDecadence", "stretch pants and a crop-top", "clothing", "stretch pants and crop-tops", () => { V.boughtItem.clothing.lazyClothes = 1; }); - addAcquisitionBlock("FSChattelReligionist", "a chattel habit", "clothing", "chattel religionist habits", () => { V.boughtItem.clothing.habit = 1; }); - addAcquisitionBlock("FSPastoralist", "Western clothing", "clothing", "Western clothing", () => { V.boughtItem.clothing.western = 1; }); - addAcquisitionBlock("FSRepopulationFocus", "a maternity dress", "clothing", "maternity dresses", () => { V.boughtItem.clothing.maternityDress = 1; }); - addAcquisitionBlock("FSRepopulationFocus", "attractive lingerie for a pregnant woman", "clothing", "maternity lingerie", () => { V.boughtItem.clothing.maternityLingerie = 1; }); + addAcquisitionBlock("FSPaternalist", "conservative clothing", "clothes", "conservative clothing", () => { V.boughtItem.clothing.conservative = 1; }); + addAcquisitionBlock("FSDegradationist", "chains", "clothes", "binding chains", () => { V.boughtItem.clothing.chains = 1; }); + addAcquisitionBlock("FSGenderFundamentalist", "a bunny outfit", "clothes", "bunny suits", () => { V.boughtItem.clothing.bunny = 1; }); + addAcquisitionBlock("FSIntellectualDependency", "a bimbo outfit", "clothes", "bimbo attire", () => { V.boughtItem.clothing.bimbo = 1; }); + addAcquisitionBlock("FSSlaveProfessionalism", "a courtesan dress", "clothes", "courtesan dresses", () => { V.boughtItem.clothing.courtesan = 1; }); + // addAcquisitionBlock("FSPetiteAdmiration", "petite dress", "clothes", "petite-sized dresses", () => { V.boughtItem.clothing.petite = 1; }); + addAcquisitionBlock("FSPhysicalIdealist", "body oil", "clothes", "body oil", () => { V.boughtItem.clothing.oil = 1; }); + addAcquisitionBlock("FSHedonisticDecadence", "stretch pants and a crop-top", "clothes", "stretch pants and crop-tops", () => { V.boughtItem.clothing.lazyClothes = 1; }); + addAcquisitionBlock("FSChattelReligionist", "a chattel habit", "clothes", "chattel religionist habits", () => { V.boughtItem.clothing.habit = 1; }); + addAcquisitionBlock("FSPastoralist", "Western clothing", "clothes", "Western clothing", () => { V.boughtItem.clothing.western = 1; }); + addAcquisitionBlock("FSRepopulationFocus", "a maternity dress", "clothes", "maternity dresses", () => { V.boughtItem.clothing.maternityDress = 1; }); + addAcquisitionBlock("FSRepopulationFocus", "attractive lingerie for a pregnant woman", "clothes", "maternity lingerie", () => { V.boughtItem.clothing.maternityLingerie = 1; }); addAcquisitionBlock("FSRepopulationFocus", "a small empathy belly", "bellyAccessory", "empathy bellies", () => { V.boughtItem.clothing.belly = 1; }); addAcquisitionBlock("FSStatuesqueGlorification", "platform heels", "shoes", "platform shoes", () => { V.boughtItem.shoes.heels = 1; }); diff --git a/src/npc/agent/agentCompany.js b/src/npc/agent/agentCompany.js new file mode 100644 index 0000000000000000000000000000000000000000..5d4d65093c590c53cd745ed16a6a21ca6856255c --- /dev/null +++ b/src/npc/agent/agentCompany.js @@ -0,0 +1,81 @@ +/** Reassign your agent's lover to the arcology run by your agent + * @param {App.Entity.SlaveState} lover + * @returns {DocumentFragment} + */ +App.UI.SlaveInteract.agentCompany = function(lover) { + const frag = document.createDocumentFragment(); + + const agent = getSlave(lover.relationshipTarget); + const neighborArcology = V.arcologies.find((a) => agent.ID === a.leaderID); + const {he, him, his, himself} = getPronouns(lover); + const {He2, His2, he2, him2, his2, wife2} = getPronouns(agent).appendSuffix('2'); + const {say} = getEnunciation(lover); + const {say: say2} = getEnunciation(agent); + + // make the assignment + assignJob(lover, Job.AGENTPARTNER); + + // clear rivalry if applicable + const rival = getSlave(lover.rivalryTarget); + if (rival) { + rival.rivalry = 0; + rival.rivalryTarget = 0; + } + lover.rivalry = 0; + lover.rivalryTarget = 0; + + // output text + let r = []; + r.push(`Working in ${neighborArcology.name}'s penthouse office, ${agent.slaveName} gets a video call from you. Naturally, ${his2} personal assistant program has been instructed to give these the highest priority, and your face appears in front of ${him2} immediately. ${He2} greets you properly, and asks you what ${he2} can do to serve you. You tell ${him2} you're planning to send one of your slaves over to ${his2} arcology to assist ${him2}. Exchanges of this kind are neither unusual nor particularly interesting, so a slight look of perplexity clouds ${agent.slaveName}'s face as ${he2} wonders why this merits a personal call. Normally, ${S.HeadGirl ? S.HeadGirl.slaveName : V.assistant.name} would handle it with ${him2} directly.`); + App.Events.addParagraph(frag, r); + + r = []; + r.push(`${His2} question is answered when you bring ${contextualIntro(agent, lover)} in close, putting ${him} in ${agent.slaveName}'s view. ${agent.slaveName}'s ${App.Desc.eyesColor(agent)} fly open with pleased surprise, but before ${he2} can speak, ${lover.slaveName} goes first.`); + + if (!canTalk(lover)) { + r.push(`Unable to speak ${himself}, ${he} simply makes a heart shape with ${his} ${hasBothArms(lover) ? "hands" : "hand"} in view of the video call, and blows ${his} ${lover.relationship === 4 ? "lover" : wife2} a kiss.`); + } else { + r.push(Spoken(lover, `"Hi ${lover.relationship === 4 ? 'lover' : 'sweetheart'},"`)); + r.push(`${he} ${say}s in a syrupy tone.`); + r.push(Spoken(lover, `"Miss me?"`)); + } + App.Events.addParagraph(frag, r); + + r = []; + r.push(`${agent.slaveName} smiles back at ${him}, glowing with pleasure, and responds with exaggerated arousal.`); + switch (agent.fetish) { + case "submissive": + r.push(Spoken(agent, `"Looking forward to sleeping in your arms, babe,"`), `the submissive`); + break; + case "cumslut": + r.push(Spoken(agent, `"Can't wait to kiss you, babe,"`), `the orally fixated`); + break; + case "humiliation": + r.push(Spoken(agent, `"Can't wait to take you right in the middle of the plaza here,"`), `the exhibitionist`); + break; + case "buttslut": + r.push(Spoken(agent, `"I can't wait to fuck you in your hot little ass,"`), `the anally fixated`); + break; + case "boobs": + r.push(Spoken(agent, `"Looking forward to feeling your breasts again,"`), `the boob-loving`); + break; + case "pregnancy": + r.push(Spoken(agent, `"Can't wait to share all the pregnant girls here with you,"`), `the impregnation fetishist`); + break; + case "dom": + r.push(Spoken(agent, `"Looking forward to shoving you facedown, bitch,"`), `the dominant`); + break; + case "sadist": + r.push(Spoken(agent, `"Looking forward to making you bite the pillow again, bitch,"`), `the sadistic`); + break; + case "masochist": + r.push(Spoken(agent, `"Can't wait to feel you hurt me again, babe,"`), `the masochistic`); + break; + default: + r.push(Spoken(agent, `"Babe, I can't wait to ${hasAnyArms(agent) ? "give you a hug and" : ""} tell you about ${neighborArcology.name},"`), `the loving`); + } + r.push(`leader of an entire arcology ${say2}s.`); + App.Events.addParagraph(frag, r); + + return frag; +}; diff --git a/src/npc/agent/agentCompany.tw b/src/npc/agent/agentCompany.tw deleted file mode 100644 index c8ea98825ad766a54c166e5918e623e39c211404..0000000000000000000000000000000000000000 --- a/src/npc/agent/agentCompany.tw +++ /dev/null @@ -1,61 +0,0 @@ -:: Agent Company [nobr] - -<<set $nextButton = "Continue", $nextLink = "AS Dump", $returnTo = "Neighbor Interact">> - -<<= assignJob(getSlave($AS), "live with your agent")>> - -<<if getSlave($AS).rivalry > 0>> - <<set _i = $slaveIndices[getSlave($AS).rivalryTarget]>> - <<if def _i>> - <<set $slaves[_i].rivalry = 0, $slaves[_i].rivalryTarget = 0>> - <<else>> - @@.red;Error, slave rival not found.@@ - <</if>> - <<set getSlave($AS).rivalry = 0, getSlave($AS).rivalryTarget = 0>> -<</if>> - -<<set _neighborArcology = $arcologies.find(function(s) { return $subSlave.ID == s.leaderID; })>> - -<<setLocalPronouns $subSlave 2>> - -Working in _neighborArcology.name's penthouse office, $subSlave.slaveName gets a video call from you. Naturally, _his2 personal assistant program has been instructed to give these the highest priority, and your face appears in front of _him2 immediately. _He2 greets you properly, and asks you what _he2 can do to serve you. You tell _him2 you're planning to send one of your slaves over to _his2 arcology to assist _him2. Exchanges of this kind are neither unusual nor particularly interesting, so a slight look of perplexity clouds $subSlave.slaveName's face as _he2 wonders why this merits a personal call. Normally, <<if $HeadGirlID>>_S.HeadGirl.slaveName<<else>>$assistant.name<</if>> would handle it with _him2 directly. - -<br><br> - -_His2 question is answered when you bring <<= contextualIntro($subSlave, getSlave($AS))>> in close, putting $him in $subSlave.slaveName's view. $subSlave.slaveName's <<= App.Desc.eyesColor($subSlave)>> fly open with pleased surprise, but before _he2 can speak, <<= getSlave($AS).slaveName>> goes first. -<<if !canTalk(getSlave($AS))>> - Unable to speak $himself, $he simply makes a heart shape with $his hand<<if hasBothArms(getSlave($AS))>>s<</if>> in view of the video call, and blows $his <<if getSlave($AS).relationship == 4>>lover<<else>>_wife2<</if>> a kiss. -<<else>> - <<run Enunciate(getSlave($AS))>> - "Hi <<if getSlave($AS).relationship == 4>>lover<<else>><<s>>weetheart<</if>>," $he <<say>>s in a syrupy tone. "Mi<<ss>> me?" -<</if>> - -<br><br> - -$subSlave.slaveName smiles back at $him, glowing with pleasure, and responds with exaggerated arousal. - -<<run Enunciate($subSlave)>> - -<<switch $subSlave.fetish>> -<<case "submissive">> - "Looking forward to <<s>>leeping in your arm<<s>>, babe," the submissive -<<case "cumslut">> - "Can't wait to ki<<ss>> you, babe," the orally fixated -<<case "humiliation">> - "Can't wait to take you right in the middle of the pla<<z>>a here," the exhibitionist -<<case "buttslut">> - "I can't wait to fuck you in your hot little a<<ss>>," the anally fixated -<<case "boobs">> - "Looking forward to feeling your brea<<s>>t<<s>> again," the boob-loving -<<case "pregnancy">> - "Can't wait to <<sh>>are all the pregnant girl<<s>> here with you," the impregnation fetishist -<<case "dom">> - "Looking forward to <<sh>>oving you fa<<c>>edown, bitch," the dominant -<<case "sadist">> - "Looking forward to making you bite the pillow again, bitch," the sadistic -<<case "masochist">> - "Can't wait to feel you hurt me again, babe," the masochistic -<<default>> - "Babe, I can't wait to <<if hasAnyArms($subSlave)>>give you a hug and <</if>>tell you about _neighborArcology.name," the loving -<</switch>> -leader of an entire arcology <<say>>s. diff --git a/src/npc/agent/agentFramework.js b/src/npc/agent/agentFramework.js index eac96b3bd9824fa6345b6c729e7ff195ad65aa05..5b00810ecb346a02ad6bf240e724b6ab35c877ee 100644 --- a/src/npc/agent/agentFramework.js +++ b/src/npc/agent/agentFramework.js @@ -13,7 +13,7 @@ App.Data.Facilities.arcologyAgent = { manager: { position: "agent", assignment: Job.AGENT, - careers: "an arcology owner", + careers: ["an arcology owner"], skill: "headGirl", publicSexUse: true, fuckdollAccepted: false, diff --git a/src/npc/children/childInteract.tw b/src/npc/children/childInteract.tw index 66c6d61c00f0991240066704887f1f959e72796b..42fe6fada60f492f28901c28f8e49f300daa7af2 100644 --- a/src/npc/children/childInteract.tw +++ b/src/npc/children/childInteract.tw @@ -967,7 +967,7 @@ FIXME: <</if>> <</if>> <<if $dispensary == 1>> - <<if ($activeChild.nipples === "partially inverted" || $activeChild.nipples === "inverted" || $activeChild.nipples === "tiny" || $activeChild.nipples === "cute" || $activeChild.nipples === "puffy")>> + <<if (["inverted", "partially inverted", "cute", "tiny", "puffy", "flat"].includes($activeChild.nipples))>> | <<link "Nipple enhancers">> <<set $activeChild.drugs = "nipple enhancers">> <</link>> diff --git a/src/npc/children/longChildDescription.js b/src/npc/children/longChildDescription.js index 9d25f7664b8a8b422787297c243d6dde3217ae18..725e764ec10dd99feed3a90b544c7292c0f7a187 100644 --- a/src/npc/children/longChildDescription.js +++ b/src/npc/children/longChildDescription.js @@ -7214,15 +7214,15 @@ App.Facilities.Nursery.LongChildDescription = function(child, {market = 0, event } if (child.rivalry) { - let lcd = V.slaveIndices[child.rivalryTarget]; - if (jsDef(lcd)) { + const rival = getSlave(child.rivalryTarget); + if (rival !== undefined) { r += `${He} `; if (child.rivalry <= 1) { - r += `<span class="lightsalmon">dislikes</span> ${SlaveFullName(slaves[lcd])}. `; + r += `<span class="lightsalmon">dislikes</span> ${SlaveFullName(rival)}. `; } else if (child.rivalry <= 2) { - r += `is ${SlaveFullName(slaves[lcd])}>>'s <span class="lightsalmon">rival.</span> `; + r += `is ${SlaveFullName(rival)}>>'s <span class="lightsalmon">rival.</span> `; } else { - r += `<span class="lightsalmon">bitterly hates</span> ${SlaveFullName(slaves[lcd])}>>. `; + r += `<span class="lightsalmon">bitterly hates</span> ${SlaveFullName(rival)}>>. `; } } } diff --git a/src/npc/descriptions/boobs/boobs.js b/src/npc/descriptions/boobs/boobs.js index 2d8c25c3ccc5c1e4ffa81fe28354243773fd8e56..9a5f6b93a9cb170ceca1a256be66e2387d333a18 100644 --- a/src/npc/descriptions/boobs/boobs.js +++ b/src/npc/descriptions/boobs/boobs.js @@ -1199,17 +1199,11 @@ App.Desc.boobs = function() { case "leather pants and pasties": case "panties and pasties": case "pasties": - r += `${slave.slaveName}'s breasts `; - if (slave.boobs > 12000) { - r += `are completely bare, except for the pasties covering ${his} nipples.`; - } else if (slave.boobs > 8000) { - r += `are completely bare, except for the pasties covering ${his} nipples.`; - } else if (slave.boobs > 4000) { - r += `are completely bare, except for the pasties covering ${his} nipples.`; - } else if (slave.boobs < 300) { - r += `are completely bare, except for the pasties covering ${his} nipples.`; + r += `${slave.slaveName}'s breasts`; + if (slave.boobs > 25000) { + r += `are completely bare, save for the proportionally tiny pasties covering ${his} ${slave.nipples} nipples.`; } else { - r += `are completely bare, except for the pasties covering ${his} nipples.`; + r += `are completely bare, save for the pasties covering ${his} ${slave.nipples} nipples.`; } break; case "a bra": @@ -1657,6 +1651,9 @@ App.Desc.nipples = function(slave, {market, eventDescription} = {}) { case "tiny": r += `tiny ${nipColor} nipples are too small for the milkers, and the suction is drawing a lot of boob in with them.`; break; + case "flat": + r += `flat ${nipColor} nipples give nothing for the milkers to catch, so it falls to the suction to keep the cups stuck to ${his} ${(slave.boobsImplant / slave.boobs) >= 0.90 ? "firm " : ""}breasts.`; + break; case "puffy": r += `puffy ${nipColor} nipples form a good seal against the milkers' suction.`; break; @@ -1682,6 +1679,9 @@ App.Desc.nipples = function(slave, {market, eventDescription} = {}) { case "tiny": r += 'stiff little nubs.'; break; + case "flat": + r += 'stiff bumps and anything but flat at the moment.'; + break; case "puffy": r += 'puffy and erect, the stiff flesh around each swelling outward to a pointy promontory.'; break; @@ -1719,6 +1719,13 @@ App.Desc.nipples = function(slave, {market, eventDescription} = {}) { case "tiny": r += 'tiny little nubs.'; break; + case "flat": + if (slave.nipplesPiercing !== 0) { + r += "pulled flat from the constant tug of oversized implants. They are held back by piercings, preventing them from blending into the areolae."; + } else { + r += "pulled flat from the constant tug of oversized implants: when soft, they blend in with the areolae."; + } + break; case "puffy": r += 'puffy, the soft flesh around each swelling outward to a promontory.'; break; @@ -1777,7 +1784,7 @@ App.Desc.nipples = function(slave, {market, eventDescription} = {}) { r += ` Since ${he} is topless, they're plainly visible.`; break; default: - if (!["fuckable", "inverted", "partially inverted", "tiny"].includes(slave.nipples)) { + if (!["fuckable", "inverted", "partially inverted", "tiny", "flat"].includes(slave.nipples)) { switch (slave.clothes) { case "cutoffs and a t-shirt": r += ` Since ${he} isn't wearing a bra, they tent the front of ${his} t-shirt.`; diff --git a/src/npc/descriptions/boobs/boobsShape.js b/src/npc/descriptions/boobs/boobsShape.js index 035d630a3ef145094f2171699bc846b2862a2cba..e7395d7b8109142f07a45d2e46e2c1e9455b3c21 100644 --- a/src/npc/descriptions/boobs/boobsShape.js +++ b/src/npc/descriptions/boobs/boobsShape.js @@ -19,182 +19,187 @@ App.Desc.boobsShape = function(slave) { r.push(`up and out like a severe push-up bra.`); } } - } else if (slave.boobsImplant === 0) { - switch (slave.boobShape) { - case "perky": - if (slave.boobs > 12000) { - r.push(`When ${he}'s on ${his} back, some of their natural perkiness can still be seen in the way they tend to obscure ${his} head and shoulders.`); - } else if (slave.boobs > 5000) { - r.push(`Their natural perkiness has helped them resist their enormous size, making them look like a normal pair of merely gigantic tits that have grown to be bigger than ${his} head without changing shape.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other. They remain naturally perky, defying gravity.`); - } else if (slave.boobs > 1000) { - r.push(`They're somewhat perky despite their large size, with ${his} nipples pointing slightly upward.`); - } else if (slave.boobs > 500) { - r.push(`They're full and perky, and ${his} nipples point upward.`); - } else if (slave.boobs > 250) { - r.push(`They're perky, and ${his} nipples point upward.`); - } else { - r.push(`They're very minimal.`); - } - break; - case "downward-facing": - if (slave.boobs > 12000) { - r.push(`Their naturally downward-facing shape makes them a convenient cushion when ${he}'s face-down, naturally placing ${him} in a kneeling position.`); - } else if (slave.boobs > 5000) { - r.push(`They're huge pillows of soft flesh, distorted by gravity and where they rest against ${his} stomach and each other. Naturally downward-facing, they are so big that ${his} nipples point directly down.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh, resting heavily against ${his} stomach and each other. Since they are naturally downward-facing, most of their mass rests low.`); - } else if (slave.boobs > 1000) { - r.push(`They're not attractively shaped, with ${his} nipples pointing downward more strongly than they should for ${his} breast size.`); - } else if (slave.boobs > 500) { - r.push(`They're not attractively shaped, with ${his} nipples pointing down.`); - } else if (slave.boobs > 250) { - r.push(`They're not attractively shaped, with ${his} nipples pointing down despite ${his} small breasts.`); - } else { - r.push(`They're very minimal.`); - } - break; - case "torpedo-shaped": - if (slave.boobs > 12000) { - r.push(`They are naturally torpedo-shaped, which can be seen in the way they stick out more than a`); - if (V.showInches === 2) { - r.push(`yard`); - } else { - r.push(`meter`); - } - r.push(`in front of ${him} when ${he} sits up.`); - } else if (slave.boobs > 5000) { - r.push(`They're huge promontories of soft flesh. Their natural torpedo shape remains to a certain extent, ${his} swaying breasts reaching an incredibly long way out from ${his} chest.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other. Their natural torpedo shape is distorted by their weight.`); - } else if (slave.boobs > 1000) { - r.push(`They're strongly torpedo-shaped despite their large size, projecting a long way from ${his} chest and swaying lewdly when ${he}'s naked.`); - } else if (slave.boobs > 500) { - r.push(`They're strongly torpedo-shaped, projecting a long way from ${his} chest and swaying cutely when ${he}'s naked.`); - } else if (slave.boobs > 250) { - r.push(`They're strongly torpedo-shaped despite their small size, projecting some way from ${his} chest.`); - } else { - r.push(`They're very minimal.`); - } - break; - case "wide-set": - if (slave.boobs > 12000) { - r.push(`They are naturally wide-set, which can be seen in the way they stick out more than a`); - if (V.showInches === 2) { - r.push(`yard`); - } else { - r.push(`meter`); - } - r.push(`to either side of ${him} when ${he}'s face-down.`); - } else if (slave.boobs > 5000) { - r.push(`They're huge pillows of soft flesh whose natural wide-set shape somehow keeps them from touching despite their mass.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh whose natural wide-set shape obscures ${his} upper arms. They rest without natural cleavage despite their size.`); - } else if (slave.boobs > 1000) { - r.push(`They're wide-set, with their weight pointing each nipple away from ${his} sternum.`); - } else if (slave.boobs > 500) { - r.push(`They're wide-set, with each nipple pointing away from ${his} sternum.`); - } else if (slave.boobs > 250) { - r.push(`They're wide-set, with each nipple pointing somewhat sideways.`); - } else { - r.push(`They're very minimal.`); - } - break; - case "saggy": - if (slave.boobs > 12000) { - r.push(`Their naturally saggy shape makes them a convenient cushion when ${he}'s face-down, naturally placing ${him} in a kneeling position.`); - } else if (slave.boobs > 5000) { - r.push(`They're huge pillows of soft flesh that sag past ${his} navel. ${His} nipples are placed on their bottoms, pointed at the ground by the heavy mass of breastflesh above them.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh that sag almost to ${his} navel. ${His} nipples are placed on their bottoms, pointed at the ground by the weight of breast above them.`); - } else if (slave.boobs > 1000) { - r.push(`They're heavy and saggy, pointing ${his} nipples at the ground.`); - } else if (slave.boobs > 500) { - r.push(`They're not attractively shaped, with ${his} nipples pointing down.`); - } else if (slave.boobs > 250) { - r.push(`They're not attractively shaped, with ${his} nipples pointing down despite ${his} small breasts.`); - } else { - r.push(`They're very minimal.`); - } - break; - default: - if (slave.boobs > 12000) { - r.push(`They anchor ${him} when ${he}'s face-down, and pin ${him} when ${he}'s on ${his} back.`); - } else if (slave.boobs > 5000) { - r.push(`They're huge pillows of soft flesh, distorted by gravity and where they rest against ${his} stomach and each other.`); - } else if (slave.boobs > 2500) { - r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other.`); - } else if (slave.boobs > 1000) { - r.push(`They're soft and round, resting heavily against ${his} chest and each other.`); - } else if (slave.boobs > 500) { - r.push(`They're nice and soft and rest naturally against ${his} chest.`); - } else if (slave.boobs > 250) { - r.push(`They're nicely rounded and rest naturally.`); - } else { - r.push(`They're very minimal.`); - } - } - } else if (slave.boobShape === "deflated") { - /* WIP */ - } else if (slave.boobsImplant <= 400) { - if (slave.boobs > 800) { - r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, but defy gravity more than could be expected given their size.`); - } else if (slave.boobs > 300) { - r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, but are perkier than could be expected given their size.`); - } else { - r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, mostly because they're so small.`); - } - if (V.arcologies[0].FSTransformationFetishist !== "unset") { - if (slave.boobsImplant > 0) { - r.push(`They are about ${Math.floor((slave.boobsImplant / slave.boobs) * 100)}% implant.`); + } else { + let showBoobShape = false; + // Only used in implant related text. + /* eslint-disable */ + let implantType = slave.boobsImplantType === "string" ? "engorged string" : + slave.boobsImplantType === "normal" ? "breast" : + "fillable breast"; + /* eslint-enable */ + if (slave.boobShape === "spherical") { + if (slave.boobs > 12000) { + r.push(`They anchor ${him} when ${he}'s face-down, pin ${him} when ${he}'s on ${his} back, and pull what little flesh is left taut when ${he} is upright. ${His} ${slave.boobsImplant} cc ${implantType} implants are extremely obvious; with little natural breast tissue to support them, they are barely recognizable as a part ${his} body.`); + } else if (slave.boobs > 6000) { + r.push(`They're huge orbs of stretched flesh, resting heavily against ${his} stomach and each other, and extremely obvious; with little natural breast tissue to support ${his} ${slave.boobsImplant} cc ${implantType} implants, they look like a pair of overinflated balloons attached to ${his} chest.`); + } else if (slave.boobs > 4000) { + r.push(`They're firm orbs of stretched flesh, resting heavily against ${his} chest and each other, and extremely obvious; with little natural breast tissue to support ${his} ${slave.boobsImplant} cc ${implantType} implants, they look like a pair of overinflated balloons attached to ${his} chest.`); + } else if (slave.boobs > 2000) { + r.push(`They're big, round, hard and extremely obvious; with little natural breast tissue to support ${his} ${slave.boobsImplant} cc ${implantType} implants, they look like a pair of balloons attached to ${his} chest.`); + } else if (slave.boobs > 1000) { + r.push(`They're big and round and hang heavily from ${his} chest. ${His} ${slave.boobsImplant} cc ${implantType} implants are extremely obvious; with little natural breast tissue to support them, they look like a pair of softballs stuck to ${him}.`); + } else if (slave.boobs > 500) { + r.push(`They're unaturally round and, with little natural breast tissue to support ${his} ${slave.boobsImplant} cc ${implantType} implants, appear attached to ${his} chest instead of part of it.`); + } else { + r.push(`They're nicely rounded and rest naturally.`); // This shouldn't be reachable } - } - } else if (slave.boobsImplant <= 600) { - if (slave.boobs > 800) { - r.push(`${He} has ${slave.boobsImplant} cc breast implants. ${His} implants are well done, but ${his} breasts are so perfect and gravity-defying that they are clearly artificial.`); - } else { - r.push(`${He} has ${slave.boobsImplant} cc breast implants. ${His} implants are well done, but ${his} breasts are so rounded and high that they are clearly artificial.`); - } - if (V.arcologies[0].FSTransformationFetishist !== "unset") { - if (slave.boobsImplant > 0) { - r.push(`They are about ${Math.floor((slave.boobsImplant / slave.boobs) * 100)}% implant.`); + } else if (slave.boobsImplant <= 400) { + if (slave.boobsImplant / slave.boobs < 0.25) { + r.push(`${He} has ${slave.boobsImplant}cc breast implants. They don't change much, since they are buried in as much boob as they are.`); + if (slave.boobs > 1000) { + showBoobShape = true; + } + } else if (slave.boobs > 800) { + r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, but defy gravity more than could be expected given their size.`); + } else if (slave.boobs > 300) { + r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, but are perkier than could be expected given their size.`); + } else { + r.push(`${He} has ${slave.boobsImplant}cc breast implants. ${His} tits look fairly natural, mostly because they're so small.`); } - } - } else { - if (slave.boobs > 2000) { - r.push(`${He} has ${slave.boobsImplant} cc`); - if (slave.boobsImplantType === "string") { - r.push(`engorged string`); - } else if (slave.boobsImplantType === "normal") { - r.push(`breast`); + } else if (slave.boobsImplant <= 600) { + if (slave.boobsImplant / slave.boobs < 0.25) { + r.push(`${He} has ${slave.boobsImplant}cc breast implants. They don't change much, since they are buried in as much boob as they are.`); + if (slave.boobs > 1000) { + showBoobShape = true; + } + } else if (slave.boobs > 800) { + r.push(`${He} has ${slave.boobsImplant} cc breast implants. ${His} implants are well done, but ${his} breasts are so perfect and gravity-defying that they are clearly artificial.`); } else { - r.push(`fillable breast`); + r.push(`${He} has ${slave.boobsImplant} cc breast implants. ${His} implants are well done, but ${his} breasts are so rounded and high that they are clearly artificial.`); } - r.push(`implants, which is obvious from the unnatural size of ${his} boobs.`); - } else if (slave.boobs - slave.boobsImplant > 800) { + } else if (slave.boobsImplant > 600) { r.push(`${He} has ${slave.boobsImplant} cc`); - if (slave.boobsImplantType === "string") { - r.push(`engorged string`); - } else if (slave.boobsImplantType === "normal") { - r.push(`breast`); + if (slave.boobsImplant / slave.boobs >= 0.75) { + r.push(`${implantType} implants. They are extremely obvious; with little natural breast tissue to support them, they look like a pair of balloons attached to ${his} chest.`); + } else if (slave.boobsImplant / slave.boobs >= 0.50) { + r.push(`${implantType} implants, which is obvious from the roundness of ${his} fake tits.`); + } else if (slave.boobsImplant / slave.boobs >= 0.25) { + r.push(`${implantType} implants, which is obvious from the unnatural size of ${his} boobs.`); } else { - r.push(`fillable breast`); + r.push(`${implantType} implants, but they make up so little of ${his} boobs that they aren't noticeable unless touched.`); } - r.push(`implants, which is obvious from the roundness of ${his} fake tits.`); } else { - r.push(`${He} has ${slave.boobsImplant} cc`); - if (slave.boobsImplantType === "string") { - r.push(`engorged string`); - } else if (slave.boobsImplantType === "normal") { - r.push(`breast`); - } else { - r.push(`fillable breast`); + showBoobShape = true; + } + if (showBoobShape) { + switch (slave.boobShape) { + case "perky": + if (slave.boobs > 12000) { + r.push(`When ${he}'s on ${his} back, some of their natural perkiness can still be seen in the way they tend to obscure ${his} head and shoulders.`); + } else if (slave.boobs > 5000) { + r.push(`Their natural perkiness has helped them resist their enormous size, making them look like a normal pair of merely gigantic tits that have grown to be bigger than ${his} head without changing shape.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other. They remain naturally perky, defying gravity.`); + } else if (slave.boobs > 1000) { + r.push(`They're somewhat perky despite their large size, with ${his} nipples pointing slightly upward.`); + } else if (slave.boobs > 500) { + r.push(`They're full and perky, and ${his} nipples point upward.`); + } else if (slave.boobs > 250) { + r.push(`They're perky, and ${his} nipples point upward.`); + } else { + r.push(`They're very minimal.`); + } + break; + case "downward-facing": + if (slave.boobs > 12000) { + r.push(`Their naturally downward-facing shape makes them a convenient cushion when ${he}'s face-down, naturally placing ${him} in a kneeling position.`); + } else if (slave.boobs > 5000) { + r.push(`They're huge pillows of soft flesh, distorted by gravity and where they rest against ${his} stomach and each other. Naturally downward-facing, they are so big that ${his} nipples point directly down.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh, resting heavily against ${his} stomach and each other. Since they are naturally downward-facing, most of their mass rests low.`); + } else if (slave.boobs > 1000) { + r.push(`They're not attractively shaped, with ${his} nipples pointing downward more strongly than they should for ${his} breast size.`); + } else if (slave.boobs > 500) { + r.push(`They're not attractively shaped, with ${his} nipples pointing down.`); + } else if (slave.boobs > 250) { + r.push(`They're not attractively shaped, with ${his} nipples pointing down despite ${his} small breasts.`); + } else { + r.push(`They're very minimal.`); + } + break; + case "torpedo-shaped": + if (slave.boobs > 12000) { + r.push(`They are naturally torpedo-shaped, which can be seen in the way they stick out more than a`); + if (V.showInches === 2) { + r.push(`yard`); + } else { + r.push(`meter`); + } + r.push(`in front of ${him} when ${he} sits up.`); + } else if (slave.boobs > 5000) { + r.push(`They're huge promontories of soft flesh. Their natural torpedo shape remains to a certain extent, ${his} swaying breasts reaching an incredibly long way out from ${his} chest.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other. Their natural torpedo shape is distorted by their weight.`); + } else if (slave.boobs > 1000) { + r.push(`They're strongly torpedo-shaped despite their large size, projecting a long way from ${his} chest and swaying lewdly when ${he}'s naked.`); + } else if (slave.boobs > 500) { + r.push(`They're strongly torpedo-shaped, projecting a long way from ${his} chest and swaying cutely when ${he}'s naked.`); + } else if (slave.boobs > 250) { + r.push(`They're strongly torpedo-shaped despite their small size, projecting some way from ${his} chest.`); + } else { + r.push(`They're very minimal.`); + } + break; + case "wide-set": + if (slave.boobs > 12000) { + r.push(`They are naturally wide-set, which can be seen in the way they stick out more than a`); + if (V.showInches === 2) { + r.push(`yard`); + } else { + r.push(`meter`); + } + r.push(`to either side of ${him} when ${he}'s face-down.`); + } else if (slave.boobs > 5000) { + r.push(`They're huge pillows of soft flesh whose natural wide-set shape somehow keeps them from touching despite their mass.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh whose natural wide-set shape obscures ${his} upper arms. They rest without natural cleavage despite their size.`); + } else if (slave.boobs > 1000) { + r.push(`They're wide-set, with their weight pointing each nipple away from ${his} sternum.`); + } else if (slave.boobs > 500) { + r.push(`They're wide-set, with each nipple pointing away from ${his} sternum.`); + } else if (slave.boobs > 250) { + r.push(`They're wide-set, with each nipple pointing somewhat sideways.`); + } else { + r.push(`They're very minimal.`); + } + break; + case "saggy": + if (slave.boobs > 12000) { + r.push(`Their naturally saggy shape makes them a convenient cushion when ${he}'s face-down, naturally placing ${him} in a kneeling position.`); + } else if (slave.boobs > 5000) { + r.push(`They're huge pillows of soft flesh that sag past ${his} navel. ${His} nipples are placed on their bottoms, pointed at the ground by the heavy mass of breastflesh above them.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh that sag almost to ${his} navel. ${His} nipples are placed on their bottoms, pointed at the ground by the weight of breast above them.`); + } else if (slave.boobs > 1000) { + r.push(`They're heavy and saggy, pointing ${his} nipples at the ground.`); + } else if (slave.boobs > 500) { + r.push(`They're not attractively shaped, with ${his} nipples pointing down.`); + } else if (slave.boobs > 250) { + r.push(`They're not attractively shaped, with ${his} nipples pointing down despite ${his} small breasts.`); + } else { + r.push(`They're very minimal.`); + } + break; + default: + if (slave.boobs > 12000) { + r.push(`They anchor ${him} when ${he}'s face-down, and pin ${him} when ${he}'s on ${his} back.`); + } else if (slave.boobs > 5000) { + r.push(`They're huge pillows of soft flesh, distorted by gravity and where they rest against ${his} stomach and each other.`); + } else if (slave.boobs > 2500) { + r.push(`They're orbs of soft flesh, resting heavily against ${his} chest and each other.`); + } else if (slave.boobs > 1000) { + r.push(`They're soft and round, resting heavily against ${his} chest and each other.`); + } else if (slave.boobs > 500) { + r.push(`They're nice and soft and rest naturally against ${his} chest.`); + } else if (slave.boobs > 250) { + r.push(`They're nicely rounded and rest naturally.`); + } else { + r.push(`They're very minimal.`); + } } - r.push(`implants. They are extremely obvious; with little natural breast tissue to support them, they look like a pair of balloons attached to ${his} chest.`); } - if (V.arcologies[0].FSTransformationFetishist !== "unset") { - if (slave.boobsImplant > 0) { + if (slave.boobsImplant > 0) { + if (V.arcologies[0].FSTransformationFetishist !== "unset") { r.push(`They are about ${Math.floor((slave.boobsImplant / slave.boobs) * 100)}% implant.`); } } diff --git a/src/npc/descriptions/butt/buttplug.js b/src/npc/descriptions/butt/buttplug.js index bf8bfd502dff87d6cd2b0935e35a0b1b88928ed4..d128de1c4eacff855293404a3dbf22cebe7459e0 100644 --- a/src/npc/descriptions/butt/buttplug.js +++ b/src/npc/descriptions/butt/buttplug.js @@ -5,7 +5,7 @@ * @param {boolean} [params.eventDescription] * @returns {string} */ -App.Desc.buttplug = function(slave, {market, eventDescription} = {}) { +App.Desc.buttplug = function(slave, { market, eventDescription } = {}) { const r = []; const { he, him, his, He, His @@ -612,73 +612,76 @@ App.Desc.buttplug = function(slave, {market, eventDescription} = {}) { } } } - - switch (slave.buttplug) { - case "plug": - r.push(`It's filled by a standard`); + const buttplug = App.Data.buttplug.get(slave.buttplug) || V.customItem.buttplug.get(slave.buttplug); + if (buttplug.width === 1) { + if (buttplug.length === 1) { + r.push(`It's filled by a standard sized`); if (slave.anus > 2) { - r.push(`buttplug, which is on the verge of falling out.`); + r.push(`${slave.buttplug}, which is on the verge of falling out.`); } else { - r.push(`buttplug.`); - } - if (slave.buttplugAttachment === "tail") { - r.push(`A tail protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "fox tail") { - r.push(`A bushy ${slave.hColor} tail with a white tip protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "cow tail") { - r.push(`A slim, spotted tail with a cute tuft at its tip protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "cat tail") { - r.push(`A tail protrudes from the back of the plug and springs upwards from ${his} rear.`); + r.push(`${slave.buttplug}.`); } - break; - case "long plug": + } else { r.push(`It's filled by a standard sized, overly long`); if (slave.anus > 2) { - r.push(`buttplug, which is on the verge of sliding out ${his} rear.`); + r.push(`${slave.buttplug}, which is on the verge of sliding out ${his} rear.`); } else { - r.push(`buttplug.`); + r.push(`${slave.buttplug}.`); } r.push(`It causes a noticeable bulge in ${his} belly.`); - if (slave.buttplugAttachment === "tail") { - r.push(`A tail protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "fox tail") { - r.push(`A bushy ${slave.hColor} tail with a white tip protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "cow tail") { - r.push(`A slim, spotted tail with a cute tuft at its tip protrudes from the back of the plug and dangles from ${his} rear.`); - } else if (slave.buttplugAttachment === "cat tail") { - r.push(`A tail protrudes from the back of the plug and springs upwards from ${his} rear.`); + } + } else if (buttplug.width === 2) { + r.push(`It's`); + if (slave.anus < 2) { + r.push(`agonizingly stretched`); + } else if (slave.anus < 3) { + r.push(`uncomfortably stretched`); + } else { + r.push(`comfortably stretched`); + } + if (buttplug.length === 1) { + r.push(`by a large ${slave.buttplug}.`); + } else { + r.push(`by a large and long ${slave.buttplug}. It causes a noticeable bulge in ${his} belly.`); + } + } else if (buttplug.width === 3) { + if (buttplug.length === 1) { + if (slave.anus < 4) { + r.push(`It's agonizingly stretched by a ${slave.buttplug} so huge ${his} anus is probably being stretched into a permanent gape.`); + } else { + r.push(`Its ridiculous gape is comfortably filled by a huge ${slave.buttplug}.`); } - break; - case "large plug": - r.push(`It's`); - if (slave.anus < 2) { - r.push(`agonizingly stretched`); - } else if (slave.anus < 3) { - r.push(`uncomfortably stretched`); + } else { + if (slave.anus < 4) { + r.push(`It's agonizingly stretched by a ${slave.buttplug} so huge it causes ${his} belly to bulge and is likely stretching ${his} anus into a permanent gape.`); } else { - r.push(`comfortably stretched`); + r.push(`Its ridiculous gape is comfortably filled by a wide and long ${slave.buttplug}. It causes a noticeable bulge in ${his} belly.`); } - r.push(`by a large buttplug.`); + } + if (slave.anus < 4) { + if (slave.fuckdoll === 0) { + if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He}'s frequently in tears from the pain, which is so sharp it often tips ${him} over into spontaneous orgasm.`); + } else { + r.push(`${He} spends much of ${his} time sobbing with anal pain and fear at having ${his} hole ruined.`); + } + } + } + } + + switch (buttplug.width) { + case 3: if (slave.buttplugAttachment === "tail") { - r.push(`${He} swings the tail from side to side with every shift of ${his} rear.`); + r.push(`${He} sways the tail back and forth with every ginger movement of ${his} rear.`); } else if (slave.buttplugAttachment === "fox tail") { - r.push(`${He} swings the bushy ${slave.hColor} tail from side to side with every shift of ${his} rear.`); + r.push(`${He} sways the bushy ${slave.hColor} tail back and forth with every ginger movement of ${his} rear.`); } else if (slave.buttplugAttachment === "cow tail") { - r.push(`${He} swings the spotted tail from side to side with every shift of ${his} rear.`); + r.push(`${He} sways the spotted tail back and forth with every ginger movement of ${his} rear.`); } else if (slave.buttplugAttachment === "cat tail") { - r.push(`${He} bounces the tail from side to side with every shift of ${his} rear.`); + r.push(`${He} jiggles the tail back and forth with every ginger movement of ${his} rear.`); } break; - case "long, large plug": - r.push(`It's`); - if (slave.anus < 2) { - r.push(`agonizingly stretched`); - } else if (slave.anus < 3) { - r.push(`uncomfortably stretched`); - } else { - r.push(`comfortably stretched`); - } - r.push(`by a large and long buttplug. It causes a noticeable bulge in ${his} belly.`); + case 2: if (slave.buttplugAttachment === "tail") { r.push(`${He} swings the tail from side to side with every shift of ${his} rear.`); } else if (slave.buttplugAttachment === "fox tail") { @@ -689,51 +692,17 @@ App.Desc.buttplug = function(slave, {market, eventDescription} = {}) { r.push(`${He} bounces the tail from side to side with every shift of ${his} rear.`); } break; - case "huge plug": - if (slave.anus < 4) { - r.push(`It's agonizingly stretched by a plug so huge ${his} anus is probably being stretched into a permanent gape.`); - if (slave.fuckdoll === 0) { - if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He}'s frequently in tears from the pain, which is so sharp it often tips ${him} over into spontaneous orgasm.`); - } else { - r.push(`${He} spends much of ${his} time sobbing with anal pain and fear at having ${his} hole ruined.`); - } - } - } else { - r.push(`Its ridiculous gape is comfortably filled by a huge buttplug.`); - } - if (slave.buttplugAttachment === "tail") { - r.push(`${He} sways the tail back and forth with every ginger movement of ${his} rear.`); - } else if (slave.buttplugAttachment === "fox tail") { - r.push(`${He} sways the bushy ${slave.hColor} tail back and forth with every ginger movement of ${his} rear.`); - } else if (slave.buttplugAttachment === "cow tail") { - r.push(`${He} sways the spotted tail back and forth with every ginger movement of ${his} rear.`); - } else if (slave.buttplugAttachment === "cat tail") { - r.push(`${He} jiggles the tail back and forth with every ginger movement of ${his} rear.`); - } - break; - case "long, huge plug": - if (slave.anus < 4) { - r.push(`It's agonizingly stretched by a plug so huge it causes ${his} belly to bulge and is likely stretching ${his} anus into a permanent gape.`); - if (slave.fuckdoll === 0) { - if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He}'s frequently in tears from the pain, which is so sharp it often tips ${him} over into spontaneous orgasm.`); - } else { - r.push(`${He} spends much of ${his} time sobbing with anal pain and fear at having ${his} hole ruined.`); - } - } - } else { - r.push(`Its ridiculous gape is comfortably filled by a wide and long buttplug. It causes a noticeable bulge in ${his} belly.`); - } + case 1: if (slave.buttplugAttachment === "tail") { - r.push(`${He} sways the tail back and forth with every ginger movement of ${his} rear.`); + r.push(`A tail protrudes from the back of the plug and dangles from ${his} rear.`); } else if (slave.buttplugAttachment === "fox tail") { - r.push(`${He} sways the bushy ${slave.hColor} tail back and forth with every ginger movement of ${his} rear.`); + r.push(`A bushy ${slave.hColor} tail with a white tip protrudes from the back of the plug and dangles from ${his} rear.`); } else if (slave.buttplugAttachment === "cow tail") { - r.push(`${He} sways the spotted tail back and forth with every ginger movement of ${his} rear.`); + r.push(`A slim, spotted tail with a cute tuft at its tip protrudes from the back of the plug and dangles from ${his} rear.`); } else if (slave.buttplugAttachment === "cat tail") { - r.push(`${He} jiggles the tail back and forth with every ginger movement of ${his} rear.`); + r.push(`A tail protrudes from the back of the plug and springs upwards from ${his} rear.`); } } + return r.join(" "); }; diff --git a/src/npc/descriptions/crotch/vagina.js b/src/npc/descriptions/crotch/vagina.js index 45c1c6ba13156cdaba99775c41e788f00210b149..f2d81c77964d16829ce7ca524ba68e7f055bda4e 100644 --- a/src/npc/descriptions/crotch/vagina.js +++ b/src/npc/descriptions/crotch/vagina.js @@ -249,7 +249,9 @@ App.Desc.vagina = function(slave) { } } } - r.push(App.Desc.vaginalAccessory(slave)); + if (slave.vaginalAccessory !== "none") { + r.push(App.Desc.vaginalAccessory(slave)); + } } if (slave.ovaImplant !== 0) { diff --git a/src/npc/descriptions/crotch/vaginalAccessory.js b/src/npc/descriptions/crotch/vaginalAccessory.js index 847437102c87cd652268f90f032854b154cf3911..74d9d8c5f6f4b8212a44afd23df921d9b746e532 100644 --- a/src/npc/descriptions/crotch/vaginalAccessory.js +++ b/src/npc/descriptions/crotch/vaginalAccessory.js @@ -3,6 +3,9 @@ * @returns {string} */ App.Desc.vaginalAccessory = function(slave) { + if (slave.vaginalAccessory === "none") { + return ""; + } const r = []; const { he, his, He, His @@ -10,35 +13,25 @@ App.Desc.vaginalAccessory = function(slave) { let held; if (slave.chastityVagina) { held = "held in place by a chastity belt"; - } else if (slave.vaginalAccessory === "bullet vibrator" || slave.vaginalAccessory === "smart bullet vibrator") { + } else if (dildoWidth(slave) === 0) { held = "held in place by a strap"; } else { held = `held in place by a strap, which ${he} can remove for vaginal intercourse`; } - switch (slave.vaginalAccessory) { - case "bullet vibrator": - case "smart bullet vibrator": // FIXME: two different descriptions? - r.push(`A bullet vibrator is attached on ${his} clit, ${held}.`); // FIXME: not super happy with this - break; - case "dildo": - /* TODO: these may need to be updated for slaves with gaping+ vaginas */ - r.push(`${His} pussy is filled by a dildo ${held}.`); - break; - case "long dildo": - r.push(`${His} pussy is filled by a very long dildo ${held}. It noticeably bulges ${his} stomach.`); + const dildo = App.Data.vaginalAccessory.get(slave.vaginalAccessory) || V.customItem.vaginalAccessory.get(slave.vaginalAccessory); + switch (dildo.width) { + case 0: + r.push(`A ${slave.vaginalAccessory} is attached on ${his} clit, ${held}.`); // FIXME: not super happy with this break; - case "large dildo": - r.push(`${His} pussy is`); - if (slave.vagina < 2) { - r.push(`painfully stretched`); - } else if (slave.vagina < 3) { - r.push(`uncomfortably filled`); + case 1: + if (dildo.length === 1) { + /* TODO: these may need to be updated for slaves with gaping+ vaginas */ + r.push(`${His} pussy is filled by a dildo ${held}.`); } else { - r.push(`comfortably filled`); + r.push(`${His} pussy is filled by a very long dildo ${held}. It noticeably bulges ${his} stomach.`); } - r.push(`by a large dildo ${held}.`); break; - case "long, large dildo": + case 2: r.push(`${His} pussy is`); if (slave.vagina < 2) { r.push(`painfully stretched`); @@ -47,33 +40,35 @@ App.Desc.vaginalAccessory = function(slave) { } else { r.push(`comfortably filled`); } - r.push(`by a very long and large dildo ${held}. It noticeably bulges ${his} stomach.`); - break; - case "huge dildo": - if (slave.vagina < 4) { - r.push(`${His} pussy is filled to the breaking point by an enormous dildo.`); - if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`); - } else { - r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`); - } + if (dildo.length === 1) { + r.push(`by a large dildo ${held}.`); } else { - r.push(`${His} cavernous pussy is comfortably filled by a huge dildo.`); - } - if (slave.chastityVagina) { - r.push(`A chastity belt locks it securely in place.`); + r.push(`by a very long and large dildo ${held}. It noticeably bulges ${his} stomach.`); } break; - case "long, huge dildo": - if (slave.vagina < 4) { - r.push(`${His} pussy is filled to the breaking point by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`); - if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { - r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`); + case 3: + if (dildo.length === 1) { + if (slave.vagina < 4) { + r.push(`${His} pussy is filled to the breaking point by an enormous dildo.`); + if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`); + } else { + r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`); + } } else { - r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`); + r.push(`${His} cavernous pussy is comfortably filled by a huge dildo.`); } } else { - r.push(`${His} cavernous pussy is comfortably filled by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`); + if (slave.vagina < 4) { + r.push(`${His} pussy is filled to the breaking point by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`); + if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) { + r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`); + } else { + r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`); + } + } else { + r.push(`${His} cavernous pussy is comfortably filled by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`); + } } if (slave.chastityVagina) { r.push(`A chastity belt locks it securely in place.`); @@ -107,27 +102,25 @@ App.Desc.vaginalAttachment = function(slave) { const { his, He, His } = getPronouns(slave); - switch (slave.vaginalAttachment) { - case "vibrator": + switch (dildoVibeLevel(slave)) { + case 2: // TODO: not sure about this description - r.push(`${He} looks distinctly uncomfortable as ${his} dildo buzzes every so often.`); + r.push(`${His} dildo buzzes every so often, when prompted by the arcology's systems to train ${his} sexuality.`); if (slave.chastityVagina) { r.push(`The chastity belt locking it in place means there is no escape.`); } // TODO: add descriptions for slaves with gaping+ vaginas break; - case "smart vibrator": + case 1: // TODO: not sure about this description - r.push(`${His} dildo buzzes every so often, when prompted by the arcology's systems to train ${his} sexuality.`); + r.push(`${He} looks distinctly uncomfortable as ${his} dildo buzzes every so often.`); if (slave.chastityVagina) { r.push(`The chastity belt locking it in place means there is no escape.`); } // TODO: add descriptions for slaves with gaping+ vaginas break; - default: - if (!(["none", "bullet vibrator", "smart bullet vibrator"].includes(slave.vaginalAccessory))) { - r.push(`${His} current accessory is silent.`); - } + case 0: + r.push(`${His} current accessory is silent.`); } return r.join(" "); }; diff --git a/src/npc/descriptions/descriptionWidgets.js b/src/npc/descriptions/descriptionWidgets.js index fc40a143f5189de6e64078d7de6291a5de458fb3..fa0da8a7f21bae215aa3c3bf0aac65e9d6c79903 100644 --- a/src/npc/descriptions/descriptionWidgets.js +++ b/src/npc/descriptions/descriptionWidgets.js @@ -1441,7 +1441,7 @@ App.Desc.geneticQuirkAssessment = function(slave) { if (slave.geneticQuirks.androgyny === 2) { r.push(`${He} has a hormonal condition resulting in androgyny.`); } else if (slave.geneticQuirks.androgyny === 1 && V.geneticMappingUpgrade >= 2) { - r.push(`${He} is a carrier of a gene that result in androgyny.`); + r.push(`${He} is a carrier of a gene that results in androgyny.`); } if (slave.geneticQuirks.pFace === 2) { r.push(`${He} has an exceedingly rare trait associated with perfect facial beauty.`); diff --git a/src/npc/descriptions/longSlave.js b/src/npc/descriptions/longSlave.js index 01f26a70524432d448f80ac1d22fc49058837f37..62c85d62c1c9eedc60eec697be271fe81a9c54e2 100644 --- a/src/npc/descriptions/longSlave.js +++ b/src/npc/descriptions/longSlave.js @@ -240,9 +240,9 @@ App.Desc.longSlave = function(slave, {market = 0, eventDescription = false, pris r.push(`${He} currently possesses ${slave.origBodyOwner}'s body.`); } if (slave.fetish !== "mindbroken" && slave.fuckdoll === 0 && slave.origBodyOwnerID > 0) { - let lsd = V.slaveIndices[slave.origBodyOwnerID]; - if (lsd) { - r.push(`${He} is fully aware that ${SlaveFullName(V.slaves[lsd])} is in ${his} old body.`); + const owner = getSlave(slave.origBodyOwnerID); + if (owner !== undefined) { + r.push(`${He} is fully aware that ${SlaveFullName(owner)} is in ${his} old body.`); } } } diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js index 710bb4afc6a7ba61a8049a96c298f6602e6a3292..f87d49ed3dc6ff3eb951f2b49b0004c1a14fb0f6 100644 --- a/src/npc/generate/generateGenetics.js +++ b/src/npc/generate/generateGenetics.js @@ -57,7 +57,7 @@ globalThis.generateGenetics = (function() { if (mother === undefined) { mother = actor1; } - activeMother = V.slaves[V.slaveIndices[actor1.ID]]; + activeMother = getSlave(actor1.ID); if (activeMother === undefined) { activeMother = actor1; } @@ -67,7 +67,7 @@ globalThis.generateGenetics = (function() { } if (actor2 > 0) { father = V.genePool.find(s => s.ID === actor2); - activeFather = V.slaves[V.slaveIndices[actor2]]; + activeFather = getSlave(actor2); if (father === undefined) { father = activeFather; } diff --git a/src/npc/generate/generateMarketSlave.js b/src/npc/generate/generateMarketSlave.js index 4f6cafd26f1b6a401a1fb19565f07ac7cc382195..5eddcdfb172475586c56fed0319b659d366c12c7 100644 --- a/src/npc/generate/generateMarketSlave.js +++ b/src/npc/generate/generateMarketSlave.js @@ -219,7 +219,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1 slave.voiceImplant += 1; } slave.waist = Math.clamp(slave.waist, -100, -15); - if (((slave.boobShape === "saggy") || (slave.boobShape === "downward-facing"))) { + if (((slave.boobShape === "saggy") || (slave.boobShape === "downward-facing") || (slave.boobShape === "spherical"))) { slave.boobShape = "normal"; } if (((slave.boobShape === "normal") || (slave.boobShape === "wide-set"))) { @@ -820,6 +820,12 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1 slave.boobsImplantType = jsEither(["normal", "normal", "normal", "string"]); } slave.boobs += slave.boobsImplant; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } slave.buttImplant = jsRandom(2, 5); if (slave.buttImplant > 4) { slave.buttImplantType = jsEither(["fillable", "fillable", "normal", "string"]); diff --git a/src/npc/generate/generateNewSlaveJS.js b/src/npc/generate/generateNewSlaveJS.js index ebc7c1822f3b2f9cfd75d73cc7b4f7bf1ca24d62..71e61312189a83fd9cf54f3d660222da506784a1 100644 --- a/src/npc/generate/generateNewSlaveJS.js +++ b/src/npc/generate/generateNewSlaveJS.js @@ -1613,6 +1613,9 @@ globalThis.GenerateNewSlave = (function() { if (slave.boobs > 800 && slave.physicalAge > jsRandom(10, 50)) { BoobShapeGen.push("saggy"); } + if (slave.boobsImplant / slave.boobs >= 0.90) { + BoobShapeGen.push("spherical"); + } if (BoobShapeGen.length === 1) { if (Math.random() < 0.5) { slave.boobShape = jsEither(BoobShapeGen); @@ -1623,7 +1626,9 @@ globalThis.GenerateNewSlave = (function() { } } - if (slave.boobs < 250) { + if (slave.boobShape === "spherical") { + slave.nipples = jsEither(["flat", "flat", "flat", "huge", "tiny", "tiny"]); + } else if (slave.boobs < 250) { slave.nipples = jsEither(["cute", "cute", "partially inverted", "puffy", "tiny", "tiny", "tiny", "tiny"]); } else if (slave.boobs < 500) { slave.nipples = jsEither(["cute", "cute", "cute", "partially inverted", "puffy", "tiny"]); diff --git a/src/npc/generate/generateRelatedSlave.js b/src/npc/generate/generateRelatedSlave.js index 58464cbc6dfe07527c68518d07a5a8100c3bd5c8..acc2cfe5e97c0ca157cc782b9b280266ca883774 100644 --- a/src/npc/generate/generateRelatedSlave.js +++ b/src/npc/generate/generateRelatedSlave.js @@ -344,7 +344,9 @@ globalThis.generateRelatedSlave = (function() { } /* breast shape - preserve if it would have been valid, otherwise reset to normal (don't reroll) */ + /* nipple size - checks for flat nipples and their validity, otherwise reroll */ const AllowedBoobShapes = []; + const AllowedNippleShapes = []; if (slave.boobs > 250 && slave.boobs < 800) { AllowedBoobShapes.push("perky"); AllowedBoobShapes.push("downward-facing"); @@ -353,9 +355,16 @@ globalThis.generateRelatedSlave = (function() { AllowedBoobShapes.push("torpedo-shaped"); AllowedBoobShapes.push("wide-set"); } + if (slave.boobsImplant / slave.boobs >= 0.90) { + AllowedBoobShapes.push("spherical"); + AllowedNippleShapes.push("flat"); + } if (!AllowedBoobShapes.includes(slave.boobShape)) { slave.boobShape = "normal"; } + if (!AllowedNippleShapes.includes(slave.nipples)) { + slave.nipples = either("cute", "puffy", "inverted"); + } /* voice */ if (slave.physicalAge <= 16 && slave.voice <= 1) { diff --git a/src/npc/generate/lawCompliance.js b/src/npc/generate/lawCompliance.js index 459c1e4c8b02ceefdd8eff3612aa3e04a08ea285..52b53183589d864c56919bd5929dbf6a55d8beb5 100644 --- a/src/npc/generate/lawCompliance.js +++ b/src/npc/generate/lawCompliance.js @@ -372,6 +372,12 @@ App.Desc.lawCompliance = function(slave, market = 0) { slave.boobs -= slave.boobsImplant; slave.boobsImplant = 0; slave.boobsImplantType = "none"; + if (slave.boobShape === "spherical") { + slave.boobShape = "normal"; + } + if (slave.nipples === "flat") { + slave.nipples = "cute"; + } } if (slave.buttImplant > 0) { slave.butt -= slave.buttImplant; diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js index 7661cd7dd0bb242e1c65be5321b3069cc8c1879b..f78667c67cbb65618b62c5f945b113cb0f39700a 100644 --- a/src/npc/generate/newSlaveIntro.js +++ b/src/npc/generate/newSlaveIntro.js @@ -259,7 +259,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = } if (slave.nipplesPiercing > 0) { - if (slave.nipples === "partially inverted") { + if (slave.nipples === "partially inverted" || slave.nipples === "flat") { slave.nipples = "cute"; } else if (slave.nipples === "inverted") { slave.nipples = "puffy"; @@ -1365,6 +1365,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = slave.boobs -= slave.boobsImplant; slave.boobsImplant = 0; slave.boobsImplantType = "none"; + if (slave.boobShape === "spherical") { + slave.boobShape = "normal"; + } + if (slave.nipples === "flat") { + slave.boobShape = "puffy"; + } slave.lips -= slave.lipsImplant; slave.lipsImplant = 0; slave.butt -= slave.buttImplant; @@ -4808,7 +4814,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = slave.boobsImplantType = "advanced fillable"; cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); surgeryDamage(slave, 10); - slave.boobShape = "normal"; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } const r = []; r.push(`You escort ${him} to the remote surgery, strap ${him} in, and put ${him} under. When ${he} awakes, ${he} can't `); if (hasAnyArms(slave)) { @@ -4835,7 +4846,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = slave.boobsImplantType = "string"; cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); surgeryDamage(slave, 10); - slave.boobShape = "normal"; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } const r = []; r.push(`You escort ${him} to the remote surgery, strap ${him} in, and put ${him} under. When ${he} awakes, ${he} can't `); if (hasAnyArms(slave)) { @@ -4869,7 +4885,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = slave.boobsImplantType = "fillable"; cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); surgeryDamage(slave, 10); - slave.boobShape = "normal"; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } const r = []; r.push(`You escort ${him} to the remote surgery, strap ${him} in, and put ${him} under. When ${he} awakes, ${he} can't `); if (hasAnyArms(slave)) { @@ -4897,7 +4918,12 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest = slave.boobsImplantType = "string"; cashX(forceNeg(V.surgeryCost), "slaveSurgery", slave); surgeryDamage(slave, 10); - slave.boobShape = "normal"; + if (slave.boobsImplant / slave.boobs >= 0.90) { + slave.boobShape = "spherical"; + slave.nipples = "flat"; + } else { + slave.boobShape = "normal"; + } const r = []; r.push(`You escort ${him} to the remote surgery, strap ${him} in, and put ${him} under. When ${he} awakes, ${he} can't `); if (hasAnyArms(slave)) { diff --git a/src/npc/generate/slaveGenerationJS.js b/src/npc/generate/slaveGenerationJS.js index 9c8dbf6aada31d5919ed55d33641d7f56116e41a..69e6c88c14b5e570f370fc1fa6141cce661dd5f2 100644 --- a/src/npc/generate/slaveGenerationJS.js +++ b/src/npc/generate/slaveGenerationJS.js @@ -167,7 +167,7 @@ globalThis.nationalityToAccent = function(slave) { break; case "American": if (V.language === "English") { - slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1]); + slave.accent = jsEither([0, 0, 0, 0, 0, 0, 1, 1, 2]); } else if (V.language === "Spanish" && slave.race === "latina") { slave.accent = jsEither([0, 1, 2, 2, 2, 3, 3]); } else if (V.language === "Chinese" && slave.race === "asian") { diff --git a/src/npc/interaction/FSuckle.tw b/src/npc/interaction/FSuckle.tw index 45949aa697fc95d30ee1ccef17688184d5bfcc08..2aee8aac679ddf7db8c1fb9a40b9993b6b7b34c2 100644 --- a/src/npc/interaction/FSuckle.tw +++ b/src/npc/interaction/FSuckle.tw @@ -104,6 +104,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t grabbing a puffy nipple, lifting it up and letting it drop back down with a loud plop and a spurt of milk. They are dripping with excess milk and the flurry of kicks in your middle tells you what you need to do. <<elseif getSlave($AS).nipples == "inverted">> prying an inverted nipple out of one of them before letting it slip back down with a loud plop and a gush of milk. A strong kick tells you that you are to take some of that cream for yourself. + <<elseif getSlave($AS).nipples == "flat">> + pinching a nubby nipple, eliciting a dribble of milk that causes you to lose your grip. A strong kick insists you wrap your lips around it and try your hardest to suck out some cream. <<elseif getSlave($AS).nipples == "fuckable">> using two fingers to pry a nippleslit open before letting it slip shut with a moist plop. A strong kick tells you that something good is hiding in there that you'll need to work out. <<else>> @@ -144,6 +146,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t exceedingly soft nipple already brushing against your lips, covering your face with excess milk as if begging for you to empty $him. <<elseif getSlave($AS).nipples == "inverted" || getSlave($AS).nipples == "partially inverted">> internally curved nipple providing an inviting hole for you to tease out with your tongue. + <<elseif getSlave($AS).nipples == "flat">> + coin-sized nipple brushing your lips, daring you to get a grip on it. <<else>> overly exertive nipple already prodding at your mouth, as if begging to be suckled on. <</if>> @@ -213,6 +217,12 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t <<else>> the inviting hole keeping all the delicious milk locked up, your instincts insisting that you pry out the flavor for yourself. <</if>> + <<elseif getSlave($AS).nipples == "flat">> + <<if _mood == 2>> + pinching the nipple with your fingertips and squeezing hard enough to force out some drops of milk. A flurry of kicks demands you wrap you lips around it and take what little milk hides within. + <<else>> + swollen and dripping with excess milk and calling on your instincts to suck on them. + <</if>> <<elseif getSlave($AS).nipples == "fuckable">> <<if _mood == 2>> using two fingers to penetrate and spread apart to appreciate the insides. They are dripping with excess milk and resemble a tiny pussy; a series of kicks insist that you have a taste<<if $PC.dick != 0>> and a little stress relief<</if>>. @@ -293,6 +303,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t Such sensations hasten your breath, making you take in more of $his womanly scent. You work with your lips and tongue to <<if getSlave($AS).nipples == "inverted" || getSlave($AS).nipples == "partially inverted">> tease out $his nipple and suckle with newfound gusto, + <<elseif getSlave($AS).nipples == "flat">> + get a hold of $his nipple and suckle with newfound gusto, <<elseif getSlave($AS).nipples == "fuckable">> explore the inner chambers of $his breasts and ease out more of $his cream in a lustful frenzy, <<else>> @@ -301,6 +313,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t as though the rest of the world did not exist. It might as well not, given how the entirety of your upper body sees and feels nothing but $his mesmerizing mammaries and <<if getSlave($AS).nipples == "puffy">> $his soft nipple in your mouth, while your sex focuses on the soft hand diligently working it. You feverishly suckle on $his nipple as you thrash your tongue, your efforts rewarded with more milk. + <<elseif getSlave($AS).nipples == "flat">> + $his milky nub in your mouth, while your sex focuses on the soft hand diligently working it. You feverishly suck on $his nipple as you thrash your tongue, your efforts accidentally forcing you off with a wet pop, but you just latch back on like nothing happened. <<elseif getSlave($AS).nipples == "inverted" || getSlave($AS).nipples == "partially inverted">> $his erect nipple in your mouth, while your sex focuses on the soft hand diligently working it. You feverishly suckle on $his nipple as you thrash your tongue, your efforts rewarded with more milk. <<elseif getSlave($AS).nipples == "fuckable">> @@ -321,6 +335,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t with your tongue, trying to get the most out of $his mammaries, you hasten $his breath and bring $him further pleasure<<if getSlave($AS).nipples == "inverted">> as it slowly hardens and leaves its inverted state<</if>>. <<if getSlave($AS).nipples == "puffy">> You note the texture of $his nipple: soft, more so even than the rest of $his boob. Your constant efforts of sucking and tongueplay are rewarded + <<elseif getSlave($AS).nipples == "flat">> + You take in the texture of $his nipple: hard and bumpy, just like the firm globe pulling it flat. Your constant efforts of sucking and tongueplay are rewarded <<elseif getSlave($AS).nipples == "fuckable">> You feverishly thrash your tongue around in the bumpy enclosure, each strong movement sending shivers through $him, causing $him to gasp and moan, as well as rewarding you <<elseif getSlave($AS).nipples != "inverted">> @@ -334,6 +350,8 @@ You <<if _mood == 2>>demand<<else>>beckon<</if>> <<= getSlave($AS).slaveName>> t Milk continues to spill into your mouth as you suckle away at the <<if getSlave($AS).nipples == "puffy">> softness, +<<eleif getSlave($AS).nipples == "flat">> + swollen bulge, <<elseif getSlave($AS).nipples == "inverted" || getSlave($AS).nipples == "partially inverted">> erect hardness, <<elseif getSlave($AS).nipples == "fuckable">> diff --git a/src/npc/interaction/fBoobs.tw b/src/npc/interaction/fBoobs.tw index 69e7ba22f877c513cc0cb489e0e5f87deede95cf..41519cf99ca9870fe6b4a959804df1ab83f13d4a 100644 --- a/src/npc/interaction/fBoobs.tw +++ b/src/npc/interaction/fBoobs.tw @@ -36,6 +36,8 @@ tits. $His nipples are so large they give $his breasts an unavoidably lewd appeal as they jut outward. <<elseif (getSlave($AS).nipples == "puffy")>> $His puffy nipples beg to be sucked. +<<elseif (getSlave($AS).nipples == "flat")>> + $His nipples are stretched nearly flat by $his implants, reducing them to two lewd little buttons. <<elseif (getSlave($AS).nipples == "partially inverted") && (getSlave($AS).nipplesPiercing == 0)>> $His partially inverted nipples should protrude at the slightest stimulation. <<elseif (getSlave($AS).nipples == "inverted") && (getSlave($AS).nipplesPiercing == 0)>> diff --git a/src/npc/interaction/fEmbrace.tw b/src/npc/interaction/fEmbrace.tw index 6a5e9a50f09cd8b7c842f1c6a22a82dcf1add6bd..83e30f78c00d17b76749f12b370b742bec20c172 100644 --- a/src/npc/interaction/fEmbrace.tw +++ b/src/npc/interaction/fEmbrace.tw @@ -55,11 +55,13 @@ You walk around $him and put your hands around $his abdomen,<<if (hasAnyLegs(get You feel $his large, erect nipples against your <<elseif (getSlave($AS).nipples == "puffy")>> You feel $his erect, puffy nipples against your + <<elseif (getSlave($AS).nipples == "flat")>> + You feel the bumps of $his flat nipples against your <<elseif getSlave($AS).nipples == "partially inverted">> You feel $his partially inverted nipples against your <<elseif getSlave($AS).nipples == "inverted">> You feel $his inverted nipples against your - <<elseif getSlave($AS).nipples == "inverted">> + <<elseif getSlave($AS).nipples == "fuckable">> You feel the slits of $his nipples against your <<else>> You feel $his erect nipples against your diff --git a/src/npc/interaction/fFeelings.tw b/src/npc/interaction/fFeelings.tw index 7aab4a8cbafc394567c3d42d5fae3986def5a249..fdfa53f0dc7881097ca53d9ffcb0f40c70c01b91 100644 --- a/src/npc/interaction/fFeelings.tw +++ b/src/npc/interaction/fFeelings.tw @@ -254,7 +254,7 @@ My favorite part of my body i<<s>> my nipple pu<<ss>>ie<<s>> of cour<<s>>e. It'<<s>> <<s>>o hot when they get abu<<s>>ed and I'm alway<<s>> trying to think of new way<<s>> to u<<s>>e them to plea<<s>>ure you. <<elseif (getSlave($AS).lactation > 0)>> my milky nipple<<s>> of cour<<s>>e. E<<s>>pe<<c>>ially when you don't touch them for awhile and my brea<<s>>t<<s>> bloat up ni<<c>>e and big. - <<elseif (getSlave($AS).nipples != "tiny")>> + <<elseif (getSlave($AS).nipples == "huge" || getSlave($AS).nipples == "puffy")>> my big nipple<<s>>, it'<<s>> like having clit<<s>> on my che<<s>>t. My only wi<<sh>> i<<s>> that they were even bigger. <<elseif (getSlave($AS).boobs > 700)>> my big boob<<s>>. I like how they feel wrapped around a dick, and they are the <<c>>enter of my world. <<S>>ometime<<s>>, I think I //am// my boobie<<s>>. I mean, they're <<s>>o much more me than the re<<s>>t of 'me,' right? @@ -286,7 +286,7 @@ My favorite part of my body i<<s>> <</if>> <<if getSlave($AS).nipples == "fuckable">> I love my fuckable nipple<<s>>, it really feel<<s>> like I've got a pair of pu<<ss>>ie<<s>> on my che<<s>>t. - <<elseif (getSlave($AS).nipples != "tiny")>> + <<elseif (getSlave($AS).nipples == "huge" || getSlave($AS).nipples == "puffy")>> I love my big nipple<<s>>, it'<<s>> like having clit<<s>> on my che<<s>>t. <</if>> <<if (getSlave($AS).lactation > 0)>>Being able to nur<<s>>e i<<s>> really <<s>>e<<x>>y, I alway<<s>> want to fuck right after. Or during.<</if>> @@ -376,7 +376,7 @@ My favorite part of my body i<<s>> my nipple pu<<ss>>ie<<s>> of cour<<s>>e. <<elseif (getSlave($AS).lactation > 0)>> my milky nipple<<s>> of cour<<s>>e. - <<elseif (getSlave($AS).nipples != "tiny")>> + <<elseif (getSlave($AS).nipples == "huge" || getSlave($AS).nipples == "puffy")>> my big nipple<<s>>, it'<<s>> like having clit<<s>> on my che<<s>>t. <<elseif (getSlave($AS).boobs > 700)>> my big boob<<s>>, I like how they feel wrapped around a dick. diff --git a/src/npc/interaction/fondleBoobs.tw b/src/npc/interaction/fondleBoobs.tw index 88af31ef0460cc868cf869063cf41eea388e9d29..5b8512a2cfcaabda5a81e19c30c1b3b069b38293 100644 --- a/src/npc/interaction/fondleBoobs.tw +++ b/src/npc/interaction/fondleBoobs.tw @@ -25,6 +25,8 @@ You call $him over so you can fondle $his $His nipples are so large they give $his breasts an unavoidably lewd appeal as they jut outward. <<elseif (getSlave($AS).nipples == "puffy")>> $His puffy nipples beg to be sucked. +<<elseif (getSlave($AS).nipples == "flat")>> + $His nipples form lewd little circles amid $his areolae. <<elseif (getSlave($AS).nipples == "partially inverted") && (getSlave($AS).nipplesPiercing == 0)>> $His partially inverted nipples should protrude at the slightest stimulation. <<elseif (getSlave($AS).nipples == "inverted") && (getSlave($AS).nipplesPiercing == 0)>> diff --git a/src/npc/startingGirls/editFamily.js b/src/npc/startingGirls/editFamily.js index 45b2e9b23ba66754aa22d8f0cbcf3bb2b6120ff3..06e395ad0c1fb12e671f47d36340b1ff2875a569 100644 --- a/src/npc/startingGirls/editFamily.js +++ b/src/npc/startingGirls/editFamily.js @@ -252,7 +252,7 @@ App.Intro.editFamily = function(slave) { } else if (slave.father !== 0) { potentialRel.father = slave.father; } else { - slave.father = -20 - 2*slave.ID; + slave.father = -20 - 2*slave.ID - 1; potentialRel.father = slave.father; } } diff --git a/src/npc/startingGirls/startingGirls.js b/src/npc/startingGirls/startingGirls.js index 68a7b5c4a16e33fd562169d777b805234d83f896..e4ed9091a95702c5a82330846b5fb420efbc5079 100644 --- a/src/npc/startingGirls/startingGirls.js +++ b/src/npc/startingGirls/startingGirls.js @@ -788,8 +788,20 @@ App.StartingGirls.physical = function(slave) { options.addOption("Butt", "butt", slave) .addValueList([["Flat", 0], ["Small", 1], ["Plump", 2], ["Big", 3], ["Huge", 4], ["Enormous", 5], ["Gigantic", 6], ["Massive", 7]]); + const oldAnus = slave.anus; options.addOption("Anus", "anus", slave) - .addValueList([["Virgin", 0], ["Normal", 1], ["Veteran", 2], ["Gaping", 3]]); + .addValue("Virgin", 0, () => { + slave.analArea = 1; + }) + .addValue("Normal", 1, () => { + slave.analArea = Math.clamp(slave.analArea + (1 - oldAnus), 1, 3); + }) + .addValue("Veteran", 2, () => { + slave.analArea = Math.clamp(slave.analArea + (2 - oldAnus), 2, 4); + }) + .addValue("Gaping", 3, () => { + slave.analArea = Math.clamp(slave.analArea + (3 - oldAnus), 3, 5); + }); if (slave.anus > 0) { let comment; @@ -800,11 +812,11 @@ App.StartingGirls.physical = function(slave) { } else { comment = "Very broad."; } - options.addOption("External anus appearance", "anus", slave) + options.addOption("External anus appearance", "analArea", slave) .addValueList([ - ["Recently stretched", slave.analArea = slave.anus], - ["Used to current size", slave.analArea = slave.anus+1], - ["Very broad", slave.analArea = slave.anus+2], + ["Recently stretched", slave.anus], + ["Used to current size", slave.anus + 1], + ["Very broad", slave.anus + 2], ]).addComment(comment); } diff --git a/src/npc/surgery/bodySwap/bodySwapReaction.tw b/src/npc/surgery/bodySwap/bodySwapReaction.tw index 0398f3bf685c9f16ffe477f004887ad3763aaa1a..e400b935e198e433e86c7a8c7dd80ea2b64629ea 100644 --- a/src/npc/surgery/bodySwap/bodySwapReaction.tw +++ b/src/npc/surgery/bodySwap/bodySwapReaction.tw @@ -651,6 +651,8 @@ Now you only have to wait for $him to wake up. $He doesn't seem interested in them until $he slips a @@.lime;finger deep inside one of the folds.@@ $He reddens at the thought of what the intent of this is. <<case "tiny">> $He's a little depressed by @@.orange;how tiny they've become.@@ + <<case "flat">> + $He's a little depressed to find @@.orange;the implants have pulled them flat.@@ <<case "puffy">> $He quivers a little as $he traces the edges of $his @@.lime;puffy nipples.@@ <<case "huge">> @@ -700,6 +702,13 @@ Now you only have to wait for $him to wake up. <<else>> $He is intrigued by this development. <</if>> + <<elseif $args[0].boobShape == "spherical">> + @@.green;they sit roundly on $his chest and don't really move much.@@ + <<if $args[0].devotion > 20>> + $He bounces to make them roll about. + <<else>> + $He is intrigued by this development. + <</if>> <<else>> @@.green;they can only be called normal.@@ <</if>> @@ -2174,6 +2183,8 @@ Now you only have to wait for $him to wake up. $He doesn't seem to understand where they have gone. <<case "tiny">> $He's a little depressed by @@.orange;how tiny they've become.@@ + <<case "flat">> + $He's a little depressed to find @@.orange;the implants have pulled them flat.@@ <<case "puffy">> $He giggles a little at the sight of how @@.lime;puffy they are.@@ <<case "huge">> @@ -2206,6 +2217,13 @@ Now you only have to wait for $him to wake up. <<else>> $He is intrigued by this development. <</if>> + <<elseif $args[0].boobShape == "spherical">> + @@.green;they are round and heavy.@@ + <<if $args[0].devotion > 20>> + $He squirms, but they don't really move much at all. + <<else>> + $He is intrigued by this development. + <</if>> <<elseif $args[0].boobShape == "torpedo-shaped">> @@.green;they stick out far from $his chest.@@ <<if $args[0].devotion > 20>> diff --git a/src/npc/surgery/organFarm.js b/src/npc/surgery/organFarm.js index e1951cdaafe6f080a73af59d0162bdd2f72b74e5..b5f8925104ae658a8662ba74139ef402a3209786 100644 --- a/src/npc/surgery/organFarm.js +++ b/src/npc/surgery/organFarm.js @@ -55,7 +55,6 @@ App.Medicine.OrganFarm.growActions = function(slave) { // put everything in one string let r = ""; if (grow !== "") { - // div.grid-2columns-auto is defined in mainStyleSheet.css r += `The fabricator is ready to grow an organ for ${him}. Extract tissue to begin growing:<div class="grid-2columns-auto">${grow}</div>`; } if (wait !== []) { @@ -268,9 +267,9 @@ App.Medicine.OrganFarm.currentlyGrowing = function() { let finishLines = []; V.organs.forEach(o => { - const index = V.slaveIndices[o.ID]; - if (index !== undefined) { - growLines.push(`${V.slaves[index].slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}, ${ + const slave = getSlave(o.ID); + if (slave !== undefined) { + growLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}, ${ weeksToCompletion(o.weeksToCompletion)} week(s) left.`); } else { growLines.push(`<span class="error">ERROR: No slave with ID ${o.ID} found.</span>`); @@ -291,9 +290,9 @@ App.Medicine.OrganFarm.currentlyGrowing = function() { }); V.completedOrgans.forEach(o => { - const index = V.slaveIndices[o.ID]; - if (index !== undefined) { - finishLines.push(`${V.slaves[index].slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}.`); + const slave = getSlave(o.ID); + if (slave !== undefined) { + finishLines.push(`${slave.slaveName}'s ${App.Medicine.OrganFarm.Organs[o.type].name}.`); } else { finishLines.push(`<span class="error">ERROR: No slave with ID ${o.ID} found.</span>`); } diff --git a/src/pregmod/cloningWorkaround.tw b/src/pregmod/cloningWorkaround.tw index 8be5b548e3c651d5b5cf9968dcd196c9a3405e8b..b4456a8f0355fe7502364a7b7b808867be953b67 100644 --- a/src/pregmod/cloningWorkaround.tw +++ b/src/pregmod/cloningWorkaround.tw @@ -8,7 +8,7 @@ <div class="note">Blank ovum prepared, please select genetic source and surrogate.</div> <div>Chosen source: _impreg</div> -<div class="majorText"> +<p> [[Yourself|Cloning Workaround][$donatrix = $PC]] <<for _cw = 0; _cw < $slaves.length; _cw++>> <<capture _cw>> @@ -20,10 +20,10 @@ <</if>> <</capture>> <</for>> -</div> +</p> <h2>Surrogate</h2> <div>Chosen surrogate: _receive</div> -<div class="majorText"> +<p> <<for _cw1 = 0; _cw1 < $slaves.length; _cw1++>> <<capture _cw1>> <<if ($slaves[_cw1].ovaries > 0 || $slaves[_cw1].mpreg > 0) && isSlaveAvailable($slaves[_cw1]) && $slaves[_cw1].preg >= 0 && $slaves[_cw1].preg < 4 && $slaves[_cw1].pregWeek >= 0 && $slaves[_cw1].pubertyXX == 1 && $slaves[_cw1].pregType < 12 && $slaves[_cw1].bellyImplant == -1 && $slaves[_cw1].broodmother == 0 && $slaves[_cw1].inflation <= 2 && $slaves[_cw1].physicalAge < 70>> @@ -52,9 +52,9 @@ <</if>> </div> <</if>> -</div> +</p> <h2>Implantation</h2> -<div class="majorText"> +<p> <<if _impreg != "Undecided" && _receive != "Undecided">> _impreg will be cloned and _receive shall act as the incubator. [[Implant clone ovum|Surrogacy][cashX(forceNeg($surgeryCost*2), "slaveSurgery"), $surgeryType = "clone"]] @@ -65,4 +65,4 @@ _receive shall act as the incubator. //Please select a genetic source// <<else>> //Please select a genetic source and surrogate// <</if>> -</div> +</p> diff --git a/src/uncategorized/RESS.tw b/src/uncategorized/RESS.tw index 77fd8147b730719c6e0f0bdf4ed8b176c55c8187..c869ff71f4b4ec4b55cfc2dd5ee6f25c998e175d 100644 --- a/src/uncategorized/RESS.tw +++ b/src/uncategorized/RESS.tw @@ -51,7 +51,7 @@ <<set $activeSlave.clothes = "restrictive latex">> <<case "inconvenient labia">> /* "pulling down the compression shorts $he was wearing" */ - <<if isItemAccessible.entry("sport shorts", "clothing")>> + <<if isItemAccessible.entry("sport shorts", "clothes")>> <<if $activeSlave.boobs >= 650>> <<set $activeSlave.clothes = "sport shorts and a sports bra">> <<else>> @@ -423,10 +423,22 @@ It's an unusually nice day, with mild sunshine, light breezes, and nothing offen $His skin shines with sunblock lotion from a bottle lying next to $him. It would be foolish of $him to let the sun ruin $his $activeSlave.skin skin. <</if>> <br><br> -$He's lying on $his back with $his arm<<if hasBothArms($activeSlave)>>s<</if>> outstretched, $his <<if ($activeSlave.boobs > 5000)>>titanic breasts resting to either side. They're so enormous they touch the ground on either side of $him.<<elseif ($activeSlave.boobs > 800) && ($activeSlave.boobsImplant == 0)>>heavy, natural breasts resting to either side.<<elseif ($activeSlave.boobsImplant == 0)>>modest breasts resting a little to either side as $his chest rises and falls with $his breath.<<else>>fake tits maintaining their proud shape regardless.<</if>> $He's relaxed and breathing slowly, and it isn't immediately clear if $he's asleep or not. $He's not aroused, and $his +$He's lying on $his back with $his arm<<if hasBothArms($activeSlave)>>s<</if>> outstretched, $his +<<if ($activeSlave.boobs > 5000)>> + titanic breasts resting to either side. They're so enormous they touch the ground on either side of $him. +<<elseif ($activeSlave.boobs > 800) && ($activeSlave.boobsImplant == 0)>> + heavy, natural breasts resting to either side. +<<elseif ($activeSlave.boobsImplant / $activeSlave.boobs >= 0.50)>> + fake tits maintaining their proud shape regardless. +<<else>> + modest breasts resting a little to either side as $his chest rises and falls with $his breath. +<</if>> +$He's relaxed and breathing slowly, and it isn't immediately clear if $he's asleep or not. $He's not aroused, and $his <<switch $activeSlave.nipples>> <<case "tiny">> tiny little nipples soft against $his breasts. +<<case "flat">> + nipples blend seamlessly into $his sunlit areolae. <<case "puffy">> puffy nipples are soft under the sunlight. <<case "partially inverted">> @@ -450,6 +462,8 @@ $He's walking awkwardly because of how painfully horny $he is. $His <<switch $activeSlave.nipples>> <<case "tiny">> tiny little nipples are rock hard. +<<case "flat">> + stretched nipples, which normally rest flush with $his areolae, are hard and prominent. <<case "puffy">> puffy nipples are flushed and stiff. <<case "partially inverted">> @@ -698,7 +712,7 @@ The sight is comical. <<if $activeSlave.belly >= 5000 || $activeSlave.weight > 9 <</if>> <<if ($activeSlave.nipples == "huge")>>Each is capped by a gigantic nipple, soft with relaxation and the heat of the spa, but hugely prominent.<</if>> <<if ($activeSlave.areolae > 1)>>$His areolae spread widely around each nipple.<</if>> -<<if $activeSlave.boobsImplant/$activeSlave.boobs >= .60>> +<<if $activeSlave.boobsImplant/$activeSlave.boobs >= .50>> $His implants keep $his tits shaped in exactly the same way regardless of currents in the water, betraying their fake nature. <<elseif ($activeSlave.boobsImplant == 0)>> $His all-natural boobs move gently with currents in the water. @@ -2870,6 +2884,8 @@ Passing near the slave dormitory late at night, you hear a quiet cry within. Thi <<switch $activeSlave.nipples>> <<case "tiny">> pricking up into little buds. +<<case "flat">> + becoming visible against $his areolae. <<case "puffy">> the puffy promontories jutting even farther out. <<case "partially inverted">> @@ -3777,8 +3793,10 @@ $He kneels with $his legs together, and then sits back, $his cute butt resting lightly on $his heels. <</if>> Then $he reaches $his arm<<if hasBothArms($activeSlave)>>s<</if>> back, and leans back, as far as $he can go. $He arches $his spine, closing $his eyes voluptuously as $he enjoys the stretch in $his lower back. The pose thrusts $his chest up and out, -<<if ($activeSlave.boobsImplant/$activeSlave.boobs) >= .60>> +<<if $activeSlave.boobShape == "spherical">> but $his implants stretch $his skin so tight that they stay tacked to $his chest, right where they are. $He looks like a stereotypical silicone queen, arching $his back and sticking $his fake cans out. +<<elseif ($activeSlave.boobsImplant/$activeSlave.boobs) >= .50>> + making $his implant-filled tits stick out even farther than they usually do. $He looks like a stereotypical silicone queen, arching $his back and sticking $his fake cans out. <<elseif $activeSlave.boobShape == "perky">> making $his spectacularly perky breasts point their $activeSlave.nipples nipples straight up at the ceiling. It's incredible, that they've managed to maintain their youthful shape despite their great weight. <<elseif $activeSlave.boobShape == "downward-facing">> @@ -9088,6 +9106,8 @@ brought in to you. This time <<= App.UI.slaveDescriptionDialog($activeSlave)>> h and tease $his <<if $activeSlave.nipples == "huge">> ridiculous + <<elseif $activeSlave.nipples == "flat">> + fat <<elseif $activeSlave.nipples == "puffy">> puffy <<elseif $activeSlave.nipples == "inverted">> @@ -9392,6 +9412,8 @@ brought in to you. This time <<= App.UI.slaveDescriptionDialog($activeSlave)>> h <<switch $activeSlave.nipples>> <<case "huge">> stroking $his lewdly erect nipples. + <<case "huge">> + tweaking $his revealed nipples. <<case "puffy">> cupping and fondling $his puffy nipples. <<case "partially inverted">> @@ -16013,6 +16035,8 @@ brought in to you. This time <<= App.UI.slaveDescriptionDialog($activeSlave)>> h <<switch $activeSlave.boobShape>> <<case "perky">> $His perky tits do their best to retain their pointy shape despite the tugging. + <<case "spherical">> + $His implant-stuffed tits retain their rounded shape despite the tugging. <<case "downward-facing">> The nipples that cap $his downward-facing udders are tugged even farther towards the ground. <<case "torpedo-shaped">> @@ -17226,6 +17250,8 @@ brought in to you. This time <<= App.UI.slaveDescriptionDialog($activeSlave)>> h $his huge nipple filling your mouth comfortably. <<case "fuckable">> drawing an unreasonable amount of breast into your mouth just to keep a seal. + <<case "flat">> + pulling $his nipple and the areolae around it into your mouth. <<default>> pulling $his soft nipple and some of the areolae around it into your mouth. <</switch>> diff --git a/src/uncategorized/freeRangeDairyAssignmentScene.tw b/src/uncategorized/freeRangeDairyAssignmentScene.tw index 20fadf51b50a5caa875ad2034eb3c45cd4657385..0653f35f7555f3d1a217277d59d3d88bdbfa9e08 100644 --- a/src/uncategorized/freeRangeDairyAssignmentScene.tw +++ b/src/uncategorized/freeRangeDairyAssignmentScene.tw @@ -165,7 +165,7 @@ Your appointed milkmaid _S.Milkmaid.slaveName helps <<= getSlave($AS).slaveName>> with installing the milking devices. <</if>> <<if getSlave($AS).lactation > 0 >> - Suction cups are attached <<if getSlave($AS).nipples == "fuckable">>over<<else>>to<</if>> $his nipples. + Suction cups are attached <<if getSlave($AS).nipples == "fuckable" || getSlave($AS).nipples == "flat">>over<<else>>to<</if>> $his nipples. <</if>> <<if getSlave($AS).balls > 0>> <<if getSlave($AS).dick > 8>> @@ -316,7 +316,7 @@ /* MILKING ROUTINE */ <p> <<if getSlave($AS).lactation > 0>> - The milking cups <<if getSlave($AS).nipples == "fuckable">>over<<else>>on<</if>> $his nipples begin to pulse rhythmically. Soon, a steady flow of breast-milk is sucked away into the storage tanks. + The milking cups <<if getSlave($AS).nipples == "fuckable" || getSlave($AS).nipples == "flat">>over<<else>>on<</if>> $his nipples begin to pulse rhythmically. Soon, a steady flow of breast-milk is sucked away into the storage tanks. <</if>> <<if getSlave($AS).dick > 0>> The milking machine uses suction to draw $his dick into the receptacle. @@ -356,7 +356,7 @@ <</if>> <<if getSlave($AS).lactation > 0>> <br> - The milking cups <<if getSlave($AS).nipples == "fuckable">>over<<else>>on<</if>> $his nipples switch from rhythmic pulsing into intense suction. Aided by $his orgasm, milk spurts from $his nipples + The milking cups <<if getSlave($AS).nipples == "fuckable" || getSlave($AS).nipples == "flat">>over<<else>>on<</if>> $his nipples switch from rhythmic pulsing into intense suction. Aided by $his orgasm, milk spurts from $his nipples <<if getSlave($AS).boobs > 20000>> in obscenely massive amounts. $His immense breasts seem to never empty. <<elseif getSlave($AS).boobs > 10000>> @@ -400,7 +400,7 @@ $He gets comfortable around $his cum-bloated belly as the impregnator continues its task. <</if>> <<if getSlave($AS).lactation > 0>> - The milking cups <<if getSlave($AS).nipples == "fuckable">>over<<else>>on<</if>> $his nipples pulse slower and with less vigor. The lactation never fully subsides. The steady but gentle suction helps increasing milk production without actually draining the breasts. + The milking cups <<if getSlave($AS).nipples == "fuckable" || getSlave($AS).nipples == "flat">>over<<else>>on<</if>> $his nipples pulse slower and with less vigor. The lactation never fully subsides. The steady but gentle suction helps increasing milk production without actually draining the breasts. <<set getSlave($AS).lactationDuration = 2>> <<set getSlave($AS).boobs -= getSlave($AS).boobsMilk, getSlave($AS).boobsMilk = 0>> <</if>> diff --git a/src/uncategorized/industrialDairyAssignmentScene.tw b/src/uncategorized/industrialDairyAssignmentScene.tw index c5c7ce8fc4b52ac412d412f8996ff8565387fa26..4d3f4473ba2fce3c198b5967b0f93eaac61d8bf6 100644 --- a/src/uncategorized/industrialDairyAssignmentScene.tw +++ b/src/uncategorized/industrialDairyAssignmentScene.tw @@ -306,7 +306,7 @@ When <<= getSlave($AS).slaveName>> reports to the dairy, it's to the <<if canSee <</if>> /* CLOSES DEVOTION */ <<if getSlave($AS).lactation > 0>> - A big soft cup attaches itself <<if getSlave($AS).nipples == "fuckable">>over<<else>>to<</if>> each of $his nipples. + A big soft cup attaches itself <<if getSlave($AS).nipples == "fuckable" || getSlave($AS).nipples == "flat">>over<<else>>to<</if>> each of $his nipples. <<if (getSlave($AS).nipples == "inverted")>> $He gasps with pain as suction unceremoniously hauls $his inverted nipples down into the cups. <<elseif (getSlave($AS).nipples == "fuckable")>> diff --git a/src/uncategorized/main.tw b/src/uncategorized/main.tw deleted file mode 100644 index cd73e8b5f033317e518a90f032a661b8e827dcad..0000000000000000000000000000000000000000 --- a/src/uncategorized/main.tw +++ /dev/null @@ -1,33 +0,0 @@ -:: Main [nobr jump-to-safe jump-from-safe] - -<<includeDOM App.MainView.errors()>> - -<<set $nextButton = "END WEEK", $nextLink = "End Week", $encyclopedia = "How to Play">> - -<<if $tabChoice.SlaveInteract != 'Description'>> - <<set $tabChoice.SlaveInteract = 'Description'>> -<</if>> - -<<run penthouseCensus()>> - -<<set $costs = Math.trunc(calculateCosts.predict())>> - -<<set $currentRule = $defaultRules[0]>> - -<<run SlaveSort.slaves($slaves)>> - -<<if $newModelUI == 1>> - <<includeDOM V.building.render()>> -<</if>> - -<<if $seeArcology == 1>> - <<includeDOM App.Desc.playerArcology(App.UI.DOM.passageLink("Hide", "Main", () => {V.seeArcology = 0}))>> -<</if>> - -<<if $seeDesk == 1>> - <<includeDOM App.Desc.officeDescription(App.UI.DOM.passageLink("Hide", "Main", () => {V.seeDesk = 0}))>> -<</if>> - -<<includeDOM App.MainView.full()>> - -<<run App.UI.SlaveList.ScrollPosition.restore()>> diff --git a/src/uncategorized/managePenthouse.tw b/src/uncategorized/managePenthouse.tw index 34163138a6feb591ba32f7e89e4aeb2102fea304..7133d8f82669f540bda3db6de7e871ff67bd9d65 100644 --- a/src/uncategorized/managePenthouse.tw +++ b/src/uncategorized/managePenthouse.tw @@ -279,6 +279,15 @@ </div> <</if>> + <div> + <<if !$toyShop>> + [[Install a workshop for making custom toys|Manage Penthouse][cashX(-10000, "capEx"), $toyShop = true, $PC.skill.engineering += .1]] + <span class="detail">Costs <<print cashFormat(10000)>></span> + <<else>> + There is a [[workshop|Toy Shop]] for making custom toys. + <</if>> + </div> + <div> <<if $studio == 0>> [[Install a media hub to convert slave video feeds into pornography|Manage Penthouse][cashX(forceNeg(Math.trunc(10000*$upgradeMultiplierArcology)), "capEx"), $studio = 1, $PC.skill.engineering += 1]] diff --git a/src/uncategorized/pRivalryActions.tw b/src/uncategorized/pRivalryActions.tw index 34a9a0b8a6ee9d1f904a1f78eb465f1f4e705b52..032d43b5269139235ae5d7714c6d14113f3f78de 100644 --- a/src/uncategorized/pRivalryActions.tw +++ b/src/uncategorized/pRivalryActions.tw @@ -417,6 +417,8 @@ Your inter-arcology war with the arcology owner behind the Daughters of Liberty <<if $hostage.boobsImplant > 10000>> <<set $hostage.boobsImplantType = "hyper fillable">> <</if>> + <<set $hostage.boobShape = "spherical">> + <<set $hostage.nipples = "flat">> <<set $hostage.fetish = "boobs">> <<set $hostage.fetishStrength = 10>> blushing as $he attempts to get dressed with $his massive <<print $hostage.boobs>>cc fake tits getting in the way. diff --git a/src/uncategorized/reBoomerang.tw b/src/uncategorized/reBoomerang.tw index 2215d07cf4eefe0c72291224c15ba335390bccd3..0aa8b04ce9859dc07975c278e40abe8929a68a5b 100644 --- a/src/uncategorized/reBoomerang.tw +++ b/src/uncategorized/reBoomerang.tw @@ -164,6 +164,10 @@ brings up the relevant feeds. There's a naked body crumpled pathetically against <<case "slimness enthusiast arcology">> "It wa<<s>> horrible." You sold $him to a pleasant Slimness Enthusiast arcology, but somehow $he's acquired grotesque implants. "The arcology got a new owner." $He shudders. "I gue<<ss>> the ni<<c>>e one wa<<s>> weak, and, and the new one i<<s>> changing thing<<s>>. <<Sh>>-<<sh>>e l-like<<s>> t-to ruin the <<s>>lim one<<s>>." It's nothing short of incredible that $he managed to get back here. $He must have sold and traded $himself without hesitation. <<set _slave.boobsImplant = 200*random(2,4), _slave.boobs += _slave.boobsImplant, _slave.boobsImplantType = "normal">> + <<if (_slave.boobsImplant / _slave.boobs >= 0.90)>> + <<set _slave.boobShape = "spherical">> + <<set _slave.nipples = "flat">> + <</if>> <<set _slave.buttImplant = random(2,4), _slave.butt = Math.clamp(_slave.butt+_slave.buttImplant,0,10), _slave.buttImplantType = "normal">> <<set _slave.lipsImplant = 10*random(1,3), _slave.lips = Math.clamp(_slave.lips+_slave.lipsImplant,0,100)>> <<case "asset expansionist arcology">> @@ -180,6 +184,10 @@ brings up the relevant feeds. There's a naked body crumpled pathetically against <<case "transformation fetishist arcology">> "It wa<<s>> horrible." You sold $him to a Transformation Fetishist arcology; it's nothing short of incredible that $he managed to get back here. $He must have sold and traded $himself without hesitation. "They were giving me new boob implant<<s>> every two week<<s>>. I ran away before another <<s>>et. I c-couldn't take any more <<s>>-<<s>>urgery." <<set _slave.boobsImplant = 200*random(9,12), _slave.boobs += _slave.boobsImplant, _slave.boobsImplantType = "normal">> + <<if (_slave.boobsImplant / _slave.boobs >= 0.90)>> + <<set _slave.boobShape = "spherical">> + <<set _slave.nipples = "flat">> + <</if>> <<case "physical idealist arcology">> "It wa<<s>> horrible." You sold $him to a Physical Idealist arcology; it's nothing short of incredible that $he managed to get back here. $He must have sold and traded $himself without hesitation. "It should have been called a <<S>>teroid Enthu<<s>>ia<<s>>t arcology." $He shivers. "The <<s>>ide effect<<s>> are terrible. I can't <<s>>leep. I can barely eat. They had to feed me with a tube." <<set _slave.muscles = 100, _slave.weight = random(-85,-75)>> @@ -198,6 +206,10 @@ brings up the relevant feeds. There's a naked body crumpled pathetically against <<case "body purist arcology">> "It wa<<s>> horrible." You sold $him to a pleasant Body Purist arcology, but somehow $he's acquired grotesque implants. "The arcology got a new owner." $He shudders. "I gue<<ss>> the ni<<c>>e one wa<<s>> weak, and, and the new one i<<s>> changing thing<<s>>. <<Sh>>-<<sh>>e l-like<<s>> t-to ruin the pure one<<s>>." It's nothing short of incredible that $he managed to get back here. $He must have sold and traded $himself without hesitation. <<set _slave.boobsImplant = 200*random(2,4), _slave.boobs += _slave.boobsImplant, _slave.boobsImplantType = "normal">> + <<if (_slave.boobsImplant / _slave.boobs >= 0.90)>> + <<set _slave.boobShape = "spherical">> + <<set _slave.nipples = "flat">> + <</if>> <<set _slave.buttImplant = random(2,4), _slave.butt = Math.clamp(_slave.butt+_slave.buttImplant,0,10), _slave.buttImplantType = "normal">> <<set _slave.lipsImplant = 10*random(1,3), _slave.lips = Math.clamp(_slave.lips+_slave.lipsImplant,0,100)>> <<case "D milf staffing" "trainer staffing">> @@ -212,10 +224,20 @@ brings up the relevant feeds. There's a naked body crumpled pathetically against <<case "implanting trainer">> "I d-don't want to be c-cut again," $he <<say>>s hollowly. $His buyer planned to use $him as a surgical teaching tool. "E-every time I'm healed, they implant me again. B-bigger." <<set _slave.boobsImplant = 200*random(8,12), _slave.boobs += _slave.boobsImplant, _slave.boobsImplantType = "advanced fillable">> + <<if (_slave.boobsImplant / _slave.boobs >= 0.90)>> + <<set _slave.boobShape = "spherical">> + <<set _slave.nipples = "flat">> + <</if>> <<set _slave.buttImplant = random(2,4), _slave.butt = Math.clamp(_slave.butt+_slave.buttImplant,0,10), _slave.buttImplantType = "normal">> <<set _slave.lipsImplant = 10*random(1,3), _slave.lips = Math.clamp(_slave.lips+_slave.lipsImplant,0,100)>> <<case "purifying trainer">> "It w-wa<<s>>n't like I thought it would be," $he <<say>>s. "The trainer you <<s>>old me to took out my implant<<s>>. B-but then they <<s>>aid my boob<<s>> had to be rebuilt, only with drug<<s>> thi<<s>> time." $He shivers. "The <<s>>ide effect<<s>> are terrible. I can't <<s>>leep. I can barely eat. They had to feed me with a tube." + <<if (_slave.boobShape == "spherical")>> + <<set _slave.boobShape = "saggy">> + <</if>> + <<if (_slave.nipples == "flat")>> + <<set _slave.nipples = "cute">> + <</if>> <<set _slave.boobs -= _slave.boobsImplant, _slave.boobsImplant = 0, _slave.boobsImplantType = "none">> <<set _slave.butt -= _slave.buttImplant, _slave.buttImplant = 0, _slave.buttImplantType = "none">> <<set _slave.lips -= _slave.lipsImplant, _slave.lipsImplant = 0>> @@ -249,6 +271,9 @@ brings up the relevant feeds. There's a naked body crumpled pathetically against <<case "clipping trainer">> "All I do i<<s>> <<s>>uck dick<<s>> and get fucked in the butt." You sold $him to a trainer who specializes in clipping and improving overly masculine slaves, and $he's definitely more feminine, if bitterly unhappy. "They're going to <<s>>ell me to a bitch brothel <<s>>oon, I know it. Plea<<s>>e, nobody'<<s>> even <<s>>aid anything to me other than '<<s>>uck my cock' or 'bend over bitch' in week<<s>>." <<set _slave.boobsImplant = 200*random(2,4), _slave.boobs += _slave.boobsImplant, _slave.boobsImplantType = "normal">> + <<if (_slave.boobsImplant / _slave.boobs >= 0.90)>> + <<set _slave.boobShape = "spherical">> + <</if>> <<set _slave.buttImplant = random(1,2), _slave.butt = Math.clamp(_slave.butt+_slave.buttImplant,0,10), _slave.buttImplantType = "normal">> <<set _slave.lipsImplant = 10*random(1,2), _slave.lips = Math.clamp(_slave.lips+_slave.lipsImplant,0,100)>> <<set _slave.waist = Math.clamp(_slave.waist+random(20,50),-100,100)>> diff --git a/src/uncategorized/reFSAcquisition.tw b/src/uncategorized/reFSAcquisition.tw index 80d81b60a50e09099b67eafb3770d8548f21fbb0..c2dc92f6e69d0f2cbb0c06adba81cfe754bda664 100644 --- a/src/uncategorized/reFSAcquisition.tw +++ b/src/uncategorized/reFSAcquisition.tw @@ -261,6 +261,13 @@ <<set $activeSlave.boobsImplant += random(4,6)*200>> <<set $activeSlave.boobs += $activeSlave.boobsImplant>> <<set $activeSlave.boobsImplantType = "normal">> +<<if ($activeSlave.boobsImplant / $activeSlave.boobs >= 0.90)>> + <<set $activeSlave.boobShape = "spherical">> + <<set $activeSlave.nipples = "flat">> +<<else>> + <<set $activeSlave.boobShape = "normal">> + <<set $activeSlave.nipples = "huge">> +<</if>> <<set $activeSlave.nipples = "huge">> <<set $activeSlave.areolae = 1>> <<set $activeSlave.butt += 1>> @@ -393,6 +400,7 @@ <<set $activeSlave.boobsImplant += random(4,6)*200>> <<set $activeSlave.boobs += $activeSlave.boobsImplant>> <<set $activeSlave.boobsImplantType = "fillable">> +<<set $activeSlave.boobShape = "normal">> <<set $activeSlave.lips = 60>> <<set $activeSlave.face = Math.clamp($activeSlave.face+20,-100,100)>> <<set $activeSlave.devotion = random(20,45)>> @@ -634,6 +642,12 @@ <<set $activeSlave.boobsImplant += random(4,6)*200>> <<set $activeSlave.boobs += $activeSlave.boobsImplant>> <<set $activeSlave.boobsImplantType = "string">> +<<if ($activeSlave.boobsImplant / $activeSlave.boobs >= 0.90)>> + <<set $activeSlave.boobShape = "spherical">> + <<set $activeSlave.nipples = "flat">> +<<else>> + <<set $activeSlave.boobShape = "normal">> +<</if>> <<set $activeSlave.buttImplant += 2>> <<set $activeSlave.butt += $activeSlave.buttImplant>> <<set $activeSlave.buttImplantType = "normal">> @@ -709,7 +723,13 @@ <<set $activeSlave.boobsImplant += random(10,20)*200>> <<set $activeSlave.boobs += $activeSlave.boobsImplant>> <<set $activeSlave.boobsImplantType = "advanced fillable">> -<<set $activeSlave.nipples = "tiny">> +<<if ($activeSlave.boobsImplant / $activeSlave.boobs >= 0.90)>> + <<set $activeSlave.boobShape = "spherical">> + <<set $activeSlave.nipples = "flat">> +<<else>> + <<set $activeSlave.boobShape = "normal">> + <<set $activeSlave.nipples = "tiny">> +<</if>> <<set $activeSlave.areolae = 2>> <<set $activeSlave.buttImplant += random(2,4)>> <<set $activeSlave.buttImplantType = "fillable">> @@ -740,7 +760,13 @@ <<set $activeSlave.boobsImplant += random(5,10)*200>> <<set $activeSlave.boobs += $activeSlave.boobsImplant>> <<set $activeSlave.boobsImplantType = "fillable">> -<<set $activeSlave.nipples = "tiny">> +<<if ($activeSlave.boobsImplant / $activeSlave.boobs >= 0.90)>> + <<set $activeSlave.boobShape = "spherical">> + <<set $activeSlave.nipples = "flat">> +<<else>> + <<set $activeSlave.boobShape = "normal">> + <<set $activeSlave.nipples = "tiny">> +<</if>> <<set $activeSlave.areolae = 2>> <<set $activeSlave.buttImplant += random(2,4)>> <<set $activeSlave.butt += $activeSlave.buttImplant>> diff --git a/src/uncategorized/surgeryDegradation.tw b/src/uncategorized/surgeryDegradation.tw index ac29f03eb38590076e436511afceca25a4dd5771..4ee418c8de425afeb2ea74f2c32e774f709ce7f9 100644 --- a/src/uncategorized/surgeryDegradation.tw +++ b/src/uncategorized/surgeryDegradation.tw @@ -46,6 +46,9 @@ <<elseif getSlave($AS).nipples == "fuckable">> Without the tissue needed to support their unusual shape, $his fuckable nipples have reverted @@.orange;to being huge and protruding.@@ <<set getSlave($AS).nipples = "huge">> + <<elseif getSlave($AS).nipples == "flat">> + Without the $his massive implants forcing them flat, $his nipples have reverted @@.lime;to being huge and protruding.@@ + <<set getSlave($AS).nipples = "huge">> <</if>> <<if getSlave($AS).fetish == "mindbroken">> As with all invasive surgery @@.health.dec;$his health has been affected.@@ @@ -79,6 +82,9 @@ <<elseif getSlave($AS).nipples == "fuckable">> Without the tissue needed to support their unusual shape, $his fuckable nipples have reverted @@.orange;to being huge and protruding.@@ <<set getSlave($AS).nipples = "huge">> + <<elseif getSlave($AS).nipples == "flat">> + Without the $his massive implants forcing them flat, $his nipples have reverted @@.lime;to being huge and protruding.@@ + <<set getSlave($AS).nipples = "huge">> <</if>> <<if getSlave($AS).fetish == "mindbroken">> As with all invasive surgery @@.health.dec;$his health has been affected.@@ @@ -517,8 +523,14 @@ As the remote surgery's long recovery cycle completes, The breast surgery is invasive, and when $his nipples heal, @@.orange;they're a bit smaller.@@ <<set getSlave($AS).nipples = "puffy">> <</if>> + <<elseif (getSlave($AS).nipples == "cute" || getSlave($AS).nipples == "tiny") && (getSlave($AS).boobsImplant / getSlave($AS).boobs >= 0.75)>> + The sudden increase in breast size has @@.orange;stretched $his already small nipples flat.@@ + <<set getSlave($AS).nipples = "flat">> <</if>> - <<if (getSlave($AS).boobShape != 0) && (random(1,100) > 50)>> + <<if (getSlave($AS).boobShape != "spherical") && (getSlave($AS).boobsImplant / getSlave($AS).boobs >= 0.90)>> + With so little actual flesh left, the shape of $his breasts are now entirely dictated by the implants within, @@.lime;rendering them comically spherical.@@ + <<set getSlave($AS).boobShape = "spherical">> + <<elseif (getSlave($AS).boobShape != "normal" && getSlave($AS).boobShape != "spherical") && (random(1,100) > 50)>> The natural shape of $his breasts has been eliminated by the cosmetic surgery, @@.lime;rendering $his boobs pretty and rounded.@@ <<set getSlave($AS).boobShape = "normal">> <</if>> @@ -743,12 +755,20 @@ As the remote surgery's long recovery cycle completes, The breast reduction surgery also @@.orange;slightly reduces $his massive areolae.@@ <<set getSlave($AS).areolae -= 1>> <</if>> + <<if (getSlave($AS).nipples == "huge")>> The breast reduction surgery also @@.orange;slightly reduces $his massive nipples.@@ <<set getSlave($AS).nipples = "puffy">> <<elseif getSlave($AS).nipples == "fuckable" && getSlave($AS).boobs < 500>> Without the tissue needed to support their unusual shape, $his fuckable nipples have reverted @@.orange;to being huge and protruding.@@ <<set getSlave($AS).nipples = "huge">> + <<elseif getSlave($AS).nipples == "flat">> + Without the $his massive implants forcing them flat, $his nipples have reverted @@.lime;to being huge and protruding.@@ + <<set getSlave($AS).nipples = "huge">> + <</if>> + <<if (getSlave($AS).boobShape == "spherical")>> + With the removal of $his load bearing implants, @@.orange;$his breasts are left deflated and sagging.@@ + <<set getSlave($AS).boobShape = "saggy">> <</if>> <<if getSlave($AS).fetish == "mindbroken">> $He shows little awareness that $his breasts are smaller. As with all surgery @@.health.dec;$his health has been slightly affected.@@ @@ -776,6 +796,9 @@ As the remote surgery's long recovery cycle completes, <<if (getSlave($AS).nipples == "huge")>> The breast reduction surgery also @@.orange;slightly reduces $his massive nipples.@@ <<set getSlave($AS).nipples = "puffy">> + <<elseif getSlave($AS).nipples == "flat">> + Without the $his massive implants forcing them flat, $his nipples have reverted @@.lime;to being huge and protruding.@@ + <<set getSlave($AS).nipples = "huge">> <<elseif getSlave($AS).nipples == "fuckable">> Without the tissue needed to support their unusual shape, $his fuckable nipples have reverted @@.orange;to being huge and protruding.@@ <<set getSlave($AS).nipples = "huge">> @@ -814,6 +837,9 @@ As the remote surgery's long recovery cycle completes, <<if (getSlave($AS).nipples == "huge")>> The breast reduction surgery also @@.orange;slightly reduces $his massive nipples.@@ <<set getSlave($AS).nipples = "puffy">> + <<elseif getSlave($AS).nipples == "flat">> + Without the $his massive implants forcing them flat, $his nipples have reverted @@.lime;to being huge and protruding.@@ + <<set getSlave($AS).nipples = "huge">> <<elseif getSlave($AS).nipples == "fuckable">> Without the tissue needed to support their unusual shape, $his fuckable nipples have reverted @@.orange;to being huge and protruding.@@ <<set getSlave($AS).nipples = "huge">> diff --git a/src/zz1-last/init.js b/src/zz1-last/init.js new file mode 100644 index 0000000000000000000000000000000000000000..6e14d81e03be8bf26a0d685622f62188440731ed --- /dev/null +++ b/src/zz1-last/init.js @@ -0,0 +1,8 @@ +App.Medicine.OrganFarm.init(); +App.Art.cacheArtData(); +App.Corporate.Init(); + +// TODO remove once setup object is no longer required. +for (let key in App.Data.misc) { + setup[key] = App.Data.misc[key]; +} diff --git a/src/zz1-last/initOrganFarm.js b/src/zz1-last/initOrganFarm.js deleted file mode 100644 index 4c1d2e41d1cc0d82cc1072adf0a1d640af4be26b..0000000000000000000000000000000000000000 --- a/src/zz1-last/initOrganFarm.js +++ /dev/null @@ -1 +0,0 @@ -App.Medicine.OrganFarm.init();